@@ -243,7 +243,96 @@ SDL_PixelFormat X11_GetPixelFormatFromVisualInfo(Display *display, XVisualInfo *
243
243
return SDL_PIXELFORMAT_UNKNOWN ;
244
244
}
245
245
246
+ static SDL_DisplayID X11_AddGenericDisplay (SDL_VideoDevice * _this , bool send_event )
247
+ {
248
+ // !!! FIXME: a lot of copy/paste from X11_InitModes_XRandR in this function.
249
+ SDL_VideoData * data = _this -> internal ;
250
+ Display * dpy = data -> display ;
251
+ const int default_screen = DefaultScreen (dpy );
252
+ Screen * screen = ScreenOfDisplay (dpy , default_screen );
253
+ int scanline_pad , n , i ;
254
+ SDL_DisplayModeData * modedata ;
255
+ SDL_DisplayData * displaydata ;
256
+ SDL_DisplayMode mode ;
257
+ XPixmapFormatValues * pixmapformats ;
258
+ Uint32 pixelformat ;
259
+ XVisualInfo vinfo ;
260
+ SDL_VideoDisplay display ;
261
+
262
+ // note that generally even if you have a multiple physical monitors, ScreenCount(dpy) still only reports ONE screen.
263
+
264
+ if (!get_visualinfo (dpy , default_screen , & vinfo )) {
265
+ return SDL_SetError ("Failed to find an X11 visual for the primary display" );
266
+ }
267
+
268
+ pixelformat = X11_GetPixelFormatFromVisualInfo (dpy , & vinfo );
269
+ if (SDL_ISPIXELFORMAT_INDEXED (pixelformat )) {
270
+ return SDL_SetError ("Palettized video modes are no longer supported" );
271
+ }
272
+
273
+ SDL_zero (mode );
274
+ mode .w = WidthOfScreen (screen );
275
+ mode .h = HeightOfScreen (screen );
276
+ mode .format = pixelformat ;
277
+
278
+ displaydata = (SDL_DisplayData * )SDL_calloc (1 , sizeof (* displaydata ));
279
+ if (!displaydata ) {
280
+ return false;
281
+ }
282
+
283
+ modedata = (SDL_DisplayModeData * )SDL_calloc (1 , sizeof (SDL_DisplayModeData ));
284
+ if (!modedata ) {
285
+ SDL_free (displaydata );
286
+ return false;
287
+ }
288
+ mode .internal = modedata ;
289
+
290
+ displaydata -> screen = default_screen ;
291
+ displaydata -> visual = vinfo .visual ;
292
+ displaydata -> depth = vinfo .depth ;
293
+
294
+ scanline_pad = SDL_BYTESPERPIXEL (pixelformat ) * 8 ;
295
+ pixmapformats = X11_XListPixmapFormats (dpy , & n );
296
+ if (pixmapformats ) {
297
+ for (i = 0 ; i < n ; ++ i ) {
298
+ if (pixmapformats [i ].depth == vinfo .depth ) {
299
+ scanline_pad = pixmapformats [i ].scanline_pad ;
300
+ break ;
301
+ }
302
+ }
303
+ X11_XFree (pixmapformats );
304
+ }
305
+
306
+ displaydata -> scanline_pad = scanline_pad ;
307
+ displaydata -> x = 0 ;
308
+ displaydata -> y = 0 ;
309
+ displaydata -> use_xrandr = false;
310
+
311
+ SDL_zero (display );
312
+ display .name = (char * )"Generic X11 Display" ; /* this is just copied and thrown away, it's safe to cast to char* here. */
313
+ display .desktop_mode = mode ;
314
+ display .internal = displaydata ;
315
+ display .content_scale = X11_GetGlobalContentScale (_this );
316
+ return SDL_AddVideoDisplay (& display , send_event );
317
+ }
318
+
246
319
#ifdef SDL_VIDEO_DRIVER_X11_XRANDR
320
+
321
+ static void X11_RemoveGenericDisplay (SDL_VideoDevice * _this )
322
+ {
323
+ SDL_DisplayID * displays = SDL_GetDisplays (NULL );
324
+ if (displays ) {
325
+ for (int i = 0 ; displays [i ]; ++ i ) {
326
+ SDL_VideoDisplay * display = SDL_GetVideoDisplay (displays [i ]);
327
+ const SDL_DisplayData * displaydata = display -> internal ;
328
+ if (!displaydata -> xrandr_output ) {
329
+ SDL_DelVideoDisplay (displays [i ], true);
330
+ }
331
+ }
332
+ SDL_free (displays );
333
+ }
334
+ }
335
+
247
336
static bool CheckXRandR (Display * display , int * major , int * minor )
248
337
{
249
338
// Default the extension not available
@@ -525,10 +614,17 @@ static bool X11_AddXRandRDisplay(SDL_VideoDevice *_this, Display *dpy, int scree
525
614
return true; // failed to query data, skip this display
526
615
}
527
616
528
- if (SDL_AddVideoDisplay (& display , send_event ) == 0 ) {
617
+ SDL_DisplayID displayID = SDL_AddVideoDisplay (& display , false);
618
+ if (displayID == 0 ) {
529
619
return false;
530
620
}
531
621
622
+ // We added an XRandR display, remove the generic display, if any
623
+ X11_RemoveGenericDisplay (_this );
624
+
625
+ if (send_event ) {
626
+ SDL_SendDisplayEvent (SDL_GetVideoDisplay (displayID ), SDL_EVENT_DISPLAY_ADDED , 0 , 0 );
627
+ }
532
628
return true;
533
629
}
534
630
@@ -592,7 +688,7 @@ static void X11_CheckDisplaysMoved(SDL_VideoDevice *_this, Display *dpy)
592
688
for (int i = 0 ; displays [i ]; ++ i ) {
593
689
SDL_VideoDisplay * display = SDL_GetVideoDisplay (displays [i ]);
594
690
const SDL_DisplayData * displaydata = display -> internal ;
595
- if (displaydata -> screen == screen ) {
691
+ if (displaydata -> xrandr_output && displaydata -> screen == screen ) {
596
692
X11_UpdateXRandRDisplay (_this , dpy , screen , displaydata -> xrandr_output , res , display );
597
693
}
598
694
}
@@ -638,8 +734,12 @@ static void X11_CheckDisplaysRemoved(SDL_VideoDevice *_this, Display *dpy)
638
734
639
735
for (int i = 0 ; i < num_displays ; ++ i ) {
640
736
if (displays [i ]) {
641
- // This display wasn't in the XRandR list
642
- SDL_DelVideoDisplay (displays [i ], true);
737
+ SDL_VideoDisplay * display = SDL_GetVideoDisplay (displays [i ]);
738
+ const SDL_DisplayData * displaydata = display -> internal ;
739
+ if (displaydata -> xrandr_output ) {
740
+ // This display wasn't in the XRandR list
741
+ SDL_DelVideoDisplay (displays [i ], true);
742
+ }
643
743
}
644
744
}
645
745
SDL_free (displays );
@@ -673,7 +773,17 @@ static void X11_HandleXRandROutputChange(SDL_VideoDevice *_this, const XRROutput
673
773
674
774
if (ev -> connection == RR_Disconnected ) { // output is going away
675
775
if (display ) {
776
+ // Add the generic display if we're about to remove the last XRandR display
777
+ SDL_DisplayID generic_display = 0 ;
778
+ if (_this -> num_displays == 1 ) {
779
+ generic_display = X11_AddGenericDisplay (_this , false);
780
+ }
781
+
676
782
SDL_DelVideoDisplay (display -> id , true);
783
+
784
+ if (generic_display ) {
785
+ SDL_SendDisplayEvent (SDL_GetVideoDisplay (generic_display ), SDL_EVENT_DISPLAY_ADDED , 0 , 0 );
786
+ }
677
787
}
678
788
X11_CheckDisplaysMoved (_this , ev -> display );
679
789
@@ -813,75 +923,7 @@ static bool X11_InitModes_XRandR(SDL_VideoDevice *_this)
813
923
enumerate the current displays and their current sizes. */
814
924
static bool X11_InitModes_StdXlib (SDL_VideoDevice * _this )
815
925
{
816
- // !!! FIXME: a lot of copy/paste from X11_InitModes_XRandR in this function.
817
- SDL_VideoData * data = _this -> internal ;
818
- Display * dpy = data -> display ;
819
- const int default_screen = DefaultScreen (dpy );
820
- Screen * screen = ScreenOfDisplay (dpy , default_screen );
821
- int scanline_pad , n , i ;
822
- SDL_DisplayModeData * modedata ;
823
- SDL_DisplayData * displaydata ;
824
- SDL_DisplayMode mode ;
825
- XPixmapFormatValues * pixmapformats ;
826
- Uint32 pixelformat ;
827
- XVisualInfo vinfo ;
828
- SDL_VideoDisplay display ;
829
-
830
- // note that generally even if you have a multiple physical monitors, ScreenCount(dpy) still only reports ONE screen.
831
-
832
- if (!get_visualinfo (dpy , default_screen , & vinfo )) {
833
- return SDL_SetError ("Failed to find an X11 visual for the primary display" );
834
- }
835
-
836
- pixelformat = X11_GetPixelFormatFromVisualInfo (dpy , & vinfo );
837
- if (SDL_ISPIXELFORMAT_INDEXED (pixelformat )) {
838
- return SDL_SetError ("Palettized video modes are no longer supported" );
839
- }
840
-
841
- SDL_zero (mode );
842
- mode .w = WidthOfScreen (screen );
843
- mode .h = HeightOfScreen (screen );
844
- mode .format = pixelformat ;
845
-
846
- displaydata = (SDL_DisplayData * )SDL_calloc (1 , sizeof (* displaydata ));
847
- if (!displaydata ) {
848
- return false;
849
- }
850
-
851
- modedata = (SDL_DisplayModeData * )SDL_calloc (1 , sizeof (SDL_DisplayModeData ));
852
- if (!modedata ) {
853
- SDL_free (displaydata );
854
- return false;
855
- }
856
- mode .internal = modedata ;
857
-
858
- displaydata -> screen = default_screen ;
859
- displaydata -> visual = vinfo .visual ;
860
- displaydata -> depth = vinfo .depth ;
861
-
862
- scanline_pad = SDL_BYTESPERPIXEL (pixelformat ) * 8 ;
863
- pixmapformats = X11_XListPixmapFormats (dpy , & n );
864
- if (pixmapformats ) {
865
- for (i = 0 ; i < n ; ++ i ) {
866
- if (pixmapformats [i ].depth == vinfo .depth ) {
867
- scanline_pad = pixmapformats [i ].scanline_pad ;
868
- break ;
869
- }
870
- }
871
- X11_XFree (pixmapformats );
872
- }
873
-
874
- displaydata -> scanline_pad = scanline_pad ;
875
- displaydata -> x = 0 ;
876
- displaydata -> y = 0 ;
877
- displaydata -> use_xrandr = false;
878
-
879
- SDL_zero (display );
880
- display .name = (char * )"Generic X11 Display" ; /* this is just copied and thrown away, it's safe to cast to char* here. */
881
- display .desktop_mode = mode ;
882
- display .internal = displaydata ;
883
- display .content_scale = X11_GetGlobalContentScale (_this );
884
- if (SDL_AddVideoDisplay (& display , true) == 0 ) {
926
+ if (X11_AddGenericDisplay (_this , true) == 0 ) {
885
927
return false;
886
928
}
887
929
return true;
0 commit comments