changeset 986:c39d14139ca5 refine_backend_if

Implement IO manager interface for X
author Thinker K.F. Li <thinker@codemud.net>
date Mon, 22 Nov 2010 00:42:29 +0800
parents bab9c0f836b9
children bf0da8c7d03f
files include/mb_backend.h src/X_supp.c
diffstat 2 files changed, 162 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/include/mb_backend.h	Mon Nov 22 00:42:29 2010 +0800
+++ b/include/mb_backend.h	Mon Nov 22 00:42:29 2010 +0800
@@ -68,7 +68,7 @@
 
 /*! \brief Type of IO that registered with an IO manager.
  */
-enum MB_IO_TYPE {MB_IO_R, MB_IO_W, MB_IO_RW};
+enum MB_IO_TYPE {MB_IO_DUMMY, MB_IO_R, MB_IO_W, MB_IO_RW};
 
 /*! \brief Function signature of callback functions for IO requests.
  */
--- a/src/X_supp.c	Mon Nov 22 00:42:29 2010 +0800
+++ b/src/X_supp.c	Mon Nov 22 00:42:29 2010 +0800
@@ -10,6 +10,7 @@
 #include "mb_redraw_man.h"
 #include "mb_timer.h"
 #include "mb_X_supp.h"
+#include "mb_backend.h"
 #include "config.h"
 
 #ifdef XSHM
@@ -36,13 +37,6 @@
 };
 
 /* @} */
-#define MAX_MONITORS 200
-typedef struct {
-    int type;
-    int fd;
-    mb_eventcb_t f;
-    void *arg;
-}  monitor_t;
 
 struct _X_MB_runtime {
     Display *display;
@@ -57,8 +51,7 @@
     int w, h;
 
     X_kb_info_t kbinfo;
-    monitor_t monitors[MAX_MONITORS];
-    int n_monitor;
+    mb_IO_man_t *io_man;
 
 #ifndef ONLY_MOUSE_MOVE_RAW
     /* States */
@@ -81,6 +74,163 @@
     int mbut_state;	       /* Button state of last motion event */
 };
 
+/*! \defgroup x_mb_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_MB_IO_man {
+    mb_IO_man_t io_man;
+    monitor_t monitors[MAX_MONITORS];
+    int n_monitor;
+};
+
+int _x_mb_io_man_reg(struct _mb_IO_man *io_man,
+		      int fd, MB_IO_TYPE type, mb_IO_cb_t cb, void *data);
+void _x_mb_io_man_unreg(struct _mb_IO_Man *io_man, int io_hdl);
+mb_IO_man_t *_x_mb_io_man_new(void);
+void _x_mb_io_man_free(mb_IO_man_t *io_man);
+
+static mb_IO_factory_t _X_supp_default_io_factory = {
+    _x_mb_io_man_new,
+    _x_mb_io_man_free
+};
+static mb_IO_factory_t *_io_factory = _X_supp_default_io_factory;
+
+static struct _X_MB_IO_man _default_io_man = {
+    {_x_mb_io_man_reg, _x_mb_io_man_unreg},
+    ,			/* monitors */
+    0			/* n_monitor */
+};
+
+static mb_IO_man_t *
+_x_mb_io_man_new(void) {
+    return (mb_IO_man_t *)&_default_io_man;
+}
+
+static void
+_x_mb_io_man_free(mb_IO_man_t *io_man) {
+}
+
+static int
+_x_mb_io_man_reg(struct _mb_IO_man *io_man,
+		     int fd, MB_IO_TYPE type, mb_IO_cb_t cb, void *data) {
+    struct _x_mb_io_man *xmb_io_man = (struct _x_mb_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_mb_io_man_unreg(struct _mb_IO_man *io_man, int io_hdl) {
+    struct _x_mb_io_man *xmb_io_man = (struct _x_mb_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_mb_handle_connection(struct _mb_IO_man *io_man) {
+    X_MB_runtime_t *rt = (X_MB_runtime_t *) be;
+    mb_tman_t *tman = rt->tman;
+    int fd;
+    mb_timeval_t now, tmo;
+    struct timeval tv;
+    fd_set rfds, wfds;
+    int nfds = 0;
+    int r, r1,i;
+
+    handle_x_event(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);
+		if(nfds <= io_man->monitors[i].fd)
+		    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);
+		if(nfds <= io_man->monitors[i].fd)
+		    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);
+	} 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))
+		    	ioman->monitors[i].cb(io_man->monitors[i].fd,
+					      MB_IO_R,
+					      rt->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(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) {
@@ -167,7 +317,6 @@
 
     subject_notify(kbinfo->kbevents, &event.event);
 }
-
 /* @} */
 
 static unsigned int get_button_state(unsigned int state) {
@@ -498,9 +647,6 @@
     }
 }
 
-#define ERR -1
-#define OK 0
-
 static int X_init_connection(const char *display_name,
 			     int w, int h,
 			     Display **displayp,
@@ -954,10 +1100,12 @@
 }
 mb_backend_t backend = { X_MB_new,
 			 X_MB_new_with_window,
+			 
 			 X_MB_free,
 			 X_MB_add_event,
 			 X_MB_remove_event,
 			 X_MB_handle_connection,
+			 
 			 X_MB_kbevents,
 			 X_MB_rdman,
 			 X_MB_tman,