diff --git a/commands.c b/commands.c index 9ff411b..7d5a986 100644 --- a/commands.c +++ b/commands.c @@ -130,7 +130,7 @@ bool cg_reload_image(arg_t a) load_image(fileidx); } else { win_set_cursor(&win, CURSOR_WATCH); - if (!tns_load(&tns, fileidx, &files[fileidx], true, false)) { + if (!tns_load(&tns, fileidx, &files[fileidx], true)) { remove_file(fileidx, false); tns.dirty = true; } diff --git a/exec/key-handler b/exec/key-handler index 184f373..a578698 100644 --- a/exec/key-handler +++ b/exec/key-handler @@ -2,33 +2,36 @@ # Example for $XDG_CONFIG_HOME/sxiv/exec/key-handler # Called by sxiv(1) after the external prefix key (C-x by default) is pressed. -# The next key combo is passed as its first argument and the path of the -# current image as its second argument. -# sxiv(1) blocks until this script terminates. It then checks if the image -# has been modified and reloads it. +# The next key combo is passed as its first argument, followed by the paths of +# all marked images or the path of the current image, if no image is marked. +# sxiv(1) blocks until this script terminates. It then checks which images +# have been modified and reloads them. # The key combo argument has the following form: "[C-][M-][S-]KEY", # where C/M/S indicate Ctrl/Meta(Alt)/Shift modifier states and KEY is the X # keysym as listed in /usr/include/X11/keysymdef.h without the "XK_" prefix. -case "$1" in +key="$1" +shift + +case "$key" in "C-c") - echo -n "$2" | xsel -i ;; + echo -n "$@" | xsel -i ;; "C-e") - urxvt -bg "#444" -fg "#eee" -sl 0 -title "$2" -e sh -c "exiv2 pr -q -pa '$2' | less" & ;; + for file in "$@"; do urxvt -bg "#444" -fg "#eee" -sl 0 -title "$file" -e sh -c "exiv2 pr -q -pa '$file' | less" & done ;; "C-g") - gimp "$2" & ;; + gimp "$@" & ;; "C-comma") - exec jpegtran -rotate 270 -copy all -outfile "$2" "$2" ;; + for file in "$@"; do jpegtran -rotate 270 -copy all -outfile "$file" "$file"; done ;; "C-period") - exec jpegtran -rotate 90 -copy all -outfile "$2" "$2" ;; + for file in "$@"; do jpegtran -rotate 90 -copy all -outfile "$file" "$file"; done ;; "C-slash") - exec jpegtran -rotate 180 -copy all -outfile "$2" "$2" ;; + for file in "$@"; do jpegtran -rotate 180 -copy all -outfile "$file" "$file"; done ;; "C-less") - exec mogrify -rotate -90 "$2" ;; + exec mogrify -rotate -90 "$@" ;; "C-greater") - exec mogrify -rotate +90 "$2" ;; + exec mogrify -rotate +90 "$@" ;; "C-question") - exec mogrify -rotate 180 "$2" ;; + exec mogrify -rotate 180 "$@" ;; esac diff --git a/main.c b/main.c index 10d15ab..5e99c43 100644 --- a/main.c +++ b/main.c @@ -467,10 +467,12 @@ void clear_resize(void) void run_key_handler(const char *key, unsigned int mask) { pid_t pid; - int retval, status; - char kstr[32], oldbar[sizeof(win.bar.l)]; - bool restore_bar = mode == MODE_IMAGE && info.cmd != NULL; - struct stat oldst, newst; + int i, j, retval, status; + int fcnt = mode == MODE_THUMB && markcnt > 0 ? markcnt : 1; + bool changed = false; + char **args, kstr[32], oldbar[sizeof(win.bar.l)]; + struct stat *oldst, newst; + struct { int fn; struct stat st; } *finfo; if (keyhandler.cmd == NULL) { if (!keyhandler.warned) { @@ -482,20 +484,34 @@ void run_key_handler(const char *key, unsigned int mask) if (key == NULL) return; + finfo = s_malloc(fcnt * sizeof(*finfo)); + args = s_malloc((fcnt + 3) * sizeof(*args)); + args[0] = keyhandler.cmd; + args[1] = kstr; + args[fcnt+2] = NULL; + if (mode == MODE_IMAGE || markcnt == 0) { + finfo[0].fn = fileidx; + stat(files[fileidx].path, &finfo[0].st); + args[2] = (char*) files[fileidx].path; + } else for (i = j = 0; i < filecnt; i++) { + if (files[i].marked) { + finfo[j].fn = i; + stat(files[i].path, &finfo[j++].st); + args[j+1] = (char*) files[i].path; + } + } snprintf(kstr, sizeof(kstr), "%s%s%s%s", mask & ControlMask ? "C-" : "", mask & Mod1Mask ? "M-" : "", mask & ShiftMask ? "S-" : "", key); - if (restore_bar) - memcpy(oldbar, win.bar.l, sizeof(win.bar.l)); + memcpy(oldbar, win.bar.l, sizeof(win.bar.l)); strncpy(win.bar.l, "Running key handler...", sizeof(win.bar.l)); win_draw(&win); win_set_cursor(&win, CURSOR_WATCH); - stat(files[fileidx].path, &oldst); if ((pid = fork()) == 0) { - execl(keyhandler.cmd, keyhandler.cmd, kstr, files[fileidx].path, NULL); + execv(keyhandler.cmd, args); warn("could not exec key handler"); exit(EXIT_FAILURE); } else if (pid < 0) { @@ -507,31 +523,31 @@ void run_key_handler(const char *key, unsigned int mask) if (WIFEXITED(status) == 0 || retval != 0) warn("key handler exited with non-zero return value: %d", retval); - if (stat(files[fileidx].path, &newst) == 0 && - memcmp(&oldst.st_mtime, &newst.st_mtime, sizeof(oldst.st_mtime)) == 0) - { - /* file has not changed */ - goto end; - } - restore_bar = false; - strncpy(win.bar.l, "Reloading image...", sizeof(win.bar.l)); - win_draw(&win); - - if (mode == MODE_IMAGE) { - img_close(&img, true); - load_image(fileidx); - } - if (!tns_load(&tns, fileidx, &files[fileidx], true, mode == MODE_IMAGE) && - mode == MODE_THUMB) - { - remove_file(fileidx, false); - tns.dirty = true; + for (i = 0; i < fcnt; i++) { + oldst = &finfo[i].st; + if (stat(files[finfo[i].fn].path, &newst) != 0 || + memcmp(&oldst->st_mtime, &newst.st_mtime, sizeof(newst.st_mtime)) != 0) + { + if (tns.thumbs != NULL) { + tns.thumbs[finfo[i].fn].loaded = false; + tns.loadnext = MIN(tns.loadnext, finfo[i].fn); + } + changed = true; + } } end: - if (restore_bar) - memcpy(win.bar.l, oldbar, sizeof(win.bar.l)); + if (mode == MODE_IMAGE) { + if (changed) { + img_close(&img, true); + load_image(fileidx); + } else if (info.cmd != NULL) { + memcpy(win.bar.l, oldbar, sizeof(win.bar.l)); + } + } reset_cursor(); redraw(); + free(finfo); + free(args); } #define MODMASK(mask) ((mask) & (ShiftMask|ControlMask|Mod1Mask)) @@ -651,7 +667,7 @@ void run(void) int xfd; fd_set fds; struct timeval timeout; - bool discard, to_set; + bool discard, reload, to_set; XEvent ev, nextev; set_timeout(redraw, 25, false); @@ -661,9 +677,10 @@ void run(void) XPending(win.env.dpy) == 0) { /* load thumbnails */ + reload = tns.loadnext != tns.cnt; set_timeout(redraw, TO_REDRAW_THUMBS, false); - if (tns_load(&tns, tns.loadnext, &files[tns.loadnext], false, false)) { - if (tns.cnt == tns.loadnext) + if (tns_load(&tns, tns.loadnext, &files[tns.loadnext], reload)) { + if (!reload) tns.cnt++; } else { remove_file(tns.loadnext, false); @@ -860,7 +877,7 @@ int main(int argc, char **argv) if (options->thumb_mode) { mode = MODE_THUMB; tns_init(&tns, filecnt, &win, &fileidx); - while (!tns_load(&tns, 0, &files[0], false, false)) + while (!tns_load(&tns, 0, &files[0], false)) remove_file(0, false); tns.cnt = 1; } else { diff --git a/sxiv.1 b/sxiv.1 index 0ed3164..06c360e 100644 --- a/sxiv.1 +++ b/sxiv.1 @@ -112,7 +112,8 @@ Toggle fullscreen mode. Toggle visibility of info bar on bottom of window. .TP .B Ctrl-x -Send the next key to the external key-handler. +Send the next key to the external key-handler. See section EXTERNAL KEY HANDLER +for more information. .TP .B g Go to the first image. @@ -354,9 +355,10 @@ located in .IR $XDG_CONFIG_HOME/sxiv/exec/key-handler . The handler is invoked by pressing .BR Ctrl-x . -The next key combo is then passed as its first argument and the path of the -current image as its second argument. sxiv(1) will block until the handler -terminates. It then checks if the image has been modified and reloads it. +The next key combo is then passed as its first argument, followed by the paths +of all marked images or the path of the current image, if no image is marked. +sxiv(1) will block until the handler terminates. It then checks which images +have been modified and reloads them. The key combo argument has the following form: "[C-][M-][S-]KEY", where C/M/S indicate Ctrl/Meta(Alt)/Shift modifier states and KEY is the X diff --git a/thumbs.c b/thumbs.c index 369dfca..14ecf74 100644 --- a/thumbs.c +++ b/thumbs.c @@ -209,8 +209,7 @@ void tns_free(tns_t *tns) } } -bool tns_load(tns_t *tns, int n, const fileinfo_t *file, - bool force, bool silent) +bool tns_load(tns_t *tns, int n, const fileinfo_t *file, bool force) { int w, h; bool cache_hit = false; @@ -295,8 +294,7 @@ bool tns_load(tns_t *tns, int n, const fileinfo_t *file, if (im == NULL && (access(file->path, R_OK) < 0 || (im = imlib_load_image(file->path)) == NULL)) { - if (!silent) - warn("could not open image: %s", file->name); + warn("could not open image: %s", file->name); return false; } } diff --git a/thumbs.h b/thumbs.h index 35864c3..1aeaccb 100644 --- a/thumbs.h +++ b/thumbs.h @@ -57,7 +57,7 @@ void tns_clean_cache(tns_t*); void tns_init(tns_t*, int, win_t*, int*); void tns_free(tns_t*); -bool tns_load(tns_t*, int, const fileinfo_t*, bool, bool); +bool tns_load(tns_t*, int, const fileinfo_t*, bool); void tns_render(tns_t*); void tns_mark(tns_t*, int, bool);