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. AFAIK the existing arg parsing system does
not support continuing execution if a flag is set, so sorry for the
messy arg handling.
The DPMS patch is also included, with a separate DPMS sleep timer in
config.h. The use for this, in my case, is keeping the screensaver on
indefinitely, whilst having running slock normally lead to screen
powering off after 3s.
---
config.def.h | 5 +++++
slock.c | 57 +++++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 52 insertions(+), 10 deletions(-)
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;
}
--
2.51.0