From f2ef5989e10861a60a6dcaf568e3158ef8d816be Mon Sep 17 00:00:00 2001 From: Aline Date: Fri, 19 May 2017 17:28:09 +0200 Subject: [PATCH] Separated time and date display --- README.md | 10 ++-- i3lock.c | 50 ++++++++++++---- unlock_indicator.c | 139 +++++++++++++++++++++++++++++---------------- 3 files changed, 134 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index a5cb947..985a54b 100644 --- a/README.md +++ b/README.md @@ -34,12 +34,14 @@ Many little improvements have been made to i3lock over time: - `-k, --clock` -- enables the clock display. - `-B, --blur` -- enables Gaussian blur - `--timestr="%H:%M:%S"` -- allows custom overriding of the time format string. Accepts `strftime` formatting. Default is `"%H:%M:%S"`. - - `--datestr="%A, %m %Y"` -- allows custom overriding of the date format string. Accepts `strftime` formatting. Default is `"%A, %m %Y"`. - - `--clockpos="ix:iy-20"` -- position of the clock. Expressions using the variables w (screen width), h (screen height), ix (indicator x position) and iy (indicator y position) can be used. - - `--clockcolor=rrggbbaa` -- color of the clock + - `--timepos="ix:iy-20"` -- position of the time. Expressions using the variables w (screen width), h (screen height), ix (indicator x position) and iy (indicator y position) can be used. + - `--timecolor=rrggbbaa` -- color of the time string - `--timefont="sans-serif"` -- font used for the time display - - `--datefont="sans-serif"` -- font used for the date display - `--timesize=32` -- font size for the time display + - `--datestr="%A, %m %Y"` -- allows custom overriding of the date format string. Accepts `strftime` formatting. Default is `"%A, %m %Y"`. + - `--datepos="ix:iy-20"` -- position of the date. Expressions using the variables w (screen width), h (screen height), ix (indicator x position), iy (indicator y position), tx (time x) and ty (time y) can be used. + - `--datecolor=rrggbbaa` -- color of the date string + - `--datefont="sans-serif"` -- font used for the date display - `--datesize=14` -- font size for the date display - All the colors have an alpha channel now. Please keep in mind that this was not intended when the program was originally written, so making things transparent that weren't before can make it look strange. diff --git a/i3lock.c b/i3lock.c index a0b9ca1..53d3d10 100644 --- a/i3lock.c +++ b/i3lock.c @@ -66,7 +66,8 @@ char ringwrongcolor[9] = "7d3300ff"; char ringcolor[9] = "337d00ff"; char linecolor[9] = "000000ff"; char textcolor[9] = "000000ff"; -char clockcolor[9] = "000000ff"; +char timecolor[9] = "000000ff"; +char datecolor[9] = "000000ff"; char keyhlcolor[9] = "33db00ff"; char bshlcolor[9] = "db3300ff"; char separatorcolor[9] = "000000ff"; @@ -85,8 +86,10 @@ char time_format[32] = "%H:%M:%S\0"; char date_format[32] = "%A, %m %Y\0"; char time_font[32] = "sans-serif\0"; char date_font[32] = "sans-serif\0"; -char clock_x_expr[32] = "ix\0"; -char clock_y_expr[32] = "iy+20\0"; +char time_x_expr[32] = "ix\0"; +char time_y_expr[32] = "iy\0"; +char date_x_expr[32] = "tx\0"; +char date_y_expr[32] = "ty+30\0"; double time_size = 32; double date_size = 14; @@ -896,7 +899,8 @@ int main(int argc, char *argv[]) { {"ringcolor", required_argument, NULL, 0}, // --r-c {"linecolor", required_argument, NULL, 0}, // --l-c {"textcolor", required_argument, NULL, 0}, // --t-c - {"clockcolor", required_argument, NULL, 0}, // --c-c + {"timecolor", required_argument, NULL, 0}, + {"datecolor", required_argument, NULL, 0}, {"keyhlcolor", required_argument, NULL, 0}, // --k-c {"bshlcolor", required_argument, NULL, 0}, // --b-c {"separatorcolor", required_argument, NULL, 0}, @@ -912,7 +916,8 @@ int main(int argc, char *argv[]) { {"datefont", required_argument, NULL, 0}, {"timesize", required_argument, NULL, 0}, {"datesize", required_argument, NULL, 0}, - {"clockpos", required_argument, NULL, 0}, + {"timepos", required_argument, NULL, 0}, + {"datepos", required_argument, NULL, 0}, {"blur", required_argument, NULL, 'B'}, @@ -1083,15 +1088,25 @@ int main(int argc, char *argv[]) { if (strlen(arg) != 8 || sscanf(arg, "%08[0-9a-fA-F]", textcolor) != 1) errx(1, "textcolor is invalid, color must be given in 8-byte format: rrggbb\n"); } - else if (strcmp(longopts[optind].name, "clockcolor") == 0) { + else if (strcmp(longopts[optind].name, "timecolor") == 0) { char *arg = optarg; /* Skip # if present */ if (arg[0] == '#') arg++; - if (strlen(arg) != 8 || sscanf(arg, "%08[0-9a-fA-F]", clockcolor) != 1) - errx(1, "clockcolor is invalid, color must be given in 8-byte format: rrggbb\n"); + if (strlen(arg) != 8 || sscanf(arg, "%08[0-9a-fA-F]", timecolor) != 1) + errx(1, "timecolor is invalid, color must be given in 8-byte format: rrggbb\n"); + } + else if (strcmp(longopts[optind].name, "datecolor") == 0) { + char *arg = optarg; + + /* Skip # if present */ + if (arg[0] == '#') + arg++; + + if (strlen(arg) != 8 || sscanf(arg, "%08[0-9a-fA-F]", datecolor) != 1) + errx(1, "datecolor is invalid, color must be given in 8-byte format: rrggbb\n"); } else if (strcmp(longopts[optind].name, "keyhlcolor") == 0) { char *arg = optarg; @@ -1167,15 +1182,26 @@ int main(int argc, char *argv[]) { if (date_size < 1) errx(1, "datesize must be larger than 0\n"); } - else if (strcmp(longopts[optind].name, "clockpos") == 0) { - //read in to clock_x_expr and clock_y_expr + else if (strcmp(longopts[optind].name, "timepos") == 0) { + //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, "date position string can be at most 31 characters\n"); + } + char* arg = optarg; + if (sscanf(arg, "%30[^:]:%30[^:]", &time_x_expr, &time_y_expr) != 2) { + errx(1, "timepos must be of the form x:y\n"); + } + } + else if (strcmp(longopts[optind].name, "datepos") == 0) { + //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"); } char* arg = optarg; - if (sscanf(arg, "%30[^:]:%30[^:]", &clock_x_expr, &clock_y_expr) != 2) { - errx(1, "clockpos must be of the form x:y\n"); + if (sscanf(arg, "%30[^:]:%30[^:]", &date_x_expr, &date_y_expr) != 2) { + errx(1, "datepos must be of the form x:y\n"); } } break; diff --git a/unlock_indicator.c b/unlock_indicator.c index a9e8679..f1acf9c 100644 --- a/unlock_indicator.c +++ b/unlock_indicator.c @@ -70,7 +70,8 @@ extern char ringwrongcolor[9]; extern char ringcolor[9]; extern char linecolor[9]; extern char textcolor[9]; -extern char clockcolor[9]; +extern char timecolor[9]; +extern char datecolor[9]; extern char keyhlcolor[9]; extern char bshlcolor[9]; extern char separatorcolor[9]; @@ -83,8 +84,10 @@ extern char time_format[32]; extern char date_format[32]; extern char time_font[32]; extern char date_font[32]; -extern char clock_x_expr[32]; -extern char clock_y_expr[32]; +extern char time_x_expr[32]; +extern char time_y_expr[32]; +extern char date_x_expr[32]; +extern char date_y_expr[32]; extern double time_size; extern double date_size; @@ -145,13 +148,16 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { /* Initialize cairo: Create one in-memory surface to render the unlock * indicator on, create one XCB surface to actually draw (one or more, * depending on the amount of screens) unlock indicators on. - * A third surface for the clock display is created as well + * create two more surfaces for time and date display */ cairo_surface_t *output = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, button_diameter_physical, button_diameter_physical); cairo_t *ctx = cairo_create(output); - cairo_surface_t *clock_output = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, clock_width_physical, clock_height_physical); - cairo_t *clock_ctx = cairo_create(clock_output); + cairo_surface_t *time_output = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, clock_width_physical, clock_height_physical); + cairo_t *time_ctx = cairo_create(time_output); + + cairo_surface_t *date_output = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, clock_width_physical, clock_height_physical); + cairo_t *date_ctx = cairo_create(date_output); 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); @@ -247,11 +253,19 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { (strtol(strgroupst[1], NULL, 16)), (strtol(strgroupst[2], NULL, 16)), (strtol(strgroupst[3], NULL, 16))}; - char strgroupsc[4][3] = {{clockcolor[0], clockcolor[1], '\0'}, - {clockcolor[2], clockcolor[3], '\0'}, - {clockcolor[4], clockcolor[5], '\0'}, - {clockcolor[6], clockcolor[7], '\0'}}; - uint32_t clock16[4] = {(strtol(strgroupsc[0], NULL, 16)), + char strgroupsc[4][3] = {{timecolor[0], timecolor[1], '\0'}, + {timecolor[2], timecolor[3], '\0'}, + {timecolor[4], timecolor[5], '\0'}, + {timecolor[6], timecolor[7], '\0'}}; + uint32_t time16[4] = {(strtol(strgroupsc[0], NULL, 16)), + (strtol(strgroupsc[1], NULL, 16)), + (strtol(strgroupsc[2], NULL, 16)), + (strtol(strgroupsc[3], NULL, 16))}; + char strgroupsd[4][3] = {{timecolor[0], timecolor[1], '\0'}, + {timecolor[2], timecolor[3], '\0'}, + {timecolor[4], timecolor[5], '\0'}, + {timecolor[6], timecolor[7], '\0'}}; + uint32_t date16[4] = {(strtol(strgroupsc[0], NULL, 16)), (strtol(strgroupsc[1], NULL, 16)), (strtol(strgroupsc[2], NULL, 16)), (strtol(strgroupsc[3], NULL, 16))}; @@ -473,48 +487,52 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { double x, y; cairo_text_extents_t extents; - cairo_set_font_size(clock_ctx, time_size); - cairo_select_font_face(clock_ctx, time_font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_source_rgba(clock_ctx, (double)clock16[0]/255, (double)clock16[1]/255, (double)clock16[2]/255, (double)clock16[3]/255); + cairo_set_font_size(time_ctx, time_size); + cairo_select_font_face(time_ctx, time_font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_source_rgba(time_ctx, (double)time16[0]/255, (double)time16[1]/255, (double)time16[2]/255, (double)time16[3]/255); - cairo_text_extents(clock_ctx, text, &extents); + cairo_text_extents(time_ctx, text, &extents); x = CLOCK_WIDTH/2 - ((extents.width / 2) + extents.x_bearing); - y = CLOCK_HEIGHT/2 - 10; + y = CLOCK_HEIGHT/2; - cairo_move_to(clock_ctx, x, y); - cairo_show_text(clock_ctx, text); - cairo_close_path(clock_ctx); + cairo_move_to(time_ctx, x, y); + cairo_show_text(time_ctx, text); + cairo_close_path(time_ctx); } if (date) { double x, y; cairo_text_extents_t extents; - cairo_select_font_face(clock_ctx, date_font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_source_rgba(clock_ctx, (double)clock16[0]/255, (double)clock16[1]/255, (double)clock16[2]/255, (double)clock16[3]/255); - cairo_set_font_size(clock_ctx, date_size); + cairo_select_font_face(date_ctx, date_font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_source_rgba(date_ctx, (double)date16[0]/255, (double)date16[1]/255, (double)date16[2]/255, (double)date16[3]/255); + cairo_set_font_size(date_ctx, date_size); - cairo_text_extents(clock_ctx, date, &extents); + cairo_text_extents(date_ctx, date, &extents); x = CLOCK_WIDTH/2 - ((extents.width / 2) + extents.x_bearing); - y = CLOCK_HEIGHT/2 - extents.y_bearing; + y = CLOCK_HEIGHT/2; - cairo_move_to(clock_ctx, x, y); - cairo_show_text(clock_ctx, date); - cairo_close_path(clock_ctx); + cairo_move_to(date_ctx, x, y); + cairo_show_text(date_ctx, date); + cairo_close_path(date_ctx); } } double ix, iy; double x, y; double w, h; + double tx = 0; + double ty = 0; int te_x_err; int te_y_err; // variable mapping for evaluating the clock position expression - te_variable vars[] = {{"ix", &ix}, {"iy", &iy}, {"w", &w}, {"h", &h}}; + te_variable vars[] = {{"ix", &ix}, {"iy", &iy}, {"w", &w}, {"h", &h}, {"tx", &tx}, {"ty", &ty}}; - te_expr *x_expr = te_compile(clock_x_expr, vars, 4, &te_x_err); - te_expr *y_expr = te_compile(clock_y_expr, vars, 4, &te_y_err); + te_expr *te_time_x_expr = te_compile(time_x_expr, vars, 6, &te_x_err); + te_expr *te_time_y_expr = te_compile(time_y_expr, vars, 6, &te_y_err); + te_expr *te_date_x_expr = te_compile(date_x_expr, vars, 6, &te_x_err); + te_expr *te_date_y_expr = te_compile(date_y_expr, vars, 6, &te_y_err); @@ -532,11 +550,18 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { cairo_rectangle(xcb_ctx, x, y, button_diameter_physical, button_diameter_physical); cairo_fill(xcb_ctx); - if (x_expr && y_expr) { - double clock_x = xr_resolutions[screen_number].x + te_eval(x_expr) - CLOCK_WIDTH / 2; - double clock_y = xr_resolutions[screen_number].y + te_eval(y_expr) - CLOCK_HEIGHT / 2; - cairo_set_source_surface(xcb_ctx, clock_output, clock_x, clock_y); - cairo_rectangle(xcb_ctx, clock_x, clock_y, CLOCK_WIDTH, CLOCK_HEIGHT); + if (te_time_x_expr && te_time_y_expr) { + tx = te_eval(te_time_x_expr); + ty = te_eval(te_time_y_expr); + double time_x = xr_resolutions[screen_number].x + tx - CLOCK_WIDTH / 2; + double time_y = xr_resolutions[screen_number].y + ty - CLOCK_HEIGHT / 2; + double date_x = xr_resolutions[screen_number].x + te_eval(te_date_x_expr) - CLOCK_WIDTH / 2; + double date_y = xr_resolutions[screen_number].y + te_eval(te_date_y_expr) - CLOCK_HEIGHT / 2; + cairo_set_source_surface(xcb_ctx, time_output, time_x, time_y); + cairo_rectangle(xcb_ctx, time_x, time_y, CLOCK_WIDTH, CLOCK_HEIGHT); + cairo_fill(xcb_ctx); + cairo_set_source_surface(xcb_ctx, date_output, date_x, date_y); + cairo_rectangle(xcb_ctx, date_x, date_y, CLOCK_WIDTH, CLOCK_HEIGHT); cairo_fill(xcb_ctx); } } @@ -551,16 +576,23 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { cairo_set_source_surface(xcb_ctx, output, x, y); cairo_rectangle(xcb_ctx, x, y, button_diameter_physical, button_diameter_physical); cairo_fill(xcb_ctx); - if (x_expr && y_expr) { - double clock_x = xr_resolutions[screen].x + te_eval(x_expr) - CLOCK_WIDTH / 2; - double clock_y = xr_resolutions[screen].y + te_eval(y_expr) - CLOCK_HEIGHT / 2; - cairo_set_source_surface(xcb_ctx, clock_output, clock_x, clock_y); - cairo_rectangle(xcb_ctx, clock_x, clock_y, CLOCK_WIDTH, CLOCK_HEIGHT); + if (te_time_x_expr && te_time_y_expr) { + tx = te_eval(te_time_x_expr); + ty = te_eval(te_time_y_expr); + double time_x = xr_resolutions[screen].x + tx - CLOCK_WIDTH / 2; + double time_y = xr_resolutions[screen].y + ty - CLOCK_HEIGHT / 2; + double date_x = xr_resolutions[screen].x + te_eval(te_date_x_expr) - CLOCK_WIDTH / 2; + double date_y = xr_resolutions[screen].y + te_eval(te_date_y_expr) - CLOCK_HEIGHT / 2; + cairo_set_source_surface(xcb_ctx, time_output, time_x, time_y); + cairo_rectangle(xcb_ctx, time_x, time_y, CLOCK_WIDTH, CLOCK_HEIGHT); + cairo_fill(xcb_ctx); + cairo_set_source_surface(xcb_ctx, date_output, date_x, date_y); + cairo_rectangle(xcb_ctx, date_x, date_y, CLOCK_WIDTH, CLOCK_HEIGHT); cairo_fill(xcb_ctx); } else { DEBUG("error codes for exprs are %d, %d\n", te_x_err, te_y_err); - DEBUG("exprs: %s, %s\n", clock_x_expr, clock_y_expr); + DEBUG("exprs: %s, %s\n", time_x_expr, time_y_expr); } } } @@ -577,21 +609,30 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { cairo_set_source_surface(xcb_ctx, output, x, y); cairo_rectangle(xcb_ctx, x, y, button_diameter_physical, button_diameter_physical); cairo_fill(xcb_ctx); - if (x_expr && y_expr) { - double clock_x = te_eval(x_expr) - CLOCK_WIDTH / 2; - double clock_y = te_eval(y_expr) - CLOCK_HEIGHT / 2; - DEBUG("Placing clock at %f, %f\n", clock_x, clock_y); - cairo_set_source_surface(xcb_ctx, clock_output, clock_x, clock_y); - cairo_rectangle(xcb_ctx, clock_x, clock_y, CLOCK_WIDTH, CLOCK_HEIGHT); + if (te_time_x_expr && te_time_y_expr) { + tx = te_eval(te_time_x_expr); + ty = te_eval(te_time_y_expr); + double time_x = tx - CLOCK_WIDTH / 2; + double time_y = tx - CLOCK_HEIGHT / 2; + double date_x = te_eval(te_date_x_expr) - CLOCK_WIDTH / 2; + double date_y = te_eval(te_date_y_expr) - CLOCK_HEIGHT / 2; + DEBUG("Placing time at %f, %f\n", time_x, time_y); + cairo_set_source_surface(xcb_ctx, time_output, time_x, time_y); + cairo_rectangle(xcb_ctx, time_x, time_y, CLOCK_WIDTH, CLOCK_HEIGHT); + cairo_fill(xcb_ctx); + cairo_set_source_surface(xcb_ctx, date_output, date_x, date_y); + cairo_rectangle(xcb_ctx, date_x, date_y, CLOCK_WIDTH, CLOCK_HEIGHT); cairo_fill(xcb_ctx); } } cairo_surface_destroy(xcb_output); - cairo_surface_destroy(clock_output); + cairo_surface_destroy(time_output); + cairo_surface_destroy(date_output); cairo_surface_destroy(output); cairo_destroy(ctx); - cairo_destroy(clock_ctx); + cairo_destroy(time_ctx); + cairo_destroy(date_ctx); cairo_destroy(xcb_ctx); return bg_pixmap; }