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
This commit is contained in:
Colin Walters 2010-02-24 11:29:44 -05:00
parent fe52a9e1a1
commit c92ce5983d
5 changed files with 148 additions and 56 deletions

View File

@ -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 clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
libstartup-notification-1.0 libstartup-notification-1.0
gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION) 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(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(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) PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)

View File

@ -248,10 +248,9 @@ AppPanelMenu.prototype = {
let focusedApp = tracker.focus_app; let focusedApp = tracker.focus_app;
let lastSequence = null; let lastSequence = null;
if (focusedApp == null) { let sequences = tracker.get_startup_sequences();
let sequences = tracker.get_startup_sequences(); if (sequences.length > 0) {
if (sequences.length > 0) lastSequence = sequences[sequences.length - 1];
lastSequence = sequences[sequences.length - 1];
} }
// If the currently focused app hasn't changed and the current // If the currently focused app hasn't changed and the current
@ -262,13 +261,17 @@ AppPanelMenu.prototype = {
&& lastSequence.get_id() == this._activeSequence.get_id()))) && lastSequence.get_id() == this._activeSequence.get_id())))
return; return;
this._focusedApp = focusedApp;
this._activeSequence = lastSequence;
if (this._iconBox.child != null) if (this._iconBox.child != null)
this._iconBox.child.destroy(); this._iconBox.child.destroy();
this._iconBox.hide(); this._iconBox.hide();
this._label.setText(''); this._label.setText('');
if (focusedApp == null && lastSequence != null)
focusedApp = lastSequence.get_app();
this._focusedApp = focusedApp;
this._activeSequence = lastSequence;
let icon; let icon;
if (this._focusedApp != null) { if (this._focusedApp != null) {
icon = this._focusedApp.get_faded_icon(AppDisplay.APPICON_SIZE); icon = this._focusedApp.get_faded_icon(AppDisplay.APPICON_SIZE);

View File

@ -1224,10 +1224,16 @@ shell_app_info_launch_full (ShellAppInfo *info,
meta_window_activate (info->window, timestamp); meta_window_activate (info->window, timestamp);
return TRUE; return TRUE;
} }
else if (info->type == SHELL_APP_INFO_TYPE_ENTRY)
filename = shell_app_info_get_desktop_file_path (info); {
gapp = g_desktop_app_info_new_from_filename (filename); gapp = g_desktop_app_info_new (shell_app_info_get_id (info));
g_free (filename); }
else
{
filename = shell_app_info_get_desktop_file_path (info);
gapp = g_desktop_app_info_new_from_filename (filename);
g_free (filename);
}
if (!gapp) if (!gapp)
{ {

View File

@ -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 * Looks only at the given window, and attempts to determine
* an application based on WM_CLASS. If that fails, then * an application based on WM_CLASS. If one can't be determined,
* a "transient" application is created. * return %NULL.
* *
* Return value: (transfer full): A newly-referenced #ShellApp * Return value: (transfer full): A newly-referenced #ShellApp, or %NULL
*/ */
static ShellApp * static ShellApp *
get_app_for_window_direct (MetaWindow *window) get_app_from_window_wmclass (MetaWindow *window)
{ {
ShellApp *app; ShellApp *app;
ShellAppSystem *appsys; ShellAppSystem *appsys;
@ -306,7 +306,7 @@ get_app_for_window_direct (MetaWindow *window)
wmclass = get_appid_from_window (window); wmclass = get_appid_from_window (window);
if (!wmclass) if (!wmclass)
return shell_app_system_get_app_for_window (appsys, window); return NULL;
with_desktop = g_strjoin (NULL, wmclass, ".desktop", NULL); with_desktop = g_strjoin (NULL, wmclass, ".desktop", NULL);
g_free (wmclass); g_free (wmclass);
@ -322,12 +322,57 @@ get_app_for_window_direct (MetaWindow *window)
app = shell_app_system_get_app (appsys, id); app = shell_app_system_get_app (appsys, id);
} }
if (app == NULL)
app = shell_app_system_get_app_for_window (appsys, window);
return app; 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: * get_app_for_window:
* *
@ -340,12 +385,12 @@ get_app_for_window (ShellWindowTracker *monitor,
MetaWindow *window) MetaWindow *window)
{ {
ShellApp *result; ShellApp *result;
MetaWindow *source_window; const char *startup_id;
GSList *group_windows;
MetaGroup *group;
GSList *iter;
result = NULL; 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) if (meta_window_get_window_type (window) == META_WINDOW_NORMAL)
{ {
result = g_hash_table_lookup (monitor->window_to_app, window); result = g_hash_table_lookup (monitor->window_to_app, window);
@ -354,43 +399,44 @@ get_app_for_window (ShellWindowTracker *monitor,
g_object_ref (result); g_object_ref (result);
return result; return result;
} }
else
return get_app_for_window_direct (window);
} }
group = meta_window_get_group (window); /* Check if the app's WM_CLASS specifies an app */
if (group == NULL) result = get_app_from_window_wmclass (window);
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);
if (result != NULL) 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); GSList *iter, *sequences;
return result;
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 * const char *
@ -588,7 +634,6 @@ on_startup_sequence_changed (MetaScreen *screen,
SnStartupSequence *sequence, SnStartupSequence *sequence,
ShellWindowTracker *self) ShellWindowTracker *self)
{ {
/* Just proxy the signal */
g_signal_emit (G_OBJECT (self), signals[STARTUP_SEQUENCE_CHANGED], 0, sequence); 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); 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 * const char *
shell_startup_sequence_get_name (ShellStartupSequence *sequence) shell_startup_sequence_get_name (ShellStartupSequence *sequence)
{ {

View File

@ -50,6 +50,7 @@ typedef struct _ShellStartupSequence ShellStartupSequence;
GType shell_startup_sequence_get_type (void); GType shell_startup_sequence_get_type (void);
const char *shell_startup_sequence_get_id (ShellStartupSequence *sequence); 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); const char *shell_startup_sequence_get_name (ShellStartupSequence *sequence);
gboolean shell_startup_sequence_get_completed (ShellStartupSequence *sequence); gboolean shell_startup_sequence_get_completed (ShellStartupSequence *sequence);
ClutterActor *shell_startup_sequence_create_icon (ShellStartupSequence *sequence, guint size); ClutterActor *shell_startup_sequence_create_icon (ShellStartupSequence *sequence, guint size);