i3lock-color

The world's most popular non-default computer lockscreen.
Index Commits Files Refs README LICENSE
commit 1aa7edc7a74d9e0bd003ec6362c3a58b92fd65b4
parent c17338052fc6edd47b95ca86e274104f5ad50e85
Author: Raymond Li <hi@raymond.li>
Date:   Mon, 15 Feb 2021 01:05:51 -0500

Merge pull request #197 from Rio6/bar-count

New --bar-count option to replace --bar-width
Diffstat:
Mexamples/lock_bar.sh | 11++++-------
Mi3lock.1 | 6++++++
Mi3lock.c | 44++++++++++++++++++++++++++++++++++----------
Munlock_indicator.c | 196+++++++++++++++++++++++++++++++------------------------------------------------
Munlock_indicator.h | 2+-
5 files changed, 122 insertions(+), 137 deletions(-)
diff --git a/examples/lock_bar.sh b/examples/lock_bar.sh
@@ -10,7 +10,7 @@ V='#bb00bbbb'  # verifying
 i3lock \
 --blur 5 \
 --bar-indicator \
---bar-position h \
+--bar-position y+h \
 --bar-direction 1 \
 --bar-max-height 50 \
 --bar-base-width 50 \
@@ -18,12 +18,11 @@ i3lock \
 --keyhlcolor 880088cc \
 --bar-periodic-step 50 \
 --bar-step 50 \
---bar-width 250 \
 --redraw-thread \
 \
 --clock \
 --force-clock \
---timepos 5:h-80 \
+--timepos x+5:y+h-80 \
 --timecolor 880088ff \
 --datepos tx:ty+15 \
 --datecolor 990099ff \
@@ -31,11 +30,9 @@ i3lock \
 --time-align 1 \
 --ringvercolor 8800ff88 \
 --ringwrongcolor ff008888 \
---statuspos 5:h-16 \
+--statuspos x+5:y+h-16 \
 --verif-align 1 \
 --wrong-align 1 \
 --verifcolor ffffffff \
 --wrongcolor ffffffff \
---modifpos -50:-50 \
-\
---screen 1
+--modifpos -50:-50
diff --git a/i3lock.1 b/i3lock.1
@@ -404,6 +404,8 @@ Sets the direction the bars grow in. 0 is the default (downwards, or rightwards,
 
 .TP
 .B \-\-bar\-width=15
+Deprecated, use \-\-bar\-count instead.
+
 Sets the width of the minibars in the bar.
 
 .TP
@@ -439,6 +441,10 @@ Works similarly to the time/date/indicator expressions. If the bar is horizontal
 If it's vertically oriented, this sets the horizontal offset from the left edge.
 
 .TP
+.B \-\-bar\-count=10
+Sets the number of minibars to draw on each screen.
+
+.TP
 .B \-\-no\-verify
 Do not verify the password entered by the user and unlock immediately.
 .B Use only for quickly testing new configurations and remember to remove to actually lock your screen!
diff --git a/i3lock.c b/i3lock.c
@@ -262,20 +262,23 @@ pthread_t draw_thread;
 // allow you to disable. handy if you use bar with lots of crap.
 bool redraw_thread = false;
 
+// experimental bar stuff
 #define BAR_VERT 0
 #define BAR_FLAT 1
 #define BAR_DEFAULT 0
 #define BAR_REVERSED 1
 #define BAR_BIDIRECTIONAL 2
-// experimental bar stuff
+#define MAX_BAR_COUNT 65535
+#define MIN_BAR_COUNT 2
+
 bool bar_enabled = false;
 double *bar_heights = NULL;
 double bar_step = 15;
 double bar_base_height = 25;
 double bar_periodic_step = 15;
 double max_bar_height = 25;
-int num_bars = 0;
-int bar_width = 150;
+int bar_count = 0;
+int bar_width = 0;
 int bar_orientation = BAR_FLAT;
 
 char bar_base_color[9] = "000000ff";
@@ -1544,6 +1547,7 @@ int main(int argc, char *argv[]) {
         {"bar-color", required_argument, NULL, 707},
         {"bar-periodic-step", required_argument, NULL, 708},
         {"bar-position", required_argument, NULL, 709},
+        {"bar-count", required_argument, NULL, 710},
 
         // misc.
         {"redraw-thread", no_argument, NULL, 900},
@@ -2090,7 +2094,6 @@ int main(int argc, char *argv[]) {
             case 702:
                 bar_width = atoi(optarg);
                 if (bar_width < 1) bar_width = 150;
-                // num_bars and bar_heights* initialized later when we grab display info
                 break;
             case 703:
                 arg = optarg;
@@ -2132,6 +2135,12 @@ int main(int argc, char *argv[]) {
                     errx(1, "bar-position must be of the form [pos] with a max length of 31\n");
                 }
                 break;
+            case 710:
+                bar_count = atoi(optarg);
+                if (bar_count > MAX_BAR_COUNT || bar_count < MIN_BAR_COUNT) {
+                    errx(1, "bar-count must be between %d and %d\n", MIN_BAR_COUNT, MAX_BAR_COUNT);
+                }
+                break;
 
             // Misc
             case 900:
@@ -2278,13 +2287,28 @@ int main(int argc, char *argv[]) {
     last_resolution[0] = screen->width_in_pixels;
     last_resolution[1] = screen->height_in_pixels;
 
-    if (bar_enabled && bar_width > 0) {
-        int tmp = screen->width_in_pixels;
-        if (bar_orientation == BAR_VERT) tmp = screen->height_in_pixels;
-        num_bars = tmp / bar_width;
-        if (tmp % bar_width != 0) ++num_bars;
+    if (bar_enabled) {
+        if (bar_count == 0) {
+            if (bar_width != 0) {
+                fprintf(stderr, "Warning: bar-width is deprecated, use bar-count instead\n");
+                int tmp = screen->width_in_pixels;
+                if (bar_orientation == BAR_VERT) tmp = screen->height_in_pixels;
+                bar_count = tmp / bar_width;
+                if (tmp % bar_width != 0) {
+                    ++bar_count;
+                }
+            } else {
+                bar_count = MIN_BAR_COUNT;
+            }
+        } else if (bar_width != 0) {
+            errx(EXIT_FAILURE, "bar-width and bar-count cannot be used at the same time");
+        }
 
-        bar_heights = (double*) calloc(num_bars, sizeof(double));
+        if (bar_count >= MIN_BAR_COUNT && bar_count <= MAX_BAR_COUNT) {
+            bar_heights = (double*) calloc(bar_count, sizeof(double));
+        } else {
+            bar_enabled = false;
+        }
     }
 
     xcb_change_window_attributes(conn, screen->root, XCB_CW_EVENT_MASK,
diff --git a/unlock_indicator.c b/unlock_indicator.c
@@ -228,8 +228,7 @@ extern double bar_base_height;
 extern double bar_periodic_step;
 extern double max_bar_height;
 extern double bar_position;
-extern int num_bars;
-extern int bar_width;
+extern int bar_count;
 extern int bar_orientation;
 
 extern char bar_base_color[9];
@@ -342,119 +341,74 @@ static void draw_text(cairo_t *ctx, text_t text) {
     cairo_stroke(ctx);
 }
 
-static void draw_bar(cairo_t *ctx, double x, double y, double bar_offset) {
-    // oh boy, here we go!
-    // TODO: get this to play nicely with multiple monitors
-    // ideally it'd intelligently span both monitors
-    double width, height;
-    double back_x = 0, back_y = 0, back_x2 = 0, back_y2 = 0, back_width = 0, back_height = 0;
-    for (int i = 0; i < num_bars; ++i) {
-        double cur_bar_height = bar_heights[i];
-
-        if (cur_bar_height > 0) {
-            if (unlock_state == STATE_BACKSPACE_ACTIVE) {
-                cairo_set_source_rgba(ctx, bshl16.red, bshl16.green, bshl16.blue, bshl16.alpha);
-            } else {
-                cairo_set_source_rgba(ctx, keyhl16.red, keyhl16.green, keyhl16.blue, keyhl16.alpha);
-            }
-        } else {
-            switch (auth_state) {
-                case STATE_AUTH_VERIFY:
-                case STATE_AUTH_LOCK:
-                    cairo_set_source_rgba(ctx, ringver16.red, ringver16.green, ringver16.blue, ringver16.alpha);
-                    break;
-                case STATE_AUTH_WRONG:
-                case STATE_I3LOCK_LOCK_FAILED:
-                    cairo_set_source_rgba(ctx, ringwrong16.red, ringwrong16.green, ringwrong16.blue, ringwrong16.alpha);
-                    break;
-                default:
-                    cairo_set_source_rgba(ctx, bar16.red, bar16.green, bar16.blue, bar16.alpha);
-                    break;
-            }
-        }
+static void draw_single_bar(cairo_t *ctx, double pos, double offset, double width, double height) {
+    if (bar_reversed) {
+        offset -= height;
+    } else if (bar_bidirectional) {
+        offset -= height / 2;
+    }
 
-        if (bar_orientation == BAR_VERT) {
-            width = (cur_bar_height <= 0 ? bar_base_height : cur_bar_height);
-            height = bar_width;
-            x = bar_offset;
-            y = i * bar_width;
-            if (bar_reversed) {
-                x -= width;
-            } else if (bar_bidirectional) {
-                width = (cur_bar_height <= 0 ? bar_base_height : cur_bar_height * 2);
-                x = bar_offset - (width / 2) + (bar_base_height / 2);
-            }
-        } else {
-            width = bar_width;
-            height = (cur_bar_height <= 0 ? bar_base_height : cur_bar_height);
-            x = i * bar_width;
-            y = bar_offset;
-            if (bar_reversed) {
-                y -= height;
-            } else if (bar_bidirectional) {
-                height = (cur_bar_height <= 0 ? bar_base_height : cur_bar_height * 2);
-                y = bar_offset - (height / 2) + (bar_base_height / 2);
-            }
-        }
+    if (bar_orientation == BAR_VERT)
+        cairo_rectangle(ctx, offset, pos, height, width);
+    else
+        cairo_rectangle(ctx, pos, offset, width, height);
+    cairo_fill(ctx);
+}
 
-        if (cur_bar_height < bar_base_height && cur_bar_height > 0) {
-            if (bar_orientation == BAR_VERT) {
-                back_x = bar_offset + cur_bar_height;
-                back_y = y;
-                back_width = bar_base_height - cur_bar_height;
-                back_height = height;
-                if (bar_reversed) {
-                    back_x = bar_offset - bar_base_height;
-                } else if (bar_bidirectional) {
-                    back_x = bar_offset;
-                    back_y2 = y;
-                    back_width = (bar_base_height - (cur_bar_height * 2)) / 2;
-                    back_x2 = bar_offset + (cur_bar_height * 2) + back_width;
-                }
-            } else {
-                back_x = x;
-                back_y = bar_offset + cur_bar_height;
-                back_width = width;
-                back_height = bar_base_height - cur_bar_height;
-                if (bar_reversed) {
-                    back_y = bar_offset - bar_base_height;
-                } else if (bar_bidirectional) {
-                    back_x2 = x;
-                    back_y = bar_offset;
-                    back_height = (bar_base_height - (cur_bar_height * 2)) / 2;
-                    back_y2 = bar_offset + (cur_bar_height * 2) + back_height;
-                }
-            }
-        }
-        cairo_rectangle(ctx, x, y, width, height);
-        cairo_fill(ctx);
-        switch (auth_state) {
-            case STATE_AUTH_VERIFY:
-            case STATE_AUTH_LOCK:
-                cairo_set_source_rgba(ctx, ringver16.red, ringver16.green, ringver16.blue, ringver16.alpha);
-                break;
-            case STATE_AUTH_WRONG:
-            case STATE_I3LOCK_LOCK_FAILED:
-                cairo_set_source_rgba(ctx, ringwrong16.red, ringwrong16.green, ringwrong16.blue, ringwrong16.alpha);
-                break;
-            default:
-                cairo_set_source_rgba(ctx, bar16.red, bar16.green, bar16.blue, bar16.alpha);
-                break;
-        }
+static void draw_bar(cairo_t *ctx, double bar_offset, double screen_x, double screen_y, double screen_w, double screen_h) {
 
-        if (cur_bar_height > 0 && cur_bar_height < bar_base_height && ((bar_bidirectional && ((cur_bar_height * 2) < bar_base_height)) || (!bar_bidirectional && (cur_bar_height < bar_base_height)))) {
-            cairo_rectangle(ctx, back_x, back_y, back_width, back_height);
-            cairo_fill(ctx);
-            if (bar_bidirectional) {
-                cairo_rectangle(ctx, back_x2, back_y2, back_width, back_height);
-                cairo_fill(ctx);
-            }
+    cairo_save(ctx);
+
+    switch (auth_state) {
+        case STATE_AUTH_VERIFY:
+        case STATE_AUTH_LOCK:
+            cairo_set_source_rgba(ctx, ringver16.red, ringver16.green, ringver16.blue, ringver16.alpha);
+            break;
+        case STATE_AUTH_WRONG:
+        case STATE_I3LOCK_LOCK_FAILED:
+            cairo_set_source_rgba(ctx, ringwrong16.red, ringwrong16.green, ringwrong16.blue, ringwrong16.alpha);
+            break;
+        default:
+            cairo_set_source_rgba(ctx, bar16.red, bar16.green, bar16.blue, bar16.alpha);
+            break;
+    }
+
+    if (bar_orientation == BAR_VERT)
+        draw_single_bar(ctx, screen_y, bar_offset, screen_h, bar_base_height);
+    else
+        draw_single_bar(ctx, screen_x, bar_offset, screen_w, bar_base_height);
+
+    if (unlock_state == STATE_BACKSPACE_ACTIVE)
+        cairo_set_source_rgba(ctx, bshl16.red, bshl16.green, bshl16.blue, bshl16.alpha);
+    else
+        cairo_set_source_rgba(ctx, keyhl16.red, keyhl16.green, keyhl16.blue, keyhl16.alpha);
+
+    cairo_set_operator(ctx, CAIRO_OPERATOR_SOURCE);
+
+    double bar_width, screen_pos;
+    if (bar_orientation == BAR_VERT) {
+        bar_width = screen_h / bar_count;
+        screen_pos = screen_y;
+    } else {
+        bar_width = screen_w / bar_count;
+        screen_pos = screen_x;
+    }
+
+    for (int i = 0; i < bar_count; ++i) {
+        double bar_height = bar_heights[i];
+        if (bar_bidirectional) bar_height *= 2;
+        if (bar_height > 0) {
+            draw_single_bar(ctx, screen_pos + i * bar_width, bar_offset, bar_width, bar_height);
         }
     }
-    for (int i = 0; i < num_bars; ++i) {
-        if (bar_heights[i] > 0)
+
+    for (int i = 0; i < bar_count; ++i) {
+        if (bar_heights[i] > 0) {
             bar_heights[i] -= bar_periodic_step;
+        }
     }
+
+    cairo_restore(ctx);
 }
 
 static void draw_indic(cairo_t *ctx, double ind_x, double ind_y) {
@@ -663,15 +617,15 @@ static void draw_elements(cairo_t *const ctx, DrawData const *const draw_data) {
         if (unlock_state == STATE_KEY_ACTIVE ||
             unlock_state == STATE_BACKSPACE_ACTIVE) {
             // note: might be biased to cause more hits on lower indices
-            // maybe see about doing ((double) rand() / RAND_MAX) * num_bars
-            int index = rand() % num_bars;
+            // maybe see about doing ((double) rand() / RAND_MAX) * bar_count
+            int index = rand() % bar_count;
             bar_heights[index] = max_bar_height;
             for (int i = 0; i < ((max_bar_height / bar_step) + 1); ++i) {
                 int low_ind = index - i;
                 while (low_ind < 0) {
-                    low_ind += num_bars;
+                    low_ind += bar_count;
                 }
-                int high_ind = (index + i) % num_bars;
+                int high_ind = (index + i) % bar_count;
                 int tmp_height = max_bar_height - (bar_step * i);
                 if (tmp_height < 0)
                     tmp_height = 0;
@@ -683,7 +637,7 @@ static void draw_elements(cairo_t *const ctx, DrawData const *const draw_data) {
                     break;
             }
         }
-        draw_bar(ctx, draw_data->bar_x, draw_data->bar_y, draw_data->bar_offset);
+        draw_bar(ctx, draw_data->bar_offset, draw_data->screen_x, draw_data->screen_y, draw_data->screen_w, draw_data->screen_h);
     }
 
     draw_text(ctx, draw_data->status_text);
@@ -971,6 +925,10 @@ void render_lock(uint32_t *resolution, xcb_drawable_t drawable) {
             height = xr_resolutions[current_screen].height / scaling_factor;
             screen_x = xr_resolutions[current_screen].x / scaling_factor;
             screen_y = xr_resolutions[current_screen].y / scaling_factor;
+            draw_data.screen_w = width;
+            draw_data.screen_h = height;
+            draw_data.screen_x = screen_x;
+            draw_data.screen_y = screen_y;
             if (te_ind_x_expr && te_ind_y_expr) {
                 draw_data.indicator_x = te_eval(te_ind_x_expr);
                 draw_data.indicator_y = te_eval(te_ind_y_expr);
@@ -978,8 +936,6 @@ void render_lock(uint32_t *resolution, xcb_drawable_t drawable) {
                 draw_data.indicator_x = screen_x + width / 2;
                 draw_data.indicator_y = screen_y + height / 2;
             }
-            draw_data.bar_x = draw_data.indicator_x - (button_diameter_physical / 2);
-            draw_data.bar_y = draw_data.indicator_y - (button_diameter_physical / 2);
             draw_data.bar_offset = te_eval(te_bar_expr);
             draw_data.time_text.x = te_eval(te_time_x_expr);
             draw_data.time_text.y = te_eval(te_time_y_expr);
@@ -1011,7 +967,7 @@ void render_lock(uint32_t *resolution, xcb_drawable_t drawable) {
             draw_data.mod_text.y = te_eval(te_modif_y_expr);
 
             DEBUG("Indicator at %fx%f on screen %d\n", draw_data.indicator_x, draw_data.indicator_y, current_screen + 1);
-            DEBUG("Bar at %fx%f on screen %d\n", draw_data.bar_x, draw_data.bar_y, current_screen + 1);
+            DEBUG("Bar at %f on screen %d\n", draw_data.bar_offset, current_screen + 1);
             DEBUG("Time at %fx%f on screen %d\n", draw_data.time_text.x, draw_data.time_text.y, current_screen + 1);
             DEBUG("Date at %fx%f on screen %d\n", draw_data.date_text.x, draw_data.date_text.y, current_screen + 1);
             DEBUG("Layout at %fx%f on screen %d\n", draw_data.keylayout_text.x, draw_data.keylayout_text.y, current_screen + 1);
@@ -1026,10 +982,12 @@ void render_lock(uint32_t *resolution, xcb_drawable_t drawable) {
          * hope for the best. */
         width = last_resolution[0] / scaling_factor;
         height = last_resolution[1] / scaling_factor;
+        draw_data.screen_w = width;
+        draw_data.screen_h = height;
+        draw_data.screen_x = 0;
+        draw_data.screen_y = 0;
         draw_data.indicator_x = width / 2;
         draw_data.indicator_y = height / 2;
-        draw_data.bar_x = draw_data.indicator_x - (button_diameter_physical / 2);
-        draw_data.bar_y = draw_data.indicator_y - (button_diameter_physical / 2);
 
         draw_data.time_text.x = te_eval(te_time_x_expr);
         draw_data.time_text.y = te_eval(te_time_y_expr);
@@ -1059,7 +1017,7 @@ void render_lock(uint32_t *resolution, xcb_drawable_t drawable) {
         draw_data.mod_text.y = te_eval(te_modif_y_expr);
 
         DEBUG("Indicator at %fx%f\n", draw_data.indicator_x, draw_data.indicator_y);
-        DEBUG("Bar at %fx%f\n", draw_data.bar_x, draw_data.bar_y);
+        DEBUG("Bar at %f\n", draw_data.bar_offset);
         DEBUG("Time at %fx%f\n", draw_data.time_text.x, draw_data.time_text.y);
         DEBUG("Date at %fx%f\n", draw_data.date_text.x, draw_data.date_text.y);
         DEBUG("Layout at %fx%f\n", draw_data.keylayout_text.x, draw_data.keylayout_text.y);
diff --git a/unlock_indicator.h b/unlock_indicator.h
@@ -34,7 +34,7 @@ typedef struct {
 
     double indicator_x, indicator_y;
 
-    double bar_x, bar_y;
+    double screen_x, screen_y, screen_w, screen_h;
     double bar_offset;
 } DrawData;