# HG changeset patch # User Thinker K.F. Li # Date 1285315602 -28800 # Node ID 881efcd8a18f638136be1e7621d627d271311d9b # Parent 3ce9daa9558b9d59b304c2755287f7aa42d52b2f# Parent bcc63b20d5c654dc33477d641647df526b4d8854 Merge from default branch diff -r 3ce9daa9558b -r 881efcd8a18f include/mb_X_supp.h --- a/include/mb_X_supp.h Tue Sep 21 00:40:36 2010 +0800 +++ b/include/mb_X_supp.h Fri Sep 24 16:06:42 2010 +0800 @@ -27,7 +27,9 @@ extern void X_MB_handle_connection(void *rt); extern void *X_MB_new(const char *display_name, int w, int h); +extern void *X_MB_new_with_win(Display *display, Window win); extern void X_MB_free(void *xmb_rt); +extern void X_MB_free_keep_win(void *rt); extern subject_t *X_MB_kbevents(void *xmb_rt); extern redraw_man_t *X_MB_rdman(void *xmb_rt); diff -r 3ce9daa9558b -r 881efcd8a18f include/mb_redraw_man.h --- a/include/mb_redraw_man.h Tue Sep 21 00:40:36 2010 +0800 +++ b/include/mb_redraw_man.h Fri Sep 24 16:06:42 2010 +0800 @@ -50,9 +50,14 @@ elmpool_t *geo_pool; elmpool_t *coord_pool; elmpool_t *shnode_pool; + elmpool_t *sh_path_pool; + elmpool_t *sh_rect_pool; elmpool_t *observer_pool; elmpool_t *subject_pool; elmpool_t *paint_color_pool; + elmpool_t *paint_linear_pool; + elmpool_t *paint_radial_pool; + elmpool_t *paint_image_pool; elmpool_t *pent_pool; elmpool_t *coord_canvas_pool; diff -r 3ce9daa9558b -r 881efcd8a18f nodejs/X_supp_njs.c --- a/nodejs/X_supp_njs.c Tue Sep 21 00:40:36 2010 +0800 +++ b/nodejs/X_supp_njs.c Fri Sep 24 16:06:42 2010 +0800 @@ -113,6 +113,22 @@ free(rt); } +/*! \brief Free njs_runtime_t. + */ +void +X_njs_MB_free_keep_win(njs_runtime_t *rt) { + /* + * stop IO and timer watcher + */ + if(rt->enable_io) + ev_io_stop(&rt->iowatcher); + if(rt->enable_timer) + ev_timer_stop(&rt->tmwatcher); + + X_MB_free_keep_win(rt->xrt); + free(rt); +} + int X_njs_MB_flush(njs_runtime_t *rt) { void *xrt = rt->xrt; @@ -141,6 +157,48 @@ return rt; } +/*! \brief Create a njs_runtime_t for an existed window. + * + * The njs_runtime_t created by this function must be free by + * X_njs_MB_free_keep_win(). + */ +njs_runtime_t * +X_njs_MB_new_with_win(void *display, long win) { + njs_runtime_t *rt; + void *xrt; + + rt = (njs_runtime_t *)malloc(sizeof(njs_runtime_t)); + ASSERT(rt != NULL); + + xrt = X_MB_new_with_win((Display *)display, win); + + rt->xrt = xrt; + rt->enable_io = 0; + rt->enable_timer = 0; /* no timer, now */ + + return rt; +} + +/*! \brief Pass a X event to X runtime. + */ +void +X_njs_MB_handle_single_event(njs_runtime_t *rt, void *evt) { + void *xrt = rt->xrt; + extern void _X_MB_handle_single_event(void *rt, void *evt); + + _X_MB_handle_single_event(xrt, evt); +} + +/*! \brief Called at end of an iteration of event loop. + */ +void +X_njs_MB_no_more_event(njs_runtime_t *rt) { + void *xrt = rt->xrt; + extern void _X_MB_no_more_event(void *rt); + + _X_MB_no_more_event(xrt); +} + /*! \brief Get X runtime that is backend of this njs runtime. */ void * diff -r 3ce9daa9558b -r 881efcd8a18f nodejs/X_supp_njs.h --- a/nodejs/X_supp_njs.h Tue Sep 21 00:40:36 2010 +0800 +++ b/nodejs/X_supp_njs.h Fri Sep 24 16:06:42 2010 +0800 @@ -16,7 +16,11 @@ extern void X_njs_MB_init_handle_connection(njs_runtime_t *rt); extern void X_njs_MB_free(njs_runtime_t *rt); extern njs_runtime_t *X_njs_MB_new(char *display_name, int w, int h); +extern void X_njs_MB_free_keep_win(njs_runtime_t *rt); +extern njs_runtime_t *X_njs_MB_new_with_win(void *display, long win); extern int X_njs_MB_flush(njs_runtime_t *rt); +extern void X_njs_MB_handle_single_event(njs_runtime_t *rt, void *evt); +extern void X_njs_MB_no_more_event(njs_runtime_t *rt); extern void *_X_njs_MB_get_X_runtime(njs_runtime_t *rt); #define X_njs_MB_kbevents(rt) X_MB_kbevents((rt)->xrt) diff -r 3ce9daa9558b -r 881efcd8a18f nodejs/mbapp.js --- a/nodejs/mbapp.js Tue Sep 21 00:40:36 2010 +0800 +++ b/nodejs/mbapp.js Fri Sep 24 16:06:42 2010 +0800 @@ -138,7 +138,32 @@ } } +var app_with_win = function(display, win) { + var self = this; + var mb_rt; + var background; + var paint; + + if(typeof display == "undefined" || typeof win == "undefined") + throw "Invalid argument"; + + mb_rt = this.mb_rt = new mbfly.mb_rt_with_win(display, win); + background = mb_rt.rect_new(0, 0, 720, 480, 0, 0); + paint = mb_rt.paint_color_new(1, 1, 1, 1); + paint.fill(background); + mb_rt.root.add_shape(background); + + this.mb_rt.kbevents. + add_event_observer(exports.EVT_KB_PRESS, + function(evt) { self.KeyPress(evt); }); + this.keymap = {}; + this.onKeyPress = null; +} + +app_with_win.prototype = app.prototype; + exports.app=app; +exports.app_with_win = app_with_win; // Put all key definition here exports.KEY_LEFT = 0xff51; diff -r 3ce9daa9558b -r 881efcd8a18f nodejs/mbfly_njs.cc --- a/nodejs/mbfly_njs.cc Tue Sep 21 00:40:36 2010 +0800 +++ b/nodejs/mbfly_njs.cc Fri Sep 24 16:06:42 2010 +0800 @@ -58,6 +58,16 @@ rdman_redraw_all(rdman); } +static void +xnjsmb_handle_single_event(njs_runtime_t *rt, void *evt) { + X_njs_MB_handle_single_event(rt, evt); +} + +static void +xnjsmb_no_more_event(njs_runtime_t *rt) { + X_njs_MB_no_more_event(rt); +} + static njs_runtime_t * _X_njs_MB_new(Handle self, char *display_name, int width, int height) { @@ -80,6 +90,27 @@ return obj; } +static njs_runtime_t * +_X_njs_MB_new_with_win(Handle self, void *display, + long win) { + njs_runtime_t *obj; + subject_t *subject; + Handle subject_o; + + obj = X_njs_MB_new_with_win(display, win); + WRAP(self, obj); /* mkroot need a wrapped object, but + * it is wrapped after returning of + * this function. So, we wrap it + * here. */ + xnjsmb_coord_mkroot(self); + + subject = X_njs_MB_kbevents(obj); + subject_o = export_xnjsmb_auto_subject_new(subject); + SET(self, "kbevents", subject_o); + + return obj; +} + /*! \defgroup njs_template_cb Callback functions for v8 engine and nodejs. * * @{ @@ -138,6 +169,8 @@ * Initialize template for MadButterfly runtime objects. */ xnjsmb_auto_mb_rt_init(); + xnjsmb_auto_mb_rt_display_init(); + xnjsmb_auto_mb_rt_with_win_init(); /* * Add properties to mb_rt templates for other modules. @@ -150,6 +183,8 @@ target->Set(String::New("mb_rt"), xnjsmb_auto_mb_rt_temp->GetFunction()); + target->Set(String::New("mb_rt_with_win"), + xnjsmb_auto_mb_rt_with_win_temp->GetFunction()); } /* @} */ diff -r 3ce9daa9558b -r 881efcd8a18f nodejs/mbfly_njs.m4 --- a/nodejs/mbfly_njs.m4 Tue Sep 21 00:40:36 2010 +0800 +++ b/nodejs/mbfly_njs.m4 Fri Sep 24 16:06:42 2010 +0800 @@ -39,6 +39,27 @@ METHOD([paint_radial_new], [xnjsmb_paint_radial_new], (NUMBER(cx), NUMBER(cy), NUMBER(r), ERR), 3, [OBJ([paint_radial], [paint_t])], - (([MOD], [xnjsmb_mb_rt_objs_mod])))], + (([MOD], [xnjsmb_mb_rt_objs_mod]))), + METHOD([handle_single_event], [xnjsmb_handle_single_event], + (OBJ([evt], [event], [void])), 1, []), + METHOD([no_more_event], [xnjsmb_no_more_event], + (), 0, [])], ((CTOR, ([_X_njs_MB_new], (SELF, STR(display_name), INT(width), INT(height)), 3)))dnl ) +dnl +dnl +dnl +STRUCT([mb_rt_display], [void], [], + [], + ())dnl +dnl +dnl Function to create mb_rt for an existed window. +dnl +STRUCT([mb_rt_with_win], [njs_runtime_t], [], + [], + ((CTOR, ([_X_njs_MB_new_with_win],dnl + (SELF, OBJ([display], [mb_rt_display], [void]),dnl + INT([window])),dnl + 2)),dnl + ([INHERIT], [mb_rt]))dnl +) diff -r 3ce9daa9558b -r 881efcd8a18f nodejs/svg.js diff -r 3ce9daa9558b -r 881efcd8a18f nodejs/testdesktop.js diff -r 3ce9daa9558b -r 881efcd8a18f src/X_main.c --- a/src/X_main.c Tue Sep 21 00:40:36 2010 +0800 +++ b/src/X_main.c Fri Sep 24 16:06:42 2010 +0800 @@ -210,7 +210,7 @@ tman = mb_tman_new(); if(tman) { /* Prepare an animation program. */ - progm = mb_progm_new(10, &rdman); + progm = mb_progm_new(30, &rdman); MB_TIMEVAL_SET(&start, 0, 0); MB_TIMEVAL_SET(&playing, 1, 0); @@ -237,6 +237,166 @@ act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); act = mb_visibility_new(VIS_VISIBLE, coord3, word); + MB_TIMEVAL_SET(&start, 5, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, 20, coord1, word); + act = mb_shift_new(0, -20, coord2, word); + act = mb_chgcolor_new(1, 0, 0, 1, fill1, word); + act = mb_chgcolor_new(0, 0, 1, 1, fill2, word); + act = mb_visibility_new(VIS_HIDDEN, coord3, word); + + MB_TIMEVAL_SET(&start, 7, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, -20, coord1, word); + act = mb_shift_new(0, 20, coord2, word); + act = mb_chgcolor_new(0, 1, 0, 0.5, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); + act = mb_visibility_new(VIS_VISIBLE, coord3, word); + + MB_TIMEVAL_SET(&start, 9, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, 20, coord1, word); + act = mb_shift_new(0, -20, coord2, word); + act = mb_chgcolor_new(0, 0, 1, 1, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 1, fill2, word); + act = mb_visibility_new(VIS_HIDDEN, coord3, word); + + MB_TIMEVAL_SET(&start, 11, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, -20, coord1, word); + act = mb_shift_new(0, 20, coord2, word); + act = mb_chgcolor_new(0, 1, 0, 0.5, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); + act = mb_visibility_new(VIS_VISIBLE, coord3, word); + + MB_TIMEVAL_SET(&start, 13, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, 20, coord1, word); + act = mb_shift_new(0, -20, coord2, word); + act = mb_chgcolor_new(0, 0, 1, 1, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 1, fill2, word); + act = mb_visibility_new(VIS_HIDDEN, coord3, word); + + MB_TIMEVAL_SET(&start, 15, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, -20, coord1, word); + act = mb_shift_new(0, 20, coord2, word); + act = mb_chgcolor_new(0, 1, 0, 0.5, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); + act = mb_visibility_new(VIS_VISIBLE, coord3, word); + + MB_TIMEVAL_SET(&start, 17, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, 20, coord1, word); + act = mb_shift_new(0, -20, coord2, word); + act = mb_chgcolor_new(0, 0, 1, 1, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 1, fill2, word); + act = mb_visibility_new(VIS_HIDDEN, coord3, word); + + MB_TIMEVAL_SET(&start, 19, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, -20, coord1, word); + act = mb_shift_new(0, 20, coord2, word); + act = mb_chgcolor_new(0, 1, 0, 0.5, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); + act = mb_visibility_new(VIS_VISIBLE, coord3, word); + + MB_TIMEVAL_SET(&start, 21, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, 20, coord1, word); + act = mb_shift_new(0, -20, coord2, word); + act = mb_chgcolor_new(0, 0, 1, 1, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 1, fill2, word); + act = mb_visibility_new(VIS_HIDDEN, coord3, word); + + MB_TIMEVAL_SET(&start, 23, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, -20, coord1, word); + act = mb_shift_new(0, 20, coord2, word); + act = mb_chgcolor_new(0, 1, 0, 0.5, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); + act = mb_visibility_new(VIS_VISIBLE, coord3, word); + + MB_TIMEVAL_SET(&start, 25, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, 20, coord1, word); + act = mb_shift_new(0, -20, coord2, word); + act = mb_chgcolor_new(0, 0, 1, 1, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 1, fill2, word); + act = mb_visibility_new(VIS_HIDDEN, coord3, word); + + MB_TIMEVAL_SET(&start, 27, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, -20, coord1, word); + act = mb_shift_new(0, 20, coord2, word); + act = mb_chgcolor_new(0, 1, 0, 0.5, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); + act = mb_visibility_new(VIS_VISIBLE, coord3, word); + + MB_TIMEVAL_SET(&start, 29, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, 20, coord1, word); + act = mb_shift_new(0, -20, coord2, word); + act = mb_chgcolor_new(0, 0, 1, 1, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 1, fill2, word); + act = mb_visibility_new(VIS_HIDDEN, coord3, word); + + MB_TIMEVAL_SET(&start, 31, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, -20, coord1, word); + act = mb_shift_new(0, 20, coord2, word); + act = mb_chgcolor_new(0, 1, 0, 0.5, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); + act = mb_visibility_new(VIS_VISIBLE, coord3, word); + + MB_TIMEVAL_SET(&start, 33, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, 20, coord1, word); + act = mb_shift_new(0, -20, coord2, word); + act = mb_chgcolor_new(0, 0, 1, 1, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 1, fill2, word); + act = mb_visibility_new(VIS_HIDDEN, coord3, word); + + MB_TIMEVAL_SET(&start, 35, 0); + MB_TIMEVAL_SET(&playing, 2, 0); + word = mb_progm_next_word(progm, &start, &playing); + + act = mb_shift_new(0, -20, coord1, word); + act = mb_shift_new(0, 20, coord2, word); + act = mb_chgcolor_new(0, 1, 0, 0.5, fill1, word); + act = mb_chgcolor_new(1, 0, 0, 0.5, fill2, word); + act = mb_visibility_new(VIS_VISIBLE, coord3, word); + /* Start playing the program. */ gettimeofday(&tv, NULL); MB_TIMEVAL_SET(&mbtv, tv.tv_sec, tv.tv_usec); diff -r 3ce9daa9558b -r 881efcd8a18f src/X_supp.c --- a/src/X_supp.c Tue Sep 21 00:40:36 2010 +0800 +++ b/src/X_supp.c Fri Sep 24 16:06:42 2010 +0800 @@ -43,6 +43,7 @@ mb_eventcb_t f; void *arg; } monitor_t; + struct _X_MB_runtime { Display *display; Window win; @@ -68,6 +69,16 @@ XImage *ximage; XShmSegmentInfo shminfo; #endif + + /* + * Following variables are used by handle_single_x_event() + */ + int last_evt_type; /* Type of last event */ + int eflag; + int ex1, ey1, ex2, ey2; /* Aggregate expose events */ + int mflag; + int mx, my; /* Position of last motion event */ + int mbut_state; /* Button state of last motion event */ }; #ifdef XSHM @@ -213,26 +224,184 @@ subject_notify(subject, (event_t *)&mouse_event); } -/*! \brief Dispatch all X events in the queue. +/*! \brief Handle motion event. */ -static void handle_x_event(X_MB_runtime_t *rt) { - Display *display = rt->display; +static void +handle_motion_event(X_MB_runtime_t *rt) { redraw_man_t *rdman = rt->rdman; - XEvent evt, peek_evt; + int x, y; + int state; + shape_t *shape; + coord_t *root; + int in_stroke; + + x = rt->mx; + y = rt->my; + state = rt->mbut_state; + + shape = find_shape_at_pos(rdman, x, y, + &in_stroke); +#ifdef ONLY_MOUSE_MOVE_RAW + if(shape != NULL) { + notify_coord_or_shape(rdman, (mb_obj_t *)shape, + x, y, EVT_MOUSE_MOVE_RAW, state, 0); + } else { + root = rdman_get_root(rdman); + notify_coord_or_shape(rdman, (mb_obj_t *)root, + x, y, EVT_MOUSE_MOVE_RAW, state, 0); + } +#else + if(shape != NULL) { + if(rt->last != shape) { + if(rt->last) + notify_coord_or_shape(rdman, rt->last, x, y, + EVT_MOUSE_OUT, state, 0); + notify_coord_or_shape(rdman, shape, x, y, + EVT_MOUSE_OVER, state, 0); + rt->last = shape; + } else + notify_coord_or_shape(rdman, shape, x, y, + EVT_MOUSE_MOVE, state, 0); + } else { + if(rt->last) { + notify_coord_or_shape(rdman, rt->last, x, y, + EVT_MOUSE_OUT, state, 0); + rt->last = NULL; + } + } +#endif + + rt->mflag = 0; +} + +/*! \brief Redraw exposed area. + */ +static void +handle_expose_event(X_MB_runtime_t *rt) { + redraw_man_t *rdman = rt->rdman; + int ex1, ey1, ex2, ey2; + + ex1 = rt->ex1; + ey1 = rt->ey1; + ex2 = rt->ex2; + ey2 = rt->ey2; + + rdman_redraw_area(rdman, ex1, ey1, (ex2 - ex1), (ey2 - ey1)); + + rt->eflag = 0; +} + +/*! \brief Handle single X event and maintain internal states. + * + * It keeps internal state in rt to improve performance. + */ +static void +handle_single_x_event(X_MB_runtime_t *rt, XEvent *evt) { + redraw_man_t *rdman = rt->rdman; XMotionEvent *mevt; XButtonEvent *bevt; XExposeEvent *eevt; XKeyEvent *xkey; - co_aix x, y, w, h; - - int eflag = 0; - int ex1=0, ey1=0, ex2=0, ey2=0; + int x, y, w, h; shape_t *shape; - coord_t *root; unsigned int state, button; int in_stroke; + + if(evt->type != MotionNotify && rt->mflag) + handle_motion_event(rt); + + 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); + + shape = find_shape_at_pos(rdman, x, y, + &in_stroke); + if(shape) + notify_coord_or_shape(rdman, (mb_obj_t *)shape, + 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); + + shape = find_shape_at_pos(rdman, x, y, + &in_stroke); + if(shape) + notify_coord_or_shape(rdman, (mb_obj_t *)shape, + x, y, EVT_MOUSE_BUT_RELEASE, + state, button); + break; + + case MotionNotify: + mevt = (XMotionEvent *)evt; + rt->mx = mevt->x; + rt->my = mevt->y; + rt->mbut_state = get_button_state(mevt->state); + rt->mflag = 1; + break; + + case KeyPress: + case KeyRelease: + xkey = &evt->xkey; + X_kb_handle_event(&rt->kbinfo, xkey); + break; + + case Expose: + eevt = &evt->xexpose; + x = eevt->x; + y = eevt->y; + w = eevt->width; + h = eevt->height; + + if(rt->eflag) { + if(x < rt->ex1) + rt->ex1 = x; + if(y < rt->ey1) + rt->ey1 = y; + if((x + w) > rt->ex2) + rt->ex2 = x + w; + if((y + h) > rt->ey2) + rt->ey2 = y + h; + } else { + rt->ex1 = x; + rt->ey1 = y; + rt->ex2 = x + w; + rt->ey2 = y + h; + rt->eflag = 1; + } + break; + } +} + +/*! \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(X_MB_runtime_t *rt) { + if(rt->mflag) + handle_motion_event(rt); + if(rt->eflag) + handle_expose_event(rt); +} + +/*! \brief Dispatch all X events in the queue. + */ +static void handle_x_event(X_MB_runtime_t *rt) { + Display *display = rt->display; + XEvent evt; int r; /* XXX: For some unknown reason, it causes a segmentation fault to @@ -244,123 +413,10 @@ if(r == -1) 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); - - shape = find_shape_at_pos(rdman, x, y, - &in_stroke); - if(shape) - notify_coord_or_shape(rdman, (mb_obj_t *)shape, - 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); - - shape = find_shape_at_pos(rdman, x, y, - &in_stroke); - if(shape) - notify_coord_or_shape(rdman, (mb_obj_t *)shape, - x, y, EVT_MOUSE_BUT_RELEASE, - state, button); - break; - - case MotionNotify: - while(XEventsQueued(display, QueuedAfterReading) > 0) { - r = XPeekEvent(display, &peek_evt); - if(r == -1) - break; - if(peek_evt.type != MotionNotify) - break; - XNextEvent(display, &evt); - } - if(r == -1) - break; - - mevt = (XMotionEvent *)&evt; - x = mevt->x; - y = mevt->y; - state = get_button_state(mevt->state); - - shape = find_shape_at_pos(rdman, x, y, - &in_stroke); -#ifdef ONLY_MOUSE_MOVE_RAW - if(shape != NULL) { - notify_coord_or_shape(rdman, (mb_obj_t *)shape, - x, y, EVT_MOUSE_MOVE_RAW, state, 0); - } else { - root = rdman_get_root(rdman); - notify_coord_or_shape(rdman, (mb_obj_t *)root, - x, y, EVT_MOUSE_MOVE_RAW, state, 0); - } -#else - if(shape != NULL) { - if(rt->last != shape) { - if(rt->last) - notify_coord_or_shape(rdman, rt->last, x, y, - EVT_MOUSE_OUT, state, 0); - notify_coord_or_shape(rdman, shape, x, y, - EVT_MOUSE_OVER, state, 0); - rt->last = shape; - } else - notify_coord_or_shape(rdman, shape, x, y, - EVT_MOUSE_MOVE, state, 0); - } else { - if(rt->last) { - notify_coord_or_shape(rdman, rt->last, x, y, - EVT_MOUSE_OUT, state, 0); - rt->last = NULL; - } - } -#endif - break; - - case KeyPress: - case KeyRelease: - xkey = &evt.xkey; - X_kb_handle_event(&rt->kbinfo, xkey); - break; - - case Expose: - eevt = &evt.xexpose; - x = eevt->x; - y = eevt->y; - w = eevt->width; - h = eevt->height; - - if(eflag) { - if(x < ex1) - ex1 = x; - if(y < ey1) - ey1 = y; - if((x + w) > ex2) - ex2 = x + w; - if((y + h) > ey2) - ey2 = y + h; - } else { - ex1 = x; - ey1 = y; - ex2 = x + w; - ey2 = y + h; - eflag = 1; - } - break; - } + handle_single_x_event(rt, &evt); } - if(eflag) { - rdman_redraw_area(rdman, ex1, ey1, (ex2 - ex1), (ey2 - ey1)); - eflag = 0; - } + no_more_event(rt); + #ifdef XSHM XSHM_update(rt); #endif @@ -616,7 +672,7 @@ * - visual */ static int -X_MB_init_with_win(X_MB_runtime_t *xmb_rt) { +X_MB_init_with_win_internal(X_MB_runtime_t *xmb_rt) { mb_img_ldr_t *img_ldr; int w, h; @@ -673,8 +729,8 @@ * 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(const char *display_name, - int w, int h, X_MB_runtime_t *xmb_rt) { +static int X_MB_init(X_MB_runtime_t *xmb_rt, const char *display_name, + int w, int h) { int r; memset(xmb_rt, 0, sizeof(X_MB_runtime_t)); @@ -686,7 +742,35 @@ if(r != OK) return ERR; - r = X_MB_init_with_win(xmb_rt); + r = X_MB_init_with_win_internal(xmb_rt); + + return r; +} + +/*! \brief Initialize a MadButterfly runtime for a window of X. + * + * Runtimes initialized with this function should be destroyed with + * X_MB_destroy_keep_win(). + */ +static int +X_MB_init_with_win(X_MB_runtime_t *xmb_rt, + Display *display, Window win) { + XWindowAttributes attrs; + int r; + + r = XGetWindowAttributes(display, win, &attrs); + if(r == 0) + return ERR; + + memset(xmb_rt, 0, sizeof(X_MB_runtime_t)); + + xmb_rt->display = display; + xmb_rt->win = win; + xmb_rt->visual = attrs.visual; + xmb_rt->w = attrs.width; + xmb_rt->h = attrs.height; + + r = X_MB_init_with_win_internal(xmb_rt); return r; } @@ -721,6 +805,28 @@ X_kb_destroy(&xmb_rt->kbinfo); } +/*! \brief Destroy a MadButterfly runtime initialized with + * X_MB_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) { + Display *display; + Window win; + + display = xmb_rt->display; + xmb_rt->display = NULL; + win = xmb_rt->win; + xmb_rt->win = 0; + + X_MB_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; int r; @@ -729,7 +835,29 @@ if(rt == NULL) return NULL; - r = X_MB_init(display_name, w, h, rt); + r = X_MB_init(rt, display_name, w, h); + if(r != OK) { + free(rt); + return NULL; + } + + return 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. + */ +void *X_MB_new_with_win(Display *display, Window win) { + X_MB_runtime_t *rt; + int r; + + rt = O_ALLOC(X_MB_runtime_t); + if(rt == NULL) + return NULL; + + r = X_MB_init_with_win(rt, display, win); if(r != OK) { free(rt); return NULL; @@ -743,6 +871,14 @@ free(rt); } +/*! \brief Free runtime created with X_MB_new_with_win(). + */ +void +X_MB_free_keep_win(void *rt) { + X_MB_destroy_keep_win((X_MB_runtime_t *) rt); + free(rt); +} + subject_t *X_MB_kbevents(void *rt) { X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; return xmb_rt->kbinfo.kbevents; @@ -854,4 +990,22 @@ return XFlush(xmb_rt->display); } +/*! \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; + + handle_single_x_event(xmb_rt, (XEvent *)evt); +} + +/*! \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; + + no_more_event(xmb_rt); +} + /* @} */ diff -r 3ce9daa9558b -r 881efcd8a18f src/paint.c --- a/src/paint.c Tue Sep 21 00:40:36 2010 +0800 +++ b/src/paint.c Fri Sep 24 16:06:42 2010 +0800 @@ -82,6 +82,8 @@ #define LIF_DIRTY 0x1 +int _paint_linear_size = sizeof(paint_linear_t); + static void paint_linear_prepare(paint_t *paint, mbe_t *cr) { paint_linear_t *linear = (paint_linear_t *)paint; mbe_pattern_t *ptn; @@ -107,7 +109,7 @@ if(linear->ptn) mbe_pattern_destroy(linear->ptn); paint_destroy(paint); - free(paint); + elmpool_elm_free(rdman->paint_linear_pool, linear); } paint_t *rdman_paint_linear_new(redraw_man_t *rdman, @@ -115,7 +117,7 @@ co_aix x2, co_aix y2) { paint_linear_t *linear; - linear = (paint_linear_t *)malloc(sizeof(paint_linear_t)); + linear = (paint_linear_t *)elmpool_elm_alloc(rdman->paint_linear_pool); if(linear == NULL) return NULL; @@ -170,6 +172,8 @@ #define RDF_DIRTY 0x1 +int _paint_radial_size = sizeof(paint_radial_t); + static void paint_radial_prepare(paint_t *paint, mbe_t *cr) { paint_radial_t *radial = (paint_radial_t *)paint; mbe_pattern_t *ptn; @@ -193,14 +197,14 @@ if(radial->ptn) mbe_pattern_destroy(radial->ptn); paint_destroy(paint); - free(paint); + elmpool_elm_free(rdman->paint_radial_pool, radial); } paint_t *rdman_paint_radial_new(redraw_man_t *rdman, co_aix cx, co_aix cy, co_aix r) { paint_radial_t *radial; - radial = O_ALLOC(paint_radial_t); + radial = elmpool_elm_alloc(rdman->paint_radial_pool); if(radial == NULL) return NULL; @@ -249,6 +253,8 @@ mbe_pattern_t *ptn; } paint_image_t; +int _paint_image_size = sizeof(paint_image_t); + static void paint_image_prepare(paint_t *paint, mbe_t *cr) { paint_image_t *paint_img = (paint_image_t *)paint; @@ -267,7 +273,7 @@ img_data = paint_img->img; MB_IMG_DATA_FREE(img_data); paint_destroy(&paint_img->paint); - free(paint); + elmpool_elm_free(rdman->paint_image_pool, paint_img); } /*! \brief Create an image painter. @@ -281,7 +287,7 @@ mb_img_data_t *img) { paint_image_t *paint; - paint = O_ALLOC(paint_image_t); + paint = elmpool_elm_alloc(rdman->paint_image_pool); if(paint == NULL) return NULL; @@ -295,7 +301,7 @@ img->stride); if(paint->surf == NULL) { paint_destroy(&paint->paint); - free(paint); + elmpool_elm_free(rdman->paint_image_pool, paint); return NULL; } @@ -303,7 +309,7 @@ if(paint->ptn == NULL) { paint_destroy(&paint->paint); mbe_surface_destroy(paint->surf); - free(paint); + elmpool_elm_free(rdman->paint_image_pool, paint); return NULL; } diff -r 3ce9daa9558b -r 881efcd8a18f src/redraw_man.c --- a/src/redraw_man.c Tue Sep 21 00:40:36 2010 +0800 +++ b/src/redraw_man.c Fri Sep 24 16:06:42 2010 +0800 @@ -644,7 +644,12 @@ int redraw_man_init(redraw_man_t *rdman, mbe_t *cr, mbe_t *backend) { extern void redraw_man_destroy(redraw_man_t *rdman); + extern int _sh_path_size; + extern int _sh_rect_size; extern int _paint_color_size; + extern int _paint_linear_size; + extern int _paint_radial_size; + extern int _paint_image_size; observer_t *addrm_ob; extern void addrm_monitor_hdlr(event_t *evt, void *arg); @@ -658,9 +663,14 @@ rdman->geo_pool = elmpool_new(sizeof(geo_t), 128); rdman->coord_pool = elmpool_new(sizeof(coord_t), 16); rdman->shnode_pool = elmpool_new(sizeof(shnode_t), 16); + rdman->sh_path_pool = elmpool_new(_sh_path_size, 16); + rdman->sh_rect_pool = elmpool_new(_sh_rect_size, 16); rdman->observer_pool = elmpool_new(sizeof(observer_t), 32); rdman->subject_pool = elmpool_new(sizeof(subject_t), 32); rdman->paint_color_pool = elmpool_new(_paint_color_size, 64); + rdman->paint_linear_pool = elmpool_new(_paint_linear_size, 64); + rdman->paint_radial_pool = elmpool_new(_paint_radial_size, 64); + rdman->paint_image_pool = elmpool_new(_paint_image_size, 64); rdman->pent_pool = elmpool_new(sizeof(mb_prop_entry_t), 128); rdman->coord_canvas_pool = elmpool_new(sizeof(coord_canvas_info_t), 16); if(!(rdman->geo_pool && rdman->coord_pool && rdman->shnode_pool && @@ -725,12 +735,22 @@ elmpool_free(rdman->coord_pool); if(rdman->shnode_pool) elmpool_free(rdman->shnode_pool); + if(rdman->sh_path_pool) + elmpool_free(rdman->sh_path_pool); + if(rdman->sh_rect_pool) + elmpool_free(rdman->sh_rect_pool); if(rdman->observer_pool) elmpool_free(rdman->observer_pool); if(rdman->subject_pool) elmpool_free(rdman->subject_pool); if(rdman->paint_color_pool) elmpool_free(rdman->paint_color_pool); + if(rdman->paint_linear_pool) + elmpool_free(rdman->paint_linear_pool); + if(rdman->paint_radial_pool) + elmpool_free(rdman->paint_radial_pool); + if(rdman->paint_image_pool) + elmpool_free(rdman->paint_image_pool); if(rdman->pent_pool) elmpool_free(rdman->pent_pool); if(rdman->coord_canvas_pool) @@ -784,9 +804,14 @@ elmpool_free(rdman->coord_pool); elmpool_free(rdman->geo_pool); elmpool_free(rdman->shnode_pool); + elmpool_free(rdman->sh_path_pool); + elmpool_free(rdman->sh_rect_pool); elmpool_free(rdman->observer_pool); elmpool_free(rdman->subject_pool); elmpool_free(rdman->paint_color_pool); + elmpool_free(rdman->paint_linear_pool); + elmpool_free(rdman->paint_radial_pool); + elmpool_free(rdman->paint_image_pool); elmpool_free(rdman->pent_pool); elmpool_free(rdman->coord_canvas_pool); @@ -1368,7 +1393,7 @@ */ static int compute_area(coord_t *coord) { - static co_aix (*poses)[2]; + static co_aix (*poses)[2] = NULL; static int max_poses = 0; geo_t *geo; int cnt, pos_cnt; @@ -1379,7 +1404,8 @@ } if(max_poses < (cnt * 2)) { - free(poses); + if(poses) + free(poses); max_poses = cnt * 2; poses = (co_aix (*)[2])malloc(sizeof(co_aix [2]) * max_poses); if(poses == NULL) diff -r 3ce9daa9558b -r 881efcd8a18f src/shape_path.c --- a/src/shape_path.c Tue Sep 21 00:40:36 2010 +0800 +++ b/src/shape_path.c Fri Sep 24 16:06:42 2010 +0800 @@ -25,9 +25,13 @@ int float_arg_len; char *user_data; char *dev_data; /* device space data */ + + redraw_man_t *rdman; /*!< \brief This is used by sh_path_free() */ } sh_path_t; #define RESERVED_AIXS sizeof(co_aix[2]) +int _sh_path_size = sizeof(sh_path_t); + #define ASSERT(x) #define SKIP_SPACE(x) while(*(x) && (isspace(*(x)) || *(x) == ',')) { (x)++; } #define SKIP_NUM(x) \ @@ -47,6 +51,20 @@ #ifdef UNITTEST #undef rdman_shape_man #define rdman_shape_man(x, y) + +#undef elmpool_elm_alloc +#define elmpool_elm_alloc(pool) _elmpool_elm_alloc(pool) +static void * +_elmpool_elm_alloc(void *dummy) { + return malloc(sizeof(sh_path_t)); +} + +#undef elmpool_elm_free +#define elmpool_elm_free(pool, elm) _elmpool_elm_free(pool, elm) +static void +_elmpool_elm_free(void *pool, void *elm) { + free(elm); +} #endif /* ============================================================ @@ -382,7 +400,7 @@ mb_obj_destroy(path); if(path->user_data) free(path->user_data); - free(path); + elmpool_elm_free(path->rdman->sh_path_pool, path); } /*! \brief Count number of arguments. @@ -800,7 +818,7 @@ cmd_cnt = (cmd_cnt + 3) & ~0x3; /*! \todo Use elmpool to manage sh_path_t objects. */ - path = (sh_path_t *)malloc(sizeof(sh_path_t)); + path = (sh_path_t *)elmpool_elm_alloc(rdman->sh_path_pool); /*! \todo Remove this memset()? */ memset(&path->shape, 0, sizeof(shape_t)); mb_obj_init(path, MBO_PATH); @@ -812,7 +830,7 @@ sizeof(co_aix) * float_arg_cnt; path->user_data = (char *)malloc(msz * 2); if(path->user_data == NULL) { - free(path); + elmpool_elm_free(rdman->sh_path_pool, path); return NULL; } @@ -821,12 +839,13 @@ r = sh_path_cmd_arg_fill(data, path); if(r == ERR) { free(path->user_data); - free(path); + elmpool_elm_free(rdman->sh_path_pool, path); return NULL; } memcpy(path->dev_data, path->user_data, msz); path->shape.free = sh_path_free; + path->rdman = rdman; rdman_shape_man(rdman, (shape_t *)path); @@ -843,7 +862,7 @@ int cmd_cnt = strlen(commands); /*! \todo Use elmpool to manage sh_path_t objects. */ - path = (sh_path_t *)malloc(sizeof(sh_path_t)); + path = (sh_path_t *)elmpool_elm_alloc(rdman->sh_path_pool); /*! \todo Remove this memset()? */ memset(&path->shape, 0, sizeof(shape_t)); mb_obj_init(path, MBO_PATH); @@ -855,7 +874,7 @@ sizeof(co_aix) * float_arg_cnt; path->user_data = (char *)malloc(msz * 2); if(path->user_data == NULL) { - free(path); + elmpool_elm_free(rdman->sh_path_pool, path); return NULL; } @@ -867,6 +886,7 @@ memcpy(path->dev_data, path->user_data, msz); path->shape.free = sh_path_free; + path->rdman = rdman; rdman_shape_man(rdman, (shape_t *)path); @@ -1003,8 +1023,9 @@ void test_rdman_shape_path_new(void) { sh_path_t *path; co_aix *pnts; + redraw_man_t rdman; - path = (sh_path_t *)rdman_shape_path_new(NULL, "M 33 25l33 55c 33 87 44 22 55 99L33 77z"); + path = (sh_path_t *)rdman_shape_path_new(&rdman, "M 33 25l33 55c 33 87 44 22 55 99L33 77z"); CU_ASSERT(path != NULL); CU_ASSERT(path->cmd_len == ((5 + RESERVED_AIXS + 3) & ~0x3)); CU_ASSERT(path->pnt_len == 12); @@ -1032,8 +1053,9 @@ co_aix *pnts; coord_t coord; geo_t geo; + redraw_man_t rdman; - path = (sh_path_t *)rdman_shape_path_new(NULL, "M 33 25l33 55C 33 87 44 22 55 99L33 77z"); + path = (sh_path_t *)rdman_shape_path_new(&rdman, "M 33 25l33 55C 33 87 44 22 55 99L33 77z"); CU_ASSERT(path != NULL); CU_ASSERT(path->cmd_len == ((5 + RESERVED_AIXS + 3) & ~0x3)); CU_ASSERT(path->pnt_len == 12); @@ -1072,9 +1094,10 @@ void test_spaces_head_tail(void) { sh_path_t *path; + redraw_man_t rdman; path = (sh_path_t *) - rdman_shape_path_new(NULL, + rdman_shape_path_new(&rdman, " M 33 25l33 55C 33 87 44 22 55 99L33 77z "); CU_ASSERT(path != NULL); sh_path_free((shape_t *)path); diff -r 3ce9daa9558b -r 881efcd8a18f src/shape_rect.c --- a/src/shape_rect.c Tue Sep 21 00:40:36 2010 +0800 +++ b/src/shape_rect.c Fri Sep 24 16:06:42 2010 +0800 @@ -12,10 +12,16 @@ co_aix w, h; co_aix rx, ry; co_aix poses[12][2]; + + redraw_man_t *rdman; /*!< \brief This is used by sh_rect_free() */ } sh_rect_t; +int _sh_rect_size = sizeof(sh_rect_t); + static void sh_rect_free(shape_t *shape) { - free(shape); + sh_rect_t *rect = (sh_rect_t *)shape; + + elmpool_elm_free(rect->rdman->sh_rect_pool, rect); } shape_t *rdman_shape_rect_new(redraw_man_t *rdman, @@ -23,7 +29,7 @@ co_aix rx, co_aix ry) { sh_rect_t *rect; - rect = (sh_rect_t *)malloc(sizeof(sh_rect_t)); + rect = (sh_rect_t *)elmpool_elm_alloc(rdman->sh_rect_pool); if(rect == NULL) return NULL; @@ -37,6 +43,7 @@ rect->rx = rx; rect->ry = ry; rect->shape.free = sh_rect_free; + rect->rdman = rdman; rdman_shape_man(rdman, (shape_t *)rect);