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 __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__);
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 /* 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;
27 * @defgroup Ecore_X_Init_Group X Library Init and Shutdown Functions
29 * Functions that start and shut down the Ecore X Library.
33 * Initialize the X display connection to the given display.
35 * @param name Display target name. If @c NULL, the default display is
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
42 ecore_x_init(const char *name)
45 uint32_t mask, list[1];
47 /* check if we have initialized already */
48 if (++_ecore_xcb_init_count != 1)
49 return _ecore_xcb_init_count;
51 LOGFN(__FILE__, __LINE__, __FUNCTION__);
53 /* try to initialize eina */
54 if (!eina_init()) return --_ecore_xcb_init_count;
56 /* setup ecore_xcb log domain */
58 eina_log_domain_register("ecore_x", ECORE_XCB_DEFAULT_LOG_COLOR);
59 if (_ecore_xcb_log_dom < 0)
61 EINA_LOG_ERR("Cannot create Ecore Xcb log domain");
63 return --_ecore_xcb_init_count;
66 /* try to initialize ecore */
69 /* unregister log domain */
70 eina_log_domain_unregister(_ecore_xcb_log_dom);
71 _ecore_xcb_log_dom = -1;
73 return --_ecore_xcb_init_count;
76 /* try to initialize ecore_event */
77 if (!ecore_event_init())
79 /* unregister log domain */
80 eina_log_domain_unregister(_ecore_xcb_log_dom);
81 _ecore_xcb_log_dom = -1;
84 return --_ecore_xcb_init_count;
87 /* NB: XLib has XInitThreads */
89 /* check for env var which says we are not going to use GL @ all
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.
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 :(
98 if ((gl = getenv("ECORE_X_NO_XLIB")))
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' */
103 /* try to connect to the display server */
104 _ecore_xcb_conn = xcb_connect(name, NULL);
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);
119 /* want to dlopen here to avoid actual library linkage */
120 libxlib = dlopen("libX11.so", (RTLD_LAZY | RTLD_GLOBAL));
122 libxlib = dlopen("libX11.so.6", (RTLD_LAZY | RTLD_GLOBAL));
124 libxlib = dlopen("libX11.so.6.3.0", (RTLD_LAZY | RTLD_GLOBAL));
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();
134 return --_ecore_xcb_init_count;
137 libxcb = dlopen("libX11-xcb.so", (RTLD_LAZY | RTLD_GLOBAL));
139 libxcb = dlopen("libX11-xcb.so.1", (RTLD_LAZY | RTLD_GLOBAL));
141 libxcb = dlopen("libX11-xcb.so.1.0.0", (RTLD_LAZY | RTLD_GLOBAL));
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();
151 return --_ecore_xcb_init_count;
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");
164 #ifdef EVAS_FRAME_QUEUING
165 if (_real_threads) _real_threads();
167 _ecore_xcb_display = _real_display(name);
168 if (!_ecore_xcb_display)
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();
177 return --_ecore_xcb_init_count;
179 if (_real_connection)
180 _ecore_xcb_conn = _real_connection(_ecore_xcb_display);
181 if (!_ecore_xcb_conn)
183 ERR("Could not get XCB Connection from XLib");
185 if (_real_close) _real_close(_ecore_xcb_display);
187 /* unregister log domain */
188 eina_log_domain_unregister(_ecore_xcb_log_dom);
189 _ecore_xcb_log_dom = -1;
190 ecore_event_shutdown();
193 return --_ecore_xcb_init_count;
196 _real_queue(_ecore_xcb_display, XCBOwnsEventQueue);
200 if (xcb_connection_has_error(_ecore_xcb_conn))
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();
208 return --_ecore_xcb_init_count;
211 /* grab the default screen */
213 xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).data;
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 */
221 /* prefetch extension data */
222 _ecore_xcb_extensions_init();
224 /* finalize extensions */
225 _ecore_xcb_extensions_finalize();
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);
232 /* setup xcb events */
233 _ecore_xcb_events_init();
235 /* setup xcb keymasks */
236 _ecore_xcb_keymap_init();
238 /* finalize xcb keymasks */
239 _ecore_xcb_keymap_finalize();
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,
248 if (!_ecore_xcb_fd_handler)
249 return _ecore_xcb_shutdown(EINA_TRUE);
252 _ecore_xcb_atoms_init();
255 _ecore_xcb_atoms_finalize();
257 /* icccm_init: dummy function */
258 ecore_x_icccm_init();
261 ecore_x_netwm_init();
263 /* old e hints init: dummy function */
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;
275 /* setup selection */
276 _ecore_xcb_selection_init();
279 _ecore_xcb_dnd_init();
281 _ecore_xcb_idle_enterer =
282 ecore_idle_enterer_add(_ecore_xcb_idle_enter, NULL);
284 return _ecore_xcb_init_count;
288 * Shuts down the Ecore X library.
290 * In shutting down the library, the X display connection is terminated
291 * and any event handlers for it are removed.
293 * @return The number of times the library has been initialized without
295 * @ingroup Ecore_X_Init_Group
298 ecore_x_shutdown(void)
300 return _ecore_xcb_shutdown(EINA_TRUE);
304 * Shuts down the Ecore X library.
306 * As ecore_x_shutdown, except do not close Display, only connection.
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
313 ecore_x_disconnect(void)
315 return _ecore_xcb_shutdown(EINA_FALSE);
319 * @defgroup Ecore_X_Flush_Group X Synchronization Functions
321 * Functions that ensure that all commands that have been issued by the
322 * Ecore X library have been sent to the server.
326 * Sends all X commands in the X Display buffer.
327 * @ingroup Ecore_X_Flush_Group
332 // LOGFN(__FILE__, __LINE__, __FUNCTION__);
335 xcb_flush(_ecore_xcb_conn);
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
343 EAPI Ecore_X_Screen *
344 ecore_x_default_screen_get(void)
346 LOGFN(__FILE__, __LINE__, __FUNCTION__);
348 return (Ecore_X_Screen *)_ecore_xcb_screen;
351 EAPI Ecore_X_Connection *
352 ecore_x_connection_get(void)
354 LOGFN(__FILE__, __LINE__, __FUNCTION__);
357 return (Ecore_X_Connection *)_ecore_xcb_conn;
361 * Return the last event time
364 ecore_x_current_time_get(void)
366 return _ecore_xcb_events_last_time_get();
370 * Flushes the command buffer and waits until all requests have been
371 * processed by the server.
372 * @ingroup Ecore_X_Flush_Group
377 LOGFN(__FILE__, __LINE__, __FUNCTION__);
380 free(xcb_get_input_focus_reply(_ecore_xcb_conn,
381 xcb_get_input_focus_unchecked(_ecore_xcb_conn),
388 LOGFN(__FILE__, __LINE__, __FUNCTION__);
391 _ecore_xcb_grab_count++;
392 if (_ecore_xcb_grab_count == 1)
393 xcb_grab_server(_ecore_xcb_conn);
399 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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);
409 * Send client message with given type and format 32.
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
420 * @return @c EINA_TRUE on success @c EINA_FALSE otherwise.
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)
427 xcb_client_message_event_t ev;
428 xcb_void_cookie_t cookie;
429 xcb_generic_error_t *err;
431 LOGFN(__FILE__, __LINE__, __FUNCTION__);
434 memset(&ev, 0, sizeof(xcb_client_message_event_t));
436 ev.response_type = XCB_CLIENT_MESSAGE;
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;
446 cookie = xcb_send_event(_ecore_xcb_conn, 0, win, mask, (const char *)&ev);
448 err = xcb_request_check(_ecore_xcb_conn, cookie);
451 DBG("Problem Sending Event");
452 DBG("\tType: %d", type);
453 DBG("\tWin: %d", win);
454 _ecore_xcb_error_handle(err);
463 * Send client message with given type and format 8.
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.
470 * @return @c EINA_TRUE on success @c EINA_FALSE otherwise.
473 ecore_x_client_message8_send(Ecore_X_Window win, Ecore_X_Atom type,
474 const void *data, int len)
476 xcb_client_message_event_t ev;
477 xcb_void_cookie_t cookie;
478 xcb_generic_error_t *err;
480 LOGFN(__FILE__, __LINE__, __FUNCTION__);
483 memset(&ev, 0, sizeof(xcb_client_message_event_t));
485 ev.response_type = XCB_CLIENT_MESSAGE;
489 if (len > 20) len = 20;
490 memcpy(ev.data.data8, data, len);
491 memset(ev.data.data8 + len, 0, 20 - len);
493 cookie = xcb_send_event(_ecore_xcb_conn, 0, win,
494 XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
496 err = xcb_request_check(_ecore_xcb_conn, cookie);
499 DBG("Problem Sending Event");
500 DBG("\tType: %d", type);
501 DBG("\tWin: %d", win);
502 _ecore_xcb_error_handle(err);
511 ecore_x_mouse_down_send(Ecore_X_Window win, int x, int y, int b)
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;
520 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
528 memset(&ev, 0, sizeof(xcb_button_press_event_t));
530 ev.response_type = XCB_BUTTON_PRESS;
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();
544 vcookie = xcb_send_event(_ecore_xcb_conn, 1, win,
545 XCB_EVENT_MASK_BUTTON_PRESS, (const char *)&ev);
547 err = xcb_request_check(_ecore_xcb_conn, vcookie);
550 _ecore_xcb_error_handle(err);
559 ecore_x_mouse_up_send(Ecore_X_Window win, int x, int y, int b)
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;
568 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
576 memset(&ev, 0, sizeof(xcb_button_release_event_t));
578 ev.response_type = XCB_BUTTON_RELEASE;
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();
592 vcookie = xcb_send_event(_ecore_xcb_conn, 1, win,
593 XCB_EVENT_MASK_BUTTON_RELEASE, (const char *)&ev);
595 err = xcb_request_check(_ecore_xcb_conn, vcookie);
598 _ecore_xcb_error_handle(err);
607 ecore_x_mouse_move_send(Ecore_X_Window win, int x, int y)
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;
616 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
624 memset(&ev, 0, sizeof(xcb_motion_notify_event_t));
626 ev.response_type = XCB_MOTION_NOTIFY;
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();
640 vcookie = xcb_send_event(_ecore_xcb_conn, 1, win,
641 XCB_EVENT_MASK_POINTER_MOTION, (const char *)&ev);
643 err = xcb_request_check(_ecore_xcb_conn, vcookie);
646 _ecore_xcb_error_handle(err);
655 ecore_x_mouse_in_send(Ecore_X_Window win, int x, int y)
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;
664 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
672 memset(&ev, 0, sizeof(xcb_enter_notify_event_t));
674 ev.response_type = XCB_ENTER_NOTIFY;
680 ev.same_screen_focus = 1;
681 ev.mode = XCB_NOTIFY_MODE_NORMAL;
682 ev.detail = XCB_NOTIFY_DETAIL_NONLINEAR;
685 ev.root_x = reply->dst_x;
686 ev.root_y = reply->dst_y;
687 ev.time = ecore_x_current_time_get();
690 vcookie = xcb_send_event(_ecore_xcb_conn, 1, win,
691 XCB_EVENT_MASK_ENTER_WINDOW, (const char *)&ev);
693 err = xcb_request_check(_ecore_xcb_conn, vcookie);
696 _ecore_xcb_error_handle(err);
705 ecore_x_mouse_out_send(Ecore_X_Window win, int x, int y)
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;
714 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
722 memset(&ev, 0, sizeof(xcb_leave_notify_event_t));
724 ev.response_type = XCB_LEAVE_NOTIFY;
730 ev.same_screen_focus = 1;
731 ev.mode = XCB_NOTIFY_MODE_NORMAL;
732 ev.detail = XCB_NOTIFY_DETAIL_NONLINEAR;
735 ev.root_x = reply->dst_x;
736 ev.root_y = reply->dst_y;
737 ev.time = ecore_x_current_time_get();
740 vcookie = xcb_send_event(_ecore_xcb_conn, 1, win,
741 XCB_EVENT_MASK_LEAVE_WINDOW, (const char *)&ev);
743 err = xcb_request_check(_ecore_xcb_conn, vcookie);
746 _ecore_xcb_error_handle(err);
755 ecore_x_keyboard_grab(Ecore_X_Window win)
757 xcb_grab_keyboard_cookie_t cookie;
758 xcb_grab_keyboard_reply_t *reply;
760 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
773 ecore_x_keyboard_ungrab(void)
775 LOGFN(__FILE__, __LINE__, __FUNCTION__);
778 xcb_ungrab_keyboard(_ecore_xcb_conn, XCB_CURRENT_TIME);
782 ecore_x_pointer_xy_get(Ecore_X_Window win, int *x, int *y)
784 xcb_query_pointer_cookie_t cookie;
785 xcb_query_pointer_reply_t *reply;
787 // LOGFN(__FILE__, __LINE__, __FUNCTION__);
790 // if (!win) win = ((xcb_screen_t *)_ecore_xcb_screen)->root;
795 cookie = xcb_query_pointer_unchecked(_ecore_xcb_conn, win);
796 reply = xcb_query_pointer_reply(_ecore_xcb_conn, cookie, NULL);
798 if (x) *x = reply->win_x;
799 if (y) *y = reply->win_y;
804 ecore_x_pointer_control_set(int accel_num, int accel_denom, int threshold)
806 xcb_void_cookie_t vcookie;
807 xcb_generic_error_t *err;
809 LOGFN(__FILE__, __LINE__, __FUNCTION__);
813 xcb_change_pointer_control_checked(_ecore_xcb_conn,
814 accel_num, accel_denom, threshold,
816 err = xcb_request_check(_ecore_xcb_conn, vcookie);
819 _ecore_xcb_error_handle(err);
828 ecore_x_pointer_control_get(int *accel_num, int *accel_denom, int *threshold)
830 xcb_get_pointer_control_cookie_t cookie;
831 xcb_get_pointer_control_reply_t *reply;
833 LOGFN(__FILE__, __LINE__, __FUNCTION__);
836 if (accel_num) *accel_num = 0;
837 if (accel_denom) *accel_denom = 0;
838 if (threshold) *threshold = 0;
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;
844 if (accel_num) *accel_num = reply->acceleration_numerator;
845 if (accel_denom) *accel_denom = reply->acceleration_denominator;
846 if (threshold) *threshold = reply->threshold;
853 ecore_x_pointer_mapping_set(unsigned char *map, int nmap)
855 xcb_set_pointer_mapping_cookie_t cookie;
856 xcb_set_pointer_mapping_reply_t *reply;
857 Eina_Bool ret = EINA_FALSE;
859 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
866 if (reply->status == XCB_MAPPING_STATUS_SUCCESS)
874 ecore_x_pointer_mapping_get(unsigned char *map, int nmap)
876 xcb_get_pointer_mapping_cookie_t cookie;
877 xcb_get_pointer_mapping_reply_t *reply;
879 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
889 nmap = xcb_get_pointer_mapping_map_length(reply);
901 tmp = xcb_get_pointer_mapping_map(reply);
902 for (i = 0; i < nmap; i++)
911 ecore_x_pointer_grab(Ecore_X_Window win)
913 xcb_grab_pointer_cookie_t cookie;
914 xcb_grab_pointer_reply_t *reply;
916 Eina_Bool ret = EINA_FALSE;
918 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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);
925 cookie = xcb_grab_pointer_unchecked(_ecore_xcb_conn, 0, win, mask,
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;
932 ret = (reply->status == XCB_GRAB_STATUS_SUCCESS) ? EINA_TRUE : EINA_FALSE;
939 ecore_x_pointer_confine_grab(Ecore_X_Window win)
941 xcb_grab_pointer_cookie_t cookie;
942 xcb_grab_pointer_reply_t *reply;
944 Eina_Bool ret = EINA_FALSE;
946 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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);
953 cookie = xcb_grab_pointer_unchecked(_ecore_xcb_conn, 0, win, mask,
956 win, XCB_NONE, XCB_CURRENT_TIME);
957 reply = xcb_grab_pointer_reply(_ecore_xcb_conn, cookie, NULL);
958 if (!reply) return EINA_FALSE;
960 ret = (reply->status == XCB_GRAB_STATUS_SUCCESS) ? EINA_TRUE : EINA_FALSE;
967 ecore_x_pointer_ungrab(void)
969 LOGFN(__FILE__, __LINE__, __FUNCTION__);
972 xcb_ungrab_pointer(_ecore_xcb_conn, XCB_CURRENT_TIME);
976 ecore_x_pointer_warp(Ecore_X_Window win, int x, int y)
978 xcb_void_cookie_t vcookie;
979 xcb_generic_error_t *err;
981 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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);
989 _ecore_xcb_error_handle(err);
998 * Invoke the standard system beep to alert users
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).
1007 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1010 ecore_x_bell(int percent)
1012 xcb_void_cookie_t cookie;
1013 xcb_generic_error_t *err;
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);
1022 _ecore_xcb_error_handle(err);
1031 ecore_x_display_size_get(Ecore_X_Display *dsp __UNUSED__, int *w, int *h)
1033 xcb_screen_t *screen;
1035 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
1045 ecore_x_display_black_pixel_get(Ecore_X_Display *dsp __UNUSED__)
1047 xcb_screen_t *screen;
1049 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1052 /* grab the default screen */
1053 screen = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).data;
1054 return screen->black_pixel;
1058 ecore_x_display_white_pixel_get(Ecore_X_Display *dsp __UNUSED__)
1060 xcb_screen_t *screen;
1062 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1065 /* grab the default screen */
1066 screen = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).data;
1067 return screen->white_pixel;
1071 ecore_x_pointer_last_xy_get(int *x, int *y)
1073 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1075 if (x) *x = _ecore_xcb_event_last_root_x;
1076 if (y) *y = _ecore_xcb_event_last_root_y;
1080 ecore_x_focus_reset(void)
1082 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1085 xcb_set_input_focus(_ecore_xcb_conn, XCB_INPUT_FOCUS_POINTER_ROOT,
1086 ((xcb_screen_t *)_ecore_xcb_screen)->root,
1092 ecore_x_events_allow_all(void)
1094 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1097 xcb_allow_events(_ecore_xcb_conn, XCB_ALLOW_ASYNC_BOTH, XCB_CURRENT_TIME);
1102 * Kill a specific client
1104 * You can kill a specific client owning window @p win
1106 * @param win Window of the client to be killed
1109 ecore_x_kill(Ecore_X_Window win)
1111 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1114 xcb_kill_client(_ecore_xcb_conn, win);
1119 * Kill all clients with subwindows under a given window.
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.
1125 * @param root The window whose children will be killed.
1128 ecore_x_killall(Ecore_X_Window root)
1130 int screens = 0, i = 0;
1132 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1137 screens = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).rem;
1139 /* Traverse window tree starting from root, and drag each
1140 * before the firing squad */
1141 for (i = 0; i < screens; ++i)
1143 xcb_query_tree_cookie_t cookie;
1144 xcb_query_tree_reply_t *reply;
1146 cookie = xcb_query_tree_unchecked(_ecore_xcb_conn, root);
1147 reply = xcb_query_tree_reply(_ecore_xcb_conn, cookie, NULL);
1150 xcb_window_t *wins = NULL;
1151 int tree_c_len, j = 0;
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]);
1162 ecore_x_sync(); // needed
1166 * Return the screen DPI
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.
1172 * @return the general screen DPI (dots/pixels per inch).
1175 ecore_x_dpi_get(void)
1177 uint16_t mw = 0, w = 0;
1179 LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
1188 * @defgroup Ecore_X_Display_Attr_Group X Display Attributes
1190 * Functions that set and retrieve X display attributes.
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
1198 EAPI Ecore_X_Display *
1199 ecore_x_display_get(void)
1205 /* if we have the 'dont use xlib' env var, then we are not using
1206 * XLib and thus cannot return a real XDisplay.
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;
1216 * Retrieves the X display file descriptor.
1217 * @return The current X display file descriptor.
1218 * @ingroup Ecore_X_Display_Attr_Group
1221 ecore_x_fd_get(void)
1223 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1225 return xcb_get_file_descriptor(_ecore_xcb_conn);
1229 ecore_x_passive_grab_replay_func_set(Eina_Bool (*func)(void *data, int type, void *event),
1232 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1234 _ecore_xcb_window_grab_replay_func = func;
1235 _ecore_xcb_window_grab_replay_data = data;
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()
1249 ecore_x_screen_size_get(const Ecore_X_Screen *screen, int *w, int *h)
1253 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1257 if (!(s = (xcb_screen_t *)screen)) return;
1258 if (w) *w = s->width_in_pixels;
1259 if (h) *h = s->height_in_pixels;
1263 * Retrieves the count of screens.
1265 * @return The count of screens.
1266 * @ingroup Ecore_X_Display_Attr_Group
1271 ecore_x_screen_count_get(void)
1273 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1276 return xcb_setup_roots_length(xcb_get_setup(_ecore_xcb_conn));
1280 * Retrieves the index number of the given screen.
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
1289 ecore_x_screen_index_get(const Ecore_X_Screen *screen)
1291 xcb_screen_iterator_t iter;
1297 xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn));
1298 for (; iter.rem; xcb_screen_next(&iter))
1300 if (iter.data == (xcb_screen_t *)screen)
1309 * Retrieves the screen based on index number.
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
1317 EAPI Ecore_X_Screen *
1318 ecore_x_screen_get(int idx)
1320 xcb_screen_iterator_t 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;
1334 ecore_x_visual_id_get(Ecore_X_Visual visual)
1336 return ((xcb_visualtype_t *)visual)->visual_id;
1340 * Retrieve the default Visual.
1342 * @param disp The Display to get the Default Visual from
1343 * @param screen The Screen.
1345 * @return The default visual.
1349 ecore_x_default_visual_get(Ecore_X_Display *disp __UNUSED__, Ecore_X_Screen *screen)
1352 xcb_depth_iterator_t diter;
1353 xcb_visualtype_iterator_t viter;
1357 s = (xcb_screen_t *)screen;
1358 diter = xcb_screen_allowed_depths_iterator(s);
1359 for (; diter.rem; xcb_depth_next(&diter))
1361 viter = xcb_depth_visuals_iterator(diter.data);
1362 for (; viter.rem; xcb_visualtype_next(&viter))
1364 if (viter.data->visual_id == s->root_visual)
1372 * Retrieve the default Colormap.
1374 * @param disp The Display to get the Default Colormap from
1375 * @param screen The Screen.
1377 * @return The default colormap.
1380 EAPI Ecore_X_Colormap
1381 ecore_x_default_colormap_get(Ecore_X_Display *disp __UNUSED__, Ecore_X_Screen *screen)
1385 s = (xcb_screen_t *)screen;
1386 return s->default_colormap;
1390 * Retrieve the default depth.
1392 * @param disp The Display to get the Default Depth from
1393 * @param screen The Screen.
1395 * @return The default depth.
1399 ecore_x_default_depth_get(Ecore_X_Display *disp __UNUSED__, Ecore_X_Screen *screen)
1403 s = (xcb_screen_t *)screen;
1404 return s->root_depth;
1408 ecore_x_xkb_select_group(int group)
1410 // XXX: implement me */
1414 * Sets the timeout for a double and triple clicks to be flagged.
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.
1420 * @param t The time in seconds
1421 * @ingroup Ecore_X_Display_Attr_Group
1424 ecore_x_double_click_time_set(double t)
1426 if (t < 0.0) t = 0.0;
1427 _ecore_xcb_double_click_time = t;
1431 * Retrieves the double and triple click flag timeout.
1433 * See @ref ecore_x_double_click_time_set for more information.
1435 * @return The timeout for double clicks in seconds.
1436 * @ingroup Ecore_X_Display_Attr_Group
1439 ecore_x_double_click_time_get(void)
1441 return _ecore_xcb_double_click_time;
1444 /* local function prototypes */
1446 _ecore_xcb_shutdown(Eina_Bool close_display)
1448 if (--_ecore_xcb_init_count != 0)
1449 return _ecore_xcb_init_count;
1451 if (!_ecore_xcb_conn)
1452 return _ecore_xcb_init_count;
1454 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1457 ecore_idle_enterer_del(_ecore_xcb_idle_enterer);
1458 _ecore_xcb_idle_enterer = NULL;
1460 if (_ecore_xcb_fd_handler)
1461 ecore_main_fd_handler_del(_ecore_xcb_fd_handler);
1463 /* disconnect from display server */
1465 xcb_disconnect(_ecore_xcb_conn);
1468 close(xcb_get_file_descriptor(_ecore_xcb_conn));
1469 _ecore_xcb_conn = NULL;
1472 /* shutdown events */
1473 _ecore_xcb_events_shutdown();
1475 /* shutdown input extension */
1476 _ecore_xcb_input_shutdown();
1478 /* shutdown gesture extension */
1479 _ecore_xcb_gesture_shutdown();
1481 /* shutdown selection */
1482 _ecore_xcb_selection_shutdown();
1485 _ecore_xcb_dnd_shutdown();
1487 /* shutdown netwm */
1488 ecore_x_netwm_shutdown();
1490 /* shutdown keymap */
1491 _ecore_xcb_keymap_shutdown();
1493 /* shutdown ecore_event */
1494 ecore_event_shutdown();
1496 /* shutdown ecore */
1499 /* unregister log domain */
1500 eina_log_domain_unregister(_ecore_xcb_log_dom);
1501 _ecore_xcb_log_dom = -1;
1506 return _ecore_xcb_init_count;
1510 _ecore_xcb_fd_handle(void *data, Ecore_Fd_Handler *hdlr __UNUSED__)
1512 xcb_connection_t *conn;
1513 xcb_generic_event_t *ev = NULL;
1515 conn = (xcb_connection_t *)data;
1517 if (_ecore_xcb_event_buffered)
1519 _ecore_xcb_events_handle(_ecore_xcb_event_buffered);
1520 free(_ecore_xcb_event_buffered);
1521 _ecore_xcb_event_buffered = NULL;
1526 while ((ev = xcb_poll_for_event(conn)))
1528 /* NB: Ecore Xlib uses filterevent for xim, but xcb does not support
1529 * xim, so no need for it here */
1531 /* check for errors first */
1532 if (xcb_connection_has_error(conn))
1534 xcb_generic_error_t *err;
1536 err = (xcb_generic_error_t *)ev;
1537 _ecore_xcb_io_error_handle(err);
1541 /* FIXME: Filter event for XIM */
1542 _ecore_xcb_events_handle(ev);
1547 return ECORE_CALLBACK_RENEW;
1551 _ecore_xcb_fd_handle_buff(void *data, Ecore_Fd_Handler *hdlr __UNUSED__)
1553 xcb_connection_t *conn;
1554 xcb_generic_event_t *ev = NULL;
1556 conn = (xcb_connection_t *)data;
1557 ev = xcb_poll_for_event(conn);
1560 /* check for errors first */
1561 if (xcb_connection_has_error(conn))
1563 xcb_generic_error_t *err;
1565 err = (xcb_generic_error_t *)ev;
1566 _ecore_xcb_io_error_handle(err);
1567 return ECORE_CALLBACK_CANCEL;
1569 _ecore_xcb_event_buffered = ev;
1570 return ECORE_CALLBACK_RENEW;
1572 return ECORE_CALLBACK_CANCEL;
1576 _ecore_xcb_idle_enter(void *data __UNUSED__)
1578 LOGFN(__FILE__, __LINE__, __FUNCTION__);
1581 xcb_flush(_ecore_xcb_conn);
1582 return ECORE_CALLBACK_RENEW;