From c66b8ded10f0d5e872e507fdff3010f732aa5449 Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Thu, 2 Apr 2020 16:06:35 +0200 Subject: Split main.cpp into separate files --- xutil.cpp | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 xutil.cpp (limited to 'xutil.cpp') diff --git a/xutil.cpp b/xutil.cpp new file mode 100644 index 0000000..e5eb8c2 --- /dev/null +++ b/xutil.cpp @@ -0,0 +1,113 @@ +#include +#include +#include +#include "xutil.h" + + +namespace x { + + Keycode::Keycode() + : code{0} {} + + Keycode::Keycode(unsigned int code) + : code{code} {} + + Keycode::operator unsigned int() const { + return code; + } + + bool Keycode::operator==(Keycode other) const { + return code == other.code; + } + + Keysym::Keysym() + : sym{0} {} + + Keysym::Keysym(unsigned int sym) + : sym{sym} {} + + Keysym::operator unsigned int() const { + return sym; + } + + Keycode Keysym::toCode(Display *dpy) const { + return XKeysymToKeycode(dpy, sym); + } + + bool Keysym::operator==(Keysym other) const { + return sym == other.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