Mercurial > MadButterfly
changeset 78:3645e29e4986
Add runtime for Xlib.
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Wed, 20 Aug 2008 23:33:04 +0800 |
parents | a6763f080da5 |
children | 5bcb329a5157 |
files | examples/svg2code_ex/Makefile examples/svg2code_ex/main.c src/Makefile src/X_supp.c src/X_supp.h src/observer.h src/timertool.c tools/mb_c_header.m4 tools/mb_c_source.m4 tools/svg2code.py |
diffstat | 10 files changed, 321 insertions(+), 48 deletions(-) [+] |
line wrap: on
line diff
--- a/examples/svg2code_ex/Makefile Wed Aug 20 00:32:11 2008 +0800 +++ b/examples/svg2code_ex/Makefile Wed Aug 20 23:33:04 2008 +0800 @@ -1,16 +1,25 @@ SVG=svg2code_ex.svg TOOLSDIR=../../tools INCS=-I../../src -CFLAGS=-g `pkg-config --cflags cairo` $(INCS) -Wall +CFLAGS+=`pkg-config --cflags cairo` $(INCS) -Wall +LDFLAGS=-L../../src/ `pkg-config --libs cairo` +LIBS=-lmbfly +BINS= ex1 -all: $(SVG:C/.svg/.o/) +all: $(BINS) + +ex1: main.o $(SVG:C/.svg/.o/) + $(CC) $(LDFLAGS) -o $@ $(.ALLSRC) $(LIBS) + +main.o: main.c $(SVG:C/.svg/.h/) + $(CC) $(CFLAGS) -c -o $@ main.c $(SVG:C/.svg/.o/): $(SVG:C/.svg/.c/) $(SVG:C/.svg/.h/) $(CC) -c $(CFLAGS) -o $@ $(SVG:C/.svg/.c/) $(SVG:C/.svg/.mb/): $(SVG) $(TOOLSDIR)/svg2code.py $(.ALLSRC) $@ - + $(SVG:C/.svg/.c/): $(SVG:C/.svg/.mb/) m4 -I $(TOOLSDIR) mb_c_source.m4 $(.ALLSRC) > $@ @@ -18,7 +27,7 @@ m4 -I $(TOOLSDIR) mb_c_header.m4 $(.ALLSRC) > $@ clean: - for i in *.mb *.o *~ $(SVG:C/.svg/.c/) $(SVG:C/.svg/.h/); do \ + for i in *.mb *.o *~ $(SVG:C/.svg/.c/) $(SVG:C/.svg/.h/) $(BINS); do \ if [ -e "$$i" ]; then \ echo "delete $$i"; \ rm -f "$$i"; \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/svg2code_ex/main.c Wed Aug 20 23:33:04 2008 +0800 @@ -0,0 +1,19 @@ +#include <stdio.h> +#include <mb_types.h> +#include <X_supp.h> +#include "svg2code_ex.h" + +int main(int argc, char * const argv[]) { + X_MB_runtime_t rt; + svg2code_ex_t *svg2code; + int r; + + r = X_MB_init(":0.0", 200, 200, &rt); + + svg2code = svg2code_ex_new(rt.rdman); + X_MB_handle_connection(rt.display, rt.rdman, rt.tman); + + X_MB_destroy(&rt); + + return 0; +}
--- a/src/Makefile Wed Aug 20 00:32:11 2008 +0800 +++ b/src/Makefile Wed Aug 20 23:33:04 2008 +0800 @@ -5,13 +5,17 @@ TESTCASE_OBJS = ${SRCS:C/(.*)\.c/testcase-\1.o/g} CFLAGS+= -Wall -I/usr/local/include `pkg-config --cflags cairo` LDFLAGS = `pkg-config --libs cairo` -BINS = testcase X_main +BINS = testcase libmbfly.a X_main all: $(BINS) testcase: testcase.o $(TESTCASE_OBJS) $(CC) $(LDFLAGS) -o $@ $(.ALLSRC) -L/usr/local/lib -lcunit +libmbfly.a: $(OBJS) + $(AR) -cr $@ $(.ALLSRC) + + .for i in $(TESTCASE_OBJS) ${i}: ${i:C/testcase-(.*).o/\1.c/} $(CC) $(CFLAGS) -DUNITTEST -g -c -o $@ $(.ALLSRC) @@ -20,7 +24,7 @@ testcase.o: testcase.c $(CC) $(CFLAGS) -c $(.ALLSRC) -X_main: X_main.o $(OBJS) +X_main: X_main.o libmbfly.a $(CC) $(CFALGS) `pkg-config --libs cairo` -o $@ $(.ALLSRC) X_main.o: X_main.c
--- a/src/X_supp.c Wed Aug 20 00:32:11 2008 +0800 +++ b/src/X_supp.c Wed Aug 20 23:33:04 2008 +0800 @@ -1,24 +1,83 @@ #include <stdio.h> +#include <stdlib.h> +#include <string.h> #include <X11/Xlib.h> #include <X11/Xutil.h> +#include <cairo.h> +#include <cairo-xlib.h> #include "redraw_man.h" #include "mb_timer.h" +#include "X_supp.h" -/*! \brief Dispatch all events in the queue. +static unsigned int get_button_state(unsigned int state) { + unsigned int but = 0; + + if(state & Button1Mask) + but |= MOUSE_BUT1; + if(state & Button2Mask) + but |= MOUSE_BUT2; + if(state & Button3Mask) + but |= MOUSE_BUT3; + + return but; +} + +static unsigned int get_button(unsigned int button) { + switch(button) { + case Button1: + return MOUSE_BUT1; + case Button2: + return MOUSE_BUT2; + case Button3: + return MOUSE_BUT3; + } + return 0; +} + +/*! \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_shapes(redraw_man_t *rdman, + co_aix x, co_aix y, int etype, + unsigned int state, + unsigned int button) { + mouse_event_t mouse_event; + shape_t *shape; + subject_t *subject; + ob_factory_t *factory; + int in_stroke; + + mouse_event.event.type = etype; + mouse_event.x = x; + mouse_event.y = y; + mouse_event.but_state = state; + mouse_event.button = button; + + shape = find_shape_at_pos(rdman, x, y, + &in_stroke); + if(shape == NULL) + return; + subject = sh_get_mouse_event_subject(shape); + factory = rdman_get_ob_factory(rdman); + + subject_notify(factory, subject, (event_t *)&mouse_event); +} + +/*! \brief Dispatch all X 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; + XButtonEvent *bevt; co_aix x, y; - int in_stroke; - int but; + unsigned int state, button; int r; while(XEventsQueued(display, QueuedAfterReading) > 0) { @@ -27,29 +86,35 @@ break; switch(evt.type) { + case ButtonPress: + bevt = (XButtonEvent *)&evt; + x = bevt->x; + y = bevt->y; + state = get_button_state(bevt->state); + button = get_button(bevt->button); + + notify_shapes(rdman, x, y, EVT_MOUSE_BUT_PRESS, + state, button); + break; + + case ButtonRelease: + bevt = (XButtonEvent *)&evt; + x = bevt->x; + y = bevt->y; + state = get_button_state(bevt->state); + button = get_button(bevt->button); + + notify_shapes(rdman, x, y, EVT_MOUSE_BUT_RELEASE, + state, button); + break; + 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; + state = get_button_state(mevt->state); - 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); + notify_shapes(rdman, x, y, EVT_MOUSE_MOVE, state, 0); break; case Expose: @@ -63,10 +128,17 @@ } /*! \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_handle_connection(Display *display, - redraw_man_t *rdman, - mb_tman_t *tman) { +void X_MB_handle_connection(Display *display, + redraw_man_t *rdman, + mb_tman_t *tman) { int fd; mb_timeval_t now, tmo; struct timeval tv; @@ -74,6 +146,9 @@ int nfds; int r; + rdman_redraw_all(rdman); + XFlush(display); + fd = XConnectionNumber(display); nfds = fd + 1; while(1) { @@ -105,3 +180,112 @@ } } } + +#define ERR -1 +#define OK 0 + +static int X_init_connection(const char *display_name, + int w, int h, + Display **displayp, + Visual **visualp, + Window *winp) { + Display *display; + Window root, win; + Visual *visual; + int screen; + XSetWindowAttributes wattr; + int depth; + int x, y; + int r; + + display = XOpenDisplay(display_name); + if(display == NULL) + return ERR; + + screen = DefaultScreen(display); + root = DefaultRootWindow(display); + visual = DefaultVisual(display, screen); + depth = DefaultDepth(display, screen); + wattr.override_redirect = False; + x = 10; + y = 10; + win = XCreateWindow(display, root, + x, y, + w, h, + 1, depth, InputOutput, visual, + CWOverrideRedirect, &wattr); + r = XMapWindow(display, win); + if(r == -1) { + XCloseDisplay(display); + return ERR; + } + + XSelectInput(display, win, PointerMotionMask | ExposureMask); + XFlush(display); + + *displayp = display; + *visualp = visual; + *winp = win; + + return OK; +} + +/*! \brief Initialize a MadButterfy runtime for Xlib. + * + * It setups a runtime environment to run MadButterfly with Xlib. + * Users should specify width and height of the opening window. + */ +int X_MB_init(const char *display_name, + int w, int h, X_MB_runtime_t *xmb_rt) { + memset(xmb_rt, 0, sizeof(X_MB_runtime_t)); + + xmb_rt->w = w; + xmb_rt->h = h; + X_init_connection(display_name, w, h, &xmb_rt->display, + &xmb_rt->visual, &xmb_rt->win); + + xmb_rt->surface = + cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); + + xmb_rt->backend_surface = + cairo_xlib_surface_create(xmb_rt->display, + xmb_rt->win, + xmb_rt->visual, + w, h); + + xmb_rt->cr = cairo_create(xmb_rt->surface); + xmb_rt->backend_cr = cairo_create(xmb_rt->backend_surface); + + cairo_set_source_surface(xmb_rt->backend_cr, xmb_rt->surface, 0, 0); + + xmb_rt->rdman = (redraw_man_t *)malloc(sizeof(redraw_man_t)); + redraw_man_init(xmb_rt->rdman, xmb_rt->cr, xmb_rt->backend_cr); + + xmb_rt->tman = mb_tman_new(); + + return OK; +} + +void X_MB_destroy(X_MB_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->cr) + cairo_destroy(xmb_rt->cr); + if(xmb_rt->backend_cr) + cairo_destroy(xmb_rt->backend_cr); + + if(xmb_rt->surface) + cairo_surface_destroy(xmb_rt->surface); + if(xmb_rt->backend_surface) + cairo_surface_destroy(xmb_rt->backend_surface); + + if(xmb_rt->display) + XCloseDisplay(xmb_rt->display); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/X_supp.h Wed Aug 20 23:33:04 2008 +0800 @@ -0,0 +1,28 @@ +#ifndef __X_SUPP_H_ +#define __X_SUPP_H_ + +#include <X11/Xlib.h> +#include "mb_timer.h" +#include "redraw_man.h" + +typedef struct _X_MB_runtime X_MB_runtime_t; +struct _X_MB_runtime { + Display *display; + Window win; + Visual *visual; + cairo_surface_t *surface, *backend_surface; + cairo_t *cr, *backend_cr; + redraw_man_t *rdman; + mb_tman_t *tman; + int w, h; +}; + +extern void X_MB_handle_connection(Display *display, + redraw_man_t *rdman, + mb_tman_t *tman); +extern int X_MB_init(const char *display_name, + int w, int h, X_MB_runtime_t *xmb_rt); +extern void X_MB_destroy(X_MB_runtime_t *xmb_rt); + + +#endif
--- a/src/observer.h Wed Aug 20 00:32:11 2008 +0800 +++ b/src/observer.h Wed Aug 20 23:33:04 2008 +0800 @@ -15,18 +15,29 @@ subject_t *tgt, *cur_tgt; }; +/*! \brief Observer of observer pattern. + * + * A target for receiving events. + */ struct _observer { evt_handler hdr; void *arg; observer_t *next; }; +/*! \brief Subject of observer pattern. + * + * Observer is a pattern to decouple caller and callee, + * especial for multiple callee. + * \see http://en.wikipedia.org/wiki/Observer_pattern + */ struct _subject { - int obj_type; - void *obj; + int obj_type; /*!< type of object (a.k.a. OBJT_*). */ + void *obj; /*!< the object this subject for. */ int flags; STAILQ(observer_t) observers; }; +/*! \brief Flag that make a subject to propagate events to parents. */ #define SUBF_STOP_PROPAGATE 0x1 enum {OBJT_GEO, OBJT_COORD}; @@ -34,7 +45,8 @@ struct _mouse_event { event_t event; int x, y; - int button; + unsigned int but_state; + unsigned int button; }; #define MOUSE_BUT1 0x1
--- a/src/timertool.c Wed Aug 20 00:32:11 2008 +0800 +++ b/src/timertool.c Wed Aug 20 23:33:04 2008 +0800 @@ -13,16 +13,20 @@ 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; + int r; if(MB_TIMEVAL_SEC(&tm) == 0) { sysctl_sz = sizeof(uint64_t); - cpufreq = sysctlbyname("kern.timecounter.tc.TSC.frequency", - &cpufreq, &sysctl_sz, - NULL, 0); + r = sysctlbyname("kern.timecounter.tc.TSC.frequency", + &cpufreq, &sysctl_sz, + NULL, 0); + if(r == -1) { + perror("sysctl"); + return; + } gettimeofday(&tv, NULL); last_ts = rdtsc();
--- a/tools/mb_c_header.m4 Wed Aug 20 00:32:11 2008 +0800 +++ b/tools/mb_c_header.m4 Wed Aug 20 23:33:04 2008 +0800 @@ -19,7 +19,8 @@ ]]) define([COLOR_STOP],[ ]) -define([REF_STOPS],) +define([REF_STOPS_RADIAL],) +define([REF_STOPS_LINEAR],) define([FILL_SHAPE],[[ paint_t *$1_fill; ]])
--- a/tools/mb_c_source.m4 Wed Aug 20 00:32:11 2008 +0800 +++ b/tools/mb_c_source.m4 Wed Aug 20 23:33:04 2008 +0800 @@ -32,7 +32,8 @@ DIMPORT([ADD_LINEAR_PAINT]) DIMPORT([ADD_RADIAL_PAINT]) DIMPORT([COLOR_STOP]) -define([REF_STOPS]) +define([REF_STOPS_RADIAL]) +define([REF_STOPS_LINEAR]) define([ADD_PATH]) define([ADD_RECT]) define([ADD_COORD]) @@ -61,12 +62,19 @@ ]) define([S_COLOR_STOP],[]) -define([S_REF_STOPS],[dnl + +define([S_REF_STOPS_RADIAL],[dnl [ stops = (grad_stop_t *)malloc(sizeof(grad_stop_t) * n_$2_stops); memcpy(stops, $2_stops, sizeof(grad_stop_t) * n_$2_stops); paint_radial_stops(obj->$1, n_$2_stops, stops); ]]) +define([S_REF_STOPS_LINEAR],[dnl +[ stops = (grad_stop_t *)malloc(sizeof(grad_stop_t) * n_$2_stops); + memcpy(stops, $2_stops, sizeof(grad_stop_t) * n_$2_stops); + paint_linear_stops(obj->$1, n_$2_stops, stops); +]]) + define([S_ADD_RECT],[[ obj->$1 = sh_rect_new($2, $3, $4, $5, 0, 0); rdman_add_shape(rdman, obj->$1, obj->$6); @@ -104,7 +112,8 @@ SIMPORT([ADD_LINEAR_PAINT]) SIMPORT([ADD_RADIAL_PAINT]) SIMPORT([COLOR_STOP]) -SIMPORT([REF_STOPS]) +SIMPORT([REF_STOPS_RADIAL]) +SIMPORT([REF_STOPS_LINEAR]) SIMPORT([ADD_PATH],) SIMPORT([ADD_RECT]) SIMPORT([ADD_COORD]) @@ -147,7 +156,8 @@ FIMPORT([ADD_LINEAR_PAINT]) FIMPORT([ADD_RADIAL_PAINT]) define([COLOR_STOP]) -define([REF_STOPS]) +define([REF_STOPS_RADIAL]) +define([REF_STOPS_LINEAR]) FIMPORT([ADD_PATH],) FIMPORT([ADD_RECT]) define([ADD_COORD])
--- a/tools/svg2code.py Wed Aug 20 00:32:11 2008 +0800 +++ b/tools/svg2code.py Wed Aug 20 23:33:04 2008 +0800 @@ -51,7 +51,8 @@ href = linear.getAttributeNS(xlinkns, 'href').strip() if href and href[0] == '#': - print >> codefo, 'REF_STOPS([%s], [%s])dnl' % (linear_id, href[1:]) + print >> codefo, 'REF_STOPS_LINEAR([%s], [%s])dnl' % ( + linear_id, href[1:]) pass pass @@ -75,7 +76,8 @@ href = radial.getAttributeNS(xlinkns, 'href').strip() if href[0] == '#': - print >> codefo, 'REF_STOPS([%s], [%s])dnl' % (radial_id, href[1:]) + print >> codefo, 'REF_STOPS_RADIAL([%s], [%s])dnl' % ( + radial_id, href[1:]) pass pass