move menus over from GLib

App menu and menubar are now properties of GtkApplication and their bus
location is exported using X window properties.

https://bugzilla.gnome.org/show_bug.cgi?id=668118
This commit is contained in:
Ryan Lortie 2012-01-16 14:46:04 -05:00
parent ed8e7d1793
commit 60317cbf1a
4 changed files with 205 additions and 58 deletions

View File

@ -134,7 +134,9 @@ static guint gtk_application_signals[LAST_SIGNAL];
enum {
PROP_ZERO,
PROP_REGISTER_SESSION
PROP_REGISTER_SESSION,
PROP_APP_MENU,
PROP_MENUBAR
};
G_DEFINE_TYPE (GtkApplication, gtk_application, G_TYPE_APPLICATION)
@ -147,7 +149,17 @@ struct _GtkApplicationPrivate
#ifdef GDK_WINDOWING_X11
GDBusConnection *session_bus;
gchar *window_prefix;
const gchar *application_id;
gchar *object_path;
GMenuModel *app_menu;
gchar *app_menu_path;
guint app_menu_id;
GMenuModel *menubar;
gchar *menubar_path;
guint menubar_id;
guint next_id;
GDBusProxy *sm_proxy;
@ -167,6 +179,59 @@ struct _GtkApplicationPrivate
};
#ifdef GDK_WINDOWING_X11
static void
gtk_application_x11_publish_menu (GtkApplication *application,
const gchar *type,
GMenuModel *model,
guint *id,
gchar **path)
{
gint i;
/* unexport any existing menu */
if (*id)
{
g_dbus_connection_unexport_menu_model (application->priv->session_bus, *id);
g_free (*path);
*path = NULL;
*id = 0;
}
/* export the new menu, if there is one */
if (model != NULL)
{
/* try getting the preferred name */
*path = g_strconcat (application->priv->object_path, "/menus/", type, NULL);
*id = g_dbus_connection_export_menu_model (application->priv->session_bus, *path, model, NULL);
/* keep trying until we get a working name... */
for (i = 0; *id == 0; i++)
{
g_free (*path);
*path = g_strdup_printf ("%s/menus/%s%d", application->priv->object_path, type, i);
*id = g_dbus_connection_export_menu_model (application->priv->session_bus, *path, model, NULL);
}
}
}
static void
gtk_application_set_app_menu_x11 (GtkApplication *application,
GMenuModel *app_menu)
{
gtk_application_x11_publish_menu (application, "appmenu", app_menu,
&application->priv->app_menu_id,
&application->priv->app_menu_path);
}
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)
@ -190,7 +255,7 @@ gtk_application_window_added_x11 (GtkApplication *application,
guint window_id;
window_id = application->priv->next_id++;
window_path = g_strdup_printf ("%s%d", application->priv->window_prefix, window_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);
}
@ -210,11 +275,11 @@ gtk_application_window_removed_x11 (GtkApplication *application,
}
static gchar *
window_prefix_from_appid (const gchar *appid)
object_path_from_appid (const gchar *appid)
{
gchar *appid_path, *iter;
appid_path = g_strconcat ("/", appid, "/windows/", NULL);
appid_path = g_strconcat ("/", appid, NULL);
for (iter = appid_path; *iter; iter++)
{
if (*iter == '.')
@ -236,7 +301,7 @@ gtk_application_startup_x11 (GtkApplication *application)
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->window_prefix = window_prefix_from_appid (application_id);
application->priv->object_path = object_path_from_appid (application_id);
gtk_application_startup_session_dbus (GTK_APPLICATION (application));
}
@ -244,8 +309,8 @@ gtk_application_startup_x11 (GtkApplication *application)
static void
gtk_application_shutdown_x11 (GtkApplication *application)
{
g_free (application->priv->window_prefix);
application->priv->window_prefix = NULL;
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);
@ -253,6 +318,25 @@ gtk_application_shutdown_x11 (GtkApplication *application)
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
@ -534,26 +618,6 @@ extract_accels_from_menu (GMenuModel *model,
}
}
static void
gtk_application_notify (GObject *object,
GParamSpec *pspec)
{
if (strcmp (pspec->name, "app-menu") == 0 ||
strcmp (pspec->name, "menubar") == 0)
{
GMenuModel *model;
g_object_get (object, pspec->name, &model, NULL);
if (model)
{
extract_accels_from_menu (model, GTK_APPLICATION (object));
g_object_unref (model);
}
}
if (G_OBJECT_CLASS (gtk_application_parent_class)->notify)
G_OBJECT_CLASS (gtk_application_parent_class)->notify (object, pspec);
}
static void
gtk_application_get_property (GObject *object,
guint prop_id,
@ -568,6 +632,14 @@ gtk_application_get_property (GObject *object,
g_value_set_boolean (value, application->priv->register_session);
break;
case PROP_APP_MENU:
g_value_set_object (value, gtk_application_get_app_menu (application));
break;
case PROP_MENUBAR:
g_value_set_object (value, gtk_application_get_menubar (application));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -588,6 +660,14 @@ gtk_application_set_property (GObject *object,
application->priv->register_session = g_value_get_boolean (value);
break;
case PROP_APP_MENU:
gtk_application_set_app_menu (application, g_value_get_object (value));
break;
case PROP_MENUBAR:
gtk_application_set_menubar (application, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -601,6 +681,18 @@ gtk_application_quit (GtkApplication *app)
g_application_set_inactivity_timeout (G_APPLICATION (app), 0);
}
static void
gtk_application_finalize (GObject *object)
{
GtkApplication *application = GTK_APPLICATION (object);
g_clear_object (&application->priv->app_menu);
g_clear_object (&application->priv->menubar);
G_OBJECT_CLASS (gtk_application_parent_class)
->finalize (object);
}
static void
gtk_application_class_init (GtkApplicationClass *class)
{
@ -609,7 +701,7 @@ gtk_application_class_init (GtkApplicationClass *class)
object_class->get_property = gtk_application_get_property;
object_class->set_property = gtk_application_set_property;
object_class->notify = gtk_application_notify;
object_class->finalize = gtk_application_finalize;
application_class->add_platform_data = gtk_application_add_platform_data;
application_class->before_emit = gtk_application_before_emit;
@ -698,6 +790,20 @@ gtk_application_class_init (GtkApplicationClass *class)
P_("Register session"),
P_("Register with the session manager"),
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_APP_MENU,
g_param_spec_object ("app-menu",
P_("Application menu"),
P_("The GMenuModel for the application menu"),
G_TYPE_MENU_MODEL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_MENUBAR,
g_param_spec_object ("menubar",
P_("Menubar"),
P_("The GMenuModel for the menubar"),
G_TYPE_MENU_MODEL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
/**
@ -918,7 +1024,7 @@ gtk_application_remove_accelerator (GtkApplication *application,
/**
* gtk_application_set_app_menu:
* @application: a #GtkApplication
* @model: (allow-none): a #GMenuModel, or %NULL
* @app_menu: (allow-none): a #GMenuModel, or %NULL
*
* Sets or unsets the application menu for @application.
*
@ -935,9 +1041,28 @@ gtk_application_remove_accelerator (GtkApplication *application,
*/
void
gtk_application_set_app_menu (GtkApplication *application,
GMenuModel *model)
GMenuModel *app_menu)
{
g_object_set (application, "app-menu", model, NULL);
g_return_if_fail (GTK_IS_APPLICATION (application));
if (app_menu != application->priv->app_menu)
{
if (application->priv->app_menu != NULL)
g_object_unref (application->priv->app_menu);
application->priv->app_menu = app_menu;
if (application->priv->app_menu != NULL)
g_object_ref (application->priv->app_menu);
extract_accels_from_menu (app_menu, application);
#ifdef GDK_WINDOWING_X11
gtk_application_set_app_menu_x11 (application, app_menu);
#endif
g_object_notify (G_OBJECT (application), "app-menu");
}
}
/**
@ -954,20 +1079,15 @@ gtk_application_set_app_menu (GtkApplication *application,
GMenuModel *
gtk_application_get_app_menu (GtkApplication *application)
{
GMenuModel *app_menu = NULL;
g_return_val_if_fail (GTK_IS_APPLICATION (application), NULL);
g_object_get (application, "app-menu", &app_menu, NULL);
if (app_menu)
g_object_unref (app_menu);
return app_menu;
return application->priv->app_menu;
}
/**
* gtk_application_set_menubar:
* @application: a #GtkApplication
* @model: (allow-none): a #GMenuModel, or %NULL
* @menubar: (allow-none): a #GMenuModel, or %NULL
*
* Sets or unsets the menubar for windows of @application.
*
@ -985,9 +1105,28 @@ gtk_application_get_app_menu (GtkApplication *application)
*/
void
gtk_application_set_menubar (GtkApplication *application,
GMenuModel *model)
GMenuModel *menubar)
{
g_object_set (application, "menubar", model, NULL);
g_return_if_fail (GTK_IS_APPLICATION (application));
if (menubar != application->priv->menubar)
{
if (application->priv->menubar != NULL)
g_object_unref (application->priv->menubar);
application->priv->menubar = menubar;
if (application->priv->menubar != NULL)
g_object_ref (application->priv->menubar);
extract_accels_from_menu (menubar, application);
#ifdef GDK_WINDOWING_X11
gtk_application_set_menubar_x11 (application, menubar);
#endif
g_object_notify (G_OBJECT (application), "menubar");
}
}
/**
@ -1004,14 +1143,9 @@ gtk_application_set_menubar (GtkApplication *application,
GMenuModel *
gtk_application_get_menubar (GtkApplication *application)
{
GMenuModel *menubar = NULL;
g_return_val_if_fail (GTK_IS_APPLICATION (application), NULL);
g_object_get (application, "menubar", &menubar, NULL);
if (menubar)
g_object_unref (menubar);
return menubar;
return application->priv->menubar;
}
#if defined(GDK_WINDOWING_X11)

View File

@ -79,11 +79,11 @@ GList * gtk_application_get_windows (GtkApplication *application);
GMenuModel * gtk_application_get_app_menu (GtkApplication *application);
void gtk_application_set_app_menu (GtkApplication *application,
GMenuModel *model);
GMenuModel *app_menu);
GMenuModel * gtk_application_get_menubar (GtkApplication *application);
void gtk_application_set_menubar (GtkApplication *application,
GMenuModel *model);
GMenuModel *menubar);
void gtk_application_add_accelerator (GtkApplication *application,
const gchar *accelerator,

View File

@ -38,5 +38,11 @@ G_GNUC_INTERNAL
GSimpleActionObserver * gtk_application_window_create_observer (GtkApplicationWindow *window,
const gchar *action_name,
GVariant *target);
G_GNUC_INTERNAL
const gchar * gtk_application_get_dbus_object_path (GtkApplication *application);
G_GNUC_INTERNAL
const gchar * gtk_application_get_app_menu_object_path (GtkApplication *application);
G_GNUC_INTERNAL
const gchar * gtk_application_get_menubar_object_path (GtkApplication *application);
#endif /* __GTK_APPLICATION_PRIVATE_H__ */

View File

@ -700,16 +700,23 @@ gtk_application_window_real_realize (GtkWidget *widget)
if (GDK_IS_X11_WINDOW (gdkwindow))
{
const gchar *unique_id;
const gchar *app_id;
gdk_x11_window_set_utf8_property (gdkwindow, "_GTK_APPLICATION_ID",
g_application_get_application_id (G_APPLICATION (application)));
gdk_x11_window_set_utf8_property (gdkwindow, "_DBUS_OBJECT_PATH", window->priv->object_path);
gdk_x11_window_set_utf8_property (gdkwindow, "_GTK_UNIQUE_BUS_NAME",
g_dbus_connection_get_unique_name (window->priv->session));
unique_id = g_dbus_connection_get_unique_name (window->priv->session);
gdk_x11_window_set_utf8_property (gdkwindow, "_DBUS_UNIQUE_NAME", unique_id);
gdk_x11_window_set_utf8_property (gdkwindow, "_GTK_APPLICATION_OBJECT_PATH",
gtk_application_get_dbus_object_path (application));
app_id = g_application_get_application_id (G_APPLICATION (application));
gdk_x11_window_set_utf8_property (gdkwindow, "_DBUS_APPLICATION_ID", app_id);
gdk_x11_window_set_utf8_property (gdkwindow, "_GTK_WINDOW_OBJECT_PATH",
window->priv->object_path);
gdk_x11_window_set_utf8_property (gdkwindow, "_GTK_APP_MENU_OBJECT_PATH",
gtk_application_get_app_menu_object_path (application));
gdk_x11_window_set_utf8_property (gdkwindow, "_GTK_MENUBAR_OBJECT_PATH",
gtk_application_get_menubar_object_path (application));
}
}
#endif