From 6060db32b949d62757b668f972648465f1e302c7 Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Wed, 31 Jan 2024 15:42:17 +0100 Subject: Initial --- xutil.cpp | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 xutil.cpp (limited to 'xutil.cpp') diff --git a/xutil.cpp b/xutil.cpp new file mode 100644 index 0000000..7adceaa --- /dev/null +++ b/xutil.cpp @@ -0,0 +1,85 @@ +#include +#include +#include +#include "xutil.h" + + +namespace x { + + Keycode Keysym::toCode(Display *dpy) const { + return XKeysymToKeycode(dpy, sym); + } + + void bel(Display *dpy) { + XkbBell(dpy, None, 100, None); + } + + using UponExitF = UponExit>; + + UponExitF XGrabKeyRAII(Display *dpy, Keycode code, int modifier, Window win) { + XGrabKey(dpy, (unsigned int)code, modifier, win, False, GrabModeAsync, GrabModeAsync); + return UponExitF{[dpy, code, modifier, win]() { + XUngrabKey(dpy, (unsigned int)code, modifier, win); + XSync(dpy, False); + }}; + } + + UponExitF XGrabKeyboardRAII(Display *dpy, Window win) { + int ret = XGrabKeyboard(dpy, win, False, GrabModeAsync, GrabModeAsync, CurrentTime); + if (ret == AlreadyGrabbed) { + XUngrabKeyboard(dpy, CurrentTime); + XSync(dpy, False); + throw std::runtime_error("Cannot grab keyboard: already grabbed"); + } + return UponExitF{[dpy]() { + XUngrabKeyboard(dpy, CurrentTime); + XSync(dpy, False); + }}; + } + + std::pair XOpenDisplayRAII(const char *name) { + Display *dpy = XOpenDisplay(name); + if (dpy == nullptr) { + std::cerr << "Cannot open X display" << std::endl; + exit(1); + } + return std::make_pair(dpy, UponExitF{[dpy]() { + XCloseDisplay(dpy); + }}); + } + + void globalKeyWatch(Display *dpy, Keysym keysym, std::function callback) { + const Window root = DefaultRootWindow(dpy); + const Keycode keycode = keysym.toCode(dpy); + + auto guard = XGrabKeyRAII(dpy, keycode, AnyModifier, root); + + XSelectInput(dpy, root, KeyPressMask); + while (true) { + XEvent ev; + XNextEvent(dpy, &ev); + if (ev.type == KeyPress && ev.xkey.keycode == (unsigned int)keycode) { + if (callback(ev.xkey)) return; + } + } + } + + void globalKeyboardGrab(Display *dpy, std::function callback) { + const Window root = DefaultRootWindow(dpy); + + try { + auto guard = XGrabKeyboardRAII(dpy, root); + + while (true) { + XEvent ev; + XNextEvent(dpy, &ev); + if (ev.type == KeyPress) { + if (callback(ev.xkey)) return; + } + } + } catch (std::exception &e) { + std::cerr << e.what() << std::endl; + } + } + +} -- cgit v1.2.3-70-g09d2