Compare commits

..

11 Commits
1.1.3 ... 1.1.6

Author SHA1 Message Date
dec05eba
b4c85910ce 1.1.6 2025-02-03 20:43:08 +01:00
dec05eba
fd63ac3626 Fix for steamdeck 2025-02-03 20:27:35 +01:00
dec05eba
2a0782eb02 Attempt to fix global hotkeys not working on steam deck (grabs keys, cant press buttons) 2025-02-03 19:58:42 +01:00
dec05eba
f505323d56 1.1.5 2025-02-03 01:25:32 +01:00
dec05eba
309cc3425b Use bundled cursor if cursor fails to load 2025-01-27 17:35:35 +01:00
dec05eba
81cb8f539f banana 2025-01-27 16:47:55 +01:00
dec05eba
5214fb1d7f Try fixing missing cursor texture on some broken systems 2025-01-27 16:46:54 +01:00
dec05eba
9aebe81ec4 amend 2025-01-27 11:56:37 +01:00
dec05eba
d73bd68a70 Default to default cursor if cursor not found 2025-01-27 11:53:49 +01:00
dec05eba
3cb156aecb Delegate keyboard grab until a button has been pressed if the device says its a mouse 2025-01-26 17:43:38 +01:00
dec05eba
dea4393588 Revert global hotkeys change, ignore mice again 2025-01-26 14:12:03 +01:00
9 changed files with 94 additions and 19 deletions

View File

@@ -39,7 +39,7 @@ This program has to grab all keyboards and create a virtual keyboard (`gsr-ui vi
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`.
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`. `images/default.cur` it part of the [Adwaita icon theme](https://gitlab.gnome.org/GNOME/adwaita-icon-theme/-/tree/master) which is licensed under `Creative Commons Attribution-Share Alike 3.0`.
# Demo
[![Click here to watch a demo video on youtube](https://img.youtube.com/vi/SOqXusCTXXA/0.jpg)](https://www.youtube.com/watch?v=SOqXusCTXXA)

9
TODO
View File

@@ -107,4 +107,11 @@ When adding window capture only add it to recording and streaming and do the win
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.
Is it possible to configure hotkey and the new hotkey to get triggered immediately?
Is it possible to configure hotkey and the new hotkey to get triggered immediately?
For keyboards that report supporting mice the keyboard grab will be delayed until any key has been pressed (and then released), see: https://github.com/dec05eba/gpu-screen-recorder-issues/issues/97
See if there is any way around this.
Instead of installing gsr-global-hotkeys in flatpak use kms-server-proxy to launch gsr-global-hotkeys inside the flatpak with root, just like gsr-kms-server. This removes the need to update gsr-global-hotkeys everytime there is an update.
Check if "modprobe uinput" is needed on some systems (old fedora?).

BIN
images/default.cur Normal file

Binary file not shown.

View File

@@ -1,4 +1,4 @@
project('gsr-ui', ['c', 'cpp'], version : '1.1.3', default_options : ['warning_level=2', 'cpp_std=c++17'], subproject_dir : 'depends')
project('gsr-ui', ['c', 'cpp'], version : '1.1.6', default_options : ['warning_level=2', 'cpp_std=c++17'], subproject_dir : 'depends')
if get_option('buildtype') == 'debug'
add_project_arguments('-g3', language : ['c', 'cpp'])
@@ -52,7 +52,7 @@ datadir = get_option('datadir')
gsr_ui_resources_path = join_paths(prefix, datadir, 'gsr-ui')
add_project_arguments('-DGSR_UI_VERSION="' + meson.project_version() + '"', language: ['c', 'cpp'])
add_project_arguments('-DGSR_FLATPAK_VERSION="5.1.2"', language: ['c', 'cpp'])
add_project_arguments('-DGSR_FLATPAK_VERSION="5.1.3"', language: ['c', 'cpp'])
executable(
meson.project_name(),
@@ -74,6 +74,7 @@ executable(
[
'tools/gsr-global-hotkeys/hotplug.c',
'tools/gsr-global-hotkeys/keyboard_event.c',
'tools/gsr-global-hotkeys/keys.c',
'tools/gsr-global-hotkeys/main.c'
],
c_args : '-fstack-protector-all',

View File

@@ -1,7 +1,7 @@
[package]
name = "gsr-ui"
type = "executable"
version = "1.1.3"
version = "1.1.6"
platforms = ["posix"]
[lang.cpp]

View File

@@ -772,9 +772,32 @@ namespace gsr {
if(cursor_size <= 1)
cursor_size = 24;
XcursorImage *cursor_image = XcursorShapeLoadImage(XC_left_ptr, cursor_theme, cursor_size);
XcursorImage *cursor_image = nullptr;
for(int cursor_size_test : {cursor_size, 24}) {
for(const char *cursor_theme_test : {cursor_theme, "default", "Adwaita"}) {
for(unsigned int shape : {XC_left_ptr, XC_arrow}) {
cursor_image = XcursorShapeLoadImage(shape, cursor_theme_test, cursor_size_test);
if(cursor_image)
goto done;
}
}
}
done:
if(!cursor_image) {
fprintf(stderr, "Error: failed to get cursor, loading bundled default cursor instead\n");
const std::string default_cursor_path = resources_path + "images/default.cur";
for(int cursor_size_test : {cursor_size, 24}) {
cursor_image = XcursorFilenameLoadImage(default_cursor_path.c_str(), cursor_size_test);
if(cursor_image)
break;
}
}
if(!cursor_image) {
fprintf(stderr, "Error: failed to get cursor\n");
XFixesShowCursor(xi_display, DefaultRootWindow(xi_display));
XFlush(xi_display);
return;
}

View File

@@ -1,4 +1,5 @@
#include "keyboard_event.h"
#include "keys.h"
/* C stdlib */
#include <stdio.h>
@@ -81,19 +82,19 @@ static void keyboard_event_fetch_update_key_states(keyboard_event *self, event_e
}
}
static void keyboard_event_process_key_state_change(keyboard_event *self, struct input_event event, event_extra_data *extra_data, int fd) {
if(event.type != EV_KEY)
static void keyboard_event_process_key_state_change(keyboard_event *self, const struct input_event *event, event_extra_data *extra_data, int fd) {
if(event->type != EV_KEY)
return;
if(!extra_data->key_states || event.code >= KEY_STATES_SIZE * 8)
if(!extra_data->key_states || event->code >= KEY_STATES_SIZE * 8)
return;
const unsigned int byte_index = event.code / 8;
const unsigned char bit_index = event.code % 8;
const unsigned int byte_index = event->code / 8;
const unsigned char bit_index = event->code % 8;
unsigned char key_byte_state = extra_data->key_states[byte_index];
const bool prev_key_pressed = (key_byte_state & (1 << bit_index)) != KEY_RELEASE;
if(event.value == KEY_RELEASE) {
if(event->value == KEY_RELEASE) {
key_byte_state &= ~(1 << bit_index);
if(prev_key_pressed)
--extra_data->num_keys_pressed;
@@ -171,8 +172,8 @@ static void keyboard_event_process_input_event_data(keyboard_event *self, event_
//fprintf(stderr, "fd: %d, type: %d, pressed %d, value: %d\n", fd, event.type, event.code, event.value);
//}
if(event.type == EV_KEY) {
keyboard_event_process_key_state_change(self, event, extra_data, fd);
if(event.type == EV_KEY && !is_mouse_button(event.code)) {
keyboard_event_process_key_state_change(self, &event, extra_data, fd);
const uint32_t modifier_bit = keycode_to_modifier_bit(event.code);
if(modifier_bit == 0) {
if(keyboard_event_on_key_pressed(self, &event, self->modifier_button_states))
@@ -293,7 +294,7 @@ static bool keyboard_event_try_add_device_if_keyboard(keyboard_event *self, cons
ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), &key_bits);
const bool supports_key_events = key_bits[KEY_A/8] & (1 << (KEY_A % 8));
//const bool supports_mouse_events = key_bits[BTN_MOUSE/8] & (1 << (BTN_MOUSE % 8));
const bool supports_mouse_events = key_bits[BTN_MOUSE/8] & (1 << (BTN_MOUSE % 8));
//const bool supports_touch_events = key_bits[BTN_TOUCH/8] & (1 << (BTN_TOUCH % 8));
const bool supports_joystick_events = key_bits[BTN_JOYSTICK/8] & (1 << (BTN_JOYSTICK % 8));
const bool supports_wheel_events = key_bits[BTN_WHEEL/8] & (1 << (BTN_WHEEL % 8));
@@ -314,9 +315,16 @@ static bool keyboard_event_try_add_device_if_keyboard(keyboard_event *self, cons
.num_keys_pressed = 0
};
keyboard_event_fetch_update_key_states(self, &self->event_extra_data[self->num_event_polls], fd);
if(self->event_extra_data[self->num_event_polls].num_keys_pressed > 0)
fprintf(stderr, "Info: device not grabbed yet because some keys are still being pressed: /dev/input/event%d\n", dev_input_id);
if(supports_mouse_events) {
fprintf(stderr, "Info: device not grabbed yet because it might be a mouse: /dev/input/event%d\n", dev_input_id);
fsync(fd);
if(ioctl(fd, EVIOCGKEY(KEY_STATES_SIZE), self->event_extra_data[self->num_event_polls].key_states) == -1)
fprintf(stderr, "Warning: failed to fetch key states for device: /dev/input/event%d\n", dev_input_id);
} else {
keyboard_event_fetch_update_key_states(self, &self->event_extra_data[self->num_event_polls], fd);
if(self->event_extra_data[self->num_event_polls].num_keys_pressed > 0)
fprintf(stderr, "Info: device not grabbed yet because some keys are still being pressed: /dev/input/event%d\n", dev_input_id);
}
++self->num_event_polls;
return true;
@@ -395,7 +403,8 @@ static int setup_virtual_keyboard_input(const char *name) {
success &= (ioctl(fd, UI_SET_MSCBIT, MSC_SCAN) != -1);
for(int i = 1; i < KEY_MAX; ++i) {
success &= (ioctl(fd, UI_SET_KEYBIT, i) != -1);
if(is_key_or_mouse_button(i))
success &= (ioctl(fd, UI_SET_KEYBIT, i) != -1);
}
for(int i = 0; i < REL_MAX; ++i) {
success &= (ioctl(fd, UI_SET_RELBIT, i) != -1);

View File

@@ -0,0 +1,25 @@
#include "keys.h"
#include <linux/input-event-codes.h>
bool is_key_or_mouse_button(uint32_t keycode) {
return (keycode >= KEY_ESC && keycode <= KEY_KPDOT)
|| (keycode >= KEY_ZENKAKUHANKAKU && keycode <= KEY_F24)
|| (keycode >= KEY_PLAYCD && keycode <= KEY_MICMUTE)
|| (keycode >= BTN_MISC && keycode <= BTN_TASK)
|| (keycode >= BTN_JOYSTICK && keycode <= BTN_THUMBR)
|| (keycode >= BTN_DIGI && keycode <= BTN_GEAR_UP)
|| (keycode >= KEY_OK && keycode <= KEY_IMAGES)
|| (keycode >= KEY_DEL_EOL && keycode <= KEY_DEL_LINE)
|| (keycode >= KEY_FN && keycode <= KEY_FN_B)
|| (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT10)
|| (keycode >= KEY_NUMERIC_0 && keycode <= KEY_LIGHTS_TOGGLE)
|| (keycode >= BTN_DPAD_UP && keycode <= BTN_DPAD_RIGHT)
|| (keycode == KEY_ALS_TOGGLE)
|| (keycode >= KEY_BUTTONCONFIG && keycode <= KEY_VOICECOMMAND)
|| (keycode >= KEY_BRIGHTNESS_MIN && keycode <= KEY_BRIGHTNESS_MAX)
|| (keycode >= KEY_KBDINPUTASSIST_PREV && keycode <= KEY_ONSCREEN_KEYBOARD);
}
bool is_mouse_button(uint32_t keycode) {
return (keycode >= BTN_MOUSE && keycode <= BTN_TASK);
}

View File

@@ -0,0 +1,10 @@
#ifndef KEYS_H
#define KEYS_H
#include <stdbool.h>
#include <stdint.h>
bool is_key_or_mouse_button(uint32_t keycode);
bool is_mouse_button(uint32_t keycode);
#endif /* KEYS_H */