Pass marked files to external key handler in thumbnail mode; fixes issue #135

This commit is contained in:
Bert Münnich 2014-08-16 21:31:05 +02:00
parent 284be74927
commit e267dc7793
6 changed files with 77 additions and 57 deletions

View file

@ -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;
}

View file

@ -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

83
main.c
View file

@ -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 {

10
sxiv.1
View file

@ -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

View file

@ -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;
}
}

View file

@ -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);