# HG changeset patch
# User wycc
# Date 1290527724 -28800
# Node ID f26c4b621ec0cbac5947e5cb8801976a966523de
# Parent 4072a302b207334d07b5a649ade0dbea921a77db# Parent bf5adf1e275e773c7d046f3a8d96c1220b58e5e0
MErge head
diff -r 4072a302b207 -r f26c4b621ec0 dox/dictionary.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dox/dictionary.h Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 examples/calculator/main.c
--- a/examples/calculator/main.c Tue Nov 23 23:54:38 2010 +0800
+++ b/examples/calculator/main.c Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 examples/drag/main.c
--- a/examples/drag/main.c Tue Nov 23 23:54:38 2010 +0800
+++ b/examples/drag/main.c Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 examples/dynamic/main.c
--- a/examples/dynamic/main.c Tue Nov 23 23:54:38 2010 +0800
+++ b/examples/dynamic/main.c Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 examples/svg2code_ex/main.c
--- a/examples/svg2code_ex/main.c Tue Nov 23 23:54:38 2010 +0800
+++ b/examples/svg2code_ex/main.c Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 examples/tank/tank_main.c
--- a/examples/tank/tank_main.c Tue Nov 23 23:54:38 2010 +0800
+++ b/examples/tank/tank_main.c Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 img/highlevel.png
Binary file img/highlevel.png has changed
diff -r 4072a302b207 -r f26c4b621ec0 img/highlevel.svg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/img/highlevel.svg Tue Nov 23 23:55:24 2010 +0800
@@ -0,0 +1,912 @@
+
+
+
+
diff -r 4072a302b207 -r f26c4b621ec0 include/mb.h
--- a/include/mb.h Tue Nov 23 23:54:38 2010 +0800
+++ b/include/mb.h Tue Nov 23 23:55:24 2010 +0800
@@ -15,5 +15,6 @@
#endif
#include "mb_animate.h"
#include "mb_shapes.h"
+#include "mb_backend.h"
#endif /* __MB_H_ */
diff -r 4072a302b207 -r f26c4b621ec0 include/mb_X_supp.h
--- a/include/mb_X_supp.h Tue Nov 23 23:54:38 2010 +0800
+++ b/include/mb_X_supp.h Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 include/mb_af.h
--- a/include/mb_af.h Tue Nov 23 23:54:38 2010 +0800
+++ b/include/mb_af.h Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 include/mb_animate.h
--- a/include/mb_animate.h Tue Nov 23 23:54:38 2010 +0800
+++ b/include/mb_animate.h Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 include/mb_backend.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/mb_backend.h Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 include/mb_backend_utils.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/mb_backend_utils.h Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 include/mb_redraw_man.h
--- a/include/mb_redraw_man.h Tue Nov 23 23:54:38 2010 +0800
+++ b/include/mb_redraw_man.h Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 nodejs/X_supp_njs.c
--- a/nodejs/X_supp_njs.c Tue Nov 23 23:54:38 2010 +0800
+++ b/nodejs/X_supp_njs.c Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 nodejs/X_supp_njs.h
--- a/nodejs/X_supp_njs.h Tue Nov 23 23:54:38 2010 +0800
+++ b/nodejs/X_supp_njs.h Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 nodejs/mbfly_njs.cc
--- a/nodejs/mbfly_njs.cc Tue Nov 23 23:54:38 2010 +0800
+++ b/nodejs/mbfly_njs.cc Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 src/X_main.c
--- a/src/X_main.c Tue Nov 23 23:54:38 2010 +0800
+++ b/src/X_main.c Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 src/X_supp.c
--- a/src/X_supp.c Tue Nov 23 23:54:38 2010 +0800
+++ b/src/X_supp.c Tue Nov 23 23:55:24 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,101 +1029,65 @@
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;
}
-void X_MB_remove_event(void *rt, int type, int fd)
+static void
+_x_supp_remove_event(mb_rt_t *rt, int hdl)
{
- 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;
- }
- }
-}
-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
- };
-/*! \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.
- */
-void _X_MB_handle_x_event_for_nodejs(void *rt) {
- handle_x_event((X_MB_runtime_t *)rt);
+ 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);
}
-/*! \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);
-}
+static int
+_x_supp_flush(mb_rt_t *rt) {
+ X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt;
+ int r;
-/*! \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;
#ifdef XSHM
XSHM_update(xmb_rt);
#endif
- return XFlush(xmb_rt->display);
+ 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;
}
-/*! \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;
-
- handle_single_x_event(xmb_rt, (XEvent *)evt);
-}
+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,
-/*! \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;
-
- no_more_event(xmb_rt);
-}
-
-/* @} */
+ _x_supp_reg_IO_factory,
+ _x_supp_reg_timer_factory,
+};
diff -r 4072a302b207 -r f26c4b621ec0 src/animate.c
--- a/src/animate.c Tue Nov 23 23:54:38 2010 +0800
+++ b/src/animate.c Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 src/mbaf/animated_menu.c
--- a/src/mbaf/animated_menu.c Tue Nov 23 23:54:38 2010 +0800
+++ b/src/mbaf/animated_menu.c Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 src/mbaf/mbapp.c
--- a/src/mbaf/mbapp.c Tue Nov 23 23:54:38 2010 +0800
+++ b/src/mbaf/mbapp.c Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 src/mbaf/mbbutton.c
--- a/src/mbaf/mbbutton.c Tue Nov 23 23:54:38 2010 +0800
+++ b/src/mbaf/mbbutton.c Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 src/sprite.c
--- a/src/sprite.c Tue Nov 23 23:54:38 2010 +0800
+++ b/src/sprite.c Tue Nov 23 23:55:24 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 4072a302b207 -r f26c4b621ec0 src/timer.c
--- a/src/timer.c Tue Nov 23 23:54:38 2010 +0800
+++ b/src/timer.c Tue Nov 23 23:55:24 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;
+}
+
+
+/* @} */