diff --git a/include/Overlay.hpp b/include/Overlay.hpp index 3bc4e25..30dcba6 100644 --- a/include/Overlay.hpp +++ b/include/Overlay.hpp @@ -157,7 +157,7 @@ namespace gsr { void on_press_save_replay(); void on_press_save_replay_1_min_replay(); void on_press_save_replay_10_min_replay(); - bool on_press_start_replay(bool disable_notification, bool finished_selection); + bool on_press_start_replay(bool disable_notification, bool finished_selection, std::string monitor_to_capture = ""); void on_press_start_record(bool finished_selection, RecordForceType force_type); void on_press_start_stream(bool finished_selection); void on_press_take_screenshot(bool finished_selection, ScreenshotForceType force_type); diff --git a/include/WindowUtils.hpp b/include/WindowUtils.hpp index 7ebe8b9..7456206 100644 --- a/include/WindowUtils.hpp +++ b/include/WindowUtils.hpp @@ -20,6 +20,13 @@ namespace gsr { std::string name; }; + struct DrawableGeometry { + int x = 0; + int y = 0; + int width = 0; + int height = 0; + }; + std::optional get_window_title(Display *dpy, Window window); Window get_focused_window(Display *dpy, WindowCaptureType cap_type, bool fallback_cursor_focused = true); std::string get_focused_window_name(Display *dpy, WindowCaptureType window_capture_type, bool fallback_cursor_focused = true); @@ -39,6 +46,8 @@ namespace gsr { void xi_warp_all_mouse_devices(Display *dpy, mgl::vec2i position); void window_set_fullscreen(Display *dpy, Window window, bool fullscreen); bool window_is_fullscreen(Display *display, Window window); + bool get_drawable_geometry(Display *display, Drawable drawable, DrawableGeometry *geometry); + std::optional get_monitor_by_window_center(Display *display, Window window); bool set_window_wm_state(Display *dpy, Window window, Atom atom); void make_window_click_through(Display *display, Window window); bool make_window_sticky(Display *dpy, Window window); diff --git a/src/Overlay.cpp b/src/Overlay.cpp index f446154..19a9789 100644 --- a/src/Overlay.cpp +++ b/src/Overlay.cpp @@ -161,26 +161,6 @@ namespace gsr { return result; } - struct DrawableGeometry { - int x, y, width, height; - }; - - static bool get_drawable_geometry(Display *display, Drawable drawable, DrawableGeometry *geometry) { - geometry->x = 0; - geometry->y = 0; - geometry->width = 0; - geometry->height = 0; - - Window root_window; - unsigned int w, h; - unsigned int dummy_border, dummy_depth; - Status s = XGetGeometry(display, drawable, &root_window, &geometry->x, &geometry->y, &w, &h, &dummy_border, &dummy_depth); - - geometry->width = w; - geometry->height = h; - return s != Success; - } - static bool diff_int(int a, int b, int difference) { return std::abs(a - b) <= difference; } @@ -2378,11 +2358,12 @@ namespace gsr { const bool is_kwin_wayland = wm_name == "KWin" && gsr_info.system_info.display_server == DisplayServer::WAYLAND; const bool prev_focused_window_is_fullscreen = focused_window_is_fullscreen; + Window focused_window = None; if (is_kwin_wayland) { focused_window_is_fullscreen = get_current_kwin_window_fullscreen(); } else { - const Window focused_window = get_focused_window(display, WindowCaptureType::FOCUSED, false); + focused_window = get_focused_window(display, WindowCaptureType::FOCUSED, false); if(window && focused_window == (Window)window->get_system_handle()) return; @@ -2390,11 +2371,22 @@ namespace gsr { } if(focused_window_is_fullscreen != prev_focused_window_is_fullscreen) { + std::string fullscreen_window_monitor; + if(is_kwin_wayland) { + fullscreen_window_monitor = get_current_kwin_window_monitor_name(); + } else { + auto window_monitor = get_monitor_by_window_center(display, focused_window); + if(window_monitor.has_value()) + fullscreen_window_monitor = std::move(window_monitor->name); + else + fullscreen_window_monitor.clear(); + } + if(recording_status == RecordingStatus::NONE && focused_window_is_fullscreen) { if(are_all_audio_tracks_available_to_capture(config.replay_config.record_options.audio_tracks_list) && is_webcam_available_to_capture(config.replay_config.record_options)) - on_press_start_replay(false, false); + on_press_start_replay(false, false, fullscreen_window_monitor); } else if(recording_status == RecordingStatus::REPLAY && !focused_window_is_fullscreen) { - on_press_start_replay(true, false); + on_press_start_replay(true, false, fullscreen_window_monitor); } } } @@ -2693,29 +2685,19 @@ namespace gsr { if(capture_target == "window") { return std::to_string(region_selector.get_window_selection()); } else if(capture_target == "focused_monitor") { - mgl_context *context = mgl_get_context(); - Display *display = (Display*)context->connection; - - const std::string wm_name = get_window_manager_name(display); - const bool is_kwin_wayland = wm_name == "KWin" && gsr_info.system_info.display_server == DisplayServer::WAYLAND; + std::optional cursor_info; + if(cursor_tracker) { + cursor_tracker->update(); + cursor_info = cursor_tracker->get_latest_cursor_info(); + } std::string focused_monitor_name; - - if (is_kwin_wayland && focused_window_is_fullscreen) { - focused_monitor_name = get_current_kwin_window_monitor_name(); + if(cursor_info) { + focused_monitor_name = std::move(cursor_info->monitor_name); } else { - std::optional cursor_info; - if(cursor_tracker) { - cursor_tracker->update(); - cursor_info = cursor_tracker->get_latest_cursor_info(); - } - - - if(cursor_info) { - focused_monitor_name = std::move(cursor_info->monitor_name); - } else { - focused_monitor_name = get_focused_monitor_by_cursor(cursor_tracker.get(), gsr_info, get_monitors(display)); - } + mgl_context *context = mgl_get_context(); + Display *display = (Display*)context->connection; + focused_monitor_name = get_focused_monitor_by_cursor(cursor_tracker.get(), gsr_info, get_monitors(display)); } focused_monitor_name = get_valid_capture_target(focused_monitor_name, capture_options); @@ -2895,7 +2877,7 @@ namespace gsr { return capture_source_arg; } - bool Overlay::on_press_start_replay(bool disable_notification, bool finished_selection) { + bool Overlay::on_press_start_replay(bool disable_notification, bool finished_selection, std::string monitor_to_capture) { if(region_selector.is_started()) return false; @@ -2956,7 +2938,7 @@ namespace gsr { } const SupportedCaptureOptions capture_options = get_supported_capture_options(gsr_info); - recording_capture_target = get_capture_target(config.replay_config.record_options.record_area_option, capture_options); + recording_capture_target = !monitor_to_capture.empty() ? monitor_to_capture : get_capture_target(config.replay_config.record_options.record_area_option, capture_options); if(!validate_capture_target(config.replay_config.record_options.record_area_option, capture_options)) { char err_msg[256]; snprintf(err_msg, sizeof(err_msg), TR("Failed to start replay, capture target \"%s\" is invalid.\nPlease change capture target in settings"), recording_capture_target.c_str()); diff --git a/src/WindowUtils.cpp b/src/WindowUtils.cpp index 12bccb7..f69465d 100644 --- a/src/WindowUtils.cpp +++ b/src/WindowUtils.cpp @@ -11,6 +11,7 @@ #include #include "xdg-output-unstable-v1-client-protocol.h" +#include #include extern "C" { @@ -893,6 +894,36 @@ namespace gsr { return is_fullscreen; } + bool get_drawable_geometry(Display *display, Drawable drawable, DrawableGeometry *geometry) { + geometry->x = 0; + geometry->y = 0; + geometry->width = 0; + geometry->height = 0; + + Window root_window; + unsigned int w, h; + unsigned int dummy_border, dummy_depth; + Status s = XGetGeometry(display, drawable, &root_window, &geometry->x, &geometry->y, &w, &h, &dummy_border, &dummy_depth); + + geometry->width = w; + geometry->height = h; + return s != Success; + } + + std::optional get_monitor_by_window_center(Display *display, Window window) { + DrawableGeometry geometry; + if(!get_drawable_geometry(display, window, &geometry)) + return std::nullopt; + + const mgl::vec2i window_center = mgl::vec2i(geometry.x, geometry.y) + mgl::vec2i(geometry.width, geometry.height) / 2; + auto monitors = get_monitors(display); + for(auto &monitor : monitors) { + if(mgl::IntRect(monitor.position, monitor.size).contains(window_center)) + return std::move(monitor); + } + return std::nullopt; + } + #define _NET_WM_STATE_REMOVE 0 #define _NET_WM_STATE_ADD 1 #define _NET_WM_STATE_TOGGLE 2