From 189736c1a96a1ad0e571ad69f01039e96455011a Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 22 Feb 2025 13:31:51 +0100 Subject: Add option to take a screenshot (default hotkey: alt+f1) --- TODO | 9 +- depends/mglpp | 2 +- images/screenshot.png | Bin 0 -> 7193 bytes include/Config.hpp | 21 ++ include/GsrInfo.hpp | 6 + include/Overlay.hpp | 9 +- include/Theme.hpp | 1 + include/Utils.hpp | 2 + include/gui/Button.hpp | 1 + include/gui/DropdownButton.hpp | 1 + include/gui/GlobalSettingsPage.hpp | 4 + include/gui/GsrPage.hpp | 5 +- include/gui/ScreenshotSettingsPage.hpp | 78 ++++++++ include/gui/SettingsPage.hpp | 2 +- meson.build | 1 + src/Config.cpp | 118 +++++++++++- src/GsrInfo.cpp | 14 ++ src/Hotplug.cpp | 3 +- src/Overlay.cpp | 288 +++++++++++++++++++++------- src/Theme.cpp | 3 + src/Utils.cpp | 8 + src/WindowUtils.cpp | 12 +- src/gui/Button.cpp | 67 +++++-- src/gui/DropdownButton.cpp | 9 + src/gui/GlobalSettingsPage.cpp | 126 ++++++------ src/gui/GsrPage.cpp | 13 +- src/gui/ScreenshotSettingsPage.cpp | 339 +++++++++++++++++++++++++++++++++ src/gui/SettingsPage.cpp | 26 +-- src/main.cpp | 7 + tools/gsr-global-hotkeys/hotplug.c | 3 +- tools/gsr-ui-cli/main.c | 2 + 31 files changed, 977 insertions(+), 203 deletions(-) create mode 100644 images/screenshot.png create mode 100644 include/gui/ScreenshotSettingsPage.hpp create mode 100644 src/gui/ScreenshotSettingsPage.cpp diff --git a/TODO b/TODO index 600023a..3675ffc 100644 --- a/TODO +++ b/TODO @@ -78,8 +78,6 @@ Dont allow autostart of replay if capture option is window recording (when windo Use global shortcuts desktop portal protocol on wayland when available. -When support for window capture is enabled on x11 then make sure to not save the window except temporary while the program is open. - Support CJK. Move ui hover code from ::draw to ::on_event, to properly handle widget event stack. @@ -121,3 +119,10 @@ 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). 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. + +Maybe change gsr-ui startup retry time in the systemd service, from 5 seconds to 2 seconds. + +Add support for window capture. This should not prompt for window selection directly but instead prompt for window selection when recording starts and hide the ui first. + For screenshots window capture should exist but "follow focused" option should not exist. + +Improve audio design. It should have a button to add/remove audio tracks and button to add audio into each audio track separately and "record audio from all applications except the selected ones" for each audio track. Then also remove the "merge audio tracks" option. diff --git a/depends/mglpp b/depends/mglpp index d875a5c..04a9fde 160000 --- a/depends/mglpp +++ b/depends/mglpp @@ -1 +1 @@ -Subproject commit d875a5c2b9cd3b123e4253ba48f8738ff5b08f1b +Subproject commit 04a9fdec5a7248245b0c3ec874a5df56e039a8f6 diff --git a/images/screenshot.png b/images/screenshot.png new file mode 100644 index 0000000..9f04433 Binary files /dev/null and b/images/screenshot.png differ diff --git a/include/Config.hpp b/include/Config.hpp index 34c2010..1c82822 100644 --- a/include/Config.hpp +++ b/include/Config.hpp @@ -17,6 +17,8 @@ namespace gsr { bool operator==(const ConfigHotkey &other) const; bool operator!=(const ConfigHotkey &other) const; + + std::string to_string(bool spaces = true, bool modifier_side = true) const; }; struct RecordOptions { @@ -101,15 +103,34 @@ namespace gsr { ConfigHotkey save_hotkey; }; + struct ScreenshotConfig { + std::string record_area_option = "screen"; + int32_t image_width = 0; + int32_t image_height = 0; + bool change_image_resolution = false; + std::string image_quality = "very_high"; + std::string image_format = "jpg"; + bool record_cursor = true; + bool restore_portal_session = true; + + bool save_screenshot_in_game_folder = false; + bool show_screenshot_saved_notifications = true; + std::string save_directory; + ConfigHotkey take_screenshot_hotkey; + }; + struct Config { Config(const SupportedCaptureOptions &capture_options); bool operator==(const Config &other); bool operator!=(const Config &other); + void set_hotkeys_to_default(); + MainConfig main_config; StreamingConfig streaming_config; RecordConfig record_config; ReplayConfig replay_config; + ScreenshotConfig screenshot_config; }; std::optional read_config(const SupportedCaptureOptions &capture_options); diff --git a/include/GsrInfo.hpp b/include/GsrInfo.hpp index a8c0742..b027cc5 100644 --- a/include/GsrInfo.hpp +++ b/include/GsrInfo.hpp @@ -20,6 +20,11 @@ namespace gsr { bool vp9 = false; }; + struct SupportedImageFormats { + bool jpeg = false; + bool png = false; + }; + struct GsrMonitor { std::string name; mgl::vec2i size; @@ -75,6 +80,7 @@ namespace gsr { SystemInfo system_info; GpuInfo gpu_info; SupportedVideoCodecs supported_video_codecs; + SupportedImageFormats supported_image_formats; }; enum class GsrInfoExitStatus { diff --git a/include/Overlay.hpp b/include/Overlay.hpp index f3025b2..812954e 100644 --- a/include/Overlay.hpp +++ b/include/Overlay.hpp @@ -35,7 +35,8 @@ namespace gsr { NONE, RECORD, REPLAY, - STREAM + STREAM, + SCREENSHOT }; class Overlay { @@ -57,6 +58,7 @@ namespace gsr { void toggle_stream(); void toggle_replay(); void save_replay(); + void take_screenshot(); void show_notification(const char *str, double timeout_seconds, mgl::Color icon_color, mgl::Color bg_color, NotificationType notification_type); bool is_open() const; bool should_exit(std::string &reason) const; @@ -70,6 +72,7 @@ namespace gsr { void handle_keyboard_mapping_event(); void on_event(mgl::Event &event); + void create_frontpage_ui_components(); void xi_setup(); void handle_xi_events(); void process_key_bindings(mgl::Event &event); @@ -84,6 +87,7 @@ namespace gsr { void on_replay_saved(const char *replay_saved_filepath); void update_gsr_replay_save(); void update_gsr_process_status(); + void update_gsr_screenshot_process_status(); void replay_status_update_status(); void update_focused_fullscreen_status(); @@ -107,6 +111,7 @@ namespace gsr { void on_press_start_replay(bool disable_notification); void on_press_start_record(); void on_press_start_stream(); + void on_press_take_screenshot(); bool update_compositor_texture(const Monitor &monitor); void force_window_on_top(); @@ -149,6 +154,7 @@ namespace gsr { pid_t notification_process = -1; int gpu_screen_recorder_process_output_fd = -1; FILE *gpu_screen_recorder_process_output_file = nullptr; + pid_t gpu_screen_recorder_screenshot_process = -1; DropdownButton *replay_dropdown_button_ptr = nullptr; DropdownButton *record_dropdown_button_ptr = nullptr; @@ -165,6 +171,7 @@ namespace gsr { bool focused_window_is_fullscreen = false; std::string record_filepath; + std::string screenshot_filepath; Display *xi_display = nullptr; int xi_opcode = 0; diff --git a/include/Theme.hpp b/include/Theme.hpp index 185bcdc..90dd8cf 100644 --- a/include/Theme.hpp +++ b/include/Theme.hpp @@ -41,6 +41,7 @@ namespace gsr { mgl::Texture stop_texture; mgl::Texture pause_texture; mgl::Texture save_texture; + mgl::Texture screenshot_texture; double double_click_timeout_seconds = 0.4; diff --git a/include/Utils.hpp b/include/Utils.hpp index e7bb3bc..f7d8538 100644 --- a/include/Utils.hpp +++ b/include/Utils.hpp @@ -24,6 +24,8 @@ namespace gsr { std::map get_xdg_variables(); std::string get_videos_dir(); + std::string get_pictures_dir(); + // Returns 0 on success int create_directory_recursive(char *path); bool file_get_content(const char *filepath, std::string &file_content); diff --git a/include/gui/Button.hpp b/include/gui/Button.hpp index eb68e99..7070457 100644 --- a/include/gui/Button.hpp +++ b/include/gui/Button.hpp @@ -30,6 +30,7 @@ namespace gsr { std::function on_click; private: void scale_sprite_to_button_size(); + float get_button_height(); private: mgl::vec2f size; mgl::Color bg_color; diff --git a/include/gui/DropdownButton.hpp b/include/gui/DropdownButton.hpp index cbbcda2..486e811 100644 --- a/include/gui/DropdownButton.hpp +++ b/include/gui/DropdownButton.hpp @@ -20,6 +20,7 @@ namespace gsr { void add_item(const std::string &text, const std::string &id, const std::string &description = ""); void set_item_label(const std::string &id, const std::string &new_label); void set_item_icon(const std::string &id, mgl::Texture *texture); + void set_item_description(const std::string &id, const std::string &new_description); void set_description(std::string description_text); void set_activated(bool activated); diff --git a/include/gui/GlobalSettingsPage.hpp b/include/gui/GlobalSettingsPage.hpp index 580e943..d0a0336 100644 --- a/include/gui/GlobalSettingsPage.hpp +++ b/include/gui/GlobalSettingsPage.hpp @@ -25,6 +25,7 @@ namespace gsr { RECORD_START_STOP, RECORD_PAUSE_UNPAUSE, STREAM_START_STOP, + TAKE_SCREENSHOT, SHOW_HIDE }; @@ -44,6 +45,7 @@ namespace gsr { std::function on_click_exit_program_button; std::function on_keyboard_hotkey_changed; std::function on_joystick_hotkey_changed; + std::function on_page_closed; private: void load_hotkeys(); @@ -55,6 +57,7 @@ namespace gsr { std::unique_ptr create_replay_hotkey_options(); std::unique_ptr create_record_hotkey_options(); std::unique_ptr create_stream_hotkey_options(); + std::unique_ptr create_screenshot_hotkey_options(); std::unique_ptr create_hotkey_control_buttons(); std::unique_ptr create_hotkey_subsection(ScrollablePage *parent_page); std::unique_ptr