xwayland: Use xdg-output name for XRandR

Currently, Xwayland assigns sequential output names for XRandR. When an
output is hotplugged, a new name is assigned sequentially (XWAYLAND0,
XWAYLAND1, etc.). This is a problem because if a monitor is unplugged
and plugged again, it will get a new name each time.

Luckily, xdg-output provides us with a name for the outputs.

Even though the protocol states that the name is not a reflection of the
underlying DRM connector name, it is to remain consistent across
sessions with the same hardware and software configuration.

So we could use the xdg-output name for the XRandR reported name for the
output.

Doing so is a bit tricky though, because the output name is set at
creation and is not supposed to change. The xdg-output event that
provides us with the name will come at a later time.

So we just allocate a default fixed size for the output name at creation
and just replace the default output name with the xdg-output name when
that is known.

Also, historically, some X11 clients were expecting output names in
Xwayland to be named XWAYLAND<x> and used that to check whether they
were running on Xwayland. Those clients should now use the Xwayland X11
extension which is designed specifically for that purpose.

Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1353
See-also: https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/954
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
This commit is contained in:
Olivier Fourdan 2023-02-02 14:17:30 +01:00
parent ddcbb46f97
commit 3c07a01c42

View File

@ -35,6 +35,8 @@
#include "xdg-output-unstable-v1-client-protocol.h"
#define MAX_OUTPUT_NAME 256
static void xwl_output_get_xdg_output(struct xwl_output *xwl_output);
static Rotation
@ -658,6 +660,21 @@ apply_output_change(struct xwl_output *xwl_output)
RRTellChanged(xwl_screen->screen);
}
static void
xwl_output_set_name(struct xwl_output *xwl_output, const char *name)
{
if (xwl_output->randr_output == NULL)
return; /* rootful */
/* Check whether the compositor is sending us something useful */
if (!name || !strlen(name)) {
ErrorF("Not using the provided output name, invalid");
return;
}
snprintf(xwl_output->randr_output->name, MAX_OUTPUT_NAME, "%s", name);
}
static void
output_handle_done(void *data, struct wl_output *wl_output)
{
@ -719,6 +736,9 @@ static void
xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output,
const char *name)
{
struct xwl_output *xwl_output = data;
xwl_output_set_name(xwl_output, name);
}
static void
@ -774,7 +794,7 @@ struct xwl_output *
xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id, Bool with_xrandr)
{
struct xwl_output *xwl_output;
char name[256];
char name[MAX_OUTPUT_NAME];
xwl_output = calloc(1, sizeof *xwl_output);
if (xwl_output == NULL) {
@ -795,7 +815,7 @@ xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id, Bool with_xrandr)
xwl_output->xwl_screen = xwl_screen;
if (with_xrandr) {
snprintf(name, sizeof name, "XWAYLAND%d",
snprintf(name, MAX_OUTPUT_NAME, "XWAYLAND%d",
xwl_screen_get_next_output_serial(xwl_screen));
xwl_output->randr_crtc = RRCrtcCreate(xwl_screen->screen, xwl_output);
@ -806,7 +826,7 @@ xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id, Bool with_xrandr)
RRCrtcSetRotations (xwl_output->randr_crtc, ALL_ROTATIONS);
xwl_output->randr_output = RROutputCreate(xwl_screen->screen, name,
strlen(name), xwl_output);
MAX_OUTPUT_NAME, xwl_output);
if (!xwl_output->randr_output) {
ErrorF("Failed creating RandR Output\n");
goto err;