- New option `-a`: Play animations at startup - Ctrl-Space toggles animation for all GIF files - Infinite loop for all animationsmaster
@@ -1,4 +1,4 @@ | |||
VERSION = git-20140723 | |||
VERSION = git-20140725 | |||
PREFIX = /usr/local | |||
MANPREFIX = $(PREFIX)/share/man | |||
@@ -68,6 +68,7 @@ of small previews is displayed, making it easy to choose an image to open. | |||
**Command line options:** | |||
-a Play animations of multi-frame images | |||
-b Do not show info bar on bottom of window | |||
-c Remove all orphaned cache files from thumbnail cache and exit | |||
-f Start in fullscreen mode | |||
@@ -117,7 +118,7 @@ of small previews is displayed, making it easy to choose an image to open. | |||
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 | |||
Ctrl-Space Play/stop animations of multi-frame images | |||
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 | |||
@@ -282,13 +282,17 @@ bool ci_navigate_frame(arg_t a) | |||
bool ci_toggle_animation(arg_t a) | |||
{ | |||
bool dirty = false; | |||
img.multi.animate = !img.multi.animate; | |||
if (img.multi.animate) { | |||
reset_timeout(animate); | |||
img.multi.animate = false; | |||
} else if (img_frame_animate(&img, true)) { | |||
dirty = img_frame_animate(&img, true); | |||
set_timeout(animate, img.multi.frames[img.multi.sel].delay, true); | |||
} else { | |||
reset_timeout(animate); | |||
} | |||
return true; | |||
return dirty; | |||
} | |||
bool ci_scroll(arg_t a) | |||
@@ -34,13 +34,6 @@ static const float zoom_levels[] = { | |||
/* default slideshow delay (in sec, overwritten via -S option): */ | |||
enum { SLIDESHOW_DELAY = 5 }; | |||
/* default settings for multi-frame gif images: */ | |||
enum { | |||
GIF_DELAY = 100, /* delay time (in ms) */ | |||
GIF_AUTOPLAY = 1, /* autoplay when loaded [0/1] */ | |||
GIF_LOOP = 0 /* loop? [0: no, 1: endless, -1: as specified in file] */ | |||
}; | |||
/* gamma correction: the user-visible ranges [-GAMMA_RANGE, 0] and | |||
* (0, GAMMA_RANGE] are mapped to the ranges [0, 1], and (1, GAMMA_MAX]. | |||
* */ | |||
@@ -35,7 +35,7 @@ | |||
#if HAVE_GIFLIB | |||
#include <gif_lib.h> | |||
enum { MIN_GIF_DELAY = 25 }; | |||
enum { DEF_GIF_DELAY = 75 }; | |||
#endif | |||
float zoom_min; | |||
@@ -85,8 +85,8 @@ void img_init(img_t *img, win_t *win) | |||
img->aa = ANTI_ALIAS; | |||
img->alpha = ALPHA_LAYER; | |||
img->multi.cap = img->multi.cnt = 0; | |||
img->multi.animate = false; | |||
img->multi.length = img->multi.repeat = 0; | |||
img->multi.animate = options->animate; | |||
img->multi.length = 0; | |||
img->cmod = imlib_create_color_modifier(); | |||
img->gamma = MIN(MAX(options->gamma, -GAMMA_RANGE), GAMMA_RANGE); | |||
@@ -160,7 +160,7 @@ bool img_load_gif(img_t *img, const fileinfo_t *file) | |||
s_malloc(sizeof(img_frame_t) * img->multi.cap); | |||
} | |||
img->multi.cnt = img->multi.sel = 0; | |||
img->multi.length = img->multi.repeat = 0; | |||
img->multi.length = 0; | |||
#if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 | |||
gif = DGifOpenFileName(file->path, NULL); | |||
@@ -194,16 +194,7 @@ bool img_load_gif(img_t *img, const fileinfo_t *file) | |||
transp = -1; | |||
delay = 10 * ((unsigned int) ext[3] << 8 | (unsigned int) ext[2]); | |||
if (delay) | |||
delay = MAX(delay, MIN_GIF_DELAY); | |||
disposal = (unsigned int) ext[1] >> 2 & 0x7; | |||
} else if (ext_code == APPLICATION_EXT_FUNC_CODE) { | |||
if (ext[0] == 11 && memcmp(ext+1, "NETSCAPE2.0", 11) == 0) { | |||
DGifGetExtensionNext(gif, &ext); | |||
if (ext && ext[0] == 3 && ext[1] == 1) | |||
img->multi.repeat = ((int) ext[3] << 8 | (int) ext[2]) - 1; | |||
} | |||
} | |||
ext = NULL; | |||
DGifGetExtensionNext(gif, &ext); | |||
@@ -289,7 +280,7 @@ bool img_load_gif(img_t *img, const fileinfo_t *file) | |||
img->multi.cap * sizeof(img_frame_t)); | |||
} | |||
img->multi.frames[img->multi.cnt].im = im; | |||
img->multi.frames[img->multi.cnt].delay = delay ? delay : GIF_DELAY; | |||
img->multi.frames[img->multi.cnt].delay = delay > 0 ? delay : DEF_GIF_DELAY; | |||
img->multi.length += img->multi.frames[img->multi.cnt].delay; | |||
img->multi.cnt++; | |||
} | |||
@@ -308,12 +299,10 @@ bool img_load_gif(img_t *img, const fileinfo_t *file) | |||
imlib_context_set_image(img->im); | |||
imlib_free_image(); | |||
img->im = img->multi.frames[0].im; | |||
img->multi.animate = GIF_AUTOPLAY; | |||
} else if (img->multi.cnt == 1) { | |||
imlib_context_set_image(img->multi.frames[0].im); | |||
imlib_free_image(); | |||
img->multi.cnt = 0; | |||
img->multi.animate = false; | |||
} | |||
imlib_context_set_image(img->im); | |||
@@ -841,21 +830,15 @@ bool img_frame_animate(img_t *img, bool restart) | |||
return false; | |||
if (img->multi.sel + 1 >= img->multi.cnt) { | |||
if (restart || GIF_LOOP == 1) { | |||
img_frame_goto(img, 0); | |||
} else if (GIF_LOOP == -1 && img->multi.repeat != 0) { | |||
if (img->multi.repeat > 0) | |||
img->multi.repeat--; | |||
img_frame_goto(img, 0); | |||
} else { | |||
img->multi.animate = false; | |||
return false; | |||
} | |||
img_frame_goto(img, 0); | |||
img->dirty = true; | |||
return true; | |||
} else if (!restart) { | |||
img_frame_goto(img, img->multi.sel + 1); | |||
img->dirty = true; | |||
return true; | |||
} else { | |||
return false; | |||
} | |||
img->multi.animate = true; | |||
img->dirty = true; | |||
return true; | |||
} | |||
@@ -36,7 +36,6 @@ typedef struct { | |||
int sel; | |||
bool animate; | |||
int length; | |||
int repeat; | |||
} multi_img_t; | |||
typedef struct { | |||
@@ -51,7 +50,6 @@ typedef struct { | |||
scalemode_t scalemode; | |||
float zoom; | |||
bool re; | |||
bool checkpan; | |||
bool dirty; | |||
bool aa; | |||
@@ -33,7 +33,7 @@ const options_t *options = (const options_t*) &_options; | |||
void print_usage(void) | |||
{ | |||
printf("usage: sxiv [-bcfhioqrtvZ] [-G GAMMA] [-g GEOMETRY] [-n NUM] " | |||
printf("usage: sxiv [-abcfhioqrtvZ] [-G GAMMA] [-g GEOMETRY] [-n NUM] " | |||
"[-N NAME] [-S DELAY] [-s MODE] [-z ZOOM] FILES...\n"); | |||
} | |||
@@ -55,6 +55,7 @@ void parse_options(int argc, char **argv) | |||
_options.scalemode = SCALE_DOWN; | |||
_options.zoom = 1.0; | |||
_options.animate = false; | |||
_options.gamma = 0; | |||
_options.slideshow = 0; | |||
@@ -67,11 +68,14 @@ void parse_options(int argc, char **argv) | |||
_options.thumb_mode = false; | |||
_options.clean_cache = false; | |||
while ((opt = getopt(argc, argv, "bcfG:g:hin:N:oqrS:s:tvZz:")) != -1) { | |||
while ((opt = getopt(argc, argv, "abcfG:g:hin:N:oqrS:s:tvZz:")) != -1) { | |||
switch (opt) { | |||
case '?': | |||
print_usage(); | |||
exit(EXIT_FAILURE); | |||
case 'a': | |||
_options.animate = true; | |||
break; | |||
case 'b': | |||
_options.hide_bar = true; | |||
break; | |||
@@ -34,6 +34,7 @@ typedef struct { | |||
/* image: */ | |||
scalemode_t scalemode; | |||
float zoom; | |||
bool animate; | |||
int gamma; | |||
int slideshow; | |||
@@ -3,7 +3,7 @@ | |||
sxiv \- Simple X Image Viewer | |||
.SH SYNOPSIS | |||
.B sxiv | |||
.RB [ \-bcfhioqrtvZ ] | |||
.RB [ \-abcfhioqrtvZ ] | |||
.RB [ \-G | |||
.IR GAMMA ] | |||
.RB [ \-g | |||
@@ -31,6 +31,9 @@ Please note, that the fullscreen mode requires an EWMH/NetWM compliant window | |||
manager. | |||
.SH OPTIONS | |||
.TP | |||
.B \-a | |||
Play animations of multi-frame images. | |||
.TP | |||
.B \-b | |||
Do not show info bar on bottom of window. | |||
.TP | |||
@@ -208,7 +211,7 @@ Go to the next frame of a multi-frame image. | |||
Go to the previous frame of a multi-frame image. | |||
.TP | |||
.B Ctrl-Space | |||
Play/pause animation of a multi-frame image. | |||
Play/stop animations of multi-frame images. | |||
.SS Panning | |||
.TP | |||
.BR h ", " Left | |||