mirror of
https://repo.dec05eba.com/gpu-screen-recorder-ui
synced 2026-04-07 03:55:23 +09:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3e6c3c3b9 | ||
|
|
38feee9f29 | ||
|
|
90a1272a65 | ||
|
|
9ada8caabc |
@@ -38,8 +38,11 @@ There are also additional dependencies needed at runtime:
|
||||
* [GPU Screen Recorder Notification](https://git.dec05eba.com/gpu-screen-recorder-notification/)
|
||||
|
||||
## Program behavior notes
|
||||
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 select "Only grab virtual devices"
|
||||
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 keyboard remapping software. To workaround this you can go into settings and select "Only grab virtual devices".\
|
||||
If you use keyboard remapping software such as keyd then make sure to make it ignore "gsr-ui virtual keyboard" (dec0:5eba device id), otherwise your keyboard can get locked
|
||||
as gpu screen recorder tries to grab keys and keyd grabs gpu screen recorder, leading to a lock.\
|
||||
If you are stuck in such a lock where you cant press and keyboard keys you can press (left) ctrl+shift+alt+esc to close gpu screen recorder and remove it from system startup.
|
||||
|
||||
# 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`.\
|
||||
|
||||
4
TODO
4
TODO
@@ -113,6 +113,8 @@ Check if "modprobe uinput" is needed on some systems (old fedora?).
|
||||
Add recording timer to see duration of recording/streaming.
|
||||
|
||||
Make folder with window name work when using gamescope. Gamescope runs x11 itself so to get the window name inside that we have to connect to the gamescope X11 server (DISPLAY=:1 on x11 and DISPLAY=:2 on wayland, but not always).
|
||||
Detect if the window is gamescope automatically (WM_CLASS = "gamescope") and get the x11 display automatically and connect to it to get the application its running.
|
||||
This seems to only be an issue on wayland? the window title of the gamescope/steam bigpicture mode is the title of the game on x11, so it works automatically on x11.
|
||||
|
||||
When clicking on current directory in file manager show a dropdown menu where you can select common directories (HOME, Videos, Downloads and mounted drives) for quick navigation. Maybe even button to search.
|
||||
|
||||
@@ -158,3 +160,5 @@ Notification with the focused monitor (with CursorTrackerWayland) assumes that t
|
||||
If CursorTrackerWayland fails then fallback to getting focused monitor by window creation trick. Need to take into consideration prime laptop with dGPU that controls external monitors which cant be captured (different /dev/dri/card device).
|
||||
Maybe automatically switch to recording with the device that controls the monitor.
|
||||
In that case also add all monitors available to capture in the capture list and automatically choose the gpu that controls the monitor.
|
||||
|
||||
Support cjk font. Use fc-match to find the location of the font. This also works in flatpak, in which case the fonts are in /run/host/..., where it lists system fonts.
|
||||
|
||||
@@ -21,6 +21,8 @@ namespace gsr {
|
||||
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];
|
||||
|
||||
@@ -65,6 +65,7 @@ namespace gsr {
|
||||
bool is_open() const;
|
||||
bool should_exit(std::string &reason) const;
|
||||
void exit();
|
||||
void go_back_to_old_ui();
|
||||
|
||||
const Config& get_config() const;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
project('gsr-ui', ['c', 'cpp'], version : '1.3.3', default_options : ['warning_level=2', 'cpp_std=c++17'], subproject_dir : 'depends')
|
||||
project('gsr-ui', ['c', 'cpp'], version : '1.3.4', 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.3.3"
|
||||
version = "1.3.4"
|
||||
platforms = ["posix"]
|
||||
|
||||
[lang.cpp]
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "../include/GlobalHotkeysLinux.hpp"
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
@@ -71,22 +70,40 @@ namespace gsr {
|
||||
}
|
||||
|
||||
GlobalHotkeysLinux::~GlobalHotkeysLinux() {
|
||||
for(int i = 0; i < 2; ++i) {
|
||||
if(read_pipes[i] > 0)
|
||||
close(read_pipes[i]);
|
||||
|
||||
if(write_pipes[i] > 0)
|
||||
close(write_pipes[i]);
|
||||
if(write_pipes[PIPE_WRITE] > 0) {
|
||||
char command[32];
|
||||
const int command_size = snprintf(command, sizeof(command), "exit\n");
|
||||
if(write(write_pipes[PIPE_WRITE], command, command_size) != command_size) {
|
||||
fprintf(stderr, "Error: GlobalHotkeysLinux::~GlobalHotkeysLinux: failed to write command to gsr-global-hotkeys, error: %s\n", strerror(errno));
|
||||
close_fds();
|
||||
}
|
||||
}
|
||||
|
||||
if(read_file)
|
||||
fclose(read_file);
|
||||
|
||||
if(process_id > 0) {
|
||||
kill(process_id, SIGKILL);
|
||||
int status;
|
||||
waitpid(process_id, &status, 0);
|
||||
}
|
||||
|
||||
close_fds();
|
||||
}
|
||||
|
||||
void GlobalHotkeysLinux::close_fds() {
|
||||
for(int i = 0; i < 2; ++i) {
|
||||
if(read_pipes[i] > 0) {
|
||||
close(read_pipes[i]);
|
||||
read_pipes[i] = -1;
|
||||
}
|
||||
|
||||
if(write_pipes[i] > 0) {
|
||||
close(write_pipes[i]);
|
||||
write_pipes[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(read_file) {
|
||||
fclose(read_file);
|
||||
read_file = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool GlobalHotkeysLinux::start() {
|
||||
|
||||
@@ -338,6 +338,13 @@ namespace gsr {
|
||||
fprintf(stderr, "pressed %s\n", id.c_str());
|
||||
overlay->take_screenshot_region();
|
||||
});
|
||||
|
||||
global_hotkeys->bind_key_press(
|
||||
config_hotkey_to_hotkey(ConfigHotkey{ mgl::Keyboard::Key::Escape, HOTKEY_MOD_LCTRL | HOTKEY_MOD_LSHIFT | HOTKEY_MOD_LALT }),
|
||||
"exit", [overlay](const std::string &id) {
|
||||
fprintf(stderr, "pressed %s\n", id.c_str());
|
||||
overlay->go_back_to_old_ui();
|
||||
});
|
||||
}
|
||||
|
||||
static std::unique_ptr<GlobalHotkeysLinux> register_linux_hotkeys(Overlay *overlay, GlobalHotkeysLinux::GrabType grab_type) {
|
||||
@@ -1468,6 +1475,19 @@ namespace gsr {
|
||||
do_exit = true;
|
||||
}
|
||||
|
||||
void Overlay::go_back_to_old_ui() {
|
||||
const bool inside_flatpak = getenv("FLATPAK_ID") != NULL;
|
||||
if(inside_flatpak)
|
||||
exit_reason = "back-to-old-ui";
|
||||
else
|
||||
exit_reason = "exit";
|
||||
|
||||
const char *args[] = { "systemctl", "disable", "--user", "gpu-screen-recorder-ui", nullptr };
|
||||
std::string stdout_str;
|
||||
exec_program_on_host_get_stdout(args, stdout_str);
|
||||
exit();
|
||||
}
|
||||
|
||||
const Config& Overlay::get_config() const {
|
||||
return config;
|
||||
}
|
||||
@@ -1560,9 +1580,9 @@ namespace gsr {
|
||||
return;
|
||||
|
||||
if(is_capture_target_monitor(recording_capture_target.c_str()))
|
||||
snprintf(msg, sizeof(msg), "Saved recording of this monitor to '%s'", filename.c_str());
|
||||
snprintf(msg, sizeof(msg), "Saved a recording of this monitor to '%s'", filename.c_str());
|
||||
else
|
||||
snprintf(msg, sizeof(msg), "Saved recording of %s to '%s'", recording_capture_target.c_str(), filename.c_str());
|
||||
snprintf(msg, sizeof(msg), "Saved a recording of %s to '%s'", recording_capture_target.c_str(), filename.c_str());
|
||||
|
||||
capture_target = recording_capture_target.c_str();
|
||||
break;
|
||||
@@ -1572,9 +1592,9 @@ namespace gsr {
|
||||
return;
|
||||
|
||||
if(is_capture_target_monitor(replay_capture_target.c_str()))
|
||||
snprintf(msg, sizeof(msg), "Saved replay of this monitor to '%s'", filename.c_str());
|
||||
snprintf(msg, sizeof(msg), "Saved a replay of this monitor to '%s'", filename.c_str());
|
||||
else
|
||||
snprintf(msg, sizeof(msg), "Saved replay of %s to '%s'", replay_capture_target.c_str(), filename.c_str());
|
||||
snprintf(msg, sizeof(msg), "Saved a replay of %s to '%s'", replay_capture_target.c_str(), filename.c_str());
|
||||
|
||||
capture_target = replay_capture_target.c_str();
|
||||
break;
|
||||
@@ -1584,9 +1604,9 @@ namespace gsr {
|
||||
return;
|
||||
|
||||
if(is_capture_target_monitor(screenshot_capture_target.c_str()))
|
||||
snprintf(msg, sizeof(msg), "Saved screenshot of this monitor to '%s'", filename.c_str());
|
||||
snprintf(msg, sizeof(msg), "Saved a screenshot of this monitor to '%s'", filename.c_str());
|
||||
else
|
||||
snprintf(msg, sizeof(msg), "Saved screenshot of %s to '%s'", screenshot_capture_target.c_str(), filename.c_str());
|
||||
snprintf(msg, sizeof(msg), "Saved a screenshot of %s to '%s'", screenshot_capture_target.c_str(), filename.c_str());
|
||||
|
||||
capture_target = screenshot_capture_target.c_str();
|
||||
break;
|
||||
@@ -1606,9 +1626,9 @@ namespace gsr {
|
||||
const std::string filename = filepath_get_filename(replay_saved_filepath);
|
||||
char msg[512];
|
||||
if(is_capture_target_monitor(replay_capture_target.c_str()))
|
||||
snprintf(msg, sizeof(msg), "Saved replay of this monitor to '%s'", filename.c_str());
|
||||
snprintf(msg, sizeof(msg), "Saved a replay of this monitor to '%s'", filename.c_str());
|
||||
else
|
||||
snprintf(msg, sizeof(msg), "Saved replay of %s to '%s'", replay_capture_target.c_str(), filename.c_str());
|
||||
snprintf(msg, sizeof(msg), "Saved a replay of %s to '%s'", replay_capture_target.c_str(), filename.c_str());
|
||||
show_notification(msg, notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::REPLAY, replay_capture_target.c_str());
|
||||
}
|
||||
}
|
||||
@@ -1709,9 +1729,9 @@ namespace gsr {
|
||||
const std::string filename = filepath_get_filename(screenshot_filepath.c_str());
|
||||
char msg[512];
|
||||
if(is_capture_target_monitor(screenshot_capture_target.c_str()))
|
||||
snprintf(msg, sizeof(msg), "Saved screenshot of this monitor to '%s'", filename.c_str());
|
||||
snprintf(msg, sizeof(msg), "Saved a screenshot of this monitor to '%s'", filename.c_str());
|
||||
else
|
||||
snprintf(msg, sizeof(msg), "Saved screenshot of %s to '%s'", screenshot_capture_target.c_str(), filename.c_str());
|
||||
snprintf(msg, sizeof(msg), "Saved a screenshot of %s to '%s'", screenshot_capture_target.c_str(), filename.c_str());
|
||||
show_notification(msg, notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::SCREENSHOT, screenshot_capture_target.c_str());
|
||||
}
|
||||
} else {
|
||||
@@ -1815,9 +1835,9 @@ namespace gsr {
|
||||
const std::string filename = filepath_get_filename(record_filepath.c_str());
|
||||
char msg[512];
|
||||
if(is_capture_target_monitor(recording_capture_target.c_str()))
|
||||
snprintf(msg, sizeof(msg), "Saved recording of this monitor to '%s'", filename.c_str());
|
||||
snprintf(msg, sizeof(msg), "Saved a recording of this monitor to '%s'", filename.c_str());
|
||||
else
|
||||
snprintf(msg, sizeof(msg), "Saved recording of %s to '%s'", recording_capture_target.c_str(), filename.c_str());
|
||||
snprintf(msg, sizeof(msg), "Saved a recording of %s to '%s'", recording_capture_target.c_str(), filename.c_str());
|
||||
show_notification(msg, notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::RECORD, recording_capture_target.c_str());
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -303,9 +303,6 @@ int main(int argc, char **argv) {
|
||||
if(exit_reason == "back-to-old-ui") {
|
||||
const char *args[] = { "gpu-screen-recorder-gtk", "use-old-ui", nullptr };
|
||||
execvp(args[0], (char* const*)args);
|
||||
} else if(exit_reason == "restart") {
|
||||
const char *args[] = { "gsr-ui", "launch-show", nullptr };
|
||||
execvp(args[0], (char* const*)args);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -18,4 +18,10 @@ To unbind all keys send `unbind_all<newline>` to the programs stdin, for example
|
||||
```
|
||||
unbind_all
|
||||
|
||||
```
|
||||
## Exit
|
||||
To close gsr-global-hotkeys send `exit<newline>` to the programs stdin, for example:
|
||||
```
|
||||
exit
|
||||
|
||||
```
|
||||
@@ -707,8 +707,11 @@ static void keyboard_event_parse_stdin_command(keyboard_event *self, const char
|
||||
}
|
||||
self->num_global_hotkeys = 0;
|
||||
fprintf(stderr, "Info: unbinded all hotkeys\n");
|
||||
} else if(strncmp(command, "exit", 4) == 0) {
|
||||
self->stdin_failed = true;
|
||||
fprintf(stderr, "Info: received exit command\n");
|
||||
} else {
|
||||
fprintf(stderr, "Warning: got invalid command: \"%s\", expected command to start with either \"bind\" or \"unbind_all\"\n", command);
|
||||
fprintf(stderr, "Warning: got invalid command: \"%s\", expected command to start with either \"bind\", \"unbind_all\" or \"exit\"\n", command);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user