# HG changeset patch # User Thinker K.F. Li # Date 1290484684 -28800 # Node ID 5d4bc2a93c0969dec8f4daf5890d2d4fd42a8439 # Parent 18329b6f77a416199dd337af71117b682d856a8f# Parent 769921baf111381afb472390043c63027863c168 Merge from refine_backend_if branch diff -r 18329b6f77a4 -r 5d4bc2a93c09 dox/dictionary.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dox/dictionary.h Tue Nov 23 11:58:04 2010 +0800 @@ -0,0 +1,24 @@ +/*! \page dictionary Dictionary + * + * This page is a list of acronyms and their meaning. + * + * - \b cb stands for CallBack. + * - \b coord stands for COORDinate. + * - \b elm stands for ELMent. + * - \b fact stands for FACTory. + * - \b geo stands for GEOmetry. + * - \b ldr stands for LoaDeR. + * - \b man stands for MANager. + * - \b mb stands for MadButterfly. + * - \b mbe stands for MadButterfly graphic Engine. + * - \b ob stands for OBserver. + * - \b obj stands for OBJect. + * - \b prop stands for PROPerty. + * - \b rdman stands for ReDraw MANager. + * - \b rect stands for RECTangle. + * - \b rm stands for ReMove. + * - \b rt stands for RunTime. + * - \b sh stands for SHapes. + * - \b tman stands for Timer MANager. + * - \b val stands for VALue. + */ diff -r 18329b6f77a4 -r 5d4bc2a93c09 examples/calculator/main.c --- a/examples/calculator/main.c Tue Nov 23 08:04:09 2010 +0800 +++ b/examples/calculator/main.c Tue Nov 23 11:58:04 2010 +0800 @@ -5,7 +5,7 @@ typedef struct _calc_data calc_data_t; struct _calc_data { - X_MB_runtime_t *rt; + mb_rt_t *rt; calculator_scr_t *code; }; @@ -64,7 +64,7 @@ char buf[20]; redraw_man_t *rdman; - rdman = X_MB_rdman(calc_data->rt); + rdman = mb_runtime_rdman(calc_data->rt); sprintf(buf, "%d%s", num, suffix); sh_stext_set_text(calc_data->code->screen_text_u, buf); @@ -142,7 +142,7 @@ break; } } - rdman = X_MB_rdman(calc_data->rt); + rdman = mb_runtime_rdman(calc_data->rt); rdman_redraw_changed(rdman); } @@ -174,24 +174,24 @@ } int main(int argc, char * const argv[]) { - X_MB_runtime_t *rt; + mb_rt_t *rt; redraw_man_t *rdman; calculator_scr_t *calculator_scr; calc_data_t calc_data; - rt = X_MB_new(":0.0", 300, 400); + rt = mb_runtime_new(":0.0", 300, 400); - rdman = X_MB_rdman(rt); + rdman = mb_runtime_rdman(rt); calculator_scr = calculator_scr_new(rdman, rdman->root_coord); calc_data.rt = rt; calc_data.code = calculator_scr; setup_observers(&calc_data); - X_MB_handle_connection(rt); + mb_runtime_event_loop(rt); calculator_scr_free(calculator_scr); - X_MB_free(rt); + mb_runtime_free(rt); return 0; } diff -r 18329b6f77a4 -r 5d4bc2a93c09 examples/drag/main.c --- a/examples/drag/main.c Tue Nov 23 08:04:09 2010 +0800 +++ b/examples/drag/main.c Tue Nov 23 11:58:04 2010 +0800 @@ -10,7 +10,7 @@ typedef struct _engine engine_t; struct _engine { - X_MB_runtime_t *rt; + mb_rt_t *rt; redraw_man_t *rdman; menu_t *menu; int state; @@ -21,12 +21,12 @@ engine_t *engine_init() { - X_MB_runtime_t *rt; - rt = X_MB_new(":0.0", 800, 600); + mb_rt_t *rt; + rt = mb_runtime_new(":0.0", 800, 600); engine_t *en = (engine_t *) malloc(sizeof(engine_t)); en->rt = rt; - en->rdman = X_MB_rdman(rt); + en->rdman = mb_runtime_rdman(rt); en->state = 0; return en; } @@ -36,13 +36,13 @@ * Start handle connections, includes one to X server. * User start to interact with the application. */ - X_MB_handle_connection(en->rt); + mb_runtime_event_loop(en->rt); /* * Clean */ menu_free(en->menu); - X_MB_free(en->rt); + mb_runtime_free(en->rt); free(en); } #define COORD_SHOW(group) coord_show(group);rdman_coord_changed(X_MB_rdman(ex_rt->rt), group) diff -r 18329b6f77a4 -r 5d4bc2a93c09 examples/dynamic/main.c --- a/examples/dynamic/main.c Tue Nov 23 08:04:09 2010 +0800 +++ b/examples/dynamic/main.c Tue Nov 23 11:58:04 2010 +0800 @@ -109,7 +109,7 @@ get_now(&timer); MB_TIMEVAL_SET(&interval, 1 ,0); MB_TIMEVAL_ADD(&timer, &interval); - mb_tman_timeout( mbaf_get_timer(app), &timer, switch_scene, app); + mb_timer_man_timeout( mbaf_get_timer(app), &timer, switch_scene, app); en->currentscene = (en->currentscene + 1) % 2; printf("switch to scene %d\n", en->currentscene + 1); @@ -147,7 +147,7 @@ MyApp_InitContent(); get_now(&tmo); MB_TIMEVAL_SET(&interval, 1 ,0); - mb_tman_timeout( mbaf_get_timer(app), &tmo, switch_scene, app); + mb_timer_man_timeout( mbaf_get_timer(app), &tmo, switch_scene, app); mbaf_loop(app); diff -r 18329b6f77a4 -r 5d4bc2a93c09 examples/svg2code_ex/main.c --- a/examples/svg2code_ex/main.c Tue Nov 23 08:04:09 2010 +0800 +++ b/examples/svg2code_ex/main.c Tue Nov 23 11:58:04 2010 +0800 @@ -10,31 +10,41 @@ typedef struct _ex_rt ex_rt_t; struct _ex_rt { - X_MB_runtime_t *rt; + mb_rt_t *rt; svg2code_ex_t *code; }; -#define COORD_SHOW(group) coord_show(group);rdman_coord_changed(X_MB_rdman(ex_rt->rt), group) -#define COORD_HIDE(group) coord_hide(group);rdman_coord_changed(X_MB_rdman(ex_rt->rt), group) +#define COORD_SHOW(group) do { \ + coord_show(group); \ + rdman_coord_changed(mb_runtime_rdman(ex_rt->rt), group); \ + } while(0) +#define COORD_HIDE(group) do { \ + coord_hide(group); \ + rdman_coord_changed(mb_runtime_rdman(ex_rt->rt), group); \ + } while(0) static void file_button_handler(event_t *evt, void *arg) { ex_rt_t *ex_rt = (ex_rt_t *)arg; + redraw_man_t *rdman; COORD_SHOW(ex_rt->code->file_menu); + rdman = mb_runtime_rdman(ex_rt->rt); /* Update changed part to UI. */ - rdman_redraw_changed(X_MB_rdman(ex_rt->rt)); + rdman_redraw_changed(rdman); } static void file_menu_handler(event_t *evt, void *arg) { ex_rt_t *ex_rt = (ex_rt_t *)arg; + redraw_man_t *rdman; COORD_HIDE(ex_rt->code->file_menu); + rdman = mb_runtime_rdman(ex_rt->rt); /* Update changed part to UI. */ - rdman_redraw_changed(X_MB_rdman(ex_rt->rt)); + rdman_redraw_changed(rdman); } int main(int argc, char * const argv[]) { - X_MB_runtime_t *rt; + mb_rt_t *rt; redraw_man_t *rdman; svg2code_ex_t *svg2code; subject_t *subject; @@ -43,12 +53,12 @@ /* * Initialize a runtime with XLib as backend. */ - rt = X_MB_new(":0.0", 800, 600); + rt = mb_runtime_new(":0.0", 800, 600); /* * Instantiate objects from a SVG file. */ - rdman = X_MB_rdman(rt); + rdman = mb_runtime_rdman(rt); svg2code = svg2code_ex_new(rdman, rdman->root_coord); /* @@ -65,13 +75,13 @@ * Start handle connections, includes one to X server. * User start to interact with the application. */ - X_MB_handle_connection(rt); + mb_runtime_event_loop(rt); /* * Clean */ svg2code_ex_free(svg2code); - X_MB_free(rt); + mb_runtime_free(rt); return 0; } diff -r 18329b6f77a4 -r 5d4bc2a93c09 examples/tank/tank_main.c --- a/examples/tank/tank_main.c Tue Nov 23 08:04:09 2010 +0800 +++ b/examples/tank/tank_main.c Tue Nov 23 11:58:04 2010 +0800 @@ -59,8 +59,8 @@ mb_progm_t *progm; mb_timeval_t start_time; observer_t *ob_redraw; - mb_timer_t *hit_tmr; - mb_tman_t *tman; + int hit_tmr; + mb_timer_man_t *timer_man; }; typedef struct _tank_bullet tank_bullet_t; /*! \brief The direction a bullet is going. @@ -106,7 +106,7 @@ tank_t *tanks[12]; int n_tanks; void *map[12][16]; - X_MB_runtime_t *mb_rt; + mb_rt_t *mb_rt; observer_t *kb_observer; }; @@ -124,7 +124,7 @@ if(tank == NULL) return NULL; - rdman = X_MB_rdman(tank_rt->mb_rt); + rdman = mb_runtime_rdman(tank_rt->mb_rt); tank->coord_pos = coord_pos; tank->coord_rot = coord_rot; @@ -145,11 +145,8 @@ return tank; } -static void tank_free(tank_t *tank, X_MB_runtime_t *xmb_rt) { - mb_tman_t *tman; - +static void tank_free(tank_t *tank, mb_rt_t *mb_rt) { if(tank->progm) { - tman = X_MB_tman(xmb_rt); mb_progm_abort(tank->progm); } free(tank); @@ -170,9 +167,9 @@ static void tank_move(tank_t *tank, int direction, tank_rt_t *tank_rt) { - X_MB_runtime_t *xmb_rt = tank_rt->mb_rt; + mb_rt_t *mb_rt = tank_rt->mb_rt; redraw_man_t *rdman; - mb_tman_t *tman; + mb_timer_man_t *timer_man; ob_factory_t *factory; /* for the program */ mb_progm_t *progm; @@ -239,9 +236,9 @@ } } - rdman = X_MB_rdman(xmb_rt); - tman = X_MB_tman(xmb_rt); - factory = X_MB_ob_factory(xmb_rt); + rdman = mb_runtime_rdman(mb_rt); + timer_man = mb_runtime_timer_man(mb_rt); + factory = mb_runtime_ob_factory(mb_rt); progm = mb_progm_new(1, rdman); tank->progm = progm; @@ -269,7 +266,7 @@ subject_add_observer(comp_sub, clean_tank_progm_handler, tank); get_now(&now); - mb_progm_start(progm, tman, &now); + mb_progm_start(progm, timer_man, &now); } /* @} */ @@ -310,6 +307,7 @@ bullet = O_ALLOC(tank_bullet_t); bullet->rdman = rdman; + bullet->hit_tmr = -1; make_bullet_elf_coords(rdman, &bullet->coord_pos, &bullet->coord_rot, @@ -338,6 +336,8 @@ } static void tank_bullet_free(tank_bullet_t *bullet) { + if(bullet->hit_tmr != -1) + mb_timer_man_remove(bullet->timer_man, bullet->hit_tmr); bullet_free(bullet->bullet_obj); rdman_coord_subtree_free(bullet->rdman, bullet->coord_pos); } @@ -350,8 +350,10 @@ bullet = tank->bullet; rdman = bullet->rdman; - if(bullet->hit_tmr != NULL) - mb_tman_remove(bullet->tman, bullet->hit_tmr); + if(bullet->hit_tmr != -1) { + mb_timer_man_remove(bullet->timer_man, bullet->hit_tmr); + bullet->hit_tmr = -1; + } coord_hide(bullet->coord_pos); rdman_coord_changed(rdman, bullet->coord_pos); @@ -364,7 +366,7 @@ static void bullet_bang(tank_bullet_t *bullet, int map_x, int map_y) { redraw_man_t *rdman; - mb_tman_t *tman; + mb_timer_man_t *timer_man; mb_progm_t *progm; mb_word_t *word; mb_timeval_t start, playing; @@ -373,7 +375,7 @@ co_aix *matrix; rdman = bullet->rdman; - tman = bullet->tman; + timer_man = bullet->timer_man; bang = bang_new(rdman, rdman->root_coord); matrix = bang->root_coord->matrix; @@ -401,11 +403,12 @@ mb_progm_free_completed(progm); get_now(&now); - mb_progm_start(progm, tman, &now); + mb_progm_start(progm, timer_man, &now); } /*! \brief To check if a bullet hits walls or tanks. */ -static void bullet_hit_chk(const mb_timeval_t *tmo, +static void bullet_hit_chk(int hdl, + const mb_timeval_t *tmo, const mb_timeval_t *now, void *arg) { tank_t *tank = (tank_t *)arg; @@ -422,9 +425,9 @@ static int move_adj[][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}}; bullet = tank->bullet; - bullet->hit_tmr = NULL; /* clear hit timer that bullet_go_out_map() - * can not remove it & currupt memory. - */ + bullet->hit_tmr = -1; /* clear hit timer that bullet_go_out_map() + * can not remove it & currupt memory. + */ MB_TIMEVAL_CP(&diff, now); MB_TIMEVAL_DIFF(&diff, &bullet->start_time); @@ -480,13 +483,13 @@ MB_TIMEVAL_SET(&next, 0, 100000); MB_TIMEVAL_ADD(&next, now); - bullet->hit_tmr = mb_tman_timeout(bullet->tman, &next, - bullet_hit_chk, arg); + bullet->hit_tmr = mb_timer_man_timeout(bullet->timer_man, &next, + bullet_hit_chk, arg); } /*! \brief To fire a bullet for a tank. */ static void tank_fire_bullet(tank_rt_t *tank_rt, tank_t *tank) { - X_MB_runtime_t *xmb_rt; + mb_rt_t *mb_rt; redraw_man_t *rdman; int map_x, map_y; int shift_x, shift_y; @@ -498,16 +501,16 @@ mb_action_t *act; mb_timeval_t start, playing; mb_timeval_t now, next; - mb_tman_t *tman; + mb_timer_man_t *timer_man; subject_t *subject; static int map_xy_adj[][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}}; if(tank->bullet != NULL) return; - xmb_rt = tank_rt->mb_rt; - rdman = X_MB_rdman(xmb_rt); - tman = X_MB_tman(xmb_rt); + mb_rt = tank_rt->mb_rt; + rdman = mb_runtime_rdman(mb_rt); + timer_man = mb_runtime_timer_man(mb_rt); dir = tank->direction; map_x = tank->map_x + map_xy_adj[dir][0]; @@ -540,7 +543,7 @@ tank->bullet = tank_bullet_new(rdman, map_x, map_y, dir); bullet = tank->bullet; - bullet->tman = tman; + bullet->timer_man = timer_man; progm = mb_progm_new(2, rdman); MB_TIMEVAL_SET(&start, 0, 0); @@ -555,11 +558,12 @@ get_now(&now); MB_TIMEVAL_CP(&bullet->start_time, &now); - mb_progm_start(progm, tman, &now); + mb_progm_start(progm, timer_man, &now); MB_TIMEVAL_SET(&next, 0, 100000); MB_TIMEVAL_ADD(&next, &now); - bullet->hit_tmr = mb_tman_timeout(tman, &next, bullet_hit_chk, tank); + bullet->hit_tmr = mb_timer_man_timeout(timer_man, &next, + bullet_hit_chk, tank); } /* @} */ @@ -615,14 +619,14 @@ } static void init_keyboard(tank_rt_t *tank_rt) { - X_MB_runtime_t *mb_rt; + mb_rt_t *mb_rt; subject_t *kbevents; redraw_man_t *rdman; mb_rt = tank_rt->mb_rt; - kbevents = X_MB_kbevents(mb_rt); + kbevents = mb_runtime_kbevents(mb_rt); - rdman = X_MB_rdman(mb_rt); + rdman = mb_runtime_rdman(mb_rt); tank_rt->kb_observer = subject_add_observer(kbevents, keyboard_handler, tank_rt); @@ -654,7 +658,7 @@ } void -initial_tank(tank_rt_t *tank_rt, X_MB_runtime_t *mb_rt) { +initial_tank(tank_rt_t *tank_rt, mb_rt_t *mb_rt) { redraw_man_t *rdman; /* for map areas */ mud_t *mud; @@ -668,7 +672,7 @@ tank_en_t *tank_en_o; int i, j; - rdman = X_MB_rdman(mb_rt); + rdman = mb_runtime_rdman(mb_rt); tank_rt->mb_rt = mb_rt; for(i = 0; i < 12; i++) { @@ -727,16 +731,16 @@ int main(int argc, char *const argv[]) { - X_MB_runtime_t *rt; + mb_rt_t *rt; tank_rt_t tank_rt; - rt = X_MB_new(":0.0", 800, 600); + rt = mb_runtime_new(":0.0", 800, 600); initial_tank(&tank_rt, rt); - X_MB_handle_connection(rt); + mb_runtime_event_loop(rt); - X_MB_free(rt); + mb_runtime_free(rt); } /* @} */ diff -r 18329b6f77a4 -r 5d4bc2a93c09 img/highlevel.png Binary file img/highlevel.png has changed diff -r 18329b6f77a4 -r 5d4bc2a93c09 img/highlevel.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/img/highlevel.svg Tue Nov 23 11:58:04 2010 +0800 @@ -0,0 +1,912 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + rdman/paint/shapes + + + + observer + + + + timer manager + + + + backend + + + + graphic engine + + + + animate + + + + image loader + + + + property + + + + element pool + + + + runtime + + + + use + + + + use + + + + use + + + + Application + + + + use + + + + diff -r 18329b6f77a4 -r 5d4bc2a93c09 include/mb.h --- a/include/mb.h Tue Nov 23 08:04:09 2010 +0800 +++ b/include/mb.h Tue Nov 23 11:58:04 2010 +0800 @@ -15,5 +15,6 @@ #endif #include "mb_animate.h" #include "mb_shapes.h" +#include "mb_backend.h" #endif /* __MB_H_ */ diff -r 18329b6f77a4 -r 5d4bc2a93c09 include/mb_X_supp.h --- a/include/mb_X_supp.h Tue Nov 23 08:04:09 2010 +0800 +++ b/include/mb_X_supp.h Tue Nov 23 11:58:04 2010 +0800 @@ -23,18 +23,9 @@ /* @} */ -typedef struct _X_MB_runtime X_MB_runtime_t; +typedef struct _X_supp_runtime X_supp_runtime_t; -extern void X_MB_handle_connection(void *rt); -extern void *X_MB_new(const char *display_name, int w, int h); -extern void *X_MB_new_with_win(Display *display, Window win); -extern void X_MB_free(void *xmb_rt); -extern void X_MB_free_keep_win(void *rt); - -extern subject_t *X_MB_kbevents(void *xmb_rt); -extern redraw_man_t *X_MB_rdman(void *xmb_rt); -extern mb_tman_t *X_MB_tman(void *xmb_rt); -extern ob_factory_t *X_MB_ob_factory(void *xmb_rt); -extern mb_img_ldr_t *X_MB_img_ldr(void *xmb_rt); +typedef Window MB_WINDOW; +typedef Display *MB_DISPLAY; #endif diff -r 18329b6f77a4 -r 5d4bc2a93c09 include/mb_af.h --- a/include/mb_af.h Tue Nov 23 08:04:09 2010 +0800 +++ b/include/mb_af.h Tue Nov 23 11:58:04 2010 +0800 @@ -3,9 +3,11 @@ #ifndef __APP_H #define __APP_H +#include "mb_backend.h" + typedef struct _mbapp mbaf_t; struct _mbapp { - void *rt; + mb_rt_t *rt; redraw_man_t *rdman; mb_sprite_t *rootsprite; mb_obj_t *root; @@ -14,7 +16,7 @@ }; mbaf_t *mbaf_init(const char *module, const char *module_dir); void mbaf_set_data(mbaf_t *app,void *data); -mb_tman_t *mbaf_get_timer(mbaf_t *app); +mb_timer_man_t *mbaf_get_timer(mbaf_t *app); void mbaf_loop(mbaf_t *app); #define MBAF_DATA(app,type) ((type *) ((app)->private)) #define MBAF_RDMAN(app) (((mbaf_t *) app)->rdman) diff -r 18329b6f77a4 -r 5d4bc2a93c09 include/mb_animate.h --- a/include/mb_animate.h Tue Nov 23 08:04:09 2010 +0800 +++ b/include/mb_animate.h Tue Nov 23 11:58:04 2010 +0800 @@ -4,8 +4,8 @@ #define __ANIMATE_H_ #include "mb_types.h" -#include "mb_timer.h" #include "mb_paint.h" +#include "mb_backend.h" /*! \page def_action How to Define An Action? * @@ -42,7 +42,7 @@ extern mb_word_t *mb_progm_next_word(mb_progm_t *progm, const mb_timeval_t *start, const mb_timeval_t *playing); -extern void mb_progm_start(mb_progm_t *progm, mb_tman_t *tman, +extern void mb_progm_start(mb_progm_t *progm, mb_timer_man_t *timer_man, mb_timeval_t *now); extern void mb_progm_abort(mb_progm_t *progm); extern subject_t *mb_progm_get_complete(mb_progm_t *progm); diff -r 18329b6f77a4 -r 5d4bc2a93c09 include/mb_backend.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/mb_backend.h Tue Nov 23 11:58:04 2010 +0800 @@ -0,0 +1,196 @@ +#ifndef __MB_BACKEND_H_ +#define __MB_BACKEND_H_ + +#include "mb_redraw_man.h" +#include "mb_timer.h" +#include "mb_observer.h" +#include "mb_img_ldr.h" + +#include "mb_config.h" + +#ifdef X_BACKEND +#include "mb_X_supp.h" +#endif + +#ifdef DFB_BACKEND +#inclde "mb_dfb_supp.h" +#endif + +struct _mb_rt; +typedef struct _mb_rt mb_rt_t; + +struct _mb_timer_man; +struct _mb_timer_factory; +struct _mb_IO_man; +struct _mb_IO_factory; + +/*! \brief Type of IO that registered with an IO manager. + */ +enum _MB_IO_TYPE {MB_IO_DUMMY, MB_IO_R, MB_IO_W, MB_IO_RW}; + +typedef struct _mb_timer_man mb_timer_man_t; +typedef struct _mb_timer_factory mb_timer_factory_t; +typedef struct _mb_IO_man mb_IO_man_t; +typedef struct _mb_IO_factory mb_IO_factory_t; +typedef enum _MB_IO_TYPE MB_IO_TYPE; + +/*! \brief Function signature of callback functions for IO requests. + */ +typedef void (*mb_IO_cb_t)(int hdl, int fd, MB_IO_TYPE type, void *data); + +/*! \brief The backend engine mb_backend_t is used to define the + * interface to realize the MB. + * + * A backend is used to receive events from the system. The MB does + * not define the backend by itself. Instead, it define an interface + * which allow the lower layer to implement the event system. Each + * backend need to provides the following events. + * + * - keyboard event + * - timer event + * - image loader(?) + * - render manager(?) + */ +typedef struct { + mb_rt_t *(*rt_new)(const char *display, int w,int h); + mb_rt_t *(*rt_new_with_win)(MB_DISPLAY display, MB_WINDOW win); + + void (*rt_free)(mb_rt_t *rt); + void (*rt_free_keep_win)(mb_rt_t *rt); + /*! \brief Request the backend to start monitoring a file descriptor. + * + * This is used only when the backend is responsible for event loop. + */ + int (*add_event)(mb_rt_t *rt, int fd, MB_IO_TYPE type, + mb_IO_cb_t f,void *arg); + /*! \brief Request the backend to stop monitoring a file descriptor. + * + * This is used only when the backend is responsible for event loop. + */ + void (*remove_event)(mb_rt_t *rt, int hdl); + /*! \brief Event Loop + * + * This is called when main application does not handle event + * loop. Or, it should register an IO factory (i.e \ref + * mb_IO_factory_t) with the backend. + */ + void (*event_loop)(mb_rt_t *rt); + + /*! \brief Flush requests to screen server if existed */ + int (*flush)(mb_rt_t *rt); + + subject_t *(*kbevents)(mb_rt_t *rt); + redraw_man_t *(*rdman)(mb_rt_t *rt); + mb_timer_man_t *(*timer_man)(mb_rt_t *rt); + ob_factory_t *(*ob_factory)(mb_rt_t *rt); + mb_img_ldr_t *(*loader)(mb_rt_t *rt); + + /* + * Following two methods are used to integrate a backend to + * event loop of main application. + */ + void (*reg_IO_factory)(mb_IO_factory_t *io_man); + void (*reg_timer_factory)(mb_timer_factory_t *tm_man); +} mb_backend_t; + +#define mb_runtime_new(disp, w, h) \ + mb_dfl_backend.rt_new((disp), (w), (h)) +#define mb_runtime_new_with_win(disp, win) \ + mb_dfl_backend.rt_new_with_win((disp), (win)) +#define mb_reg_IO_factory(io_fact) \ + mb_dfl_backend.reg_IO_factory(io_fact) +#define mb_reg_timer_factory(tm_fact) \ + mb_dfl_backend.reg_timer_factory(tm_fact) + +/* + * This is defined by backend implementations. For example, X_supp.c + * or dfb_supp.c should defined a backend. + */ +extern mb_backend_t mb_dfl_backend; + +#define mb_runtime_free(rt) \ + mb_dfl_backend.rt_free(rt) +#define mb_runtime_free_keep_win(rt) \ + mb_dfl_backend.rt_free_keep_win(rt) +#define mb_runtime_add_event(rt, fd, type, cb, arg) \ + mb_dfl_backend.add_event((rt), (fd), (type), (cb), (arg)) +#define mb_runtime_remove_event(hdl) \ + mb_dfl_backend.remove_event((rt), (hdl)) +#define mb_runtime_event_loop(rt) \ + mb_dfl_backend.event_loop(rt) +#define mb_runtime_flush(rt) \ + mb_dfl_backend.flush(rt) +#define mb_runtime_kbevents(rt) \ + mb_dfl_backend.kbevents(rt) +#define mb_runtime_rdman(rt) \ + mb_dfl_backend.rdman(rt) +#define mb_runtime_timer_man(rt) \ + mb_dfl_backend.timer_man(rt) +#define mb_runtime_ob_factory(rt) \ + mb_dfl_backend.ob_factory(rt) +#define mb_runtime_loader(rt) \ + mb_dfl_backend.loader(rt) + + +/*! \brief IO Manager + */ +struct _mb_IO_man { + int (*reg)(struct _mb_IO_man *io_man, + int fd, MB_IO_TYPE type, mb_IO_cb_t cb, void *data); + void (*unreg)(struct _mb_IO_man *io_man, + int io_hdl); +}; + +/*! \brief Factory of IO managers. + */ +struct _mb_IO_factory { + mb_IO_man_t *(*io_man_new)(void); + void (*io_man_free)(mb_IO_man_t *io_man); +}; + +#define mb_io_man_reg(io_man, fd, type, cb, data) \ + (io_man)->reg(io_man, fd, type, cb, data) +#define mb_io_man_unreg(io_man, io_hdl) \ + (io_man)->unreg(io_man, io_hdl) +#define mb_io_man_new(io_fact) (io_fact)->io_man_new() +#define mb_io_man_free(io_fact, io_man) (io_fact)->io_man_free(io_man) + +/*! \brief Function signature of callback functions for timers. + */ +typedef void (*mb_timer_cb_t)(int hdl, + const mb_timeval_t *tmo, + const mb_timeval_t *now, + void *data); + +/*! \brief Timer manager + */ +struct _mb_timer_man { + /*! \brief Setup a timeout callback. + * + * \return -1 for error. + */ + int (*timeout)(struct _mb_timer_man *tm_man, + mb_timeval_t *tmout, /* tiemout (wall time) */ + mb_timer_cb_t cb, void *data); + /*! \brief Remove a timeout request. + * + * \param tm_hdl is the handle returned by _mb_timer_man::timeout. + */ + void (*remove)(struct _mb_timer_man *tm_man, int tm_hdl); +}; + +/*! \brief Factory of timer manager. + */ +struct _mb_timer_factory { + mb_timer_man_t *(*timer_man_new)(void); + void (*timer_man_free)(mb_timer_man_t *timer_man); +}; + +#define mb_timer_man_timeout(tm_man, tmout, cb, data) \ + (tm_man)->timeout((tm_man), (tmout), (cb), (data)) +#define mb_timer_man_remove(tm_man, tm_hdl) \ + (tm_man)->remove((tm_man), (tm_hdl)) +#define mb_timer_man_new(tm_fact) (tm_fact)->timer_man_new() +#define mb_timer_man_free(tm_fact, tm_man) (tm_fact)->timer_man_free(tm_man) + +#endif /* __MB_BACKEND_H_ */ diff -r 18329b6f77a4 -r 5d4bc2a93c09 include/mb_backend_utils.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/mb_backend_utils.h Tue Nov 23 11:58:04 2010 +0800 @@ -0,0 +1,12 @@ +#ifndef __MB_BACKEND_UTILS_H_ +#define __MB_BACKEND_UTILS_H_ + +#include "mb_backend.h" +#include "mb_timer.h" + +/*! \brief A facotry of timer manager implemented with mb_tman_t. + */ +extern mb_timer_factory_t tman_timer_factory; +extern mb_tman_t *tman_timer_man_get_tman(mb_timer_man_t *tm_man); + +#endif /* __MB_BACKEND_UTILS_H_ */ diff -r 18329b6f77a4 -r 5d4bc2a93c09 include/mb_redraw_man.h --- a/include/mb_redraw_man.h Tue Nov 23 08:04:09 2010 +0800 +++ b/include/mb_redraw_man.h Tue Nov 23 11:58:04 2010 +0800 @@ -8,7 +8,6 @@ #include "mb_types.h" #include "mb_observer.h" #include "mb_img_ldr.h" -#include "mb_timer.h" typedef struct _redraw_man redraw_man_t; @@ -234,7 +233,7 @@ /*! \brief Set the search path of dymanic object loading. * */ -extern void sprite_set_search_path(char *path); +extern void sprite_set_search_path(const char *path); extern paint_t *rdman_img_ldr_load_paint(redraw_man_t *rdman, const char *img_id); @@ -243,31 +242,5 @@ #define MONITOR_READ 1 #define MONITOR_WRITE 2 -/*! \brief The backend engine mb_backend_t is used to define the interface to realize the MB. - * - * A backend is used to receive events from the system. The MB does not define the backend by itself. - * Instead, it define an interface which allow the lower layer to implement the event system. Each - * backend need to provides the following events. - * - * - keyboard event - * - timer event - * - image loader(?) - * - render manager(?) - */ -typedef struct { - - void *(*init)(const char *display,int w,int h); - void (*free)(void *be); - void (*add_event)(void *be,int type, int fd, mb_eventcb_t f,void *arg); - void (*remove_event)(void *be,int type, int fd); - void (*loop)(void *be); - subject_t *(*kbevents)(void *be); - redraw_man_t *(*rdman)(void *be); - mb_tman_t *(*tman)(void *be); - ob_factory_t *(*factory)(void *be); - mb_img_ldr_t *(*loader)(void *be); -} mb_backend_t; - -extern mb_backend_t backend; #endif /* __REDRAW_MAN_H_ */ diff -r 18329b6f77a4 -r 5d4bc2a93c09 nodejs/X_supp_njs.c --- a/nodejs/X_supp_njs.c Tue Nov 23 08:04:09 2010 +0800 +++ b/nodejs/X_supp_njs.c Tue Nov 23 11:58:04 2010 +0800 @@ -7,17 +7,115 @@ * The part is about */ #include +#include #include #include #include #include "mb_X_supp.h" #include "mb_tools.h" +#include #include "X_supp_njs.h" #ifndef ASSERT #define ASSERT(x) #endif +#define OK 0 +#define ERR -1 + + +/*! \defgroup njs_timer_man Timer manager for nodejs. + * @{ + */ +struct _njs_timer_timeout { + ev_timer tmwatcher; + mb_timer_cb_t cb; + mb_timeval_t *timeout; + void *data; +}; + +static int njs_timer_man_timeout(mb_timer_man_t *tm_man, + mb_timeval_t *tm_out, + mb_timer_cb_t cb, void *data); +static void njs_timer_man_remove(mb_timer_man_t *tm_man, int tm_hdl); +static mb_timer_man_t *njs_timer_man_new(void); +static void njs_timer_man_free(mb_timer_man_t *timer_man); + +static mb_timer_man_t njs_timer_man = { + njs_timer_man_timeout, + njs_timer_man_remove +}; + +static mb_timer_factory_t njs_timer_factory = { + njs_timer_man_new, + njs_timer_man_free +}; + +static void +njs_timer_man_cb(EV_P_ ev_timer *tmwatcher, int revent) { + struct _njs_timer_timeout *timer_timeout = + MEM2OBJ(tmwatcher, struct _njs_timer_timeout, tmwatcher); + mb_timeval_t now; + + get_now(&now); + timer_timeout->cb((int)timer_timeout, timer_timeout->timeout, &now, + timer_timeout->data); +} + +static int +njs_timer_man_timeout(mb_timer_man_t *tm_man, + mb_timeval_t *timeout, + mb_timer_cb_t cb, void *data) { + struct _njs_timer_timeout *timer_timeout; + mb_timeval_t now, timeout_diff; + ev_tstamp timeout_stamp; + + timer_timeout = O_ALLOC(struct _njs_timer_timeout); + if(timer_timeout == NULL) + return ERR; + + timer_timeout->cb = cb; + timer_timeout->timeout = timeout; + + get_now(&now); + + memcpy(&timeout_diff, timeout, sizeof(mb_timeval_t)); + MB_TIMEVAL_DIFF(&timeout_diff, &now); + timeout_stamp = (ev_tstamp)MB_TIMEVAL_SEC(&timeout_diff) + + (ev_tstamp)MB_TIMEVAL_USEC(&timeout_diff) / 1000000; + ev_timer_init(&timer_timeout->tmwatcher, njs_timer_man_cb, + timeout_stamp, 0); + ev_timer_start(&timer_timeout->tmwatcher); + + return (int)timer_timeout; +} + +static void +njs_timer_man_remove(struct _mb_timer_man *tm_man, int tm_hdl) { + struct _njs_timer_timeout *timer_timeout = + (struct _njs_timer_timeout *)tm_hdl; + + ev_timer_stop(&timer_timeout->tmwatcher); + free(timer_timeout); +} + +static mb_timer_man_t * +njs_timer_man_new(void) { + return &njs_timer_man; +} + +static void +njs_timer_man_free(mb_timer_man_t *timer_man) { +} + +void +X_njs_MB_reg_timer_man(void) { + mb_reg_timer_factory(&njs_timer_factory); +} + +/* @} */ + +#ifdef USE_MB_TMAN static void timer_cb(EV_P_ ev_timer *tmwatcher, int revent); /*! \brief Register next timeout with libev. @@ -76,6 +174,115 @@ set_next_timeout(rt); } +#endif /* USE_MB_TMAN */ + +/*! \defgroup njs_io_man IO manager for nodejs. + * @{ + */ +struct _njs_io_reg { + ev_io iowatcher; + int fd; + mb_IO_cb_t cb; + void *data; +}; + +static int njs_io_man_reg(struct _mb_IO_man *io_man, + int fd, MB_IO_TYPE type, mb_IO_cb_t cb, void *data); +static void njs_io_man_unreg(struct _mb_IO_man *io_man, int io_hdl); +static mb_IO_man_t *njs_io_man_new(void); +static void njs_io_man_free(mb_IO_man_t *io_man); + +static mb_IO_man_t njs_io_man = { + njs_io_man_reg, + njs_io_man_unreg +}; + +/*! \brief IO factory to integrate MadButterfly to event loop of nodejs. + */ +static mb_IO_factory_t njs_io_factory = { + njs_io_man_new, + njs_io_man_free +}; + +/*! \brief Bridge libev callback to IO manager callback. + */ +static void +njs_io_man_cb(EV_P_ ev_io *iowatcher, int revent) { + struct _njs_io_reg *io_reg = + MEM2OBJ(iowatcher, struct _njs_io_reg, iowatcher); + MB_IO_TYPE type; + + switch(revent & (EV_READ | EV_WRITE)) { + case EV_READ: + type = MB_IO_R; + break; + case EV_WRITE: + type = MB_IO_W; + break; + case EV_READ | EV_WRITE: + type = MB_IO_RW; + break; + } + + io_reg->cb((int)io_reg, io_reg->fd, type, io_reg->data); +} + +static int +njs_io_man_reg(struct _mb_IO_man *io_man, + int fd, MB_IO_TYPE type, mb_IO_cb_t cb, void *data) { + int _type; + struct _njs_io_reg *io_reg; + + if(type == MB_IO_R) + _type = EV_READ; + else if(type == MB_IO_W) + _type = EV_WRITE; + else if(type == MB_IO_RW) + _type = EV_READ | EV_WRITE; + else + return ERR; + + io_reg = O_ALLOC(struct _njs_io_reg); + if(io_reg == NULL) + return ERR; + + io_reg->fd = fd; + io_reg->cb = cb; + io_reg->data = data; + + ev_io_init(&io_reg->iowatcher, njs_io_man_cb, fd, _type); + ev_io_start(&io_reg->iowatcher); + + return (int)io_reg; +} + +static void +njs_io_man_unreg(struct _mb_IO_man *io_man, int io_hdl) { + struct _njs_io_reg *io_reg = (struct _njs_io_reg *)io_hdl; + + ev_io_stop(&io_reg->iowatcher); + free(io_reg); +} + +static mb_IO_man_t * +njs_io_man_new(void) { + return &njs_io_man; +} + +static void +njs_io_man_free(mb_IO_man_t *io_man) { +} + +/*! \brief Register an IO factory with MadButterfly backend. + */ +void +X_njs_MB_reg_IO_man(void) { + mb_reg_IO_factory(&njs_io_factory); +} + +/* @} */ + +#if 0 /*! \brief Handle connection coming data and timeout of timers. * * \param rt is a runtime object for X. @@ -96,20 +303,16 @@ set_next_timeout(rt); } +#endif /*! \brief Free njs_runtime_t. */ void X_njs_MB_free(njs_runtime_t *rt) { - /* - * stop IO and timer watcher + /*! + * TODO: Release all IO and timer request. */ - if(rt->enable_io) - ev_io_stop(&rt->iowatcher); - if(rt->enable_timer) - ev_timer_stop(&rt->tmwatcher); - - X_MB_free(rt->xrt); + mb_runtime_free(rt->xrt); free(rt); } @@ -118,41 +321,32 @@ void X_njs_MB_free_keep_win(njs_runtime_t *rt) { /* - * stop IO and timer watcher + * TODO: Release all IO and timer request. */ - if(rt->enable_io) - ev_io_stop(&rt->iowatcher); - if(rt->enable_timer) - ev_timer_stop(&rt->tmwatcher); - - X_MB_free_keep_win(rt->xrt); + mb_runtime_free_keep_win(rt->xrt); free(rt); } int X_njs_MB_flush(njs_runtime_t *rt) { - void *xrt = rt->xrt; + mb_rt_t *mb_rt = rt->xrt; int r; - extern int _X_MB_flush_x_conn_for_nodejs(void *rt); - _X_MB_flush_x_conn_for_nodejs(xrt); - + r = mb_runtime_flush(mb_rt); return r; } njs_runtime_t * X_njs_MB_new(char *display_name, int w, int h) { njs_runtime_t *rt; - void *xrt; + mb_rt_t *mb_rt; rt = (njs_runtime_t *)malloc(sizeof(njs_runtime_t)); ASSERT(rt != NULL); - xrt = X_MB_new(display_name, w, h); + mb_rt = mb_runtime_new(display_name, w, h); - rt->xrt = xrt; - rt->enable_io = 0; - rt->enable_timer = 0; /* no timer, now */ + rt->xrt = mb_rt; return rt; } @@ -165,16 +359,14 @@ njs_runtime_t * X_njs_MB_new_with_win(void *display, long win) { njs_runtime_t *rt; - void *xrt; + mb_rt_t *mb_rt; rt = (njs_runtime_t *)malloc(sizeof(njs_runtime_t)); ASSERT(rt != NULL); - xrt = X_MB_new_with_win((Display *)display, win); + mb_rt = mb_runtime_new_with_win((Display *)display, win); - rt->xrt = xrt; - rt->enable_io = 0; - rt->enable_timer = 0; /* no timer, now */ + rt->xrt = mb_rt; return rt; } @@ -183,25 +375,29 @@ */ void X_njs_MB_handle_single_event(njs_runtime_t *rt, void *evt) { +#if 0 void *xrt = rt->xrt; extern void _X_MB_handle_single_event(void *rt, void *evt); _X_MB_handle_single_event(xrt, evt); +#endif } /*! \brief Called at end of an iteration of event loop. */ void X_njs_MB_no_more_event(njs_runtime_t *rt) { - void *xrt = rt->xrt; - extern void _X_MB_no_more_event(void *rt); +#if 0 + mb_rt_t *xrt = rt->xrt; + extern void _X_MB_no_more_event(mb_rt_t *rt); _X_MB_no_more_event(xrt); +#endif } /*! \brief Get X runtime that is backend of this njs runtime. */ -void * +mb_rt_t * _X_njs_MB_get_X_runtime(njs_runtime_t *rt) { return rt->xrt; } diff -r 18329b6f77a4 -r 5d4bc2a93c09 nodejs/X_supp_njs.h --- a/nodejs/X_supp_njs.h Tue Nov 23 08:04:09 2010 +0800 +++ b/nodejs/X_supp_njs.h Tue Nov 23 11:58:04 2010 +0800 @@ -4,16 +4,15 @@ #define __X_SUPP_NJS_H_ #include +#include typedef struct _njs_runtime { - ev_io iowatcher; - ev_timer tmwatcher; - int enable_io; - int enable_timer; - void *xrt; + mb_rt_t *xrt; } njs_runtime_t; -extern void X_njs_MB_init_handle_connection(njs_runtime_t *rt); +extern void X_njs_MB_reg_timer_man(void); +extern void X_njs_MB_reg_IO_man(void); +/* extern void X_njs_MB_init_handle_connection(njs_runtime_t *rt); */ extern void X_njs_MB_free(njs_runtime_t *rt); extern njs_runtime_t *X_njs_MB_new(char *display_name, int w, int h); extern void X_njs_MB_free_keep_win(njs_runtime_t *rt); @@ -21,13 +20,12 @@ extern int X_njs_MB_flush(njs_runtime_t *rt); extern void X_njs_MB_handle_single_event(njs_runtime_t *rt, void *evt); extern void X_njs_MB_no_more_event(njs_runtime_t *rt); -extern void *_X_njs_MB_get_X_runtime(njs_runtime_t *rt); +extern mb_rt_t *_X_njs_MB_get_X_runtime(njs_runtime_t *rt); -#define X_njs_MB_kbevents(rt) X_MB_kbevents((rt)->xrt) -#define X_njs_MB_rdman(rt) X_MB_rdman((rt)->xrt) -#define X_njs_MB_tman(rt) X_MB_tman((rt)->xrt) -#define X_njs_MB_ob_factory(rt) X_MB_ob_factory((rt)->xrt) -#define X_njs_MB_img_ldr(rt) X_MB_img_ldr((rt)->xrt) -#define X_njs_MB_kbevents(rt) X_MB_kbevents((rt)->xrt) +#define X_njs_MB_kbevents(rt) mb_runtime_kbevents((rt)->xrt) +#define X_njs_MB_rdman(rt) mb_runtime_rdman((rt)->xrt) +#define X_njs_MB_timer_man(rt) mb_runtime_timer_man((rt)->xrt) +#define X_njs_MB_ob_factory(rt) mb_runtime_ob_factory((rt)->xrt) +#define X_njs_MB_img_ldr(rt) mb_runtime_img_ldr((rt)->xrt) #endif /* __X_SUPP_NJS_H_ */ diff -r 18329b6f77a4 -r 5d4bc2a93c09 nodejs/mbfly_njs.cc --- a/nodejs/mbfly_njs.cc Tue Nov 23 08:04:09 2010 +0800 +++ b/nodejs/mbfly_njs.cc Tue Nov 23 11:58:04 2010 +0800 @@ -80,7 +80,6 @@ * it is wrapped after returning of * this function. So, we wrap it * here. */ - X_njs_MB_init_handle_connection(obj); xnjsmb_coord_mkroot(self); subject = X_njs_MB_kbevents(obj); @@ -171,6 +170,8 @@ xnjsmb_auto_mb_rt_init(); xnjsmb_auto_mb_rt_display_init(); xnjsmb_auto_mb_rt_with_win_init(); + X_njs_MB_reg_timer_man(); + X_njs_MB_reg_IO_man(); /* * Add properties to mb_rt templates for other modules. diff -r 18329b6f77a4 -r 5d4bc2a93c09 src/X_main.c --- a/src/X_main.c Tue Nov 23 08:04:09 2010 +0800 +++ b/src/X_main.c Tue Nov 23 11:58:04 2010 +0800 @@ -15,6 +15,7 @@ #include "mb_paint.h" #include "mb_timer.h" #include "mb_animate.h" +#include "mb_backend_utils.h" #define OK 0 #define ERR -1 @@ -69,15 +70,18 @@ XFlush(display); } -void handle_connection(Display *display, mb_tman_t *tman, +void handle_connection(Display *display, mb_timer_man_t *timer_man, redraw_man_t *rdman, int w, int h) { int xcon; fd_set rds; int nfds; struct timeval tmo; mb_timeval_t mb_tmo, next_mb_tmo; + mb_tman_t *tman; int r; + tman = tman_timer_man_get_tman(timer_man); + XSelectInput(display, win, PointerMotionMask | ExposureMask); XFlush(display); @@ -136,7 +140,7 @@ grad_stop_t fill3_stops[3]; mbe_font_face_t *face; struct timeval tv; - mb_tman_t *tman; + mb_timer_man_t *timer_man; mb_timeval_t mbtv, start, playing; mb_progm_t *progm; mb_word_t *word; @@ -207,8 +211,8 @@ XFlush(display); - tman = mb_tman_new(); - if(tman) { + timer_man = mb_timer_man_new(&tman_timer_factory); + if(timer_man) { /* Prepare an animation program. */ progm = mb_progm_new(30, &rdman); @@ -400,12 +404,12 @@ /* Start playing the program. */ gettimeofday(&tv, NULL); MB_TIMEVAL_SET(&mbtv, tv.tv_sec, tv.tv_usec); - mb_progm_start(progm, tman, &mbtv); + mb_progm_start(progm, timer_man, &mbtv); - handle_connection(display, tman, &rdman, w, h); + handle_connection(display, timer_man, &rdman, w, h); mb_progm_free(progm); - mb_tman_free(tman); + mb_timer_man_free(&tman_timer_factory, timer_man); } rdman_paint_free(&rdman, fill1); diff -r 18329b6f77a4 -r 5d4bc2a93c09 src/X_supp.c --- a/src/X_supp.c Tue Nov 23 08:04:09 2010 +0800 +++ b/src/X_supp.c Tue Nov 23 11:58:04 2010 +0800 @@ -10,6 +10,8 @@ #include "mb_redraw_man.h" #include "mb_timer.h" #include "mb_X_supp.h" +#include "mb_backend.h" +#include "mb_backend_utils.h" #include "config.h" #ifdef XSHM @@ -22,8 +24,12 @@ #define ERR -1 #define OK 0 +#define ASSERT(x) + #define ONLY_MOUSE_MOVE_RAW 1 +static mb_timer_factory_t *_timer_factory = &tman_timer_factory; + /*! \ingroup xkb * @{ */ @@ -36,15 +42,8 @@ }; /* @} */ -#define MAX_MONITORS 200 -typedef struct { - int type; - int fd; - mb_eventcb_t f; - void *arg; -} monitor_t; -struct _X_MB_runtime { +struct _X_supp_runtime { Display *display; Window win; Visual *visual; @@ -52,13 +51,12 @@ mbe_pattern_t *surface_ptn; mbe_t *cr, *backend_cr; redraw_man_t *rdman; - mb_tman_t *tman; mb_img_ldr_t *img_ldr; int w, h; X_kb_info_t kbinfo; - monitor_t monitors[MAX_MONITORS]; - int n_monitor; + mb_IO_man_t *io_man; + mb_timer_man_t *timer_man; #ifndef ONLY_MOUSE_MOVE_RAW /* States */ @@ -70,6 +68,9 @@ XShmSegmentInfo shminfo; #endif + /* For handle connection */ + int io_hdl; + /* * Following variables are used by handle_single_x_event() */ @@ -81,9 +82,176 @@ int mbut_state; /* Button state of last motion event */ }; +static void _x_supp_handle_x_event(X_supp_runtime_t *rt); + +/*! \defgroup x_supp_io IO manager for X. + * @{ + */ +#define MAX_MONITORS 200 + +typedef struct { + int type; + int fd; + mb_IO_cb_t cb; + void *data; +} monitor_t; + +struct _X_supp_IO_man { + mb_IO_man_t io_man; + monitor_t monitors[MAX_MONITORS]; + int n_monitor; +}; + +static int _x_supp_io_man_reg(struct _mb_IO_man *io_man, + int fd, MB_IO_TYPE type, + mb_IO_cb_t cb, void *data); +static void _x_supp_io_man_unreg(struct _mb_IO_man *io_man, int io_hdl); +static mb_IO_man_t *_x_supp_io_man_new(void); +static void _x_supp_io_man_free(mb_IO_man_t *io_man); + +static mb_IO_factory_t _X_supp_default_io_factory = { + _x_supp_io_man_new, + _x_supp_io_man_free +}; +static mb_IO_factory_t *_io_factory = &_X_supp_default_io_factory; + +static struct _X_supp_IO_man _default_io_man = { + {_x_supp_io_man_reg, _x_supp_io_man_unreg}, + {}, /* monitors */ + 0 /* n_monitor */ +}; + +static mb_IO_man_t * +_x_supp_io_man_new(void) { + return (mb_IO_man_t *)&_default_io_man; +} + +static void +_x_supp_io_man_free(mb_IO_man_t *io_man) { +} + +static int +_x_supp_io_man_reg(struct _mb_IO_man *io_man, + int fd, MB_IO_TYPE type, mb_IO_cb_t cb, void *data) { + struct _X_supp_IO_man *xmb_io_man = (struct _X_supp_IO_man *)io_man; + int i; + + for(i = 0; i < xmb_io_man->n_monitor; i++) { + if (xmb_io_man->monitors[i].type == MB_IO_DUMMY) + break; + } + if (i == MAX_MONITORS) + return ERR; + + xmb_io_man->monitors[i].type = type; + xmb_io_man->monitors[i].fd = fd; + xmb_io_man->monitors[i].cb = cb; + xmb_io_man->monitors[i].data = data; + i++; + if(i > xmb_io_man->n_monitor) + xmb_io_man->n_monitor = i; + return i - 1; +} + +static void +_x_supp_io_man_unreg(struct _mb_IO_man *io_man, int io_hdl) { + struct _X_supp_IO_man *xmb_io_man = (struct _X_supp_IO_man *)io_man; + + ASSERT(io_hdl < xmb_io_man->n_monitor); + xmb_io_man->monitors[io_hdl].type = MB_IO_DUMMY; +} + +/*! \brief Handle connection coming data and timeout of timers. + * + * \param display is a Display returned by XOpenDisplay(). + * \param rdman is a redraw manager. + * \param tman is a timer manager. + * + * The display is managed by specified rdman and tman. rdman draws + * on the display, and tman trigger actions according timers. + */ +static void +_x_supp_event_loop(mb_rt_t *rt) { + struct _X_supp_runtime *xmb_rt = (struct _X_supp_runtime *)rt; + struct _X_supp_IO_man *io_man = (struct _X_supp_IO_man *)xmb_rt->io_man; + mb_timer_man_t *timer_man = (mb_timer_man_t *)xmb_rt->timer_man; + redraw_man_t *rdman; + mb_tman_t *tman = tman_timer_man_get_tman(timer_man); + mb_timeval_t now, tmo; + struct timeval tv; + fd_set rfds, wfds; + int nfds = 0; + int r, r1,i; + + rdman = mb_runtime_rdman(rt); + + _x_supp_handle_x_event(xmb_rt); + + while(1) { + FD_ZERO(&rfds); + FD_ZERO(&wfds); + for(i = 0; i < io_man->n_monitor; i++) { + if(io_man->monitors[i].type == MB_IO_R || + io_man->monitors[i].type == MB_IO_RW) { + FD_SET(io_man->monitors[i].fd, &rfds); + nfds = MB_MAX(nfds, io_man->monitors[i].fd + 1); + } + if(io_man->monitors[i].type == MB_IO_W || + io_man->monitors[i].type == MB_IO_RW) { + FD_SET(io_man->monitors[i].fd, &wfds); + nfds = MB_MAX(nfds, io_man->monitors[i].fd + 1); + } + } + + get_now(&now); + r = mb_tman_next_timeout(tman, &now, &tmo); + + if(r == 0) { + tv.tv_sec = MB_TIMEVAL_SEC(&tmo); + tv.tv_usec = MB_TIMEVAL_USEC(&tmo); + r1 = select(nfds, &rfds, NULL, NULL, &tv); + } else + r1 = select(nfds, &rfds, NULL, NULL, NULL); + + if(r1 == -1) { + perror("select"); + break; + } + + if(r1 == 0) { + get_now(&now); + mb_tman_handle_timeout(tman, &now); + rdman_redraw_changed(rdman); +#ifdef XSHM + XSHM_update(xmb_rt); +#endif + XFlush(xmb_rt->display); + } else { + for(i = 0; i < io_man->n_monitor; i++) { + if(io_man->monitors[i].type == MB_IO_R || + io_man->monitors[i].type == MB_IO_RW) { + if(FD_ISSET(io_man->monitors[i].fd, &rfds)) + io_man->monitors[i].cb(i, io_man->monitors[i].fd, + MB_IO_R, + io_man->monitors[i].data); + } + if(io_man->monitors[i].type == MB_IO_W || + io_man->monitors[i].type == MB_IO_RW) { + if(FD_ISSET(io_man->monitors[i].fd, &wfds)) + io_man->monitors[i].cb(i, io_man->monitors[i].fd, + MB_IO_W, + io_man->monitors[i].data); + } + } + } + } +} + +/* @} */ + #ifdef XSHM static void -XSHM_update(X_MB_runtime_t *xmb_rt) { +XSHM_update(X_supp_runtime_t *xmb_rt) { GC gc; gc = DefaultGC(xmb_rt->display, DefaultScreen(xmb_rt->display)); @@ -148,7 +316,8 @@ XFree(kbinfo->syms); } -/*! \brief Accept X keyboard events from handle_x_event() and dispatch it. +/*! \brief Accept X keyboard events from _x_supp_handle_x_event() and + * dispatch it. */ static void X_kb_handle_event(X_kb_info_t *kbinfo, XKeyEvent *xkey) { unsigned int code; @@ -167,7 +336,6 @@ subject_notify(kbinfo->kbevents, &event.event); } - /* @} */ static unsigned int get_button_state(unsigned int state) { @@ -227,7 +395,7 @@ /*! \brief Handle motion event. */ static void -handle_motion_event(X_MB_runtime_t *rt) { +handle_motion_event(X_supp_runtime_t *rt) { redraw_man_t *rdman = rt->rdman; int x, y; int state; @@ -277,7 +445,7 @@ /*! \brief Redraw exposed area. */ static void -handle_expose_event(X_MB_runtime_t *rt) { +handle_expose_event(X_supp_runtime_t *rt) { redraw_man_t *rdman = rt->rdman; int ex1, ey1, ex2, ey2; @@ -296,7 +464,7 @@ * It keeps internal state in rt to improve performance. */ static void -handle_single_x_event(X_MB_runtime_t *rt, XEvent *evt) { +handle_single_x_event(X_supp_runtime_t *rt, XEvent *evt) { redraw_man_t *rdman = rt->rdman; XMotionEvent *mevt; XButtonEvent *bevt; @@ -390,7 +558,7 @@ * perform some actions according current internal state. */ static void -no_more_event(X_MB_runtime_t *rt) { +no_more_event(X_supp_runtime_t *rt) { if(rt->mflag) handle_motion_event(rt); if(rt->eflag) @@ -399,7 +567,7 @@ /*! \brief Dispatch all X events in the queue. */ -static void handle_x_event(X_MB_runtime_t *rt) { +static void _x_supp_handle_x_event(X_supp_runtime_t *rt) { Display *display = rt->display; XEvent evt; int r; @@ -423,84 +591,13 @@ XFlush(display); } -/*! \brief Handle connection coming data and timeout of timers. - * - * \param display is a Display returned by XOpenDisplay(). - * \param rdman is a redraw manager. - * \param tman is a timer manager. - * - * The display is managed by specified rdman and tman. rdman draws - * on the display, and tman trigger actions according timers. - */ -void X_MB_handle_connection(void *be) { - X_MB_runtime_t *rt = (X_MB_runtime_t *) be; - Display *display = rt->display; - redraw_man_t *rdman = rt->rdman; - mb_tman_t *tman = rt->tman; - int fd; - mb_timeval_t now, tmo; - struct timeval tv; - fd_set rfds,wfds; - int nfds; - int r, r1,i; - - handle_x_event(rt); - - fd = XConnectionNumber(display); - nfds = fd + 1; - while(1) { - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_SET(fd, &rfds); - for(i=0;in_monitor;i++) { - if (rt->monitors[i].type == MONITOR_READ) - FD_SET(rt->monitors[i].fd, &rfds); - else if (rt->monitors[i].type == MONITOR_WRITE) - FD_SET(rt->monitors[i].fd, &wfds); - } - - get_now(&now); - r = mb_tman_next_timeout(tman, &now, &tmo); +static void +_x_supp_handle_connection(int hdl, int fd, MB_IO_TYPE type, void *data) { + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *)data; - if(r == 0) { - tv.tv_sec = MB_TIMEVAL_SEC(&tmo); - tv.tv_usec = MB_TIMEVAL_USEC(&tmo); - r1 = select(nfds, &rfds, NULL, NULL, &tv); - } else - r1 = select(nfds, &rfds, NULL, NULL, NULL); - - if(r1 == -1) { - perror("select"); - break; - } - - if(r1 == 0) { - get_now(&now); - mb_tman_handle_timeout(tman, &now); - rdman_redraw_changed(rdman); -#ifdef XSHM - XSHM_update(rt); -#endif - XFlush(display); - } else if(FD_ISSET(fd, &rfds)){ - handle_x_event(rt); - } else { - for(i=0;in_monitor;i++) { - if (rt->monitors[i].type == MONITOR_READ) { - if (FD_ISSET(rt->monitors[i].fd, &rfds)) - rt->monitors[i].f(rt->monitors[i].fd,rt->monitors[i].arg); - } else if (rt->monitors[i].type == MONITOR_WRITE) { - if (FD_ISSET(rt->monitors[i].fd, &wfds)) - rt->monitors[i].f(rt->monitors[i].fd,rt->monitors[i].arg); - } - } - } - } + _x_supp_handle_x_event(xmb_rt); } -#define ERR -1 -#define OK 0 - static int X_init_connection(const char *display_name, int w, int h, Display **displayp, @@ -573,7 +670,7 @@ #ifdef XSHM static void -xshm_destroy(X_MB_runtime_t *xmb_rt) { +xshm_destroy(X_supp_runtime_t *xmb_rt) { XShmSegmentInfo *shminfo; shminfo = &xmb_rt->shminfo; @@ -599,7 +696,7 @@ } static void -xshm_init(X_MB_runtime_t *xmb_rt) { +xshm_init(X_supp_runtime_t *xmb_rt) { Display *display; Visual *visual; XImage *ximage; @@ -661,20 +758,21 @@ /*! \brief Initialize a MadButterfy runtime for Xlib. * - * This one is very like X_MB_init(), except it accepts a - * X_MB_runtime_t object initialized with a display connected to a X + * This one is very like _x_supp_init(), except it accepts a + * X_supp_runtime_t object initialized with a display connected to a X * server and an opened window. * - * Following field of the X_MB_runtime_t object should be initialized. + * Following field of the X_supp_runtime_t object should be initialized. * - w, h * - win * - display * - visual */ static int -X_MB_init_with_win_internal(X_MB_runtime_t *xmb_rt) { +_x_supp_init_with_win_internal(X_supp_runtime_t *xmb_rt) { mb_img_ldr_t *img_ldr; int w, h; + int disp_fd; w = xmb_rt->w; h = xmb_rt->h; @@ -708,12 +806,13 @@ // to the redraw_man_t instead. xmb_rt->rdman->rt = xmb_rt; - xmb_rt->tman = mb_tman_new(); + xmb_rt->io_man = mb_io_man_new(_io_factory); + xmb_rt->timer_man = mb_timer_man_new(_timer_factory); img_ldr = simple_mb_img_ldr_new(""); xmb_rt->img_ldr = img_ldr; - rdman_set_img_ldr(xmb_rt->rdman, img_ldr); - memset(xmb_rt->monitors,0,sizeof(xmb_rt->monitors)); + /*! \todo Remove rdman_set_img_ldr() */ + rdman_set_img_ldr(xmb_rt->rdman, img_ldr); /* this is ncessary? */ #ifndef ONLY_MOUSE_MOVE_RAW xmb_rt->last = NULL; @@ -721,6 +820,12 @@ X_kb_init(&xmb_rt->kbinfo, xmb_rt->display, xmb_rt->rdman); + disp_fd = XConnectionNumber(xmb_rt->display); + xmb_rt->io_hdl = mb_io_man_reg(xmb_rt->io_man, disp_fd, + MB_IO_R, + _x_supp_handle_connection, + xmb_rt); + return OK; } @@ -729,11 +834,11 @@ * It setups a runtime environment to run MadButterfly with Xlib. * Users should specify width and height of the opening window. */ -static int X_MB_init(X_MB_runtime_t *xmb_rt, const char *display_name, - int w, int h) { +static int _x_supp_init(X_supp_runtime_t *xmb_rt, const char *display_name, + int w, int h) { int r; - memset(xmb_rt, 0, sizeof(X_MB_runtime_t)); + memset(xmb_rt, 0, sizeof(X_supp_runtime_t)); xmb_rt->w = w; xmb_rt->h = h; @@ -742,7 +847,7 @@ if(r != OK) return ERR; - r = X_MB_init_with_win_internal(xmb_rt); + r = _x_supp_init_with_win_internal(xmb_rt); return r; } @@ -750,11 +855,11 @@ /*! \brief Initialize a MadButterfly runtime for a window of X. * * Runtimes initialized with this function should be destroyed with - * X_MB_destroy_keep_win(). + * x_supp_destroy_keep_win(). */ static int -X_MB_init_with_win(X_MB_runtime_t *xmb_rt, - Display *display, Window win) { +_x_supp_init_with_win(X_supp_runtime_t *xmb_rt, + Display *display, Window win) { XWindowAttributes attrs; int r; @@ -762,7 +867,7 @@ if(r == 0) return ERR; - memset(xmb_rt, 0, sizeof(X_MB_runtime_t)); + memset(xmb_rt, 0, sizeof(X_supp_runtime_t)); xmb_rt->display = display; xmb_rt->win = win; @@ -770,19 +875,24 @@ xmb_rt->w = attrs.width; xmb_rt->h = attrs.height; - r = X_MB_init_with_win_internal(xmb_rt); + r = _x_supp_init_with_win_internal(xmb_rt); return r; } -static void X_MB_destroy(X_MB_runtime_t *xmb_rt) { +static void x_supp_destroy(X_supp_runtime_t *xmb_rt) { if(xmb_rt->rdman) { redraw_man_destroy(xmb_rt->rdman); free(xmb_rt->rdman); } - if(xmb_rt->tman) - mb_tman_free(xmb_rt->tman); + if(xmb_rt->io_hdl) + mb_io_man_unreg(xmb_rt->io_man, xmb_rt->io_hdl); + + if(xmb_rt->io_man) + mb_io_man_free(_io_factory, xmb_rt->io_man); + if(xmb_rt->timer_man) + mb_timer_man_free(_timer_factory, xmb_rt->timer_man); if(xmb_rt->img_ldr) MB_IMG_LDR_FREE(xmb_rt->img_ldr); @@ -806,13 +916,13 @@ } /*! \brief Destroy a MadButterfly runtime initialized with - * X_MB_init_with_win(). + * _x_supp_init_with_win(). * * Destroying a runtime with this function prevent the window and * display associated with the runtime being closed. */ static void -X_MB_destroy_keep_win(X_MB_runtime_t *xmb_rt) { +x_supp_destroy_keep_win(X_supp_runtime_t *xmb_rt) { Display *display; Window win; @@ -821,89 +931,97 @@ win = xmb_rt->win; xmb_rt->win = 0; - X_MB_destroy(xmb_rt); + x_supp_destroy(xmb_rt); xmb_rt->display = display; xmb_rt->win = win; } -void *X_MB_new(const char *display_name, int w, int h) { - X_MB_runtime_t *rt; +static mb_rt_t * +_x_supp_new(const char *display_name, int w, int h) { + X_supp_runtime_t *rt; int r; - rt = O_ALLOC(X_MB_runtime_t); + rt = O_ALLOC(X_supp_runtime_t); if(rt == NULL) return NULL; - r = X_MB_init(rt, display_name, w, h); + r = _x_supp_init(rt, display_name, w, h); if(r != OK) { free(rt); return NULL; } - return rt; + return (mb_rt_t *)rt; } /*! \brief Create a new runtime for existed window for X. * * The object returned by this function must be free with - * X_MB_free_keep_win() to prevent the window from closed. + * _x_supp_free_keep_win() to prevent the window from closed. */ -void *X_MB_new_with_win(Display *display, Window win) { - X_MB_runtime_t *rt; +static mb_rt_t * +_x_supp_new_with_win(MB_DISPLAY display, MB_WINDOW win) { + X_supp_runtime_t *rt; int r; - rt = O_ALLOC(X_MB_runtime_t); + rt = O_ALLOC(X_supp_runtime_t); if(rt == NULL) return NULL; - r = X_MB_init_with_win(rt, display, win); + r = _x_supp_init_with_win(rt, display, win); if(r != OK) { free(rt); return NULL; } - return rt; + return (mb_rt_t *)rt; } -void X_MB_free(void *rt) { - X_MB_destroy((X_MB_runtime_t *) rt); +static void +_x_supp_free(mb_rt_t *rt) { + x_supp_destroy((X_supp_runtime_t *) rt); free(rt); } -/*! \brief Free runtime created with X_MB_new_with_win(). +/*! \brief Free runtime created with _x_supp_new_with_win(). */ -void -X_MB_free_keep_win(void *rt) { - X_MB_destroy_keep_win((X_MB_runtime_t *) rt); +static void +_x_supp_free_keep_win(mb_rt_t *rt) { + x_supp_destroy_keep_win((X_supp_runtime_t *) rt); free(rt); } -subject_t *X_MB_kbevents(void *rt) { - X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; +static subject_t * +_x_supp_kbevents(mb_rt_t *rt) { + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt; return xmb_rt->kbinfo.kbevents; } -redraw_man_t *X_MB_rdman(void *rt) { - X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; +static redraw_man_t * +_x_supp_rdman(mb_rt_t *rt) { + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt; return xmb_rt->rdman; } -mb_tman_t *X_MB_tman(void *rt) { - X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; - return xmb_rt->tman; +static mb_timer_man_t * +_x_supp_timer_man(mb_rt_t *rt) { + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt; + return xmb_rt->timer_man; } -ob_factory_t *X_MB_ob_factory(void *rt) { - X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; +static ob_factory_t * +_x_supp_ob_factory(mb_rt_t *rt) { + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt; ob_factory_t *factory; factory = rdman_get_ob_factory(xmb_rt->rdman); return factory; } -mb_img_ldr_t *X_MB_img_ldr(void *rt) { - X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; +static mb_img_ldr_t * +_x_supp_img_ldr(mb_rt_t *rt) { + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt; mb_img_ldr_t *img_ldr; img_ldr = xmb_rt->img_ldr; @@ -911,79 +1029,91 @@ return img_ldr; } -void X_MB_add_event(void *rt, int type, int fd, mb_eventcb_t f,void *arg) +static int +_x_supp_add_event(mb_rt_t *rt, int fd, MB_IO_TYPE type, + mb_IO_cb_t cb, void *data) { - X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; - int i; + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt; + mb_IO_man_t *io_man = xmb_rt->io_man; + int hdl; - for(i=0;in_monitor;i++) { - if (xmb_rt->monitors[i].type == type && xmb_rt->monitors[i].fd == fd) { - xmb_rt->monitors[i].f = f; - xmb_rt->monitors[i].arg = arg; - return; - } - } - for(i=0;in_monitor;i++) { - if (xmb_rt->monitors[i].type == 0) { - xmb_rt->monitors[i].type = type; - xmb_rt->monitors[i].fd = fd; - xmb_rt->monitors[i].f = f; - xmb_rt->monitors[i].arg = arg; - return; - } - } - if (i == MAX_MONITORS) return; - xmb_rt->monitors[i].type = type; - xmb_rt->monitors[i].fd = fd; - xmb_rt->monitors[i].f = f; - xmb_rt->monitors[i].arg = arg; - i++; - xmb_rt->n_monitor=i; + hdl = mb_io_man_reg(io_man, fd, type, cb, data); + return hdl; +} + +static void +_x_supp_remove_event(mb_rt_t *rt, int hdl) +{ + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt; + mb_IO_man_t *io_man = xmb_rt->io_man; + + mb_io_man_unreg(io_man, hdl); } -void X_MB_remove_event(void *rt, int type, int fd) -{ - X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; - int i; - for(i=0;in_monitor;i++) { - if (xmb_rt->monitors[i].type == type && xmb_rt->monitors[i].fd == fd) { - xmb_rt->monitors[i].type = 0; - return; - } - } +static int +_x_supp_flush(mb_rt_t *rt) { + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt; + int r; + +#ifdef XSHM + XSHM_update(xmb_rt); +#endif + r = XFlush(xmb_rt->display); + return r == 0? ERR: OK; +} + +static void +_x_supp_reg_IO_factory(mb_IO_factory_t *io_factory) { + _io_factory = io_factory; +} + +static void +_x_supp_reg_timer_factory(mb_timer_factory_t *timer_factory) { + _timer_factory = timer_factory; } -mb_backend_t backend = { X_MB_new, - X_MB_free, - X_MB_add_event, - X_MB_remove_event, - X_MB_handle_connection, - X_MB_kbevents, - X_MB_rdman, - X_MB_tman, - X_MB_ob_factory, - X_MB_img_ldr - }; + +mb_backend_t mb_dfl_backend = { _x_supp_new, + _x_supp_new_with_win, + + _x_supp_free, + _x_supp_free_keep_win, + _x_supp_add_event, + _x_supp_remove_event, + _x_supp_event_loop, + _x_supp_flush, + + _x_supp_kbevents, + _x_supp_rdman, + _x_supp_timer_man, + _x_supp_ob_factory, + _x_supp_img_ldr, + + _x_supp_reg_IO_factory, + _x_supp_reg_timer_factory, +}; + +#if 0 /*! \defgroup x_supp_nodejs_sup Export functions for supporting nodejs plugin. * * These functions are for internal using. * @{ */ -/*! \brief Exported for nodejs plugin to call handle_x_event. +/*! \brief Exported for nodejs plugin to call _x_supp_handle_x_event. */ -void _X_MB_handle_x_event_for_nodejs(void *rt) { - handle_x_event((X_MB_runtime_t *)rt); +void _x_supp_handle_x_event_for_nodejs(mb_rt_t *rt) { + _x_supp_handle_x_event((X_supp_runtime_t *)rt); } /*! \brief Get X connect for nodejs plugin. */ -int _X_MB_get_x_conn_for_nodejs(void *rt) { - return XConnectionNumber(((X_MB_runtime_t *)rt)->display); +int _x_supp_get_x_conn_for_nodejs(mb_rt_t *rt) { + return XConnectionNumber(((X_supp_runtime_t *)rt)->display); } /*! \brief Flush buffer for the X connection of a runtime object. */ -int _X_MB_flush_x_conn_for_nodejs(void *rt) { - X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *)rt; +int _x_supp_flush_x_conn_for_nodejs(mb_rt_t *rt) { + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *)rt; #ifdef XSHM XSHM_update(xmb_rt); #endif @@ -993,8 +1123,8 @@ /*! \brief Handle single X event. */ void -_X_MB_handle_single_event(void *rt, void *evt) { - X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *)rt; +_x_supp_handle_single_event(mb_rt_t *rt, void *evt) { + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *)rt; handle_single_x_event(xmb_rt, (XEvent *)evt); } @@ -1002,10 +1132,11 @@ /*! \brief Called at end of an iteration of X event loop. */ void -_X_MB_no_more_event(void *rt) { - X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *)rt; +_x_supp_no_more_event(mb_rt_t *rt) { + X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *)rt; no_more_event(xmb_rt); } /* @} */ +#endif /* 0 */ diff -r 18329b6f77a4 -r 5d4bc2a93c09 src/animate.c --- a/src/animate.c Tue Nov 23 08:04:09 2010 +0800 +++ b/src/animate.c Tue Nov 23 11:58:04 2010 +0800 @@ -26,7 +26,7 @@ * a word, it call stop of actions in the word. * * A program is driven by a timer. Once a program is started, it registers - * with timer for periodic running. \ref mb_tman_t is timer of + * with timer for periodic running. \ref mb_timer_man_t is timer of * MadButterfly. The update frequence is 10fps by default, now. * * \section use_progm How to Use Animation Program? @@ -61,7 +61,7 @@ * * gettimeofday(&tv, NULL); * MB_TIMEVAL_SET(&mbtv, tv.tv_sec, tv.tv_usec); - * mb_progm_start(progm, tman, &mbtv); + * mb_progm_start(progm, timer_man, &mbtv); * \endcode * * @@ -98,9 +98,9 @@ mb_timeval_t start_time; int first_playing; /*!< first playing word. */ - mb_tman_t *tman; + mb_timer_man_t *timer_man; subject_t *complete; /*!< notify when a program is completed. */ - mb_timer_t *cur_timer; + int cur_timer; int n_words; int max_words; @@ -139,6 +139,7 @@ progm->max_words = max_words; for(i = 0; i < max_words; i++) STAILQ_INIT(progm->words[i].actions); + progm->cur_timer = -1; return progm; } @@ -233,7 +234,8 @@ * between now and next_tmo. It is not obviously if time stepping * small. */ -static void mb_progm_step(const mb_timeval_t *tmo, +static void mb_progm_step(int timer_hdl, + const mb_timeval_t *tmo, const mb_timeval_t *now, void *arg) { mb_progm_t *progm = (mb_progm_t *)arg; @@ -289,8 +291,8 @@ word = progm->words + progm->first_playing; if(MB_TIMEVAL_LATER(&word->abs_start, &next_tmo)) MB_TIMEVAL_CP(&next_tmo, &word->abs_start); - timer = mb_tman_timeout(progm->tman, &next_tmo, - mb_progm_step, progm); + timer = mb_timer_man_timeout(progm->timer_man, &next_tmo, + mb_progm_step, progm); progm->cur_timer = timer; } else { /* Make program to complete. */ @@ -300,20 +302,20 @@ comp_evt.progm = progm; subject_notify(progm->complete, &comp_evt.event); #endif /* UNITTEST */ - progm->cur_timer = NULL; + progm->cur_timer = -1; } } -void mb_progm_start(mb_progm_t *progm, mb_tman_t *tman, +void mb_progm_start(mb_progm_t *progm, mb_timer_man_t *timer_man, mb_timeval_t *now) { - mb_timer_t *timer; + int timer; mb_word_t *word; int i; if(progm->n_words == 0) return; - progm->tman = tman; + progm->timer_man = timer_man; MB_TIMEVAL_CP(&progm->start_time, now); progm->first_playing = 0; @@ -326,13 +328,13 @@ } if(MB_TIMEVAL_EQ(&progm->words[0].abs_start, now)) { - mb_progm_step(now, now, progm); + mb_progm_step(-1, now, now, progm); return; } - timer = mb_tman_timeout(tman, &progm->words[0].abs_start, - mb_progm_step, progm); - ASSERT(timer != NULL); + timer = mb_timer_man_timeout(timer_man, &progm->words[0].abs_start, + mb_progm_step, progm); + ASSERT(timer != -1); /* We need timer to abort it. */ progm->cur_timer = timer; @@ -343,13 +345,13 @@ mb_progm_abort(progm); MB_TIMEVAL_SET(&infi, 0x7fffffff,0); - mb_progm_step(&progm->start_time, &infi,progm); + mb_progm_step(-1, &progm->start_time, &infi,progm); } void mb_progm_abort(mb_progm_t *progm) { /*! \todo Make sure abort release resources. */ - if(progm->cur_timer) { - mb_tman_remove(progm->tman, progm->cur_timer); - progm->cur_timer = NULL; + if(progm->cur_timer != -1) { + mb_timer_man_remove(progm->timer_man, progm->cur_timer); + progm->cur_timer = -1; } } @@ -375,6 +377,7 @@ #ifdef UNITTEST +#include "mb_backend_utils.h" #include typedef struct _mb_dummy mb_dummy_t; @@ -441,14 +444,17 @@ mb_progm_t *progm; mb_word_t *word; mb_action_t *acts[4]; + mb_timer_man_t *timer_man; mb_tman_t *tman; mb_timeval_t tv1, tv2, now, tmo_after; int logcnt = 0; int logs[256]; int r; - tman = mb_tman_new(); - CU_ASSERT(tman != NULL); + timer_man = mb_timer_man_new(&tman_timer_factory); + CU_ASSERT(timer_man != -1); + + tman = tman_timer_man_get_tman(timer_man); progm = mb_progm_new(3, NULL); CU_ASSERT(progm != NULL); @@ -475,7 +481,7 @@ CU_ASSERT(acts[2] != NULL); MB_TIMEVAL_SET(&now, 0, 0); - mb_progm_start(progm, tman, &now); + mb_progm_start(progm, timer_man, &now); r = mb_tman_next_timeout(tman, &now, &tmo_after); CU_ASSERT(r == 0); @@ -541,7 +547,7 @@ CU_ASSERT(r == -1); mb_progm_free(progm); - mb_tman_free(tman); + mb_timer_man_free(&tman_timer_factory, timer_man); } CU_pSuite get_animate_suite(void) { diff -r 18329b6f77a4 -r 5d4bc2a93c09 src/mbaf/animated_menu.c --- a/src/mbaf/animated_menu.c Tue Nov 23 08:04:09 2010 +0800 +++ b/src/mbaf/animated_menu.c Tue Nov 23 11:58:04 2010 +0800 @@ -108,7 +108,7 @@ mb_progm_free_completed(progm); m->ready--; subject_add_observer(mb_progm_get_complete(progm), mb_animated_menu_complete,m); - mb_progm_start(progm, X_MB_tman(MBAF_RDMAN(m->app)->rt), &now); + mb_progm_start(progm, mb_runtime_timer_man(MBAF_RDMAN(m->app)->rt), &now); rdman_redraw_changed(MBAF_RDMAN(m->app)); tmp = m->items[8]; for(i=8;i>0;i--) { @@ -158,7 +158,7 @@ mb_progm_free_completed(progm); m->ready--; subject_add_observer(mb_progm_get_complete(progm), mb_animated_menu_complete,m); - mb_progm_start(progm, X_MB_tman(MBAF_RDMAN(m->app)->rt), &now); + mb_progm_start(progm, mb_runtime_timer_man(MBAF_RDMAN(m->app)->rt), &now); rdman_redraw_changed(MBAF_RDMAN(m->app)); tmp = m->items[0]; for(i=0;i<8;i++) { @@ -185,7 +185,7 @@ mb_progm_free_completed(progm); m->ready--; subject_add_observer(mb_progm_get_complete(progm), mb_animated_menu_complete,m); - mb_progm_start(progm, X_MB_tman(MBAF_RDMAN(m->app)->rt), &now); + mb_progm_start(progm, mb_runtime_timer_man(MBAF_RDMAN(m->app)->rt), &now); rdman_redraw_changed(MBAF_RDMAN(m->app)); } diff -r 18329b6f77a4 -r 5d4bc2a93c09 src/mbaf/mbapp.c --- a/src/mbaf/mbapp.c Tue Nov 23 08:04:09 2010 +0800 +++ b/src/mbaf/mbapp.c Tue Nov 23 11:58:04 2010 +0800 @@ -2,25 +2,26 @@ // vim: sw=4:ts=8:sts=4 #include #include +#include mbaf_t *mbaf_init(const char *module, const char *module_dir) { mbaf_t *app = (mbaf_t *) malloc(sizeof(mbaf_t)); - void *rt; + mb_rt_t *rt; - rt = backend.init(":0.0", 800, 600); + rt = mb_runtime_new(":0.0", 800, 600); if(rt == NULL) return NULL; sprite_set_search_path(module_dir); app->rt = rt; - app->rdman = backend.rdman(rt); - app->kbevents = backend.kbevents(rt); + app->rdman = mb_runtime_rdman(rt); + app->kbevents = mb_runtime_kbevents(rt); app->rootsprite= sprite_load(module,app->rdman, app->rdman->root_coord); if(app->rootsprite == NULL) { - backend.free(rt); + mb_runtime_free(rt); free(app); return NULL; } @@ -36,9 +37,9 @@ app->private = (void *) data; } -mb_tman_t *mbaf_get_timer(mbaf_t *app) +mb_timer_man_t *mbaf_get_timer(mbaf_t *app) { - return backend.tman(app->rt); + return mb_runtime_timer_man(app->rt); } void mbaf_loop(mbaf_t *app) @@ -47,11 +48,11 @@ * Start handle connections, includes one to X server. * User start to interact with the application. */ - backend.loop(app->rt); + mb_runtime_event_loop(app->rt); /* * Clean */ - backend.free(app->rt); + mb_runtime_free(app->rt); free(app); } diff -r 18329b6f77a4 -r 5d4bc2a93c09 src/mbaf/mbbutton.c --- a/src/mbaf/mbbutton.c Tue Nov 23 08:04:09 2010 +0800 +++ b/src/mbaf/mbbutton.c Tue Nov 23 11:58:04 2010 +0800 @@ -93,7 +93,7 @@ subject_add_observer(mb_progm_get_complete(btn->progm), mb_button_end_animated_cb,btn); get_now(&now); printf("rt = %x\n", btn->rdman->rt); - mb_progm_start(progm, X_MB_tman(btn->rdman->rt), &now); + mb_progm_start(progm, mb_runtime_timer_man(btn->rdman->rt), &now); if (btn->press) btn->press(btn->arg); } diff -r 18329b6f77a4 -r 5d4bc2a93c09 src/sprite.c --- a/src/sprite.c Tue Nov 23 08:04:09 2010 +0800 +++ b/src/sprite.c Tue Nov 23 11:58:04 2010 +0800 @@ -41,7 +41,7 @@ return fullname; } -void sprite_set_search_path(char *path) { +void sprite_set_search_path(const char *path) { int sz; if (sprite_search_path) diff -r 18329b6f77a4 -r 5d4bc2a93c09 src/timer.c --- a/src/timer.c Tue Nov 23 08:04:09 2010 +0800 +++ b/src/timer.c Tue Nov 23 11:58:04 2010 +0800 @@ -6,6 +6,7 @@ #include #include "mb_timer.h" #include "mb_tools.h" +#include "mb_backend.h" #define OK 0 @@ -122,3 +123,101 @@ return OK; } + +/*! \defgroup tman_timer_man Timer manager based on mb_tman_t. + * + * This implmentation of timer manager is based on mb_tman_t. + * @{ + */ +struct _tman_timer_man { + mb_timer_man_t timer_man; + mb_tman_t *tman; +}; + +static int _tman_timer_man_timeout(struct _mb_timer_man *tm_man, + mb_timeval_t *tmout, + mb_timer_cb_t cb, void *data); +static void _tman_timer_man_remove(struct _mb_timer_man *tm_man, int tm_hdl); +static mb_timer_man_t *_tman_timer_fact_new(void); +static void _tman_timer_fact_free(mb_timer_man_t *timer_man); + +static struct _tman_timer_man _tman_default_timer_man = { + {_tman_timer_man_timeout, _tman_timer_man_remove}, + NULL +}; + +mb_timer_factory_t tman_timer_factory = { + _tman_timer_fact_new, + _tman_timer_fact_free +}; + +/*! \brief Content of a timeout request. + * + * This is only used by internal of X support. This data structure + * carry information to adopt mb_tman_t to mb_timer_man_t. + */ +struct _tman_timeout_data { + mb_timer_t *timer; /*!< Handle returned by mb_tman_timeout() */ + mb_timer_cb_t cb; /*!< Real callback function */ + void *data; /*!< data for real callback */ +}; + +static void +_tman_tmo_hdlr(const mb_timeval_t *tmo, + const mb_timeval_t *now, + void *arg) { + struct _tman_timeout_data *data = (struct _tman_timeout_data *)arg; + + data->cb((int)data, tmo, now, data->data); +} + +static int +_tman_timer_man_timeout(struct _mb_timer_man *tm_man, + mb_timeval_t *tmout, /* timeout (wall time) */ + mb_timer_cb_t cb, void *data) { + struct _tman_timer_man *timer_man = (struct _tman_timer_man *)tm_man; + mb_timer_t *timer; + struct _tman_timeout_data *tmout_data; + + tmout_data = O_ALLOC(struct _tman_timeout_data); + tmout_data->cb = cb; + tmout_data->data = data; + timer = mb_tman_timeout(timer_man->tman, tmout, + _tman_tmo_hdlr, tmout_data); + if(timer == NULL) + return ERR; + tmout_data->timer = timer; + + return (int)tmout_data; +} + +static void +_tman_timer_man_remove(struct _mb_timer_man *tm_man, int tm_hdl) { + struct _tman_timer_man *timer_man = (struct _tman_timer_man *)tm_man; + struct _tman_timeout_data *tmout_data = + (struct _tman_timeout_data *)tm_hdl; + + mb_tman_remove(timer_man->tman, tmout_data->timer); + free(tmout_data); +} + +static mb_timer_man_t * +_tman_timer_fact_new(void) { + if(_tman_default_timer_man.tman == NULL) + _tman_default_timer_man.tman = mb_tman_new(); + return (mb_timer_man_t *)&_tman_default_timer_man; +} + +static void +_tman_timer_fact_free(mb_timer_man_t *timer_man) { +} + +mb_tman_t * +tman_timer_man_get_tman(mb_timer_man_t *tm_man) { + struct _tman_timer_man *timer_man = (struct _tman_timer_man *)tm_man; + + return timer_man->tman; +} + + +/* @} */