i3lock-color

The world's most popular non-default computer lockscreen.
Index Commits Files Refs README LICENSE
commit 4c3fb648ee3b91de30f1bcee0d7b02f276bd8808
parent e07c3f0abeb86c74386cf70535f8c30b5ed46e7d
Author: Cassandra <cassandra@techfo.xyz>
Date:   Sun,  6 May 2018 21:06:25 -0400

Merge branch 'dev'

Diffstat:
Mi3lock.c | 140++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Munlock_indicator.c | 29+++++++++++++++++++++++++++++
2 files changed, 147 insertions(+), 22 deletions(-)
diff --git a/i3lock.c b/i3lock.c
@@ -17,6 +17,7 @@
 #include <pwd.h>
 #include <sys/types.h>
 #include <string.h>
+#include <dirent.h>
 #include <unistd.h>
 #include <stdbool.h>
 #include <stdint.h>
@@ -92,6 +93,7 @@ int screen_number = 0;
 int internal_line_source = 0;
 /* bool for showing the clock; why am I commenting this? */
 bool show_clock = false;
+bool slideshow_enabled = false;
 bool always_show_clock = false;
 bool show_indicator = false;
 float refresh_rate = 1.0;
@@ -205,6 +207,11 @@ 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 ignore_empty_password = false;
 bool skip_repeated_empty_password = false;
@@ -241,10 +248,19 @@ bool bar_reversed = false;
 #define isutf(c) (((c)&0xC0) != 0x80)
 
 /*
+ * Checks if the given path leads to an actual file or something else, e.g. a directory
+ */
+int is_regular_file(const char *path) {
+    struct stat path_stat;
+    stat(path, &path_stat);
+    return S_ISREG(path_stat.st_mode);
+}
+
+/*
  * Decrements i to point to the previous unicode glyph
  *
  */
-void u8_dec(char *s, int *i) {
+static void u8_dec(char *s, int *i) {
     (void)(isutf(s[--(*i)]) || isutf(s[--(*i)]) || isutf(s[--(*i)]) || --(*i));
 }
 
@@ -258,7 +274,7 @@ void u8_dec(char *s, int *i) {
  * credit to the XKB/xcb implementation (no libx11) from https://gist.github.com/bluetech/6061368
  * docs are really sparse, so finding some random implementation was nice
  */
-char* get_keylayoutname(int mode, xcb_connection_t* conn) {
+static char* get_keylayoutname(int mode, xcb_connection_t* conn) {
     if (mode < 0 || mode > 2) return NULL;
     char* newans = NULL, *answer = xcb_get_key_group_names(conn);
     DEBUG("keylayout answer is: [%s]\n", answer);
@@ -1069,11 +1085,78 @@ static void raise_loop(xcb_window_t window) {
     }
 }
 
+/*
+ * Loads an image from the given path. Handles JPEG and PNG. Returns NULL in case of error.
+ */
+static cairo_surface_t* load_image(char* image_path) {
+    cairo_surface_t *img = NULL;
+    JPEG_INFO jpg_info;
+
+    if (verify_png_image(image_path)) {
+        /* Create a pixmap to render on, fill it with the background color */
+        img = cairo_image_surface_create_from_png(image_path);
+    } else if (file_is_jpg(image_path)) {
+        DEBUG("Image looks like a jpeg, decoding\n");
+        unsigned char* jpg_data = read_JPEG_file(image_path, &jpg_info);
+            if (jpg_data != NULL) {
+                img = cairo_image_surface_create_for_data(jpg_data,
+                        CAIRO_FORMAT_ARGB32, jpg_info.width, jpg_info.height,
+                        jpg_info.stride);
+            }
+    }
+
+    /* In case loading failed, we just pretend no -i was specified. */
+    if (img && cairo_surface_status(img) != CAIRO_STATUS_SUCCESS) {
+        fprintf(stderr, "Could not load image \"%s\": %s\n",
+                image_path, cairo_status_to_string(cairo_surface_status(img)));
+        img = NULL;
+    }
+
+    return img;
+}
+
+/*
+ * Loads the images from the provided directory and stores them in the pointer array
+ * img_slideshow
+ */
+static void load_slideshow_images(const char *path) {
+    slideshow_enabled = true;
+    DIR *d;
+    struct dirent *dir;
+    int file_count = 0;
+
+    d = opendir(path);
+    if (d == NULL) {
+        printf("Could not open directory: %s\n", path);
+        exit(0);
+    }
+
+    while ((dir = readdir(d)) != NULL) {
+        if (file_count >= 256) {
+            break;
+        }
+
+        char path_to_image[256];
+        strcpy(path_to_image, path);
+        strcat(path_to_image, "/");
+        strcat(path_to_image, dir->d_name);
+
+        img_slideshow[file_count] = load_image(path_to_image);
+
+        if (img_slideshow[file_count] != NULL) {
+            ++file_count;
+        }
+    }
+
+    slideshow_image_count = file_count;
+
+    closedir(d);
+}
+
 int main(int argc, char *argv[]) {
     struct passwd *pw;
     char *username;
     char *image_path = NULL;
-    JPEG_INFO jpg_info;
 #ifndef __OpenBSD__
     int ret;
     struct pam_conv conv = {conv_callback, NULL};
@@ -1192,6 +1275,10 @@ int main(int argc, char *argv[]) {
         {"composite", no_argument, NULL, 902},
         {"pass-media-keys", no_argument, NULL, 'm'},
 
+        /* slideshow options */
+        {"slideshow-interval", required_argument, NULL, 903},
+        {"slideshow-random-selection", no_argument, NULL, 904},
+
         {NULL, no_argument, NULL, 0}};
 
     if ((pw = getpwuid(getuid())) == NULL)
@@ -1499,7 +1586,9 @@ int main(int argc, char *argv[]) {
                 break;
 // Positions
             case 540:
+                //read in to time_x_expr and time_y_expr
                 if (strlen(optarg) > 31) {
+                    // this is overly restrictive since both the x and y string buffers have size 32, but it's easier to check.
                     errx(1, "time position string can be at most 31 characters\n");
                 }
                 arg = optarg;
@@ -1508,7 +1597,9 @@ int main(int argc, char *argv[]) {
                 }
                 break;
             case 541:
+                //read in to date_x_expr and date_y_expr
                 if (strlen(optarg) > 31) {
+                    // this is overly restrictive since both the x and y string buffers have size 32, but it's easier to check.
                     errx(1, "date position string can be at most 31 characters\n");
                 }
                 arg = optarg;
@@ -1517,6 +1608,7 @@ int main(int argc, char *argv[]) {
                 }
                 break;
             case 542:
+                //read in to time_x_expr and time_y_expr
                 if (strlen(optarg) > 31) {
                     errx(1, "verif position string can be at most 31 characters\n");
                 }
@@ -1545,6 +1637,7 @@ int main(int argc, char *argv[]) {
                 break;
             case 545:
                 if (strlen(optarg) > 31) {
+                    // this is overly restrictive since both the x and y string buffers have size 32, but it's easier to check.
                     errx(1, "status position string can be at most 31 characters\n");
                 }
                 arg = optarg;
@@ -1554,6 +1647,7 @@ int main(int argc, char *argv[]) {
                 break;
             case 546:
                 if (strlen(optarg) > 31) {
+                    // this is overly restrictive since both the x and y string buffers have size 32, but it's easier to check.
                     errx(1, "modif position string can be at most 31 characters\n");
                 }
                 arg = optarg;
@@ -1563,6 +1657,7 @@ int main(int argc, char *argv[]) {
                 break;
             case 547:
                 if (strlen(optarg) > 31) {
+                    // this is overly restrictive since both the x and y string buffers have size 32, but it's easier to check.
                     errx(1, "indicator position string can be at most 31 characters\n");
                 }
                 arg = optarg;
@@ -1648,6 +1743,16 @@ int main(int argc, char *argv[]) {
             case 902:
                 composite = true;
                 break;
+            case 903:
+                slideshow_interval = atoi(optarg);
+
+                if (slideshow_interval < 0) {
+                    slideshow_interval = 10;
+                }
+                break;
+            case 904:
+                slideshow_random_selection = true;
+                break;
             case 'm':
                 pass_media_keys = true;
                 break;
@@ -1778,25 +1883,16 @@ int main(int argc, char *argv[]) {
                                  (uint32_t[]){XCB_EVENT_MASK_STRUCTURE_NOTIFY});
 
     init_colors_once();
-    if (verify_png_image(image_path)) {
-        /* Create a pixmap to render on, fill it with the background color */
-        img = cairo_image_surface_create_from_png(image_path);
-    } else if (file_is_jpg(image_path)) {
-        DEBUG("Image looks like a jpeg, decoding\n");
-        unsigned char* jpg_data = read_JPEG_file(image_path, &jpg_info);
-            if (jpg_data != NULL) {
-                img = cairo_image_surface_create_for_data(jpg_data,
-                        CAIRO_FORMAT_ARGB32, jpg_info.width, jpg_info.height,
-                        jpg_info.stride);
-            }
-    }
-    /* In case loading failed, we just pretend no -i was specified. */
-    if (img && cairo_surface_status(img) != CAIRO_STATUS_SUCCESS) {
-        fprintf(stderr, "Could not load image \"%s\": %s\n",
-                image_path, cairo_status_to_string(cairo_surface_status(img)));
-        img = NULL;
+    if (image_path != NULL) {
+        if (is_regular_file(image_path)) {
+            img = load_image(image_path);
+        } else {
+            /* Path to a directory is provided -> use slideshow mode */
+            load_slideshow_images(image_path);
+        }
+
+        free(image_path);
     }
-    free(image_path);
 
     xcb_pixmap_t* blur_pixmap = NULL;
     if (blur) {
@@ -1916,7 +2012,7 @@ int main(int argc, char *argv[]) {
      * file descriptor becomes readable). */
     ev_invoke(main_loop, xcb_check, 0);
 
-    if (show_clock || bar_enabled) {
+    if (show_clock || bar_enabled || slideshow_enabled) {
         if (redraw_thread) {
             struct timespec ts;
             double s;
diff --git a/unlock_indicator.c b/unlock_indicator.c
@@ -59,6 +59,12 @@ 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;
+extern bool slideshow_random_selection;
+
+unsigned long lastCheck;
 
 /* Whether the image should be tiled. */
 extern bool tile;
@@ -148,6 +154,8 @@ static struct ev_periodic *time_redraw_tick;
 /* Cache the screen’s visual, necessary for creating a Cairo context. */
 static xcb_visualtype_t *vistype;
 
+int current_slideshow_index = 0;
+
 /* Maintain the current unlock/PAM state to draw the appropriate unlock
  * indicator. */
 unlock_state_t unlock_state;
@@ -578,6 +586,10 @@ static void colorgen_rgb(rgb_str_t *tmp, const char *src, rgb_t *dest) {
 }
 
 void init_colors_once(void) {
+
+    /* initialize for slideshow time interval */
+    lastCheck = (unsigned long)time(NULL);
+
     rgba_str_t tmp;
     rgb_str_t tmp_rgb;
 
@@ -682,6 +694,23 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
     cairo_surface_t *xcb_output = cairo_xcb_surface_create(conn, bg_pixmap, vistype, resolution[0], resolution[1]);
     cairo_t *xcb_ctx = cairo_create(xcb_output);
 
+    /*update image according to the slideshow_interval*/
+    if (slideshow_image_count > 0) {
+        unsigned long now = (unsigned long)time(NULL);
+        if (img == NULL || now - lastCheck >= slideshow_interval) {
+            if (slideshow_random_selection) {
+                img = img_slideshow[rand() % slideshow_image_count];
+            } else {
+                img = img_slideshow[current_slideshow_index++];
+
+                if (current_slideshow_index >= slideshow_image_count) {
+                    current_slideshow_index = 0;
+                }
+            }
+            lastCheck = now;
+        }
+    }
+
     if (blur_img || img) {
         if (blur_img) {
             cairo_set_source_surface(xcb_ctx, blur_img, 0, 0);