From 47ada4d79844d9a98d9689d0de0c92864e0fc372 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 20 Jan 2025 23:11:00 +0100 Subject: Add option to save replay with controller (double-click share button), allow prime-run on wayland --- TODO | 7 +- include/Config.hpp | 1 + include/GlobalHotkeysJoystick.hpp | 53 +++++++++ include/Hotplug.hpp | 33 ++++++ include/Overlay.hpp | 3 + include/gui/GlobalSettingsPage.hpp | 13 +- meson.build | 5 + src/Config.cpp | 1 + src/GlobalHotkeysJoystick.cpp | 236 +++++++++++++++++++++++++++++++++++++ src/GlobalHotkeysLinux.cpp | 4 +- src/GlobalHotkeysX11.cpp | 3 + src/Hotplug.cpp | 81 +++++++++++++ src/Overlay.cpp | 12 +- src/gui/GlobalSettingsPage.cpp | 108 +++++++++++++---- src/main.cpp | 121 ++++++++----------- tools/gsr-global-hotkeys/hotplug.c | 8 +- tools/gsr-global-hotkeys/main.c | 23 ++++ 17 files changed, 606 insertions(+), 106 deletions(-) create mode 100644 include/GlobalHotkeysJoystick.hpp create mode 100644 include/Hotplug.hpp create mode 100644 src/GlobalHotkeysJoystick.cpp create mode 100644 src/Hotplug.cpp diff --git a/TODO b/TODO index 6ff1858..3020e6d 100644 --- a/TODO +++ b/TODO @@ -112,4 +112,9 @@ Make gsr-ui flatpak systemd work nicely with non-flatpak gsr-ui. Maybe change Ex When enabling X11 global hotkey again only grab lalt, not ralt. When adding window capture only add it to recording and streaming and do the window selection when recording starts, to make it more ergonomic with hotkeys. - If hotkey for recording/streaming start is pressed on the button for start is clicked then hide the ui if it's visible and show the window selection option (cursor). \ No newline at end of file + If hotkey for recording/streaming start is pressed on the button for start is clicked then hide the ui if it's visible and show the window selection option (cursor). + +Instead of using x11 in gsr-global-hotkeys do the keysym to keycode mapping in gsr-ui and send that to gsr-global-hotkeys. Also improve gsr-global-hotkeys setup performance + by only grabbing keys after the first button press. + +Show an error that prime run will be disabled when using desktop portal capture option. This can cause issues as the user may have selected a video codec option that isn't available on their iGPU but is available on the prime-run dGPU. \ No newline at end of file diff --git a/include/Config.hpp b/include/Config.hpp index 6f81c1c..e7b629f 100644 --- a/include/Config.hpp +++ b/include/Config.hpp @@ -44,6 +44,7 @@ namespace gsr { int32_t config_file_version = 0; bool software_encoding_warning_shown = false; std::string hotkeys_enable_option = "enable_hotkeys"; + std::string joystick_hotkeys_enable_option = "disable_hotkeys"; std::string tint_color; }; diff --git a/include/GlobalHotkeysJoystick.hpp b/include/GlobalHotkeysJoystick.hpp new file mode 100644 index 0000000..367de18 --- /dev/null +++ b/include/GlobalHotkeysJoystick.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include "GlobalHotkeys.hpp" +#include "Hotplug.hpp" +#include +#include +#include +#include +#include + +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(); + 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 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; + + mgl::Clock double_click_clock; + int num_times_clicked = 0; + bool save_replay = false; + int hotplug_poll_index = -1; + Hotplug hotplug; + }; +} \ No newline at end of file diff --git a/include/Hotplug.hpp b/include/Hotplug.hpp new file mode 100644 index 0000000..38fe25d --- /dev/null +++ b/include/Hotplug.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include + +namespace gsr { + enum class HotplugAction { + ADD, + REMOVE + }; + + using HotplugEventCallback = std::function; + + class Hotplug { + public: + Hotplug() = default; + Hotplug(const Hotplug&) = delete; + Hotplug& operator=(const Hotplug&) = delete; + ~Hotplug(); + + bool start(); + int steal_fd(); + void process_event_data(int fd, const HotplugEventCallback &callback); + private: + void parse_netlink_data(const char *line, const HotplugEventCallback &callback); + private: + int fd = -1; + bool started = false; + bool event_is_add = false; + bool event_is_remove = false; + bool subsystem_is_input = false; + char event_data[1024]; + }; +} \ No newline at end of file diff --git a/include/Overlay.hpp b/include/Overlay.hpp index 9f1a5ae..2ccfb02 100644 --- a/include/Overlay.hpp +++ b/include/Overlay.hpp @@ -61,6 +61,9 @@ namespace gsr { void exit(); const Config& get_config() const; + + std::function on_keyboard_hotkey_changed; + std::function on_joystick_hotkey_changed; private: void xi_setup(); void handle_xi_events(); diff --git a/include/gui/GlobalSettingsPage.hpp b/include/gui/GlobalSettingsPage.hpp index 06098f0..1066bb5 100644 --- a/include/gui/GlobalSettingsPage.hpp +++ b/include/gui/GlobalSettingsPage.hpp @@ -24,13 +24,15 @@ namespace gsr { void save(); void on_navigate_away_from_page() override; - // Called with (enable, exit_status) - std::function on_startup_changed; - // Called with (reason) - std::function on_click_exit_program_button; + std::function on_startup_changed; + std::function on_click_exit_program_button; + std::function on_keyboard_hotkey_changed; + std::function on_joystick_hotkey_changed; private: std::unique_ptr create_appearance_subsection(ScrollablePage *parent_page); std::unique_ptr create_startup_subsection(ScrollablePage *parent_page); + std::unique_ptr create_enable_keyboard_hotkeys_button(); + std::unique_ptr create_enable_joystick_hotkeys_button(); std::unique_ptr create_hotkey_subsection(ScrollablePage *parent_page); std::unique_ptr