Commit 246ae00b authored by Olivier Fourdan's avatar Olivier Fourdan 🛠 Committed by Olivier Fourdan
Browse files

xwayland: Notify of root size change with XRandR emulation

Some clients (typically Java, but maybe others) rely on ConfigureNotify
or RRScreenChangeNotify events to tell that the XRandR request is

When emulated XRandR is used in Xwayland, compute the emulated root size
and send the expected ConfigureNotify and RRScreenChangeNotify events
with the emulated size of the root window to the asking X11 client.

Note that the root window size does not actually change, as XRandR
emulation is achieved by scaling the client window using viewports in
Wayland, so this event is sort of misleading.

Also, because Xwayland is using viewports, emulating XRandR does not
reconfigure the outputs location, meaning that the actual size of the
root window which encompasses all the outputs together may not change
in a multi-monitor setup. To work around this limitation, when using an
emulated mode, we report the size of that emulated mode alone as the
root size for the configure notify event.

Signed-off-by: Olivier Fourdan's avatarOlivier Fourdan <>
Reviewed-by: default avatarHans de Goede <>
parent f9f705bf
Pipeline #421414 passed with stages
in 10 minutes and 18 seconds
......@@ -468,6 +468,85 @@ xwl_output_set_randr_emu_props(struct xwl_screen *xwl_screen, ClientPtr client)
xwl_output_set_randr_emu_prop_callback, &prop);
static inline void
xwl_output_get_emulated_root_size(struct xwl_output *xwl_output,
ClientPtr client,
int *width,
int *height)
struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
struct xwl_emulated_mode *emulated_mode;
emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, client);
/* If not an emulated mode, just return the actual screen size */
if (!emulated_mode) {
*width = xwl_screen->width;
*height = xwl_screen->height;
if (xwl_output->rotation & (RR_Rotate_0 | RR_Rotate_180)) {
*width = emulated_mode->width;
*height = emulated_mode->height;
} else {
*width = emulated_mode->height;
*height = emulated_mode->width;
static int
xwl_output_get_rr_event_mask(WindowPtr pWin, ClientPtr client)
RREventPtr pRREvent, *pHead;
dixLookupResourceByType((void **) &pHead, pWin->,
RREventType, client, DixReadAccess);
pRREvent = NULL;
if (pHead) {
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
if (pRREvent->client == client)
if (pRREvent)
return pRREvent->mask;
return 0;
static void
xwl_output_notify_emulated_root_size(struct xwl_output *xwl_output,
ClientPtr client,
int new_emulated_root_width,
int new_emulated_root_height)
struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
ScreenPtr pScreen = xwl_screen->screen;
WindowPtr pRoot = pScreen->root;
xEvent event = {
.u.configureNotify.event = pRoot->,
.u.configureNotify.window = pRoot->,
.u.configureNotify.aboveSibling = None,
.u.configureNotify.x = 0,
.u.configureNotify.y = 0,
.u.configureNotify.width = new_emulated_root_width,
.u.configureNotify.height = new_emulated_root_height,
.u.configureNotify.borderWidth = pRoot->borderWidth,
.u.configureNotify.override = pRoot->overrideRedirect
event.u.u.type = ConfigureNotify;
if (!client || client == serverClient || client->clientGone)
if (EventMaskForClient(pRoot, client) & StructureNotifyMask)
WriteEventsToClient(client, 1, &event);
if (xwl_output_get_rr_event_mask(pRoot, client) & RRScreenChangeNotifyMask)
RRDeliverScreenEvent(client, pRoot, pScreen);
xwl_output_set_window_randr_emu_props(struct xwl_screen *xwl_screen,
WindowPtr window)
......@@ -482,10 +561,16 @@ void
xwl_output_set_emulated_mode(struct xwl_output *xwl_output, ClientPtr client,
RRModePtr mode, Bool from_vidmode)
int old_emulated_width, old_emulated_height;
int new_emulated_width, new_emulated_height;
DebugF("XWAYLAND: xwl_output_set_emulated_mode from %s: %dx%d\n",
from_vidmode ? "vidmode" : "randr",
mode->mode.width, mode->mode.height);
xwl_output_get_emulated_root_size(xwl_output, client,
&old_emulated_width, &old_emulated_height);
/* modes[0] is the actual (not-emulated) output mode */
if (mode == xwl_output->randr_output->modes[0])
xwl_output_remove_emulated_mode_for_client(xwl_output, client);
......@@ -495,6 +580,15 @@ xwl_output_set_emulated_mode(struct xwl_output *xwl_output, ClientPtr client,
xwl_output_set_randr_emu_props(xwl_output->xwl_screen, client);
xwl_output_get_emulated_root_size(xwl_output, client,
&new_emulated_width, &new_emulated_height);
if (new_emulated_width != old_emulated_width ||
new_emulated_height != old_emulated_height)
xwl_output_notify_emulated_root_size(xwl_output, client,
static void
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment