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