slock-message-xft-20261008-65cb721.diff (7898B)
1 From ae7e6d53035be99c24b514cbb26005d37656d632 Mon Sep 17 00:00:00 2001 2 From: Sourav Nayak <nonameblank007@gmail.com> 3 Date: Thu, 8 Oct 2026 00:36:01 +0530 4 Subject: [PATCH] slock: update message patch for upcoming 1.8 version and support system fonts 5 6 --- 7 config.def.h | 12 ++++ 8 config.mk | 8 ++- 9 slock.1 | 7 +++ 10 slock.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++-- 11 4 files changed, 177 insertions(+), 6 deletions(-) 12 13 diff --git a/config.def.h b/config.def.h 14 index 9855e21..d18e03f 100644 15 --- a/config.def.h 16 +++ b/config.def.h 17 @@ -10,3 +10,15 @@ static const char *colorname[NUMCOLS] = { 18 19 /* treat a cleared input like a wrong password (color) */ 20 static const int failonclear = 1; 21 + 22 +/* default message */ 23 +static const char * message = "Suckless: Software that sucks less."; 24 + 25 +/* text color */ 26 +static const char * text_color = "#ffffff"; 27 + 28 +/* font name (slock -f/fc-list) */ 29 +static const char * font_name = "monospace"; 30 + 31 +/* font size (must be a valid size) */ 32 +static const double font_size = 18.0; 33 \ No newline at end of file 34 diff --git a/config.mk b/config.mk 35 index 9fe5bff..921834e 100644 36 --- a/config.mk 37 +++ b/config.mk 38 @@ -10,9 +10,13 @@ MANPREFIX = ${PREFIX}/share/man 39 X11INC = /usr/X11R6/include 40 X11LIB = /usr/X11R6/lib 41 42 +# freetype 43 +FREETYPELIBS = -lfontconfig -lXft 44 +FREETYPEINC = /usr/include/freetype2 45 + 46 # includes and libs 47 -INCS = -I. -I/usr/include -I${X11INC} 48 -LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr 49 +INCS = -I. -I/usr/include -I${X11INC} -I${FREETYPEINC} 50 +LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} ${FREETYPELIBS} -lX11 -lXext -lXrandr -lXinerama 51 52 # flags 53 CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H 54 diff --git a/slock.1 b/slock.1 55 index e485992..66a5f97 100644 56 --- a/slock.1 57 +++ b/slock.1 58 @@ -7,6 +7,8 @@ 59 .Sh SYNOPSIS 60 .Nm 61 .Op Fl v 62 +.Op Fl f 63 +.Op Fl m 64 .Sh DESCRIPTION 65 .Nm 66 is a simple X screen locker. 67 @@ -14,6 +16,11 @@ The options are as follows: 68 .Bl -tag -width Ds 69 .It Fl v 70 Print version information to stdout and exit. 71 +.It Fl f 72 +List all valid X fonts and exit. 73 +.It Fl m 74 +Overrides default slock lock message. 75 +.TP 76 .El 77 .Sh EXIT STATUS 78 .Ex -std 79 diff --git a/slock.c b/slock.c 80 index 9c587e1..fe6ef5d 100644 81 --- a/slock.c 82 +++ b/slock.c 83 @@ -15,14 +15,20 @@ 84 #include <unistd.h> 85 #include <sys/types.h> 86 #include <X11/extensions/Xrandr.h> 87 +#include <X11/extensions/Xinerama.h> 88 #include <X11/keysym.h> 89 #include <X11/Xlib.h> 90 #include <X11/Xutil.h> 91 +#include <X11/Xft/Xft.h> 92 +#include <fontconfig/fontconfig.h> 93 94 #include "util.h" 95 96 char *argv0; 97 98 +/* global count to prevent repeated error messages */ 99 +int count_error = 0; 100 + 101 enum { 102 INIT, 103 INPUT, 104 @@ -82,6 +88,122 @@ dontkillme(void) 105 } 106 #endif 107 108 +static void 109 +writemessage(Display *dpy, Window win, int screen) 110 +{ 111 + int len, line_len, line_start, width, height, s_width, s_height, i, j, k, tab_replace, tab_size; 112 + XineramaScreenInfo *xsi = NULL; 113 + XftFont *font = NULL; 114 + XftDraw *draw; 115 + XftColor color; 116 + Visual *vis; 117 + Colormap cmap; 118 + XGlyphInfo ext; 119 + char font_pattern[256]; 120 + 121 + snprintf(font_pattern, sizeof(font_pattern), "%s:size=%f:antialias=true:autohint=true", 122 + font_name, font_size); 123 + 124 + font = XftFontOpenName(dpy, screen, font_pattern); 125 + if (!font) 126 + font = XftFontOpenName(dpy, screen, "monospace:size=12"); 127 + 128 + if (!font) { 129 + if (count_error == 0) { 130 + fprintf(stderr, "slock: Unable to load font \"%s\"\n", font_pattern); 131 + fprintf(stderr, "slock: Try listing fonts with 'slock -f'\n"); 132 + count_error++; 133 + } 134 + return; 135 + } 136 + 137 + vis = DefaultVisual(dpy, screen); 138 + cmap = DefaultColormap(dpy, screen); 139 + 140 + if (!XftColorAllocName(dpy, vis, cmap, text_color, &color)) { 141 + fprintf(stderr, "slock: Unable to allocate color \"%s\"\n", text_color); 142 + XftFontClose(dpy, font); 143 + return; 144 + } 145 + 146 + draw = XftDrawCreate(dpy, win, vis, cmap); 147 + if (!draw) { 148 + XftColorFree(dpy, vis, cmap, &color); 149 + XftFontClose(dpy, font); 150 + return; 151 + } 152 + 153 + XftTextExtentsUtf8(dpy, font, (FcChar8 *)" ", 1, &ext); 154 + tab_size = 8 * (ext.xOff > 0 ? ext.xOff : 8); 155 + 156 + len = strlen(message); 157 + 158 + /* Max max line length (cut at '\n') */ 159 + line_len = 0; 160 + line_start = 0; 161 + k = 0; 162 + for (i = j = 0; i < len; i++) { 163 + if (message[i] == '\n') { 164 + if (i - j > line_len) { 165 + line_len = i - j; 166 + line_start = j; 167 + } 168 + k++; 169 + i++; 170 + j = i; 171 + } 172 + } 173 + if (line_len == 0) { 174 + line_len = len; 175 + line_start = 0; 176 + } 177 + 178 + if (XineramaIsActive(dpy)) { 179 + xsi = XineramaQueryScreens(dpy, &i); 180 + s_width = xsi[0].width; 181 + s_height = xsi[0].height; 182 + } else { 183 + s_width = DisplayWidth(dpy, screen); 184 + s_height = DisplayHeight(dpy, screen); 185 + } 186 + 187 + XftTextExtentsUtf8(dpy, font, (FcChar8 *)(message + line_start), line_len, &ext); 188 + int line_spacing = font->ascent + font->descent + 6; 189 + height = s_height * 3 / 7 - (k * line_spacing) / 3; 190 + width = (s_width - ext.xOff) / 2; 191 + 192 + /* Look for '\n' and print the text between them. */ 193 + for (i = j = k = 0; i <= len; i++) { 194 + /* i == len is the special case for the last line */ 195 + if (i == len || message[i] == '\n') { 196 + tab_replace = 0; 197 + while (message[j] == '\t' && j < i) { 198 + tab_replace++; 199 + j++; 200 + } 201 + 202 + XftDrawStringUtf8(draw, &color, font, 203 + width + tab_size * tab_replace, 204 + height + (k * line_spacing) + font->ascent, 205 + (FcChar8 *)(message + j), i - j); 206 + 207 + while (i < len && message[i] == '\n') { 208 + i++; 209 + j = i; 210 + k++; 211 + } 212 + } 213 + } 214 + 215 + /* xsi should not be NULL anyway if Xinerama is active, but to be safe */ 216 + if (XineramaIsActive(dpy) && xsi != NULL) 217 + XFree(xsi); 218 + 219 + XftDrawDestroy(draw); 220 + XftColorFree(dpy, vis, cmap, &color); 221 + XftFontClose(dpy, font); 222 +} 223 + 224 static const char * 225 gethash(void) 226 { 227 @@ -196,6 +318,7 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, 228 locks[screen]->win, 229 locks[screen]->colors[color]); 230 XClearWindow(dpy, locks[screen]->win); 231 + writemessage(dpy, locks[screen]->win, screen); 232 } 233 oldc = color; 234 } 235 @@ -302,7 +425,7 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) 236 static void 237 usage(void) 238 { 239 - die("usage: slock [-v]\n"); 240 + die("usage: slock [-v] [-f] [-m message]\n"); 241 } 242 243 int 244 @@ -315,11 +438,30 @@ main(int argc, char **argv) { 245 gid_t dgid; 246 const char *hash; 247 Display *dpy; 248 - int s, nlocks, nscreens; 249 + int i, s, nlocks, nscreens; 250 + FcFontSet *fs; 251 + FcPattern *pat; 252 + FcObjectSet *os; 253 254 if (argc > 1 && !strcmp(argv[1], "-v")) { 255 puts("slock-"VERSION); 256 return 0; 257 + } else if (argc > 1 && !strcmp(argv[1], "-m")) { 258 + if (argc < 3) 259 + usage(); 260 + message = argv[2]; 261 + } else if (argc > 1 && !strcmp(argv[1], "-f")) { 262 + if (!FcInit()) 263 + die("slock: Fontconfig initialization failed\n"); 264 + pat = FcPatternCreate(); 265 + os = FcObjectSetBuild(FC_FAMILY, NULL); 266 + fs = FcFontList(NULL, pat, os); 267 + for (i = 0; fs && i < fs->nfont; i++) { 268 + FcChar8 *fam; 269 + if (FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &fam) == FcResultMatch) 270 + printf("%s\n", fam); 271 + } 272 + return 0; 273 } else if (argc > 1) { 274 usage(); 275 } 276 @@ -345,6 +487,10 @@ main(int argc, char **argv) { 277 if (!crypt("", hash)) 278 die("slock: crypt: %s\n", strerror(errno)); 279 280 + /* Initialize Fontconfig cache BEFORE dropping privileges */ 281 + if (!FcInit()) 282 + die("slock: Fontconfig initialization failed\n"); 283 + 284 if (!(dpy = XOpenDisplay(NULL))) 285 die("slock: cannot open display\n"); 286 287 @@ -364,10 +510,12 @@ main(int argc, char **argv) { 288 if (!(locks = calloc(nscreens, sizeof(struct lock *)))) 289 die("slock: out of memory\n"); 290 for (nlocks = 0, s = 0; s < nscreens; s++) { 291 - if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL) 292 + if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL) { 293 + writemessage(dpy, locks[s]->win, s); 294 nlocks++; 295 - else 296 + } else { 297 break; 298 + } 299 } 300 XSync(dpy, 0); 301 302 -- 303 2.55.0 304