commit 4c3fb648ee3b91de30f1bcee0d7b02f276bd8808
parent e07c3f0abeb86c74386cf70535f8c30b5ed46e7d
Author: Cassandra <cassandra@techfo.xyz>
Date: Sun, 6 May 2018 21:06:25 -0400
Merge branch 'dev'
Diffstat:
| M | i3lock.c | | | 140 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- |
| M | unlock_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);