diff options
Diffstat (limited to 'src/winwidget.c')
-rw-r--r-- | src/winwidget.c | 179 |
1 files changed, 161 insertions, 18 deletions
diff --git a/src/winwidget.c b/src/winwidget.c index b68d56f..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-2018 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,6 +83,10 @@ static winwidget winwidget_allocate(void) ret->click_offset_y = 0; ret->has_rotated = 0; +#ifdef HAVE_INOTIFY + ret->inotify_wd = -1; +#endif + return(ret); } @@ -95,8 +104,13 @@ winwidget winwidget_create_from_image(Imlib_Image im, 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 (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); @@ -124,8 +138,13 @@ winwidget winwidget_create_from_file(gib_list * list, 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); } @@ -135,6 +154,7 @@ winwidget winwidget_create_from_file(gib_list * list, char type) void winwidget_create_window(winwidget ret, int w, int h) { + XWindowAttributes window_attr; XSetWindowAttributes attr; XEvent ev; XClassHint *xch; @@ -203,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; @@ -242,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, @@ -298,7 +337,7 @@ void winwidget_create_window(winwidget ret, int w, int h) 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); @@ -425,7 +464,12 @@ void winwidget_render_image(winwidget winwid, int resize, int force_alias) int antialias = 0; 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); } @@ -505,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) @@ -663,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); @@ -674,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; @@ -707,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) @@ -722,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 @@ -740,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); @@ -823,6 +960,8 @@ void winwidget_resize(winwidget winwid, int w, int h, int force_resize) 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; @@ -919,8 +1058,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; @@ -1062,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); |