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