From f656e7712dfc9f7f96cd09174cece8154758a303 Mon Sep 17 00:00:00 2001 From: ColumbusUtrigas Date: Mon, 30 Jan 2023 12:48:31 +0400 Subject: [PATCH] xft text, timer --- config.h | 10 +++- config.mk | 8 ++- slock.c | 157 +++++++++++++++++++++++++++++++----------------------- 3 files changed, 104 insertions(+), 71 deletions(-) diff --git a/config.h b/config.h index a3fc819..2b57fc2 100644 --- a/config.h +++ b/config.h @@ -20,5 +20,11 @@ static const char * message = "Enter password to unlock"; /* text color */ static const char * text_color = "#abb2bf"; -/* text size (must be a valid size) */ -static const char * text_size = "-*-*-medium-r-*-sans-34-*-*-*-*-*-*-*"; +/* text font */ +static const char * text_font = "sans:pixelsize=30"; + +/* time text color */ +static const char * time_color = "#abb2bf"; + +/* time text font */ +static const char * time_font = "sans:bold:pixelsize=100"; diff --git a/config.mk b/config.mk index 74429ae..48d7fbe 100644 --- a/config.mk +++ b/config.mk @@ -10,9 +10,13 @@ MANPREFIX = ${PREFIX}/share/man X11INC = /usr/X11R6/include X11LIB = /usr/X11R6/lib +# freetype +FREETYPELIBS = -lfontconfig -lXft +FREETYPEINC = /usr/include/freetype2 + # 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${FREETYPEINC} +LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr ${FREETYPELIBS} # flags CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H diff --git a/slock.c b/slock.c index d5e29ba..187f8e8 100644 --- a/slock.c +++ b/slock.c @@ -1,10 +1,14 @@ /* See LICENSE file for license details. */ +#include +#include #define _XOPEN_SOURCE 500 #if HAVE_SHADOW_H #include #endif #include +#include +#include #include #include #include @@ -14,11 +18,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include "arg.h" #include "util.h" @@ -32,10 +38,18 @@ enum { NUMCOLS }; +enum { + TEXT, + TIME +}; + struct lock { int screen; Window root, win; Pixmap pmap; + XftDraw* draw; + XftFont* fonts[2]; + XftColor font_colors[2]; unsigned long colors[NUMCOLS]; }; @@ -58,75 +72,75 @@ die(const char *errstr, ...) exit(1); } +static int +wait_fd(int fd, double seconds) +{ + struct timeval tv; + fd_set in_fds; + FD_ZERO(&in_fds); + FD_SET(fd, &in_fds); + tv.tv_sec = trunc(seconds); + tv.tv_usec = (seconds - trunc(seconds))*1000000; + return select(fd+1, &in_fds, 0, 0, &tv); +} + +static int +XNextEventTimeout(Display *dpy, XEvent *ev, double seconds) +{ + if (XPending(dpy) || wait_fd(ConnectionNumber(dpy), seconds)) + { + return XNextEvent(dpy, ev); + } + + return 0; +} + #ifdef __linux__ #include #include static void -writemessage(Display *dpy, Window win, int screen) +writemessage(Display *dpy, struct lock *lock) { - int len, line_len, width, height, i, j, k, tab_replace, tab_size; - XGCValues gr_values; - XFontStruct *fontinfo; - XColor color, dummy; - GC gc; - fontinfo = XLoadQueryFont(dpy, text_size); - 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); + int len, timelen, x, y, timex, timey; + time_t currenttime; + struct tm *ltime; + int screen = lock->screen; + Window win = lock->win; + char str[256] = {0}; /* - * Start formatting and drawing text + * Time text + */ + + XftDraw* draw = XftDrawCreate(dpy, win, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen)); + + time(¤ttime); + ltime = localtime(¤ttime); + snprintf(str, sizeof(str), "%02d:%02d", ltime->tm_hour, ltime->tm_min); + timelen = strlen(str); + + XGlyphInfo ext; + XftTextExtents8(dpy, lock->fonts[TIME], (XftChar8*)str, timelen, &ext); + timex = (DisplayWidth(dpy, screen) - ext.width) / 2; + timey = (DisplayHeight(dpy, screen) - ext.height) / 2; + + XftDrawString8(draw, &lock->font_colors[TIME], lock->fonts[TIME], timex, timey, (XftChar8*)str, timelen); + + /* + * Message 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; + XftTextExtents8(dpy, lock->fonts[TEXT], (XftChar8*)message, len, &ext); + x = (DisplayWidth(dpy, screen) - ext.width) / 2; + y = (DisplayHeight(dpy, screen) - ext.height) / 8 * 7; - height = DisplayHeight(dpy, screen)*3/7 - (k*20)/3; - width = (DisplayWidth(dpy, screen) - 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++; - } - } - } + XftDrawString8(draw, &lock->font_colors[TEXT], lock->fonts[TEXT], x, y, (XftChar8*)message, len); } - static void dontkillme(void) { @@ -196,7 +210,7 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, { XRRScreenChangeNotifyEvent *rre; char buf[32], passwd[256], *inputhash; - int num, screen, running, failure, oldc; + int num, screen, running, failure; unsigned int len, color; KeySym ksym; XEvent ev; @@ -204,9 +218,9 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, len = 0; running = 1; failure = 0; - oldc = INIT; + color = INIT; - while (running && !XNextEvent(dpy, &ev)) { + while (running && !XNextEventTimeout(dpy, &ev, 0.5)) { if (ev.type == KeyPress) { explicit_bzero(&buf, sizeof(buf)); num = XLookupString(&ev.xkey, buf, sizeof(buf), &ksym, 0); @@ -239,6 +253,7 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, break; case XK_Escape: explicit_bzero(&passwd, sizeof(passwd)); + running = 0; len = 0; break; case XK_BackSpace: @@ -254,16 +269,6 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, break; } color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT); - if (running && oldc != color) { - for (screen = 0; screen < nscreens; screen++) { - XSetWindowBackground(dpy, - locks[screen]->win, - locks[screen]->colors[color]); - XClearWindow(dpy, locks[screen]->win); - writemessage(dpy, locks[screen]->win, screen); - } - oldc = color; - } } else if (rr->active && ev.type == rr->evbase + RRScreenChangeNotify) { rre = (XRRScreenChangeNotifyEvent*)&ev; for (screen = 0; screen < nscreens; screen++) { @@ -275,6 +280,17 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, } } else for (screen = 0; screen < nscreens; screen++) XRaiseWindow(dpy, locks[screen]->win); + + if (running) { + for (screen = 0; screen < nscreens; screen++) { + XSetWindowBackground(dpy, + locks[screen]->win, + locks[screen]->colors[color]); + XClearWindow(dpy, locks[screen]->win); + writemessage(dpy, locks[screen]); + XSync(dpy, locks[screen]->win); + } + } } } @@ -315,6 +331,12 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) &color, &color, 0, 0); XDefineCursor(dpy, lock->win, invisible); + lock->fonts[TEXT] = XftFontOpenName(dpy, screen, text_font); + lock->fonts[TIME] = XftFontOpenName(dpy, screen, time_font); + + XftColorAllocName(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), text_color, &lock->font_colors[TEXT]); + XftColorAllocName(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), time_color, &lock->font_colors[TIME]); + /* Try to grab mouse pointer *and* keyboard for 600ms, else fail the lock */ for (i = 0, ptgrab = kbgrab = -1; i < 6; i++) { if (ptgrab != GrabSuccess) { @@ -356,6 +378,7 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) if (kbgrab != GrabSuccess) fprintf(stderr, "slock: unable to grab keyboard for screen %d\n", screen); + return NULL; } @@ -429,7 +452,7 @@ main(int argc, char **argv) { die("slock: out of memory\n"); for (nlocks = 0, s = 0; s < nscreens; s++) { if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL) { - writemessage(dpy, locks[s]->win, s); + writemessage(dpy, locks[s]); nlocks++; } else { break;