diff options
author | Daniel Friesel <derf@finalrewind.org> | 2019-04-12 16:34:12 +0200 |
---|---|---|
committer | Daniel Friesel <derf@finalrewind.org> | 2019-04-12 16:34:12 +0200 |
commit | f8270763d6eb37e944999aa30fb648e564353a46 (patch) | |
tree | 3f59564728c1ea7933f0a24f662920110da6c18c | |
parent | e6dd09e65e22cc13692e09b0018960e878b965c7 (diff) | |
parent | a9ffd5d2234433bc3f3829713b0968a1d6c13b94 (diff) |
Merge branch 'master' of https://github.com/swillner/feh into swillner-master
-rw-r--r-- | .travis.yml | 1 | ||||
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | config.mk | 7 | ||||
-rw-r--r-- | man/Makefile | 1 | ||||
-rw-r--r-- | man/feh.pre | 3 | ||||
-rw-r--r-- | src/feh.h | 3 | ||||
-rw-r--r-- | src/filelist.c | 2 | ||||
-rw-r--r-- | src/help.raw | 1 | ||||
-rw-r--r-- | src/main.c | 34 | ||||
-rw-r--r-- | src/options.c | 13 | ||||
-rw-r--r-- | src/options.h | 4 | ||||
-rw-r--r-- | src/thumbnail.c | 10 | ||||
-rw-r--r-- | src/winwidget.c | 83 | ||||
-rw-r--r-- | src/winwidget.h | 9 |
14 files changed, 166 insertions, 6 deletions
diff --git a/.travis.yml b/.travis.yml index f59e68c..a12b97d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,3 +27,4 @@ env: - stat64=1 - verscmp=0 - xinerama=0 + - inotify=1 @@ -89,6 +89,7 @@ indicates that the corresponding feature is enabled by default. | debug | 0 | debug build, enables `--debug` | | exif | 0 | Builtin EXIF tag display support | | help | 0 | include help text (refers to the manpage otherwise) | +| inotify | 0 | enable inotify, needed for `--auto-reload` | | stat64 | 0 | Support CIFS shares from 64bit hosts on 32bit machines | | verscmp | 1 | Support naturing sorting (`--version-sort`). Requires a GNU-compatible libc exposing `strverscmp` | | xinerama | 1 | Support Xinerama/XRandR multiscreen setups | @@ -86,6 +86,13 @@ else MAN_EXIF = disabled endif +ifeq (${inotify},1) + CFLAGS += -DHAVE_INOTIFY + MAN_INOTIFY = enabled +else + MAN_INOTIFY = disabled +endif + MAN_DATE ?= ${shell date '+%B %d, %Y'} # Uncomment this to use dmalloc diff --git a/man/Makefile b/man/Makefile index 9209de1..acf8629 100644 --- a/man/Makefile +++ b/man/Makefile @@ -12,6 +12,7 @@ all: ${TARGETS} -e 's/\$$MAN_CURL\$$/${MAN_CURL}/' \ -e 's/\$$MAN_DEBUG\$$/${MAN_DEBUG}/' \ -e 's/\$$MAN_EXIF\$$/${MAN_EXIF}/' \ + -e 's/\$$MAN_INOTIFY\$$/${MAN_INOTIFY}/' \ -e 's/\$$MAN_VERSCMP\$$/${MAN_VERSCMP}/' \ -e 's/\$$MAN_XINERAMA\$$/${MAN_XINERAMA}/' \ < ${@:.1=.pre} > $@ diff --git a/man/feh.pre b/man/feh.pre index b1ef16a..f59301f 100644 --- a/man/feh.pre +++ b/man/feh.pre @@ -26,7 +26,8 @@ $VERSION$ . Compile-time switches: libcurl support $MAN_CURL$, natural sorting support $MAN_VERSCMP$, Xinerama support -$MAN_XINERAMA$, builtin EXIF support $MAN_EXIF$$MAN_DEBUG$ +$MAN_XINERAMA$, builtin EXIF support $MAN_EXIF$, inotify support +$MAN_INOTIFY$$MAN_DEBUG$ . . .Sh DESCRIPTION @@ -179,6 +179,9 @@ void feh_edit_inplace_lossless(winwidget w, int orientation); gib_list *feh_wrap_string(char *text, int wrap_width, Imlib_Font fn, gib_style * style); char *build_caption_filename(feh_file * file, short create_dir); gib_list *feh_list_jump(gib_list * root, gib_list * l, int direction, int num); +#ifdef HAVE_INOTIFY +void feh_event_handle_inotify(void); +#endif /* Imlib stuff */ extern Display *disp; diff --git a/src/filelist.c b/src/filelist.c index 6f4f6df..e3ae020 100644 --- a/src/filelist.c +++ b/src/filelist.c @@ -76,7 +76,7 @@ void feh_file_free(feh_file * file) #ifdef HAVE_LIBEXIF if (file->ed) exif_data_unref(file->ed); -#endif +#endif free(file); return; } diff --git a/src/help.raw b/src/help.raw index ca7c85c..7a9a658 100644 --- a/src/help.raw +++ b/src/help.raw @@ -99,6 +99,7 @@ OPTIONS --max-dimension WxH Only show images with width <= W and height <= H --scroll-step COUNT scroll COUNT pixels when movement key is pressed --cache-size NUM imlib cache size in mebibytes (0 .. 2048) + --auto-reload automatically reload shown image if file was changed MONTAGE MODE OPTIONS -X, --ignore-aspect Set thumbnail to specified width/height without @@ -34,6 +34,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "wallpaper.h" #include <termios.h> +#ifdef HAVE_INOTIFY +#include <sys/inotify.h> +#endif + char **cmdargv = NULL; int cmdargc = 0; char *mode = NULL; @@ -53,6 +57,15 @@ int main(int argc, char **argv) init_x_and_imlib(); init_keyevents(); init_buttonbindings(); +#ifdef HAVE_INOTIFY + if (opt.auto_reload) { + opt.inotify_fd = inotify_init(); + if (opt.inotify_fd < 0) { + opt.auto_reload = 0; + eprintf("inotify_init failed"); + } + } +#endif } feh_event_init(); @@ -146,6 +159,13 @@ int feh_main_iteration(int block) FD_SET(xfd, &fdset); if (control_via_stdin) FD_SET(STDIN_FILENO, &fdset); +#ifdef HAVE_INOTIFY + if (opt.auto_reload) { + FD_SET(opt.inotify_fd, &fdset); + if (opt.inotify_fd >= fdsize) + fdsize = opt.inotify_fd + 1; + } +#endif /* Timers */ ft = first_timer; @@ -191,6 +211,10 @@ int feh_main_iteration(int block) } else if ((count > 0) && (FD_ISSET(0, &fdset))) feh_event_handle_stdin(); +#ifdef HAVE_INOTIFY + else if (count && (FD_ISSET(opt.inotify_fd, &fdset))) + feh_event_handle_inotify(); +#endif } } else { /* Don't block if there are events in the queue. That's a bit rude ;-) */ @@ -204,6 +228,10 @@ int feh_main_iteration(int block) eprintf("Connection to X display lost"); else if ((count > 0) && (FD_ISSET(0, &fdset))) feh_event_handle_stdin(); +#ifdef HAVE_INOTIFY + else if (count && (FD_ISSET(opt.inotify_fd, &fdset))) + feh_event_handle_inotify(); +#endif } } if (window_num == 0 || sig_exit != 0) @@ -218,6 +246,12 @@ void feh_clean_exit(void) free(opt.menu_font); +#ifdef HAVE_INOTIFY + if (opt.auto_reload) + if (close(opt.inotify_fd)) + eprintf("inotify close failed"); +#endif + if(disp) XCloseDisplay(disp); diff --git a/src/options.c b/src/options.c index 37fad88..2a5aae8 100644 --- a/src/options.c +++ b/src/options.c @@ -25,7 +25,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include <strings.h> - #include "feh.h" #include "filelist.h" #include "options.h" @@ -425,6 +424,9 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun) {"conversion-timeout" , 1, 0, 245}, {"version-sort" , 0, 0, 246}, {"offset" , 1, 0, 247}, +#ifdef HAVE_INOTIFY + {"auto-reload" , 0, 0, 248}, +#endif {0, 0, 0, 0} }; int optch = 0, cmdx = 0; @@ -810,6 +812,11 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun) opt.offset_flags = XParseGeometry(optarg, &opt.offset_x, &opt.offset_y, (unsigned int *)&discard, (unsigned int *)&discard); break; +#ifdef HAVE_INOTIFY + case 248: + opt.auto_reload = 1; + break; +#endif default: break; } @@ -897,6 +904,10 @@ static void show_version(void) "exif " #endif +#ifdef HAVE_INOTIFY + "inotify " +#endif + #ifdef INCLUDE_HELP "help " #endif diff --git a/src/options.h b/src/options.h index 7f8fe9c..883c8e2 100644 --- a/src/options.h +++ b/src/options.h @@ -58,6 +58,10 @@ struct __fehoptions { unsigned char draw_exif; unsigned char auto_rotate; #endif +#ifdef HAVE_INOTIFY + unsigned char auto_reload; + int inotify_fd; +#endif unsigned char list; unsigned char quiet; unsigned char preload; diff --git a/src/thumbnail.c b/src/thumbnail.c index 45fbabe..5197618 100644 --- a/src/thumbnail.c +++ b/src/thumbnail.c @@ -93,7 +93,6 @@ void init_thumbnail_mode(void) if (!opt.thumb_title) opt.thumb_title = "%n"; - mode = "thumbnail"; if (opt.font) @@ -177,6 +176,7 @@ void init_thumbnail_mode(void) td.h + title_area_h, 0, 0, 0, 255); } + if (opt.display) { winwid = winwidget_create_from_image(td.im_main, WIN_TYPE_THUMBNAIL); winwidget_rename(winwid, PACKAGE " [thumbnail mode]"); @@ -418,6 +418,7 @@ void init_thumbnail_mode(void) } } + return; } @@ -783,7 +784,6 @@ void feh_thumbnail_show_fullsize(feh_file *thumbfile) if (!l) { eprintf("Cannot find %s in filelist, wtf", thumbfile->filename); } - thumbwin = winwidget_get_first_window_of_type(WIN_TYPE_THUMBNAIL_VIEWER); if (!thumbwin) { thumbwin = winwidget_create_from_file( @@ -793,7 +793,13 @@ void feh_thumbnail_show_fullsize(feh_file *thumbfile) winwidget_show(thumbwin); } else if (FEH_FILE(thumbwin->file->data) != thumbfile) { thumbwin->file = l; +#ifdef HAVE_INOTIFY + winwidget_inotify_remove(thumbwin); +#endif feh_reload_image(thumbwin, 1, 1); +#ifdef HAVE_INOTIFY + winwidget_inotify_add(thumbwin, thumbfile); +#endif } } diff --git a/src/winwidget.c b/src/winwidget.c index bb4fdae..020ee5b 100644 --- a/src/winwidget.c +++ b/src/winwidget.c @@ -30,6 +30,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "options.h" #include "events.h" +#ifdef HAVE_INOTIFY +#include <sys/inotify.h> +#endif + static void winwidget_unregister(winwidget win); static void winwidget_register(winwidget win); static winwidget winwidget_allocate(void); @@ -78,6 +82,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); } @@ -662,6 +670,9 @@ void winwidget_destroy_xwin(winwidget winwid) void winwidget_destroy(winwidget winwid) { +#ifdef HAVE_INOTIFY + winwidget_inotify_remove(winwid); +#endif winwidget_destroy_xwin(winwid); if (winwid->name) free(winwid->name); @@ -673,6 +684,67 @@ 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)) + eprintf("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) { + D(("Adding inotify watch for %s\n", file->filename)); + char dir[PATH_MAX]; + feh_file_dirname(dir, file, PATH_MAX); + winwid->inotify_wd = inotify_add_watch(opt.inotify_fd, dir, IN_CLOSE_WRITE | IN_MOVED_TO); + if (winwid->inotify_wd < 0) + eprintf("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 implicitely 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, 1); + } + } + break; + } + } + i += sizeof(struct inotify_event) + event->len; + } +} +#endif + void winwidget_destroy_all(void) { int i; @@ -706,7 +778,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) diff --git a/src/winwidget.h b/src/winwidget.h index 0a707ac..4d8fc4b 100644 --- a/src/winwidget.h +++ b/src/winwidget.h @@ -116,8 +116,17 @@ struct __winwidget { time_t click_start_time; unsigned char has_rotated; + +#ifdef HAVE_INOTIFY + int inotify_wd; +#endif }; +#ifdef HAVE_INOTIFY +void winwidget_inotify_remove(winwidget winwid); +void winwidget_inotify_add(winwidget winwid, feh_file * file); +#endif + int winwidget_loadimage(winwidget winwid, feh_file * filename); void winwidget_show(winwidget winwid); void winwidget_show_menu(winwidget winwid); |