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