From c92ce5983d751491d5887ac6e0c6d95b9a0cbffb Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 24 Feb 2010 11:29:44 -0500 Subject: [PATCH] Consume startup-notification APPLICATION_ID This patch ensures we're showing the correct data when doing startup-notification. https://bugzilla.gnome.org/show_bug.cgi?id=612833 --- configure.ac | 11 +++ js/ui/panel.js | 17 ++-- src/shell-app-system.c | 14 +++- src/shell-window-tracker.c | 161 ++++++++++++++++++++++++++----------- src/shell-window-tracker.h | 1 + 5 files changed, 148 insertions(+), 56 deletions(-) diff --git a/configure.ac b/configure.ac index 2f5c0ca47..710e61b3b 100644 --- a/configure.ac +++ b/configure.ac @@ -70,6 +70,17 @@ PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 gtk+-2.0 dbus-glib-1 clutter-glx-1.0 >= $CLUTTER_MIN_VERSION libstartup-notification-1.0 gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION) + +# This is for the newly added application id bits, we can replace this with +# a version check later +saved_CFLAGS=$CFLAGS +saved_LIBS=$LIBS +CFLAGS=$MUTTER_PLUGIN_CFLAGS +LIBS=$MUTTER_PLUGIN_LIBS +AC_CHECK_FUNCS(sn_startup_sequence_get_application_id) +CFLAGS=$saved_CFLAGS +LIBS=$saved_LIBS + PKG_CHECK_MODULES(TIDY, clutter-1.0) PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-2.0 libcroco-0.6 gnome-desktop-2.0 >= 2.26) PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0) diff --git a/js/ui/panel.js b/js/ui/panel.js index e35a655ae..bd9c11b51 100644 --- a/js/ui/panel.js +++ b/js/ui/panel.js @@ -248,10 +248,9 @@ AppPanelMenu.prototype = { let focusedApp = tracker.focus_app; let lastSequence = null; - if (focusedApp == null) { - let sequences = tracker.get_startup_sequences(); - if (sequences.length > 0) - lastSequence = sequences[sequences.length - 1]; + let sequences = tracker.get_startup_sequences(); + if (sequences.length > 0) { + lastSequence = sequences[sequences.length - 1]; } // If the currently focused app hasn't changed and the current @@ -262,13 +261,17 @@ AppPanelMenu.prototype = { && lastSequence.get_id() == this._activeSequence.get_id()))) return; - this._focusedApp = focusedApp; - this._activeSequence = lastSequence; - if (this._iconBox.child != null) this._iconBox.child.destroy(); this._iconBox.hide(); this._label.setText(''); + + if (focusedApp == null && lastSequence != null) + focusedApp = lastSequence.get_app(); + + this._focusedApp = focusedApp; + this._activeSequence = lastSequence; + let icon; if (this._focusedApp != null) { icon = this._focusedApp.get_faded_icon(AppDisplay.APPICON_SIZE); diff --git a/src/shell-app-system.c b/src/shell-app-system.c index c2d002531..94d5a7987 100644 --- a/src/shell-app-system.c +++ b/src/shell-app-system.c @@ -1224,10 +1224,16 @@ shell_app_info_launch_full (ShellAppInfo *info, meta_window_activate (info->window, timestamp); return TRUE; } - - filename = shell_app_info_get_desktop_file_path (info); - gapp = g_desktop_app_info_new_from_filename (filename); - g_free (filename); + else if (info->type == SHELL_APP_INFO_TYPE_ENTRY) + { + gapp = g_desktop_app_info_new (shell_app_info_get_id (info)); + } + else + { + filename = shell_app_info_get_desktop_file_path (info); + gapp = g_desktop_app_info_new_from_filename (filename); + g_free (filename); + } if (!gapp) { diff --git a/src/shell-window-tracker.c b/src/shell-window-tracker.c index 1c9ee6c89..9f91917e3 100644 --- a/src/shell-window-tracker.c +++ b/src/shell-window-tracker.c @@ -286,16 +286,16 @@ shell_window_tracker_is_window_interesting (MetaWindow *window) } /** - * get_app_for_window_direct: + * get_app_from_window_wmclass: * * Looks only at the given window, and attempts to determine - * an application based on WM_CLASS. If that fails, then - * a "transient" application is created. + * an application based on WM_CLASS. If one can't be determined, + * return %NULL. * - * Return value: (transfer full): A newly-referenced #ShellApp + * Return value: (transfer full): A newly-referenced #ShellApp, or %NULL */ static ShellApp * -get_app_for_window_direct (MetaWindow *window) +get_app_from_window_wmclass (MetaWindow *window) { ShellApp *app; ShellAppSystem *appsys; @@ -306,7 +306,7 @@ get_app_for_window_direct (MetaWindow *window) wmclass = get_appid_from_window (window); if (!wmclass) - return shell_app_system_get_app_for_window (appsys, window); + return NULL; with_desktop = g_strjoin (NULL, wmclass, ".desktop", NULL); g_free (wmclass); @@ -322,12 +322,57 @@ get_app_for_window_direct (MetaWindow *window) app = shell_app_system_get_app (appsys, id); } - if (app == NULL) - app = shell_app_system_get_app_for_window (appsys, window); - return app; } +/** + * get_app_from_window_group: + * @monitor: a #ShellWindowTracker + * @window: a #MetaWindow + * + * Check other windows in the group for @window to see if we have + * an application for one of them. + * + * Return value: (transfer full): A newly-referenced #ShellApp, or %NULL + */ +static ShellApp* +get_app_from_window_group (ShellWindowTracker *monitor, + MetaWindow *window) +{ + ShellApp *result; + GSList *group_windows; + MetaGroup *group; + GSList *iter; + + group = meta_window_get_group (window); + if (group == NULL) + return NULL; + + group_windows = meta_group_list_windows (group); + + result = NULL; + /* Try finding a window in the group of type NORMAL; if we + * succeed, use that as our source. */ + for (iter = group_windows; iter; iter = iter->next) + { + MetaWindow *group_window = iter->data; + + if (meta_window_get_window_type (group_window) != META_WINDOW_NORMAL) + continue; + + result = g_hash_table_lookup (monitor->window_to_app, group_window); + if (result) + break; + } + + g_slist_free (group_windows); + + if (result) + g_object_ref (result); + + return result; +} + /** * get_app_for_window: * @@ -340,12 +385,12 @@ get_app_for_window (ShellWindowTracker *monitor, MetaWindow *window) { ShellApp *result; - MetaWindow *source_window; - GSList *group_windows; - MetaGroup *group; - GSList *iter; + const char *startup_id; result = NULL; + /* First, we check whether we already know about this window, + * if so, just return that. + */ if (meta_window_get_window_type (window) == META_WINDOW_NORMAL) { result = g_hash_table_lookup (monitor->window_to_app, window); @@ -354,43 +399,44 @@ get_app_for_window (ShellWindowTracker *monitor, g_object_ref (result); return result; } - else - return get_app_for_window_direct (window); } - group = meta_window_get_group (window); - if (group == NULL) - group_windows = g_slist_prepend (NULL, window); - else - group_windows = meta_group_list_windows (group); - - source_window = window; - - result = NULL; - /* Try finding a window in the group of type NORMAL; if we - * succeed, use that as our source. */ - for (iter = group_windows; iter; iter = iter->next) - { - MetaWindow *group_window = iter->data; - - if (meta_window_get_window_type (group_window) != META_WINDOW_NORMAL) - continue; - - source_window = group_window; - result = g_hash_table_lookup (monitor->window_to_app, group_window); - if (result) - break; - } - - g_slist_free (group_windows); - + /* Check if the app's WM_CLASS specifies an app */ + result = get_app_from_window_wmclass (window); if (result != NULL) + return result; + + /* Now we check whether we have a match through startup-notification */ + startup_id = meta_window_get_startup_id (window); + if (startup_id) { - g_object_ref (result); - return result; + GSList *iter, *sequences; + + sequences = shell_window_tracker_get_startup_sequences (monitor); + for (iter = sequences; iter; iter = iter->next) + { + ShellStartupSequence *sequence = iter->data; + const char *id = shell_startup_sequence_get_id (sequence); + if (strcmp (id, startup_id) != 0) + continue; + + result = shell_startup_sequence_get_app (sequence); + if (result) + break; + } } - return get_app_for_window_direct (source_window); + /* If we didn't get a startup-notification match, see if we matched + * any other windows in the group. + */ + if (result == NULL) + result = get_app_from_window_group (monitor, window); + + /* Our last resort - we create a fake app from the window */ + if (result == NULL) + result = shell_app_system_get_app_for_window (shell_app_system_get_default (), window); + + return result; } const char * @@ -588,7 +634,6 @@ on_startup_sequence_changed (MetaScreen *screen, SnStartupSequence *sequence, ShellWindowTracker *self) { - /* Just proxy the signal */ g_signal_emit (G_OBJECT (self), signals[STARTUP_SEQUENCE_CHANGED], 0, sequence); } @@ -795,6 +840,32 @@ shell_startup_sequence_get_id (ShellStartupSequence *sequence) return sn_startup_sequence_get_id ((SnStartupSequence*)sequence); } +/** + * shell_startup_sequence_get_app: + * @sequence: A #ShellStartupSequence + * + * Returns: (transfer full): The application being launched, or %NULL if unknown. + */ +ShellApp * +shell_startup_sequence_get_app (ShellStartupSequence *sequence) +{ +#ifdef HAVE_SN_STARTUP_SEQUENCE_GET_APPLICATION_ID + const char *appid; + ShellAppSystem *appsys; + ShellApp *app; + + appid = sn_startup_sequence_get_application_id ((SnStartupSequence*)sequence); + if (!appid) + return NULL; + + appsys = shell_app_system_get_default (); + app = shell_app_system_get_app_for_path (appsys, appid); + return app; +#else + return NULL; +#endif +} + const char * shell_startup_sequence_get_name (ShellStartupSequence *sequence) { diff --git a/src/shell-window-tracker.h b/src/shell-window-tracker.h index acc3028a9..bb2014dbe 100644 --- a/src/shell-window-tracker.h +++ b/src/shell-window-tracker.h @@ -50,6 +50,7 @@ typedef struct _ShellStartupSequence ShellStartupSequence; GType shell_startup_sequence_get_type (void); const char *shell_startup_sequence_get_id (ShellStartupSequence *sequence); +ShellApp *shell_startup_sequence_get_app (ShellStartupSequence *sequence); const char *shell_startup_sequence_get_name (ShellStartupSequence *sequence); gboolean shell_startup_sequence_get_completed (ShellStartupSequence *sequence); ClutterActor *shell_startup_sequence_create_icon (ShellStartupSequence *sequence, guint size);