diff --git a/debian/changelog b/debian/changelog index 624a5dfe..64c0dbfe 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +xapp (1.8.10) ulyana; urgency=medium + + [ Michael Webster ] + * sn-item.c: Prefer an icon name from the system theme instead of always sending an icon path. This doesn't work for symbolic icons. + * sn-item.c: Always set an available icon, regardless of visibility state requested by an app. The icon and visibility state aren't necessarily set at the same time. + + -- Clement Lefebvre Wed, 09 Sep 2020 10:39:34 +0100 + xapp (1.8.9) ulyana; urgency=medium [ Michael Webster ] diff --git a/meson.build b/meson.build index a2a414f7..040799a5 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project('xapp', 'c', - version : '1.8.9' + version : '1.8.10' ) gnome = import('gnome') diff --git a/xapp-sn-watcher/sn-item.c b/xapp-sn-watcher/sn-item.c index d5f8def2..ca6d1c59 100644 --- a/xapp-sn-watcher/sn-item.c +++ b/xapp-sn-watcher/sn-item.c @@ -393,6 +393,11 @@ set_icon_from_pixmap (SnItem *item, SnItemPropertiesResult *new_props) { surface = new_props->attention_icon_surface; } + else + if (new_props->icon_surface) + { + surface = new_props->icon_surface; + } } if (surface != NULL) @@ -423,9 +428,9 @@ set_icon_from_pixmap (SnItem *item, SnItemPropertiesResult *new_props) } static gchar * -get_icon_filename_from_theme (SnItem *item, - const gchar *theme_path, - const gchar *icon_name) +get_name_or_path_from_theme (SnItem *item, + const gchar *theme_path, + const gchar *icon_name) { GtkIconInfo *info; gchar *filename; @@ -435,7 +440,7 @@ get_icon_filename_from_theme (SnItem *item, array[0] = icon_name; array[1] = NULL; - // We have a theme path, but try the system theme first + // We may have a theme path, but try the system theme first GtkIconTheme *theme = gtk_icon_theme_get_default (); host_icon_size = get_icon_size (item); @@ -445,7 +450,15 @@ get_icon_filename_from_theme (SnItem *item, lookup_ui_scale (), GTK_ICON_LOOKUP_FORCE_SVG | GTK_ICON_LOOKUP_FORCE_SYMBOLIC); - if (info == NULL) + if (info != NULL) + { + // If the icon is found in the system theme, we can just pass along the icon name + // as is, this way symbolics work properly. + g_object_unref (info); + return g_strdup (icon_name); + } + + if (theme_path != NULL) { // Make a temp theme based off of the provided path GtkIconTheme *theme = gtk_icon_theme_new (); @@ -477,8 +490,10 @@ set_icon_name (SnItem *item, const gchar *icon_theme_path, const gchar *icon_name) { - g_debug ("Checking for icon name for %s", - item->sortable_name); + g_debug ("Checking for icon name for %s - theme path: '%s', icon name: '%s'", + item->sortable_name, + icon_theme_path, + icon_name); if (icon_name == NULL) { @@ -488,17 +503,16 @@ set_icon_name (SnItem *item, if (g_path_is_absolute (icon_name)) { xapp_status_icon_set_icon_name (item->status_icon, icon_name); - return TRUE; } else { - gchar *filename = get_icon_filename_from_theme (item, icon_theme_path, icon_name); + gchar *used_name = get_name_or_path_from_theme (item, icon_theme_path, icon_name); - if (filename != NULL) + if (used_name != NULL) { - xapp_status_icon_set_icon_name (item->status_icon, filename); - g_free (filename); + xapp_status_icon_set_icon_name (item->status_icon, used_name); + g_free (used_name); return TRUE; } } @@ -512,7 +526,10 @@ set_icon_name_or_path (SnItem *item, { const gchar *name_to_use = NULL; - if (item->status == STATUS_ACTIVE) + // Set an icon here, even if we're passive (hidden) - eventually only the + // status property might change, but we wouldn't have an icon then (unless + // the app sets the icon at the same time). + if (item->status == STATUS_ACTIVE || item->status == STATUS_PASSIVE) { if (new_props->icon_name) { @@ -717,7 +734,7 @@ get_all_properties_callback (GObject *source_object, { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - g_critical ("Could get propertyies for %s: %s\n", + g_critical ("Could not get properties for %s: %s\n", g_dbus_proxy_get_name (item->sn_item_proxy), error->message); } @@ -888,7 +905,7 @@ get_all_properties_callback (GObject *source_object, update_menu (item, new_props); } - if (new_props->update_icon) + if (new_props->update_icon || new_props->update_status) { update_icon (item, new_props); } diff --git a/xapp-sn-watcher/xapp-sn-watcher.c b/xapp-sn-watcher/xapp-sn-watcher.c index 3d25ef6f..802bd8ca 100644 --- a/xapp-sn-watcher/xapp-sn-watcher.c +++ b/xapp-sn-watcher/xapp-sn-watcher.c @@ -307,6 +307,18 @@ typedef struct gchar *service; } NewSnProxyData; +static void +free_sn_proxy_data (NewSnProxyData *data) +{ + g_free (data->key); + g_free (data->path); + g_free (data->bus_name); + g_free (data->service); + g_object_unref (data->invocation); + + g_slice_free (NewSnProxyData, data); +} + static void sn_item_proxy_new_completed (GObject *source, GAsyncResult *res, @@ -322,6 +334,24 @@ sn_item_proxy_new_completed (GObject *source, proxy = sn_item_interface_proxy_new_finish (res, &error); + g_hash_table_steal_extended (watcher->items, + data->key, + &stolen_ptr, + NULL); + + if ((gchar *) stolen_ptr == NULL) + { + g_dbus_method_invocation_return_error (data->invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "New StatusNotifierItem disappeared before " + "its registration was complete."); + + free_sn_proxy_data (data); + g_clear_object (&proxy); + return; + } + if (error != NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -330,11 +360,8 @@ sn_item_proxy_new_completed (GObject *source, data->bus_name, error->message); } - g_hash_table_steal_extended (watcher->items, - data->key, - &stolen_ptr, - NULL); g_free (stolen_ptr); + free_sn_proxy_data (data); g_dbus_method_invocation_take_error (data->invocation, error); return; @@ -343,11 +370,6 @@ sn_item_proxy_new_completed (GObject *source, item = sn_item_new ((GDBusProxy *) proxy, g_str_has_prefix (data->path, APPINDICATOR_PATH_PREFIX)); - g_hash_table_steal_extended (watcher->items, - data->key, - &stolen_ptr, - NULL); - g_hash_table_insert (watcher->items, stolen_ptr, item); @@ -360,12 +382,7 @@ sn_item_proxy_new_completed (GObject *source, sn_watcher_interface_complete_register_status_notifier_item (watcher->skeleton, data->invocation); - g_free (data->key); - g_free (data->path); - g_free (data->bus_name); - g_free (data->service); - g_object_unref (data->invocation); - g_slice_free (NewSnProxyData, data); + free_sn_proxy_data (data); } static gboolean @@ -493,6 +510,26 @@ continue_startup (XAppSnWatcher *watcher) NULL); } +static void +unref_proxy (gpointer data) +{ + // if g_hash_table_remove is called from handle_sn_item_name_owner_lost + // *before* sn_item_proxy_new_completed is complete, the key will be + // pointing to a NULL value, so avoid trying to free it. + + if (data == NULL) + { + return; + } + + SnItem *item = SN_ITEM (data); + + if (item) + { + g_object_unref (item); + } +} + static void watcher_startup (GApplication *application) { @@ -504,7 +541,7 @@ watcher_startup (GApplication *application) xapp_settings = g_settings_new (STATUS_ICON_SCHEMA); watcher->items = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, g_object_unref); + g_free, (GDestroyNotify) unref_proxy); /* This buys us 30 seconds (gapp timeout) - we'll either be re-held immediately * because there's a monitor or exit after the 30 seconds. */