1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif /* ifdef HAVE_CONFIG_H */
4
5 #ifdef STDC_HEADERS
6 # include <stdlib.h>
7 # include <stddef.h>
8 #else
9 # ifdef HAVE_STDLIB_H
10 # include <stdlib.h>
11 # endif
12 #endif
13
14 #include <stdlib.h>
15 #include <string.h>
16 #include <unistd.h>
17
18 //#define LOGRT 1
19
20 #ifdef LOGRT
21 #include <dlfcn.h>
22 #endif /* ifdef LOGRT */
23
24 #include "Ecore.h"
25 #include "ecore_private.h"
26 #include "ecore_x_private.h"
27 #include "Ecore_X.h"
28 #include "Ecore_X_Atoms.h"
29 #include "Ecore_Input.h"
30
31 static Ecore_X_Version _version = { VMAJ, VMIN, VMIC, VREV };
32 EAPI Ecore_X_Version *ecore_x_version = &_version;
33
34 static Eina_Bool _ecore_x_fd_handler(void *data,
35 Ecore_Fd_Handler *fd_handler);
36 static Eina_Bool _ecore_x_fd_handler_buf(void *data,
37 Ecore_Fd_Handler *fd_handler);
38 static int _ecore_x_key_mask_get(XModifierKeymap *mod, KeySym sym);
39 static int _ecore_x_event_modifier(unsigned int state);
40
41 static Ecore_Fd_Handler *_ecore_x_fd_handler_handle = NULL;
42
43 static const int AnyXEvent = 0; /* 0 can be used as there are no event types
44 * with index 0 and 1 as they are used for
45 * errors
46 */
47
48 static int _ecore_x_event_shape_id = 0;
49 static int _ecore_x_event_screensaver_id = 0;
50 static int _ecore_x_event_sync_id = 0;
51 int _ecore_xlib_log_dom = -1;
52
53 Eina_Bool _ecore_xlib_sync = EINA_FALSE;
54
55 #ifdef ECORE_XRANDR
56 static int _ecore_x_event_randr_id = 0;
57 #endif /* ifdef ECORE_XRANDR */
58 #ifdef ECORE_XFIXES
59 static int _ecore_x_event_fixes_selection_id = 0;
60 #endif /* ifdef ECORE_XFIXES */
61 #ifdef ECORE_XDAMAGE
62 static int _ecore_x_event_damage_id = 0;
63 #endif /* ifdef ECORE_XDAMAGE */
64 #ifdef ECORE_XKB
65 static int _ecore_x_event_xkb_id = 0;
66 #endif /* ifdef ECORE_XKB */
67 static int _ecore_x_event_handlers_num = 0;
68 typedef void (*Ecore_X_Event_Handler) (XEvent *event);
69 static Ecore_X_Event_Handler *_ecore_x_event_handlers = NULL;
70
71 static int _ecore_x_init_count = 0;
72 static int _ecore_x_grab_count = 0;
73
74 Display *_ecore_x_disp = NULL;
75 double _ecore_x_double_click_time = 0.25;
76 Time _ecore_x_event_last_time = 0;
77 Window _ecore_x_event_last_win = 0;
78 int _ecore_x_event_last_root_x = 0;
79 int _ecore_x_event_last_root_y = 0;
80 Eina_Bool _ecore_x_xcursor = EINA_FALSE;
81
82 Ecore_X_Window _ecore_x_private_win = 0;
83
84 Ecore_X_Atom _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_NUM];
85
86 EAPI int ECORE_X_EVENT_ANY = 0;
87 EAPI int ECORE_X_EVENT_MOUSE_IN = 0;
88 EAPI int ECORE_X_EVENT_MOUSE_OUT = 0;
89 EAPI int ECORE_X_EVENT_WINDOW_FOCUS_IN = 0;
90 EAPI int ECORE_X_EVENT_WINDOW_FOCUS_OUT = 0;
91 EAPI int ECORE_X_EVENT_WINDOW_KEYMAP = 0;
92 EAPI int ECORE_X_EVENT_WINDOW_DAMAGE = 0;
93 EAPI int ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = 0;
94 EAPI int ECORE_X_EVENT_WINDOW_CREATE = 0;
95 EAPI int ECORE_X_EVENT_WINDOW_DESTROY = 0;
96 EAPI int ECORE_X_EVENT_WINDOW_HIDE = 0;
97 EAPI int ECORE_X_EVENT_WINDOW_SHOW = 0;
98 EAPI int ECORE_X_EVENT_WINDOW_SHOW_REQUEST = 0;
99 EAPI int ECORE_X_EVENT_WINDOW_REPARENT = 0;
100 EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE = 0;
101 EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = 0;
102 EAPI int ECORE_X_EVENT_WINDOW_GRAVITY = 0;
103 EAPI int ECORE_X_EVENT_WINDOW_RESIZE_REQUEST = 0;
104 EAPI int ECORE_X_EVENT_WINDOW_STACK = 0;
105 EAPI int ECORE_X_EVENT_WINDOW_STACK_REQUEST = 0;
106 EAPI int ECORE_X_EVENT_WINDOW_PROPERTY = 0;
107 EAPI int ECORE_X_EVENT_WINDOW_COLORMAP = 0;
108 EAPI int ECORE_X_EVENT_WINDOW_MAPPING = 0;
109 EAPI int ECORE_X_EVENT_MAPPING_CHANGE = 0;
110 EAPI int ECORE_X_EVENT_SELECTION_CLEAR = 0;
111 EAPI int ECORE_X_EVENT_SELECTION_REQUEST = 0;
112 EAPI int ECORE_X_EVENT_SELECTION_NOTIFY = 0;
113 EAPI int ECORE_X_EVENT_FIXES_SELECTION_NOTIFY = 0;
114 EAPI int ECORE_X_EVENT_CLIENT_MESSAGE = 0;
115 EAPI int ECORE_X_EVENT_WINDOW_SHAPE = 0;
116 EAPI int ECORE_X_EVENT_SCREENSAVER_NOTIFY = 0;
117 EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_FLICK;
118 EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_PAN;
119 EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_PINCHROTATION;
120 EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_TAP;
121 EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_TAPNHOLD;
122 EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_HOLD;
123 EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_GROUP;
124 EAPI int ECORE_X_EVENT_SYNC_COUNTER = 0;
125 EAPI int ECORE_X_EVENT_SYNC_ALARM = 0;
126 EAPI int ECORE_X_EVENT_SCREEN_CHANGE = 0;
127 EAPI int ECORE_X_EVENT_DAMAGE_NOTIFY = 0;
128 EAPI int ECORE_X_EVENT_RANDR_CRTC_CHANGE = 0;
129 EAPI int ECORE_X_EVENT_RANDR_OUTPUT_CHANGE = 0;
130 EAPI int ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY = 0;
131 EAPI int ECORE_X_EVENT_WINDOW_DELETE_REQUEST = 0;
132 EAPI int ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = 0;
133 EAPI int ECORE_X_EVENT_WINDOW_STATE_REQUEST = 0;
134 EAPI int ECORE_X_EVENT_FRAME_EXTENTS_REQUEST = 0;
135 EAPI int ECORE_X_EVENT_PING = 0;
136 EAPI int ECORE_X_EVENT_DESKTOP_CHANGE = 0;
137
138 EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_NEW = 0;
139 EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE = 0;
140 EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE = 0;
141
142 EAPI int ECORE_X_EVENT_XKB_STATE_NOTIFY = 0;
143 EAPI int ECORE_X_EVENT_XKB_NEWKBD_NOTIFY = 0;
144
145
146 EAPI int ECORE_X_EVENT_GENERIC = 0;
147
148 EAPI int ECORE_X_EVENT_PRESENT_CONFIGURE = 0;
149 EAPI int ECORE_X_EVENT_PRESENT_COMPLETE = 0;
150 EAPI int ECORE_X_EVENT_PRESENT_IDLE = 0;
151
152 EAPI int ECORE_X_MODIFIER_SHIFT = 0;
153 EAPI int ECORE_X_MODIFIER_CTRL = 0;
154 EAPI int ECORE_X_MODIFIER_ALT = 0;
155 EAPI int ECORE_X_MODIFIER_WIN = 0;
156 EAPI int ECORE_X_MODIFIER_ALTGR = 0;
157
158 EAPI int ECORE_X_LOCK_SCROLL = 0;
159 EAPI int ECORE_X_LOCK_NUM = 0;
160 EAPI int ECORE_X_LOCK_CAPS = 0;
161 EAPI int ECORE_X_LOCK_SHIFT = 0;
162
163 EAPI int ECORE_X_RAW_BUTTON_PRESS = 0;
164 EAPI int ECORE_X_RAW_BUTTON_RELEASE = 0;
165 EAPI int ECORE_X_RAW_MOTION = 0;
166
167 EAPI int ECORE_X_DEVICES_CHANGE = 0;
168
169 #ifdef LOGRT
170 static double t0 = 0.0;
171 static Status (*_logrt_real_reply)(Display *disp,
172 void *rep,
173 int extra,
174 Bool discard) = NULL;
175 static void
_logrt_init(void)176 _logrt_init(void)
177 {
178 void *lib;
179
180 lib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY);
181 if (!lib)
182 lib = dlopen("libX11.so.6", RTLD_GLOBAL | RTLD_LAZY);
183
184 if (!lib)
185 lib = dlopen("libX11.so.6.3", RTLD_GLOBAL | RTLD_LAZY);
186
187 if (!lib)
188 lib = dlopen("libX11.so.6.3.0", RTLD_GLOBAL | RTLD_LAZY);
189
190 _logrt_real_reply = dlsym(lib, "_XReply");
191 t0 = ecore_time_get();
192 }
193
194 Status
_XReply(Display * disp,void * rep,int extra,Bool discard)195 _XReply(Display *disp,
196 void *rep,
197 int extra,
198 Bool discard)
199 {
200 void *bt[128];
201 int i, n;
202 char **sym;
203
204 n = backtrace(bt, 128);
205 if (n > 0)
206 {
207 sym = backtrace_symbols(bt, n);
208 printf("ROUNDTRIP: %4.4f :", ecore_time_get() - t0);
209 if (sym)
210 {
211 for (i = n - 1; i > 0; i--)
212 {
213 char *fname = strchr(sym[i], '(');
214 if (fname)
215 {
216 char *tsym = alloca(strlen(fname) + 1);
217 char *end;
218 strcpy(tsym, fname + 1);
219 end = strchr(tsym, '+');
220 if (end)
221 {
222 *end = 0;
223 printf("%s", tsym);
224 }
225 else
226 printf("???");
227 }
228 else
229 printf("???");
230
231 if (i > 1)
232 printf(" > ");
233 }
234 printf("\n");
235 }
236 }
237
238 // fixme: logme
239 return _logrt_real_reply(disp, rep, extra, discard);
240 }
241
242 #endif /* ifdef LOGRT */
243
244 /* wrapper to use XkbKeycodeToKeysym when possible */
245 KeySym
_ecore_x_XKeycodeToKeysym(Display * display,KeyCode keycode,int idx)246 _ecore_x_XKeycodeToKeysym(Display *display, KeyCode keycode, int idx)
247 {
248 #ifdef ECORE_XKB
249 return XkbKeycodeToKeysym(display, keycode, 0, idx);
250 #else
251 return XKeycodeToKeysym(display, keycode, idx);
252 #endif
253 }
254
255 void
_ecore_x_modifiers_get(void)256 _ecore_x_modifiers_get(void)
257 {
258 XModifierKeymap *mod;
259 ECORE_X_MODIFIER_SHIFT = 0;
260 ECORE_X_MODIFIER_CTRL = 0;
261 ECORE_X_MODIFIER_ALT = 0;
262 ECORE_X_MODIFIER_WIN = 0;
263 ECORE_X_MODIFIER_ALTGR = 0;
264 ECORE_X_LOCK_SCROLL = 0;
265 ECORE_X_LOCK_NUM = 0;
266 ECORE_X_LOCK_CAPS = 0;
267 ECORE_X_LOCK_SHIFT = 0;
268
269 mod = XGetModifierMapping(_ecore_x_disp);
270 if ((!mod) || (mod->max_keypermod <= 0)) goto clean_up;
271
272 /* everything has these... unless its like a pda... :) */
273 ECORE_X_MODIFIER_SHIFT = _ecore_x_key_mask_get(mod, XK_Shift_L);
274 ECORE_X_MODIFIER_CTRL = _ecore_x_key_mask_get(mod, XK_Control_L);
275
276 /* apple's xdarwin has no alt!!!! */
277 ECORE_X_MODIFIER_ALT = _ecore_x_key_mask_get(mod, XK_Alt_L);
278 if (!ECORE_X_MODIFIER_ALT)
279 ECORE_X_MODIFIER_ALT = _ecore_x_key_mask_get(mod, XK_Meta_L);
280
281 if (!ECORE_X_MODIFIER_ALT)
282 ECORE_X_MODIFIER_ALT = _ecore_x_key_mask_get(mod, XK_Super_L);
283
284 /* the windows key... a valid modifier :) */
285 ECORE_X_MODIFIER_WIN = _ecore_x_key_mask_get(mod, XK_Super_L);
286 if (!ECORE_X_MODIFIER_WIN)
287 ECORE_X_MODIFIER_WIN = _ecore_x_key_mask_get(mod, XK_Meta_L);
288
289 ECORE_X_MODIFIER_ALTGR = _ecore_x_key_mask_get(mod, XK_Mode_switch);
290
291 if (ECORE_X_MODIFIER_WIN == ECORE_X_MODIFIER_ALT)
292 ECORE_X_MODIFIER_WIN = 0;
293
294 if (ECORE_X_MODIFIER_ALT == ECORE_X_MODIFIER_CTRL)
295 ECORE_X_MODIFIER_ALT = 0;
296
297 if (ECORE_X_MODIFIER_ALTGR)
298 {
299 if ((ECORE_X_MODIFIER_ALTGR == ECORE_X_MODIFIER_SHIFT) ||
300 (ECORE_X_MODIFIER_ALTGR == ECORE_X_MODIFIER_CTRL) ||
301 (ECORE_X_MODIFIER_ALTGR == ECORE_X_MODIFIER_ALT) ||
302 (ECORE_X_MODIFIER_ALTGR == ECORE_X_MODIFIER_WIN))
303 {
304 ERR("ALTGR conflicts with other modifiers. IGNORE ALTGR");
305 ECORE_X_MODIFIER_ALTGR = 0;
306 }
307 }
308
309 if (ECORE_X_MODIFIER_ALT)
310 {
311 if ((ECORE_X_MODIFIER_ALT == ECORE_X_MODIFIER_SHIFT) ||
312 (ECORE_X_MODIFIER_ALT == ECORE_X_MODIFIER_CTRL) ||
313 (ECORE_X_MODIFIER_ALT == ECORE_X_MODIFIER_WIN))
314 {
315 ERR("ALT conflicts with other modifiers. IGNORE ALT");
316 ECORE_X_MODIFIER_ALT = 0;
317 }
318 }
319
320 if (ECORE_X_MODIFIER_WIN)
321 {
322 if ((ECORE_X_MODIFIER_WIN == ECORE_X_MODIFIER_SHIFT) ||
323 (ECORE_X_MODIFIER_WIN == ECORE_X_MODIFIER_CTRL))
324 {
325 ERR("WIN conflicts with other modifiers. IGNORE WIN");
326 ECORE_X_MODIFIER_WIN = 0;
327 }
328 }
329
330 if (ECORE_X_MODIFIER_SHIFT)
331 {
332 if (ECORE_X_MODIFIER_SHIFT == ECORE_X_MODIFIER_CTRL)
333 {
334 ERR("CTRL conflicts with other modifiers. IGNORE CTRL");
335 ECORE_X_MODIFIER_CTRL = 0;
336 }
337 }
338
339 ECORE_X_LOCK_SCROLL = _ecore_x_key_mask_get(mod, XK_Scroll_Lock);
340 ECORE_X_LOCK_NUM = _ecore_x_key_mask_get(mod, XK_Num_Lock);
341 ECORE_X_LOCK_CAPS = _ecore_x_key_mask_get(mod, XK_Caps_Lock);
342 ECORE_X_LOCK_SHIFT = _ecore_x_key_mask_get(mod, XK_Shift_Lock);
343
344 clean_up:
345 if (mod)
346 {
347 if (mod->modifiermap) XFree(mod->modifiermap);
348 XFree(mod);
349 }
350 }
351
352 static Eina_Bool
_ecore_x_init1(void)353 _ecore_x_init1(void)
354 {
355 LOGFN;
356 #ifdef LOGRT
357 _logrt_init();
358 #endif /* ifdef LOGRT */
359
360 eina_init();
361 _ecore_xlib_log_dom = eina_log_domain_register
362 ("ecore_x", ECORE_XLIB_DEFAULT_LOG_COLOR);
363 if (_ecore_xlib_log_dom < 0)
364 {
365 EINA_LOG_ERR(
366 "Impossible to create a log domain for the Ecore Xlib module.");
367 return EINA_FALSE;
368 }
369
370 if (!ecore_init())
371 goto shutdown_eina;
372 if (!ecore_event_init())
373 goto shutdown_ecore;
374
375 return EINA_TRUE;
376 shutdown_ecore:
377 ecore_shutdown();
378 shutdown_eina:
379 eina_log_domain_unregister(_ecore_xlib_log_dom);
380 _ecore_xlib_log_dom = -1;
381 eina_shutdown();
382 return EINA_FALSE;
383 }
384
385 static Eina_Bool
_ecore_x_init2(void)386 _ecore_x_init2(void)
387 {
388 int shape_base = 0;
389 int shape_err_base = 0;
390 #ifdef ECORE_XSS
391 int screensaver_base = 0;
392 int screensaver_err_base = 0;
393 #endif /* ifdef ECORE_XSS */
394 int sync_base = 0;
395 int sync_err_base = 0;
396 #ifdef ECORE_XRANDR
397 int randr_base = 0;
398 int randr_err_base = 0;
399 #endif /* ifdef ECORE_XRANDR */
400 #ifdef ECORE_XFIXES
401 int fixes_base = 0;
402 int fixes_err_base = 0;
403 #endif /* ifdef ECORE_XFIXES */
404 #ifdef ECORE_XDAMAGE
405 int damage_base = 0;
406 int damage_err_base = 0;
407 #endif /* ifdef ECORE_XDAMAGE */
408 #ifdef ECORE_XKB
409 int xkb_base = 0;
410 #endif /* ifdef ECORE_XKB */
411
412 _ecore_x_error_handler_init();
413 _ecore_x_event_handlers_num = LASTEvent;
414
415 #define ECORE_X_EVENT_HANDLERS_GROW(ext_base, ext_num_events) \
416 do { \
417 if (_ecore_x_event_handlers_num < (ext_base + ext_num_events)) { \
418 _ecore_x_event_handlers_num = (ext_base + ext_num_events); } \
419 } while (0)
420
421 if (XShapeQueryExtension(_ecore_x_disp, &shape_base, &shape_err_base))
422 _ecore_x_event_shape_id = shape_base;
423
424 ECORE_X_EVENT_HANDLERS_GROW(shape_base, ShapeNumberEvents);
425
426 #ifdef ECORE_XSS
427 if (XScreenSaverQueryExtension(_ecore_x_disp, &screensaver_base,
428 &screensaver_err_base))
429 _ecore_x_event_screensaver_id = screensaver_base;
430
431 ECORE_X_EVENT_HANDLERS_GROW(screensaver_base, ScreenSaverNumberEvents);
432 #endif /* ifdef ECORE_XSS */
433
434 if (XSyncQueryExtension(_ecore_x_disp, &sync_base, &sync_err_base))
435 {
436 int major, minor;
437
438 _ecore_x_event_sync_id = sync_base;
439 if (!XSyncInitialize(_ecore_x_disp, &major, &minor))
440 _ecore_x_event_sync_id = 0;
441 }
442
443 ECORE_X_EVENT_HANDLERS_GROW(sync_base, XSyncNumberEvents);
444
445 #ifdef ECORE_XRANDR
446 if (XRRQueryExtension(_ecore_x_disp, &randr_base, &randr_err_base))
447 _ecore_x_event_randr_id = randr_base;
448
449 ECORE_X_EVENT_HANDLERS_GROW(randr_base, RRNumberEvents);
450 #endif /* ifdef ECORE_XRANDR */
451
452 #ifdef ECORE_XFIXES
453 if (XFixesQueryExtension(_ecore_x_disp, &fixes_base, &fixes_err_base))
454 _ecore_x_event_fixes_selection_id = fixes_base;
455
456 ECORE_X_EVENT_HANDLERS_GROW(fixes_base, XFixesNumberEvents);
457 #endif /* ifdef ECORE_XFIXES */
458
459 #ifdef ECORE_XDAMAGE
460 if (XDamageQueryExtension(_ecore_x_disp, &damage_base, &damage_err_base))
461 _ecore_x_event_damage_id = damage_base;
462
463 ECORE_X_EVENT_HANDLERS_GROW(damage_base, XDamageNumberEvents);
464 #endif /* ifdef ECORE_XDAMAGE */
465
466 #ifdef ECORE_XKB
467 {
468 int dummy;
469
470 if (XkbQueryExtension(_ecore_x_disp, &dummy, &xkb_base,
471 &dummy, &dummy, &dummy))
472 _ecore_x_event_xkb_id = xkb_base;
473 XkbSelectEventDetails(_ecore_x_disp, XkbUseCoreKbd, XkbStateNotify,
474 XkbAllStateComponentsMask, XkbGroupStateMask);
475 XkbSelectEventDetails(_ecore_x_disp, XkbUseCoreKbd, XkbNewKeyboardNotify,
476 XkbNewKeyboardNotifyMask, XkbNewKeyboardNotifyMask);
477 }
478 ECORE_X_EVENT_HANDLERS_GROW(xkb_base, XkbNumberEvents);
479 #endif
480
481 _ecore_x_event_handlers = calloc(_ecore_x_event_handlers_num, sizeof(Ecore_X_Event_Handler));
482 if (!_ecore_x_event_handlers)
483 goto close_display;
484
485 #ifdef ECORE_XCURSOR
486 _ecore_x_xcursor = XcursorSupportsARGB(_ecore_x_disp) ? EINA_TRUE : EINA_FALSE;
487 #endif /* ifdef ECORE_XCURSOR */
488 _ecore_x_event_handlers[AnyXEvent] = _ecore_x_event_handle_any_event;
489 _ecore_x_event_handlers[KeyPress] = _ecore_x_event_handle_key_press;
490 _ecore_x_event_handlers[KeyRelease] = _ecore_x_event_handle_key_release;
491 _ecore_x_event_handlers[ButtonPress] = _ecore_x_event_handle_button_press;
492 _ecore_x_event_handlers[ButtonRelease] = _ecore_x_event_handle_button_release;
493 _ecore_x_event_handlers[MotionNotify] = _ecore_x_event_handle_motion_notify;
494 _ecore_x_event_handlers[EnterNotify] = _ecore_x_event_handle_enter_notify;
495 _ecore_x_event_handlers[LeaveNotify] = _ecore_x_event_handle_leave_notify;
496 _ecore_x_event_handlers[FocusIn] = _ecore_x_event_handle_focus_in;
497 _ecore_x_event_handlers[FocusOut] = _ecore_x_event_handle_focus_out;
498 _ecore_x_event_handlers[KeymapNotify] = _ecore_x_event_handle_keymap_notify;
499 _ecore_x_event_handlers[Expose] = _ecore_x_event_handle_expose;
500 _ecore_x_event_handlers[GraphicsExpose] = _ecore_x_event_handle_graphics_expose;
501 _ecore_x_event_handlers[VisibilityNotify] = _ecore_x_event_handle_visibility_notify;
502 _ecore_x_event_handlers[CreateNotify] = _ecore_x_event_handle_create_notify;
503 _ecore_x_event_handlers[DestroyNotify] = _ecore_x_event_handle_destroy_notify;
504 _ecore_x_event_handlers[UnmapNotify] = _ecore_x_event_handle_unmap_notify;
505 _ecore_x_event_handlers[MapNotify] = _ecore_x_event_handle_map_notify;
506 _ecore_x_event_handlers[MapRequest] = _ecore_x_event_handle_map_request;
507 _ecore_x_event_handlers[ReparentNotify] = _ecore_x_event_handle_reparent_notify;
508 _ecore_x_event_handlers[ConfigureNotify] = _ecore_x_event_handle_configure_notify;
509 _ecore_x_event_handlers[ConfigureRequest] = _ecore_x_event_handle_configure_request;
510 _ecore_x_event_handlers[GravityNotify] = _ecore_x_event_handle_gravity_notify;
511 _ecore_x_event_handlers[ResizeRequest] = _ecore_x_event_handle_resize_request;
512 _ecore_x_event_handlers[CirculateNotify] = _ecore_x_event_handle_circulate_notify;
513 _ecore_x_event_handlers[CirculateRequest] = _ecore_x_event_handle_circulate_request;
514 _ecore_x_event_handlers[PropertyNotify] = _ecore_x_event_handle_property_notify;
515 _ecore_x_event_handlers[SelectionClear] = _ecore_x_event_handle_selection_clear;
516 _ecore_x_event_handlers[SelectionRequest] = _ecore_x_event_handle_selection_request;
517 _ecore_x_event_handlers[SelectionNotify] = _ecore_x_event_handle_selection_notify;
518 _ecore_x_event_handlers[ColormapNotify] = _ecore_x_event_handle_colormap_notify;
519 _ecore_x_event_handlers[ClientMessage] = _ecore_x_event_handle_client_message;
520 _ecore_x_event_handlers[MappingNotify] = _ecore_x_event_handle_mapping_notify;
521 #ifdef GenericEvent
522 _ecore_x_event_handlers[GenericEvent] = _ecore_x_event_handle_generic_event;
523 #endif /* ifdef GenericEvent */
524
525 if (_ecore_x_event_shape_id)
526 _ecore_x_event_handlers[_ecore_x_event_shape_id] = _ecore_x_event_handle_shape_change;
527 if (_ecore_x_event_screensaver_id)
528 _ecore_x_event_handlers[_ecore_x_event_screensaver_id] = _ecore_x_event_handle_screensaver_notify;
529 if (_ecore_x_event_sync_id)
530 {
531 _ecore_x_event_handlers[_ecore_x_event_sync_id + XSyncCounterNotify] = _ecore_x_event_handle_sync_counter;
532 _ecore_x_event_handlers[_ecore_x_event_sync_id + XSyncAlarmNotify] = _ecore_x_event_handle_sync_alarm;
533 }
534
535 #ifdef ECORE_XRANDR
536 if (_ecore_x_event_randr_id)
537 {
538 _ecore_x_event_handlers[_ecore_x_event_randr_id + RRScreenChangeNotify] = _ecore_x_event_handle_randr_change;
539 _ecore_x_event_handlers[_ecore_x_event_randr_id + RRNotify] = _ecore_x_event_handle_randr_notify;
540 }
541 #endif /* ifdef ECORE_XRANDR */
542 #ifdef ECORE_XFIXES
543 if (_ecore_x_event_fixes_selection_id)
544 _ecore_x_event_handlers[_ecore_x_event_fixes_selection_id] = _ecore_x_event_handle_fixes_selection_notify;
545
546 #endif /* ifdef ECORE_XFIXES */
547 #ifdef ECORE_XDAMAGE
548 if (_ecore_x_event_damage_id)
549 _ecore_x_event_handlers[_ecore_x_event_damage_id] = _ecore_x_event_handle_damage_notify;
550
551 #endif /* ifdef ECORE_XDAMAGE */
552 #ifdef ECORE_XKB
553 // set x autorepeat detection to on. that means instead of
554 // press-release-press-release-press-release
555 // you get
556 // press-press-press-press-press-release
557 do
558 {
559 Bool works = 0;
560 XkbSetDetectableAutoRepeat(_ecore_x_disp, 1, &works);
561 }
562 while (0);
563 if (_ecore_x_event_xkb_id)
564 _ecore_x_event_handlers[_ecore_x_event_xkb_id] = _ecore_x_event_handle_xkb;
565 #endif /* ifdef ECORE_XKB */
566
567 ECORE_X_EVENT_ANY = ecore_event_type_new();
568 ECORE_X_EVENT_MOUSE_IN = ecore_event_type_new();
569 ECORE_X_EVENT_MOUSE_OUT = ecore_event_type_new();
570 ECORE_X_EVENT_WINDOW_FOCUS_IN = ecore_event_type_new();
571 ECORE_X_EVENT_WINDOW_FOCUS_OUT = ecore_event_type_new();
572 ECORE_X_EVENT_WINDOW_KEYMAP = ecore_event_type_new();
573 ECORE_X_EVENT_WINDOW_DAMAGE = ecore_event_type_new();
574 ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = ecore_event_type_new();
575 ECORE_X_EVENT_WINDOW_CREATE = ecore_event_type_new();
576 ECORE_X_EVENT_WINDOW_DESTROY = ecore_event_type_new();
577 ECORE_X_EVENT_WINDOW_HIDE = ecore_event_type_new();
578 ECORE_X_EVENT_WINDOW_SHOW = ecore_event_type_new();
579 ECORE_X_EVENT_WINDOW_SHOW_REQUEST = ecore_event_type_new();
580 ECORE_X_EVENT_WINDOW_REPARENT = ecore_event_type_new();
581 ECORE_X_EVENT_WINDOW_CONFIGURE = ecore_event_type_new();
582 ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = ecore_event_type_new();
583 ECORE_X_EVENT_WINDOW_GRAVITY = ecore_event_type_new();
584 ECORE_X_EVENT_WINDOW_RESIZE_REQUEST = ecore_event_type_new();
585 ECORE_X_EVENT_WINDOW_STACK = ecore_event_type_new();
586 ECORE_X_EVENT_WINDOW_STACK_REQUEST = ecore_event_type_new();
587 ECORE_X_EVENT_WINDOW_PROPERTY = ecore_event_type_new();
588 ECORE_X_EVENT_WINDOW_COLORMAP = ecore_event_type_new();
589 ECORE_X_EVENT_WINDOW_MAPPING = ecore_event_type_new();
590 ECORE_X_EVENT_MAPPING_CHANGE = ecore_event_type_new();
591 ECORE_X_EVENT_SELECTION_CLEAR = ecore_event_type_new();
592 ECORE_X_EVENT_SELECTION_REQUEST = ecore_event_type_new();
593 ECORE_X_EVENT_SELECTION_NOTIFY = ecore_event_type_new();
594 ECORE_X_EVENT_CLIENT_MESSAGE = ecore_event_type_new();
595 ECORE_X_EVENT_WINDOW_SHAPE = ecore_event_type_new();
596 ECORE_X_EVENT_SCREENSAVER_NOTIFY = ecore_event_type_new();
597 ECORE_X_EVENT_GESTURE_NOTIFY_FLICK = ecore_event_type_new();
598 ECORE_X_EVENT_GESTURE_NOTIFY_PAN = ecore_event_type_new();
599 ECORE_X_EVENT_GESTURE_NOTIFY_PINCHROTATION = ecore_event_type_new();
600 ECORE_X_EVENT_GESTURE_NOTIFY_TAP = ecore_event_type_new();
601 ECORE_X_EVENT_GESTURE_NOTIFY_TAPNHOLD = ecore_event_type_new();
602 ECORE_X_EVENT_GESTURE_NOTIFY_HOLD = ecore_event_type_new();
603 ECORE_X_EVENT_GESTURE_NOTIFY_GROUP = ecore_event_type_new();
604 ECORE_X_EVENT_SYNC_COUNTER = ecore_event_type_new();
605 ECORE_X_EVENT_SYNC_ALARM = ecore_event_type_new();
606 ECORE_X_EVENT_SCREEN_CHANGE = ecore_event_type_new();
607 ECORE_X_EVENT_RANDR_CRTC_CHANGE = ecore_event_type_new();
608 ECORE_X_EVENT_RANDR_OUTPUT_CHANGE = ecore_event_type_new();
609 ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY = ecore_event_type_new();
610 ECORE_X_EVENT_DAMAGE_NOTIFY = ecore_event_type_new();
611
612 ECORE_X_EVENT_WINDOW_DELETE_REQUEST = ecore_event_type_new();
613
614 ECORE_X_EVENT_DESKTOP_CHANGE = ecore_event_type_new();
615 ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = ecore_event_type_new();
616 ECORE_X_EVENT_WINDOW_STATE_REQUEST = ecore_event_type_new();
617 ECORE_X_EVENT_FRAME_EXTENTS_REQUEST = ecore_event_type_new();
618 ECORE_X_EVENT_PING = ecore_event_type_new();
619
620 ECORE_X_EVENT_STARTUP_SEQUENCE_NEW = ecore_event_type_new();
621 ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE = ecore_event_type_new();
622 ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE = ecore_event_type_new();
623
624 ECORE_X_EVENT_XKB_STATE_NOTIFY = ecore_event_type_new();
625 ECORE_X_EVENT_XKB_NEWKBD_NOTIFY = ecore_event_type_new();
626
627 ECORE_X_EVENT_GENERIC = ecore_event_type_new();
628
629 ECORE_X_RAW_BUTTON_PRESS = ecore_event_type_new();
630 ECORE_X_RAW_BUTTON_RELEASE = ecore_event_type_new();
631 ECORE_X_RAW_MOTION = ecore_event_type_new();
632
633 ECORE_X_DEVICES_CHANGE = ecore_event_type_new();
634
635 _ecore_x_modifiers_get();
636
637 _ecore_x_atoms_init();
638
639 /* Set up the ICCCM hints */
640 ecore_x_icccm_init();
641
642 /* Set up the _NET_... hints */
643 ecore_x_netwm_init();
644
645 /* old e hints init */
646 ecore_x_e_init();
647
648 /* This is just to be anal about naming conventions */
649
650 _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_DELETE_REQUEST] =
651 ECORE_X_ATOM_WM_DELETE_WINDOW;
652 _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_TAKE_FOCUS] =
653 ECORE_X_ATOM_WM_TAKE_FOCUS;
654 _ecore_x_atoms_wm_protocols[ECORE_X_NET_WM_PROTOCOL_PING] =
655 ECORE_X_ATOM_NET_WM_PING;
656 _ecore_x_atoms_wm_protocols[ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST] =
657 ECORE_X_ATOM_NET_WM_SYNC_REQUEST;
658
659 _ecore_x_selection_data_init();
660 _ecore_x_dnd_init();
661 _ecore_x_fixes_init();
662 _ecore_x_damage_init();
663 _ecore_x_composite_init();
664 _ecore_x_present_init();
665 _ecore_x_dpms_init();
666 _ecore_x_randr_init();
667 _ecore_x_input_init();
668 _ecore_x_events_init();
669
670 _ecore_x_fd_handler_handle =
671 ecore_main_fd_handler_add(ConnectionNumber(_ecore_x_disp),
672 ECORE_FD_READ,
673 _ecore_x_fd_handler, _ecore_x_disp,
674 _ecore_x_fd_handler_buf, _ecore_x_disp);
675 if (!_ecore_x_fd_handler_handle)
676 goto free_event_handlers;
677
678 _ecore_x_private_win = ecore_x_window_override_new(0, -77, -777, 123, 456);
679 _ecore_xlib_sync = !!getenv("ECORE_X_SYNC");
680
681 return EINA_TRUE;
682
683 free_event_handlers:
684 free(_ecore_x_event_handlers);
685 _ecore_x_event_handlers = NULL;
686 close_display:
687 XCloseDisplay(_ecore_x_disp);
688 _ecore_x_fd_handler_handle = NULL;
689 _ecore_x_disp = NULL;
690 ecore_event_shutdown();
691 ecore_shutdown();
692 eina_log_domain_unregister(_ecore_xlib_log_dom);
693 _ecore_xlib_log_dom = -1;
694 eina_shutdown();
695 return EINA_FALSE;
696 }
697
698 /**
699 * @defgroup Ecore_X_Init_Group X Library Init and Shutdown Functions
700 *
701 * Functions that start and shut down the Ecore X Library.
702 */
703
704 /**
705 * Initialize the X display connection to the given display.
706 *
707 * @param name Display target name. If @c NULL, the default display is
708 * assumed.
709 * @return The number of times the library has been initialized without
710 * being shut down. 0 is returned if an error occurs.
711 * @ingroup Ecore_X_Init_Group
712 */
713 EAPI int
ecore_x_init(const char * name)714 ecore_x_init(const char *name)
715 {
716 if (++_ecore_x_init_count != 1)
717 return _ecore_x_init_count;
718
719 if (!_ecore_x_init1())
720 return --_ecore_x_init_count;
721
722 #ifdef EVAS_FRAME_QUEUING
723 XInitThreads();
724 #endif /* ifdef EVAS_FRAME_QUEUING */
725 _ecore_x_disp = XOpenDisplay((char *)name);
726 if (!_ecore_x_disp)
727 goto shutdown_ecore_event;
728 if (_ecore_x_init2())
729 return _ecore_x_init_count;
730 shutdown_ecore_event:
731 ecore_event_shutdown();
732 ecore_shutdown();
733 eina_log_domain_unregister(_ecore_xlib_log_dom);
734 _ecore_xlib_log_dom = -1;
735 eina_shutdown();
736 return --_ecore_x_init_count;
737 }
738
739 EAPI int
ecore_x_init_from_display(Ecore_X_Display * display)740 ecore_x_init_from_display(Ecore_X_Display *display)
741 {
742 EINA_SAFETY_ON_NULL_RETURN_VAL(display, 0);
743 if (++_ecore_x_init_count != 1)
744 return _ecore_x_init_count;
745
746 if (!_ecore_x_init1())
747 return --_ecore_x_init_count;
748 _ecore_x_disp = display;
749 if (_ecore_x_init2())
750 return _ecore_x_init_count;
751 ecore_event_shutdown();
752 ecore_shutdown();
753 eina_log_domain_unregister(_ecore_xlib_log_dom);
754 _ecore_xlib_log_dom = -1;
755 eina_shutdown();
756 return --_ecore_x_init_count;
757 }
758 static Eina_Bool _ecore_x_window_manage_succeeded = EINA_FALSE;
759 int
_ecore_x_shutdown(void)760 _ecore_x_shutdown(void)
761 {
762 if (!_ecore_x_disp)
763 return 0;
764
765 LOGFN;
766
767 ecore_event_type_flush(ECORE_X_EVENT_ANY,
768 ECORE_X_EVENT_MOUSE_IN,
769 ECORE_X_EVENT_MOUSE_OUT,
770 ECORE_X_EVENT_WINDOW_FOCUS_IN,
771 ECORE_X_EVENT_WINDOW_FOCUS_OUT,
772 ECORE_X_EVENT_WINDOW_KEYMAP,
773 ECORE_X_EVENT_WINDOW_DAMAGE,
774 ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE,
775 ECORE_X_EVENT_WINDOW_CREATE,
776 ECORE_X_EVENT_WINDOW_DESTROY,
777 ECORE_X_EVENT_WINDOW_HIDE,
778 ECORE_X_EVENT_WINDOW_SHOW,
779 ECORE_X_EVENT_WINDOW_SHOW_REQUEST,
780 ECORE_X_EVENT_WINDOW_REPARENT,
781 ECORE_X_EVENT_WINDOW_CONFIGURE,
782 ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST,
783 ECORE_X_EVENT_WINDOW_GRAVITY,
784 ECORE_X_EVENT_WINDOW_RESIZE_REQUEST,
785 ECORE_X_EVENT_WINDOW_STACK,
786 ECORE_X_EVENT_WINDOW_STACK_REQUEST,
787 ECORE_X_EVENT_WINDOW_PROPERTY,
788 ECORE_X_EVENT_WINDOW_COLORMAP,
789 ECORE_X_EVENT_WINDOW_MAPPING,
790 ECORE_X_EVENT_MAPPING_CHANGE,
791 ECORE_X_EVENT_SELECTION_CLEAR,
792 ECORE_X_EVENT_SELECTION_REQUEST,
793 ECORE_X_EVENT_SELECTION_NOTIFY,
794 ECORE_X_EVENT_CLIENT_MESSAGE,
795 ECORE_X_EVENT_WINDOW_SHAPE,
796 ECORE_X_EVENT_SCREENSAVER_NOTIFY,
797 ECORE_X_EVENT_GESTURE_NOTIFY_FLICK,
798 ECORE_X_EVENT_GESTURE_NOTIFY_PAN,
799 ECORE_X_EVENT_GESTURE_NOTIFY_PINCHROTATION,
800 ECORE_X_EVENT_GESTURE_NOTIFY_TAP,
801 ECORE_X_EVENT_GESTURE_NOTIFY_TAPNHOLD,
802 ECORE_X_EVENT_GESTURE_NOTIFY_HOLD,
803 ECORE_X_EVENT_GESTURE_NOTIFY_GROUP,
804 ECORE_X_EVENT_SYNC_COUNTER,
805 ECORE_X_EVENT_SYNC_ALARM,
806 ECORE_X_EVENT_SCREEN_CHANGE,
807 ECORE_X_EVENT_RANDR_CRTC_CHANGE,
808 ECORE_X_EVENT_RANDR_OUTPUT_CHANGE,
809 ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY,
810 ECORE_X_EVENT_DAMAGE_NOTIFY,
811 ECORE_X_EVENT_WINDOW_DELETE_REQUEST,
812 ECORE_X_EVENT_DESKTOP_CHANGE,
813 ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST,
814 ECORE_X_EVENT_WINDOW_STATE_REQUEST,
815 ECORE_X_EVENT_FRAME_EXTENTS_REQUEST,
816 ECORE_X_EVENT_PING,
817 ECORE_X_EVENT_STARTUP_SEQUENCE_NEW,
818 ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE,
819 ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE,
820 ECORE_X_EVENT_XKB_STATE_NOTIFY,
821 ECORE_X_EVENT_XKB_NEWKBD_NOTIFY,
822 ECORE_X_EVENT_GENERIC,
823 ECORE_X_RAW_BUTTON_PRESS,
824 ECORE_X_RAW_BUTTON_RELEASE,
825 ECORE_X_RAW_MOTION,
826 ECORE_X_EVENT_PRESENT_CONFIGURE,
827 ECORE_X_EVENT_PRESENT_COMPLETE,
828 ECORE_X_EVENT_PRESENT_IDLE);
829 ecore_main_fd_handler_del(_ecore_x_fd_handler_handle);
830
831 free(_ecore_x_event_handlers);
832 _ecore_x_fd_handler_handle = NULL;
833 _ecore_x_event_handlers = NULL;
834 _ecore_x_window_manage_succeeded = EINA_FALSE;
835 _ecore_x_events_shutdown();
836 _ecore_x_input_shutdown();
837 _ecore_x_selection_shutdown();
838 _ecore_x_dnd_shutdown();
839 ecore_x_netwm_shutdown();
840
841 return 0;
842 }
843
844 static void
_ecore_x_shutdown2(void)845 _ecore_x_shutdown2(void)
846 {
847 ecore_event_shutdown();
848 ecore_shutdown();
849
850 eina_log_domain_unregister(_ecore_xlib_log_dom);
851 _ecore_xlib_log_dom = -1;
852 eina_shutdown();
853 _ecore_xlib_sync = EINA_FALSE;
854 }
855
856 /**
857 * Shuts down the Ecore X library.
858 *
859 * In shutting down the library, the X display connection is terminated
860 * and any event handlers for it are removed.
861 *
862 * @return The number of times the library has been initialized without
863 * being shut down. 0 is returned if an error occurs.
864 * @ingroup Ecore_X_Init_Group
865 */
866 EAPI int
ecore_x_shutdown(void)867 ecore_x_shutdown(void)
868 {
869 if (!_ecore_x_init_count)
870 {
871 CRI("Calling ecore_x_shutdown without init! BUG!");
872 return 0;
873 }
874 if (--_ecore_x_init_count != 0)
875 return _ecore_x_init_count;
876 if (_ecore_x_shutdown()) return _ecore_x_init_count;
877 if (_ecore_x_disp)
878 XCloseDisplay(_ecore_x_disp);
879 _ecore_x_disp = NULL;
880 _ecore_x_shutdown2();
881 return 0;
882 }
883
884 /**
885 * Shuts down the Ecore X library.
886 *
887 * As ecore_x_shutdown, except do not close Display, only connection.
888 *
889 * @ingroup Ecore_X_Init_Group
890 */
891 EAPI int
ecore_x_disconnect(void)892 ecore_x_disconnect(void)
893 {
894 if (--_ecore_x_init_count != 0)
895 return _ecore_x_init_count;
896 if (_ecore_x_shutdown()) return _ecore_x_init_count;
897 close(ConnectionNumber(_ecore_x_disp));
898 // FIXME: may have to clean up x display internal here
899 // getting segv here? hmmm. odd. disable
900 // XFree(_ecore_x_disp);
901 _ecore_x_disp = NULL;
902 _ecore_x_shutdown2();
903 return 0;
904 }
905
906 /**
907 * @defgroup Ecore_X_Display_Attr_Group X Display Attributes
908 *
909 * Functions that set and retrieve X display attributes.
910 */
911
912 /**
913 * Retrieves the Ecore_X_Display handle used for the current X connection.
914 * @return The current X display.
915 * @ingroup Ecore_X_Display_Attr_Group
916 */
917 EAPI Ecore_X_Display *
ecore_x_display_get(void)918 ecore_x_display_get(void)
919 {
920 return (Ecore_X_Display *)_ecore_x_disp;
921 }
922
923 /**
924 * Retrieves the X display file descriptor.
925 * @return The current X display file descriptor.
926 * @ingroup Ecore_X_Display_Attr_Group
927 */
928 EAPI int
ecore_x_fd_get(void)929 ecore_x_fd_get(void)
930 {
931 LOGFN;
932 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, 0);
933 return ConnectionNumber(_ecore_x_disp);
934 }
935
936 /**
937 * Retrieves the Ecore_X_Screen handle used for the current X connection.
938 * @return The current default screen.
939 * @ingroup Ecore_X_Display_Attr_Group
940 */
941 EAPI Ecore_X_Screen *
ecore_x_default_screen_get(void)942 ecore_x_default_screen_get(void)
943 {
944 LOGFN;
945 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, NULL);
946 return (Ecore_X_Screen *)DefaultScreenOfDisplay(_ecore_x_disp);
947 }
948
949 /**
950 * Retrieves the size of an Ecore_X_Screen.
951 * @param screen the handle to the screen to query.
952 * @param w where to return the width. May be NULL. Returns 0 on errors.
953 * @param h where to return the height. May be NULL. Returns 0 on errors.
954 * @ingroup Ecore_X_Display_Attr_Group
955 * @see ecore_x_default_screen_get()
956 *
957 * @since 1.1
958 */
959 EAPI void
ecore_x_screen_size_get(const Ecore_X_Screen * screen,int * w,int * h)960 ecore_x_screen_size_get(const Ecore_X_Screen *screen,
961 int *w,
962 int *h)
963 {
964 Screen *s = (Screen *)screen;
965 LOGFN;
966 if (w) *w = 0;
967 if (h) *h = 0;
968 EINA_SAFETY_ON_NULL_RETURN(screen);
969 if (w) *w = s->width;
970 if (h) *h = s->height;
971 }
972
973 /**
974 * Retrieves the number of screens.
975 *
976 * @return The count of the number of screens.
977 * @ingroup Ecore_X_Display_Attr_Group
978 *
979 * @since 1.1
980 */
981 EAPI int
ecore_x_screen_count_get(void)982 ecore_x_screen_count_get(void)
983 {
984 LOGFN;
985 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, 0);
986 return ScreenCount(_ecore_x_disp);
987 }
988
989 /**
990 * Retrieves the index number of the given screen.
991 *
992 * @param screen The screen for which the index will be retrieved.
993 * @return The index number of the screen.
994 * @ingroup Ecore_X_Display_Attr_Group
995 *
996 * @since 1.1
997 */
998 EAPI int
ecore_x_screen_index_get(const Ecore_X_Screen * screen)999 ecore_x_screen_index_get(const Ecore_X_Screen *screen)
1000 {
1001 EINA_SAFETY_ON_NULL_RETURN_VAL(screen, -1);
1002 return XScreenNumberOfScreen((Screen *)screen);
1003 }
1004
1005 /**
1006 * Retrieves the screen based on index number.
1007 *
1008 * @param idx The index that will be used to retrieve the screen.
1009 * @return The Ecore_X_Screen at this index.
1010 * @ingroup Ecore_X_Display_Attr_Group
1011 *
1012 * @since 1.1
1013 */
1014 EAPI Ecore_X_Screen *
ecore_x_screen_get(int idx)1015 ecore_x_screen_get(int idx)
1016 {
1017 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, NULL);
1018 return XScreenOfDisplay(_ecore_x_disp, idx);
1019 }
1020
1021 /**
1022 * Sets the timeout for a double and triple clicks to be flagged.
1023 *
1024 * This sets the time between clicks before the double_click flag is
1025 * set in a button down event. If 3 clicks occur within double this
1026 * time, the triple_click flag is also set.
1027 *
1028 * @param t The time in seconds
1029 * @ingroup Ecore_X_Display_Attr_Group
1030 */
1031 EAPI void
ecore_x_double_click_time_set(double t)1032 ecore_x_double_click_time_set(double t)
1033 {
1034 if (t < 0.0)
1035 t = 0.0;
1036
1037 _ecore_x_double_click_time = t;
1038 }
1039
1040 /**
1041 * Retrieves the double and triple click flag timeout.
1042 *
1043 * See @ref ecore_x_double_click_time_set for more information.
1044 *
1045 * @return The timeout for double clicks in seconds.
1046 * @ingroup Ecore_X_Display_Attr_Group
1047 */
1048 EAPI double
ecore_x_double_click_time_get(void)1049 ecore_x_double_click_time_get(void)
1050 {
1051 return _ecore_x_double_click_time;
1052 }
1053
1054 /**
1055 * @defgroup Ecore_X_Flush_Group X Synchronization Functions
1056 *
1057 * Functions that ensure that all commands that have been issued by the
1058 * Ecore X library have been sent to the server.
1059 */
1060
1061 /**
1062 * Sends all X commands in the X Display buffer.
1063 * @ingroup Ecore_X_Flush_Group
1064 */
1065 EAPI void
ecore_x_flush(void)1066 ecore_x_flush(void)
1067 {
1068 LOGFN;
1069 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
1070 XFlush(_ecore_x_disp);
1071 }
1072
1073 /**
1074 * Flushes the command buffer and waits until all requests have been
1075 * processed by the server.
1076 * @ingroup Ecore_X_Flush_Group
1077 */
1078 EAPI void
ecore_x_sync(void)1079 ecore_x_sync(void)
1080 {
1081 LOGFN;
1082 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
1083 XSync(_ecore_x_disp, False);
1084 }
1085
1086 /**
1087 * Kill all clients with subwindows under a given window.
1088 *
1089 * You can kill all clients connected to the X server by using
1090 * @ref ecore_x_window_root_list to get a list of root windows, and
1091 * then passing each root window to this function.
1092 *
1093 * @param root The window whose children will be killed.
1094 */
1095 EAPI void
ecore_x_killall(Ecore_X_Window root)1096 ecore_x_killall(Ecore_X_Window root)
1097 {
1098 unsigned int j;
1099 Window root_r;
1100 Window parent_r;
1101 Window *children_r = NULL;
1102 unsigned int num_children = 0;
1103
1104 LOGFN;
1105 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
1106 XGrabServer(_ecore_x_disp);
1107 /* Tranverse window tree starting from root, and drag each
1108 * before the firing squad */
1109 while (XQueryTree(_ecore_x_disp, root, &root_r, &parent_r,
1110 &children_r, &num_children) && (num_children > 0))
1111 {
1112 for (j = 0; j < num_children; ++j)
1113 {
1114 XKillClient(_ecore_x_disp, children_r[j]);
1115 }
1116
1117 XFree(children_r);
1118 }
1119 XUngrabServer(_ecore_x_disp);
1120 XSync(_ecore_x_disp, False);
1121 }
1122
1123 /**
1124 * Kill a specific client
1125 *
1126 * You can kill a specific client owning window @p win
1127 *
1128 * @param win Window of the client to be killed
1129 */
1130 EAPI void
ecore_x_kill(Ecore_X_Window win)1131 ecore_x_kill(Ecore_X_Window win)
1132 {
1133 LOGFN;
1134 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
1135 XKillClient(_ecore_x_disp, win);
1136 if (_ecore_xlib_sync) ecore_x_sync();
1137 }
1138
1139 /**
1140 * Return the last event time
1141 */
1142 EAPI Ecore_X_Time
ecore_x_current_time_get(void)1143 ecore_x_current_time_get(void)
1144 {
1145 return _ecore_x_event_last_time;
1146 }
1147
1148 /**
1149 * Return the screen DPI
1150 *
1151 * This is a simplistic call to get DPI. It does not account for differing
1152 * DPI in the x amd y axes nor does it account for multihead or xinerama and
1153 * xrander where different parts of the screen may have different DPI etc.
1154 *
1155 * @return the general screen DPI (dots/pixels per inch).
1156 */
1157 EAPI int
ecore_x_dpi_get(void)1158 ecore_x_dpi_get(void)
1159 {
1160 Screen *s;
1161
1162 LOGFN;
1163 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, 0);
1164 s = DefaultScreenOfDisplay(_ecore_x_disp);
1165 if (s->mwidth <= 0)
1166 return 75;
1167
1168 return (((s->width * 254) / s->mwidth) + 5) / 10;
1169 }
1170
1171 /**
1172 * Invoke the standard system beep to alert users
1173 *
1174 * @param percent The volume at which the bell rings. Must be in the range
1175 * [-100,+100]. If percent >= 0, the final volume will be:
1176 * base - [(base * percent) / 100] + percent
1177 * Otherwise, it's calculated as:
1178 * base + [(base * percent) / 100]
1179 * where @c base is the bell's base volume as set by XChangeKeyboardControl(3).
1180 *
1181 * @returns @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1182 */
1183 EAPI Eina_Bool
ecore_x_bell(int percent)1184 ecore_x_bell(int percent)
1185 {
1186 int ret;
1187
1188 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
1189 ret = XBell(_ecore_x_disp, percent);
1190 if (ret == BadValue)
1191 return EINA_FALSE;
1192
1193 return EINA_TRUE;
1194 }
1195
1196 static Eina_Bool
_ecore_x_fd_handler(void * data,Ecore_Fd_Handler * fd_handler EINA_UNUSED)1197 _ecore_x_fd_handler(void *data,
1198 Ecore_Fd_Handler *fd_handler EINA_UNUSED)
1199 {
1200 Display *d;
1201
1202 d = data;
1203 while (XPending(d))
1204 {
1205 XEvent ev;
1206
1207 XNextEvent(d, &ev);
1208 #ifdef BUILD_ECORE_IMF_XIM
1209 /* Filter event for XIM */
1210 if (XFilterEvent(&ev, ev.xkey.window))
1211 continue;
1212
1213 #endif /* ifdef BUILD_ECORE_IMF_XIM */
1214 if ((ev.type >= 0) && (ev.type < _ecore_x_event_handlers_num))
1215 {
1216 if (_ecore_x_event_handlers[AnyXEvent])
1217 _ecore_x_event_handlers[AnyXEvent] (&ev);
1218
1219 if (_ecore_x_event_handlers[ev.type])
1220 _ecore_x_event_handlers[ev.type] (&ev);
1221 }
1222 }
1223 return ECORE_CALLBACK_RENEW;
1224 }
1225
1226 static Eina_Bool
_ecore_x_fd_handler_buf(void * data,Ecore_Fd_Handler * fd_handler EINA_UNUSED)1227 _ecore_x_fd_handler_buf(void *data,
1228 Ecore_Fd_Handler *fd_handler EINA_UNUSED)
1229 {
1230 Display *d;
1231
1232 d = data;
1233 if (XPending(d))
1234 return ECORE_CALLBACK_RENEW;
1235
1236 return ECORE_CALLBACK_CANCEL;
1237 }
1238
1239 static int
_ecore_x_key_mask_get(XModifierKeymap * mod,KeySym sym)1240 _ecore_x_key_mask_get(XModifierKeymap *mod, KeySym sym)
1241 {
1242 KeySym sym2;
1243 int i, j, mask = 0;
1244 const int masks[8] =
1245 {
1246 ShiftMask, LockMask, ControlMask,
1247 Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
1248 };
1249
1250 for (i = 0; i < (8 * mod->max_keypermod); i++)
1251 {
1252 for (j = 0; j < 8; j++)
1253 {
1254 sym2 = _ecore_x_XKeycodeToKeysym(_ecore_x_disp,
1255 mod->modifiermap[i], j);
1256 if (sym2 != 0)
1257 break;
1258 }
1259 if (sym2 == sym) mask = masks[i / mod->max_keypermod];
1260 }
1261 return mask;
1262 }
1263
1264 /*****************************************************************************/
1265 /*****************************************************************************/
1266 /*****************************************************************************/
1267 /* FIXME: these funcs need categorising */
1268 /*****************************************************************************/
1269
1270 /**
1271 * Get a list of all the root windows on the server.
1272 *
1273 * @note The returned array will need to be freed after use.
1274 * @param num_ret Pointer to integer to put number of windows returned in.
1275 * @return An array of all the root windows. @c NULL is returned if memory
1276 * could not be allocated for the list, or if @p num_ret is @c NULL.
1277 */
1278 EAPI Ecore_X_Window *
ecore_x_window_root_list(int * num_ret)1279 ecore_x_window_root_list(int *num_ret)
1280 {
1281 int num, i;
1282 Ecore_X_Window *roots;
1283
1284 if (!num_ret)
1285 return NULL;
1286
1287 *num_ret = 0;
1288
1289 LOGFN;
1290 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, NULL);
1291 num = ScreenCount(_ecore_x_disp);
1292 roots = malloc(num * sizeof(Ecore_X_Window));
1293 if (!roots)
1294 return NULL;
1295
1296 *num_ret = num;
1297 for (i = 0; i < num; i++)
1298 roots[i] = RootWindow(_ecore_x_disp, i);
1299 return roots;
1300 }
1301
1302 EAPI Ecore_X_Window
ecore_x_window_root_first_get(void)1303 ecore_x_window_root_first_get(void)
1304 {
1305 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, 0);
1306 return RootWindow(_ecore_x_disp, 0);
1307 /*
1308 int num;
1309 Ecore_X_Window root, *roots = NULL;
1310
1311 LOGFN;
1312 roots = ecore_x_window_root_list(&num);
1313 if (!(roots)) return 0;
1314
1315 if (num > 0)
1316 root = roots[0];
1317 else
1318 root = 0;
1319
1320 free(roots);
1321 return root;
1322 */
1323 }
1324
1325 static void _ecore_x_window_manage_error(void *data);
1326
1327 static void
_ecore_x_window_manage_error(void * data EINA_UNUSED)1328 _ecore_x_window_manage_error(void *data EINA_UNUSED)
1329 {
1330 if ((ecore_x_error_request_get() == X_ChangeWindowAttributes) &&
1331 (ecore_x_error_code_get() == BadAccess))
1332 _ecore_x_window_manage_succeeded = EINA_FALSE;
1333 }
1334
1335 EAPI Eina_Bool
ecore_x_window_manage(Ecore_X_Window win)1336 ecore_x_window_manage(Ecore_X_Window win)
1337 {
1338 XWindowAttributes att;
1339
1340 LOGFN;
1341 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
1342 if (XGetWindowAttributes(_ecore_x_disp, win, &att) != True)
1343 return EINA_FALSE;
1344
1345 ecore_x_sync();
1346 _ecore_x_window_manage_succeeded = EINA_TRUE;
1347 ecore_x_error_handler_set(_ecore_x_window_manage_error, NULL);
1348 XSelectInput(_ecore_x_disp, win,
1349 EnterWindowMask |
1350 LeaveWindowMask |
1351 PropertyChangeMask |
1352 ResizeRedirectMask |
1353 SubstructureRedirectMask |
1354 SubstructureNotifyMask |
1355 StructureNotifyMask |
1356 KeyPressMask |
1357 KeyReleaseMask |
1358 att.your_event_mask);
1359 ecore_x_sync();
1360 ecore_x_error_handler_set(NULL, NULL);
1361 if (!_ecore_x_window_manage_succeeded)
1362 {
1363 return EINA_FALSE;
1364 }
1365
1366 return EINA_TRUE;
1367 }
1368
1369 EAPI void
ecore_x_window_container_manage(Ecore_X_Window win)1370 ecore_x_window_container_manage(Ecore_X_Window win)
1371 {
1372 LOGFN;
1373 if (_ecore_x_window_manage_succeeded && (win == ecore_x_window_root_first_get())) return;
1374 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
1375 XSelectInput(_ecore_x_disp, win,
1376 SubstructureRedirectMask |
1377 SubstructureNotifyMask);
1378 if (_ecore_xlib_sync) ecore_x_sync();
1379 }
1380
1381 EAPI void
ecore_x_window_client_manage(Ecore_X_Window win)1382 ecore_x_window_client_manage(Ecore_X_Window win)
1383 {
1384 LOGFN;
1385 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
1386 if (_ecore_x_window_manage_succeeded && (win == ecore_x_window_root_first_get())) return;
1387 XSelectInput(_ecore_x_disp, win,
1388 PropertyChangeMask |
1389 // ResizeRedirectMask |
1390 FocusChangeMask |
1391 ColormapChangeMask |
1392 VisibilityChangeMask |
1393 StructureNotifyMask |
1394 SubstructureNotifyMask
1395 );
1396 if (_ecore_xlib_sync) ecore_x_sync();
1397 XShapeSelectInput(_ecore_x_disp, win, ShapeNotifyMask);
1398 if (_ecore_xlib_sync) ecore_x_sync();
1399 }
1400
1401 EAPI void
ecore_x_window_sniff(Ecore_X_Window win)1402 ecore_x_window_sniff(Ecore_X_Window win)
1403 {
1404 LOGFN;
1405 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
1406 if (_ecore_x_window_manage_succeeded && (win == ecore_x_window_root_first_get())) return;
1407 XSelectInput(_ecore_x_disp, win,
1408 PropertyChangeMask |
1409 SubstructureNotifyMask);
1410 if (_ecore_xlib_sync) ecore_x_sync();
1411 }
1412
1413 /* this is internal-only for now */
1414 EAPI void
ecore_x_window_root_properties_select(void)1415 ecore_x_window_root_properties_select(void)
1416 {
1417 LOGFN;
1418 if (_ecore_x_window_manage_succeeded) return;
1419 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
1420 XSelectInput(_ecore_x_disp, ecore_x_window_root_first_get(), PropertyChangeMask);
1421 if (_ecore_xlib_sync) ecore_x_sync();
1422 }
1423
1424 EAPI void
ecore_x_window_client_sniff(Ecore_X_Window win)1425 ecore_x_window_client_sniff(Ecore_X_Window win)
1426 {
1427 LOGFN;
1428 if (_ecore_x_window_manage_succeeded && (win == ecore_x_window_root_first_get())) return;
1429 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
1430 XSelectInput(_ecore_x_disp, win,
1431 PropertyChangeMask |
1432 FocusChangeMask |
1433 ColormapChangeMask |
1434 VisibilityChangeMask |
1435 StructureNotifyMask |
1436 SubstructureNotifyMask);
1437 if (_ecore_xlib_sync) ecore_x_sync();
1438 XShapeSelectInput(_ecore_x_disp, win, ShapeNotifyMask);
1439 if (_ecore_xlib_sync) ecore_x_sync();
1440 }
1441
1442 EAPI Eina_Bool
ecore_x_window_attributes_get(Ecore_X_Window win,Ecore_X_Window_Attributes * att_ret)1443 ecore_x_window_attributes_get(Ecore_X_Window win,
1444 Ecore_X_Window_Attributes *att_ret)
1445 {
1446 XWindowAttributes att;
1447 Eina_Bool ret;
1448
1449 LOGFN;
1450 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
1451 ret = XGetWindowAttributes(_ecore_x_disp, win, &att);
1452 if (_ecore_xlib_sync) ecore_x_sync();
1453 if (!ret) return EINA_FALSE;
1454
1455 memset(att_ret, 0, sizeof(Ecore_X_Window_Attributes));
1456 att_ret->root = att.root;
1457 att_ret->x = att.x;
1458 att_ret->y = att.y;
1459 att_ret->w = att.width;
1460 att_ret->h = att.height;
1461 att_ret->border = att.border_width;
1462 att_ret->depth = att.depth;
1463 if (att.map_state != IsUnmapped)
1464 att_ret->visible = 1;
1465
1466 if (att.map_state == IsViewable)
1467 att_ret->viewable = 1;
1468
1469 if (att.override_redirect)
1470 att_ret->override = 1;
1471
1472 if (att.class == InputOnly)
1473 att_ret->input_only = 1;
1474
1475 if (att.save_under)
1476 att_ret->save_under = 1;
1477
1478 att_ret->event_mask.mine = att.your_event_mask;
1479 att_ret->event_mask.all = att.all_event_masks;
1480 att_ret->event_mask.no_propagate = att.do_not_propagate_mask;
1481 att_ret->window_gravity = att.win_gravity;
1482 att_ret->pixel_gravity = att.bit_gravity;
1483 att_ret->colormap = att.colormap;
1484 att_ret->visual = att.visual;
1485 return EINA_TRUE;
1486 }
1487
1488 EAPI void
ecore_x_window_save_set_add(Ecore_X_Window win)1489 ecore_x_window_save_set_add(Ecore_X_Window win)
1490 {
1491 LOGFN;
1492 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
1493 XAddToSaveSet(_ecore_x_disp, win);
1494 if (_ecore_xlib_sync) ecore_x_sync();
1495 }
1496
1497 EAPI void
ecore_x_window_save_set_del(Ecore_X_Window win)1498 ecore_x_window_save_set_del(Ecore_X_Window win)
1499 {
1500 LOGFN;
1501 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
1502 XRemoveFromSaveSet(_ecore_x_disp, win);
1503 if (_ecore_xlib_sync) ecore_x_sync();
1504 }
1505
1506 EAPI Ecore_X_Window *
ecore_x_window_children_get(Ecore_X_Window win,int * num)1507 ecore_x_window_children_get(Ecore_X_Window win,
1508 int *num)
1509 {
1510 Ecore_X_Window *windows = NULL;
1511 Eina_Bool success;
1512 Window root_ret = 0, parent_ret = 0, *children_ret = NULL;
1513 unsigned int children_ret_num = 0;
1514
1515 LOGFN;
1516 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, NULL);
1517 success = XQueryTree(_ecore_x_disp, win, &root_ret, &parent_ret, &children_ret,
1518 &children_ret_num);
1519 if (_ecore_xlib_sync) ecore_x_sync();
1520 if (!success) return NULL;
1521
1522 if (children_ret)
1523 {
1524 windows = malloc(children_ret_num * sizeof(Ecore_X_Window));
1525 if (windows)
1526 {
1527 unsigned int i;
1528
1529 for (i = 0; i < children_ret_num; i++)
1530 windows[i] = children_ret[i];
1531 *num = children_ret_num;
1532 }
1533
1534 XFree(children_ret);
1535 }
1536
1537 return windows;
1538 }
1539
1540 EAPI Eina_Bool
ecore_x_pointer_control_set(int accel_num,int accel_denom,int threshold)1541 ecore_x_pointer_control_set(int accel_num,
1542 int accel_denom,
1543 int threshold)
1544 {
1545 Eina_Bool ret;
1546 LOGFN;
1547 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
1548 ret = !!XChangePointerControl(_ecore_x_disp, 1, 1,
1549 accel_num, accel_denom, threshold);
1550 if (_ecore_xlib_sync) ecore_x_sync();
1551 return ret;
1552 }
1553
1554 EAPI Eina_Bool
ecore_x_pointer_control_get(int * accel_num,int * accel_denom,int * threshold)1555 ecore_x_pointer_control_get(int *accel_num,
1556 int *accel_denom,
1557 int *threshold)
1558 {
1559 Eina_Bool ret;
1560 LOGFN;
1561 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
1562 ret = !!XGetPointerControl(_ecore_x_disp,
1563 accel_num, accel_denom, threshold);
1564 if (_ecore_xlib_sync) ecore_x_sync();
1565 return ret;
1566 }
1567
1568 EAPI Eina_Bool
ecore_x_pointer_mapping_set(unsigned char * map,int nmap)1569 ecore_x_pointer_mapping_set(unsigned char *map,
1570 int nmap)
1571 {
1572 Eina_Bool ret;
1573 LOGFN;
1574 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
1575 ret = (XSetPointerMapping(_ecore_x_disp, map, nmap) == MappingSuccess);
1576 if (_ecore_xlib_sync) ecore_x_sync();
1577 return ret;
1578 }
1579
1580 EAPI Eina_Bool
ecore_x_pointer_mapping_get(unsigned char * map,int nmap)1581 ecore_x_pointer_mapping_get(unsigned char *map,
1582 int nmap)
1583 {
1584 Eina_Bool ret;
1585 LOGFN;
1586 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
1587 ret = !!XGetPointerMapping(_ecore_x_disp, map, nmap);
1588 if (_ecore_xlib_sync) ecore_x_sync();
1589 return ret;
1590 }
1591
1592 EAPI Eina_Bool
ecore_x_pointer_grab(Ecore_X_Window win)1593 ecore_x_pointer_grab(Ecore_X_Window win)
1594 {
1595 Eina_Bool ret;
1596 LOGFN;
1597 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
1598 ret = (XGrabPointer(_ecore_x_disp, win, False,
1599 ButtonPressMask | ButtonReleaseMask |
1600 EnterWindowMask | LeaveWindowMask | PointerMotionMask,
1601 GrabModeAsync, GrabModeAsync,
1602 None, None, CurrentTime) == GrabSuccess);
1603 if (_ecore_xlib_sync) ecore_x_sync();
1604 return ret;
1605 }
1606
1607 EAPI Eina_Bool
ecore_x_pointer_confine_grab(Ecore_X_Window win)1608 ecore_x_pointer_confine_grab(Ecore_X_Window win)
1609 {
1610 Eina_Bool ret;
1611 LOGFN;
1612 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
1613 ret = (XGrabPointer(_ecore_x_disp, win, False,
1614 ButtonPressMask | ButtonReleaseMask |
1615 EnterWindowMask | LeaveWindowMask | PointerMotionMask,
1616 GrabModeAsync, GrabModeAsync,
1617 win, None, CurrentTime) == GrabSuccess);
1618 if (_ecore_xlib_sync) ecore_x_sync();
1619 return ret;
1620 }
1621
1622 EAPI void
ecore_x_pointer_ungrab(void)1623 ecore_x_pointer_ungrab(void)
1624 {
1625 LOGFN;
1626 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
1627 XUngrabPointer(_ecore_x_disp, CurrentTime);
1628 if (_ecore_xlib_sync) ecore_x_sync();
1629 }
1630
1631 EAPI Eina_Bool
ecore_x_pointer_warp(Ecore_X_Window win,int x,int y)1632 ecore_x_pointer_warp(Ecore_X_Window win,
1633 int x,
1634 int y)
1635 {
1636 Eina_Bool ret;
1637 LOGFN;
1638 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
1639 ret = !!XWarpPointer(_ecore_x_disp, None, win, 0, 0, 0, 0, x, y);
1640 if (_ecore_xlib_sync) ecore_x_sync();
1641 return ret;
1642 }
1643
1644 EAPI Eina_Bool
ecore_x_keyboard_grab(Ecore_X_Window win)1645 ecore_x_keyboard_grab(Ecore_X_Window win)
1646 {
1647 Eina_Bool ret;
1648 LOGFN;
1649 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
1650 ret = (XGrabKeyboard(_ecore_x_disp, win, False,
1651 GrabModeAsync, GrabModeAsync,
1652 CurrentTime) == GrabSuccess);
1653 if (_ecore_xlib_sync) ecore_x_sync();
1654 return ret;
1655 }
1656
1657 EAPI void
ecore_x_keyboard_ungrab(void)1658 ecore_x_keyboard_ungrab(void)
1659 {
1660 LOGFN;
1661 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
1662 XUngrabKeyboard(_ecore_x_disp, CurrentTime);
1663 }
1664
1665 EAPI void
ecore_x_grab(void)1666 ecore_x_grab(void)
1667 {
1668 LOGFN;
1669 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
1670 _ecore_x_grab_count++;
1671 if (_ecore_x_grab_count == 1)
1672 XGrabServer(_ecore_x_disp);
1673 }
1674
1675 EAPI void
ecore_x_ungrab(void)1676 ecore_x_ungrab(void)
1677 {
1678 LOGFN;
1679 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
1680 _ecore_x_grab_count--;
1681 if (_ecore_x_grab_count < 0)
1682 _ecore_x_grab_count = 0;
1683
1684 if (_ecore_x_grab_count == 0)
1685 XUngrabServer(_ecore_x_disp);
1686 }
1687
1688 Eina_Bool (*_ecore_window_grab_replay_func)(void *data,
1689 int event_type,
1690 void *event);
1691 void *_ecore_window_grab_replay_data;
1692
1693 EAPI void
ecore_x_passive_grab_replay_func_set(Eina_Bool (* func)(void * data,int event_type,void * event),void * data)1694 ecore_x_passive_grab_replay_func_set(Eina_Bool (*func)(void *data,
1695 int event_type,
1696 void *event),
1697 void *data)
1698 {
1699 LOGFN;
1700 _ecore_window_grab_replay_func = func;
1701 _ecore_window_grab_replay_data = data;
1702 }
1703
1704
1705
1706
1707
1708
1709 //////////////////////////////////////////////////////////////////////////////
1710 int _ecore_window_grabs_num = 0;
1711 Wingrab *_ecore_window_grabs = NULL;
1712
1713 static void
_ecore_x_window_button_grab_internal(Ecore_X_Window win,int button,Ecore_X_Event_Mask event_mask,int mod,int any_mod)1714 _ecore_x_window_button_grab_internal(Ecore_X_Window win,
1715 int button,
1716 Ecore_X_Event_Mask event_mask,
1717 int mod,
1718 int any_mod)
1719 {
1720 unsigned int b;
1721 unsigned int m;
1722 unsigned int locks[8];
1723 int i, ev;
1724
1725 LOGFN;
1726 b = button;
1727 if (b == 0)
1728 b = AnyButton;
1729
1730 m = _ecore_x_event_modifier(mod);
1731 if (any_mod)
1732 m = AnyModifier;
1733
1734 locks[0] = 0;
1735 locks[1] = ECORE_X_LOCK_CAPS;
1736 locks[2] = ECORE_X_LOCK_NUM;
1737 locks[3] = ECORE_X_LOCK_SCROLL;
1738 locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM;
1739 locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL;
1740 locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1741 locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1742 ev = event_mask;
1743 for (i = 0; i < 8; i++)
1744 XGrabButton(_ecore_x_disp, b, m | locks[i],
1745 win, False, ev, GrabModeSync, GrabModeAsync, None, None);
1746 }
1747
1748 EAPI void
ecore_x_window_button_grab(Ecore_X_Window win,int button,Ecore_X_Event_Mask event_mask,int mod,int any_mod)1749 ecore_x_window_button_grab(Ecore_X_Window win,
1750 int button,
1751 Ecore_X_Event_Mask event_mask,
1752 int mod,
1753 int any_mod)
1754 {
1755 Wingrab *t;
1756
1757 _ecore_x_window_button_grab_internal(win, button, event_mask, mod, any_mod);
1758 _ecore_window_grabs_num++;
1759 t = realloc(_ecore_window_grabs,
1760 _ecore_window_grabs_num * sizeof(Wingrab));
1761 if (!t) return;
1762 _ecore_window_grabs = t;
1763 _ecore_window_grabs[_ecore_window_grabs_num - 1].win = win;
1764 _ecore_window_grabs[_ecore_window_grabs_num - 1].button = button;
1765 _ecore_window_grabs[_ecore_window_grabs_num - 1].event_mask = event_mask;
1766 _ecore_window_grabs[_ecore_window_grabs_num - 1].mod = mod;
1767 _ecore_window_grabs[_ecore_window_grabs_num - 1].any_mod = any_mod;
1768 }
1769
1770 static void
_ecore_x_sync_magic_send(int val,Ecore_X_Window swin,int b,int mod,int anymod)1771 _ecore_x_sync_magic_send(int val, Ecore_X_Window swin, int b, int mod, int anymod)
1772 {
1773 XEvent xev = { 0 };
1774
1775 xev.xclient.type = ClientMessage;
1776 xev.xclient.serial = 0;
1777 xev.xclient.send_event = True;
1778 xev.xclient.display = _ecore_x_disp;
1779 xev.xclient.window = _ecore_x_private_win;
1780 xev.xclient.format = 32;
1781 xev.xclient.message_type = 27777;
1782 xev.xclient.data.l[0] = 0x7162534;
1783 xev.xclient.data.l[1] = val | (anymod << 8);
1784 xev.xclient.data.l[2] = swin;
1785 xev.xclient.data.l[3] = b;
1786 xev.xclient.data.l[4] = mod;
1787 XSendEvent(_ecore_x_disp, _ecore_x_private_win, False, NoEventMask, &xev);
1788 }
1789
1790 int
_ecore_x_window_grab_remove(Ecore_X_Window win,int button,int mod,int any_mod)1791 _ecore_x_window_grab_remove(Ecore_X_Window win, int button, int mod, int any_mod)
1792 {
1793 int i, shuffle = 0;
1794 Wingrab *t;
1795
1796 if (_ecore_window_grabs_num > 0)
1797 {
1798 for (i = 0; i < _ecore_window_grabs_num; i++)
1799 {
1800 if (shuffle)
1801 _ecore_window_grabs[i - 1] = _ecore_window_grabs[i];
1802
1803 if ((!shuffle) && (_ecore_window_grabs[i].win == win) &&
1804 (((button >= 0) && (_ecore_window_grabs[i].mod == mod) &&
1805 (_ecore_window_grabs[i].any_mod == any_mod)) ||
1806 (button < 0)))
1807 shuffle = 1;
1808 }
1809 if (shuffle)
1810 {
1811 _ecore_window_grabs_num--;
1812 if (_ecore_window_grabs_num <= 0)
1813 {
1814 free(_ecore_window_grabs);
1815 _ecore_window_grabs = NULL;
1816 return shuffle;
1817 }
1818 t = realloc(_ecore_window_grabs,
1819 _ecore_window_grabs_num *
1820 sizeof(Wingrab));
1821 if (!t) return shuffle;
1822 _ecore_window_grabs = t;
1823 }
1824 }
1825 return shuffle;
1826 }
1827
1828 static void
_ecore_x_window_button_ungrab_internal(Ecore_X_Window win,int button,int mod,int any_mod)1829 _ecore_x_window_button_ungrab_internal(Ecore_X_Window win,
1830 int button,
1831 int mod,
1832 int any_mod)
1833 {
1834 unsigned int b;
1835 unsigned int m;
1836 unsigned int locks[8];
1837 int i;
1838
1839 LOGFN;
1840 b = button;
1841 if (b == 0)
1842 b = AnyButton;
1843
1844 m = _ecore_x_event_modifier(mod);
1845 if (any_mod)
1846 m = AnyModifier;
1847
1848 locks[0] = 0;
1849 locks[1] = ECORE_X_LOCK_CAPS;
1850 locks[2] = ECORE_X_LOCK_NUM;
1851 locks[3] = ECORE_X_LOCK_SCROLL;
1852 locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM;
1853 locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL;
1854 locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1855 locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1856 for (i = 0; i < 8; i++)
1857 {
1858 XUngrabButton(_ecore_x_disp, b, m | locks[i], win);
1859 if (_ecore_xlib_sync) ecore_x_sync();
1860 }
1861 }
1862
1863 EAPI void
ecore_x_window_button_ungrab(Ecore_X_Window win,int button,int mod,int any_mod)1864 ecore_x_window_button_ungrab(Ecore_X_Window win,
1865 int button,
1866 int mod,
1867 int any_mod)
1868 {
1869 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
1870 _ecore_x_window_button_ungrab_internal(win, button, mod, any_mod);
1871 _ecore_x_sync_magic_send(1, win, button, mod, any_mod);
1872 // _ecore_x_window_grab_remove(win, button, mod, any_mod);
1873 }
1874
_ecore_x_window_grab_suspend(void)1875 void _ecore_x_window_grab_suspend(void)
1876 {
1877 int i;
1878
1879 for (i = 0; i < _ecore_window_grabs_num; i++)
1880 {
1881 _ecore_x_window_button_ungrab_internal
1882 (_ecore_window_grabs[i].win, _ecore_window_grabs[i].button,
1883 _ecore_window_grabs[i].mod, _ecore_window_grabs[i].any_mod);
1884 }
1885 }
1886
_ecore_x_window_grab_resume(void)1887 void _ecore_x_window_grab_resume(void)
1888 {
1889 int i;
1890
1891 for (i = 0; i < _ecore_window_grabs_num; i++)
1892 {
1893 _ecore_x_window_button_grab_internal
1894 (_ecore_window_grabs[i].win, _ecore_window_grabs[i].button,
1895 _ecore_window_grabs[i].event_mask,
1896 _ecore_window_grabs[i].mod, _ecore_window_grabs[i].any_mod);
1897 }
1898 }
1899
1900
1901
1902
1903
1904
1905
1906
1907 //////////////////////////////////////////////////////////////////////////////
1908
1909 int _ecore_key_grabs_num = 0;
1910 typedef struct _Keygrab Keygrab;
1911 struct _Keygrab
1912 {
1913 Window win;
1914 char *key;
1915 int mod, any_mod;
1916 };
1917 Keygrab *_ecore_key_grabs = NULL;
1918
1919 static KeyCode
_ecore_x_window_key_grab_internal(Ecore_X_Window win,const char * key,int mod,int any_mod)1920 _ecore_x_window_key_grab_internal(Ecore_X_Window win,
1921 const char *key,
1922 int mod,
1923 int any_mod)
1924 {
1925 KeyCode keycode = 0;
1926 KeySym keysym;
1927 unsigned int m;
1928 unsigned int locks[8];
1929 int i;
1930
1931 LOGFN;
1932 if (!strncmp(key, "Keycode-", 8))
1933 keycode = atoi(key + 8);
1934 else
1935 {
1936 keysym = XStringToKeysym(key);
1937 if (keysym == NoSymbol)
1938 return 0;
1939
1940 keycode = XKeysymToKeycode(_ecore_x_disp, keysym);
1941 }
1942
1943 if (keycode == 0)
1944 return 0;
1945
1946 m = _ecore_x_event_modifier(mod);
1947 if (any_mod)
1948 m = AnyModifier;
1949
1950 locks[0] = 0;
1951 locks[1] = ECORE_X_LOCK_CAPS;
1952 locks[2] = ECORE_X_LOCK_NUM;
1953 locks[3] = ECORE_X_LOCK_SCROLL;
1954 locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM;
1955 locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL;
1956 locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1957 locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1958 for (i = 0; i < 8; i++)
1959 {
1960 XGrabKey(_ecore_x_disp, keycode, m | locks[i],
1961 win, False, GrabModeAsync, GrabModeAsync);
1962 if (_ecore_xlib_sync) ecore_x_sync();
1963 }
1964 return keycode;
1965 }
1966
1967 EAPI void
ecore_x_window_key_grab(Ecore_X_Window win,const char * key,int mod,int any_mod)1968 ecore_x_window_key_grab(Ecore_X_Window win,
1969 const char *key,
1970 int mod,
1971 int any_mod)
1972 {
1973 Keygrab *t;
1974 KeyCode keycode;
1975
1976 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
1977 if (!(keycode = _ecore_x_window_key_grab_internal(win, key, mod, any_mod)))
1978 return;
1979 _ecore_key_grabs_num++;
1980 t = realloc(_ecore_key_grabs,
1981 _ecore_key_grabs_num * sizeof(Keygrab));
1982 if (!t) return;
1983 _ecore_key_grabs = t;
1984 _ecore_key_grabs[_ecore_key_grabs_num - 1].win = win;
1985 _ecore_key_grabs[_ecore_key_grabs_num - 1].key = strdup(key);
1986 _ecore_key_grabs[_ecore_key_grabs_num - 1].mod = mod;
1987 _ecore_key_grabs[_ecore_key_grabs_num - 1].any_mod = any_mod;
1988 }
1989
1990 int
_ecore_x_key_grab_remove(Ecore_X_Window win,const char * key,int mod,int any_mod)1991 _ecore_x_key_grab_remove(Ecore_X_Window win,
1992 const char *key,
1993 int mod,
1994 int any_mod)
1995 {
1996 int i, shuffle = 0;
1997 Keygrab *t;
1998
1999 if (_ecore_key_grabs_num > 0)
2000 {
2001 for (i = 0; i < _ecore_key_grabs_num; i++)
2002 {
2003 if (shuffle)
2004 _ecore_key_grabs[i - 1] = _ecore_key_grabs[i];
2005
2006 if ((!shuffle) && (_ecore_key_grabs[i].win == win) &&
2007 ((key && ((!strcmp(_ecore_key_grabs[i].key, key)) &&
2008 (_ecore_key_grabs[i].mod == mod) &&
2009 (_ecore_key_grabs[i].any_mod == any_mod))) ||
2010 (!key)))
2011 {
2012 free(_ecore_key_grabs[i].key);
2013 _ecore_key_grabs[i].key = NULL;
2014 shuffle = 1;
2015 }
2016 }
2017 if (shuffle)
2018 {
2019 _ecore_key_grabs_num--;
2020 if (_ecore_key_grabs_num <= 0)
2021 {
2022 free(_ecore_key_grabs);
2023 _ecore_key_grabs = NULL;
2024 return shuffle;
2025 }
2026 t = realloc(_ecore_key_grabs,
2027 _ecore_key_grabs_num * sizeof(Keygrab));
2028 if (!t) return shuffle;
2029 _ecore_key_grabs = t;
2030 }
2031 }
2032 return shuffle;
2033 }
2034
2035 static KeyCode
_ecore_x_window_key_ungrab_internal(Ecore_X_Window win,const char * key,int mod,int any_mod)2036 _ecore_x_window_key_ungrab_internal(Ecore_X_Window win,
2037 const char *key,
2038 int mod,
2039 int any_mod)
2040 {
2041 KeyCode keycode = 0;
2042 KeySym keysym;
2043 unsigned int m;
2044 unsigned int locks[8];
2045 int i;
2046
2047 LOGFN;
2048 if (!strncmp(key, "Keycode-", 8))
2049 keycode = atoi(key + 8);
2050 else
2051 {
2052 keysym = XStringToKeysym(key);
2053 if (keysym == NoSymbol)
2054 return 0;
2055
2056 keycode = XKeysymToKeycode(_ecore_x_disp, keysym);
2057 }
2058
2059 if (keycode == 0)
2060 return 0;
2061
2062 m = _ecore_x_event_modifier(mod);
2063 if (any_mod)
2064 m = AnyModifier;
2065
2066 locks[0] = 0;
2067 locks[1] = ECORE_X_LOCK_CAPS;
2068 locks[2] = ECORE_X_LOCK_NUM;
2069 locks[3] = ECORE_X_LOCK_SCROLL;
2070 locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM;
2071 locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL;
2072 locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
2073 locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
2074 for (i = 0; i < 8; i++)
2075 XUngrabKey(_ecore_x_disp, keycode, m | locks[i], win);
2076 return keycode;
2077 }
2078
2079 EAPI void
ecore_x_window_key_ungrab(Ecore_X_Window win,const char * key,int mod,int any_mod)2080 ecore_x_window_key_ungrab(Ecore_X_Window win,
2081 const char *key,
2082 int mod,
2083 int any_mod)
2084 {
2085 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
2086 _ecore_x_window_key_ungrab_internal(win, key, mod, any_mod);
2087 _ecore_x_sync_magic_send(2, win, XStringToKeysym(key), mod, any_mod);
2088 // _ecore_x_key_grab_remove(win, key, mod, any_mod);
2089 }
2090
2091 void
_ecore_x_key_grab_suspend(void)2092 _ecore_x_key_grab_suspend(void)
2093 {
2094 int i;
2095
2096 for (i = 0; i < _ecore_key_grabs_num; i++)
2097 {
2098 _ecore_x_window_key_ungrab_internal
2099 (_ecore_key_grabs[i].win, _ecore_key_grabs[i].key,
2100 _ecore_key_grabs[i].mod, _ecore_key_grabs[i].any_mod);
2101 }
2102 }
2103
2104 void
_ecore_x_key_grab_resume(void)2105 _ecore_x_key_grab_resume(void)
2106 {
2107 int i;
2108
2109 for (i = 0; i < _ecore_key_grabs_num; i++)
2110 {
2111 _ecore_x_window_key_grab_internal
2112 (_ecore_key_grabs[i].win, _ecore_key_grabs[i].key,
2113 _ecore_key_grabs[i].mod, _ecore_key_grabs[i].any_mod);
2114 }
2115 }
2116
2117
2118
2119
2120
2121
2122
2123
2124 /**
2125 * Send client message with given type and format 32.
2126 *
2127 * @param win The window the message is sent to.
2128 * @param type The client message type.
2129 * @param mask The mask of the message to be sent.
2130 * @param d0 The client message data item 1
2131 * @param d1 The client message data item 2
2132 * @param d2 The client message data item 3
2133 * @param d3 The client message data item 4
2134 * @param d4 The client message data item 5
2135 *
2136 * @return @c EINA_TRUE on success @c EINA_FALSE otherwise.
2137 */
2138 EAPI Eina_Bool
ecore_x_client_message32_send(Ecore_X_Window win,Ecore_X_Atom type,Ecore_X_Event_Mask mask,long d0,long d1,long d2,long d3,long d4)2139 ecore_x_client_message32_send(Ecore_X_Window win,
2140 Ecore_X_Atom type,
2141 Ecore_X_Event_Mask mask,
2142 long d0,
2143 long d1,
2144 long d2,
2145 long d3,
2146 long d4)
2147 {
2148 XEvent xev = { 0 };
2149 Eina_Bool ret;
2150
2151 LOGFN;
2152 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
2153 xev.xclient.window = win;
2154 xev.xclient.type = ClientMessage;
2155 xev.xclient.message_type = type;
2156 xev.xclient.format = 32;
2157 xev.xclient.data.l[0] = d0;
2158 xev.xclient.data.l[1] = d1;
2159 xev.xclient.data.l[2] = d2;
2160 xev.xclient.data.l[3] = d3;
2161 xev.xclient.data.l[4] = d4;
2162
2163 ret = !!XSendEvent(_ecore_x_disp, win, False, mask, &xev);
2164 if (_ecore_xlib_sync) ecore_x_sync();
2165 return ret;
2166 }
2167
2168 /**
2169 * Send client message with given type and format 8.
2170 *
2171 * @param win The window the message is sent to.
2172 * @param type The client message type.
2173 * @param data Data to be sent.
2174 * @param len Number of data bytes, max @c 20.
2175 *
2176 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
2177 */
2178 EAPI Eina_Bool
ecore_x_client_message8_send(Ecore_X_Window win,Ecore_X_Atom type,const void * data,int len)2179 ecore_x_client_message8_send(Ecore_X_Window win,
2180 Ecore_X_Atom type,
2181 const void *data,
2182 int len)
2183 {
2184 XEvent xev = { 0 };
2185 Eina_Bool ret;
2186
2187 LOGFN;
2188 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
2189 xev.xclient.window = win;
2190 xev.xclient.type = ClientMessage;
2191 xev.xclient.message_type = type;
2192 xev.xclient.format = 8;
2193 if (len > 20)
2194 len = 20;
2195
2196 if (data && len > 0)
2197 memcpy(xev.xclient.data.b, data, len);
2198 if (len < 20)
2199 memset(xev.xclient.data.b + len, 0, 20 - len);
2200
2201 ret = !!XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev);
2202 if (_ecore_xlib_sync) ecore_x_sync();
2203 return ret;
2204 }
2205
2206 EAPI Eina_Bool
ecore_x_mouse_move_send(Ecore_X_Window win,int x,int y)2207 ecore_x_mouse_move_send(Ecore_X_Window win,
2208 int x,
2209 int y)
2210 {
2211 XEvent xev = { 0 };
2212 XWindowAttributes att;
2213 Window tw;
2214 int rx, ry;
2215 Eina_Bool ret;
2216
2217 LOGFN;
2218 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
2219 XGetWindowAttributes(_ecore_x_disp, win, &att);
2220 XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw);
2221 xev.xmotion.type = MotionNotify;
2222 xev.xmotion.window = win;
2223 xev.xmotion.root = att.root;
2224 xev.xmotion.subwindow = win;
2225 xev.xmotion.time = _ecore_x_event_last_time;
2226 xev.xmotion.x = x;
2227 xev.xmotion.y = y;
2228 xev.xmotion.x_root = rx;
2229 xev.xmotion.y_root = ry;
2230 xev.xmotion.state = 0;
2231 xev.xmotion.is_hint = 0;
2232 xev.xmotion.same_screen = 1;
2233 ret = !!XSendEvent(_ecore_x_disp, win, True, PointerMotionMask, &xev);
2234 if (_ecore_xlib_sync) ecore_x_sync();
2235 return ret;
2236 }
2237
2238 EAPI Eina_Bool
ecore_x_mouse_down_send(Ecore_X_Window win,int x,int y,int b)2239 ecore_x_mouse_down_send(Ecore_X_Window win,
2240 int x,
2241 int y,
2242 int b)
2243 {
2244 XEvent xev = { 0 };
2245 XWindowAttributes att;
2246 Window tw;
2247 int rx, ry;
2248 Eina_Bool ret;
2249
2250 LOGFN;
2251 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
2252 XGetWindowAttributes(_ecore_x_disp, win, &att);
2253 XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw);
2254 xev.xbutton.type = ButtonPress;
2255 xev.xbutton.window = win;
2256 xev.xbutton.root = att.root;
2257 xev.xbutton.subwindow = win;
2258 xev.xbutton.time = _ecore_x_event_last_time;
2259 xev.xbutton.x = x;
2260 xev.xbutton.y = y;
2261 xev.xbutton.x_root = rx;
2262 xev.xbutton.y_root = ry;
2263 xev.xbutton.state = 1 << b;
2264 xev.xbutton.button = b;
2265 xev.xbutton.same_screen = 1;
2266 ret = !!XSendEvent(_ecore_x_disp, win, True, ButtonPressMask, &xev);
2267 if (_ecore_xlib_sync) ecore_x_sync();
2268 return ret;
2269 }
2270
2271 EAPI Eina_Bool
ecore_x_mouse_up_send(Ecore_X_Window win,int x,int y,int b)2272 ecore_x_mouse_up_send(Ecore_X_Window win,
2273 int x,
2274 int y,
2275 int b)
2276 {
2277 XEvent xev = { 0 };
2278 XWindowAttributes att;
2279 Window tw;
2280 int rx, ry;
2281 Eina_Bool ret;
2282
2283 LOGFN;
2284 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
2285 XGetWindowAttributes(_ecore_x_disp, win, &att);
2286 XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw);
2287 xev.xbutton.type = ButtonRelease;
2288 xev.xbutton.window = win;
2289 xev.xbutton.root = att.root;
2290 xev.xbutton.subwindow = win;
2291 xev.xbutton.time = _ecore_x_event_last_time;
2292 xev.xbutton.x = x;
2293 xev.xbutton.y = y;
2294 xev.xbutton.x_root = rx;
2295 xev.xbutton.y_root = ry;
2296 xev.xbutton.state = 0;
2297 xev.xbutton.button = b;
2298 xev.xbutton.same_screen = 1;
2299 ret = !!XSendEvent(_ecore_x_disp, win, True, ButtonReleaseMask, &xev);
2300 if (_ecore_xlib_sync) ecore_x_sync();
2301 return ret;
2302 }
2303
2304 EAPI Eina_Bool
ecore_x_mouse_in_send(Ecore_X_Window win,int x,int y)2305 ecore_x_mouse_in_send(Ecore_X_Window win,
2306 int x,
2307 int y)
2308 {
2309 XEvent xev = { 0 };
2310 XWindowAttributes att;
2311 Window tw;
2312 int rx, ry;
2313 Eina_Bool ret;
2314
2315 LOGFN;
2316 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
2317 XGetWindowAttributes(_ecore_x_disp, win, &att);
2318 XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw);
2319 xev.xcrossing.type = EnterNotify;
2320 xev.xcrossing.window = win;
2321 xev.xcrossing.root = att.root;
2322 xev.xcrossing.subwindow = win;
2323 xev.xcrossing.time = _ecore_x_event_last_time;
2324 xev.xcrossing.x = x;
2325 xev.xcrossing.y = y;
2326 xev.xcrossing.x_root = rx;
2327 xev.xcrossing.y_root = ry;
2328 xev.xcrossing.mode = NotifyNormal;
2329 xev.xcrossing.detail = NotifyNonlinear;
2330 xev.xcrossing.same_screen = 1;
2331 xev.xcrossing.focus = 0;
2332 xev.xcrossing.state = 0;
2333 ret = !!XSendEvent(_ecore_x_disp, win, True, EnterWindowMask, &xev);
2334 if (_ecore_xlib_sync) ecore_x_sync();
2335 return ret;
2336 }
2337
2338 EAPI Eina_Bool
ecore_x_mouse_out_send(Ecore_X_Window win,int x,int y)2339 ecore_x_mouse_out_send(Ecore_X_Window win,
2340 int x,
2341 int y)
2342 {
2343 XEvent xev = { 0 };
2344 XWindowAttributes att;
2345 Window tw;
2346 int rx, ry;
2347 Eina_Bool ret;
2348
2349 LOGFN;
2350 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
2351 XGetWindowAttributes(_ecore_x_disp, win, &att);
2352 XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw);
2353 xev.xcrossing.type = LeaveNotify;
2354 xev.xcrossing.window = win;
2355 xev.xcrossing.root = att.root;
2356 xev.xcrossing.subwindow = win;
2357 xev.xcrossing.time = _ecore_x_event_last_time;
2358 xev.xcrossing.x = x;
2359 xev.xcrossing.y = y;
2360 xev.xcrossing.x_root = rx;
2361 xev.xcrossing.y_root = ry;
2362 xev.xcrossing.mode = NotifyNormal;
2363 xev.xcrossing.detail = NotifyNonlinear;
2364 xev.xcrossing.same_screen = 1;
2365 xev.xcrossing.focus = 0;
2366 xev.xcrossing.state = 0;
2367 ret = !!XSendEvent(_ecore_x_disp, win, True, LeaveWindowMask, &xev);
2368 if (_ecore_xlib_sync) ecore_x_sync();
2369 return ret;
2370 }
2371
2372 EAPI void
ecore_x_focus_reset(void)2373 ecore_x_focus_reset(void)
2374 {
2375 LOGFN;
2376 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
2377 XSetInputFocus(_ecore_x_disp, PointerRoot, RevertToPointerRoot, CurrentTime);
2378 if (_ecore_xlib_sync) ecore_x_sync();
2379 }
2380
2381 EAPI void
ecore_x_events_allow_all(void)2382 ecore_x_events_allow_all(void)
2383 {
2384 LOGFN;
2385 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
2386 XAllowEvents(_ecore_x_disp, AsyncBoth, CurrentTime);
2387 if (_ecore_xlib_sync) ecore_x_sync();
2388 }
2389
2390 EAPI void
ecore_x_pointer_last_xy_get(int * x,int * y)2391 ecore_x_pointer_last_xy_get(int *x,
2392 int *y)
2393 {
2394 if (x)
2395 *x = _ecore_x_event_last_root_x;
2396
2397 if (y)
2398 *y = _ecore_x_event_last_root_y;
2399 }
2400
2401 EAPI void
ecore_x_pointer_xy_get(Ecore_X_Window win,int * x,int * y)2402 ecore_x_pointer_xy_get(Ecore_X_Window win,
2403 int *x,
2404 int *y)
2405 {
2406 Window rwin, cwin;
2407 int rx, ry, wx, wy, ret;
2408 unsigned int mask;
2409
2410 LOGFN;
2411 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
2412 ret = XQueryPointer(_ecore_x_disp, win, &rwin, &cwin,
2413 &rx, &ry, &wx, &wy, &mask);
2414 if (!ret)
2415 wx = wy = -1;
2416
2417 if (x) *x = wx;
2418 if (y) *y = wy;
2419 if (_ecore_xlib_sync) ecore_x_sync();
2420 }
2421
2422 EAPI void
ecore_x_pointer_root_xy_get(int * x,int * y)2423 ecore_x_pointer_root_xy_get(int *x, int *y)
2424 {
2425 Ecore_X_Window *root;
2426 Window rwin, cwin;
2427 int rx, ry, wx, wy, ret = 0;
2428 int i, num;
2429 unsigned int mask;
2430
2431 LOGFN;
2432 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
2433 root = ecore_x_window_root_list(&num);
2434 for (i = 0; i < num; i++)
2435 {
2436 ret = XQueryPointer(_ecore_x_disp, root[i], &rwin, &cwin,
2437 &rx, &ry, &wx, &wy, &mask);
2438 if (_ecore_xlib_sync) ecore_x_sync();
2439 if (ret) break;
2440 }
2441
2442 if (!ret)
2443 rx = ry = -1;
2444
2445 if (x) *x = rx;
2446 if (y) *y = ry;
2447 free(root);
2448 }
2449
2450 /**
2451 * Retrieve the Visual ID from a given Visual.
2452 *
2453 * @param visual The Visual to get the ID for.
2454 *
2455 * @return The visual id.
2456 * @since 1.1.0
2457 */
2458 EAPI unsigned int
ecore_x_visual_id_get(Ecore_X_Visual visual)2459 ecore_x_visual_id_get(Ecore_X_Visual visual)
2460 {
2461 unsigned int vis;
2462 vis = XVisualIDFromVisual(visual);
2463 if (_ecore_xlib_sync) ecore_x_sync();
2464 return vis;
2465 }
2466
2467 /**
2468 * Retrieve the default Visual.
2469 *
2470 * @param disp The Display to get the Default Visual from
2471 * @param screen The Screen.
2472 *
2473 * @return The default visual.
2474 * @since 1.1.0
2475 */
2476 EAPI Ecore_X_Visual
ecore_x_default_visual_get(Ecore_X_Display * disp,Ecore_X_Screen * screen)2477 ecore_x_default_visual_get(Ecore_X_Display *disp,
2478 Ecore_X_Screen *screen)
2479 {
2480 Ecore_X_Visual vis = DefaultVisual(disp, ecore_x_screen_index_get(screen));
2481 if (_ecore_xlib_sync) ecore_x_sync();
2482 return vis;
2483 }
2484
2485 /**
2486 * Retrieve the default Colormap.
2487 *
2488 * @param disp The Display to get the Default Colormap from
2489 * @param screen The Screen.
2490 *
2491 * @return The default colormap.
2492 * @since 1.1.0
2493 */
2494 EAPI Ecore_X_Colormap
ecore_x_default_colormap_get(Ecore_X_Display * disp,Ecore_X_Screen * screen)2495 ecore_x_default_colormap_get(Ecore_X_Display *disp,
2496 Ecore_X_Screen *screen)
2497 {
2498 Ecore_X_Colormap col = DefaultColormap(disp, ecore_x_screen_index_get(screen));
2499 if (_ecore_xlib_sync) ecore_x_sync();
2500 return col;
2501 }
2502
2503 /**
2504 * Retrieve the default depth.
2505 *
2506 * @param disp The Display to get the Default Depth from
2507 * @param screen The Screen.
2508 *
2509 * @return The default depth.
2510 * @since 1.1.0
2511 */
2512 EAPI int
ecore_x_default_depth_get(Ecore_X_Display * disp,Ecore_X_Screen * screen)2513 ecore_x_default_depth_get(Ecore_X_Display *disp,
2514 Ecore_X_Screen *screen)
2515 {
2516 int depth = DefaultDepth(disp, ecore_x_screen_index_get(screen));
2517 if (_ecore_xlib_sync) ecore_x_sync();
2518 return depth;
2519 }
2520
2521 EAPI Ecore_X_Connection *
ecore_x_connection_get(void)2522 ecore_x_connection_get(void)
2523 {
2524 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, NULL);
2525 return XGetXCBConnection(_ecore_x_disp);
2526 }
2527
2528 EAPI void
ecore_x_xkb_select_group(int group)2529 ecore_x_xkb_select_group(int group)
2530 {
2531 #ifdef ECORE_XKB
2532 EINA_SAFETY_ON_NULL_RETURN(_ecore_x_disp);
2533 XkbLockGroup(_ecore_x_disp, XkbUseCoreKbd, group);
2534 if (_ecore_xlib_sync) ecore_x_sync();
2535 #endif
2536 }
2537
2538 EAPI Eina_Bool
ecore_x_xkb_track_state(void)2539 ecore_x_xkb_track_state(void)
2540 {
2541 Eina_Bool ret = EINA_FALSE;
2542 #ifdef ECORE_XKB
2543 unsigned mask = XkbNewKeyboardNotifyMask | XkbMapNotifyMask |
2544 XkbStateNotifyMask | XkbCompatMapNotifyMask;
2545 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
2546 ret = XkbSelectEvents(_ecore_x_disp, XkbUseCoreKbd, mask, mask);
2547 if (_ecore_xlib_sync) ecore_x_sync();
2548 #endif
2549 return ret;
2550 }
2551
2552 EAPI Eina_Bool
ecore_x_xkb_state_get(Ecore_X_Xkb_State * state)2553 ecore_x_xkb_state_get(Ecore_X_Xkb_State *state)
2554 {
2555 Eina_Bool ret = EINA_FALSE;
2556 #ifdef ECORE_XKB
2557 XkbStateRec xkbstate;
2558
2559 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
2560 ret = XkbGetState(_ecore_x_disp, XkbUseCoreKbd, &xkbstate);
2561 if (!ret) return ret;
2562
2563 state->group = xkbstate.group;
2564 state->base_group = xkbstate.base_group;
2565 state->latched_group = xkbstate.latched_group;
2566 state->locked_group = xkbstate.locked_group;
2567
2568 state->mods = xkbstate.mods;
2569 state->base_mods = xkbstate.base_mods;
2570 state->latched_mods = xkbstate.latched_mods;
2571 state->locked_mods = xkbstate.locked_mods;
2572 #endif
2573 return ret;
2574 }
2575
2576 /*****************************************************************************/
2577 /*****************************************************************************/
2578 /*****************************************************************************/
2579
2580 static int
_ecore_x_event_modifier(unsigned int state)2581 _ecore_x_event_modifier(unsigned int state)
2582 {
2583 int xmodifiers = 0;
2584
2585 if (state & ECORE_EVENT_MODIFIER_SHIFT)
2586 xmodifiers |= ECORE_X_MODIFIER_SHIFT;
2587
2588 if (state & ECORE_EVENT_MODIFIER_CTRL)
2589 xmodifiers |= ECORE_X_MODIFIER_CTRL;
2590
2591 if (state & ECORE_EVENT_MODIFIER_ALT)
2592 xmodifiers |= ECORE_X_MODIFIER_ALT;
2593
2594 if (state & ECORE_EVENT_MODIFIER_WIN)
2595 xmodifiers |= ECORE_X_MODIFIER_WIN;
2596
2597 if (state & ECORE_EVENT_MODIFIER_ALTGR)
2598 xmodifiers |= ECORE_X_MODIFIER_ALTGR;
2599
2600 if (state & ECORE_EVENT_LOCK_SCROLL)
2601 xmodifiers |= ECORE_X_LOCK_SCROLL;
2602
2603 if (state & ECORE_EVENT_LOCK_NUM)
2604 xmodifiers |= ECORE_X_LOCK_NUM;
2605
2606 if (state & ECORE_EVENT_LOCK_CAPS)
2607 xmodifiers |= ECORE_X_LOCK_CAPS;
2608
2609 if (state & ECORE_EVENT_LOCK_SHIFT)
2610 xmodifiers |= ECORE_X_LOCK_SHIFT;
2611
2612 return xmodifiers;
2613 }
2614