[mutter/wip/wayland-display: 36/62] Reverse handling of XRandR events between Screen and MonitorManager



commit 2d4e4f801e30aad3ca9d6bc681418bfd6c1c037e
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Mon Jul 22 18:57:12 2013 +0200

    Reverse handling of XRandR events between Screen and MonitorManager
    
    Now MonitorManager does its own handling of XRandR events, which
    means we no longer handle ConfigureNotify on the root window.
    MetaScreen reacts to MonitorManager::monitor-changed and updates
    its internal state, including the new size.
    
    This paves the way for doing display configuration using only
    the dummy backend, which would allow testing wl_output interfaces.

 src/core/display.c               |   33 +++-------
 src/core/monitor-private.h       |    7 ++-
 src/core/monitor.c               |  129 +++++++++++++++++++++++++++-----------
 src/core/screen-private.h        |    4 -
 src/core/screen.c                |   53 +++++-----------
 src/wayland/meta-wayland-stage.c |   18 +++---
 6 files changed, 135 insertions(+), 109 deletions(-)
---
diff --git a/src/core/display.c b/src/core/display.c
index 8dff82d..47a39ff 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -2126,6 +2126,7 @@ meta_display_handle_event (MetaDisplay *display,
   gboolean bypass_compositor;
   gboolean filter_out_event;
   XIEvent *input_event;
+  MetaMonitorManager *monitor;
 
 #ifdef WITH_VERBOSE_MODE
   if (dump_events)
@@ -2135,6 +2136,14 @@ meta_display_handle_event (MetaDisplay *display,
 #ifdef HAVE_STARTUP_NOTIFICATION
   sn_display_process_event (display->sn_display, event);
 #endif
+
+  /* Intercept XRandR events early and don't attempt any
+     processing for them. We still let them through to Gdk though,
+     so it can update its own internal state.
+  */
+  monitor = meta_monitor_manager_get ();
+  if (meta_monitor_manager_handle_xevent (monitor, event))
+    return FALSE;
   
   bypass_compositor = FALSE;
   filter_out_event = FALSE;
@@ -2853,32 +2862,10 @@ meta_display_handle_event (MetaDisplay *display,
                 meta_stack_tracker_configure_event (screen->stack_tracker,
                                                     &event->xconfigure);
             }
+
           if (window && window->override_redirect)
             meta_window_configure_notify (window, &event->xconfigure);
-          else
-            /* Handle screen resize */
-            {
-              MetaScreen *screen;
 
-              screen = meta_display_screen_for_root (display,
-                                                     event->xconfigure.window);
-
-              if (screen != NULL)
-                {
-#ifdef HAVE_RANDR
-                  /* do the resize the official way */
-                  XRRUpdateConfiguration (event);
-#else
-                  /* poke around in Xlib */
-                  screen->xscreen->width   = event->xconfigure.width;
-                  screen->xscreen->height  = event->xconfigure.height;
-#endif
-             
-                  meta_screen_resize (screen, 
-                                      event->xconfigure.width,
-                                      event->xconfigure.height);
-                }
-            }
           break;
         case ConfigureRequest:
           /* This comment and code is found in both twm and fvwm */
diff --git a/src/core/monitor-private.h b/src/core/monitor-private.h
index 8c24c8d..9dcf1b4 100644
--- a/src/core/monitor-private.h
+++ b/src/core/monitor-private.h
@@ -163,6 +163,11 @@ MetaOutput         *meta_monitor_manager_get_outputs       (MetaMonitorManager *
 
 int                 meta_monitor_manager_get_primary_index (MetaMonitorManager *manager);
 
-void                meta_monitor_manager_invalidate        (MetaMonitorManager *manager);
+gboolean            meta_monitor_manager_handle_xevent     (MetaMonitorManager *manager,
+                                                            XEvent             *event);
+
+void                meta_monitor_manager_get_screen_size   (MetaMonitorManager *manager,
+                                                            int                *width,
+                                                            int                *height);
 
 #endif
diff --git a/src/core/monitor.c b/src/core/monitor.c
index 9b5421f..29a1285 100644
--- a/src/core/monitor.c
+++ b/src/core/monitor.c
@@ -57,16 +57,17 @@ enum wl_output_transform {
 #endif
 
 typedef enum {
+  META_BACKEND_UNSPECIFIED,
   META_BACKEND_DUMMY,
   META_BACKEND_XRANDR,
   META_BACKEND_COGL
-} MetaBackend;
+} MetaMonitorBackend;
 
 struct _MetaMonitorManager
 {
   GObject parent_instance;
 
-  MetaBackend backend;
+  MetaMonitorBackend backend;
 
   /* XXX: this structure is very badly
      packed, but I like the logical organization
@@ -76,6 +77,8 @@ struct _MetaMonitorManager
 
   int max_screen_width;
   int max_screen_height;
+  int screen_width;
+  int screen_height;
 
   /* Outputs refer to physical screens,
      CRTCs refer to stuff that can drive outputs
@@ -101,6 +104,8 @@ struct _MetaMonitorManager
   Display *xdisplay;
   XRRScreenResources *resources;
   int time;
+  int rr_event_base;
+  int rr_error_base;
 #endif
 
   int dbus_name_id;
@@ -126,23 +131,17 @@ make_dummy_monitor_config (MetaMonitorManager *manager)
 {
   manager->backend = META_BACKEND_DUMMY;
 
+  manager->max_screen_width = 65535;
+  manager->max_screen_height = 65535;
+  manager->screen_width = 1024;
+  manager->screen_height = 768;
+
   manager->modes = g_new0 (MetaMonitorMode, 1);
   manager->n_modes = 1;
 
   manager->modes[0].mode_id = 1;
-  if (manager->xdisplay)
-    {
-      Screen *screen = ScreenOfDisplay (manager->xdisplay,
-                                        DefaultScreen (manager->xdisplay));
-
-      manager->modes[0].width = WidthOfScreen (screen);
-      manager->modes[0].height = HeightOfScreen (screen);
-    }
-  else
-    {
-      manager->modes[0].width = 1024;
-      manager->modes[0].height = 768;
-    }
+  manager->modes[0].width = manager->screen_width;
+  manager->modes[0].height = manager->screen_height;
   manager->modes[0].refresh_rate = 60.0;
 
   manager->crtcs = g_new0 (MetaCRTC, 1);
@@ -178,9 +177,6 @@ make_dummy_monitor_config (MetaMonitorManager *manager)
   manager->outputs[0].possible_crtcs[0] = &manager->crtcs[0];
   manager->outputs[0].n_possible_clones = 0;
   manager->outputs[0].possible_clones = g_new0 (MetaOutput *, 0);
-
-  manager->max_screen_width = manager->modes[0].width;
-  manager->max_screen_height = manager->modes[0].height;
 }
 
 #ifdef HAVE_RANDR
@@ -193,6 +189,7 @@ read_monitor_infos_from_xrandr (MetaMonitorManager *manager)
     unsigned int i, j, k;
     unsigned int n_actual_outputs;
     int min_width, min_height;
+    Screen *screen;
 
     if (manager->resources)
       XRRFreeScreenResources (manager->resources);
@@ -204,12 +201,17 @@ read_monitor_infos_from_xrandr (MetaMonitorManager *manager)
                            &manager->max_screen_width,
                            &manager->max_screen_height);
 
+    screen = ScreenOfDisplay (manager->xdisplay,
+                              DefaultScreen (manager->xdisplay));
+    /* This is updated because we called RRUpdateConfiguration below */
+    manager->screen_width = WidthOfScreen (screen);
+    manager->screen_height = HeightOfScreen (screen);
+
     resources = XRRGetScreenResourcesCurrent (manager->xdisplay,
                                               DefaultRootWindow (manager->xdisplay));
     if (!resources)
       return make_dummy_monitor_config (manager);
 
-    manager->backend = META_BACKEND_XRANDR;
     manager->resources = resources;
     manager->time = resources->configTimestamp;
     manager->n_outputs = resources->noutput;
@@ -432,8 +434,6 @@ read_monitor_infos_from_cogl (MetaMonitorManager *manager)
   if (output_list == NULL)
     return make_dummy_monitor_config (manager);
 
-  manager->backend = META_BACKEND_COGL;
-
   n = g_list_length (output_list);
   modes = g_array_new (FALSE, TRUE, sizeof (MetaMonitorMode));
   crtcs = g_array_sized_new (FALSE, TRUE, sizeof (MetaCRTC), n);
@@ -527,7 +527,7 @@ has_dummy_output (void)
   compositor = meta_wayland_compositor_get_default ();
   return !meta_wayland_compositor_is_native (compositor);
 #else
-  return FALSE
+  return FALSE;
 #endif
 }
 
@@ -536,7 +536,7 @@ meta_monitor_manager_init (MetaMonitorManager *manager)
 {
 }
 
-static gboolean
+static MetaMonitorBackend
 make_debug_config (MetaMonitorManager *manager)
 {
   const char *env;
@@ -544,17 +544,17 @@ make_debug_config (MetaMonitorManager *manager)
   env = g_getenv ("META_DEBUG_MULTIMONITOR");
 
   if (env == NULL)
-    return FALSE;
+    return META_BACKEND_UNSPECIFIED;
 
 #ifdef HAVE_RANDR
   if (strcmp (env, "xrandr") == 0)
-    read_monitor_infos_from_xrandr (manager);
+    return META_BACKEND_XRANDR;
   else
 #endif
     if (strcmp (env, "cogl") == 0)
-      read_monitor_infos_from_cogl (manager);
+      return META_BACKEND_COGL;
     else
-      make_dummy_monitor_config (manager);
+      return META_BACKEND_DUMMY;
 
   return TRUE;
 }
@@ -562,18 +562,15 @@ make_debug_config (MetaMonitorManager *manager)
 static void
 read_current_config (MetaMonitorManager *manager)
 {
-  if (make_debug_config (manager))
-    return;
-
-  if (has_dummy_output ())
-    return make_dummy_monitor_config (manager);
-
 #ifdef HAVE_RANDR
-  if (!meta_is_display_server ())
+  if (manager->backend == META_BACKEND_XRANDR)
     return read_monitor_infos_from_xrandr (manager);
 #endif
 
-  return read_monitor_infos_from_cogl (manager);
+  if (manager->backend == META_BACKEND_COGL)
+    return read_monitor_infos_from_cogl (manager);
+  else
+    return make_dummy_monitor_config (manager);
 }
 
 /*
@@ -680,6 +677,42 @@ meta_monitor_manager_new (Display *display)
 
   manager->xdisplay = display;
 
+  manager->backend = make_debug_config (manager);
+
+  if (manager->backend == META_BACKEND_UNSPECIFIED)
+    {
+#ifdef HAVE_XRANDR
+      if (display)
+        manager->backend = META_BACKEND_XRANDR;
+      else
+#endif
+        if (has_dummy_output ())
+          manager->backend = META_BACKEND_DUMMY;
+        else
+          manager->backend = META_BACKEND_COGL;
+    }
+
+#ifdef HAVE_XRANDR
+  if (manager->backend == META_BACKEND_XRANDR)
+    {
+      if (!XRRQueryExtension (display,
+                              &manager->rr_event_base,
+                              &manager->rr_error_base))
+        {
+          manager->backend = META_BACKEND_DUMMY;
+        }
+      else
+        {
+          /* We only use ScreenChangeNotify, but GDK uses the others,
+             and we don't want to step on its toes */
+          XRRSelectInput (display, DefaultRootWindow (display),
+                          RRScreenChangeNotifyMask
+                          | RRCrtcChangeNotifyMask
+                          | RROutputPropertyNotifyMask);
+        }
+    }
+#endif
+
   read_current_config (manager);
   make_logical_config (manager);
   return manager;
@@ -1265,7 +1298,17 @@ meta_monitor_manager_get_primary_index (MetaMonitorManager *manager)
 }
 
 void
-meta_monitor_manager_invalidate (MetaMonitorManager *manager)
+meta_monitor_manager_get_screen_size (MetaMonitorManager *manager,
+                                      int                *width,
+                                      int                *height)
+{
+  *width = manager->screen_width;
+  *height = manager->screen_height;
+}
+
+gboolean
+meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
+                                    XEvent             *event)
 {
   MetaOutput *old_outputs;
   MetaCRTC *old_crtcs;
@@ -1273,6 +1316,15 @@ meta_monitor_manager_invalidate (MetaMonitorManager *manager)
   MetaMonitorMode *old_modes;
   int n_old_outputs;
 
+  if (manager->backend != META_BACKEND_XRANDR)
+    return FALSE;
+
+#ifdef HAVE_RANDR
+  if ((event->type - manager->rr_event_base) != RRScreenChangeNotify)
+    return FALSE;
+
+  XRRUpdateConfiguration (event);
+
   /* Save the old structures, so they stay valid during the update */
   old_outputs = manager->outputs;
   n_old_outputs = manager->n_outputs;
@@ -1290,5 +1342,10 @@ meta_monitor_manager_invalidate (MetaMonitorManager *manager)
   free_output_array (old_outputs, n_old_outputs);
   g_free (old_modes);
   g_free (old_crtcs);
+
+  return TRUE;
+#else
+  return FALSE;
+#endif
 }
 
diff --git a/src/core/screen-private.h b/src/core/screen-private.h
index 7bdcf9a..7b322ae 100644
--- a/src/core/screen-private.h
+++ b/src/core/screen-private.h
@@ -219,10 +219,6 @@ void meta_screen_calc_workspace_layout (MetaScreen          *screen,
                                         MetaWorkspaceLayout *layout);
 void meta_screen_free_workspace_layout (MetaWorkspaceLayout *layout);
 
-void meta_screen_resize (MetaScreen *screen,
-                         int         width,
-                         int         height);
-
 void     meta_screen_minimize_all_on_active_workspace_except (MetaScreen *screen,
                                                               MetaWindow *keep);
 
diff --git a/src/core/screen.c b/src/core/screen.c
index 67cb161..a943ac0 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -516,9 +516,7 @@ meta_screen_new (MetaDisplay *display,
   char buf[128];
   guint32 manager_timestamp;
   gulong current_workspace;
-#ifdef HAVE_WAYLAND
-  MetaWaylandCompositor *compositor = NULL;
-#endif
+  MetaMonitorManager *manager;
   
   replace_current_wm = meta_get_replace_current_wm ();
   
@@ -679,18 +677,17 @@ meta_screen_new (MetaDisplay *display,
   screen->rect.x = screen->rect.y = 0;
   
 #ifdef HAVE_WAYLAND
-  if (meta_is_display_server ())
-    {
-      compositor = meta_wayland_compositor_get_default ();
-      screen->rect.width = clutter_actor_get_width (compositor->stage);
-      screen->rect.height = clutter_actor_get_height (compositor->stage);
-    }
-  else
+  if (!meta_is_display_server ())
 #endif
-    {
-      screen->rect.width = WidthOfScreen (screen->xscreen);
-      screen->rect.height = HeightOfScreen (screen->xscreen);
-    }
+    meta_monitor_manager_initialize (screen->display->xdisplay);
+
+  manager = meta_monitor_manager_get ();
+  g_signal_connect (manager, "monitors-changed",
+                    G_CALLBACK (on_monitors_changed), screen);
+
+  meta_monitor_manager_get_screen_size (manager,
+                                        &screen->rect.width,
+                                        &screen->rect.height);
 
   screen->current_cursor = -1; /* invalid/unset */
   screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
@@ -716,18 +713,7 @@ meta_screen_new (MetaDisplay *display,
   screen->compositor_data = NULL;
   screen->guard_window = None;
 
-  {
-    MetaMonitorManager *manager;
-
-    if (!meta_is_display_server ())
-      meta_monitor_manager_initialize (screen->display->xdisplay);
-
-    reload_monitor_infos (screen);
-
-    manager = meta_monitor_manager_get ();
-    g_signal_connect (manager, "monitors-changed",
-                      G_CALLBACK (on_monitors_changed), screen);
-  }
+  reload_monitor_infos (screen);
   
   meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
 
@@ -2833,23 +2819,16 @@ meta_screen_resize_func (MetaScreen *screen,
   meta_window_recalc_features (window);
 }
 
-void
-meta_screen_resize (MetaScreen *screen,
-                    int         width,
-                    int         height)
-{
-  screen->rect.width = width;
-  screen->rect.height = height;
-
-  meta_monitor_manager_invalidate (meta_monitor_manager_get ());
-}
-
 static void
 on_monitors_changed (MetaMonitorManager *manager,
                      MetaScreen         *screen)
 {
   GSList *tmp, *windows;
 
+  meta_monitor_manager_get_screen_size (manager,
+                                        &screen->rect.width,
+                                        &screen->rect.height);
+
   reload_monitor_infos (screen);
   set_desktop_geometry_hint (screen);
 
diff --git a/src/wayland/meta-wayland-stage.c b/src/wayland/meta-wayland-stage.c
index cbcfccb..20cb386 100644
--- a/src/wayland/meta-wayland-stage.c
+++ b/src/wayland/meta-wayland-stage.c
@@ -248,17 +248,19 @@ void
 meta_wayland_stage_apply_monitor_config (MetaWaylandStage *stage)
 {
   MetaMonitorManager *manager;
-  MetaMonitorInfo *infos;
-  int n_infos;
+  int width, height;
 
   manager = meta_monitor_manager_get ();
-  infos = meta_monitor_manager_get_monitor_infos (manager, &n_infos);
-
-  g_assert (n_infos == 1 || g_getenv ("META_DEBUG_MULTIMONITOR"));
+  meta_monitor_manager_get_screen_size (manager, &width, &height);
 
   /* FIXME: when we support a sliced stage, this is the place to do it
      But! This is not the place to apply KMS config, here we only
-     notify Clutter/Cogl/GL that the framebuffer sizes changed */
-  clutter_actor_set_size (CLUTTER_ACTOR (stage),
-                         infos[0].rect.width, infos[0].rect.height);
+     notify Clutter/Cogl/GL that the framebuffer sizes changed.
+
+     And because for now clutter does not do sliced, we use one
+     framebuffer the size of the whole screen, and when running on
+     bare metal MetaMonitorManager will do the necessary tricks to
+     show the right portions on the right screens.
+  */
+  clutter_actor_set_size (CLUTTER_ACTOR (stage), width, height);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]