gappinfo: Add launch-started signal

Emit this when we're about to spawn or DBus activate a GAppInfo.  This
allows lauchers to keep the appinfo associated with a startup id.

We use a GVariant to allow for future exansion of the supplied data.
This commit is contained in:
Guido Günther 2021-09-29 08:19:09 +02:00
parent 5890b2bdea
commit 7665b748bb
4 changed files with 90 additions and 3 deletions

View File

@ -1103,6 +1103,7 @@ g_app_info_delete (GAppInfo *appinfo)
enum {
LAUNCH_FAILED,
LAUNCH_STARTED,
LAUNCHED,
LAST_SIGNAL
};
@ -1160,6 +1161,41 @@ g_app_launch_context_class_init (GAppLaunchContextClass *klass)
NULL, NULL, NULL,
G_TYPE_NONE, 1, G_TYPE_STRING);
/**
* GAppLaunchContext::launch-started:
* @context: the object emitting the signal
* @info: the #GAppInfo that is about to be launched
* @platform_data: (nullable): additional platform-specific data for this launch
*
* The #GAppLaunchContext::launch-started signal is emitted when a #GAppInfo is
* about to be launched. If non-null the @platform_data is an
* GVariant dictionary mapping strings to variants (ie `a{sv}`), which
* contains additional, platform-specific data about this launch. On
* UNIX, at least the `startup-notification-id` keys will be
* present.
*
* The value of the `startup-notification-id` key (type `s`) is a startup
* notification ID corresponding to the format from the [startup-notification
* specification](https://specifications.freedesktop.org/startup-notification-spec/startup-notification-0.1.txt).
* It allows tracking the progress of the launchee through startup.
*
* It is guaranteed that this signal is followed by either a #GAppLaunchContext::launched or
* #GAppLaunchContext::launch-failed signal.
*
* Since: 2.72
*/
signals[LAUNCH_STARTED] = g_signal_new (I_("launch-started"),
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GAppLaunchContextClass, launch_started),
NULL, NULL,
_g_cclosure_marshal_VOID__OBJECT_VARIANT,
G_TYPE_NONE, 2,
G_TYPE_APP_INFO, G_TYPE_VARIANT);
g_signal_set_va_marshaller (signals[LAUNCH_STARTED],
G_TYPE_FROM_CLASS (klass),
_g_cclosure_marshal_VOID__OBJECT_VARIANTv);
/**
* GAppLaunchContext::launched:
* @context: the object emitting the signal

View File

@ -293,12 +293,14 @@ struct _GAppLaunchContextClass
void (* launched) (GAppLaunchContext *context,
GAppInfo *info,
GVariant *platform_data);
void (* launch_started) (GAppLaunchContext *context,
GAppInfo *info,
GVariant *platform_data);
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
};
GLIB_AVAILABLE_IN_ALL

View File

@ -2731,6 +2731,26 @@ notify_desktop_launch (GDBusConnection *session_bus,
g_object_unref (msg);
}
static void
emit_launch_started (GAppLaunchContext *context,
GDesktopAppInfo *info,
const gchar *startup_id)
{
GVariantBuilder builder;
GVariant *platform_data = NULL;
if (startup_id)
{
g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
g_variant_builder_add (&builder, "{sv}",
"startup-notification-id",
g_variant_new_string (startup_id));
platform_data = g_variant_ref_sink (g_variant_builder_end (&builder));
}
g_signal_emit_by_name (context, "launch-started", info, platform_data);
g_clear_pointer (&platform_data, g_variant_unref);
}
#define _SPAWN_FLAGS_DEFAULT (G_SPAWN_SEARCH_PATH)
static gboolean
@ -2826,6 +2846,8 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
}
g_list_free_full (launched_files, g_object_unref);
emit_launch_started (launch_context, info, sn_id);
}
/* Wrap the @argv in a command which will set the
@ -3057,6 +3079,9 @@ launch_uris_with_dbus (GDesktopAppInfo *info,
g_variant_dict_init (&dict, platform_data);
g_variant_dict_lookup (&dict, "desktop-startup-id", "s", &data->startup_id);
if (launch_context)
emit_launch_started (launch_context, info, data->startup_id);
g_dbus_connection_call (session_bus, info->app_id, object_path, "org.freedesktop.Application",
uris ? "Open" : "Activate", g_variant_builder_end (&builder),
NULL, G_DBUS_CALL_FLAGS_NONE, -1,

View File

@ -728,6 +728,20 @@ test_show_in (void)
assert_shown ("invalid-desktop.desktop", FALSE, "../invalid/desktop:../invalid/desktop");
}
static void
on_launch_started (GAppLaunchContext *context, GAppInfo *info, GVariant *platform_data, gpointer data)
{
gboolean *invoked = data;
g_assert_true (G_IS_APP_LAUNCH_CONTEXT (context));
g_assert_true (G_IS_APP_INFO (info));
/* Our default context doesn't fill in any platform data */
g_assert_null (platform_data);
g_assert_false (*invoked);
*invoked = TRUE;
}
/* Test g_desktop_app_info_launch_uris_as_manager() and
* g_desktop_app_info_launch_uris_as_manager_with_fds()
*/
@ -738,6 +752,8 @@ test_launch_as_manager (void)
GError *error = NULL;
gboolean retval;
const gchar *path;
gboolean invoked = FALSE;
GAppLaunchContext *context;
if (g_getenv ("DISPLAY") == NULL || g_getenv ("DISPLAY")[0] == '\0')
{
@ -754,23 +770,31 @@ test_launch_as_manager (void)
return;
}
retval = g_desktop_app_info_launch_uris_as_manager (appinfo, NULL, NULL, 0,
context = g_app_launch_context_new ();
g_signal_connect (context, "launch-started",
G_CALLBACK (on_launch_started),
&invoked);
retval = g_desktop_app_info_launch_uris_as_manager (appinfo, NULL, context, 0,
NULL, NULL,
NULL, NULL,
&error);
g_assert_no_error (error);
g_assert_true (retval);
g_assert_true (invoked);
invoked = FALSE;
retval = g_desktop_app_info_launch_uris_as_manager_with_fds (appinfo,
NULL, NULL, 0,
NULL, context, 0,
NULL, NULL,
NULL, NULL,
-1, -1, -1,
&error);
g_assert_no_error (error);
g_assert_true (retval);
g_assert_true (invoked);
g_object_unref (appinfo);
g_assert_finalize_object (context);
}
int