comparison src/X_supp.c @ 869:c18058fb48ee

Export API for JS to feed X events. We need the API that JS code can feed X events to X runtime.
author Thinker K.F. Li <thinker@codemud.net>
date Fri, 24 Sep 2010 03:22:19 +0800
parents 586e50f82c1f
children 512204bcafba
comparison
equal deleted inserted replaced
868:f41ac71266bc 869:c18058fb48ee
41 int type; 41 int type;
42 int fd; 42 int fd;
43 mb_eventcb_t f; 43 mb_eventcb_t f;
44 void *arg; 44 void *arg;
45 } monitor_t; 45 } monitor_t;
46
46 struct _X_MB_runtime { 47 struct _X_MB_runtime {
47 Display *display; 48 Display *display;
48 Window win; 49 Window win;
49 Visual *visual; 50 Visual *visual;
50 mbe_surface_t *surface, *backend_surface; 51 mbe_surface_t *surface, *backend_surface;
66 67
67 #ifdef XSHM 68 #ifdef XSHM
68 XImage *ximage; 69 XImage *ximage;
69 XShmSegmentInfo shminfo; 70 XShmSegmentInfo shminfo;
70 #endif 71 #endif
72
73 /*
74 * Following variables are used by handle_single_x_event()
75 */
76 int last_evt_type; /* Type of last event */
77 int eflag;
78 int ex1, ey1, ex2, ey2; /* Aggregate expose events */
79 int mflag;
80 int mx, my; /* Position of last motion event */
81 int mbut_state; /* Button state of last motion event */
71 }; 82 };
72 83
73 #ifdef XSHM 84 #ifdef XSHM
74 static void 85 static void
75 XSHM_update(X_MB_runtime_t *xmb_rt) { 86 XSHM_update(X_MB_runtime_t *xmb_rt) {
211 subject = coord_get_mouse_event((coord_t *)obj); 222 subject = coord_get_mouse_event((coord_t *)obj);
212 223
213 subject_notify(subject, (event_t *)&mouse_event); 224 subject_notify(subject, (event_t *)&mouse_event);
214 } 225 }
215 226
216 /*! \brief Dispatch all X events in the queue. 227 /*! \brief Handle motion event.
217 */ 228 */
218 static void handle_x_event(X_MB_runtime_t *rt) { 229 static void
219 Display *display = rt->display; 230 handle_motion_event(X_MB_runtime_t *rt) {
220 redraw_man_t *rdman = rt->rdman; 231 redraw_man_t *rdman = rt->rdman;
221 XEvent evt, peek_evt; 232 int x, y;
233 int state;
234 shape_t *shape;
235 coord_t *root;
236 int in_stroke;
237
238 x = rt->mx;
239 y = rt->my;
240 state = rt->mbut_state;
241
242 shape = find_shape_at_pos(rdman, x, y,
243 &in_stroke);
244 #ifdef ONLY_MOUSE_MOVE_RAW
245 if(shape != NULL) {
246 notify_coord_or_shape(rdman, (mb_obj_t *)shape,
247 x, y, EVT_MOUSE_MOVE_RAW, state, 0);
248 } else {
249 root = rdman_get_root(rdman);
250 notify_coord_or_shape(rdman, (mb_obj_t *)root,
251 x, y, EVT_MOUSE_MOVE_RAW, state, 0);
252 }
253 #else
254 if(shape != NULL) {
255 if(rt->last != shape) {
256 if(rt->last)
257 notify_coord_or_shape(rdman, rt->last, x, y,
258 EVT_MOUSE_OUT, state, 0);
259 notify_coord_or_shape(rdman, shape, x, y,
260 EVT_MOUSE_OVER, state, 0);
261 rt->last = shape;
262 } else
263 notify_coord_or_shape(rdman, shape, x, y,
264 EVT_MOUSE_MOVE, state, 0);
265 } else {
266 if(rt->last) {
267 notify_coord_or_shape(rdman, rt->last, x, y,
268 EVT_MOUSE_OUT, state, 0);
269 rt->last = NULL;
270 }
271 }
272 #endif
273
274 rt->mflag = 0;
275 }
276
277 /*! \brief Redraw exposed area.
278 */
279 static void
280 handle_expose_event(X_MB_runtime_t *rt) {
281 redraw_man_t *rdman = rt->rdman;
282 int ex1, ey1, ex2, ey2;
283
284 ex1 = rt->ex1;
285 ey1 = rt->ey1;
286 ex2 = rt->ex2;
287 ey2 = rt->ey2;
288
289 rdman_redraw_area(rdman, ex1, ey1, (ex2 - ex1), (ey2 - ey1));
290
291 rt->eflag = 0;
292 }
293
294 /*! \brief Handle single X event and maintain internal states.
295 *
296 * It keeps internal state in rt to improve performance.
297 */
298 static void
299 handle_single_x_event(X_MB_runtime_t *rt, XEvent *evt) {
300 redraw_man_t *rdman = rt->rdman;
222 XMotionEvent *mevt; 301 XMotionEvent *mevt;
223 XButtonEvent *bevt; 302 XButtonEvent *bevt;
224 XExposeEvent *eevt; 303 XExposeEvent *eevt;
225 XKeyEvent *xkey; 304 XKeyEvent *xkey;
226 co_aix x, y, w, h; 305 int x, y, w, h;
227
228 int eflag = 0;
229 int ex1=0, ey1=0, ex2=0, ey2=0;
230 306
231 shape_t *shape; 307 shape_t *shape;
232 coord_t *root;
233 308
234 unsigned int state, button; 309 unsigned int state, button;
235 int in_stroke; 310 int in_stroke;
311
312 if(evt->type != MotionNotify && rt->mflag)
313 handle_motion_event(rt);
314
315 switch(evt->type) {
316 case ButtonPress:
317 bevt = (XButtonEvent *)evt;
318 x = bevt->x;
319 y = bevt->y;
320 state = get_button_state(bevt->state);
321 button = get_button(bevt->button);
322
323 shape = find_shape_at_pos(rdman, x, y,
324 &in_stroke);
325 if(shape)
326 notify_coord_or_shape(rdman, (mb_obj_t *)shape,
327 x, y, EVT_MOUSE_BUT_PRESS,
328 state, button);
329 break;
330
331 case ButtonRelease:
332 bevt = (XButtonEvent *)evt;
333 x = bevt->x;
334 y = bevt->y;
335 state = get_button_state(bevt->state);
336 button = get_button(bevt->button);
337
338 shape = find_shape_at_pos(rdman, x, y,
339 &in_stroke);
340 if(shape)
341 notify_coord_or_shape(rdman, (mb_obj_t *)shape,
342 x, y, EVT_MOUSE_BUT_RELEASE,
343 state, button);
344 break;
345
346 case MotionNotify:
347 mevt = (XMotionEvent *)evt;
348 rt->mx = mevt->x;
349 rt->my = mevt->y;
350 rt->mbut_state = get_button_state(mevt->state);
351 rt->mflag = 1;
352 break;
353
354 case KeyPress:
355 case KeyRelease:
356 xkey = &evt->xkey;
357 X_kb_handle_event(&rt->kbinfo, xkey);
358 break;
359
360 case Expose:
361 eevt = &evt->xexpose;
362 x = eevt->x;
363 y = eevt->y;
364 w = eevt->width;
365 h = eevt->height;
366
367 if(rt->eflag) {
368 if(x < rt->ex1)
369 rt->ex1 = x;
370 if(y < rt->ey1)
371 rt->ey1 = y;
372 if((x + w) > rt->ex2)
373 rt->ex2 = x + w;
374 if((y + h) > rt->ey2)
375 rt->ey2 = y + h;
376 } else {
377 rt->ex1 = x;
378 rt->ey1 = y;
379 rt->ex2 = x + w;
380 rt->ey2 = y + h;
381 rt->eflag = 1;
382 }
383 break;
384 }
385 }
386
387 /*! \brief Call when no more event in an event iteration.
388 *
389 * No more event means event queue is emplty. This function will
390 * perform some actions according current internal state.
391 */
392 static void
393 no_more_event(X_MB_runtime_t *rt) {
394 if(rt->mflag)
395 handle_motion_event(rt);
396 if(rt->eflag)
397 handle_expose_event(rt);
398 }
399
400 /*! \brief Dispatch all X events in the queue.
401 */
402 static void handle_x_event(X_MB_runtime_t *rt) {
403 Display *display = rt->display;
404 XEvent evt;
236 int r; 405 int r;
237 406
238 /* XXX: For some unknown reason, it causes a segmentation fault to 407 /* XXX: For some unknown reason, it causes a segmentation fault to
239 * called XEventsQueued() after receiving first Expose event 408 * called XEventsQueued() after receiving first Expose event
240 * and before redraw for the event. 409 * and before redraw for the event.
242 while(XEventsQueued(display, QueuedAfterReading) > 0) { 411 while(XEventsQueued(display, QueuedAfterReading) > 0) {
243 r = XNextEvent(display, &evt); 412 r = XNextEvent(display, &evt);
244 if(r == -1) 413 if(r == -1)
245 break; 414 break;
246 415
247 switch(evt.type) { 416 handle_single_x_event(rt, &evt);
248 case ButtonPress: 417 }
249 bevt = (XButtonEvent *)&evt; 418 no_more_event(rt);
250 x = bevt->x; 419
251 y = bevt->y;
252 state = get_button_state(bevt->state);
253 button = get_button(bevt->button);
254
255 shape = find_shape_at_pos(rdman, x, y,
256 &in_stroke);
257 if(shape)
258 notify_coord_or_shape(rdman, (mb_obj_t *)shape,
259 x, y, EVT_MOUSE_BUT_PRESS,
260 state, button);
261 break;
262
263 case ButtonRelease:
264 bevt = (XButtonEvent *)&evt;
265 x = bevt->x;
266 y = bevt->y;
267 state = get_button_state(bevt->state);
268 button = get_button(bevt->button);
269
270 shape = find_shape_at_pos(rdman, x, y,
271 &in_stroke);
272 if(shape)
273 notify_coord_or_shape(rdman, (mb_obj_t *)shape,
274 x, y, EVT_MOUSE_BUT_RELEASE,
275 state, button);
276 break;
277
278 case MotionNotify:
279 while(XEventsQueued(display, QueuedAfterReading) > 0) {
280 r = XPeekEvent(display, &peek_evt);
281 if(r == -1)
282 break;
283 if(peek_evt.type != MotionNotify)
284 break;
285 XNextEvent(display, &evt);
286 }
287 if(r == -1)
288 break;
289
290 mevt = (XMotionEvent *)&evt;
291 x = mevt->x;
292 y = mevt->y;
293 state = get_button_state(mevt->state);
294
295 shape = find_shape_at_pos(rdman, x, y,
296 &in_stroke);
297 #ifdef ONLY_MOUSE_MOVE_RAW
298 if(shape != NULL) {
299 notify_coord_or_shape(rdman, (mb_obj_t *)shape,
300 x, y, EVT_MOUSE_MOVE_RAW, state, 0);
301 } else {
302 root = rdman_get_root(rdman);
303 notify_coord_or_shape(rdman, (mb_obj_t *)root,
304 x, y, EVT_MOUSE_MOVE_RAW, state, 0);
305 }
306 #else
307 if(shape != NULL) {
308 if(rt->last != shape) {
309 if(rt->last)
310 notify_coord_or_shape(rdman, rt->last, x, y,
311 EVT_MOUSE_OUT, state, 0);
312 notify_coord_or_shape(rdman, shape, x, y,
313 EVT_MOUSE_OVER, state, 0);
314 rt->last = shape;
315 } else
316 notify_coord_or_shape(rdman, shape, x, y,
317 EVT_MOUSE_MOVE, state, 0);
318 } else {
319 if(rt->last) {
320 notify_coord_or_shape(rdman, rt->last, x, y,
321 EVT_MOUSE_OUT, state, 0);
322 rt->last = NULL;
323 }
324 }
325 #endif
326 break;
327
328 case KeyPress:
329 case KeyRelease:
330 xkey = &evt.xkey;
331 X_kb_handle_event(&rt->kbinfo, xkey);
332 break;
333
334 case Expose:
335 eevt = &evt.xexpose;
336 x = eevt->x;
337 y = eevt->y;
338 w = eevt->width;
339 h = eevt->height;
340
341 if(eflag) {
342 if(x < ex1)
343 ex1 = x;
344 if(y < ey1)
345 ey1 = y;
346 if((x + w) > ex2)
347 ex2 = x + w;
348 if((y + h) > ey2)
349 ey2 = y + h;
350 } else {
351 ex1 = x;
352 ey1 = y;
353 ex2 = x + w;
354 ey2 = y + h;
355 eflag = 1;
356 }
357 break;
358 }
359 }
360 if(eflag) {
361 rdman_redraw_area(rdman, ex1, ey1, (ex2 - ex1), (ey2 - ey1));
362 eflag = 0;
363 }
364 #ifdef XSHM 420 #ifdef XSHM
365 XSHM_update(rt); 421 XSHM_update(rt);
366 #endif 422 #endif
367 XFlush(display); 423 XFlush(display);
368 } 424 }
852 XSHM_update(xmb_rt); 908 XSHM_update(xmb_rt);
853 #endif 909 #endif
854 return XFlush(xmb_rt->display); 910 return XFlush(xmb_rt->display);
855 } 911 }
856 912
913 /*! \brief Handle single X event.
914 */
915 void
916 _X_MB_handle_single_event(void *rt, void *evt) {
917 X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *)rt;
918
919 handle_single_x_event(xmb_rt, (XEvent *)evt);
920 }
921
922 /*! \brief Called at end of an iteration of X event loop.
923 */
924 void
925 _X_MB_no_more_event(void *rt) {
926 X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *)rt;
927
928 no_more_event(xmb_rt);
929 }
930
857 /* @} */ 931 /* @} */