aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBert Münnich <ber.t@posteo.de>2014-08-16 21:31:05 +0200
committerBert Münnich <ber.t@posteo.de>2014-08-16 21:49:46 +0200
commite267dc7793df0c3d8b1dcc48575a11d402df5499 (patch)
treecbd24fe32acedcb3951e1d8f337a950d38da28ae
parent284be749278a7b6471926a618877dbb3adc8c1ad (diff)
Pass marked files to external key handler in thumbnail mode; fixes issue #135
-rw-r--r--commands.c2
-rw-r--r--exec/key-handler31
-rw-r--r--main.c81
-rw-r--r--sxiv.110
-rw-r--r--thumbs.c6
-rw-r--r--thumbs.h2
6 files changed, 76 insertions, 56 deletions
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;
+ 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;
+ }
}
- restore_bar = false;
- strncpy(win.bar.l, "Reloading image...", sizeof(win.bar.l));
- win_draw(&win);
-
+end:
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;
+ if (changed) {
+ img_close(&img, true);
+ load_image(fileidx);
+ } else if (info.cmd != NULL) {
+ memcpy(win.bar.l, oldbar, sizeof(win.bar.l));
+ }
}
-end:
- if (restore_bar)
- 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);