1 #include "ecore_xcb_private.h"
2 #include <X11/Xlib-xcb.h>
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);
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;
18 static Ecore_X_Version _version = { VMAJ, VMIN, VMIC, VREV };
19 EAPI Ecore_X_Version *ecore_x_version = &_version;
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;
30 * @defgroup Ecore_X_Init_Group X Library Init and Shutdown Functions
31 * @ingroup Ecore_X_Group
33 * Functions that start and shut down the Ecore X Library.
37 _ecore_x_init(const char *name, Ecore_X_Display *display)
40 uint32_t mask, list[1];
42 /* check if we have initialized already */
43 if (++_ecore_xcb_init_count != 1)
44 return _ecore_xcb_init_count;
46 LOGFN(__FILE__, __LINE__, __FUNCTION__);
48 /* try to initialize eina */
49 if (!eina_init()) return --_ecore_xcb_init_count;
51 /* setup ecore_xcb log domain */
53 eina_log_domain_register("ecore_x", ECORE_XCB_DEFAULT_LOG_COLOR);
54 if (_ecore_xcb_log_dom < 0)
56 EINA_LOG_ERR("Cannot create Ecore Xcb log domain");
58 return --_ecore_xcb_init_count;
61 /* try to initialize ecore */
64 /* unregister log domain */
65 eina_log_domain_unregister(_ecore_xcb_log_dom);
66 _ecore_xcb_log_dom = -1;
68 return --_ecore_xcb_init_count;
71 /* try to initialize ecore_event */
72 if (!ecore_event_init())
74 /* unregister log domain */
75 eina_log_domain_unregister(_ecore_xcb_log_dom);
76 _ecore_xcb_log_dom = -1;
79 return --_ecore_xcb_init_count;
82 /* NB: XLib has XInitThreads */
84 /* check for env var which says we are not going to use GL @ all
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.
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 :(
93 if ((gl = getenv("ECORE_X_NO_XLIB")))
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' */
98 /* try to connect to the display server */
99 _ecore_xcb_conn = xcb_connect(name, NULL);
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);
114 /* want to dlopen here to avoid actual library linkage */
115 libxlib = dlopen("libX11.so", (RTLD_LAZY | RTLD_GLOBAL));
117 libxlib = dlopen("libX11.so.6", (RTLD_LAZY | RTLD_GLOBAL));
119 libxlib = dlopen("libX11.so.6.3.0", (RTLD_LAZY | RTLD_GLOBAL));
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();
129 return --_ecore_xcb_init_count;
132 libxcb = dlopen("libX11-xcb.so", (RTLD_LAZY | RTLD_GLOBAL));
134 libxcb = dlopen("libX11-xcb.so.1", (RTLD_LAZY | RTLD_GLOBAL));
136 libxcb = dlopen("libX11-xcb.so.1.0.0", (RTLD_LAZY | RTLD_GLOBAL));
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();
146 return --_ecore_xcb_init_count;
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");
159 #ifdef EVAS_FRAME_QUEUING
160 if (_real_threads) _real_threads();
162 _ecore_xcb_display = display ? display : _real_display(name);
163 if (!_ecore_xcb_display)
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();
172 return --_ecore_xcb_init_count;
174 if (_real_connection)
175 _ecore_xcb_conn = _real_connection(_ecore_xcb_display);
176 if (!_ecore_xcb_conn)
178 ERR("Could not get XCB Connection from XLib");
180 if (_real_close) _real_close(_ecore_xcb_display);
182 /* unregister log domain */
183 eina_log_domain_unregister(_ecore_xcb_log_dom);
184 _ecore_xcb_log_dom = -1;
185 ecore_event_shutdown();
188 return --_ecore_xcb_init_count;
191 _real_queue(_ecore_xcb_display, XCBOwnsEventQueue);
195 if (xcb_connection_has_error(_ecore_xcb_conn))
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();
203 return --_ecore_xcb_init_count;
206 /* grab the default screen */
208 xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).data;
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 */
216 /* prefetch extension data */
217 _ecore_xcb_extensions_init();
219 /* finalize extensions */
220 _ecore_xcb_extensions_finalize();
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);
227 /* setup xcb events */
228 _ecore_xcb_events_init();
230 /* setup xcb keymasks */
231 _ecore_xcb_keymap_init();
233 /* finalize xcb keymasks */
234 _ecore_xcb_keymap_finalize();
237 _ecore_xcb_atoms_init();
240 _ecore_xcb_atoms_finalize();
242 /* icccm_init: dummy function */
243 ecore_x_icccm_init();
246 ecore_x_netwm_init();
248 /* old e hints init: dummy function */
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;
260 /* setup selection */
261 _ecore_xcb_selection_init();
264 _ecore_xcb_dnd_init();
266 _ecore_xcb_idle_enterer =
267 ecore_idle_enterer_add(_ecore_xcb_idle_enter, NULL);
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,
276 if (!_ecore_xcb_fd_handler)
277 return _ecore_xcb_shutdown(EINA_TRUE);
279 return _ecore_xcb_init_count;
283 * Initialize the X display connection to the given display.
285 * @param name Display target name. If @c NULL, the default display is
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
292 ecore_x_init(const char *name)
294 return _ecore_x_init(name, NULL);
298 ecore_x_init_from_display(Ecore_X_Display *display)
300 EINA_SAFETY_ON_NULL_RETURN_VAL(display, 0);
301 return _ecore_x_init(NULL, display);
305 * Shuts down the Ecore X library.
307 * In shutting down the library, the X display connection is terminated
308 * and any event handlers for it are removed.
310 * @return The number of times the library has been initialized without
312 * @ingroup Ecore_X_Init_Group
315 ecore_x_shutdown(void)
317 return _ecore_xcb_shutdown(EINA_TRUE);
321 * Shuts down the Ecore X library.
323 * As ecore_x_shutdown, except do not close Display, only connection.
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
330 ecore_x_disconnect(void)
332 return _ecore_xcb_shutdown(EINA_FALSE);
336 * @defgroup Ecore_X_Flush_Group X Synchronization Functions
337 * @ingroup Ecore_X_Group
339 * Functions that ensure that all commands that have been issued by the
340 * Ecore X library have been sent to the server.
344 * Sends all X commands in the X Display buffer.
345 * @ingroup Ecore_X_Flush_Group
350 // LOGFN(__FILE__, __LINE__, __FUNCTION__);
353 xcb_flush(_ecore_xcb_conn);
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
361 EAPI Ecore_X_Screen *
362 ecore_x_default_screen_get(void)
364 LOGFN(__FILE__, __LINE__, __FUNCTION__);
366 return (Ecore_X_Screen *)_ecore_xcb_screen;
369 EAPI Ecore_X_Connection *
370 ecore_x_connection_get(void)
372 LOGFN(__FILE__, __LINE__, __FUNCTION__);
375 return (Ecore_X_Connection *)_ecore_xcb_conn;
379 * Return the last event time
382 ecore_x_current_time_get(void)
384 return _ecore_xcb_events_last_time_get();
388 * Flushes the command buffer and waits until all requests have been
389 * processed by the server.
390 * @ingroup Ecore_X_Flush_Group
395 LOGFN(__FILE__, __LINE__, __FUNCTION__);
398 free(xcb_get_input_focus_reply(_ecore_xcb_conn,
399 xcb_get_input_focus_unchecked(_ecore_xcb_conn),
406 LOGFN(__FILE__, __LINE__, __FUNCTION__);
409 _ecore_xcb_grab_count++;
410 if (_ecore_xcb_grab_count == 1)
411 xcb_grab_server(_ecore_xcb_conn);
417 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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);
427 * Send client message with given type and format 32.
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
438 * @return @c EINA_TRUE on success @c EINA_FALSE otherwise.
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)
445 xcb_client_message_event_t ev;
446 xcb_void_cookie_t cookie;
447 xcb_generic_error_t *err;
449 LOGFN(__FILE__, __LINE__, __FUNCTION__);
452 memset(&ev, 0, sizeof(xcb_client_message_event_t));
454 ev.response_type = XCB_CLIENT_MESSAGE;
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;
464 cookie = xcb_send_event(_ecore_xcb_conn, 0, win, mask, (const char *)&ev);
466 err = xcb_request_check(_ecore_xcb_conn, cookie);
469 DBG("Problem Sending Event");
470 DBG("\tType: %d", type);
471 DBG("\tWin: %d", win);
472 _ecore_xcb_error_handle(err);
481 * Send client message with given type and format 8.
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.
488 * @return @c EINA_TRUE on success @c EINA_FALSE otherwise.
491 ecore_x_client_message8_send(Ecore_X_Window win, Ecore_X_Atom type,
492 const void *data, int len)
494 xcb_client_message_event_t ev;
495 xcb_void_cookie_t cookie;
496 xcb_generic_error_t *err;
498 LOGFN(__FILE__, __LINE__, __FUNCTION__);
501 memset(&ev, 0, sizeof(xcb_client_message_event_t));
503 ev.response_type = XCB_CLIENT_MESSAGE;
510 memcpy(ev.data.data8, data, len);
512 memset(ev.data.data8 + len, 0, 20 - len);
514 cookie = xcb_send_event(_ecore_xcb_conn, 0, win,
515 XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
517 err = xcb_request_check(_ecore_xcb_conn, cookie);
520 DBG("Problem Sending Event");
521 DBG("\tType: %d", type);
522 DBG("\tWin: %d", win);
523 _ecore_xcb_error_handle(err);
532 ecore_x_mouse_down_send(Ecore_X_Window win, int x, int y, int b)
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;
541 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
549 memset(&ev, 0, sizeof(xcb_button_press_event_t));
551 ev.response_type = XCB_BUTTON_PRESS;
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();
565 vcookie = xcb_send_event(_ecore_xcb_conn, 1, win,
566 XCB_EVENT_MASK_BUTTON_PRESS, (const char *)&ev);
568 err = xcb_request_check(_ecore_xcb_conn, vcookie);
571 _ecore_xcb_error_handle(err);
580 ecore_x_mouse_up_send(Ecore_X_Window win, int x, int y, int b)
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;
589 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
597 memset(&ev, 0, sizeof(xcb_button_release_event_t));
599 ev.response_type = XCB_BUTTON_RELEASE;
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();
613 vcookie = xcb_send_event(_ecore_xcb_conn, 1, win,
614 XCB_EVENT_MASK_BUTTON_RELEASE, (const char *)&ev);
616 err = xcb_request_check(_ecore_xcb_conn, vcookie);
619 _ecore_xcb_error_handle(err);
628 ecore_x_mouse_move_send(Ecore_X_Window win, int x, int y)
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;
637 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
645 memset(&ev, 0, sizeof(xcb_motion_notify_event_t));
647 ev.response_type = XCB_MOTION_NOTIFY;
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();
661 vcookie = xcb_send_event(_ecore_xcb_conn, 1, win,
662 XCB_EVENT_MASK_POINTER_MOTION, (const char *)&ev);
664 err = xcb_request_check(_ecore_xcb_conn, vcookie);
667 _ecore_xcb_error_handle(err);
676 ecore_x_mouse_in_send(Ecore_X_Window win, int x, int y)
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;
685 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
693 memset(&ev, 0, sizeof(xcb_enter_notify_event_t));
695 ev.response_type = XCB_ENTER_NOTIFY;
701 ev.same_screen_focus = 1;
702 ev.mode = XCB_NOTIFY_MODE_NORMAL;
703 ev.detail = XCB_NOTIFY_DETAIL_NONLINEAR;
706 ev.root_x = reply->dst_x;
707 ev.root_y = reply->dst_y;
708 ev.time = ecore_x_current_time_get();
711 vcookie = xcb_send_event(_ecore_xcb_conn, 1, win,
712 XCB_EVENT_MASK_ENTER_WINDOW, (const char *)&ev);
714 err = xcb_request_check(_ecore_xcb_conn, vcookie);
717 _ecore_xcb_error_handle(err);
726 ecore_x_mouse_out_send(Ecore_X_Window win, int x, int y)
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;
735 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
743 memset(&ev, 0, sizeof(xcb_leave_notify_event_t));
745 ev.response_type = XCB_LEAVE_NOTIFY;
751 ev.same_screen_focus = 1;
752 ev.mode = XCB_NOTIFY_MODE_NORMAL;
753 ev.detail = XCB_NOTIFY_DETAIL_NONLINEAR;
756 ev.root_x = reply->dst_x;
757 ev.root_y = reply->dst_y;
758 ev.time = ecore_x_current_time_get();
761 vcookie = xcb_send_event(_ecore_xcb_conn, 1, win,
762 XCB_EVENT_MASK_LEAVE_WINDOW, (const char *)&ev);
764 err = xcb_request_check(_ecore_xcb_conn, vcookie);
767 _ecore_xcb_error_handle(err);
776 ecore_x_keyboard_grab(Ecore_X_Window win)
778 xcb_grab_keyboard_cookie_t cookie;
779 xcb_grab_keyboard_reply_t *reply;
781 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
794 ecore_x_keyboard_ungrab(void)
796 LOGFN(__FILE__, __LINE__, __FUNCTION__);
799 xcb_ungrab_keyboard(_ecore_xcb_conn, XCB_CURRENT_TIME);
803 ecore_x_pointer_xy_get(Ecore_X_Window win, int *x, int *y)
805 xcb_query_pointer_cookie_t cookie;
806 xcb_query_pointer_reply_t *reply;
808 // LOGFN(__FILE__, __LINE__, __FUNCTION__);
811 // if (!win) win = ((xcb_screen_t *)_ecore_xcb_screen)->root;
816 cookie = xcb_query_pointer_unchecked(_ecore_xcb_conn, win);
817 reply = xcb_query_pointer_reply(_ecore_xcb_conn, cookie, NULL);
819 if (x) *x = reply->win_x;
820 if (y) *y = reply->win_y;
825 ecore_x_pointer_control_set(int accel_num, int accel_denom, int threshold)
827 xcb_void_cookie_t vcookie;
828 xcb_generic_error_t *err;
830 LOGFN(__FILE__, __LINE__, __FUNCTION__);
834 xcb_change_pointer_control_checked(_ecore_xcb_conn,
835 accel_num, accel_denom, threshold,
837 err = xcb_request_check(_ecore_xcb_conn, vcookie);
840 _ecore_xcb_error_handle(err);
849 ecore_x_pointer_control_get(int *accel_num, int *accel_denom, int *threshold)
851 xcb_get_pointer_control_cookie_t cookie;
852 xcb_get_pointer_control_reply_t *reply;
854 LOGFN(__FILE__, __LINE__, __FUNCTION__);
857 if (accel_num) *accel_num = 0;
858 if (accel_denom) *accel_denom = 0;
859 if (threshold) *threshold = 0;
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;
865 if (accel_num) *accel_num = reply->acceleration_numerator;
866 if (accel_denom) *accel_denom = reply->acceleration_denominator;
867 if (threshold) *threshold = reply->threshold;
874 ecore_x_pointer_mapping_set(unsigned char *map, int nmap)
876 xcb_set_pointer_mapping_cookie_t cookie;
877 xcb_set_pointer_mapping_reply_t *reply;
878 Eina_Bool ret = EINA_FALSE;
880 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
887 if (reply->status == XCB_MAPPING_STATUS_SUCCESS)
895 ecore_x_pointer_mapping_get(unsigned char *map, int nmap)
897 xcb_get_pointer_mapping_cookie_t cookie;
898 xcb_get_pointer_mapping_reply_t *reply;
900 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
910 nmap = xcb_get_pointer_mapping_map_length(reply);
922 tmp = xcb_get_pointer_mapping_map(reply);
923 for (i = 0; i < nmap; i++)
932 ecore_x_pointer_grab(Ecore_X_Window win)
934 xcb_grab_pointer_cookie_t cookie;
935 xcb_grab_pointer_reply_t *reply;
937 Eina_Bool ret = EINA_FALSE;
939 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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);
946 cookie = xcb_grab_pointer_unchecked(_ecore_xcb_conn, 0, win, mask,
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;
953 ret = (reply->status == XCB_GRAB_STATUS_SUCCESS) ? EINA_TRUE : EINA_FALSE;
960 ecore_x_pointer_confine_grab(Ecore_X_Window win)
962 xcb_grab_pointer_cookie_t cookie;
963 xcb_grab_pointer_reply_t *reply;
965 Eina_Bool ret = EINA_FALSE;
967 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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);
974 cookie = xcb_grab_pointer_unchecked(_ecore_xcb_conn, 0, win, mask,
977 win, XCB_NONE, XCB_CURRENT_TIME);
978 reply = xcb_grab_pointer_reply(_ecore_xcb_conn, cookie, NULL);
979 if (!reply) return EINA_FALSE;
981 ret = (reply->status == XCB_GRAB_STATUS_SUCCESS) ? EINA_TRUE : EINA_FALSE;
988 ecore_x_pointer_ungrab(void)
990 LOGFN(__FILE__, __LINE__, __FUNCTION__);
993 xcb_ungrab_pointer(_ecore_xcb_conn, XCB_CURRENT_TIME);
997 ecore_x_pointer_warp(Ecore_X_Window win, int x, int y)
999 xcb_void_cookie_t vcookie;
1000 xcb_generic_error_t *err;
1002 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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);
1010 _ecore_xcb_error_handle(err);
1019 * Invoke the standard system beep to alert users
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).
1028 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1031 ecore_x_bell(int percent)
1033 xcb_void_cookie_t cookie;
1034 xcb_generic_error_t *err;
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);
1043 _ecore_xcb_error_handle(err);
1052 ecore_x_display_size_get(Ecore_X_Display *dsp EINA_UNUSED, int *w, int *h)
1054 xcb_screen_t *screen;
1056 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
1066 ecore_x_display_black_pixel_get(Ecore_X_Display *dsp EINA_UNUSED)
1068 xcb_screen_t *screen;
1070 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1073 /* grab the default screen */
1074 screen = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).data;
1075 return screen->black_pixel;
1079 ecore_x_display_white_pixel_get(Ecore_X_Display *dsp EINA_UNUSED)
1081 xcb_screen_t *screen;
1083 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1086 /* grab the default screen */
1087 screen = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).data;
1088 return screen->white_pixel;
1092 ecore_x_pointer_last_xy_get(int *x, int *y)
1094 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1096 if (x) *x = _ecore_xcb_event_last_root_x;
1097 if (y) *y = _ecore_xcb_event_last_root_y;
1101 ecore_x_focus_reset(void)
1103 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1106 xcb_set_input_focus(_ecore_xcb_conn, XCB_INPUT_FOCUS_POINTER_ROOT,
1107 ((xcb_screen_t *)_ecore_xcb_screen)->root,
1113 ecore_x_events_allow_all(void)
1115 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1118 xcb_allow_events(_ecore_xcb_conn, XCB_ALLOW_ASYNC_BOTH, XCB_CURRENT_TIME);
1123 * Kill a specific client
1125 * You can kill a specific client owning window @p win
1127 * @param win Window of the client to be killed
1130 ecore_x_kill(Ecore_X_Window win)
1132 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1135 xcb_kill_client(_ecore_xcb_conn, win);
1140 * Kill all clients with subwindows under a given window.
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.
1146 * @param root The window whose children will be killed.
1149 ecore_x_killall(Ecore_X_Window root)
1151 int screens = 0, i = 0;
1153 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1158 screens = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).rem;
1160 /* Traverse window tree starting from root, and drag each
1161 * before the firing squad */
1162 for (i = 0; i < screens; ++i)
1164 xcb_query_tree_cookie_t cookie;
1165 xcb_query_tree_reply_t *reply;
1167 cookie = xcb_query_tree_unchecked(_ecore_xcb_conn, root);
1168 reply = xcb_query_tree_reply(_ecore_xcb_conn, cookie, NULL);
1171 xcb_window_t *wins = NULL;
1172 int tree_c_len, j = 0;
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]);
1183 ecore_x_sync(); // needed
1187 * Return the screen DPI
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.
1193 * @return the general screen DPI (dots/pixels per inch).
1196 ecore_x_dpi_get(void)
1198 uint16_t mw = 0, w = 0;
1200 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
1209 * @defgroup Ecore_X_Display_Attr_Group X Display Attributes
1210 * @ingroup Ecore_X_Group
1212 * Functions that set and retrieve X display attributes.
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
1220 EAPI Ecore_X_Display *
1221 ecore_x_display_get(void)
1227 /* if we have the 'dont use xlib' env var, then we are not using
1228 * XLib and thus cannot return a real XDisplay.
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;
1238 * Retrieves the X display file descriptor.
1239 * @return The current X display file descriptor.
1240 * @ingroup Ecore_X_Display_Attr_Group
1243 ecore_x_fd_get(void)
1245 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1247 return xcb_get_file_descriptor(_ecore_xcb_conn);
1251 ecore_x_passive_grab_replay_func_set(Eina_Bool (*func)(void *data, int type, void *event),
1254 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1256 _ecore_xcb_window_grab_replay_func = func;
1257 _ecore_xcb_window_grab_replay_data = data;
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()
1271 ecore_x_screen_size_get(const Ecore_X_Screen *screen, int *w, int *h)
1275 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1279 if (!(s = (xcb_screen_t *)screen)) return;
1280 if (w) *w = s->width_in_pixels;
1281 if (h) *h = s->height_in_pixels;
1285 * Retrieves the count of screens.
1287 * @return The count of screens.
1288 * @ingroup Ecore_X_Display_Attr_Group
1293 ecore_x_screen_count_get(void)
1295 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1298 return xcb_setup_roots_length(xcb_get_setup(_ecore_xcb_conn));
1302 * Retrieves the index number of the given screen.
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
1311 ecore_x_screen_index_get(const Ecore_X_Screen *screen)
1313 xcb_screen_iterator_t iter;
1319 xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn));
1320 for (; iter.rem; xcb_screen_next(&iter))
1322 if (iter.data == (xcb_screen_t *)screen)
1331 * Retrieves the screen based on index number.
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
1339 EAPI Ecore_X_Screen *
1340 ecore_x_screen_get(int idx)
1342 xcb_screen_iterator_t 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;
1356 ecore_x_visual_id_get(Ecore_X_Visual visual)
1358 return ((xcb_visualtype_t *)visual)->visual_id;
1362 * Retrieve the default Visual.
1364 * @param disp The Display to get the Default Visual from
1365 * @param screen The Screen.
1367 * @return The default visual.
1371 ecore_x_default_visual_get(Ecore_X_Display *disp EINA_UNUSED, Ecore_X_Screen *screen)
1374 xcb_depth_iterator_t diter;
1375 xcb_visualtype_iterator_t viter;
1379 s = (xcb_screen_t *)screen;
1380 diter = xcb_screen_allowed_depths_iterator(s);
1381 for (; diter.rem; xcb_depth_next(&diter))
1383 viter = xcb_depth_visuals_iterator(diter.data);
1384 for (; viter.rem; xcb_visualtype_next(&viter))
1386 if (viter.data->visual_id == s->root_visual)
1394 * Retrieve the default Colormap.
1396 * @param disp The Display to get the Default Colormap from
1397 * @param screen The Screen.
1399 * @return The default colormap.
1402 EAPI Ecore_X_Colormap
1403 ecore_x_default_colormap_get(Ecore_X_Display *disp EINA_UNUSED, Ecore_X_Screen *screen)
1407 s = (xcb_screen_t *)screen;
1408 return s->default_colormap;
1412 * Retrieve the default depth.
1414 * @param disp The Display to get the Default Depth from
1415 * @param screen The Screen.
1417 * @return The default depth.
1421 ecore_x_default_depth_get(Ecore_X_Display *disp EINA_UNUSED, Ecore_X_Screen *screen)
1425 s = (xcb_screen_t *)screen;
1426 return s->root_depth;
1430 ecore_x_xkb_select_group(int group EINA_UNUSED)
1432 // XXX: implement me */
1436 * Sets the timeout for a double and triple clicks to be flagged.
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.
1442 * @param t The time in seconds
1443 * @ingroup Ecore_X_Display_Attr_Group
1446 ecore_x_double_click_time_set(double t)
1448 if (t < 0.0) t = 0.0;
1449 _ecore_xcb_double_click_time = t;
1453 * Retrieves the double and triple click flag timeout.
1455 * See @ref ecore_x_double_click_time_set for more information.
1457 * @return The timeout for double clicks in seconds.
1458 * @ingroup Ecore_X_Display_Attr_Group
1461 ecore_x_double_click_time_get(void)
1463 return _ecore_xcb_double_click_time;
1466 /* local function prototypes */
1468 _ecore_xcb_shutdown(Eina_Bool close_display)
1470 if (--_ecore_xcb_init_count != 0)
1471 return _ecore_xcb_init_count;
1473 if (!_ecore_xcb_conn)
1474 return _ecore_xcb_init_count;
1476 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1479 ecore_idle_enterer_del(_ecore_xcb_idle_enterer);
1480 _ecore_xcb_idle_enterer = NULL;
1482 if (_ecore_xcb_fd_handler)
1483 ecore_main_fd_handler_del(_ecore_xcb_fd_handler);
1485 /* disconnect from display server */
1487 xcb_disconnect(_ecore_xcb_conn);
1490 close(xcb_get_file_descriptor(_ecore_xcb_conn));
1491 _ecore_xcb_conn = NULL;
1494 /* shutdown events */
1495 _ecore_xcb_events_shutdown();
1497 /* shutdown input extension */
1498 _ecore_xcb_input_shutdown();
1500 /* shutdown gesture extension */
1501 _ecore_xcb_gesture_shutdown();
1503 /* shutdown selection */
1504 _ecore_xcb_selection_shutdown();
1507 _ecore_xcb_dnd_shutdown();
1509 /* shutdown netwm */
1510 ecore_x_netwm_shutdown();
1512 /* shutdown keymap */
1513 _ecore_xcb_keymap_shutdown();
1515 /* shutdown ecore_event */
1516 ecore_event_shutdown();
1518 /* shutdown ecore */
1521 /* unregister log domain */
1522 eina_log_domain_unregister(_ecore_xcb_log_dom);
1523 _ecore_xcb_log_dom = -1;
1528 return _ecore_xcb_init_count;
1532 _ecore_xcb_fd_handle(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
1534 xcb_connection_t *conn;
1535 xcb_generic_event_t *ev = NULL;
1537 conn = (xcb_connection_t *)data;
1539 if (_ecore_xcb_event_buffered)
1541 _ecore_xcb_events_handle(_ecore_xcb_event_buffered);
1542 free(_ecore_xcb_event_buffered);
1543 _ecore_xcb_event_buffered = NULL;
1548 while ((ev = xcb_poll_for_event(conn)))
1550 /* NB: Ecore Xlib uses filterevent for xim, but xcb does not support
1551 * xim, so no need for it here */
1553 /* check for errors first */
1554 if (xcb_connection_has_error(conn))
1556 xcb_generic_error_t *err;
1558 err = (xcb_generic_error_t *)ev;
1559 _ecore_xcb_io_error_handle(err);
1563 /* FIXME: Filter event for XIM */
1564 _ecore_xcb_events_handle(ev);
1569 return ECORE_CALLBACK_RENEW;
1573 _ecore_xcb_fd_handle_buff(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
1575 xcb_connection_t *conn;
1576 xcb_generic_event_t *ev = NULL;
1578 conn = (xcb_connection_t *)data;
1579 ev = xcb_poll_for_event(conn);
1582 /* check for errors first */
1583 if (xcb_connection_has_error(conn))
1585 xcb_generic_error_t *err;
1587 err = (xcb_generic_error_t *)ev;
1588 _ecore_xcb_io_error_handle(err);
1589 return ECORE_CALLBACK_CANCEL;
1591 _ecore_xcb_event_buffered = ev;
1592 return ECORE_CALLBACK_RENEW;
1594 return ECORE_CALLBACK_CANCEL;
1598 _ecore_xcb_idle_enter(void *data EINA_UNUSED)
1600 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1603 xcb_flush(_ecore_xcb_conn);
1604 return ECORE_CALLBACK_RENEW;