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:
M | config.h | | | 9 | +++++++++ |
M | config.mk | | | 4 | ++-- |
M | slock.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);