From 2ec59c6812ef2112dde2a7ce8c068d0c8155ed06 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 21 Mar 2025 23:47:24 +0100 Subject: Add alt+f2 to take a screenshot of a region --- TODO | 2 +- include/Config.hpp | 1 + include/Overlay.hpp | 3 ++- include/gui/GlobalSettingsPage.hpp | 3 +++ src/Config.cpp | 4 +++- src/Overlay.cpp | 31 ++++++++++++++++++++++--------- src/gui/GlobalSettingsPage.cpp | 26 ++++++++++++++++++++++++++ src/gui/SettingsPage.cpp | 2 +- src/main.cpp | 5 +++++ tools/gsr-ui-cli/main.c | 24 +++++++++++++++++------- 10 files changed, 81 insertions(+), 20 deletions(-) diff --git a/TODO b/TODO index 8eced48..d3e4229 100644 --- a/TODO +++ b/TODO @@ -141,7 +141,7 @@ Allow using a hotkey such as printscreen or any other non-alphanumeric key witho Use x11 shm instead of XGetImage (https://stackoverflow.com/questions/43442675/how-to-use-xshmgetimage-and-xshmputimage). -Add a hotkey to record/stream/replay/screenshot region. +Add a hotkey to record/stream/replay region. Do xi grab for keys as well. Otherwise the ui cant be used for keyboard input if a program has grabbed the keyboard, and there could possibly be a game that grabs the keyboard as well. diff --git a/include/Config.hpp b/include/Config.hpp index 1e2e9cb..0e8e4eb 100644 --- a/include/Config.hpp +++ b/include/Config.hpp @@ -126,6 +126,7 @@ namespace gsr { bool show_screenshot_saved_notifications = true; std::string save_directory; ConfigHotkey take_screenshot_hotkey; + ConfigHotkey take_screenshot_region_hotkey; }; struct Config { diff --git a/include/Overlay.hpp b/include/Overlay.hpp index 5ed7f51..d7b8af1 100644 --- a/include/Overlay.hpp +++ b/include/Overlay.hpp @@ -59,6 +59,7 @@ namespace gsr { void toggle_replay(); void save_replay(); void take_screenshot(); + void take_screenshot_region(); 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; @@ -111,7 +112,7 @@ namespace gsr { bool on_press_start_replay(bool disable_notification, bool finished_region_selection); void on_press_start_record(bool finished_region_selection); void on_press_start_stream(bool finished_region_selection); - void on_press_take_screenshot(bool finished_region_selection); + void on_press_take_screenshot(bool finished_region_selection, bool force_region_capture); bool update_compositor_texture(const Monitor &monitor); void force_window_on_top(); diff --git a/include/gui/GlobalSettingsPage.hpp b/include/gui/GlobalSettingsPage.hpp index c261ab6..5df5b9c 100644 --- a/include/gui/GlobalSettingsPage.hpp +++ b/include/gui/GlobalSettingsPage.hpp @@ -26,6 +26,7 @@ namespace gsr { RECORD_PAUSE_UNPAUSE, STREAM_START_STOP, TAKE_SCREENSHOT, + TAKE_SCREENSHOT_REGION, SHOW_HIDE }; @@ -58,6 +59,7 @@ namespace gsr { 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_screenshot_region_hotkey_options(); std::unique_ptr create_hotkey_control_buttons(); std::unique_ptr create_keyboard_hotkey_subsection(ScrollablePage *parent_page); std::unique_ptr create_controller_hotkey_subsection(ScrollablePage *parent_page); @@ -91,6 +93,7 @@ namespace gsr { Button *pause_unpause_recording_button_ptr = nullptr; Button *start_stop_streaming_button_ptr = nullptr; Button *take_screenshot_button_ptr = nullptr; + Button *take_screenshot_region_button_ptr = nullptr; Button *show_hide_button_ptr = nullptr; ConfigHotkey configure_config_hotkey; diff --git a/src/Config.cpp b/src/Config.cpp index 734f827..6f33359 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -140,6 +140,7 @@ namespace gsr { replay_config.save_hotkey = {mgl::Keyboard::F10, HOTKEY_MOD_LALT}; screenshot_config.take_screenshot_hotkey = {mgl::Keyboard::F1, HOTKEY_MOD_LALT}; + screenshot_config.take_screenshot_region_hotkey = {mgl::Keyboard::F2, HOTKEY_MOD_LALT}; main_config.show_hide_hotkey = {mgl::Keyboard::Z, HOTKEY_MOD_LALT}; } @@ -262,7 +263,8 @@ namespace gsr { {"screenshot.save_screenshot_in_game_folder", &config.screenshot_config.save_screenshot_in_game_folder}, {"screenshot.show_screenshot_saved_notifications", &config.screenshot_config.show_screenshot_saved_notifications}, {"screenshot.save_directory", &config.screenshot_config.save_directory}, - {"screenshot.take_screenshot_hotkey", &config.screenshot_config.take_screenshot_hotkey} + {"screenshot.take_screenshot_hotkey", &config.screenshot_config.take_screenshot_hotkey}, + {"screenshot.take_screenshot_region_hotkey", &config.screenshot_config.take_screenshot_region_hotkey} }; } diff --git a/src/Overlay.cpp b/src/Overlay.cpp index 0be7375..dabeeaa 100644 --- a/src/Overlay.cpp +++ b/src/Overlay.cpp @@ -318,6 +318,13 @@ namespace gsr { fprintf(stderr, "pressed %s\n", id.c_str()); overlay->take_screenshot(); }); + + global_hotkeys->bind_key_press( + config_hotkey_to_hotkey(overlay->get_config().screenshot_config.take_screenshot_region_hotkey), + "take_screenshot_region", [overlay](const std::string &id) { + fprintf(stderr, "pressed %s\n", id.c_str()); + overlay->take_screenshot_region(); + }); } static std::unique_ptr register_linux_hotkeys(Overlay *overlay, GlobalHotkeysLinux::GrabType grab_type) { @@ -1311,7 +1318,11 @@ namespace gsr { } void Overlay::take_screenshot() { - on_press_take_screenshot(false); + on_press_take_screenshot(false, false); + } + + void Overlay::take_screenshot_region() { + on_press_take_screenshot(false, true); } static const char* notification_type_to_string(NotificationType notification_type) { @@ -2300,7 +2311,7 @@ namespace gsr { show_notification("Streaming has started", notification_timeout_seconds, get_color_theme().tint_color, get_color_theme().tint_color, NotificationType::STREAM); } - void Overlay::on_press_take_screenshot(bool finished_region_selection) { + void Overlay::on_press_take_screenshot(bool finished_region_selection, bool force_region_capture) { if(region_selector.is_started()) return; @@ -2309,18 +2320,20 @@ namespace gsr { return; } - if(!validate_capture_target(gsr_info, config.screenshot_config.record_area_option)) { + const bool region_capture = config.screenshot_config.record_area_option == "region" || force_region_capture; + const char *record_area_option = region_capture ? "region" : config.screenshot_config.record_area_option.c_str(); + if(!validate_capture_target(gsr_info, record_area_option)) { char err_msg[256]; - snprintf(err_msg, sizeof(err_msg), "Failed to take a screenshot, capture target \"%s\" is invalid. Please change capture target in settings", config.screenshot_config.record_area_option.c_str()); + snprintf(err_msg, sizeof(err_msg), "Failed to take a screenshot, capture target \"%s\" is invalid. Please change capture target in settings", record_area_option); show_notification(err_msg, notification_error_timeout_seconds, mgl::Color(255, 0, 0, 0), mgl::Color(255, 0, 0, 0), NotificationType::SCREENSHOT); return; } - if(config.screenshot_config.record_area_option == "region" && !finished_region_selection) { + if(region_capture && !finished_region_selection) { start_region_capture = true; - on_region_selected = [this]() { + on_region_selected = [this, force_region_capture]() { usleep(200 * 1000); // Hack: wait 0.2 seconds before taking a screenshot to allow user to move cursor away. TODO: Remove this - on_press_take_screenshot(true); + on_press_take_screenshot(true, force_region_capture); }; return; } @@ -2329,7 +2342,7 @@ namespace gsr { const std::string output_file = config.screenshot_config.save_directory + "/Screenshot_" + get_date_str() + "." + config.screenshot_config.image_format; // TODO: Validate image format std::vector args = { - "gpu-screen-recorder", "-w", config.screenshot_config.record_area_option.c_str(), + "gpu-screen-recorder", "-w", record_area_option, "-cursor", config.screenshot_config.record_cursor ? "yes" : "no", "-v", "no", "-q", config.screenshot_config.image_quality.c_str(), @@ -2350,7 +2363,7 @@ namespace gsr { } char region_str[128]; - if(config.screenshot_config.record_area_option == "region") + if(region_capture) add_region_command(args, region_str, sizeof(region_str), region_selector); args.push_back(nullptr); diff --git a/src/gui/GlobalSettingsPage.cpp b/src/gui/GlobalSettingsPage.cpp index f8cdf20..defd710 100644 --- a/src/gui/GlobalSettingsPage.cpp +++ b/src/gui/GlobalSettingsPage.cpp @@ -300,6 +300,21 @@ namespace gsr { return list; } + std::unique_ptr GlobalSettingsPage::create_screenshot_region_hotkey_options() { + auto list = std::make_unique(List::Orientation::HORIZONTAL, List::Alignment::CENTER); + + list->add_widget(std::make_unique