comparison src/X_supp.c @ 1067:7b4e80ab671a openvg

merge from default branch
author Thinker K.F. Li <thinker@codemud.net>
date Wed, 01 Dec 2010 12:25:56 +0800
parents bd18951b51d5 e415c55b4a0d
children d09f603438d8
comparison
equal deleted inserted replaced
630:bd18951b51d5 1067:7b4e80ab671a
1 // -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*-
2 // vim: sw=4:ts=8:sts=4
1 #include <stdio.h> 3 #include <stdio.h>
2 #include <stdlib.h> 4 #include <stdlib.h>
3 #include <string.h> 5 #include <string.h>
4 #include <X11/Xlib.h> 6 #include <X11/Xlib.h>
5 #include <X11/Xutil.h> 7 #include <X11/Xutil.h>
8 #include <cairo-xlib.h>
6 #include "mb_graph_engine.h" 9 #include "mb_graph_engine.h"
7 #include "mb_redraw_man.h" 10 #include "mb_redraw_man.h"
8 #include "mb_timer.h" 11 #include "mb_timer.h"
9 #include "mb_X_supp.h" 12 #include "mb_X_supp.h"
13 #include "mb_backend.h"
14 #include "mb_backend_utils.h"
15 #include "config.h"
16
17 #ifdef XSHM
18 /* \sa http://www.xfree86.org/current/mit-shm.html */
19 #include <sys/ipc.h>
20 #include <sys/shm.h>
21 #include <X11/extensions/XShm.h>
22 static void XSHM_update(X_supp_runtime_t *xmb_rt);
23 #endif
10 24
11 #define ERR -1 25 #define ERR -1
12 #define OK 0 26 #define OK 0
13 27
28 #define ASSERT(x)
29
14 #define ONLY_MOUSE_MOVE_RAW 1 30 #define ONLY_MOUSE_MOVE_RAW 1
31
32 static mb_timer_factory_t *_timer_factory = &tman_timer_factory;
15 33
16 /*! \ingroup xkb 34 /*! \ingroup xkb
17 * @{ 35 * @{
18 */ 36 */
19 struct _X_kb_info { 37 struct _X_kb_info {
20 int keycode_min, keycode_max; 38 int keycode_min, keycode_max;
21 int ksym_per_code; 39 int ksym_per_code;
22 KeySym *syms; 40 KeySym *syms;
23 subject_t *kbevents; 41 subject_t *kbevents;
24 ob_factory_t *ob_factory; 42 observer_factory_t *observer_factory;
25 }; 43 };
26 44
27 /* @} */ 45 /* @} */
28 #define MAX_MONITORS 200 46
29 typedef struct { 47 struct _X_supp_runtime {
30 int type;
31 int fd;
32 mb_eventcb_t f;
33 void *arg;
34 } monitor_t;
35 struct _X_MB_runtime {
36 Display *display; 48 Display *display;
37 Window win; 49 Window win;
38 Visual *visual; 50 Visual *visual;
39 mbe_surface_t *surface, *backend_surface; 51 mbe_surface_t *surface, *backend_surface;
40 mbe_pattern_t *surface_ptn; 52 mbe_pattern_t *surface_ptn;
41 mbe_t *cr, *backend_cr; 53 mbe_t *cr, *backend_cr;
42 redraw_man_t *rdman; 54 redraw_man_t *rdman;
43 mb_tman_t *tman;
44 mb_img_ldr_t *img_ldr; 55 mb_img_ldr_t *img_ldr;
45 int w, h; 56 int w, h;
46 57
47 X_kb_info_t kbinfo; 58 X_kb_info_t kbinfo;
48 monitor_t monitors[MAX_MONITORS]; 59 mb_IO_man_t *io_man;
49 int n_monitor; 60 mb_timer_man_t *timer_man;
50 61
51 #ifndef ONLY_MOUSE_MOVE_RAW 62 #ifndef ONLY_MOUSE_MOVE_RAW
52 /* States */ 63 /* States */
53 shape_t *last; 64 shape_t *last;
54 #endif 65 #endif
66
67 #ifdef XSHM
68 XImage *ximage;
69 XShmSegmentInfo shminfo;
70 #endif
71
72 /* For handle connection */
73 int io_hdl;
74
75 /*
76 * Following variables are used by handle_single_x_event()
77 */
78 int last_evt_type; /* Type of last event */
79 int eflag;
80 int ex1, ey1, ex2, ey2; /* Aggregate expose events */
81 int mflag;
82 int mx, my; /* Position of last motion event */
83 int mbut_state; /* Button state of last motion event */
55 }; 84 };
85
86 static void _x_supp_handle_x_event(X_supp_runtime_t *rt);
87
88 /*! \defgroup x_supp_io IO manager for X.
89 * @{
90 */
91 #define MAX_MONITORS 200
92
93 typedef struct {
94 int type;
95 int fd;
96 mb_IO_cb_t cb;
97 void *data;
98 } monitor_t;
99
100 struct _X_supp_IO_man {
101 mb_IO_man_t io_man;
102 monitor_t monitors[MAX_MONITORS];
103 int n_monitor;
104 };
105
106 static int _x_supp_io_man_reg(struct _mb_IO_man *io_man,
107 int fd, MB_IO_TYPE type,
108 mb_IO_cb_t cb, void *data);
109 static void _x_supp_io_man_unreg(struct _mb_IO_man *io_man, int io_hdl);
110 static mb_IO_man_t *_x_supp_io_man_new(void);
111 static void _x_supp_io_man_free(mb_IO_man_t *io_man);
112
113 static mb_IO_factory_t _X_supp_default_io_factory = {
114 _x_supp_io_man_new,
115 _x_supp_io_man_free
116 };
117 static mb_IO_factory_t *_io_factory = &_X_supp_default_io_factory;
118
119 static struct _X_supp_IO_man _default_io_man = {
120 {_x_supp_io_man_reg, _x_supp_io_man_unreg},
121 {}, /* monitors */
122 0 /* n_monitor */
123 };
124
125 static mb_IO_man_t *
126 _x_supp_io_man_new(void) {
127 return (mb_IO_man_t *)&_default_io_man;
128 }
129
130 static void
131 _x_supp_io_man_free(mb_IO_man_t *io_man) {
132 }
133
134 static int
135 _x_supp_io_man_reg(struct _mb_IO_man *io_man,
136 int fd, MB_IO_TYPE type, mb_IO_cb_t cb, void *data) {
137 struct _X_supp_IO_man *xmb_io_man = (struct _X_supp_IO_man *)io_man;
138 int i;
139
140 for(i = 0; i < xmb_io_man->n_monitor; i++) {
141 if (xmb_io_man->monitors[i].type == MB_IO_DUMMY)
142 break;
143 }
144 if (i == MAX_MONITORS)
145 return ERR;
146
147 xmb_io_man->monitors[i].type = type;
148 xmb_io_man->monitors[i].fd = fd;
149 xmb_io_man->monitors[i].cb = cb;
150 xmb_io_man->monitors[i].data = data;
151 i++;
152 if(i > xmb_io_man->n_monitor)
153 xmb_io_man->n_monitor = i;
154 return i - 1;
155 }
156
157 static void
158 _x_supp_io_man_unreg(struct _mb_IO_man *io_man, int io_hdl) {
159 struct _X_supp_IO_man *xmb_io_man = (struct _X_supp_IO_man *)io_man;
160
161 ASSERT(io_hdl < xmb_io_man->n_monitor);
162 xmb_io_man->monitors[io_hdl].type = MB_IO_DUMMY;
163 }
164
165 /*! \brief Handle connection coming data and timeout of timers.
166 *
167 * \param display is a Display returned by XOpenDisplay().
168 * \param rdman is a redraw manager.
169 * \param tman is a timer manager.
170 *
171 * The display is managed by specified rdman and tman. rdman draws
172 * on the display, and tman trigger actions according timers.
173 */
174 static void
175 _x_supp_event_loop(mb_rt_t *rt) {
176 struct _X_supp_runtime *xmb_rt = (struct _X_supp_runtime *)rt;
177 struct _X_supp_IO_man *io_man = (struct _X_supp_IO_man *)xmb_rt->io_man;
178 mb_timer_man_t *timer_man = (mb_timer_man_t *)xmb_rt->timer_man;
179 redraw_man_t *rdman;
180 mb_tman_t *tman = tman_timer_man_get_tman(timer_man);
181 mb_timeval_t now, tmo;
182 struct timeval tv;
183 fd_set rfds, wfds;
184 int nfds = 0;
185 int r, r1,i;
186
187 rdman = mb_runtime_rdman(rt);
188
189 _x_supp_handle_x_event(xmb_rt);
190
191 while(1) {
192 FD_ZERO(&rfds);
193 FD_ZERO(&wfds);
194 for(i = 0; i < io_man->n_monitor; i++) {
195 if(io_man->monitors[i].type == MB_IO_R ||
196 io_man->monitors[i].type == MB_IO_RW) {
197 FD_SET(io_man->monitors[i].fd, &rfds);
198 nfds = MB_MAX(nfds, io_man->monitors[i].fd + 1);
199 }
200 if(io_man->monitors[i].type == MB_IO_W ||
201 io_man->monitors[i].type == MB_IO_RW) {
202 FD_SET(io_man->monitors[i].fd, &wfds);
203 nfds = MB_MAX(nfds, io_man->monitors[i].fd + 1);
204 }
205 }
206
207 get_now(&now);
208 r = mb_tman_next_timeout(tman, &now, &tmo);
209
210 if(r == 0) {
211 tv.tv_sec = MB_TIMEVAL_SEC(&tmo);
212 tv.tv_usec = MB_TIMEVAL_USEC(&tmo);
213 r1 = select(nfds, &rfds, NULL, NULL, &tv);
214 } else
215 r1 = select(nfds, &rfds, NULL, NULL, NULL);
216
217 if(r1 == -1) {
218 perror("select");
219 break;
220 }
221
222 if(r1 == 0) {
223 get_now(&now);
224 mb_tman_handle_timeout(tman, &now);
225 rdman_redraw_changed(rdman);
226 #ifdef XSHM
227 XSHM_update(xmb_rt);
228 #endif
229 XFlush(xmb_rt->display);
230 } else {
231 for(i = 0; i < io_man->n_monitor; i++) {
232 if(io_man->monitors[i].type == MB_IO_R ||
233 io_man->monitors[i].type == MB_IO_RW) {
234 if(FD_ISSET(io_man->monitors[i].fd, &rfds))
235 io_man->monitors[i].cb(i, io_man->monitors[i].fd,
236 MB_IO_R,
237 io_man->monitors[i].data);
238 }
239 if(io_man->monitors[i].type == MB_IO_W ||
240 io_man->monitors[i].type == MB_IO_RW) {
241 if(FD_ISSET(io_man->monitors[i].fd, &wfds))
242 io_man->monitors[i].cb(i, io_man->monitors[i].fd,
243 MB_IO_W,
244 io_man->monitors[i].data);
245 }
246 }
247 }
248 }
249 }
250
251 /* @} */
252
253 #ifdef XSHM
254 static void
255 XSHM_update(X_supp_runtime_t *xmb_rt) {
256 GC gc;
257
258 gc = DefaultGC(xmb_rt->display, DefaultScreen(xmb_rt->display));
259 if(xmb_rt->ximage) { /* support XSHM */
260 XShmPutImage(xmb_rt->display,
261 xmb_rt->win,
262 gc,
263 xmb_rt->ximage,
264 0, 0, 0, 0,
265 xmb_rt->w, xmb_rt->h, 0);
266 }
267 }
268 #endif
56 269
57 /*! \defgroup xkb X Keyboard Handling 270 /*! \defgroup xkb X Keyboard Handling
58 * 271 *
59 * Accept keyboard events from X server and delivery it to 272 * Accept keyboard events from X server and delivery it to
60 * application through observer pattern. There is a subject, 273 * application through observer pattern. There is a subject,
71 } 284 }
72 285
73 static int X_kb_init(X_kb_info_t *kbinfo, Display *display, 286 static int X_kb_init(X_kb_info_t *kbinfo, Display *display,
74 redraw_man_t *rdman) { 287 redraw_man_t *rdman) {
75 int n_syms; 288 int n_syms;
76 ob_factory_t *factory; 289 observer_factory_t *factory;
77 int r; 290 int r;
78 291
79 r = XDisplayKeycodes(display, 292 r = XDisplayKeycodes(display,
80 &kbinfo->keycode_min, 293 &kbinfo->keycode_min,
81 &kbinfo->keycode_max); 294 &kbinfo->keycode_max);
87 n_syms, 300 n_syms,
88 &kbinfo->ksym_per_code); 301 &kbinfo->ksym_per_code);
89 if(kbinfo->syms == NULL) 302 if(kbinfo->syms == NULL)
90 return ERR; 303 return ERR;
91 304
92 factory = rdman_get_ob_factory(rdman); 305 factory = rdman_get_observer_factory(rdman);
93 kbinfo->kbevents = subject_new(factory, kbinfo, OBJT_KB); 306 kbinfo->kbevents = subject_new(factory, kbinfo, OBJT_KB);
94 if(kbinfo->kbevents == NULL) 307 if(kbinfo->kbevents == NULL)
95 return ERR; 308 return ERR;
96 /*! \todo Make sure ob_factory is still need. */ 309 /*! \todo Make sure observer_factory is still need. */
97 kbinfo->ob_factory = factory; 310 kbinfo->observer_factory = factory;
98 311
99 return OK; 312 return OK;
100 } 313 }
101 314
102 static void X_kb_destroy(X_kb_info_t *kbinfo) { 315 static void X_kb_destroy(X_kb_info_t *kbinfo) {
103 subject_free(kbinfo->kbevents); 316 subject_free(kbinfo->kbevents);
104 XFree(kbinfo->syms); 317 XFree(kbinfo->syms);
105 } 318 }
106 319
107 /*! \brief Accept X keyboard events from handle_x_event() and dispatch it. 320 /*! \brief Accept X keyboard events from _x_supp_handle_x_event() and
321 * dispatch it.
108 */ 322 */
109 static void X_kb_handle_event(X_kb_info_t *kbinfo, XKeyEvent *xkey) { 323 static void X_kb_handle_event(X_kb_info_t *kbinfo, XKeyEvent *xkey) {
110 unsigned int code; 324 unsigned int code;
111 int sym; 325 int sym;
112 X_kb_event_t event; 326 X_kb_event_t event;
121 event.keycode = code; 335 event.keycode = code;
122 event.sym = sym; 336 event.sym = sym;
123 337
124 subject_notify(kbinfo->kbevents, &event.event); 338 subject_notify(kbinfo->kbevents, &event.event);
125 } 339 }
126
127 /* @} */ 340 /* @} */
128 341
129 static unsigned int get_button_state(unsigned int state) { 342 static unsigned int get_button_state(unsigned int state) {
130 unsigned int but = 0; 343 unsigned int but = 0;
131 344
133 but |= MOUSE_BUT1; 346 but |= MOUSE_BUT1;
134 if(state & Button2Mask) 347 if(state & Button2Mask)
135 but |= MOUSE_BUT2; 348 but |= MOUSE_BUT2;
136 if(state & Button3Mask) 349 if(state & Button3Mask)
137 but |= MOUSE_BUT3; 350 but |= MOUSE_BUT3;
138 351
139 return but; 352 return but;
140 } 353 }
141 354
142 static unsigned int get_button(unsigned int button) { 355 static unsigned int get_button(unsigned int button) {
143 switch(button) { 356 switch(button) {
169 mouse_event.event.type = etype; 382 mouse_event.event.type = etype;
170 mouse_event.x = x; 383 mouse_event.x = x;
171 mouse_event.y = y; 384 mouse_event.y = y;
172 mouse_event.but_state = state; 385 mouse_event.but_state = state;
173 mouse_event.button = button; 386 mouse_event.button = button;
174 387
175 if(IS_MBO_SHAPES(obj)) 388 if(IS_MBO_SHAPES(obj))
176 subject = sh_get_mouse_event_subject((shape_t *)obj); 389 subject = sh_get_mouse_event_subject((shape_t *)obj);
177 else 390 else
178 subject = coord_get_mouse_event((coord_t *)obj); 391 subject = coord_get_mouse_event((coord_t *)obj);
392
393 subject_notify(subject, (event_t *)&mouse_event);
394 }
395
396 /*! \brief Handle motion event.
397 */
398 static void
399 handle_motion_event(X_supp_runtime_t *rt) {
400 redraw_man_t *rdman = rt->rdman;
401 int x, y;
402 int state;
403 shape_t *shape;
404 coord_t *root;
405 int in_stroke;
179 406
180 subject_notify(subject, (event_t *)&mouse_event); 407 x = rt->mx;
181 } 408 y = rt->my;
182 409 state = rt->mbut_state;
183 /*! \brief Dispatch all X events in the queue. 410
184 */ 411 shape = find_shape_at_pos(rdman, x, y,
185 static void handle_x_event(X_MB_runtime_t *rt) { 412 &in_stroke);
186 Display *display = rt->display; 413 #ifdef ONLY_MOUSE_MOVE_RAW
414 if(shape != NULL) {
415 notify_coord_or_shape(rdman, (mb_obj_t *)shape,
416 x, y, EVT_MOUSE_MOVE_RAW, state, 0);
417 } else {
418 root = rdman_get_root(rdman);
419 notify_coord_or_shape(rdman, (mb_obj_t *)root,
420 x, y, EVT_MOUSE_MOVE_RAW, state, 0);
421 }
422 #else
423 if(shape != NULL) {
424 if(rt->last != shape) {
425 if(rt->last)
426 notify_coord_or_shape(rdman, rt->last, x, y,
427 EVT_MOUSE_OUT, state, 0);
428 notify_coord_or_shape(rdman, shape, x, y,
429 EVT_MOUSE_OVER, state, 0);
430 rt->last = shape;
431 } else
432 notify_coord_or_shape(rdman, shape, x, y,
433 EVT_MOUSE_MOVE, state, 0);
434 } else {
435 if(rt->last) {
436 notify_coord_or_shape(rdman, rt->last, x, y,
437 EVT_MOUSE_OUT, state, 0);
438 rt->last = NULL;
439 }
440 }
441 #endif
442
443 rt->mflag = 0;
444 }
445
446 /*! \brief Redraw exposed area.
447 */
448 static void
449 handle_expose_event(X_supp_runtime_t *rt) {
187 redraw_man_t *rdman = rt->rdman; 450 redraw_man_t *rdman = rt->rdman;
188 XEvent evt, peek_evt; 451 int ex1, ey1, ex2, ey2;
452
453 ex1 = rt->ex1;
454 ey1 = rt->ey1;
455 ex2 = rt->ex2;
456 ey2 = rt->ey2;
457
458 rdman_redraw_area(rdman, ex1, ey1, (ex2 - ex1), (ey2 - ey1));
459
460 rt->eflag = 0;
461 }
462
463 /*! \brief Handle single X event and maintain internal states.
464 *
465 * It keeps internal state in rt to improve performance.
466 */
467 static void
468 handle_single_x_event(X_supp_runtime_t *rt, XEvent *evt) {
469 redraw_man_t *rdman = rt->rdman;
189 XMotionEvent *mevt; 470 XMotionEvent *mevt;
190 XButtonEvent *bevt; 471 XButtonEvent *bevt;
191 XExposeEvent *eevt; 472 XExposeEvent *eevt;
192 XKeyEvent *xkey; 473 XKeyEvent *xkey;
193 co_aix x, y, w, h; 474 int x, y, w, h;
194
195 int eflag = 0;
196 int ex1=0, ey1=0, ex2=0, ey2=0;
197 475
198 shape_t *shape; 476 shape_t *shape;
199 coord_t *root;
200 477
201 unsigned int state, button; 478 unsigned int state, button;
202 int in_stroke; 479 int in_stroke;
480
481 if(evt->type != MotionNotify && rt->mflag)
482 handle_motion_event(rt);
483
484 switch(evt->type) {
485 case ButtonPress:
486 bevt = (XButtonEvent *)evt;
487 x = bevt->x;
488 y = bevt->y;
489 state = get_button_state(bevt->state);
490 button = get_button(bevt->button);
491
492 shape = find_shape_at_pos(rdman, x, y,
493 &in_stroke);
494 if(shape)
495 notify_coord_or_shape(rdman, (mb_obj_t *)shape,
496 x, y, EVT_MOUSE_BUT_PRESS,
497 state, button);
498 break;
499
500 case ButtonRelease:
501 bevt = (XButtonEvent *)evt;
502 x = bevt->x;
503 y = bevt->y;
504 state = get_button_state(bevt->state);
505 button = get_button(bevt->button);
506
507 shape = find_shape_at_pos(rdman, x, y,
508 &in_stroke);
509 if(shape)
510 notify_coord_or_shape(rdman, (mb_obj_t *)shape,
511 x, y, EVT_MOUSE_BUT_RELEASE,
512 state, button);
513 break;
514
515 case MotionNotify:
516 mevt = (XMotionEvent *)evt;
517 rt->mx = mevt->x;
518 rt->my = mevt->y;
519 rt->mbut_state = get_button_state(mevt->state);
520 rt->mflag = 1;
521 break;
522
523 case KeyPress:
524 case KeyRelease:
525 xkey = &evt->xkey;
526 X_kb_handle_event(&rt->kbinfo, xkey);
527 break;
528
529 case Expose:
530 eevt = &evt->xexpose;
531 x = eevt->x;
532 y = eevt->y;
533 w = eevt->width;
534 h = eevt->height;
535
536 if(rt->eflag) {
537 if(x < rt->ex1)
538 rt->ex1 = x;
539 if(y < rt->ey1)
540 rt->ey1 = y;
541 if((x + w) > rt->ex2)
542 rt->ex2 = x + w;
543 if((y + h) > rt->ey2)
544 rt->ey2 = y + h;
545 } else {
546 rt->ex1 = x;
547 rt->ey1 = y;
548 rt->ex2 = x + w;
549 rt->ey2 = y + h;
550 rt->eflag = 1;
551 }
552 break;
553 }
554 }
555
556 /*! \brief Call when no more event in an event iteration.
557 *
558 * No more event means event queue is emplty. This function will
559 * perform some actions according current internal state.
560 */
561 static void
562 no_more_event(X_supp_runtime_t *rt) {
563 if(rt->mflag)
564 handle_motion_event(rt);
565 if(rt->eflag)
566 handle_expose_event(rt);
567 }
568
569 /*! \brief Dispatch all X events in the queue.
570 */
571 static void _x_supp_handle_x_event(X_supp_runtime_t *rt) {
572 Display *display = rt->display;
573 XEvent evt;
203 int r; 574 int r;
204 575
205 /* XXX: For some unknown reason, it causes a segmentation fault to 576 /* XXX: For some unknown reason, it causes a segmentation fault to
206 * called XEventsQueued() after receiving first Expose event 577 * called XEventsQueued() after receiving first Expose event
207 * and before redraw for the event. 578 * and before redraw for the event.
209 while(XEventsQueued(display, QueuedAfterReading) > 0) { 580 while(XEventsQueued(display, QueuedAfterReading) > 0) {
210 r = XNextEvent(display, &evt); 581 r = XNextEvent(display, &evt);
211 if(r == -1) 582 if(r == -1)
212 break; 583 break;
213 584
214 switch(evt.type) { 585 handle_single_x_event(rt, &evt);
215 case ButtonPress: 586 }
216 bevt = (XButtonEvent *)&evt; 587 no_more_event(rt);
217 x = bevt->x; 588
218 y = bevt->y; 589 #ifdef XSHM
219 state = get_button_state(bevt->state); 590 XSHM_update(rt);
220 button = get_button(bevt->button);
221
222 shape = find_shape_at_pos(rdman, x, y,
223 &in_stroke);
224 if(shape)
225 notify_coord_or_shape(rdman, (mb_obj_t *)shape,
226 x, y, EVT_MOUSE_BUT_PRESS,
227 state, button);
228 break;
229
230 case ButtonRelease:
231 bevt = (XButtonEvent *)&evt;
232 x = bevt->x;
233 y = bevt->y;
234 state = get_button_state(bevt->state);
235 button = get_button(bevt->button);
236
237 shape = find_shape_at_pos(rdman, x, y,
238 &in_stroke);
239 if(shape)
240 notify_coord_or_shape(rdman, (mb_obj_t *)shape,
241 x, y, EVT_MOUSE_BUT_RELEASE,
242 state, button);
243 break;
244
245 case MotionNotify:
246 while(XEventsQueued(display, QueuedAfterReading) > 0) {
247 r = XPeekEvent(display, &peek_evt);
248 if(r == -1)
249 break;
250 if(peek_evt.type != MotionNotify)
251 break;
252 XNextEvent(display, &evt);
253 }
254 if(r == -1)
255 break;
256
257 mevt = (XMotionEvent *)&evt;
258 x = mevt->x;
259 y = mevt->y;
260 state = get_button_state(mevt->state);
261
262 shape = find_shape_at_pos(rdman, x, y,
263 &in_stroke);
264 #ifdef ONLY_MOUSE_MOVE_RAW
265 if(shape != NULL) {
266 notify_coord_or_shape(rdman, (mb_obj_t *)shape,
267 x, y, EVT_MOUSE_MOVE_RAW, state, 0);
268 } else {
269 root = rdman_get_root(rdman);
270 notify_coord_or_shape(rdman, (mb_obj_t *)root,
271 x, y, EVT_MOUSE_MOVE_RAW, state, 0);
272 }
273 #else
274 if(shape != NULL) {
275 if(rt->last != shape) {
276 if(rt->last)
277 notify_coord_or_shape(rdman, rt->last, x, y,
278 EVT_MOUSE_OUT, state, 0);
279 notify_coord_or_shape(rdman, shape, x, y,
280 EVT_MOUSE_OVER, state, 0);
281 rt->last = shape;
282 } else
283 notify_coord_or_shape(rdman, shape, x, y,
284 EVT_MOUSE_MOVE, state, 0);
285 } else {
286 if(rt->last) {
287 notify_coord_or_shape(rdman, rt->last, x, y,
288 EVT_MOUSE_OUT, state, 0);
289 rt->last = NULL;
290 }
291 }
292 #endif 591 #endif
293 break;
294
295 case KeyPress:
296 case KeyRelease:
297 xkey = &evt.xkey;
298 X_kb_handle_event(&rt->kbinfo, xkey);
299 break;
300
301 case Expose:
302 eevt = &evt.xexpose;
303 x = eevt->x;
304 y = eevt->y;
305 w = eevt->width;
306 h = eevt->height;
307
308 if(eflag) {
309 if(x < ex1)
310 ex1 = x;
311 if(y < ey1)
312 ey1 = y;
313 if((x + w) > ex2)
314 ex2 = x + w;
315 if((y + h) > ey2)
316 ey2 = y + h;
317 } else {
318 ex1 = x;
319 ey1 = y;
320 ex2 = x + w;
321 ey2 = y + h;
322 eflag = 1;
323 }
324 break;
325 }
326 }
327 if(eflag) {
328 rdman_redraw_area(rdman, ex1, ey1, (ex2 - ex1), (ey2 - ey1));
329 eflag = 0;
330 }
331 XFlush(display); 592 XFlush(display);
332 } 593 }
333 594
334 /*! \brief Handle connection coming data and timeout of timers. 595 static void
335 * 596 _x_supp_handle_connection(int hdl, int fd, MB_IO_TYPE type, void *data) {
336 * \param display is a Display returned by XOpenDisplay(). 597 X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *)data;
337 * \param rdman is a redraw manager. 598
338 * \param tman is a timer manager. 599 _x_supp_handle_x_event(xmb_rt);
339 * 600 }
340 * The display is managed by specified rdman and tman. rdman draws
341 * on the display, and tman trigger actions according timers.
342 */
343 void X_MB_handle_connection(void *be) {
344 X_MB_runtime_t *rt = (X_MB_runtime_t *) be;
345 Display *display = rt->display;
346 redraw_man_t *rdman = rt->rdman;
347 mb_tman_t *tman = rt->tman;
348 int fd;
349 mb_timeval_t now, tmo;
350 struct timeval tv;
351 fd_set rfds,wfds;
352 int nfds;
353 int r, r1,i;
354
355 handle_x_event(rt);
356
357 fd = XConnectionNumber(display);
358 nfds = fd + 1;
359 while(1) {
360 FD_ZERO(&rfds);
361 FD_ZERO(&wfds);
362 FD_SET(fd, &rfds);
363 for(i=0;i<rt->n_monitor;i++) {
364 if (rt->monitors[i].type == MONITOR_READ)
365 FD_SET(rt->monitors[i].fd, &rfds);
366 else if (rt->monitors[i].type == MONITOR_WRITE)
367 FD_SET(rt->monitors[i].fd, &wfds);
368 }
369
370 get_now(&now);
371 r = mb_tman_next_timeout(tman, &now, &tmo);
372
373 if(r == 0) {
374 tv.tv_sec = MB_TIMEVAL_SEC(&tmo);
375 tv.tv_usec = MB_TIMEVAL_USEC(&tmo);
376 r1 = select(nfds, &rfds, NULL, NULL, &tv);
377 } else
378 r1 = select(nfds, &rfds, NULL, NULL, NULL);
379
380 if(r1 == -1) {
381 perror("select");
382 break;
383 }
384
385 if(r1 == 0) {
386 get_now(&now);
387 mb_tman_handle_timeout(tman, &now);
388 rdman_redraw_changed(rdman);
389 XFlush(display);
390 } else if(FD_ISSET(fd, &rfds)){
391 handle_x_event(rt);
392 } else {
393 for(i=0;i<rt->n_monitor;i++) {
394 if (rt->monitors[i].type == MONITOR_READ)
395 if (FD_ISSET(rt->monitors[i].fd, &rfds))
396 rt->monitors[i].f(rt->monitors[i].fd,rt->monitors[i].arg);
397 else if (rt->monitors[i].type == MONITOR_WRITE)
398 if (FD_ISSET(rt->monitors[i].fd, &wfds))
399 rt->monitors[i].f(rt->monitors[i].fd,rt->monitors[i].arg);
400 }
401 }
402 }
403 }
404
405 #define ERR -1
406 #define OK 0
407 601
408 static int X_init_connection(const char *display_name, 602 static int X_init_connection(const char *display_name,
409 int w, int h, 603 int w, int h,
410 Display **displayp, 604 Display **displayp,
411 Visual **visualp, 605 Visual **visualp,
415 Visual *visual; 609 Visual *visual;
416 int screen; 610 int screen;
417 XSetWindowAttributes wattr; 611 XSetWindowAttributes wattr;
418 int depth; 612 int depth;
419 int x, y; 613 int x, y;
614 int draw_root = 0;
615 const char *disp_name;
616 char disp_buf[32];
617 int cp;
420 int r; 618 int r;
421 619
422 display = XOpenDisplay(display_name); 620 /*
621 * Support drawing on the root window.
622 */
623 disp_name = display_name;
624 if(strstr(display_name, ":root") != NULL) {
625 draw_root = 1;
626 cp = strlen(display_name) - 5;
627 if(cp >= 32)
628 cp = 31;
629 memcpy(disp_buf, display_name, cp);
630 disp_buf[cp] = 0;
631 disp_name = disp_buf;
632 }
633
634 display = XOpenDisplay(disp_name);
423 if(display == NULL) 635 if(display == NULL)
424 return ERR; 636 return ERR;
425 637
426 screen = DefaultScreen(display); 638 screen = DefaultScreen(display);
427 root = DefaultRootWindow(display); 639 root = DefaultRootWindow(display);
428 visual = DefaultVisual(display, screen); 640 visual = DefaultVisual(display, screen);
429 depth = DefaultDepth(display, screen); 641 depth = DefaultDepth(display, screen);
430 wattr.override_redirect = False; 642 wattr.override_redirect = False;
431 x = 10; 643 x = 10;
432 y = 10; 644 y = 10;
433 win = XCreateWindow(display, root, 645 if(draw_root)
434 x, y, 646 win = RootWindowOfScreen(ScreenOfDisplay(display, screen));
435 w, h, 647 else {
436 1, depth, InputOutput, visual, 648 win = XCreateWindow(display, root,
437 CWOverrideRedirect, &wattr); 649 x, y,
438 r = XMapWindow(display, win); 650 w, h,
439 if(r == -1) { 651 1, depth, InputOutput, visual,
440 XCloseDisplay(display); 652 CWOverrideRedirect, &wattr);
441 return ERR; 653 r = XMapWindow(display, win);
654 if(r == -1) {
655 XCloseDisplay(display);
656 return ERR;
657 }
442 } 658 }
443 659
444 XSelectInput(display, win, PointerMotionMask | ExposureMask | 660 XSelectInput(display, win, PointerMotionMask | ExposureMask |
445 ButtonPressMask | ButtonReleaseMask | 661 ButtonPressMask | ButtonReleaseMask |
446 KeyPressMask | KeyReleaseMask); 662 KeyPressMask | KeyReleaseMask);
451 *winp = win; 667 *winp = win;
452 668
453 return OK; 669 return OK;
454 } 670 }
455 671
672 #ifdef XSHM
673 static void
674 xshm_destroy(X_supp_runtime_t *xmb_rt) {
675 XShmSegmentInfo *shminfo;
676
677 shminfo = &xmb_rt->shminfo;
678
679 if(xmb_rt->shminfo.shmaddr) {
680 XShmDetach(xmb_rt->display, shminfo);
681 }
682
683 if(xmb_rt->ximage) {
684 XDestroyImage(xmb_rt->ximage);
685 xmb_rt->ximage = NULL;
686 }
687
688 if(shminfo->shmaddr) {
689 shmdt(shminfo->shmaddr);
690 shminfo->shmaddr = NULL;
691 }
692
693 if(shminfo->shmid) {
694 shmctl(shminfo->shmid, IPC_RMID, 0);
695 shminfo->shmid = 0;
696 }
697 }
698
699 static void
700 xshm_init(X_supp_runtime_t *xmb_rt) {
701 Display *display;
702 Visual *visual;
703 XImage *ximage;
704 int screen;
705 int depth;
706 int support_shm;
707 int mem_sz;
708 XShmSegmentInfo *shminfo;
709 int surf_fmt;
710
711 display = xmb_rt->display;
712 visual = xmb_rt->visual;
713 shminfo = &xmb_rt->shminfo;
714
715 support_shm = XShmQueryExtension(display);
716 if(!support_shm)
717 return;
718
719 screen = DefaultScreen(display);
720 depth = DefaultDepth(display, screen);
721
722 if(depth != 24 && depth != 32)
723 return;
724
725 xmb_rt->ximage = XShmCreateImage(display, visual, depth,
726 ZPixmap, NULL, shminfo,
727 xmb_rt->w, xmb_rt->h);
728 ximage = xmb_rt->ximage;
729
730 mem_sz = ximage->bytes_per_line * ximage->height;
731 shminfo->shmid = shmget(IPC_PRIVATE, mem_sz, IPC_CREAT | 0777);
732 if(shminfo->shmid == -1) {
733 xshm_destroy(xmb_rt);
734 return;
735 }
736
737 shminfo->shmaddr = shmat(shminfo->shmid, 0, 0);
738 ximage->data = shminfo->shmaddr;
739
740 shminfo->readOnly = 0;
741
742 XShmAttach(display, shminfo);
743
744 switch(depth) {
745 case 24: surf_fmt = CAIRO_FORMAT_RGB24; break;
746 case 32: surf_fmt = CAIRO_FORMAT_ARGB32; break;
747 }
748
749 xmb_rt->backend_surface =
750 mbe_image_surface_create_for_data((unsigned char *)ximage->data,
751 surf_fmt,
752 xmb_rt->w,
753 xmb_rt->h,
754 ximage->bytes_per_line);
755 if(xmb_rt->backend_surface == NULL)
756 xshm_destroy(xmb_rt);
757 }
758 #endif /* XSHM */
759
456 /*! \brief Initialize a MadButterfy runtime for Xlib. 760 /*! \brief Initialize a MadButterfy runtime for Xlib.
457 * 761 *
458 * It setups a runtime environment to run MadButterfly with Xlib. 762 * This one is very like _x_supp_init(), except it accepts a
459 * Users should specify width and height of the opening window. 763 * X_supp_runtime_t object initialized with a display connected to a X
460 */ 764 * server and an opened window.
461 static int X_MB_init(const char *display_name, 765 *
462 int w, int h, X_MB_runtime_t *xmb_rt) { 766 * Following field of the X_supp_runtime_t object should be initialized.
767 * - w, h
768 * - win
769 * - display
770 * - visual
771 */
772 static int
773 _x_supp_init_with_win_internal(X_supp_runtime_t *xmb_rt) {
463 mb_img_ldr_t *img_ldr; 774 mb_img_ldr_t *img_ldr;
464 775 int w, h;
465 memset(xmb_rt, 0, sizeof(X_MB_runtime_t)); 776 int disp_fd;
466 777
467 xmb_rt->w = w; 778 w = xmb_rt->w;
468 xmb_rt->h = h; 779 h = xmb_rt->h;
469 X_init_connection(display_name, w, h, &xmb_rt->display, 780
470 &xmb_rt->visual, &xmb_rt->win); 781 #ifdef XSHM
471 #ifdef OPENVG_GRAPH_ENGINE 782 xshm_init(xmb_rt);
472 _ge_openvg_disp_id = xmb_rt->display;
473 #endif 783 #endif
474
475 mbe_init();
476 784
477 xmb_rt->surface = 785 xmb_rt->surface =
478 mbe_image_surface_create(MB_IFMT_ARGB32, w, h); 786 mbe_image_surface_create(MB_IFMT_ARGB32, w, h);
479 787
480 xmb_rt->surface_ptn = 788 xmb_rt->surface_ptn =
481 mbe_pattern_create_for_surface(xmb_rt->surface); 789 mbe_pattern_create_for_surface(xmb_rt->surface);
482 790
483 #ifdef OPENVG_GRAPH_ENGINE 791 if(xmb_rt->backend_surface == NULL) /* xshm_init() may create one */
484 xmb_rt->backend_surface = 792 xmb_rt->backend_surface =
485 mbe_vg_win_surface_create(xmb_rt->display, 793 mbe_xlib_surface_create(xmb_rt->display,
486 xmb_rt->win, 794 xmb_rt->win,
487 xmb_rt->visual, 795 xmb_rt->visual,
488 w, h); 796 w, h);
489 #else
490 xmb_rt->backend_surface =
491 mbe_xlib_surface_create(xmb_rt->display,
492 xmb_rt->win,
493 xmb_rt->visual,
494 w, h);
495 #endif
496 797
497 xmb_rt->cr = mbe_create(xmb_rt->surface); 798 xmb_rt->cr = mbe_create(xmb_rt->surface);
498 xmb_rt->backend_cr = mbe_create(xmb_rt->backend_surface); 799 xmb_rt->backend_cr = mbe_create(xmb_rt->backend_surface);
499 800
500 /* TODO: Remove this line. Since we use mbe_copy_source(), it
501 * will set source for the backend. So, this line is redundants.
502 * It can be removed. sourface_ptn can be removed, too.
503 */
504 mbe_set_source(xmb_rt->backend_cr, xmb_rt->surface_ptn); 801 mbe_set_source(xmb_rt->backend_cr, xmb_rt->surface_ptn);
505 802
506 xmb_rt->rdman = (redraw_man_t *)malloc(sizeof(redraw_man_t)); 803 xmb_rt->rdman = (redraw_man_t *)malloc(sizeof(redraw_man_t));
507 redraw_man_init(xmb_rt->rdman, xmb_rt->cr, xmb_rt->backend_cr); 804 redraw_man_init(xmb_rt->rdman, xmb_rt->cr, xmb_rt->backend_cr);
508 // FIXME: This is a wired loopback reference. This is inly required when we need 805 // FIXME: This is a wired loopback reference. This is inly required when we need
509 // to get the xmb_rt->tman for the animation. We should relocate the tman 806 // to get the xmb_rt->tman for the animation. We should relocate the tman
510 // to the redraw_man_t instead. 807 // to the redraw_man_t instead.
511 xmb_rt->rdman->rt = xmb_rt; 808 xmb_rt->rdman->rt = xmb_rt;
512 xmb_rt->rdman->w = w; 809
513 xmb_rt->rdman->h = h; 810 xmb_rt->io_man = mb_io_man_new(_io_factory);
514 811 xmb_rt->timer_man = mb_timer_man_new(_timer_factory);
515 xmb_rt->tman = mb_tman_new();
516 812
517 img_ldr = simple_mb_img_ldr_new(""); 813 img_ldr = simple_mb_img_ldr_new("");
518 xmb_rt->img_ldr = img_ldr; 814 xmb_rt->img_ldr = img_ldr;
519 rdman_set_img_ldr(xmb_rt->rdman, img_ldr); 815 /*! \todo Remove rdman_set_img_ldr() */
520 memset(xmb_rt->monitors,0,sizeof(xmb_rt->monitors)); 816 rdman_set_img_ldr(xmb_rt->rdman, img_ldr); /* this is ncessary? */
521 817
522 #ifndef ONLY_MOUSE_MOVE_RAW 818 #ifndef ONLY_MOUSE_MOVE_RAW
523 xmb_rt->last = NULL; 819 xmb_rt->last = NULL;
524 #endif 820 #endif
525 821
526 X_kb_init(&xmb_rt->kbinfo, xmb_rt->display, xmb_rt->rdman); 822 X_kb_init(&xmb_rt->kbinfo, xmb_rt->display, xmb_rt->rdman);
527 823
824 disp_fd = XConnectionNumber(xmb_rt->display);
825 xmb_rt->io_hdl = mb_io_man_reg(xmb_rt->io_man, disp_fd,
826 MB_IO_R,
827 _x_supp_handle_connection,
828 xmb_rt);
829
528 return OK; 830 return OK;
529 } 831 }
530 832
531 static void X_MB_destroy(X_MB_runtime_t *xmb_rt) { 833 /*! \brief Initialize a MadButterfy runtime for Xlib.
834 *
835 * It setups a runtime environment to run MadButterfly with Xlib.
836 * Users should specify width and height of the opening window.
837 */
838 static int _x_supp_init(X_supp_runtime_t *xmb_rt, const char *display_name,
839 int w, int h) {
840 int r;
841
842 memset(xmb_rt, 0, sizeof(X_supp_runtime_t));
843
844 xmb_rt->w = w;
845 xmb_rt->h = h;
846 r = X_init_connection(display_name, w, h, &xmb_rt->display,
847 &xmb_rt->visual, &xmb_rt->win);
848 if(r != OK)
849 return ERR;
850
851 r = _x_supp_init_with_win_internal(xmb_rt);
852
853 return r;
854 }
855
856 /*! \brief Initialize a MadButterfly runtime for a window of X.
857 *
858 * Runtimes initialized with this function should be destroyed with
859 * x_supp_destroy_keep_win().
860 */
861 static int
862 _x_supp_init_with_win(X_supp_runtime_t *xmb_rt,
863 Display *display, Window win) {
864 XWindowAttributes attrs;
865 int r;
866
867 r = XGetWindowAttributes(display, win, &attrs);
868 if(r == 0)
869 return ERR;
870
871 memset(xmb_rt, 0, sizeof(X_supp_runtime_t));
872
873 xmb_rt->display = display;
874 xmb_rt->win = win;
875 xmb_rt->visual = attrs.visual;
876 xmb_rt->w = attrs.width;
877 xmb_rt->h = attrs.height;
878
879 r = _x_supp_init_with_win_internal(xmb_rt);
880
881 return r;
882 }
883
884 static void x_supp_destroy(X_supp_runtime_t *xmb_rt) {
532 if(xmb_rt->rdman) { 885 if(xmb_rt->rdman) {
533 redraw_man_destroy(xmb_rt->rdman); 886 redraw_man_destroy(xmb_rt->rdman);
534 free(xmb_rt->rdman); 887 free(xmb_rt->rdman);
535 } 888 }
536 889
537 if(xmb_rt->tman) 890 if(xmb_rt->io_hdl)
538 mb_tman_free(xmb_rt->tman); 891 mb_io_man_unreg(xmb_rt->io_man, xmb_rt->io_hdl);
892
893 if(xmb_rt->io_man)
894 mb_io_man_free(_io_factory, xmb_rt->io_man);
895 if(xmb_rt->timer_man)
896 mb_timer_man_free(_timer_factory, xmb_rt->timer_man);
539 897
540 if(xmb_rt->img_ldr) 898 if(xmb_rt->img_ldr)
541 MB_IMG_LDR_FREE(xmb_rt->img_ldr); 899 MB_IMG_LDR_FREE(xmb_rt->img_ldr);
542 900
543 if(xmb_rt->cr) 901 if(xmb_rt->cr)
556 XCloseDisplay(xmb_rt->display); 914 XCloseDisplay(xmb_rt->display);
557 915
558 X_kb_destroy(&xmb_rt->kbinfo); 916 X_kb_destroy(&xmb_rt->kbinfo);
559 } 917 }
560 918
561 void *X_MB_new(const char *display_name, int w, int h) { 919 /*! \brief Destroy a MadButterfly runtime initialized with
562 X_MB_runtime_t *rt; 920 * _x_supp_init_with_win().
921 *
922 * Destroying a runtime with this function prevent the window and
923 * display associated with the runtime being closed.
924 */
925 static void
926 x_supp_destroy_keep_win(X_supp_runtime_t *xmb_rt) {
927 Display *display;
928 Window win;
929
930 display = xmb_rt->display;
931 xmb_rt->display = NULL;
932 win = xmb_rt->win;
933 xmb_rt->win = 0;
934
935 x_supp_destroy(xmb_rt);
936
937 xmb_rt->display = display;
938 xmb_rt->win = win;
939 }
940
941 static mb_rt_t *
942 _x_supp_new(const char *display_name, int w, int h) {
943 X_supp_runtime_t *rt;
563 int r; 944 int r;
564 945
565 rt = O_ALLOC(X_MB_runtime_t); 946 rt = O_ALLOC(X_supp_runtime_t);
566 if(rt == NULL) 947 if(rt == NULL)
567 return NULL; 948 return NULL;
568 949
569 r = X_MB_init(display_name, w, h, rt); 950 r = _x_supp_init(rt, display_name, w, h);
570 if(r != OK) { 951 if(r != OK) {
571 free(rt); 952 free(rt);
572 return NULL; 953 return NULL;
573 } 954 }
574 955
575 return rt; 956 return (mb_rt_t *)rt;
576 } 957 }
577 958
578 void X_MB_free(void *rt) { 959 /*! \brief Create a new runtime for existed window for X.
579 X_MB_destroy((X_MB_runtime_t *) rt); 960 *
961 * The object returned by this function must be free with
962 * _x_supp_free_keep_win() to prevent the window from closed.
963 */
964 static mb_rt_t *
965 _x_supp_new_with_win(MB_DISPLAY display, MB_WINDOW win) {
966 X_supp_runtime_t *rt;
967 int r;
968
969 rt = O_ALLOC(X_supp_runtime_t);
970 if(rt == NULL)
971 return NULL;
972
973 r = _x_supp_init_with_win(rt, display, win);
974 if(r != OK) {
975 free(rt);
976 return NULL;
977 }
978
979 return (mb_rt_t *)rt;
980 }
981
982 static void
983 _x_supp_free(mb_rt_t *rt) {
984 x_supp_destroy((X_supp_runtime_t *) rt);
580 free(rt); 985 free(rt);
581 } 986 }
582 987
583 subject_t *X_MB_kbevents(void *rt) { 988 /*! \brief Free runtime created with _x_supp_new_with_win().
584 X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; 989 */
990 static void
991 _x_supp_free_keep_win(mb_rt_t *rt) {
992 x_supp_destroy_keep_win((X_supp_runtime_t *) rt);
993 free(rt);
994 }
995
996 static subject_t *
997 _x_supp_kbevents(mb_rt_t *rt) {
998 X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt;
585 return xmb_rt->kbinfo.kbevents; 999 return xmb_rt->kbinfo.kbevents;
586 } 1000 }
587 1001
588 redraw_man_t *X_MB_rdman(void *rt) { 1002 static redraw_man_t *
589 X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; 1003 _x_supp_rdman(mb_rt_t *rt) {
1004 X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt;
590 return xmb_rt->rdman; 1005 return xmb_rt->rdman;
591 } 1006 }
592 1007
593 mb_tman_t *X_MB_tman(void *rt) { 1008 static mb_timer_man_t *
594 X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; 1009 _x_supp_timer_man(mb_rt_t *rt) {
595 return xmb_rt->tman; 1010 X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt;
596 } 1011 return xmb_rt->timer_man;
597 1012 }
598 ob_factory_t *X_MB_ob_factory(void *rt) { 1013
599 X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; 1014 static observer_factory_t *
600 ob_factory_t *factory; 1015 _x_supp_observer_factory(mb_rt_t *rt) {
601 1016 X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt;
602 factory = rdman_get_ob_factory(xmb_rt->rdman); 1017 observer_factory_t *factory;
1018
1019 factory = rdman_get_observer_factory(xmb_rt->rdman);
603 return factory; 1020 return factory;
604 } 1021 }
605 1022
606 mb_img_ldr_t *X_MB_img_ldr(void *rt) { 1023 static mb_img_ldr_t *
607 X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; 1024 _x_supp_img_ldr(mb_rt_t *rt) {
608 X_MB_runtime_t *img_ldr; 1025 X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt;
1026 mb_img_ldr_t *img_ldr;
609 1027
610 img_ldr = xmb_rt->img_ldr; 1028 img_ldr = xmb_rt->img_ldr;
611 1029
612 return img_ldr; 1030 return img_ldr;
613 } 1031 }
614 1032
615 void X_MB_add_event(void *rt, int type, int fd, mb_eventcb_t f,void *arg) 1033 static int
1034 _x_supp_add_event(mb_rt_t *rt, int fd, MB_IO_TYPE type,
1035 mb_IO_cb_t cb, void *data)
616 { 1036 {
617 X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; 1037 X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt;
618 int i; 1038 mb_IO_man_t *io_man = xmb_rt->io_man;
619 1039 int hdl;
620 for(i=0;i<xmb_rt->n_monitor;i++) { 1040
621 if (xmb_rt->monitors[i].type == type && xmb_rt->monitors[i].fd == fd) { 1041 hdl = mb_io_man_reg(io_man, fd, type, cb, data);
622 xmb_rt->monitors[i].f = f; 1042 return hdl;
623 xmb_rt->monitors[i].arg = arg; 1043 }
624 return; 1044
625 } 1045 static void
626 } 1046 _x_supp_remove_event(mb_rt_t *rt, int hdl)
627 for(i=0;i<xmb_rt->n_monitor;i++) {
628 if (xmb_rt->monitors[i].type == 0) {
629 xmb_rt->monitors[i].type = type;
630 xmb_rt->monitors[i].fd = fd;
631 xmb_rt->monitors[i].f = f;
632 xmb_rt->monitors[i].arg = arg;
633 return;
634 }
635 }
636 if (i == MAX_MONITORS) return;
637 xmb_rt->monitors[i].type = type;
638 xmb_rt->monitors[i].fd = fd;
639 xmb_rt->monitors[i].f = f;
640 xmb_rt->monitors[i].arg = arg;
641 i++;
642 xmb_rt->n_monitor=i;
643 }
644
645 void X_MB_remove_event(void *rt, int type, int fd)
646 { 1047 {
647 X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; 1048 X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt;
648 int i; 1049 mb_IO_man_t *io_man = xmb_rt->io_man;
649 for(i=0;i<xmb_rt->n_monitor;i++) { 1050
650 if (xmb_rt->monitors[i].type == type && xmb_rt->monitors[i].fd == fd) { 1051 mb_io_man_unreg(io_man, hdl);
651 xmb_rt->monitors[i].type = 0; 1052 }
652 return; 1053
653 } 1054 static int
654 } 1055 _x_supp_flush(mb_rt_t *rt) {
655 } 1056 X_supp_runtime_t *xmb_rt = (X_supp_runtime_t *) rt;
656 mb_backend_t backend = { X_MB_new, 1057 int r;
657 X_MB_free, 1058
658 X_MB_add_event, 1059 #ifdef XSHM
659 X_MB_remove_event, 1060 XSHM_update(xmb_rt);
660 X_MB_handle_connection, 1061 #endif
661 X_MB_kbevents, 1062 r = XFlush(xmb_rt->display);
662 X_MB_rdman, 1063 return r == 0? ERR: OK;
663 X_MB_tman, 1064 }
664 X_MB_ob_factory, 1065
665 X_MB_img_ldr 1066 static void
666 }; 1067 _x_supp_reg_IO_factory(mb_IO_factory_t *io_factory) {
667 /*! \defgroup x_supp_nodejs_sup Export functions for supporting nodejs plugin. 1068 _io_factory = io_factory;
668 * 1069 }
669 * These functions are for internal using. 1070
670 * @{ 1071 static void
671 */ 1072 _x_supp_reg_timer_factory(mb_timer_factory_t *timer_factory) {
672 /*! \brief Exported for nodejs plugin to call handle_x_event. 1073 _timer_factory = timer_factory;
673 */ 1074 }
674 void _X_MB_handle_x_event_for_nodejs(void *rt) { 1075
675 handle_x_event((X_MB_runtime_t *)rt); 1076 mb_backend_t mb_dfl_backend = { _x_supp_new,
676 } 1077 _x_supp_new_with_win,
677 1078
678 /*! \brief Get X connect for nodejs plugin. 1079 _x_supp_free,
679 */ 1080 _x_supp_free_keep_win,
680 int _X_MB_get_x_conn_for_nodejs(void *rt) { 1081 _x_supp_add_event,
681 return XConnectionNumber(((X_MB_runtime_t *)rt)->display); 1082 _x_supp_remove_event,
682 } 1083 _x_supp_event_loop,
683 1084 _x_supp_flush,
684 /*! \brief Flush buffer for the X connection of a runtime object. 1085
685 */ 1086 _x_supp_kbevents,
686 int _X_MB_flush_x_conn_for_nodejs(void *rt) { 1087 _x_supp_rdman,
687 return XFlush(((X_MB_runtime_t *)rt)->display); 1088 _x_supp_timer_man,
688 } 1089 _x_supp_observer_factory,
689 1090 _x_supp_img_ldr,
690 /* @} */ 1091
1092 _x_supp_reg_IO_factory,
1093 _x_supp_reg_timer_factory,
1094 };