diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt index aefc7e117..0996b501b 100644 --- a/docs/reference/gio/gio-sections.txt +++ b/docs/reference/gio/gio-sections.txt @@ -2815,6 +2815,8 @@ g_application_get_flags g_application_set_flags g_application_set_action_group +g_application_set_menu +g_application_get_menu g_application_get_is_registered g_application_get_is_remote diff --git a/gio/gapplication.c b/gio/gapplication.c index de3c422f1..0abdcfc9d 100644 --- a/gio/gapplication.c +++ b/gio/gapplication.c @@ -27,6 +27,7 @@ #include "gapplicationcommandline.h" #include "gapplicationimpl.h" #include "gactiongroup.h" +#include "gmenumodel.h" #include "gsettings.h" #include "gioenumtypes.h" @@ -88,7 +89,11 @@ * GApplication also implements the #GActionGroup interface and lets you * easily export actions by adding them with g_application_set_action_group(). * When invoking an action by calling g_action_group_activate_action() on - * the application, it is always invoked in the primary instance. + * the application, it is always invoked in the primary instance. The actions + * are also exported on the session bus, and GIO provides the #GDBusActionGroup + * wrapper to conveniently access them remotely. Additionally, + * g_application_set_menu() can be used to export representation data + * for the actions, in the form of a #GMenuModel. * * There is a number of different entry points into a #GApplication: * @@ -149,6 +154,7 @@ struct _GApplicationPrivate gchar *id; GActionGroup *actions; + GMenuModel *menu; guint inactivity_timeout_id; guint inactivity_timeout; @@ -171,7 +177,8 @@ enum PROP_IS_REGISTERED, PROP_IS_REMOTE, PROP_INACTIVITY_TIMEOUT, - PROP_ACTION_GROUP + PROP_ACTION_GROUP, + PROP_MENU }; enum @@ -393,6 +400,11 @@ g_application_set_property (GObject *object, g_value_get_object (value)); break; + case PROP_MENU: + g_application_set_menu (application, + g_value_get_object (value)); + break; + default: g_assert_not_reached (); } @@ -405,7 +417,7 @@ g_application_set_property (GObject *object, * * Sets or unsets the group of actions associated with the application. * - * These actions are the actions that can be remotely invoked. + * These actions can be invoked remotely. * * It is an error to call this function after the application has been * registered. @@ -428,6 +440,54 @@ g_application_set_action_group (GApplication *application, g_object_ref (application->priv->actions); } +/** + * g_application_set_menu: + * @application: a #GApplication + * @menu: (allow-none): a #GMenuModel, or %NULL + * + * Sets or unsets the menu associated with the application. The menu + * provides representation data for the exported actions of @application. + * + * It is an error to call this function after the application has been + * registered. + * + * Since: 2.32 + */ +void +g_application_set_menu (GApplication *application, + GMenuModel *menu) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + g_return_if_fail (!application->priv->is_registered); + + if (application->priv->menu != NULL) + g_object_unref (application->priv->menu); + + application->priv->menu = menu; + + if (application->priv->menu != NULL) + g_object_ref (application->priv->menu); +} + +/** + * g_application_get_menu: + * @application: a #GApplication + * + * Returns the menu model that has been set + * with g_application_set_menu(). + * + * Returns: the #GMenuModel associated with @application + * + * Since: 2.32 + */ +GMenuModel * +g_application_get_menu (GApplication *application) +{ + g_return_val_if_fail (G_IS_APPLICATION (application), NULL); + + return application->priv->menu; +} + static void g_application_get_property (GObject *object, guint prop_id, @@ -563,6 +623,13 @@ g_application_class_init (GApplicationClass *class) G_TYPE_ACTION_GROUP, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_MENU, + g_param_spec_object ("menu", + P_("Menu model"), + P_("The menu that the application exports"), + G_TYPE_MENU_MODEL, + G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); + /** * GApplication::startup: * @application: the application diff --git a/gio/gapplication.h b/gio/gapplication.h index c432a3311..2778ac0d2 100644 --- a/gio/gapplication.h +++ b/gio/gapplication.h @@ -151,6 +151,10 @@ void g_application_set_flags (GApplic void g_application_set_action_group (GApplication *application, GActionGroup *action_group); +void g_application_set_menu (GApplication *application, + GMenuModel *menu); +GMenuModel *g_application_get_menu (GApplication *application); + gboolean g_application_get_is_registered (GApplication *application); gboolean g_application_get_is_remote (GApplication *application); diff --git a/gio/gapplicationimpl-dbus.c b/gio/gapplicationimpl-dbus.c index ef4eaee71..27cd39cd4 100644 --- a/gio/gapplicationimpl-dbus.c +++ b/gio/gapplicationimpl-dbus.c @@ -29,6 +29,7 @@ #include "gdbusconnection.h" #include "gdbusintrospection.h" #include "gdbuserror.h" +#include "gmenuexporter.h" #include #include @@ -118,6 +119,7 @@ struct _GApplicationImpl gchar *object_path; guint object_id; gboolean actions_exported; + gboolean menu_exported; gpointer app; }; @@ -238,6 +240,8 @@ g_application_impl_destroy (GApplicationImpl *impl) impl->object_id); if (impl->actions_exported) g_action_group_exporter_stop (impl->app); + if (impl->menu_exported) + g_menu_exporter_stop (g_application_get_menu (impl->app)); g_dbus_connection_call (impl->session_bus, "org.freedesktop.DBus", @@ -337,6 +341,30 @@ g_application_impl_register (GApplication *application, } impl->actions_exported = TRUE; + if (g_application_get_menu (impl->app)) + { + if (!g_menu_exporter_export (impl->session_bus, + impl->object_path, + g_application_get_menu (impl->app), + error)) + { + g_action_group_exporter_stop (impl->app); + impl->actions_exported = FALSE; + + g_dbus_connection_unregister_object (impl->session_bus, + impl->object_id); + + g_object_unref (impl->session_bus); + g_free (impl->object_path); + impl->session_bus = NULL; + impl->object_path = NULL; + + g_slice_free (GApplicationImpl, impl); + return NULL; + } + impl->menu_exported = TRUE; + } + /* DBUS_NAME_FLAG_DO_NOT_QUEUE: 0x4 */ reply = g_dbus_connection_call_sync (impl->session_bus, "org.freedesktop.DBus", @@ -358,6 +386,12 @@ g_application_impl_register (GApplication *application, g_action_group_exporter_stop (impl->app); impl->actions_exported = FALSE; + if (impl->menu_exported) + { + g_menu_exporter_stop (g_application_get_menu (impl->app)); + impl->menu_exported = FALSE; + } + g_object_unref (impl->session_bus); g_free (impl->object_path); impl->session_bus = NULL; @@ -392,6 +426,11 @@ g_application_impl_register (GApplication *application, impl->object_id = 0; g_action_group_exporter_stop (impl->app); impl->actions_exported = FALSE; + if (impl->menu_exported) + { + g_menu_exporter_stop (g_application_get_menu (impl->app)); + impl->menu_exported = FALSE; + } if (flags & G_APPLICATION_IS_SERVICE) { diff --git a/gio/gio.symbols b/gio/gio.symbols index e382ae677..76f6b606c 100644 --- a/gio/gio.symbols +++ b/gio/gio.symbols @@ -19,6 +19,7 @@ g_application_get_flags g_application_get_inactivity_timeout g_application_get_is_registered g_application_get_is_remote +g_application_get_menu g_application_hold g_application_id_is_valid g_application_new @@ -27,6 +28,7 @@ g_application_register g_application_release g_application_run g_application_set_action_group +g_application_set_menu g_application_set_application_id g_application_set_default g_application_set_flags