Krolyxon
Commit 1e84773

Branches

Refs →

nsxiv1e84773

Data driven timeout handling

Author
Bert
Date
2011-09-02 04:33 +0200
Parent
391e6e7
Commit
1e84773276ede56309a145dc08a4f3d47ad3a29f

+137 −100

6 files changed

  1. M Makefile +1 −1
  2. M commands.c +14 −11
  3. M main.c +111 −69
  4. M types.h +5 −3
  5. M util.c +0 −13
  6. M util.h +6 −3
M Makefile View
@@ -1,6 +1,6 @@
11 all: sxiv
22
3−VERSION = git-20110819
3+VERSION = git-20110902
44
55 CC = gcc
66 DESTDIR =
M commands.c View
@@ -30,6 +30,11 @@
3030 void cleanup();
3131 void remove_file(int, unsigned char);
3232 void load_image(int);
33+void redraw();
34+void hide_cursor();
35+void animate();
36+void set_timeout(timeout_f, int, int);
37+void reset_timeout(timeout_f);
3338
3439 extern appmode_t mode;
3540 extern img_t img;
@@ -39,10 +44,6 @@ extern win_t win;
3944 extern fileinfo_t *files;
4045 extern int filecnt, fileidx;
4146
42−extern int timo_cursor;
43−extern int timo_redraw;
44−extern int timo_adelay;
45−
4647 int it_quit(arg_t a) {
4748 cleanup();
4849 exit(0);
@@ -54,12 +55,11 @@ int it_switch_mode(arg_t a) {
5455 tns_init(&tns, filecnt);
5556 img_close(&img, 0);
5657 win_set_cursor(&win, CURSOR_ARROW);
57− timo_cursor = 0;
58+ reset_timeout(hide_cursor);
5859 tns.sel = fileidx;
5960 tns.dirty = 1;
6061 mode = MODE_THUMB;
6162 } else {
62− timo_cursor = TO_CURSOR_HIDE;
6363 load_image(tns.sel);
6464 mode = MODE_IMAGE;
6565 }
@@ -68,11 +68,11 @@ int it_switch_mode(arg_t a) {
6868
6969 int it_toggle_fullscreen(arg_t a) {
7070 win_toggle_fullscreen(&win);
71+ set_timeout(redraw, TO_REDRAW_RESIZE, 0);
7172 if (mode == MODE_IMAGE)
7273 img.checkpan = 1;
7374 else
7475 tns.dirty = 1;
75− timo_redraw = TO_WIN_RESIZE;
7676 return 0;
7777 }
7878
@@ -156,15 +156,18 @@ int i_navigate_frame(arg_t a) {
156156 }
157157
158158 int i_toggle_animation(arg_t a) {
159+ int delay;
160+
159161 if (mode != MODE_IMAGE)
160162 return 0;
161163
162164 if (img.multi.animate) {
163− timo_adelay = 0;
165+ reset_timeout(animate);
164166 img.multi.animate = 0;
165167 return 0;
166168 } else {
167− timo_adelay = img_frame_animate(&img, 1);
169+ delay = img_frame_animate(&img, 1);
170+ set_timeout(animate, delay, 1);
168171 return 1;
169172 }
170173 }
@@ -245,8 +248,8 @@ int i_drag(arg_t a) {
245248 }
246249
247250 win_set_cursor(&win, CURSOR_ARROW);
248− timo_cursor = TO_CURSOR_HIDE;
249− timo_redraw = 0;
251+ set_timeout(hide_cursor, TO_CURSOR_HIDE, 1);
252+ reset_timeout(redraw);
250253
251254 return 0;
252255 }
M main.c View
@@ -41,6 +41,17 @@ enum {
4141 FNAME_CNT = 1024
4242 };
4343
44+typedef struct {
45+ struct timeval when;
46+ Bool active;
47+ timeout_f handler;
48+} timeout_t;
49+
50+/* timeout handler functions: */
51+void redraw();
52+void hide_cursor();
53+void animate();
54+
4455 appmode_t mode;
4556 img_t img;
4657 tns_t tns;
@@ -52,9 +63,11 @@ size_t filesize;
5263
5364 char win_title[TITLE_LEN];
5465
55−int timo_cursor;
56−int timo_redraw;
57−int timo_adelay; /* multi-frame animation delay time */
66+timeout_t timeouts[] = {
67+ { { 0, 0 }, False, redraw },
68+ { { 0, 0 }, False, hide_cursor },
69+ { { 0, 0 }, False, animate }
70+};
5871
5972 void cleanup() {
6073 static int in = 0;
@@ -120,6 +133,54 @@ void remove_file(int n, unsigned char silent) {
120133 tns.cnt--;
121134 }
122135
136+void set_timeout(timeout_f handler, int time, int overwrite) {
137+ int i;
138+
139+ for (i = 0; i < LEN(timeouts); i++) {
140+ if (timeouts[i].handler == handler) {
141+ if (!timeouts[i].active || overwrite) {
142+ gettimeofday(&timeouts[i].when, 0);
143+ MSEC_ADD_TO_TIMEVAL(time, &timeouts[i].when);
144+ timeouts[i].active = True;
145+ }
146+ return;
147+ }
148+ }
149+}
150+
151+void reset_timeout(timeout_f handler) {
152+ int i;
153+
154+ for (i = 0; i < LEN(timeouts); i++) {
155+ if (timeouts[i].handler == handler) {
156+ timeouts[i].active = False;
157+ return;
158+ }
159+ }
160+}
161+
162+int check_timeouts(struct timeval *t) {
163+ int i, tdiff, tmin = -1;
164+ struct timeval now;
165+
166+ gettimeofday(&now, 0);
167+ for (i = 0; i < LEN(timeouts); i++) {
168+ if (timeouts[i].active) {
169+ tdiff = TIMEDIFF(&timeouts[i].when, &now);
170+ if (tdiff <= 0) {
171+ timeouts[i].active = False;
172+ if (timeouts[i].handler)
173+ timeouts[i].handler();
174+ } else if (tmin < 0 || tdiff < tmin) {
175+ tmin = tdiff;
176+ }
177+ }
178+ }
179+ if (tmin > 0 && t)
180+ MSEC_TO_TIMEVAL(tmin, t);
181+ return tmin > 0;
182+}
183+
123184 void load_image(int new) {
124185 struct stat fstats;
125186
@@ -144,9 +205,9 @@ void load_image(int new) {
144205
145206 if (img.multi.cnt) {
146207 if (img.multi.animate)
147− timo_adelay = img.multi.frames[img.multi.sel].delay;
208+ set_timeout(animate, img.multi.frames[img.multi.sel].delay, 1);
148209 else
149− timo_adelay = 0;
210+ reset_timeout(animate);
150211 }
151212 }
152213
@@ -186,15 +247,31 @@ void update_title() {
186247 void redraw() {
187248 if (mode == MODE_IMAGE) {
188249 img_render(&img, &win);
189− if (timo_cursor)
190− win_set_cursor(&win, CURSOR_ARROW);
191− else
250+ if (img.multi.animate) {
192251 win_set_cursor(&win, CURSOR_NONE);
252+ } else {
253+ win_set_cursor(&win, CURSOR_ARROW);
254+ set_timeout(hide_cursor, TO_CURSOR_HIDE, 1);
255+ }
193256 } else {
194257 tns_render(&tns, &win);
195258 }
196259 update_title();
197− timo_redraw = 0;
260+ reset_timeout(redraw);
261+}
262+
263+void hide_cursor() {
264+ win_set_cursor(&win, CURSOR_NONE);
265+}
266+
267+void animate() {
268+ int delay;
269+
270+ delay = img_frame_animate(&img, 0);
271+ if (delay) {
272+ set_timeout(animate, delay, 1);
273+ redraw();
274+ }
198275 }
199276
200277 Bool keymask(const keymap_t *k, unsigned int state) {
@@ -233,7 +310,7 @@ void on_buttonpress(XButtonEvent *bev) {
233310
234311 if (mode == MODE_IMAGE) {
235312 win_set_cursor(&win, CURSOR_ARROW);
236− timo_cursor = TO_CURSOR_HIDE;
313+ set_timeout(hide_cursor, TO_CURSOR_HIDE, 1);
237314
238315 for (i = 0; i < LEN(buttons); i++) {
239316 if (buttons[i].button == bev->button &&
@@ -252,7 +329,7 @@ void on_buttonpress(XButtonEvent *bev) {
252329 if (sel == tns.sel) {
253330 load_image(tns.sel);
254331 mode = MODE_IMAGE;
255− timo_cursor = TO_CURSOR_HIDE;
332+ set_timeout(hide_cursor, TO_CURSOR_HIDE, 1);
256333 } else {
257334 tns_highlight(&tns, &win, tns.sel, False);
258335 tns_highlight(&tns, &win, sel, True);
@@ -272,75 +349,39 @@ void on_buttonpress(XButtonEvent *bev) {
272349 }
273350
274351 void run() {
275− int xfd, timeout;
352+ int xfd;
276353 fd_set fds;
277− struct timeval tt, t0, t1;
354+ struct timeval timeout;
278355 XEvent ev;
279356
280− timo_cursor = mode == MODE_IMAGE ? TO_CURSOR_HIDE : 0;
281−
282357 redraw();
283358
284359 while (1) {
285− if (mode == MODE_THUMB && tns.cnt < filecnt) {
360+ if (!XPending(win.env.dpy)) {
286361 /* load thumbnails */
287− win_set_cursor(&win, CURSOR_WATCH);
288− gettimeofday(&t0, 0);
289−
290− while (tns.cnt < filecnt && !XPending(win.env.dpy)) {
362+ while (mode == MODE_THUMB && tns.cnt < filecnt) {
363+ win_set_cursor(&win, CURSOR_WATCH);
291364 if (tns_load(&tns, tns.cnt, &files[tns.cnt], False, False))
292365 tns.cnt++;
293366 else
294367 remove_file(tns.cnt, 0);
295− gettimeofday(&t1, 0);
296− if (TIMEDIFF(&t1, &t0) >= TO_THUMBS_LOAD)
297− break;
298− }
299− if (tns.cnt == filecnt)
300− win_set_cursor(&win, CURSOR_ARROW);
301− if (!XPending(win.env.dpy)) {
302− redraw();
303− continue;
304− } else {
305− timo_redraw = TO_THUMBS_LOAD;
306− }
307− }
308−
309− if (timo_cursor || timo_redraw || timo_adelay) {
310− /* check active timeouts */
311− gettimeofday(&t0, 0);
312− timeout = min_int_nz(3, timo_cursor, timo_redraw, timo_adelay);
313− MSEC_TO_TIMEVAL(timeout, &tt);
314− xfd = ConnectionNumber(win.env.dpy);
315− FD_ZERO(&fds);
316− FD_SET(xfd, &fds);
317−
318− if (!XPending(win.env.dpy))
319− select(xfd + 1, &fds, 0, 0, &tt);
320− gettimeofday(&t1, 0);
321− timeout = MIN(TIMEDIFF(&t1, &t0), timeout);
322−
323− /* timeouts fired? */
324− if (timo_cursor) {
325− timo_cursor = MAX(0, timo_cursor - timeout);
326− if (!timo_cursor)
327− win_set_cursor(&win, CURSOR_NONE);
328− }
329− if (timo_redraw) {
330− timo_redraw = MAX(0, timo_redraw - timeout);
331− if (!timo_redraw)
368+ if (tns.cnt == filecnt) {
332369 redraw();
333− }
334− if (timo_adelay) {
335− timo_adelay = MAX(0, timo_adelay - timeout);
336− if (!timo_adelay) {
337− if ((timo_adelay = img_frame_animate(&img, 0)))
338− redraw();
370+ win_set_cursor(&win, CURSOR_ARROW);
371+ } else {
372+ set_timeout(redraw, TO_REDRAW_THUMBS, 0);
373+ check_timeouts(NULL);
339374 }
340375 }
341− if ((timo_cursor || timo_redraw || timo_adelay) &&
342− !XPending(win.env.dpy))
343− continue;
376+
377+ /* handle timeouts */
378+ if (check_timeouts(&timeout)) {
379+ xfd = ConnectionNumber(win.env.dpy);
380+ FD_ZERO(&fds);
381+ FD_SET(xfd, &fds);
382+ if (!select(xfd + 1, &fds, 0, 0, &timeout))
383+ check_timeouts(NULL);
384+ }
344385 }
345386
346387 if (!XNextEvent(win.env.dpy, &ev)) {
@@ -355,7 +396,7 @@ void run() {
355396 break;
356397 case ConfigureNotify:
357398 if (win_configure(&win, &ev.xconfigure)) {
358− timo_redraw = TO_WIN_RESIZE;
399+ set_timeout(redraw, TO_REDRAW_RESIZE, 0);
359400 if (mode == MODE_IMAGE)
360401 img.checkpan = 1;
361402 else
@@ -366,9 +407,10 @@ void run() {
366407 on_keypress(&ev.xkey);
367408 break;
368409 case MotionNotify:
369− if (!timo_cursor)
410+ if (mode == MODE_IMAGE) {
370411 win_set_cursor(&win, CURSOR_ARROW);
371− timo_cursor = TO_CURSOR_HIDE;
412+ set_timeout(hide_cursor, TO_CURSOR_HIDE, 1);
413+ }
372414 break;
373415 }
374416 }
M types.h View
@@ -33,9 +33,11 @@ typedef struct {
3333
3434 /* timeouts in milliseconds: */
3535 enum {
36− TO_WIN_RESIZE = 75,
37− TO_CURSOR_HIDE = 1500,
38− TO_THUMBS_LOAD = 200
36+ TO_REDRAW_RESIZE = 75,
37+ TO_REDRAW_THUMBS = 200,
38+ TO_CURSOR_HIDE = 1500
3939 };
4040
41+typedef void (*timeout_f)(void);
42+
4143 #endif /* TYPES_H */
M util.c View
@@ -87,19 +87,6 @@ void die(const char* fmt, ...) {
8787 exit(1);
8888 }
8989
90−int min_int_nz(int n, ...) {
91− va_list args;
92− int i, a, m = 0;
93−
94− va_start(args, n);
95− for (i = 0; i < n; i++) {
96− if ((a = va_arg(args, int)) && (!m || a < m))
97− m = a;
98− }
99− va_end(args);
100− return m;
101−}
102−
10390 void size_readable(float *size, const char **unit) {
10491 const char *units[] = { "", "K", "M", "G" };
10592 int i;
M util.h View
@@ -33,7 +33,12 @@
3333
3434 #define MSEC_TO_TIMEVAL(t,tv) { \
3535 (tv)->tv_sec = (t) / 1000; \
36− (tv)->tv_usec = (t) % 1000 * 1000; \
36+ (tv)->tv_usec = (t) % 1000 * 1000; \
37+}
38+
39+#define MSEC_ADD_TO_TIMEVAL(t,tv) { \
40+ (tv)->tv_sec += (t) / 1000; \
41+ (tv)->tv_usec += (t) % 1000 * 1000; \
3742 }
3843
3944 #ifndef TIMESPEC_TO_TIMEVAL
@@ -60,8 +65,6 @@ char* s_strdup(char*);
6065 void warn(const char*, ...);
6166 void die(const char*, ...);
6267
63−int min_int_nz(int, ...);
64−
6568 void size_readable(float*, const char**);
6669
6770 char* absolute_path(const char*);