commit 5fc1bbee1bb42d9d345badc43dc380df8ea59bcd
parent c20a1103b6e965c0e60bff014f0ac47f77473e8d
Author: cat <cat@plan9.rocks>
Date: Mon, 3 Nov 2025 17:01:12 +0000
[slock][patches][visual-unlock-dpms] add patch
Diffstat:
2 files changed, 165 insertions(+), 0 deletions(-)
diff --git a/tools.suckless.org/slock/patches/visual-unlock-dpms/index.md b/tools.suckless.org/slock/patches/visual-unlock-dpms/index.md
@@ -0,0 +1,31 @@
+Visual Unlock + DPMS
+====================
+
+Description
+-----------
+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.
+
+Unlike the unlock screen patch, this uses an arg (-u) to enable the
+unlocked screen functionality, and the mouse will remain hidden. The
+primary use case for this would be in a script to spawn a screensaver
+when the screen is locked.
+
+The DPMS patch is also included, with a separate DPMS sleep timer in
+config.def.h. This might be used to keep the screensaver on for 5
+minutes, while running slock without -u has the screen sleep after 3
+seconds of inactivity.
+
+If you would not like to use DPMS, set both DPMS timers to 0 in your
+config.h.
+
+
+Download
+--------
+* [slock-visual-unlock-dpms-1.6.diff](slock-visual-unlock-dpms-1.6.diff)
+
+Authors
+-------
+* cat <cat@plan9.rocks>
diff --git a/tools.suckless.org/slock/patches/visual-unlock-dpms/slock-visual-unlock-dpms-1.6.diff b/tools.suckless.org/slock/patches/visual-unlock-dpms/slock-visual-unlock-dpms-1.6.diff
@@ -0,0 +1,134 @@
+diff --git a/config.def.h b/config.def.h
+index 9855e21..97a4842 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -10,3 +10,8 @@ static const char *colorname[NUMCOLS] = {
+
+ /* treat a cleared input like a wrong password (color) */
+ static const int failonclear = 1;
++
++/* time in seconds before the monitor shuts down */
++static int monitortime = 3;
++/* time in seconds before the monitor shuts down, if visual_unlock is enabled */
++static const int monitortime_vu = 0;
+diff --git a/slock.c b/slock.c
+index b5a9b04..c9ddfb2 100644
+--- a/slock.c
++++ b/slock.c
+@@ -1,4 +1,5 @@
+ /* See LICENSE file for license details. */
++#include <X11/Xmd.h>
+ #define _XOPEN_SOURCE 500
+ #if HAVE_SHADOW_H
+ #include <shadow.h>
+@@ -9,6 +10,7 @@
+ #include <grp.h>
+ #include <pwd.h>
+ #include <stdarg.h>
++#include <stdbool.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
+@@ -16,6 +18,7 @@
+ #include <spawn.h>
+ #include <sys/types.h>
+ #include <X11/extensions/Xrandr.h>
++#include <X11/extensions/dpms.h>
+ #include <X11/keysym.h>
+ #include <X11/Xlib.h>
+ #include <X11/Xutil.h>
+@@ -45,6 +48,8 @@ struct xrandr {
+ int errbase;
+ };
+
++bool visual_unlock = false;
++
+ #include "config.h"
+
+ static void
+@@ -272,7 +277,8 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
+
+ /* input is grabbed: we can lock the screen */
+ if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) {
+- XMapRaised(dpy, lock->win);
++ if (!visual_unlock)
++ XMapRaised(dpy, lock->win);
+ if (rr->active)
+ XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask);
+
+@@ -301,7 +307,7 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
+ static void
+ usage(void)
+ {
+- die("usage: slock [-v] [cmd [arg ...]]\n");
++ die("usage: slock [-u] [-v] [cmd [arg ...]]\n");
+ }
+
+ int
+@@ -315,14 +321,20 @@ main(int argc, char **argv) {
+ const char *hash;
+ Display *dpy;
+ int s, nlocks, nscreens;
+-
+- ARGBEGIN {
+- case 'v':
+- puts("slock-"VERSION);
+- return 0;
+- default:
+- usage();
+- } ARGEND
++ CARD16 standby, suspend, off;
++ BOOL dpms_state;
++
++ if (argc > 1 && strcmp(argv[1], "-u") == 0) {
++ visual_unlock = true;
++ } else {
++ ARGBEGIN {
++ case 'v':
++ puts("slock-"VERSION);
++ return 0;
++ default:
++ usage();
++ } ARGEND
++ }
+
+ /* validate drop-user and -group */
+ errno = 0;
+@@ -375,6 +387,25 @@ main(int argc, char **argv) {
+ if (nlocks != nscreens)
+ return 1;
+
++ /* DPMS magic to disable the monitor */
++ if (visual_unlock) monitortime = monitortime_vu;
++
++ if (!DPMSCapable(dpy))
++ die("slock: DPMSCapable failed\n");
++ if (!DPMSInfo(dpy, &standby, &dpms_state))
++ die("slock: DPMSInfo failed\n");
++ if (!DPMSEnable(dpy) && !dpms_state)
++ die("slock: DPMSEnable failed\n");
++ if (!DPMSGetTimeouts(dpy, &standby, &suspend, &off))
++ die("slock: DPMSGetTimeouts failed\n");
++ if (!standby || !suspend || !off)
++ die("slock: at least one DPMS variable is zero\n");
++ if (!DPMSSetTimeouts(dpy, monitortime, monitortime, monitortime))
++ die("slock: DPMSSetTimeouts failed\n");
++ if (!DPMSSetTimeouts(dpy, monitortime, monitortime, monitortime))
++ die("slock: DPMSSetTimeouts failed\n");
++ XSync(dpy, 0);
++
+ /* run post-lock command */
+ if (argc > 0) {
+ pid_t pid;
+@@ -389,5 +420,11 @@ main(int argc, char **argv) {
+ /* everything is now blank. Wait for the correct password */
+ readpw(dpy, &rr, locks, nscreens, hash);
+
++ /* reset DPMS values to inital ones */
++ DPMSSetTimeouts(dpy, standby, suspend, off);
++ if (!dpms_state)
++ DPMSDisable(dpy);
++ XSync(dpy, 0);
++
+ return 0;
+ }