# HG changeset patch # User Thinker K.F. Li # Date 1285269739 -28800 # Node ID c18058fb48eecd4c032a2369d696f32347a2e277 # Parent f41ac71266bcec8a8f34adc9b04e3844acf4f297 Export API for JS to feed X events. We need the API that JS code can feed X events to X runtime. diff -r f41ac71266bc -r c18058fb48ee nodejs/X_supp_njs.c --- a/nodejs/X_supp_njs.c Thu Sep 23 10:51:25 2010 +0800 +++ b/nodejs/X_supp_njs.c Fri Sep 24 03:22:19 2010 +0800 @@ -141,6 +141,25 @@ 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; + + _X_MB_no_more_event(xrt); +} + /*! \brief Get X runtime that is backend of this njs runtime. */ void * diff -r f41ac71266bc -r c18058fb48ee nodejs/X_supp_njs.h --- a/nodejs/X_supp_njs.h Thu Sep 23 10:51:25 2010 +0800 +++ b/nodejs/X_supp_njs.h Fri Sep 24 03:22:19 2010 +0800 @@ -17,6 +17,8 @@ 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 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 f41ac71266bc -r c18058fb48ee nodejs/mbfly_njs.cc --- a/nodejs/mbfly_njs.cc Thu Sep 23 10:51:25 2010 +0800 +++ b/nodejs/mbfly_njs.cc Fri Sep 24 03:22:19 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) { diff -r f41ac71266bc -r c18058fb48ee nodejs/mbfly_njs.m4 --- a/nodejs/mbfly_njs.m4 Thu Sep 23 10:51:25 2010 +0800 +++ b/nodejs/mbfly_njs.m4 Fri Sep 24 03:22:19 2010 +0800 @@ -39,6 +39,10 @@ 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 ) diff -r f41ac71266bc -r c18058fb48ee src/X_supp.c --- a/src/X_supp.c Thu Sep 23 10:51:25 2010 +0800 +++ b/src/X_supp.c Fri Sep 24 03:22:19 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 @@ -854,4 +910,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); +} + /* @} */