[gtk+/wip/gmenu] GtkApplication: export windows on the bus



commit a9e007acecea53349e2439407007caa5c514398f
Author: Ryan Lortie <desrt desrt ca>
Date:   Mon Dec 5 00:27:11 2011 -0500

    GtkApplication: export windows on the bus
    
    And advertise their location on the bus using X11 properties.

 gtk/gtkapplication.c |  152 +++++++++++++++++++++++++++++++++++++++++++++++++-
 gtk/gtkwindow.c      |   17 ------
 2 files changed, 151 insertions(+), 18 deletions(-)
---
diff --git a/gtk/gtkapplication.c b/gtk/gtkapplication.c
index 1d1bba9..43e891b 100644
--- a/gtk/gtkapplication.c
+++ b/gtk/gtkapplication.c
@@ -30,7 +30,7 @@
 #include "gtkapplication.h"
 #include "gtkmarshalers.h"
 #include "gtkmain.h"
-#include "gtkwindow.h"
+#include "gtkapplicationwindow.h"
 
 #include <gdk/gdk.h>
 #ifdef GDK_WINDOWING_X11
@@ -76,8 +76,142 @@ G_DEFINE_TYPE (GtkApplication, gtk_application, G_TYPE_APPLICATION)
 struct _GtkApplicationPrivate
 {
   GList *windows;
+
+#ifdef GDK_WINDOWING_X11
+  GDBusConnection *session;
+  gchar *window_prefix;
+  guint next_id;
+#endif
 };
 
+#ifdef GDK_WINDOWING_X11
+typedef struct
+{
+  guint action_export_id;
+  guint window_id;
+} GtkApplicationWindowInfo;
+
+static void
+gtk_application_window_realized_x11 (GtkWindow *window,
+                                     gpointer   user_data)
+{
+  GtkApplication *application = user_data;
+  GtkApplicationWindowInfo *info;
+  GdkWindow *gdkwindow;
+  gchar *window_path;
+  const gchar *unique_id;
+  const gchar *app_id;
+
+  gdkwindow = gtk_widget_get_window (GTK_WIDGET (window));
+
+  if (!GDK_IS_X11_WINDOW (gdkwindow))
+    return;
+
+  info = g_object_get_data (G_OBJECT (window), "GtkApplication::window-info");
+
+  window_path = g_strdup_printf ("%s%d", application->priv->window_prefix, info->window_id);
+  gdk_x11_window_set_utf8_property (gdkwindow, "_DBUS_OBJECT_PATH", window_path);
+  g_free (window_path);
+
+  unique_id = g_dbus_connection_get_unique_name (application->priv->session);
+  gdk_x11_window_set_utf8_property (gdkwindow, "_DBUS_UNIQUE_NAME", unique_id);
+
+  app_id = g_application_get_application_id (G_APPLICATION (application));
+  gdk_x11_window_set_utf8_property (gdkwindow, "_DBUS_APPLICATION_ID", app_id);
+}
+
+static void
+gtk_application_window_added_x11 (GtkApplication *application,
+                                  GtkWindow      *window)
+{
+  GtkApplicationWindowInfo *info;
+
+  if (application->priv->session == NULL)
+    return;
+
+  if (!GTK_IS_APPLICATION_WINDOW (window))
+    return;
+
+  /* GtkApplicationWindow associates with us when it is first created,
+   * so surely it's not realized yet...
+   */
+  g_assert (!gtk_widget_get_realized (GTK_WIDGET (window)));
+
+  /* ...but we want to know when it is. */
+  g_signal_connect (window, "realize", G_CALLBACK (gtk_application_window_realized_x11), application);
+
+  info = g_slice_new (GtkApplicationWindowInfo);
+  do
+    {
+      gchar *window_path;
+
+      info->window_id = application->priv->next_id++;
+      window_path = g_strdup_printf ("%s%d", application->priv->window_prefix, info->window_id);
+      info->action_export_id = g_dbus_connection_export_action_group (application->priv->session, window_path,
+                                                                      G_ACTION_GROUP (window), NULL);
+      g_free (window_path);
+    }
+  while (!info->action_export_id);
+
+  g_object_set_data (G_OBJECT (window), "GtkApplication::window-info", info);
+}
+
+static void
+gtk_application_window_removed_x11 (GtkApplication *application,
+                                    GtkWindow      *window)
+{
+  GtkApplicationWindowInfo *info;
+
+  if (application->priv->session == NULL)
+    return;
+
+  if (!GTK_IS_APPLICATION_WINDOW (window))
+    return;
+
+  info = g_object_steal_data (G_OBJECT (window), "GtkApplication::window-info");
+
+  g_dbus_connection_unexport_action_group (application->priv->session, info->action_export_id);
+
+  g_slice_free (GtkApplicationWindowInfo, info);
+}
+
+static gchar *
+window_prefix_from_appid (const gchar *appid)
+{
+  gchar *appid_path, *iter;
+
+  appid_path = g_strconcat ("/", appid, "/windows/", NULL);
+  for (iter = appid_path; *iter; iter++)
+    {
+      if (*iter == '.')
+        *iter = '/';
+
+      if (*iter == '-')
+        *iter = '_';
+    }
+
+  return appid_path;
+}
+
+static void
+gtk_application_startup_x11 (GtkApplication *application)
+{
+  const gchar *application_id;
+
+  application_id = g_application_get_application_id (G_APPLICATION (application));
+  application->priv->session = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+  application->priv->window_prefix = window_prefix_from_appid (application_id);
+}
+
+static void
+gtk_application_shutdown_x11 (GtkApplication *application)
+{
+  g_free (application->priv->window_prefix);
+  application->priv->window_prefix = NULL;
+  application->priv->session = NULL;
+}
+#endif
+
 static gboolean
 gtk_application_focus_in_event_cb (GtkWindow      *window,
                                    GdkEventFocus  *event,
@@ -104,11 +238,19 @@ gtk_application_startup (GApplication *application)
     ->startup (application);
 
   gtk_init (0, 0);
+
+#ifdef GDK_WINDOWING_X11
+  gtk_application_startup_x11 (GTK_APPLICATION (application));
+#endif
 }
 
 static void
 gtk_application_shutdown (GApplication *application)
 {
+#ifdef GDK_WINDOWING_X11
+  gtk_application_shutdown_x11 (GTK_APPLICATION (application));
+#endif
+
   G_APPLICATION_CLASS (gtk_application_parent_class)
     ->shutdown (application);
 }
@@ -179,6 +321,10 @@ gtk_application_window_added (GtkApplication *application,
   g_signal_connect (window, "focus-in-event",
                     G_CALLBACK (gtk_application_focus_in_event_cb),
                     application);
+
+#ifdef GDK_WINDOWING_X11
+  gtk_application_window_added_x11 (application, window);
+#endif
 }
 
 static void
@@ -187,6 +333,10 @@ gtk_application_window_removed (GtkApplication *application,
 {
   GtkApplicationPrivate *priv = application->priv;
 
+#ifdef GDK_WINDOWING_X11
+  gtk_application_window_removed_x11 (application, window);
+#endif
+
   g_signal_handlers_disconnect_by_func (window,
                                         gtk_application_focus_in_event_cb,
                                         application);
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 775161e..2a485ef 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -2658,7 +2658,6 @@ gtk_window_set_application (GtkWindow      *window,
                             GtkApplication *application)
 {
   GtkWindowPrivate *priv;
-  GdkWindow *gdkwindow;
 
   g_return_if_fail (GTK_IS_WINDOW (window));
 
@@ -2678,22 +2677,6 @@ gtk_window_set_application (GtkWindow      *window,
 
       g_object_notify (G_OBJECT (window), "application");
     }
-
-#ifdef GDK_WINDOWING_X11
-  gdkwindow = gtk_widget_get_window (GTK_WIDGET (window));
-  if (gdkwindow)
-    {
-      if (GDK_IS_X11_WINDOW (gdkwindow))
-	{
-	  const char *id;
-	  if (application)
-	    id = g_application_get_application_id ((GApplication*)application);
-	  else
-	    id = NULL;
-	  gdk_x11_window_set_utf8_property (gdkwindow, "_DBUS_APPLICATION_ID", id);
-	}
-    }
-#endif
 }
 
 /**



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