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