5656
5757#include <regex.h>
5858
59- #include <cairo.h> // To get the size of icons, determine_icon_destination ()
59+ #include <cairo.h> // To get the size of icons, move_icon_to_destination ()
6060
6161#define FNM_FILE_NAME 2
6262
@@ -127,16 +127,17 @@ char * get_thumbnail_path(char *path, char *thumbnail_size, gboolean verbose)
127127 return thumbnail_path ;
128128}
129129
130- /* Return the path where a given icon can be installed in $HOME.
130+ /* Move an icon file to the path where a given icon can be installed in $HOME.
131131 * This is needed because png and xpm icons cannot be installed in a generic
132132 * location but are only picked up in directories that have the size of
133133 * the icon as part of their directory name, as specified in the theme.index
134134 * See https://github.com/probonopd/AppImageKit/issues/258
135135 */
136136
137- gchar * determine_icon_destination (gchar * icon_path )
137+ void move_icon_to_destination (gchar * icon_path , gboolean verbose )
138138{
139- gchar * dest_dir ;
139+ // FIXME: This default location is most likely wrong, icons there will be ignored
140+ gchar * dest_dir = dest_dir = g_build_path ("/" , g_get_user_data_dir (), "/icons/hicolor/" , NULL );;
140141
141142 if ((g_str_has_suffix (icon_path , ".svg" )) || (g_str_has_suffix (icon_path , ".svgz" ))) {
142143 dest_dir = g_build_path ("/" , g_get_user_data_dir (), "/icons/hicolor/scalable" , NULL );
@@ -145,36 +146,51 @@ gchar* determine_icon_destination(gchar *icon_path)
145146 if ((g_str_has_suffix (icon_path , ".png" )) || (g_str_has_suffix (icon_path , ".xpm" ))) {
146147
147148 cairo_surface_t * image ;
148-
149+
150+ int w = 0 ;
151+ int h = 0 ;
152+
149153 if (g_str_has_suffix (icon_path , ".xpm" )) {
150154 // TODO: GdkPixbuf has a convenient way to load XPM data. Then you can call
151155 // gdk_cairo_set_source_pixbuf() to transfer the data to a Cairo surface.
152156 fprintf (stderr , "XPM size parsing not yet implemented\n" );
153- return NULL ;
154157 }
155158
159+
156160 if (g_str_has_suffix (icon_path , ".png" )) {
157161 image = cairo_image_surface_create_from_png (icon_path );
162+ w = cairo_image_surface_get_width (image );
163+ h = cairo_image_surface_get_height (image );
164+ cairo_surface_destroy (image );
158165 }
159-
160- int w = cairo_image_surface_get_width (image );
161- int h = cairo_image_surface_get_height (image );
162-
166+
163167 // FIXME: The following sizes are taken from the hicolor icon theme.
164168 // Probably the right thing to do would be to figure out at runtime which icon sizes are allowable.
165169 // Or could we put our own index.theme into .local/share/icons/ and have it observed?
166170 if ((w != h ) || ((w != 16 ) && (w != 24 ) && (w != 32 ) && (w != 36 ) && (w != 48 ) && (w != 64 ) && (w != 72 ) && (w != 96 ) && (w != 128 ) && (w != 192 ) && (w != 256 ) && (w != 512 ))){
167171 fprintf (stderr , "%s has nonstandard size w = %i, h = %i; please fix it\n" , icon_path , w , h );
168- return NULL ;
172+ } else {
173+ dest_dir = g_build_path ("/" , g_get_user_data_dir (), "/icons/hicolor/" , g_strdup_printf ("%ix%i" , w , h ), NULL );
169174 }
170-
171- cairo_surface_destroy (image );
172-
173- dest_dir = g_build_path ("/" , g_get_user_data_dir (), "/icons/hicolor/" , g_strdup_printf ("%ix%i" , w , h ), NULL );
174175 }
175-
176- return (dest_dir );
177-
176+ if (verbose )
177+ fprintf (stderr , "dest_dir %s\n" , dest_dir );
178+
179+ gchar * icon_dest_path = g_build_path ("/" , dest_dir , g_path_get_basename (icon_path ), NULL );
180+ if (verbose )
181+ fprintf (stderr , "Move from %s to %s\n" , icon_path , icon_dest_path );
182+ if (g_mkdir_with_parents (g_path_get_dirname (dest_dir ), 0755 ))
183+ fprintf (stderr , "Could not create directory: %s\n" , dest_dir );
184+ GError * error = NULL ;
185+ GFile * icon_file = g_file_new_for_path (icon_path );
186+ GFile * target_file = g_file_new_for_path (icon_dest_path );
187+ if (!g_file_move (icon_file , target_file , G_FILE_COPY_OVERWRITE , NULL , NULL , NULL , & error )) {
188+ fprintf (stderr , "Error moving file: %s\n" , error -> message );
189+ g_error_free (error );
190+ }
191+ g_object_unref (icon_file );
192+ g_object_unref (target_file );
193+
178194}
179195
180196/* Check if a file is an AppImage. Returns the image type if it is, or -1 if it isn't */
@@ -279,12 +295,12 @@ gchar **squash_get_matching_files(sqfs *fs, char *pattern, gchar *desktop_icon_v
279295 * share/pixmaps is ONLY searched in /usr but not in $XDG_DATA_DIRS and hence $HOME and this seems to be true at least in XFCE */
280296 if (g_str_has_prefix (trv .path , "usr/share/pixmaps/" )){
281297 dest_basename = g_strdup_printf ("%s_%s_%s" , vendorprefix , md5 , g_path_get_basename (trv .path ));
282- dest = g_build_path ("/" , g_get_user_data_dir (), "/icons/hicolor/scalable/apps/ " , dest_basename , NULL );
298+ dest = g_build_path ("/" , "/tmp " , dest_basename , NULL );
283299 }
284300 /* Some AppImages only have the icon in their root directory, so we have to get it from there */
285301 if ((g_str_has_prefix (trv .path , desktop_icon_value_original )) && (! strstr (trv .path , "/" )) && ( (g_str_has_suffix (trv .path , ".png" )) || (g_str_has_suffix (trv .path , ".xpm" )) || (g_str_has_suffix (trv .path , ".svg" )) || (g_str_has_suffix (trv .path , ".svgz" )))){
286302 dest_basename = g_strdup_printf ("%s_%s_%s.%s" , vendorprefix , md5 , desktop_icon_value_original , get_file_extension (trv .path ));
287- dest = g_build_path ("/" , g_get_user_data_dir (), "/icons/hicolor/scalable/apps/ " , dest_basename , NULL );
303+ dest = g_build_path ("/" , "/tmp " , dest_basename , NULL );
288304 }
289305
290306 if (dest ){
@@ -315,6 +331,12 @@ gchar **squash_get_matching_files(sqfs *fs, char *pattern, gchar *desktop_icon_v
315331
316332 if (verbose )
317333 fprintf (stderr , "Installed: %s\n" , dest );
334+
335+ // If we were unsure about the size of an icon, we temporarily installed
336+ // it to /tmp and now move it into the proper place
337+ if (g_str_has_prefix (dest , "/tmp/" )) {
338+ move_icon_to_destination (dest , verbose );
339+ }
318340 }
319341 }
320342 }
@@ -660,13 +682,13 @@ bool appimage_type1_register_in_system(char *path, gboolean verbose)
660682 /* According to https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#install_icons
661683 * share/pixmaps is ONLY searched in /usr but not in $XDG_DATA_DIRS and hence $HOME and this seems to be true at least in XFCE */
662684 if (g_str_has_prefix (filename , "usr/share/pixmaps/" )){
663- dest = g_build_path ("/" , g_get_home_dir (), ".icons " , dest_basename , NULL );
685+ dest = g_build_path ("/" , "/tmp " , dest_basename , NULL );
664686 }
665687 /* Some AppImages only have the icon in their root directory, so we have to get it from there */
666688 if (desktop_icon_value_original ){
667689 if ((g_str_has_prefix (filename , desktop_icon_value_original )) && (! strstr (filename , "/" )) && ( (g_str_has_suffix (filename , ".png" )) || (g_str_has_suffix (filename , ".xpm" )) || (g_str_has_suffix (filename , ".svg" )) || (g_str_has_suffix (filename , ".svgz" )))){
668690 dest_basename = g_strdup_printf ("%s_%s_%s.%s" , vendorprefix , md5 , desktop_icon_value_original , get_file_extension (filename ));
669- dest = g_build_path ("/" , g_get_home_dir (), ".icons " , dest_basename , NULL );
691+ dest = g_build_path ("/" , "/tmp " , dest_basename , NULL );
670692 }
671693 }
672694
@@ -708,7 +730,14 @@ bool appimage_type1_register_in_system(char *path, gboolean verbose)
708730
709731
710732 if (verbose )
711- fprintf (stderr , "Installed: %s\n" , dest );
733+ fprintf (stderr , "Installed: %s\n" , dest );
734+
735+ // If we were unsure about the size of an icon, we temporarily installed
736+ // it to /tmp and now move it into the proper place
737+ if (g_str_has_prefix (dest , "/tmp/" )) {
738+ move_icon_to_destination (dest , verbose );
739+ }
740+
712741 }
713742 }
714743 archive_read_close (a );
0 commit comments