changeset 77:a6763f080da5

-
author Thinker K.F. Li <thinker@branda.to>
date Wed, 20 Aug 2008 00:32:11 +0800
parents 8706356a61b4
children 3645e29e4986
files src/Makefile src/X_main.c src/X_supp.c src/mb_timer.h src/mb_types.h src/observer.c src/timertool.c src/tools.c
diffstat 8 files changed, 174 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/Makefile	Tue Aug 19 19:14:01 2008 +0800
+++ b/src/Makefile	Wed Aug 20 00:32:11 2008 +0800
@@ -1,6 +1,6 @@
 SRCS =	coord.c geo.c shape_path.c shape_text.c shape_rect.c \
 	redraw_man.c timer.c animate.c paint.c event.c observer.c \
-	X_supp.c tools.c
+	X_supp.c timertool.c tools.c
 OBJS = ${SRCS:C/(.*)\.c/\1.o/g}
 TESTCASE_OBJS = ${SRCS:C/(.*)\.c/testcase-\1.o/g}
 CFLAGS+=	-Wall -I/usr/local/include `pkg-config --cflags cairo`
--- a/src/X_main.c	Tue Aug 19 19:14:01 2008 +0800
+++ b/src/X_main.c	Wed Aug 20 00:32:11 2008 +0800
@@ -58,9 +58,8 @@
 	    hint_shape(rdman, shape);
 	    break;
 	case Expose:
-	    rdman_redraw_all(rdman);
-	    /* rdman_redraw_area(rdman, evt.xexpose.x, evt.xexpose.y,
-	       evt.xexpose.width, evt.xexpose.height); */
+	    rdman_redraw_area(rdman, evt.xexpose.x, evt.xexpose.y,
+			      evt.xexpose.width, evt.xexpose.height);
 	    break;
 	}
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/X_supp.c	Wed Aug 20 00:32:11 2008 +0800
@@ -0,0 +1,107 @@
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "redraw_man.h"
+#include "mb_timer.h"
+
+
+/*! \brief Dispatch all events in the queue.
+ */
+static void handle_x_event(Display *display,
+			   redraw_man_t *rdman,
+			   mb_tman_t *tman) {
+    XEvent evt;
+    XMotionEvent *mevt;
+    mouse_event_t mouse_event;
+    shape_t *shape;
+    subject_t *subject;
+    ob_factory_t *factory;
+    co_aix x, y;
+    int in_stroke;
+    int but;
+    int r;
+
+    while(XEventsQueued(display, QueuedAfterReading) > 0) {
+	r = XNextEvent(display, &evt);
+	if(r == -1)
+	    break;
+
+	switch(evt.type) {
+	case MotionNotify:
+	    mevt = (XMotionEvent *)&evt;
+	    x = mevt->x;
+	    y = mevt->y;
+	    but = 0;
+	    if(mevt->state & Button1Mask)
+		but |= MOUSE_BUT1;
+	    if(mevt->state & Button2Mask)
+		but |= MOUSE_BUT2;
+	    if(mevt->state & Button3Mask)
+		but |= MOUSE_BUT3;
+
+	    mouse_event.event.type = EVT_MOUSE_MOVE;
+	    mouse_event.x = x;
+	    mouse_event.y = y;
+	    mouse_event.button = but;
+
+	    shape = find_shape_at_pos(rdman, x, y,
+				      &in_stroke);
+	    subject = sh_get_mouse_event_subject(shape);
+	    factory = rdman_get_ob_factory(rdman);
+
+	    subject_notify(factory, subject, (event_t *)&mouse_event);
+	    break;
+
+	case Expose:
+	    rdman_redraw_area(rdman, evt.xexpose.x, evt.xexpose.y,
+			      evt.xexpose.width, evt.xexpose.height);
+	    break;
+	}
+    }
+    rdman_redraw_changed(rdman);
+    XFlush(display);
+}
+
+/*! \brief Handle connection coming data and timeout of timers.
+ */
+void X_handle_connection(Display *display,
+			 redraw_man_t *rdman,
+			 mb_tman_t *tman) {
+    int fd;
+    mb_timeval_t now, tmo;
+    struct timeval tv;
+    fd_set rfds;
+    int nfds;
+    int r;
+
+    fd = XConnectionNumber(display);
+    nfds = fd + 1;
+    while(1) {
+	FD_ZERO(&rfds);
+	FD_SET(fd, &rfds);
+	
+	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);
+	    r = select(nfds, &rfds, NULL, NULL, &tv);
+	} else
+	    r = select(nfds, &rfds, NULL, NULL, NULL);
+
+	if(r == -1) {
+	    perror("select");
+	    break;
+	}
+
+	if(r == 0) {
+	    get_now(&now);
+	    mb_tman_handle_timeout(tman, &now);
+	    rdman_redraw_changed(rdman);
+	    XFlush(display);
+	} else if(FD_ISSET(fd, &rfds)){
+	    handle_x_event(display, rdman, tman);
+	}
+    }
+}
--- a/src/mb_timer.h	Tue Aug 19 19:14:01 2008 +0800
+++ b/src/mb_timer.h	Wed Aug 20 00:32:11 2008 +0800
@@ -69,4 +69,7 @@
     } while(0)
 
 
+extern void get_now(mb_timeval_t *tmo);
+
+
 #endif /* __MB_TIMER_H_ */
--- a/src/mb_types.h	Tue Aug 19 19:14:01 2008 +0800
+++ b/src/mb_types.h	Wed Aug 20 00:32:11 2008 +0800
@@ -149,6 +149,8 @@
 	(sh)->geo->shape = NULL;		\
 	(sh)->geo = NULL;			\
     } while(0)
+#define sh_get_geo(sh) ((sh)->geo)
+#define sh_get_mouse_event_subject(sh) ((sh)->geo->mouse_event)
 extern void sh_attach_coord(shape_t *sh, coord_t *coord);
 extern void sh_detach_coord(shape_t *sh);
 
--- a/src/observer.c	Tue Aug 19 19:14:01 2008 +0800
+++ b/src/observer.c	Wed Aug 20 00:32:11 2008 +0800
@@ -32,7 +32,9 @@
 void subject_notify(ob_factory_t *factory, subject_t *subject, event_t *evt) {
     observer_t *observer;
 
+    evt->tgt = subject;
     while(subject) {
+	evt->cur_tgt = subject->obj;
 	for(observer = STAILQ_HEAD(subject->observers);
 	    observer != NULL;
 	    observer = STAILQ_NEXT(observer_t, next, observer)) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/timertool.c	Wed Aug 20 00:32:11 2008 +0800
@@ -0,0 +1,57 @@
+#include <sys/time.h>
+#ifdef __FreeBSD__
+#include <machine/cpufunc.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#endif
+#include "mb_timer.h"
+
+
+#ifdef __FreeBSD__
+void get_now(mb_timeval_t *tmo) {
+    struct timeval tv;
+    static uint64_t cpufreq;
+    static mb_timeval_t tm = {0, 0};
+    static uint64_t last_ts;
+
+    mb_timeval_t diff_tm;
+    uint64_t ts, diff, udiff, sdiff;
+    size_t sysctl_sz;
+
+    if(MB_TIMEVAL_SEC(&tm) == 0) {
+	sysctl_sz = sizeof(uint64_t);
+	cpufreq = sysctlbyname("kern.timecounter.tc.TSC.frequency",
+			       &cpufreq, &sysctl_sz,
+			       NULL, 0);
+
+	gettimeofday(&tv, NULL);
+	last_ts = rdtsc();
+
+	MB_TIMEVAL_SET(tmo, tv.tv_sec, tv.tv_usec);
+	MB_TIMEVAL_CP(&tm, tmo);
+	diff = 0;
+    } else {
+	ts = rdtsc();
+	diff += ts - last_ts;
+	sdiff = diff / cpufreq;
+	udiff = (diff % cpufreq) * 1000000 / cpufreq;
+
+	MB_TIMEVAL_SET(&diff_tm, sdiff, udiff);
+	MB_TIMEVAL_CP(tmo, &tm);
+	MB_TIMEVAL_ADD(tmo, &diff_tm);
+
+	MB_TIMEVAL_SET(&diff_tm, sdiff, 0);
+	MB_TIMEVAL_ADD(&tm, &diff_tm);
+
+	last_ts += sdiff;
+    }
+}
+#else /* __FreeBSD__ */
+void get_now(mb_timeval_t *tmo) {
+    struct timeval tv;
+
+    gettimeofday(&tv, NULL);
+    MB_TIMEVAL_SET(tmo, tv.tv_sec, tv.tv_usec);
+}
+#endif /* __FreeBSD__ */
+
--- a/src/tools.c	Tue Aug 19 19:14:01 2008 +0800
+++ b/src/tools.c	Wed Aug 20 00:32:11 2008 +0800
@@ -108,7 +108,6 @@
     }
 }
 
-
 #ifdef UNITTEST
 
 #include <CUnit/Basic.h>