summaryrefslogtreecommitdiff
path: root/xlockkbd.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlockkbd.c')
-rw-r--r--xlockkbd.c78
1 files changed, 72 insertions, 6 deletions
diff --git a/xlockkbd.c b/xlockkbd.c
index 3e98621..2e970c5 100644
--- a/xlockkbd.c
+++ b/xlockkbd.c
@@ -1,13 +1,54 @@
+#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
-static void die(const char *s)
+struct named_mask {
+ const char *name;
+ unsigned int mask;
+};
+
+static const struct named_mask named_masks[] = {
+ { "Shift", ShiftMask },
+ { "Control", ControlMask },
+ { "Ctrl", ControlMask },
+ { "Alt", Mod1Mask },
+ { "Super", Mod4Mask },
+ { "Mod1", Mod1Mask },
+ { "Mod2", Mod2Mask },
+ { "Mod3", Mod3Mask },
+ { "Mod4", Mod4Mask },
+ { "Mod5", Mod5Mask }
+};
+#define len_named_masks (sizeof(named_masks) / sizeof(*named_masks))
+
+static unsigned int str_to_mask(const char *s)
+{
+ for (size_t i = 0; i < len_named_masks; ++i) {
+ const struct named_mask *m = named_masks + i;
+ if (!strcmp(s, m->name))
+ return m->mask;
+ }
+
+ return 0;
+}
+
+static void die(const char *fmt, ...)
{
- fprintf(stderr, "xlockkbd: %s\n", s);
+ va_list ap;
+ va_start(ap, fmt);
+
+ char *s;
+ if (vasprintf(&s, fmt, ap) != -1)
+ fprintf(stderr, "xlockkbd: %s\n", s);
+ else
+ fprintf(stderr, "xlockkbd: unknown error\n");
+
+ va_end(ap);
exit(1);
}
@@ -30,18 +71,43 @@ static bool grab_kbd(Display *d, int screen)
return (res == GrabSuccess);
}
-static void wait_for_key(Display *d)
+static void wait_for_release(Display *d, KeySym key, unsigned int mask)
{
XEvent ev;
while (!XNextEvent(d, &ev)) {
if (ev.type == KeyPress &&
- XLookupKeysym(&ev.xkey, 0) == XK_Escape)
+ XLookupKeysym(&ev.xkey, 0) == key &&
+ (mask & ev.xkey.state) == mask)
break;
}
}
-int main()
+int main(int argc, char **argv)
{
+ unsigned int mask = 0, arg_mask;
+ KeySym key = NoSymbol, arg_key;
+
+ for (int i = 1; i < argc; ++i) {
+ if ((arg_mask = str_to_mask(argv[i]))) {
+ mask = mask | arg_mask;
+ } else if (key != NoSymbol) {
+ die("more than one non-modifier key provided");
+ } else {
+ if ((arg_key = XStringToKeysym(argv[i])) == NoSymbol)
+ die("unknown key: %s", argv[i]);
+ if (arg_key >= XK_A && arg_key <= XK_Z)
+ die("use Shift modifier for uppercase key: %s",
+ argv[i]);
+ key = arg_key;
+ }
+ }
+
+ if (key == NoSymbol) {
+ if (mask)
+ die("no non-modifier key provided");
+ key = XK_Escape;
+ }
+
Display *d = XOpenDisplay(NULL);
if (!d)
die("cannot open display");
@@ -51,6 +117,6 @@ int main()
die("failed to grab keyboard");
}
- wait_for_key(d);
+ wait_for_release(d, key, mask);
return 0;
}