From 47867eb45b7e1004974c6f0adba2342253ac65f9 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Fri, 18 Oct 2024 11:26:41 -0400 Subject: [PATCH] x11: Support sorting displays via the priority hint Store the connector name for displays and use it for sorting them according to priority, if the hint is set. --- include/SDL3/SDL_hints.h | 1 + src/video/x11/SDL_x11modes.c | 49 ++++++++++++++++++++++++++++++++++++ src/video/x11/SDL_x11modes.h | 1 + 3 files changed, 51 insertions(+) diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 3afd1a5676344..e097ce072f233 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -3158,6 +3158,7 @@ extern "C" { * * - KMSDRM (kmsdrm) * - Wayland (wayland) + * - X11 (x11) * * This hint should be set before SDL is initialized. * diff --git a/src/video/x11/SDL_x11modes.c b/src/video/x11/SDL_x11modes.c index 1194af2c0e9de..f2170c4ba6f5c 100644 --- a/src/video/x11/SDL_x11modes.c +++ b/src/video/x11/SDL_x11modes.c @@ -623,6 +623,7 @@ static bool X11_FillXRandRDisplayInfo(SDL_VideoDevice *_this, Display *dpy, int displaydata->y = display_y; displaydata->use_xrandr = true; displaydata->xrandr_output = outputid; + SDL_strlcpy(displaydata->connector_name, display_name, sizeof(displaydata->connector_name)); SetXRandRModeInfo(dpy, res, output_crtc, modeID, &mode); SetXRandRDisplayName(dpy, EDID, display_name, display_name_size, outputid, display_mm_width, display_mm_height); @@ -751,6 +752,52 @@ void X11_HandleXRandREvent(SDL_VideoDevice *_this, const XEvent *xevent) } } +static void X11_SortOutputsByPriorityHint(SDL_VideoDevice *_this) +{ + const char *name_hint = SDL_GetHint(SDL_HINT_VIDEO_DISPLAY_PRIORITY); + + if (name_hint) { + char *saveptr; + char *str = SDL_strdup(name_hint); + SDL_VideoDisplay **sorted_list = SDL_malloc(sizeof(SDL_VideoDisplay *) * _this->num_displays); + + if (str && sorted_list) { + int sorted_index = 0; + + // Sort the requested displays to the front of the list. + const char *token = SDL_strtok_r(str, ",", &saveptr); + while (token) { + for (int i = 0; i < _this->num_displays; ++i) { + SDL_VideoDisplay *d = _this->displays[i]; + if (d) { + SDL_DisplayData *data = d->internal; + if (SDL_strcmp(token, data->connector_name) == 0) { + sorted_list[sorted_index++] = d; + _this->displays[i] = NULL; + break; + } + } + } + + token = SDL_strtok_r(NULL, ",", &saveptr); + } + + // Append the remaining displays to the end of the list. + for (int i = 0; i < _this->num_displays; ++i) { + if (_this->displays[i]) { + sorted_list[sorted_index++] = _this->displays[i]; + } + } + + // Copy the sorted list back to the display list. + SDL_memcpy(_this->displays, sorted_list, sizeof(SDL_VideoDisplay *) * _this->num_displays); + } + + SDL_free(str); + SDL_free(sorted_list); + } +} + static bool X11_InitModes_XRandR(SDL_VideoDevice *_this) { SDL_VideoData *data = _this->internal; @@ -810,6 +857,8 @@ static bool X11_InitModes_XRandR(SDL_VideoDevice *_this) return SDL_SetError("No available displays"); } + X11_SortOutputsByPriorityHint(_this); + return true; } #endif // SDL_VIDEO_DRIVER_X11_XRANDR diff --git a/src/video/x11/SDL_x11modes.h b/src/video/x11/SDL_x11modes.h index 4c250b6a72cb0..d8a92032bd1d5 100644 --- a/src/video/x11/SDL_x11modes.h +++ b/src/video/x11/SDL_x11modes.h @@ -38,6 +38,7 @@ struct SDL_DisplayData #ifdef SDL_VIDEO_DRIVER_X11_XRANDR RROutput xrandr_output; + char connector_name[16]; #endif };