slock

git clone git://mattcarlson.org/repos/slock.git
Log | Files | Refs

commit 7d39ef77fa7085e8ce077fc8976bc99bad7d5d37
parent 19b66f19f5c5eea3d3e62844b28bc8f336d4eb83
Author: Matthew Carlson <matt@mcarlson.xyz>
Date:   Fri, 16 Jul 2021 03:22:53 -0400

Merge branch 'xft' into slock

Diffstat:
Mconfig.h | 9+++++++++
Mconfig.mk | 4++--
Mslock.c | 108++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 116 insertions(+), 5 deletions(-)

diff --git a/config.h b/config.h @@ -21,3 +21,12 @@ ResourcePref resources[] = { /* treat a cleared input like a wrong password (color) */ static const int failonclear = 1; + +/* default message */ +static const char * message = "Suckless: Software that sucks less."; + +/* text color */ +static const char * text_color = "#ffffff"; + +/* text size (must be a valid size) */ +static const char * font_name = "sans-serif:size:pixelsize=24:antialias=true:autohint=true"; diff --git a/config.mk b/config.mk @@ -11,8 +11,8 @@ X11INC = /usr/X11R6/include X11LIB = /usr/X11R6/lib # includes and libs -INCS = -I. -I/usr/include -I${X11INC} -LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr +INCS = -I. -I/usr/include -I${X11INC} -I/usr/include/freetype2 +LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr -lXinerama -lXft # flags CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H diff --git a/slock.c b/slock.c @@ -15,18 +15,24 @@ #include <string.h> #include <unistd.h> #include <sys/types.h> +#include <fontconfig/fontconfig.h> #include <X11/extensions/Xrandr.h> +#include <X11/extensions/Xinerama.h> #include <X11/keysym.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/XKBlib.h> #include <X11/Xresource.h> +#include <X11/Xft/Xft.h> #include "arg.h" #include "util.h" char *argv0; +/* global count to prevent repeated error messages */ +int count_error = 0; + enum { INIT, INPUT, @@ -100,6 +106,96 @@ 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; + XftFont *fontinfo; + XftColor xftcolor; + XftDraw *xftdraw; + XGlyphInfo ext_msg, ext_space; + XineramaScreenInfo *xsi; + xftdraw = XftDrawCreate(dpy, win, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen)); + fontinfo = XftFontOpenName(dpy, screen, font_name); + XftColorAllocName(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), text_color, &xftcolor); + + if (fontinfo == NULL) { + if (count_error == 0) { + fprintf(stderr, "slock: Unable to load font \"%s\"\n", font_name); + count_error++; + } + return; + } + + XftTextExtentsUtf8(dpy, fontinfo, (XftChar8 *) " ", 1, &ext_space); + tab_size = 8 * ext_space.width; + + /* 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); + } + + XftTextExtentsUtf8(dpy, fontinfo, (XftChar8 *)message, line_len, &ext_msg); + height = s_height*3/7 - (k*20)/3; + width = (s_width - ext_msg.width)/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++; + } + + XftDrawStringUtf8(xftdraw, &xftcolor, fontinfo, width + tab_size*tab_replace, height + 20*k, (XftChar8 *)(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); + + XftFontClose(dpy, fontinfo); + XftColorFree(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), &xftcolor); + XftDrawDestroy(xftdraw); +} + static const char * gethash(void) { @@ -218,6 +314,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; } @@ -375,7 +472,7 @@ config_init(Display *dpy) static void usage(void) { - die("usage: slock [-v] [cmd [arg ...]]\n"); + die("usage: slock [-v] [-m message] [cmd [arg ...]]\n"); } int @@ -394,6 +491,9 @@ main(int argc, char **argv) { case 'v': fprintf(stderr, "slock-"VERSION"\n"); return 0; + case 'm': + message = EARGF(usage()); + break; default: usage(); } ARGEND @@ -440,10 +540,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);