From 67981227770dcea0bb0fe0ff21cb87bba2bdf794 Mon Sep 17 00:00:00 2001 From: Eric Koegel Date: Sat, 7 Apr 2012 11:00:45 +0300 Subject: [PATCH] Emblems on thumbnail file icons are missing (Bug #8645) Fix how gdk_pixbuf_composite draws the emblem to the icon so that icons with a different width & height work. This patch also reworks how the respective peek_pixbuf functions work to cut down on unnecessary actions. --- src/xfdesktop-file-icon-manager.c | 10 ++- src/xfdesktop-file-utils.c | 35 ++++++---- src/xfdesktop-regular-file-icon.c | 132 +++++++++++++++++++++---------------- src/xfdesktop-special-file-icon.c | 78 +++++++++++++++------- src/xfdesktop-volume-icon.c | 60 +++++++++++------ 5 files changed, 197 insertions(+), 118 deletions(-) diff --git a/src/xfdesktop-file-icon-manager.c b/src/xfdesktop-file-icon-manager.c index 0c6b244..b6e015a 100644 --- a/src/xfdesktop-file-icon-manager.c +++ b/src/xfdesktop-file-icon-manager.c @@ -1927,13 +1927,15 @@ xfdesktop_file_icon_manager_add_icon(XfdesktopFileIconManager *fmanager, gboolean do_add = FALSE; const gchar *name; GFile *file; + gchar *path = NULL; file = xfdesktop_file_icon_peek_file(icon); - if(fmanager->priv->show_thumbnails && g_file_get_path(file) != NULL) { - xfdesktop_thumbnailer_queue_thumbnail(fmanager->priv->thumbnailer, - g_file_get_path(file)); - } + if(file != NULL) + path = g_file_get_path(file); + + if(fmanager->priv->show_thumbnails && path != NULL) + xfdesktop_thumbnailer_queue_thumbnail(fmanager->priv->thumbnailer, path); name = xfdesktop_icon_peek_label(XFDESKTOP_ICON(icon)); diff --git a/src/xfdesktop-file-utils.c b/src/xfdesktop-file-utils.c index 2670bbd..e8e2d62 100644 --- a/src/xfdesktop-file-utils.c +++ b/src/xfdesktop-file-utils.c @@ -505,7 +505,7 @@ xfdesktop_file_utils_get_icon(const gchar *custom_icon_name, } if(!pix_theme && icon) { - if(G_IS_THEMED_ICON(icon)) { + if(G_IS_THEMED_ICON(icon) || G_IS_FILE_ICON(icon)) { GtkIconInfo *icon_info = gtk_icon_theme_lookup_by_gicon(itheme, icon, size, ITHEME_FLAGS); @@ -541,8 +541,16 @@ xfdesktop_file_utils_get_icon(const gchar *custom_icon_name, } if(emblem) { - gint emblem_pix_size = gdk_pixbuf_get_width(emblem); - gint dest_size = size - emblem_pix_size; + gint pix_width, pix_height; + gint emblem_size; + gint dest_width, dest_height; + + pix_width = gdk_pixbuf_get_width(pix); + pix_height = gdk_pixbuf_get_height(pix); + emblem_size = gdk_pixbuf_get_width(emblem); + + dest_width = pix_width - emblem_size; + dest_height = pix_height - emblem_size; /* if we're using the fallback icon, we don't want to draw an emblem on * it, since other icons might use it without the emblem */ @@ -552,20 +560,21 @@ xfdesktop_file_utils_get_icon(const gchar *custom_icon_name, pix = tmp; } - if(dest_size < 0) - g_critical("xfdesktop_file_utils_get_file_icon(): (dest_size > 0) failed"); + if(dest_width < 0 || dest_height < 0) + g_critical("xfdesktop_file_utils_get_file_icon(): (dest_width < 0 || dest_height < 0) failed"); else { - DBG("calling gdk_pixbuf_composite(%p, %p, %d, %d, %d, %d, %.1f, %.1f, %.1f, %.1f, %d, %d)", + DBG("calling gdk_pixbuf_composite(%p, %p, %d, %d, %d, %d, %d, %d, %.1f, %.1f, %d, %d) pixbuf w: %d h: %d\n", emblem, pix, - dest_size, dest_size, - emblem_pix_size, emblem_pix_size, - (gdouble)dest_size, (gdouble)dest_size, - 1.0, 1.0, GDK_INTERP_BILINEAR, 255); + dest_width, dest_height, + emblem_size, emblem_size, + dest_width, dest_height, + 1.0, 1.0, GDK_INTERP_BILINEAR, 255, pix_width, pix_height); + /* Add the emblem */ gdk_pixbuf_composite(emblem, pix, - dest_size, dest_size, - emblem_pix_size, emblem_pix_size, - dest_size, dest_size, + dest_width, dest_height, + emblem_size, emblem_size, + dest_width, dest_height, 1.0, 1.0, GDK_INTERP_BILINEAR, 255); } } diff --git a/src/xfdesktop-regular-file-icon.c b/src/xfdesktop-regular-file-icon.c index f42f6d6..47546d0 100644 --- a/src/xfdesktop-regular-file-icon.c +++ b/src/xfdesktop-regular-file-icon.c @@ -59,6 +59,8 @@ struct _XfdesktopRegularFileIconPrivate { GdkPixbuf *pix; + GIcon *gicon; + gchar *icon_name; gchar *display_name; gchar *tooltip; guint pix_opacity; @@ -97,7 +99,7 @@ static void xfdesktop_regular_file_icon_tfi_init(ThunarxFileInfoIface *iface); #endif static inline void xfdesktop_regular_file_icon_invalidate_pixbuf(XfdesktopRegularFileIcon *icon); - +static inline void xfdesktop_regular_file_icon_release_gicon(XfdesktopRegularFileIcon *icon); #ifdef HAVE_THUNARX G_DEFINE_TYPE_EXTENDED(XfdesktopRegularFileIcon, xfdesktop_regular_file_icon, @@ -148,6 +150,8 @@ xfdesktop_regular_file_icon_init(XfdesktopRegularFileIcon *icon) XfdesktopRegularFileIconPrivate); icon->priv->pix_opacity = 100; icon->priv->display_name = NULL; + icon->priv->gicon = NULL; + icon->priv->icon_name = NULL; } static void @@ -178,7 +182,13 @@ xfdesktop_regular_file_icon_finalize(GObject *obj) if(icon->priv->thumbnail_file) g_object_unref(icon->priv->thumbnail_file); - + + if(icon->priv->gicon) + g_object_unref(icon->priv->gicon); + + if(icon->priv->icon_name) + g_free(icon->priv->icon_name); + G_OBJECT_CLASS(xfdesktop_regular_file_icon_parent_class)->finalize(obj); } @@ -223,6 +233,8 @@ xfdesktop_regular_file_icon_delete_thumbnail_file(XfdesktopIcon *icon) file_icon->priv->thumbnail_file = NULL; } + xfdesktop_regular_file_icon_release_gicon(file_icon); + xfdesktop_regular_file_icon_invalidate_pixbuf(file_icon); xfdesktop_icon_pixbuf_changed(XFDESKTOP_ICON(icon)); } @@ -242,6 +254,8 @@ xfdesktop_regular_file_icon_set_thumbnail_file(XfdesktopIcon *icon, GFile *file) file_icon->priv->thumbnail_file = file; + xfdesktop_regular_file_icon_release_gicon(file_icon); + xfdesktop_regular_file_icon_invalidate_pixbuf(file_icon); xfdesktop_icon_pixbuf_changed(XFDESKTOP_ICON(icon)); } @@ -251,23 +265,30 @@ xfdesktop_regular_file_icon_peek_pixbuf(XfdesktopIcon *icon, gint size) { XfdesktopRegularFileIcon *file_icon = XFDESKTOP_REGULAR_FILE_ICON(icon); - gchar *icon_name = NULL; GdkPixbuf *emblem_pix = NULL; if(size != file_icon->priv->cur_pix_size) xfdesktop_regular_file_icon_invalidate_pixbuf(file_icon); - if(!file_icon->priv->pix) { - GIcon *gicon = NULL; + /* Still valid */ + if(file_icon->priv->pix != NULL) + return file_icon->priv->pix; + if(file_icon->priv->gicon == NULL) { /* create a GFile for the $HOME/.thumbnails/ directory */ gchar *thumbnail_dir_path = g_build_filename(xfce_get_homedir(), ".thumbnails", NULL); GFile *thumbnail_dir = g_file_new_for_path(thumbnail_dir_path); + /* Ensure the previous icon_name gets cleared out */ + if(file_icon->priv->icon_name) { + g_free(file_icon->priv->icon_name); + file_icon->priv->icon_name = NULL; + } + if(g_file_has_prefix(file_icon->priv->file, thumbnail_dir)) { /* use the filename as custom icon name for thumbnails */ - icon_name = g_file_get_path(file_icon->priv->file); + file_icon->priv->icon_name = g_file_get_path(file_icon->priv->file); /* release thumbnail path */ g_object_unref(thumbnail_dir); @@ -286,7 +307,7 @@ xfdesktop_regular_file_icon_peek_pixbuf(XfdesktopIcon *icon, /* try to parse the key file from the contents of the file */ if (g_key_file_load_from_data(key_file, contents, length, 0, NULL)) { /* try to determine the custom icon name */ - icon_name = g_key_file_get_string(key_file, + file_icon->priv->icon_name = g_key_file_get_string(key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_ICON, NULL); @@ -300,64 +321,50 @@ xfdesktop_regular_file_icon_peek_pixbuf(XfdesktopIcon *icon, /* If we have a thumbnail then they are enabled, use it. */ if(file_icon->priv->thumbnail_file) { - file_icon->priv->pix = gdk_pixbuf_new_from_file_at_size(g_file_get_path(file_icon->priv->thumbnail_file), - size, size, - NULL); + file_icon->priv->gicon = g_file_icon_new(file_icon->priv->thumbnail_file); + } + else + { + file_icon->priv->gicon = g_file_info_get_icon(file_icon->priv->file_info); + if(file_icon->priv->gicon) + g_object_ref(file_icon->priv->gicon); } } + } - /* load the symlink emblem if necessary */ - if(g_file_info_get_attribute_boolean(file_icon->priv->file_info, - G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK)) - { - GtkIconTheme *itheme = gtk_icon_theme_get_default(); - gint sym_pix_size = size * 2 / 3; - - emblem_pix = gtk_icon_theme_load_icon(itheme, EMBLEM_SYMLINK, - sym_pix_size, ITHEME_FLAGS, - NULL); - if(emblem_pix) { - if(gdk_pixbuf_get_width(emblem_pix) != sym_pix_size - || gdk_pixbuf_get_height(emblem_pix) != sym_pix_size) - { - GdkPixbuf *tmp = gdk_pixbuf_scale_simple(emblem_pix, - sym_pix_size, - sym_pix_size, - GDK_INTERP_BILINEAR); - g_object_unref(emblem_pix); - emblem_pix = tmp; - } + /* load the symlink emblem if necessary */ + if(g_file_info_get_attribute_boolean(file_icon->priv->file_info, + G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK)) + { + GtkIconTheme *itheme = gtk_icon_theme_get_default(); + gint sym_pix_size = size / 3; + + emblem_pix = gtk_icon_theme_load_icon(itheme, EMBLEM_SYMLINK, + sym_pix_size, ITHEME_FLAGS, + NULL); + if(emblem_pix) { + if(gdk_pixbuf_get_width(emblem_pix) != sym_pix_size + || gdk_pixbuf_get_height(emblem_pix) != sym_pix_size) + { + GdkPixbuf *tmp = gdk_pixbuf_scale_simple(emblem_pix, + sym_pix_size, + sym_pix_size, + GDK_INTERP_BILINEAR); + g_object_unref(emblem_pix); + emblem_pix = tmp; } } + } - if(file_icon->priv->file_info) - gicon = g_file_info_get_icon(file_icon->priv->file_info); - - if(file_icon->priv->pix) { - if(emblem_pix) { - gint emblem_pix_size = gdk_pixbuf_get_width(emblem_pix); - gint dest_size = size - emblem_pix_size; + file_icon->priv->pix = xfdesktop_file_utils_get_icon(file_icon->priv->icon_name, + file_icon->priv->gicon, + size, emblem_pix, + file_icon->priv->pix_opacity); - /* We have to add the emblem */ - gdk_pixbuf_composite(emblem_pix, file_icon->priv->pix, - dest_size, dest_size, - emblem_pix_size, emblem_pix_size, - dest_size, dest_size, - 1.0, 1.0, GDK_INTERP_BILINEAR, 255); - } - } else { - file_icon->priv->pix = xfdesktop_file_utils_get_icon(icon_name, gicon, - size, emblem_pix, - file_icon->priv->pix_opacity); - } - - file_icon->priv->cur_pix_size = size; + file_icon->priv->cur_pix_size = size; - if(emblem_pix) - g_object_unref(emblem_pix); - - g_free(icon_name); - } + if(emblem_pix) + g_object_unref(emblem_pix); return file_icon->priv->pix; } @@ -686,6 +693,7 @@ xfdesktop_regular_file_icon_update_file_info(XfdesktopFileIcon *icon, regular_file_icon->priv->tooltip = NULL; /* not really easy to check if this changed or not, so just invalidate it */ + xfdesktop_regular_file_icon_release_gicon(regular_file_icon); xfdesktop_regular_file_icon_invalidate_pixbuf(regular_file_icon); xfdesktop_icon_pixbuf_changed(XFDESKTOP_ICON(icon)); } @@ -748,3 +756,13 @@ xfdesktop_regular_file_icon_set_pixbuf_opacity(XfdesktopRegularFileIcon *icon, xfdesktop_regular_file_icon_invalidate_pixbuf(icon); xfdesktop_icon_pixbuf_changed(XFDESKTOP_ICON(icon)); } + +static inline void +xfdesktop_regular_file_icon_release_gicon(XfdesktopRegularFileIcon *icon) +{ + /* release the old icon */ + if(icon->priv->gicon) { + g_object_unref(icon->priv->gicon); + icon->priv->gicon = NULL; + } +} diff --git a/src/xfdesktop-special-file-icon.c b/src/xfdesktop-special-file-icon.c index fa0bc0b..ee81281 100644 --- a/src/xfdesktop-special-file-icon.c +++ b/src/xfdesktop-special-file-icon.c @@ -56,6 +56,8 @@ struct _XfdesktopSpecialFileIconPrivate { XfdesktopSpecialFileIconType type; GdkPixbuf *pix; + GIcon *gicon; + gchar *icon_name; gchar *tooltip; gint cur_pix_size; GFileMonitor *monitor; @@ -98,7 +100,7 @@ static void xfdesktop_special_file_icon_tfi_init(ThunarxFileInfoIface *iface); static inline void xfdesktop_special_file_icon_invalidate_pixbuf(XfdesktopSpecialFileIcon *icon); - +static inline void xfdesktop_special_file_icon_release_gicon(XfdesktopSpecialFileIcon *icon); #ifdef HAVE_THUNARX G_DEFINE_TYPE_EXTENDED(XfdesktopSpecialFileIcon, xfdesktop_special_file_icon, @@ -145,6 +147,8 @@ xfdesktop_special_file_icon_init(XfdesktopSpecialFileIcon *icon) icon->priv = G_TYPE_INSTANCE_GET_PRIVATE(icon, XFDESKTOP_TYPE_SPECIAL_FILE_ICON, XfdesktopSpecialFileIconPrivate); + icon->priv->gicon = NULL; + icon->priv->icon_name = NULL; } static void @@ -174,7 +178,13 @@ xfdesktop_special_file_icon_finalize(GObject *obj) if(icon->priv->tooltip) g_free(icon->priv->tooltip); - + + if(icon->priv->gicon) + g_object_unref(icon->priv->gicon); + + if(icon->priv->icon_name) + g_free(icon->priv->icon_name); + G_OBJECT_CLASS(xfdesktop_special_file_icon_parent_class)->finalize(obj); } @@ -220,38 +230,47 @@ xfdesktop_special_file_icon_peek_pixbuf(XfdesktopIcon *icon, gint size) { XfdesktopSpecialFileIcon *file_icon = XFDESKTOP_SPECIAL_FILE_ICON(icon); - GIcon *gicon = NULL; - const gchar *custom_icon_name = NULL; GFile *parent = NULL; if(size != file_icon->priv->cur_pix_size) xfdesktop_special_file_icon_invalidate_pixbuf(file_icon); - /* Already have a good icon */ + /* Still valid */ if(file_icon->priv->pix != NULL) return file_icon->priv->pix; - /* use a custom icon name for the local filesystem root */ - parent = g_file_get_parent(file_icon->priv->file); - if(!parent && g_file_has_uri_scheme(file_icon->priv->file, "file")) - custom_icon_name = "drive-harddisk"; - if(parent) - g_object_unref(parent); - - /* use a custom icon for the trash, based on it having files - * the user can delete */ - if(file_icon->priv->type == XFDESKTOP_SPECIAL_FILE_ICON_TRASH) { - if(file_icon->priv->trash_item_count == 0) - custom_icon_name = "user-trash"; - else - custom_icon_name = "user-trash-full"; - } + if(file_icon->priv->gicon == NULL) { + /* Ensure the previous icon_name gets cleared out */ + if(file_icon->priv->icon_name) { + g_free(file_icon->priv->icon_name); + file_icon->priv->icon_name = NULL; + } + + /* use a custom icon name for the local filesystem root */ + parent = g_file_get_parent(file_icon->priv->file); + if(!parent && g_file_has_uri_scheme(file_icon->priv->file, "file")) + file_icon->priv->icon_name = g_strdup("drive-harddisk"); + if(parent) + g_object_unref(parent); + + /* use a custom icon for the trash, based on it having files + * the user can delete */ + if(file_icon->priv->type == XFDESKTOP_SPECIAL_FILE_ICON_TRASH) { + if(file_icon->priv->trash_item_count == 0) + file_icon->priv->icon_name = g_strdup("user-trash"); + else + file_icon->priv->icon_name = g_strdup("user-trash-full"); + } + + if(file_icon->priv->file_info) + file_icon->priv->gicon = g_file_info_get_icon(file_icon->priv->file_info); - if(file_icon->priv->file_info) - gicon = g_file_info_get_icon(file_icon->priv->file_info); + if(file_icon->priv->gicon) + g_object_ref(file_icon->priv->gicon); + } - file_icon->priv->pix = xfdesktop_file_utils_get_icon(custom_icon_name, - gicon, + file_icon->priv->pix = xfdesktop_file_utils_get_icon(file_icon->priv->icon_name, + file_icon->priv->gicon, size, NULL, 100); @@ -594,6 +613,7 @@ xfdesktop_special_file_icon_changed(GFileMonitor *monitor, special_file_icon->priv->tooltip = NULL; /* update the icon */ + xfdesktop_special_file_icon_release_gicon(special_file_icon); xfdesktop_special_file_icon_invalidate_pixbuf(special_file_icon); xfdesktop_icon_pixbuf_changed(XFDESKTOP_ICON(special_file_icon)); } @@ -719,3 +739,13 @@ xfdesktop_special_file_icon_get_icon_type(XfdesktopSpecialFileIcon *icon) g_return_val_if_fail(XFDESKTOP_IS_SPECIAL_FILE_ICON(icon), -1); return icon->priv->type; } + +static inline void +xfdesktop_special_file_icon_release_gicon(XfdesktopSpecialFileIcon *icon) +{ + /* release the old icon */ + if(icon->priv->gicon) { + g_object_unref(icon->priv->gicon); + icon->priv->gicon = NULL; + } +} diff --git a/src/xfdesktop-volume-icon.c b/src/xfdesktop-volume-icon.c index c0cae93..9bffcd2 100644 --- a/src/xfdesktop-volume-icon.c +++ b/src/xfdesktop-volume-icon.c @@ -61,6 +61,7 @@ struct _XfdesktopVolumeIconPrivate { GdkPixbuf *pix; + GIcon *gicon; gchar *tooltip; gint cur_pix_size; gchar *label; @@ -103,7 +104,7 @@ static void xfdesktop_volume_icon_tfi_init(ThunarxFileInfoIface *iface); #endif static inline void xfdesktop_volume_icon_invalidate_pixbuf(XfdesktopVolumeIcon *icon); - +static inline void xfdesktop_volume_icon_release_gicon(XfdesktopVolumeIcon *icon); #ifdef HAVE_THUNARX G_DEFINE_TYPE_EXTENDED(XfdesktopVolumeIcon, xfdesktop_volume_icon, @@ -157,6 +158,7 @@ xfdesktop_volume_icon_init(XfdesktopVolumeIcon *icon) { icon->priv = G_TYPE_INSTANCE_GET_PRIVATE(icon, XFDESKTOP_TYPE_VOLUME_ICON, XfdesktopVolumeIconPrivate); + icon->priv->gicon = NULL; } static void @@ -195,7 +197,10 @@ xfdesktop_volume_icon_finalize(GObject *obj) if(icon->priv->tooltip) g_free(icon->priv->tooltip); - + + if(icon->priv->gicon) + g_object_unref(icon->priv->gicon); + G_OBJECT_CLASS(xfdesktop_volume_icon_parent_class)->finalize(obj); } @@ -256,34 +261,38 @@ xfdesktop_volume_icon_peek_pixbuf(XfdesktopIcon *icon, gint size) { XfdesktopVolumeIcon *file_icon = XFDESKTOP_VOLUME_ICON(icon); + gint opacity = 100; g_return_val_if_fail(XFDESKTOP_IS_VOLUME_ICON(icon), NULL); if(size != file_icon->priv->cur_pix_size) xfdesktop_volume_icon_invalidate_pixbuf(file_icon); - if(!file_icon->priv->pix) { - GIcon *gicon = NULL; + /* Still valid */ + if(file_icon->priv->pix != NULL) + return file_icon->priv->pix; - if(file_icon->priv->volume) - gicon = g_volume_get_icon(file_icon->priv->volume); + if(file_icon->priv->gicon == NULL) { + /* icon changed, get a new one and keep a ref to it */ + if(file_icon->priv->volume) { + file_icon->priv->gicon = g_volume_get_icon(file_icon->priv->volume); - file_icon->priv->pix = xfdesktop_file_utils_get_icon(NULL, gicon, size, - NULL, 100); - - /* If the volume isn't mounted show it as semi-transparent */ - if(!xfdesktop_volume_icon_is_mounted(icon)) { - GdkPixbuf *temp; - temp = exo_gdk_pixbuf_lucent(file_icon->priv->pix, 50); - - if(temp != NULL) { - g_object_unref(G_OBJECT(file_icon->priv->pix)); - file_icon->priv->pix = temp; - } + if(file_icon->priv->gicon) + g_object_ref(file_icon->priv->gicon); } - - file_icon->priv->cur_pix_size = size; } + + /* If the volume isn't mounted show it as semi-transparent */ + if(!xfdesktop_volume_icon_is_mounted(icon)) + opacity = 50; + + file_icon->priv->pix = xfdesktop_file_utils_get_icon(NULL, + file_icon->priv->gicon, + size, + NULL, + opacity); + + file_icon->priv->cur_pix_size = size; return file_icon->priv->pix; } @@ -796,6 +805,7 @@ xfdesktop_volume_icon_update_file_info(XfdesktopFileIcon *icon, } /* not really easy to check if this changed or not, so just invalidate it */ + xfdesktop_volume_icon_release_gicon(volume_icon); xfdesktop_volume_icon_invalidate_pixbuf(volume_icon); xfdesktop_icon_pixbuf_changed(XFDESKTOP_ICON(icon)); } @@ -997,3 +1007,13 @@ xfdesktop_volume_icon_peek_volume(XfdesktopVolumeIcon *icon) g_return_val_if_fail(XFDESKTOP_IS_VOLUME_ICON(icon), NULL); return icon->priv->volume; } + +static inline void +xfdesktop_volume_icon_release_gicon(XfdesktopVolumeIcon *icon) +{ + /* release the old icon */ + if(icon->priv->gicon) { + g_object_unref(icon->priv->gicon); + icon->priv->gicon = NULL; + } +} -- 1.7.5.4