changeset 1044:5d4bc2a93c09

Merge from refine_backend_if branch
author Thinker K.F. Li <thinker@codemud.net>
date Tue, 23 Nov 2010 11:58:04 +0800
parents 18329b6f77a4 (current diff) 769921baf111 (diff)
children bf5adf1e275e
files
diffstat 26 files changed, 1967 insertions(+), 406 deletions(-) [+]
line wrap: on
line diff
--- /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.
+ */
--- 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;
 }
--- 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)
--- 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);
--- 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;
 }
--- 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);
 }
 
 /* @} */
Binary file img/highlevel.png has changed
--- /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 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.47 r22583"
+   sodipodi:docname="highlevel.svg">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective10" />
+    <inkscape:perspective
+       id="perspective2830"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 0.5 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective2852"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 0.5 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective2877"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 0.5 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective2905"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 0.5 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective2938"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 0.5 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective2987"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 0.5 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective3015"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 0.5 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective3043"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 0.5 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective3071"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 0.5 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective3099"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 0.5 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective3207"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 0.5 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective3256"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 0.5 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective3287"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 0.5 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective3339"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 0.5 : 1"
+       sodipodi:type="inkscape:persp3d" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1"
+     inkscape:cx="195.30247"
+     inkscape:cy="627.63476"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1440"
+     inkscape:window-height="900"
+     inkscape:window-x="-1"
+     inkscape:window-y="-1"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <g
+       id="g3128"
+       transform="matrix(0.49,0,0,0.49,150.2233,284.31953)"
+       inkscape:transform-center-x="0"
+       inkscape:transform-center-y="0"
+       inkscape:bbox-x="213.8497"
+       inkscape:bbox-y="653.14279"
+       inkscape:bbox-width="134.79007"
+       inkscape:bbox-height="31.352081"
+       inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         inkscape:bbox-height="31.352081"
+         inkscape:bbox-width="134.79007"
+         inkscape:bbox-y="653.14279"
+         inkscape:bbox-x="213.8497"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         y="173.17871"
+         x="132.52283"
+         height="58.637783"
+         width="269.73572"
+         id="rect2816"
+         style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" />
+      <text
+         inkscape:bbox-height="10.432598"
+         inkscape:bbox-width="120.12752"
+         inkscape:bbox-y="663.60253"
+         inkscape:bbox-x="221.18097"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         sodipodi:linespacing="125%"
+         id="text2818"
+         y="208.56694"
+         x="142.96393"
+         style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+         xml:space="preserve"><tspan
+           inkscape:bbox-height="10.432598"
+           inkscape:bbox-width="120.12752"
+           inkscape:bbox-y="663.60253"
+           inkscape:bbox-x="221.18097"
+           y="208.56694"
+           x="142.96393"
+           inkscape:transform-center-y="0"
+           inkscape:transform-center-x="0"
+           id="tspan2820"
+           sodipodi:role="line">rdman/paint/shapes</tspan></text>
+    </g>
+    <g
+       id="g3133"
+       transform="matrix(0,-0.49,0.49,0,449.04412,564.75137)"
+       inkscape:transform-center-x="0"
+       inkscape:transform-center-y="0"
+       inkscape:bbox-x="569.75296"
+       inkscape:bbox-y="549.7048"
+       inkscape:bbox-width="31.352081"
+       inkscape:bbox-height="134.79007"
+       inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         inkscape:bbox-height="134.79007"
+         inkscape:bbox-width="31.352081"
+         inkscape:bbox-y="549.70479"
+         inkscape:bbox-x="569.75296"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         y="249.01759"
+         x="129.39545"
+         height="58.637783"
+         width="269.73572"
+         id="rect2816-7"
+         style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" />
+      <text
+         inkscape:bbox-height="53.352578"
+         inkscape:bbox-width="8.3429199"
+         inkscape:bbox-y="590.42354"
+         inkscape:bbox-x="581.25754"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         sodipodi:linespacing="125%"
+         id="text2818-9"
+         y="286.53815"
+         x="208.87659"
+         style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+         xml:space="preserve"><tspan
+           inkscape:bbox-height="53.352578"
+           inkscape:bbox-width="8.3429199"
+           inkscape:bbox-y="590.42354"
+           inkscape:bbox-x="581.25754"
+           y="286.53815"
+           x="208.87659"
+           inkscape:transform-center-y="0"
+           inkscape:transform-center-x="0"
+           id="tspan2820-3"
+           sodipodi:role="line">observer</tspan></text>
+    </g>
+    <g
+       id="g3181"
+       transform="matrix(0.49,0,0,0.49,57.15012,178.96602)"
+       inkscape:transform-center-x="0"
+       inkscape:transform-center-y="0"
+       inkscape:bbox-x="352.12911"
+       inkscape:bbox-y="595.67724"
+       inkscape:bbox-width="134.79007"
+       inkscape:bbox-height="31.352081"
+       inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         inkscape:bbox-height="31.352081"
+         inkscape:bbox-width="134.79007"
+         inkscape:bbox-y="595.67724"
+         inkscape:bbox-x="352.12911"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         y="505.46249"
+         x="604.67096"
+         height="58.637783"
+         width="269.73572"
+         id="rect2816-7-8"
+         style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" />
+      <text
+         inkscape:bbox-height="10.516816"
+         inkscape:bbox-width="90.161436"
+         inkscape:bbox-y="606.09488"
+         inkscape:bbox-x="374.44342"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         sodipodi:linespacing="125%"
+         id="text2818-9-0"
+         y="540.76477"
+         x="647.24731"
+         style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+         xml:space="preserve"><tspan
+           inkscape:bbox-height="10.516816"
+           inkscape:bbox-width="90.161436"
+           inkscape:bbox-y="606.09488"
+           inkscape:bbox-x="374.44342"
+           y="540.76477"
+           x="647.24731"
+           inkscape:transform-center-y="0"
+           inkscape:transform-center-x="0"
+           id="tspan2820-3-2"
+           sodipodi:role="line">timer manager</tspan></text>
+    </g>
+    <g
+       id="g3143"
+       transform="matrix(0.49,0,0,0.49,-1.3250335,168.4974)"
+       inkscape:transform-center-x="0"
+       inkscape:transform-center-y="0"
+       inkscape:bbox-x="263.04767"
+       inkscape:bbox-y="711.11625"
+       inkscape:bbox-width="134.79007"
+       inkscape:bbox-height="31.352081"
+       inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         inkscape:bbox-height="31.352081"
+         inkscape:bbox-width="134.79007"
+         inkscape:bbox-y="711.11626"
+         inkscape:bbox-x="263.04767"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         y="291.23721"
+         x="542.20917"
+         height="58.637783"
+         width="269.73572"
+         id="rect2816-7-8-4"
+         style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" />
+      <text
+         inkscape:bbox-height="8.3429199"
+         inkscape:bbox-width="49.194277"
+         inkscape:bbox-y="722.62084"
+         inkscape:bbox-x="305.84557"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         sodipodi:linespacing="125%"
+         id="text2818-9-0-8"
+         y="328.75775"
+         x="625.03113"
+         style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+         xml:space="preserve"><tspan
+           inkscape:bbox-height="8.3429199"
+           inkscape:bbox-width="49.194277"
+           inkscape:bbox-y="722.62084"
+           inkscape:bbox-x="305.84557"
+           y="328.75775"
+           x="625.03113"
+           inkscape:transform-center-y="0"
+           inkscape:transform-center-x="0"
+           id="tspan2820-3-2-3"
+           sodipodi:role="line">backend</tspan></text>
+    </g>
+    <g
+       id="g3153"
+       transform="matrix(0.49,0,0,0.49,108.0819,221.28227)"
+       inkscape:transform-center-x="0"
+       inkscape:transform-center-y="0"
+       inkscape:bbox-x="213.8497"
+       inkscape:bbox-y="557.95824"
+       inkscape:bbox-width="134.79007"
+       inkscape:bbox-height="31.352081"
+       inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         inkscape:bbox-height="31.352081"
+         inkscape:bbox-width="134.79007"
+         inkscape:bbox-y="557.95824"
+         inkscape:bbox-x="213.8497"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         y="496.08035"
+         x="218.52568"
+         height="58.637783"
+         width="269.73572"
+         id="rect2816-7-8-9"
+         style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" />
+      <text
+         inkscape:bbox-height="10.516816"
+         inkscape:bbox-width="90.019316"
+         inkscape:bbox-y="568.37588"
+         inkscape:bbox-x="236.23509"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         sodipodi:linespacing="125%"
+         id="text2818-9-0-0"
+         y="531.38263"
+         x="260.54883"
+         style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+         xml:space="preserve"><tspan
+           inkscape:bbox-height="10.516816"
+           inkscape:bbox-width="90.019316"
+           inkscape:bbox-y="568.37588"
+           inkscape:bbox-x="236.23509"
+           y="531.38263"
+           x="260.54883"
+           inkscape:transform-center-y="0"
+           inkscape:transform-center-x="0"
+           id="tspan2820-3-2-5"
+           sodipodi:role="line">graphic engine</tspan></text>
+    </g>
+    <g
+       id="g3163"
+       transform="matrix(0.49,0,0,0.49,145.98816,39.516328)"
+       inkscape:transform-center-x="0"
+       inkscape:transform-center-y="0"
+       inkscape:bbox-x="352.12911"
+       inkscape:bbox-y="653.14278"
+       inkscape:bbox-width="134.79007"
+       inkscape:bbox-height="31.352081"
+       inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         inkscape:bbox-height="31.352081"
+         inkscape:bbox-width="134.79007"
+         inkscape:bbox-y="653.14278"
+         inkscape:bbox-x="352.12911"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         y="672.7771"
+         x="423.36884"
+         height="58.637783"
+         width="269.73572"
+         id="rect2816-7-8-9-2"
+         style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" />
+      <text
+         inkscape:bbox-height="8.3429199"
+         inkscape:bbox-width="48.688965"
+         inkscape:bbox-y="664.64735"
+         inkscape:bbox-x="395.17966"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         sodipodi:linespacing="125%"
+         id="text2818-9-0-0-2"
+         y="710.29767"
+         x="507.60876"
+         style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+         xml:space="preserve"><tspan
+           inkscape:bbox-height="8.3429199"
+           inkscape:bbox-width="48.688965"
+           inkscape:bbox-y="664.64735"
+           inkscape:bbox-x="395.17966"
+           y="710.29767"
+           x="507.60876"
+           inkscape:transform-center-y="0"
+           inkscape:transform-center-x="0"
+           id="tspan2820-3-2-5-7"
+           sodipodi:role="line">animate</tspan></text>
+    </g>
+    <g
+       id="g3168"
+       transform="matrix(0,-0.49,0.49,0,111.91294,803.04184)"
+       inkscape:transform-center-x="0"
+       inkscape:transform-center-y="0"
+       inkscape:bbox-x="494.66467"
+       inkscape:bbox-y="549.70479"
+       inkscape:bbox-width="31.352081"
+       inkscape:bbox-height="134.79007"
+       inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         inkscape:bbox-height="134.79007"
+         inkscape:bbox-width="31.352081"
+         inkscape:bbox-y="549.70479"
+         inkscape:bbox-x="494.66467"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         y="783.79901"
+         x="615.70251"
+         height="58.637783"
+         width="269.73572"
+         id="rect2816-7-8-9-2-3"
+         style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" />
+      <text
+         inkscape:bbox-height="78.82875"
+         inkscape:bbox-width="10.516816"
+         inkscape:bbox-y="577.68545"
+         inkscape:bbox-x="505.08231"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         sodipodi:linespacing="125%"
+         id="text2818-9-0-0-2-7"
+         y="819.10132"
+         x="668.28522"
+         style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+         xml:space="preserve"><tspan
+           inkscape:bbox-height="78.82875"
+           inkscape:bbox-width="10.516816"
+           inkscape:bbox-y="577.68545"
+           inkscape:bbox-x="505.08231"
+           y="819.10132"
+           x="668.28522"
+           inkscape:transform-center-y="0"
+           inkscape:transform-center-x="0"
+           id="tspan2820-3-2-5-7-9"
+           sodipodi:role="line">image loader</tspan></text>
+    </g>
+    <g
+       id="g3173"
+       transform="matrix(0,-0.49,0.49,0,141.02882,584.67276)"
+       inkscape:transform-center-x="0"
+       inkscape:transform-center-y="0"
+       inkscape:bbox-x="534.50744"
+       inkscape:bbox-y="549.70479"
+       inkscape:bbox-width="31.352081"
+       inkscape:bbox-height="134.79007"
+       inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         inkscape:bbox-height="134.79007"
+         inkscape:bbox-width="31.352081"
+         inkscape:bbox-y="549.70479"
+         inkscape:bbox-x="534.50743"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         y="805.69061"
+         x="170.05133"
+         height="58.637783"
+         width="269.73572"
+         id="rect2816-7-8-9-2-0"
+         style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" />
+      <text
+         inkscape:bbox-height="51.910332"
+         inkscape:bbox-width="9.8957031"
+         inkscape:bbox-y="591.14466"
+         inkscape:bbox-x="545.23563"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         sodipodi:linespacing="125%"
+         id="text2818-9-0-0-2-2"
+         y="840.35913"
+         x="250.10181"
+         style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+         xml:space="preserve"><tspan
+           inkscape:bbox-height="51.910332"
+           inkscape:bbox-width="9.8957031"
+           inkscape:bbox-y="591.14466"
+           inkscape:bbox-x="545.23563"
+           y="840.35913"
+           x="250.10181"
+           inkscape:transform-center-y="0"
+           inkscape:transform-center-x="0"
+           id="tspan2820-3-2-5-7-3"
+           sodipodi:role="line">property</tspan></text>
+    </g>
+    <g
+       id="g3158"
+       transform="matrix(0.49,0,0,0.49,174.74193,126.86394)"
+       inkscape:transform-center-x="0"
+       inkscape:transform-center-y="0"
+       inkscape:bbox-x="213.8497"
+       inkscape:bbox-y="595.67724"
+       inkscape:bbox-width="134.79007"
+       inkscape:bbox-height="31.352081"
+       inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         inkscape:bbox-height="31.352081"
+         inkscape:bbox-width="134.79007"
+         inkscape:bbox-y="595.67724"
+         inkscape:bbox-x="213.8497"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         y="611.79327"
+         x="82.48481"
+         height="58.637783"
+         width="269.73572"
+         id="rect2816-7-8-9-9"
+         style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" />
+      <text
+         inkscape:bbox-height="10.432598"
+         inkscape:bbox-width="78.333965"
+         inkscape:bbox-y="606.13697"
+         inkscape:bbox-x="242.07775"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         sodipodi:linespacing="125%"
+         id="text2818-9-0-0-9"
+         y="647.18152"
+         x="136.47473"
+         style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+         xml:space="preserve"><tspan
+           inkscape:bbox-height="10.432598"
+           inkscape:bbox-width="78.333965"
+           inkscape:bbox-y="606.13697"
+           inkscape:bbox-x="242.07775"
+           y="647.18152"
+           x="136.47473"
+           inkscape:transform-center-y="0"
+           inkscape:transform-center-x="0"
+           id="tspan2820-3-2-5-70"
+           sodipodi:role="line">element pool</tspan></text>
+    </g>
+    <g
+       id="g3148"
+       transform="matrix(0.49,0,0,0.49,36.985323,103.36979)"
+       inkscape:transform-center-x="0"
+       inkscape:transform-center-y="0"
+       inkscape:bbox-x="408.62703"
+       inkscape:bbox-y="711.11625"
+       inkscape:bbox-width="134.79007"
+       inkscape:bbox-height="31.352081"
+       inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         inkscape:bbox-height="31.352081"
+         inkscape:bbox-width="134.79007"
+         inkscape:bbox-y="711.11625"
+         inkscape:bbox-x="408.62703"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         y="424.1507"
+         x="761.12549"
+         height="58.637783"
+         width="269.73572"
+         id="rect2816-7-8-4-9"
+         style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:5.34605646" />
+      <text
+         inkscape:bbox-height="8.3429199"
+         inkscape:bbox-width="46.68877"
+         inkscape:bbox-y="722.62084"
+         inkscape:bbox-x="452.67768"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         sodipodi:linespacing="125%"
+         id="text2818-9-0-8-8"
+         y="461.67123"
+         x="846.50409"
+         style="font-size:22px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+         xml:space="preserve"><tspan
+           inkscape:bbox-height="8.3429199"
+           inkscape:bbox-width="46.68877"
+           inkscape:bbox-y="722.62084"
+           inkscape:bbox-x="452.67768"
+           y="461.67123"
+           x="846.50409"
+           inkscape:transform-center-y="0"
+           inkscape:transform-center-x="0"
+           id="tspan2820-3-2-3-6"
+           sodipodi:role="line">runtime</tspan></text>
+    </g>
+    <g
+       id="g3194"
+       transform="matrix(0.49,0,0,0.49,290.43922,204.63397)"
+       inkscape:transform-center-x="0"
+       inkscape:transform-center-y="0"
+       inkscape:bbox-x="222.3793"
+       inkscape:bbox-y="634.08892"
+       inkscape:bbox-width="111.6012"
+       inkscape:bbox-height="9.6956378"
+       inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         inkscape:bbox-height="9.6956378"
+         inkscape:bbox-width="111.6012"
+         inkscape:bbox-y="634.08891"
+         inkscape:bbox-x="222.3793"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         y="416.21155"
+         x="-138.8978"
+         height="19.787016"
+         width="227.75755"
+         id="rect3186"
+         style="fill:#cccccc;fill-opacity:1;stroke:none" />
+      <text
+         inkscape:bbox-height="6.7528125"
+         inkscape:bbox-width="21.877734"
+         inkscape:bbox-y="635.56033"
+         inkscape:bbox-x="267.24104"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         sodipodi:linespacing="125%"
+         id="text3190"
+         y="432.65582"
+         x="-49.218239"
+         style="font-size:24px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#800000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+         xml:space="preserve"><tspan
+           inkscape:bbox-height="6.7528125"
+           inkscape:bbox-width="21.877734"
+           inkscape:bbox-y="635.56033"
+           inkscape:bbox-x="267.24104"
+           y="432.65582"
+           x="-49.218239"
+           inkscape:transform-center-y="0"
+           inkscape:transform-center-x="0"
+           id="tspan3192"
+           sodipodi:role="line">use</tspan></text>
+    </g>
+    <g
+       id="g3243"
+       transform="matrix(0.49,0,0,0.49,164.01503,215.36088)"
+       inkscape:transform-center-x="0"
+       inkscape:transform-center-y="0"
+       inkscape:bbox-x="219.31448"
+       inkscape:bbox-y="691.17135"
+       inkscape:bbox-width="368.28064"
+       inkscape:bbox-height="9.6956378"
+       inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         inkscape:bbox-height="9.6956378"
+         inkscape:bbox-width="368.28064"
+         inkscape:bbox-y="691.17135"
+         inkscape:bbox-x="219.31448"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         y="277.82513"
+         x="112.85602"
+         height="19.787016"
+         width="751.59314"
+         id="rect3186-7"
+         style="fill:#cccccc;fill-opacity:1;stroke:none" />
+      <text
+         inkscape:bbox-height="6.7528125"
+         inkscape:bbox-width="21.877734"
+         inkscape:bbox-y="692.64277"
+         inkscape:bbox-x="392.51593"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         sodipodi:linespacing="125%"
+         id="text3190-6"
+         y="294.26941"
+         x="464.45337"
+         style="font-size:24px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#800000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+         xml:space="preserve"><tspan
+           inkscape:bbox-height="6.7528125"
+           inkscape:bbox-width="21.877734"
+           inkscape:bbox-y="692.64277"
+           inkscape:bbox-x="392.51593"
+           y="294.26941"
+           x="464.45337"
+           inkscape:transform-center-y="0"
+           inkscape:transform-center-x="0"
+           id="tspan3192-2"
+           sodipodi:role="line">use</tspan></text>
+    </g>
+    <g
+       id="g3194-7"
+       transform="matrix(0.49,0,0,0.49,431.78345,204.63397)"
+       inkscape:transform-center-x="0"
+       inkscape:transform-center-y="0"
+       inkscape:bbox-x="363.72353"
+       inkscape:bbox-y="634.08892"
+       inkscape:bbox-width="111.6012"
+       inkscape:bbox-height="9.6956378"
+       inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         inkscape:bbox-height="9.6956378"
+         inkscape:bbox-width="111.6012"
+         inkscape:bbox-y="634.08891"
+         inkscape:bbox-x="363.72353"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         y="416.21155"
+         x="-138.8978"
+         height="19.787016"
+         width="227.75755"
+         id="rect3186-0"
+         style="fill:#cccccc;fill-opacity:1;stroke:none" />
+      <text
+         inkscape:bbox-height="6.7528125"
+         inkscape:bbox-width="21.877734"
+         inkscape:bbox-y="635.56033"
+         inkscape:bbox-x="408.58527"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         sodipodi:linespacing="125%"
+         id="text3190-3"
+         y="432.65582"
+         x="-49.218239"
+         style="font-size:24px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#800000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+         xml:space="preserve"><tspan
+           inkscape:bbox-height="6.7528125"
+           inkscape:bbox-width="21.877734"
+           inkscape:bbox-y="635.56033"
+           inkscape:bbox-x="408.58527"
+           y="432.65582"
+           x="-49.218239"
+           inkscape:transform-center-y="0"
+           inkscape:transform-center-x="0"
+           id="tspan3192-9"
+           sodipodi:role="line">use</tspan></text>
+    </g>
+    <g
+       id="g3404"
+       transform="translate(-10.31929,0)"
+       inkscape:transform-center-x="0"
+       inkscape:transform-center-y="0"
+       inkscape:bbox-x="211.22823"
+       inkscape:bbox-y="781.89572"
+       inkscape:bbox-width="384.44808"
+       inkscape:bbox-height="31.35208"
+       inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         inkscape:bbox-height="31.35208"
+         inkscape:bbox-width="384.44808"
+         inkscape:bbox-y="781.89572"
+         inkscape:bbox-x="211.22823"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         y="241.26933"
+         x="223.70247"
+         height="27.042181"
+         width="380.13818"
+         id="rect2816-7-9"
+         style="fill:#003380;fill-opacity:1;stroke:#00112b;stroke-width:4.30989933" />
+      <text
+         inkscape:bbox-height="10.432597"
+         inkscape:bbox-width="67.943473"
+         inkscape:bbox-y="792.35545"
+         inkscape:bbox-x="369.48054"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         sodipodi:linespacing="125%"
+         id="text2818-9-1"
+         y="257.7644"
+         x="379.74719"
+         style="font-size:10.77999973px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+         xml:space="preserve"><tspan
+           inkscape:bbox-height="10.432597"
+           inkscape:bbox-width="67.943473"
+           inkscape:bbox-y="792.35545"
+           inkscape:bbox-x="369.48054"
+           y="257.7644"
+           x="379.74719"
+           inkscape:transform-center-y="0"
+           inkscape:transform-center-x="0"
+           id="tspan2820-3-7"
+           sodipodi:role="line">Application</tspan></text>
+    </g>
+    <g
+       id="g3396"
+       transform="translate(-10,0)"
+       inkscape:transform-center-x="0"
+       inkscape:transform-center-y="0"
+       inkscape:bbox-x="210.06335"
+       inkscape:bbox-y="765.72395"
+       inkscape:bbox-width="386.77783"
+       inkscape:bbox-height="9.6956377"
+       inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90">
+      <rect
+         inkscape:bbox-height="9.6956377"
+         inkscape:bbox-width="386.77783"
+         inkscape:bbox-y="765.72395"
+         inkscape:bbox-x="210.06335"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         y="276.9426"
+         x="220.06335"
+         height="9.6956377"
+         width="386.77783"
+         id="rect3186-7-3"
+         style="fill:#cccccc;fill-opacity:1;stroke:none" />
+      <text
+         inkscape:bbox-height="6.7528126"
+         inkscape:bbox-width="21.877735"
+         inkscape:bbox-y="767.19538"
+         inkscape:bbox-x="392.51342"
+         inkscape:transform-center-y="0"
+         inkscape:transform-center-x="0"
+         sodipodi:linespacing="125%"
+         id="text3190-6-6"
+         y="285.00027"
+         x="401.59467"
+         style="font-size:11.76000023px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#800000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+         xml:space="preserve"><tspan
+           inkscape:bbox-height="6.7528126"
+           inkscape:bbox-width="21.877735"
+           inkscape:bbox-y="767.19538"
+           inkscape:bbox-x="392.51342"
+           y="285.00027"
+           x="401.59467"
+           inkscape:transform-center-y="0"
+           inkscape:transform-center-x="0"
+           id="tspan3192-2-5"
+           sodipodi:role="line">use</tspan></text>
+    </g>
+    <rect
+       style="fill:none;stroke:#999999;stroke-width:0.83045471"
+       id="rect3375"
+       width="401.16956"
+       height="206.16954"
+       x="206.91522"
+       y="301.2774"
+       inkscape:transform-center-x="0"
+       inkscape:transform-center-y="0"
+       inkscape:bbox-x="206.49999"
+       inkscape:bbox-y="544.50001"
+       inkscape:bbox-width="402.00001"
+       inkscape:bbox-height="207"
+       inkscape:export-filename="/home/thinker/progm/MadButterfly/img/highlevel.png"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90" />
+  </g>
+</svg>
--- 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_ */
--- 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
--- 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)
--- 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);
--- /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_ */
--- /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_ */
--- 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_ */
--- 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 <stdio.h>
+#include <string.h>
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 #include <ev.h>
 #include "mb_X_supp.h"
 #include "mb_tools.h"
+#include <mb_backend.h>
 #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;
 }
--- 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 <ev.h>
+#include <mb_backend.h>
 
 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_ */
--- 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.
--- 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);
--- 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;i<rt->n_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;i<rt->n_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;i<xmb_rt->n_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;i<xmb_rt->n_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;i<xmb_rt->n_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 */
--- 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 <CUnit/Basic.h>
 
 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) {
--- 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));
 }
 
--- 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 <mb.h>
 #include <mb_af.h>
+#include <mb_backend.h>
 
 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);
 }
--- 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);
 }
--- 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)
--- 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 <string.h>
 #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;
+}
+
+
+/* @} */