slock

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 2cf80900dad28a63647bcd6488382cd243abe562
parent 35633d45672d14bd798c478c45d1a17064701aa9
Author: bakkeby <bakkeby@gmail.com>
Date:   Thu, 17 Oct 2019 19:06:39 +0200

Added capscolor, control clear, dpms, mediakeys, message, pam auth, quickcancel patches

Diffstat:
A.gitignore | 3+++
AREADME.md | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mconfig.def.h | 38++++++++++++++++++++++++++++++++++++++
Mconfig.mk | 8+++++++-
Apatch/dpms.c | 10++++++++++
Apatch/include.c | 13+++++++++++++
Apatch/include.h | 5+++++
Apatch/message.c | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apatch/pamauth.c | 27+++++++++++++++++++++++++++
Apatch/pamauth.h | 6++++++
Apatches.h | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mslock.c | 196+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
12 files changed, 526 insertions(+), 6 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,3 @@ +*.o +dwm +config.h diff --git a/README.md b/README.md @@ -0,0 +1,54 @@ +Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this slock 1.4 project has a different take on patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. + +For example to include the `capscolor` patch then you would only need to flip this setting from 0 to 1 in [patches.h](https://github.com/bakkeby/slock-flexipatch/blob/master/patches.h): +```c +#define CAPSCOLOR_PATCH 1 +``` + +Once you have found out what works for you and what doesn't then you should be in a better position to choose patches should you want to start patching from scratch. + +Alternatively if you have found the patches you want, but don't want the rest of the flexipatch entanglement on your plate then you may want to have a look at [flexipatch-finalizer](https://github.com/bakkeby/flexipatch-finalizer); a custom pre-processor tool that removes all the unused flexipatch code leaving you with a build that contains the patches you selected. + +Refer to [https://tools.suckless.org/slock/](https://tools.suckless.org/slock/) for details on the slock tool, how to install it and how it works. + +--- + +### Changelog: + +2019-10-17 - Added capscolor, control clear, dpms, mediakeys, message, pam auth, quickcancel patches + +2019-10-16 - Introduced [flexipatch-finalizer](https://github.com/bakkeby/flexipatch-finalizer) + +### Patches included: + + - [capscolor](https://tools.suckless.org/slock/patches/capscolor/) + - adds an additional color to indicate the state of Caps Lock + + - [control-clear](https://tools.suckless.org/slock/patches/control-clear/) + - with this patch slock will no longer change to the failure color if a control key is pressed while the buffer is empty + - this may be useful if, for example, you wake your monitor up by pressing a control key and don't want to spoil the detection of failed unlocking attempts + + - [dpms](https://tools.suckless.org/slock/patches/dpms/) + - interacts with the Display Power Signaling and automatically shuts down the monitor after a configurable amount of seconds + - the monitor will automatically be activated by pressing a key or moving the mouse and the password can be entered then + + - [mediakeys](https://tools.suckless.org/slock/patches/mediakeys/) + - allows media keys to be used while the screen is locked, e.g. adjust volume or skip to the next song without having to unlock the screen first + + - [message](https://tools.suckless.org/slock/patches/message/) + - this patch lets you add a custom message to your lock screen + + - [pam-auth](https://tools.suckless.org/slock/patches/pam_auth/) + - replaces shadow support with PAM authentication support + + - [quickcancel](https://tools.suckless.org/slock/patches/quickcancel/) + - cancel slock by moving the mouse within a certain time-period after slock started + - the time-period can be defined in seconds with the setting timetocancel in the config.h + - this can be useful if you forgot to disable xautolock during an activity that requires no input (e.g. reading text, watching video, etc.) + + - [terminalkeys](https://tools.suckless.org/slock/patches/terminalkeys/) + - adds key commands that are commonly used in terminal applications (in particular the login prompt) + + - [unlockscreen](https://tools.suckless.org/slock/patches/unlock_screen/) + - this patch keeps the screen unlocked, but keeps the input locked + - that is, the screen is not affected by slock, but users will not be able to interact with the X session unless they enter the correct password +\ No newline at end of file diff --git a/config.def.h b/config.def.h @@ -6,7 +6,44 @@ static const char *colorname[NUMCOLS] = { [INIT] = "black", /* after initialization */ [INPUT] = "#005577", /* during input */ [FAILED] = "#CC3333", /* wrong password */ + #if CAPSCOLOR_PATCH + [CAPS] = "red", /* CapsLock on */ + #endif // CAPSCOLOR_PATCH + #if PAMAUTH_PATCH + [PAM] = "#9400D3", /* waiting for PAM */ + #endif // CAPSCOLOR_PATCH }; /* treat a cleared input like a wrong password (color) */ static const int failonclear = 1; + +#if CONTROLCLEAR_PATCH +/* allow control key to trigger fail on clear */ +static const int controlkeyclear = 0; +#endif // CONTROLCLEAR_PATCH + +#if DPMS_PATCH +/* time in seconds before the monitor shuts down */ +static const int monitortime = 5; +#endif // DPMS_PATCH + +#if MESSAGE_PATCH +/* 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 = "6x10"; +#endif // MESSAGE_PATCH + +#if PAMAUTH_PATCH +/* PAM service that's used for authentication */ +static const char* pam_service = "login"; +#endif // PAMAUTH_PATCH + +#if QUICKCANCEL_PATCH +/* time in seconds to cancel lock with mouse movement */ +static const int timetocancel = 4; +#endif // QUICKCANCEL_PATCH +\ No newline at end of file diff --git a/config.mk b/config.mk @@ -10,9 +10,15 @@ MANPREFIX = ${PREFIX}/share/man X11INC = /usr/X11R6/include X11LIB = /usr/X11R6/lib +# Uncomment for message patch / MESSAGE_PATCH +#XINERAMA=-lXinerama + +# Uncomment for pam auth patch / PAMAUTH_PATCH +#PAM=-lpam + # includes and libs INCS = -I. -I/usr/include -I${X11INC} -LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr +LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr ${XINERAMA} ${PAM} # flags CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H diff --git a/patch/dpms.c b/patch/dpms.c @@ -0,0 +1,9 @@ +#include <X11/extensions/dpms.h> + +static void +monitorreset(Display* dpy, CARD16 standby, CARD16 suspend, CARD16 off) +{ + DPMSSetTimeouts(dpy, standby, suspend, off); + DPMSForceLevel(dpy, DPMSModeOn); + XFlush(dpy); +} +\ No newline at end of file diff --git a/patch/include.c b/patch/include.c @@ -0,0 +1,12 @@ +/* Patches */ +#if DPMS_PATCH +#include "dpms.c" +#endif + +#if MESSAGE_PATCH +#include "message.c" +#endif + +#if PAMAUTH_PATCH +#include "pamauth.c" +#endif +\ No newline at end of file diff --git a/patch/include.h b/patch/include.h @@ -0,0 +1,4 @@ +/* Patches */ +#if PAMAUTH_PATCH +#include "pamauth.h" +#endif +\ No newline at end of file diff --git a/patch/message.c b/patch/message.c @@ -0,0 +1,94 @@ +#include <X11/extensions/Xinerama.h> + +/* global count to prevent repeated error messages */ +int count_error = 0; + +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; + XGCValues gr_values; + XFontStruct *fontinfo; + XColor color, dummy; + XineramaScreenInfo *xsi; + GC gc; + fontinfo = XLoadQueryFont(dpy, font_name); + + if (fontinfo == NULL) { + if (count_error == 0) { + fprintf(stderr, "slock: Unable to load font \"%s\"\n", font_name); + fprintf(stderr, "slock: Try listing fonts with 'slock -f'\n"); + count_error++; + } + return; + } + + 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); + + /* 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); + } + + height = s_height*3/7 - (k*20)/3; + width = (s_width - 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++; + } + } + } + + /* xsi should not be NULL anyway if Xinerama is active, but to be safe */ + if (XineramaIsActive(dpy) && xsi != NULL) + XFree(xsi); +} +\ No newline at end of file diff --git a/patch/pamauth.c b/patch/pamauth.c @@ -0,0 +1,27 @@ +char passwd[256]; + +static int +pam_conv(int num_msg, const struct pam_message **msg, + struct pam_response **resp, void *appdata_ptr) +{ + int retval = PAM_CONV_ERR; + for (int i=0; i<num_msg; i++) { + if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF && + strncmp(msg[i]->msg, "Password: ", 10) == 0) { + struct pam_response *resp_msg = malloc(sizeof(struct pam_response)); + if (!resp_msg) + die("malloc failed\n"); + char *password = malloc(strlen(passwd) + 1); + if (!password) + die("malloc failed\n"); + memset(password, 0, strlen(passwd) + 1); + strcpy(password, passwd); + resp_msg->resp_retcode = 0; + resp_msg->resp = password; + resp[i] = resp_msg; + retval = PAM_SUCCESS; + } + } + return retval; +} + diff --git a/patch/pamauth.h b/patch/pamauth.h @@ -0,0 +1,5 @@ +#include <security/pam_appl.h> +#include <security/pam_misc.h> + +static int pam_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr); +struct pam_conv pamc = {pam_conv, NULL}; +\ No newline at end of file diff --git a/patches.h b/patches.h @@ -0,0 +1,75 @@ +/* + * This file contains patch control flags. + * + * In principle you should be able to mix and match any patches + * you may want. In cases where patches are logically incompatible + * one patch may take precedence over the other as noted in the + * relevant descriptions. + */ + +/* Patches */ + +/* This patch introduces an additional color to indicate the state of Caps Lock. + * https://tools.suckless.org/slock/patches/capscolor/ + */ +#define CAPSCOLOR_PATCH 0 + +/* Adds an additional configuration parameter, controlkeyclear. When set to 1, slock will no + * longer change to the failure color if a control key is pressed while the buffer is empty. + * This may be useful if, for example, you wake your monitor up by pressing a control key + * and don't want to spoil the detection of failed unlocking attempts. + * https://tools.suckless.org/slock/patches/control-clear/ + */ +#define CONTROLCLEAR_PATCH 0 + +/* This patch interacts with the Display Power Signaling and automatically shuts down +* the monitor after a configurable amount of seconds. +* The monitor will automatically be activated by pressing a key or moving the mouse +* and the password can be entered then. +* https://tools.suckless.org/slock/patches/dpms/ +*/ +#define DPMS_PATCH 0 + +/* This patch allows media keys to be used while the screen is locked. Allows for volume + * to be adjusted or to skip to the next song without having to unlock the screen first. + * https://tools.suckless.org/slock/patches/mediakeys/ + */ +#define MEDIAKEYS_PATCH 0 + +/* This patch lets you add a message to your lock screen. You can place a default message + * in config.h and you can also pass a message with the -m command line option. + * If you enable this then you also need to add the -lXinerama library to the LIBS + * configuration in config.mk. Look for and uncomment the XINERAMA placeholder. + * https://tools.suckless.org/slock/patches/message/ + */ +#define MESSAGE_PATCH 0 + +/* Replaces shadow support with PAM authentication support. + * Change variable pam_service in config.def.h to the corresponding PAM service. + * The default configuration is for ArchLinux's login service. + * If you enable this then you also need to add the -lpam library to the LIBS configuration + * in config.mk. Look for and uncomment the PAM placeholder. + * https://tools.suckless.org/slock/patches/pam_auth/ + */ +#define PAMAUTH_PATCH 0 + +/* Cancel slock by moving the mouse within a certain time-period after slock started. + * The time-period can be defined in seconds with the setting timetocancel in the config.h. + * This can be useful if you forgot to disable xautolock during an activity that requires + * no input (e.g. reading text, watching video, etc.). + * https://tools.suckless.org/slock/patches/quickcancel/ + */ +#define QUICKCANCEL_PATCH 0 + +/* Adds key commands that are commonly used in terminal applications (in particular the + * login prompt) to slock. + * https://tools.suckless.org/slock/patches/terminalkeys/ + */ +#define TERMINALKEYS_PATCH 0 + +/* This patch keeps the screen unlocked but keeps the input locked. That is, the screen + * is not affected by slock, but users will not be able to interact with the X session + * unless they enter the correct password. + * https://tools.suckless.org/slock/patches/unlock_screen/ + */ +#define UNLOCKSCREEN_PATCH 0 +\ No newline at end of file diff --git a/slock.c b/slock.c @@ -19,15 +19,36 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> +#include "patches.h" +#if CAPSCOLOR_PATCH +#include <X11/XKBlib.h> +#endif // CAPSCOLOR_PATCH +#if MEDIAKEYS_PATCH +#include <X11/XF86keysym.h> +#endif // MEDIAKEYS_PATCH +#if QUICKCANCEL_PATCH +#include <time.h> +#endif // QUICKCANCEL_PATCH + #include "arg.h" #include "util.h" char *argv0; +#if QUICKCANCEL_PATCH +static time_t locktime; +#endif // QUICKCANCEL_PATCH + enum { INIT, INPUT, FAILED, + #if CAPSCOLOR_PATCH + CAPS, + #endif // CAPSCOLOR_PATCH + #if PAMAUTH_PATCH + PAM, + #endif // PAMAUTH_PATCH NUMCOLS }; @@ -44,6 +65,7 @@ struct xrandr { int errbase; }; +#include "patch/include.h" #include "config.h" static void @@ -57,6 +79,8 @@ die(const char *errstr, ...) exit(1); } +#include "patch/include.c" + #ifdef __linux__ #include <fcntl.h> #include <linux/oom.h> @@ -121,6 +145,10 @@ gethash(void) } #endif /* HAVE_SHADOW_H */ + #if PAMAUTH_PATCH + /* pam, store user name */ + hash = pw->pw_name; + #endif // PAMAUTH_PATCH return hash; } @@ -129,18 +157,39 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, const char *hash) { XRRScreenChangeNotifyEvent *rre; + #if PAMAUTH_PATCH + char buf[32]; + int retval; + pam_handle_t *pamh; + #else char buf[32], passwd[256], *inputhash; + #endif // PAMAUTH_PATCH int num, screen, running, failure, oldc; unsigned int len, color; + #if CAPSCOLOR_PATCH + int caps; + unsigned int indicators; + #endif // CAPSCOLOR_PATCH KeySym ksym; XEvent ev; len = 0; + #if CAPSCOLOR_PATCH + caps = 0; + #endif // CAPSCOLOR_PATCH running = 1; failure = 0; oldc = INIT; + #if CAPSCOLOR_PATCH + if (!XkbGetIndicatorState(dpy, XkbUseCoreKbd, &indicators)) + caps = indicators & 1; + + #endif // CAPSCOLOR_PATCH while (running && !XNextEvent(dpy, &ev)) { + #if QUICKCANCEL_PATCH + running = !((time(NULL) - locktime < timetocancel) && (ev.type == MotionNotify)); + #endif // QUICKCANCEL_PATCH if (ev.type == KeyPress) { explicit_bzero(&buf, sizeof(buf)); num = XLookupString(&ev.xkey, buf, sizeof(buf), &ksym, 0); @@ -156,14 +205,55 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, IsPFKey(ksym) || IsPrivateKeypadKey(ksym)) continue; + #if TERMINALKEYS_PATCH + if (ev.xkey.state & ControlMask) { + switch (ksym) { + case XK_u: + ksym = XK_Escape; + break; + case XK_m: + ksym = XK_Return; + break; + case XK_j: + ksym = XK_Return; + break; + case XK_h: + ksym = XK_BackSpace; + break; + } + } + #endif // TERMINALKEYS_PATCH switch (ksym) { case XK_Return: passwd[len] = '\0'; errno = 0; + #if PAMAUTH_PATCH + retval = pam_start(pam_service, hash, &pamc, &pamh); + color = PAM; + for (screen = 0; screen < nscreens; screen++) { + XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[color]); + XClearWindow(dpy, locks[screen]->win); + XRaiseWindow(dpy, locks[screen]->win); + } + XSync(dpy, False); + + if (retval == PAM_SUCCESS) + retval = pam_authenticate(pamh, 0); + if (retval == PAM_SUCCESS) + retval = pam_acct_mgmt(pamh, 0); + + running = 1; + if (retval == PAM_SUCCESS) + running = 0; + else + fprintf(stderr, "slock: %s\n", pam_strerror(pamh, retval)); + pam_end(pamh, retval); + #else if (!(inputhash = crypt(passwd, hash))) fprintf(stderr, "slock: crypt: %s\n", strerror(errno)); else running = !!strcmp(inputhash, hash); + #endif // PAMAUTH_PATCH if (running) { XBell(dpy, 100); failure = 1; @@ -179,21 +269,51 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, if (len) passwd[--len] = '\0'; break; + #if CAPSCOLOR_PATCH + case XK_Caps_Lock: + caps = !caps; + break; + #endif // CAPSCOLOR_PATCH + #if MEDIAKEYS_PATCH + case XF86XK_AudioLowerVolume: + case XF86XK_AudioMute: + case XF86XK_AudioRaiseVolume: + case XF86XK_AudioPlay: + case XF86XK_AudioStop: + case XF86XK_AudioPrev: + case XF86XK_AudioNext: + XSendEvent(dpy, DefaultRootWindow(dpy), True, KeyPressMask, &ev); + break; + #endif // MEDIAKEYS_PATCH default: + #if CONTROLCLEAR_PATCH + if (controlkeyclear && iscntrl((int)buf[0])) + continue; + if (num && (len + num < sizeof(passwd))) + #else if (num && !iscntrl((int)buf[0]) && - (len + num < sizeof(passwd))) { + (len + num < sizeof(passwd))) + #endif // CONTROLCLEAR_PATCH + { memcpy(passwd + len, buf, num); len += num; } break; } + #if CAPSCOLOR_PATCH + color = len ? (caps ? CAPS : INPUT) : (failure || failonclear ? FAILED : INIT); + #else color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT); + #endif // CAPSCOLOR_PATCH if (running && oldc != color) { for (screen = 0; screen < nscreens; screen++) { XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[color]); XClearWindow(dpy, locks[screen]->win); + #if MESSAGE_PATCH + writemessage(dpy, locks[screen]->win, screen); + #endif // MESSAGE_PATCH } oldc = color; } @@ -262,7 +382,13 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) ptgrab = XGrabPointer(dpy, lock->root, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync, - GrabModeAsync, None, invisible, CurrentTime); + GrabModeAsync, None, + #if UNLOCKSCREEN_PATCH + None, + #else + invisible, + #endif // UNLOCKSCREEN_PATCH + CurrentTime); } if (kbgrab != GrabSuccess) { kbgrab = XGrabKeyboard(dpy, lock->root, True, @@ -271,11 +397,16 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) /* input is grabbed: we can lock the screen */ if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) { + #if !UNLOCKSCREEN_PATCH XMapRaised(dpy, lock->win); + #endif // UNLOCKSCREEN_PATCH if (rr->active) XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask); XSelectInput(dpy, lock->root, SubstructureNotifyMask); + #if QUICKCANCEL_PATCH + locktime = time(NULL); + #endif // QUICKCANCEL_PATCH return lock; } @@ -300,7 +431,11 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) static void usage(void) { + #if MESSAGE_PATCH + die("usage: slock [-v] [-f] [-m message] [cmd [arg ...]]\n"); + #else die("usage: slock [-v] [cmd [arg ...]]\n"); + #endif // MESSAGE_PATCH } int @@ -314,11 +449,30 @@ main(int argc, char **argv) { const char *hash; Display *dpy; int s, nlocks, nscreens; - + #if DPMS_PATCH + CARD16 standby, suspend, off; + #endif // DPMS_PATCH + #if MESSAGE_PATCH + int i, count_fonts; + char **font_names; + #endif // MESSAGE_PATCH ARGBEGIN { case 'v': fprintf(stderr, "slock-"VERSION"\n"); return 0; + #if MESSAGE_PATCH + case 'm': + message = EARGF(usage()); + break; + case 'f': + if (!(dpy = XOpenDisplay(NULL))) + die("slock: cannot open display\n"); + font_names = XListFonts(dpy, "*", 10000 /* list 10000 fonts*/, &count_fonts); + for (i=0; i<count_fonts; i++) { + fprintf(stderr, "%s\n", *(font_names+i)); + } + return 0; + #endif // MESSAGE_PATCH default: usage(); } ARGEND @@ -339,10 +493,15 @@ main(int argc, char **argv) { dontkillme(); #endif + #if PAMAUTH_PATCH + /* the contents of hash are used to transport the current user name */ + #endif // PAMAUTH_PATCH hash = gethash(); errno = 0; + #if !PAMAUTH_PATCH if (!crypt("", hash)) die("slock: crypt: %s\n", strerror(errno)); + #endif // PAMAUTH_PATCH if (!(dpy = XOpenDisplay(NULL))) die("slock: cannot open display\n"); @@ -363,10 +522,14 @@ 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) { + #if MESSAGE_PATCH + writemessage(dpy, locks[s]->win, s); + #endif // MESSAGE_PATCH nlocks++; - else + } else { break; + } } XSync(dpy, 0); @@ -374,12 +537,31 @@ main(int argc, char **argv) { if (nlocks != nscreens) return 1; + #if DPMS_PATCH + /* DPMS-magic to disable the monitor */ + if (!DPMSCapable(dpy)) + die("slock: DPMSCapable failed\n"); + if (!DPMSEnable(dpy)) + die("slock: DPMSEnable failed\n"); + if (!DPMSGetTimeouts(dpy, &standby, &suspend, &off)) + die("slock: DPMSGetTimeouts failed\n"); + if (!standby || !suspend || !off) + /* set values if there arent some */ + standby = suspend = off = 300; + + DPMSSetTimeouts(dpy, monitortime, monitortime, monitortime); + XFlush(dpy); + #endif // DPMS_PATCH + /* run post-lock command */ if (argc > 0) { switch (fork()) { case -1: die("slock: fork failed: %s\n", strerror(errno)); case 0: + #if DPMS_PATCH + monitorreset(dpy, standby, suspend, off); + #endif // DPMS_PATCH if (close(ConnectionNumber(dpy)) < 0) die("slock: close: %s\n", strerror(errno)); execvp(argv[0], argv); @@ -390,6 +572,10 @@ main(int argc, char **argv) { /* everything is now blank. Wait for the correct password */ readpw(dpy, &rr, locks, nscreens, hash); + #if DPMS_PATCH + /* reset DPMS values to inital ones */ + monitorreset(dpy, standby, suspend, off); + #endif // DPMS_PATCH return 0; }