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