summaryrefslogtreecommitdiff
path: root/unlock_indicator.c
diff options
context:
space:
mode:
Diffstat (limited to 'unlock_indicator.c')
-rw-r--r--unlock_indicator.c61
1 files changed, 39 insertions, 22 deletions
diff --git a/unlock_indicator.c b/unlock_indicator.c
index 3d98a5f..73320cb 100644
--- a/unlock_indicator.c
+++ b/unlock_indicator.c
@@ -50,9 +50,9 @@
50#define BUTTON_CENTER (BUTTON_RADIUS + 5) 50#define BUTTON_CENTER (BUTTON_RADIUS + 5)
51#define BUTTON_DIAMETER (2 * BUTTON_SPACE) 51#define BUTTON_DIAMETER (2 * BUTTON_SPACE)
52 52
53/****************************************************************************** 53/*******************************************************************************
54 * Variables defined in i3lock.c. 54 * Variables defined in i3lock.c.
55 *****************************************************************************/ 55 ******************************************************************************/
56 56
57extern bool debug_mode; 57extern bool debug_mode;
58 58
@@ -100,16 +100,16 @@ extern bool show_failed_attempts;
100/* Number of failed unlock attempts. */ 100/* Number of failed unlock attempts. */
101extern int failed_attempts; 101extern int failed_attempts;
102 102
103/****************************************************************************** 103/*******************************************************************************
104 * Variables defined in xcb.c. 104 * Variables defined in xcb.c.
105 *****************************************************************************/ 105 ******************************************************************************/
106 106
107/* The root screen, to determine the DPI. */ 107/* The root screen, to determine the DPI. */
108extern xcb_screen_t *screen; 108extern xcb_screen_t *screen;
109 109
110/****************************************************************************** 110/*******************************************************************************
111 * Local variables. 111 * Local variables.
112 *****************************************************************************/ 112 ******************************************************************************/
113 113
114/* Cache the screen’s visual, necessary for creating a Cairo context. */ 114/* Cache the screen’s visual, necessary for creating a Cairo context. */
115static xcb_visualtype_t *vistype; 115static xcb_visualtype_t *vistype;
@@ -124,8 +124,7 @@ auth_state_t auth_state;
124 * resolution and returns it. 124 * resolution and returns it.
125 * 125 *
126 */ 126 */
127xcb_pixmap_t draw_image(uint32_t *resolution) { 127void draw_image(xcb_pixmap_t bg_pixmap, uint32_t *resolution) {
128 xcb_pixmap_t bg_pixmap = XCB_NONE;
129 const double scaling_factor = get_dpi_value() / 96.0; 128 const double scaling_factor = get_dpi_value() / 96.0;
130 int button_diameter_physical = ceil(scaling_factor * BUTTON_DIAMETER); 129 int button_diameter_physical = ceil(scaling_factor * BUTTON_DIAMETER);
131 DEBUG("scaling_factor is %.f, physical diameter is %d px\n", 130 DEBUG("scaling_factor is %.f, physical diameter is %d px\n",
@@ -133,7 +132,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
133 132
134 if (!vistype) 133 if (!vistype)
135 vistype = get_root_visual_type(screen); 134 vistype = get_root_visual_type(screen);
136 bg_pixmap = create_bg_pixmap(conn, screen, resolution, color); 135
137 /* Initialize cairo: Create one in-memory surface to render the unlock 136 /* Initialize cairo: Create one in-memory surface to render the unlock
138 * indicator on, create one XCB surface to actually draw (one or more, 137 * indicator on, create one XCB surface to actually draw (one or more,
139 * depending on the amount of screens) unlock indicators on. */ 138 * depending on the amount of screens) unlock indicators on. */
@@ -143,6 +142,19 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
143 cairo_surface_t *xcb_output = cairo_xcb_surface_create(conn, bg_pixmap, vistype, resolution[0], resolution[1]); 142 cairo_surface_t *xcb_output = cairo_xcb_surface_create(conn, bg_pixmap, vistype, resolution[0], resolution[1]);
144 cairo_t *xcb_ctx = cairo_create(xcb_output); 143 cairo_t *xcb_ctx = cairo_create(xcb_output);
145 144
145 /* After the first iteration, the pixmap will still contain the previous
146 * contents. Explicitly clear the entire pixmap with the background color
147 * first to get back into a defined state: */
148 char strgroups[3][3] = {{color[0], color[1], '\0'},
149 {color[2], color[3], '\0'},
150 {color[4], color[5], '\0'}};
151 uint32_t rgb16[3] = {(strtol(strgroups[0], NULL, 16)),
152 (strtol(strgroups[1], NULL, 16)),
153 (strtol(strgroups[2], NULL, 16))};
154 cairo_set_source_rgb(xcb_ctx, rgb16[0] / 255.0, rgb16[1] / 255.0, rgb16[2] / 255.0);
155 cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]);
156 cairo_fill(xcb_ctx);
157
146 if (img) { 158 if (img) {
147 if (!tile) { 159 if (!tile) {
148 cairo_set_source_surface(xcb_ctx, img, 0, 0); 160 cairo_set_source_surface(xcb_ctx, img, 0, 0);
@@ -157,16 +169,6 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
157 cairo_fill(xcb_ctx); 169 cairo_fill(xcb_ctx);
158 cairo_pattern_destroy(pattern); 170 cairo_pattern_destroy(pattern);
159 } 171 }
160 } else {
161 char strgroups[3][3] = {{color[0], color[1], '\0'},
162 {color[2], color[3], '\0'},
163 {color[4], color[5], '\0'}};
164 uint32_t rgb16[3] = {(strtol(strgroups[0], NULL, 16)),
165 (strtol(strgroups[1], NULL, 16)),
166 (strtol(strgroups[2], NULL, 16))};
167 cairo_set_source_rgb(xcb_ctx, rgb16[0] / 255.0, rgb16[1] / 255.0, rgb16[2] / 255.0);
168 cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]);
169 cairo_fill(xcb_ctx);
170 } 172 }
171 173
172 if (unlock_indicator && 174 if (unlock_indicator &&
@@ -394,7 +396,18 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
394 cairo_surface_destroy(output); 396 cairo_surface_destroy(output);
395 cairo_destroy(ctx); 397 cairo_destroy(ctx);
396 cairo_destroy(xcb_ctx); 398 cairo_destroy(xcb_ctx);
397 return bg_pixmap; 399}
400
401static xcb_pixmap_t bg_pixmap = XCB_NONE;
402
403/*
404 * Releases the current background pixmap so that the next redraw_screen() call
405 * will allocate a new one with the updated resolution.
406 *
407 */
408void free_bg_pixmap(void) {
409 xcb_free_pixmap(conn, bg_pixmap);
410 bg_pixmap = XCB_NONE;
398} 411}
399 412
400/* 413/*
@@ -403,12 +416,16 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
403 */ 416 */
404void redraw_screen(void) { 417void redraw_screen(void) {
405 DEBUG("redraw_screen(unlock_state = %d, auth_state = %d)\n", unlock_state, auth_state); 418 DEBUG("redraw_screen(unlock_state = %d, auth_state = %d)\n", unlock_state, auth_state);
406 xcb_pixmap_t bg_pixmap = draw_image(last_resolution); 419 if (bg_pixmap == XCB_NONE) {
420 DEBUG("allocating pixmap for %d x %d px\n", last_resolution[0], last_resolution[1]);
421 bg_pixmap = create_bg_pixmap(conn, screen, last_resolution, color);
422 }
423
424 draw_image(bg_pixmap, last_resolution);
407 xcb_change_window_attributes(conn, win, XCB_CW_BACK_PIXMAP, (uint32_t[1]){bg_pixmap}); 425 xcb_change_window_attributes(conn, win, XCB_CW_BACK_PIXMAP, (uint32_t[1]){bg_pixmap});
408 /* XXX: Possible optimization: Only update the area in the middle of the 426 /* XXX: Possible optimization: Only update the area in the middle of the
409 * screen instead of the whole screen. */ 427 * screen instead of the whole screen. */
410 xcb_clear_area(conn, 0, win, 0, 0, last_resolution[0], last_resolution[1]); 428 xcb_clear_area(conn, 0, win, 0, 0, last_resolution[0], last_resolution[1]);
411 xcb_free_pixmap(conn, bg_pixmap);
412 xcb_flush(conn); 429 xcb_flush(conn);
413} 430}
414 431