ソースを参照

Data driven timeout handling

master
Bert 13年前
コミット
1e84773276
6個のファイルの変更137行の追加100行の削除
  1. +1
    -1
      Makefile
  2. +14
    -11
      commands.c
  3. +111
    -69
      main.c
  4. +5
    -3
      types.h
  5. +0
    -13
      util.c
  6. +6
    -3
      util.h

+ 1
- 1
Makefile ファイルの表示

@@ -1,6 +1,6 @@
all: sxiv all: sxiv


VERSION = git-20110819 VERSION = git-20110902


CC = gcc CC = gcc
DESTDIR = DESTDIR =


+ 14
- 11
commands.c ファイルの表示

@@ -30,6 +30,11 @@
void cleanup(); void cleanup();
void remove_file(int, unsigned char); void remove_file(int, unsigned char);
void load_image(int); void load_image(int);
void redraw();
void hide_cursor();
void animate();
void set_timeout(timeout_f, int, int);
void reset_timeout(timeout_f);


extern appmode_t mode; extern appmode_t mode;
extern img_t img; extern img_t img;
@@ -39,10 +44,6 @@ extern win_t win;
extern fileinfo_t *files; extern fileinfo_t *files;
extern int filecnt, fileidx; extern int filecnt, fileidx;


extern int timo_cursor;
extern int timo_redraw;
extern int timo_adelay;

int it_quit(arg_t a) { int it_quit(arg_t a) {
cleanup(); cleanup();
exit(0); exit(0);
@@ -54,12 +55,11 @@ int it_switch_mode(arg_t a) {
tns_init(&tns, filecnt); tns_init(&tns, filecnt);
img_close(&img, 0); img_close(&img, 0);
win_set_cursor(&win, CURSOR_ARROW); win_set_cursor(&win, CURSOR_ARROW);
timo_cursor = 0; reset_timeout(hide_cursor);
tns.sel = fileidx; tns.sel = fileidx;
tns.dirty = 1; tns.dirty = 1;
mode = MODE_THUMB; mode = MODE_THUMB;
} else { } else {
timo_cursor = TO_CURSOR_HIDE;
load_image(tns.sel); load_image(tns.sel);
mode = MODE_IMAGE; mode = MODE_IMAGE;
} }
@@ -68,11 +68,11 @@ int it_switch_mode(arg_t a) {


int it_toggle_fullscreen(arg_t a) { int it_toggle_fullscreen(arg_t a) {
win_toggle_fullscreen(&win); win_toggle_fullscreen(&win);
set_timeout(redraw, TO_REDRAW_RESIZE, 0);
if (mode == MODE_IMAGE) if (mode == MODE_IMAGE)
img.checkpan = 1; img.checkpan = 1;
else else
tns.dirty = 1; tns.dirty = 1;
timo_redraw = TO_WIN_RESIZE;
return 0; return 0;
} }


@@ -156,15 +156,18 @@ int i_navigate_frame(arg_t a) {
} }


int i_toggle_animation(arg_t a) { int i_toggle_animation(arg_t a) {
int delay;

if (mode != MODE_IMAGE) if (mode != MODE_IMAGE)
return 0; return 0;


if (img.multi.animate) { if (img.multi.animate) {
timo_adelay = 0; reset_timeout(animate);
img.multi.animate = 0; img.multi.animate = 0;
return 0; return 0;
} else { } else {
timo_adelay = img_frame_animate(&img, 1); delay = img_frame_animate(&img, 1);
set_timeout(animate, delay, 1);
return 1; return 1;
} }
} }
@@ -245,8 +248,8 @@ int i_drag(arg_t a) {
} }
win_set_cursor(&win, CURSOR_ARROW); win_set_cursor(&win, CURSOR_ARROW);
timo_cursor = TO_CURSOR_HIDE; set_timeout(hide_cursor, TO_CURSOR_HIDE, 1);
timo_redraw = 0; reset_timeout(redraw);


return 0; return 0;
} }


+ 111
- 69
main.c ファイルの表示

@@ -41,6 +41,17 @@ enum {
FNAME_CNT = 1024 FNAME_CNT = 1024
}; };


typedef struct {
struct timeval when;
Bool active;
timeout_f handler;
} timeout_t;

/* timeout handler functions: */
void redraw();
void hide_cursor();
void animate();

appmode_t mode; appmode_t mode;
img_t img; img_t img;
tns_t tns; tns_t tns;
@@ -52,9 +63,11 @@ size_t filesize;


char win_title[TITLE_LEN]; char win_title[TITLE_LEN];


int timo_cursor; timeout_t timeouts[] = {
int timo_redraw; { { 0, 0 }, False, redraw },
int timo_adelay; /* multi-frame animation delay time */ { { 0, 0 }, False, hide_cursor },
{ { 0, 0 }, False, animate }
};


void cleanup() { void cleanup() {
static int in = 0; static int in = 0;
@@ -120,6 +133,54 @@ void remove_file(int n, unsigned char silent) {
tns.cnt--; tns.cnt--;
} }


void set_timeout(timeout_f handler, int time, int overwrite) {
int i;

for (i = 0; i < LEN(timeouts); i++) {
if (timeouts[i].handler == handler) {
if (!timeouts[i].active || overwrite) {
gettimeofday(&timeouts[i].when, 0);
MSEC_ADD_TO_TIMEVAL(time, &timeouts[i].when);
timeouts[i].active = True;
}
return;
}
}
}

void reset_timeout(timeout_f handler) {
int i;

for (i = 0; i < LEN(timeouts); i++) {
if (timeouts[i].handler == handler) {
timeouts[i].active = False;
return;
}
}
}

int check_timeouts(struct timeval *t) {
int i, tdiff, tmin = -1;
struct timeval now;

gettimeofday(&now, 0);
for (i = 0; i < LEN(timeouts); i++) {
if (timeouts[i].active) {
tdiff = TIMEDIFF(&timeouts[i].when, &now);
if (tdiff <= 0) {
timeouts[i].active = False;
if (timeouts[i].handler)
timeouts[i].handler();
} else if (tmin < 0 || tdiff < tmin) {
tmin = tdiff;
}
}
}
if (tmin > 0 && t)
MSEC_TO_TIMEVAL(tmin, t);
return tmin > 0;
}

void load_image(int new) { void load_image(int new) {
struct stat fstats; struct stat fstats;


@@ -144,9 +205,9 @@ void load_image(int new) {


if (img.multi.cnt) { if (img.multi.cnt) {
if (img.multi.animate) if (img.multi.animate)
timo_adelay = img.multi.frames[img.multi.sel].delay; set_timeout(animate, img.multi.frames[img.multi.sel].delay, 1);
else else
timo_adelay = 0; reset_timeout(animate);
} }
} }


@@ -186,15 +247,31 @@ void update_title() {
void redraw() { void redraw() {
if (mode == MODE_IMAGE) { if (mode == MODE_IMAGE) {
img_render(&img, &win); img_render(&img, &win);
if (timo_cursor) if (img.multi.animate) {
win_set_cursor(&win, CURSOR_ARROW);
else
win_set_cursor(&win, CURSOR_NONE); win_set_cursor(&win, CURSOR_NONE);
} else {
win_set_cursor(&win, CURSOR_ARROW);
set_timeout(hide_cursor, TO_CURSOR_HIDE, 1);
}
} else { } else {
tns_render(&tns, &win); tns_render(&tns, &win);
} }
update_title(); update_title();
timo_redraw = 0; reset_timeout(redraw);
}

void hide_cursor() {
win_set_cursor(&win, CURSOR_NONE);
}

void animate() {
int delay;

delay = img_frame_animate(&img, 0);
if (delay) {
set_timeout(animate, delay, 1);
redraw();
}
} }


Bool keymask(const keymap_t *k, unsigned int state) { Bool keymask(const keymap_t *k, unsigned int state) {
@@ -233,7 +310,7 @@ void on_buttonpress(XButtonEvent *bev) {


if (mode == MODE_IMAGE) { if (mode == MODE_IMAGE) {
win_set_cursor(&win, CURSOR_ARROW); win_set_cursor(&win, CURSOR_ARROW);
timo_cursor = TO_CURSOR_HIDE; set_timeout(hide_cursor, TO_CURSOR_HIDE, 1);


for (i = 0; i < LEN(buttons); i++) { for (i = 0; i < LEN(buttons); i++) {
if (buttons[i].button == bev->button && if (buttons[i].button == bev->button &&
@@ -252,7 +329,7 @@ void on_buttonpress(XButtonEvent *bev) {
if (sel == tns.sel) { if (sel == tns.sel) {
load_image(tns.sel); load_image(tns.sel);
mode = MODE_IMAGE; mode = MODE_IMAGE;
timo_cursor = TO_CURSOR_HIDE; set_timeout(hide_cursor, TO_CURSOR_HIDE, 1);
} else { } else {
tns_highlight(&tns, &win, tns.sel, False); tns_highlight(&tns, &win, tns.sel, False);
tns_highlight(&tns, &win, sel, True); tns_highlight(&tns, &win, sel, True);
@@ -272,75 +349,39 @@ void on_buttonpress(XButtonEvent *bev) {
} }


void run() { void run() {
int xfd, timeout; int xfd;
fd_set fds; fd_set fds;
struct timeval tt, t0, t1; struct timeval timeout;
XEvent ev; XEvent ev;


timo_cursor = mode == MODE_IMAGE ? TO_CURSOR_HIDE : 0;

redraw(); redraw();


while (1) { while (1) {
if (mode == MODE_THUMB && tns.cnt < filecnt) { if (!XPending(win.env.dpy)) {
/* load thumbnails */ /* load thumbnails */
win_set_cursor(&win, CURSOR_WATCH); while (mode == MODE_THUMB && tns.cnt < filecnt) {
gettimeofday(&t0, 0); win_set_cursor(&win, CURSOR_WATCH);

while (tns.cnt < filecnt && !XPending(win.env.dpy)) {
if (tns_load(&tns, tns.cnt, &files[tns.cnt], False, False)) if (tns_load(&tns, tns.cnt, &files[tns.cnt], False, False))
tns.cnt++; tns.cnt++;
else else
remove_file(tns.cnt, 0); remove_file(tns.cnt, 0);
gettimeofday(&t1, 0); if (tns.cnt == filecnt) {
if (TIMEDIFF(&t1, &t0) >= TO_THUMBS_LOAD)
break;
}
if (tns.cnt == filecnt)
win_set_cursor(&win, CURSOR_ARROW);
if (!XPending(win.env.dpy)) {
redraw();
continue;
} else {
timo_redraw = TO_THUMBS_LOAD;
}
}
if (timo_cursor || timo_redraw || timo_adelay) {
/* check active timeouts */
gettimeofday(&t0, 0);
timeout = min_int_nz(3, timo_cursor, timo_redraw, timo_adelay);
MSEC_TO_TIMEVAL(timeout, &tt);
xfd = ConnectionNumber(win.env.dpy);
FD_ZERO(&fds);
FD_SET(xfd, &fds);

if (!XPending(win.env.dpy))
select(xfd + 1, &fds, 0, 0, &tt);
gettimeofday(&t1, 0);
timeout = MIN(TIMEDIFF(&t1, &t0), timeout);

/* timeouts fired? */
if (timo_cursor) {
timo_cursor = MAX(0, timo_cursor - timeout);
if (!timo_cursor)
win_set_cursor(&win, CURSOR_NONE);
}
if (timo_redraw) {
timo_redraw = MAX(0, timo_redraw - timeout);
if (!timo_redraw)
redraw(); redraw();
} win_set_cursor(&win, CURSOR_ARROW);
if (timo_adelay) { } else {
timo_adelay = MAX(0, timo_adelay - timeout); set_timeout(redraw, TO_REDRAW_THUMBS, 0);
if (!timo_adelay) { check_timeouts(NULL);
if ((timo_adelay = img_frame_animate(&img, 0)))
redraw();
} }
} }
if ((timo_cursor || timo_redraw || timo_adelay) && /* handle timeouts */
!XPending(win.env.dpy)) if (check_timeouts(&timeout)) {
continue; xfd = ConnectionNumber(win.env.dpy);
FD_ZERO(&fds);
FD_SET(xfd, &fds);
if (!select(xfd + 1, &fds, 0, 0, &timeout))
check_timeouts(NULL);
}
} }


if (!XNextEvent(win.env.dpy, &ev)) { if (!XNextEvent(win.env.dpy, &ev)) {
@@ -355,7 +396,7 @@ void run() {
break; break;
case ConfigureNotify: case ConfigureNotify:
if (win_configure(&win, &ev.xconfigure)) { if (win_configure(&win, &ev.xconfigure)) {
timo_redraw = TO_WIN_RESIZE; set_timeout(redraw, TO_REDRAW_RESIZE, 0);
if (mode == MODE_IMAGE) if (mode == MODE_IMAGE)
img.checkpan = 1; img.checkpan = 1;
else else
@@ -366,9 +407,10 @@ void run() {
on_keypress(&ev.xkey); on_keypress(&ev.xkey);
break; break;
case MotionNotify: case MotionNotify:
if (!timo_cursor) if (mode == MODE_IMAGE) {
win_set_cursor(&win, CURSOR_ARROW); win_set_cursor(&win, CURSOR_ARROW);
timo_cursor = TO_CURSOR_HIDE; set_timeout(hide_cursor, TO_CURSOR_HIDE, 1);
}
break; break;
} }
} }


+ 5
- 3
types.h ファイルの表示

@@ -33,9 +33,11 @@ typedef struct {


/* timeouts in milliseconds: */ /* timeouts in milliseconds: */
enum { enum {
TO_WIN_RESIZE = 75, TO_REDRAW_RESIZE = 75,
TO_CURSOR_HIDE = 1500, TO_REDRAW_THUMBS = 200,
TO_THUMBS_LOAD = 200 TO_CURSOR_HIDE = 1500
}; };


typedef void (*timeout_f)(void);

#endif /* TYPES_H */ #endif /* TYPES_H */

+ 0
- 13
util.c ファイルの表示

@@ -87,19 +87,6 @@ void die(const char* fmt, ...) {
exit(1); exit(1);
} }


int min_int_nz(int n, ...) {
va_list args;
int i, a, m = 0;

va_start(args, n);
for (i = 0; i < n; i++) {
if ((a = va_arg(args, int)) && (!m || a < m))
m = a;
}
va_end(args);
return m;
}

void size_readable(float *size, const char **unit) { void size_readable(float *size, const char **unit) {
const char *units[] = { "", "K", "M", "G" }; const char *units[] = { "", "K", "M", "G" };
int i; int i;


+ 6
- 3
util.h ファイルの表示

@@ -33,7 +33,12 @@


#define MSEC_TO_TIMEVAL(t,tv) { \ #define MSEC_TO_TIMEVAL(t,tv) { \
(tv)->tv_sec = (t) / 1000; \ (tv)->tv_sec = (t) / 1000; \
(tv)->tv_usec = (t) % 1000 * 1000; \ (tv)->tv_usec = (t) % 1000 * 1000; \
}

#define MSEC_ADD_TO_TIMEVAL(t,tv) { \
(tv)->tv_sec += (t) / 1000; \
(tv)->tv_usec += (t) % 1000 * 1000; \
} }


#ifndef TIMESPEC_TO_TIMEVAL #ifndef TIMESPEC_TO_TIMEVAL
@@ -60,8 +65,6 @@ char* s_strdup(char*);
void warn(const char*, ...); void warn(const char*, ...);
void die(const char*, ...); void die(const char*, ...);


int min_int_nz(int, ...);

void size_readable(float*, const char**); void size_readable(float*, const char**);


char* absolute_path(const char*); char* absolute_path(const char*);


||||||
x
 
000:0
読み込み中…
キャンセル
保存