comparison src/X_supp.c @ 78:3645e29e4986

Add runtime for Xlib.
author Thinker K.F. Li <thinker@branda.to>
date Wed, 20 Aug 2008 23:33:04 +0800
parents a6763f080da5
children 13fdf205047b
comparison
equal deleted inserted replaced
77:a6763f080da5 78:3645e29e4986
1 #include <stdio.h> 1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
2 #include <X11/Xlib.h> 4 #include <X11/Xlib.h>
3 #include <X11/Xutil.h> 5 #include <X11/Xutil.h>
6 #include <cairo.h>
7 #include <cairo-xlib.h>
4 #include "redraw_man.h" 8 #include "redraw_man.h"
5 #include "mb_timer.h" 9 #include "mb_timer.h"
6 10 #include "X_supp.h"
7 11
8 /*! \brief Dispatch all events in the queue. 12
13 static unsigned int get_button_state(unsigned int state) {
14 unsigned int but = 0;
15
16 if(state & Button1Mask)
17 but |= MOUSE_BUT1;
18 if(state & Button2Mask)
19 but |= MOUSE_BUT2;
20 if(state & Button3Mask)
21 but |= MOUSE_BUT3;
22
23 return but;
24 }
25
26 static unsigned int get_button(unsigned int button) {
27 switch(button) {
28 case Button1:
29 return MOUSE_BUT1;
30 case Button2:
31 return MOUSE_BUT2;
32 case Button3:
33 return MOUSE_BUT3;
34 }
35 return 0;
36 }
37
38 /*! \brief Notify observers of the shape at specified
39 * position for mouse event.
40 *
41 * Observers of parent shapes may be called if the subject is not
42 * with SUBF_STOP_PROPAGATE flag. The subject of mouse event
43 * for a shape is returned by sh_get_mouse_event_subject().
44 */
45 static void notify_shapes(redraw_man_t *rdman,
46 co_aix x, co_aix y, int etype,
47 unsigned int state,
48 unsigned int button) {
49 mouse_event_t mouse_event;
50 shape_t *shape;
51 subject_t *subject;
52 ob_factory_t *factory;
53 int in_stroke;
54
55 mouse_event.event.type = etype;
56 mouse_event.x = x;
57 mouse_event.y = y;
58 mouse_event.but_state = state;
59 mouse_event.button = button;
60
61 shape = find_shape_at_pos(rdman, x, y,
62 &in_stroke);
63 if(shape == NULL)
64 return;
65 subject = sh_get_mouse_event_subject(shape);
66 factory = rdman_get_ob_factory(rdman);
67
68 subject_notify(factory, subject, (event_t *)&mouse_event);
69 }
70
71 /*! \brief Dispatch all X events in the queue.
9 */ 72 */
10 static void handle_x_event(Display *display, 73 static void handle_x_event(Display *display,
11 redraw_man_t *rdman, 74 redraw_man_t *rdman,
12 mb_tman_t *tman) { 75 mb_tman_t *tman) {
13 XEvent evt; 76 XEvent evt;
14 XMotionEvent *mevt; 77 XMotionEvent *mevt;
15 mouse_event_t mouse_event; 78 XButtonEvent *bevt;
16 shape_t *shape;
17 subject_t *subject;
18 ob_factory_t *factory;
19 co_aix x, y; 79 co_aix x, y;
20 int in_stroke; 80 unsigned int state, button;
21 int but;
22 int r; 81 int r;
23 82
24 while(XEventsQueued(display, QueuedAfterReading) > 0) { 83 while(XEventsQueued(display, QueuedAfterReading) > 0) {
25 r = XNextEvent(display, &evt); 84 r = XNextEvent(display, &evt);
26 if(r == -1) 85 if(r == -1)
27 break; 86 break;
28 87
29 switch(evt.type) { 88 switch(evt.type) {
89 case ButtonPress:
90 bevt = (XButtonEvent *)&evt;
91 x = bevt->x;
92 y = bevt->y;
93 state = get_button_state(bevt->state);
94 button = get_button(bevt->button);
95
96 notify_shapes(rdman, x, y, EVT_MOUSE_BUT_PRESS,
97 state, button);
98 break;
99
100 case ButtonRelease:
101 bevt = (XButtonEvent *)&evt;
102 x = bevt->x;
103 y = bevt->y;
104 state = get_button_state(bevt->state);
105 button = get_button(bevt->button);
106
107 notify_shapes(rdman, x, y, EVT_MOUSE_BUT_RELEASE,
108 state, button);
109 break;
110
30 case MotionNotify: 111 case MotionNotify:
31 mevt = (XMotionEvent *)&evt; 112 mevt = (XMotionEvent *)&evt;
32 x = mevt->x; 113 x = mevt->x;
33 y = mevt->y; 114 y = mevt->y;
34 but = 0; 115 state = get_button_state(mevt->state);
35 if(mevt->state & Button1Mask) 116
36 but |= MOUSE_BUT1; 117 notify_shapes(rdman, x, y, EVT_MOUSE_MOVE, state, 0);
37 if(mevt->state & Button2Mask)
38 but |= MOUSE_BUT2;
39 if(mevt->state & Button3Mask)
40 but |= MOUSE_BUT3;
41
42 mouse_event.event.type = EVT_MOUSE_MOVE;
43 mouse_event.x = x;
44 mouse_event.y = y;
45 mouse_event.button = but;
46
47 shape = find_shape_at_pos(rdman, x, y,
48 &in_stroke);
49 subject = sh_get_mouse_event_subject(shape);
50 factory = rdman_get_ob_factory(rdman);
51
52 subject_notify(factory, subject, (event_t *)&mouse_event);
53 break; 118 break;
54 119
55 case Expose: 120 case Expose:
56 rdman_redraw_area(rdman, evt.xexpose.x, evt.xexpose.y, 121 rdman_redraw_area(rdman, evt.xexpose.x, evt.xexpose.y,
57 evt.xexpose.width, evt.xexpose.height); 122 evt.xexpose.width, evt.xexpose.height);
61 rdman_redraw_changed(rdman); 126 rdman_redraw_changed(rdman);
62 XFlush(display); 127 XFlush(display);
63 } 128 }
64 129
65 /*! \brief Handle connection coming data and timeout of timers. 130 /*! \brief Handle connection coming data and timeout of timers.
66 */ 131 *
67 void X_handle_connection(Display *display, 132 * \param display is a Display returned by XOpenDisplay().
68 redraw_man_t *rdman, 133 * \param rdman is a redraw manager.
69 mb_tman_t *tman) { 134 * \param tman is a timer manager.
135 *
136 * The display is managed by specified rdman and tman. rdman draws
137 * on the display, and tman trigger actions according timers.
138 */
139 void X_MB_handle_connection(Display *display,
140 redraw_man_t *rdman,
141 mb_tman_t *tman) {
70 int fd; 142 int fd;
71 mb_timeval_t now, tmo; 143 mb_timeval_t now, tmo;
72 struct timeval tv; 144 struct timeval tv;
73 fd_set rfds; 145 fd_set rfds;
74 int nfds; 146 int nfds;
75 int r; 147 int r;
148
149 rdman_redraw_all(rdman);
150 XFlush(display);
76 151
77 fd = XConnectionNumber(display); 152 fd = XConnectionNumber(display);
78 nfds = fd + 1; 153 nfds = fd + 1;
79 while(1) { 154 while(1) {
80 FD_ZERO(&rfds); 155 FD_ZERO(&rfds);
103 } else if(FD_ISSET(fd, &rfds)){ 178 } else if(FD_ISSET(fd, &rfds)){
104 handle_x_event(display, rdman, tman); 179 handle_x_event(display, rdman, tman);
105 } 180 }
106 } 181 }
107 } 182 }
183
184 #define ERR -1
185 #define OK 0
186
187 static int X_init_connection(const char *display_name,
188 int w, int h,
189 Display **displayp,
190 Visual **visualp,
191 Window *winp) {
192 Display *display;
193 Window root, win;
194 Visual *visual;
195 int screen;
196 XSetWindowAttributes wattr;
197 int depth;
198 int x, y;
199 int r;
200
201 display = XOpenDisplay(display_name);
202 if(display == NULL)
203 return ERR;
204
205 screen = DefaultScreen(display);
206 root = DefaultRootWindow(display);
207 visual = DefaultVisual(display, screen);
208 depth = DefaultDepth(display, screen);
209 wattr.override_redirect = False;
210 x = 10;
211 y = 10;
212 win = XCreateWindow(display, root,
213 x, y,
214 w, h,
215 1, depth, InputOutput, visual,
216 CWOverrideRedirect, &wattr);
217 r = XMapWindow(display, win);
218 if(r == -1) {
219 XCloseDisplay(display);
220 return ERR;
221 }
222
223 XSelectInput(display, win, PointerMotionMask | ExposureMask);
224 XFlush(display);
225
226 *displayp = display;
227 *visualp = visual;
228 *winp = win;
229
230 return OK;
231 }
232
233 /*! \brief Initialize a MadButterfy runtime for Xlib.
234 *
235 * It setups a runtime environment to run MadButterfly with Xlib.
236 * Users should specify width and height of the opening window.
237 */
238 int X_MB_init(const char *display_name,
239 int w, int h, X_MB_runtime_t *xmb_rt) {
240 memset(xmb_rt, 0, sizeof(X_MB_runtime_t));
241
242 xmb_rt->w = w;
243 xmb_rt->h = h;
244 X_init_connection(display_name, w, h, &xmb_rt->display,
245 &xmb_rt->visual, &xmb_rt->win);
246
247 xmb_rt->surface =
248 cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h);
249
250 xmb_rt->backend_surface =
251 cairo_xlib_surface_create(xmb_rt->display,
252 xmb_rt->win,
253 xmb_rt->visual,
254 w, h);
255
256 xmb_rt->cr = cairo_create(xmb_rt->surface);
257 xmb_rt->backend_cr = cairo_create(xmb_rt->backend_surface);
258
259 cairo_set_source_surface(xmb_rt->backend_cr, xmb_rt->surface, 0, 0);
260
261 xmb_rt->rdman = (redraw_man_t *)malloc(sizeof(redraw_man_t));
262 redraw_man_init(xmb_rt->rdman, xmb_rt->cr, xmb_rt->backend_cr);
263
264 xmb_rt->tman = mb_tman_new();
265
266 return OK;
267 }
268
269 void X_MB_destroy(X_MB_runtime_t *xmb_rt) {
270 if(xmb_rt->rdman) {
271 redraw_man_destroy(xmb_rt->rdman);
272 free(xmb_rt->rdman);
273 }
274
275 if(xmb_rt->tman)
276 mb_tman_free(xmb_rt->tman);
277
278 if(xmb_rt->cr)
279 cairo_destroy(xmb_rt->cr);
280 if(xmb_rt->backend_cr)
281 cairo_destroy(xmb_rt->backend_cr);
282
283 if(xmb_rt->surface)
284 cairo_surface_destroy(xmb_rt->surface);
285 if(xmb_rt->backend_surface)
286 cairo_surface_destroy(xmb_rt->backend_surface);
287
288 if(xmb_rt->display)
289 XCloseDisplay(xmb_rt->display);
290 }
291