sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

slock-colormessage-20200210-35633d4.diff (7273B)


      1 From 53ba5a8d3608ca9c9c406b12c51c2bfdfb3e01d3 Mon Sep 17 00:00:00 2001
      2 From: Guy Shefy <guyshefyb@gmail.com>
      3 Date: Wed, 10 Feb 2021 00:17:46 +0200
      4 Subject: [PATCH] Add a message command with 24 bit color support
      5 
      6 ---
      7  config.def.h |   9 +++
      8  config.mk    |   2 +-
      9  slock.1      |   7 +++
     10  slock.c      | 154 +++++++++++++++++++++++++++++++++++++++++++++++++--
     11  4 files changed, 167 insertions(+), 5 deletions(-)
     12 
     13 diff --git a/config.def.h b/config.def.h
     14 index 9855e21..c2a0ab2 100644
     15 --- a/config.def.h
     16 +++ b/config.def.h
     17 @@ -10,3 +10,12 @@ 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 +/* text size (must be a valid size) */
     29 +static const char * font_name = "6x10";
     30 diff --git a/config.mk b/config.mk
     31 index 74429ae..c4ccf66 100644
     32 --- a/config.mk
     33 +++ b/config.mk
     34 @@ -12,7 +12,7 @@ X11LIB = /usr/X11R6/lib
     35  
     36  # includes and libs
     37  INCS = -I. -I/usr/include -I${X11INC}
     38 -LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr
     39 +LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr -lXinerama
     40  
     41  # flags
     42  CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H
     43 diff --git a/slock.1 b/slock.1
     44 index 82cdcd6..946165f 100644
     45 --- a/slock.1
     46 +++ b/slock.1
     47 @@ -6,6 +6,8 @@
     48  .Sh SYNOPSIS
     49  .Nm
     50  .Op Fl v
     51 +.Op Fl f
     52 +.Op Fl m Ar message
     53  .Op Ar cmd Op Ar arg ...
     54  .Sh DESCRIPTION
     55  .Nm
     56 @@ -16,6 +18,11 @@ is executed after the screen has been locked.
     57  .Bl -tag -width Ds
     58  .It Fl v
     59  Print version information to stdout and exit.
     60 +.It Fl f
     61 +List all valid X fonts and exit.
     62 +.It Fl m Ar message
     63 +Overrides default slock lock message.
     64 +.TP
     65  .El
     66  .Sh SECURITY CONSIDERATIONS
     67  To make sure a locked screen can not be bypassed by switching VTs
     68 diff --git a/slock.c b/slock.c
     69 index 5ae738c..b8b7fe4 100644
     70 --- a/slock.c
     71 +++ b/slock.c
     72 @@ -15,6 +15,7 @@
     73  #include <unistd.h>
     74  #include <sys/types.h>
     75  #include <X11/extensions/Xrandr.h>
     76 +#include <X11/extensions/Xinerama.h>
     77  #include <X11/keysym.h>
     78  #include <X11/Xlib.h>
     79  #include <X11/Xutil.h>
     80 @@ -24,6 +25,9 @@
     81  
     82  char *argv0;
     83  
     84 +/* global count to prevent repeated error messages */
     85 +int count_error = 0;
     86 +
     87  enum {
     88  	INIT,
     89  	INPUT,
     90 @@ -83,6 +87,132 @@ dontkillme(void)
     91  }
     92  #endif
     93  
     94 +static int
     95 +readescapedint(const char *str, int *i) {
     96 +	int n = 0;
     97 +	if (str[*i])
     98 +		++*i;
     99 +	while(str[*i] && str[*i] != ';' && str[*i] != 'm') {
    100 +		n = 10 * n + str[*i] - '0';
    101 +		++*i;
    102 +	}
    103 +	return n;
    104 +}
    105 +
    106 +static void
    107 +writemessage(Display *dpy, Window win, int screen)
    108 +{
    109 +	int len, line_len, width, height, s_width, s_height, i, k, tab_size, r, g, b, escaped_int, curr_line_len;
    110 +	XGCValues gr_values;
    111 +	XFontStruct *fontinfo;
    112 +	XColor color, dummy;
    113 +	XineramaScreenInfo *xsi;
    114 +	GC gc;
    115 +	fontinfo = XLoadQueryFont(dpy, font_name);
    116 +
    117 +	if (fontinfo == NULL) {
    118 +		if (count_error == 0) {
    119 +			fprintf(stderr, "slock: Unable to load font \"%s\"\n", font_name);
    120 +			fprintf(stderr, "slock: Try listing fonts with 'slock -f'\n");
    121 +			count_error++;
    122 +		}
    123 +		return;
    124 +	}
    125 +
    126 +	tab_size = 8 * XTextWidth(fontinfo, " ", 1);
    127 +
    128 +	XAllocNamedColor(dpy, DefaultColormap(dpy, screen),
    129 +		 text_color, &color, &dummy);
    130 +
    131 +	gr_values.font = fontinfo->fid;
    132 +	gr_values.foreground = color.pixel;
    133 +	gc=XCreateGC(dpy,win,GCFont+GCForeground, &gr_values);
    134 +
    135 +	/*  To prevent "Uninitialized" warnings. */
    136 +	xsi = NULL;
    137 +
    138 +	/*
    139 +	 * Start formatting and drawing text
    140 +	 */
    141 +
    142 +	len = strlen(message);
    143 +
    144 +	/* Max max line length (cut at '\n') */
    145 +	line_len = curr_line_len = 0;
    146 +	k = 0;
    147 +	for (i = 0; i < len; i++) {
    148 +		if (message[i] == '\n') {
    149 +			curr_line_len = 0;
    150 +			k++;
    151 +		} else if (message[i] == 0x1b) {
    152 +			while (i < len && message[i] != 'm') {
    153 +				i++;
    154 +			}
    155 +			if (i == len)
    156 +				die("slock: unclosed escape sequence\n");
    157 +		} else {
    158 +			curr_line_len += XTextWidth(fontinfo, message + i, 1);
    159 +			if (curr_line_len > line_len)
    160 +				line_len = curr_line_len;
    161 +		}
    162 +	}
    163 +	/* If there is only one line */
    164 +	if (line_len == 0)
    165 +		line_len = len;
    166 +
    167 +	if (XineramaIsActive(dpy)) {
    168 +		xsi = XineramaQueryScreens(dpy, &i);
    169 +		s_width = xsi[0].width;
    170 +		s_height = xsi[0].height;
    171 +	} else {
    172 +		s_width = DisplayWidth(dpy, screen);
    173 +		s_height = DisplayHeight(dpy, screen);
    174 +	}
    175 +	height = s_height*3/7 - (k*20)/3;
    176 +	width  = (s_width - line_len)/2;
    177 +
    178 +	line_len = 0;
    179 +	/* print the text while parsing 24 bit color ANSI escape codes*/
    180 +	for (i = k = 0; i < len; i++) {
    181 +		switch (message[i]) {
    182 +			case '\n':
    183 +				line_len = 0;
    184 +				while (message[i + 1] == '\t') {
    185 +					line_len += tab_size;
    186 +					i++;
    187 +				}
    188 +				k++;
    189 +				break;
    190 +			case 0x1b:
    191 +				i++;
    192 +				if (message[i] == '[') {
    193 +					escaped_int = readescapedint(message, &i);
    194 +					if (escaped_int == 39)
    195 +						continue;
    196 +					if (escaped_int != 38)
    197 +						die("slock: unknown escape sequence%d\n", escaped_int);
    198 +					if (readescapedint(message, &i) != 2)
    199 +						die("slock: only 24 bit color supported\n");
    200 +					r = readescapedint(message, &i) & 0xff;
    201 +					g = readescapedint(message, &i) & 0xff;
    202 +					b = readescapedint(message, &i) & 0xff;
    203 +					XSetForeground(dpy, gc, r << 16 | g << 8 | b);
    204 +				} else
    205 +					die("slock: unknown escape sequence\n");
    206 +				break;
    207 +			default:
    208 +				XDrawString(dpy, win, gc, width + line_len, height + 20 * k, message + i, 1);
    209 +				line_len += XTextWidth(fontinfo, message + i, 1);
    210 +		}
    211 +	}
    212 +
    213 +	/* xsi should not be NULL anyway if Xinerama is active, but to be safe */
    214 +	if (XineramaIsActive(dpy) && xsi != NULL)
    215 +			XFree(xsi);
    216 +}
    217 +
    218 +
    219 +
    220  static const char *
    221  gethash(void)
    222  {
    223 @@ -194,6 +324,7 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
    224  					                     locks[screen]->win,
    225  					                     locks[screen]->colors[color]);
    226  					XClearWindow(dpy, locks[screen]->win);
    227 +					writemessage(dpy, locks[screen]->win, screen);
    228  				}
    229  				oldc = color;
    230  			}
    231 @@ -300,7 +431,7 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
    232  static void
    233  usage(void)
    234  {
    235 -	die("usage: slock [-v] [cmd [arg ...]]\n");
    236 +	die("usage: slock [-v] [-f] [-m message] [cmd [arg ...]]\n");
    237  }
    238  
    239  int
    240 @@ -313,12 +444,25 @@ main(int argc, char **argv) {
    241  	gid_t dgid;
    242  	const char *hash;
    243  	Display *dpy;
    244 -	int s, nlocks, nscreens;
    245 +	int i, s, nlocks, nscreens;
    246 +	int count_fonts;
    247 +	char **font_names;
    248  
    249  	ARGBEGIN {
    250  	case 'v':
    251  		fprintf(stderr, "slock-"VERSION"\n");
    252  		return 0;
    253 +	case 'm':
    254 +		message = EARGF(usage());
    255 +		break;
    256 +	case 'f':
    257 +		if (!(dpy = XOpenDisplay(NULL)))
    258 +			die("slock: cannot open display\n");
    259 +		font_names = XListFonts(dpy, "*", 10000 /* list 10000 fonts*/, &count_fonts);
    260 +		for (i=0; i<count_fonts; i++) {
    261 +			fprintf(stderr, "%s\n", *(font_names+i));
    262 +		}
    263 +		return 0;
    264  	default:
    265  		usage();
    266  	} ARGEND
    267 @@ -363,10 +507,12 @@ main(int argc, char **argv) {
    268  	if (!(locks = calloc(nscreens, sizeof(struct lock *))))
    269  		die("slock: out of memory\n");
    270  	for (nlocks = 0, s = 0; s < nscreens; s++) {
    271 -		if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL)
    272 +		if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL) {
    273 +			writemessage(dpy, locks[s]->win, s);
    274  			nlocks++;
    275 -		else
    276 +		} else {
    277  			break;
    278 +		}
    279  	}
    280  	XSync(dpy, 0);
    281  
    282 -- 
    283 2.30.0
    284