|
@@ -243,7 +243,96 @@ SDL_PixelFormat X11_GetPixelFormatFromVisualInfo(Display *display, XVisualInfo *
|
|
|
return SDL_PIXELFORMAT_UNKNOWN;
|
|
|
}
|
|
|
|
|
|
+static SDL_DisplayID X11_AddGenericDisplay(SDL_VideoDevice *_this, bool send_event)
|
|
|
+{
|
|
|
+ // !!! FIXME: a lot of copy/paste from X11_InitModes_XRandR in this function.
|
|
|
+ SDL_VideoData *data = _this->internal;
|
|
|
+ Display *dpy = data->display;
|
|
|
+ const int default_screen = DefaultScreen(dpy);
|
|
|
+ Screen *screen = ScreenOfDisplay(dpy, default_screen);
|
|
|
+ int scanline_pad, n, i;
|
|
|
+ SDL_DisplayModeData *modedata;
|
|
|
+ SDL_DisplayData *displaydata;
|
|
|
+ SDL_DisplayMode mode;
|
|
|
+ XPixmapFormatValues *pixmapformats;
|
|
|
+ Uint32 pixelformat;
|
|
|
+ XVisualInfo vinfo;
|
|
|
+ SDL_VideoDisplay display;
|
|
|
+
|
|
|
+ // note that generally even if you have a multiple physical monitors, ScreenCount(dpy) still only reports ONE screen.
|
|
|
+
|
|
|
+ if (!get_visualinfo(dpy, default_screen, &vinfo)) {
|
|
|
+ return SDL_SetError("Failed to find an X11 visual for the primary display");
|
|
|
+ }
|
|
|
+
|
|
|
+ pixelformat = X11_GetPixelFormatFromVisualInfo(dpy, &vinfo);
|
|
|
+ if (SDL_ISPIXELFORMAT_INDEXED(pixelformat)) {
|
|
|
+ return SDL_SetError("Palettized video modes are no longer supported");
|
|
|
+ }
|
|
|
+
|
|
|
+ SDL_zero(mode);
|
|
|
+ mode.w = WidthOfScreen(screen);
|
|
|
+ mode.h = HeightOfScreen(screen);
|
|
|
+ mode.format = pixelformat;
|
|
|
+
|
|
|
+ displaydata = (SDL_DisplayData *)SDL_calloc(1, sizeof(*displaydata));
|
|
|
+ if (!displaydata) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ modedata = (SDL_DisplayModeData *)SDL_calloc(1, sizeof(SDL_DisplayModeData));
|
|
|
+ if (!modedata) {
|
|
|
+ SDL_free(displaydata);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ mode.internal = modedata;
|
|
|
+
|
|
|
+ displaydata->screen = default_screen;
|
|
|
+ displaydata->visual = vinfo.visual;
|
|
|
+ displaydata->depth = vinfo.depth;
|
|
|
+
|
|
|
+ scanline_pad = SDL_BYTESPERPIXEL(pixelformat) * 8;
|
|
|
+ pixmapformats = X11_XListPixmapFormats(dpy, &n);
|
|
|
+ if (pixmapformats) {
|
|
|
+ for (i = 0; i < n; ++i) {
|
|
|
+ if (pixmapformats[i].depth == vinfo.depth) {
|
|
|
+ scanline_pad = pixmapformats[i].scanline_pad;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ X11_XFree(pixmapformats);
|
|
|
+ }
|
|
|
+
|
|
|
+ displaydata->scanline_pad = scanline_pad;
|
|
|
+ displaydata->x = 0;
|
|
|
+ displaydata->y = 0;
|
|
|
+ displaydata->use_xrandr = false;
|
|
|
+
|
|
|
+ SDL_zero(display);
|
|
|
+ display.name = (char *)"Generic X11 Display"; /* this is just copied and thrown away, it's safe to cast to char* here. */
|
|
|
+ display.desktop_mode = mode;
|
|
|
+ display.internal = displaydata;
|
|
|
+ display.content_scale = X11_GetGlobalContentScale(_this);
|
|
|
+ return SDL_AddVideoDisplay(&display, send_event);
|
|
|
+}
|
|
|
+
|
|
|
#ifdef SDL_VIDEO_DRIVER_X11_XRANDR
|
|
|
+
|
|
|
+static void X11_RemoveGenericDisplay(SDL_VideoDevice *_this)
|
|
|
+{
|
|
|
+ SDL_DisplayID *displays = SDL_GetDisplays(NULL);
|
|
|
+ if (displays) {
|
|
|
+ for (int i = 0; displays[i]; ++i) {
|
|
|
+ SDL_VideoDisplay *display = SDL_GetVideoDisplay(displays[i]);
|
|
|
+ const SDL_DisplayData *displaydata = display->internal;
|
|
|
+ if (!displaydata->xrandr_output) {
|
|
|
+ SDL_DelVideoDisplay(displays[i], true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ SDL_free(displays);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static bool CheckXRandR(Display *display, int *major, int *minor)
|
|
|
{
|
|
|
// Default the extension not available
|
|
@@ -525,10 +614,17 @@ static bool X11_AddXRandRDisplay(SDL_VideoDevice *_this, Display *dpy, int scree
|
|
|
return true; // failed to query data, skip this display
|
|
|
}
|
|
|
|
|
|
- if (SDL_AddVideoDisplay(&display, send_event) == 0) {
|
|
|
+ SDL_DisplayID displayID = SDL_AddVideoDisplay(&display, false);
|
|
|
+ if (displayID == 0) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ // We added an XRandR display, remove the generic display, if any
|
|
|
+ X11_RemoveGenericDisplay(_this);
|
|
|
+
|
|
|
+ if (send_event) {
|
|
|
+ SDL_SendDisplayEvent(SDL_GetVideoDisplay(displayID), SDL_EVENT_DISPLAY_ADDED, 0, 0);
|
|
|
+ }
|
|
|
return true;
|
|
|
}
|
|
|
|
|
@@ -592,7 +688,7 @@ static void X11_CheckDisplaysMoved(SDL_VideoDevice *_this, Display *dpy)
|
|
|
for (int i = 0; displays[i]; ++i) {
|
|
|
SDL_VideoDisplay *display = SDL_GetVideoDisplay(displays[i]);
|
|
|
const SDL_DisplayData *displaydata = display->internal;
|
|
|
- if (displaydata->screen == screen) {
|
|
|
+ if (displaydata->xrandr_output && displaydata->screen == screen) {
|
|
|
X11_UpdateXRandRDisplay(_this, dpy, screen, displaydata->xrandr_output, res, display);
|
|
|
}
|
|
|
}
|
|
@@ -638,8 +734,12 @@ static void X11_CheckDisplaysRemoved(SDL_VideoDevice *_this, Display *dpy)
|
|
|
|
|
|
for (int i = 0; i < num_displays; ++i) {
|
|
|
if (displays[i]) {
|
|
|
- // This display wasn't in the XRandR list
|
|
|
- SDL_DelVideoDisplay(displays[i], true);
|
|
|
+ SDL_VideoDisplay *display = SDL_GetVideoDisplay(displays[i]);
|
|
|
+ const SDL_DisplayData *displaydata = display->internal;
|
|
|
+ if (displaydata->xrandr_output) {
|
|
|
+ // This display wasn't in the XRandR list
|
|
|
+ SDL_DelVideoDisplay(displays[i], true);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
SDL_free(displays);
|
|
@@ -673,7 +773,17 @@ static void X11_HandleXRandROutputChange(SDL_VideoDevice *_this, const XRROutput
|
|
|
|
|
|
if (ev->connection == RR_Disconnected) { // output is going away
|
|
|
if (display) {
|
|
|
+ // Add the generic display if we're about to remove the last XRandR display
|
|
|
+ SDL_DisplayID generic_display = 0;
|
|
|
+ if (_this->num_displays == 1) {
|
|
|
+ generic_display = X11_AddGenericDisplay(_this, false);
|
|
|
+ }
|
|
|
+
|
|
|
SDL_DelVideoDisplay(display->id, true);
|
|
|
+
|
|
|
+ if (generic_display) {
|
|
|
+ SDL_SendDisplayEvent(SDL_GetVideoDisplay(generic_display), SDL_EVENT_DISPLAY_ADDED, 0, 0);
|
|
|
+ }
|
|
|
}
|
|
|
X11_CheckDisplaysMoved(_this, ev->display);
|
|
|
|
|
@@ -813,75 +923,7 @@ static bool X11_InitModes_XRandR(SDL_VideoDevice *_this)
|
|
|
enumerate the current displays and their current sizes. */
|
|
|
static bool X11_InitModes_StdXlib(SDL_VideoDevice *_this)
|
|
|
{
|
|
|
- // !!! FIXME: a lot of copy/paste from X11_InitModes_XRandR in this function.
|
|
|
- SDL_VideoData *data = _this->internal;
|
|
|
- Display *dpy = data->display;
|
|
|
- const int default_screen = DefaultScreen(dpy);
|
|
|
- Screen *screen = ScreenOfDisplay(dpy, default_screen);
|
|
|
- int scanline_pad, n, i;
|
|
|
- SDL_DisplayModeData *modedata;
|
|
|
- SDL_DisplayData *displaydata;
|
|
|
- SDL_DisplayMode mode;
|
|
|
- XPixmapFormatValues *pixmapformats;
|
|
|
- Uint32 pixelformat;
|
|
|
- XVisualInfo vinfo;
|
|
|
- SDL_VideoDisplay display;
|
|
|
-
|
|
|
- // note that generally even if you have a multiple physical monitors, ScreenCount(dpy) still only reports ONE screen.
|
|
|
-
|
|
|
- if (!get_visualinfo(dpy, default_screen, &vinfo)) {
|
|
|
- return SDL_SetError("Failed to find an X11 visual for the primary display");
|
|
|
- }
|
|
|
-
|
|
|
- pixelformat = X11_GetPixelFormatFromVisualInfo(dpy, &vinfo);
|
|
|
- if (SDL_ISPIXELFORMAT_INDEXED(pixelformat)) {
|
|
|
- return SDL_SetError("Palettized video modes are no longer supported");
|
|
|
- }
|
|
|
-
|
|
|
- SDL_zero(mode);
|
|
|
- mode.w = WidthOfScreen(screen);
|
|
|
- mode.h = HeightOfScreen(screen);
|
|
|
- mode.format = pixelformat;
|
|
|
-
|
|
|
- displaydata = (SDL_DisplayData *)SDL_calloc(1, sizeof(*displaydata));
|
|
|
- if (!displaydata) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- modedata = (SDL_DisplayModeData *)SDL_calloc(1, sizeof(SDL_DisplayModeData));
|
|
|
- if (!modedata) {
|
|
|
- SDL_free(displaydata);
|
|
|
- return false;
|
|
|
- }
|
|
|
- mode.internal = modedata;
|
|
|
-
|
|
|
- displaydata->screen = default_screen;
|
|
|
- displaydata->visual = vinfo.visual;
|
|
|
- displaydata->depth = vinfo.depth;
|
|
|
-
|
|
|
- scanline_pad = SDL_BYTESPERPIXEL(pixelformat) * 8;
|
|
|
- pixmapformats = X11_XListPixmapFormats(dpy, &n);
|
|
|
- if (pixmapformats) {
|
|
|
- for (i = 0; i < n; ++i) {
|
|
|
- if (pixmapformats[i].depth == vinfo.depth) {
|
|
|
- scanline_pad = pixmapformats[i].scanline_pad;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- X11_XFree(pixmapformats);
|
|
|
- }
|
|
|
-
|
|
|
- displaydata->scanline_pad = scanline_pad;
|
|
|
- displaydata->x = 0;
|
|
|
- displaydata->y = 0;
|
|
|
- displaydata->use_xrandr = false;
|
|
|
-
|
|
|
- SDL_zero(display);
|
|
|
- display.name = (char *)"Generic X11 Display"; /* this is just copied and thrown away, it's safe to cast to char* here. */
|
|
|
- display.desktop_mode = mode;
|
|
|
- display.internal = displaydata;
|
|
|
- display.content_scale = X11_GetGlobalContentScale(_this);
|
|
|
- if (SDL_AddVideoDisplay(&display, true) == 0) {
|
|
|
+ if (X11_AddGenericDisplay(_this, true) == 0) {
|
|
|
return false;
|
|
|
}
|
|
|
return true;
|