summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/feh.h10
-rw-r--r--src/filelist.c11
-rw-r--r--src/imlib.c194
-rw-r--r--src/index.c2
-rw-r--r--src/menu.c17
-rw-r--r--src/slideshow.c93
-rw-r--r--src/thumbnail.c2
-rw-r--r--src/timers.c33
-rw-r--r--src/timers.h2
-rw-r--r--src/winwidget.c7
10 files changed, 301 insertions, 70 deletions
diff --git a/src/feh.h b/src/feh.h
index e735871..0b7b627 100644
--- a/src/feh.h
+++ b/src/feh.h
@@ -115,6 +115,14 @@ enum slide_change { SLIDE_NEXT, SLIDE_PREV, SLIDE_RAND, SLIDE_FIRST, SLIDE_LAST,
SLIDE_JUMP_PREV_DIR
};
+enum feh_load_error {
+ LOAD_ERROR_IMLIB = 0,
+ LOAD_ERROR_IMAGEMAGICK,
+ LOAD_ERROR_CURL,
+ LOAD_ERROR_DCRAW,
+ LOAD_ERROR_MAGICBYTES
+};
+
#define INPLACE_EDIT_FLIP -1
#define INPLACE_EDIT_MIRROR -2
@@ -172,7 +180,7 @@ void feh_display_status(char stat);
void real_loadables_mode(int loadable);
void feh_reload_image(winwidget w, int resize, int force_new);
void feh_filelist_image_remove(winwidget winwid, char do_delete);
-void feh_imlib_print_load_error(char *file, winwidget w, Imlib_Load_Error err);
+void feh_print_load_error(char *file, winwidget w, Imlib_Load_Error err, enum feh_load_error feh_err);
void slideshow_save_image(winwidget win);
void feh_edit_inplace(winwidget w, int orientation);
void feh_edit_inplace_lossless(winwidget w, int orientation);
diff --git a/src/filelist.c b/src/filelist.c
index 361ac19..ae8d7b2 100644
--- a/src/filelist.c
+++ b/src/filelist.c
@@ -659,8 +659,17 @@ char *feh_absolute_path(char *path)
void feh_save_filelist()
{
char *tmpname;
+ char *base_dir = "";
- tmpname = feh_unique_filename("", "filelist");
+ if (opt.output_dir) {
+ base_dir = estrjoin("", opt.output_dir, "/", NULL);
+ }
+
+ tmpname = feh_unique_filename(base_dir, "filelist");
+
+ if (opt.output_dir) {
+ free(base_dir);
+ }
if (opt.verbose)
fprintf(stderr, "saving filelist to filename '%s'\n", tmpname);
diff --git a/src/imlib.c b/src/imlib.c
index e06a813..9ee4c08 100644
--- a/src/imlib.c
+++ b/src/imlib.c
@@ -164,11 +164,31 @@ int feh_load_image_char(Imlib_Image * im, char *filename)
return(i);
}
-void feh_imlib_print_load_error(char *file, winwidget w, Imlib_Load_Error err)
+void feh_print_load_error(char *file, winwidget w, Imlib_Load_Error err, enum feh_load_error feh_err)
{
if (err == IMLIB_LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS)
eprintf("%s - Out of file descriptors while loading", file);
else if (!opt.quiet || w) {
+ switch (feh_err) {
+ case LOAD_ERROR_IMLIB:
+ // handled in the next switch/case statement
+ break;
+ case LOAD_ERROR_IMAGEMAGICK:
+ im_weprintf(w, "%s - No ImageMagick loader for that file format", file);
+ break;
+ case LOAD_ERROR_CURL:
+ im_weprintf(w, "%s - libcurl was unable to retrieve the file", file);
+ break;
+ case LOAD_ERROR_DCRAW:
+ im_weprintf(w, "%s - Unable to open preview via dcraw", file);
+ break;
+ case LOAD_ERROR_MAGICBYTES:
+ im_weprintf(w, "%s - Does not look like an image (magic bytes missing)", file);
+ break;
+ }
+ if (feh_err != LOAD_ERROR_IMLIB) {
+ return;
+ }
switch (err) {
case IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST:
im_weprintf(w, "%s - File does not exist", file);
@@ -215,9 +235,104 @@ void feh_imlib_print_load_error(char *file, winwidget w, Imlib_Load_Error err)
}
}
+/*
+ * This is a workaround for an Imlib2 regression, causing unloadable image
+ * detection to be excessively slow (and, thus, causing feh to hang for a while
+ * when encountering an unloadable image). We use magic byte detection to
+ * avoid calling Imlib2 for files it probably cannot handle. See
+ * <https://phab.enlightenment.org/T8739> and
+ * <https://github.com/derf/feh/issues/505>.
+ *
+ * Note that this drops support for bz2-compressed files, unless
+ * FEH_SKIP_MAGIC is set
+ */
+int feh_is_image(feh_file * file)
+{
+ unsigned char buf[16];
+ FILE *fh = fopen(file->filename, "r");
+ if (!fh) {
+ return 0;
+ }
+ if (fread(buf, 1, 16, fh) != 16) {
+ fclose(fh);
+ return 0;
+ }
+ fclose(fh);
+
+ if (buf[0] == 0xff && buf[1] == 0xd8) {
+ // JPEG
+ return 1;
+ }
+ if (!memcmp(buf, "\x89PNG\x0d\x0a\x1a\x0a", 8)) {
+ // PNG
+ return 1;
+ }
+ if (buf[0] == 'A' && buf[1] == 'R' && buf[2] == 'G' && buf[3] == 'B') {
+ // ARGB
+ return 1;
+ }
+ if (buf[0] == 'B' && buf[1] == 'M') {
+ // BMP
+ return 1;
+ }
+ if (!memcmp(buf, "farbfeld", 8)) {
+ // farbfeld
+ return 1;
+ }
+ if (buf[0] == 'G' && buf[1] == 'I' && buf[2] == 'F') {
+ // GIF
+ return 1;
+ }
+ if (buf[0] == 0x00 && buf[1] == 0x00 && buf[2] <= 0x02 && buf[3] == 0x00) {
+ // ICO
+ return 1;
+ }
+ if (!memcmp(buf, "FORM", 4)) {
+ // Amiga IFF ILBM
+ return 1;
+ }
+ if (buf[0] == 'P' && buf[1] >= '1' && buf[1] <= '7') {
+ // PNM et al.
+ return 1;
+ }
+ if (strstr(file->filename, ".tga")) {
+ // TGA
+ return 1;
+ }
+ if (!memcmp(buf, "II\x2a\x00", 4) || !memcmp(buf, "MM\x00\x2a", 4)) {
+ // TIFF
+ return 1;
+ }
+ if (!memcmp(buf, "RIFF", 4)) {
+ // might be webp
+ return 1;
+ }
+ if (!memcmp(buf + 4, "ftyphei", 7) || !memcmp(buf + 4, "ftypmif1", 8)) {
+ // HEIC/HEIF - note that this is only supported in imlib2-heic. Ordinary
+ // imlib2 releases do not support heic/heif images as of 2021-01.
+ return 1;
+ }
+ buf[15] = 0;
+ if (strstr((char *)buf, "XPM")) {
+ // XPM
+ return 1;
+ }
+ if (strstr(file->filename, ".bz2") || strstr(file->filename, ".gz")) {
+ // Imlib2 supports compressed images. It relies on the filename to
+ // determine the appropriate loader and does not use magic bytes here.
+ return 1;
+ }
+ // moved to the end as this variable won't be set in most cases
+ if (getenv("FEH_SKIP_MAGIC")) {
+ return 1;
+ }
+ return 0;
+}
+
int feh_load_image(Imlib_Image * im, feh_file * file)
{
Imlib_Load_Error err = IMLIB_LOAD_ERROR_NONE;
+ enum feh_load_error feh_err = LOAD_ERROR_IMLIB;
enum { SRC_IMLIB, SRC_HTTP, SRC_MAGICK, SRC_DCRAW } image_source = SRC_IMLIB;
char *tmpname = NULL;
char *real_filename = NULL;
@@ -230,23 +345,37 @@ int feh_load_image(Imlib_Image * im, feh_file * file)
if (path_is_url(file->filename)) {
image_source = SRC_HTTP;
- if ((tmpname = feh_http_load_image(file->filename)) == NULL)
+ if ((tmpname = feh_http_load_image(file->filename)) == NULL) {
+ feh_err = LOAD_ERROR_CURL;
err = IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST;
+ }
}
- else if (opt.conversion_timeout >= 0 && feh_file_is_raw(file->filename)) {
- image_source = SRC_DCRAW;
- tmpname = feh_dcraw_load_image(file->filename);
- if (!tmpname)
+ else {
+ if (feh_is_image(file)) {
+ *im = imlib_load_image_with_error_return(file->filename, &err);
+ } else {
+ feh_err = LOAD_ERROR_MAGICBYTES;
err = IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT;
+ }
}
- else
- *im = imlib_load_image_with_error_return(file->filename, &err);
if (opt.conversion_timeout >= 0 && (
(err == IMLIB_LOAD_ERROR_UNKNOWN) ||
(err == IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT))) {
- image_source = SRC_MAGICK;
- tmpname = feh_magick_load_image(file->filename);
+ if (feh_file_is_raw(file->filename)) {
+ image_source = SRC_DCRAW;
+ tmpname = feh_dcraw_load_image(file->filename);
+ if (!tmpname) {
+ feh_err = LOAD_ERROR_DCRAW;
+ }
+ } else {
+ image_source = SRC_MAGICK;
+ feh_err = LOAD_ERROR_IMLIB;
+ tmpname = feh_magick_load_image(file->filename);
+ if (!tmpname) {
+ feh_err = LOAD_ERROR_IMAGEMAGICK;
+ }
+ }
}
if (tmpname) {
@@ -269,7 +398,14 @@ int feh_load_image(Imlib_Image * im, feh_file * file)
file->filename = real_filename;
#ifdef HAVE_LIBEXIF
- file->ed = exif_get_data(tmpname);
+ /*
+ * if we're called from within feh_reload_image, file->ed is already
+ * populated.
+ */
+ if (file->ed) {
+ exif_data_unref(file->ed);
+ }
+ file->ed = exif_data_new_from_file(tmpname);
#endif
}
if (!opt.use_conversion_cache && ((image_source != SRC_HTTP) || !opt.keep_http))
@@ -279,8 +415,19 @@ int feh_load_image(Imlib_Image * im, feh_file * file)
// add_file_to_rm_filelist duplicates tmpname
add_file_to_rm_filelist(tmpname);
- if (image_source != SRC_HTTP && !opt.use_conversion_cache)
+ if (!opt.use_conversion_cache)
free(tmpname);
+ } else if (im) {
+#ifdef HAVE_LIBEXIF
+ /*
+ * if we're called from within feh_reload_image, file->ed is already
+ * populated.
+ */
+ if (file->ed) {
+ exif_data_unref(file->ed);
+ }
+ file->ed = exif_data_new_from_file(file->filename);
+#endif
}
if ((err) || (!im)) {
@@ -288,7 +435,7 @@ int feh_load_image(Imlib_Image * im, feh_file * file)
fputs("\n", stderr);
reset_output = 1;
}
- feh_imlib_print_load_error(file->filename, NULL, err);
+ feh_print_load_error(file->filename, NULL, err, feh_err);
D(("Load *failed*\n"));
return(0);
}
@@ -305,14 +452,12 @@ int feh_load_image(Imlib_Image * im, feh_file * file)
#ifdef HAVE_LIBEXIF
int orientation = 0;
- ExifData *exifData = exif_data_new_from_file(file->filename);
- if (exifData) {
- ExifByteOrder byteOrder = exif_data_get_byte_order(exifData);
- ExifEntry *exifEntry = exif_data_get_entry(exifData, EXIF_TAG_ORIENTATION);
+ if (file->ed) {
+ ExifByteOrder byteOrder = exif_data_get_byte_order(file->ed);
+ ExifEntry *exifEntry = exif_data_get_entry(file->ed, EXIF_TAG_ORIENTATION);
if (exifEntry && opt.auto_rotate)
orientation = exif_get_short(exifEntry->data, byteOrder);
}
- file->ed = exifData;
if (orientation == 2)
gib_imlib_image_flip_horizontal(*im);
@@ -430,11 +575,9 @@ static int feh_file_is_raw(char *filename)
}
if (childpid == 0) {
- if (opt.quiet) {
- int devnull = open("/dev/null", O_WRONLY);
- dup2(devnull, 1);
- dup2(devnull, 2);
- }
+ int devnull = open("/dev/null", O_WRONLY);
+ dup2(devnull, 1);
+ dup2(devnull, 2);
execlp("dcraw", "dcraw", "-i", filename, NULL);
_exit(1);
} else {
@@ -1087,6 +1230,7 @@ void feh_draw_exif(winwidget w)
info_buf[i], IMLIB_TEXT_TO_RIGHT, 0, 0, 0, 255);
gib_imlib_text_draw(im, fn, NULL, 1, (i * line_height) + 1,
info_buf[i], IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255);
+ free(info_buf[i]);
}
@@ -1417,8 +1561,8 @@ void feh_edit_inplace(winwidget w, int op)
FEH_FILE(w->file->data)->filename, &err);
gib_imlib_free_image(old);
if (err)
- feh_imlib_print_load_error(FEH_FILE(w->file->data)->filename,
- w, err);
+ feh_print_load_error(FEH_FILE(w->file->data)->filename,
+ w, err, LOAD_ERROR_IMLIB);
feh_reload_image(w, 1, 1);
} else {
/*
diff --git a/src/index.c b/src/index.c
index 3633c96..85a3ee8 100644
--- a/src/index.c
+++ b/src/index.c
@@ -332,7 +332,7 @@ void init_index_mode(void)
gib_imlib_save_image_with_error_return(im_main, output_buf, &err);
if (err) {
- feh_imlib_print_load_error(output_buf, im_main, err);
+ feh_print_load_error(output_buf, im_main, err, LOAD_ERROR_IMLIB);
}
else if (opt.verbose) {
int tw, th;
diff --git a/src/menu.c b/src/menu.c
index aca3435..b1deedb 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -80,6 +80,8 @@ enum {
CB_OPT_FREEZE_WINDOW,
CB_OPT_FULLSCREEN,
CB_EDIT_ROTATE,
+ CB_EDIT_MIRROR,
+ CB_EDIT_FLIP,
CB_OPT_AUTO_ZOOM,
CB_OPT_KEEP_ZOOM_VP
};
@@ -920,7 +922,12 @@ void feh_menu_init_main(void)
feh_menu_add_entry(m, "Reload", NULL, CB_RELOAD, 0, NULL);
feh_menu_add_entry(m, "Save Image", NULL, CB_SAVE_IMAGE, 0, NULL);
feh_menu_add_entry(m, "Save List", NULL, CB_SAVE_FILELIST, 0, NULL);
- feh_menu_add_entry(m, "Edit in Place", "EDIT", 0, 0, NULL);
+ if (opt.edit) {
+ feh_menu_add_entry(m, "Edit in Place", "EDIT", 0, 0, NULL);
+ }
+ else {
+ feh_menu_add_entry(m, "Change View", "EDIT", 0, 0, NULL);
+ }
feh_menu_add_entry(m, "Background", "BACKGROUND", 0, 0, NULL);
feh_menu_add_entry(m, NULL, NULL, 0, 0, NULL);
feh_menu_add_entry(m, "Hide", NULL, CB_REMOVE, 0, NULL);
@@ -963,6 +970,8 @@ void feh_menu_init_common()
feh_menu_add_entry(m, "Rotate 90 CW", NULL, CB_EDIT_ROTATE, 1, NULL);
feh_menu_add_entry(m, "Rotate 180", NULL, CB_EDIT_ROTATE, 2, NULL);
feh_menu_add_entry(m, "Rotate 90 CCW", NULL, CB_EDIT_ROTATE, 3, NULL);
+ feh_menu_add_entry(m, "Mirror", NULL, CB_EDIT_MIRROR, 0, NULL);
+ feh_menu_add_entry(m, "Flip", NULL, CB_EDIT_FLIP, 0, NULL);
menu_bg = feh_menu_new();
menu_bg->name = estrdup("BACKGROUND");
@@ -1309,6 +1318,12 @@ void feh_menu_cb(feh_menu * m, feh_menu_item * i, int action, unsigned short dat
case CB_EDIT_ROTATE:
feh_edit_inplace(m->fehwin, data);
break;
+ case CB_EDIT_MIRROR:
+ feh_edit_inplace(m->fehwin, INPLACE_EDIT_MIRROR);
+ break;
+ case CB_EDIT_FLIP:
+ feh_edit_inplace(m->fehwin, INPLACE_EDIT_FLIP);
+ break;
case CB_SAVE_IMAGE:
slideshow_save_image(m->fehwin);
break;
diff --git a/src/slideshow.c b/src/slideshow.c
index 03e8e06..3a3cd0a 100644
--- a/src/slideshow.c
+++ b/src/slideshow.c
@@ -135,47 +135,54 @@ void cb_reload_timer(void *data)
winwidget w = (winwidget) data;
- /* save the current filename for refinding it in new list */
- current_filename = estrdup(FEH_FILE(current_file->data)->filename);
+ /*
+ * multi-window mode has no concept of a "current file" and
+ * dynamically adding/removing windows is not implemented at the moment.
+ * So don't reload filelists in multi-window mode.
+ */
+ if (current_file != NULL) {
+ /* save the current filename for refinding it in new list */
+ current_filename = estrdup(FEH_FILE(current_file->data)->filename);
- for (l = filelist; l; l = l->next) {
- feh_file_free(l->data);
- l->data = NULL;
- }
- gib_list_free_and_data(filelist);
- filelist = NULL;
- filelist_len = 0;
- current_file = NULL;
-
- /* rebuild filelist from original_file_items */
- if (gib_list_length(original_file_items) > 0)
- for (l = gib_list_last(original_file_items); l; l = l->prev)
- add_file_to_filelist_recursively(l->data, FILELIST_FIRST);
- else if (!opt.filelistfile && !opt.bgmode)
- add_file_to_filelist_recursively(".", FILELIST_FIRST);
-
- if (opt.filelistfile) {
- filelist = gib_list_cat(filelist, feh_read_filelist(opt.filelistfile));
- }
-
- if (!(filelist_len = gib_list_length(filelist))) {
- eprintf("No files found to reload.");
- }
+ for (l = filelist; l; l = l->next) {
+ feh_file_free(l->data);
+ l->data = NULL;
+ }
+ gib_list_free_and_data(filelist);
+ filelist = NULL;
+ filelist_len = 0;
+ current_file = NULL;
+
+ /* rebuild filelist from original_file_items */
+ if (gib_list_length(original_file_items) > 0)
+ for (l = gib_list_last(original_file_items); l; l = l->prev)
+ add_file_to_filelist_recursively(l->data, FILELIST_FIRST);
+ else if (!opt.filelistfile && !opt.bgmode)
+ add_file_to_filelist_recursively(".", FILELIST_FIRST);
+
+ if (opt.filelistfile) {
+ filelist = gib_list_cat(filelist, feh_read_filelist(opt.filelistfile));
+ }
+
+ if (!(filelist_len = gib_list_length(filelist))) {
+ eprintf("No files found to reload.");
+ }
- feh_prepare_filelist();
+ feh_prepare_filelist();
- /* find the previously current file */
- for (l = filelist; l; l = l->next)
- if (strcmp(FEH_FILE(l->data)->filename, current_filename) == 0) {
- current_file = l;
- break;
- }
+ /* find the previously current file */
+ for (l = filelist; l; l = l->next)
+ if (strcmp(FEH_FILE(l->data)->filename, current_filename) == 0) {
+ current_file = l;
+ break;
+ }
- free(current_filename);
+ free(current_filename);
- if (!current_file)
- current_file = filelist;
- w->file = current_file;
+ if (!current_file)
+ current_file = filelist;
+ w->file = current_file;
+ }
feh_reload_image(w, 1, 0);
feh_add_unique_timer(cb_reload_timer, w, opt.reload);
@@ -218,6 +225,18 @@ void slideshow_change_image(winwidget winwid, int change, int render)
/* The for loop prevents us looping infinitely */
for (i = 0; i < our_filelist_len; i++) {
winwidget_free_image(winwid);
+#ifdef HAVE_LIBEXIF
+ /*
+ * An EXIF data chunk requires up to 50 kB of space. For large and
+ * long-running slideshows, this would acculumate gigabytes of
+ * EXIF data after a few days. We therefore do not cache EXIF data
+ * in slideshows.
+ */
+ if (FEH_FILE(winwid->file->data)->ed) {
+ exif_data_unref(FEH_FILE(winwid->file->data)->ed);
+ FEH_FILE(winwid->file->data)->ed = NULL;
+ }
+#endif
switch (change) {
case SLIDE_NEXT:
current_file = feh_list_jump(filelist, current_file, FORWARD, 1);
@@ -619,7 +638,7 @@ void slideshow_save_image(winwidget win)
gib_imlib_save_image_with_error_return(win->im, tmpname, &err);
if (err)
- feh_imlib_print_load_error(tmpname, win, err);
+ feh_print_load_error(tmpname, win, err, LOAD_ERROR_IMLIB);
free(tmpname);
return;
diff --git a/src/thumbnail.c b/src/thumbnail.c
index 41bd1a0..e7b05a8 100644
--- a/src/thumbnail.c
+++ b/src/thumbnail.c
@@ -392,7 +392,7 @@ void init_thumbnail_mode(void)
}
gib_imlib_save_image_with_error_return(td.im_main, output_buf, &err);
if (err) {
- feh_imlib_print_load_error(output_buf, td.im_main, err);
+ feh_print_load_error(output_buf, td.im_main, err, LOAD_ERROR_IMLIB);
}
else if (opt.verbose) {
int tw, th;
diff --git a/src/timers.c b/src/timers.c
index 4bdd64e..b2cdbc7 100644
--- a/src/timers.c
+++ b/src/timers.c
@@ -58,7 +58,37 @@ double feh_get_time(void)
return((double) timev.tv_sec + (((double) timev.tv_usec) / 1000000));
}
-void feh_remove_timer(char *name)
+void feh_remove_timer_by_data(void *data)
+{
+ fehtimer ft, ptr, pptr;
+
+ D(("removing timer for %p\n", data));
+ pptr = NULL;
+ ptr = first_timer;
+ while (ptr) {
+ D(("Stepping through event list\n"));
+ ft = ptr;
+ if (ft->data == data) {
+ D(("Found it. Removing\n"));
+ if (pptr)
+ pptr->next = ft->next;
+ else
+ first_timer = ft->next;
+ if (ft->next)
+ ft->next->in += ft->in;
+ if (ft->name)
+ free(ft->name);
+ if (ft)
+ free(ft);
+ return;
+ }
+ pptr = ptr;
+ ptr = ptr->next;
+ }
+ return;
+}
+
+static void feh_remove_timer(char *name)
{
fehtimer ft, ptr, pptr;
@@ -88,6 +118,7 @@ void feh_remove_timer(char *name)
return;
}
+
void feh_add_timer(void (*func) (void *data), void *data, double in, char *name)
{
fehtimer ft, ptr, pptr;
diff --git a/src/timers.h b/src/timers.h
index a4243ca..e95d9b5 100644
--- a/src/timers.h
+++ b/src/timers.h
@@ -37,7 +37,7 @@ struct __fehtimer {
void feh_handle_timer(void);
double feh_get_time(void);
-void feh_remove_timer(char *name);
+void feh_remove_timer_by_data(void *data);
void feh_add_timer(void (*func) (void *data), void *data, double in, char *name);
void feh_add_unique_timer(void (*func) (void *data), void *data, double in);
diff --git a/src/winwidget.c b/src/winwidget.c
index 696f3db..37031ec 100644
--- a/src/winwidget.c
+++ b/src/winwidget.c
@@ -29,6 +29,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "winwidget.h"
#include "options.h"
#include "events.h"
+#include "timers.h"
#ifdef HAVE_INOTIFY
#include <sys/inotify.h>
@@ -694,6 +695,9 @@ void winwidget_destroy(winwidget winwid)
#ifdef HAVE_INOTIFY
winwidget_inotify_remove(winwid);
#endif
+ if (opt.reload > 0 && opt.multiwindow) {
+ feh_remove_timer_by_data(winwid);
+ }
winwidget_destroy_xwin(winwid);
if (winwid->name)
free(winwid->name);
@@ -1031,8 +1035,9 @@ void winwidget_rename(winwidget winwid, char *newname)
void winwidget_free_image(winwidget w)
{
- if (w->im)
+ if (w->im) {
gib_imlib_free_image(w->im);
+ }
w->im = NULL;
w->im_w = 0;
w->im_h = 0;