changeset 1124:b5ff72dbc910

merge
author wycc
date Thu, 09 Dec 2010 07:48:46 +0800
parents aad659b6b625 (current diff) 17cbb862a8c6 (diff)
children 5b2394f67ad0
files
diffstat 23 files changed, 1022 insertions(+), 116 deletions(-) [+]
line wrap: on
line diff
--- a/configure.ac	Thu Dec 09 07:48:08 2010 +0800
+++ b/configure.ac	Thu Dec 09 07:48:46 2010 +0800
@@ -83,6 +83,7 @@
         [case "${withval}" in
             ('X') backend='X'; default_graphic_engine="cairo" ;;
             ('dfb') backend='dfb'; default_graphic_engine="dfb" ;;
+	    ('console') backend='console'; default_graphic_engine="openvg" ;;
             ('no') backend='none'; default_graphic_engine="cairo" ;;
             (*) AC_MSG_ERROR([bad value ${withval} for --with-backend]) ;;
         esac],[backend='X'; default_graphic_engine="cairo"])
@@ -105,7 +106,7 @@
 	[case "${withval}" in
 	    ('cairo') image_loader="cairo" ;;
 	    ('imlib2') image_loader="imlib2" ;;
-	    ('no') image_loader="none" ;;
+	    ('dummy') image_loader="dummy" ;;
 	    (*) AC_MSG_ERROR([bad value ${withval} for --with-image-loader])
 	    	;;
 	esac], [image_loader="cairo"])
@@ -123,8 +124,9 @@
 
 # Validate options
 [case "${backend}-${graphic_engine}-${image_loader}" in
-    X-cairo-*|X-openvg-imlib2) ;;
+    X-cairo-*|X-openvg-imlib2|X-openvg-dummy) ;;
     dfb-cairo-*) ;;
+    console-openvg-imlib2|console-openvg-dummy) ;;
     none-*-*) ;;
     *)] AC_MSG_ERROR([The combination of --with-backend=${backend}, --with-graphic-engine=${graphic_engine} and --with-image-loader=${image_loader} is invalid]) [;;
 esac]
@@ -185,6 +187,13 @@
     AC_DEFINE([DFB_BACKEND])
 [fi]
 
+AM_CONDITIONAL([CONSOLE_BACKEND],
+	[test x$backend = x'console' -a x"${graphic_engine}" = x"openvg"])
+
+[if [ x"${backend}" = x'console' -a x"${graphic_engine}" = x"openvg" ]; then]
+    AC_DEFINE([CONSOLE_BACKEND])
+[fi]
+
 AM_CONDITIONAL([CAIRO_IMG_LOADER],
 	[test x"${image_loader}" = x"cairo"])
 
@@ -202,6 +211,13 @@
     AC_DEFINE([IMLIB2_IMG_LOADER])
 [fi]
 
+AM_CONDITIONAL([DUMMY_IMG_LOADER],
+	[test x"${image_loader}" = x"dummy"])
+
+[if [ x"${image_loader}" = x"dummy" ]; then]
+    AC_DEFINE([DUMMY_IMG_LOADER])
+[fi]
+
 AM_CONDITIONAL([XSHM],
 	[test x"${xshm}" = xtrue -a x"${graphic_engine}" = x"cairo" -a x$backend = x'X'])
 
@@ -252,8 +268,10 @@
 AH_TEMPLATE([DFB_GRAPH_ENGINE], [Enable DirectFB Graphic Engine])
 AH_TEMPLATE([CAIRO_IMG_LOADER], [Enable Cairo Image Loader])
 AH_TEMPLATE([IMLIB2_IMG_LOADER], [Enable Imlib2 Image Loader])
+AH_TEMPLATE([DUMMY_IMG_LOADER], [Enable Dummy Image Loader])
 AH_TEMPLATE([X_BACKEND], [Enable X backend])
 AH_TEMPLATE([DFB_BACKEND], [Enable DirectFB backend])
+AH_TEMPLATE([CONSOLE_BACKEND], [Enable console backend])
 AH_TEMPLATE([XSHM], [Enable XSHM])
 
 AC_OUTPUT
--- a/examples/calculator/main.c	Thu Dec 09 07:48:08 2010 +0800
+++ b/examples/calculator/main.c	Thu Dec 09 07:48:46 2010 +0800
@@ -179,7 +179,11 @@
     calculator_scr_t *calculator_scr;
     calc_data_t calc_data;
 
+#ifdef CONSOLE_BACKEND
+    rt = mb_runtime_new(NULL, 300, 400);
+#else
     rt = mb_runtime_new(":0.0", 300, 400);
+#endif
 
     rdman = mb_runtime_rdman(rt);
     calculator_scr = calculator_scr_new(rdman, rdman->root_coord);
@@ -187,6 +191,8 @@
     calc_data.rt = rt;
     calc_data.code = calculator_scr;
     setup_observers(&calc_data);
+    
+    mb_runtime_flush(rt);
 
     mb_runtime_event_loop(rt);
 
--- a/examples/tank/enemy.c	Thu Dec 09 07:48:08 2010 +0800
+++ b/examples/tank/enemy.c	Thu Dec 09 07:48:46 2010 +0800
@@ -11,6 +11,38 @@
 };
 typedef struct _enemy enemy_t;
 
+/*! \brief Pheromone Map trace the freq. the enemy tanks moving on an area.
+ *
+ * Every time a tank move to an area, it leaves 100 units of pheromone
+ * on the area.  And 9 of 10 pheromone are removed from the area for
+ * every time slice (1/3 second).  The max value of phereomone in an
+ * area is 991.
+ */
+static int pheromone_map[MAP_H][MAP_W];
+
+static void
+init_pheromone_map(void) {
+    int i, j;
+    
+    for(i = 0; i < MAP_H; i++)
+	for(j = 0; j < MAP_W; j++)
+	    pheromone_map[i][j] = 0;
+}
+
+static void
+remove_pheromone(void) {
+    int i, j;
+    
+    for(i = 0; i < MAP_H; i++)
+	for(j = 0; j < MAP_W; j++)
+	    pheromone_map[i][j] = pheromone_map[i][j] * 9 / 10;
+}
+
+static void
+leave_pheromone(int x, int y) {
+    pheromone_map[y][x] += 100;
+}
+
 /* \brief Fire and move to the target tank if they are in a row or column.
  */
 static int
@@ -75,6 +107,8 @@
 	if(me->direction == target_dir && me->bullet == NULL)
 	    tank_fire_bullet(tank_rt, me);
 	tank_move(me, target_dir, tank_rt);
+	
+	leave_pheromone(me->map_x, me->map_y);
 	return 1;
     }
 
@@ -95,8 +129,11 @@
     int x, y;
     int i, tank_i;
     int dir, chk_dir;
+    int interest_areas[4];
+    int all_interest;
+    int min_interest;
     int possibles;
-    int which_dir;
+    int interest_dir;
     
     me = enemy->tank;
     tanks = tank_rt->tanks;
@@ -106,15 +143,18 @@
 	x = me->map_x + shift_xy[i][0];
 	y = me->map_y + shift_xy[i][1];
 	
+	interest_areas[i] = 0;
+	
 	/* Check obstacles */
 	if(x == -1 || y == -1 || x >= MAP_W || y >= MAP_H) {
 	    /* Out of range */
 	    status[i] = SOMETHING;
 	    continue;
 	}
-	if(map[y][x] == MUD)
+	if(map[y][x] == MUD) {
 	    status[i] = NOTHING;
-	else
+	    interest_areas[i] = 992 - pheromone_map[y][x];
+	} else
 	    status[i] = SOMETHING;
 	
 	/* Check tanks */
@@ -134,6 +174,8 @@
     }
     if(i == 4) {		/* Status is not changed */
 	tank_move(me, me->direction, tank_rt);
+	
+	leave_pheromone(me->map_x, me->map_y);
 	return;
     }
 
@@ -155,12 +197,22 @@
 	break;
     }
 
+    /* Compute itnerest for nearby areas */
     possibles = 0;
+    all_interest = 0;
+    min_interest = 992;
     for(i = 0; i < 3; i++) {
 	chk_dir = (dir + 3  + i) % 4;
-	if(status[chk_dir] == NOTHING)
+	if(status[chk_dir] == NOTHING) {
 	    possibles++;
+	    all_interest += interest_areas[chk_dir];
+	    if(min_interest > interest_areas[chk_dir])
+		min_interest = interest_areas[chk_dir];
+	}
     }
+    all_interest -= (min_interest * possibles) + possibles;
+    for(i = 0; i < 4; i++)
+	interest_areas[i] = interest_areas[i] - min_interest + 1;
 
     if(possibles == 0) {	/* Only can move backward */
 	switch(me->direction) {
@@ -177,15 +229,17 @@
 	    tank_move(me, TD_RIGHT, tank_rt);
 	    break;
 	}
+	
+	leave_pheromone(me->map_x, me->map_y);
 	return;
     }
     
-    which_dir = (rand() % possibles) + 1;
+    interest_dir = (rand() % all_interest) + 1;
     for(i = 0; i < 3; i++) {
 	chk_dir = (dir + 3  + i) % 4;
 	if(status[chk_dir] == NOTHING) {
-	    which_dir--;
-	    if(which_dir == 0)
+	    interest_dir -= interest_areas[chk_dir];
+	    if(interest_dir <= 0)
 		break;
 	}
     }
@@ -203,6 +257,8 @@
 	tank_move(me, TD_UP, tank_rt);
 	break;
     }
+    
+    leave_pheromone(me->map_x, me->map_y);
 }
 
 static void
@@ -229,17 +285,18 @@
 static enemy_t *enemies = NULL;
 static mb_timer_man_t *timer_man;
 
+static void enemy_tick(int hdl, const mb_timeval_t *tmo,
+		       const mb_timeval_t *now, void *data);
+
 /*! \brief Drive every enemy tanks.
  */
 static void
-enemy_tank_driver(int hdl, const mb_timeval_t *tmo,
-		  const mb_timeval_t *now, void *data) {
-    tank_rt_t *tank_rt = (tank_rt_t *)data;
+enemy_tank_driver(tank_rt_t *tank_rt) {
     enemy_t *enemy;
     int n_enemy;
     mb_timeval_t timeout, addend;
     int i;
-    
+
     n_enemy = tank_rt->n_enemy;
     for(i = 0; i < n_enemy; i++) {
 	enemy = enemies + i;
@@ -250,7 +307,16 @@
     get_now(&timeout);
     MB_TIMEVAL_SET(&addend, 0, 300000);
     MB_TIMEVAL_ADD(&timeout, &addend);
-    mb_timer_man_timeout(timer_man, &timeout, enemy_tank_driver, tank_rt);
+    mb_timer_man_timeout(timer_man, &timeout, enemy_tick, tank_rt);
+}
+
+static void
+enemy_tick(int hdl, const mb_timeval_t *tmo,
+	   const mb_timeval_t *now, void *data) {
+    tank_rt_t *tank_rt = (tank_rt_t *)data;
+    
+    remove_pheromone();
+    enemy_tank_driver(tank_rt);
 }
 
 /*! \brief Start a timer for enemy tank driver.
@@ -264,7 +330,7 @@
     get_now(&timeout);
     MB_TIMEVAL_SET(&addend, 0, 300000);
     MB_TIMEVAL_ADD(&timeout, &addend);
-    mb_timer_man_timeout(timer_man, &timeout, enemy_tank_driver, tank_rt);
+    mb_timer_man_timeout(timer_man, &timeout, enemy_tick, tank_rt);
 }
 
 void
--- a/examples/tank/tank_main.c	Thu Dec 09 07:48:08 2010 +0800
+++ b/examples/tank/tank_main.c	Thu Dec 09 07:48:46 2010 +0800
@@ -508,7 +508,7 @@
     } while(0)
 
 static void keyboard_handler(event_t *event, void *arg) {
-    X_kb_event_t *xkey = (X_kb_event_t *)event;
+    mb_kb_event_t *xkey = (mb_kb_event_t *)event;
     tank_rt_t *tank_rt = (tank_rt_t *)arg;
     int direction;
 
@@ -662,7 +662,11 @@
     mb_rt_t *rt;
     tank_rt_t tank_rt;
 
+#ifdef CONSOLE_BACKEND
+    rt = mb_runtime_new(NULL, 800, 600);
+#else
     rt = mb_runtime_new(":0.0", 800, 600);
+#endif
 
     initial_tank(&tank_rt, rt);
     
--- a/include/mb_X_supp.h	Thu Dec 09 07:48:08 2010 +0800
+++ b/include/mb_X_supp.h	Thu Dec 09 07:48:46 2010 +0800
@@ -4,26 +4,6 @@
 #define __X_SUPP_H_
 
 #include <X11/Xlib.h>
-#include "mb_types.h"
-#include "mb_timer.h"
-#include "mb_redraw_man.h"
-#include "mb_img_ldr.h"
-
-/*! \ingroup xkb
- * @{
- */
-typedef struct _X_kb_info X_kb_info_t;
-
-struct _X_kb_event {
-    event_t event;
-    int keycode;
-    int sym;
-};
-typedef struct _X_kb_event X_kb_event_t;
-
-/* @} */
-
-typedef struct _X_supp_runtime X_supp_runtime_t;
 
 typedef Window MB_WINDOW;
 typedef Display *MB_DISPLAY;
--- a/include/mb_ani_menu.h	Thu Dec 09 07:48:08 2010 +0800
+++ b/include/mb_ani_menu.h	Thu Dec 09 07:48:46 2010 +0800
@@ -18,7 +18,7 @@
 	void (*callback)(struct _mb_animated_menu *m, int sel);
 	void (*update_callback)(struct _mb_animated_menu *m, int sel);
 	mb_progm_t *progm;
-	X_kb_event_t pending_keys[16];
+	mb_kb_event_t pending_keys[16];
     int pending_pos, pending_last;
 } mb_animated_menu_t;
 /** \brief Create an instace of animated menu.
--- a/include/mb_backend.h	Thu Dec 09 07:48:08 2010 +0800
+++ b/include/mb_backend.h	Thu Dec 09 07:48:46 2010 +0800
@@ -16,6 +16,10 @@
 #inclde "mb_dfb_supp.h"
 #endif
 
+#ifdef CONSOLE_BACKEND
+#include "mb_cons_supp.h"
+#endif
+
 struct _mb_rt;
 typedef struct _mb_rt mb_rt_t;
 
--- a/include/mb_config.h.in	Thu Dec 09 07:48:08 2010 +0800
+++ b/include/mb_config.h.in	Thu Dec 09 07:48:46 2010 +0800
@@ -21,6 +21,9 @@
 /* Enable Imlib2 Image Loader */
 #undef IMLIB2_IMG_LOADER
 
+/* Enable Dummy Image Loader */
+#undef DUMMY_IMG_LOADER
+
 /* Enable sh_text */
 #undef SH_TEXT
 
@@ -33,4 +36,10 @@
 /* Enable DirectFB backend */
 #undef DFB_BACKEND
 
+/* Enable console backend */
+#undef CONSOLE_BACKEND
+
+/* Enable XSHM */
+#undef XSHM
+
 #endif /* __MB_CONFIG_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/mb_cons_supp.h	Thu Dec 09 07:48:46 2010 +0800
@@ -0,0 +1,9 @@
+// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*-
+// vim: sw=4:ts=8:sts=4
+#ifndef __CONS_SUPP_H_
+#define __CONS_SUPP_H_
+
+typedef void *MB_WINDOW;
+typedef void *MB_DISPLAY;
+
+#endif
--- a/include/mb_graph_engine_cairo.h	Thu Dec 09 07:48:08 2010 +0800
+++ b/include/mb_graph_engine_cairo.h	Thu Dec 09 07:48:46 2010 +0800
@@ -26,7 +26,6 @@
 #define mbe_image_surface_get_width cairo_image_surface_get_width
 #define mbe_image_surface_get_data cairo_image_surface_get_data
 #define mbe_scaled_font_reference cairo_scaled_font_reference
-#define mbe_win_surface_create cairo_xlib_surface_create
 #define mbe_scaled_font_destroy cairo_scaled_font_destroy
 #define mbe_font_face_reference cairo_font_face_reference
 #define mbe_font_face_destroy cairo_font_face_destroy
@@ -57,6 +56,7 @@
 #define mbe_stroke cairo_stroke
 #define mbe_create cairo_create
 #define mbe_paint cairo_paint
+#define mbe_flush(canvas)
 #define mbe_save cairo_save
 #define mbe_fill cairo_fill
 #define mbe_init()
@@ -78,6 +78,12 @@
 }
 
 
+extern mbe_surface_t *mbe_win_surface_create(void *display,
+					     void *drawable,
+					     int fmt,
+					     int width,
+					     int height);
+
 extern mbe_font_face_t * mbe_query_font_face(const char *family,
 					     int slant, int weight);
 extern void mbe_free_font_face(mbe_font_face_t *face);
--- a/include/mb_graph_engine_openvg.h	Thu Dec 09 07:48:08 2010 +0800
+++ b/include/mb_graph_engine_openvg.h	Thu Dec 09 07:48:46 2010 +0800
@@ -12,8 +12,8 @@
  * @{
  */
 #define mbe_scaled_font_text_extents(scaled, utf8, extents)
-#define mbe_image_surface_get_stride(surface) (20)
-#define mbe_image_surface_get_format(surface) ((mb_img_fmt_t)0)
+#define mbe_image_surface_get_stride(surface) ((surface)->w * 4)
+#define mbe_image_surface_get_format(surface) ((surface)->fmt)
 #define mbe_image_surface_get_height(surface) (surface)->h
 #define mbe_image_surface_get_width(surface) (surface)->w
 #define mbe_image_surface_get_data(surface) ((unsigned char *)NULL)
@@ -207,9 +207,12 @@
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 
-extern mbe_surface_t *mbe_win_surface_create(Display *display,
-					     Drawable drawable,
-					     Visual *visual,
+/*
+ * TODO: define a proper type for display and drawable.
+ */
+extern mbe_surface_t *mbe_win_surface_create(void *display,
+					     void *drawable,
+					     int fmt,
 					     int width, int height);
 #endif
 
@@ -223,6 +226,7 @@
 extern void mbe_surface_destroy(mbe_surface_t *surface);
 
 extern void mbe_copy_source(mbe_t *src_canvas, mbe_t *dst_canvas);
+extern void mbe_flush(mbe_t *canvas);
 extern mbe_t *mbe_create(mbe_surface_t *surface);
 extern void mbe_destroy(mbe_t *canvas);
 extern void mbe_paint_with_alpha(mbe_t *canvas, co_comp_t alpha);
--- a/include/mb_observer.h	Thu Dec 09 07:48:08 2010 +0800
+++ b/include/mb_observer.h	Thu Dec 09 07:48:46 2010 +0800
@@ -82,6 +82,13 @@
     observer_t *observer; /*!< \brief Observer been added or removed. */
 };
 
+struct _mb_kb_event {
+    event_t event;
+    int keycode;
+    int sym;
+};
+typedef struct _mb_kb_event mb_kb_event_t;
+
 /*! \brief Observer factory.
  *
  * It provides functions for allocation of subject and observer objects,
--- a/nodejs/observer.cc	Thu Dec 09 07:48:08 2010 +0800
+++ b/nodejs/observer.cc	Thu Dec 09 07:48:46 2010 +0800
@@ -31,7 +31,7 @@
 static void
 xnjsmb_event_mod(Handle<Object> self, event_t *evt) {
     mouse_event_t *mevt;
-    X_kb_event_t *xkbevt;
+    mb_kb_event_t *xkbevt;
 
     switch(evt->type) {
     case EVT_ANY:
@@ -49,7 +49,7 @@
 
     case EVT_KB_PRESS:
     case EVT_KB_RELEASE:
-	xkbevt = (X_kb_event_t *)evt;
+	xkbevt = (mb_kb_event_t *)evt;
 	SET(self, "keycode", Integer::New(xkbevt->keycode));
 	SET(self, "sym", Integer::New(xkbevt->sym));
 	break;
--- a/src/Makefile.am	Thu Dec 09 07:48:08 2010 +0800
+++ b/src/Makefile.am	Thu Dec 09 07:48:46 2010 +0800
@@ -45,6 +45,10 @@
 libmbfly_la_SOURCES += dfb_supp.c
 endif
 
+if CONSOLE_BACKEND
+libmbfly_la_SOURCES += cons_supp.c
+endif
+
 if CAIRO_IMG_LOADER
 libmbfly_la_SOURCES += img_ldr.c
 endif
@@ -56,6 +60,10 @@
 libmbfly_la_LDFLAGS += @imlib2_LIBS@
 endif
 
+if DUMMY_IMG_LOADER
+libmbfly_la_SOURCES += img_ldr_dummy.c
+endif
+
 if CAIRO_GRAPH_ENGINE
 libmbfly_la_SOURCES += graph_engine_cairo.c
 
--- a/src/X_supp.c	Thu Dec 09 07:48:08 2010 +0800
+++ b/src/X_supp.c	Thu Dec 09 07:48:46 2010 +0800
@@ -18,7 +18,6 @@
 #include <sys/ipc.h>
 #include <sys/shm.h>
 #include <X11/extensions/XShm.h>
-static void XSHM_update(X_supp_runtime_t *xmb_rt);
 #endif
 
 #define ERR -1
@@ -40,6 +39,7 @@
     subject_t *kbevents;
     observer_factory_t *observer_factory;
 };
+typedef struct _X_kb_info X_kb_info_t;
 
 /* @} */
 
@@ -80,6 +80,7 @@
     int mx, my;		       /* Position of last motion event */
     int mbut_state;	       /* Button state of last motion event */
 };
+typedef struct _X_supp_runtime X_supp_runtime_t;
 
 static void _x_supp_handle_x_event(X_supp_runtime_t *rt);
 
@@ -160,6 +161,10 @@
     xmb_io_man->monitors[io_hdl].type = MB_IO_DUMMY;
 }
 
+#ifdef XSHM
+static void XSHM_update(X_supp_runtime_t *xmb_rt);
+#endif
+
 /*! \brief Handle connection coming data and timeout of timers.
  *
  * \param display is a Display returned by XOpenDisplay().
@@ -321,7 +326,7 @@
 static void X_kb_handle_event(X_kb_info_t *kbinfo, XKeyEvent *xkey) {
     unsigned int code;
     int sym;
-    X_kb_event_t event;
+    mb_kb_event_t event;
 
     code = xkey->keycode;
     sym = keycode2sym(kbinfo, code);
@@ -755,6 +760,48 @@
 }
 #endif /* XSHM */
 
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+static int
+_get_img_fmt_from_xvisual(Display *display, Visual *visual) {
+    VisualID visual_id;
+    XVisualInfo temp;
+    XVisualInfo *infos;
+    int n;
+    int fmt = -1;
+    
+    visual_id = XVisualIDFromVisual(visual);
+    temp.visualid = visual_id;
+    infos = XGetVisualInfo(display, VisualIDMask, &temp, &n);
+    if(n != 1)
+	return -1;
+
+    switch(infos->depth) {
+    case 32:
+	fmt = MB_IFMT_ARGB32;
+	break;
+	
+    case 24:
+	fmt = MB_IFMT_RGB24;
+	break;
+	
+    case 16:
+	fmt = MB_IFMT_RGB16_565;
+	break;
+	
+    case 8:
+	fmt = MB_IFMT_A8;
+	break;
+	
+    case 1:
+	fmt = MB_IFMT_A1;
+	break;
+    }
+
+    return fmt;
+}
+
 /*! \brief Initialize a MadButterfy runtime for Xlib.
  *
  * This one is very like _x_supp_init(), except it accepts a
@@ -772,6 +819,7 @@
     mb_img_ldr_t *img_ldr;
     int w, h;
     int disp_fd;
+    int fmt;
 
     w = xmb_rt->w;
     h = xmb_rt->h;
@@ -785,17 +833,24 @@
     xmb_rt->surface =
 	mbe_image_surface_create(MB_IFMT_ARGB32, w, h);
 
-    if(xmb_rt->backend_surface == NULL) /* xshm_init() may create one */
+    if(xmb_rt->backend_surface == NULL) { /* xshm_init() may create one */
+	fmt = _get_img_fmt_from_xvisual(xmb_rt->display, xmb_rt->visual);
+	if(fmt == -1)
+	    return ERR;
+    
 	xmb_rt->backend_surface =
 	    mbe_win_surface_create(xmb_rt->display,
 				   xmb_rt->win,
-				   xmb_rt->visual,
+				   fmt,
 				   w, h);
+    }
 
     xmb_rt->cr = mbe_create(xmb_rt->surface);
     xmb_rt->backend_cr = mbe_create(xmb_rt->backend_surface);
     
     xmb_rt->rdman = (redraw_man_t *)malloc(sizeof(redraw_man_t));
+    xmb_rt->rdman->w = w;
+    xmb_rt->rdman->h = h;
     redraw_man_init(xmb_rt->rdman, xmb_rt->cr, xmb_rt->backend_cr);
     /* FIXME: This is a wired loopback reference. This is inly
      *        required when we need to get the xmb_rt->tman for the
--- a/src/animate.c	Thu Dec 09 07:48:08 2010 +0800
+++ b/src/animate.c	Thu Dec 09 07:48:46 2010 +0800
@@ -246,7 +246,7 @@
 #endif /* UNITTEST */
     mb_timeval_t next_tmo;
     mb_word_t *word;
-    mb_timer_t *timer;
+    int timer;
     int i;
 
     MB_TIMEVAL_SET(&next_tmo, 0, STEP_INTERVAL);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cons_supp.c	Thu Dec 09 07:48:46 2010 +0800
@@ -0,0 +1,667 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+#include "mb_graph_engine.h"
+#include "mb_redraw_man.h"
+#include "mb_timer.h"
+#include "mb_cons_supp.h"
+#include "mb_backend.h"
+#include "mb_backend_utils.h"
+#include "config.h"
+
+#define ERR -1
+#define OK 0
+
+#define FALSE 0
+#define TRUE 1
+
+#define ASSERT(x)
+
+#define ONLY_MOUSE_MOVE_RAW 1
+
+typedef int keysym;
+
+static mb_timer_factory_t *_timer_factory = &tman_timer_factory;
+
+/*! \ingroup console_kb
+ * @{
+ */
+struct _cons_kb_info {
+    int kb_fd;
+    
+    int keycode_min, keycode_max;
+    int ksym_per_code;
+    keysym *syms;
+    subject_t *kbevents;
+    observer_factory_t *observer_factory;
+};
+typedef struct _cons_kb_info cons_kb_info_t;
+
+/* @} */
+
+struct _cons_supp_runtime {
+    MB_DISPLAY display;
+    MB_WINDOW win;
+    
+    mbe_surface_t *surface;
+    mbe_t *cr;
+    redraw_man_t *rdman;
+    mb_img_ldr_t *img_ldr;
+    int w, h;
+
+    cons_kb_info_t kbinfo;
+    mb_IO_man_t *io_man;
+    mb_timer_man_t *timer_man;
+
+#ifndef ONLY_MOUSE_MOVE_RAW
+    /* States */
+    shape_t *last;
+#endif
+
+    /* For handle connection */
+    int io_hdl;
+
+    /*
+     * Following variables are used by handle_single_cons_event()
+     */
+    int last_evt_type;	       /* Type of last event */
+    int ex1, ey1, ex2, ey2;    /* Aggregate expose events */
+    int mx, my;		       /* Position of last motion event */
+    int mbut_state;	       /* Button state of last motion event */
+};
+typedef struct _cons_supp_runtime cons_supp_runtime_t;
+
+static void _cons_supp_handle_cons_event(cons_supp_runtime_t *rt);
+
+/*! \defgroup cons_supp_io IO manager for console.
+ * @{
+ */
+#define MAX_MONITORS 200
+
+typedef struct {
+    int type;
+    int fd;
+    mb_IO_cb_t cb;
+    void *data;
+}  monitor_t;
+
+struct _cons_supp_IO_man {
+    mb_IO_man_t io_man;
+    monitor_t monitors[MAX_MONITORS];
+    int n_monitor;
+};
+
+static int _cons_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 _cons_supp_io_man_unreg(struct _mb_IO_man *io_man, int io_hdl);
+static mb_IO_man_t *_cons_supp_io_man_new(void);
+static void _cons_supp_io_man_free(mb_IO_man_t *io_man);
+
+static mb_IO_factory_t _cons_supp_default_io_factory = {
+    _cons_supp_io_man_new,
+    _cons_supp_io_man_free
+};
+static mb_IO_factory_t *_io_factory = &_cons_supp_default_io_factory;
+
+static struct _cons_supp_IO_man _default_io_man = {
+    {_cons_supp_io_man_reg, _cons_supp_io_man_unreg},
+    {},			/* monitors */
+    0			/* n_monitor */
+};
+
+static mb_IO_man_t *
+_cons_supp_io_man_new(void) {
+    return (mb_IO_man_t *)&_default_io_man;
+}
+
+static void
+_cons_supp_io_man_free(mb_IO_man_t *io_man) {
+}
+
+static int
+_cons_supp_io_man_reg(struct _mb_IO_man *io_man,
+		      int fd, MB_IO_TYPE type, mb_IO_cb_t cb, void *data) {
+    struct _cons_supp_IO_man *cmb_io_man = (struct _cons_supp_IO_man *)io_man;
+    int i;
+
+    for(i = 0; i < cmb_io_man->n_monitor; i++) {
+        if (cmb_io_man->monitors[i].type == MB_IO_DUMMY)
+	    break;
+    }
+    if (i == MAX_MONITORS)
+	return ERR;
+    
+    cmb_io_man->monitors[i].type = type;
+    cmb_io_man->monitors[i].fd = fd;
+    cmb_io_man->monitors[i].cb = cb;
+    cmb_io_man->monitors[i].data = data;
+    i++;
+    if(i > cmb_io_man->n_monitor)
+	cmb_io_man->n_monitor = i;
+    return i - 1;
+}
+
+static void
+_cons_supp_io_man_unreg(struct _mb_IO_man *io_man, int io_hdl) {
+    struct _cons_supp_IO_man *cmb_io_man = (struct _cons_supp_IO_man *)io_man;
+    
+    ASSERT(io_hdl < cmb_io_man->n_monitor);
+    cmb_io_man->monitors[io_hdl].type = MB_IO_DUMMY;
+}
+
+/*! \brief Handle connection coming data and timeout of timers.
+ *
+ */
+static void
+_cons_supp_event_loop(mb_rt_t *rt) {
+    struct _cons_supp_runtime *cmb_rt = (struct _cons_supp_runtime *)rt;
+    struct _cons_supp_IO_man *io_man =
+	(struct _cons_supp_IO_man *)cmb_rt->io_man;
+    mb_timer_man_t *timer_man = (mb_timer_man_t *)cmb_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);
+    rdman_redraw_all(rdman);
+    
+    _cons_supp_handle_cons_event(cmb_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);
+	} 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);
+		}
+            }
+	}
+    }
+}
+
+/* @} */
+
+/*! \defgroup console_kb Console Keyboard Handling
+ *
+ * Accept keyboard events from console and delivery it to
+ * application through observer pattern.  There is a subject,
+ * per X-connection, for that.
+ * @{
+ */
+static int keycode2sym(cons_kb_info_t *kbinfo, unsigned int keycode) {
+    /* TODO: implement keycode to key symbol translation */
+    return 0;
+}
+
+static int cons_kb_init(cons_kb_info_t *kbinfo, MB_DISPLAY display,
+			redraw_man_t *rdman) {
+    int n_syms;
+    observer_factory_t *factory;
+    int r;
+
+    /* TODO: set keycode_min, keycode_max and syms */
+    if((int)display != -1)
+	kbinfo->kb_fd = (int)display;
+    else
+	kbinfo->kb_fd = STDIN_FILENO;
+
+    factory = rdman_get_observer_factory(rdman);
+    kbinfo->kbevents = subject_new(factory, kbinfo, OBJT_KB);
+    if(kbinfo->kbevents == NULL)
+	return ERR;
+    /*! \todo Make sure observer_factory is still need. */
+    kbinfo->observer_factory = factory;
+
+    return OK;
+}
+
+static void cons_kb_destroy(cons_kb_info_t *kbinfo) {
+    subject_free(kbinfo->kbevents);
+}
+/* @} */
+
+/*! \brief Notify observers of the shape at specified
+ *	position for mouse event.
+ *
+ * Observers of parent shapes may be called if the subject is not
+ * with SUBF_STOP_PROPAGATE flag.  The subject of mouse event
+ * for a shape is returned by sh_get_mouse_event_subject().
+ */
+static void notify_coord_or_shape(redraw_man_t *rdman,
+				  mb_obj_t *obj,
+				  co_aix x, co_aix y, int etype,
+				  unsigned int state,
+				  unsigned int button) {
+    mouse_event_t mouse_event;
+    subject_t *subject;
+
+    mouse_event.event.type = etype;
+    mouse_event.x = x;
+    mouse_event.y = y;
+    mouse_event.but_state = state;
+    mouse_event.button = button;
+
+    if(IS_MBO_SHAPES(obj))
+	subject = sh_get_mouse_event_subject((shape_t *)obj);
+    else
+	subject = coord_get_mouse_event((coord_t *)obj);
+
+    subject_notify(subject, (event_t *)&mouse_event);
+}
+
+/*! \brief Handle keyboard event and maintain internal states.
+ *
+ * It keeps internal state in rt to improve performance.
+ */
+static void
+handle_single_cons_event(cons_supp_runtime_t *rt) {
+    /* TODO: handle keyboard and mouse events. */
+    printf("handle_single_cons_event() will be implemented later\n");
+}
+
+/*! \brief Call when no more event in an event iteration.
+ *
+ * No more event means event queue is emplty.  This function will
+ * perform some actions according current internal state.
+ */
+static void
+no_more_event(cons_supp_runtime_t *rt) {
+}
+
+/*! \brief Dispatch all console events in the queue.
+ */
+static void _cons_supp_handle_cons_event(cons_supp_runtime_t *cmb_rt) {
+    int console_fd = (int)cmb_rt->display;
+    struct pollfd pfd = {console_fd, POLLIN, 0};
+    int r;
+
+    while((r = poll(&pfd, 1, 0)) > 0) {
+	handle_single_cons_event(cmb_rt);
+    }
+    no_more_event(cmb_rt);
+}
+
+static void
+_cons_supp_handle_connection(int hdl, int fd, MB_IO_TYPE type, void *data) {
+    cons_supp_runtime_t *cmb_rt = (cons_supp_runtime_t *)data;
+
+    _cons_supp_handle_cons_event(cmb_rt);
+}
+
+/*! \brief Initialize a MadButterfy runtime for Xlib.
+ *
+ * This one is very like _cons_supp_init(), except it accepts a
+ * cons_supp_runtime_t object initialized with a display connected to a X
+ * server and an opened window.
+ *
+ * Following field of the cons_supp_runtime_t object should be initialized.
+ *   - w, h
+ *   - win
+ *   - display
+ *   - visual
+ */
+static int
+_cons_supp_init_with_win_internal(cons_supp_runtime_t *cmb_rt) {
+    mb_img_ldr_t *img_ldr;
+    int w, h;
+    int console_fd;
+
+    w = cmb_rt->w;
+    h = cmb_rt->h;
+    
+    mbe_init();
+    
+    cmb_rt->surface =
+	mbe_win_surface_create(cmb_rt->display, cmb_rt->win,
+			       MB_IFMT_ARGB32, w, h);
+
+    cmb_rt->cr = mbe_create(cmb_rt->surface);
+    
+    cmb_rt->rdman = (redraw_man_t *)malloc(sizeof(redraw_man_t));
+    redraw_man_init(cmb_rt->rdman, cmb_rt->cr, NULL);
+    cmb_rt->rdman->w = w;
+    cmb_rt->rdman->h = h;
+    /* FIXME: This is a wired loopback reference. This is inly
+     *        required when we need to get the cmb_rt->tman for the
+     *        animation. We should relocate the tman to the
+     *        redraw_man_t instead.
+     */
+    cmb_rt->rdman->rt = cmb_rt;
+
+    cmb_rt->io_man = mb_io_man_new(_io_factory);
+    cmb_rt->timer_man = mb_timer_man_new(_timer_factory);
+
+    img_ldr = simple_mb_img_ldr_new("");
+    cmb_rt->img_ldr = img_ldr;
+    /*! \todo Remove rdman_set_img_ldr() */
+    rdman_set_img_ldr(cmb_rt->rdman, img_ldr); /* this is ncessary? */
+
+#ifndef ONLY_MOUSE_MOVE_RAW
+    cmb_rt->last = NULL;
+#endif
+
+    cons_kb_init(&cmb_rt->kbinfo, cmb_rt->display, cmb_rt->rdman);
+
+    console_fd = (int)cmb_rt->display;
+    cmb_rt->io_hdl = mb_io_man_reg(cmb_rt->io_man, console_fd,
+				   MB_IO_R,
+				   _cons_supp_handle_connection,
+				   cmb_rt);
+
+    return OK;
+}
+
+/*! \brief Initialize a MadButterfy runtime for console.
+ *
+ * It setups a runtime environment to run MadButterfly with console.
+ * Users should specify width and height of the opening window.
+ *
+ * \param display_name is actually the path to the console/input device.
+ */
+static int _cons_supp_init(cons_supp_runtime_t *cmb_rt,
+			   const char *display_name,
+			   int w, int h) {
+    int r;
+    int console_fd;
+
+    memset(cmb_rt, 0, sizeof(cons_supp_runtime_t));
+
+    if(display_name == NULL || strlen(display_name) == 0)
+	console_fd = STDIN_FILENO;
+    else {
+	console_fd = open(display_name, O_RDONLY);
+	if(console_fd == -1)
+	    return ERR;
+    }
+    
+    cmb_rt->display = (MB_DISPLAY)console_fd;
+    cmb_rt->win = NULL;
+    cmb_rt->w = w;
+    cmb_rt->h = h;
+    
+    r = _cons_supp_init_with_win_internal(cmb_rt);
+    
+    return r;
+}
+
+/*! \brief Initialize a MadButterfly runtime for a window of console.
+ *
+ * This function is equivalent to _cons_supp_init() with fixed width
+ * and height.  Since, there is no window for console.
+ *
+ * Runtimes initialized with this function should be destroyed with
+ * cons_supp_destroy_keep_win().
+ *
+ * \param display is actually a file descriptor of console (input device).
+ */
+static int
+_cons_supp_init_with_win(cons_supp_runtime_t *cmb_rt,
+			 MB_DISPLAY display, MB_WINDOW win) {
+    int r;
+
+    memset(cmb_rt, 0, sizeof(cons_supp_runtime_t));
+
+    cmb_rt->display = display;
+    cmb_rt->w = 800;
+    cmb_rt->h = 600;
+    
+    r = _cons_supp_init_with_win_internal(cmb_rt);
+
+    return r;
+}
+
+static void cons_supp_destroy_keep_win(cons_supp_runtime_t *cmb_rt);
+
+static void cons_supp_destroy(cons_supp_runtime_t *cmb_rt) {
+    int console_fd = cmb_rt = (int)cmb_rt->display;
+    
+    close(console_fd);
+    cons_supp_destroy_keep_win(cmb_rt);
+}
+
+/*! \brief Destroy a MadButterfly runtime initialized with
+ *	_cons_supp_init_with_win().
+ *
+ * Destroying a runtime with this function prevent the window and
+ * display associated with the runtime being closed.
+ */
+static void
+cons_supp_destroy_keep_win(cons_supp_runtime_t *cmb_rt) {
+    if(cmb_rt->rdman) {
+	redraw_man_destroy(cmb_rt->rdman);
+	free(cmb_rt->rdman);
+    }
+
+    if(cmb_rt->io_hdl)
+	mb_io_man_unreg(cmb_rt->io_man, cmb_rt->io_hdl);
+
+    if(cmb_rt->io_man)
+	mb_io_man_free(_io_factory, cmb_rt->io_man);
+    if(cmb_rt->timer_man)
+	mb_timer_man_free(_timer_factory, cmb_rt->timer_man);
+
+    if(cmb_rt->img_ldr)
+	MB_IMG_LDR_FREE(cmb_rt->img_ldr);
+
+    if(cmb_rt->cr)
+	mbe_destroy(cmb_rt->cr);
+
+    if(cmb_rt->surface)
+	mbe_surface_destroy(cmb_rt->surface);
+
+    cons_kb_destroy(&cmb_rt->kbinfo);
+}
+
+static mb_rt_t *
+_cons_supp_new(const char *display_name, int w, int h) {
+    cons_supp_runtime_t *rt;
+    int r;
+
+    rt = O_ALLOC(cons_supp_runtime_t);
+    if(rt == NULL)
+	return NULL;
+
+    r = _cons_supp_init(rt, display_name, w, h);
+    if(r != OK) {
+	free(rt);
+	return NULL;
+    }
+
+    return (mb_rt_t *)rt;
+}
+
+/*! \brief Create a new runtime for existed window for console.
+ *
+ * The object returned by this function must be free with
+ * _cons_supp_free_keep_win() to prevent the window from closed.
+ */
+static mb_rt_t *
+_cons_supp_new_with_win(MB_DISPLAY display, MB_WINDOW win) {
+    cons_supp_runtime_t *rt;
+    int r;
+
+    rt = O_ALLOC(cons_supp_runtime_t);
+    if(rt == NULL)
+	return NULL;
+
+    r = _cons_supp_init_with_win(rt, display, win);
+    if(r != OK) {
+	free(rt);
+	return NULL;
+    }
+
+    return (mb_rt_t *)rt;
+}
+
+static void
+_cons_supp_free(mb_rt_t *rt) {
+    cons_supp_destroy((cons_supp_runtime_t *) rt);
+    free(rt);
+}
+
+/*! \brief Free runtime created with _cons_supp_new_with_win().
+ */
+static void
+_cons_supp_free_keep_win(mb_rt_t *rt) {
+    cons_supp_destroy_keep_win((cons_supp_runtime_t *) rt);
+    free(rt);
+}
+
+static subject_t *
+_cons_supp_kbevents(mb_rt_t *rt) {
+    cons_supp_runtime_t *cmb_rt = (cons_supp_runtime_t *) rt;
+    return cmb_rt->kbinfo.kbevents;
+}
+
+static redraw_man_t *
+_cons_supp_rdman(mb_rt_t *rt) {
+    cons_supp_runtime_t *cmb_rt = (cons_supp_runtime_t *) rt;
+    return cmb_rt->rdman;
+}
+
+static mb_timer_man_t *
+_cons_supp_timer_man(mb_rt_t *rt) {
+    cons_supp_runtime_t *cmb_rt = (cons_supp_runtime_t *) rt;
+    return cmb_rt->timer_man;
+}
+
+static observer_factory_t *
+_cons_supp_observer_factory(mb_rt_t *rt) {
+    cons_supp_runtime_t *cmb_rt = (cons_supp_runtime_t *) rt;
+    observer_factory_t *factory;
+
+    factory = rdman_get_observer_factory(cmb_rt->rdman);
+    return factory;
+}
+
+static mb_img_ldr_t *
+_cons_supp_img_ldr(mb_rt_t *rt) {
+    cons_supp_runtime_t *cmb_rt = (cons_supp_runtime_t *) rt;
+    mb_img_ldr_t *img_ldr;
+
+    img_ldr = cmb_rt->img_ldr;
+
+    return img_ldr;
+}
+
+static int
+_cons_supp_add_event(mb_rt_t *rt, int fd, MB_IO_TYPE type,
+		     mb_IO_cb_t cb, void *data)
+{
+    cons_supp_runtime_t *cmb_rt = (cons_supp_runtime_t *) rt;
+    mb_IO_man_t *io_man = cmb_rt->io_man;
+    int hdl;
+
+    hdl = mb_io_man_reg(io_man, fd, type, cb, data);
+    return hdl;
+}
+
+static void
+_cons_supp_remove_event(mb_rt_t *rt, int hdl)
+{
+    cons_supp_runtime_t *cmb_rt = (cons_supp_runtime_t *) rt;
+    mb_IO_man_t *io_man = cmb_rt->io_man;
+
+    mb_io_man_unreg(io_man, hdl);
+}
+
+static int
+_cons_supp_flush(mb_rt_t *rt) {
+    cons_supp_runtime_t *cmb_rt = (cons_supp_runtime_t *)rt;
+    
+    mbe_flush(cmb_rt->cr);
+    return OK;
+}
+
+static void
+_cons_supp_reg_IO_factory(mb_IO_factory_t *io_factory) {
+    _io_factory = io_factory;
+}
+
+static void
+_cons_supp_reg_timer_factory(mb_timer_factory_t *timer_factory) {
+    _timer_factory = timer_factory;
+}
+
+mb_backend_t mb_dfl_backend = { _cons_supp_new,
+				_cons_supp_new_with_win,
+				
+				_cons_supp_free,
+				_cons_supp_free_keep_win,
+				_cons_supp_add_event,
+				_cons_supp_remove_event,
+				_cons_supp_event_loop,
+				_cons_supp_flush,
+				
+				_cons_supp_kbevents,
+				_cons_supp_rdman,
+				_cons_supp_timer_man,
+				_cons_supp_observer_factory,
+				_cons_supp_img_ldr,
+
+				_cons_supp_reg_IO_factory,
+				_cons_supp_reg_timer_factory,
+};
+
+/*
+ * Local Variables:
+ * indent-tabs-mode: t
+ * tab-width: 8
+ * c-basic-offset: 4
+ * c-file-style:"stroustrup"
+ * fill-column:79
+ * End:
+ */
+// vim: sw=4:ts=8:sts=4:textwidth=79
--- a/src/graph_engine_cairo.c	Thu Dec 09 07:48:08 2010 +0800
+++ b/src/graph_engine_cairo.c	Thu Dec 09 07:48:46 2010 +0800
@@ -1,5 +1,6 @@
 // -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*-
 // vim: sw=4:ts=8:sts=4
+#include <X11/Xlib.h>
 #include <fontconfig/fontconfig.h>
 #include <cairo-ft.h>
 #include "mb_graph_engine_cairo.h"
@@ -82,6 +83,23 @@
 
 }
 
+extern mbe_surface_t *
+mbe_win_surface_create(void *display, void *drawable,
+		       int fmt, int width, int height) {
+    XWindowAttributes attrs;
+    mbe_surface_t *surf;
+    int r;
+
+    r = XGetWindowAttributes((Display *)display, (Drawable)drawable, &attrs);
+    if(r == 0)
+	return NULL;
+    
+    surf = cairo_xlib_surface_create((Display *)display, (Drawable)drawable,
+				     attrs.visual, width, height);
+
+    return surf;
+}
+
 /*! \brief Find out a font face for a pattern specified.
  *
  * The pattern, here, is a vector of family, slant, and weight.
--- a/src/graph_engine_openvg.c	Thu Dec 09 07:48:08 2010 +0800
+++ b/src/graph_engine_openvg.c	Thu Dec 09 07:48:46 2010 +0800
@@ -540,76 +540,30 @@
 }
 
 #ifdef EGL_GLX
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-static int
-_get_img_fmt_from_xvisual(Display *display, Visual *visual) {
-    VisualID visual_id;
-    XVisualInfo temp;
-    XVisualInfo *infos;
-    int n;
-    int fmt = -1;
-    
-    visual_id = XVisualIDFromVisual(visual);
-    temp.visualid = visual_id;
-    infos = XGetVisualInfo(display, VisualIDMask, &temp, &n);
-    if(n != 1)
-	return -1;
-
-    switch(infos->depth) {
-    case 32:
-	fmt = MB_IFMT_ARGB32;
-	break;
-	
-    case 24:
-	fmt = MB_IFMT_RGB24;
-	break;
-	
-    case 16:
-	fmt = MB_IFMT_RGB16_565;
-	break;
-	
-    case 8:
-	fmt = MB_IFMT_A8;
-	break;
-	
-    case 1:
-	fmt = MB_IFMT_A1;
-	break;
-    }
-
-    return fmt;
-}
-
 /*! \brief Create an EGL window surface for X11.
  *
  * This function is compiled only for GLX enabled.
  */
 mbe_surface_t *
-mbe_win_surface_create(Display *display, Drawable drawable,
-		       Visual *visual, int width, int height) {
+mbe_win_surface_create(void *display, void *drawable,
+		       int fmt, int width, int height) {
     EGLDisplay egl_disp;
     EGLSurface egl_surface;
     mbe_surface_t *surface;
     EGLConfig config;
     EGLint attrib_list[2] = {EGL_NONE};
-    int fmt;
     int r;
 
-    fmt = _get_img_fmt_from_xvisual(display, visual);
-    if(fmt == -1)
-	return NULL;
-    
     r = _openvg_find_config(fmt, width, height, &config);
     if(r != 0)
 	return NULL;
 
-    egl_disp = eglGetDisplay(display);
+    egl_disp = eglGetDisplay((Display *)display);
     if(egl_disp == EGL_NO_DISPLAY || egl_disp != _VG_DISPLAY())
 	return NULL;
 
-    egl_surface = eglCreateWindowSurface(egl_disp, config, drawable,
+    egl_surface = eglCreateWindowSurface(egl_disp, config,
+					 (Drawable)drawable,
 					 attrib_list);
 
     surface = O_ALLOC(mbe_surface_t);
@@ -721,6 +675,17 @@
     eglSwapBuffers(display, VG_MBE_SURFACE(dst_canvas));
 }
 
+void
+mbe_flush(mbe_t *canvas) {
+    EGLDisplay display;
+    mbe_surface_t *surface;
+
+    _MK_CURRENT_CTX(canvas);
+    display = _VG_DISPLAY();
+    surface = VG_MBE_SURFACE(canvas);
+    eglSwapBuffers(display, surface);
+}
+
 mbe_t *
 mbe_create(mbe_surface_t *surface) {
     EGLDisplay display;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/img_ldr_dummy.c	Thu Dec 09 07:48:46 2010 +0800
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include "mb_img_ldr.h"
+
+static mb_img_data_t *img_ldr_dummy_load(mb_img_ldr_t *ldr,
+					 const char *img_id);
+static void img_ldr_dummy_free(mb_img_ldr_t *ldr);
+
+static mb_img_ldr_t img_ldr = {
+    img_ldr_dummy_load,
+    img_ldr_dummy_free
+};
+
+#ifndef ERR
+#include <stdio.h>
+#include <stdlib.h>
+#define ERR(msg) do { fprintf(stderr, __FILE__ ":%d: %s", __LINE__, msg); abort(); } while(0)
+#endif
+#ifndef NOT_IMPLEMENT
+#define NOT_IMPLEMENT(func)			\
+    ERR(func " is not impmemented\n")
+#endif
+
+static mb_img_data_t *
+img_ldr_dummy_load(mb_img_ldr_t *ldr, const char *img_id) {
+    NOT_IMPLEMENT("img_ldr_dummy_load");
+    return NULL;
+}
+
+static void
+img_ldr_dummy_free(mb_img_ldr_t *ldr) {
+    NOT_IMPLEMENT("img_ldr_dummy_free");
+}
+
+mb_img_ldr_t *
+simple_mb_img_ldr_new(const char *img_repository) {
+    return &img_ldr;
+}
+
--- a/src/img_ldr_imlib2.c	Thu Dec 09 07:48:08 2010 +0800
+++ b/src/img_ldr_imlib2.c	Thu Dec 09 07:48:46 2010 +0800
@@ -1,6 +1,7 @@
 // -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*-
 // vim: sw=4:ts=8:sts=4
 #include <stdio.h>
+#include <stdint.h>
 #include <string.h>
 #include <Imlib2.h>
 #include "mb_graph_engine.h"
@@ -19,7 +20,6 @@
 
 struct _simple_mb_img_data {
     mb_img_data_t img;
-    Imlib_Image img_hdl;
 };
 typedef struct _simple_mb_img_data simple_mb_img_data_t;
 
@@ -31,7 +31,11 @@
     simple_mb_img_data_t *img;
     Imlib_Image img_hdl;
     int w, h;
-    void *data;
+    int i, j, pos;
+    uint32_t alpha;
+    uint32_t value;
+    uint32_t *data;
+    uint32_t *premultiple_data;
     char *fname;
     int sz;
 
@@ -50,21 +54,56 @@
     imlib_context_set_image(img_hdl);
     w = imlib_image_get_width();
     h = imlib_image_get_height();
-    data = imlib_image_get_data_for_reading_only();
+    data = (uint32_t *)imlib_image_get_data_for_reading_only();
 
     img = O_ALLOC(simple_mb_img_data_t);
     if(img == NULL) {
 	imlib_free_image();
 	return NULL;
     }
-    img->img.content = data;
+    
+    premultiple_data = (uint32_t *)malloc(4 * w * h);
+    if(premultiple_data == NULL) {
+	free(img);
+	imlib_free_image();
+	return NULL;
+    }
+    memcpy(premultiple_data, data, 4 * w * h);
+
+    /* Pre-multiply
+     *
+     * Our reference model is Cairo.  In Cairo model, image is
+     * pre-multiplied with alpha, but imlib2 is not.  So, we do it
+     * here.
+     */
+    pos = 0;
+    for(i = 0; i < h; i++) {
+	for(j = 0; j < w; j++) {
+	    value = data[pos];
+	    alpha = value >> 24;
+	    if(alpha != 0xff) {
+		if(alpha == 0)
+		    value = 0;
+		else {
+		    value = (value & 0xff000000) |
+			(((value & 0xff0000) * alpha / 0xff) & 0xff0000) |
+			(((value & 0xff00) * alpha / 0xff) & 0xff00) |
+			((value & 0xff) * alpha / 0xff);
+		}
+	    }
+	    premultiple_data[pos++] = value;
+	}
+    }
+    
+    img->img.content = premultiple_data;
     img->img.w = w;
     img->img.h = h;
     img->img.stride = w * 4;
     img->img.fmt = MB_IFMT_ARGB32;
     img->img.free = simple_mb_img_ldr_img_free;
-    img->img_hdl = img_hdl;
 
+    imlib_free_image();
+    
     return (mb_img_data_t *)img;
 }
 
@@ -72,8 +111,7 @@
 void simple_mb_img_ldr_img_free(mb_img_data_t *img) {
     simple_mb_img_data_t *simg = (simple_mb_img_data_t *)img;
 
-    imlib_context_set_image(simg->img_hdl);
-    imlib_free_image();
+    free(simg->img.content);
     free(img);
 }
 
--- a/src/mbaf/animated_menu.c	Thu Dec 09 07:48:08 2010 +0800
+++ b/src/mbaf/animated_menu.c	Thu Dec 09 07:48:46 2010 +0800
@@ -259,7 +259,7 @@
 static void mb_animated_menu_send_pending_key(event_t *ev,void *arg)
 {
     mb_animated_menu_t *m = (mb_animated_menu_t *) arg;
-    X_kb_event_t *xkey;
+    mb_kb_event_t *xkey;
 
     xkey = &m->pending_keys[m->pending_pos];
     m->pending_pos = (m->pending_pos + 1) & 0xf;
@@ -268,7 +268,7 @@
 static void mb_animated_menu_keyHandler(event_t *ev, void *arg)
 {
     mb_animated_menu_t *m = (mb_animated_menu_t *) arg;
-    X_kb_event_t *xkey = (X_kb_event_t *)ev;
+    mb_kb_event_t *xkey = (mb_kb_event_t *)ev;
     if(xkey->event.type != EVT_KB_PRESS) {
         return;
     }
--- a/src/redraw_man.c	Thu Dec 09 07:48:08 2010 +0800
+++ b/src/redraw_man.c	Thu Dec 09 07:48:46 2010 +0800
@@ -2474,10 +2474,14 @@
 	 * rules.
 	 */
 	draw_shapes_in_dirty_areas(rdman);
-	n_areas = _coord_get_dirty_areas(rdman->root_coord)->num;
-	areas = _coord_get_dirty_areas(rdman->root_coord)->ds;
-	copy_cr_2_backend(rdman, n_areas, areas);
-	reset_clip(rdman->backend);
+	if(rdman->backend) {
+	    n_areas = _coord_get_dirty_areas(rdman->root_coord)->num;
+	    areas = _coord_get_dirty_areas(rdman->root_coord)->ds;
+	    copy_cr_2_backend(rdman, n_areas, areas);
+	    reset_clip(rdman->backend);
+	} else {
+	    mbe_flush(rdman->cr);
+	}
 	for(i = 0; i < rdman->zeroing_coords.num; i++) {
 	    coord = rdman->zeroing_coords.ds[i];
 	    DARRAY_CLEAN(_coord_get_dirty_areas(coord));
@@ -2515,8 +2519,8 @@
     area.x = area.y = 0;
 #ifndef UNITTEST
     surface = mbe_get_target(rdman->cr);
-    area.w = mbe_image_surface_get_width(surface);
-    area.h = mbe_image_surface_get_height(surface);
+    area.w = rdman->w;
+    area.h = rdman->h;
 #else
     area.w = 1024;
     area.h = 1024;