Pass marked files to external key handler in thumbnail mode; fixes issue #135
This commit is contained in:
parent
284be74927
commit
e267dc7793
@ -130,7 +130,7 @@ bool cg_reload_image(arg_t a)
|
|||||||
load_image(fileidx);
|
load_image(fileidx);
|
||||||
} else {
|
} else {
|
||||||
win_set_cursor(&win, CURSOR_WATCH);
|
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);
|
remove_file(fileidx, false);
|
||||||
tns.dirty = true;
|
tns.dirty = true;
|
||||||
}
|
}
|
||||||
|
@ -2,33 +2,36 @@
|
|||||||
|
|
||||||
# Example for $XDG_CONFIG_HOME/sxiv/exec/key-handler
|
# Example for $XDG_CONFIG_HOME/sxiv/exec/key-handler
|
||||||
# Called by sxiv(1) after the external prefix key (C-x by default) is pressed.
|
# 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
|
# The next key combo is passed as its first argument, followed by the paths of
|
||||||
# current image as its second argument.
|
# 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 if the image
|
# sxiv(1) blocks until this script terminates. It then checks which images
|
||||||
# has been modified and reloads it.
|
# have been modified and reloads them.
|
||||||
|
|
||||||
# The key combo argument has the following form: "[C-][M-][S-]KEY",
|
# 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
|
# 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.
|
# keysym as listed in /usr/include/X11/keysymdef.h without the "XK_" prefix.
|
||||||
|
|
||||||
case "$1" in
|
key="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
case "$key" in
|
||||||
"C-c")
|
"C-c")
|
||||||
echo -n "$2" | xsel -i ;;
|
echo -n "$@" | xsel -i ;;
|
||||||
"C-e")
|
"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")
|
"C-g")
|
||||||
gimp "$2" & ;;
|
gimp "$@" & ;;
|
||||||
"C-comma")
|
"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")
|
"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")
|
"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")
|
"C-less")
|
||||||
exec mogrify -rotate -90 "$2" ;;
|
exec mogrify -rotate -90 "$@" ;;
|
||||||
"C-greater")
|
"C-greater")
|
||||||
exec mogrify -rotate +90 "$2" ;;
|
exec mogrify -rotate +90 "$@" ;;
|
||||||
"C-question")
|
"C-question")
|
||||||
exec mogrify -rotate 180 "$2" ;;
|
exec mogrify -rotate 180 "$@" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
83
main.c
83
main.c
@ -467,10 +467,12 @@ void clear_resize(void)
|
|||||||
void run_key_handler(const char *key, unsigned int mask)
|
void run_key_handler(const char *key, unsigned int mask)
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int retval, status;
|
int i, j, retval, status;
|
||||||
char kstr[32], oldbar[sizeof(win.bar.l)];
|
int fcnt = mode == MODE_THUMB && markcnt > 0 ? markcnt : 1;
|
||||||
bool restore_bar = mode == MODE_IMAGE && info.cmd != NULL;
|
bool changed = false;
|
||||||
struct stat oldst, newst;
|
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.cmd == NULL) {
|
||||||
if (!keyhandler.warned) {
|
if (!keyhandler.warned) {
|
||||||
@ -482,20 +484,34 @@ void run_key_handler(const char *key, unsigned int mask)
|
|||||||
if (key == NULL)
|
if (key == NULL)
|
||||||
return;
|
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",
|
snprintf(kstr, sizeof(kstr), "%s%s%s%s",
|
||||||
mask & ControlMask ? "C-" : "",
|
mask & ControlMask ? "C-" : "",
|
||||||
mask & Mod1Mask ? "M-" : "",
|
mask & Mod1Mask ? "M-" : "",
|
||||||
mask & ShiftMask ? "S-" : "", key);
|
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));
|
strncpy(win.bar.l, "Running key handler...", sizeof(win.bar.l));
|
||||||
win_draw(&win);
|
win_draw(&win);
|
||||||
win_set_cursor(&win, CURSOR_WATCH);
|
win_set_cursor(&win, CURSOR_WATCH);
|
||||||
stat(files[fileidx].path, &oldst);
|
|
||||||
|
|
||||||
if ((pid = fork()) == 0) {
|
if ((pid = fork()) == 0) {
|
||||||
execl(keyhandler.cmd, keyhandler.cmd, kstr, files[fileidx].path, NULL);
|
execv(keyhandler.cmd, args);
|
||||||
warn("could not exec key handler");
|
warn("could not exec key handler");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
} else if (pid < 0) {
|
} else if (pid < 0) {
|
||||||
@ -507,31 +523,31 @@ void run_key_handler(const char *key, unsigned int mask)
|
|||||||
if (WIFEXITED(status) == 0 || retval != 0)
|
if (WIFEXITED(status) == 0 || retval != 0)
|
||||||
warn("key handler exited with non-zero return value: %d", retval);
|
warn("key handler exited with non-zero return value: %d", retval);
|
||||||
|
|
||||||
if (stat(files[fileidx].path, &newst) == 0 &&
|
for (i = 0; i < fcnt; i++) {
|
||||||
memcmp(&oldst.st_mtime, &newst.st_mtime, sizeof(oldst.st_mtime)) == 0)
|
oldst = &finfo[i].st;
|
||||||
{
|
if (stat(files[finfo[i].fn].path, &newst) != 0 ||
|
||||||
/* file has not changed */
|
memcmp(&oldst->st_mtime, &newst.st_mtime, sizeof(newst.st_mtime)) != 0)
|
||||||
goto end;
|
{
|
||||||
}
|
if (tns.thumbs != NULL) {
|
||||||
restore_bar = false;
|
tns.thumbs[finfo[i].fn].loaded = false;
|
||||||
strncpy(win.bar.l, "Reloading image...", sizeof(win.bar.l));
|
tns.loadnext = MIN(tns.loadnext, finfo[i].fn);
|
||||||
win_draw(&win);
|
}
|
||||||
|
changed = true;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
if (restore_bar)
|
if (mode == MODE_IMAGE) {
|
||||||
memcpy(win.bar.l, oldbar, sizeof(win.bar.l));
|
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();
|
reset_cursor();
|
||||||
redraw();
|
redraw();
|
||||||
|
free(finfo);
|
||||||
|
free(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MODMASK(mask) ((mask) & (ShiftMask|ControlMask|Mod1Mask))
|
#define MODMASK(mask) ((mask) & (ShiftMask|ControlMask|Mod1Mask))
|
||||||
@ -651,7 +667,7 @@ void run(void)
|
|||||||
int xfd;
|
int xfd;
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
bool discard, to_set;
|
bool discard, reload, to_set;
|
||||||
XEvent ev, nextev;
|
XEvent ev, nextev;
|
||||||
|
|
||||||
set_timeout(redraw, 25, false);
|
set_timeout(redraw, 25, false);
|
||||||
@ -661,9 +677,10 @@ void run(void)
|
|||||||
XPending(win.env.dpy) == 0)
|
XPending(win.env.dpy) == 0)
|
||||||
{
|
{
|
||||||
/* load thumbnails */
|
/* load thumbnails */
|
||||||
|
reload = tns.loadnext != tns.cnt;
|
||||||
set_timeout(redraw, TO_REDRAW_THUMBS, false);
|
set_timeout(redraw, TO_REDRAW_THUMBS, false);
|
||||||
if (tns_load(&tns, tns.loadnext, &files[tns.loadnext], false, false)) {
|
if (tns_load(&tns, tns.loadnext, &files[tns.loadnext], reload)) {
|
||||||
if (tns.cnt == tns.loadnext)
|
if (!reload)
|
||||||
tns.cnt++;
|
tns.cnt++;
|
||||||
} else {
|
} else {
|
||||||
remove_file(tns.loadnext, false);
|
remove_file(tns.loadnext, false);
|
||||||
@ -860,7 +877,7 @@ int main(int argc, char **argv)
|
|||||||
if (options->thumb_mode) {
|
if (options->thumb_mode) {
|
||||||
mode = MODE_THUMB;
|
mode = MODE_THUMB;
|
||||||
tns_init(&tns, filecnt, &win, &fileidx);
|
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);
|
remove_file(0, false);
|
||||||
tns.cnt = 1;
|
tns.cnt = 1;
|
||||||
} else {
|
} else {
|
||||||
|
10
sxiv.1
10
sxiv.1
@ -112,7 +112,8 @@ Toggle fullscreen mode.
|
|||||||
Toggle visibility of info bar on bottom of window.
|
Toggle visibility of info bar on bottom of window.
|
||||||
.TP
|
.TP
|
||||||
.B Ctrl-x
|
.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
|
.TP
|
||||||
.B g
|
.B g
|
||||||
Go to the first image.
|
Go to the first image.
|
||||||
@ -354,9 +355,10 @@ located in
|
|||||||
.IR $XDG_CONFIG_HOME/sxiv/exec/key-handler .
|
.IR $XDG_CONFIG_HOME/sxiv/exec/key-handler .
|
||||||
The handler is invoked by pressing
|
The handler is invoked by pressing
|
||||||
.BR Ctrl-x .
|
.BR Ctrl-x .
|
||||||
The next key combo is then passed as its first argument and the path of the
|
The next key combo is then passed as its first argument, followed by the paths
|
||||||
current image as its second argument. sxiv(1) will block until the handler
|
of all marked images or the path of the current image, if no image is marked.
|
||||||
terminates. It then checks if the image has been modified and reloads it.
|
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",
|
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
|
where C/M/S indicate Ctrl/Meta(Alt)/Shift modifier states and KEY is the X
|
||||||
|
6
thumbs.c
6
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 tns_load(tns_t *tns, int n, const fileinfo_t *file, bool force)
|
||||||
bool force, bool silent)
|
|
||||||
{
|
{
|
||||||
int w, h;
|
int w, h;
|
||||||
bool cache_hit = false;
|
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 ||
|
if (im == NULL && (access(file->path, R_OK) < 0 ||
|
||||||
(im = imlib_load_image(file->path)) == NULL))
|
(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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
thumbs.h
2
thumbs.h
@ -57,7 +57,7 @@ void tns_clean_cache(tns_t*);
|
|||||||
void tns_init(tns_t*, int, win_t*, int*);
|
void tns_init(tns_t*, int, win_t*, int*);
|
||||||
void tns_free(tns_t*);
|
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_render(tns_t*);
|
||||||
void tns_mark(tns_t*, int, bool);
|
void tns_mark(tns_t*, int, bool);
|
||||||
|
Loading…
Reference in New Issue
Block a user