summaryrefslogtreecommitdiff
path: root/src/winwidget.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/winwidget.c')
-rw-r--r--src/winwidget.c452
1 files changed, 270 insertions, 182 deletions
diff --git a/src/winwidget.c b/src/winwidget.c
index 9495c7f..3b90158 100644
--- a/src/winwidget.c
+++ b/src/winwidget.c
@@ -1,7 +1,7 @@
/* winwidget.c
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2011 Daniel Friesel.
+Copyright (C) 2010-2025 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -29,6 +29,11 @@ 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>
+#endif
static void winwidget_unregister(winwidget win);
static void winwidget_register(winwidget win);
@@ -78,10 +83,14 @@ static winwidget winwidget_allocate(void)
ret->click_offset_y = 0;
ret->has_rotated = 0;
+#ifdef HAVE_INOTIFY
+ ret->inotify_wd = -1;
+#endif
+
return(ret);
}
-winwidget winwidget_create_from_image(Imlib_Image im, char *name, char type)
+winwidget winwidget_create_from_image(Imlib_Image im, char type)
{
winwidget ret = NULL;
@@ -95,20 +104,20 @@ winwidget winwidget_create_from_image(Imlib_Image im, char *name, char type)
ret->w = ret->im_w = gib_imlib_image_get_width(ret->im);
ret->h = ret->im_h = gib_imlib_image_get_height(ret->im);
- if (name)
- ret->name = estrdup(name);
- else
- ret->name = estrdup(PACKAGE);
-
- if (opt.full_screen && (type != WIN_TYPE_THUMBNAIL))
+ if (opt.full_screen && (type != WIN_TYPE_THUMBNAIL)) {
ret->full_screen = True;
+ } else if (opt.default_zoom) {
+ ret->zoom = 0.01 * opt.default_zoom;
+ ret->w *= ret->zoom;
+ ret->h *= ret->zoom;
+ }
winwidget_create_window(ret, ret->w, ret->h);
winwidget_render_image(ret, 1, 0);
return(ret);
}
-winwidget winwidget_create_from_file(gib_list * list, char *name, char type)
+winwidget winwidget_create_from_file(gib_list * list, char type)
{
winwidget ret = NULL;
feh_file *file = FEH_FILE(list->data);
@@ -119,12 +128,8 @@ winwidget winwidget_create_from_file(gib_list * list, char *name, char type)
ret = winwidget_allocate();
ret->file = list;
ret->type = type;
- if (name)
- ret->name = estrdup(name);
- else
- ret->name = estrdup(file->filename);
- if (winwidget_loadimage(ret, file) == 0) {
+ if ((winwidget_loadimage(ret, file) == 0) || feh_should_ignore_image(ret->im)) {
winwidget_destroy(ret);
return(NULL);
}
@@ -133,8 +138,13 @@ winwidget winwidget_create_from_file(gib_list * list, char *name, char type)
ret->w = ret->im_w = gib_imlib_image_get_width(ret->im);
ret->h = ret->im_h = gib_imlib_image_get_height(ret->im);
D(("image is %dx%d pixels, format %s\n", ret->w, ret->h, gib_imlib_image_format(ret->im)));
- if (opt.full_screen)
+ if (opt.full_screen) {
ret->full_screen = True;
+ } else if (opt.default_zoom) {
+ ret->zoom = 0.01 * opt.default_zoom;
+ ret->w *= ret->zoom;
+ ret->h *= ret->zoom;
+ }
winwidget_create_window(ret, ret->w, ret->h);
winwidget_render_image(ret, 1, 0);
}
@@ -144,6 +154,7 @@ winwidget winwidget_create_from_file(gib_list * list, char *name, char type)
void winwidget_create_window(winwidget ret, int w, int h)
{
+ XWindowAttributes window_attr;
XSetWindowAttributes attr;
XEvent ev;
XClassHint *xch;
@@ -153,7 +164,12 @@ void winwidget_create_window(winwidget ret, int w, int h)
int x = 0;
int y = 0;
char *tmpname;
+#ifdef HOST_NAME_MAX
char hostname[HOST_NAME_MAX];
+#else /* ! HOST_NAME_MAX */
+ long host_name_max;
+ char *hostname;
+#endif /* HOST_NAME_MAX */
D(("winwidget_create_window %dx%d\n", w, h));
@@ -207,7 +223,6 @@ void winwidget_create_window(winwidget ret, int w, int h)
}
if (opt.paused) {
- printf("name %s\n", ret->name);
tmpname = estrjoin(" ", ret->name, "[Paused]", NULL);
free(ret->name);
ret->name = tmpname;
@@ -246,11 +261,31 @@ void winwidget_create_window(winwidget ret, int w, int h)
}
}
- ret->win =
- XCreateWindow(disp, DefaultRootWindow(disp), x, y, w, h, 0,
- depth, InputOutput, vis,
- CWOverrideRedirect | CWSaveUnder | CWBackingStore
- | CWColormap | CWBackPixel | CWBorderPixel | CWEventMask, &attr);
+ if (opt.x11_windowid == 0) {
+ ret->win =
+ XCreateWindow(disp, DefaultRootWindow(disp), x, y, w, h, 0,
+ depth, InputOutput, vis,
+ CWOverrideRedirect | CWSaveUnder | CWBackingStore
+ | CWColormap | CWBackPixel | CWBorderPixel | CWEventMask,
+ &attr);
+ } else {
+ /* x11_windowid is a pointer to the window */
+ ret->win = (Window) opt.x11_windowid;
+
+ /* set our attributes on the window */
+ XChangeWindowAttributes(disp, ret->win,
+ CWOverrideRedirect | CWSaveUnder | CWBackingStore
+ | CWColormap | CWBackPixel | CWBorderPixel
+ | CWEventMask, &attr);
+
+ /* determine the size and visibility of the window */
+ XGetWindowAttributes(disp, ret->win, &window_attr);
+ ret->visible = (window_attr.map_state == IsViewable);
+ ret->x = window_attr.x;
+ ret->y = window_attr.y;
+ ret->w = window_attr.width;
+ ret->h = window_attr.height;
+ }
if (mwmhints.flags) {
XChangeProperty(disp, ret->win, prop, prop, 32,
@@ -278,18 +313,31 @@ void winwidget_create_window(winwidget ret, int w, int h)
XChangeProperty(disp, ret->win, prop, XA_CARDINAL, sizeof(pid_t) * 8,
PropModeReplace, (const unsigned char *)&pid, 1);
+#ifdef HOST_NAME_MAX
if (gethostname(hostname, HOST_NAME_MAX) == 0) {
hostname[HOST_NAME_MAX-1] = '\0';
prop = XInternAtom(disp, "WM_CLIENT_MACHINE", False);
XChangeProperty(disp, ret->win, prop, XA_STRING, sizeof(char) * 8,
PropModeReplace, (unsigned char *)hostname, strlen(hostname));
}
+#else /* ! HOST_NAME_MAX */
+ if ((host_name_max = sysconf(_SC_HOST_NAME_MAX)) != -1 ) {
+ if ((hostname = calloc(1, host_name_max + 1)) != NULL ) {
+ if (gethostname(hostname, host_name_max) == 0) {
+ prop = XInternAtom(disp, "WM_CLIENT_MACHINE", False);
+ XChangeProperty(disp, ret->win, prop, XA_STRING, sizeof(char) * 8,
+ PropModeReplace, (unsigned char *)hostname, strlen(hostname));
+ }
+ free(hostname);
+ }
+ }
+#endif /* HOST_NAME_MAX */
XSetWMProtocols(disp, ret->win, &wmDeleteWindow, 1);
winwidget_update_title(ret);
xch = XAllocClassHint();
xch->res_name = "feh";
- xch->res_class = "feh";
+ xch->res_class = opt.x11_class ? opt.x11_class : "feh";
XSetClassHint(disp, ret->win, xch);
XFree(xch);
@@ -314,11 +362,12 @@ void winwidget_create_window(winwidget ret, int w, int h)
winwidget_register(ret);
/* do not scale down a thumbnail list window, only those created from it */
- if (opt.scale_down && (ret->type != WIN_TYPE_THUMBNAIL)) {
+ if (opt.geom_enabled && (ret->type != WIN_TYPE_THUMBNAIL)) {
opt.geom_w = w;
opt.geom_h = h;
opt.geom_flags |= WidthValue | HeightValue;
}
+
return;
}
@@ -373,17 +422,18 @@ void winwidget_setup_pixmaps(winwidget winwid)
if (winwid->gc == None) {
XGCValues gcval;
- if (opt.image_bg == IMAGE_BG_WHITE) {
- gcval.foreground = WhitePixel(disp, DefaultScreen(disp));
+ if (!opt.image_bg || !strcmp(opt.image_bg, "default")) {
+ gcval.foreground = BlackPixel(disp, DefaultScreen(disp));
winwid->gc = XCreateGC(disp, winwid->win, GCForeground, &gcval);
- }
- else if (opt.image_bg == IMAGE_BG_CHECKS) {
+ } else if (!strcmp(opt.image_bg, "checks")) {
gcval.tile = feh_create_checks();
gcval.fill_style = FillTiled;
winwid->gc = XCreateGC(disp, winwid->win, GCTile | GCFillStyle, &gcval);
- }
- else {
- gcval.foreground = BlackPixel(disp, DefaultScreen(disp));
+ } else {
+ XColor color;
+ Colormap cmap = DefaultColormap(disp, DefaultScreen(disp));
+ XAllocNamedColor(disp, cmap, (char*) opt.image_bg, &color, &color);
+ gcval.foreground = color.pixel;
winwid->gc = XCreateGC(disp, winwid->win, GCForeground, &gcval);
}
}
@@ -412,140 +462,70 @@ void winwidget_render_image(winwidget winwid, int resize, int force_alias)
int sx, sy, sw, sh, dx, dy, dw, dh;
int calc_w, calc_h;
int antialias = 0;
- int need_center = winwid->had_resize;
if (!winwid->full_screen && resize) {
- winwidget_resize(winwid, winwid->im_w, winwid->im_h, 0);
+ if (opt.default_zoom) {
+ winwid->zoom = 0.01 * opt.default_zoom;
+ winwidget_resize(winwid, winwid->im_w * winwid->zoom, winwid->im_h * winwid->zoom, 0);
+ } else {
+ winwidget_resize(winwid, winwid->im_w, winwid->im_h, 0);
+ }
winwidget_reset_image(winwid);
}
- /* bounds checks for panning */
- if (winwid->im_x > winwid->w)
- winwid->im_x = winwid->w;
- if (winwid->im_y > winwid->h)
- winwid->im_y = winwid->h;
-
D(("winwidget_render_image resize %d force_alias %d im %dx%d\n",
resize, force_alias, winwid->im_w, winwid->im_h));
- winwidget_setup_pixmaps(winwid);
-
- if (!winwid->full_screen && ((gib_imlib_image_has_alpha(winwid->im))
- || (opt.geom_flags & (WidthValue | HeightValue))
- || (winwid->im_x || winwid->im_y) || (winwid->zoom != 1.0)
- || (winwid->w > winwid->im_w || winwid->h > winwid->im_h)
- || (winwid->has_rotated)))
- feh_draw_checks(winwid);
+ /* winwidget_setup_pixmaps(winwid) resets the winwid->had_resize flag */
+ int had_resize = winwid->had_resize || resize;
- if (!winwid->full_screen && opt.zoom_mode
- && (winwid->zoom == 1.0) && ! (opt.geom_flags & (WidthValue | HeightValue))
- && (winwid->w > winwid->im_w) && (winwid->h > winwid->im_h))
- feh_calc_needed_zoom(&(winwid->zoom), winwid->im_w, winwid->im_h, winwid->w, winwid->h);
+ winwidget_setup_pixmaps(winwid);
- /*
- * In case of a resize, the geomflags (and im_w, im_h) get updated by
- * the ConfigureNotify handler.
- */
- if (need_center && !winwid->full_screen
- && (opt.geom_flags & (WidthValue | HeightValue))
- && ((winwid->w < winwid->im_w) || (winwid->h < winwid->im_h)))
- feh_calc_needed_zoom(&(winwid->zoom), winwid->im_w, winwid->im_h, winwid->w, winwid->h);
+ if (had_resize && !opt.keep_zoom_vp && (winwid->type != WIN_TYPE_THUMBNAIL)) {
+ double required_zoom = 1.0;
+ feh_calc_needed_zoom(&required_zoom, winwid->im_w, winwid->im_h, winwid->w, winwid->h);
+ winwid->zoom = opt.default_zoom ? (0.01 * opt.default_zoom) : 1.0;
- if (resize && (winwid->full_screen
- || (opt.geom_flags & (WidthValue | HeightValue)))) {
- int smaller; /* Is the image smaller than screen? */
- int max_w = 0, max_h = 0;
+ if ((opt.scale_down || (winwid->full_screen && !opt.default_zoom))
+ && winwid->zoom > required_zoom)
+ winwid->zoom = required_zoom;
+ else if ((opt.zoom_mode && required_zoom > 1)
+ && (!opt.default_zoom || required_zoom < winwid->zoom))
+ winwid->zoom = required_zoom;
- if (winwid->full_screen) {
- max_w = scr->width;
- max_h = scr->height;
-#ifdef HAVE_LIBXINERAMA
- if (opt.xinerama && xinerama_screens) {
- max_w = xinerama_screens[xinerama_screen].width;
- max_h = xinerama_screens[xinerama_screen].height;
+ if (opt.offset_flags & XValue) {
+ if (opt.offset_flags & XNegative) {
+ winwid->im_x = winwid->w - (winwid->im_w * winwid->zoom) - opt.offset_x;
+ } else {
+ winwid->im_x = - opt.offset_x * winwid->zoom;
}
-#endif /* HAVE_LIBXINERAMA */
} else {
- if (opt.geom_flags & WidthValue) {
- max_w = opt.geom_w;
- }
- if (opt.geom_flags & HeightValue) {
- max_h = opt.geom_h;
- }
+ winwid->im_x = (int) (winwid->w - (winwid->im_w * winwid->zoom)) >> 1;
}
-
- D(("Calculating for fullscreen/fixed geom render\n"));
- smaller = ((winwid->im_w < max_w)
- && (winwid->im_h < max_h));
-
- if (!smaller || opt.zoom_mode) {
- double ratio = 0.0;
-
- /* Image is larger than the screen (so wants shrinking), or it's
- smaller but wants expanding to fill it */
- ratio = feh_calc_needed_zoom(&(winwid->zoom), winwid->im_w, winwid->im_h, max_w, max_h);
-
- /* contributed by Jens Laas <jens.laas@data.slu.se>
- * What it does:
- * zooms images by a fixed amount but never larger than the screen.
- *
- * Why:
- * This is nice if you got a collection of images where some
- * are small and can stand a small zoom. Large images are unaffected.
- *
- * When does it work, and how?
- * You have to be in fullscreen mode _and_ have auto-zoom turned on.
- * "feh -FZ --zoom 130 imagefile" will do the trick.
- * -zoom percent - the new switch.
- * 100 = orignal size,
- * 130 is 30% larger.
- */
- if (opt.default_zoom) {
- double old_zoom = winwid->zoom;
-
- winwid->zoom = 0.01 * opt.default_zoom;
- if (opt.default_zoom != 100) {
- if ((winwid->im_h * winwid->zoom) > max_h)
- winwid->zoom = old_zoom;
- else if ((winwid->im_w * winwid->zoom) > max_w)
- winwid->zoom = old_zoom;
- }
-
- winwid->im_x = ((int)
- (max_w - (winwid->im_w * winwid->zoom))) >> 1;
- winwid->im_y = ((int)
- (max_h - (winwid->im_h * winwid->zoom))) >> 1;
+ if (opt.offset_flags & YValue) {
+ if (opt.offset_flags & YNegative) {
+ winwid->im_y = winwid->h - (winwid->im_h * winwid->zoom) - opt.offset_y;
} else {
- if (ratio > 1.0) {
- /* height is the factor */
- winwid->im_x = 0;
- winwid->im_y = ((int)
- (max_h - (winwid->im_h * winwid->zoom))) >> 1;
- } else {
- /* width is the factor */
- winwid->im_x = ((int)
- (max_w - (winwid->im_w * winwid->zoom))) >> 1;
- winwid->im_y = 0;
- }
+ winwid->im_y = - opt.offset_y * winwid->zoom;
}
} else {
- /* my modification to jens hack, allow --zoom without auto-zoom mode */
- if (opt.default_zoom) {
- winwid->zoom = 0.01 * opt.default_zoom;
- } else {
- winwid->zoom = 1.0;
- }
- /* Just center the image in the window */
- winwid->im_x = (int) (max_w - (winwid->im_w * winwid->zoom)) >> 1;
- winwid->im_y = (int) (max_h - (winwid->im_h * winwid->zoom)) >> 1;
+ winwid->im_y = (int) (winwid->h - (winwid->im_h * winwid->zoom)) >> 1;
}
}
- else if (need_center && !winwid->full_screen
- && (winwid->type != WIN_TYPE_THUMBNAIL) && !opt.keep_zoom_vp) {
- winwid->im_x = (int) (winwid->w - (winwid->im_w * winwid->zoom)) >> 1;
- winwid->im_y = (int) (winwid->h - (winwid->im_h * winwid->zoom)) >> 1;
- }
+
+ winwid->had_resize = 0;
+
+ if (opt.keep_zoom_vp)
+ winwidget_sanitise_offsets(winwid);
+
+ if (!winwid->full_screen && ((gib_imlib_image_has_alpha(winwid->im))
+ || (opt.geom_flags & (WidthValue | HeightValue))
+ || (winwid->im_x || winwid->im_y)
+ || (winwid->w > winwid->im_w * winwid->zoom)
+ || (winwid->h > winwid->im_h * winwid->zoom)
+ || (winwid->has_rotated)))
+ feh_draw_checks(winwid);
/* Now we ensure only to render the area we're looking at */
dx = winwid->im_x;
@@ -569,10 +549,18 @@ void winwidget_render_image(winwidget winwid, int resize, int force_alias)
calc_h = lround(winwid->im_h * winwid->zoom);
dw = (winwid->w - winwid->im_x);
dh = (winwid->h - winwid->im_y);
- if (calc_w < dw)
+ if (calc_w < dw) {
dw = calc_w;
- if (calc_h < dh)
+ if (!winwid->full_screen) {
+ dx = 0;
+ }
+ }
+ if (calc_h < dh) {
dh = calc_h;
+ if (!winwid->full_screen) {
+ dy = 0;
+ }
+ }
if (dw > winwid->w)
dw = winwid->w;
if (dh > winwid->h)
@@ -584,7 +572,7 @@ void winwidget_render_image(winwidget winwid, int resize, int force_alias)
D(("sx: %d sy: %d sw: %d sh: %d dx: %d dy: %d dw: %d dh: %d zoom: %f\n",
sx, sy, sw, sh, dx, dy, dw, dh, winwid->zoom));
- if ((winwid->zoom != 1.0) && !force_alias && !winwid->force_aliasing)
+ if ((winwid->zoom != 1.0 || winwid->has_rotated) && !force_alias && !winwid->force_aliasing)
antialias = 1;
D(("winwidget_render(): winwid->im_angle = %f\n", winwid->im_angle));
@@ -616,6 +604,13 @@ void winwidget_render_image(winwidget winwid, int resize, int force_alias)
feh_draw_info(winwid);
if (winwid->errstr)
feh_draw_errstr(winwid);
+ if (winwid->file != NULL) {
+ if (opt.title && winwid->type != WIN_TYPE_THUMBNAIL_VIEWER) {
+ winwidget_rename(winwid, feh_printf(opt.title, FEH_FILE(winwid->file->data), winwid));
+ } else if (opt.thumb_title && winwid->type == WIN_TYPE_THUMBNAIL_VIEWER) {
+ winwidget_rename(winwid, feh_printf(opt.thumb_title, FEH_FILE(winwid->file->data), winwid));
+ }
+ }
} else if ((opt.mode == MODE_ZOOM) && !antialias)
feh_draw_zoom(winwid);
@@ -673,14 +668,15 @@ Pixmap feh_create_checks(void)
if (!checks)
eprintf("Unable to create a teeny weeny imlib image. I detect problems");
- if (opt.image_bg == IMAGE_BG_WHITE)
- gib_imlib_image_fill_rectangle(checks, 0, 0, 16, 16, 255, 255, 255, 255);
- else if (opt.image_bg == IMAGE_BG_BLACK)
- gib_imlib_image_fill_rectangle(checks, 0, 0, 16, 16, 0, 0, 0, 255);
- else {
+ if (!opt.image_bg || !strcmp(opt.image_bg, "default") || !strcmp(opt.image_bg, "checks")) {
gib_imlib_image_fill_rectangle(checks, 0, 0, 16, 16, 144, 144, 144, 255);
gib_imlib_image_fill_rectangle(checks, 0, 0, 8, 8, 100, 100, 100, 255);
gib_imlib_image_fill_rectangle(checks, 8, 8, 8, 8, 100, 100, 100, 255);
+ } else {
+ XColor color;
+ Colormap cmap = DefaultColormap(disp, DefaultScreen(disp));
+ XAllocNamedColor(disp, cmap, (char*) opt.image_bg, &color, &color);
+ gib_imlib_image_fill_rectangle(checks, 0, 0, 16, 16, color.red, color.green, color.blue, 255);
}
checks_pmap = XCreatePixmap(disp, root, 16, 16, depth);
@@ -690,13 +686,6 @@ Pixmap feh_create_checks(void)
return(checks_pmap);
}
-void winwidget_clear_background(winwidget w)
-{
- XSetWindowBackgroundPixmap(disp, w->win, feh_create_checks());
- /* XClearWindow(disp, w->win); */
- return;
-}
-
void feh_draw_checks(winwidget win)
{
static GC gc = None;
@@ -726,6 +715,12 @@ void winwidget_destroy_xwin(winwidget winwid)
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);
@@ -737,6 +732,76 @@ void winwidget_destroy(winwidget winwid)
return;
}
+#ifdef HAVE_INOTIFY
+void winwidget_inotify_remove(winwidget winwid)
+{
+ if (winwid->inotify_wd >= 0) {
+ D(("Removing inotify watch\n"));
+ if (inotify_rm_watch(opt.inotify_fd, winwid->inotify_wd))
+ weprintf("inotify_rm_watch failed:");
+ winwid->inotify_wd = -1;
+ }
+}
+#endif
+
+#ifdef HAVE_INOTIFY
+void winwidget_inotify_add(winwidget winwid, feh_file * file)
+{
+ if (opt.auto_reload && !path_is_url(file->filename)) {
+ D(("Adding inotify watch for %s\n", file->filename));
+ char dir[PATH_MAX];
+ feh_file_dirname(dir, file, PATH_MAX);
+
+ /*
+ * Handle files without directory part, e.g. "feh somefile.jpg".
+ * These always reside in the current directory.
+ */
+ if (dir[0] == '\0') {
+ dir[0] = '.';
+ dir[1] = '\0';
+ }
+ winwid->inotify_wd = inotify_add_watch(opt.inotify_fd, dir, IN_CLOSE_WRITE | IN_MOVED_TO);
+ if (winwid->inotify_wd < 0)
+ weprintf("inotify_add_watch failed:");
+ }
+}
+#endif
+
+#ifdef HAVE_INOTIFY
+#define INOTIFY_BUFFER_LEN (1024 * (sizeof (struct inotify_event)) + 16)
+void feh_event_handle_inotify(void)
+{
+ D(("Received inotify events\n"));
+ char buf[INOTIFY_BUFFER_LEN];
+ int i = 0;
+ int len = read (opt.inotify_fd, buf, INOTIFY_BUFFER_LEN);
+ if (len < 0) {
+ if (errno != EINTR)
+ eprintf("inotify event read failed");
+ } else if (!len)
+ eprintf("inotify event read failed");
+ while (i < len) {
+ struct inotify_event *event;
+ event = (struct inotify_event *) &buf[i];
+ for (int j = 0; j < window_num; j++) {
+ if(windows[j]->inotify_wd == event->wd) {
+ if (event->mask & IN_IGNORED) {
+ D(("inotify watch was implicitly removed\n"));
+ windows[j]->inotify_wd = -1;
+ } else if (event->mask & (IN_CLOSE_WRITE | IN_MOVED_TO)) {
+ if (strcmp(event->name, FEH_FILE(windows[j]->file->data)->name) == 0) {
+ D(("inotify says file changed\n"));
+ feh_reload_image(windows[j], 0, 0);
+ }
+ }
+ break;
+ }
+ }
+ i += sizeof(struct inotify_event) + event->len;
+ }
+}
+#endif
+
void winwidget_destroy_all(void)
{
int i;
@@ -770,7 +835,16 @@ winwidget winwidget_get_first_window_of_type(unsigned int type)
int winwidget_loadimage(winwidget winwid, feh_file * file)
{
D(("filename %s\n", file->filename));
- return(feh_load_image(&(winwid->im), file));
+#ifdef HAVE_INOTIFY
+ winwidget_inotify_remove(winwid);
+#endif
+ int res = feh_load_image(&(winwid->im), file);
+#ifdef HAVE_INOTIFY
+ if (res) {
+ winwidget_inotify_add(winwid, file);
+ }
+#endif
+ return(res);
}
void winwidget_show(winwidget winwid)
@@ -785,6 +859,8 @@ void winwidget_show(winwidget winwid)
/* wait for the window to map */
D(("Waiting for window to map\n"));
XMaskEvent(disp, StructureNotifyMask, &ev);
+ winwidget_get_geometry(winwid, NULL);
+
/* Unfortunately, StructureNotifyMask does not only mask
* the events of type MapNotify (which we want to mask here)
* but also such of type ConfigureNotify (and others, see
@@ -803,8 +879,6 @@ void winwidget_show(winwidget winwid)
void winwidget_move(winwidget winwid, int x, int y)
{
if (winwid && ((winwid->x != x) || (winwid->y != y))) {
- winwid->x = x;
- winwid->y = y;
winwid->x = (x > scr->width) ? scr->width : x;
winwid->y = (y > scr->height) ? scr->height : y;
XMoveWindow(disp, winwid->win, winwid->x, winwid->y);
@@ -856,30 +930,38 @@ void winwidget_resize(winwidget winwid, int w, int h, int force_resize)
D((" x %d y %d w %d h %d\n", attributes.x, attributes.y, winwid->w,
winwid->h));
- if ((opt.geom_flags & (WidthValue | HeightValue)) && !force_resize) {
- winwid->had_resize = 1;
- return;
- }
+ if ((opt.geom_flags & (WidthValue | HeightValue)) && !force_resize) {
+ winwid->had_resize = 1;
+ return;
+ }
if (winwid && ((winwid->w != w) || (winwid->h != h))) {
- /* winwidget_clear_background(winwid); */
if (opt.screen_clip) {
- winwid->w = (w > scr_width) ? scr_width : w;
- winwid->h = (h > scr_height) ? scr_height : h;
+ double required_zoom = winwid->zoom;
+ if (opt.scale_down && !opt.keep_zoom_vp) {
+ int max_w = (w > scr_width) ? scr_width : w;
+ int max_h = (h > scr_height) ? scr_height : h;
+ feh_calc_needed_zoom(&required_zoom, winwid->im_w, winwid->im_h, max_w, max_h);
+ }
+ int desired_w = winwid->im_w * required_zoom;
+ int desired_h = winwid->im_h * required_zoom;
+ winwid->w = (desired_w > scr_width) ? scr_width : desired_w;
+ winwid->h = (desired_h > scr_height) ? scr_height : desired_h;
}
if (winwid->full_screen) {
- XTranslateCoordinates(disp, winwid->win, attributes.root,
- -attributes.border_width -
- attributes.x,
- -attributes.border_width - attributes.y, &tc_x, &tc_y, &dw);
- winwid->x = tc_x;
- winwid->y = tc_y;
- XMoveResizeWindow(disp, winwid->win, tc_x, tc_y, winwid->w, winwid->h);
+ XTranslateCoordinates(disp, winwid->win, attributes.root,
+ -attributes.border_width - attributes.x,
+ -attributes.border_width - attributes.y, &tc_x, &tc_y, &dw);
+ winwid->x = tc_x;
+ winwid->y = tc_y;
+ XMoveResizeWindow(disp, winwid->win, tc_x, tc_y, winwid->w, winwid->h);
} else
XResizeWindow(disp, winwid->win, winwid->w, winwid->h);
winwid->had_resize = 1;
XFlush(disp);
+ winwidget_get_geometry(winwid, NULL);
+
if (force_resize && (opt.geom_flags & (WidthValue | HeightValue))
&& (winwid->type != WIN_TYPE_THUMBNAIL)) {
opt.geom_w = winwid->w;
@@ -976,8 +1058,9 @@ void winwidget_rename(winwidget winwid, char *newname)
void winwidget_free_image(winwidget w)
{
- if (w->im)
- gib_imlib_free_image_and_decache(w->im);
+ if (w->im) {
+ gib_imlib_free_image(w->im);
+ }
w->im = NULL;
w->im_w = 0;
w->im_h = 0;
@@ -1001,10 +1084,12 @@ void feh_debug_print_winwid(winwidget w)
void winwidget_reset_image(winwidget winwid)
{
- winwid->zoom = 1.0;
- winwid->old_zoom = 1.0;
- winwid->im_x = 0;
- winwid->im_y = 0;
+ if (!opt.keep_zoom_vp) {
+ winwid->zoom = 1.0;
+ winwid->old_zoom = 1.0;
+ winwid->im_x = 0;
+ winwid->im_y = 0;
+ }
winwid->im_angle = 0.0;
winwid->has_rotated = 0;
return;
@@ -1117,8 +1202,11 @@ void winwidget_get_geometry(winwidget winwid, int *rect)
{
unsigned int bw, bp;
Window child;
+
+ int inner_rect[4];
+
if (!rect)
- return;
+ rect = inner_rect;
XGetGeometry(disp, winwid->win, &root, &(rect[0]), &(rect[1]), (unsigned
int *)&(rect[2]), (unsigned int *)&(rect[3]), &bw, &bp);