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