Tizen 2.1 base
[framework/uifw/ecore.git] / src / lib / ecore_x / xcb / ecore_xcb.c
1 #include "ecore_xcb_private.h"
2 #include <X11/Xlib-xcb.h>
3 #include <dlfcn.h>
4
5 /* local function prototypes */
6 static int _ecore_xcb_shutdown(Eina_Bool close_display);
7 static Eina_Bool _ecore_xcb_fd_handle(void *data, Ecore_Fd_Handler *hdlr __UNUSED__);
8 static Eina_Bool _ecore_xcb_fd_handle_buff(void *data, Ecore_Fd_Handler *hdlr __UNUSED__);
9 static Eina_Bool _ecore_xcb_idle_enter(void *data __UNUSED__);
10
11 /* local variables */
12 static int _ecore_xcb_init_count = 0;
13 static int _ecore_xcb_grab_count = 0;
14 static Ecore_Fd_Handler *_ecore_xcb_fd_handler = NULL;
15 static xcb_generic_event_t *_ecore_xcb_event_buffered = NULL;
16 static Ecore_Idle_Enterer *_ecore_xcb_idle_enterer = NULL;
17
18 /* external variables */
19 int _ecore_xcb_log_dom = -1;
20 Ecore_X_Display *_ecore_xcb_display = NULL;
21 Ecore_X_Connection *_ecore_xcb_conn = NULL;
22 Ecore_X_Screen *_ecore_xcb_screen = NULL;
23 Ecore_X_Atom _ecore_xcb_atoms_wm_protocol[ECORE_X_WM_PROTOCOL_NUM];
24 double _ecore_xcb_double_click_time = 0.25;
25
26 /**
27  * @defgroup Ecore_X_Init_Group X Library Init and Shutdown Functions
28  *
29  * Functions that start and shut down the Ecore X Library.
30  */
31
32 /**
33  * Initialize the X display connection to the given display.
34  *
35  * @param   name Display target name.  If @c NULL, the default display is
36  *               assumed.
37  * @return  The number of times the library has been initialized without
38  *          being shut down.  0 is returned if an error occurs.
39  * @ingroup Ecore_X_Init_Group
40  */
41 EAPI int
42 ecore_x_init(const char *name)
43 {
44    char *gl = NULL;
45    uint32_t mask, list[1];
46
47    /* check if we have initialized already */
48    if (++_ecore_xcb_init_count != 1)
49      return _ecore_xcb_init_count;
50
51    LOGFN(__FILE__, __LINE__, __FUNCTION__);
52
53    /* try to initialize eina */
54    if (!eina_init()) return --_ecore_xcb_init_count;
55
56    /* setup ecore_xcb log domain */
57    _ecore_xcb_log_dom =
58      eina_log_domain_register("ecore_x", ECORE_XCB_DEFAULT_LOG_COLOR);
59    if (_ecore_xcb_log_dom < 0)
60      {
61         EINA_LOG_ERR("Cannot create Ecore Xcb log domain");
62         eina_shutdown();
63         return --_ecore_xcb_init_count;
64      }
65
66    /* try to initialize ecore */
67    if (!ecore_init())
68      {
69         /* unregister log domain */
70          eina_log_domain_unregister(_ecore_xcb_log_dom);
71          _ecore_xcb_log_dom = -1;
72          eina_shutdown();
73          return --_ecore_xcb_init_count;
74      }
75
76    /* try to initialize ecore_event */
77    if (!ecore_event_init())
78      {
79         /* unregister log domain */
80          eina_log_domain_unregister(_ecore_xcb_log_dom);
81          _ecore_xcb_log_dom = -1;
82          ecore_shutdown();
83          eina_shutdown();
84          return --_ecore_xcb_init_count;
85      }
86
87    /* NB: XLib has XInitThreads */
88
89    /* check for env var which says we are not going to use GL @ all
90     *
91     * NB: This is done because if someone wants a 'pure' xcb implementation
92     * of ecore_x, all they need do is export this variable in the environment
93     * and ecore_x will not use xlib stuff at all.
94     *
95     * The upside is you can get pure xcb-based ecore_x (w/ all the speed), but
96     * there is a down-side here in that you cannot get OpenGL without XLib :(
97     */
98    if ((gl = getenv("ECORE_X_NO_XLIB")))
99      {
100         /* we found the env var that says 'Yes, we are not ever gonna try
101          * OpenGL so it is safe to not use XLib at all' */
102
103         /* try to connect to the display server */
104         _ecore_xcb_conn = xcb_connect(name, NULL);
105      }
106    else
107      {
108         /* env var was not specified, so we will assume that the user
109          * may want opengl @ some point. connect this way for opengl to work */
110         void *libxcb, *libxlib;
111         Display *(*_real_display)(const char *display);
112         xcb_connection_t *(*_real_connection)(Display * dpy);
113         void (*_real_queue)(Display *dpy, enum XEventQueueOwner owner);
114         int (*_real_close)(Display *dpy);
115 #ifdef EVAS_FRAME_QUEUING
116         Status (*_real_threads)(void);
117 #endif
118
119         /* want to dlopen here to avoid actual library linkage */
120         libxlib = dlopen("libX11.so", (RTLD_LAZY | RTLD_GLOBAL));
121         if (!libxlib)
122           libxlib = dlopen("libX11.so.6", (RTLD_LAZY | RTLD_GLOBAL));
123         if (!libxlib)
124           libxlib = dlopen("libX11.so.6.3.0", (RTLD_LAZY | RTLD_GLOBAL));
125         if (!libxlib)
126           {
127              ERR("Could not dlsym to libX11");
128              /* unregister log domain */
129              eina_log_domain_unregister(_ecore_xcb_log_dom);
130              _ecore_xcb_log_dom = -1;
131              ecore_event_shutdown();
132              ecore_shutdown();
133              eina_shutdown();
134              return --_ecore_xcb_init_count;
135           }
136
137         libxcb = dlopen("libX11-xcb.so", (RTLD_LAZY | RTLD_GLOBAL));
138         if (!libxcb)
139           libxcb = dlopen("libX11-xcb.so.1", (RTLD_LAZY | RTLD_GLOBAL));
140         if (!libxcb)
141           libxcb = dlopen("libX11-xcb.so.1.0.0", (RTLD_LAZY | RTLD_GLOBAL));
142         if (!libxcb)
143           {
144              ERR("Could not dlsym to libX11-xcb");
145              /* unregister log domain */
146              eina_log_domain_unregister(_ecore_xcb_log_dom);
147              _ecore_xcb_log_dom = -1;
148              ecore_event_shutdown();
149              ecore_shutdown();
150              eina_shutdown();
151              return --_ecore_xcb_init_count;
152           }
153
154         _real_display = dlsym(libxlib, "XOpenDisplay");
155         _real_close = dlsym(libxlib, "XCloseDisplay");
156         _real_connection = dlsym(libxcb, "XGetXCBConnection");
157         _real_queue = dlsym(libxcb, "XSetEventQueueOwner");
158 #ifdef EVAS_FRAME_QUEUING
159         _real_threads = dlsym(libxlib, "XInitThreads");
160 #endif
161
162         if (_real_display)
163           {
164 #ifdef EVAS_FRAME_QUEUING
165              if (_real_threads) _real_threads();
166 #endif
167              _ecore_xcb_display = _real_display(name);
168              if (!_ecore_xcb_display)
169                {
170                   ERR("Could not open Display via XLib");
171                   /* unregister log domain */
172                   eina_log_domain_unregister(_ecore_xcb_log_dom);
173                   _ecore_xcb_log_dom = -1;
174                   ecore_event_shutdown();
175                   ecore_shutdown();
176                   eina_shutdown();
177                   return --_ecore_xcb_init_count;
178                }
179              if (_real_connection)
180                _ecore_xcb_conn = _real_connection(_ecore_xcb_display);
181              if (!_ecore_xcb_conn)
182                {
183                   ERR("Could not get XCB Connection from XLib");
184
185                   if (_real_close) _real_close(_ecore_xcb_display);
186
187                   /* unregister log domain */
188                   eina_log_domain_unregister(_ecore_xcb_log_dom);
189                   _ecore_xcb_log_dom = -1;
190                   ecore_event_shutdown();
191                   ecore_shutdown();
192                   eina_shutdown();
193                   return --_ecore_xcb_init_count;
194                }
195              if (_real_queue)
196                _real_queue(_ecore_xcb_display, XCBOwnsEventQueue);
197           }
198      }
199
200    if (xcb_connection_has_error(_ecore_xcb_conn))
201      {
202         CRIT("XCB Connection has error");
203         eina_log_domain_unregister(_ecore_xcb_log_dom);
204         _ecore_xcb_log_dom = -1;
205         ecore_event_shutdown();
206         ecore_shutdown();
207         eina_shutdown();
208         return --_ecore_xcb_init_count;
209      }
210
211    /* grab the default screen */
212    _ecore_xcb_screen =
213      xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).data;
214
215    /* NB: This method of init/finalize extensions first, then atoms
216     * Does end up being 2 round trips to X, BUT if we do extensions init then
217     * atoms init first, and call the 'finalize' functions later, we end up
218     * being slower, so it's a trade-off. This current method clocks in
219     * around 0.003 for fetching atoms VS 0.010 for init both then finalize */
220
221    /* prefetch extension data */
222    _ecore_xcb_extensions_init();
223
224    /* finalize extensions */
225    _ecore_xcb_extensions_finalize();
226
227    /* set keyboard autorepeat */
228    mask = XCB_KB_AUTO_REPEAT_MODE;
229    list[0] = XCB_AUTO_REPEAT_MODE_ON;
230    xcb_change_keyboard_control(_ecore_xcb_conn, mask, list);
231
232    /* setup xcb events */
233    _ecore_xcb_events_init();
234
235    /* setup xcb keymasks */
236    _ecore_xcb_keymap_init();
237
238    /* finalize xcb keymasks */
239    _ecore_xcb_keymap_finalize();
240
241    /* setup ecore fd handler */
242    _ecore_xcb_fd_handler =
243      ecore_main_fd_handler_add(xcb_get_file_descriptor(_ecore_xcb_conn),
244                                ECORE_FD_READ, _ecore_xcb_fd_handle,
245                                _ecore_xcb_conn, _ecore_xcb_fd_handle_buff,
246                                _ecore_xcb_conn);
247
248    if (!_ecore_xcb_fd_handler)
249      return _ecore_xcb_shutdown(EINA_TRUE);
250
251    /* prefetch atoms */
252    _ecore_xcb_atoms_init();
253
254    /* finalize atoms */
255    _ecore_xcb_atoms_finalize();
256
257    /* icccm_init: dummy function */
258    ecore_x_icccm_init();
259
260    /* setup netwm */
261    ecore_x_netwm_init();
262
263    /* old e hints init: dummy function */
264    ecore_x_e_init();
265
266    _ecore_xcb_atoms_wm_protocol[ECORE_X_WM_PROTOCOL_DELETE_REQUEST] =
267      ECORE_X_ATOM_WM_DELETE_WINDOW;
268    _ecore_xcb_atoms_wm_protocol[ECORE_X_WM_PROTOCOL_TAKE_FOCUS] =
269      ECORE_X_ATOM_WM_TAKE_FOCUS;
270    _ecore_xcb_atoms_wm_protocol[ECORE_X_NET_WM_PROTOCOL_PING] =
271      ECORE_X_ATOM_NET_WM_PING;
272    _ecore_xcb_atoms_wm_protocol[ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST] =
273      ECORE_X_ATOM_NET_WM_SYNC_REQUEST;
274
275    /* setup selection */
276    _ecore_xcb_selection_init();
277
278    /* setup dnd */
279    _ecore_xcb_dnd_init();
280
281    _ecore_xcb_idle_enterer =
282      ecore_idle_enterer_add(_ecore_xcb_idle_enter, NULL);
283
284    return _ecore_xcb_init_count;
285 }
286
287 /**
288  * Shuts down the Ecore X library.
289  *
290  * In shutting down the library, the X display connection is terminated
291  * and any event handlers for it are removed.
292  *
293  * @return  The number of times the library has been initialized without
294  *          being shut down.
295  * @ingroup Ecore_X_Init_Group
296  */
297 EAPI int
298 ecore_x_shutdown(void)
299 {
300    return _ecore_xcb_shutdown(EINA_TRUE);
301 }
302
303 /**
304  * Shuts down the Ecore X library.
305  *
306  * As ecore_x_shutdown, except do not close Display, only connection.
307  *
308  * @return The number of times the library has been initialized without
309  * being shut down. 0 is returned if an error occurs.
310  * @ingroup Ecore_X_Init_Group
311  */
312 EAPI int
313 ecore_x_disconnect(void)
314 {
315    return _ecore_xcb_shutdown(EINA_FALSE);
316 }
317
318 /**
319  * @defgroup Ecore_X_Flush_Group X Synchronization Functions
320  *
321  * Functions that ensure that all commands that have been issued by the
322  * Ecore X library have been sent to the server.
323  */
324
325 /**
326  * Sends all X commands in the X Display buffer.
327  * @ingroup Ecore_X_Flush_Group
328  */
329 EAPI void
330 ecore_x_flush(void)
331 {
332 //   LOGFN(__FILE__, __LINE__, __FUNCTION__);
333
334    CHECK_XCB_CONN;
335    xcb_flush(_ecore_xcb_conn);
336 }
337
338 /**
339  * Retrieves the Ecore_X_Screen handle used for the current X connection.
340  * @return  The current default screen.
341  * @ingroup Ecore_X_Display_Attr_Group
342  */
343 EAPI Ecore_X_Screen *
344 ecore_x_default_screen_get(void)
345 {
346    LOGFN(__FILE__, __LINE__, __FUNCTION__);
347
348    return (Ecore_X_Screen *)_ecore_xcb_screen;
349 }
350
351 EAPI Ecore_X_Connection *
352 ecore_x_connection_get(void)
353 {
354    LOGFN(__FILE__, __LINE__, __FUNCTION__);
355
356    CHECK_XCB_CONN;
357    return (Ecore_X_Connection *)_ecore_xcb_conn;
358 }
359
360 /**
361  * Return the last event time
362  */
363 EAPI Ecore_X_Time
364 ecore_x_current_time_get(void)
365 {
366    return _ecore_xcb_events_last_time_get();
367 }
368
369 /**
370  * Flushes the command buffer and waits until all requests have been
371  * processed by the server.
372  * @ingroup Ecore_X_Flush_Group
373  */
374 EAPI void
375 ecore_x_sync(void)
376 {
377    LOGFN(__FILE__, __LINE__, __FUNCTION__);
378
379    CHECK_XCB_CONN;
380    free(xcb_get_input_focus_reply(_ecore_xcb_conn,
381                                   xcb_get_input_focus_unchecked(_ecore_xcb_conn),
382                                   NULL));
383 }
384
385 EAPI void
386 ecore_x_grab(void)
387 {
388    LOGFN(__FILE__, __LINE__, __FUNCTION__);
389
390    CHECK_XCB_CONN;
391    _ecore_xcb_grab_count++;
392    if (_ecore_xcb_grab_count == 1)
393      xcb_grab_server(_ecore_xcb_conn);
394 }
395
396 EAPI void
397 ecore_x_ungrab(void)
398 {
399    LOGFN(__FILE__, __LINE__, __FUNCTION__);
400
401    CHECK_XCB_CONN;
402    _ecore_xcb_grab_count--;
403    if (_ecore_xcb_grab_count < 0) _ecore_xcb_grab_count = 0;
404    if (_ecore_xcb_grab_count == 0)
405      xcb_ungrab_server(_ecore_xcb_conn);
406 }
407
408 /**
409  * Send client message with given type and format 32.
410  *
411  * @param win     The window the message is sent to.
412  * @param type    The client message type.
413  * @param mask    The mask of the message to be sent.
414  * @param d0      The client message data item 1
415  * @param d1      The client message data item 2
416  * @param d2      The client message data item 3
417  * @param d3      The client message data item 4
418  * @param d4      The client message data item 5
419  *
420  * @return @c EINA_TRUE on success @c EINA_FALSE otherwise.
421  */
422 EAPI Eina_Bool
423 ecore_x_client_message32_send(Ecore_X_Window win, Ecore_X_Atom type,
424                               Ecore_X_Event_Mask mask,
425                               long d0, long d1, long d2, long d3, long d4)
426 {
427    xcb_client_message_event_t ev;
428    xcb_void_cookie_t cookie;
429    xcb_generic_error_t *err;
430
431    LOGFN(__FILE__, __LINE__, __FUNCTION__);
432    CHECK_XCB_CONN;
433
434    memset(&ev, 0, sizeof(xcb_client_message_event_t));
435
436    ev.response_type = XCB_CLIENT_MESSAGE;
437    ev.format = 32;
438    ev.window = win;
439    ev.type = type;
440    ev.data.data32[0] = (uint32_t)d0;
441    ev.data.data32[1] = (uint32_t)d1;
442    ev.data.data32[2] = (uint32_t)d2;
443    ev.data.data32[3] = (uint32_t)d3;
444    ev.data.data32[4] = (uint32_t)d4;
445
446    cookie = xcb_send_event(_ecore_xcb_conn, 0, win, mask, (const char *)&ev);
447
448    err = xcb_request_check(_ecore_xcb_conn, cookie);
449    if (err)
450      {
451         DBG("Problem Sending Event");
452         DBG("\tType: %d", type);
453         DBG("\tWin: %d", win);
454         _ecore_xcb_error_handle(err);
455         free(err);
456         return EINA_FALSE;
457      }
458
459    return EINA_TRUE;
460 }
461
462 /**
463  * Send client message with given type and format 8.
464  *
465  * @param win     The window the message is sent to.
466  * @param type    The client message type.
467  * @param data    Data to be sent.
468  * @param len     Number of data bytes, max @c 20.
469  *
470  * @return @c EINA_TRUE on success @c EINA_FALSE otherwise.
471  */
472 EAPI Eina_Bool
473 ecore_x_client_message8_send(Ecore_X_Window win, Ecore_X_Atom type,
474                              const void *data, int len)
475 {
476    xcb_client_message_event_t ev;
477    xcb_void_cookie_t cookie;
478    xcb_generic_error_t *err;
479
480    LOGFN(__FILE__, __LINE__, __FUNCTION__);
481    CHECK_XCB_CONN;
482
483    memset(&ev, 0, sizeof(xcb_client_message_event_t));
484
485    ev.response_type = XCB_CLIENT_MESSAGE;
486    ev.format = 8;
487    ev.window = win;
488    ev.type = type;
489    if (len > 20) len = 20;
490    memcpy(ev.data.data8, data, len);
491    memset(ev.data.data8 + len, 0, 20 - len);
492
493    cookie = xcb_send_event(_ecore_xcb_conn, 0, win,
494                            XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
495
496    err = xcb_request_check(_ecore_xcb_conn, cookie);
497    if (err)
498      {
499         DBG("Problem Sending Event");
500         DBG("\tType: %d", type);
501         DBG("\tWin: %d", win);
502         _ecore_xcb_error_handle(err);
503         free(err);
504         return EINA_FALSE;
505      }
506
507    return EINA_TRUE;
508 }
509
510 EAPI Eina_Bool
511 ecore_x_mouse_down_send(Ecore_X_Window win, int x, int y, int b)
512 {
513    xcb_translate_coordinates_cookie_t cookie;
514    xcb_translate_coordinates_reply_t *reply;
515    xcb_button_press_event_t ev;
516    xcb_void_cookie_t vcookie;
517    xcb_generic_error_t *err;
518    Ecore_X_Window root = 0;
519
520    LOGFN(__FILE__, __LINE__, __FUNCTION__);
521    CHECK_XCB_CONN;
522
523    root = ecore_x_window_root_get(win);
524    cookie = xcb_translate_coordinates(_ecore_xcb_conn, win, root, x, y);
525    reply = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie, NULL);
526    if (!reply) return EINA_FALSE;
527
528    memset(&ev, 0, sizeof(xcb_button_press_event_t));
529
530    ev.response_type = XCB_BUTTON_PRESS;
531    ev.event = win;
532    ev.child = win;
533    ev.root = root;
534    ev.event_x = x;
535    ev.event_y = y;
536    ev.same_screen = 1;
537    ev.state = 1 << b;
538    ev.detail = b; // xcb uses detail for button
539    ev.root_x = reply->dst_x;
540    ev.root_y = reply->dst_y;
541    ev.time = ecore_x_current_time_get();
542    free(reply);
543
544    vcookie = xcb_send_event(_ecore_xcb_conn, 1, win,
545                             XCB_EVENT_MASK_BUTTON_PRESS, (const char *)&ev);
546
547    err = xcb_request_check(_ecore_xcb_conn, vcookie);
548    if (err)
549      {
550         _ecore_xcb_error_handle(err);
551         free(err);
552         return EINA_FALSE;
553      }
554
555    return EINA_TRUE;
556 }
557
558 EAPI Eina_Bool
559 ecore_x_mouse_up_send(Ecore_X_Window win, int x, int y, int b)
560 {
561    xcb_translate_coordinates_cookie_t cookie;
562    xcb_translate_coordinates_reply_t *reply;
563    xcb_button_release_event_t ev;
564    xcb_void_cookie_t vcookie;
565    xcb_generic_error_t *err;
566    Ecore_X_Window root = 0;
567
568    LOGFN(__FILE__, __LINE__, __FUNCTION__);
569    CHECK_XCB_CONN;
570
571    root = ecore_x_window_root_get(win);
572    cookie = xcb_translate_coordinates(_ecore_xcb_conn, win, root, x, y);
573    reply = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie, NULL);
574    if (!reply) return EINA_FALSE;
575
576    memset(&ev, 0, sizeof(xcb_button_release_event_t));
577
578    ev.response_type = XCB_BUTTON_RELEASE;
579    ev.event = win;
580    ev.child = win;
581    ev.root = root;
582    ev.event_x = x;
583    ev.event_y = y;
584    ev.same_screen = 1;
585    ev.state = 0;
586    ev.root_x = reply->dst_x;
587    ev.root_y = reply->dst_y;
588    ev.detail = b; // xcb uses detail for button
589    ev.time = ecore_x_current_time_get();
590    free(reply);
591
592    vcookie = xcb_send_event(_ecore_xcb_conn, 1, win,
593                             XCB_EVENT_MASK_BUTTON_RELEASE, (const char *)&ev);
594
595    err = xcb_request_check(_ecore_xcb_conn, vcookie);
596    if (err)
597      {
598         _ecore_xcb_error_handle(err);
599         free(err);
600         return EINA_FALSE;
601      }
602
603    return EINA_TRUE;
604 }
605
606 EAPI Eina_Bool
607 ecore_x_mouse_move_send(Ecore_X_Window win, int x, int y)
608 {
609    xcb_translate_coordinates_cookie_t cookie;
610    xcb_translate_coordinates_reply_t *reply;
611    xcb_motion_notify_event_t ev;
612    xcb_void_cookie_t vcookie;
613    xcb_generic_error_t *err;
614    Ecore_X_Window root = 0;
615
616    LOGFN(__FILE__, __LINE__, __FUNCTION__);
617    CHECK_XCB_CONN;
618
619    root = ecore_x_window_root_get(win);
620    cookie = xcb_translate_coordinates(_ecore_xcb_conn, win, root, x, y);
621    reply = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie, NULL);
622    if (!reply) return EINA_FALSE;
623
624    memset(&ev, 0, sizeof(xcb_motion_notify_event_t));
625
626    ev.response_type = XCB_MOTION_NOTIFY;
627    ev.event = win;
628    ev.child = win;
629    ev.root = root;
630    ev.event_x = x;
631    ev.event_y = y;
632    ev.same_screen = 1;
633    ev.state = 0;
634    ev.detail = 0; // xcb uses 'detail' for is_hint
635    ev.root_x = reply->dst_x;
636    ev.root_y = reply->dst_y;
637    ev.time = ecore_x_current_time_get();
638    free(reply);
639
640    vcookie = xcb_send_event(_ecore_xcb_conn, 1, win,
641                             XCB_EVENT_MASK_POINTER_MOTION, (const char *)&ev);
642
643    err = xcb_request_check(_ecore_xcb_conn, vcookie);
644    if (err)
645      {
646         _ecore_xcb_error_handle(err);
647         free(err);
648         return EINA_FALSE;
649      }
650
651    return EINA_TRUE;
652 }
653
654 EAPI Eina_Bool
655 ecore_x_mouse_in_send(Ecore_X_Window win, int x, int y)
656 {
657    xcb_translate_coordinates_cookie_t cookie;
658    xcb_translate_coordinates_reply_t *reply;
659    xcb_enter_notify_event_t ev;
660    xcb_void_cookie_t vcookie;
661    xcb_generic_error_t *err;
662    Ecore_X_Window root = 0;
663
664    LOGFN(__FILE__, __LINE__, __FUNCTION__);
665    CHECK_XCB_CONN;
666
667    root = ecore_x_window_root_get(win);
668    cookie = xcb_translate_coordinates(_ecore_xcb_conn, win, root, x, y);
669    reply = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie, NULL);
670    if (!reply) return EINA_FALSE;
671
672    memset(&ev, 0, sizeof(xcb_enter_notify_event_t));
673
674    ev.response_type = XCB_ENTER_NOTIFY;
675    ev.event = win;
676    ev.child = win;
677    ev.root = root;
678    ev.event_x = x;
679    ev.event_y = y;
680    ev.same_screen_focus = 1;
681    ev.mode = XCB_NOTIFY_MODE_NORMAL;
682    ev.detail = XCB_NOTIFY_DETAIL_NONLINEAR;
683    /* ev.focus = 0; */
684    ev.state = 0;
685    ev.root_x = reply->dst_x;
686    ev.root_y = reply->dst_y;
687    ev.time = ecore_x_current_time_get();
688    free(reply);
689
690    vcookie = xcb_send_event(_ecore_xcb_conn, 1, win,
691                             XCB_EVENT_MASK_ENTER_WINDOW, (const char *)&ev);
692
693    err = xcb_request_check(_ecore_xcb_conn, vcookie);
694    if (err)
695      {
696         _ecore_xcb_error_handle(err);
697         free(err);
698         return EINA_FALSE;
699      }
700
701    return EINA_TRUE;
702 }
703
704 EAPI Eina_Bool
705 ecore_x_mouse_out_send(Ecore_X_Window win, int x, int y)
706 {
707    xcb_translate_coordinates_cookie_t cookie;
708    xcb_translate_coordinates_reply_t *reply;
709    xcb_leave_notify_event_t ev;
710    xcb_void_cookie_t vcookie;
711    xcb_generic_error_t *err;
712    Ecore_X_Window root = 0;
713
714    LOGFN(__FILE__, __LINE__, __FUNCTION__);
715    CHECK_XCB_CONN;
716
717    root = ecore_x_window_root_get(win);
718    cookie = xcb_translate_coordinates(_ecore_xcb_conn, win, root, x, y);
719    reply = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie, NULL);
720    if (!reply) return EINA_FALSE;
721
722    memset(&ev, 0, sizeof(xcb_leave_notify_event_t));
723
724    ev.response_type = XCB_LEAVE_NOTIFY;
725    ev.event = win;
726    ev.child = win;
727    ev.root = root;
728    ev.event_x = x;
729    ev.event_y = y;
730    ev.same_screen_focus = 1;
731    ev.mode = XCB_NOTIFY_MODE_NORMAL;
732    ev.detail = XCB_NOTIFY_DETAIL_NONLINEAR;
733    /* ev.focus = 0; */
734    ev.state = 0;
735    ev.root_x = reply->dst_x;
736    ev.root_y = reply->dst_y;
737    ev.time = ecore_x_current_time_get();
738    free(reply);
739
740    vcookie = xcb_send_event(_ecore_xcb_conn, 1, win,
741                             XCB_EVENT_MASK_LEAVE_WINDOW, (const char *)&ev);
742
743    err = xcb_request_check(_ecore_xcb_conn, vcookie);
744    if (err)
745      {
746         _ecore_xcb_error_handle(err);
747         free(err);
748         return EINA_FALSE;
749      }
750
751    return EINA_TRUE;
752 }
753
754 EAPI Eina_Bool
755 ecore_x_keyboard_grab(Ecore_X_Window win)
756 {
757    xcb_grab_keyboard_cookie_t cookie;
758    xcb_grab_keyboard_reply_t *reply;
759
760    LOGFN(__FILE__, __LINE__, __FUNCTION__);
761    CHECK_XCB_CONN;
762
763    cookie =
764      xcb_grab_keyboard_unchecked(_ecore_xcb_conn, 0, win, XCB_CURRENT_TIME,
765                                  XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
766    reply = xcb_grab_keyboard_reply(_ecore_xcb_conn, cookie, NULL);
767    if (!reply) return EINA_FALSE;
768    free(reply);
769    return EINA_TRUE;
770 }
771
772 EAPI void
773 ecore_x_keyboard_ungrab(void)
774 {
775    LOGFN(__FILE__, __LINE__, __FUNCTION__);
776    CHECK_XCB_CONN;
777
778    xcb_ungrab_keyboard(_ecore_xcb_conn, XCB_CURRENT_TIME);
779 }
780
781 EAPI void
782 ecore_x_pointer_xy_get(Ecore_X_Window win, int *x, int *y)
783 {
784    xcb_query_pointer_cookie_t cookie;
785    xcb_query_pointer_reply_t *reply;
786
787 //   LOGFN(__FILE__, __LINE__, __FUNCTION__);
788    CHECK_XCB_CONN;
789
790 //   if (!win) win = ((xcb_screen_t *)_ecore_xcb_screen)->root;
791
792    if (x) *x = -1;
793    if (y) *y = -1;
794
795    cookie = xcb_query_pointer_unchecked(_ecore_xcb_conn, win);
796    reply = xcb_query_pointer_reply(_ecore_xcb_conn, cookie, NULL);
797    if (!reply) return;
798    if (x) *x = reply->win_x;
799    if (y) *y = reply->win_y;
800    free(reply);
801 }
802
803 EAPI Eina_Bool
804 ecore_x_pointer_control_set(int accel_num, int accel_denom, int threshold)
805 {
806    xcb_void_cookie_t vcookie;
807    xcb_generic_error_t *err;
808
809    LOGFN(__FILE__, __LINE__, __FUNCTION__);
810    CHECK_XCB_CONN;
811
812    vcookie =
813      xcb_change_pointer_control_checked(_ecore_xcb_conn,
814                                         accel_num, accel_denom, threshold, 
815                                         1, 1);
816    err = xcb_request_check(_ecore_xcb_conn, vcookie);
817    if (err)
818      {
819         _ecore_xcb_error_handle(err);
820         free(err);
821         return EINA_FALSE;
822      }
823
824    return EINA_TRUE;
825 }
826
827 EAPI Eina_Bool
828 ecore_x_pointer_control_get(int *accel_num, int *accel_denom, int *threshold)
829 {
830    xcb_get_pointer_control_cookie_t cookie;
831    xcb_get_pointer_control_reply_t *reply;
832
833    LOGFN(__FILE__, __LINE__, __FUNCTION__);
834    CHECK_XCB_CONN;
835
836    if (accel_num) *accel_num = 0;
837    if (accel_denom) *accel_denom = 0;
838    if (threshold) *threshold = 0;
839
840    cookie = xcb_get_pointer_control_unchecked(_ecore_xcb_conn);
841    reply = xcb_get_pointer_control_reply(_ecore_xcb_conn, cookie, NULL);
842    if (!reply) return EINA_FALSE;
843
844    if (accel_num) *accel_num = reply->acceleration_numerator;
845    if (accel_denom) *accel_denom = reply->acceleration_denominator;
846    if (threshold) *threshold = reply->threshold;
847    free(reply);
848
849    return EINA_TRUE;
850 }
851
852 EAPI Eina_Bool
853 ecore_x_pointer_mapping_set(unsigned char *map, int nmap)
854 {
855    xcb_set_pointer_mapping_cookie_t cookie;
856    xcb_set_pointer_mapping_reply_t *reply;
857    Eina_Bool ret = EINA_FALSE;
858
859    LOGFN(__FILE__, __LINE__, __FUNCTION__);
860    CHECK_XCB_CONN;
861
862    cookie = xcb_set_pointer_mapping_unchecked(_ecore_xcb_conn, nmap, map);
863    reply = xcb_set_pointer_mapping_reply(_ecore_xcb_conn, cookie, NULL);
864    if (!reply) return EINA_FALSE;
865
866    if (reply->status == XCB_MAPPING_STATUS_SUCCESS)
867      ret = EINA_TRUE;
868
869    free(reply);
870    return ret;
871 }
872
873 EAPI Eina_Bool
874 ecore_x_pointer_mapping_get(unsigned char *map, int nmap)
875 {
876    xcb_get_pointer_mapping_cookie_t cookie;
877    xcb_get_pointer_mapping_reply_t *reply;
878
879    LOGFN(__FILE__, __LINE__, __FUNCTION__);
880    CHECK_XCB_CONN;
881
882    if (map) *map = 0;
883    nmap = 0;
884
885    cookie = xcb_get_pointer_mapping_unchecked(_ecore_xcb_conn);
886    reply = xcb_get_pointer_mapping_reply(_ecore_xcb_conn, cookie, NULL);
887    if (!reply) return EINA_FALSE;
888
889    nmap = xcb_get_pointer_mapping_map_length(reply);
890    if (nmap <= 0)
891      {
892         free(reply);
893         return EINA_FALSE;
894      }
895
896    if (map)
897      {
898         uint8_t *tmp;
899         int i = 0;
900
901         tmp = xcb_get_pointer_mapping_map(reply);
902         for (i = 0; i < nmap; i++)
903           map[i] = tmp[i];
904      }
905
906    free(reply);
907    return EINA_TRUE;
908 }
909
910 EAPI Eina_Bool
911 ecore_x_pointer_grab(Ecore_X_Window win)
912 {
913    xcb_grab_pointer_cookie_t cookie;
914    xcb_grab_pointer_reply_t *reply;
915    uint16_t mask;
916    Eina_Bool ret = EINA_FALSE;
917
918    LOGFN(__FILE__, __LINE__, __FUNCTION__);
919    CHECK_XCB_CONN;
920
921    mask = (XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE |
922            XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW |
923            XCB_EVENT_MASK_POINTER_MOTION);
924
925    cookie = xcb_grab_pointer_unchecked(_ecore_xcb_conn, 0, win, mask,
926                                        XCB_GRAB_MODE_ASYNC,
927                                        XCB_GRAB_MODE_ASYNC,
928                                        XCB_NONE, XCB_NONE, XCB_CURRENT_TIME);
929    reply = xcb_grab_pointer_reply(_ecore_xcb_conn, cookie, NULL);
930    if (!reply) return EINA_FALSE;
931
932    ret = (reply->status == XCB_GRAB_STATUS_SUCCESS) ? EINA_TRUE : EINA_FALSE;
933
934    free(reply);
935    return ret;
936 }
937
938 EAPI Eina_Bool
939 ecore_x_pointer_confine_grab(Ecore_X_Window win)
940 {
941    xcb_grab_pointer_cookie_t cookie;
942    xcb_grab_pointer_reply_t *reply;
943    uint16_t mask;
944    Eina_Bool ret = EINA_FALSE;
945
946    LOGFN(__FILE__, __LINE__, __FUNCTION__);
947    CHECK_XCB_CONN;
948
949    mask = (XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE |
950            XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW |
951            XCB_EVENT_MASK_POINTER_MOTION);
952
953    cookie = xcb_grab_pointer_unchecked(_ecore_xcb_conn, 0, win, mask,
954                                        XCB_GRAB_MODE_ASYNC,
955                                        XCB_GRAB_MODE_ASYNC,
956                                        win, XCB_NONE, XCB_CURRENT_TIME);
957    reply = xcb_grab_pointer_reply(_ecore_xcb_conn, cookie, NULL);
958    if (!reply) return EINA_FALSE;
959
960    ret = (reply->status == XCB_GRAB_STATUS_SUCCESS) ? EINA_TRUE : EINA_FALSE;
961
962    free(reply);
963    return ret;
964 }
965
966 EAPI void
967 ecore_x_pointer_ungrab(void)
968 {
969    LOGFN(__FILE__, __LINE__, __FUNCTION__);
970    CHECK_XCB_CONN;
971
972    xcb_ungrab_pointer(_ecore_xcb_conn, XCB_CURRENT_TIME);
973 }
974
975 EAPI Eina_Bool
976 ecore_x_pointer_warp(Ecore_X_Window win, int x, int y)
977 {
978    xcb_void_cookie_t vcookie;
979    xcb_generic_error_t *err;
980
981    LOGFN(__FILE__, __LINE__, __FUNCTION__);
982    CHECK_XCB_CONN;
983
984    vcookie =
985      xcb_warp_pointer_checked(_ecore_xcb_conn, XCB_NONE, win, 0, 0, 0, 0, x, y);
986    err = xcb_request_check(_ecore_xcb_conn, vcookie);
987    if (err)
988      {
989         _ecore_xcb_error_handle(err);
990         free(err);
991         return EINA_FALSE;
992      }
993
994    return EINA_TRUE;
995 }
996
997 /**
998  * Invoke the standard system beep to alert users
999  *
1000  * @param percent The volume at which the bell rings. Must be in the range
1001  * [-100,+100]. If percent >= 0, the final volume will be:
1002  *       base - [(base * percent) / 100] + percent
1003  * Otherwise, it's calculated as:
1004  *       base + [(base * percent) / 100]
1005  * where @c base is the bell's base volume as set by XChangeKeyboardControl(3).
1006  *
1007  * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1008  */
1009 EAPI Eina_Bool
1010 ecore_x_bell(int percent)
1011 {
1012    xcb_void_cookie_t cookie;
1013    xcb_generic_error_t *err;
1014
1015    CHECK_XCB_CONN;
1016
1017    // FIXME: Use unchecked version after development is ironed out
1018    cookie = xcb_bell_checked(_ecore_xcb_conn, percent);
1019    err = xcb_request_check(_ecore_xcb_conn, cookie);
1020    if (err)
1021      {
1022         _ecore_xcb_error_handle(err);
1023         free(err);
1024         return EINA_FALSE;
1025      }
1026
1027    return EINA_TRUE;
1028 }
1029
1030 EAPI void
1031 ecore_x_display_size_get(Ecore_X_Display *dsp __UNUSED__, int *w, int *h)
1032 {
1033    xcb_screen_t *screen;
1034
1035    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1036    CHECK_XCB_CONN;
1037
1038    /* grab the default screen */
1039    screen = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).data;
1040    if (w) *w = screen->width_in_pixels;
1041    if (h) *h = screen->height_in_pixels;
1042 }
1043
1044 EAPI unsigned long
1045 ecore_x_display_black_pixel_get(Ecore_X_Display *dsp __UNUSED__)
1046 {
1047    xcb_screen_t *screen;
1048
1049    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1050    CHECK_XCB_CONN;
1051
1052    /* grab the default screen */
1053    screen = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).data;
1054    return screen->black_pixel;
1055 }
1056
1057 EAPI unsigned long
1058 ecore_x_display_white_pixel_get(Ecore_X_Display *dsp __UNUSED__)
1059 {
1060    xcb_screen_t *screen;
1061
1062    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1063    CHECK_XCB_CONN;
1064
1065    /* grab the default screen */
1066    screen = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).data;
1067    return screen->white_pixel;
1068 }
1069
1070 EAPI void
1071 ecore_x_pointer_last_xy_get(int *x, int *y)
1072 {
1073    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1074
1075    if (x) *x = _ecore_xcb_event_last_root_x;
1076    if (y) *y = _ecore_xcb_event_last_root_y;
1077 }
1078
1079 EAPI void
1080 ecore_x_focus_reset(void)
1081 {
1082    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1083    CHECK_XCB_CONN;
1084
1085    xcb_set_input_focus(_ecore_xcb_conn, XCB_INPUT_FOCUS_POINTER_ROOT,
1086                        ((xcb_screen_t *)_ecore_xcb_screen)->root,
1087                        XCB_CURRENT_TIME);
1088 //   ecore_x_flush();
1089 }
1090
1091 EAPI void
1092 ecore_x_events_allow_all(void)
1093 {
1094    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1095    CHECK_XCB_CONN;
1096
1097    xcb_allow_events(_ecore_xcb_conn, XCB_ALLOW_ASYNC_BOTH, XCB_CURRENT_TIME);
1098 //   ecore_x_flush();
1099 }
1100
1101 /**
1102  * Kill a specific client
1103  *
1104  * You can kill a specific client owning window @p win
1105  *
1106  * @param win Window of the client to be killed
1107  */
1108 EAPI void
1109 ecore_x_kill(Ecore_X_Window win)
1110 {
1111    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1112    CHECK_XCB_CONN;
1113
1114    xcb_kill_client(_ecore_xcb_conn, win);
1115 //   ecore_x_flush();
1116 }
1117
1118 /**
1119  * Kill all clients with subwindows under a given window.
1120  *
1121  * You can kill all clients connected to the X server by using
1122  * @ref ecore_x_window_root_list to get a list of root windows, and
1123  * then passing each root window to this function.
1124  *
1125  * @param root The window whose children will be killed.
1126  */
1127 EAPI void
1128 ecore_x_killall(Ecore_X_Window root)
1129 {
1130    int screens = 0, i = 0;
1131
1132    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1133    CHECK_XCB_CONN;
1134
1135    ecore_x_grab();
1136
1137    screens = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).rem;
1138
1139    /* Traverse window tree starting from root, and drag each
1140     * before the firing squad */
1141    for (i = 0; i < screens; ++i)
1142      {
1143         xcb_query_tree_cookie_t cookie;
1144         xcb_query_tree_reply_t *reply;
1145
1146         cookie = xcb_query_tree_unchecked(_ecore_xcb_conn, root);
1147         reply = xcb_query_tree_reply(_ecore_xcb_conn, cookie, NULL);
1148         if (reply)
1149           {
1150              xcb_window_t *wins = NULL;
1151              int tree_c_len, j = 0;
1152
1153              wins = xcb_query_tree_children(reply);
1154              tree_c_len = xcb_query_tree_children_length(reply);
1155              for (j = 0; j < tree_c_len; j++)
1156                xcb_kill_client(_ecore_xcb_conn, wins[j]);
1157              free(reply);
1158           }
1159      }
1160
1161    ecore_x_ungrab();
1162    ecore_x_sync(); // needed
1163 }
1164
1165 /**
1166  * Return the screen DPI
1167  *
1168  * This is a simplistic call to get DPI. It does not account for differing
1169  * DPI in the x amd y axes nor does it account for multihead or xinerama and
1170  * xrander where different parts of the screen may have differen DPI etc.
1171  *
1172  * @return the general screen DPI (dots/pixels per inch).
1173  */
1174 EAPI int
1175 ecore_x_dpi_get(void)
1176 {
1177    uint16_t mw = 0, w = 0;
1178
1179    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1180
1181    mw = ((xcb_screen_t *)_ecore_xcb_screen)->width_in_millimeters;
1182    if (mw <= 0) return 75;
1183    w = ((xcb_screen_t *)_ecore_xcb_screen)->width_in_pixels;
1184    return (((w * 254) / mw) + 5) / 10;
1185 }
1186
1187 /**
1188  * @defgroup Ecore_X_Display_Attr_Group X Display Attributes
1189  *
1190  * Functions that set and retrieve X display attributes.
1191  */
1192
1193 /**
1194  * Retrieves the Ecore_X_Display handle used for the current X connection.
1195  * @return  The current X display.
1196  * @ingroup Ecore_X_Display_Attr_Group
1197  */
1198 EAPI Ecore_X_Display *
1199 ecore_x_display_get(void)
1200 {
1201    char *gl = NULL;
1202
1203    CHECK_XCB_CONN;
1204
1205    /* if we have the 'dont use xlib' env var, then we are not using
1206     * XLib and thus cannot return a real XDisplay.
1207     *
1208     * NB: This may break EFL in some places and needs lots of testing !!! */
1209    if ((gl = getenv("ECORE_X_NO_XLIB")))
1210      return (Ecore_X_Display *)_ecore_xcb_conn;
1211    else /* we can safely return an XDisplay var */
1212      return (Ecore_X_Display *)_ecore_xcb_display;
1213 }
1214
1215 /**
1216  * Retrieves the X display file descriptor.
1217  * @return  The current X display file descriptor.
1218  * @ingroup Ecore_X_Display_Attr_Group
1219  */
1220 EAPI int
1221 ecore_x_fd_get(void)
1222 {
1223    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1224    CHECK_XCB_CONN;
1225    return xcb_get_file_descriptor(_ecore_xcb_conn);
1226 }
1227
1228 EAPI void
1229 ecore_x_passive_grab_replay_func_set(Eina_Bool (*func)(void *data, int type, void *event),
1230                                      void *data)
1231 {
1232    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1233
1234    _ecore_xcb_window_grab_replay_func = func;
1235    _ecore_xcb_window_grab_replay_data = data;
1236 }
1237
1238 /**
1239  * Retrieves the size of an Ecore_X_Screen.
1240  * @param screen the handle to the screen to query.
1241  * @param w where to return the width. May be NULL. Returns 0 on errors.
1242  * @param h where to return the height. May be NULL. Returns 0 on errors.
1243  * @ingroup Ecore_X_Display_Attr_Group
1244  * @see ecore_x_default_screen_get()
1245  *
1246  * @since 1.1
1247  */
1248 EAPI void
1249 ecore_x_screen_size_get(const Ecore_X_Screen *screen, int *w, int *h)
1250 {
1251    xcb_screen_t *s;
1252
1253    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1254
1255    if (w) *w = 0;
1256    if (h) *h = 0;
1257    if (!(s = (xcb_screen_t *)screen)) return;
1258    if (w) *w = s->width_in_pixels;
1259    if (h) *h = s->height_in_pixels;
1260 }
1261
1262 /**
1263  * Retrieves the count of screens.
1264  *
1265  * @return  The count of screens.
1266  * @ingroup Ecore_X_Display_Attr_Group
1267  *
1268  * @since 1.1
1269  */
1270 EAPI int
1271 ecore_x_screen_count_get(void)
1272 {
1273    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1274    CHECK_XCB_CONN;
1275
1276    return xcb_setup_roots_length(xcb_get_setup(_ecore_xcb_conn));
1277 }
1278
1279 /**
1280  * Retrieves the index number of the given screen.
1281  *
1282  * @param screen The screen for which index will be gotten.
1283  * @return  The index number of the screen.
1284  * @ingroup Ecore_X_Display_Attr_Group
1285  *
1286  * @since 1.1
1287  */
1288 EAPI int
1289 ecore_x_screen_index_get(const Ecore_X_Screen *screen)
1290 {
1291    xcb_screen_iterator_t iter;
1292    int i = 0;
1293
1294    CHECK_XCB_CONN;
1295
1296    iter =
1297      xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn));
1298    for (; iter.rem; xcb_screen_next(&iter))
1299      {
1300         if (iter.data == (xcb_screen_t *)screen)
1301           return i;
1302         i++;
1303      }
1304
1305    return 0;
1306 }
1307
1308 /**
1309  * Retrieves the screen based on index number.
1310  *
1311  * @param idx The index that will be used to retrieve the screen.
1312  * @return  The Ecore_X_Screen at this index.
1313  * @ingroup Ecore_X_Display_Attr_Group
1314  *
1315  * @since 1.1
1316  */
1317 EAPI Ecore_X_Screen *
1318 ecore_x_screen_get(int idx)
1319 {
1320    xcb_screen_iterator_t iter;
1321    int i = 0;
1322
1323    CHECK_XCB_CONN;
1324
1325    iter =
1326      xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn));
1327    for (i = 0; iter.rem; xcb_screen_next(&iter), i++)
1328      if (i == idx) return iter.data;
1329
1330    return NULL;
1331 }
1332
1333 EAPI unsigned int
1334 ecore_x_visual_id_get(Ecore_X_Visual visual)
1335 {
1336    return ((xcb_visualtype_t *)visual)->visual_id;
1337 }
1338
1339 /**
1340  * Retrieve the default Visual.
1341  *
1342  * @param disp  The Display to get the Default Visual from
1343  * @param screen The Screen.
1344  *
1345  * @return The default visual.
1346  * @since 1.1.0
1347  */
1348 EAPI Ecore_X_Visual
1349 ecore_x_default_visual_get(Ecore_X_Display *disp __UNUSED__, Ecore_X_Screen *screen)
1350 {
1351    xcb_screen_t *s;
1352    xcb_depth_iterator_t diter;
1353    xcb_visualtype_iterator_t viter;
1354
1355    CHECK_XCB_CONN;
1356
1357    s = (xcb_screen_t *)screen;
1358    diter = xcb_screen_allowed_depths_iterator(s);
1359    for (; diter.rem; xcb_depth_next(&diter))
1360      {
1361         viter = xcb_depth_visuals_iterator(diter.data);
1362         for (; viter.rem; xcb_visualtype_next(&viter))
1363           {
1364              if (viter.data->visual_id == s->root_visual)
1365                return viter.data;
1366           }
1367      }
1368    return 0;
1369 }
1370
1371 /**
1372  * Retrieve the default Colormap.
1373  *
1374  * @param disp  The Display to get the Default Colormap from
1375  * @param screen The Screen.
1376  *
1377  * @return The default colormap.
1378  * @since 1.1.0
1379  */
1380 EAPI Ecore_X_Colormap
1381 ecore_x_default_colormap_get(Ecore_X_Display *disp __UNUSED__, Ecore_X_Screen *screen)
1382 {
1383    xcb_screen_t *s;
1384
1385    s = (xcb_screen_t *)screen;
1386    return s->default_colormap;
1387 }
1388
1389 /**
1390  * Retrieve the default depth.
1391  *
1392  * @param disp  The Display to get the Default Depth from
1393  * @param screen The Screen.
1394  *
1395  * @return The default depth.
1396  * @since 1.1.0
1397  */
1398 EAPI int
1399 ecore_x_default_depth_get(Ecore_X_Display *disp __UNUSED__, Ecore_X_Screen *screen)
1400 {
1401    xcb_screen_t *s;
1402
1403    s = (xcb_screen_t *)screen;
1404    return s->root_depth;
1405 }
1406
1407 EAPI void
1408 ecore_x_xkb_select_group(int group)
1409 {
1410    // XXX: implement me */
1411 }
1412
1413 /**
1414  * Sets the timeout for a double and triple clicks to be flagged.
1415  *
1416  * This sets the time between clicks before the double_click flag is
1417  * set in a button down event. If 3 clicks occur within double this
1418  * time, the triple_click flag is also set.
1419  *
1420  * @param   t The time in seconds
1421  * @ingroup Ecore_X_Display_Attr_Group
1422  */
1423 EAPI void
1424 ecore_x_double_click_time_set(double t)
1425 {
1426    if (t < 0.0) t = 0.0;
1427    _ecore_xcb_double_click_time = t;
1428 }
1429
1430 /**
1431  * Retrieves the double and triple click flag timeout.
1432  *
1433  * See @ref ecore_x_double_click_time_set for more information.
1434  *
1435  * @return  The timeout for double clicks in seconds.
1436  * @ingroup Ecore_X_Display_Attr_Group
1437  */
1438 EAPI double
1439 ecore_x_double_click_time_get(void)
1440 {
1441    return _ecore_xcb_double_click_time;
1442 }
1443
1444 /* local function prototypes */
1445 static int
1446 _ecore_xcb_shutdown(Eina_Bool close_display)
1447 {
1448    if (--_ecore_xcb_init_count != 0)
1449      return _ecore_xcb_init_count;
1450
1451    if (!_ecore_xcb_conn)
1452      return _ecore_xcb_init_count;
1453
1454    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1455    CHECK_XCB_CONN;
1456
1457    ecore_idle_enterer_del(_ecore_xcb_idle_enterer);
1458    _ecore_xcb_idle_enterer = NULL;
1459
1460    if (_ecore_xcb_fd_handler)
1461      ecore_main_fd_handler_del(_ecore_xcb_fd_handler);
1462
1463    /* disconnect from display server */
1464    if (close_display)
1465      xcb_disconnect(_ecore_xcb_conn);
1466    else
1467      {
1468         close(xcb_get_file_descriptor(_ecore_xcb_conn));
1469         _ecore_xcb_conn = NULL;
1470      }
1471
1472    /* shutdown events */
1473    _ecore_xcb_events_shutdown();
1474
1475    /* shutdown input extension */
1476    _ecore_xcb_input_shutdown();
1477
1478    /* shutdown gesture extension */
1479    _ecore_xcb_gesture_shutdown();
1480
1481    /* shutdown selection */
1482    _ecore_xcb_selection_shutdown();
1483
1484    /* shutdown dnd */
1485    _ecore_xcb_dnd_shutdown();
1486
1487    /* shutdown netwm */
1488    ecore_x_netwm_shutdown();
1489
1490    /* shutdown keymap */
1491    _ecore_xcb_keymap_shutdown();
1492
1493    /* shutdown ecore_event */
1494    ecore_event_shutdown();
1495
1496    /* shutdown ecore */
1497    ecore_shutdown();
1498
1499    /* unregister log domain */
1500    eina_log_domain_unregister(_ecore_xcb_log_dom);
1501    _ecore_xcb_log_dom = -1;
1502
1503    /* shutdown eina */
1504    eina_shutdown();
1505
1506    return _ecore_xcb_init_count;
1507 }
1508
1509 static Eina_Bool
1510 _ecore_xcb_fd_handle(void *data, Ecore_Fd_Handler *hdlr __UNUSED__)
1511 {
1512    xcb_connection_t *conn;
1513    xcb_generic_event_t *ev = NULL;
1514
1515    conn = (xcb_connection_t *)data;
1516
1517    if (_ecore_xcb_event_buffered)
1518      {
1519         _ecore_xcb_events_handle(_ecore_xcb_event_buffered);
1520         free(_ecore_xcb_event_buffered);
1521         _ecore_xcb_event_buffered = NULL;
1522      }
1523
1524 //   xcb_flush(conn);
1525
1526    while ((ev = xcb_poll_for_event(conn)))
1527      {
1528         /* NB: Ecore Xlib uses filterevent for xim, but xcb does not support
1529          * xim, so no need for it here */
1530
1531           /* check for errors first */
1532            if (xcb_connection_has_error(conn))
1533              {
1534                 xcb_generic_error_t *err;
1535
1536                 err = (xcb_generic_error_t *)ev;
1537                 _ecore_xcb_io_error_handle(err);
1538              }
1539            else
1540              {
1541                 /* FIXME: Filter event for XIM */
1542                 _ecore_xcb_events_handle(ev);
1543                 free(ev);
1544              }
1545      }
1546
1547    return ECORE_CALLBACK_RENEW;
1548 }
1549
1550 static Eina_Bool
1551 _ecore_xcb_fd_handle_buff(void *data, Ecore_Fd_Handler *hdlr __UNUSED__)
1552 {
1553    xcb_connection_t *conn;
1554    xcb_generic_event_t *ev = NULL;
1555
1556    conn = (xcb_connection_t *)data;
1557    ev = xcb_poll_for_event(conn);
1558    if (ev)
1559      {
1560         /* check for errors first */
1561         if (xcb_connection_has_error(conn))
1562           {
1563              xcb_generic_error_t *err;
1564
1565              err = (xcb_generic_error_t *)ev;
1566              _ecore_xcb_io_error_handle(err);
1567              return ECORE_CALLBACK_CANCEL;
1568           }
1569         _ecore_xcb_event_buffered = ev;
1570         return ECORE_CALLBACK_RENEW;
1571      }
1572    return ECORE_CALLBACK_CANCEL;
1573 }
1574
1575 static Eina_Bool
1576 _ecore_xcb_idle_enter(void *data __UNUSED__)
1577 {
1578    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1579    CHECK_XCB_CONN;
1580
1581    xcb_flush(_ecore_xcb_conn);
1582    return ECORE_CALLBACK_RENEW;
1583 }