x11: Trap XRandr errors when getting outputs during init and update
authorMarco Trevisan (Treviño) <mail@3v1n0.net>
Thu, 1 Jun 2023 22:23:51 +0000 (00:23 +0200)
committerMarco Trevisan (Treviño) <mail@3v1n0.net>
Thu, 1 Jun 2023 22:30:14 +0000 (00:30 +0200)
We may try to update the XRR outputs and Crtcs when they're changing in
the server, and so we may get BadRROutput that we're currently not
handling properly.

As per this, use traps and check whether we got errors, and if we did
let's ignore the current output.

It's not required to call init_randr13() again because if we got errors
it's very likely that there's a change coming that will be notified at
next iteration during which we'll repeat the init actions.

gdk/x11/gdkscreen-x11.c

index 601326515126354c41e3947cc77423c568040478..2456f14b29d703d2329f434e090cd11f6b68502b 100644 (file)
@@ -685,8 +685,13 @@ init_randr13 (GdkX11Screen *x11_screen)
   for (i = 0; i < resources->noutput; ++i)
     {
       RROutput output = resources->outputs[i];
-      XRROutputInfo *output_info =
-        XRRGetOutputInfo (x11_screen->xdisplay, resources, output);
+      XRROutputInfo *output_info;
+
+      gdk_x11_display_error_trap_push (display);
+      output_info = XRRGetOutputInfo (x11_screen->xdisplay, resources, output);
+
+      if (gdk_x11_display_error_trap_pop (display))
+        continue;
 
       if (output_info->connection == RR_Disconnected)
         {
@@ -697,13 +702,22 @@ init_randr13 (GdkX11Screen *x11_screen)
       if (output_info->crtc)
        {
          GdkX11Monitor *monitor;
-         XRRCrtcInfo *crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc);
+          XRRCrtcInfo *crtc;
           char *name;
           GdkRectangle geometry;
           GdkRectangle newgeo;
           int j;
           int refresh_rate = 0;
 
+          gdk_x11_display_error_trap_push (display);
+          crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc);
+
+          if (gdk_x11_display_error_trap_pop (display))
+            {
+              XRRFreeOutputInfo (output_info);
+              continue;
+            }
+
           for (j = 0; j < resources->nmode; j++)
             {
               XRRModeInfo *xmode = &resources->modes[j];
@@ -775,8 +789,10 @@ init_randr13 (GdkX11Screen *x11_screen)
     }
 
   x11_display->primary_monitor = 0;
+  gdk_x11_display_error_trap_push (display);
   primary_output = XRRGetOutputPrimary (x11_screen->xdisplay,
                                         x11_screen->xroot_window);
+  gdk_x11_display_error_trap_pop_ignored (display);
 
   for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (x11_display->monitors)); i++)
     {