Revised command structure and key and mouse button mappings

This commit is contained in:
Bert Münnich 2014-07-23 21:50:31 +02:00
parent 5d0679b855
commit 06164c29b7
8 changed files with 336 additions and 392 deletions

View file

@ -1,4 +1,4 @@
VERSION = git-20140615
VERSION = git-20140723
PREFIX = /usr/local
MANPREFIX = $(PREFIX)/share/man

View file

@ -89,24 +89,17 @@ of small previews is displayed, making it easy to choose an image to open.
**Key mappings:**
0-9 Prefix the next command with a number (denoted via [count])
q Quit sxiv
Return Switch to thumbnail mode / open selected image
0-9 Prefix the next command with a number (denoted via [count])
f Toggle fullscreen mode
b Toggle visibility of info bar on bottom of window
Ctrl-x Send the next key to the external key-handler
g Go to first image
G Go to the last image, or image number [count]
f Toggle fullscreen mode (requires an EWMH/NetWM compliant
window manager)
b Toggle visibility of info bar on bottom of window
r Reload image
R Reload all thumbnails
D Remove image from file list and go to next image
Ctrl-h,j,k,l Scroll one window width/height left/down/up/right
m Mark/unmark current image
M Reverse all image marks
N Go [count] marked images forward
@ -114,18 +107,20 @@ of small previews is displayed, making it easy to choose an image to open.
*Thumbnail mode:*
h,j,k,l Move selection left/down/up/right [count] times
Ctrl-j,k Scroll thumbnail grid one window height down/up
h,j,k,l Move selection left/down/up/right [count] times (also with
arrow keys)
R Reload all thumbnails
*Image mode:*
n,Space Go [count] images forward
p,Backspace Go [count] images backward
[,] Go [count] * 10 images backward/forward
Ctrl-n,p Go to the next/previous frame of a multi-frame image
Ctrl-Space Play/pause animation of a multi-frame image
h,j,k,l Scroll image 1/5 of window width/height or [count] pixels
left/down/up/right (also with arrow keys)
H,J,K,L Scroll to left/bottom/top/right image edge
+ Zoom in
- Zoom out
= Set zoom level to 100%, or [count]%
@ -133,23 +128,13 @@ of small previews is displayed, making it easy to choose an image to open.
W Fit image to window
e Fit image to window width
E Fit image to window height
h,j,k,l Pan image 1/5 of window width/height or [count] pixels
left/down/up/right (also with arrow keys)
H,J,K,L Pan to left/bottom/top/right image edge
Ctrl-h,j,k,l Pan image one window width/height left/down/up/right
(also with Ctrl-arrow keys)
<,> Rotate image (counter-)clockwise by 90 degrees
? Rotate image by 180 degrees
|,_ Flip image horizontally/vertically
{,} Decrease/increase gamma
Ctrl-g Reset gamma
a Toggle anti-aliasing
A Toggle visibility of alpha-channel, i.e. transparency
s Toggle slideshow or set delay to [count] seconds
@ -158,11 +143,11 @@ of small previews is displayed, making it easy to choose an image to open.
*Image mode:*
Button1 Go to the next image
Button2 Drag image with mouse while keeping it pressed
Button3 Go to the previous image
Scroll Pan image up/down
Shift+Scroll Pan image left/right
Ctrl+Scroll Zoom in/out
Button2 Drag image with mouse while keeping it pressed
Wheel Scroll image up/down
Shift+Wheel Scroll image left/right
Ctrl+Wheel Zoom in/out
Download & Changelog

View file

@ -1,4 +1,4 @@
/* Copyright 2011, 2012 Bert Muennich
/* Copyright 2011, 2012, 2014 Bert Muennich
*
* This file is part of sxiv.
*
@ -58,7 +58,7 @@ const int ss_delays[] = {
1, 2, 3, 5, 10, 15, 20, 30, 60, 120, 180, 300, 600
};
cmdreturn_t it_quit(arg_t a)
bool cg_quit(arg_t a)
{
unsigned int i;
@ -72,7 +72,7 @@ cmdreturn_t it_quit(arg_t a)
exit(EXIT_SUCCESS);
}
cmdreturn_t it_switch_mode(arg_t a)
bool cg_switch_mode(arg_t a)
{
if (mode == MODE_IMAGE) {
if (tns.thumbs == NULL)
@ -90,10 +90,10 @@ cmdreturn_t it_switch_mode(arg_t a)
load_image(tns.sel);
mode = MODE_IMAGE;
}
return CMD_DIRTY;
return true;
}
cmdreturn_t it_toggle_fullscreen(arg_t a)
bool cg_toggle_fullscreen(arg_t a)
{
win_toggle_fullscreen(&win);
/* redraw after next ConfigureNotify event */
@ -102,10 +102,10 @@ cmdreturn_t it_toggle_fullscreen(arg_t a)
img.checkpan = img.dirty = true;
else
tns.dirty = true;
return CMD_OK;
return false;
}
cmdreturn_t it_toggle_bar(arg_t a)
bool cg_toggle_bar(arg_t a)
{
win_toggle_bar(&win);
if (mode == MODE_IMAGE) {
@ -115,27 +115,16 @@ cmdreturn_t it_toggle_bar(arg_t a)
} else {
tns.dirty = true;
}
return CMD_DIRTY;
return true;
}
cmdreturn_t it_prefix_external(arg_t a)
bool cg_prefix_external(arg_t a)
{
extprefix = true;
return CMD_OK;
return false;
}
cmdreturn_t t_reload_all(arg_t a)
{
if (mode == MODE_THUMB) {
tns_free(&tns);
tns_init(&tns, filecnt, &win);
return CMD_DIRTY;
} else {
return CMD_INVALID;
}
}
cmdreturn_t it_reload_image(arg_t a)
bool cg_reload_image(arg_t a)
{
if (mode == MODE_IMAGE) {
load_image(fileidx);
@ -148,120 +137,77 @@ cmdreturn_t it_reload_image(arg_t a)
tns.sel = tns.cnt - 1;
}
}
return CMD_DIRTY;
return true;
}
cmdreturn_t it_remove_image(arg_t a)
bool cg_remove_image(arg_t a)
{
if (mode == MODE_IMAGE) {
remove_file(fileidx, true);
load_image(fileidx >= filecnt ? filecnt - 1 : fileidx);
return CMD_DIRTY;
return true;
} else if (tns.sel < tns.cnt) {
remove_file(tns.sel, true);
tns.dirty = true;
if (tns.sel >= tns.cnt)
tns.sel = tns.cnt - 1;
return CMD_DIRTY;
return true;
} else {
return CMD_OK;
return false;
}
}
cmdreturn_t i_navigate(arg_t a)
{
long n = (long) a;
if (mode == MODE_IMAGE) {
if (prefix > 0)
n *= prefix;
n += fileidx;
if (n < 0)
n = 0;
if (n >= filecnt)
n = filecnt - 1;
if (n != fileidx) {
load_image(n);
return CMD_DIRTY;
}
}
return CMD_INVALID;
}
cmdreturn_t i_alternate(arg_t a)
{
if (mode == MODE_IMAGE) {
load_image(alternate);
return CMD_DIRTY;
} else {
return CMD_INVALID;
}
}
cmdreturn_t it_first(arg_t a)
bool cg_first(arg_t a)
{
if (mode == MODE_IMAGE && fileidx != 0) {
load_image(0);
return CMD_DIRTY;
return true;
} else if (mode == MODE_THUMB && tns.sel != 0) {
tns.sel = 0;
tns.dirty = true;
return CMD_DIRTY;
return true;
} else {
return CMD_OK;
return false;
}
}
cmdreturn_t it_n_or_last(arg_t a)
bool cg_n_or_last(arg_t a)
{
int n = prefix != 0 && prefix - 1 < filecnt ? prefix - 1 : filecnt - 1;
if (mode == MODE_IMAGE && fileidx != n) {
load_image(n);
return CMD_DIRTY;
return true;
} else if (mode == MODE_THUMB && tns.sel != n) {
tns.sel = n;
tns.dirty = true;
return CMD_DIRTY;
return true;
} else {
return CMD_OK;
return false;
}
}
cmdreturn_t i_navigate_frame(arg_t a)
bool cg_scroll_screen(arg_t a)
{
if (mode != MODE_IMAGE)
return CMD_INVALID;
direction_t dir = (direction_t) a;
if (mode == MODE_IMAGE)
return img_pan(&img, dir, -1);
else
return !img.multi.animate && img_frame_navigate(&img, (long) a);
return tns_scroll(&tns, dir, true);
}
cmdreturn_t i_toggle_animation(arg_t a)
{
if (mode != MODE_IMAGE)
return CMD_INVALID;
if (img.multi.animate) {
reset_timeout(animate);
img.multi.animate = false;
} else if (img_frame_animate(&img, true)) {
set_timeout(animate, img.multi.frames[img.multi.sel].delay, true);
}
return CMD_DIRTY;
}
cmdreturn_t it_toggle_image_mark(arg_t a)
bool cg_toggle_image_mark(arg_t a)
{
int sel = mode == MODE_IMAGE ? fileidx : tns.sel;
files[sel].marked = !files[sel].marked;
if (mode == MODE_THUMB)
tns_mark(&tns, sel, files[sel].marked);
return CMD_DIRTY;
return true;
}
cmdreturn_t it_reverse_marks(arg_t a)
bool cg_reverse_marks(arg_t a)
{
int i, cnt = mode == MODE_IMAGE ? filecnt : tns.cnt;
@ -269,10 +215,10 @@ cmdreturn_t it_reverse_marks(arg_t a)
files[i].marked = !files[i].marked;
if (mode == MODE_THUMB)
tns.dirty = true;
return CMD_DIRTY;
return true;
}
cmdreturn_t it_navigate_marked(arg_t a)
bool cg_navigate_marked(arg_t a)
{
long n = (long) a;
int d, i, cnt, sel, new;
@ -297,40 +243,66 @@ cmdreturn_t it_navigate_marked(arg_t a)
tns.sel = new;
tns.dirty = true;
}
return CMD_DIRTY;
return true;
} else {
return CMD_OK;
return false;
}
}
cmdreturn_t it_scroll_move(arg_t a)
bool ci_navigate(arg_t a)
{
direction_t dir = (direction_t) a;
long n = (long) a;
if (mode == MODE_IMAGE)
return img_pan(&img, dir, prefix);
else
return tns_move_selection(&tns, dir, prefix);
if (prefix > 0)
n *= prefix;
n += fileidx;
if (n < 0)
n = 0;
if (n >= filecnt)
n = filecnt - 1;
if (n != fileidx) {
load_image(n);
return true;
} else {
return false;
}
}
cmdreturn_t it_scroll_screen(arg_t a)
bool ci_alternate(arg_t a)
{
direction_t dir = (direction_t) a;
if (mode == MODE_IMAGE)
return img_pan(&img, dir, -1);
else
return tns_scroll(&tns, dir, true);
load_image(alternate);
return true;
}
cmdreturn_t i_scroll_to_edge(arg_t a)
bool ci_navigate_frame(arg_t a)
{
return !img.multi.animate && img_frame_navigate(&img, (long) a);
}
bool ci_toggle_animation(arg_t a)
{
if (img.multi.animate) {
reset_timeout(animate);
img.multi.animate = false;
} else if (img_frame_animate(&img, true)) {
set_timeout(animate, img.multi.frames[img.multi.sel].delay, true);
}
return true;
}
bool ci_scroll(arg_t a)
{
direction_t dir = (direction_t) a;
if (mode == MODE_IMAGE)
return img_pan_edge(&img, dir);
else
return CMD_INVALID;
return img_pan(&img, dir, prefix);
}
bool ci_scroll_to_edge(arg_t a)
{
direction_t dir = (direction_t) a;
return img_pan_edge(&img, dir);
}
/* Xlib helper function for i_drag() */
@ -344,7 +316,7 @@ Bool is_motionnotify(Display *d, XEvent *e, XPointer a)
ox = x, oy = y; \
break
cmdreturn_t i_drag(arg_t a)
bool ci_drag(arg_t a)
{
int dx = 0, dy = 0, i, ox, oy, x, y;
unsigned int ui;
@ -352,10 +324,8 @@ cmdreturn_t i_drag(arg_t a)
XEvent e;
Window w;
if (mode != MODE_IMAGE)
return CMD_INVALID;
if (!XQueryPointer(win.env.dpy, win.xwin, &w, &w, &i, &i, &ox, &oy, &ui))
return CMD_OK;
return false;
win_set_cursor(&win, CURSOR_HAND);
@ -398,117 +368,109 @@ cmdreturn_t i_drag(arg_t a)
dx = dy = 0;
}
}
win_set_cursor(&win, CURSOR_ARROW);
set_timeout(reset_cursor, TO_CURSOR_HIDE, true);
reset_timeout(redraw);
return CMD_OK;
return true;
}
cmdreturn_t i_zoom(arg_t a)
bool ci_zoom(arg_t a)
{
long scale = (long) a;
if (mode != MODE_IMAGE)
return CMD_INVALID;
if (scale > 0)
return img_zoom_in(&img);
else if (scale < 0)
return img_zoom_out(&img);
else
return CMD_OK;
return false;
}
cmdreturn_t i_set_zoom(arg_t a)
bool ci_set_zoom(arg_t a)
{
if (mode == MODE_IMAGE)
return img_zoom(&img, (prefix ? prefix : (long) a) / 100.0);
else
return CMD_INVALID;
return img_zoom(&img, (prefix ? prefix : (long) a) / 100.0);
}
cmdreturn_t i_fit_to_win(arg_t a)
bool ci_fit_to_win(arg_t a)
{
scalemode_t sm = (scalemode_t) a;
if (mode == MODE_IMAGE)
return img_fit_win(&img, sm);
else
return CMD_INVALID;
return img_fit_win(&img, sm);
}
cmdreturn_t i_rotate(arg_t a)
bool ci_rotate(arg_t a)
{
degree_t degree = (degree_t) a;
if (mode == MODE_IMAGE) {
img_rotate(&img, degree);
return CMD_DIRTY;
} else {
return CMD_INVALID;
}
img_rotate(&img, degree);
return true;
}
cmdreturn_t i_flip(arg_t a)
bool ci_flip(arg_t a)
{
flipdir_t dir = (flipdir_t) a;
if (mode == MODE_IMAGE) {
img_flip(&img, dir);
return CMD_DIRTY;
} else {
return CMD_INVALID;
}
img_flip(&img, dir);
return true;
}
cmdreturn_t i_slideshow(arg_t a)
bool ci_change_gamma(arg_t a)
{
if (mode == MODE_IMAGE) {
if (prefix > 0) {
img.ss.on = true;
img.ss.delay = prefix;
set_timeout(slideshow, img.ss.delay * 1000, true);
} else if (img.ss.on) {
img.ss.on = false;
reset_timeout(slideshow);
} else {
img.ss.on = true;
}
return CMD_DIRTY;
} else {
return CMD_INVALID;
}
return img_change_gamma(&img, (long) a);
}
cmdreturn_t i_toggle_antialias(arg_t a)
bool ci_toggle_antialias(arg_t a)
{
if (mode == MODE_IMAGE) {
img_toggle_antialias(&img);
return CMD_DIRTY;
} else {
return CMD_INVALID;
}
img_toggle_antialias(&img);
return true;
}
cmdreturn_t i_toggle_alpha(arg_t a)
bool ci_toggle_alpha(arg_t a)
{
if (mode == MODE_IMAGE) {
img.alpha = !img.alpha;
img.dirty = true;
return CMD_DIRTY;
} else {
return CMD_INVALID;
}
img.alpha = !img.alpha;
img.dirty = true;
return true;
}
cmdreturn_t i_change_gamma(arg_t a)
bool ci_slideshow(arg_t a)
{
if (mode == MODE_IMAGE) {
return img_change_gamma(&img, (long) a);
if (prefix > 0) {
img.ss.on = true;
img.ss.delay = prefix;
set_timeout(slideshow, img.ss.delay * 1000, true);
} else if (img.ss.on) {
img.ss.on = false;
reset_timeout(slideshow);
} else {
return CMD_INVALID;
img.ss.on = true;
}
return true;
}
bool ct_move_sel(arg_t a)
{
direction_t dir = (direction_t) a;
return tns_move_selection(&tns, dir, prefix);
}
bool ct_reload_all(arg_t a)
{
tns_free(&tns);
tns_init(&tns, filecnt, &win);
return false;
}
#undef G_CMD
#define G_CMD(c) { -1, cg_##c },
#undef I_CMD
#define I_CMD(c) { MODE_IMAGE, ci_##c },
#undef T_CMD
#define T_CMD(c) { MODE_THUMB, ct_##c },
const cmd_t cmds[CMD_COUNT] = {
#include "commands.lst"
};

View file

@ -1,4 +1,4 @@
/* Copyright 2011 Bert Muennich
/* Copyright 2011, 2014 Bert Muennich
*
* This file is part of sxiv.
*
@ -23,58 +23,37 @@
#include "types.h"
typedef enum {
CMD_INVALID = -1,
CMD_OK = 0,
CMD_DIRTY = 1
} cmdreturn_t;
typedef void* arg_t;
typedef cmdreturn_t (*command_f)(arg_t);
typedef bool (*cmd_f)(arg_t);
#define G_CMD(c) g_##c,
#define I_CMD(c) i_##c,
#define T_CMD(c) t_##c,
typedef enum {
#include "commands.lst"
CMD_COUNT
} cmd_id_t;
typedef struct {
int mode;
cmd_f func;
} cmd_t;
typedef struct {
unsigned int mask;
KeySym ksym;
command_f cmd;
cmd_id_t cmd;
arg_t arg;
} keymap_t;
typedef struct {
unsigned int mask;
unsigned int button;
command_f cmd;
cmd_id_t cmd;
arg_t arg;
} button_t;
cmdreturn_t it_quit(arg_t);
cmdreturn_t it_switch_mode(arg_t);
cmdreturn_t it_toggle_fullscreen(arg_t);
cmdreturn_t it_toggle_bar(arg_t);
cmdreturn_t it_prefix_external(arg_t);
cmdreturn_t t_reload_all(arg_t);
cmdreturn_t it_reload_image(arg_t);
cmdreturn_t it_remove_image(arg_t);
cmdreturn_t i_navigate(arg_t);
cmdreturn_t i_alternate(arg_t);
cmdreturn_t it_first(arg_t);
cmdreturn_t it_n_or_last(arg_t);
cmdreturn_t i_navigate_frame(arg_t);
cmdreturn_t i_toggle_animation(arg_t);
cmdreturn_t it_toggle_image_mark(arg_t);
cmdreturn_t it_reverse_marks(arg_t);
cmdreturn_t it_navigate_marked(arg_t);
cmdreturn_t it_scroll_move(arg_t);
cmdreturn_t it_scroll_screen(arg_t);
cmdreturn_t i_scroll_to_edge(arg_t);
cmdreturn_t i_drag(arg_t);
cmdreturn_t i_zoom(arg_t);
cmdreturn_t i_set_zoom(arg_t);
cmdreturn_t i_fit_to_win(arg_t);
cmdreturn_t i_rotate(arg_t);
cmdreturn_t i_flip(arg_t);
cmdreturn_t i_slideshow(arg_t);
cmdreturn_t i_toggle_antialias(arg_t);
cmdreturn_t i_toggle_alpha(arg_t);
cmdreturn_t i_change_gamma(arg_t);
const extern cmd_t cmds[CMD_COUNT];
#endif /* COMMANDS_H */

34
commands.lst Normal file
View file

@ -0,0 +1,34 @@
G_CMD(quit)
G_CMD(switch_mode)
G_CMD(toggle_fullscreen)
G_CMD(toggle_bar)
G_CMD(prefix_external)
G_CMD(reload_image)
G_CMD(remove_image)
G_CMD(first)
G_CMD(n_or_last)
G_CMD(scroll_screen)
G_CMD(toggle_image_mark)
G_CMD(reverse_marks)
G_CMD(navigate_marked)
I_CMD(navigate)
I_CMD(alternate)
I_CMD(navigate_frame)
I_CMD(toggle_animation)
I_CMD(scroll)
I_CMD(scroll_to_edge)
I_CMD(drag)
I_CMD(zoom)
I_CMD(set_zoom)
I_CMD(fit_to_win)
I_CMD(rotate)
I_CMD(flip)
I_CMD(change_gamma)
I_CMD(toggle_antialias)
I_CMD(toggle_alpha)
I_CMD(slideshow)
T_CMD(move_sel)
T_CMD(reload_all)

View file

@ -69,16 +69,37 @@ enum { THUMB_SIZE = 60 };
/* keyboard mappings for image and thumbnail mode: */
static const keymap_t keys[] = {
/* modifiers key function argument */
{ 0, XK_q, it_quit, (arg_t) None },
{ 0, XK_Return, it_switch_mode, (arg_t) None },
{ 0, XK_f, it_toggle_fullscreen, (arg_t) None },
{ 0, XK_b, it_toggle_bar, (arg_t) None },
{ 0, XK_q, g_quit, (arg_t) None },
{ 0, XK_Return, g_switch_mode, (arg_t) None },
{ 0, XK_f, g_toggle_fullscreen, (arg_t) None },
{ 0, XK_b, g_toggle_bar, (arg_t) None },
{ ControlMask, XK_x, g_prefix_external, (arg_t) None },
{ 0, XK_g, g_first, (arg_t) None },
{ 0, XK_G, g_n_or_last, (arg_t) None },
{ 0, XK_r, g_reload_image, (arg_t) None },
{ 0, XK_D, g_remove_image, (arg_t) None },
{ ControlMask, XK_h, g_scroll_screen, (arg_t) DIR_LEFT },
{ ControlMask, XK_Left, g_scroll_screen, (arg_t) DIR_LEFT },
{ ControlMask, XK_j, g_scroll_screen, (arg_t) DIR_DOWN },
{ ControlMask, XK_Down, g_scroll_screen, (arg_t) DIR_DOWN },
{ ControlMask, XK_k, g_scroll_screen, (arg_t) DIR_UP },
{ ControlMask, XK_Up, g_scroll_screen, (arg_t) DIR_UP },
{ ControlMask, XK_l, g_scroll_screen, (arg_t) DIR_RIGHT },
{ ControlMask, XK_Right, g_scroll_screen, (arg_t) DIR_RIGHT },
{ 0, XK_m, g_toggle_image_mark, (arg_t) None },
{ 0, XK_M, g_reverse_marks, (arg_t) None },
{ 0, XK_N, g_navigate_marked, (arg_t) +1 },
{ 0, XK_P, g_navigate_marked, (arg_t) -1 },
{ ControlMask, XK_x, it_prefix_external, (arg_t) None },
{ 0, XK_r, it_reload_image, (arg_t) None },
{ 0, XK_h, t_move_sel, (arg_t) DIR_LEFT },
{ 0, XK_Left, t_move_sel, (arg_t) DIR_LEFT },
{ 0, XK_j, t_move_sel, (arg_t) DIR_DOWN },
{ 0, XK_Down, t_move_sel, (arg_t) DIR_DOWN },
{ 0, XK_k, t_move_sel, (arg_t) DIR_UP },
{ 0, XK_Up, t_move_sel, (arg_t) DIR_UP },
{ 0, XK_l, t_move_sel, (arg_t) DIR_RIGHT },
{ 0, XK_Right, t_move_sel, (arg_t) DIR_RIGHT },
{ 0, XK_R, t_reload_all, (arg_t) None },
{ 0, XK_D, it_remove_image, (arg_t) None },
{ 0, XK_n, i_navigate, (arg_t) +1 },
{ 0, XK_space, i_navigate, (arg_t) +1 },
@ -87,41 +108,21 @@ static const keymap_t keys[] = {
{ 0, XK_bracketright, i_navigate, (arg_t) +10 },
{ 0, XK_bracketleft, i_navigate, (arg_t) -10 },
{ ControlMask, XK_6, i_alternate, (arg_t) None },
{ 0, XK_g, it_first, (arg_t) None },
{ 0, XK_G, it_n_or_last, (arg_t) None },
{ ControlMask, XK_n, i_navigate_frame, (arg_t) +1 },
{ ControlMask, XK_p, i_navigate_frame, (arg_t) -1 },
{ ControlMask, XK_space, i_toggle_animation, (arg_t) None },
{ 0, XK_m, it_toggle_image_mark, (arg_t) None },
{ 0, XK_M, it_reverse_marks, (arg_t) None },
{ 0, XK_N, it_navigate_marked, (arg_t) +1 },
{ 0, XK_P, it_navigate_marked, (arg_t) -1 },
{ 0, XK_h, it_scroll_move, (arg_t) DIR_LEFT },
{ 0, XK_Left, it_scroll_move, (arg_t) DIR_LEFT },
{ 0, XK_j, it_scroll_move, (arg_t) DIR_DOWN },
{ 0, XK_Down, it_scroll_move, (arg_t) DIR_DOWN },
{ 0, XK_k, it_scroll_move, (arg_t) DIR_UP },
{ 0, XK_Up, it_scroll_move, (arg_t) DIR_UP },
{ 0, XK_l, it_scroll_move, (arg_t) DIR_RIGHT },
{ 0, XK_Right, it_scroll_move, (arg_t) DIR_RIGHT },
{ ControlMask, XK_h, it_scroll_screen, (arg_t) DIR_LEFT },
{ ControlMask, XK_Left, it_scroll_screen, (arg_t) DIR_LEFT },
{ ControlMask, XK_j, it_scroll_screen, (arg_t) DIR_DOWN },
{ ControlMask, XK_Down, it_scroll_screen, (arg_t) DIR_DOWN },
{ ControlMask, XK_k, it_scroll_screen, (arg_t) DIR_UP },
{ ControlMask, XK_Up, it_scroll_screen, (arg_t) DIR_UP },
{ ControlMask, XK_l, it_scroll_screen, (arg_t) DIR_RIGHT },
{ ControlMask, XK_Right, it_scroll_screen, (arg_t) DIR_RIGHT },
{ 0, XK_h, i_scroll, (arg_t) DIR_LEFT },
{ 0, XK_Left, i_scroll, (arg_t) DIR_LEFT },
{ 0, XK_j, i_scroll, (arg_t) DIR_DOWN },
{ 0, XK_Down, i_scroll, (arg_t) DIR_DOWN },
{ 0, XK_k, i_scroll, (arg_t) DIR_UP },
{ 0, XK_Up, i_scroll, (arg_t) DIR_UP },
{ 0, XK_l, i_scroll, (arg_t) DIR_RIGHT },
{ 0, XK_Right, i_scroll, (arg_t) DIR_RIGHT },
{ 0, XK_H, i_scroll_to_edge, (arg_t) DIR_LEFT },
{ 0, XK_J, i_scroll_to_edge, (arg_t) DIR_DOWN },
{ 0, XK_K, i_scroll_to_edge, (arg_t) DIR_UP },
{ 0, XK_L, i_scroll_to_edge, (arg_t) DIR_RIGHT },
{ 0, XK_plus, i_zoom, (arg_t) +1 },
{ 0, XK_KP_Add, i_zoom, (arg_t) +1 },
{ 0, XK_minus, i_zoom, (arg_t) -1 },
@ -131,22 +132,17 @@ static const keymap_t keys[] = {
{ 0, XK_W, i_fit_to_win, (arg_t) SCALE_FIT },
{ 0, XK_e, i_fit_to_win, (arg_t) SCALE_WIDTH },
{ 0, XK_E, i_fit_to_win, (arg_t) SCALE_HEIGHT },
{ 0, XK_less, i_rotate, (arg_t) DEGREE_270 },
{ 0, XK_greater, i_rotate, (arg_t) DEGREE_90 },
{ 0, XK_question, i_rotate, (arg_t) DEGREE_180 },
{ 0, XK_bar, i_flip, (arg_t) FLIP_HORIZONTAL },
{ 0, XK_underscore, i_flip, (arg_t) FLIP_VERTICAL },
{ 0, XK_s, i_slideshow, (arg_t) None },
{ 0, XK_a, i_toggle_antialias, (arg_t) None },
{ 0, XK_A, i_toggle_alpha, (arg_t) None },
{ 0, XK_braceleft, i_change_gamma, (arg_t) -1 },
{ 0, XK_braceright, i_change_gamma, (arg_t) +1 },
{ ControlMask, XK_g, i_change_gamma, (arg_t) 0 },
{ 0, XK_a, i_toggle_antialias, (arg_t) None },
{ 0, XK_A, i_toggle_alpha, (arg_t) None },
{ 0, XK_s, i_slideshow, (arg_t) None },
};
/* mouse button mappings for image mode: */
@ -155,12 +151,12 @@ static const button_t buttons[] = {
{ 0, 1, i_navigate, (arg_t) +1 },
{ 0, 3, i_navigate, (arg_t) -1 },
{ 0, 2, i_drag, (arg_t) None },
{ 0, 4, it_scroll_move, (arg_t) DIR_UP },
{ 0, 5, it_scroll_move, (arg_t) DIR_DOWN },
{ ShiftMask, 4, it_scroll_move, (arg_t) DIR_LEFT },
{ ShiftMask, 5, it_scroll_move, (arg_t) DIR_RIGHT },
{ 0, 6, it_scroll_move, (arg_t) DIR_LEFT },
{ 0, 7, it_scroll_move, (arg_t) DIR_RIGHT },
{ 0, 4, i_scroll, (arg_t) DIR_UP },
{ 0, 5, i_scroll, (arg_t) DIR_DOWN },
{ ShiftMask, 4, i_scroll, (arg_t) DIR_LEFT },
{ ShiftMask, 5, i_scroll, (arg_t) DIR_RIGHT },
{ 0, 6, i_scroll, (arg_t) DIR_LEFT },
{ 0, 7, i_scroll, (arg_t) DIR_RIGHT },
{ ControlMask, 4, i_zoom, (arg_t) +1 },
{ ControlMask, 5, i_zoom, (arg_t) -1 },
};

18
main.c
View file

@ -567,13 +567,10 @@ void on_keypress(XKeyEvent *kev)
} else for (i = 0; i < ARRLEN(keys); i++) {
if (keys[i].ksym == ksym &&
MODMASK(keys[i].mask | sh) == MODMASK(kev->state) &&
keys[i].cmd != NULL)
keys[i].cmd >= 0 && keys[i].cmd < CMD_COUNT &&
(cmds[keys[i].cmd].mode < 0 || cmds[keys[i].cmd].mode == mode))
{
cmdreturn_t ret = keys[i].cmd(keys[i].arg);
if (ret == CMD_INVALID)
continue;
if (ret == CMD_DIRTY)
if (cmds[keys[i].cmd].func(keys[i].arg))
redraw();
break;
}
@ -596,13 +593,10 @@ void on_buttonpress(XButtonEvent *bev)
for (i = 0; i < ARRLEN(buttons); i++) {
if (buttons[i].button == bev->button &&
MODMASK(buttons[i].mask) == MODMASK(bev->state) &&
buttons[i].cmd != NULL)
buttons[i].cmd >= 0 && buttons[i].cmd < CMD_COUNT &&
(cmds[buttons[i].cmd].mode < 0 || cmds[buttons[i].cmd].mode == mode))
{
cmdreturn_t ret = buttons[i].cmd(buttons[i].arg);
if (ret == CMD_INVALID)
continue;
if (ret == CMD_DIRTY)
if (cmds[buttons[i].cmd].func(buttons[i].arg))
redraw();
break;
}

156
sxiv.1
View file

@ -92,23 +92,16 @@ Set zoom level to ZOOM percent.
.SH GENERAL KEYBOARD COMMANDS
The following keyboard commands are available in both image and thumbnail mode:
.TP
.BR 0 \- 9
Prefix the next command with a number (denoted via
.IR count ).
.TP
.B q
Quit sxiv.
.TP
.B Return
Switch to thumbnail mode / open selected image in image mode.
.TP
.BR 0 \- 9
Prefix the next command with a number (denoted via
.IR count ).
.TP
.B g
Go to the first image.
.TP
.B G
Go to the last image, or image number
.IR count .
.TP
.B f
Toggle fullscreen mode.
.TP
@ -118,15 +111,31 @@ Toggle visibility of info bar on bottom of window.
.B Ctrl-x
Send the next key to the external key-handler.
.TP
.B g
Go to the first image.
.TP
.B G
Go to the last image, or image number
.IR count .
.TP
.B r
Reload image.
.TP
.B R
Reload all thumbnails.
.TP
.B D
Remove current image from file list and go to next image.
.TP
.BR Ctrl-h ", " Ctrl-Left
Scroll left one screen width.
.TP
.BR Ctrl-j ", " Ctrl-Down
Scroll down one screen height.
.TP
.BR Ctrl-k ", " Ctrl-Up
Scroll up one screen height.
.TP
.BR Ctrl-l ", " Ctrl-Right
Scroll right one screen width.
.TP
.B m
Mark/unmark the current image.
.TP
@ -165,11 +174,8 @@ Move selection right
.I count
times.
.TP
.BR Ctrl-j ", " Ctrl-Down
Scroll thumbnail grid one window height down.
.TP
.BR Ctrl-k ", " Ctrl-Up
Scroll thumbnail grid one window height up.
.B R
Reload all thumbnails.
.SH IMAGE KEYBOARD COMMANDS
The following keyboard commands are only available in image mode:
.SS Navigate image list
@ -203,6 +209,39 @@ Go to the previous frame of a multi-frame image.
.TP
.B Ctrl-Space
Play/pause animation of a multi-frame image.
.SS Panning
.TP
.BR h ", " Left
Scroll image 1/5 of window width or
.I count
pixel left.
.TP
.BR j ", " Down
Scroll image 1/5 of window height or
.I count
pixel down.
.TP
.BR k ", " Up
Scroll image 1/5 of window height or
.I count
pixel up.
.TP
.BR l ", " Right
Scroll image 1/5 of window width or
.I count
pixel right.
.TP
.B H
Scroll to left image edge.
.TP
.B J
Scroll to bottom image edge.
.TP
.B K
Scroll to top image edge.
.TP
.B L
Scroll to right image edge.
.SS Zooming
.TP
.BR +
@ -226,51 +265,6 @@ Fit image to window width.
.TP
.B E
Fit image to window height.
.SS Panning
.TP
.BR h ", " Left
Pan image 1/5 of window width or
.I count
pixel left.
.TP
.BR j ", " Down
Pan image 1/5 of window height or
.I count
pixel down.
.TP
.BR k ", " Up
Pan image 1/5 of window height or
.I count
pixel up.
.TP
.BR l ", " Right
Pan image 1/5 of window width or
.I count
pixel right.
.TP
.B H
Pan to left image edge.
.TP
.B J
Pan to bottom image edge.
.TP
.B K
Pan to top image edge.
.TP
.B L
Pan to right image edge.
.TP
.BR Ctrl-h ", " Ctrl-Left
Pan image one window width left.
.TP
.BR Ctrl-j ", " Ctrl-Down
Pan image one window height down.
.TP
.BR Ctrl-k ", " Ctrl-Up
Pan image one window height up.
.TP
.BR Ctrl-l ", " Ctrl-Right
Pan image one window width right.
.SS Rotation
.TP
.B <
@ -281,7 +275,7 @@ Rotate image clockwise by 90 degrees.
.TP
.B ?
Rotate image by 180 degrees.
.SS Flip
.SS Flipping
.TP
.B |
Flip image horizontally.
@ -319,6 +313,22 @@ Go to next image.
.TP
.B Button3
Go to the previous image.
.SS Panning
.TP
.B Button2
Drag the image with the mouse while keeping this button pressed down.
.TP
.B ScrollUp
Scroll image up.
.TP
.B ScrollDown
Scroll image down.
.TP
.B Shift+ScrollUp
Scroll image left.
.TP
.B Shift+ScrollDown
Scroll image right.
.SS Zooming
.TP
.B Ctrl+ScrollUp
@ -326,22 +336,6 @@ Zoom in.
.TP
.B Ctrl+ScrollDown
Zoom out.
.SS Panning/Moving
.TP
.B Button2
Drag the image with the mouse while keeping this button pressed down.
.TP
.B ScrollUp
Pan image up.
.TP
.B ScrollDown
Pan image down.
.TP
.B Shift+ScrollUp
Pan image left.
.TP
.B Shift+ScrollDown
Pan image right.
.SH STATUS BAR
The information displayed on the left side of the status bar can be replaced
with the output of a user-provided script, which is called by sxiv whenever an