diff options
| author | Andrew Guschin <saintruler@gmail.com> | 2021-09-02 23:45:56 +0400 |
|---|---|---|
| committer | Andrew Guschin <saintruler@gmail.com> | 2021-09-02 23:45:56 +0400 |
| commit | 14068dfebb01001cb732866235df96f84ffb6d82 (patch) | |
| tree | 189e7a1defddb64be8db1cda9eb79aeffc8c71d8 /slock.c | |
| parent | ec94f1e8f8a9ef263ff1be098901d1708be4804d (diff) | |
Diffstat (limited to 'slock.c')
| -rw-r--r-- | slock.c | 140 |
1 files changed, 136 insertions, 4 deletions
@@ -15,6 +15,8 @@ #include <unistd.h> #include <sys/types.h> #include <X11/extensions/Xrandr.h> +#include <X11/extensions/dpms.h> +#include <X11/extensions/Xinerama.h> #include <X11/keysym.h> #include <X11/Xlib.h> #include <X11/Xutil.h> @@ -24,6 +26,9 @@ char *argv0; +/* global count to prevent repeated error messages */ +int count_error = 0; + enum { INIT, INPUT, @@ -83,6 +88,98 @@ dontkillme(void) } #endif +static void +writemessage(Display *dpy, Window win, int screen) +{ + int len, line_len, width, height, s_width, s_height, i, j, k, tab_replace, tab_size; + XGCValues gr_values; + XFontStruct *fontinfo; + XColor color, dummy; + XineramaScreenInfo *xsi; + GC 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 = 8 * XTextWidth(fontinfo, " ", 1); + + XAllocNamedColor(dpy, DefaultColormap(dpy, screen), + text_color, &color, &dummy); + + gr_values.font = fontinfo->fid; + gr_values.foreground = color.pixel; + gc=XCreateGC(dpy,win,GCFont+GCForeground, &gr_values); + + /* To prevent "Uninitialized" warnings. */ + xsi = NULL; + + /* + * Start formatting and drawing text + */ + + len = strlen(message); + + /* Max max line length (cut at '\n') */ + line_len = 0; + k = 0; + for (i = j = 0; i < len; i++) { + if (message[i] == '\n') { + if (i - j > line_len) + line_len = i - j; + k++; + i++; + j = i; + } + } + /* If there is only one line */ + if (line_len == 0) + line_len = len; + + if (XineramaIsActive(dpy)) { + xsi = XineramaQueryScreens(dpy, &i); + s_width = xsi[0].width; + s_height = xsi[0].height; + } else { + s_width = DisplayWidth(dpy, screen); + s_height = DisplayHeight(dpy, screen); + } + + height = s_height*3/7 - (k*20)/3; + width = (s_width - XTextWidth(fontinfo, message, line_len))/2; + + /* Look for '\n' and print the text between them. */ + for (i = j = k = 0; i <= len; i++) { + /* i == len is the special case for the last line */ + if (i == len || message[i] == '\n') { + tab_replace = 0; + while (message[j] == '\t' && j < i) { + tab_replace++; + j++; + } + + XDrawString(dpy, win, gc, width + tab_size*tab_replace, height + 20*k, message + j, i - j); + while (i < 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,6 +291,7 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, locks[screen]->win, locks[screen]->colors[color]); XClearWindow(dpy, locks[screen]->win); + writemessage(dpy, locks[screen]->win, screen); } oldc = color; } @@ -292,7 +390,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 @@ -305,12 +403,26 @@ main(int argc, char **argv) { gid_t dgid; const char *hash; Display *dpy; - int s, nlocks, nscreens; + int i, s, nlocks, nscreens; + CARD16 standby, suspend, off; + int count_fonts; + char **font_names; ARGBEGIN { case 'v': fprintf(stderr, "slock-"VERSION"\n"); return 0; + case 'm': + 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; i<count_fonts; i++) { + fprintf(stderr, "%s\n", *(font_names+i)); + } + return 0; default: usage(); } ARGEND @@ -355,10 +467,12 @@ main(int argc, char **argv) { if (!(locks = calloc(nscreens, sizeof(struct lock *)))) die("slock: out of memory\n"); for (nlocks = 0, s = 0; s < nscreens; s++) { - if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL) + if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL) { + writemessage(dpy, locks[s]->win, s); nlocks++; - else + } else { break; + } } XSync(dpy, 0); @@ -366,6 +480,20 @@ main(int argc, char **argv) { if (nlocks != nscreens) return 1; + /* DPMS magic to disable the monitor */ + if (!DPMSCapable(dpy)) + die("slock: DPMSCapable failed\n"); + if (!DPMSEnable(dpy)) + die("slock: DPMSEnable failed\n"); + if (!DPMSGetTimeouts(dpy, &standby, &suspend, &off)) + die("slock: DPMSGetTimeouts failed\n"); + if (!standby || !suspend || !off) + die("slock: at least one DPMS variable is zero\n"); + if (!DPMSSetTimeouts(dpy, monitortime, monitortime, monitortime)) + die("slock: DPMSSetTimeouts failed\n"); + + XSync(dpy, 0); + /* run post-lock command */ if (argc > 0) { switch (fork()) { @@ -383,5 +511,9 @@ main(int argc, char **argv) { /* everything is now blank. Wait for the correct password */ readpw(dpy, &rr, locks, nscreens, hash); + /* reset DPMS values to inital ones */ + DPMSSetTimeouts(dpy, standby, suspend, off); + XSync(dpy, 0); + return 0; } |