[gnome-settings-daemon] Handle video out keys in media-keys



commit d1a4f8cd587d7817fc7685f287c0e71190751ca6
Author: Ray Strode <rstrode redhat com>
Date:   Wed Jun 30 17:55:59 2010 +0100

    Handle video out keys in media-keys
    
    Instead of reimplementing keyboard events capture in xrandr,
    add D-Bus methods to rotate the screen, and switch video modes
    to the xrandr plugin, and make the media-keys plugin handle call
    those methods when the keys are pressed.
    
    This patch almost entirely written by:
    
    Bastien Nocera <hadess hadess net>
    
    with minor fixes.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=623223

 plugins/media-keys/acme.h                   |   10 ++-
 plugins/media-keys/gsd-media-keys-manager.c |  138 +++++++++++++++++++++++---
 plugins/xrandr/gsd-xrandr-manager.c         |  124 +++++-------------------
 plugins/xrandr/gsd-xrandr-manager.xml       |    8 ++
 4 files changed, 162 insertions(+), 118 deletions(-)
---
diff --git a/plugins/media-keys/acme.h b/plugins/media-keys/acme.h
index 4ba6859..d52535f 100644
--- a/plugins/media-keys/acme.h
+++ b/plugins/media-keys/acme.h
@@ -49,6 +49,9 @@ enum {
         FORWARD_KEY,
         REPEAT_KEY,
         RANDOM_KEY,
+        VIDEO_OUT_KEY,
+        VIDEO_OUT2_KEY,
+        ROTATE_VIDEO_KEY,
         HANDLED_KEYS
 };
 
@@ -80,7 +83,12 @@ static struct {
         { REWIND_KEY, "rewind", "XF86AudioRewind", NULL },
         { FORWARD_KEY, "forward", "XF86AudioForward", NULL },
         { REPEAT_KEY, "repeat", "XF86AudioRepeat", NULL },
-        { RANDOM_KEY, "random", "XF86AudioRandomPlay", NULL}
+        { RANDOM_KEY, "random", "XF86AudioRandomPlay", NULL},
+        { VIDEO_OUT_KEY, NULL, "<Mod4>p", NULL },
+        /* Key code of the XF86Display key (Fn-F7 on Thinkpads, Fn-F4 on HP machines, etc.) */
+        { VIDEO_OUT2_KEY, NULL, "XF86Display", NULL },
+        /* Key code of the XF86RotateWindows key (present on some tablets) */
+        { ROTATE_VIDEO_KEY, NULL, "XF86RotateWindows", NULL },
 };
 
 #endif /* __ACME_H__ */
diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c
index dbbc21d..eec7d9b 100644
--- a/plugins/media-keys/gsd-media-keys-manager.c
+++ b/plugins/media-keys/gsd-media-keys-manager.c
@@ -106,6 +106,8 @@ struct GsdMediaKeysManagerPrivate
         guint            owner_id;
         GDBusNodeInfo   *introspection_data;
         GDBusConnection *connection;
+        GDBusProxy      *xrandr_proxy;
+        GCancellable    *cancellable;
 };
 
 static void     gsd_media_keys_manager_class_init  (GsdMediaKeysManagerClass *klass);
@@ -948,9 +950,86 @@ do_multimedia_player_action (GsdMediaKeysManager *manager,
         return gsd_media_player_key_pressed (manager, key);
 }
 
+static void
+on_xrandr_action_call_finished (GObject             *source_object,
+				GAsyncResult        *res,
+				GsdMediaKeysManager *manager)
+{
+        GError *error = NULL;
+        GVariant *variant;
+        char *action;
+
+        action = g_object_get_data (G_OBJECT (source_object),
+				    "gsd-media-keys-manager-xrandr-action");
+
+	variant = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
+
+	g_object_unref (manager->priv->cancellable);
+	manager->priv->cancellable = NULL;
+
+        if (!res) {
+                g_warning ("Unable to call '%s': %s", action, error->message);
+                g_error_free (error);
+        } else {
+		g_variant_unref (variant);
+	}
+
+        g_free (action);
+}
+
+static void
+do_xrandr_action (GsdMediaKeysManager *manager,
+                  const char          *action,
+                  gint64               timestamp)
+{
+        GsdMediaKeysManagerPrivate *priv = manager->priv;
+
+        if (priv->connection == NULL || priv->xrandr_proxy == NULL) {
+                g_warning ("No existing D-Bus connection trying to handle XRANDR keys");
+                return;
+        }
+
+        if (priv->cancellable != NULL) {
+                g_debug ("xrandr action already in flight");
+                return;
+        }
+
+	priv->cancellable = g_cancellable_new ();
+
+        g_object_set_data (G_OBJECT (priv->xrandr_proxy),
+			   "gsd-media-keys-manager-xrandr-action",
+			   g_strdup (action));
+
+	g_dbus_proxy_call (priv->xrandr_proxy,
+			   action,
+			   g_variant_new ("(x)", timestamp),
+			   G_DBUS_CALL_FLAGS_NONE,
+			   -1,
+			   priv->cancellable,
+			   (GAsyncReadyCallback) on_xrandr_action_call_finished,
+			   manager);
+}
+
+static gboolean
+do_video_out_action (GsdMediaKeysManager *manager,
+                     gint64               timestamp)
+{
+        do_xrandr_action (manager, "VideoModeSwitch", timestamp);
+        return FALSE;
+}
+
+static gboolean
+do_video_rotate_action (GsdMediaKeysManager *manager,
+                        gint64               timestamp)
+{
+        do_xrandr_action (manager, "Rotate", timestamp);
+        return FALSE;
+}
+
 static gboolean
 do_action (GsdMediaKeysManager *manager,
-           int                  type)
+           int                  type,
+           gint64               timestamp)
 {
         char *cmd;
         char *path;
@@ -1032,8 +1111,16 @@ do_action (GsdMediaKeysManager *manager,
                 return do_multimedia_player_action (manager, "Repeat");
         case RANDOM_KEY:
                 return do_multimedia_player_action (manager, "Shuffle");
-        default:
+        case VIDEO_OUT_KEY:
+        case VIDEO_OUT2_KEY:
+                do_video_out_action (manager, timestamp);
+                break;
+	case ROTATE_VIDEO_KEY:
+		do_video_rotate_action (manager, timestamp);
+		break;
+        case HANDLED_KEYS:
                 g_assert_not_reached ();
+        /* Note, no default so compiler catches missing keys */
         }
 
         return FALSE;
@@ -1092,7 +1179,7 @@ acme_filter_events (GdkXEvent           *xevent,
 
                         manager->priv->current_screen = acme_get_screen_from_event (manager, xany);
 
-                        if (do_action (manager, keys[i].key_type) == FALSE) {
+                        if (do_action (manager, keys[i].key_type, xev->xkey.time) == FALSE) {
                                 return GDK_FILTER_REMOVE;
                         } else {
                                 return GDK_FILTER_CONTINUE;
@@ -1200,6 +1287,12 @@ gsd_media_keys_manager_stop (GsdMediaKeysManager *manager)
                 priv->volume_monitor = NULL;
         }
 
+	if (priv->cancellable != NULL) {
+		g_cancellable_cancel (priv->cancellable);
+		g_object_unref (priv->cancellable);
+		priv->cancellable = NULL;
+	}
+
         if (priv->owner_id > 0) {
                 g_bus_unown_name (priv->owner_id);
                 priv->owner_id = 0;
@@ -1311,16 +1404,6 @@ gsd_media_keys_manager_constructor (GType                  type,
 }
 
 static void
-gsd_media_keys_manager_dispose (GObject *object)
-{
-        GsdMediaKeysManager *media_keys_manager;
-
-        media_keys_manager = GSD_MEDIA_KEYS_MANAGER (object);
-
-        G_OBJECT_CLASS (gsd_media_keys_manager_parent_class)->dispose (object);
-}
-
-static void
 gsd_media_keys_manager_class_init (GsdMediaKeysManagerClass *klass)
 {
         GObjectClass   *object_class = G_OBJECT_CLASS (klass);
@@ -1328,7 +1411,6 @@ gsd_media_keys_manager_class_init (GsdMediaKeysManagerClass *klass)
         object_class->get_property = gsd_media_keys_manager_get_property;
         object_class->set_property = gsd_media_keys_manager_set_property;
         object_class->constructor = gsd_media_keys_manager_constructor;
-        object_class->dispose = gsd_media_keys_manager_dispose;
         object_class->finalize = gsd_media_keys_manager_finalize;
 
         g_type_class_add_private (klass, sizeof (GsdMediaKeysManagerPrivate));
@@ -1338,7 +1420,6 @@ static void
 gsd_media_keys_manager_init (GsdMediaKeysManager *manager)
 {
         manager->priv = GSD_MEDIA_KEYS_MANAGER_GET_PRIVATE (manager);
-
 }
 
 static void
@@ -1357,6 +1438,20 @@ gsd_media_keys_manager_finalize (GObject *object)
 }
 
 static void
+xrandr_ready_cb (GObject             *source_object,
+		 GAsyncResult        *res,
+		 GsdMediaKeysManager *manager)
+{
+	GError *error = NULL;
+
+	manager->priv->xrandr_proxy = g_dbus_proxy_new_finish (res, &error);
+	if (manager->priv->xrandr_proxy == NULL) {
+		g_warning ("Failed to get proxy for XRandR operations: %s", error->message);
+		g_error_free (error);
+	}
+}
+
+static void
 on_bus_acquired (GDBusConnection     *connection,
                  const gchar         *name,
                  GsdMediaKeysManager *manager)
@@ -1370,8 +1465,19 @@ on_bus_acquired (GDBusConnection     *connection,
                                                              manager,
                                                              NULL,
                                                              NULL);
-        if (registration_id > 0)
+        if (registration_id > 0) {
                 manager->priv->connection = connection;
+
+		g_dbus_proxy_new (manager->priv->connection,
+				  G_DBUS_PROXY_FLAGS_NONE,
+				  NULL,
+				  "org.gnome.SettingsDaemon",
+				  "/org/gnome/SettingsDaemon/XRANDR",
+				  "org.gnome.SettingsDaemon.XRANDR_2",
+				  NULL,
+				  (GAsyncReadyCallback) xrandr_ready_cb,
+				  manager);
+	}
 }
 
 static void
diff --git a/plugins/xrandr/gsd-xrandr-manager.c b/plugins/xrandr/gsd-xrandr-manager.c
index fec9c16..e5a0404 100644
--- a/plugins/xrandr/gsd-xrandr-manager.c
+++ b/plugins/xrandr/gsd-xrandr-manager.c
@@ -81,12 +81,6 @@ struct GsdXrandrManagerPrivate
 {
         DBusGConnection *dbus_connection;
 
-        /* Key code of the XF86Display key (Fn-F7 on Thinkpads, Fn-F4 on HP machines, etc.) */
-        guint switch_video_mode_keycode;
-
-        /* Key code of the XF86RotateWindows key (present on some tablets) */
-        guint rotate_windows_keycode;
-
         GnomeRRScreen *rw_screen;
         gboolean running;
 
@@ -119,6 +113,8 @@ static void get_allowed_rotations_for_output (GnomeRRConfig *config,
                                               GnomeOutputInfo *output,
                                               int *out_num_rotations,
                                               GnomeRRRotation *out_rotations);
+static void handle_fn_f7 (GsdXrandrManager *mgr, guint32 timestamp);
+static void handle_rotate_windows (GsdXrandrManager *mgr, guint32 timestamp);
 
 G_DEFINE_TYPE (GsdXrandrManager, gsd_xrandr_manager, G_TYPE_OBJECT)
 
@@ -613,7 +609,27 @@ gsd_xrandr_manager_2_apply_configuration (GsdXrandrManager *manager,
         return result;
 }
 
-/* We include this after the definition of gsd_xrandr_manager_apply_configuration() so the prototype will already exist */
+/* DBus method for org.gnome.SettingsDaemon.XRANDR_2 VideoModeSwitch; see gsd-xrandr-manager.xml for the interface definition */
+static gboolean
+gsd_xrandr_manager_2_video_mode_switch (GsdXrandrManager *manager,
+					guint32           timestamp,
+					GError          **error)
+{
+	handle_fn_f7 (manager, timestamp);
+	return TRUE;
+}
+
+/* DBus method for org.gnome.SettingsDaemon.XRANDR_2 Rotate; see gsd-xrandr-manager.xml for the interface definition */
+static gboolean
+gsd_xrandr_manager_2_rotate (GsdXrandrManager *manager,
+			     guint32           timestamp,
+			     GError          **error)
+{
+	handle_rotate_windows (manager, timestamp);
+	return TRUE;
+}
+
+/* We include this after the definition of gsd_xrandr_manager_* D-Bus methods so the prototype will already exist */
 #include "gsd-xrandr-manager-glue.h"
 
 static gboolean
@@ -1301,33 +1317,6 @@ out:
         gnome_rr_config_free (current);
 }
 
-static GdkFilterReturn
-event_filter (GdkXEvent           *xevent,
-              GdkEvent            *event,
-              gpointer             data)
-{
-        GsdXrandrManager *manager = data;
-        XEvent *xev = (XEvent *) xevent;
-
-        if (!manager->priv->running)
-                return GDK_FILTER_CONTINUE;
-
-        /* verify we have a key event */
-        if (xev->xany.type != KeyPress && xev->xany.type != KeyRelease)
-                return GDK_FILTER_CONTINUE;
-
-        if (xev->xany.type == KeyPress) {
-                if (xev->xkey.keycode == manager->priv->switch_video_mode_keycode)
-                        handle_fn_f7 (manager, xev->xkey.time);
-                else if (xev->xkey.keycode == manager->priv->rotate_windows_keycode)
-                        handle_rotate_windows (manager, xev->xkey.time);
-
-                return GDK_FILTER_CONTINUE;
-        }
-
-        return GDK_FILTER_CONTINUE;
-}
-
 static void
 auto_configure_outputs (GsdXrandrManager *manager, guint32 timestamp)
 {
@@ -1741,30 +1730,6 @@ gsd_xrandr_manager_start (GsdXrandrManager *manager,
         manager->priv->running = TRUE;
         manager->priv->settings = g_settings_new (CONF_DIR);
 
-        if (manager->priv->switch_video_mode_keycode) {
-                gdk_error_trap_push ();
-
-                XGrabKey (gdk_x11_get_default_xdisplay(),
-                          manager->priv->switch_video_mode_keycode, AnyModifier,
-                          gdk_x11_get_default_root_xwindow(),
-                          True, GrabModeAsync, GrabModeAsync);
-
-                gdk_flush ();
-                gdk_error_trap_pop ();
-        }
-
-        if (manager->priv->rotate_windows_keycode) {
-                gdk_error_trap_push ();
-
-                XGrabKey (gdk_x11_get_default_xdisplay(),
-                          manager->priv->rotate_windows_keycode, AnyModifier,
-                          gdk_x11_get_default_root_xwindow(),
-                          True, GrabModeAsync, GrabModeAsync);
-
-                gdk_flush ();
-                gdk_error_trap_pop ();
-        }
-
         show_timestamps_dialog (manager, "Startup");
         if (!apply_stored_configuration_at_startup (manager, GDK_CURRENT_TIME)) /* we don't have a real timestamp at startup anyway */
                 if (!apply_default_configuration_from_file (manager, GDK_CURRENT_TIME))
@@ -1774,10 +1739,6 @@ gsd_xrandr_manager_start (GsdXrandrManager *manager,
         log_msg ("State of screen after initial configuration:\n");
         log_screen (manager->priv->rw_screen);
 
-        gdk_window_add_filter (gdk_get_default_root_window(),
-                               (GdkFilterFunc)event_filter,
-                               manager);
-
         log_close ();
 
         gnome_settings_profile_end (NULL);
@@ -1792,30 +1753,6 @@ gsd_xrandr_manager_stop (GsdXrandrManager *manager)
 
         manager->priv->running = FALSE;
 
-        if (manager->priv->switch_video_mode_keycode) {
-                gdk_error_trap_push ();
-
-                XUngrabKey (gdk_x11_get_default_xdisplay(),
-                            manager->priv->switch_video_mode_keycode, AnyModifier,
-                            gdk_x11_get_default_root_xwindow());
-
-                gdk_error_trap_pop ();
-        }
-
-        if (manager->priv->rotate_windows_keycode) {
-                gdk_error_trap_push ();
-
-                XUngrabKey (gdk_x11_get_default_xdisplay(),
-                            manager->priv->rotate_windows_keycode, AnyModifier,
-                            gdk_x11_get_default_root_xwindow());
-
-                gdk_error_trap_pop ();
-        }
-
-        gdk_window_remove_filter (gdk_get_default_root_window (),
-                                  (GdkFilterFunc) event_filter,
-                                  manager);
-
         if (manager->priv->settings != NULL) {
                 g_object_unref (manager->priv->settings);
                 manager->priv->settings = NULL;
@@ -1913,26 +1850,11 @@ gsd_xrandr_manager_class_init (GsdXrandrManagerClass *klass)
         g_type_class_add_private (klass, sizeof (GsdXrandrManagerPrivate));
 }
 
-static guint
-get_keycode_for_keysym_name (const char *name)
-{
-        Display *dpy;
-        guint keyval;
-
-        dpy = gdk_x11_get_default_xdisplay ();
-
-        keyval = gdk_keyval_from_name (name);
-        return XKeysymToKeycode (dpy, keyval);
-}
-
 static void
 gsd_xrandr_manager_init (GsdXrandrManager *manager)
 {
         manager->priv = GSD_XRANDR_MANAGER_GET_PRIVATE (manager);
 
-        manager->priv->switch_video_mode_keycode = get_keycode_for_keysym_name (VIDEO_KEYSYM);
-        manager->priv->rotate_windows_keycode = get_keycode_for_keysym_name (ROTATE_KEYSYM);
-
         manager->priv->current_fn_f7_config = -1;
         manager->priv->fn_f7_configs = NULL;
 }
diff --git a/plugins/xrandr/gsd-xrandr-manager.xml b/plugins/xrandr/gsd-xrandr-manager.xml
index 365a552..1057d75 100644
--- a/plugins/xrandr/gsd-xrandr-manager.xml
+++ b/plugins/xrandr/gsd-xrandr-manager.xml
@@ -19,5 +19,13 @@
       the future) for the RANDR calls themselves -->
       <arg name="timestamp" type="x" direction="in"/>
     </method>
+    <method name="VideoModeSwitch">
+       <!-- Timestamp for the RANDR call itself -->
+       <arg name="timestamp" type="x" direction="in"/>
+    </method>
+    <method name="Rotate">
+       <!-- Timestamp for the RANDR call itself -->
+       <arg name="timestamp" type="x" direction="in"/>
+    </method>
   </interface>
 </node>



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