diff src/X_supp.c @ 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 769921baf111
children bf5adf1e275e
line wrap: on
line diff
--- 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 */