diff options
Diffstat (limited to 'xutil.h')
-rw-r--r-- | xutil.h | 95 |
1 files changed, 95 insertions, 0 deletions
@@ -0,0 +1,95 @@ +#pragma once + +#include <functional> +#include <optional> +#include <X11/Xlib.h> + + +namespace x { + + // Typed wrapper for an X keycode + class Keycode { + public: + Keycode() = default; + inline Keycode(unsigned int code) : code{code} {}; + inline explicit operator unsigned int() const { return code; }; + inline bool operator==(Keycode other) const { return code == other.code; } + private: + unsigned int code = 0; + }; + + // Typed wrapper for an X keysym + class Keysym { + public: + Keysym() = default; + inline Keysym(unsigned int sym) : sym{sym} {}; + inline explicit operator unsigned int() const { return sym; } + Keycode toCode(Display *dpy) const; + inline bool operator==(Keysym other) const { return sym == other.sym; } + private: + unsigned int sym = 0; + }; + + // Play the system bell + void bel(Display *dpy); + + // Run a handler on scope exit + template <typename Cleanup> + class UponExit { + public: + UponExit(Cleanup cleanup) : cleanup{cleanup} {} + ~UponExit() { + if (cleanup) (*cleanup)(); + } + UponExit(const UponExit&) = delete; + UponExit(UponExit &&other) : cleanup{move(other.cleanup)} { + other.cleanup.reset(); + } + UponExit& operator=(const UponExit&) = delete; + UponExit& operator=(UponExit &&other) { + cleanup = move(other.cleanup); + other.cleanup.reset(); + } + + private: + std::optional<Cleanup> cleanup; + }; + + // Grab a single key (code + modifier) on the X server in the given window. + // Drop the UponExit to ungrab. For a global grab, use + // DefaultRootWindow(dpy) as the window. + UponExit<std::function<void()>> XGrabKeyRAII(Display *dpy, Keycode code, int modifier, Window win); + + // Grab a the whole keyboard on the X server in the given window. Drop the + // UponExit to ungrab. For a global grab, use DefaultRootWindow(dpy) as the + // window. + UponExit<std::function<void()>> XGrabKeyboardRAII(Display *dpy, Window win); + + // Open the specified display (pass nullptr to use $DISPLAY). Drop the UponExit to close. + std::pair<Display*, UponExit<std::function<void()>>> XOpenDisplayRAII(const char *name); + + // Grab the specified key globally for any modifier combination, and run + // the callback on every hit of that key. Ungrabs and returns when the + // callback returns true. + void globalKeyWatch(Display *dpy, Keysym keysym, std::function<bool(const XKeyEvent&)> callback); + + // Grab the whole keyboard globally, and run the callback on every keyboard + // key event. Ungrabs and returns when the callback returns true. + void globalKeyboardGrab(Display *dpy, std::function<bool(const XKeyEvent&)> callback); + +} + +template <> +struct std::hash<x::Keycode> { + size_t operator()(x::Keycode code) const { + return std::hash<unsigned int>{}((unsigned int)code); + } +}; + +template <> +struct std::hash<x::Keysym> { + size_t operator()(x::Keysym sym) const { + return std::hash<unsigned int>{}((unsigned int)sym); + } +}; + |