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