35c3259a42eea0eefcb49a95fb10a901ea431fca
[profile/ivi/ecore.git] / src / lib / ecore_x / xcb / ecore_xcb.c
1 #include <string.h>
2
3 #include <X11/keysym.h>
4
5 #include <Ecore.h>
6 #include <Ecore_Input.h>
7
8 #include "ecore_xcb_private.h"
9 #include "Ecore_X_Atoms.h"
10
11 static Eina_Bool      _ecore_xcb_fd_handler(void *data, Ecore_Fd_Handler *fd_handler);
12 static Eina_Bool      _ecore_xcb_fd_handler_buf(void *data, Ecore_Fd_Handler *fd_handler);
13 static int            _ecore_xcb_key_mask_get(xcb_keysym_t sym);
14 static int            _ecore_xcb_event_modifier(unsigned int state);
15
16 static void *         _ecore_xcb_event_filter_start(void *data);
17 static Eina_Bool      _ecore_xcb_event_filter_filter(void *data, void *loop_data,int type, void *event);
18 static void           _ecore_xcb_event_filter_end(void *data, void *loop_data);
19
20 static Ecore_Fd_Handler *_ecore_xcb_fd_handler_handle = NULL;
21 static Ecore_Event_Filter *_ecore_xcb_filter_handler = NULL;
22
23 static const int XCB_EVENT_ANY = 0; /* 0 can be used as there are no event types
24                                      * with index 0 and 1 as they are used for
25                                      * errors
26                                      */
27
28 #ifdef ECORE_XCB_DAMAGE
29 static int _ecore_xcb_event_damage_id = 0;
30 #endif /* ECORE_XCB_DAMAGE */
31 #ifdef ECORE_XCB_RANDR
32 static int _ecore_xcb_event_randr_id = 0;
33 #endif /* ECORE_XCB_RANDR */
34 #ifdef ECORE_XCB_SCREENSAVER
35 static int _ecore_xcb_event_screensaver_id = 0;
36 #endif /* ECORE_XCB_SCREENSAVER */
37 #ifdef ECORE_XCB_SHAPE
38 static int _ecore_xcb_event_shape_id = 0;
39 #endif /* ECORE_XCB_SHAPE */
40 #ifdef ECORE_XCB_SYNC
41 static int _ecore_xcb_event_sync_id = 0;
42 #endif /* ECORE_XCB_SYNC */
43 #ifdef ECORE_XCB_FIXES
44 static int _ecore_xcb_event_fixes_selection_id = 0;
45 #endif /* ECORE_XCB_FIXES */
46
47 static int _ecore_xcb_event_handlers_num = 0;
48 static void (**_ecore_xcb_event_handlers) (xcb_generic_event_t * event) = NULL;
49 static xcb_generic_event_t *_ecore_xcb_event_buffered = NULL;
50
51 static int _ecore_xcb_init_count = 0;
52 static int _ecore_xcb_grab_count = 0;
53 int _ecore_x11xcb_log_dom = -1;
54
55 Ecore_X_Connection *_ecore_xcb_conn = NULL;
56 Ecore_X_Screen *_ecore_xcb_screen = NULL;
57 double _ecore_xcb_double_click_time = 0.25;
58 Ecore_X_Time _ecore_xcb_event_last_time = XCB_NONE;
59 Ecore_X_Window _ecore_xcb_event_last_window = XCB_NONE;
60 int16_t _ecore_xcb_event_last_root_x = 0;
61 int16_t _ecore_xcb_event_last_root_y = 0;
62 int _ecore_xcb_xcursor = 0;
63
64 Ecore_X_Window _ecore_xcb_private_window = 0;
65
66 /* FIXME - These are duplicates after making ecore atoms public */
67
68 Ecore_X_Atom _ecore_xcb_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_NUM];
69
70 EAPI int ECORE_X_EVENT_ANY = 0;
71 EAPI int ECORE_X_EVENT_MOUSE_IN = 0;
72 EAPI int ECORE_X_EVENT_MOUSE_OUT = 0;
73 EAPI int ECORE_X_EVENT_WINDOW_FOCUS_IN = 0;
74 EAPI int ECORE_X_EVENT_WINDOW_FOCUS_OUT = 0;
75 EAPI int ECORE_X_EVENT_WINDOW_KEYMAP = 0;
76 EAPI int ECORE_X_EVENT_WINDOW_DAMAGE = 0;
77 EAPI int ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = 0;
78 EAPI int ECORE_X_EVENT_WINDOW_CREATE = 0;
79 EAPI int ECORE_X_EVENT_WINDOW_DESTROY = 0;
80 EAPI int ECORE_X_EVENT_WINDOW_HIDE = 0;
81 EAPI int ECORE_X_EVENT_WINDOW_SHOW = 0;
82 EAPI int ECORE_X_EVENT_WINDOW_SHOW_REQUEST = 0;
83 EAPI int ECORE_X_EVENT_WINDOW_REPARENT = 0;
84 EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE = 0;
85 EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = 0;
86 EAPI int ECORE_X_EVENT_WINDOW_GRAVITY = 0;
87 EAPI int ECORE_X_EVENT_WINDOW_RESIZE_REQUEST = 0;
88 EAPI int ECORE_X_EVENT_WINDOW_STACK = 0;
89 EAPI int ECORE_X_EVENT_WINDOW_STACK_REQUEST = 0;
90 EAPI int ECORE_X_EVENT_WINDOW_PROPERTY = 0;
91 EAPI int ECORE_X_EVENT_WINDOW_COLORMAP = 0;
92 EAPI int ECORE_X_EVENT_WINDOW_MAPPING = 0;
93 EAPI int ECORE_X_EVENT_SELECTION_CLEAR = 0;
94 EAPI int ECORE_X_EVENT_SELECTION_REQUEST = 0;
95 EAPI int ECORE_X_EVENT_SELECTION_NOTIFY = 0;
96 EAPI int ECORE_X_EVENT_CLIENT_MESSAGE = 0;
97 EAPI int ECORE_X_EVENT_WINDOW_SHAPE = 0;
98 EAPI int ECORE_X_EVENT_SCREENSAVER_NOTIFY = 0;
99 EAPI int ECORE_X_EVENT_SYNC_COUNTER = 0;
100 EAPI int ECORE_X_EVENT_SYNC_ALARM = 0;
101 EAPI int ECORE_X_EVENT_SCREEN_CHANGE = 0;
102 EAPI int ECORE_X_EVENT_DAMAGE_NOTIFY = 0;
103
104 EAPI int ECORE_X_EVENT_WINDOW_DELETE_REQUEST = 0;
105 /*
106    EAPI int ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE = 0;
107    EAPI int ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE = 0;
108    EAPI int ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE = 0;
109    EAPI int ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE = 0;
110    EAPI int ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE = 0;
111    EAPI int ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE = 0;
112    EAPI int ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE = 0;
113    EAPI int ECORE_X_EVENT_WINDOW_PROP_DESKTOP_CHANGE = 0;
114  */
115
116 EAPI int ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = 0;
117 EAPI int ECORE_X_EVENT_WINDOW_STATE_REQUEST = 0;
118 EAPI int ECORE_X_EVENT_FRAME_EXTENTS_REQUEST = 0;
119 EAPI int ECORE_X_EVENT_PING = 0;
120 EAPI int ECORE_X_EVENT_DESKTOP_CHANGE = 0;
121
122 EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_NEW = 0;
123 EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE = 0;
124 EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE = 0;
125
126 EAPI int ECORE_X_MODIFIER_SHIFT = 0;
127 EAPI int ECORE_X_MODIFIER_CTRL = 0;
128 EAPI int ECORE_X_MODIFIER_ALT = 0;
129 EAPI int ECORE_X_MODIFIER_WIN = 0;
130
131 EAPI int ECORE_X_LOCK_SCROLL = 0;
132 EAPI int ECORE_X_LOCK_NUM = 0;
133 EAPI int ECORE_X_LOCK_CAPS = 0;
134
135 /**
136  * @defgroup Ecore_Xcb_Init_Group X Library Init and Shutdown Functions
137  *
138  * Functions that start and shut down the Ecore X Library.
139  */
140
141 /**
142  * Initialize the X display connection to the given display.
143  *
144  * @param   name Display target name.  If @c NULL, the default display is
145  *               assumed.
146  * @return  The number of times the library has been initialized without
147  *          being shut down.  0 is returned if an error occurs.
148  * @ingroup Ecore_Xcb_Init_Group
149  */
150 EAPI int
151 ecore_x_init(const char *name)
152 {
153    xcb_screen_iterator_t iter;
154    int screen;
155    uint32_t max_request_length;
156    const xcb_query_extension_reply_t *reply_big_requests;
157 #ifdef ECORE_XCB_DAMAGE
158    const xcb_query_extension_reply_t *reply_damage;
159 #endif /* ECORE_XCB_DAMAGE */
160 #ifdef ECORE_XCB_COMPOSITE
161    const xcb_query_extension_reply_t *reply_composite;
162 #endif /* ECORE_XCB_COMPOSITE */
163 #ifdef ECORE_XCB_DPMS
164    const xcb_query_extension_reply_t *reply_dpms;
165 #endif /* ECORE_XCB_DPMS */
166 #ifdef ECORE_XCB_RANDR
167    const xcb_query_extension_reply_t *reply_randr;
168 #endif /* ECORE_XCB_RANDR */
169 #ifdef ECORE_XCB_SCREENSAVER
170    const xcb_query_extension_reply_t *reply_screensaver;
171 #endif /* ECORE_XCB_SCREENSAVER */
172 #ifdef ECORE_XCB_SHAPE
173    const xcb_query_extension_reply_t *reply_shape;
174 #endif /* ECORE_XCB_SHAPE */
175 #ifdef ECORE_XCB_SYNC
176    xcb_sync_initialize_cookie_t cookie_sync_init;
177    xcb_sync_initialize_reply_t *reply_sync_init;
178    const xcb_query_extension_reply_t *reply_sync;
179 #endif /* ECORE_XCB_SYNC */
180 #ifdef ECORE_XCB_FIXES
181    const xcb_query_extension_reply_t *reply_xfixes;
182 #endif /* ECORE_XCB_FIXES */
183 #ifdef ECORE_XCB_XINERAMA
184    const xcb_query_extension_reply_t *reply_xinerama;
185 #endif /* ECORE_XCB_XINERAMA */
186 #ifdef ECORE_XCB_XPRINT
187    const xcb_query_extension_reply_t *reply_xprint;
188 #endif /* ECORE_XCB_XPRINT */
189
190    xcb_intern_atom_cookie_t atom_cookies[ECORE_X_ATOMS_COUNT];
191
192    if (++_ecore_xcb_init_count != 1)
193       return _ecore_xcb_init_count;
194
195    /* We init some components (not related to XCB) */
196    if (!eina_init())
197       return --_ecore_xcb_init_count;
198
199    _ecore_x11xcb_log_dom = eina_log_domain_register("EcoreXCB", ECORE_XLIB_XCB_DEFAULT_LOG_COLOR);
200    if (_ecore_x11xcb_log_dom < 0)
201      {
202         EINA_LOG_ERR("Impossible to create a log domain the Ecore XCB module.");
203         goto shutdown_eina;
204      }
205
206    if (!ecore_init())
207       goto shutdown_eina;
208    if (!ecore_event_init())
209       goto shutdown_ecore;
210
211    _ecore_xcb_conn = xcb_connect(name, &screen);
212    if (xcb_connection_has_error(_ecore_xcb_conn))
213       goto shutdown_ecore_event;
214
215    /* FIXME: no error code right now */
216    /* _ecore_xcb_error_handler_init(); */
217
218    /********************/
219    /* First round trip */
220    /********************/
221
222    /*
223     * Non blocking stuff:
224     *
225     * 1. We request the atoms
226     * 2. We Prefetch the extension data
227     *
228     */
229
230    /* We request the atoms (non blocking) */
231    _ecore_x_atom_init(atom_cookies);
232
233    /* We prefetch all the extension data (non blocking) */
234
235    xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_big_requests_id);
236
237 #ifdef ECORE_XCB_DAMAGE
238    xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_damage_id);
239 #endif /* ECORE_XCB_DAMAGE */
240
241 #ifdef ECORE_XCB_COMPOSITE
242    xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_composite_id);
243 #endif /* ECORE_XCB_COMPOSITE */
244
245 #ifdef ECORE_XCB_DPMS
246    xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_dpms_id);
247 #endif /* ECORE_XCB_DPMS */
248
249 #ifdef ECORE_XCB_RANDR
250    xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_randr_id);
251 #endif /* ECORE_XCB_RANDR */
252
253 #ifdef ECORE_XCB_SCREENSAVER
254    xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_screensaver_id);
255 #endif /* ECORE_XCB_SCREENSAVER */
256
257 #ifdef ECORE_XCB_SHAPE
258    xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_shape_id);
259 #endif /* ECORE_XCB_SHAPE */
260
261 #ifdef ECORE_XCB_SYNC
262    xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_sync_id);
263    cookie_sync_init = xcb_sync_initialize_unchecked(_ecore_xcb_conn,
264                                                     XCB_SYNC_MAJOR_VERSION,
265                                                     XCB_SYNC_MINOR_VERSION);
266 #endif /* ECORE_XCB_SYNC */
267
268 #ifdef ECORE_XCB_FIXES
269    xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_xfixes_id);
270 #endif /* ECORE_XCB_FIXES */
271
272 #ifdef ECORE_XCB_XINERAMA
273    xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_xinerama_id);
274 #endif /* ECORE_XCB_XINERAMA */
275
276 #ifdef ECORE_XCB_XPRINT
277    xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_x_print_id);
278 #endif /* ECORE_XCB_XPRINT */
279
280    _ecore_x_reply_init();
281    _ecore_x_dnd_init();
282    ecore_x_netwm_init();
283    _ecore_x_selection_init();
284
285    /* There is no LASTEvent constant in XCB */
286    /* LASTevent is equal to 35 */
287    _ecore_xcb_event_handlers_num = 35;
288
289    /* We get the default screen */
290    iter = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn));
291    for (; iter.rem; --screen, xcb_screen_next (&iter))
292       if (screen == 0)
293         {
294            _ecore_xcb_screen = iter.data;
295            break;
296         }
297
298    /*
299     * Blocking stuff:
300     *
301     * 1. We get the atoms
302     * 2. We ask for the extension data
303     *
304     */
305
306    /* We get the atoms (blocking) */
307    _ecore_x_atom_init_finalize(atom_cookies);
308
309    /* We then ask for the extension data (blocking) */
310    reply_big_requests = xcb_get_extension_data(_ecore_xcb_conn, &xcb_big_requests_id);
311
312 #ifdef ECORE_XCB_DAMAGE
313    reply_damage = xcb_get_extension_data(_ecore_xcb_conn, &xcb_damage_id);
314    if (reply_damage)
315       _ecore_xcb_event_damage_id = reply_damage->first_event + XCB_DAMAGE_NOTIFY;
316
317    if (_ecore_xcb_event_damage_id >= _ecore_xcb_event_handlers_num)
318       _ecore_xcb_event_handlers_num = _ecore_xcb_event_damage_id + 1;
319
320 #endif /* ECORE_XCB_DAMAGE */
321
322 #ifdef ECORE_XCB_COMPOSITE
323    reply_composite = xcb_get_extension_data(_ecore_xcb_conn, &xcb_composite_id);
324 #endif /* ECORE_XCB_COMPOSITE */
325
326 #ifdef ECORE_XCB_DPMS
327    reply_dpms = xcb_get_extension_data(_ecore_xcb_conn, &xcb_dpms_id);
328 #endif /* ECORE_XCB_DPMS */
329
330 #ifdef ECORE_XCB_RANDR
331    reply_randr = xcb_get_extension_data(_ecore_xcb_conn, &xcb_randr_id);
332    if (reply_randr)
333       _ecore_xcb_event_randr_id = reply_randr->first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY;
334
335    if (_ecore_xcb_event_randr_id >= _ecore_xcb_event_handlers_num)
336       _ecore_xcb_event_handlers_num = _ecore_xcb_event_randr_id + 1;
337
338 #endif /* ECORE_XCB_RANDR */
339
340 #ifdef ECORE_XCB_SCREENSAVER
341    reply_screensaver = xcb_get_extension_data(_ecore_xcb_conn, &xcb_screensaver_id);
342    if (reply_screensaver)
343       _ecore_xcb_event_screensaver_id = reply_screensaver->first_event + XCB_SCREENSAVER_NOTIFY;
344
345    if (_ecore_xcb_event_screensaver_id >= _ecore_xcb_event_handlers_num)
346       _ecore_xcb_event_handlers_num = _ecore_xcb_event_screensaver_id + 1;
347
348 #endif /* ECORE_XCB_SCREENSAVER */
349
350 #ifdef ECORE_XCB_SHAPE
351    reply_shape = xcb_get_extension_data(_ecore_xcb_conn, &xcb_shape_id);
352    if (reply_shape)
353       _ecore_xcb_event_shape_id = reply_shape->first_event + XCB_SHAPE_NOTIFY;
354
355    if (_ecore_xcb_event_shape_id >= _ecore_xcb_event_handlers_num)
356       _ecore_xcb_event_handlers_num = _ecore_xcb_event_shape_id + 1;
357
358 #endif /* ECORE_XCB_SHAPE */
359
360 #ifdef ECORE_XCB_SYNC
361    reply_sync = xcb_get_extension_data(_ecore_xcb_conn, &xcb_sync_id);
362    if (reply_sync)
363      {
364         _ecore_xcb_event_sync_id = reply_sync->first_event;
365         reply_sync_init = xcb_sync_initialize_reply(_ecore_xcb_conn,
366                                                     cookie_sync_init, NULL);
367         if (!reply_sync_init)
368            _ecore_xcb_event_sync_id = 0;
369         else
370            free(reply_sync_init);
371      }
372
373    if (_ecore_xcb_event_sync_id + XCB_SYNC_ALARM_NOTIFY >= _ecore_xcb_event_handlers_num)
374       _ecore_xcb_event_handlers_num = _ecore_xcb_event_sync_id + XCB_SYNC_ALARM_NOTIFY + 1;
375
376 #endif /* ECORE_XCB_SYNC */
377
378 #ifdef ECORE_XCB_FIXES
379    reply_xfixes = xcb_get_extension_data(_ecore_xcb_conn, &xcb_xfixes_id);
380    if (reply_xfixes)
381       _ecore_xcb_event_fixes_selection_id = reply_xfixes->first_event + XCB_XFIXES_SELECTION_NOTIFY;
382
383    if (_ecore_xcb_event_fixes_selection_id >= _ecore_xcb_event_handlers_num)
384       _ecore_xcb_event_handlers_num = _ecore_xcb_event_fixes_selection_id + 1;
385
386 #endif /* ECORE_XCB_FIXES */
387
388 #ifdef ECORE_XCB_XINERAMA
389    reply_xinerama = xcb_get_extension_data(_ecore_xcb_conn, &xcb_xinerama_id);
390 #endif /* ECORE_XCB_XINERAMA */
391
392 #ifdef ECORE_XCB_XPRINT
393    reply_xprint = xcb_get_extension_data(_ecore_xcb_conn, &xcb_x_print_id);
394 #endif /* ECORE_XCB_XPRINT */
395
396    /*********************/
397    /* Second round trip */
398    /*********************/
399
400    /* We ask for the QueryVersion request of the extensions */
401 #ifdef ECORE_XCB_DAMAGE
402    _ecore_x_damage_init(reply_damage);
403 #endif /* ECORE_XCB_DAMAGE */
404 #ifdef ECORE_XCB_COMPOSITE
405    _ecore_x_composite_init(reply_composite);
406 #endif /* ECORE_XCB_COMPOSITE */
407 #ifdef ECORE_XCB_DPMS
408    _ecore_x_dpms_init(reply_dpms);
409 #endif /* ECORE_XCB_DPMS */
410 #ifdef ECORE_XCB_RANDR
411    _ecore_x_randr_init(reply_randr);
412 #endif /* ECORE_XCB_RANDR */
413 #ifdef ECORE_XCB_SCREENSAVER
414    _ecore_x_screensaver_init(reply_screensaver);
415 #endif /* ECORE_XCB_SCREENSAVER */
416 #ifdef ECORE_XCB_SHAPE
417    _ecore_x_shape_init(reply_shape);
418 #endif /* ECORE_XCB_SHAPE */
419 #ifdef ECORE_XCB_SYNC
420    _ecore_x_sync_init(reply_sync);
421 #endif /* ECORE_XCB_SYNC */
422 #ifdef ECORE_XCB_FIXES
423    _ecore_x_xfixes_init(reply_xfixes);
424 #endif /* ECORE_XCB_FIXES */
425 #ifdef ECORE_XCB_XINERAMA
426    _ecore_x_xinerama_init(reply_xinerama);
427 #endif /* ECORE_XCB_XINERAMA */
428
429    /* we enable the Big Request extension if present */
430    max_request_length = xcb_get_maximum_request_length(_ecore_xcb_conn);
431
432    _ecore_xcb_event_handlers = calloc(_ecore_xcb_event_handlers_num, sizeof(void *));
433    if (!_ecore_xcb_event_handlers)
434       goto finalize_extensions;
435
436 #ifdef ECORE_XCB_CURSOR
437    _ecore_xcb_xcursor = XcursorSupportsARGB(_ecore_xcb_conn);
438 #endif /* ECORE_XCB_CURSOR */
439
440    _ecore_xcb_event_handlers[XCB_EVENT_ANY] = _ecore_x_event_handle_any_event;
441    _ecore_xcb_event_handlers[XCB_KEY_PRESS] = _ecore_x_event_handle_key_press;
442    _ecore_xcb_event_handlers[XCB_KEY_RELEASE] = _ecore_x_event_handle_key_release;
443    _ecore_xcb_event_handlers[XCB_BUTTON_PRESS] = _ecore_x_event_handle_button_press;
444    _ecore_xcb_event_handlers[XCB_BUTTON_RELEASE] = _ecore_x_event_handle_button_release;
445    _ecore_xcb_event_handlers[XCB_MOTION_NOTIFY] = _ecore_x_event_handle_motion_notify;
446    _ecore_xcb_event_handlers[XCB_ENTER_NOTIFY] = _ecore_x_event_handle_enter_notify;
447    _ecore_xcb_event_handlers[XCB_LEAVE_NOTIFY] = _ecore_x_event_handle_leave_notify;
448    _ecore_xcb_event_handlers[XCB_FOCUS_IN] = _ecore_x_event_handle_focus_in;
449    _ecore_xcb_event_handlers[XCB_FOCUS_OUT] = _ecore_x_event_handle_focus_out;
450    _ecore_xcb_event_handlers[XCB_KEYMAP_NOTIFY] = _ecore_x_event_handle_keymap_notify;
451    _ecore_xcb_event_handlers[XCB_EXPOSE] = _ecore_x_event_handle_expose;
452    _ecore_xcb_event_handlers[XCB_GRAPHICS_EXPOSURE] = _ecore_x_event_handle_graphics_expose;
453    _ecore_xcb_event_handlers[XCB_VISIBILITY_NOTIFY] = _ecore_x_event_handle_visibility_notify;
454    _ecore_xcb_event_handlers[XCB_CREATE_NOTIFY] = _ecore_x_event_handle_create_notify;
455    _ecore_xcb_event_handlers[XCB_DESTROY_NOTIFY] = _ecore_x_event_handle_destroy_notify;
456    _ecore_xcb_event_handlers[XCB_UNMAP_NOTIFY] = _ecore_x_event_handle_unmap_notify;
457    _ecore_xcb_event_handlers[XCB_MAP_NOTIFY] = _ecore_x_event_handle_map_notify;
458    _ecore_xcb_event_handlers[XCB_MAP_REQUEST] = _ecore_x_event_handle_map_request;
459    _ecore_xcb_event_handlers[XCB_REPARENT_NOTIFY] = _ecore_x_event_handle_reparent_notify;
460    _ecore_xcb_event_handlers[XCB_CONFIGURE_NOTIFY] = _ecore_x_event_handle_configure_notify;
461    _ecore_xcb_event_handlers[XCB_CONFIGURE_REQUEST] = _ecore_x_event_handle_configure_request;
462    _ecore_xcb_event_handlers[XCB_GRAVITY_NOTIFY] = _ecore_x_event_handle_gravity_notify;
463    _ecore_xcb_event_handlers[XCB_RESIZE_REQUEST] = _ecore_x_event_handle_resize_request;
464    _ecore_xcb_event_handlers[XCB_CIRCULATE_NOTIFY] = _ecore_x_event_handle_circulate_notify;
465    _ecore_xcb_event_handlers[XCB_CIRCULATE_REQUEST] = _ecore_x_event_handle_circulate_request;
466    _ecore_xcb_event_handlers[XCB_PROPERTY_NOTIFY] = _ecore_x_event_handle_property_notify;
467    _ecore_xcb_event_handlers[XCB_SELECTION_CLEAR] = _ecore_x_event_handle_selection_clear;
468    _ecore_xcb_event_handlers[XCB_SELECTION_REQUEST] = _ecore_x_event_handle_selection_request;
469    _ecore_xcb_event_handlers[XCB_SELECTION_NOTIFY] = _ecore_x_event_handle_selection_notify;
470    _ecore_xcb_event_handlers[XCB_COLORMAP_NOTIFY] = _ecore_x_event_handle_colormap_notify;
471    _ecore_xcb_event_handlers[XCB_CLIENT_MESSAGE] = _ecore_x_event_handle_client_message;
472    _ecore_xcb_event_handlers[XCB_MAPPING_NOTIFY] = _ecore_x_event_handle_mapping_notify;
473 #ifdef ECORE_XCB_DAMAGE
474    if (_ecore_xcb_event_damage_id)
475       _ecore_xcb_event_handlers[_ecore_xcb_event_damage_id] = _ecore_x_event_handle_damage_notify;
476
477 #endif /* ECORE_XCB_DAMAGE */
478 #ifdef ECORE_XCB_RANDR
479    if (_ecore_xcb_event_randr_id)
480       _ecore_xcb_event_handlers[_ecore_xcb_event_randr_id] = _ecore_x_event_handle_randr_change;
481
482 #endif /* ECORE_XCB_RANDR */
483 #ifdef ECORE_XCB_SCREENSAVER
484    if (_ecore_xcb_event_screensaver_id)
485       _ecore_xcb_event_handlers[_ecore_xcb_event_screensaver_id] = _ecore_x_event_handle_screensaver_notify;
486
487 #endif /* ECORE_XCB_SCREENSAVER */
488 #ifdef ECORE_XCB_SHAPE
489    if (_ecore_xcb_event_shape_id)
490       _ecore_xcb_event_handlers[_ecore_xcb_event_shape_id] = _ecore_x_event_handle_shape_change;
491
492 #endif /* ECORE_XCB_SHAPE */
493 #ifdef ECORE_XCB_SYNC
494    if (_ecore_xcb_event_sync_id)
495      {
496         _ecore_xcb_event_handlers[_ecore_xcb_event_sync_id + XCB_SYNC_COUNTER_NOTIFY] =
497            _ecore_x_event_handle_sync_counter;
498         _ecore_xcb_event_handlers[_ecore_xcb_event_sync_id + XCB_SYNC_ALARM_NOTIFY] =
499            _ecore_x_event_handle_sync_alarm;
500      }
501
502 #endif /* ECORE_XCB_SYNC */
503 #ifdef ECORE_XCB_FIXES
504    if (_ecore_xcb_event_fixes_selection_id)
505       _ecore_xcb_event_handlers[_ecore_xcb_event_fixes_selection_id] = _ecore_x_event_handle_fixes_selection_notify;
506
507 #endif /* ECORE_XCB_FIXES */
508
509    if (!ECORE_X_EVENT_ANY)
510      {
511         ECORE_X_EVENT_ANY = ecore_event_type_new();
512         ECORE_X_EVENT_MOUSE_IN = ecore_event_type_new();
513         ECORE_X_EVENT_MOUSE_OUT = ecore_event_type_new();
514         ECORE_X_EVENT_WINDOW_FOCUS_IN = ecore_event_type_new();
515         ECORE_X_EVENT_WINDOW_FOCUS_OUT = ecore_event_type_new();
516         ECORE_X_EVENT_WINDOW_KEYMAP = ecore_event_type_new();
517         ECORE_X_EVENT_WINDOW_DAMAGE = ecore_event_type_new();
518         ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = ecore_event_type_new();
519         ECORE_X_EVENT_WINDOW_CREATE = ecore_event_type_new();
520         ECORE_X_EVENT_WINDOW_DESTROY = ecore_event_type_new();
521         ECORE_X_EVENT_WINDOW_HIDE = ecore_event_type_new();
522         ECORE_X_EVENT_WINDOW_SHOW = ecore_event_type_new();
523         ECORE_X_EVENT_WINDOW_SHOW_REQUEST = ecore_event_type_new();
524         ECORE_X_EVENT_WINDOW_REPARENT = ecore_event_type_new();
525         ECORE_X_EVENT_WINDOW_CONFIGURE = ecore_event_type_new();
526         ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = ecore_event_type_new();
527         ECORE_X_EVENT_WINDOW_GRAVITY = ecore_event_type_new();
528         ECORE_X_EVENT_WINDOW_RESIZE_REQUEST = ecore_event_type_new();
529         ECORE_X_EVENT_WINDOW_STACK = ecore_event_type_new();
530         ECORE_X_EVENT_WINDOW_STACK_REQUEST = ecore_event_type_new();
531         ECORE_X_EVENT_WINDOW_PROPERTY = ecore_event_type_new();
532         ECORE_X_EVENT_WINDOW_COLORMAP = ecore_event_type_new();
533         ECORE_X_EVENT_WINDOW_MAPPING = ecore_event_type_new();
534         ECORE_X_EVENT_SELECTION_CLEAR = ecore_event_type_new();
535         ECORE_X_EVENT_SELECTION_REQUEST = ecore_event_type_new();
536         ECORE_X_EVENT_SELECTION_NOTIFY = ecore_event_type_new();
537         ECORE_X_EVENT_CLIENT_MESSAGE = ecore_event_type_new();
538         ECORE_X_EVENT_WINDOW_SHAPE = ecore_event_type_new();
539         ECORE_X_EVENT_SCREENSAVER_NOTIFY = ecore_event_type_new();
540         ECORE_X_EVENT_SYNC_COUNTER = ecore_event_type_new();
541         ECORE_X_EVENT_SYNC_ALARM = ecore_event_type_new();
542         ECORE_X_EVENT_SCREEN_CHANGE = ecore_event_type_new();
543         ECORE_X_EVENT_DAMAGE_NOTIFY = ecore_event_type_new();
544
545         ECORE_X_EVENT_WINDOW_DELETE_REQUEST = ecore_event_type_new();
546         /*
547            ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE             = ecore_event_type_new();
548            ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE     = ecore_event_type_new();
549            ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE        = ecore_event_type_new();
550            ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE         = ecore_event_type_new();
551            ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE = ecore_event_type_new();
552            ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE    = ecore_event_type_new();
553            ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE               = ecore_event_type_new();
554            ECORE_X_EVENT_WINDOW_PROP_DESKTOP_CHANGE           = ecore_event_type_new();
555          */
556
557         ECORE_X_EVENT_DESKTOP_CHANGE = ecore_event_type_new();
558         ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = ecore_event_type_new();
559         ECORE_X_EVENT_WINDOW_STATE_REQUEST = ecore_event_type_new();
560         ECORE_X_EVENT_FRAME_EXTENTS_REQUEST = ecore_event_type_new();
561         ECORE_X_EVENT_PING = ecore_event_type_new();
562
563         ECORE_X_EVENT_STARTUP_SEQUENCE_NEW = ecore_event_type_new();
564         ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE = ecore_event_type_new();
565         ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE = ecore_event_type_new();
566      }
567
568    /* everything has these... unless its like a pda... :) */
569    ECORE_X_MODIFIER_SHIFT = _ecore_xcb_key_mask_get(XK_Shift_L);
570    ECORE_X_MODIFIER_CTRL = _ecore_xcb_key_mask_get(XK_Control_L);
571
572    /* apple's xdarwin has no alt!!!! */
573    ECORE_X_MODIFIER_ALT = _ecore_xcb_key_mask_get(XK_Alt_L);
574    if (!ECORE_X_MODIFIER_ALT)
575       ECORE_X_MODIFIER_ALT = _ecore_xcb_key_mask_get(XK_Meta_L);
576
577    if (!ECORE_X_MODIFIER_ALT)
578       ECORE_X_MODIFIER_ALT = _ecore_xcb_key_mask_get(XK_Super_L);
579
580    /* the windows key... a valid modifier :) */
581    ECORE_X_MODIFIER_WIN = _ecore_xcb_key_mask_get(XK_Super_L);
582    if (!ECORE_X_MODIFIER_WIN)
583       ECORE_X_MODIFIER_WIN = _ecore_xcb_key_mask_get(XK_Mode_switch);
584
585    if (!ECORE_X_MODIFIER_WIN)
586       ECORE_X_MODIFIER_WIN = _ecore_xcb_key_mask_get(XK_Meta_L);
587
588    if (ECORE_X_MODIFIER_WIN == ECORE_X_MODIFIER_ALT)
589       ECORE_X_MODIFIER_WIN = 0;
590
591    if (ECORE_X_MODIFIER_ALT == ECORE_X_MODIFIER_CTRL)
592       ECORE_X_MODIFIER_ALT = 0;
593
594    ECORE_X_LOCK_SCROLL = _ecore_xcb_key_mask_get(XK_Scroll_Lock);
595    ECORE_X_LOCK_NUM = _ecore_xcb_key_mask_get(XK_Num_Lock);
596    ECORE_X_LOCK_CAPS = _ecore_xcb_key_mask_get(XK_Caps_Lock);
597
598    _ecore_xcb_fd_handler_handle =
599       ecore_main_fd_handler_add(xcb_get_file_descriptor(_ecore_xcb_conn),
600                                 ECORE_FD_READ,
601                                 _ecore_xcb_fd_handler, _ecore_xcb_conn,
602                                 _ecore_xcb_fd_handler_buf, _ecore_xcb_conn);
603    if (!_ecore_xcb_fd_handler_handle)
604       goto free_event_handlers;
605
606    _ecore_xcb_filter_handler = ecore_event_filter_add(_ecore_xcb_event_filter_start, _ecore_xcb_event_filter_filter, _ecore_xcb_event_filter_end, NULL);
607
608    /* This is just to be anal about naming conventions */
609
610    _ecore_xcb_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_DELETE_REQUEST] = ECORE_X_ATOM_WM_DELETE_WINDOW;
611    _ecore_xcb_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_TAKE_FOCUS] = ECORE_X_ATOM_WM_TAKE_FOCUS;
612    _ecore_xcb_atoms_wm_protocols[ECORE_X_NET_WM_PROTOCOL_PING] = ECORE_X_ATOM_NET_WM_PING;
613    _ecore_xcb_atoms_wm_protocols[ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST] = ECORE_X_ATOM_NET_WM_SYNC_REQUEST;
614
615    _ecore_xcb_init_count++;
616
617    _ecore_xcb_private_window = ecore_x_window_override_new(0, -77, -777, 123, 456);
618
619    /* We finally get the replies of the QueryVersion request */
620 #ifdef ECORE_XCB_DAMAGE
621    _ecore_x_damage_init_finalize();
622 #endif /* ECORE_XCB_DAMAGE */
623 #ifdef ECORE_XCB_COMPOSITE
624    _ecore_x_composite_init_finalize();
625 #endif /* ECORE_XCB_COMPOSITE */
626 #ifdef ECORE_XCB_DPMS
627    _ecore_x_dpms_init_finalize();
628 #endif /* ECORE_XCB_DPMS */
629 #ifdef ECORE_XCB_RANDR
630    _ecore_x_randr_init_finalize();
631 #endif /* ECORE_XCB_RANDR */
632 #ifdef ECORE_XCB_SCREENSAVER
633    _ecore_x_screensaver_init_finalize();
634 #endif /* ECORE_XCB_SCREENSAVER */
635 #ifdef ECORE_XCB_SHAPE
636    _ecore_x_shape_init_finalize();
637 #endif /* ECORE_XCB_SHAPE */
638 #ifdef ECORE_XCB_SYNC
639    _ecore_x_sync_init_finalize();
640 #endif /* ECORE_XCB_SYNC */
641 #ifdef ECORE_XCB_FIXES
642    _ecore_x_xfixes_init_finalize();
643 #endif /* ECORE_XCB_FIXES */
644 #ifdef ECORE_XCB_XINERAMA
645    _ecore_x_xinerama_init_finalize();
646 #endif /* ECORE_XCB_XINERAMA */
647
648    return _ecore_xcb_init_count;
649
650 free_event_handlers:
651    free(_ecore_xcb_event_handlers);
652    _ecore_xcb_event_handlers = NULL;
653 finalize_extensions:
654    /* We get the replies of the QueryVersion request because we leave */
655 #ifdef ECORE_XCB_DAMAGE
656    _ecore_x_damage_init_finalize();
657 #endif /* ECORE_XCB_DAMAGE */
658 #ifdef ECORE_XCB_COMPOSITE
659    _ecore_x_composite_init_finalize();
660 #endif /* ECORE_XCB_COMPOSITE */
661 #ifdef ECORE_XCB_DPMS
662    _ecore_x_dpms_init_finalize();
663 #endif /* ECORE_XCB_DPMS */
664 #ifdef ECORE_XCB_RANDR
665    _ecore_x_randr_init_finalize();
666 #endif /* ECORE_XCB_RANDR */
667 #ifdef ECORE_XCB_SCREENSAVER
668    _ecore_x_screensaver_init_finalize();
669 #endif /* ECORE_XCB_SCREENSAVER */
670 #ifdef ECORE_XCB_SHAPE
671    _ecore_x_shape_init_finalize();
672 #endif /* ECORE_XCB_SHAPE */
673 #ifdef ECORE_XCB_SYNC
674    _ecore_x_sync_init_finalize();
675 #endif /* ECORE_XCB_SYNC */
676 #ifdef ECORE_XCB_FIXES
677    _ecore_x_xfixes_init_finalize();
678 #endif /* ECORE_XCB_FIXES */
679 #ifdef ECORE_XCB_XINERAMA
680    _ecore_x_xinerama_init_finalize();
681 #endif /* ECORE_XCB_XINERAMA */
682 shutdown_ecore_event:
683    ecore_event_shutdown();
684 shutdown_ecore:
685    ecore_shutdown();
686 shutdown_eina:
687    eina_log_domain_unregister(_ecore_x11xcb_log_dom);
688    _ecore_x11xcb_log_dom = -1;
689    eina_shutdown();
690
691    return --_ecore_xcb_init_count;
692 } /* ecore_x_init */
693
694 static int
695 _ecore_x_shutdown(int close_display)
696 {
697    if (--_ecore_xcb_init_count != 0)
698       return _ecore_xcb_init_count;
699
700    if (!_ecore_xcb_conn)
701       return _ecore_xcb_init_count;
702
703    ecore_main_fd_handler_del(_ecore_xcb_fd_handler_handle);
704    if (close_display)
705       xcb_disconnect(_ecore_xcb_conn);
706    else
707       close(xcb_get_file_descriptor(_ecore_xcb_conn));
708
709    free(_ecore_xcb_event_handlers);
710    ecore_event_filter_del(_ecore_xcb_filter_handler);
711    _ecore_xcb_fd_handler_handle = NULL;
712    _ecore_xcb_filter_handler = NULL;
713    _ecore_xcb_conn = NULL;
714    _ecore_xcb_event_handlers = NULL;
715    _ecore_x_selection_shutdown();
716    _ecore_x_dnd_shutdown();
717    ecore_x_netwm_shutdown();
718    _ecore_x_reply_shutdown();
719
720    ecore_event_shutdown();
721    ecore_shutdown();
722
723    eina_log_domain_unregister(_ecore_x11xcb_log_dom);
724    _ecore_x11xcb_log_dom = -1;
725    eina_shutdown();
726
727    return _ecore_xcb_init_count;
728 } /* _ecore_x_shutdown */
729
730 /**
731  * Shuts down the Ecore X library.
732  *
733  * In shutting down the library, the X display connection is terminated
734  * and any event handlers for it are removed.
735  *
736  * @return  The number of times the library has been initialized without
737  *          being shut down.
738  * @ingroup Ecore_Xcb_Init_Group
739  */
740 EAPI int
741 ecore_x_shutdown(void)
742 {
743    return _ecore_x_shutdown(1);
744 } /* ecore_x_shutdown */
745
746 /**
747  * Shuts down the Ecore X library.
748  *
749  * As ecore_xcb_shutdown, except do not close Display, only connection.
750  *
751  * @ingroup Ecore_Xcb_Init_Group
752  */
753 EAPI int
754 ecore_x_disconnect(void)
755 {
756    return _ecore_x_shutdown(0);
757 } /* ecore_x_disconnect */
758
759 /**
760  * @defgroup Ecore_Xcb_Display_Attr_Group X Display Attributes
761  *
762  * Functions that set and retrieve X display attributes.
763  */
764
765 EAPI Ecore_X_Display *
766 ecore_x_display_get(void)
767 {
768    return NULL;
769 } /* ecore_x_display_get */
770
771 /**
772  * Retrieves the Ecore_X_Connection handle used for the current X connection.
773  * @return  The current X connection.
774  * @ingroup Ecore_Xcb_Display_Attr_Group
775  */
776 EAPI Ecore_X_Connection *
777 ecore_x_connection_get(void)
778 {
779    return (Ecore_X_Connection *)_ecore_xcb_conn;
780 } /* ecore_x_connection_get */
781
782 /**
783  * Retrieves the X display file descriptor.
784  * @return  The current X display file descriptor.
785  * @ingroup Ecore_Xcb_Display_Attr_Group
786  */
787 EAPI int
788 ecore_x_fd_get(void)
789 {
790    return xcb_get_file_descriptor(_ecore_xcb_conn);
791 } /* ecore_x_fd_get */
792
793 /**
794  * Retrieves the Ecore_X_Screen handle used for the current X connection.
795  * @return  The current default screen.
796  * @ingroup Ecore_Xcb_Display_Attr_Group
797  */
798 EAPI Ecore_X_Screen *
799 ecore_x_default_screen_get(void)
800 {
801    return (Ecore_X_Screen *)_ecore_xcb_screen;
802 } /* ecore_x_default_screen_get */
803
804 /**
805  * Sets the timeout for a double and triple clicks to be flagged.
806  *
807  * This sets the time between clicks before the double_click flag is
808  * set in a button down event. If 3 clicks occur within double this
809  * time, the triple_click flag is also set.
810  *
811  * @param   t The time in seconds
812  * @ingroup Ecore_Xcb_Display_Attr_Group
813  */
814 EAPI void
815 ecore_x_double_click_time_set(double t)
816 {
817    if (t < 0.0)
818       t = 0.0;
819
820    _ecore_xcb_double_click_time = t;
821 } /* ecore_x_double_click_time_set */
822
823 /**
824  * Retrieves the double and triple click flag timeout.
825  *
826  * See @ref ecore_xcb_double_click_time_set for more information.
827  *
828  * @return  The timeout for double clicks in seconds.
829  * @ingroup Ecore_Xcb_Display_Attr_Group
830  */
831 EAPI double
832 ecore_x_double_click_time_get(void)
833 {
834    return _ecore_xcb_double_click_time;
835 } /* ecore_x_double_click_time_get */
836
837 /**
838  * @defgroup Ecore_Xcb_Flush_Group X Synchronization Functions
839  *
840  * Functions that ensure that all commands that have been issued by the
841  * Ecore X library have been sent to the server.
842  */
843
844 /**
845  * Sends all X commands in the X Display buffer.
846  * @ingroup Ecore_Xcb_Flush_Group
847  */
848 EAPI void
849 ecore_x_flush(void)
850 {
851    xcb_flush(_ecore_xcb_conn);
852 } /* ecore_x_flush */
853
854 /**
855  * Flushes the command buffer and waits until all requests have been
856  * processed by the server.
857  * @ingroup Ecore_Xcb_Flush_Group
858  */
859 EAPI void
860 ecore_x_sync(void)
861 {
862    free(xcb_get_input_focus_reply(_ecore_xcb_conn, xcb_get_input_focus(_ecore_xcb_conn), NULL));
863 } /* ecore_x_sync */
864
865 /**
866  * Kill all clients with subwindows under a given window.
867  *
868  * You can kill all clients connected to the X server by using
869  * @ref ecore_x_window_root_list to get a list of root windows, and
870  * then passing each root window to this function.
871  *
872  * @param root The window whose children will be killed.
873  */
874 EAPI void
875 ecore_x_killall(Ecore_X_Window root)
876 {
877    int screens;
878    int i;
879
880    xcb_grab_server(_ecore_xcb_conn);
881    screens = xcb_setup_roots_iterator (xcb_get_setup (_ecore_xcb_conn)).rem;
882
883    /* Tranverse window tree starting from root, and drag each
884     * before the firing squad */
885    for (i = 0; i < screens; ++i)
886      {
887         xcb_query_tree_cookie_t cookie;
888         xcb_query_tree_reply_t *reply;
889
890         cookie = xcb_query_tree_unchecked(_ecore_xcb_conn, root);
891         reply = xcb_query_tree_reply(_ecore_xcb_conn, cookie, NULL);
892         if (reply)
893           {
894              xcb_window_t *wins = NULL;
895              int tree_c_len;
896              int i;
897
898              wins = xcb_query_tree_children(reply);
899              tree_c_len = xcb_query_tree_children_length(reply);
900              for (i = 0; i < tree_c_len; i++)
901                 xcb_kill_client(_ecore_xcb_conn, wins[i]);
902              free(reply);
903           }
904      }
905
906    xcb_ungrab_server(_ecore_xcb_conn);
907    free(xcb_get_input_focus_reply(_ecore_xcb_conn, xcb_get_input_focus(_ecore_xcb_conn), NULL));
908 } /* ecore_x_killall */
909
910 /**
911  * Kill a specific client
912  *
913  * You can kill a specific client woning window @p window
914  *
915  * @param window Window of the client to be killed
916  */
917 EAPI void
918 ecore_x_kill(Ecore_X_Window window)
919 {
920    xcb_kill_client(_ecore_xcb_conn, window);
921 } /* ecore_x_kill */
922
923 /**
924  * TODO: Invoke the standard system beep to alert users
925  */
926 EAPI Eina_Bool
927 ecore_x_bell(int percent)
928 {
929    return 0;
930 } /* ecore_x_bell */
931
932 /**
933  * Return the last event time
934  */
935 EAPI Ecore_X_Time
936 ecore_x_current_time_get(void)
937 {
938    return _ecore_xcb_event_last_time;
939 } /* ecore_x_current_time_get */
940
941 static void
942 handle_event(xcb_generic_event_t *ev)
943 {
944    uint8_t response_type = ev->response_type & ~0x80;
945
946    if (response_type < _ecore_xcb_event_handlers_num)
947      {
948         if (_ecore_xcb_event_handlers[XCB_EVENT_ANY])
949            _ecore_xcb_event_handlers[XCB_EVENT_ANY] (ev);
950
951         if (_ecore_xcb_event_handlers[response_type])
952            _ecore_xcb_event_handlers[response_type] (ev);
953      }
954 } /* handle_event */
955
956 static Eina_Bool
957 _ecore_xcb_fd_handler(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
958 {
959    xcb_connection_t *c;
960    xcb_generic_event_t *ev;
961
962    c = (xcb_connection_t *)data;
963
964 /*    INF ("nbr events: %d", _ecore_xcb_event_handlers_num); */
965
966    /* We check if _ecore_xcb_event_buffered is NULL or not */
967    if (_ecore_xcb_event_buffered)
968      {
969         handle_event(_ecore_xcb_event_buffered);
970         _ecore_xcb_event_buffered = NULL;
971      }
972
973    while ((ev = xcb_poll_for_event(c)))
974       handle_event(ev);
975
976    return ECORE_CALLBACK_RENEW;
977 } /* _ecore_xcb_fd_handler */
978
979 static Eina_Bool
980 _ecore_xcb_fd_handler_buf(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
981 {
982    xcb_connection_t *c;
983
984    c = (xcb_connection_t *)data;
985
986    _ecore_xcb_event_buffered = xcb_poll_for_event(c);
987    if (!_ecore_xcb_event_buffered)
988       return ECORE_CALLBACK_CANCEL;
989
990    return ECORE_CALLBACK_RENEW;
991 } /* _ecore_xcb_fd_handler_buf */
992
993 /* FIXME: possible roundtrip */
994 /* FIXME: fix xcb_keysyms. It's ugly !! (reply in xcb_key_symbols_get_keysym) */
995 static int
996 _ecore_xcb_key_mask_get(xcb_keysym_t sym)
997 {
998    xcb_get_modifier_mapping_cookie_t cookie;
999    xcb_get_modifier_mapping_reply_t *reply;
1000    xcb_key_symbols_t *symbols;
1001    xcb_keysym_t sym2;
1002    int i, j;
1003    xcb_keycode_t *keycodes = NULL;
1004    int mod_keys_len;
1005    const int masks[8] =
1006    {
1007       XCB_MOD_MASK_SHIFT,
1008       XCB_MOD_MASK_LOCK,
1009       XCB_MOD_MASK_CONTROL,
1010       XCB_MOD_MASK_1,
1011       XCB_MOD_MASK_2,
1012       XCB_MOD_MASK_3,
1013       XCB_MOD_MASK_4,
1014       XCB_MOD_MASK_5
1015    };
1016
1017    cookie = xcb_get_modifier_mapping_unchecked(_ecore_xcb_conn);
1018    symbols = xcb_key_symbols_alloc(_ecore_xcb_conn);
1019
1020    reply = xcb_get_modifier_mapping_reply(_ecore_xcb_conn, cookie, NULL);
1021    if (!reply)
1022      {
1023         xcb_key_symbols_free(symbols);
1024
1025         return 0;
1026      }
1027
1028    keycodes = xcb_get_modifier_mapping_keycodes(reply);
1029    mod_keys_len = xcb_get_modifier_mapping_keycodes_length(reply);
1030    for (i = 0; i < mod_keys_len; i++)
1031      {
1032         for (j = 0; j < 8; j++)
1033           {
1034              sym2 = xcb_key_symbols_get_keysym(symbols, keycodes[i], j);
1035              if (sym2 != 0)
1036                 break;
1037           }
1038         if (sym2 == sym)
1039           {
1040              int mask;
1041
1042              mask = masks[j];
1043              free(reply);
1044              xcb_key_symbols_free(symbols);
1045              return mask;
1046           }
1047      }
1048
1049    free(reply);
1050    xcb_key_symbols_free(symbols);
1051
1052    return 0;
1053 } /* _ecore_xcb_key_mask_get */
1054
1055 typedef struct _Ecore_X_Filter_Data   Ecore_X_Filter_Data;
1056
1057 struct _Ecore_X_Filter_Data
1058 {
1059    int last_event_type;
1060 };
1061
1062 static void *
1063 _ecore_xcb_event_filter_start(void *data __UNUSED__)
1064 {
1065    Ecore_X_Filter_Data *filter_data;
1066
1067    filter_data = calloc(1, sizeof(Ecore_X_Filter_Data));
1068    return filter_data;
1069 } /* _ecore_xcb_event_filter_start */
1070
1071 static Eina_Bool
1072 _ecore_xcb_event_filter_filter(void *data __UNUSED__, void *loop_data,int type, void *event __UNUSED__)
1073 {
1074    Ecore_X_Filter_Data *filter_data;
1075
1076    filter_data = loop_data;
1077    if (!filter_data)
1078       return EINA_TRUE;
1079
1080    if (type == ECORE_EVENT_MOUSE_MOVE)
1081      {
1082         if ((filter_data->last_event_type) == ECORE_EVENT_MOUSE_MOVE)
1083           {
1084              filter_data->last_event_type = type;
1085              return EINA_FALSE;
1086           }
1087      }
1088
1089    filter_data->last_event_type = type;
1090    return EINA_TRUE;
1091 } /* _ecore_xcb_event_filter_filter */
1092
1093 static void
1094 _ecore_xcb_event_filter_end(void *data __UNUSED__, void *loop_data)
1095 {
1096    Ecore_X_Filter_Data *filter_data;
1097
1098    filter_data = loop_data;
1099    if (filter_data)
1100       free(filter_data);
1101 } /* _ecore_xcb_event_filter_end */
1102
1103 /*****************************************************************************/
1104 /*****************************************************************************/
1105 /*****************************************************************************/
1106 /* FIXME: these funcs need categorising */
1107 /*****************************************************************************/
1108
1109 /**
1110  * Get a list of all the root windows on the server.
1111  *
1112  * @note   The returned array will need to be freed after use.
1113  * @param  num_ret Pointer to integer to put number of windows returned in.
1114  * @return An array of all the root windows.  @c NULL is returned if memory
1115  *         could not be allocated for the list, or if @p num_ret is @c NULL.
1116  */
1117 EAPI Ecore_X_Window *
1118 ecore_x_window_root_list(int *num_ret)
1119 {
1120    xcb_screen_iterator_t iter;
1121    const xcb_setup_t *setup;
1122    uint8_t i;
1123    uint8_t num;
1124    Ecore_X_Window *roots;
1125 /* #ifdef ECORE_XCBXPRINT */
1126 /*    int xp_base, xp_err_base; */
1127 /* #endif /\* ECORE_XCBXPRINT *\/ */
1128
1129    if (!num_ret)
1130       return NULL;
1131
1132    *num_ret = 0;
1133
1134    /* FIXME: todo... */
1135 /* #ifdef ECORE_XCBXPRINT */
1136 /*    num = ScreenCount(_ecore_xcb_conn); */
1137 /*    if (ecore_xcb_xprint_query()) */
1138 /*      { */
1139 /*      Screen **ps = NULL; */
1140 /*      int psnum = 0; */
1141
1142 /*      ps = XpQueryScreens(_ecore_xcb_conn, &psnum); */
1143 /*      if (ps) */
1144 /*        { */
1145 /*           int overlap, j; */
1146
1147 /*           overlap = 0; */
1148 /*           for (i = 0; i < num; i++) */
1149 /*             { */
1150 /*                for (j = 0; j < psnum; j++) */
1151 /*                  { */
1152 /*                     if (ScreenOfDisplay(_ecore_xcb_conn, i) == ps[j]) */
1153 /*                       overlap++; */
1154 /*                  } */
1155 /*             } */
1156 /*           roots = malloc((num - overlap) * sizeof(Ecore_X_Window)); */
1157 /*           if (roots) */
1158 /*             { */
1159 /*                int k; */
1160
1161 /*                k = 0; */
1162 /*                for (i = 0; i < num; i++) */
1163 /*                  { */
1164 /*                     int is_print; */
1165
1166 /*                     is_print = 0; */
1167 /*                     for (j = 0; j < psnum; j++) */
1168 /*                       { */
1169 /*                          if (ScreenOfDisplay(_ecore_xcb_conn, i) == ps[j]) */
1170 /*                            { */
1171 /*                               is_print = 1; */
1172 /*                               break; */
1173 /*                            } */
1174 /*                       } */
1175 /*                     if (!is_print) */
1176 /*                       { */
1177 /*                          roots[k] = RootWindow(_ecore_xcb_conn, i); */
1178 /*                          k++; */
1179 /*                       } */
1180 /*                  } */
1181 /*                *num_ret = k; */
1182 /*             } */
1183 /*           XFree(ps); */
1184 /*        } */
1185 /*      else */
1186 /*        { */
1187 /*           roots = malloc(num * sizeof(Ecore_X_Window)); */
1188 /*           if (!roots) return NULL; */
1189 /*           *num_ret = num; */
1190 /*           for (i = 0; i < num; i++) */
1191 /*             roots[i] = RootWindow(_ecore_xcb_conn, i); */
1192 /*        } */
1193 /*      } */
1194 /*    else */
1195 /*      { */
1196 /*      roots = malloc(num * sizeof(Ecore_X_Window)); */
1197 /*      if (!roots) return NULL; */
1198 /*      *num_ret = num; */
1199 /*      for (i = 0; i < num; i++) */
1200 /*        roots[i] = RootWindow(_ecore_xcb_conn, i); */
1201 /*      } */
1202 /* #else */
1203    setup = xcb_get_setup (_ecore_xcb_conn);
1204    iter = xcb_setup_roots_iterator (setup);
1205    num = setup->roots_len;
1206    roots = malloc(num * sizeof(Ecore_X_Window));
1207    if (!roots)
1208       return NULL;
1209
1210    *num_ret = num;
1211    for (i = 0; iter.rem; xcb_screen_next(&iter), i++)
1212       roots[i] = iter.data->root;
1213 /* #endif /\* ECORE_XCBXPRINT *\/ */
1214
1215    return roots;
1216 } /* ecore_x_window_root_list */
1217
1218 EAPI Ecore_X_Window
1219 ecore_x_window_root_first_get(void)
1220 {
1221    Ecore_X_Window *roots = NULL;
1222    Ecore_X_Window root;
1223    int num;
1224
1225    roots = ecore_x_window_root_list(&num);
1226    if(!(roots))
1227       return 0;
1228
1229    if (num > 0)
1230       root = roots[0];
1231    else
1232       root = 0;
1233
1234    free(roots);
1235    return root;
1236 } /* ecore_x_window_root_first_get */
1237
1238 /* FIXME: todo */
1239
1240 static void      _ecore_x_window_manage_error(void *data);
1241
1242 static int _ecore_xcb_window_manage_failed = 0;
1243 static void
1244 _ecore_x_window_manage_error(void *data __UNUSED__)
1245 {
1246 /*    if ((ecore_xcb_error_request_get() == X_ChangeWindowAttributes) && */
1247 /*        (ecore_xcb_error_code_get() == BadAccess)) */
1248 /*      _ecore_xcb_window_manage_failed = 1; */
1249 } /* _ecore_x_window_manage_error */
1250
1251 /* FIXME: round trip */
1252 EAPI int
1253 ecore_x_window_manage(Ecore_X_Window window)
1254 {
1255    xcb_get_window_attributes_cookie_t cookie_attr;
1256    xcb_get_input_focus_cookie_t cookie_sync;
1257    xcb_get_window_attributes_reply_t *reply_attr;
1258    xcb_get_input_focus_reply_t *reply_sync;
1259    uint32_t value_list;
1260
1261    cookie_attr = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window);
1262    cookie_sync = xcb_get_input_focus_unchecked(_ecore_xcb_conn);
1263
1264    reply_attr = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie_attr, NULL);
1265    if (!reply_attr)
1266      {
1267         reply_sync = xcb_get_input_focus_reply(_ecore_xcb_conn, cookie_sync, NULL);
1268         if (reply_sync)
1269            free(reply_sync);
1270
1271         return 0;
1272      }
1273
1274    reply_sync = xcb_get_input_focus_reply(_ecore_xcb_conn, cookie_sync, NULL);
1275    if (reply_sync)
1276       free(reply_sync);
1277
1278    _ecore_xcb_window_manage_failed = 0;
1279    /* FIXME: no error code yet */
1280    /* ecore_xcb_error_handler_set(_ecore_xcb_window_manage_error, NULL); */
1281
1282    value_list =
1283       XCB_EVENT_MASK_KEY_PRESS |
1284       XCB_EVENT_MASK_KEY_RELEASE |
1285       XCB_EVENT_MASK_ENTER_WINDOW |
1286       XCB_EVENT_MASK_LEAVE_WINDOW |
1287       XCB_EVENT_MASK_STRUCTURE_NOTIFY |
1288       XCB_EVENT_MASK_RESIZE_REDIRECT |
1289       XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
1290       XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT |
1291       XCB_EVENT_MASK_PROPERTY_CHANGE |
1292       reply_attr->your_event_mask;
1293    xcb_change_window_attributes(_ecore_xcb_conn, window,
1294                                 XCB_CW_EVENT_MASK,
1295                                 &value_list);
1296    free(reply_attr);
1297
1298    cookie_sync = xcb_get_input_focus_unchecked(_ecore_xcb_conn);
1299    if (reply_sync)
1300       free(reply_sync);
1301
1302    /* FIXME: no error code yet */
1303    /* ecore_xcb_error_handler_set(NULL, NULL); */
1304    if (_ecore_xcb_window_manage_failed)
1305      {
1306         _ecore_xcb_window_manage_failed = 0;
1307         return 0;
1308      }
1309
1310    return 1;
1311 } /* ecore_x_window_manage */
1312
1313 EAPI int
1314 ecore_x_pointer_control_set(int accel_num,
1315                             int accel_denom,
1316                             int threshold)
1317 {
1318    xcb_change_pointer_control(_ecore_xcb_conn,
1319                               accel_num, accel_denom, threshold,
1320                               1, 1);
1321    return 1;
1322 } /* ecore_x_pointer_control_set */
1323
1324 EAPI void
1325 ecore_x_pointer_control_get_prefetch(void)
1326 {
1327    xcb_get_pointer_control_cookie_t cookie;
1328
1329    cookie = xcb_get_pointer_control_unchecked(_ecore_xcb_conn);
1330    _ecore_xcb_cookie_cache(cookie.sequence);
1331 } /* ecore_x_pointer_control_get_prefetch */
1332
1333 EAPI void
1334 ecore_x_pointer_control_get_fetch(void)
1335 {
1336    xcb_get_pointer_control_cookie_t cookie;
1337    xcb_get_pointer_control_reply_t *reply;
1338
1339    cookie.sequence = _ecore_xcb_cookie_get();
1340    reply = xcb_get_pointer_control_reply(_ecore_xcb_conn, cookie, NULL);
1341    _ecore_xcb_reply_cache(reply);
1342 } /* ecore_x_pointer_control_get_fetch */
1343
1344 EAPI int
1345 ecore_x_pointer_control_get(int *accel_num,
1346                             int *accel_denom,
1347                             int *threshold)
1348 {
1349    xcb_get_pointer_control_reply_t *reply;
1350
1351    if (accel_num)
1352       *accel_num = 0;
1353
1354    if (accel_denom)
1355       *accel_denom = 1;
1356
1357    if (threshold)
1358       *threshold = 0;
1359
1360    reply = _ecore_xcb_reply_get();
1361    if (!reply)
1362       return 0;
1363
1364    if (accel_num)
1365       *accel_num = reply->acceleration_numerator;
1366
1367    if (accel_denom)
1368       *accel_denom = reply->acceleration_denominator;
1369
1370    if (threshold)
1371       *threshold = reply->threshold;
1372
1373    return 1;
1374 } /* ecore_x_pointer_control_get */
1375
1376 EAPI int
1377 ecore_x_pointer_mapping_set(unsigned char *map,
1378                             int            nmap)
1379 {
1380    xcb_set_pointer_mapping(_ecore_xcb_conn, nmap, map);
1381    return 1;
1382 } /* ecore_x_pointer_mapping_set */
1383
1384 EAPI void
1385 ecore_x_pointer_mapping_get_prefetch(void)
1386 {
1387    xcb_get_pointer_mapping_cookie_t cookie;
1388
1389    cookie = xcb_get_pointer_mapping_unchecked(_ecore_xcb_conn);
1390    _ecore_xcb_cookie_cache(cookie.sequence);
1391 } /* ecore_x_pointer_mapping_get_prefetch */
1392
1393 EAPI void
1394 ecore_x_pointer_mapping_get_fetch(void)
1395 {
1396    xcb_get_pointer_mapping_cookie_t cookie;
1397    xcb_get_pointer_mapping_reply_t *reply;
1398
1399    cookie.sequence = _ecore_xcb_cookie_get();
1400    reply = xcb_get_pointer_mapping_reply(_ecore_xcb_conn, cookie, NULL);
1401    _ecore_xcb_reply_cache(reply);
1402 } /* ecore_x_pointer_mapping_get_fetch */
1403
1404 EAPI int
1405 ecore_x_pointer_mapping_get(unsigned char *map,
1406                             int            nmap)
1407 {
1408    xcb_get_pointer_mapping_cookie_t cookie;
1409    xcb_get_pointer_mapping_reply_t *reply;
1410    uint8_t *tmp;
1411    int i;
1412
1413    cookie = xcb_get_pointer_mapping_unchecked(_ecore_xcb_conn);
1414    reply = xcb_get_pointer_mapping_reply(_ecore_xcb_conn, cookie, NULL);
1415    if (!reply)
1416       return 0;
1417
1418    if (nmap > xcb_get_pointer_mapping_map_length(reply))
1419       return 0;
1420
1421    tmp = xcb_get_pointer_mapping_map(reply);
1422
1423    for (i = 0; i < nmap; i++)
1424       map[i] = tmp[i];
1425
1426    return 1;
1427 } /* ecore_x_pointer_mapping_get */
1428
1429 EAPI int
1430 ecore_x_pointer_grab(Ecore_X_Window window)
1431 {
1432    xcb_grab_pointer_cookie_t cookie;
1433    xcb_grab_pointer_reply_t *reply;
1434
1435    cookie = xcb_grab_pointer_unchecked(_ecore_xcb_conn, 0, window,
1436                                        XCB_EVENT_MASK_BUTTON_PRESS |
1437                                        XCB_EVENT_MASK_BUTTON_RELEASE |
1438                                        XCB_EVENT_MASK_ENTER_WINDOW |
1439                                        XCB_EVENT_MASK_LEAVE_WINDOW |
1440                                        XCB_EVENT_MASK_POINTER_MOTION,
1441                                        XCB_GRAB_MODE_ASYNC,
1442                                        XCB_GRAB_MODE_ASYNC,
1443                                        XCB_NONE, XCB_NONE,
1444                                        XCB_CURRENT_TIME);
1445    reply = xcb_grab_pointer_reply(_ecore_xcb_conn, cookie, NULL);
1446    if (!reply)
1447       return 0;
1448
1449    free(reply);
1450
1451    return 1;
1452 } /* ecore_x_pointer_grab */
1453
1454 EAPI int
1455 ecore_x_pointer_confine_grab(Ecore_X_Window window)
1456 {
1457    xcb_grab_pointer_cookie_t cookie;
1458    xcb_grab_pointer_reply_t *reply;
1459
1460    cookie = xcb_grab_pointer_unchecked(_ecore_xcb_conn, 0, window,
1461                                        XCB_EVENT_MASK_BUTTON_PRESS |
1462                                        XCB_EVENT_MASK_BUTTON_RELEASE |
1463                                        XCB_EVENT_MASK_ENTER_WINDOW |
1464                                        XCB_EVENT_MASK_LEAVE_WINDOW |
1465                                        XCB_EVENT_MASK_POINTER_MOTION,
1466                                        XCB_GRAB_MODE_ASYNC,
1467                                        XCB_GRAB_MODE_ASYNC,
1468                                        window, XCB_NONE,
1469                                        XCB_CURRENT_TIME);
1470    reply = xcb_grab_pointer_reply(_ecore_xcb_conn, cookie, NULL);
1471    if (!reply)
1472       return 0;
1473
1474    free(reply);
1475
1476    return 1;
1477 } /* ecore_x_pointer_confine_grab */
1478
1479 EAPI void
1480 ecore_x_pointer_ungrab(void)
1481 {
1482    xcb_ungrab_pointer(_ecore_xcb_conn, XCB_CURRENT_TIME);
1483 } /* ecore_x_pointer_ungrab */
1484
1485 EAPI int
1486 ecore_x_pointer_warp(Ecore_X_Window window,
1487                      int            x,
1488                      int            y)
1489 {
1490    xcb_warp_pointer(_ecore_xcb_conn, XCB_NONE, window, 0, 0, 0, 0, x, y);
1491
1492    return 1;
1493 } /* ecore_x_pointer_warp */
1494
1495 EAPI int
1496 ecore_x_keyboard_grab(Ecore_X_Window window)
1497 {
1498    xcb_grab_keyboard_cookie_t cookie;
1499    xcb_grab_keyboard_reply_t *reply;
1500
1501    cookie = xcb_grab_keyboard_unchecked(_ecore_xcb_conn, 0, window,
1502                                         XCB_CURRENT_TIME,
1503                                         XCB_GRAB_MODE_ASYNC,
1504                                         XCB_GRAB_MODE_ASYNC);
1505    reply = xcb_grab_keyboard_reply(_ecore_xcb_conn, cookie, NULL);
1506    if (!reply)
1507       return 0;
1508
1509    free(reply);
1510
1511    return 1;
1512 } /* ecore_x_keyboard_grab */
1513
1514 EAPI void
1515 ecore_x_keyboard_ungrab(void)
1516 {
1517    xcb_ungrab_keyboard(_ecore_xcb_conn, XCB_CURRENT_TIME);
1518 } /* ecore_x_keyboard_ungrab */
1519
1520 EAPI void
1521 ecore_x_grab(void)
1522 {
1523    _ecore_xcb_grab_count++;
1524
1525    if (_ecore_xcb_grab_count == 1)
1526       xcb_grab_server(_ecore_xcb_conn);
1527 } /* ecore_x_grab */
1528
1529 EAPI void
1530 ecore_x_ungrab(void)
1531 {
1532    _ecore_xcb_grab_count--;
1533    if (_ecore_xcb_grab_count < 0)
1534       _ecore_xcb_grab_count = 0;
1535
1536    if (_ecore_xcb_grab_count == 0)
1537      {
1538         xcb_ungrab_server(_ecore_xcb_conn);
1539         free(xcb_get_input_focus_reply(_ecore_xcb_conn, xcb_get_input_focus(_ecore_xcb_conn), NULL));
1540      }
1541 } /* ecore_x_ungrab */
1542
1543 int _ecore_window_grabs_num = 0;
1544 Ecore_X_Window *_ecore_window_grabs = NULL;
1545 Eina_Bool (*_ecore_window_grab_replay_func)(void *data, int event_type, void *event);
1546 void *_ecore_window_grab_replay_data;
1547
1548 EAPI void
1549 ecore_x_passive_grab_replay_func_set(Eina_Bool                             (*func)(void *data,
1550                                                                      int   event_type,
1551                                                                      void *event),
1552                                      void                                 *data)
1553 {
1554    _ecore_window_grab_replay_func = func;
1555    _ecore_window_grab_replay_data = data;
1556 } /* ecore_x_passive_grab_replay_func_set */
1557
1558 EAPI void
1559 ecore_x_window_button_grab(Ecore_X_Window     window,
1560                            int                button,
1561                            Ecore_X_Event_Mask event_mask,
1562                            int                mod,
1563                            int                any_mod)
1564 {
1565    int i;
1566    uint16_t m;
1567    uint16_t locks[8];
1568    uint16_t ev;
1569
1570    m = _ecore_xcb_event_modifier(mod);
1571    if (any_mod)
1572       m = XCB_BUTTON_MASK_ANY;
1573
1574    locks[0] = 0;
1575    locks[1] = ECORE_X_LOCK_CAPS;
1576    locks[2] = ECORE_X_LOCK_NUM;
1577    locks[3] = ECORE_X_LOCK_SCROLL;
1578    locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM;
1579    locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL;
1580    locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1581    locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1582    ev = event_mask;
1583    for (i = 0; i < 8; i++)
1584       xcb_grab_button(_ecore_xcb_conn, 0, window, ev,
1585                       XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC,
1586                       XCB_NONE, XCB_NONE, button, m | locks[i]);
1587    _ecore_window_grabs_num++;
1588    _ecore_window_grabs = realloc(_ecore_window_grabs,
1589                                  _ecore_window_grabs_num * sizeof(Ecore_X_Window));
1590    _ecore_window_grabs[_ecore_window_grabs_num - 1] = window;
1591 } /* ecore_x_window_button_grab */
1592
1593 void
1594 _ecore_x_sync_magic_send(int            val,
1595                          Ecore_X_Window swindow)
1596 {
1597    xcb_client_message_event_t ev;
1598
1599    ev.response_type = XCB_CLIENT_MESSAGE | 0x80;
1600    ev.format = 32;
1601    ev.window = _ecore_xcb_private_window;
1602    ev.type = 27777;
1603    ev.data.data32[0] = 0x7162534;
1604    ev.data.data32[1] = 0x10000000 + val;
1605    ev.data.data32[2] = swindow;
1606
1607    xcb_send_event(_ecore_xcb_conn, 0, _ecore_xcb_private_window,
1608                   XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
1609 } /* _ecore_x_sync_magic_send */
1610
1611 void
1612 _ecore_x_window_grab_remove(Ecore_X_Window window)
1613 {
1614    int i, shuffle = 0;
1615
1616    if (_ecore_window_grabs_num > 0)
1617      {
1618         for (i = 0; i < _ecore_window_grabs_num; i++)
1619           {
1620              if (shuffle)
1621                 _ecore_window_grabs[i - 1] = _ecore_window_grabs[i];
1622
1623              if ((!shuffle) && (_ecore_window_grabs[i] == window))
1624                 shuffle = 1;
1625           }
1626         if (shuffle)
1627           {
1628              _ecore_window_grabs_num--;
1629              _ecore_window_grabs = realloc(_ecore_window_grabs,
1630                                            _ecore_window_grabs_num * sizeof(Ecore_X_Window));
1631           }
1632      }
1633 } /* _ecore_x_window_grab_remove */
1634
1635 EAPI void
1636 ecore_x_window_button_ungrab(Ecore_X_Window window,
1637                              int            button,
1638                              int            mod,
1639                              int            any_mod)
1640 {
1641    int i;
1642    uint16_t m;
1643    uint16_t locks[8];
1644
1645    m = _ecore_xcb_event_modifier(mod);
1646    if (any_mod)
1647       m = XCB_BUTTON_MASK_ANY;
1648
1649    locks[0] = 0;
1650    locks[1] = ECORE_X_LOCK_CAPS;
1651    locks[2] = ECORE_X_LOCK_NUM;
1652    locks[3] = ECORE_X_LOCK_SCROLL;
1653    locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM;
1654    locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL;
1655    locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1656    locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1657    for (i = 0; i < 8; i++)
1658       xcb_ungrab_button(_ecore_xcb_conn, button, window, m | locks[i]);
1659    _ecore_x_sync_magic_send(1, window);
1660 } /* ecore_x_window_button_ungrab */
1661
1662 int _ecore_key_grabs_num = 0;
1663 Ecore_X_Window *_ecore_key_grabs = NULL;
1664
1665 EAPI void
1666 ecore_x_window_key_grab(Ecore_X_Window window,
1667                         const char    *key,
1668                         int            mod,
1669                         int            any_mod)
1670 {
1671    xcb_keycode_t keycode = 0;
1672    uint16_t m;
1673    uint16_t locks[8];
1674    int i;
1675
1676    if (!strncmp(key, "Keycode-", 8))
1677       keycode = atoi(key + 8);
1678
1679    /* FIXME: TODO... */
1680
1681 /*    else */
1682 /*      { */
1683 /*         KeySym              keysym; */
1684
1685 /*      keysym = XStringToKeysym(key); */
1686 /*      if (keysym == NoSymbol) return; */
1687 /*      keycode  = XKeysymToKeycode(_ecore_xcb_conn, XStringToKeysym(key)); */
1688 /*      } */
1689    if (keycode == 0)
1690       return;
1691
1692    m = _ecore_xcb_event_modifier(mod);
1693    if (any_mod)
1694       m = XCB_BUTTON_MASK_ANY;
1695
1696    locks[0] = 0;
1697    locks[1] = ECORE_X_LOCK_CAPS;
1698    locks[2] = ECORE_X_LOCK_NUM;
1699    locks[3] = ECORE_X_LOCK_SCROLL;
1700    locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM;
1701    locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL;
1702    locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1703    locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1704    for (i = 0; i < 8; i++)
1705       xcb_grab_key(_ecore_xcb_conn, 1, window, m | locks[i], keycode,
1706                    XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC);
1707    _ecore_key_grabs_num++;
1708    _ecore_key_grabs = realloc(_ecore_key_grabs,
1709                               _ecore_key_grabs_num * sizeof(Ecore_X_Window));
1710    _ecore_key_grabs[_ecore_key_grabs_num - 1] = window;
1711 } /* ecore_x_window_key_grab */
1712
1713 void
1714 _ecore_x_key_grab_remove(Ecore_X_Window window)
1715 {
1716    int i, shuffle = 0;
1717
1718    if (_ecore_key_grabs_num > 0)
1719      {
1720         for (i = 0; i < _ecore_key_grabs_num; i++)
1721           {
1722              if (shuffle)
1723                 _ecore_key_grabs[i - 1] = _ecore_key_grabs[i];
1724
1725              if ((!shuffle) && (_ecore_key_grabs[i] == window))
1726                 shuffle = 1;
1727           }
1728         if (shuffle)
1729           {
1730              _ecore_key_grabs_num--;
1731              _ecore_key_grabs = realloc(_ecore_key_grabs,
1732                                         _ecore_key_grabs_num * sizeof(Ecore_X_Window));
1733           }
1734      }
1735 } /* _ecore_x_key_grab_remove */
1736
1737 EAPI void
1738 ecore_x_window_key_ungrab(Ecore_X_Window window,
1739                           const char    *key,
1740                           int            mod,
1741                           int            any_mod)
1742 {
1743    xcb_keycode_t keycode = 0;
1744    uint16_t m;
1745    uint16_t locks[8];
1746    int i;
1747
1748    if (!strncmp(key, "Keycode-", 8))
1749       keycode = atoi(key + 8);
1750
1751    /* FIXME: todo... */
1752
1753 /*    else */
1754 /*      { */
1755 /*         KeySym              keysym; */
1756
1757 /*      keysym = XStringToKeysym(key); */
1758 /*      if (keysym == NoSymbol) return; */
1759 /*      keycode  = XKeysymToKeycode(_ecore_xcb_conn, XStringToKeysym(key)); */
1760 /*      } */
1761    if (keycode == 0)
1762       return;
1763
1764    m = _ecore_xcb_event_modifier(mod);
1765    if (any_mod)
1766       m = XCB_BUTTON_MASK_ANY;
1767
1768    locks[0] = 0;
1769    locks[1] = ECORE_X_LOCK_CAPS;
1770    locks[2] = ECORE_X_LOCK_NUM;
1771    locks[3] = ECORE_X_LOCK_SCROLL;
1772    locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM;
1773    locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL;
1774    locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1775    locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1776    for (i = 0; i < 8; i++)
1777       xcb_ungrab_key(_ecore_xcb_conn, keycode, window, m | locks[i]);
1778    _ecore_x_sync_magic_send(2, window);
1779 } /* ecore_x_window_key_ungrab */
1780
1781 /**
1782  * Send client message with given type and format 32.
1783  *
1784  * @param window  The window the message is sent to.
1785  * @param type    The client message type.
1786  * @param mask    The client message mask.
1787  * @param d0      The client message data item 1
1788  * @param d1      The client message data item 2
1789  * @param d2      The client message data item 3
1790  * @param d3      The client message data item 4
1791  * @param d4      The client message data item 5
1792  *
1793  * @return !0 on success.
1794  */
1795 EAPI int
1796 ecore_x_client_message32_send(Ecore_X_Window     window,
1797                               Ecore_X_Atom       type,
1798                               Ecore_X_Event_Mask mask,
1799                               long               d0,
1800                               long               d1,
1801                               long               d2,
1802                               long               d3,
1803                               long               d4)
1804 {
1805    xcb_client_message_event_t ev;
1806
1807    ev.response_type = XCB_CLIENT_MESSAGE | 0x80;
1808    ev.format = 32;
1809    ev.window = window;
1810    ev.type = type;
1811    ev.data.data32[0] = d0;
1812    ev.data.data32[1] = d1;
1813    ev.data.data32[2] = d2;
1814    ev.data.data32[3] = d3;
1815    ev.data.data32[4] = d4;
1816
1817    xcb_send_event(_ecore_xcb_conn, 0, window, mask, (const char *)&ev);
1818
1819    return 1;
1820 } /* ecore_x_client_message32_send */
1821
1822 /**
1823  * Send client message with given type and format 8.
1824  *
1825  * @param window  The window the message is sent to.
1826  * @param type    The client message type.
1827  * @param data    Data to be sent.
1828  * @param len     Number of data bytes, max 20.
1829  *
1830  * @return !0 on success.
1831  */
1832 EAPI int
1833 ecore_x_client_message8_send(Ecore_X_Window window,
1834                              Ecore_X_Atom   type,
1835                              const void    *data,
1836                              int            len)
1837 {
1838    xcb_client_message_event_t ev;
1839
1840    ev.response_type = XCB_CLIENT_MESSAGE | 0x80;
1841    ev.format = 8;
1842    ev.window = window;
1843    ev.type = type;
1844    if (len > 20)
1845       len = 20;
1846
1847    memcpy(ev.data.data8, data, len);
1848    memset(ev.data.data8 + len, 0, 20 - len);
1849
1850    xcb_send_event(_ecore_xcb_conn, 0, window, XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
1851
1852    return 1;
1853 } /* ecore_x_client_message8_send */
1854
1855 /* FIXME: round trip */
1856 EAPI int
1857 ecore_x_mouse_move_send(Ecore_X_Window window,
1858                         int            x,
1859                         int            y)
1860 {
1861    xcb_motion_notify_event_t ev;
1862    xcb_get_geometry_cookie_t cookie_geom;
1863    xcb_translate_coordinates_cookie_t cookie_trans;
1864    xcb_get_geometry_reply_t *reply_geom;
1865    xcb_translate_coordinates_reply_t *reply_trans;
1866
1867    cookie_geom = xcb_get_geometry_unchecked(_ecore_xcb_conn, window);
1868    reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL);
1869    if (!reply_geom)
1870       return 0;
1871
1872    cookie_trans = xcb_translate_coordinates_unchecked(_ecore_xcb_conn, window, reply_geom->root, x, y);
1873    reply_trans = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie_trans, NULL);
1874    if (!reply_trans)
1875      {
1876         free(reply_geom);
1877         return 0;
1878      }
1879
1880    ev.response_type = XCB_MOTION_NOTIFY;
1881    ev.detail = 0;
1882    ev.time = _ecore_xcb_event_last_time;
1883    ev.root = reply_geom->root;
1884    ev.event = window;
1885    ev.child = window;
1886    ev.root_x = reply_trans->dst_x;
1887    ev.root_y = reply_trans->dst_y;
1888    ev.event_x = x;
1889    ev.event_y = y;
1890    ev.state = 0;
1891    ev.same_screen = 1;
1892
1893    xcb_send_event(_ecore_xcb_conn, 1, window, XCB_EVENT_MASK_POINTER_MOTION, (const char *)&ev);
1894
1895    free(reply_geom);
1896    free(reply_trans);
1897
1898    return 1;
1899 } /* ecore_x_mouse_move_send */
1900
1901 /* FIXME: round trip */
1902 EAPI int
1903 ecore_x_mouse_down_send(Ecore_X_Window window,
1904                         int            x,
1905                         int            y,
1906                         int            button)
1907 {
1908    xcb_button_press_event_t ev;
1909    xcb_get_geometry_cookie_t cookie_geom;
1910    xcb_translate_coordinates_cookie_t cookie_trans;
1911    xcb_get_geometry_reply_t *reply_geom;
1912    xcb_translate_coordinates_reply_t *reply_trans;
1913
1914    cookie_geom = xcb_get_geometry_unchecked(_ecore_xcb_conn, window);
1915    reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL);
1916    if (!reply_geom)
1917       return 0;
1918
1919    cookie_trans = xcb_translate_coordinates_unchecked(_ecore_xcb_conn, window, reply_geom->root, x, y);
1920    reply_trans = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie_trans, NULL);
1921    if (!reply_trans)
1922      {
1923         free(reply_geom);
1924         return 0;
1925      }
1926
1927    ev.response_type = XCB_BUTTON_PRESS;
1928    ev.detail = button;
1929    ev.time = _ecore_xcb_event_last_time;
1930    ev.root = reply_geom->root;
1931    ev.event = window;
1932    ev.child = window;
1933    ev.root_x = reply_trans->dst_x;
1934    ev.root_y = reply_trans->dst_y;
1935    ev.event_x = x;
1936    ev.event_y = y;
1937    ev.state = 1 << button;
1938    ev.same_screen = 1;
1939
1940    xcb_send_event(_ecore_xcb_conn, 1, window, XCB_EVENT_MASK_BUTTON_PRESS, (const char *)&ev);
1941
1942    free(reply_geom);
1943    free(reply_trans);
1944
1945    return 1;
1946 } /* ecore_x_mouse_down_send */
1947
1948 /* FIXME: round trip */
1949 EAPI int
1950 ecore_x_mouse_up_send(Ecore_X_Window window,
1951                       int            x,
1952                       int            y,
1953                       int            button)
1954 {
1955    xcb_button_release_event_t ev;
1956    xcb_get_geometry_cookie_t cookie_geom;
1957    xcb_translate_coordinates_cookie_t cookie_trans;
1958    xcb_get_geometry_reply_t *reply_geom;
1959    xcb_translate_coordinates_reply_t *reply_trans;
1960
1961    cookie_geom = xcb_get_geometry_unchecked(_ecore_xcb_conn, window);
1962    reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL);
1963    if (!reply_geom)
1964       return 0;
1965
1966    cookie_trans = xcb_translate_coordinates_unchecked(_ecore_xcb_conn, window, reply_geom->root, x, y);
1967    reply_trans = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie_trans, NULL);
1968    if (!reply_trans)
1969      {
1970         free(reply_geom);
1971         return 0;
1972      }
1973
1974    ev.response_type = XCB_BUTTON_RELEASE;
1975    ev.detail = button;
1976    ev.time = _ecore_xcb_event_last_time;
1977    ev.root = reply_geom->root;
1978    ev.event = window;
1979    ev.child = window;
1980    ev.root_x = reply_trans->dst_x;
1981    ev.root_y = reply_trans->dst_y;
1982    ev.event_x = x;
1983    ev.event_y = y;
1984    ev.state = 0;
1985    ev.same_screen = 1;
1986
1987    xcb_send_event(_ecore_xcb_conn, 1, window, XCB_EVENT_MASK_BUTTON_RELEASE, (const char *)&ev);
1988
1989    free(reply_geom);
1990    free(reply_trans);
1991
1992    return 1;
1993 } /* ecore_x_mouse_up_send */
1994
1995 EAPI void
1996 ecore_x_focus_reset(void)
1997 {
1998    xcb_set_input_focus(_ecore_xcb_conn,
1999                        (uint8_t)XCB_INPUT_FOCUS_POINTER_ROOT,
2000                        XCB_INPUT_FOCUS_POINTER_ROOT,
2001                        XCB_CURRENT_TIME);
2002 } /* ecore_x_focus_reset */
2003
2004 EAPI void
2005 ecore_x_events_allow_all(void)
2006 {
2007    xcb_allow_events(_ecore_xcb_conn, XCB_ALLOW_ASYNC_BOTH, XCB_CURRENT_TIME);
2008 } /* ecore_x_events_allow_all */
2009
2010 EAPI void
2011 ecore_x_pointer_last_xy_get(int *x,
2012                             int *y)
2013 {
2014    if (x)
2015       *x = _ecore_xcb_event_last_root_x;
2016
2017    if (y)
2018       *y = _ecore_xcb_event_last_root_y;
2019 } /* ecore_x_pointer_last_xy_get */
2020
2021 /*****************************************************************************/
2022 /*****************************************************************************/
2023 /*****************************************************************************/
2024
2025 static int
2026 _ecore_xcb_event_modifier(unsigned int state)
2027 {
2028    int xmodifiers = 0;
2029
2030    if (state & ECORE_EVENT_MODIFIER_SHIFT)
2031       xmodifiers |= ECORE_X_MODIFIER_SHIFT;
2032
2033    if (state & ECORE_EVENT_MODIFIER_CTRL)
2034       xmodifiers |= ECORE_X_MODIFIER_CTRL;
2035
2036    if (state & ECORE_EVENT_MODIFIER_ALT)
2037       xmodifiers |= ECORE_X_MODIFIER_ALT;
2038
2039    if (state & ECORE_EVENT_MODIFIER_WIN)
2040       xmodifiers |= ECORE_X_MODIFIER_WIN;
2041
2042    if (state & ECORE_EVENT_LOCK_SCROLL)
2043       xmodifiers |= ECORE_X_LOCK_SCROLL;
2044
2045    if (state & ECORE_EVENT_LOCK_NUM)
2046       xmodifiers |= ECORE_X_LOCK_NUM;
2047
2048    if (state & ECORE_EVENT_LOCK_CAPS)
2049       xmodifiers |= ECORE_X_LOCK_CAPS;
2050
2051    return xmodifiers;
2052 } /* _ecore_xcb_event_modifier */
2053