#pragma once #include #include namespace x { // Typed wrapper for an X keycode class Keycode { public: Keycode(); Keycode(unsigned int code); explicit operator unsigned int() const; bool operator==(Keycode other) const; private: unsigned int code; }; // Typed wrapper for an X keysym class Keysym { public: Keysym(); Keysym(unsigned int sym); explicit operator unsigned int() const; Keycode toCode(Display *dpy) const; bool operator==(Keysym other) const; private: unsigned int sym; }; // Play the system bell void bel(Display *dpy); // Run a handler on scope exit template 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; }; // 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> 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> XGrabKeyboardRAII(Display *dpy, Window win); // Open the specified display (pass nullptr to use $DISPLAY). Drop the UponExit to close. std::pair>> 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 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 callback); } template <> struct std::hash { size_t operator()(x::Keycode code) const { return std::hash{}((unsigned int)code); } }; template <> struct std::hash { size_t operator()(x::Keysym sym) const { return std::hash{}((unsigned int)sym); } };