[ecore] merged svn latest code (svn54830)
[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 Eina_Bool _ecore_x_xcursor = EINA_FALSE;
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
257      ("ecore_x", 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) ? EINA_TRUE : EINA_FALSE;
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      {
681         close(ConnectionNumber(_ecore_x_disp));
682         // FIXME: may have to clean up x display internal here
683         XFree(_ecore_x_disp);
684      }
685
686    free(_ecore_x_event_handlers);
687    _ecore_x_fd_handler_handle = NULL;
688    _ecore_x_disp = NULL;
689    _ecore_x_event_handlers = NULL;
690    _ecore_x_input_shutdown();
691    _ecore_x_selection_shutdown();
692    _ecore_x_dnd_shutdown();
693    ecore_x_netwm_shutdown();
694
695    ecore_event_shutdown();
696    ecore_shutdown();
697
698    eina_log_domain_unregister(_ecore_xlib_log_dom);
699    _ecore_xlib_log_dom = -1;
700    eina_shutdown();
701
702    return _ecore_x_init_count;
703 } /* _ecore_x_shutdown */
704
705 /**
706  * Shuts down the Ecore X library.
707  *
708  * In shutting down the library, the X display connection is terminated
709  * and any event handlers for it are removed.
710  *
711  * @return  The number of times the library has been initialized without
712  *          being shut down.
713  * @ingroup Ecore_X_Init_Group
714  */
715 EAPI int
716 ecore_x_shutdown(void)
717 {
718    return _ecore_x_shutdown(1);
719 } /* ecore_x_shutdown */
720
721 /**
722  * Shuts down the Ecore X library.
723  *
724  * As ecore_x_shutdown, except do not close Display, only connection.
725  *
726  * @ingroup Ecore_X_Init_Group
727  */
728 EAPI int
729 ecore_x_disconnect(void)
730 {
731    return _ecore_x_shutdown(0);
732 } /* ecore_x_disconnect */
733
734 /**
735  * @defgroup Ecore_X_Display_Attr_Group X Display Attributes
736  *
737  * Functions that set and retrieve X display attributes.
738  */
739
740 /**
741  * Retrieves the Ecore_X_Display handle used for the current X connection.
742  * @return  The current X display.
743  * @ingroup Ecore_X_Display_Attr_Group
744  */
745 EAPI Ecore_X_Display *
746 ecore_x_display_get(void)
747 {
748    return (Ecore_X_Display *)_ecore_x_disp;
749 } /* ecore_x_display_get */
750
751 /**
752  * Retrieves the X display file descriptor.
753  * @return  The current X display file descriptor.
754  * @ingroup Ecore_X_Display_Attr_Group
755  */
756 EAPI int
757 ecore_x_fd_get(void)
758 {
759    LOGFN(__FILE__, __LINE__, __FUNCTION__);
760    return ConnectionNumber(_ecore_x_disp);
761 } /* ecore_x_fd_get */
762
763 /**
764  * Retrieves the Ecore_X_Screen handle used for the current X connection.
765  * @return  The current default screen.
766  * @ingroup Ecore_Xcb_Display_Attr_Group
767  */
768 EAPI Ecore_X_Screen *
769 ecore_x_default_screen_get(void)
770 {
771    LOGFN(__FILE__, __LINE__, __FUNCTION__);
772    return (Ecore_X_Screen *)DefaultScreenOfDisplay(_ecore_x_disp);
773 } /* ecore_x_default_screen_get */
774
775 /**
776  * Sets the timeout for a double and triple clicks to be flagged.
777  *
778  * This sets the time between clicks before the double_click flag is
779  * set in a button down event. If 3 clicks occur within double this
780  * time, the triple_click flag is also set.
781  *
782  * @param   t The time in seconds
783  * @ingroup Ecore_X_Display_Attr_Group
784  */
785 EAPI void
786 ecore_x_double_click_time_set(double t)
787 {
788    if (t < 0.0)
789       t = 0.0;
790
791    _ecore_x_double_click_time = t;
792 } /* ecore_x_double_click_time_set */
793
794 /**
795  * Retrieves the double and triple click flag timeout.
796  *
797  * See @ref ecore_x_double_click_time_set for more information.
798  *
799  * @return  The timeout for double clicks in seconds.
800  * @ingroup Ecore_X_Display_Attr_Group
801  */
802 EAPI double
803 ecore_x_double_click_time_get(void)
804 {
805    return _ecore_x_double_click_time;
806 } /* ecore_x_double_click_time_get */
807
808 /**
809  * @defgroup Ecore_X_Flush_Group X Synchronization Functions
810  *
811  * Functions that ensure that all commands that have been issued by the
812  * Ecore X library have been sent to the server.
813  */
814
815 /**
816  * Sends all X commands in the X Display buffer.
817  * @ingroup Ecore_X_Flush_Group
818  */
819 EAPI void
820 ecore_x_flush(void)
821 {
822    LOGFN(__FILE__, __LINE__, __FUNCTION__);
823    XFlush(_ecore_x_disp);
824 } /* ecore_x_flush */
825
826 /**
827  * Flushes the command buffer and waits until all requests have been
828  * processed by the server.
829  * @ingroup Ecore_X_Flush_Group
830  */
831 EAPI void
832 ecore_x_sync(void)
833 {
834    LOGFN(__FILE__, __LINE__, __FUNCTION__);
835    XSync(_ecore_x_disp, False);
836 } /* ecore_x_sync */
837
838 /**
839  * Kill all clients with subwindows under a given window.
840  *
841  * You can kill all clients connected to the X server by using
842  * @ref ecore_x_window_root_list to get a list of root windows, and
843  * then passing each root window to this function.
844  *
845  * @param root The window whose children will be killed.
846  */
847 EAPI void
848 ecore_x_killall(Ecore_X_Window root)
849 {
850    unsigned int j;
851    Window root_r;
852    Window parent_r;
853    Window *children_r = NULL;
854    unsigned int num_children = 0;
855
856    LOGFN(__FILE__, __LINE__, __FUNCTION__);
857    XGrabServer(_ecore_x_disp);
858    /* Tranverse window tree starting from root, and drag each
859     * before the firing squad */
860    while (XQueryTree(_ecore_x_disp, root, &root_r, &parent_r,
861                      &children_r, &num_children) && (num_children > 0))
862      {
863         for (j = 0; j < num_children; ++j)
864           {
865              XKillClient(_ecore_x_disp, children_r[j]);
866           }
867
868         XFree(children_r);
869      }
870    XUngrabServer(_ecore_x_disp);
871    XSync(_ecore_x_disp, False);
872 } /* ecore_x_killall */
873
874 /**
875  * Kill a specific client
876  *
877  * You can kill a specific client owning window @p win
878  *
879  * @param win Window of the client to be killed
880  */
881 EAPI void
882 ecore_x_kill(Ecore_X_Window win)
883 {
884    LOGFN(__FILE__, __LINE__, __FUNCTION__);
885    XKillClient(_ecore_x_disp, win);
886 } /* ecore_x_kill */
887
888 /**
889  * Return the last event time
890  */
891 EAPI Ecore_X_Time
892 ecore_x_current_time_get(void)
893 {
894    return _ecore_x_event_last_time;
895 } /* ecore_x_current_time_get */
896
897 /**
898  * Return the screen DPI
899  *
900  * This is a simplistic call to get DPI. It does not account for differing
901  * DPI in the x amd y axes nor does it accoutn for multihead or xinerama and
902  * xrander where different parts of the screen may have differen DPI etc.
903  *
904  * @return the general screen DPI (dots/pixels per inch).
905  */
906 EAPI int
907 ecore_x_dpi_get(void)
908 {
909    Screen *s;
910
911    LOGFN(__FILE__, __LINE__, __FUNCTION__);
912    s = DefaultScreenOfDisplay(_ecore_x_disp);
913    if (s->mwidth <= 0)
914       return 75;
915
916    return (((s->width * 254) / s->mwidth) + 5) / 10;
917 } /* ecore_x_dpi_get */
918
919 /**
920  * Invoke the standard system beep to alert users
921  *
922  * @param percent The volume at which the bell rings. Must be in the range
923  * [-100,+100]. If percent >= 0, the final volume will be:
924  *       base - [(base * percent) / 100] + percent
925  * Otherwise, it's calculated as:
926  *       base + [(base * percent) / 100]
927  * where @c base is the bell's base volume as set by XChangeKeyboardControl(3).
928  *
929  * @returns EINA_TRUE on success, EINA_FALSE otherwise.
930  */
931 EAPI Eina_Bool
932 ecore_x_bell(int percent)
933 {
934    int ret;
935
936    ret = XBell(_ecore_x_disp, percent);
937    if (ret == BadValue)
938       return EINA_FALSE;
939
940    return EINA_TRUE;
941 } /* ecore_x_bell */
942
943 static Eina_Bool
944 _ecore_x_fd_handler(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
945 {
946    Display *d;
947
948    d = data;
949    while (XPending(d))
950      {
951         XEvent ev;
952
953         XNextEvent(d, &ev);
954
955 #ifdef ENABLE_XIM
956         /* Filter event for XIM */
957         if (XFilterEvent(&ev, ev.xkey.window))
958            continue;
959
960 #endif /* ifdef ENABLE_XIM */
961
962         if ((ev.type >= 0) && (ev.type < _ecore_x_event_handlers_num))
963           {
964              if (_ecore_x_event_handlers[AnyXEvent])
965                 _ecore_x_event_handlers[AnyXEvent] (&ev);
966
967              if (_ecore_x_event_handlers[ev.type])
968                 _ecore_x_event_handlers[ev.type] (&ev);
969           }
970      }
971    return ECORE_CALLBACK_RENEW;
972 } /* _ecore_x_fd_handler */
973
974 static Eina_Bool
975 _ecore_x_fd_handler_buf(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
976 {
977    Display *d;
978
979    d = data;
980    if (XPending(d))
981       return ECORE_CALLBACK_RENEW;
982
983    return ECORE_CALLBACK_CANCEL;
984 } /* _ecore_x_fd_handler_buf */
985
986 static int
987 _ecore_x_key_mask_get(KeySym sym)
988 {
989    XModifierKeymap *mod;
990    KeySym sym2;
991    int i, j;
992    const int masks[8] =
993    {
994       ShiftMask, LockMask, ControlMask,
995       Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
996    };
997
998    mod = XGetModifierMapping(_ecore_x_disp);
999    if ((mod) && (mod->max_keypermod > 0))
1000       for (i = 0; i < (8 * mod->max_keypermod); i++)
1001         {
1002            for (j = 0; j < 8; j++)
1003              {
1004                 sym2 = XKeycodeToKeysym(_ecore_x_disp, mod->modifiermap[i], j);
1005                 if (sym2 != 0)
1006                    break;
1007              }
1008            if (sym2 == sym)
1009              {
1010                 int mask;
1011
1012                 mask = masks[i / mod->max_keypermod];
1013                 if (mod->modifiermap)
1014                    XFree(mod->modifiermap);
1015
1016                 XFree(mod);
1017                 return mask;
1018              }
1019         }
1020
1021    if (mod)
1022      {
1023         if (mod->modifiermap)
1024            XFree(mod->modifiermap);
1025
1026         XFree(mod);
1027      }
1028
1029    return 0;
1030 } /* _ecore_x_key_mask_get */
1031
1032 /*****************************************************************************/
1033 /*****************************************************************************/
1034 /*****************************************************************************/
1035 /* FIXME: these funcs need categorising */
1036 /*****************************************************************************/
1037
1038 /**
1039  * Get a list of all the root windows on the server.
1040  *
1041  * @note   The returned array will need to be freed after use.
1042  * @param  num_ret Pointer to integer to put number of windows returned in.
1043  * @return An array of all the root windows.  @c NULL is returned if memory
1044  *         could not be allocated for the list, or if @p num_ret is @c NULL.
1045  */
1046 EAPI Ecore_X_Window *
1047 ecore_x_window_root_list(int *num_ret)
1048 {
1049    int num, i;
1050    Ecore_X_Window *roots;
1051 #ifdef ECORE_XPRINT
1052    int xp_base, xp_err_base;
1053 #endif /* ifdef ECORE_XPRINT */
1054
1055    if (!num_ret)
1056       return NULL;
1057
1058    *num_ret = 0;
1059
1060    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1061 #ifdef ECORE_XPRINT
1062    num = ScreenCount(_ecore_x_disp);
1063    if (XpQueryExtension(_ecore_x_disp, &xp_base, &xp_err_base))
1064      {
1065         Screen **ps = NULL;
1066         int psnum = 0;
1067
1068         ps = XpQueryScreens(_ecore_x_disp, &psnum);
1069         if (ps)
1070           {
1071              int overlap, j;
1072
1073              overlap = 0;
1074              for (i = 0; i < num; i++)
1075                {
1076                   for (j = 0; j < psnum; j++)
1077                     {
1078                        if (ScreenOfDisplay(_ecore_x_disp, i) == ps[j])
1079                           overlap++;
1080                     }
1081                }
1082              roots = malloc((num - overlap) * sizeof(Window));
1083              if (roots)
1084                {
1085                   int k;
1086
1087                   k = 0;
1088                   for (i = 0; i < num; i++)
1089                     {
1090                        int is_print;
1091
1092                        is_print = 0;
1093                        for (j = 0; j < psnum; j++)
1094                          {
1095                             if (ScreenOfDisplay(_ecore_x_disp, i) == ps[j])
1096                               {
1097                                  is_print = 1;
1098                                  break;
1099                               }
1100                          }
1101                        if (!is_print)
1102                          {
1103                             roots[k] = RootWindow(_ecore_x_disp, i);
1104                             k++;
1105                          }
1106                     }
1107                   *num_ret = k;
1108                }
1109
1110              XFree(ps);
1111           }
1112         else
1113           {
1114              roots = malloc(num * sizeof(Window));
1115              if (!roots)
1116                 return NULL;
1117
1118              *num_ret = num;
1119              for (i = 0; i < num; i++)
1120                 roots[i] = RootWindow(_ecore_x_disp, i);
1121           }
1122      }
1123    else
1124      {
1125         roots = malloc(num * sizeof(Window));
1126         if (!roots)
1127            return NULL;
1128
1129         *num_ret = num;
1130         for (i = 0; i < num; i++)
1131            roots[i] = RootWindow(_ecore_x_disp, i);
1132      }
1133
1134 #else /* ifdef ECORE_XPRINT */
1135    num = ScreenCount(_ecore_x_disp);
1136    roots = malloc(num * sizeof(Window));
1137    if (!roots)
1138       return NULL;
1139
1140    *num_ret = num;
1141    for (i = 0; i < num; i++)
1142       roots[i] = RootWindow(_ecore_x_disp, i);
1143 #endif /* ifdef ECORE_XPRINT */
1144    return roots;
1145 } /* ecore_x_window_root_list */
1146
1147 EAPI Ecore_X_Window
1148 ecore_x_window_root_first_get(void)
1149 {
1150    return RootWindow(_ecore_x_disp, 0);
1151 /*
1152    int num;
1153    Ecore_X_Window root, *roots = NULL;
1154
1155    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1156    roots = ecore_x_window_root_list(&num);
1157    if (!(roots)) return 0;
1158
1159    if (num > 0)
1160      root = roots[0];
1161    else
1162      root = 0;
1163
1164    free(roots);
1165    return root;
1166  */
1167 } /* ecore_x_window_root_first_get */
1168
1169 static void      _ecore_x_window_manage_error(void *data);
1170
1171 static int _ecore_x_window_manage_failed = 0;
1172 static void
1173 _ecore_x_window_manage_error(void *data __UNUSED__)
1174 {
1175    if ((ecore_x_error_request_get() == X_ChangeWindowAttributes) &&
1176        (ecore_x_error_code_get() == BadAccess))
1177       _ecore_x_window_manage_failed = 1;
1178 } /* _ecore_x_window_manage_error */
1179
1180 EAPI Eina_Bool
1181 ecore_x_window_manage(Ecore_X_Window win)
1182 {
1183    XWindowAttributes att;
1184
1185    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1186    if (XGetWindowAttributes(_ecore_x_disp, win, &att) != True)
1187       return EINA_FALSE;
1188
1189    ecore_x_sync();
1190    _ecore_x_window_manage_failed = 0;
1191    ecore_x_error_handler_set(_ecore_x_window_manage_error, NULL);
1192    XSelectInput(_ecore_x_disp, win,
1193                 EnterWindowMask |
1194                 LeaveWindowMask |
1195                 PropertyChangeMask |
1196                 ResizeRedirectMask |
1197                 SubstructureRedirectMask |
1198                 SubstructureNotifyMask |
1199                 StructureNotifyMask |
1200                 KeyPressMask |
1201                 KeyReleaseMask |
1202                 att.your_event_mask);
1203    ecore_x_sync();
1204    ecore_x_error_handler_set(NULL, NULL);
1205    if (_ecore_x_window_manage_failed)
1206      {
1207         _ecore_x_window_manage_failed = 0;
1208         return EINA_FALSE;
1209      }
1210
1211    return EINA_TRUE;
1212 } /* ecore_x_window_manage */
1213
1214 EAPI void
1215 ecore_x_window_container_manage(Ecore_X_Window win)
1216 {
1217    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1218    XSelectInput(_ecore_x_disp, win,
1219                 SubstructureRedirectMask |
1220                 SubstructureNotifyMask);
1221 } /* ecore_x_window_container_manage */
1222
1223 EAPI void
1224 ecore_x_window_client_manage(Ecore_X_Window win)
1225 {
1226    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1227    XSelectInput(_ecore_x_disp, win,
1228                 PropertyChangeMask |
1229 //              ResizeRedirectMask |
1230                 FocusChangeMask |
1231                 ColormapChangeMask |
1232                 VisibilityChangeMask |
1233                 StructureNotifyMask |
1234                 SubstructureNotifyMask
1235                 );
1236    XShapeSelectInput(_ecore_x_disp, win, ShapeNotifyMask);
1237 } /* ecore_x_window_client_manage */
1238
1239 EAPI void
1240 ecore_x_window_sniff(Ecore_X_Window win)
1241 {
1242    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1243    XSelectInput(_ecore_x_disp, win,
1244                 PropertyChangeMask |
1245                 SubstructureNotifyMask);
1246 } /* ecore_x_window_sniff */
1247
1248 EAPI void
1249 ecore_x_window_client_sniff(Ecore_X_Window win)
1250 {
1251    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1252    XSelectInput(_ecore_x_disp, win,
1253                 PropertyChangeMask |
1254                 FocusChangeMask |
1255                 ColormapChangeMask |
1256                 VisibilityChangeMask |
1257                 StructureNotifyMask |
1258                 SubstructureNotifyMask);
1259    XShapeSelectInput(_ecore_x_disp, win, ShapeNotifyMask);
1260 } /* ecore_x_window_client_sniff */
1261
1262 EAPI Eina_Bool
1263 ecore_x_window_attributes_get(Ecore_X_Window             win,
1264                               Ecore_X_Window_Attributes *att_ret)
1265 {
1266    XWindowAttributes att;
1267
1268    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1269    if (!XGetWindowAttributes(_ecore_x_disp, win, &att))
1270       return EINA_FALSE;
1271
1272    memset(att_ret, 0, sizeof(Ecore_X_Window_Attributes));
1273    att_ret->root = att.root;
1274    att_ret->x = att.x;
1275    att_ret->y = att.y;
1276    att_ret->w = att.width;
1277    att_ret->h = att.height;
1278    att_ret->border = att.border_width;
1279    att_ret->depth = att.depth;
1280    if (att.map_state != IsUnmapped)
1281       att_ret->visible = 1;
1282
1283    if (att.map_state == IsViewable)
1284       att_ret->viewable = 1;
1285
1286    if (att.override_redirect)
1287       att_ret->override = 1;
1288
1289    if (att.class == InputOnly)
1290       att_ret->input_only = 1;
1291
1292    if (att.save_under)
1293       att_ret->save_under = 1;
1294
1295    att_ret->event_mask.mine = att.your_event_mask;
1296    att_ret->event_mask.all = att.all_event_masks;
1297    att_ret->event_mask.no_propagate = att.do_not_propagate_mask;
1298    att_ret->window_gravity = att.win_gravity;
1299    att_ret->pixel_gravity = att.bit_gravity;
1300    att_ret->colormap = att.colormap;
1301    att_ret->visual = att.visual;
1302    return EINA_TRUE;
1303 } /* ecore_x_window_attributes_get */
1304
1305 EAPI void
1306 ecore_x_window_save_set_add(Ecore_X_Window win)
1307 {
1308    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1309    XAddToSaveSet(_ecore_x_disp, win);
1310 } /* ecore_x_window_save_set_add */
1311
1312 EAPI void
1313 ecore_x_window_save_set_del(Ecore_X_Window win)
1314 {
1315    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1316    XRemoveFromSaveSet(_ecore_x_disp, win);
1317 } /* ecore_x_window_save_set_del */
1318
1319 EAPI Ecore_X_Window *
1320 ecore_x_window_children_get(Ecore_X_Window win, int *num)
1321 {
1322    Ecore_X_Window *windows = NULL;
1323    Window root_ret = 0, parent_ret = 0, *children_ret = NULL;
1324    unsigned int children_ret_num = 0;
1325
1326    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1327    if (!XQueryTree(_ecore_x_disp, win, &root_ret, &parent_ret, &children_ret,
1328                    &children_ret_num))
1329       return NULL;
1330
1331    if (children_ret)
1332      {
1333         windows = malloc(children_ret_num * sizeof(Ecore_X_Window));
1334         if (windows)
1335           {
1336              unsigned int i;
1337
1338              for (i = 0; i < children_ret_num; i++)
1339                 windows[i] = children_ret[i];
1340              *num = children_ret_num;
1341           }
1342
1343         XFree(children_ret);
1344      }
1345
1346    return windows;
1347 } /* ecore_x_window_children_get */
1348
1349 EAPI Eina_Bool
1350 ecore_x_pointer_control_set(int accel_num, int accel_denom, int threshold)
1351 {
1352    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1353    return XChangePointerControl(_ecore_x_disp, 1, 1,
1354                                 accel_num, accel_denom, threshold) ? EINA_TRUE : EINA_FALSE;
1355 } /* ecore_x_pointer_control_set */
1356
1357 EAPI Eina_Bool
1358 ecore_x_pointer_control_get(int *accel_num, int *accel_denom, int *threshold)
1359 {
1360    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1361    return XGetPointerControl(_ecore_x_disp,
1362                              accel_num, accel_denom, threshold) ? EINA_TRUE : EINA_FALSE;
1363 } /* ecore_x_pointer_control_get */
1364
1365 EAPI Eina_Bool
1366 ecore_x_pointer_mapping_set(unsigned char *map, int nmap)
1367 {
1368    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1369    return XSetPointerMapping(_ecore_x_disp, map, nmap) ? EINA_TRUE : EINA_FALSE;
1370 } /* ecore_x_pointer_mapping_set */
1371
1372 EAPI Eina_Bool
1373 ecore_x_pointer_mapping_get(unsigned char *map, int nmap)
1374 {
1375    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1376    return XGetPointerMapping(_ecore_x_disp, map, nmap) ? EINA_TRUE : EINA_FALSE;
1377 } /* ecore_x_pointer_mapping_get */
1378
1379 EAPI Eina_Bool
1380 ecore_x_pointer_grab(Ecore_X_Window win)
1381 {
1382    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1383    if (XGrabPointer(_ecore_x_disp, win, False,
1384                     ButtonPressMask | ButtonReleaseMask |
1385                     EnterWindowMask | LeaveWindowMask | PointerMotionMask,
1386                     GrabModeAsync, GrabModeAsync,
1387                     None, None, CurrentTime) == GrabSuccess)
1388       return EINA_TRUE;
1389
1390    return EINA_FALSE;
1391 } /* ecore_x_pointer_grab */
1392
1393 EAPI Eina_Bool
1394 ecore_x_pointer_confine_grab(Ecore_X_Window win)
1395 {
1396    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1397    if (XGrabPointer(_ecore_x_disp, win, False,
1398                     ButtonPressMask | ButtonReleaseMask |
1399                     EnterWindowMask | LeaveWindowMask | PointerMotionMask,
1400                     GrabModeAsync, GrabModeAsync,
1401                     win, None, CurrentTime) == GrabSuccess)
1402       return EINA_TRUE;
1403
1404    return EINA_FALSE;
1405 } /* ecore_x_pointer_confine_grab */
1406
1407 EAPI void
1408 ecore_x_pointer_ungrab(void)
1409 {
1410    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1411    XUngrabPointer(_ecore_x_disp, CurrentTime);
1412 } /* ecore_x_pointer_ungrab */
1413
1414 EAPI Eina_Bool
1415 ecore_x_pointer_warp(Ecore_X_Window win, int x, int y)
1416 {
1417    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1418    return XWarpPointer(_ecore_x_disp, None, win, 0, 0, 0, 0, x, y) ? EINA_TRUE : EINA_FALSE;
1419 } /* ecore_x_pointer_warp */
1420
1421 EAPI Eina_Bool
1422 ecore_x_keyboard_grab(Ecore_X_Window win)
1423 {
1424    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1425    if (XGrabKeyboard(_ecore_x_disp, win, False,
1426                      GrabModeAsync, GrabModeAsync,
1427                      CurrentTime) == GrabSuccess)
1428       return EINA_TRUE;
1429
1430    return EINA_FALSE;
1431 } /* ecore_x_keyboard_grab */
1432
1433 EAPI void
1434 ecore_x_keyboard_ungrab(void)
1435 {
1436    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1437    XUngrabKeyboard(_ecore_x_disp, CurrentTime);
1438 } /* ecore_x_keyboard_ungrab */
1439
1440 EAPI void
1441 ecore_x_grab(void)
1442 {
1443    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1444    _ecore_x_grab_count++;
1445    if (_ecore_x_grab_count == 1)
1446       XGrabServer(_ecore_x_disp);
1447 } /* ecore_x_grab */
1448
1449 EAPI void
1450 ecore_x_ungrab(void)
1451 {
1452    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1453    _ecore_x_grab_count--;
1454    if (_ecore_x_grab_count < 0)
1455       _ecore_x_grab_count = 0;
1456
1457    if (_ecore_x_grab_count == 0)
1458       XUngrabServer(_ecore_x_disp);
1459 } /* ecore_x_ungrab */
1460
1461 int _ecore_window_grabs_num = 0;
1462 Window *_ecore_window_grabs = NULL;
1463 Eina_Bool (*_ecore_window_grab_replay_func)(void *data, int event_type,
1464                                             void *event);
1465 void *_ecore_window_grab_replay_data;
1466
1467 EAPI void
1468 ecore_x_passive_grab_replay_func_set(Eina_Bool (*func)(void *data,
1469                                                        int event_type,
1470                                                        void *event), void *data)
1471 {
1472    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1473    _ecore_window_grab_replay_func = func;
1474    _ecore_window_grab_replay_data = data;
1475 } /* ecore_x_passive_grab_replay_func_set */
1476
1477 EAPI void
1478 ecore_x_window_button_grab(Ecore_X_Window win, int button,
1479                            Ecore_X_Event_Mask event_mask,
1480                            int mod, int any_mod)
1481 {
1482    unsigned int b;
1483    unsigned int m;
1484    unsigned int locks[8];
1485    int i, ev;
1486
1487    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1488    b = button;
1489    if (b == 0)
1490       b = AnyButton;
1491
1492    m = _ecore_x_event_modifier(mod);
1493    if (any_mod)
1494       m = AnyModifier;
1495
1496    locks[0] = 0;
1497    locks[1] = ECORE_X_LOCK_CAPS;
1498    locks[2] = ECORE_X_LOCK_NUM;
1499    locks[3] = ECORE_X_LOCK_SCROLL;
1500    locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM;
1501    locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL;
1502    locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1503    locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1504    ev = event_mask;
1505    for (i = 0; i < 8; i++)
1506       XGrabButton(_ecore_x_disp, b, m | locks[i],
1507                   win, False, ev, GrabModeSync, GrabModeAsync, None, None);
1508    _ecore_window_grabs_num++;
1509    _ecore_window_grabs = realloc(_ecore_window_grabs,
1510                                  _ecore_window_grabs_num * sizeof(Window));
1511    _ecore_window_grabs[_ecore_window_grabs_num - 1] = win;
1512 } /* ecore_x_window_button_grab */
1513
1514 void
1515 _ecore_x_sync_magic_send(int val, Ecore_X_Window swin)
1516 {
1517    XEvent xev;
1518
1519    xev.xclient.type = ClientMessage;
1520    xev.xclient.serial = 0;
1521    xev.xclient.send_event = True;
1522    xev.xclient.display = _ecore_x_disp;
1523    xev.xclient.window = _ecore_x_private_win;
1524    xev.xclient.format = 32;
1525    xev.xclient.message_type = 27777;
1526    xev.xclient.data.l[0] = 0x7162534;
1527    xev.xclient.data.l[1] = 0x10000000 + val;
1528    xev.xclient.data.l[2] = swin;
1529    XSendEvent(_ecore_x_disp, _ecore_x_private_win, False, NoEventMask, &xev);
1530 } /* _ecore_x_sync_magic_send */
1531
1532 void
1533 _ecore_x_window_grab_remove(Ecore_X_Window win)
1534 {
1535    int i, shuffle = 0;
1536
1537    if (_ecore_window_grabs_num > 0)
1538      {
1539         for (i = 0; i < _ecore_window_grabs_num; i++)
1540           {
1541              if (shuffle)
1542                 _ecore_window_grabs[i - 1] = _ecore_window_grabs[i];
1543
1544              if ((!shuffle) && (_ecore_window_grabs[i] == win))
1545                 shuffle = 1;
1546           }
1547         if (shuffle)
1548           {
1549              _ecore_window_grabs_num--;
1550              _ecore_window_grabs = realloc(_ecore_window_grabs,
1551                                            _ecore_window_grabs_num *
1552                                            sizeof(Window));
1553           }
1554      }
1555 } /* _ecore_x_window_grab_remove */
1556
1557 EAPI void
1558 ecore_x_window_button_ungrab(Ecore_X_Window win, int button,
1559                              int mod, int any_mod)
1560 {
1561    unsigned int b;
1562    unsigned int m;
1563    unsigned int locks[8];
1564    int i;
1565
1566    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1567    b = button;
1568    if (b == 0)
1569       b = AnyButton;
1570
1571    m = _ecore_x_event_modifier(mod);
1572    if (any_mod)
1573       m = AnyModifier;
1574
1575    locks[0] = 0;
1576    locks[1] = ECORE_X_LOCK_CAPS;
1577    locks[2] = ECORE_X_LOCK_NUM;
1578    locks[3] = ECORE_X_LOCK_SCROLL;
1579    locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM;
1580    locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL;
1581    locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1582    locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1583    for (i = 0; i < 8; i++)
1584       XUngrabButton(_ecore_x_disp, b, m | locks[i], win);
1585    _ecore_x_sync_magic_send(1, win);
1586 } /* ecore_x_window_button_ungrab */
1587
1588 int _ecore_key_grabs_num = 0;
1589 Window *_ecore_key_grabs = NULL;
1590
1591 EAPI void
1592 ecore_x_window_key_grab(Ecore_X_Window win, const char *key,
1593                         int mod, int any_mod)
1594 {
1595    KeyCode keycode = 0;
1596    KeySym keysym;
1597    unsigned int m;
1598    unsigned int locks[8];
1599    int i;
1600
1601    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1602    if (!strncmp(key, "Keycode-", 8))
1603       keycode = atoi(key + 8);
1604    else
1605      {
1606         keysym = XStringToKeysym(key);
1607         if (keysym == NoSymbol)
1608            return;
1609
1610         keycode = XKeysymToKeycode(_ecore_x_disp, XStringToKeysym(key));
1611      }
1612
1613    if (keycode == 0)
1614       return;
1615
1616    m = _ecore_x_event_modifier(mod);
1617    if (any_mod)
1618       m = AnyModifier;
1619
1620    locks[0] = 0;
1621    locks[1] = ECORE_X_LOCK_CAPS;
1622    locks[2] = ECORE_X_LOCK_NUM;
1623    locks[3] = ECORE_X_LOCK_SCROLL;
1624    locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM;
1625    locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL;
1626    locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1627    locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1628    for (i = 0; i < 8; i++)
1629       XGrabKey(_ecore_x_disp, keycode, m | locks[i],
1630                win, False, GrabModeSync, GrabModeAsync);
1631    _ecore_key_grabs_num++;
1632    _ecore_key_grabs = realloc(_ecore_key_grabs,
1633                               _ecore_key_grabs_num * sizeof(Window));
1634    _ecore_key_grabs[_ecore_key_grabs_num - 1] = win;
1635 } /* ecore_x_window_key_grab */
1636
1637 void
1638 _ecore_x_key_grab_remove(Ecore_X_Window win)
1639 {
1640    int i, shuffle = 0;
1641
1642    if (_ecore_key_grabs_num > 0)
1643      {
1644         for (i = 0; i < _ecore_key_grabs_num; i++)
1645           {
1646              if (shuffle)
1647                 _ecore_key_grabs[i - 1] = _ecore_key_grabs[i];
1648
1649              if ((!shuffle) && (_ecore_key_grabs[i] == win))
1650                 shuffle = 1;
1651           }
1652         if (shuffle)
1653           {
1654              _ecore_key_grabs_num--;
1655              _ecore_key_grabs = realloc(_ecore_key_grabs,
1656                                         _ecore_key_grabs_num * sizeof(Window));
1657           }
1658      }
1659 } /* _ecore_x_key_grab_remove */
1660
1661 EAPI void
1662 ecore_x_window_key_ungrab(Ecore_X_Window win, const char *key,
1663                           int mod, int any_mod)
1664 {
1665    KeyCode keycode = 0;
1666    KeySym keysym;
1667    unsigned int m;
1668    unsigned int locks[8];
1669    int i;
1670
1671    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1672    if (!strncmp(key, "Keycode-", 8))
1673       keycode = atoi(key + 8);
1674    else
1675      {
1676         keysym = XStringToKeysym(key);
1677         if (keysym == NoSymbol)
1678            return;
1679
1680         keycode = XKeysymToKeycode(_ecore_x_disp, XStringToKeysym(key));
1681      }
1682
1683    if (keycode == 0)
1684       return;
1685
1686    m = _ecore_x_event_modifier(mod);
1687    if (any_mod)
1688       m = AnyModifier;
1689
1690    locks[0] = 0;
1691    locks[1] = ECORE_X_LOCK_CAPS;
1692    locks[2] = ECORE_X_LOCK_NUM;
1693    locks[3] = ECORE_X_LOCK_SCROLL;
1694    locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM;
1695    locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL;
1696    locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1697    locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL;
1698    for (i = 0; i < 8; i++)
1699       XUngrabKey(_ecore_x_disp, keycode, m | locks[i], win);
1700    _ecore_x_sync_magic_send(2, win);
1701 } /* ecore_x_window_key_ungrab */
1702
1703 /**
1704  * Send client message with given type and format 32.
1705  *
1706  * @param win     The window the message is sent to.
1707  * @param type    The client message type.
1708  * @param d0      The client message data item 1
1709  * @param d1      The client message data item 2
1710  * @param d2      The client message data item 3
1711  * @param d3      The client message data item 4
1712  * @param d4      The client message data item 5
1713  *
1714  * @return EINA_TRUE on success EINA_FALSE otherwise.
1715  */
1716 EAPI Eina_Bool
1717 ecore_x_client_message32_send(Ecore_X_Window win, Ecore_X_Atom type,
1718                               Ecore_X_Event_Mask mask,
1719                               long d0, long d1, long d2, long d3, long d4)
1720 {
1721    XEvent xev;
1722
1723    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1724    xev.xclient.window = win;
1725    xev.xclient.type = ClientMessage;
1726    xev.xclient.message_type = type;
1727    xev.xclient.format = 32;
1728    xev.xclient.data.l[0] = d0;
1729    xev.xclient.data.l[1] = d1;
1730    xev.xclient.data.l[2] = d2;
1731    xev.xclient.data.l[3] = d3;
1732    xev.xclient.data.l[4] = d4;
1733
1734    return XSendEvent(_ecore_x_disp, win, False, mask, &xev) ? EINA_TRUE : EINA_FALSE;
1735 } /* ecore_x_client_message32_send */
1736
1737 /**
1738  * Send client message with given type and format 8.
1739  *
1740  * @param win     The window the message is sent to.
1741  * @param type    The client message type.
1742  * @param data    Data to be sent.
1743  * @param len     Number of data bytes, max 20.
1744  *
1745  * @return EINA_TRUE on success EINA_FALSE otherwise.
1746  */
1747 EAPI Eina_Bool
1748 ecore_x_client_message8_send(Ecore_X_Window win, Ecore_X_Atom type,
1749                              const void *data, int len)
1750 {
1751    XEvent xev;
1752
1753    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1754    xev.xclient.window = win;
1755    xev.xclient.type = ClientMessage;
1756    xev.xclient.message_type = type;
1757    xev.xclient.format = 8;
1758    if (len > 20)
1759       len = 20;
1760
1761    memcpy(xev.xclient.data.b, data, len);
1762    memset(xev.xclient.data.b + len, 0, 20 - len);
1763
1764    return XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev) ? EINA_TRUE : EINA_FALSE;
1765 } /* ecore_x_client_message8_send */
1766
1767 EAPI Eina_Bool
1768 ecore_x_mouse_move_send(Ecore_X_Window win, int x, int y)
1769 {
1770    XEvent xev;
1771    XWindowAttributes att;
1772    Window tw;
1773    int rx, ry;
1774
1775    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1776    XGetWindowAttributes(_ecore_x_disp, win, &att);
1777    XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw);
1778    xev.xmotion.type = MotionNotify;
1779    xev.xmotion.window = win;
1780    xev.xmotion.root = att.root;
1781    xev.xmotion.subwindow = win;
1782    xev.xmotion.time = _ecore_x_event_last_time;
1783    xev.xmotion.x = x;
1784    xev.xmotion.y = y;
1785    xev.xmotion.x_root = rx;
1786    xev.xmotion.y_root = ry;
1787    xev.xmotion.state = 0;
1788    xev.xmotion.is_hint = 0;
1789    xev.xmotion.same_screen = 1;
1790    return XSendEvent(_ecore_x_disp, win, True, PointerMotionMask, &xev) ? EINA_TRUE : EINA_FALSE;
1791 } /* ecore_x_mouse_move_send */
1792
1793 EAPI Eina_Bool
1794 ecore_x_mouse_down_send(Ecore_X_Window win, int x, int y, int b)
1795 {
1796    XEvent xev;
1797    XWindowAttributes att;
1798    Window tw;
1799    int rx, ry;
1800
1801    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1802    XGetWindowAttributes(_ecore_x_disp, win, &att);
1803    XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw);
1804    xev.xbutton.type = ButtonPress;
1805    xev.xbutton.window = win;
1806    xev.xbutton.root = att.root;
1807    xev.xbutton.subwindow = win;
1808    xev.xbutton.time = _ecore_x_event_last_time;
1809    xev.xbutton.x = x;
1810    xev.xbutton.y = y;
1811    xev.xbutton.x_root = rx;
1812    xev.xbutton.y_root = ry;
1813    xev.xbutton.state = 1 << b;
1814    xev.xbutton.button = b;
1815    xev.xbutton.same_screen = 1;
1816    return XSendEvent(_ecore_x_disp, win, True, ButtonPressMask, &xev) ? EINA_TRUE : EINA_FALSE;
1817 } /* ecore_x_mouse_down_send */
1818
1819 EAPI Eina_Bool
1820 ecore_x_mouse_up_send(Ecore_X_Window win, int x, int y, int b)
1821 {
1822    XEvent xev;
1823    XWindowAttributes att;
1824    Window tw;
1825    int rx, ry;
1826
1827    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1828    XGetWindowAttributes(_ecore_x_disp, win, &att);
1829    XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw);
1830    xev.xbutton.type = ButtonRelease;
1831    xev.xbutton.window = win;
1832    xev.xbutton.root = att.root;
1833    xev.xbutton.subwindow = win;
1834    xev.xbutton.time = _ecore_x_event_last_time;
1835    xev.xbutton.x = x;
1836    xev.xbutton.y = y;
1837    xev.xbutton.x_root = rx;
1838    xev.xbutton.y_root = ry;
1839    xev.xbutton.state = 0;
1840    xev.xbutton.button = b;
1841    xev.xbutton.same_screen = 1;
1842    return XSendEvent(_ecore_x_disp, win, True, ButtonReleaseMask, &xev) ? EINA_TRUE : EINA_FALSE;
1843 } /* ecore_x_mouse_up_send */
1844
1845 EAPI void
1846 ecore_x_focus_reset(void)
1847 {
1848    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1849    XSetInputFocus(_ecore_x_disp, PointerRoot, RevertToPointerRoot, CurrentTime);
1850 } /* ecore_x_focus_reset */
1851
1852 EAPI void
1853 ecore_x_events_allow_all(void)
1854 {
1855    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1856    XAllowEvents(_ecore_x_disp, AsyncBoth, CurrentTime);
1857 } /* ecore_x_events_allow_all */
1858
1859 EAPI void
1860 ecore_x_pointer_last_xy_get(int *x, int *y)
1861 {
1862    if (x)
1863       *x = _ecore_x_event_last_root_x;
1864
1865    if (y)
1866       *y = _ecore_x_event_last_root_y;
1867 } /* ecore_x_pointer_last_xy_get */
1868
1869 EAPI void
1870 ecore_x_pointer_xy_get(Ecore_X_Window win, int *x, int *y)
1871 {
1872    Window rwin, cwin;
1873    int rx, ry, wx, wy, ret;
1874    unsigned int mask;
1875
1876    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1877    ret = XQueryPointer(_ecore_x_disp,
1878                        win,
1879                        &rwin,
1880                        &cwin,
1881                        &rx,
1882                        &ry,
1883                        &wx,
1884                        &wy,
1885                        &mask);
1886    if (!ret)
1887       wx = wy = -1;
1888
1889    if (x)
1890       *x = wx;
1891
1892    if (y)
1893       *y = wy;
1894 } /* ecore_x_pointer_xy_get */
1895
1896 /*****************************************************************************/
1897 /*****************************************************************************/
1898 /*****************************************************************************/
1899
1900 static int
1901 _ecore_x_event_modifier(unsigned int state)
1902 {
1903    int xmodifiers = 0;
1904
1905    if (state & ECORE_EVENT_MODIFIER_SHIFT)
1906       xmodifiers |= ECORE_X_MODIFIER_SHIFT;
1907
1908    if (state & ECORE_EVENT_MODIFIER_CTRL)
1909       xmodifiers |= ECORE_X_MODIFIER_CTRL;
1910
1911    if (state & ECORE_EVENT_MODIFIER_ALT)
1912       xmodifiers |= ECORE_X_MODIFIER_ALT;
1913
1914    if (state & ECORE_EVENT_MODIFIER_WIN)
1915       xmodifiers |= ECORE_X_MODIFIER_WIN;
1916
1917    if (state & ECORE_EVENT_LOCK_SCROLL)
1918       xmodifiers |= ECORE_X_LOCK_SCROLL;
1919
1920    if (state & ECORE_EVENT_LOCK_NUM)
1921       xmodifiers |= ECORE_X_LOCK_NUM;
1922
1923    if (state & ECORE_EVENT_LOCK_CAPS)
1924       xmodifiers |= ECORE_X_LOCK_CAPS;
1925
1926    return xmodifiers;
1927 } /* _ecore_x_event_modifier */
1928