aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBert <ber.t@gmx.com>2011-09-02 04:33:44 +0200
committerBert <ber.t@gmx.com>2011-09-02 04:33:44 +0200
commit1e84773276ede56309a145dc08a4f3d47ad3a29f (patch)
tree44dcbcaa8ae2248e089b74abadce86da1a547a6f
parent391e6e707968a8ee74e88b5e19ba90e799572c93 (diff)
Data driven timeout handling
-rw-r--r--Makefile2
-rw-r--r--commands.c25
-rw-r--r--main.c180
-rw-r--r--types.h8
-rw-r--r--util.c13
-rw-r--r--util.h9
6 files changed, 137 insertions, 100 deletions
diff --git a/Makefile b/Makefile
index ade1b3e..07c577a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
all: sxiv
-VERSION = git-20110819
+VERSION = git-20110902
CC = gcc
DESTDIR =
diff --git a/commands.c b/commands.c
index 51f7a55..123d4f5 100644
--- a/commands.c
+++ b/commands.c
@@ -30,6 +30,11 @@
void cleanup();
void remove_file(int, unsigned char);
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 img_t img;
@@ -39,10 +44,6 @@ extern win_t win;
extern fileinfo_t *files;
extern int filecnt, fileidx;
-extern int timo_cursor;
-extern int timo_redraw;
-extern int timo_adelay;
-
int it_quit(arg_t a) {
cleanup();
exit(0);
@@ -54,12 +55,11 @@ int it_switch_mode(arg_t a) {
tns_init(&tns, filecnt);
img_close(&img, 0);
win_set_cursor(&win, CURSOR_ARROW);
- timo_cursor = 0;
+ reset_timeout(hide_cursor);
tns.sel = fileidx;
tns.dirty = 1;
mode = MODE_THUMB;
} else {
- timo_cursor = TO_CURSOR_HIDE;
load_image(tns.sel);
mode = MODE_IMAGE;
}
@@ -68,11 +68,11 @@ int it_switch_mode(arg_t a) {
int it_toggle_fullscreen(arg_t a) {
win_toggle_fullscreen(&win);
+ set_timeout(redraw, TO_REDRAW_RESIZE, 0);
if (mode == MODE_IMAGE)
img.checkpan = 1;
else
tns.dirty = 1;
- timo_redraw = TO_WIN_RESIZE;
return 0;
}
@@ -156,15 +156,18 @@ int i_navigate_frame(arg_t a) {
}
int i_toggle_animation(arg_t a) {
+ int delay;
+
if (mode != MODE_IMAGE)
return 0;
if (img.multi.animate) {
- timo_adelay = 0;
+ reset_timeout(animate);
img.multi.animate = 0;
return 0;
} else {
- timo_adelay = img_frame_animate(&img, 1);
+ delay = img_frame_animate(&img, 1);
+ set_timeout(animate, delay, 1);
return 1;
}
}
@@ -245,8 +248,8 @@ int i_drag(arg_t a) {
}
win_set_cursor(&win, CURSOR_ARROW);
- timo_cursor = TO_CURSOR_HIDE;
- timo_redraw = 0;
+ set_timeout(hide_cursor, TO_CURSOR_HIDE, 1);
+ reset_timeout(redraw);
return 0;
}
diff --git a/main.c b/main.c
index 6545cfb..5866823 100644
--- a/main.c
+++ b/main.c
@@ -41,6 +41,17 @@ enum {
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;
img_t img;
tns_t tns;
@@ -52,9 +63,11 @@ size_t filesize;
char win_title[TITLE_LEN];
-int timo_cursor;
-int timo_redraw;
-int timo_adelay; /* multi-frame animation delay time */
+timeout_t timeouts[] = {
+ { { 0, 0 }, False, redraw },
+ { { 0, 0 }, False, hide_cursor },
+ { { 0, 0 }, False, animate }
+};
void cleanup() {
static int in = 0;
@@ -120,6 +133,54 @@ void remove_file(int n, unsigned char silent) {
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) {
struct stat fstats;
@@ -144,9 +205,9 @@ void load_image(int new) {
if (img.multi.cnt) {
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
- timo_adelay = 0;
+ reset_timeout(animate);
}
}
@@ -186,15 +247,31 @@ void update_title() {
void redraw() {
if (mode == MODE_IMAGE) {
img_render(&img, &win);
- if (timo_cursor)
- win_set_cursor(&win, CURSOR_ARROW);
- else
+ if (img.multi.animate) {
win_set_cursor(&win, CURSOR_NONE);
+ } else {
+ win_set_cursor(&win, CURSOR_ARROW);
+ set_timeout(hide_cursor, TO_CURSOR_HIDE, 1);
+ }
} else {
tns_render(&tns, &win);
}
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) {
@@ -233,7 +310,7 @@ void on_buttonpress(XButtonEvent *bev) {
if (mode == MODE_IMAGE) {
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++) {
if (buttons[i].button == bev->button &&
@@ -252,7 +329,7 @@ void on_buttonpress(XButtonEvent *bev) {
if (sel == tns.sel) {
load_image(tns.sel);
mode = MODE_IMAGE;
- timo_cursor = TO_CURSOR_HIDE;
+ set_timeout(hide_cursor, TO_CURSOR_HIDE, 1);
} else {
tns_highlight(&tns, &win, tns.sel, False);
tns_highlight(&tns, &win, sel, True);
@@ -272,75 +349,39 @@ void on_buttonpress(XButtonEvent *bev) {
}
void run() {
- int xfd, timeout;
+ int xfd;
fd_set fds;
- struct timeval tt, t0, t1;
+ struct timeval timeout;
XEvent ev;
- timo_cursor = mode == MODE_IMAGE ? TO_CURSOR_HIDE : 0;
-
redraw();
while (1) {
- if (mode == MODE_THUMB && tns.cnt < filecnt) {
+ if (!XPending(win.env.dpy)) {
/* load thumbnails */
- win_set_cursor(&win, CURSOR_WATCH);
- gettimeofday(&t0, 0);
-
- while (tns.cnt < filecnt && !XPending(win.env.dpy)) {
+ while (mode == MODE_THUMB && tns.cnt < filecnt) {
+ win_set_cursor(&win, CURSOR_WATCH);
if (tns_load(&tns, tns.cnt, &files[tns.cnt], False, False))
tns.cnt++;
else
remove_file(tns.cnt, 0);
- gettimeofday(&t1, 0);
- 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)
+ if (tns.cnt == filecnt) {
redraw();
- }
- if (timo_adelay) {
- timo_adelay = MAX(0, timo_adelay - timeout);
- if (!timo_adelay) {
- if ((timo_adelay = img_frame_animate(&img, 0)))
- redraw();
+ win_set_cursor(&win, CURSOR_ARROW);
+ } else {
+ set_timeout(redraw, TO_REDRAW_THUMBS, 0);
+ check_timeouts(NULL);
}
}
- if ((timo_cursor || timo_redraw || timo_adelay) &&
- !XPending(win.env.dpy))
- continue;
+
+ /* handle timeouts */
+ if (check_timeouts(&timeout)) {
+ 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)) {
@@ -355,7 +396,7 @@ void run() {
break;
case ConfigureNotify:
if (win_configure(&win, &ev.xconfigure)) {
- timo_redraw = TO_WIN_RESIZE;
+ set_timeout(redraw, TO_REDRAW_RESIZE, 0);
if (mode == MODE_IMAGE)
img.checkpan = 1;
else
@@ -366,9 +407,10 @@ void run() {
on_keypress(&ev.xkey);
break;
case MotionNotify:
- if (!timo_cursor)
+ if (mode == MODE_IMAGE) {
win_set_cursor(&win, CURSOR_ARROW);
- timo_cursor = TO_CURSOR_HIDE;
+ set_timeout(hide_cursor, TO_CURSOR_HIDE, 1);
+ }
break;
}
}
diff --git a/types.h b/types.h
index f19d693..bf8d4e2 100644
--- a/types.h
+++ b/types.h
@@ -33,9 +33,11 @@ typedef struct {
/* timeouts in milliseconds: */
enum {
- TO_WIN_RESIZE = 75,
- TO_CURSOR_HIDE = 1500,
- TO_THUMBS_LOAD = 200
+ TO_REDRAW_RESIZE = 75,
+ TO_REDRAW_THUMBS = 200,
+ TO_CURSOR_HIDE = 1500
};
+typedef void (*timeout_f)(void);
+
#endif /* TYPES_H */
diff --git a/util.c b/util.c
index 5bed511..0c4574e 100644
--- a/util.c
+++ b/util.c
@@ -87,19 +87,6 @@ void die(const char* fmt, ...) {
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) {
const char *units[] = { "", "K", "M", "G" };
int i;
diff --git a/util.h b/util.h
index a891054..19ebcd7 100644
--- a/util.h
+++ b/util.h
@@ -33,7 +33,12 @@
#define MSEC_TO_TIMEVAL(t,tv) { \
(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
@@ -60,8 +65,6 @@ char* s_strdup(char*);
void warn(const char*, ...);
void die(const char*, ...);
-int min_int_nz(int, ...);
-
void size_readable(float*, const char**);
char* absolute_path(const char*);