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