Mercurial > MadButterfly
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 /* @} */ |