From 764b955f0678f34c23ba27b87b23bce280ce909c Mon Sep 17 00:00:00 2001 From: Louis Burda Date: Thu, 28 Sep 2023 02:16:32 +0200 Subject: Display message when screen is locked --- slock.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 133 insertions(+), 5 deletions(-) (limited to 'slock.c') diff --git a/slock.c b/slock.c index 42b4df3..6217dce 100644 --- a/slock.c +++ b/slock.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,9 @@ char *argv0; +/* global count to prevent repeated error messages */ +int count_error = 0; + enum { INIT, INPUT, @@ -88,6 +92,106 @@ dontkillme(void) } #endif +static void +writemessage(Display *dpy, Window win, int screen, const char* message) +{ + int msg_len, max_line_len, max_line_width, xoffset, yoffset, screen_width, + screen_height, i, j, k, line_count, tab_replace, tab_size, font_height; + XGCValues gr_values; + XFontStruct *fontinfo; + XColor fg_color, bg_color, dummy; + XineramaScreenInfo *xsi; + GC fg_gc, bg_gc; + fontinfo = XLoadQueryFont(dpy, font_name); + + if (fontinfo == NULL) { + if (count_error == 0) { + fprintf(stderr, "slock: Unable to load font \"%s\"\n", font_name); + fprintf(stderr, "slock: Try listing fonts with 'slock -f'\n"); + count_error++; + } + return; + } + + tab_size = 4 * XTextWidth(fontinfo, " ", 1); + + XAllocNamedColor(dpy, DefaultColormap(dpy, screen), + text_fg_color, &fg_color, &dummy); + + gr_values.font = fontinfo->fid; + gr_values.foreground = fg_color.pixel; + fg_gc = XCreateGC(dpy, win, GCFont+GCForeground, &gr_values); + + XAllocNamedColor(dpy, DefaultColormap(dpy, screen), + text_bg_color, &bg_color, &dummy); + + gr_values.foreground = bg_color.pixel; + bg_gc = XCreateGC(dpy, win, GCFont+GCForeground, &gr_values); + + /* To prevent "Uninitialized" warnings. */ + xsi = NULL; + + msg_len = strlen(message); + + /* Calculate max line length, j : last line, k : longest line */ + max_line_len = 0; + line_count = 0; + for (i = j = k = 0; i <= msg_len; i++) { + if (i == msg_len || message[i] == '\n') { + if (i - j > max_line_len) { + max_line_len = i - j; + k = j; + } + line_count++; + j = i + 1; + } + } + + max_line_width = XTextWidth(fontinfo, message + k, max_line_len); + + if (XineramaIsActive(dpy)) { + xsi = XineramaQueryScreens(dpy, &i); + screen_width = xsi[0].width; + screen_height = xsi[0].height; + } else { + screen_width = DisplayWidth(dpy, screen); + screen_height = DisplayHeight(dpy, screen); + } + + font_height = fontinfo->ascent + fontinfo->descent; + yoffset = screen_height * 3 / 7 - line_count * font_height / 3; + xoffset = (screen_width - max_line_width) / 2; + + /* Draw background rect */ + XFillRectangle(dpy, win, bg_gc, xoffset - 1, yoffset - fontinfo->ascent, + max_line_width + 2, line_count * font_height); + + /* Print line by line, j : last line, k : line counter */ + for (i = j = k = 0; i <= msg_len; i++) { + if (i == msg_len || message[i] == '\n') { + tab_replace = 0; + while (message[j] == '\t' && j < i) { + tab_replace++; + j++; + } + + XDrawString(dpy, win, fg_gc, xoffset + tab_size * tab_replace, + yoffset + 20 * k, message + j, i - j); + while (i < msg_len && message[i] == '\n') { + i++; + j = i; + k++; + } + } + } + + /* xsi should not be NULL anyway if Xinerama is active, but to be safe */ + if (XineramaIsActive(dpy) && xsi != NULL) + XFree(xsi); +} + + + static const char * gethash(void) { @@ -194,13 +298,22 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, break; } color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT); - if (running && oldc != color) { + if (running) { for (screen = 0; screen < nscreens; screen++) { if(locks[screen]->bgmap) XSetWindowBackgroundPixmap(dpy, locks[screen]->win, locks[screen]->bgmap); else XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[0]); XClearWindow(dpy, locks[screen]->win); + if (len) { + char* passwd_mask = malloc(len + 1); + memset(passwd_mask, '*', len); + passwd_mask[len] = '\0'; + writemessage(dpy, locks[screen]->win, screen, passwd_mask); + free(passwd_mask); + } else { + writemessage(dpy, locks[screen]->win, screen, lock_message); + } } oldc = color; } @@ -320,7 +433,7 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) static void usage(void) { - die("usage: slock [-v] [cmd [arg ...]]\n"); + die("usage: slock [-v] [-f] [-m message] [cmd [arg ...]]\n"); } int @@ -333,13 +446,26 @@ main(int argc, char **argv) { gid_t dgid; const char *hash; Display *dpy; - int s, nlocks, nscreens; + int i, s, nlocks, nscreens; + int count_fonts; + char **font_names; CARD16 standby, suspend, off; ARGBEGIN { case 'v': fprintf(stderr, "slock-"VERSION"\n"); return 0; + case 'm': + lock_message = EARGF(usage()); + break; + case 'f': + if (!(dpy = XOpenDisplay(NULL))) + die("slock: cannot open display\n"); + font_names = XListFonts(dpy, "*", 10000 /* list 10000 fonts*/, &count_fonts); + for (i=0; iwin, s, lock_message); nlocks++; - else + } else { break; + } } XSync(dpy, 0); -- cgit v1.2.3-71-gd317