+static void
+gtk_application_set_menubar_x11 (GtkApplication *application,
+ GMenuModel *menubar)
+{
+ gtk_application_x11_publish_menu (application, "menubar", menubar,
+ &application->priv->menubar_id,
+ &application->priv->menubar_path);
+}
+
+static void
+gtk_application_window_added_x11 (GtkApplication *application,
+ GtkWindow *window)
+{
+ if (application->priv->session_bus == NULL)
+ return;
+
+ if (GTK_IS_APPLICATION_WINDOW (window))
+ {
+ GtkApplicationWindow *app_window = GTK_APPLICATION_WINDOW (window);
+ gboolean success;
+
+ /* 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)));
+
+ do
+ {
+ gchar *window_path;
+ guint window_id;
+
+ window_id = application->priv->next_id++;
+ window_path = g_strdup_printf ("%s/window/%d", application->priv->object_path, window_id);
+ success = gtk_application_window_publish (app_window, application->priv->session_bus, window_path);
+ g_free (window_path);
+ }
+ while (!success);
+ }
+}
+
+static void
+gtk_application_window_removed_x11 (GtkApplication *application,
+ GtkWindow *window)
+{
+ if (application->priv->session_bus == NULL)
+ return;
+
+ if (GTK_IS_APPLICATION_WINDOW (window))
+ gtk_application_window_unpublish (GTK_APPLICATION_WINDOW (window));
+}
+
+static gchar *
+object_path_from_appid (const gchar *appid)
+{
+ gchar *appid_path, *iter;
+
+ appid_path = g_strconcat ("/", appid, NULL);
+ for (iter = appid_path; *iter; iter++)
+ {
+ if (*iter == '.')
+ *iter = '/';
+
+ if (*iter == '-')
+ *iter = '_';
+ }
+
+ return appid_path;
+}
+
+static void gtk_application_startup_session_dbus (GtkApplication *app);
+
+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_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+ application->priv->object_path = object_path_from_appid (application_id);
+
+ gtk_application_startup_session_dbus (GTK_APPLICATION (application));
+}
+
+static void
+gtk_application_shutdown_x11 (GtkApplication *application)
+{
+ g_free (application->priv->object_path);
+ application->priv->object_path = NULL;
+ g_clear_object (&application->priv->session_bus);
+
+ g_clear_object (&application->priv->sm_proxy);
+ g_clear_object (&application->priv->client_proxy);
+ g_free (application->priv->app_id);
+ g_free (application->priv->client_path);
+}
+
+const gchar *
+gtk_application_get_dbus_object_path (GtkApplication *application)
+{
+ return application->priv->object_path;
+}
+
+const gchar *
+gtk_application_get_app_menu_object_path (GtkApplication *application)
+{
+ return application->priv->app_menu_path;
+}
+
+const gchar *
+gtk_application_get_menubar_object_path (GtkApplication *application)
+{
+ return application->priv->menubar_path;
+}
+
+#endif
+
+#ifdef GDK_WINDOWING_QUARTZ
+
+typedef struct {
+ guint cookie;
+ GtkApplicationInhibitFlags flags;
+ char *reason;
+ GtkWindow *window;
+} GtkApplicationQuartzInhibitor;
+
+static void
+gtk_application_quartz_inhibitor_free (GtkApplicationQuartzInhibitor *inhibitor)
+{
+ g_free (inhibitor->reason);
+ g_clear_object (&inhibitor->window);
+ g_slice_free (GtkApplicationQuartzInhibitor, inhibitor);
+}
+
+static void
+gtk_application_menu_changed_quartz (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ GtkApplication *application = GTK_APPLICATION (object);
+ GMenu *combined;
+
+ combined = g_menu_new ();
+ g_menu_append_submenu (combined, "Application", gtk_application_get_app_menu (application));
+ g_menu_append_section (combined, NULL, gtk_application_get_menubar (application));
+
+ gtk_quartz_set_main_menu (G_MENU_MODEL (combined), G_ACTION_OBSERVABLE (application->priv->muxer));
+}
+
+static void gtk_application_startup_session_quartz (GtkApplication *app);
+
+static void
+gtk_application_startup_quartz (GtkApplication *application)
+{
+ [NSApp finishLaunching];
+
+ application->priv->muxer = g_action_muxer_new ();
+ g_action_muxer_insert (application->priv->muxer, "app", G_ACTION_GROUP (application));
+
+ g_signal_connect (application, "notify::app-menu", G_CALLBACK (gtk_application_menu_changed_quartz), NULL);
+ g_signal_connect (application, "notify::menubar", G_CALLBACK (gtk_application_menu_changed_quartz), NULL);
+ gtk_application_menu_changed_quartz (G_OBJECT (application), NULL, NULL);
+
+ gtk_application_startup_session_quartz (application);
+}
+
+static void
+gtk_application_shutdown_quartz (GtkApplication *application)
+{
+ g_signal_handlers_disconnect_by_func (application, gtk_application_menu_changed_quartz, NULL);
+
+ g_object_unref (application->priv->muxer);
+ application->priv->muxer = NULL;
+
+ g_slist_free_full (application->priv->inhibitors,
+ (GDestroyNotify) gtk_application_quartz_inhibitor_free);
+ application->priv->inhibitors = NULL;
+}
+
+static void
+gtk_application_focus_changed (GtkApplication *application,
+ GtkWindow *window)