[mutter] xwayland: Set xrandr primary output
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] xwayland: Set xrandr primary output
- Date: Fri, 11 Dec 2020 14:09:08 +0000 (UTC)
commit 4f544b63626aa98a0e706c3862def62b41adb628
Author: Aleksandr Mezin <mezin alexander gmail com>
Date: Wed Nov 11 18:17:14 2020 +0600
xwayland: Set xrandr primary output
To find XWayland output that should be the primary one, iterate through all
XWayland outputs, and compare their geometry to the geometry of the primary
logical monitor.
To avoid possible race conditions (Mutter's monitor configuration already
updated, but Xrandr not yet), set the output both after Randr notifications and
after 'monitors-changed' signal.
https://gitlab.gnome.org/GNOME/mutter/-/issues/1407
Signed-off-by: Aleksandr Mezin <mezin alexander gmail com>
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1558>
src/wayland/meta-wayland-private.h | 4 ++
src/wayland/meta-xwayland-private.h | 3 +
src/wayland/meta-xwayland.c | 115 ++++++++++++++++++++++++++++++++++++
src/x11/events.c | 2 +-
4 files changed, 123 insertions(+), 1 deletion(-)
---
diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h
index 074644ebb5..679e31804c 100644
--- a/src/wayland/meta-wayland-private.h
+++ b/src/wayland/meta-wayland-private.h
@@ -67,6 +67,10 @@ typedef struct
GList *x11_windows;
MetaXWaylandDnd *dnd;
+
+ gboolean has_xrandr;
+ int rr_event_base;
+ int rr_error_base;
} MetaXWaylandManager;
struct _MetaWaylandCompositor
diff --git a/src/wayland/meta-xwayland-private.h b/src/wayland/meta-xwayland-private.h
index fa5461c3e3..bba0934bdf 100644
--- a/src/wayland/meta-xwayland-private.h
+++ b/src/wayland/meta-xwayland-private.h
@@ -36,6 +36,9 @@ meta_xwayland_complete_init (MetaDisplay *display,
void
meta_xwayland_shutdown (MetaXWaylandManager *manager);
+gboolean
+meta_xwayland_handle_xevent (XEvent *event);
+
/* wl_data_device/X11 selection interoperation */
void meta_xwayland_init_dnd (Display *xdisplay);
void meta_xwayland_shutdown_dnd (Display *xdisplay);
diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c
index 99d0ef55dd..b9832a587e 100644
--- a/src/wayland/meta-xwayland.c
+++ b/src/wayland/meta-xwayland.c
@@ -39,8 +39,10 @@
#include <linux/random.h>
#endif
#include <unistd.h>
+#include <X11/extensions/Xrandr.h>
#include <X11/Xauth.h>
+#include "backends/meta-monitor-manager-private.h"
#include "backends/meta-settings-private.h"
#include "core/main-private.h"
#include "meta/main.h"
@@ -52,6 +54,9 @@ static int display_number_override = -1;
static void meta_xwayland_stop_xserver (MetaXWaylandManager *manager);
+static void
+meta_xwayland_set_primary_output (Display *xdisplay);
+
void
meta_xwayland_associate_window_with_surface (MetaWindow *window,
MetaWaylandSurface *surface)
@@ -871,17 +876,50 @@ meta_xwayland_init (MetaXWaylandManager *manager,
return TRUE;
}
+static void
+monitors_changed_cb (MetaMonitorManager *monitor_manager)
+{
+ MetaX11Display *x11_display = meta_get_display ()->x11_display;
+
+ meta_xwayland_set_primary_output (x11_display->xdisplay);
+}
+
static void
on_x11_display_closing (MetaDisplay *display)
{
Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
meta_xwayland_shutdown_dnd (xdisplay);
+ g_signal_handlers_disconnect_by_func (meta_monitor_manager_get (),
+ monitors_changed_cb,
+ NULL);
g_signal_handlers_disconnect_by_func (display,
on_x11_display_closing,
NULL);
}
+static void
+meta_xwayland_init_xrandr (MetaXWaylandManager *manager,
+ Display *xdisplay)
+{
+ MetaMonitorManager *monitor_manager = meta_monitor_manager_get ();
+
+ manager->has_xrandr = XRRQueryExtension (xdisplay,
+ &manager->rr_event_base,
+ &manager->rr_error_base);
+
+ if (!manager->has_xrandr)
+ return;
+
+ XRRSelectInput (xdisplay, DefaultRootWindow (xdisplay),
+ RRCrtcChangeNotifyMask | RROutputChangeNotifyMask);
+
+ g_signal_connect (monitor_manager, "monitors-changed",
+ G_CALLBACK (monitors_changed_cb), NULL);
+
+ meta_xwayland_set_primary_output (xdisplay);
+}
+
/* To be called right after connecting */
void
meta_xwayland_complete_init (MetaDisplay *display,
@@ -904,6 +942,7 @@ meta_xwayland_complete_init (MetaDisplay *display,
G_CALLBACK (on_x11_display_closing), NULL);
meta_xwayland_init_dnd (xdisplay);
add_local_user_to_xhost (xdisplay);
+ meta_xwayland_init_xrandr (manager, xdisplay);
if (meta_get_x11_display_policy () == META_DISPLAY_POLICY_ON_DEMAND)
{
@@ -945,3 +984,79 @@ meta_xwayland_shutdown (MetaXWaylandManager *manager)
g_clear_pointer (&manager->auth_file, g_free);
}
}
+
+static void
+meta_xwayland_set_primary_output (Display *xdisplay)
+{
+ XRRScreenResources *resources;
+ MetaMonitorManager *monitor_manager;
+ MetaLogicalMonitor *primary_monitor;
+ int i;
+
+ monitor_manager = meta_monitor_manager_get ();
+ primary_monitor =
+ meta_monitor_manager_get_primary_logical_monitor (monitor_manager);
+
+ if (!primary_monitor)
+ return;
+
+ resources = XRRGetScreenResourcesCurrent (xdisplay,
+ DefaultRootWindow (xdisplay));
+ if (!resources)
+ return;
+
+ for (i = 0; i < resources->noutput; i++)
+ {
+ RROutput output_id = resources->outputs[i];
+ XRROutputInfo *xrandr_output;
+ XRRCrtcInfo *crtc_info = NULL;
+ MetaRectangle crtc_geometry;
+
+ xrandr_output = XRRGetOutputInfo (xdisplay, resources, output_id);
+ if (!xrandr_output)
+ continue;
+
+ if (xrandr_output->crtc)
+ crtc_info = XRRGetCrtcInfo (xdisplay, resources, xrandr_output->crtc);
+
+ XRRFreeOutputInfo (xrandr_output);
+
+ if (!crtc_info)
+ continue;
+
+ crtc_geometry.x = crtc_info->x;
+ crtc_geometry.y = crtc_info->y;
+ crtc_geometry.width = crtc_info->width;
+ crtc_geometry.height = crtc_info->height;
+
+ XRRFreeCrtcInfo (crtc_info);
+
+ if (meta_rectangle_equal (&crtc_geometry, &primary_monitor->rect))
+ {
+ XRRSetOutputPrimary (xdisplay, DefaultRootWindow (xdisplay),
+ output_id);
+ break;
+ }
+ }
+
+ XRRFreeScreenResources (resources);
+}
+
+gboolean
+meta_xwayland_handle_xevent (XEvent *event)
+{
+ MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
+ MetaXWaylandManager *manager = &compositor->xwayland_manager;
+
+ if (meta_xwayland_dnd_handle_event (event))
+ return TRUE;
+
+ if (manager->has_xrandr && event->type == manager->rr_event_base + RRNotify)
+ {
+ MetaX11Display *x11_display = meta_get_display ()->x11_display;
+ meta_xwayland_set_primary_output (x11_display->xdisplay);
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/src/x11/events.c b/src/x11/events.c
index ccd56afed4..efa8f9856b 100644
--- a/src/x11/events.c
+++ b/src/x11/events.c
@@ -1793,7 +1793,7 @@ meta_x11_display_handle_xevent (MetaX11Display *x11_display,
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor () &&
- meta_xwayland_dnd_handle_event (event))
+ meta_xwayland_handle_xevent (event))
{
bypass_gtk = bypass_compositor = TRUE;
goto out;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]