diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt index add972f12..52ebbbb92 100644 --- a/docs/reference/gio/gio-sections.txt +++ b/docs/reference/gio/gio-sections.txt @@ -2953,6 +2953,9 @@ g_application_open g_application_run g_application_set_default g_application_get_default + +g_application_mark_busy +g_application_unmark_busy G_TYPE_APPLICATION G_APPLICATION diff --git a/gio/gapplication.c b/gio/gapplication.c index 36c91bdac..638bb31c8 100644 --- a/gio/gapplication.c +++ b/gio/gapplication.c @@ -239,6 +239,7 @@ struct _GApplicationPrivate guint inactivity_timeout_id; guint inactivity_timeout; guint use_count; + guint busy_count; guint is_registered : 1; guint is_remote : 1; @@ -1850,5 +1851,62 @@ g_application_quit (GApplication *application) application->priv->must_quit_now = TRUE; } +/** + * g_application_mark_busy: + * @application: a #GApplication + * + * Increases the busy count of @application. + * + * Use this function to indicate that the application is busy, for instance + * while a long running operation is pending. + * + * The busy state will be exposed to other processes, so a session shell will + * use that information to indicate the state to the user (e.g. with a + * spinner). + * + * To cancel the busy indication, use g_application_unmark_busy(). + * + * Since: 2.38 + **/ +void +g_application_mark_busy (GApplication *application) +{ + gboolean was_busy; + + g_return_if_fail (G_IS_APPLICATION (application)); + + was_busy = (application->priv->busy_count > 0); + application->priv->busy_count++; + + if (!was_busy) + g_application_impl_set_busy_state (application->priv->impl, TRUE); +} + +/** + * g_application_unmark_busy: + * @application: a #GApplication + * + * Decreases the busy count of @application. + * + * When the busy count reaches zero, the new state will be propagated + * to other processes. + * + * This function must only be called to cancel the effect of a previous + * call to g_application_mark_busy(). + * + * Since: 2.38 + **/ +void +g_application_unmark_busy (GApplication *application) +{ + g_return_if_fail (G_IS_APPLICATION (application)); + g_return_if_fail (application->priv->busy_count > 0); + + application->priv->busy_count--; + + if (application->priv->busy_count == 0) + g_application_impl_set_busy_state (application->priv->impl, FALSE); +} + /* Epilogue {{{1 */ /* vim:set foldmethod=marker: */ diff --git a/gio/gapplication.h b/gio/gapplication.h index 7829892c7..5878a7f8e 100644 --- a/gio/gapplication.h +++ b/gio/gapplication.h @@ -196,6 +196,11 @@ GApplication * g_application_get_default (void); GLIB_AVAILABLE_IN_2_32 void g_application_set_default (GApplication *application); +GLIB_AVAILABLE_IN_2_38 +void g_application_mark_busy (GApplication *application); +GLIB_AVAILABLE_IN_2_38 +void g_application_unmark_busy (GApplication *application); + G_END_DECLS #endif /* __G_APPLICATION_H__ */ diff --git a/gio/gapplicationimpl-dbus.c b/gio/gapplicationimpl-dbus.c index 5afb0d05a..68b0d288a 100644 --- a/gio/gapplicationimpl-dbus.c +++ b/gio/gapplicationimpl-dbus.c @@ -67,6 +67,7 @@ static const gchar org_gtk_Application_xml[] = "" "" "" + "" "" ""; @@ -99,6 +100,7 @@ struct _GApplicationImpl gboolean properties_live; gboolean primary; + gboolean busy; GApplication *app; }; @@ -106,6 +108,46 @@ struct _GApplicationImpl static GApplicationCommandLine * g_dbus_command_line_new (GDBusMethodInvocation *invocation); +static GVariant * +g_application_impl_get_property (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GError **error, + gpointer user_data) +{ + GApplicationImpl *impl = user_data; + + if (strcmp (property_name, "Busy") == 0) + return g_variant_new_boolean (impl->busy); + + g_assert_not_reached (); + + return NULL; +} + +static void +send_property_change (GApplicationImpl *impl) +{ + GVariantBuilder builder; + + g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); + g_variant_builder_add (&builder, + "{sv}", + "Busy", g_variant_new_boolean (impl->busy)); + + g_dbus_connection_emit_signal (impl->session_bus, + NULL, + impl->object_path, + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + g_variant_new ("(sa{sv}as)", + "org.gtk.Application", + &builder, + NULL), + NULL); +} static void g_application_impl_method_call (GDBusConnection *connection, @@ -229,6 +271,8 @@ g_application_impl_attempt_primary (GApplicationImpl *impl, { const static GDBusInterfaceVTable vtable = { g_application_impl_method_call, + g_application_impl_get_property, + NULL /* set_property */ }; GApplicationClass *app_class = G_APPLICATION_GET_CLASS (impl->app); GVariant *reply; @@ -352,6 +396,17 @@ g_application_impl_stop_primary (GApplicationImpl *impl) } } +void +g_application_impl_set_busy_state (GApplicationImpl *impl, + gboolean busy) +{ + if (impl->busy != busy) + { + impl->busy = busy; + send_property_change (impl); + } +} + void g_application_impl_destroy (GApplicationImpl *impl) { diff --git a/gio/gapplicationimpl.h b/gio/gapplicationimpl.h index 8743d0fd2..85d7a3e0c 100644 --- a/gio/gapplicationimpl.h +++ b/gio/gapplicationimpl.h @@ -39,3 +39,6 @@ void g_application_impl_flush (GApplic GDBusConnection * g_application_impl_get_dbus_connection (GApplicationImpl *impl); const gchar * g_application_impl_get_dbus_object_path (GApplicationImpl *impl); + +void g_application_impl_set_busy_state (GApplicationImpl *impl, + gboolean busy);