mirror of
https://repo.dec05eba.com/gpu-screen-recorder-ui
synced 2026-04-08 20:34:52 +09:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c6e2aff07 | ||
|
|
26ff639f25 | ||
|
|
a812d7dbbb | ||
|
|
57ae00063c | ||
|
|
fa5b7a0c75 | ||
|
|
52ce22ae22 | ||
|
|
f379b87b33 |
11
README.md
11
README.md
@@ -7,9 +7,10 @@ Note: This software is still in early alpha. Expect bugs, and please report any
|
||||
You can report an issue by emailing the issue to dec05eba@protonmail.com.
|
||||
|
||||
# Usage
|
||||
Run `gsr-ui` and press `Alt+Z` to show/hide the UI. You can start the overlay UI at system startup by running `systemctl enable --now --user gpu-screen-recorder-ui`.
|
||||
Run `gsr-ui` and press `Left Alt+Z` to show/hide the UI. You can start the overlay UI at system startup by running `systemctl enable --now --user gpu-screen-recorder-ui`.
|
||||
There is also an option in the settings to enable/disable starting the program on system startup. This option only works on systems that use systemd.
|
||||
You have to manually add `gsr-ui` to system startup on systems that uses another init system.
|
||||
You have to manually add `gsr-ui` to system startup on systems that uses another init system.\
|
||||
A program called `gsr-ui-cli` is also installed when installing this software. This can be used to remotely control the UI. Run `gsr-ui-cli --help` to list the available commands.
|
||||
|
||||
# Installation
|
||||
If you are using an Arch Linux based distro then you can find gpu screen recorder ui on aur under the name gpu-screen-recorder-ui (`yay -S gpu-screen-recorder-ui`).\
|
||||
@@ -34,10 +35,10 @@ There are also additional dependencies needed at runtime:
|
||||
* [GPU Screen Recorder Notification](https://git.dec05eba.com/gpu-screen-recorder-notification/)
|
||||
|
||||
## Program behavior notes
|
||||
At the moment different keyboard layouts are not supported. The physical layout of keys are used for global hotkeys. If your Z and Y keys are swapped for example then you need to press Alt+Y instead of Alt+Z to open/hide the UI.\
|
||||
At the moment different keyboard layouts are not supported. The physical layout of keys are used for global hotkeys. If your Z and Y keys are swapped for example then you need to press Left Alt+Y instead of Left Alt+Z to open/hide the UI.\
|
||||
If you experience this issue then please email dec05eba@protonmail.com to get it fixed.\
|
||||
This program has to grab all keyboards and create a virtual keyboard (`gsr-ui virtual keyboard`) to make global hotkeys work on all Wayland compositors.
|
||||
This might cause issues for you if you use input remapping software. To workaround this you can go into settings and disable hotkeys and use the included `gsr-ui-cli` tool to control the UI remotely. You can combine `gsr-ui-cli` commands to hotkeys in your desktop environments hotkey settings.
|
||||
This might cause issues for you if you use input remapping software. To workaround this you can go into settings and select "Only grab virtual devices"
|
||||
|
||||
# License
|
||||
This software is licensed under GPL3.0-only. Files under `fonts/` directory belong to the Noto Sans Google fonts project and they are licensed under `SIL Open Font License`.
|
||||
@@ -56,5 +57,5 @@ If you want to donate you can donate via bitcoin or monero.
|
||||
|
||||
# Known issues
|
||||
* When the UI is open the wallpaper is shown instead of the game on Hyprland and Sway. This is an issue with Hyprland and Sway. It cant be fixed until the UI is redesigned to not be a fullscreen overlay.
|
||||
* Different keyboard layouts are not supported at the moment. The physical layout of keys are used for global hotkeys. If your Z and Y keys are swapped for example then you need to press Alt+Y instead of Alt+Z to open/hide the UI. If you experience this issue then please email dec05eba@protonmail.com to get it fixed.
|
||||
* Different keyboard layouts are not supported at the moment. The physical layout of keys are used for global hotkeys. If your Z and Y keys are swapped for example then you need to press Left Alt+Y instead of Left Alt+Z to open/hide the UI. If you experience this issue then please email dec05eba@protonmail.com to get it fixed.
|
||||
* The mouse position can sometimes shift when opening the UI.
|
||||
|
||||
10
TODO
10
TODO
@@ -92,7 +92,7 @@ Move ui hover code from ::draw to ::on_event, to properly handle widget event st
|
||||
|
||||
Save audio devices by name instead of id. This is more robust since audio id can change(?).
|
||||
|
||||
Improve linux global hotkeys startup time by parsing /proc/bus/input/devices instead of ioctl.
|
||||
Improve linux global hotkeys startup time by parsing /proc/bus/input/devices instead of ioctl. <- Do this!
|
||||
|
||||
We can get the name of the running steam game without x11 by listing processes and finding the one that runs a program called "reaper" with the arguments SteamLaunch AppId=<number>. The binary comes after the -- argument, get the name of the game by parsing out name from that, in the format steamapps/common/<name>/.
|
||||
|
||||
@@ -105,4 +105,10 @@ Show warning if another instance of gpu screen recorder is already running when
|
||||
Keyboard leds get turned off when stopping gsr-global-hotkeys (for example numlock). The numlock key has to be pressed twice again to make it look correct to match its state.
|
||||
|
||||
Implement hotkey changing in global settings by getting mgl key events. During this time gsr-global-hotkey would either need to be paused or add code in the callback handler for the existing hotkeys since they are grabbing hotkeys.
|
||||
This can only be done after gsr-global-hotkeys properly handle different keyboard layouts to make sure mgl keys match gsr-global-hotkey keys.
|
||||
This can only be done after gsr-global-hotkeys properly handle different keyboard layouts to make sure mgl keys match gsr-global-hotkey keys.
|
||||
|
||||
Re-enable hotkey disable option for flatpak.
|
||||
|
||||
Make gsr-ui flatpak systemd work nicely with non-flatpak gsr-ui. Maybe change ExecStart to do flatpak run ... || gsr-ui, but make it run as a shell command first with /bin/sh -c "".
|
||||
|
||||
When enabling X11 global hotkey again only grab lalt, not ralt.
|
||||
Submodule depends/mglpp updated: 3c33f0f813...1ce8b2de75
@@ -43,7 +43,7 @@ namespace gsr {
|
||||
struct MainConfig {
|
||||
int32_t config_file_version = 0;
|
||||
bool software_encoding_warning_shown = false;
|
||||
bool enable_hotkeys = true;
|
||||
std::string hotkeys_enable_option = "enable_hotkeys";
|
||||
std::string tint_color;
|
||||
};
|
||||
|
||||
|
||||
@@ -7,7 +7,12 @@
|
||||
namespace gsr {
|
||||
class GlobalHotkeysLinux : public GlobalHotkeys {
|
||||
public:
|
||||
GlobalHotkeysLinux();
|
||||
enum class GrabType {
|
||||
ALL,
|
||||
VIRTUAL
|
||||
};
|
||||
|
||||
GlobalHotkeysLinux(GrabType grab_type);
|
||||
GlobalHotkeysLinux(const GlobalHotkeysLinux&) = delete;
|
||||
GlobalHotkeysLinux& operator=(const GlobalHotkeysLinux&) = delete;
|
||||
~GlobalHotkeysLinux() override;
|
||||
@@ -20,5 +25,6 @@ namespace gsr {
|
||||
int pipes[2];
|
||||
FILE *read_file = nullptr;
|
||||
std::unordered_map<std::string, GlobalHotkeyCallback> bound_actions_by_id;
|
||||
GrabType grab_type;
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
project('gsr-ui', ['c', 'cpp'], version : '1.0.4', default_options : ['warning_level=2', 'cpp_std=c++17'], subproject_dir : 'depends')
|
||||
project('gsr-ui', ['c', 'cpp'], version : '1.0.5', default_options : ['warning_level=2', 'cpp_std=c++17'], subproject_dir : 'depends')
|
||||
|
||||
if get_option('buildtype') == 'debug'
|
||||
add_project_arguments('-g3', language : ['c', 'cpp'])
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "gsr-ui"
|
||||
type = "executable"
|
||||
version = "1.0.4"
|
||||
version = "1.0.5"
|
||||
platforms = ["posix"]
|
||||
|
||||
[lang.cpp]
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace gsr {
|
||||
return {
|
||||
{"main.config_file_version", &config.main_config.config_file_version},
|
||||
{"main.software_encoding_warning_shown", &config.main_config.software_encoding_warning_shown},
|
||||
{"main.enable_hotkeys", &config.main_config.enable_hotkeys},
|
||||
{"main.hotkeys_enable_option", &config.main_config.hotkeys_enable_option},
|
||||
{"main.tint_color", &config.main_config.tint_color},
|
||||
|
||||
{"streaming.record_options.record_area_option", &config.streaming_config.record_options.record_area_option},
|
||||
|
||||
@@ -9,7 +9,15 @@
|
||||
#define PIPE_WRITE 1
|
||||
|
||||
namespace gsr {
|
||||
GlobalHotkeysLinux::GlobalHotkeysLinux() {
|
||||
static const char* grab_type_to_arg(GlobalHotkeysLinux::GrabType grab_type) {
|
||||
switch(grab_type) {
|
||||
case GlobalHotkeysLinux::GrabType::ALL: return "--all";
|
||||
case GlobalHotkeysLinux::GrabType::VIRTUAL: return "--virtual";
|
||||
}
|
||||
return "--all";
|
||||
}
|
||||
|
||||
GlobalHotkeysLinux::GlobalHotkeysLinux(GrabType grab_type) : grab_type(grab_type) {
|
||||
for(int i = 0; i < 2; ++i) {
|
||||
pipes[i] = -1;
|
||||
}
|
||||
@@ -32,6 +40,7 @@ namespace gsr {
|
||||
}
|
||||
|
||||
bool GlobalHotkeysLinux::start() {
|
||||
const char *grab_type_arg = grab_type_to_arg(grab_type);
|
||||
const bool inside_flatpak = getenv("FLATPAK_ID") != NULL;
|
||||
const char *user_homepath = getenv("HOME");
|
||||
if(!user_homepath)
|
||||
@@ -61,10 +70,10 @@ namespace gsr {
|
||||
}
|
||||
|
||||
if(inside_flatpak) {
|
||||
const char *args[] = { "flatpak-spawn", "--host", "--", gsr_global_hotkeys_flatpak, NULL };
|
||||
const char *args[] = { "flatpak-spawn", "--host", "--", gsr_global_hotkeys_flatpak, grab_type_arg, nullptr };
|
||||
execvp(args[0], (char* const*)args);
|
||||
} else {
|
||||
const char *args[] = { "gsr-global-hotkeys", NULL };
|
||||
const char *args[] = { "gsr-global-hotkeys", grab_type_arg, nullptr };
|
||||
execvp(args[0], (char* const*)args);
|
||||
}
|
||||
|
||||
|
||||
@@ -827,7 +827,9 @@ namespace gsr {
|
||||
window_create_params.override_redirect = prevent_game_minimizing;
|
||||
window_create_params.background_color = bg_color;
|
||||
window_create_params.support_alpha = true;
|
||||
window_create_params.window_type = MGL_WINDOW_TYPE_NORMAL;
|
||||
// MGL_WINDOW_TYPE_DIALOG is needed for kde plasma wayland in some cases, otherwise the window will pop up on another activity
|
||||
// or may not be visible at all
|
||||
window_create_params.window_type = MGL_WINDOW_TYPE_DIALOG;
|
||||
window_create_params.render_api = MGL_RENDER_API_EGL;
|
||||
|
||||
if(!window->create("gsr ui", window_create_params))
|
||||
@@ -847,6 +849,7 @@ namespace gsr {
|
||||
mgl_window *win = window->internal_window();
|
||||
if(win->num_monitors == 0) {
|
||||
fprintf(stderr, "gsr warning: no monitors found, not showing overlay\n");
|
||||
window.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -89,11 +89,14 @@ namespace gsr {
|
||||
}
|
||||
|
||||
std::unique_ptr<Subsection> GlobalSettingsPage::create_hotkey_subsection(ScrollablePage *parent_page) {
|
||||
auto list = std::make_unique<List>(List::Orientation::VERTICAL);
|
||||
auto enable_hotkeys_radio_button = std::make_unique<RadioButton>(&get_theme().body_font, RadioButton::Orientation::HORIZONTAL);
|
||||
const bool inside_flatpak = getenv("FLATPAK_ID") != NULL;
|
||||
|
||||
auto enable_hotkeys_radio_button = std::make_unique<RadioButton>(&get_theme().body_font, RadioButton::Orientation::VERTICAL);
|
||||
enable_hotkeys_radio_button_ptr = enable_hotkeys_radio_button.get();
|
||||
enable_hotkeys_radio_button->add_item("Enable hotkeys and restart", "enable_hotkeys");
|
||||
enable_hotkeys_radio_button->add_item("Disable hotkeys and restart", "disable_hotkeys");
|
||||
enable_hotkeys_radio_button->add_item("Enable hotkeys", "enable_hotkeys");
|
||||
if(!inside_flatpak)
|
||||
enable_hotkeys_radio_button->add_item("Disable hotkeys", "disable_hotkeys");
|
||||
enable_hotkeys_radio_button->add_item("Only grab virtual devices (supports input remapping software)", "enable_hotkeys_virtual_devices");
|
||||
enable_hotkeys_radio_button->on_selection_changed = [&](const std::string&, const std::string &id) {
|
||||
if(!on_click_exit_program_button)
|
||||
return true;
|
||||
@@ -102,11 +105,12 @@ namespace gsr {
|
||||
on_click_exit_program_button("restart");
|
||||
else if(id == "disable_hotkeys")
|
||||
on_click_exit_program_button("restart");
|
||||
else if(id == "enable_hotkeys_virtual_devices")
|
||||
on_click_exit_program_button("restart");
|
||||
|
||||
return true;
|
||||
};
|
||||
list->add_widget(std::move(enable_hotkeys_radio_button));
|
||||
return std::make_unique<Subsection>("Hotkeys", std::move(list), mgl::vec2f(parent_page->get_inner_size().x, 0.0f));
|
||||
return std::make_unique<Subsection>("Hotkeys", std::move(enable_hotkeys_radio_button), mgl::vec2f(parent_page->get_inner_size().x, 0.0f));
|
||||
}
|
||||
|
||||
std::unique_ptr<Button> GlobalSettingsPage::create_exit_program_button() {
|
||||
@@ -165,12 +169,12 @@ namespace gsr {
|
||||
const int exit_status = exec_program_on_host_get_stdout(args, stdout_str);
|
||||
startup_radio_button_ptr->set_selected_item(exit_status == 0 ? "start_on_system_startup" : "dont_start_on_system_startup", false, false);
|
||||
|
||||
enable_hotkeys_radio_button_ptr->set_selected_item(config.main_config.enable_hotkeys ? "enable_hotkeys" : "disable_hotkeys", false, false);
|
||||
enable_hotkeys_radio_button_ptr->set_selected_item(config.main_config.hotkeys_enable_option, false, false);
|
||||
}
|
||||
|
||||
void GlobalSettingsPage::save() {
|
||||
config.main_config.tint_color = tint_color_radio_button_ptr->get_selected_id();
|
||||
config.main_config.enable_hotkeys = enable_hotkeys_radio_button_ptr->get_selected_id() == "enable_hotkeys";
|
||||
config.main_config.hotkeys_enable_option = enable_hotkeys_radio_button_ptr->get_selected_id();
|
||||
save_config(config);
|
||||
}
|
||||
}
|
||||
10
src/main.cpp
10
src/main.cpp
@@ -95,8 +95,8 @@ static std::unique_ptr<gsr::GlobalHotkeysX11> register_x11_hotkeys(gsr::Overlay
|
||||
return global_hotkeys;
|
||||
}
|
||||
|
||||
static std::unique_ptr<gsr::GlobalHotkeysLinux> register_linux_hotkeys(gsr::Overlay *overlay) {
|
||||
auto global_hotkeys = std::make_unique<gsr::GlobalHotkeysLinux>();
|
||||
static std::unique_ptr<gsr::GlobalHotkeysLinux> register_linux_hotkeys(gsr::Overlay *overlay, gsr::GlobalHotkeysLinux::GrabType grab_type) {
|
||||
auto global_hotkeys = std::make_unique<gsr::GlobalHotkeysLinux>(grab_type);
|
||||
if(!global_hotkeys->start())
|
||||
fprintf(stderr, "error: failed to start global hotkeys\n");
|
||||
|
||||
@@ -314,8 +314,10 @@ int main(int argc, char **argv) {
|
||||
rpc_add_commands(rpc.get(), overlay.get());
|
||||
|
||||
std::unique_ptr<gsr::GlobalHotkeys> global_hotkeys = nullptr;
|
||||
if(overlay->get_config().main_config.enable_hotkeys)
|
||||
global_hotkeys = register_linux_hotkeys(overlay.get());
|
||||
if(overlay->get_config().main_config.hotkeys_enable_option == "enable_hotkeys")
|
||||
global_hotkeys = register_linux_hotkeys(overlay.get(), gsr::GlobalHotkeysLinux::GrabType::ALL);
|
||||
else if(overlay->get_config().main_config.hotkeys_enable_option == "enable_hotkeys_virtual_devices")
|
||||
global_hotkeys = register_linux_hotkeys(overlay.get(), gsr::GlobalHotkeysLinux::GrabType::VIRTUAL);
|
||||
|
||||
// TODO: Add hotkeys in Overlay when using x11 global hotkeys. The hotkeys in Overlay should duplicate each key that is used for x11 global hotkeys.
|
||||
|
||||
|
||||
@@ -165,7 +165,8 @@ static void keyboard_event_process_input_event_data(keyboard_event *self, event_
|
||||
default: {
|
||||
const bool shift_pressed = self->lshift_button_state == KEYBOARD_BUTTON_PRESSED || self->rshift_button_state == KEYBOARD_BUTTON_PRESSED;
|
||||
const bool ctrl_pressed = self->lctrl_button_state == KEYBOARD_BUTTON_PRESSED || self->rctrl_button_state == KEYBOARD_BUTTON_PRESSED;
|
||||
const bool alt_pressed = self->lalt_button_state == KEYBOARD_BUTTON_PRESSED || self->ralt_button_state == KEYBOARD_BUTTON_PRESSED;
|
||||
const bool lalt_pressed = self->lalt_button_state == KEYBOARD_BUTTON_PRESSED;
|
||||
const bool ralt_pressed = self->ralt_button_state == KEYBOARD_BUTTON_PRESSED;
|
||||
const bool meta_pressed = self->lmeta_button_state == KEYBOARD_BUTTON_PRESSED || self->rmeta_button_state == KEYBOARD_BUTTON_PRESSED;
|
||||
//fprintf(stderr, "pressed key: %d, state: %d, shift: %s, ctrl: %s, alt: %s, meta: %s\n", event.code, event.value,
|
||||
// shift_pressed ? "yes" : "no", ctrl_pressed ? "yes" : "no", alt_pressed ? "yes" : "no", meta_pressed ? "yes" : "no");
|
||||
@@ -174,8 +175,10 @@ static void keyboard_event_process_input_event_data(keyboard_event *self, event_
|
||||
modifiers |= KEYBOARD_MODKEY_SHIFT;
|
||||
if(ctrl_pressed)
|
||||
modifiers |= KEYBOARD_MODKEY_CTRL;
|
||||
if(alt_pressed)
|
||||
modifiers |= KEYBOARD_MODKEY_ALT;
|
||||
if(lalt_pressed)
|
||||
modifiers |= KEYBOARD_MODKEY_LALT;
|
||||
if(ralt_pressed)
|
||||
modifiers |= KEYBOARD_MODKEY_RALT;
|
||||
if(meta_pressed)
|
||||
modifiers |= KEYBOARD_MODKEY_SUPER;
|
||||
|
||||
@@ -213,11 +216,41 @@ static bool keyboard_event_has_event_with_dev_input_fd(keyboard_event *self, int
|
||||
return false;
|
||||
}
|
||||
|
||||
/* TODO: Is there a more efficient way to do this? */
|
||||
static bool dev_input_is_virtual(int dev_input_id) {
|
||||
DIR *dir = opendir("/sys/devices/virtual/input");
|
||||
if(!dir)
|
||||
return false;
|
||||
|
||||
bool is_virtual = false;
|
||||
char virtual_input_filepath[1024];
|
||||
for(;;) {
|
||||
struct dirent *entry = readdir(dir);
|
||||
if(!entry)
|
||||
break;
|
||||
|
||||
if(strncmp(entry->d_name, "input", 5) != 0)
|
||||
continue;
|
||||
|
||||
snprintf(virtual_input_filepath, sizeof(virtual_input_filepath), "/sys/devices/virtual/input/%s/event%d", entry->d_name, dev_input_id);
|
||||
if(access(virtual_input_filepath, F_OK) == 0) {
|
||||
is_virtual = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return is_virtual;
|
||||
}
|
||||
|
||||
static bool keyboard_event_try_add_device_if_keyboard(keyboard_event *self, const char *dev_input_filepath) {
|
||||
const int dev_input_id = get_dev_input_id_from_filepath(dev_input_filepath);
|
||||
if(dev_input_id == -1)
|
||||
return false;
|
||||
|
||||
if(self->grab_type == KEYBOARD_GRAB_TYPE_VIRTUAL && !dev_input_is_virtual(dev_input_id))
|
||||
return false;
|
||||
|
||||
if(keyboard_event_has_event_with_dev_input_fd(self, dev_input_id))
|
||||
return false;
|
||||
|
||||
@@ -373,10 +406,11 @@ static int setup_virtual_keyboard_input(const char *name) {
|
||||
return fd;
|
||||
}
|
||||
|
||||
bool keyboard_event_init(keyboard_event *self, bool poll_stdout_error, bool exclusive_grab) {
|
||||
bool keyboard_event_init(keyboard_event *self, bool poll_stdout_error, bool exclusive_grab, keyboard_grab_type grab_type) {
|
||||
memset(self, 0, sizeof(*self));
|
||||
self->stdout_event_index = -1;
|
||||
self->hotplug_event_index = -1;
|
||||
self->grab_type = grab_type;
|
||||
|
||||
if(exclusive_grab) {
|
||||
self->uinput_fd = setup_virtual_keyboard_input(GSR_UI_VIRTUAL_KEYBOARD_NAME);
|
||||
|
||||
@@ -18,10 +18,11 @@
|
||||
#define MAX_EVENT_POLLS 32
|
||||
|
||||
typedef enum {
|
||||
KEYBOARD_MODKEY_ALT = 1 << 0,
|
||||
KEYBOARD_MODKEY_SUPER = 1 << 1,
|
||||
KEYBOARD_MODKEY_CTRL = 1 << 2,
|
||||
KEYBOARD_MODKEY_SHIFT = 1 << 3
|
||||
KEYBOARD_MODKEY_LALT = 1 << 0,
|
||||
KEYBOARD_MODKEY_RALT = 1 << 2,
|
||||
KEYBOARD_MODKEY_SUPER = 1 << 3,
|
||||
KEYBOARD_MODKEY_CTRL = 1 << 4,
|
||||
KEYBOARD_MODKEY_SHIFT = 1 << 5
|
||||
} keyboard_modkeys;
|
||||
|
||||
typedef enum {
|
||||
@@ -36,6 +37,11 @@ typedef struct {
|
||||
int num_keys_pressed;
|
||||
} event_extra_data;
|
||||
|
||||
typedef enum {
|
||||
KEYBOARD_GRAB_TYPE_ALL,
|
||||
KEYBOARD_GRAB_TYPE_VIRTUAL
|
||||
} keyboard_grab_type;
|
||||
|
||||
typedef struct {
|
||||
struct pollfd event_polls[MAX_EVENT_POLLS]; /* Current size is |num_event_polls| */
|
||||
event_extra_data event_extra_data[MAX_EVENT_POLLS]; /* Current size is |num_event_polls| */
|
||||
@@ -45,6 +51,7 @@ typedef struct {
|
||||
int hotplug_event_index;
|
||||
int uinput_fd;
|
||||
bool stdout_failed;
|
||||
keyboard_grab_type grab_type;
|
||||
|
||||
hotplug_event hotplug_ev;
|
||||
|
||||
@@ -62,7 +69,7 @@ typedef struct {
|
||||
/* Return true to allow other applications to receive the key input (when using exclusive grab) */
|
||||
typedef bool (*key_callback)(uint32_t key, uint32_t modifiers, int press_status, void *userdata);
|
||||
|
||||
bool keyboard_event_init(keyboard_event *self, bool poll_stdout_error, bool exclusive_grab);
|
||||
bool keyboard_event_init(keyboard_event *self, bool poll_stdout_error, bool exclusive_grab, keyboard_grab_type grab_type);
|
||||
void keyboard_event_deinit(keyboard_event *self);
|
||||
|
||||
/* If |timeout_milliseconds| is -1 then wait until an event is received */
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
/* C stdlib */
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/* POSIX */
|
||||
#include <unistd.h>
|
||||
@@ -15,12 +16,12 @@ typedef struct {
|
||||
|
||||
#define NUM_GLOBAL_HOTKEYS 6
|
||||
static global_hotkey global_hotkeys[NUM_GLOBAL_HOTKEYS] = {
|
||||
{ .key = KEY_Z, .modifiers = KEYBOARD_MODKEY_ALT, .action = "show_hide" },
|
||||
{ .key = KEY_F9, .modifiers = KEYBOARD_MODKEY_ALT, .action = "record" },
|
||||
{ .key = KEY_F7, .modifiers = KEYBOARD_MODKEY_ALT, .action = "pause" },
|
||||
{ .key = KEY_F8, .modifiers = KEYBOARD_MODKEY_ALT, .action = "stream" },
|
||||
{ .key = KEY_F10, .modifiers = KEYBOARD_MODKEY_ALT | KEYBOARD_MODKEY_SHIFT, .action = "replay_start" },
|
||||
{ .key = KEY_F10, .modifiers = KEYBOARD_MODKEY_ALT, .action = "replay_save" }
|
||||
{ .key = KEY_Z, .modifiers = KEYBOARD_MODKEY_LALT, .action = "show_hide" },
|
||||
{ .key = KEY_F9, .modifiers = KEYBOARD_MODKEY_LALT, .action = "record" },
|
||||
{ .key = KEY_F7, .modifiers = KEYBOARD_MODKEY_LALT, .action = "pause" },
|
||||
{ .key = KEY_F8, .modifiers = KEYBOARD_MODKEY_LALT, .action = "stream" },
|
||||
{ .key = KEY_F10, .modifiers = KEYBOARD_MODKEY_LALT | KEYBOARD_MODKEY_SHIFT, .action = "replay_start" },
|
||||
{ .key = KEY_F10, .modifiers = KEYBOARD_MODKEY_LALT, .action = "replay_save" }
|
||||
};
|
||||
|
||||
static bool on_key_callback(uint32_t key, uint32_t modifiers, int press_status, void *userdata) {
|
||||
@@ -37,7 +38,32 @@ static bool on_key_callback(uint32_t key, uint32_t modifiers, int press_status,
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
static void usage(void) {
|
||||
fprintf(stderr, "usage: gsr-global-hotkeys [--all|--virtual]\n");
|
||||
fprintf(stderr, "OPTIONS:\n");
|
||||
fprintf(stderr, " --all Grab all devices.\n");
|
||||
fprintf(stderr, " --virtual Grab all virtual devices only.\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
keyboard_grab_type grab_type = KEYBOARD_GRAB_TYPE_ALL;
|
||||
if(argc == 2) {
|
||||
const char *grab_type_arg = argv[1];
|
||||
if(strcmp(grab_type_arg, "--all") == 0) {
|
||||
grab_type = KEYBOARD_GRAB_TYPE_ALL;
|
||||
} else if(strcmp(grab_type_arg, "--virtual") == 0) {
|
||||
grab_type = KEYBOARD_GRAB_TYPE_VIRTUAL;
|
||||
} else {
|
||||
fprintf(stderr, "Error: expected --all or --virtual, got %s\n", grab_type_arg);
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
} else if(argc != 1) {
|
||||
fprintf(stderr, "Error: expected 0 or 1 arguments, got %d argument(s)\n", argc);
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
const uid_t user_id = getuid();
|
||||
if(geteuid() != 0) {
|
||||
if(setuid(0) == -1) {
|
||||
@@ -47,7 +73,7 @@ int main(void) {
|
||||
}
|
||||
|
||||
keyboard_event keyboard_ev;
|
||||
if(!keyboard_event_init(&keyboard_ev, true, true)) {
|
||||
if(!keyboard_event_init(&keyboard_ev, true, true, grab_type)) {
|
||||
fprintf(stderr, "Error: failed to setup hotplugging and no keyboard input devices were found\n");
|
||||
setuid(user_id);
|
||||
return 1;
|
||||
|
||||
@@ -50,6 +50,7 @@ static void usage(void) {
|
||||
printf(" toggle-stream Start/stop streaming.\n");
|
||||
printf(" toggle-replay Start/stop replay.\n");
|
||||
printf(" replay-save Save replay.\n");
|
||||
printf("\n");
|
||||
printf("EXAMPLES:\n");
|
||||
printf(" gsr-ui-cli toggle-show\n");
|
||||
printf(" gsr-ui-cli toggle-record\n");
|
||||
|
||||
Reference in New Issue
Block a user