aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md4
m---------depends/mglpp0
-rw-r--r--include/Overlay.hpp3
-rw-r--r--include/WindowUtils.hpp7
-rw-r--r--src/Overlay.cpp68
-rw-r--r--src/WindowUtils.cpp17
6 files changed, 64 insertions, 35 deletions
diff --git a/README.md b/README.md
index a85e083..b3a8d0e 100644
--- a/README.md
+++ b/README.md
@@ -54,8 +54,8 @@ If you want to donate you can donate via bitcoin or monero.
* Monero: 4An9kp2qW1C9Gah7ewv4JzcNFQ5TAX7ineGCqXWK6vQnhsGGcRpNgcn8r9EC3tMcgY7vqCKs3nSRXhejMHBaGvFdN2egYet
# Known issues
-* When the UI is open the wallpaper is shown instead of the game on Hyprland and Sway. This is an issue with Hyprland and Sway. It cant be fixed until the UI is redesigned to not be a fullscreen overlay.
-* Opening the UI when a game is fullscreened can mess up the game window a bit on Hyprland and Sway. I believe this is an issue in Hyprland and Sway.
+* When the UI is open the wallpaper is shown instead of the game on Hyprland. This is an issue with Hyprland. It cant be fixed until the UI is redesigned to not be a fullscreen overlay.
+* Opening the UI when a game is fullscreened can mess up the game window a bit on Hyprland. I believe this is an issue with Hyprland.
# FAQ
## I get an error when trying to start the gpu-screen-recorder-ui.service systemd service
diff --git a/depends/mglpp b/depends/mglpp
-Subproject 1ce8b2de75f334696bc3b0037160ce3623c46e7
+Subproject e776c85d1986ee9cd7629ec5f04e89f79230378
diff --git a/include/Overlay.hpp b/include/Overlay.hpp
index e802cd0..45776b8 100644
--- a/include/Overlay.hpp
+++ b/include/Overlay.hpp
@@ -5,6 +5,7 @@
#include "GsrInfo.hpp"
#include "Config.hpp"
#include "window_texture.h"
+#include "WindowUtils.hpp"
#include <mglpp/window/Window.hpp>
#include <mglpp/window/Event.hpp>
@@ -97,7 +98,7 @@ namespace gsr {
void on_press_start_replay(bool disable_notification);
void on_press_start_record();
void on_press_start_stream();
- bool update_compositor_texture(const mgl_monitor *monitor);
+ bool update_compositor_texture(const Monitor &monitor);
void force_window_on_top();
private:
diff --git a/include/WindowUtils.hpp b/include/WindowUtils.hpp
index d17c0fd..c8806df 100644
--- a/include/WindowUtils.hpp
+++ b/include/WindowUtils.hpp
@@ -2,6 +2,7 @@
#include <mglpp/system/vec.hpp>
#include <string>
+#include <vector>
#include <X11/Xlib.h>
namespace gsr {
@@ -10,10 +11,16 @@ namespace gsr {
CURSOR
};
+ struct Monitor {
+ mgl::vec2i position;
+ mgl::vec2i size;
+ };
+
Window get_focused_window(Display *dpy, WindowCaptureType cap_type);
std::string get_focused_window_name(Display *dpy, WindowCaptureType window_capture_type);
mgl::vec2i get_cursor_position(Display *dpy, Window *window);
mgl::vec2i create_window_get_center_position(Display *display);
std::string get_window_manager_name(Display *display);
bool is_compositor_running(Display *dpy, int screen);
+ std::vector<Monitor> get_monitors(Display *dpy);
} \ No newline at end of file
diff --git a/src/Overlay.cpp b/src/Overlay.cpp
index 48aa4d3..0d74637 100644
--- a/src/Overlay.cpp
+++ b/src/Overlay.cpp
@@ -164,7 +164,7 @@ namespace gsr {
return std::abs(a - b) <= difference;
}
- static bool is_window_fullscreen_on_monitor(Display *display, Window window, const mgl_monitor *monitor) {
+ static bool is_window_fullscreen_on_monitor(Display *display, Window window, const Monitor &monitor) {
if(!window)
return false;
@@ -173,8 +173,8 @@ namespace gsr {
return false;
const int margin = 2;
- return diff_int(geometry.x, monitor->pos.x, margin) && diff_int(geometry.y, monitor->pos.y, margin)
- && diff_int(geometry.width, monitor->size.x, margin) && diff_int(geometry.height, monitor->size.y, margin);
+ return diff_int(geometry.x, monitor.position.x, margin) && diff_int(geometry.y, monitor.position.y, margin)
+ && diff_int(geometry.width, monitor.size.x, margin) && diff_int(geometry.height, monitor.size.y, margin);
}
/*static bool is_window_fullscreen_on_monitor(Display *display, Window window, const mgl_monitor *monitors, int num_monitors) {
@@ -279,15 +279,13 @@ namespace gsr {
}
// Returns the first monitor if not found. Assumes there is at least one monitor connected.
- static const mgl_monitor* find_monitor_at_position(mgl::Window &window, mgl::vec2i pos) {
- const mgl_window *win = window.internal_window();
- assert(win->num_monitors > 0);
- for(int i = 0; i < win->num_monitors; ++i) {
- const mgl_monitor *mon = &win->monitors[i];
- if(mgl::IntRect({ mon->pos.x, mon->pos.y }, { mon->size.x, mon->size.y }).contains(pos))
- return mon;
+ static const Monitor* find_monitor_at_position(const std::vector<Monitor> &monitors, mgl::vec2i pos) {
+ assert(!monitors.empty());
+ for(const Monitor &monitor : monitors) {
+ if(mgl::IntRect(monitor.position, monitor.size).contains(pos))
+ return &monitor;
}
- return &win->monitors[0];
+ return &monitors.front();
}
static std::string get_power_supply_online_filepath() {
@@ -712,25 +710,39 @@ namespace gsr {
mgl_context *context = mgl_get_context();
Display *display = (Display*)context->connection;
+ const std::vector<Monitor> monitors = get_monitors(display);
+ if(monitors.empty()) {
+ fprintf(stderr, "gsr warning: no monitors found, not showing overlay\n");
+ window.reset();
+ return;
+ }
+
const std::string wm_name = get_window_manager_name(display);
const bool is_kwin = wm_name == "KWin";
+ const bool is_wlroots = wm_name.find("wlroots") != std::string::npos;
// The cursor position is wrong on wayland if an x11 window is not focused. On wayland we instead create a window and get the position where the wayland compositor puts it
Window x11_cursor_window = None;
const mgl::vec2i cursor_position = get_cursor_position(display, &x11_cursor_window);
const mgl::vec2i monitor_position_query_value = (x11_cursor_window || gsr_info.system_info.display_server != DisplayServer::WAYLAND) ? cursor_position : create_window_get_center_position(display);
+ const Monitor *focused_monitor = find_monitor_at_position(monitors, monitor_position_query_value);
+ if(is_wlroots) {
+ window_pos = focused_monitor->position;
+ window_size = focused_monitor->size;
+ } else {
+ window_pos = {0, 0};
+ window_size = {32, 32};
+ }
+
// Wayland doesn't allow XGrabPointer/XGrabKeyboard when a wayland application is focused.
// If the focused window is a wayland application then don't use override redirect and instead create
// a fullscreen window for the ui.
const bool prevent_game_minimizing = gsr_info.system_info.display_server != DisplayServer::WAYLAND || x11_cursor_window;
- window_size = { 32, 32 };
- window_pos = { 0, 0 };
-
mgl::Window::CreateParams window_create_params;
window_create_params.size = window_size;
- if(prevent_game_minimizing) {
+ if(is_wlroots || prevent_game_minimizing) {
window_create_params.min_size = window_size;
window_create_params.max_size = window_size;
}
@@ -757,33 +769,26 @@ namespace gsr {
data = 1;
XChangeProperty(display, window->get_system_handle(), XInternAtom(display, "GAMESCOPE_EXTERNAL_OVERLAY", False), XA_CARDINAL, 32, PropModeReplace, &data, 1);
+ window_pos = focused_monitor->position;
+ window_size = focused_monitor->size;
if(!init_theme(resources_path)) {
fprintf(stderr, "Error: failed to load theme\n");
- ::exit(1);
- }
-
- mgl_window *win = window->internal_window();
- if(win->num_monitors == 0) {
- fprintf(stderr, "gsr warning: no monitors found, not showing overlay\n");
window.reset();
return;
}
-
- const mgl_monitor *focused_monitor = find_monitor_at_position(*window, monitor_position_query_value);
- window_pos = {focused_monitor->pos.x, focused_monitor->pos.y};
- window_size = {focused_monitor->size.x, focused_monitor->size.y};
get_theme().set_window_size(window_size);
- if(prevent_game_minimizing) {
+ if(is_wlroots || prevent_game_minimizing) {
window->set_size(window_size);
window->set_size_limits(window_size, window_size);
window->set_position(window_pos);
}
+ mgl_window *win = window->internal_window();
win->cursor_position.x = cursor_position.x - window_pos.x;
win->cursor_position.y = cursor_position.y - window_pos.y;
- update_compositor_texture(focused_monitor);
+ update_compositor_texture(*focused_monitor);
bg_screenshot_overlay = mgl::Rectangle(mgl::vec2f(get_theme().window_width, get_theme().window_height));
top_bar_background = mgl::Rectangle(mgl::vec2f(get_theme().window_width, get_theme().window_height*0.06f).floor());
@@ -991,7 +996,8 @@ namespace gsr {
// XFlush(display);
// }
- window->set_fullscreen(true);
+ if(!is_wlroots)
+ window->set_fullscreen(true);
visible = true;
@@ -1954,7 +1960,7 @@ namespace gsr {
show_notification("Streaming has started", 3.0, get_color_theme().tint_color, get_color_theme().tint_color, NotificationType::STREAM);
}
- bool Overlay::update_compositor_texture(const mgl_monitor *monitor) {
+ bool Overlay::update_compositor_texture(const Monitor &monitor) {
window_texture_deinit(&window_texture);
window_texture_sprite.set_texture(nullptr);
screenshot_texture.clear();
@@ -1977,7 +1983,7 @@ namespace gsr {
window_texture_texture = mgl::Texture(window_texture.texture_id, MGL_TEXTURE_FORMAT_RGB);
window_texture_sprite.set_texture(&window_texture_texture);
} else {
- XImage *img = XGetImage(display, DefaultRootWindow(display), monitor->pos.x, monitor->pos.y, monitor->size.x, monitor->size.y, AllPlanes, ZPixmap);
+ XImage *img = XGetImage(display, DefaultRootWindow(display), monitor.position.x, monitor.position.y, monitor.size.x, monitor.size.y, AllPlanes, ZPixmap);
if(!img)
fprintf(stderr, "Error: failed to take a screenshot\n");
@@ -2003,4 +2009,4 @@ namespace gsr {
XFlush(display);
}
}
-} \ No newline at end of file
+}
diff --git a/src/WindowUtils.cpp b/src/WindowUtils.cpp
index 0bd3a8e..ea9dfbd 100644
--- a/src/WindowUtils.cpp
+++ b/src/WindowUtils.cpp
@@ -6,6 +6,10 @@
#include <mglpp/system/Utf8.hpp>
+extern "C" {
+#include <mgl/window/window.h>
+}
+
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
@@ -470,7 +474,18 @@ namespace gsr {
bool is_compositor_running(Display *dpy, int screen) {
char prop_name[20];
snprintf(prop_name, sizeof(prop_name), "_NET_WM_CM_S%d", screen);
- Atom prop_atom = XInternAtom(dpy, prop_name, False);
+ const Atom prop_atom = XInternAtom(dpy, prop_name, False);
return XGetSelectionOwner(dpy, prop_atom) != None;
}
+
+ static void get_monitors_callback(const mgl_monitor *monitor, void *userdata) {
+ std::vector<Monitor> *monitors = (std::vector<Monitor>*)userdata;
+ monitors->push_back({mgl::vec2i(monitor->pos.x, monitor->pos.y), mgl::vec2i(monitor->size.x, monitor->size.y)});
+ }
+
+ std::vector<Monitor> get_monitors(Display *dpy) {
+ std::vector<Monitor> monitors;
+ mgl_for_each_active_monitor_output(dpy, get_monitors_callback, &monitors);
+ return monitors;
+ }
} \ No newline at end of file