diff options
author | dec05eba <dec05eba@protonmail.com> | 2025-02-10 19:31:27 +0100 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2025-02-10 19:31:27 +0100 |
commit | fc2f6f4c500d0364d5dd5cf366be2fa8592f8469 (patch) | |
tree | ad8ffcab18e0aeca25abb4ea0f751f8bf12b7f8b | |
parent | f4e44cbef5dbbc2a2b71e7b9b70ee72d30b7c6a6 (diff) |
Better detect focused x11 window on wayland, properly get focused game name on wayland
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | include/WindowUtils.hpp | 2 | ||||
-rw-r--r-- | src/Overlay.cpp | 2 | ||||
-rw-r--r-- | src/WindowUtils.cpp | 25 |
4 files changed, 24 insertions, 8 deletions
@@ -118,5 +118,4 @@ Check if "modprobe uinput" is needed on some systems (old fedora?). Add recording timer to see duration of recording/streaming. -Saving video into a folder with the name of the game doesn't always work on wayland. This happens when trying to save a video with the ui open and the ui opens without override redirect. - Maybe a solution would be to query all windows (top to bottom) and check which window the cursor is inside, ignoring the gsr-ui window
\ No newline at end of file +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).
\ No newline at end of file diff --git a/include/WindowUtils.hpp b/include/WindowUtils.hpp index ddecaea..99b45e9 100644 --- a/include/WindowUtils.hpp +++ b/include/WindowUtils.hpp @@ -3,6 +3,7 @@ #include <mglpp/system/vec.hpp> #include <string> #include <vector> +#include <optional> #include <X11/Xlib.h> namespace gsr { @@ -16,6 +17,7 @@ namespace gsr { mgl::vec2i size; }; + std::optional<std::string> get_window_title(Display *dpy, Window window); Window get_focused_window(Display *dpy, WindowCaptureType cap_type); std::string get_focused_window_name(Display *dpy, WindowCaptureType window_capture_type); std::string get_window_name_at_position(Display *dpy, mgl::vec2i position, Window ignore_window); diff --git a/src/Overlay.cpp b/src/Overlay.cpp index 8a1eefc..feb4e6f 100644 --- a/src/Overlay.cpp +++ b/src/Overlay.cpp @@ -1453,6 +1453,8 @@ namespace gsr { const Window gsr_ui_window = window ? window->get_system_handle() : None; std::string focused_window_name = get_window_name_at_cursor_position(display, gsr_ui_window); if(focused_window_name.empty()) + focused_window_name = get_focused_window_name(display, WindowCaptureType::FOCUSED); + if(focused_window_name.empty()) focused_window_name = "Game"; string_replace_characters(focused_window_name.data(), "/\\", '_'); diff --git a/src/WindowUtils.cpp b/src/WindowUtils.cpp index 3d3a6a6..c8bb859 100644 --- a/src/WindowUtils.cpp +++ b/src/WindowUtils.cpp @@ -16,8 +16,6 @@ extern "C" { #include <string.h> #include <poll.h> -#include <optional> - #define MAX_PROPERTY_VALUE_LEN 4096 namespace gsr { @@ -105,7 +103,17 @@ namespace gsr { unsigned int dummy_u; mgl::vec2i root_pos; XQueryPointer(dpy, DefaultRootWindow(dpy), &root_window, window, &root_pos.x, &root_pos.y, &dummy_i, &dummy_i, &dummy_u); + + const Window direct_window = *window; *window = window_get_target_window_child(dpy, *window); + // HACK: Count some other x11 windows as having an x11 window focused. Some games seem to create an Input window and that gets focused. + if(!*window) { + XWindowAttributes attr; + memset(&attr, 0, sizeof(attr)); + XGetWindowAttributes(dpy, direct_window, &attr); + if(attr.c_class == InputOnly && !get_window_title(dpy, direct_window)) + *window = direct_window; + } return root_pos; } @@ -162,7 +170,7 @@ namespace gsr { return result; } - static std::optional<std::string> get_window_title(Display *dpy, Window window) { + std::optional<std::string> get_window_title(Display *dpy, Window window) { const Atom net_wm_name_atom = XInternAtom(dpy, "_NET_WM_NAME", False); const Atom wm_name_atom = XInternAtom(dpy, "WM_NAME", False); const Atom utf8_string_atom = XInternAtom(dpy, "UTF8_STRING", False); @@ -252,13 +260,18 @@ namespace gsr { XWindowAttributes attr; memset(&attr, 0, sizeof(attr)); XGetWindowAttributes(dpy, children[i], &attr); - if(attr.override_redirect || attr.c_class != InputOutput) + if(attr.override_redirect || attr.c_class != InputOutput || attr.map_state != IsViewable) continue; - if(position.x >= attr.x && position.x <= attr.x + attr.width && position.y >= attr.y && position.y <= attr.y + attr.height && window_is_user_program(dpy, children[i])) { - const std::optional<std::string> window_title = get_window_title(dpy, children[i]); + if(position.x >= attr.x && position.x <= attr.x + attr.width && position.y >= attr.y && position.y <= attr.y + attr.height) { + const Window real_window = window_get_target_window_child(dpy, children[i]); + if(!real_window || real_window == ignore_window) + continue; + + const std::optional<std::string> window_title = get_window_title(dpy, real_window); if(window_title) result = strip(window_title.value()); + break; } } |