aboutsummaryrefslogtreecommitdiff
path: root/include/GlobalHotkeys
diff options
context:
space:
mode:
Diffstat (limited to 'include/GlobalHotkeys')
-rw-r--r--include/GlobalHotkeys/GlobalHotkeys.hpp45
-rw-r--r--include/GlobalHotkeys/GlobalHotkeysJoystick.hpp70
-rw-r--r--include/GlobalHotkeys/GlobalHotkeysLinux.hpp34
-rw-r--r--include/GlobalHotkeys/GlobalHotkeysX11.hpp34
4 files changed, 183 insertions, 0 deletions
diff --git a/include/GlobalHotkeys/GlobalHotkeys.hpp b/include/GlobalHotkeys/GlobalHotkeys.hpp
new file mode 100644
index 0000000..2927fa7
--- /dev/null
+++ b/include/GlobalHotkeys/GlobalHotkeys.hpp
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <stdint.h>
+#include <functional>
+#include <string>
+
+namespace mgl {
+ class Event;
+}
+
+namespace gsr {
+ enum HotkeyModifier : uint32_t {
+ HOTKEY_MOD_LSHIFT = 1 << 0,
+ HOTKEY_MOD_RSHIFT = 1 << 1,
+ HOTKEY_MOD_LCTRL = 1 << 2,
+ HOTKEY_MOD_RCTRL = 1 << 3,
+ HOTKEY_MOD_LALT = 1 << 4,
+ HOTKEY_MOD_RALT = 1 << 5,
+ HOTKEY_MOD_LSUPER = 1 << 6,
+ HOTKEY_MOD_RSUPER = 1 << 7
+ };
+
+ struct Hotkey {
+ uint32_t key = 0; // X11 keysym
+ uint32_t modifiers = 0; // HotkeyModifier
+ };
+
+ using GlobalHotkeyCallback = std::function<void(const std::string &id)>;
+
+ class GlobalHotkeys {
+ public:
+ GlobalHotkeys() = default;
+ GlobalHotkeys(const GlobalHotkeys&) = delete;
+ GlobalHotkeys& operator=(const GlobalHotkeys&) = delete;
+ virtual ~GlobalHotkeys() = default;
+
+ virtual bool bind_key_press(Hotkey hotkey, const std::string &id, GlobalHotkeyCallback callback) { (void)hotkey; (void)id; (void)callback; return false; }
+ virtual void unbind_key_press(const std::string &id) { (void)id; }
+ virtual void unbind_all_keys() {}
+ virtual bool bind_action(const std::string &id, GlobalHotkeyCallback callback) { (void)id; (void)callback; return false; };
+ virtual void poll_events() = 0;
+ // Returns true if the event wasn't consumed (if the event didn't match a key that has been bound)
+ virtual bool on_event(mgl::Event &event) { (void)event; return true; }
+ };
+} \ No newline at end of file
diff --git a/include/GlobalHotkeys/GlobalHotkeysJoystick.hpp b/include/GlobalHotkeys/GlobalHotkeysJoystick.hpp
new file mode 100644
index 0000000..4b266cb
--- /dev/null
+++ b/include/GlobalHotkeys/GlobalHotkeysJoystick.hpp
@@ -0,0 +1,70 @@
+#pragma once
+
+#include "GlobalHotkeys.hpp"
+#include "../Hotplug.hpp"
+#include <unordered_map>
+#include <thread>
+#include <poll.h>
+#include <linux/joystick.h>
+
+namespace gsr {
+ static constexpr int max_js_poll_fd = 16;
+
+ class GlobalHotkeysJoystick : public GlobalHotkeys {
+ class GlobalHotkeysJoystickHotplugDelegate;
+ public:
+ GlobalHotkeysJoystick() = default;
+ GlobalHotkeysJoystick(const GlobalHotkeysJoystick&) = delete;
+ GlobalHotkeysJoystick& operator=(const GlobalHotkeysJoystick&) = delete;
+ ~GlobalHotkeysJoystick() override;
+
+ bool start();
+ // Currently valid ids:
+ // save_replay
+ // save_1_min_replay
+ // save_10_min_replay
+ // take_screenshot
+ // toggle_record
+ // toggle_replay
+ // toggle_show
+ bool bind_action(const std::string &id, GlobalHotkeyCallback callback) override;
+ void poll_events() override;
+ private:
+ void read_events();
+ void process_js_event(int fd, js_event &event);
+ bool add_device(const char *dev_input_filepath, bool print_error = true);
+ bool remove_device(const char *dev_input_filepath);
+ bool remove_poll_fd(int index);
+ // Returns -1 if not found
+ int get_poll_fd_index_by_dev_input_id(int dev_input_id) const;
+ private:
+ struct ExtraData {
+ int dev_input_id = 0;
+ };
+
+ std::unordered_map<std::string, GlobalHotkeyCallback> bound_actions_by_id;
+ std::thread read_thread;
+
+ pollfd poll_fd[max_js_poll_fd];
+ ExtraData extra_data[max_js_poll_fd];
+ int num_poll_fd = 0;
+ int event_fd = -1;
+ int event_index = -1;
+
+ bool playstation_button_pressed = false;
+ bool up_pressed = false;
+ bool down_pressed = false;
+ bool left_pressed = false;
+ bool right_pressed = false;
+
+ bool save_replay = false;
+ bool save_1_min_replay = false;
+ bool save_10_min_replay = false;
+ bool take_screenshot = false;
+ bool toggle_record = false;
+ bool toggle_replay = false;
+ bool toggle_show = false;
+ int hotplug_poll_index = -1;
+ Hotplug hotplug;
+ };
+} \ No newline at end of file
diff --git a/include/GlobalHotkeys/GlobalHotkeysLinux.hpp b/include/GlobalHotkeys/GlobalHotkeysLinux.hpp
new file mode 100644
index 0000000..959d095
--- /dev/null
+++ b/include/GlobalHotkeys/GlobalHotkeysLinux.hpp
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "GlobalHotkeys.hpp"
+#include <unordered_map>
+#include <sys/types.h>
+
+namespace gsr {
+ class GlobalHotkeysLinux : public GlobalHotkeys {
+ public:
+ enum class GrabType {
+ ALL,
+ VIRTUAL
+ };
+
+ GlobalHotkeysLinux(GrabType grab_type);
+ GlobalHotkeysLinux(const GlobalHotkeysLinux&) = delete;
+ GlobalHotkeysLinux& operator=(const GlobalHotkeysLinux&) = delete;
+ ~GlobalHotkeysLinux() override;
+
+ bool start();
+ bool bind_key_press(Hotkey hotkey, const std::string &id, GlobalHotkeyCallback callback) override;
+ void unbind_all_keys() override;
+ void poll_events() override;
+ private:
+ void close_fds();
+ private:
+ pid_t process_id = 0;
+ int read_pipes[2];
+ int write_pipes[2];
+ FILE *read_file = nullptr;
+ std::unordered_map<std::string, GlobalHotkeyCallback> bound_actions_by_id;
+ GrabType grab_type;
+ };
+} \ No newline at end of file
diff --git a/include/GlobalHotkeys/GlobalHotkeysX11.hpp b/include/GlobalHotkeys/GlobalHotkeysX11.hpp
new file mode 100644
index 0000000..610399a
--- /dev/null
+++ b/include/GlobalHotkeys/GlobalHotkeysX11.hpp
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "GlobalHotkeys.hpp"
+#include <unordered_map>
+#include <X11/Xlib.h>
+
+namespace gsr {
+ class GlobalHotkeysX11 : public GlobalHotkeys {
+ public:
+ GlobalHotkeysX11();
+ GlobalHotkeysX11(const GlobalHotkeysX11&) = delete;
+ GlobalHotkeysX11& operator=(const GlobalHotkeysX11&) = delete;
+ ~GlobalHotkeysX11() override;
+
+ // Hotkey key is a KeySym (XK_z for example) and modifiers is a bitmask of X11 modifier masks (for example ShiftMask | Mod1Mask)
+ bool bind_key_press(Hotkey hotkey, const std::string &id, GlobalHotkeyCallback callback) override;
+ void unbind_key_press(const std::string &id) override;
+ void unbind_all_keys() override;
+ void poll_events() override;
+ bool on_event(mgl::Event &event) override;
+ private:
+ // Returns true if a key bind has been registered for the hotkey
+ bool call_hotkey_callback(Hotkey hotkey) const;
+ private:
+ struct HotkeyData {
+ Hotkey hotkey;
+ GlobalHotkeyCallback callback;
+ };
+
+ Display *dpy = nullptr;
+ XEvent xev;
+ std::unordered_map<std::string, HotkeyData> bound_keys_by_id;
+ };
+} \ No newline at end of file