summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/atomnames.h6
-rw-r--r--src/core/iconcache.c68
-rw-r--r--src/core/iconcache.h6
-rw-r--r--src/core/window-private.h2
-rw-r--r--src/core/window-props.c64
-rw-r--r--src/core/window.c40
-rw-r--r--src/include/ui.h4
-rw-r--r--src/ui/ui.c41
8 files changed, 166 insertions, 65 deletions
diff --git a/src/core/atomnames.h b/src/core/atomnames.h
index cea869d0..2e9e6c8d 100644
--- a/src/core/atomnames.h
+++ b/src/core/atomnames.h
@@ -60,6 +60,7 @@ item(_MARCO_SET_KEYBINDINGS_MESSAGE)
item(_MARCO_TOGGLE_VERBOSE)
item(_GTK_THEME_VARIANT)
item(_GTK_FRAME_EXTENTS)
+item(_GTK_APPLICATION_ID)
item(_GTK_SHOW_WINDOW_MENU)
item(_GTK_WORKAREAS)
item(_MATE_PANEL_ACTION)
@@ -76,6 +77,11 @@ item(TIMESTAMP)
item(VERSION)
item(ATOM_PAIR)
+/* This is only used if BAMF is installed and the daemon is running.
+ * Otherwise it's a no-op
+ */
+item(_BAMF_DESKTOP_FILE)
+
/* Oddities: These are used, and we need atoms for them,
* but when we need all _NET_WM hints (i.e. when we're making
* lists of which _NET_WM hints we support in order to advertise
diff --git a/src/core/iconcache.c b/src/core/iconcache.c
index a45d3d99..580a521c 100644
--- a/src/core/iconcache.c
+++ b/src/core/iconcache.c
@@ -31,7 +31,7 @@
/* The icon-reading code is also in libwnck, please sync bugfixes */
-static void
+static gboolean
get_fallback_icons (MetaScreen *screen,
GdkPixbuf **iconp,
int ideal_width,
@@ -45,6 +45,11 @@ get_fallback_icons (MetaScreen *screen,
*/
*iconp = meta_ui_get_default_window_icon (screen->ui);
*mini_iconp = meta_ui_get_default_mini_icon (screen->ui);
+
+ if (*iconp && *mini_iconp)
+ return TRUE;
+
+ return FALSE;
}
static gboolean
@@ -524,6 +529,7 @@ meta_icon_cache_init (MetaIconCache *icon_cache)
icon_cache->wm_hints_dirty = TRUE;
icon_cache->kwm_win_icon_dirty = TRUE;
icon_cache->net_wm_icon_dirty = TRUE;
+ icon_cache->g_desktop_app_icon_dirty = TRUE;
icon_cache->wm_hints_dirty_forced = FALSE;
icon_cache->kwm_win_icon_dirty_forced = FALSE;
@@ -551,6 +557,7 @@ clear_icon_cache (MetaIconCache *icon_cache,
icon_cache->wm_hints_dirty = TRUE;
icon_cache->kwm_win_icon_dirty = TRUE;
icon_cache->net_wm_icon_dirty = TRUE;
+ icon_cache->g_desktop_app_icon_dirty = TRUE;
}
}
@@ -566,6 +573,7 @@ meta_icon_cache_invalidate (MetaIconCache *icon_cache)
icon_cache->wm_hints_dirty = TRUE;
icon_cache->kwm_win_icon_dirty = TRUE;
icon_cache->net_wm_icon_dirty = TRUE;
+ icon_cache->g_desktop_app_icon_dirty = TRUE;
icon_cache->wm_hints_dirty_forced = TRUE;
icon_cache->kwm_win_icon_dirty_forced = TRUE;
@@ -594,6 +602,9 @@ meta_icon_cache_get_icon_invalidated (MetaIconCache *icon_cache)
else if (icon_cache->origin <= USING_WM_HINTS &&
icon_cache->wm_hints_dirty)
return TRUE;
+ else if (icon_cache->origin <= USING_G_DESKTOP_APP &&
+ icon_cache->g_desktop_app_icon_dirty)
+ return TRUE;
else if (icon_cache->origin <= USING_NET_WM_ICON &&
icon_cache->net_wm_icon_dirty)
return TRUE;
@@ -691,7 +702,7 @@ scaled_from_pixdata (guchar *pixdata,
gboolean
meta_read_icons (MetaScreen *screen,
Window xwindow,
- char *res_name,
+ char *desktop_id,
MetaIconCache *icon_cache,
Pixmap wm_hints_pixmap,
Pixmap wm_hints_mask,
@@ -743,6 +754,31 @@ meta_read_icons (MetaScreen *screen,
* we haven't done that since the last change.
*/
+ if (icon_cache->origin <= USING_G_DESKTOP_APP &&
+ icon_cache->g_desktop_app_icon_dirty &&
+ desktop_id != NULL)
+ {
+ icon_cache->g_desktop_app_icon_dirty = FALSE;
+
+ *iconp = meta_ui_get_window_icon_from_desktop_id (screen->ui, desktop_id);
+ *mini_iconp = meta_ui_get_mini_icon_from_desktop_id (screen->ui, desktop_id);
+
+ if (*iconp && *mini_iconp)
+ {
+ replace_cache (icon_cache, USING_G_DESKTOP_APP,
+ *iconp, *mini_iconp);
+
+ return TRUE;
+ }
+ else
+ {
+ if (*iconp)
+ g_object_unref (G_OBJECT (*iconp));
+ if (*mini_iconp)
+ g_object_unref (G_OBJECT (*mini_iconp));
+ }
+ }
+
if (icon_cache->origin <= USING_NET_WM_ICON &&
icon_cache->net_wm_icon_dirty)
@@ -849,25 +885,19 @@ meta_read_icons (MetaScreen *screen,
{
icon_cache->fallback_icon_dirty_forced = FALSE;
- if (res_name != NULL)
+ if (get_fallback_icons (screen,
+ iconp,
+ ideal_width,
+ ideal_height,
+ mini_iconp,
+ ideal_mini_width,
+ ideal_mini_height))
{
- *iconp = meta_ui_get_window_icon_from_name (screen->ui, res_name);
- *mini_iconp = meta_ui_get_mini_icon_from_name (screen->ui, res_name);
- }
-
- if (*iconp == NULL || *mini_iconp == NULL)
- get_fallback_icons (screen,
- iconp,
- ideal_width,
- ideal_height,
- mini_iconp,
- ideal_mini_width,
- ideal_mini_height);
+ replace_cache (icon_cache, USING_FALLBACK_ICON,
+ *iconp, *mini_iconp);
- replace_cache (icon_cache, USING_FALLBACK_ICON,
- *iconp, *mini_iconp);
-
- return TRUE;
+ return TRUE;
+ }
}
if (!icon_cache->want_fallback &&
diff --git a/src/core/iconcache.h b/src/core/iconcache.h
index 7e9a1f6d..353787c7 100644
--- a/src/core/iconcache.h
+++ b/src/core/iconcache.h
@@ -38,7 +38,8 @@ typedef enum
USING_FALLBACK_ICON,
USING_KWM_WIN_ICON,
USING_WM_HINTS,
- USING_NET_WM_ICON
+ USING_NET_WM_ICON,
+ USING_G_DESKTOP_APP
} IconOrigin;
struct _MetaIconCache
@@ -51,6 +52,7 @@ struct _MetaIconCache
guint wm_hints_dirty : 1;
guint kwm_win_icon_dirty : 1;
guint net_wm_icon_dirty : 1;
+ guint g_desktop_app_icon_dirty : 1;
guint wm_hints_dirty_forced : 1;
guint kwm_win_icon_dirty_forced : 1;
@@ -67,7 +69,7 @@ gboolean meta_icon_cache_get_icon_invalidated (MetaIconCache *icon_cache);
gboolean meta_read_icons (MetaScreen *screen,
Window xwindow,
- char *res_name,
+ char *desktop_id,
MetaIconCache *icon_cache,
Pixmap wm_hints_pixmap,
Pixmap wm_hints_mask,
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 02b7df42..52864a86 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -133,6 +133,8 @@ struct _MetaWindow
char *wm_client_machine;
char *startup_id;
char *gtk_theme_variant;
+ char *gtk_application_id;
+ char *bamf_desktop_file;
int net_wm_pid;
diff --git a/src/core/window-props.c b/src/core/window-props.c
index e1275817..4383100f 100644
--- a/src/core/window-props.c
+++ b/src/core/window-props.c
@@ -311,20 +311,19 @@ get_local_pid (MetaWindow *window)
spec.client = window->xwindow;
spec.mask = XRES_CLIENT_ID_PID_MASK;
- if (!XResQueryClientIds (window->display->xdisplay,
+ if (XResQueryClientIds (window->display->xdisplay,
1,
&spec,
&num_ids,
- &client_ids))
- return pid;
+ &client_ids) != Success)
+ return pid;
for (i = 0; i < num_ids; i++)
{
- if (client_ids[i].spec.mask == XRES_CLIENT_ID_PID_MASK)
- {
- pid = XResGetClientPid (&client_ids[i]);
- break;
- }
+ pid = XResGetClientPid (&client_ids[i]);
+
+ if (pid != -1)
+ break;
}
XResClientIdsDestroy (num_ids, client_ids);
@@ -1603,6 +1602,53 @@ reload_gtk_theme_variant (MetaWindow *window,
meta_ui_update_frame_style (window->screen->ui, window->frame->xwindow);
}
}
+
+static void
+reload_gtk_application_id (MetaWindow *window,
+ MetaPropValue *value,
+ gboolean initial)
+{
+ char *requested = NULL;
+ char *current = window->gtk_application_id;
+
+ if (value->type != META_PROP_VALUE_INVALID)
+ {
+ requested = value->v.str;
+ meta_verbose ("Requested \"%s\" gtk-application-id for window %s.\n",
+ requested, window->desc);
+ }
+
+ if (g_strcmp0 (requested, current) != 0)
+ {
+ g_free (current);
+
+ window->gtk_application_id = g_strdup (requested);
+ }
+}
+
+static void
+reload_bamf_desktop_file (MetaWindow *window,
+ MetaPropValue *value,
+ gboolean initial)
+{
+ char *requested = NULL;
+ char *current = window->bamf_desktop_file;
+
+ if (value->type != META_PROP_VALUE_INVALID)
+ {
+ requested = value->v.str;
+ meta_verbose ("Requested _BAMF_DESKTOP_FILE \"%s\" for window %s.\n",
+ requested, window->desc);
+ }
+
+ if (g_strcmp0 (requested, current) != 0)
+ {
+ g_free (current);
+
+ window->bamf_desktop_file = g_strdup (requested);
+ }
+}
+
/**
* Initialises the property hooks system. Each row in the table named "hooks"
* represents an action to take when a property is found on a newly-created
@@ -1652,6 +1698,8 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
{ display->atom__NET_WM_USER_TIME_WINDOW, META_PROP_VALUE_WINDOW, reload_net_wm_user_time_window },
{ display->atom__GTK_THEME_VARIANT, META_PROP_VALUE_UTF8, reload_gtk_theme_variant, },
{ display->atom__GTK_FRAME_EXTENTS, META_PROP_VALUE_CARDINAL_LIST, reload_gtk_frame_extents },
+ { display->atom__GTK_APPLICATION_ID, META_PROP_VALUE_UTF8, reload_gtk_application_id },
+ { display->atom__BAMF_DESKTOP_FILE, META_PROP_VALUE_STRING, reload_bamf_desktop_file },
{ 0 },
};
diff --git a/src/core/window.c b/src/core/window.c
index c1702dd8..050c89f8 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -263,7 +263,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
gulong existing_wm_state;
gulong event_mask;
MetaMoveResizeFlags flags;
-#define N_INITIAL_PROPS 20
+#define N_INITIAL_PROPS 22
Atom initial_props[N_INITIAL_PROPS];
int i;
gboolean has_shape;
@@ -563,6 +563,8 @@ meta_window_new_with_attrs (MetaDisplay *display,
window->wm_client_machine = NULL;
window->startup_id = NULL;
window->gtk_theme_variant = NULL;
+ window->gtk_application_id = NULL;
+ window->bamf_desktop_file = NULL;
window->net_wm_pid = -1;
@@ -621,6 +623,8 @@ meta_window_new_with_attrs (MetaDisplay *display,
initial_props[i++] = display->atom__NET_WM_USER_TIME_WINDOW;
initial_props[i++] = display->atom__NET_WM_FULLSCREEN_MONITORS;
initial_props[i++] = display->atom__GTK_THEME_VARIANT;
+ initial_props[i++] = display->atom__GTK_APPLICATION_ID;
+ initial_props[i++] = display->atom__BAMF_DESKTOP_FILE;
g_assert (N_INITIAL_PROPS == i);
meta_window_reload_properties (window, initial_props, N_INITIAL_PROPS, TRUE);
@@ -6107,6 +6111,33 @@ redraw_icon (MetaWindow *window)
meta_ui_queue_frame_draw (window->screen->ui, window->frame->xwindow);
}
+static gchar*
+meta_window_get_desktop_id (MetaWindow *window)
+{
+ gchar* desktop_id = NULL;
+
+ if (window->gtk_application_id != NULL)
+ {
+ meta_verbose ("Request desktop ID from _GTK_APPLICATION_ID '%s'\n", window->gtk_application_id);
+
+ /* Generate a desktop extension to the application ID (e.g. org.mate.Caja.desktop). */
+ desktop_id = g_strconcat(window->gtk_application_id, ".desktop", NULL);
+ }
+ else if (window->bamf_desktop_file != NULL)
+ {
+ meta_verbose ("Request desktop ID from _BAMF_DESKTOP_FILE '%s'\n", window->bamf_desktop_file);
+
+ /* Remove any paths to separate the application ID */
+ gchar **path_parts = g_strsplit (window->bamf_desktop_file, "/", -1);
+ /* Generate a desktop ID the application ID (e.g. org.mate.Caja.desktop). */
+ if (g_strv_length(path_parts) > 0)
+ desktop_id = g_strdup (path_parts[g_strv_length(path_parts)-1]);
+ g_strfreev (path_parts);
+ }
+
+ return desktop_id;
+}
+
void
meta_window_update_icon_now (MetaWindow *window)
{
@@ -6117,10 +6148,11 @@ meta_window_update_icon_now (MetaWindow *window)
mini_icon = NULL;
int icon_size = meta_prefs_get_icon_size();
+ gchar* desktop_id = meta_window_get_desktop_id (window);
if (meta_read_icons (window->screen,
window->xwindow,
- window->res_name,
+ desktop_id,
&window->icon_cache,
window->wm_hints_pixmap,
window->wm_hints_mask,
@@ -6143,6 +6175,8 @@ meta_window_update_icon_now (MetaWindow *window)
redraw_icon (window);
}
+ g_free (desktop_id);
+
g_assert (window->icon);
g_assert (window->mini_icon);
}
@@ -9015,6 +9049,8 @@ meta_window_finalize (GObject *object)
g_clear_pointer (&window->icon_name, g_free);
g_clear_pointer (&window->desc, g_free);
g_clear_pointer (&window->gtk_theme_variant, g_free);
+ g_clear_pointer (&window->gtk_application_id, g_free);
+ g_clear_pointer (&window->bamf_desktop_file, g_free);
G_OBJECT_CLASS (meta_window_parent_class)->finalize (object);
}
diff --git a/src/include/ui.h b/src/include/ui.h
index 9d95e37a..8eb6dd5e 100644
--- a/src/include/ui.h
+++ b/src/include/ui.h
@@ -157,8 +157,8 @@ void meta_ui_pop_delay_exposes (MetaUI *ui);
GdkPixbuf* meta_ui_get_default_window_icon (MetaUI *ui);
GdkPixbuf* meta_ui_get_default_mini_icon (MetaUI *ui);
-GdkPixbuf* meta_ui_get_window_icon_from_name (MetaUI *ui, char *name);
-GdkPixbuf* meta_ui_get_mini_icon_from_name (MetaUI *ui, char *name);
+GdkPixbuf* meta_ui_get_window_icon_from_desktop_id (MetaUI *ui, char *desktop_id);
+GdkPixbuf* meta_ui_get_mini_icon_from_desktop_id (MetaUI *ui, char *desktop_id);
gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay,
Window xwindow);
diff --git a/src/ui/ui.c b/src/ui/ui.c
index 2b15cc82..00500c03 100644
--- a/src/ui/ui.c
+++ b/src/ui/ui.c
@@ -650,43 +650,22 @@ meta_ui_get_default_mini_icon (MetaUI *ui)
}
static GdkPixbuf *
-load_window_icon_from_name (char *name, int size, int scale)
+load_window_icon_from_desktop_id (char *desktop_id, int size, int scale)
{
GtkIconTheme *theme = gtk_icon_theme_get_default ();
GdkPixbuf *pixbuf = NULL;
- /* If the res_name window property maps to an icon, use that */
- pixbuf = gtk_icon_theme_load_icon_for_scale (theme, name, size, scale, GTK_ICON_LOOKUP_FORCE_SIZE, NULL);
- if (pixbuf != NULL)
- return pixbuf;
-
- char ***results;
- gchar *desktop_id = NULL;
- gint i, j;
GDesktopAppInfo *info;
GIcon *gicon;
GtkIconInfo *icon_info;
- /* Find a proper desktop file based on the window property name */
- results = g_desktop_app_info_search (name);
-
- for (i = 0; results[i]; i++)
- {
- for (j = 0; results[i][j]; j++)
- {
- /* We are only interested in the top ranking result, so we use that and free up the rest */
- if (desktop_id == NULL)
- desktop_id = g_strdup(results[i][j]);
- }
- g_strfreev (results[i]);
- }
- g_free (results);
-
- if (desktop_id == NULL)
+ if (desktop_id == NULL || !g_str_has_suffix (desktop_id, ".desktop"))
return NULL;
- /* Now that we have the desktop file ID, we extract the icon from it and render it */
info = g_desktop_app_info_new (desktop_id);
+ if (info == NULL)
+ return NULL;
+
gicon = g_app_info_get_icon (G_APP_INFO (info));
icon_info = gtk_icon_theme_lookup_by_gicon_for_scale (theme, gicon, size, scale, GTK_ICON_LOOKUP_FORCE_SIZE);
if (icon_info)
@@ -695,13 +674,11 @@ load_window_icon_from_name (char *name, int size, int scale)
g_object_unref (icon_info);
}
- g_free (desktop_id);
-
return pixbuf;
}
GdkPixbuf*
-meta_ui_get_window_icon_from_name (MetaUI *ui, char *name)
+meta_ui_get_window_icon_from_desktop_id (MetaUI *ui, char *desktop_id)
{
int scale;
int size;
@@ -709,11 +686,11 @@ meta_ui_get_window_icon_from_name (MetaUI *ui, char *name)
scale = gtk_widget_get_scale_factor (GTK_WIDGET (ui->frames));
size = meta_prefs_get_icon_size() / scale;
- return load_window_icon_from_name (name, size, scale);
+ return load_window_icon_from_desktop_id (desktop_id, size, scale);
}
GdkPixbuf*
-meta_ui_get_mini_icon_from_name (MetaUI *ui, char *name)
+meta_ui_get_mini_icon_from_desktop_id (MetaUI *ui, char *desktop_id)
{
int scale;
int size;
@@ -721,7 +698,7 @@ meta_ui_get_mini_icon_from_name (MetaUI *ui, char *name)
scale = gtk_widget_get_scale_factor (GTK_WIDGET (ui->frames));
size = META_MINI_ICON_WIDTH / scale;
- return load_window_icon_from_name (name, size, scale);
+ return load_window_icon_from_desktop_id (desktop_id, size, scale);
}
gboolean