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