[mutter/wip/wayland-work: 41/42] MonitorKms: add hotplug support



commit b86471458a34e55397c9293d9cddf5054cc175d0
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Sat Sep 14 17:55:18 2013 +0200

    MonitorKms: add hotplug support
    
    Use GUdev to listen to the kernel events which are emitted when
    monitors are hotplugged and hotunplugged.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=706308

 configure.ac           |    1 +
 src/core/monitor-kms.c |   55 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 4829295..f74bf10 100644
--- a/configure.ac
+++ b/configure.ac
@@ -81,6 +81,7 @@ MUTTER_PC_MODULES="
    cogl-1.0 >= 1.13.3
    upower-glib > 0.9.11
    gnome-desktop-3.0
+   gudev-1.0
 "
 
 GLIB_GSETTINGS
diff --git a/src/core/monitor-kms.c b/src/core/monitor-kms.c
index 9a1cb50..e7197fa 100644
--- a/src/core/monitor-kms.c
+++ b/src/core/monitor-kms.c
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <clutter/clutter.h>
+#include <gudev/gudev.h>
 
 #include <errno.h>
 #include <sys/ioctl.h>
@@ -61,6 +62,7 @@ struct _MetaMonitorManagerKms
   MetaMonitorManager parent_instance;
 
   int fd;
+  GUdevClient *udev;
 
   drmModeConnector **connectors;
   unsigned int       n_connectors;
@@ -896,12 +898,60 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
 }
 
 static void
+on_uevent (GUdevClient        *client,
+           const char         *action,
+           GUdevDevice        *device,
+           MetaMonitorManager *manager)
+{
+  MetaOutput *old_outputs;
+  MetaCRTC *old_crtcs;
+  MetaMonitorMode *old_modes;
+  unsigned int n_old_outputs, n_old_modes;
+
+  /* This is similar to MetaMonitorManagerXRandR->handle_xevent(), except
+     that we only get here for actual HW changes - reconfigurations
+     from other clients must go through our DBus API, and we don't
+     need to fiddle with timestamps.
+  */
+
+  /* Save the old structures, so they stay valid during the update */
+  old_outputs = manager->outputs;
+  n_old_outputs = manager->n_outputs;
+  old_modes = manager->modes;
+  n_old_modes = manager->n_modes;
+  old_crtcs = manager->crtcs;
+
+  manager->serial++;
+  meta_monitor_manager_kms_read_current (manager);
+
+  /* Check if an hotplug actually happened (maybe the uevent was for
+     something we don't care about, like a new card). If not,
+     just update our data structures (which should not be changed anyway)
+     and emit the signal. */
+  if (meta_monitor_config_match_current (manager->config, manager))
+    {
+      meta_monitor_config_update_current (manager->config, manager);
+      meta_monitor_manager_rebuild_derived (manager);
+    }
+  else
+    {
+      if (!meta_monitor_config_apply_stored (manager->config, manager))
+        meta_monitor_config_make_default (manager->config, manager);
+    }
+
+  meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
+  meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
+  g_free (old_crtcs);
+}
+
+static void
 meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
 {
   ClutterBackend *backend;
   CoglContext *cogl_context;
   CoglDisplay *cogl_display;
   CoglRenderer *cogl_renderer;
+  static const char *subsystems[] = { "drm/drm_minor", NULL };
 
   backend = clutter_get_default_backend ();
   cogl_context = clutter_backend_get_cogl_context (backend);
@@ -909,6 +959,10 @@ meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
   cogl_renderer = cogl_display_get_renderer (cogl_display);
 
   manager_kms->fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
+
+  manager_kms->udev = g_udev_client_new (subsystems);
+  g_signal_connect (manager_kms->udev, "uevent",
+                    G_CALLBACK (on_uevent), manager_kms);
 }
 
 static void
@@ -917,6 +971,7 @@ meta_monitor_manager_kms_finalize (GObject *object)
   MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (object);
 
   free_resources (manager_kms);
+  g_clear_object (&manager_kms->udev);
 
   G_OBJECT_CLASS (meta_monitor_manager_kms_parent_class)->finalize (object);
 }


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