2007-12-13 05:16:33 +00:00
|
|
|
|
/* gdkapplaunchcontext-x11.c - Gtk+ implementation for GAppLaunchContext
|
|
|
|
|
|
|
|
|
|
Copyright (C) 2007 Red Hat, Inc.
|
|
|
|
|
|
|
|
|
|
The Gnome Library is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU Library General Public License as
|
|
|
|
|
published by the Free Software Foundation; either version 2 of the
|
|
|
|
|
License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
The Gnome Library is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public
|
2012-02-27 13:01:10 +00:00
|
|
|
|
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
|
|
|
|
Author: Alexander Larsson <alexl@redhat.com>
|
|
|
|
|
*/
|
|
|
|
|
|
2008-06-22 14:28:52 +00:00
|
|
|
|
#include "config.h"
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
2010-12-21 07:32:15 +00:00
|
|
|
|
#include "gdkx11applaunchcontext.h"
|
2010-12-11 05:14:53 +00:00
|
|
|
|
#include "gdkapplaunchcontextprivate.h"
|
2022-09-24 03:33:42 +00:00
|
|
|
|
#include <glib/gi18n-lib.h>
|
2010-12-16 03:09:35 +00:00
|
|
|
|
#include "gdkprivate-x11.h"
|
2018-02-07 05:00:01 +00:00
|
|
|
|
#include "gdkdisplay-x11.h"
|
2022-09-24 03:23:27 +00:00
|
|
|
|
#include "gdkprivate.h"
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
2010-10-15 02:05:51 +00:00
|
|
|
|
#include <glib.h>
|
|
|
|
|
#include <gio/gdesktopappinfo.h>
|
|
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <unistd.h>
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
|
|
|
|
static char *
|
2010-11-28 04:12:09 +00:00
|
|
|
|
get_display_name (GFile *file,
|
|
|
|
|
GFileInfo *info)
|
2007-12-13 05:16:33 +00:00
|
|
|
|
{
|
|
|
|
|
char *name, *tmp;
|
|
|
|
|
|
|
|
|
|
name = NULL;
|
|
|
|
|
if (info)
|
2010-11-28 04:12:09 +00:00
|
|
|
|
name = g_strdup (g_file_info_get_display_name (info));
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
|
{
|
|
|
|
|
name = g_file_get_basename (file);
|
2021-04-19 20:39:53 +00:00
|
|
|
|
if (name == NULL)
|
|
|
|
|
name = g_file_get_uri (file);
|
|
|
|
|
|
2007-12-13 05:16:33 +00:00
|
|
|
|
if (!g_utf8_validate (name, -1, NULL))
|
2010-11-28 04:12:09 +00:00
|
|
|
|
{
|
|
|
|
|
tmp = name;
|
|
|
|
|
name =
|
|
|
|
|
g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, TRUE);
|
|
|
|
|
g_free (tmp);
|
|
|
|
|
}
|
2007-12-13 05:16:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GIcon *
|
2010-11-28 04:12:09 +00:00
|
|
|
|
get_icon (GFile *file,
|
|
|
|
|
GFileInfo *info)
|
2007-12-13 05:16:33 +00:00
|
|
|
|
{
|
|
|
|
|
GIcon *icon;
|
|
|
|
|
|
|
|
|
|
icon = NULL;
|
2010-11-28 04:12:09 +00:00
|
|
|
|
|
2007-12-13 05:16:33 +00:00
|
|
|
|
if (info)
|
|
|
|
|
{
|
|
|
|
|
icon = g_file_info_get_icon (info);
|
|
|
|
|
if (icon)
|
2010-11-28 04:12:09 +00:00
|
|
|
|
g_object_ref (icon);
|
2007-12-13 05:16:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
gicon_to_string (GIcon *icon)
|
|
|
|
|
{
|
|
|
|
|
GFile *file;
|
|
|
|
|
const char *const *names;
|
|
|
|
|
|
|
|
|
|
if (G_IS_FILE_ICON (icon))
|
|
|
|
|
{
|
|
|
|
|
file = g_file_icon_get_file (G_FILE_ICON (icon));
|
|
|
|
|
if (file)
|
2010-11-28 04:12:09 +00:00
|
|
|
|
return g_file_get_path (file);
|
2007-12-13 05:16:33 +00:00
|
|
|
|
}
|
|
|
|
|
else if (G_IS_THEMED_ICON (icon))
|
|
|
|
|
{
|
|
|
|
|
names = g_themed_icon_get_names (G_THEMED_ICON (icon));
|
|
|
|
|
if (names)
|
2010-11-28 04:12:09 +00:00
|
|
|
|
return g_strdup (names[0]);
|
2007-12-13 05:16:33 +00:00
|
|
|
|
}
|
2008-08-03 19:28:05 +00:00
|
|
|
|
else if (G_IS_EMBLEMED_ICON (icon))
|
|
|
|
|
{
|
|
|
|
|
GIcon *base;
|
|
|
|
|
|
|
|
|
|
base = g_emblemed_icon_get_icon (G_EMBLEMED_ICON (icon));
|
|
|
|
|
|
|
|
|
|
return gicon_to_string (base);
|
|
|
|
|
}
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
end_startup_notification (GdkDisplay *display,
|
2010-11-28 04:12:09 +00:00
|
|
|
|
const char *startup_id)
|
2007-12-13 05:16:33 +00:00
|
|
|
|
{
|
|
|
|
|
gdk_x11_display_broadcast_startup_message (display, "remove",
|
2010-11-28 04:12:09 +00:00
|
|
|
|
"ID", startup_id,
|
|
|
|
|
NULL);
|
2007-12-13 05:16:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* This should be fairly long, as it's confusing to users if a startup
|
2014-02-07 18:32:47 +00:00
|
|
|
|
* ends when it shouldn’t (it appears that the startup failed, and
|
2007-12-13 05:16:33 +00:00
|
|
|
|
* they have to relaunch the app). Also the timeout only matters when
|
2014-02-07 18:32:47 +00:00
|
|
|
|
* there are bugs and apps don’t end their own startup sequence.
|
2007-12-13 05:16:33 +00:00
|
|
|
|
*
|
|
|
|
|
* This timeout is a "last resort" timeout that ignores whether the
|
|
|
|
|
* startup sequence has shown activity or not. Metacity and the
|
|
|
|
|
* tasklist have smarter, and correspondingly able-to-be-shorter
|
2014-02-07 18:32:47 +00:00
|
|
|
|
* timeouts. The reason our timeout is dumb is that we don’t monitor
|
|
|
|
|
* the sequence (don’t use an SnMonitorContext)
|
2007-12-13 05:16:33 +00:00
|
|
|
|
*/
|
2010-12-21 07:32:15 +00:00
|
|
|
|
#define STARTUP_TIMEOUT_LENGTH_SECONDS 30
|
2020-07-31 14:54:41 +00:00
|
|
|
|
#define STARTUP_TIMEOUT_LENGTH (STARTUP_TIMEOUT_LENGTH_SECONDS * 1000) /* ms */
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
2010-12-21 07:32:15 +00:00
|
|
|
|
typedef struct
|
2007-12-13 05:16:33 +00:00
|
|
|
|
{
|
|
|
|
|
GdkDisplay *display;
|
|
|
|
|
char *startup_id;
|
2020-07-31 14:54:41 +00:00
|
|
|
|
gint64 time;
|
2007-12-13 05:16:33 +00:00
|
|
|
|
} StartupNotificationData;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
free_startup_notification_data (gpointer data)
|
|
|
|
|
{
|
|
|
|
|
StartupNotificationData *sn_data = data;
|
|
|
|
|
|
|
|
|
|
g_object_unref (sn_data->display);
|
|
|
|
|
g_free (sn_data->startup_id);
|
|
|
|
|
g_free (sn_data);
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-21 07:32:15 +00:00
|
|
|
|
typedef struct
|
2007-12-13 05:16:33 +00:00
|
|
|
|
{
|
|
|
|
|
GSList *contexts;
|
|
|
|
|
guint timeout_id;
|
|
|
|
|
} StartupTimeoutData;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
free_startup_timeout (void *data)
|
|
|
|
|
{
|
|
|
|
|
StartupTimeoutData *std;
|
|
|
|
|
|
|
|
|
|
std = data;
|
|
|
|
|
|
2015-07-31 21:57:04 +00:00
|
|
|
|
g_slist_free_full (std->contexts, free_startup_notification_data);
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
|
|
|
|
if (std->timeout_id != 0)
|
|
|
|
|
{
|
|
|
|
|
g_source_remove (std->timeout_id);
|
|
|
|
|
std->timeout_id = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_free (std);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
startup_timeout (void *data)
|
|
|
|
|
{
|
|
|
|
|
StartupTimeoutData *std;
|
|
|
|
|
GSList *tmp;
|
2020-07-31 14:54:41 +00:00
|
|
|
|
gint64 now;
|
2007-12-13 05:16:33 +00:00
|
|
|
|
int min_timeout;
|
|
|
|
|
|
|
|
|
|
std = data;
|
|
|
|
|
|
|
|
|
|
min_timeout = STARTUP_TIMEOUT_LENGTH;
|
|
|
|
|
|
2020-07-31 14:54:41 +00:00
|
|
|
|
now = g_get_monotonic_time ();
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
|
|
|
|
tmp = std->contexts;
|
|
|
|
|
while (tmp != NULL)
|
|
|
|
|
{
|
|
|
|
|
StartupNotificationData *sn_data;
|
|
|
|
|
GSList *next;
|
|
|
|
|
double elapsed;
|
|
|
|
|
|
|
|
|
|
sn_data = tmp->data;
|
|
|
|
|
next = tmp->next;
|
|
|
|
|
|
2020-07-31 14:54:41 +00:00
|
|
|
|
elapsed = (now - sn_data->time) / 1000.0;
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
|
|
|
|
if (elapsed >= STARTUP_TIMEOUT_LENGTH)
|
2010-11-28 04:12:09 +00:00
|
|
|
|
{
|
|
|
|
|
std->contexts = g_slist_remove (std->contexts, sn_data);
|
|
|
|
|
end_startup_notification (sn_data->display, sn_data->startup_id);
|
|
|
|
|
free_startup_notification_data (sn_data);
|
|
|
|
|
}
|
2007-12-13 05:16:33 +00:00
|
|
|
|
else
|
2010-11-28 04:12:09 +00:00
|
|
|
|
{
|
|
|
|
|
min_timeout = MIN (min_timeout, (STARTUP_TIMEOUT_LENGTH - elapsed));
|
|
|
|
|
}
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
|
|
|
|
tmp = next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (std->contexts == NULL)
|
|
|
|
|
std->timeout_id = 0;
|
2013-10-22 13:43:43 +00:00
|
|
|
|
else {
|
2007-12-13 05:16:33 +00:00
|
|
|
|
std->timeout_id = g_timeout_add_seconds ((min_timeout + 500)/1000, startup_timeout, std);
|
2021-07-26 21:03:15 +00:00
|
|
|
|
gdk_source_set_static_name_by_id (std->timeout_id, "[gtk] startup_timeout");
|
2013-10-22 13:43:43 +00:00
|
|
|
|
}
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
|
|
|
|
/* always remove this one, but we may have reinstalled another one. */
|
2012-01-31 00:12:27 +00:00
|
|
|
|
return G_SOURCE_REMOVE;
|
2007-12-13 05:16:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2017-11-17 15:18:20 +00:00
|
|
|
|
add_startup_timeout (GdkX11Screen *screen,
|
|
|
|
|
const char *startup_id)
|
2007-12-13 05:16:33 +00:00
|
|
|
|
{
|
|
|
|
|
StartupTimeoutData *data;
|
|
|
|
|
StartupNotificationData *sn_data;
|
|
|
|
|
|
|
|
|
|
data = g_object_get_data (G_OBJECT (screen), "appinfo-startup-data");
|
|
|
|
|
|
|
|
|
|
if (data == NULL)
|
|
|
|
|
{
|
|
|
|
|
data = g_new (StartupTimeoutData, 1);
|
|
|
|
|
data->contexts = NULL;
|
|
|
|
|
data->timeout_id = 0;
|
|
|
|
|
|
|
|
|
|
g_object_set_data_full (G_OBJECT (screen), "appinfo-startup-data",
|
2010-11-28 04:12:09 +00:00
|
|
|
|
data, free_startup_timeout);
|
2007-12-13 05:16:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sn_data = g_new (StartupNotificationData, 1);
|
2017-11-01 23:41:45 +00:00
|
|
|
|
sn_data->display = g_object_ref (GDK_SCREEN_DISPLAY (screen));
|
2007-12-13 05:16:33 +00:00
|
|
|
|
sn_data->startup_id = g_strdup (startup_id);
|
2020-07-31 14:54:41 +00:00
|
|
|
|
sn_data->time = g_get_monotonic_time ();
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
|
|
|
|
data->contexts = g_slist_prepend (data->contexts, sn_data);
|
|
|
|
|
|
2013-10-22 13:43:43 +00:00
|
|
|
|
if (data->timeout_id == 0) {
|
2007-12-13 05:16:33 +00:00
|
|
|
|
data->timeout_id = g_timeout_add_seconds (STARTUP_TIMEOUT_LENGTH_SECONDS,
|
2010-11-28 04:12:09 +00:00
|
|
|
|
startup_timeout, data);
|
2021-07-26 21:03:15 +00:00
|
|
|
|
gdk_source_set_static_name_by_id (data->timeout_id, "[gtk] startup_timeout");
|
2013-10-22 13:43:43 +00:00
|
|
|
|
}
|
2007-12-13 05:16:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-12-09 06:08:05 +00:00
|
|
|
|
static char *
|
2010-12-21 07:32:15 +00:00
|
|
|
|
gdk_x11_app_launch_context_get_startup_notify_id (GAppLaunchContext *context,
|
2010-12-09 06:08:05 +00:00
|
|
|
|
GAppInfo *info,
|
|
|
|
|
GList *files)
|
2007-12-13 05:16:33 +00:00
|
|
|
|
{
|
|
|
|
|
static int sequence = 0;
|
|
|
|
|
GdkDisplay *display;
|
2017-11-17 15:18:20 +00:00
|
|
|
|
GdkX11Screen *screen;
|
2007-12-13 05:16:33 +00:00
|
|
|
|
int files_count;
|
|
|
|
|
char *description;
|
|
|
|
|
char *icon_name;
|
|
|
|
|
const char *binary_name;
|
2010-03-13 23:10:25 +00:00
|
|
|
|
const char *application_id;
|
2007-12-13 05:16:33 +00:00
|
|
|
|
char *screen_str;
|
|
|
|
|
char *workspace_str;
|
|
|
|
|
GIcon *icon;
|
|
|
|
|
guint32 timestamp;
|
|
|
|
|
char *startup_id;
|
2010-11-28 04:12:09 +00:00
|
|
|
|
GFileInfo *fileinfo;
|
2010-12-11 05:14:53 +00:00
|
|
|
|
GdkAppLaunchContext *ctx;
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
2023-01-04 21:35:56 +00:00
|
|
|
|
if (!info)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2010-12-11 05:14:53 +00:00
|
|
|
|
ctx = GDK_APP_LAUNCH_CONTEXT (context);
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
2010-12-11 05:14:53 +00:00
|
|
|
|
display = ctx->display;
|
2017-11-01 22:06:24 +00:00
|
|
|
|
screen = GDK_X11_DISPLAY (display)->screen;
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
2010-11-28 04:12:09 +00:00
|
|
|
|
fileinfo = NULL;
|
|
|
|
|
|
2007-12-13 05:16:33 +00:00
|
|
|
|
files_count = g_list_length (files);
|
|
|
|
|
if (files_count == 0)
|
2010-11-28 04:12:09 +00:00
|
|
|
|
{
|
2019-07-24 13:51:22 +00:00
|
|
|
|
description = g_strdup_printf (_("Starting “%s”"), g_app_info_get_name (info));
|
2010-11-28 04:12:09 +00:00
|
|
|
|
}
|
2007-12-13 05:16:33 +00:00
|
|
|
|
else if (files_count == 1)
|
2010-09-03 16:48:50 +00:00
|
|
|
|
{
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *display_name;
|
2010-11-28 04:12:09 +00:00
|
|
|
|
|
|
|
|
|
if (g_file_is_native (files->data))
|
|
|
|
|
fileinfo = g_file_query_info (files->data,
|
|
|
|
|
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
|
|
|
|
|
G_FILE_ATTRIBUTE_STANDARD_ICON,
|
|
|
|
|
0, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
display_name = get_display_name (files->data, fileinfo);
|
2019-07-24 13:51:22 +00:00
|
|
|
|
description = g_strdup_printf (_("Opening “%s”"), display_name);
|
2010-09-03 16:48:50 +00:00
|
|
|
|
g_free (display_name);
|
|
|
|
|
}
|
2007-12-13 05:16:33 +00:00
|
|
|
|
else
|
2009-06-15 22:04:49 +00:00
|
|
|
|
description = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE,
|
2010-11-28 04:12:09 +00:00
|
|
|
|
"Opening %d Item",
|
|
|
|
|
"Opening %d Items",
|
|
|
|
|
files_count), files_count);
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
|
|
|
|
icon_name = NULL;
|
2010-12-11 05:14:53 +00:00
|
|
|
|
if (ctx->icon_name)
|
|
|
|
|
icon_name = g_strdup (ctx->icon_name);
|
2007-12-13 05:16:33 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
icon = NULL;
|
|
|
|
|
|
2010-12-11 05:14:53 +00:00
|
|
|
|
if (ctx->icon != NULL)
|
|
|
|
|
icon = g_object_ref (ctx->icon);
|
2007-12-13 05:16:33 +00:00
|
|
|
|
else if (files_count == 1)
|
2010-11-28 04:12:09 +00:00
|
|
|
|
icon = get_icon (files->data, fileinfo);
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
|
|
|
|
if (icon == NULL)
|
2010-11-28 04:12:09 +00:00
|
|
|
|
{
|
|
|
|
|
icon = g_app_info_get_icon (info);
|
Fix a segfault if the GAppInfo does not have an icon
This fixes the following backtrace:
0 g_logv (log_domain=0x7ffff60461a4 "GLib-GObject", log_level=<optimized out>,
format=0x7ffff599c322 "%s: assertion `%s' failed", args1=0x7fffffffc418) at gmessages.c:577
1 0x00007ffff59312d2 in g_log (log_domain=<optimized out>, log_level=<optimized out>,
format=<optimized out>) at gmessages.c:591
2 0x00007ffff601c3c7 in g_object_ref (_object=0x0) at gobject.c:2648
3 0x00007ffff7721e22 in gdk_x11_app_launch_context_get_startup_notify_id (context=<optimized out>,
info=0x7fffe8004b40, files=<optimized out>) at gdkapplaunchcontext-x11.c:331
4 0x00007ffff62e60d0 in _g_desktop_app_info_launch_uris_internal (appinfo=0x7fffe8004b40, uris=0x0,
launch_context=0x7fffe401c800, spawn_flags=G_SPAWN_SEARCH_PATH, user_setup=0, user_setup_data=0x0,
pid_callback=0, pid_callback_data=0x0, error=0x7fffffffc848) at gdesktopappinfo.c:1269
5 0x00007ffff62e630a in g_desktop_app_info_launch_uris (appinfo=<optimized out>, uris=<optimized out>,
launch_context=<optimized out>, error=<optimized out>) at gdesktopappinfo.c:1341
6 0x00007ffff62e636b in g_desktop_app_info_launch (appinfo=0x7fffe8004b40, files=<optimized out>,
launch_context=0x7fffe401c800, error=0x7fffffffc848) at gdesktopappinfo.c:1388
2011-09-13 15:16:28 +00:00
|
|
|
|
if (icon != NULL)
|
|
|
|
|
g_object_ref (icon);
|
2010-11-28 04:12:09 +00:00
|
|
|
|
}
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
Fix a segfault if the GAppInfo does not have an icon
This fixes the following backtrace:
0 g_logv (log_domain=0x7ffff60461a4 "GLib-GObject", log_level=<optimized out>,
format=0x7ffff599c322 "%s: assertion `%s' failed", args1=0x7fffffffc418) at gmessages.c:577
1 0x00007ffff59312d2 in g_log (log_domain=<optimized out>, log_level=<optimized out>,
format=<optimized out>) at gmessages.c:591
2 0x00007ffff601c3c7 in g_object_ref (_object=0x0) at gobject.c:2648
3 0x00007ffff7721e22 in gdk_x11_app_launch_context_get_startup_notify_id (context=<optimized out>,
info=0x7fffe8004b40, files=<optimized out>) at gdkapplaunchcontext-x11.c:331
4 0x00007ffff62e60d0 in _g_desktop_app_info_launch_uris_internal (appinfo=0x7fffe8004b40, uris=0x0,
launch_context=0x7fffe401c800, spawn_flags=G_SPAWN_SEARCH_PATH, user_setup=0, user_setup_data=0x0,
pid_callback=0, pid_callback_data=0x0, error=0x7fffffffc848) at gdesktopappinfo.c:1269
5 0x00007ffff62e630a in g_desktop_app_info_launch_uris (appinfo=<optimized out>, uris=<optimized out>,
launch_context=<optimized out>, error=<optimized out>) at gdesktopappinfo.c:1341
6 0x00007ffff62e636b in g_desktop_app_info_launch (appinfo=0x7fffe8004b40, files=<optimized out>,
launch_context=0x7fffe401c800, error=0x7fffffffc848) at gdesktopappinfo.c:1388
2011-09-13 15:16:28 +00:00
|
|
|
|
if (icon != NULL)
|
|
|
|
|
{
|
|
|
|
|
icon_name = gicon_to_string (icon);
|
|
|
|
|
g_object_unref (icon);
|
|
|
|
|
}
|
2007-12-13 05:16:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
binary_name = g_app_info_get_executable (info);
|
|
|
|
|
|
2010-12-11 05:14:53 +00:00
|
|
|
|
timestamp = ctx->timestamp;
|
2007-12-13 05:16:33 +00:00
|
|
|
|
if (timestamp == GDK_CURRENT_TIME)
|
|
|
|
|
timestamp = gdk_x11_display_get_user_time (display);
|
|
|
|
|
|
2016-09-09 14:34:21 +00:00
|
|
|
|
screen_str = g_strdup_printf ("%d", gdk_x11_screen_get_screen_number (screen));
|
2010-12-11 05:14:53 +00:00
|
|
|
|
if (ctx->workspace > -1)
|
|
|
|
|
workspace_str = g_strdup_printf ("%d", ctx->workspace);
|
2007-12-13 05:16:33 +00:00
|
|
|
|
else
|
|
|
|
|
workspace_str = NULL;
|
2023-11-15 04:45:17 +00:00
|
|
|
|
|
2010-03-13 23:10:25 +00:00
|
|
|
|
if (G_IS_DESKTOP_APP_INFO (info))
|
|
|
|
|
application_id = g_desktop_app_info_get_filename (G_DESKTOP_APP_INFO (info));
|
|
|
|
|
else
|
|
|
|
|
application_id = NULL;
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
|
|
|
|
startup_id = g_strdup_printf ("%s-%lu-%s-%s-%d_TIME%lu",
|
2010-11-28 04:12:09 +00:00
|
|
|
|
g_get_prgname (),
|
|
|
|
|
(unsigned long)getpid (),
|
|
|
|
|
g_get_host_name (),
|
|
|
|
|
binary_name,
|
|
|
|
|
sequence++,
|
|
|
|
|
(unsigned long)timestamp);
|
|
|
|
|
|
2007-12-13 05:16:33 +00:00
|
|
|
|
gdk_x11_display_broadcast_startup_message (display, "new",
|
2010-11-28 04:12:09 +00:00
|
|
|
|
"ID", startup_id,
|
|
|
|
|
"NAME", g_app_info_get_name (info),
|
|
|
|
|
"SCREEN", screen_str,
|
|
|
|
|
"BIN", binary_name,
|
|
|
|
|
"ICON", icon_name,
|
|
|
|
|
"DESKTOP", workspace_str,
|
|
|
|
|
"DESCRIPTION", description,
|
|
|
|
|
"WMCLASS", NULL, /* FIXME */
|
|
|
|
|
"APPLICATION_ID", application_id,
|
|
|
|
|
NULL);
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
|
|
|
|
g_free (description);
|
|
|
|
|
g_free (screen_str);
|
|
|
|
|
g_free (workspace_str);
|
|
|
|
|
g_free (icon_name);
|
2010-11-28 04:12:09 +00:00
|
|
|
|
if (fileinfo)
|
|
|
|
|
g_object_unref (fileinfo);
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
|
|
|
|
add_startup_timeout (screen, startup_id);
|
|
|
|
|
|
|
|
|
|
return startup_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-12-09 06:08:05 +00:00
|
|
|
|
static void
|
2010-12-21 07:32:15 +00:00
|
|
|
|
gdk_x11_app_launch_context_launch_failed (GAppLaunchContext *context,
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *startup_notify_id)
|
2007-12-13 05:16:33 +00:00
|
|
|
|
{
|
2010-12-11 05:14:53 +00:00
|
|
|
|
GdkAppLaunchContext *ctx;
|
2017-11-17 15:18:20 +00:00
|
|
|
|
GdkX11Screen *screen;
|
2007-12-13 05:16:33 +00:00
|
|
|
|
StartupTimeoutData *data;
|
|
|
|
|
StartupNotificationData *sn_data;
|
|
|
|
|
GSList *l;
|
|
|
|
|
|
2010-12-11 05:14:53 +00:00
|
|
|
|
ctx = GDK_APP_LAUNCH_CONTEXT (context);
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
2017-11-01 22:06:24 +00:00
|
|
|
|
screen = GDK_X11_DISPLAY (ctx->display)->screen;
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
|
|
|
|
data = g_object_get_data (G_OBJECT (screen), "appinfo-startup-data");
|
|
|
|
|
|
|
|
|
|
if (data)
|
|
|
|
|
{
|
|
|
|
|
for (l = data->contexts; l != NULL; l = l->next)
|
2010-11-28 04:12:09 +00:00
|
|
|
|
{
|
|
|
|
|
sn_data = l->data;
|
|
|
|
|
if (strcmp (startup_notify_id, sn_data->startup_id) == 0)
|
|
|
|
|
{
|
|
|
|
|
data->contexts = g_slist_remove (data->contexts, sn_data);
|
|
|
|
|
end_startup_notification (sn_data->display, sn_data->startup_id);
|
|
|
|
|
free_startup_notification_data (sn_data);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2007-12-13 05:16:33 +00:00
|
|
|
|
|
|
|
|
|
if (data->contexts == NULL)
|
2010-11-28 04:12:09 +00:00
|
|
|
|
{
|
|
|
|
|
g_source_remove (data->timeout_id);
|
|
|
|
|
data->timeout_id = 0;
|
|
|
|
|
}
|
2007-12-13 05:16:33 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2010-12-09 06:08:05 +00:00
|
|
|
|
|
2010-12-21 07:32:15 +00:00
|
|
|
|
struct _GdkX11AppLaunchContext
|
|
|
|
|
{
|
|
|
|
|
GdkAppLaunchContext parent_instance;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct _GdkX11AppLaunchContextClass
|
|
|
|
|
{
|
|
|
|
|
GdkAppLaunchContextClass parent_class;
|
|
|
|
|
};
|
|
|
|
|
|
2010-12-09 06:08:05 +00:00
|
|
|
|
|
2010-12-21 07:32:15 +00:00
|
|
|
|
G_DEFINE_TYPE (GdkX11AppLaunchContext, gdk_x11_app_launch_context, GDK_TYPE_APP_LAUNCH_CONTEXT)
|
2010-12-09 06:08:05 +00:00
|
|
|
|
|
|
|
|
|
static void
|
2010-12-21 07:32:15 +00:00
|
|
|
|
gdk_x11_app_launch_context_class_init (GdkX11AppLaunchContextClass *klass)
|
2010-12-09 06:08:05 +00:00
|
|
|
|
{
|
|
|
|
|
GAppLaunchContextClass *ctx_class = G_APP_LAUNCH_CONTEXT_CLASS (klass);
|
|
|
|
|
|
2010-12-21 07:32:15 +00:00
|
|
|
|
ctx_class->get_startup_notify_id = gdk_x11_app_launch_context_get_startup_notify_id;
|
|
|
|
|
ctx_class->launch_failed = gdk_x11_app_launch_context_launch_failed;
|
2010-12-09 06:08:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2010-12-21 07:32:15 +00:00
|
|
|
|
gdk_x11_app_launch_context_init (GdkX11AppLaunchContext *ctx)
|
2010-12-09 06:08:05 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GdkAppLaunchContext *
|
|
|
|
|
_gdk_x11_display_get_app_launch_context (GdkDisplay *display)
|
|
|
|
|
{
|
|
|
|
|
GdkAppLaunchContext *ctx;
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *display_name;
|
2010-12-09 06:08:05 +00:00
|
|
|
|
|
2010-12-21 07:32:15 +00:00
|
|
|
|
ctx = g_object_new (GDK_TYPE_X11_APP_LAUNCH_CONTEXT,
|
2010-12-15 07:37:03 +00:00
|
|
|
|
"display", display,
|
|
|
|
|
NULL);
|
2010-12-09 06:08:05 +00:00
|
|
|
|
|
2015-10-12 14:11:11 +00:00
|
|
|
|
display_name = gdk_display_get_name (display);
|
2015-09-15 12:17:05 +00:00
|
|
|
|
if (display_name)
|
|
|
|
|
g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (ctx),
|
|
|
|
|
"DISPLAY", display_name);
|
|
|
|
|
|
2010-12-09 06:08:05 +00:00
|
|
|
|
return ctx;
|
|
|
|
|
}
|