Mercurial > MadButterfly
changeset 39:db2aa914e14b
timer for animation
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Wed, 06 Aug 2008 21:05:11 +0800 |
parents | 8d219ebd729e |
children | e292beec12d4 |
files | src/Makefile src/X_main.c src/mb_timer.h src/timer.c src/tools.h |
diffstat | 5 files changed, 255 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/src/Makefile Wed Aug 06 10:20:34 2008 +0800 +++ b/src/Makefile Wed Aug 06 21:05:11 2008 +0800 @@ -1,5 +1,5 @@ SRCS = coord.c geo.c shape_path.c shape_text.c shape_rect.c \ - redraw_man.c paint.c event.c tools.c + redraw_man.c timer.c paint.c event.c tools.c OBJS = ${SRCS:C/(.*)\.c/\1.o/g} TESTCASE_OBJS = ${SRCS:C/(.*)\.c/testcase-\1.o/g} CFLAGS+= -Wall -I/usr/local/include `pkg-config --cflags cairo`
--- a/src/X_main.c Wed Aug 06 10:20:34 2008 +0800 +++ b/src/X_main.c Wed Aug 06 21:05:11 2008 +0800 @@ -1,5 +1,7 @@ #include <stdio.h> #include <unistd.h> +#include <sys/time.h> +#include <sys/select.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <cairo.h> @@ -9,10 +11,29 @@ #include "shapes.h" #include "redraw_man.h" #include "paint.h" +#include "mb_timer.h" + +#define OK 0 +#define ERR -1 Display *display; Window win; +struct test_motion_data { + paint_t *text_stroke; + redraw_man_t *rdman; +}; + +void test_motion(mbsec_t sec, mbusec_t usec, + mbsec_t now_sec, mbusec_t now_usec, + void *arg) { + struct test_motion_data *data = (struct test_motion_data *)arg; + + paint_color_set(data->text_stroke, 1, 0.5, 0.5, 0.5); + rdman_paint_changed(data->rdman, data->text_stroke); + rdman_redraw_changed(data->rdman); +} + void hint_shape(redraw_man_t *rdman, shape_t *shape) { static shape_t *last_shape = NULL; if(last_shape != shape) { @@ -38,8 +59,11 @@ shape_t *shape = NULL; int in_stroke; - XSelectInput(display, win, PointerMotionMask | ExposureMask); - while((r = XNextEvent(display, &evt)) == 0) { + while(XEventsQueued(display, QueuedAfterReading) > 0) { + r = XNextEvent(display, &evt); + if(r == -1) + break; + switch(evt.type) { case MotionNotify: mevt = (XMotionEvent *)&evt; @@ -55,6 +79,56 @@ break; } } + XFlush(display); +} + +void handle_connection(Display *display, mb_tman_t *tman, + redraw_man_t *rdman, int w, int h) { + int xcon; + fd_set rds; + int nfds; + struct timeval tmo; + int r; + + XSelectInput(display, win, PointerMotionMask | ExposureMask); + XFlush(display); + + xcon = XConnectionNumber(display); + nfds = xcon + 1; + while(1) { + FD_ZERO(&rds); + FD_SET(xcon, &rds); + r = gettimeofday(&tmo, NULL); + if(r == -1) { + perror("gettimeofday"); + return; + } + + r = mb_tman_next_timeout(tman, + tmo.tv_sec, tmo.tv_usec, + (mbsec_t *)&tmo.tv_sec, + (mbusec_t *)&tmo.tv_usec); + if(r != OK) + r = select(nfds, &rds, NULL, NULL, NULL); + else + r = select(nfds, &rds, NULL, NULL, &tmo); + + if(r == -1) { + perror("select"); + return; + } + if(r == 0) { + r = gettimeofday(&tmo, NULL); + if(r == -1) { + perror("gettimeofday"); + return; + } + mb_tman_handle_timeout(tman, tmo.tv_sec, tmo.tv_usec); + XFlush(display); + } else if(FD_ISSET(xcon, &rds)) { + event_interaction(display, rdman, w, h); + } + } } void draw_path(cairo_t *cr, int w, int h) { @@ -68,6 +142,9 @@ shape_t *text; grad_stop_t fill3_stops[3]; cairo_font_face_t *face; + struct test_motion_data mdata; + struct timeval tv; + mb_tman_t *tman; int i; tmpsuf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); @@ -213,7 +290,18 @@ XFlush(display); } - event_interaction(display, &rdman, w, h); + tman = mb_tman_new(); + if(tman) { + mdata.text_stroke = text_stroke; + mdata.rdman = &rdman; + gettimeofday(&tv, NULL); + tv.tv_sec += 3; + mb_tman_timeout(tman, tv.tv_sec, tv.tv_usec, + test_motion, &mdata); + + handle_connection(display, tman, &rdman, w, h); + mb_tman_free(tman); + } fill1->free(fill1); fill2->free(fill2);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mb_timer.h Wed Aug 06 21:05:11 2008 +0800 @@ -0,0 +1,27 @@ +#ifndef __MB_TIMER_H_ +#define __MB_TIMER_H_ + +typedef uint32_t mbsec_t; +typedef uint32_t mbusec_t; +typedef struct _mb_timer mb_timer_t; +typedef struct _mb_tman mb_tman_t; + +typedef void (*mb_tmo_hdlr)(mbsec_t sec, mbusec_t usec, + mbsec_t now_sec, mbusec_t now_usec, + void *arg); + +extern mb_tman_t *mb_tman_new(void); +extern void mb_tman_free(mb_tman_t *tman); +extern mb_timer_t *mb_tman_timeout(mb_tman_t *tman, + mbsec_t sec, mbusec_t usec, + mb_tmo_hdlr hdlr, void *arg); +extern int mb_tman_remove(mb_tman_t *tman, mb_timer_t *timer); +extern int mb_tman_next_timeout(mb_tman_t *tman, + mbsec_t now_sec, mbusec_t now_usec, + mbsec_t *after_sec, mbusec_t *after_usec); +extern int mb_tman_handle_timeout(mb_tman_t *tman, + mbsec_t now_sec, mbusec_t now_usec); + + + +#endif /* __MB_TIMER_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/timer.c Wed Aug 06 21:05:11 2008 +0800 @@ -0,0 +1,131 @@ +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include "mb_timer.h" +#include "tools.h" + + +#define OK 0 +#define ERR -1 + +struct _mb_timer { + mbsec_t sec; + mbusec_t usec; + mb_tmo_hdlr hdlr; + void *arg; + mb_timer_t *next; +}; + +struct _mb_tman { + STAILQ(mb_timer_t) timers; + elmpool_t *timer_pool; +}; + +mb_tman_t *mb_tman_new(void) { + mb_tman_t *tman; + + tman = (mb_tman_t *)malloc(sizeof(mb_tman_t)); + if(tman == NULL) + return NULL; + + tman->timer_pool = elmpool_new(sizeof(mb_timer_t), 32); + if(tman->timer_pool == NULL) { + free(tman); + return NULL; + } + + STAILQ_INIT(tman->timers); + + return tman; +} + +void mb_tman_free(mb_tman_t *tman) { + elmpool_free(tman->timer_pool); + free(tman); +} + +mb_timer_t *mb_tman_timeout(mb_tman_t *tman, + mbsec_t sec, mbusec_t usec, + mb_tmo_hdlr hdlr, void *arg) { + mb_timer_t *timer, *visit, *last; + + timer = elmpool_elm_alloc(tman->timer_pool); + if(timer == NULL) + return NULL; + + timer->sec = sec; + timer->usec = usec; + timer->hdlr = hdlr; + timer->arg = arg; + + last = NULL; + for(visit = STAILQ_HEAD(tman->timers); + visit != NULL; + visit = STAILQ_NEXT(mb_timer_t, next, visit)) { + if(sec < visit->sec) + break; + if(sec == visit->sec && usec < visit->usec) + break; + last = visit; + } + + if(last == NULL) + STAILQ_INS(tman->timers, mb_timer_t, next, timer); + else if(visit == NULL) + STAILQ_INS_TAIL(tman->timers, mb_timer_t, next, timer); + else + STAILQ_INS_AFTER(mb_timer_t, next, timer, last); + + return timer; +} + +int mb_tman_remove(mb_tman_t *tman, mb_timer_t *timer) { + STAILQ_REMOVE(tman->timers, mb_timer_t, next, timer); + elmpool_elm_free(tman->timer_pool, timer); + + return OK; +} + +int mb_tman_next_timeout(mb_tman_t *tman, + mbsec_t now_sec, mbusec_t now_usec, + mbsec_t *after_sec, mbusec_t *after_usec) { + mb_timer_t *timer; + + timer = STAILQ_HEAD(tman->timers); + if(timer == NULL) + return ERR; + + if(now_sec > timer->sec || + (now_sec == timer->usec && now_usec >= timer->usec)) { + *after_sec = 0; + *after_usec = 0; + return OK; + } + + *after_sec = timer->sec - now_sec; + if(now_usec > timer->usec) { + --*after_sec; + *after_usec = 1000000 + timer->usec - now_usec; + } else + *after_usec = timer->usec - now_usec; + + return OK; +} + +int mb_tman_handle_timeout(mb_tman_t *tman, + mbsec_t now_sec, mbusec_t now_usec) { + mb_timer_t *timer; + + while((timer = STAILQ_HEAD(tman->timers)) != NULL){ + if(now_sec < timer->sec || + (now_sec == timer->sec && now_usec < timer->usec)) + break; + timer->hdlr(timer->sec, timer->usec, + now_sec, now_usec, + timer->arg); + STAILQ_REMOVE(tman->timers, mb_timer_t, next, timer); + elmpool_elm_free(tman->timer_pool, timer); + } + + return OK; +}
--- a/src/tools.h Wed Aug 06 10:20:34 2008 +0800 +++ b/src/tools.h Wed Aug 06 21:05:11 2008 +0800 @@ -39,6 +39,11 @@ if((q).head == NULL) \ (q).head = elm; \ } while(0) +#define STAILQ_INS_AFTER(type, field, follow, elm) \ + do { \ + (follow)->field = (elm)->field; \ + (elm)->field = follow; \ + } while(0) #define STAILQ_REMOVE(q, type, field, elm) \ do { \ if((elm) == (q).head) { \