@@ -123,11 +123,13 @@ void img_render(img_t *img, win_t *win) { | |||||
/* center image in window */ | /* center image in window */ | ||||
img->x = (win->w - img->w * img->zoom) / 2; | img->x = (win->w - img->w * img->zoom) / 2; | ||||
img->y = (win->h - img->h * img->zoom) / 2; | img->y = (win->h - img->h * img->zoom) / 2; | ||||
} else { | } else if (img->cp) { | ||||
/* typically after zooming and panning */ | /* only useful after zooming */ | ||||
img_check_pan(img, win); | img_check_pan(img, win); | ||||
img->cp = 0; | |||||
} | } | ||||
/* calculate source and destination offsets */ | |||||
if (img->x < 0) { | if (img->x < 0) { | ||||
sx = -img->x / img->zoom; | sx = -img->x / img->zoom; | ||||
sw = win->w / img->zoom; | sw = win->w / img->zoom; | ||||
@@ -172,6 +174,7 @@ int img_zoom(img_t *img, float z) { | |||||
img->x -= (img->w * z - img->w * img->zoom) / 2; | img->x -= (img->w * z - img->w * img->zoom) / 2; | ||||
img->y -= (img->h * z - img->h * img->zoom) / 2; | img->y -= (img->h * z - img->h * img->zoom) / 2; | ||||
img->zoom = z; | img->zoom = z; | ||||
img->cp = 1; | |||||
return 1; | return 1; | ||||
} else { | } else { | ||||
return 0; | return 0; | ||||
@@ -205,3 +208,32 @@ int img_zoom_out(img_t *img) { | |||||
return 0; | return 0; | ||||
} | } | ||||
int img_pan(img_t *img, win_t *win, pandir_t dir) { | |||||
int ox, oy; | |||||
if (!img || !win) | |||||
return 0; | |||||
ox = img->x; | |||||
oy = img->y; | |||||
switch (dir) { | |||||
case PAN_LEFT: | |||||
img->x += win->w / 5; | |||||
break; | |||||
case PAN_RIGHT: | |||||
img->x -= win->w / 5; | |||||
break; | |||||
case PAN_UP: | |||||
img->y += win->h / 5; | |||||
break; | |||||
case PAN_DOWN: | |||||
img->y -= win->h / 5; | |||||
break; | |||||
} | |||||
img_check_pan(img, win); | |||||
return ox != img->x || oy != img->y; | |||||
} |
@@ -27,9 +27,17 @@ enum scalemode { | |||||
SCALE_ZOOM | SCALE_ZOOM | ||||
}; | }; | ||||
typedef enum pandir_e { | |||||
PAN_LEFT = 0, | |||||
PAN_RIGHT, | |||||
PAN_UP, | |||||
PAN_DOWN | |||||
} pandir_t; | |||||
typedef struct img_s { | typedef struct img_s { | ||||
float zoom; | float zoom; | ||||
unsigned char re; | unsigned char re; | ||||
unsigned char cp; | |||||
int x; | int x; | ||||
int y; | int y; | ||||
int w; | int w; | ||||
@@ -45,4 +53,6 @@ void img_render(img_t*, win_t*); | |||||
int img_zoom_in(img_t*); | int img_zoom_in(img_t*); | ||||
int img_zoom_out(img_t*); | int img_zoom_out(img_t*); | ||||
int img_pan(img_t*, win_t*, pandir_t); | |||||
#endif /* IMAGE_H */ | #endif /* IMAGE_H */ |
@@ -108,13 +108,14 @@ void cleanup() { | |||||
void on_keypress(XEvent *ev) { | void on_keypress(XEvent *ev) { | ||||
char key; | char key; | ||||
int len; | |||||
KeySym keysym; | KeySym keysym; | ||||
int changed; | |||||
if (!ev) | if (!ev) | ||||
return; | return; | ||||
len = XLookupString(&ev->xkey, &key, 1, &keysym, NULL); | XLookupString(&ev->xkey, &key, 1, &keysym, NULL); | ||||
changed = 0; | |||||
switch (keysym) { | switch (keysym) { | ||||
case XK_Escape: | case XK_Escape: | ||||
@@ -122,48 +123,58 @@ void on_keypress(XEvent *ev) { | |||||
exit(2); | exit(2); | ||||
case XK_space: | case XK_space: | ||||
key = 'n'; | key = 'n'; | ||||
len = 1; | |||||
break; | break; | ||||
case XK_BackSpace: | case XK_BackSpace: | ||||
key = 'p'; | key = 'p'; | ||||
len = 1; | |||||
break; | break; | ||||
} | } | ||||
if (!len) | |||||
return; | |||||
switch (key) { | switch (key) { | ||||
case 'q': | case 'q': | ||||
cleanup(); | cleanup(); | ||||
exit(0); | exit(0); | ||||
/* navigate through image list */ | |||||
case 'n': | case 'n': | ||||
if (fileidx + 1 < filecnt) { | if (fileidx + 1 < filecnt) { | ||||
img_load(&img, filenames[++fileidx]); | img_load(&img, filenames[++fileidx]); | ||||
img_render(&img, &win); | changed = 1; | ||||
update_title(); | |||||
} | } | ||||
break; | break; | ||||
case 'p': | case 'p': | ||||
if (fileidx > 0) { | if (fileidx > 0) { | ||||
img_load(&img, filenames[--fileidx]); | img_load(&img, filenames[--fileidx]); | ||||
img_render(&img, &win); | changed = 1; | ||||
update_title(); | |||||
} | } | ||||
break; | break; | ||||
/* zooming */ | |||||
case '+': | case '+': | ||||
case '=': | case '=': | ||||
if (img_zoom_in(&img)) { | changed = img_zoom_in(&img); | ||||
img_render(&img, &win); | |||||
update_title(); | |||||
} | |||||
break; | break; | ||||
case '-': | case '-': | ||||
if (img_zoom_out(&img)) { | changed = img_zoom_out(&img); | ||||
img_render(&img, &win); | |||||
update_title(); | |||||
} | |||||
break; | break; | ||||
/* panning */ | |||||
case 'h': | |||||
changed = img_pan(&img, &win, PAN_LEFT); | |||||
break; | |||||
case 'j': | |||||
changed = img_pan(&img, &win, PAN_DOWN); | |||||
break; | |||||
case 'k': | |||||
changed = img_pan(&img, &win, PAN_UP); | |||||
break; | |||||
case 'l': | |||||
changed = img_pan(&img, &win, PAN_RIGHT); | |||||
break; | |||||
} | |||||
if (changed) { | |||||
img_render(&img, &win); | |||||
update_title(); | |||||
} | } | ||||
} | } | ||||