i3lock-color

The world's most popular non-default computer lockscreen.
Index Commits Files Refs README LICENSE
commit 91092a1bf1c24a9ea82f169f3d4502ad3bc5fdeb
parent de35e177fb6a56ba2f6a2f069eefff8cf4c5195d
Author: Rio6 <rio.liu@r26.me>
Date:   Sat, 29 May 2021 00:27:15 -0400

refactor background types to use enum

Diffstat:
Mi3lock.c | 46+++++++++++++++++++++++++++++++++-------------
Munlock_indicator.c | 99+++++++++++++++++++++++++++++++++++--------------------------------------------
Munlock_indicator.h | 11++++++++++-
3 files changed, 87 insertions(+), 69 deletions(-)
diff --git a/i3lock.c b/i3lock.c
@@ -243,14 +243,13 @@ static uint8_t xkb_base_error;
 static int randr_base = -1;
 
 cairo_surface_t *img = NULL;
-cairo_surface_t *blur_img = NULL;
 cairo_surface_t *img_slideshow[256];
 int slideshow_image_count = 0;
 int slideshow_interval = 10;
 bool slideshow_random_selection = false;
 
-bool tile = false;
-bool centered = false;
+background_type_t bg_type = NONE;
+
 bool ignore_empty_password = false;
 bool skip_repeated_empty_password = false;
 bool pass_media_keys = false;
@@ -1435,6 +1434,9 @@ int main(int argc, char *argv[]) {
         {"raw", required_argument, NULL, 998},
         {"tiling", no_argument, NULL, 't'},
         {"centered", no_argument, NULL, 'C'},
+        {"fill", no_argument, NULL, 'F'},
+        {"scale", no_argument, NULL, 'L'},
+        {"scale", no_argument, NULL, 'M'},
         {"ignore-empty-password", no_argument, NULL, 'e'},
         {"inactivity-timeout", required_argument, NULL, 'I'},
         {"show-failed-attempts", no_argument, NULL, 'f'},
@@ -1624,16 +1626,33 @@ int main(int argc, char *argv[]) {
                 image_path = strdup(optarg);
                 break;
             case 't':
-                if(centered) {
-                    errx(EXIT_FAILURE, "i3lock-color: Options tiling and centered conflict.");
+                if(bg_type != NONE) {
+                    errx(EXIT_FAILURE, "i3lock-color: Options tiling, centered, and fill conflict.");
                 }
-                tile = true;
+                bg_type = TILE;
                 break;
             case 'C':
-                if(tile) {
-                    errx(EXIT_FAILURE, "i3lock-color: Options tiling and centered conflict.");
+                if(bg_type != NONE) {
+                    errx(EXIT_FAILURE, "i3lock-color: Options tiling, centered, and fill conflict.");
+                }
+                bg_type = CENTER;
+                break;
+            case 'F':
+                if(bg_type != NONE) {
+                    errx(EXIT_FAILURE, "i3lock-color: Options tiling, centered, and fill conflict.");
+                }
+                bg_type = FILL;
+            case 'L':
+                if(bg_type != NONE) {
+                    errx(EXIT_FAILURE, "i3lock-color: Options tiling, centered, and fill conflict.");
                 }
-                centered = true;
+                bg_type = SCALE;
+                break;
+            case 'M':
+                if(bg_type != NONE) {
+                    errx(EXIT_FAILURE, "i3lock-color: Options tiling, centered, and fill conflict.");
+                }
+                bg_type = MAX;
                 break;
             case 'p':
                 if (!strcmp(optarg, "win")) {
@@ -2349,20 +2368,21 @@ int main(int argc, char *argv[]) {
         *blur_pixmap = capture_bg_pixmap(conn, screen, last_resolution);
         cairo_surface_t *xcb_img = cairo_xcb_surface_create(conn, *blur_pixmap, vistype, last_resolution[0], last_resolution[1]);
 
-        blur_img = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, last_resolution[0], last_resolution[1]);
+        cairo_surface_t *blur_img = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, last_resolution[0], last_resolution[1]);
         cairo_t *ctx = cairo_create(blur_img);
         cairo_set_source_surface(ctx, xcb_img, 0, 0);
         cairo_paint(ctx);
 
         blur_image_surface(blur_img, blur_sigma);
         if (img) {
-            // Display image centered on all outputs.
-            draw_image(last_resolution, ctx);
+            // Display image on all outputs.
+            draw_image(last_resolution, img, ctx);
             cairo_surface_destroy(img);
-            img = NULL;
         }
         cairo_destroy(ctx);
         cairo_surface_destroy(xcb_img);
+
+        img = blur_img;
     }
 
     xcb_window_t stolen_focus = find_focused_window(conn, screen->root);
diff --git a/unlock_indicator.c b/unlock_indicator.c
@@ -62,7 +62,6 @@ extern char *modifier_string;
 
 /* A Cairo surface containing the specified image (-i), if any. */
 extern cairo_surface_t *img;
-extern cairo_surface_t *blur_img;
 extern cairo_surface_t *img_slideshow[256];
 extern int slideshow_image_count;
 extern int slideshow_interval;
@@ -70,9 +69,8 @@ extern bool slideshow_random_selection;
 
 unsigned long lastCheck;
 
-/* Whether the image should be tiled or centered. */
-extern bool centered;
-extern bool tile;
+/* How the background image should be displayed */
+extern background_type_t bg_type;
 /* The background color to use (in hex). */
 extern char color[9];
 /* indicator color options */
@@ -699,13 +697,8 @@ void render_lock(uint32_t *resolution, xcb_drawable_t drawable) {
         }
     }
 
-    if (blur_img || img) {
-        if (blur_img) {
-            cairo_set_source_surface(xcb_ctx, blur_img, 0, 0);
-            cairo_paint(xcb_ctx);
-        } else {  // img can no longer be non-NULL if blur_img is not null
-            draw_image(resolution, xcb_ctx);
-        }
+    if (img) {
+        draw_image(resolution, img, xcb_ctx);
     } else {
         cairo_set_source_rgba(xcb_ctx, background.red, background.green, background.blue, background.alpha);
         cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]);
@@ -1108,54 +1101,50 @@ void render_lock(uint32_t *resolution, xcb_drawable_t drawable) {
  * Draws the configured image on the provided context. The image is drawn centered on all monitors, tiled, or just
  * painted starting from 0,0.
  */
-void draw_image(uint32_t* resolution, cairo_t* xcb_ctx) {
-    if (centered) {
-        double image_width = cairo_image_surface_get_width(img);
-        double image_height = cairo_image_surface_get_height(img);
-
-        xcb_randr_get_screen_resources_current_reply_t *reply = xcb_randr_get_screen_resources_current_reply(
-                conn, xcb_randr_get_screen_resources_current(conn, screen->root), NULL);
-
-        xcb_timestamp_t timestamp = reply->config_timestamp;
-        int len = xcb_randr_get_screen_resources_current_outputs_length(reply);
-        xcb_randr_output_t *randr_outputs = xcb_randr_get_screen_resources_current_outputs(reply);
-
-        // For every output
-        for (int i = 0; i < len; i++) {
-            xcb_randr_get_output_info_reply_t *output = xcb_randr_get_output_info_reply(
-                    conn, xcb_randr_get_output_info(conn, randr_outputs[i], timestamp), NULL);
-            if (output == NULL)
-                continue;
-
-            if (output->crtc == XCB_NONE || output->connection == XCB_RANDR_CONNECTION_DISCONNECTED)
-                continue;
+void draw_image(uint32_t* root_resolution, cairo_surface_t *img, cairo_t* xcb_ctx) {
+    double image_width = cairo_image_surface_get_width(img);
+    double image_height = cairo_image_surface_get_height(img);
+
+    switch (bg_type) {
+        case CENTER:
+        case FILL:
+        case SCALE:
+        case MAX:
+            cairo_save(xcb_ctx);
+            for (int i = 0; i < xr_screens; i++) {
+                // Paint around center of monitor
+                double origin_x = xr_resolutions[i].x + (xr_resolutions[i].width  / 2.0 - image_width  / 2.0);
+                double origin_y = xr_resolutions[i].y + (xr_resolutions[i].height / 2.0 - image_height / 2.0);
+
+                if (bg_type == SCALE) {
+                    cairo_scale(xcb_ctx,
+                        (double) xr_resolutions[i].width / image_width,
+                        (double) xr_resolutions[i].height / image_height);
+                }
 
-            xcb_randr_get_crtc_info_cookie_t infoCookie = xcb_randr_get_crtc_info(conn, output->crtc,
-                                                                                  timestamp);
-            xcb_randr_get_crtc_info_reply_t *crtc = xcb_randr_get_crtc_info_reply(conn, infoCookie, NULL);
+                cairo_set_source_surface(xcb_ctx, img, origin_x, origin_y);
+                cairo_paint(xcb_ctx);
+            }
+            cairo_restore(xcb_ctx);
+            break;
 
-            // Paint around center of monitor
-            double origin_x = crtc->x + (crtc->width / 2.0 - image_width / 2.0);
-            double origin_y = crtc->y + (crtc->height / 2.0 - image_height / 2.0);
+        case TILE:
+            {
+                /* create a pattern and fill a rectangle as big as the screen */
+                cairo_pattern_t *pattern;
+                pattern = cairo_pattern_create_for_surface(img);
+                cairo_set_source(xcb_ctx, pattern);
+                cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
+                cairo_rectangle(xcb_ctx, 0, 0, root_resolution[0], root_resolution[1]);
+                cairo_fill(xcb_ctx);
+                cairo_pattern_destroy(pattern);
+                break;
+            }
 
-            cairo_set_source_surface(xcb_ctx, img, origin_x, origin_y);
+        default:
+            cairo_set_source_surface(xcb_ctx, img, 0, 0);
             cairo_paint(xcb_ctx);
-
-            free(crtc);
-            free(output);
-        }
-    }  else if (tile) {
-        /* create a pattern and fill a rectangle as big as the screen */
-        cairo_pattern_t *pattern;
-        pattern = cairo_pattern_create_for_surface(img);
-        cairo_set_source(xcb_ctx, pattern);
-        cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
-        cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]);
-        cairo_fill(xcb_ctx);
-        cairo_pattern_destroy(pattern);
-    } else {
-        cairo_set_source_surface(xcb_ctx, img, 0, 0);
-        cairo_paint(xcb_ctx);
+            break;
     }
 
 }
diff --git a/unlock_indicator.h b/unlock_indicator.h
@@ -38,8 +38,17 @@ typedef struct {
     double bar_x, bar_y, bar_width;
 } DrawData;
 
+typedef enum {
+    NONE,
+    TILE,
+    CENTER,
+    FILL,
+    SCALE,
+    MAX,
+} background_type_t;
+
 void render_lock(uint32_t* resolution, xcb_drawable_t drawable);
-void draw_image(uint32_t* resolution, cairo_t* xcb_ctx);
+void draw_image(uint32_t* resolution, cairo_surface_t* img, cairo_t* xcb_ctx);
 void init_colors_once(void);
 void redraw_screen(void);
 void clear_indicator(void);