8a1eb1b2810094e31c049fbc45e2192a6d154ab1
[profile/ivi/ecore.git] / src / lib / ecore_x / xlib / ecore_x.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4 #include "ecore_private.h"
5 #include "Ecore.h"
6 #include "ecore_x_private.h"
7 #include "Ecore_X.h"
8 #include "Ecore_X_Atoms.h"
9
10 static int _ecore_x_fd_handler(void *data, Ecore_Fd_Handler *fd_handler);
11 static int _ecore_x_fd_handler_buf(void *data, Ecore_Fd_Handler *fd_handler);
12 static int _ecore_x_key_mask_get(KeySym sym);
13
14 static Ecore_Fd_Handler *_ecore_x_fd_handler_handle = NULL;
15 static int _ecore_x_event_shape_id = 0;
16 static int _ecore_x_event_screensaver_id = 0;
17 static int _ecore_x_event_sync_id = 0;
18 #ifdef ECORE_XRANDR
19 static int _ecore_x_event_randr_id = 0;
20 #endif
21 #ifdef ECORE_XFIXES
22 static int _ecore_x_event_fixes_selection_id = 0;
23 #endif
24 #ifdef ECORE_XDAMAGE
25 static int _ecore_x_event_damage_id = 0;
26 #endif
27 static int _ecore_x_event_handlers_num = 0;
28 static void (**_ecore_x_event_handlers) (XEvent * event) = NULL;
29
30 static int _ecore_x_init_count = 0;
31 static int _ecore_x_grab_count = 0;
32
33 Display *_ecore_x_disp = NULL;
34 double   _ecore_x_double_click_time = 0.25;
35 Time     _ecore_x_event_last_time = 0;
36 Window   _ecore_x_event_last_win = 0;
37 int      _ecore_x_event_last_root_x = 0;
38 int      _ecore_x_event_last_root_y = 0;
39 int      _ecore_x_xcursor = 0;
40
41 Ecore_X_Window _ecore_x_private_win = 0;
42
43 Ecore_X_Atom _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_NUM];
44
45 EAPI int ECORE_X_EVENT_KEY_DOWN = 0;
46 EAPI int ECORE_X_EVENT_KEY_UP = 0;
47 EAPI int ECORE_X_EVENT_MOUSE_BUTTON_DOWN = 0;
48 EAPI int ECORE_X_EVENT_MOUSE_BUTTON_UP = 0;
49 EAPI int ECORE_X_EVENT_MOUSE_MOVE = 0;
50 EAPI int ECORE_X_EVENT_MOUSE_IN = 0;
51 EAPI int ECORE_X_EVENT_MOUSE_OUT = 0;
52 EAPI int ECORE_X_EVENT_MOUSE_WHEEL = 0;
53 EAPI int ECORE_X_EVENT_WINDOW_FOCUS_IN = 0;
54 EAPI int ECORE_X_EVENT_WINDOW_FOCUS_OUT = 0;
55 EAPI int ECORE_X_EVENT_WINDOW_KEYMAP = 0;
56 EAPI int ECORE_X_EVENT_WINDOW_DAMAGE = 0;
57 EAPI int ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = 0;
58 EAPI int ECORE_X_EVENT_WINDOW_CREATE = 0;
59 EAPI int ECORE_X_EVENT_WINDOW_DESTROY = 0;
60 EAPI int ECORE_X_EVENT_WINDOW_HIDE = 0;
61 EAPI int ECORE_X_EVENT_WINDOW_SHOW = 0;
62 EAPI int ECORE_X_EVENT_WINDOW_SHOW_REQUEST = 0;
63 EAPI int ECORE_X_EVENT_WINDOW_REPARENT = 0;
64 EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE = 0;
65 EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = 0;
66 EAPI int ECORE_X_EVENT_WINDOW_GRAVITY = 0;
67 EAPI int ECORE_X_EVENT_WINDOW_RESIZE_REQUEST = 0;
68 EAPI int ECORE_X_EVENT_WINDOW_STACK = 0;
69 EAPI int ECORE_X_EVENT_WINDOW_STACK_REQUEST = 0;
70 EAPI int ECORE_X_EVENT_WINDOW_PROPERTY = 0;
71 EAPI int ECORE_X_EVENT_WINDOW_COLORMAP = 0;
72 EAPI int ECORE_X_EVENT_WINDOW_MAPPING = 0;
73 EAPI int ECORE_X_EVENT_SELECTION_CLEAR = 0;
74 EAPI int ECORE_X_EVENT_SELECTION_REQUEST = 0;
75 EAPI int ECORE_X_EVENT_SELECTION_NOTIFY = 0;
76 EAPI int ECORE_X_EVENT_CLIENT_MESSAGE = 0;
77 EAPI int ECORE_X_EVENT_WINDOW_SHAPE = 0;
78 EAPI int ECORE_X_EVENT_SCREENSAVER_NOTIFY = 0;
79 EAPI int ECORE_X_EVENT_SYNC_COUNTER = 0;
80 EAPI int ECORE_X_EVENT_SYNC_ALARM = 0;
81 EAPI int ECORE_X_EVENT_SCREEN_CHANGE = 0;
82 EAPI int ECORE_X_EVENT_DAMAGE_NOTIFY = 0;
83
84 EAPI int ECORE_X_EVENT_WINDOW_DELETE_REQUEST = 0;
85 /*
86 EAPI int ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE = 0;
87 EAPI int ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE = 0;
88 EAPI int ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE = 0;
89 EAPI int ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE = 0;
90 EAPI int ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE = 0;
91 EAPI int ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE = 0;
92 EAPI int ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE = 0;
93 EAPI int ECORE_X_EVENT_WINDOW_PROP_DESKTOP_CHANGE = 0;
94 */
95
96 EAPI int ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = 0;
97 EAPI int ECORE_X_EVENT_WINDOW_STATE_REQUEST = 0;
98 EAPI int ECORE_X_EVENT_FRAME_EXTENTS_REQUEST = 0;
99 EAPI int ECORE_X_EVENT_PING = 0;
100 EAPI int ECORE_X_EVENT_DESKTOP_CHANGE = 0;
101
102 EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_NEW = 0;
103 EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE = 0;
104 EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE = 0;
105
106 EAPI int ECORE_X_MODIFIER_SHIFT = 0;
107 EAPI int ECORE_X_MODIFIER_CTRL = 0;
108 EAPI int ECORE_X_MODIFIER_ALT = 0;
109 EAPI int ECORE_X_MODIFIER_WIN = 0;
110
111 EAPI int ECORE_X_LOCK_SCROLL = 0;
112 EAPI int ECORE_X_LOCK_NUM = 0;
113 EAPI int ECORE_X_LOCK_CAPS = 0;
114
115 /**
116  * @defgroup Ecore_X_Init_Group X Library Init and Shutdown Functions
117  *
118  * Functions that start and shut down the Ecore X Library.
119  */
120
121 /**
122  * Initialize the X display connection to the given display.
123  *
124  * @param   name Display target name.  If @c NULL, the default display is
125  *               assumed.
126  * @return  The number of times the library has been initialized without
127  *          being shut down.  0 is returned if an error occurs.
128  * @ingroup Ecore_X_Init_Group
129  */
130 EAPI int
131 ecore_x_init(const char *name)
132 {
133    int shape_base = 0;
134    int shape_err_base = 0;
135 #ifdef ECORE_XSS
136    int screensaver_base = 0;
137    int screensaver_err_base = 0;
138 #endif
139    int sync_base = 0;
140    int sync_err_base = 0;
141 #ifdef ECORE_XRANDR
142    int randr_base = 0;
143    int randr_err_base = 0;
144 #endif
145 #ifdef ECORE_XFIXES
146    int fixes_base = 0;
147    int fixes_err_base = 0;
148 #endif
149 #ifdef ECORE_XDAMAGE
150    int damage_base = 0;
151    int damage_err_base = 0;
152 #endif
153    
154    if (_ecore_x_init_count > 0) 
155      {
156         _ecore_x_init_count++;
157         return _ecore_x_init_count;
158      }
159    _ecore_x_disp = XOpenDisplay((char *)name);
160    if (!_ecore_x_disp) return 0;
161    _ecore_x_error_handler_init();
162    _ecore_x_event_handlers_num = LASTEvent;
163    
164    if (XShapeQueryExtension(_ecore_x_disp, &shape_base, &shape_err_base))
165      _ecore_x_event_shape_id = shape_base + ShapeNotify;
166    if (_ecore_x_event_shape_id >= _ecore_x_event_handlers_num)
167      _ecore_x_event_handlers_num = _ecore_x_event_shape_id + 1;
168    
169 #ifdef ECORE_XSS
170    if (XScreenSaverQueryExtension(_ecore_x_disp, &screensaver_base, &screensaver_err_base))
171      _ecore_x_event_screensaver_id = screensaver_base + ScreenSaverNotify;
172 #endif   
173    if (_ecore_x_event_screensaver_id >= _ecore_x_event_handlers_num)
174      _ecore_x_event_handlers_num = _ecore_x_event_screensaver_id + 1;
175    
176    if (XSyncQueryExtension(_ecore_x_disp, &sync_base, &sync_err_base))
177      {
178         int major, minor;
179
180         _ecore_x_event_sync_id = sync_base;
181         if (!XSyncInitialize(_ecore_x_disp, &major, &minor))
182           _ecore_x_event_sync_id = 0;
183      }
184    if (_ecore_x_event_sync_id + XSyncAlarmNotify >= _ecore_x_event_handlers_num)
185      _ecore_x_event_handlers_num = _ecore_x_event_sync_id + XSyncAlarmNotify + 1;
186    
187 #ifdef ECORE_XRANDR
188    if (XRRQueryExtension(_ecore_x_disp, &randr_base, &randr_err_base))
189      _ecore_x_event_randr_id = randr_base + RRScreenChangeNotify;
190    if (_ecore_x_event_randr_id >= _ecore_x_event_handlers_num)
191      _ecore_x_event_handlers_num = _ecore_x_event_randr_id + 1;
192 #endif
193
194 #ifdef ECORE_XFIXES
195    if (XFixesQueryExtension(_ecore_x_disp, &fixes_base, &fixes_err_base))
196      _ecore_x_event_fixes_selection_id = fixes_base + XFixesSelectionNotify;
197    if (_ecore_x_event_fixes_selection_id >= _ecore_x_event_handlers_num)
198      _ecore_x_event_handlers_num = _ecore_x_event_fixes_selection_id + 1;
199 #endif
200
201 #ifdef ECORE_XDAMAGE
202    if (XDamageQueryExtension(_ecore_x_disp, &damage_base, &damage_err_base))
203      _ecore_x_event_damage_id = damage_base + XDamageNotify;
204    if (_ecore_x_event_damage_id >= _ecore_x_event_handlers_num)
205      _ecore_x_event_handlers_num = _ecore_x_event_damage_id + 1;
206 #endif
207
208    _ecore_x_event_handlers = calloc(_ecore_x_event_handlers_num, sizeof(void *));
209    if (!_ecore_x_event_handlers)
210      {
211         XCloseDisplay(_ecore_x_disp);
212         _ecore_x_fd_handler_handle = NULL;
213         _ecore_x_disp = NULL;
214         return 0;       
215      }
216 #ifdef ECORE_XCURSOR   
217    _ecore_x_xcursor = XcursorSupportsARGB(_ecore_x_disp);
218 #endif
219    _ecore_x_event_handlers[KeyPress]         = _ecore_x_event_handle_key_press;
220    _ecore_x_event_handlers[KeyRelease]       = _ecore_x_event_handle_key_release;
221    _ecore_x_event_handlers[ButtonPress]      = _ecore_x_event_handle_button_press;
222    _ecore_x_event_handlers[ButtonRelease]    = _ecore_x_event_handle_button_release;
223    _ecore_x_event_handlers[MotionNotify]     = _ecore_x_event_handle_motion_notify;
224    _ecore_x_event_handlers[EnterNotify]      = _ecore_x_event_handle_enter_notify;
225    _ecore_x_event_handlers[LeaveNotify]      = _ecore_x_event_handle_leave_notify;
226    _ecore_x_event_handlers[FocusIn]          = _ecore_x_event_handle_focus_in;
227    _ecore_x_event_handlers[FocusOut]         = _ecore_x_event_handle_focus_out;
228    _ecore_x_event_handlers[KeymapNotify]     = _ecore_x_event_handle_keymap_notify;
229    _ecore_x_event_handlers[Expose]           = _ecore_x_event_handle_expose;
230    _ecore_x_event_handlers[GraphicsExpose]   = _ecore_x_event_handle_graphics_expose;
231    _ecore_x_event_handlers[VisibilityNotify] = _ecore_x_event_handle_visibility_notify;
232    _ecore_x_event_handlers[CreateNotify]     = _ecore_x_event_handle_create_notify;
233    _ecore_x_event_handlers[DestroyNotify]    = _ecore_x_event_handle_destroy_notify;
234    _ecore_x_event_handlers[UnmapNotify]      = _ecore_x_event_handle_unmap_notify;
235    _ecore_x_event_handlers[MapNotify]        = _ecore_x_event_handle_map_notify;
236    _ecore_x_event_handlers[MapRequest]       = _ecore_x_event_handle_map_request;
237    _ecore_x_event_handlers[ReparentNotify]   = _ecore_x_event_handle_reparent_notify;
238    _ecore_x_event_handlers[ConfigureNotify]  = _ecore_x_event_handle_configure_notify;
239    _ecore_x_event_handlers[ConfigureRequest] = _ecore_x_event_handle_configure_request;
240    _ecore_x_event_handlers[GravityNotify]    = _ecore_x_event_handle_gravity_notify;
241    _ecore_x_event_handlers[ResizeRequest]    = _ecore_x_event_handle_resize_request;
242    _ecore_x_event_handlers[CirculateNotify]  = _ecore_x_event_handle_circulate_notify;
243    _ecore_x_event_handlers[CirculateRequest] = _ecore_x_event_handle_circulate_request;
244    _ecore_x_event_handlers[PropertyNotify]   = _ecore_x_event_handle_property_notify;
245    _ecore_x_event_handlers[SelectionClear]   = _ecore_x_event_handle_selection_clear;
246    _ecore_x_event_handlers[SelectionRequest] = _ecore_x_event_handle_selection_request;
247    _ecore_x_event_handlers[SelectionNotify]  = _ecore_x_event_handle_selection_notify;
248    _ecore_x_event_handlers[ColormapNotify]   = _ecore_x_event_handle_colormap_notify;
249    _ecore_x_event_handlers[ClientMessage]    = _ecore_x_event_handle_client_message;
250    _ecore_x_event_handlers[MappingNotify]    = _ecore_x_event_handle_mapping_notify;
251    if (_ecore_x_event_shape_id)
252      _ecore_x_event_handlers[_ecore_x_event_shape_id] = _ecore_x_event_handle_shape_change;
253    if (_ecore_x_event_screensaver_id)
254      _ecore_x_event_handlers[_ecore_x_event_screensaver_id] = _ecore_x_event_handle_screensaver_notify;
255    if (_ecore_x_event_sync_id)
256      {
257         _ecore_x_event_handlers[_ecore_x_event_sync_id + XSyncCounterNotify] =
258            _ecore_x_event_handle_sync_counter;
259         _ecore_x_event_handlers[_ecore_x_event_sync_id + XSyncAlarmNotify] =
260            _ecore_x_event_handle_sync_alarm;
261      }
262 #ifdef ECORE_XRANDR
263    if (_ecore_x_event_randr_id)
264      _ecore_x_event_handlers[_ecore_x_event_randr_id] = _ecore_x_event_handle_randr_change;
265 #endif
266 #ifdef ECORE_XFIXES
267    if (_ecore_x_event_fixes_selection_id)
268      _ecore_x_event_handlers[_ecore_x_event_fixes_selection_id] = _ecore_x_event_handle_fixes_selection_notify;
269 #endif
270 #ifdef ECORE_XDAMAGE
271    if (_ecore_x_event_damage_id)
272      _ecore_x_event_handlers[_ecore_x_event_damage_id] = _ecore_x_event_handle_damage_notify;
273 #endif
274
275    if (!ECORE_X_EVENT_KEY_DOWN)
276      {
277         ECORE_X_EVENT_KEY_DOWN                 = ecore_event_type_new();
278         ECORE_X_EVENT_KEY_UP                   = ecore_event_type_new();
279         ECORE_X_EVENT_MOUSE_BUTTON_DOWN        = ecore_event_type_new();
280         ECORE_X_EVENT_MOUSE_BUTTON_UP          = ecore_event_type_new();
281         ECORE_X_EVENT_MOUSE_MOVE               = ecore_event_type_new();
282         ECORE_X_EVENT_MOUSE_IN                 = ecore_event_type_new();
283         ECORE_X_EVENT_MOUSE_OUT                = ecore_event_type_new();
284         ECORE_X_EVENT_MOUSE_WHEEL              = ecore_event_type_new();
285         ECORE_X_EVENT_WINDOW_FOCUS_IN          = ecore_event_type_new();
286         ECORE_X_EVENT_WINDOW_FOCUS_OUT         = ecore_event_type_new();
287         ECORE_X_EVENT_WINDOW_KEYMAP            = ecore_event_type_new();
288         ECORE_X_EVENT_WINDOW_DAMAGE            = ecore_event_type_new();
289         ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = ecore_event_type_new();
290         ECORE_X_EVENT_WINDOW_CREATE            = ecore_event_type_new();
291         ECORE_X_EVENT_WINDOW_DESTROY           = ecore_event_type_new();
292         ECORE_X_EVENT_WINDOW_HIDE              = ecore_event_type_new();
293         ECORE_X_EVENT_WINDOW_SHOW              = ecore_event_type_new();
294         ECORE_X_EVENT_WINDOW_SHOW_REQUEST      = ecore_event_type_new();
295         ECORE_X_EVENT_WINDOW_REPARENT          = ecore_event_type_new();
296         ECORE_X_EVENT_WINDOW_CONFIGURE         = ecore_event_type_new();
297         ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = ecore_event_type_new();
298         ECORE_X_EVENT_WINDOW_GRAVITY           = ecore_event_type_new();
299         ECORE_X_EVENT_WINDOW_RESIZE_REQUEST    = ecore_event_type_new();
300         ECORE_X_EVENT_WINDOW_STACK             = ecore_event_type_new();
301         ECORE_X_EVENT_WINDOW_STACK_REQUEST     = ecore_event_type_new();
302         ECORE_X_EVENT_WINDOW_PROPERTY          = ecore_event_type_new();
303         ECORE_X_EVENT_WINDOW_COLORMAP          = ecore_event_type_new();
304         ECORE_X_EVENT_WINDOW_MAPPING           = ecore_event_type_new();
305         ECORE_X_EVENT_SELECTION_CLEAR          = ecore_event_type_new();
306         ECORE_X_EVENT_SELECTION_REQUEST        = ecore_event_type_new();
307         ECORE_X_EVENT_SELECTION_NOTIFY         = ecore_event_type_new();
308         ECORE_X_EVENT_CLIENT_MESSAGE           = ecore_event_type_new();
309         ECORE_X_EVENT_WINDOW_SHAPE             = ecore_event_type_new();
310         ECORE_X_EVENT_SCREENSAVER_NOTIFY       = ecore_event_type_new();
311         ECORE_X_EVENT_SYNC_COUNTER             = ecore_event_type_new();
312         ECORE_X_EVENT_SYNC_ALARM               = ecore_event_type_new();
313         ECORE_X_EVENT_SCREEN_CHANGE            = ecore_event_type_new();
314         ECORE_X_EVENT_DAMAGE_NOTIFY            = ecore_event_type_new();
315         
316         ECORE_X_EVENT_WINDOW_DELETE_REQUEST                = ecore_event_type_new();
317         /*
318         ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE             = ecore_event_type_new();
319         ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE     = ecore_event_type_new();
320         ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE        = ecore_event_type_new();
321         ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE         = ecore_event_type_new();
322         ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE = ecore_event_type_new();
323         ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE    = ecore_event_type_new();
324         ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE               = ecore_event_type_new();
325         ECORE_X_EVENT_WINDOW_PROP_DESKTOP_CHANGE           = ecore_event_type_new();
326         */
327
328         ECORE_X_EVENT_DESKTOP_CHANGE           = ecore_event_type_new();
329         ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = ecore_event_type_new();
330         ECORE_X_EVENT_WINDOW_STATE_REQUEST     = ecore_event_type_new();
331         ECORE_X_EVENT_FRAME_EXTENTS_REQUEST    = ecore_event_type_new();
332         ECORE_X_EVENT_PING                     = ecore_event_type_new();
333
334         ECORE_X_EVENT_STARTUP_SEQUENCE_NEW     = ecore_event_type_new();
335         ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE  = ecore_event_type_new();
336         ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE  = ecore_event_type_new();
337      }
338    
339    /* everything has these... unless its like a pda... :) */
340    ECORE_X_MODIFIER_SHIFT = _ecore_x_key_mask_get(XK_Shift_L);
341    ECORE_X_MODIFIER_CTRL  = _ecore_x_key_mask_get(XK_Control_L);
342    
343    /* apple's xdarwin has no alt!!!! */
344    ECORE_X_MODIFIER_ALT   = _ecore_x_key_mask_get(XK_Alt_L);
345    if (!ECORE_X_MODIFIER_ALT) 
346      ECORE_X_MODIFIER_ALT = _ecore_x_key_mask_get(XK_Meta_L);
347    if (!ECORE_X_MODIFIER_ALT) 
348      ECORE_X_MODIFIER_ALT = _ecore_x_key_mask_get(XK_Super_L);   
349    
350    /* the windows key... a valid modifier :) */
351    ECORE_X_MODIFIER_WIN   = _ecore_x_key_mask_get(XK_Super_L);
352    if (!ECORE_X_MODIFIER_WIN) 
353      ECORE_X_MODIFIER_WIN = _ecore_x_key_mask_get(XK_Mode_switch);
354    if (!ECORE_X_MODIFIER_WIN) 
355      ECORE_X_MODIFIER_WIN = _ecore_x_key_mask_get(XK_Meta_L);
356    
357    if (ECORE_X_MODIFIER_WIN == ECORE_X_MODIFIER_ALT)
358      ECORE_X_MODIFIER_WIN = 0;
359    if (ECORE_X_MODIFIER_ALT == ECORE_X_MODIFIER_CTRL)
360      ECORE_X_MODIFIER_ALT = 0;
361    
362    ECORE_X_LOCK_SCROLL    = _ecore_x_key_mask_get(XK_Scroll_Lock);
363    ECORE_X_LOCK_NUM       = _ecore_x_key_mask_get(XK_Num_Lock);
364    ECORE_X_LOCK_CAPS      = _ecore_x_key_mask_get(XK_Caps_Lock);
365    
366    _ecore_x_fd_handler_handle = 
367      ecore_main_fd_handler_add(ConnectionNumber(_ecore_x_disp),
368                                ECORE_FD_READ,
369                                _ecore_x_fd_handler, _ecore_x_disp,
370                                _ecore_x_fd_handler_buf, _ecore_x_disp);
371    if (!_ecore_x_fd_handler_handle)
372      {
373         XCloseDisplay(_ecore_x_disp);
374         free(_ecore_x_event_handlers);
375         _ecore_x_fd_handler_handle = NULL;
376         _ecore_x_disp = NULL;
377         _ecore_x_event_handlers = NULL;
378         return 0;
379      }
380
381    _ecore_x_atoms_init();
382
383    /* Set up the ICCCM hints */
384    ecore_x_icccm_init();
385
386    /* Set up the _NET_... hints */
387    ecore_x_netwm_init();
388
389    /* old e hints init */
390    ecore_x_e_init();
391    
392    /* This is just to be anal about naming conventions */
393
394    _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_DELETE_REQUEST] = ECORE_X_ATOM_WM_DELETE_WINDOW;
395    _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_TAKE_FOCUS] = ECORE_X_ATOM_WM_TAKE_FOCUS;
396    _ecore_x_atoms_wm_protocols[ECORE_X_NET_WM_PROTOCOL_PING] = ECORE_X_ATOM_NET_WM_PING;
397    _ecore_x_atoms_wm_protocols[ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST] = ECORE_X_ATOM_NET_WM_SYNC_REQUEST;
398
399    _ecore_x_selection_data_init();
400    _ecore_x_dnd_init();
401    _ecore_x_fixes_init();
402    _ecore_x_damage_init();
403    _ecore_x_composite_init();
404    _ecore_x_dpms_init();
405    
406    _ecore_x_init_count++;
407    
408    _ecore_x_private_win = ecore_x_window_override_new(0, -77, -777, 123, 456);
409    
410    return _ecore_x_init_count;
411 }
412
413 static int
414 _ecore_x_shutdown(int close_display)
415 {
416    _ecore_x_init_count--;
417    if (_ecore_x_init_count > 0) return _ecore_x_init_count;
418    if (!_ecore_x_disp) return _ecore_x_init_count;
419    if (close_display)
420       XCloseDisplay(_ecore_x_disp);
421    else
422       close(ConnectionNumber(_ecore_x_disp));
423    free(_ecore_x_event_handlers);
424    ecore_main_fd_handler_del(_ecore_x_fd_handler_handle);
425    _ecore_x_fd_handler_handle = NULL;
426    _ecore_x_disp = NULL;
427    _ecore_x_event_handlers = NULL;
428    _ecore_x_selection_shutdown();
429    _ecore_x_dnd_shutdown();
430    ecore_x_netwm_shutdown();
431    if (_ecore_x_init_count < 0) _ecore_x_init_count = 0;
432    return _ecore_x_init_count;
433 }
434
435 /**
436  * Shuts down the Ecore X library.
437  *
438  * In shutting down the library, the X display connection is terminated
439  * and any event handlers for it are removed.
440  *
441  * @return  The number of times the library has been initialized without
442  *          being shut down.
443  * @ingroup Ecore_X_Init_Group
444  */
445 EAPI int
446 ecore_x_shutdown(void)
447 {
448    return _ecore_x_shutdown(1);
449 }
450
451 /**
452  * Shuts down the Ecore X library.
453  *
454  * As ecore_x_shutdown, except do not close Display, only connection.
455  *
456  * @ingroup Ecore_X_Init_Group
457  */
458 EAPI int
459 ecore_x_disconnect(void)
460 {
461    return _ecore_x_shutdown(0);
462 }
463
464 /**
465  * @defgroup Ecore_X_Display_Attr_Group X Display Attributes
466  *
467  * Functions that set and retrieve X display attributes.
468  */
469
470 /**
471  * Retrieves the Ecore_X_Display handle used for the current X connection.
472  * @return  The current X display.
473  * @ingroup Ecore_X_Display_Attr_Group
474  */
475 EAPI Ecore_X_Display *
476 ecore_x_display_get(void)
477 {
478    return (Ecore_X_Display *)_ecore_x_disp;
479 }
480
481 /**
482  * Retrieves the X display file descriptor.
483  * @return  The current X display file descriptor.
484  * @ingroup Ecore_X_Display_Attr_Group
485  */
486 EAPI int
487 ecore_x_fd_get(void)
488 {
489    return ConnectionNumber(_ecore_x_disp);
490 }
491
492 /**
493  * Sets the timeout for a double and triple clicks to be flagged.
494  * 
495  * This sets the time between clicks before the double_click flag is
496  * set in a button down event. If 3 clicks occur within double this
497  * time, the triple_click flag is also set.
498  *
499  * @param   t The time in seconds
500  * @ingroup Ecore_X_Display_Attr_Group
501  */
502 EAPI void
503 ecore_x_double_click_time_set(double t)
504 {
505    if (t < 0.0) t = 0.0;
506    _ecore_x_double_click_time = t;
507 }
508
509 /**
510  * Retrieves the double and triple click flag timeout.
511  *
512  * See @ref ecore_x_double_click_time_set for more information.
513  *
514  * @return  The timeout for double clicks in seconds.
515  * @ingroup Ecore_X_Display_Attr_Group
516  */
517 EAPI double
518 ecore_x_double_click_time_get(void)
519 {
520    return _ecore_x_double_click_time;
521 }
522
523 /**
524  * @defgroup Ecore_X_Flush_Group X Synchronization Functions
525  *
526  * Functions that ensure that all commands that have been issued by the
527  * Ecore X library have been sent to the server.
528  */
529
530 /**
531  * Sends all X commands in the X Display buffer.
532  * @ingroup Ecore_X_Flush_Group
533  */
534 EAPI void
535 ecore_x_flush(void)
536 {
537    XFlush(_ecore_x_disp);
538 }
539
540 /**
541  * Flushes the command buffer and waits until all requests have been
542  * processed by the server.
543  * @ingroup Ecore_X_Flush_Group
544  */
545 EAPI void
546 ecore_x_sync(void)
547 {
548    XSync(_ecore_x_disp, False);
549 }
550
551 /**
552  * Kill all clients with subwindows under a given window.
553  *
554  * You can kill all clients connected to the X server by using
555  * @ref ecore_x_window_root_list to get a list of root windows, and
556  * then passing each root window to this function.
557  *
558  * @param root The window whose children will be killed.
559  */
560 EAPI void
561 ecore_x_killall(Ecore_X_Window root)
562 {
563    unsigned int j;
564    Window root_r;
565    Window parent_r;
566    Window *children_r = NULL;
567    unsigned int num_children = 0;
568    
569    XGrabServer(_ecore_x_disp);
570    /* Tranverse window tree starting from root, and drag each
571     * before the firing squad */
572    while (XQueryTree(_ecore_x_disp, root, &root_r, &parent_r,
573                      &children_r, &num_children) && (num_children > 0))
574      {
575         for (j = 0; j < num_children; ++j)
576           {
577              XKillClient(_ecore_x_disp, children_r[j]);
578           }
579         
580         XFree(children_r);
581      }
582    XUngrabServer(_ecore_x_disp);
583    XSync(_ecore_x_disp, False);
584 }
585
586 /**
587  * Kill a specific client
588  *
589  * You can kill a specific client owning window @p win
590  *
591  * @param win Window of the client to be killed
592  */
593 EAPI void
594 ecore_x_kill(Ecore_X_Window win)
595 {
596    XKillClient(_ecore_x_disp, win);
597 }
598
599 /**
600  * Return the last event time
601  */
602 EAPI Ecore_X_Time
603 ecore_x_current_time_get(void)
604 {
605    return _ecore_x_event_last_time;
606 }
607
608 /**
609  * Return the screen DPI
610  *
611  * This is a simplistic call to get DPI. It does not account for differing
612  * DPI in the x amd y axes nor does it accoutn for multihead or xinerama and
613  * xrander where different parts of the screen may have differen DPI etc.
614  *
615  * @return the general screen DPI (dots/pixels per inch).
616  */
617 EAPI int
618 ecore_x_dpi_get(void)
619 {
620    Screen *s;
621    
622    s = DefaultScreenOfDisplay(_ecore_x_disp);
623    if (s->mwidth <= 0) return 75;
624    return (((s->width * 254) / s->mwidth) + 5) / 10;
625 }
626
627 static int
628 _ecore_x_fd_handler(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
629 {
630    Display *d;
631    
632    d = data;
633    while (XPending(d))
634      {
635         XEvent ev;
636         
637         XNextEvent(d, &ev);
638
639         /* Filter event for XIM */
640         if (XFilterEvent(&ev, ev.xkey.window)) continue;
641
642         if ((ev.type >= 0) && (ev.type < _ecore_x_event_handlers_num))
643           {
644              if (_ecore_x_event_handlers[ev.type])
645                _ecore_x_event_handlers[ev.type] (&ev);
646           }
647      }
648    return 1;
649 }
650
651 static int
652 _ecore_x_fd_handler_buf(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
653 {
654    Display *d;
655
656    d = data;
657    if (XPending(d)) return 1;
658    return 0;
659 }
660
661 static int
662 _ecore_x_key_mask_get(KeySym sym)
663 {
664    XModifierKeymap    *mod;
665    KeySym              sym2;
666    int                 i, j;
667    const int           masks[8] = 
668      {
669         ShiftMask, LockMask, ControlMask, 
670           Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
671      };
672    
673    mod = XGetModifierMapping(_ecore_x_disp);
674    if ((mod) && (mod->max_keypermod > 0))
675      {
676         for (i = 0; i < (8 * mod->max_keypermod); i++)
677           {
678              for (j = 0; j < 8; j++)
679                {
680                   sym2 = XKeycodeToKeysym(_ecore_x_disp, mod->modifiermap[i], j);
681                   if (sym2 != 0) break;
682                }
683              if (sym2 == sym)
684                {
685                   int mask;
686                   
687                   mask = masks[i / mod->max_keypermod];
688                   if (mod->modifiermap) XFree(mod->modifiermap);
689                   XFree(mod);
690                   return mask;
691                }
692           }
693      }
694    if (mod)
695      {
696         if (mod->modifiermap) XFree(mod->modifiermap);
697         XFree(mod);
698      }
699   return 0;
700 }
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723 /*****************************************************************************/
724 /*****************************************************************************/
725 /*****************************************************************************/
726 /* FIXME: these funcs need categorising */
727 /*****************************************************************************/
728
729 /**
730  * Get a list of all the root windows on the server.
731  *
732  * @note   The returned array will need to be freed after use.
733  * @param  num_ret Pointer to integer to put number of windows returned in.
734  * @return An array of all the root windows.  @c NULL is returned if memory
735  *         could not be allocated for the list, or if @p num_ret is @c NULL.
736  */
737 EAPI Ecore_X_Window *
738 ecore_x_window_root_list(int *num_ret)
739 {
740    int num, i;
741    Ecore_X_Window *roots;
742 #ifdef ECORE_XPRINT
743    int xp_base, xp_err_base;
744 #endif
745    
746    if (!num_ret) return NULL;
747    *num_ret = 0;
748
749 #ifdef ECORE_XPRINT
750    num = ScreenCount(_ecore_x_disp);
751    if (XpQueryExtension(_ecore_x_disp, &xp_base, &xp_err_base))
752      {
753         Screen **ps = NULL;
754         int psnum = 0;
755         
756         ps = XpQueryScreens(_ecore_x_disp, &psnum);
757         if (ps)
758           {
759              int overlap, j;
760              
761              overlap = 0;
762              for (i = 0; i < num; i++)
763                {
764                   for (j = 0; j < psnum; j++)
765                     {
766                        if (ScreenOfDisplay(_ecore_x_disp, i) == ps[j])
767                          overlap++;
768                     }
769                }
770              roots = malloc((num - overlap) * sizeof(Window));
771              if (roots)
772                {
773                   int k;
774                   
775                   k = 0;
776                   for (i = 0; i < num; i++)
777                     {
778                        int is_print;
779                        
780                        is_print = 0;
781                        for (j = 0; j < psnum; j++)
782                          {
783                             if (ScreenOfDisplay(_ecore_x_disp, i) == ps[j])
784                               {
785                                  is_print = 1;
786                                  break;
787                               }
788                          }
789                        if (!is_print)
790                          {
791                             roots[k] = RootWindow(_ecore_x_disp, i);
792                             k++;
793                          }
794                     }
795                   *num_ret = k;
796                }
797              XFree(ps);
798           }
799         else
800           {
801              roots = malloc(num * sizeof(Window));
802              if (!roots) return NULL;
803              *num_ret = num;
804              for (i = 0; i < num; i++)
805                roots[i] = RootWindow(_ecore_x_disp, i);
806           }
807      }
808    else
809      {
810         roots = malloc(num * sizeof(Window));
811         if (!roots) return NULL;
812         *num_ret = num;
813         for (i = 0; i < num; i++)
814           roots[i] = RootWindow(_ecore_x_disp, i);
815      }
816 #else   
817    num = ScreenCount(_ecore_x_disp);
818    roots = malloc(num * sizeof(Window));
819    if (!roots) return NULL;
820    *num_ret = num;
821    for (i = 0; i < num; i++)
822      roots[i] = RootWindow(_ecore_x_disp, i);
823 #endif   
824    return roots;
825 }
826
827 EAPI Ecore_X_Window
828 ecore_x_window_root_first_get(void)
829 {
830    int num;
831    Ecore_X_Window root, *roots = NULL;
832
833    roots = ecore_x_window_root_list(&num);
834    if(!(roots)) return 0;
835    
836    if (num > 0)
837       root = roots[0];
838    else
839       root = 0;
840
841    free(roots);
842    return root;
843 }
844
845
846 static void _ecore_x_window_manage_error(void *data);
847
848 static int _ecore_x_window_manage_failed = 0;
849 static void
850 _ecore_x_window_manage_error(void *data __UNUSED__)
851 {
852    if ((ecore_x_error_request_get() == X_ChangeWindowAttributes) &&
853        (ecore_x_error_code_get() == BadAccess))
854      _ecore_x_window_manage_failed = 1;
855 }
856
857 EAPI int
858 ecore_x_window_manage(Ecore_X_Window win)
859 {
860    XWindowAttributes   att;
861    
862    if (XGetWindowAttributes(_ecore_x_disp, win, &att) != True) return 0;
863    ecore_x_sync();
864    _ecore_x_window_manage_failed = 0;
865    ecore_x_error_handler_set(_ecore_x_window_manage_error, NULL);
866    XSelectInput(_ecore_x_disp, win, 
867                 EnterWindowMask | 
868                 LeaveWindowMask | 
869                 PropertyChangeMask | 
870                 ResizeRedirectMask |
871                 SubstructureRedirectMask | 
872                 SubstructureNotifyMask |
873                 StructureNotifyMask |
874                 KeyPressMask | 
875                 KeyReleaseMask |
876                 att.your_event_mask);
877    ecore_x_sync();
878    ecore_x_error_handler_set(NULL, NULL);
879    if (_ecore_x_window_manage_failed)
880      {
881         _ecore_x_window_manage_failed = 0;
882         return 0;
883      }
884    return 1;
885 }
886
887 EAPI void
888 ecore_x_window_container_manage(Ecore_X_Window win)
889 {
890    XSelectInput(_ecore_x_disp, win, 
891                 SubstructureRedirectMask | 
892                 SubstructureNotifyMask);
893 }
894
895 EAPI void
896 ecore_x_window_client_manage(Ecore_X_Window win)
897 {
898    XSelectInput(_ecore_x_disp, win, 
899                 PropertyChangeMask | 
900 //              ResizeRedirectMask |
901                 FocusChangeMask |
902                 ColormapChangeMask |
903                 VisibilityChangeMask |
904                 StructureNotifyMask
905                 );
906    XShapeSelectInput(_ecore_x_disp, win, ShapeNotifyMask);
907 }
908
909 EAPI void
910 ecore_x_window_sniff(Ecore_X_Window win)
911 {
912    XSelectInput(_ecore_x_disp, win,
913                 PropertyChangeMask |
914                 SubstructureNotifyMask);
915 }
916
917 EAPI void
918 ecore_x_window_client_sniff(Ecore_X_Window win)
919 {
920    XSelectInput(_ecore_x_disp, win,
921                 PropertyChangeMask |
922                 FocusChangeMask |
923                 ColormapChangeMask |
924                 VisibilityChangeMask |
925                 StructureNotifyMask);
926    XShapeSelectInput(_ecore_x_disp, win, ShapeNotifyMask);
927 }
928
929 /**
930  * Retrieves the atom value associated with the given name.
931  * @param  name The given name.
932  * @return Associated atom value.
933  */
934 EAPI Ecore_X_Atom    
935 ecore_x_atom_get(const char *name)
936 {
937    if (!_ecore_x_disp) return 0;
938    return XInternAtom(_ecore_x_disp, name, False);
939 }
940
941 EAPI void
942 ecore_x_atoms_get(const char **names, int num, Ecore_X_Atom *atoms)
943 {
944    Atom *atoms_int;
945    int i;
946    
947    if (!_ecore_x_disp) return;
948    atoms_int = alloca(num * sizeof(Atom));
949    XInternAtoms(_ecore_x_disp, (char **)names, num, False, atoms_int);
950    for (i = 0; i < num; i++)
951      atoms[i] = atoms_int[i];
952 }
953
954
955
956
957
958
959 EAPI int
960 ecore_x_window_attributes_get(Ecore_X_Window win, Ecore_X_Window_Attributes *att_ret)
961 {
962    XWindowAttributes att;
963    
964    if (!XGetWindowAttributes(_ecore_x_disp, win, &att)) return 0;
965    memset(att_ret, 0, sizeof(Ecore_X_Window_Attributes));
966    att_ret->root = att.root;
967    att_ret->x = att.x;
968    att_ret->y = att.y;
969    att_ret->w = att.width;
970    att_ret->h = att.height;
971    att_ret->border = att.border_width;
972    att_ret->depth = att.depth;
973    if (att.map_state != IsUnmapped) att_ret->visible = 1;
974    if (att.map_state == IsViewable) att_ret->viewable = 1;
975    if (att.override_redirect) att_ret->override = 1;
976    if (att.class == InputOnly) att_ret->input_only = 1;
977    if (att.save_under) att_ret->save_under = 1;
978    att_ret->event_mask.mine = att.your_event_mask;
979    att_ret->event_mask.all = att.all_event_masks;
980    att_ret->event_mask.no_propagate = att.do_not_propagate_mask;
981    att_ret->window_gravity = att.win_gravity;
982    att_ret->pixel_gravity = att.bit_gravity;
983    att_ret->colormap = att.colormap;
984    att_ret->visual = att.visual;
985    return 1;
986 }
987
988 EAPI void
989 ecore_x_window_save_set_add(Ecore_X_Window win)
990 {
991    XAddToSaveSet(_ecore_x_disp, win);
992 }
993
994 EAPI void
995 ecore_x_window_save_set_del(Ecore_X_Window win)
996 {
997    XRemoveFromSaveSet(_ecore_x_disp, win);
998 }
999
1000 EAPI Ecore_X_Window *
1001 ecore_x_window_children_get(Ecore_X_Window win, int *num)
1002 {
1003    Ecore_X_Window     *windows = NULL;
1004    Window              root_ret = 0, parent_ret = 0, *children_ret = NULL;
1005    unsigned int        children_ret_num = 0;
1006    
1007    if (!XQueryTree(_ecore_x_disp, win, &root_ret, &parent_ret, &children_ret,
1008                    &children_ret_num))
1009      {
1010         return NULL;
1011      }
1012    if (children_ret)
1013      {
1014         windows = malloc(children_ret_num * sizeof(Ecore_X_Window));
1015         if (windows)
1016           {
1017              unsigned int i;
1018              
1019              for (i = 0; i < children_ret_num; i++)
1020                windows[i] = children_ret[i];
1021              *num = children_ret_num;
1022           }
1023         XFree(children_ret);
1024      }
1025    return windows;
1026 }
1027
1028 EAPI int
1029 ecore_x_pointer_control_set(int accel_num, int accel_denom, int threshold)
1030 {
1031    return XChangePointerControl(_ecore_x_disp, 1, 1, 
1032                                 accel_num, accel_denom, threshold);
1033 }
1034
1035 EAPI int
1036 ecore_x_pointer_control_get(int *accel_num, int *accel_denom, int *threshold)
1037 {
1038    return XGetPointerControl(_ecore_x_disp, 
1039                                 accel_num, accel_denom, threshold);
1040 }
1041
1042 EAPI int
1043 ecore_x_pointer_mapping_set(unsigned char *map, int nmap)
1044 {
1045    return XSetPointerMapping(_ecore_x_disp, map, nmap);
1046 }
1047
1048 EAPI int
1049 ecore_x_pointer_mapping_get(unsigned char *map, int nmap)
1050 {
1051    return XGetPointerMapping(_ecore_x_disp, map, nmap);
1052 }
1053
1054 EAPI int
1055 ecore_x_pointer_grab(Ecore_X_Window win)
1056 {
1057    if (XGrabPointer(_ecore_x_disp, win, False,
1058                     ButtonPressMask | ButtonReleaseMask | 
1059                     EnterWindowMask | LeaveWindowMask | PointerMotionMask,
1060                     GrabModeAsync, GrabModeAsync,
1061                     None, None, CurrentTime) == GrabSuccess) return 1;
1062    return 0;
1063 }
1064
1065 EAPI int
1066 ecore_x_pointer_confine_grab(Ecore_X_Window win)
1067 {
1068    if (XGrabPointer(_ecore_x_disp, win, False,
1069                     ButtonPressMask | ButtonReleaseMask | 
1070                     EnterWindowMask | LeaveWindowMask | PointerMotionMask,
1071                     GrabModeAsync, GrabModeAsync,
1072                     win, None, CurrentTime) == GrabSuccess) return 1;
1073    return 0;
1074 }
1075
1076 EAPI void
1077 ecore_x_pointer_ungrab(void)
1078 {
1079    XUngrabPointer(_ecore_x_disp, CurrentTime);
1080 }
1081
1082 EAPI int
1083 ecore_x_pointer_warp(Ecore_X_Window win, int x, int y)
1084 {
1085    return XWarpPointer(_ecore_x_disp, None, win, 0, 0, 0, 0, x, y);
1086 }
1087
1088 EAPI int
1089 ecore_x_keyboard_grab(Ecore_X_Window win)
1090 {
1091    if (XGrabKeyboard(_ecore_x_disp, win, False,
1092                      GrabModeAsync, GrabModeAsync,
1093                      CurrentTime) == GrabSuccess) return 1;
1094    return 0;
1095 }
1096
1097 EAPI void
1098 ecore_x_keyboard_ungrab(void)
1099 {
1100    XUngrabKeyboard(_ecore_x_disp, CurrentTime);   
1101 }
1102
1103 EAPI void
1104 ecore_x_grab(void)
1105 {
1106    _ecore_x_grab_count++;
1107    
1108    if (_ecore_x_grab_count == 1)
1109       XGrabServer(_ecore_x_disp);
1110 }
1111
1112 EAPI void
1113 ecore_x_ungrab(void)
1114 {
1115    _ecore_x_grab_count--;
1116    if (_ecore_x_grab_count < 0)
1117       _ecore_x_grab_count = 0;
1118
1119    if (_ecore_x_grab_count == 0)
1120    {
1121       XUngrabServer(_ecore_x_disp);
1122       XSync(_ecore_x_disp, False);
1123    }
1124 }
1125
1126 int      _ecore_window_grabs_num = 0;
1127 Window  *_ecore_window_grabs = NULL;
1128 int    (*_ecore_window_grab_replay_func) (void *data, int event_type, void *event);
1129 void    *_ecore_window_grab_replay_data;
1130
1131 EAPI void
1132 ecore_x_passive_grab_replay_func_set(int (*func) (void *data, int event_type, void *event), void *data)
1133 {
1134    _ecore_window_grab_replay_func = func;
1135    _ecore_window_grab_replay_data = data;
1136 }
1137
1138 EAPI void
1139 ecore_x_window_button_grab(Ecore_X_Window win, int button, 
1140                            Ecore_X_Event_Mask event_mask,
1141                            int mod, int any_mod)
1142 {
1143    unsigned int        b;
1144    unsigned int        m;
1145    unsigned int        locks[8];
1146    int                 i, ev;
1147    
1148    b = button;
1149    if (b == 0) b = AnyButton;
1150    m = mod;
1151    if (any_mod) m = AnyModifier;
1152    locks[0] = 0;
1153    locks[1] = ECORE_X_LOCK_CAPS;
1154    locks[2] = ECORE_X_LOCK_NUM;
1155    locks[3] = ECORE_X_LOCK_SCROLL;
1156    locks[4] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM;
1157    locks[5] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_SCROLL;
1158    locks[6] = ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
1159    locks[7] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
1160    ev = event_mask;
1161    for (i = 0; i < 8; i++)
1162      XGrabButton(_ecore_x_disp, b, m | locks[i],
1163                  win, False, ev, GrabModeSync, GrabModeAsync, None, None);
1164    _ecore_window_grabs_num++;
1165    _ecore_window_grabs = realloc(_ecore_window_grabs, 
1166                                  _ecore_window_grabs_num * sizeof(Window));
1167    _ecore_window_grabs[_ecore_window_grabs_num - 1] = win;
1168 }
1169
1170 void
1171 _ecore_x_sync_magic_send(int val, Ecore_X_Window swin)
1172 {
1173    XEvent xev;
1174    
1175    xev.xclient.type = ClientMessage;
1176    xev.xclient.serial = 0;
1177    xev.xclient.send_event = True;
1178    xev.xclient.display = _ecore_x_disp;
1179    xev.xclient.window = _ecore_x_private_win;
1180    xev.xclient.format = 32;
1181    xev.xclient.message_type = 27777;
1182    xev.xclient.data.l[0] = 0x7162534;
1183    xev.xclient.data.l[1] = 0x10000000 + val;
1184    xev.xclient.data.l[2] = swin;
1185    XSendEvent(_ecore_x_disp, _ecore_x_private_win, False, NoEventMask, &xev);
1186 }
1187
1188 void
1189 _ecore_x_window_grab_remove(Ecore_X_Window win)
1190 {
1191    int i, shuffle = 0;
1192    
1193    if (_ecore_window_grabs_num > 0)
1194      {
1195         for (i = 0; i < _ecore_window_grabs_num; i++)
1196           {
1197              if (shuffle) _ecore_window_grabs[i - 1] = _ecore_window_grabs[i];
1198              if ((!shuffle) && (_ecore_window_grabs[i] == win))
1199                shuffle = 1;
1200           }
1201         if (shuffle)
1202           {
1203              _ecore_window_grabs_num--;
1204              _ecore_window_grabs = realloc(_ecore_window_grabs, 
1205                                            _ecore_window_grabs_num * sizeof(Window));
1206           }
1207      }
1208 }
1209
1210 EAPI void
1211 ecore_x_window_button_ungrab(Ecore_X_Window win, int button, 
1212                              int mod, int any_mod)
1213 {
1214    unsigned int        b;
1215    unsigned int        m;
1216    unsigned int        locks[8];
1217    int                 i;
1218    
1219    b = button;
1220    if (b == 0) b = AnyButton;
1221    m = mod;
1222    if (any_mod) m = AnyModifier;
1223    locks[0] = 0;
1224    locks[1] = ECORE_X_LOCK_CAPS;
1225    locks[2] = ECORE_X_LOCK_NUM;
1226    locks[3] = ECORE_X_LOCK_SCROLL;
1227    locks[4] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM;
1228    locks[5] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_SCROLL;
1229    locks[6] = ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
1230    locks[7] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
1231    for (i = 0; i < 8; i++)
1232      XUngrabButton(_ecore_x_disp, b, m | locks[i], win);
1233    _ecore_x_sync_magic_send(1, win);
1234 }
1235
1236 int      _ecore_key_grabs_num = 0;
1237 Window  *_ecore_key_grabs = NULL;
1238
1239 EAPI void
1240 ecore_x_window_key_grab(Ecore_X_Window win, const char *key, 
1241                         int mod, int any_mod)
1242 {
1243    KeyCode             keycode = 0;
1244    KeySym              keysym;
1245    unsigned int        m;
1246    unsigned int        locks[8];
1247    int                 i;
1248    
1249    if (!strncmp(key, "Keycode-", 8))
1250      keycode = atoi(key + 8);
1251    else
1252      {
1253         keysym = XStringToKeysym(key);
1254         if (keysym == NoSymbol) return;
1255         keycode  = XKeysymToKeycode(_ecore_x_disp, XStringToKeysym(key));
1256      }
1257    if (keycode == 0) return;
1258    
1259    m = mod;
1260    if (any_mod) m = AnyModifier;
1261    locks[0] = 0;
1262    locks[1] = ECORE_X_LOCK_CAPS;
1263    locks[2] = ECORE_X_LOCK_NUM;
1264    locks[3] = ECORE_X_LOCK_SCROLL;
1265    locks[4] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM;
1266    locks[5] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_SCROLL;
1267    locks[6] = ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
1268    locks[7] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
1269    for (i = 0; i < 8; i++)
1270      XGrabKey(_ecore_x_disp, keycode, m | locks[i],
1271               win, False, GrabModeSync, GrabModeAsync);
1272    _ecore_key_grabs_num++;
1273    _ecore_key_grabs = realloc(_ecore_key_grabs,
1274                               _ecore_key_grabs_num * sizeof(Window));
1275    _ecore_key_grabs[_ecore_key_grabs_num - 1] = win;
1276 }
1277
1278 void
1279 _ecore_x_key_grab_remove(Ecore_X_Window win)
1280 {
1281    int i, shuffle = 0;
1282    
1283    if (_ecore_key_grabs_num > 0)
1284      {
1285         for (i = 0; i < _ecore_key_grabs_num; i++)
1286           {
1287              if (shuffle) _ecore_key_grabs[i - 1] = _ecore_key_grabs[i];
1288              if ((!shuffle) && (_ecore_key_grabs[i] == win))
1289                shuffle = 1;
1290           }
1291         if (shuffle)
1292           {
1293              _ecore_key_grabs_num--;
1294              _ecore_key_grabs = realloc(_ecore_key_grabs, 
1295                                         _ecore_key_grabs_num * sizeof(Window));
1296           }
1297      }
1298 }
1299
1300 EAPI void
1301 ecore_x_window_key_ungrab(Ecore_X_Window win, const char *key,
1302                           int mod, int any_mod)
1303 {
1304    KeyCode             keycode = 0;
1305    KeySym              keysym;
1306    unsigned int        m;
1307    unsigned int        locks[8];
1308    int                 i;
1309
1310    if (!strncmp(key, "Keycode-", 8))
1311      keycode = atoi(key + 8);
1312    else
1313      {
1314         keysym = XStringToKeysym(key);
1315         if (keysym == NoSymbol) return;
1316         keycode  = XKeysymToKeycode(_ecore_x_disp, XStringToKeysym(key));
1317      }
1318    if (keycode == 0) return;
1319    
1320    m = mod;
1321    if (any_mod) m = AnyModifier;
1322    locks[0] = 0;
1323    locks[1] = ECORE_X_LOCK_CAPS;
1324    locks[2] = ECORE_X_LOCK_NUM;
1325    locks[3] = ECORE_X_LOCK_SCROLL;
1326    locks[4] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM;
1327    locks[5] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_SCROLL;
1328    locks[6] = ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
1329    locks[7] = ECORE_X_LOCK_CAPS   | ECORE_X_LOCK_NUM    | ECORE_X_LOCK_SCROLL;
1330    for (i = 0; i < 8; i++)
1331      XUngrabKey(_ecore_x_disp, keycode, m | locks[i], win);
1332    _ecore_x_sync_magic_send(2, win);
1333 }
1334
1335 /**
1336  * Send client message with given type and format 32.
1337  *
1338  * @param win     The window the message is sent to.
1339  * @param type    The client message type.
1340  * @param d0      The client message data item 1
1341  * @param d1      The client message data item 2
1342  * @param d2      The client message data item 3
1343  * @param d3      The client message data item 4
1344  * @param d4      The client message data item 5
1345  *
1346  * @return !0 on success.
1347  */
1348 EAPI int
1349 ecore_x_client_message32_send(Ecore_X_Window win, Ecore_X_Atom type,
1350                               Ecore_X_Event_Mask mask,
1351                               long d0, long d1, long d2, long d3, long d4)
1352 {
1353     XEvent xev;
1354
1355     xev.xclient.window = win;
1356     xev.xclient.type = ClientMessage;
1357     xev.xclient.message_type = type;
1358     xev.xclient.format = 32;
1359     xev.xclient.data.l[0] = d0;
1360     xev.xclient.data.l[1] = d1;
1361     xev.xclient.data.l[2] = d2;
1362     xev.xclient.data.l[3] = d3;
1363     xev.xclient.data.l[4] = d4;
1364
1365     return XSendEvent(_ecore_x_disp, win, False, mask, &xev);
1366 }
1367
1368 /**
1369  * Send client message with given type and format 8.
1370  *
1371  * @param win     The window the message is sent to.
1372  * @param type    The client message type.
1373  * @param data    Data to be sent.
1374  * @param len     Number of data bytes, max 20.
1375  *
1376  * @return !0 on success.
1377  */
1378 EAPI int
1379 ecore_x_client_message8_send(Ecore_X_Window win, Ecore_X_Atom type,
1380                              const void *data, int len)
1381 {
1382     XEvent xev;
1383
1384     xev.xclient.window = win;
1385     xev.xclient.type = ClientMessage;
1386     xev.xclient.message_type = type;
1387     xev.xclient.format = 8;
1388     if (len > 20)
1389         len = 20;
1390     memcpy(xev.xclient.data.b, data, len);
1391     memset(xev.xclient.data.b + len, 0, 20 - len);
1392
1393     return XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev);
1394 }
1395
1396 EAPI int
1397 ecore_x_mouse_move_send(Ecore_X_Window win, int x, int y)
1398 {
1399    XEvent xev;
1400    XWindowAttributes att;
1401    Window tw;
1402    int rx, ry;
1403
1404    XGetWindowAttributes(_ecore_x_disp, win, &att);
1405    XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw);
1406    xev.xmotion.type = MotionNotify;
1407    xev.xmotion.window = win;
1408    xev.xmotion.root = att.root;
1409    xev.xmotion.subwindow = win;
1410    xev.xmotion.time = _ecore_x_event_last_time;
1411    xev.xmotion.x = x;
1412    xev.xmotion.y = y;
1413    xev.xmotion.x_root = rx;
1414    xev.xmotion.y_root = ry;
1415    xev.xmotion.state = 0;
1416    xev.xmotion.is_hint = 0;
1417    xev.xmotion.same_screen = 1;
1418    return XSendEvent(_ecore_x_disp, win, True, PointerMotionMask, &xev);
1419 }
1420
1421 EAPI int
1422 ecore_x_mouse_down_send(Ecore_X_Window win, int x, int y, int b)
1423 {
1424    XEvent xev;
1425    XWindowAttributes att;
1426    Window tw;
1427    int rx, ry;
1428
1429    XGetWindowAttributes(_ecore_x_disp, win, &att);
1430    XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw);
1431    xev.xbutton.type = ButtonPress;
1432    xev.xbutton.window = win;
1433    xev.xbutton.root = att.root;
1434    xev.xbutton.subwindow = win;
1435    xev.xbutton.time = _ecore_x_event_last_time;
1436    xev.xbutton.x = x;
1437    xev.xbutton.y = y;
1438    xev.xbutton.x_root = rx;
1439    xev.xbutton.y_root = ry;
1440    xev.xbutton.state = 1 << b;
1441    xev.xbutton.button = b;
1442    xev.xbutton.same_screen = 1;
1443    return XSendEvent(_ecore_x_disp, win, True, ButtonPressMask, &xev);
1444 }
1445
1446 EAPI int
1447 ecore_x_mouse_up_send(Ecore_X_Window win, int x, int y, int b)
1448 {
1449    XEvent xev;
1450    XWindowAttributes att;
1451    Window tw;
1452    int rx, ry;
1453
1454    XGetWindowAttributes(_ecore_x_disp, win, &att);
1455    XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw);
1456    xev.xbutton.type = ButtonRelease;
1457    xev.xbutton.window = win;
1458    xev.xbutton.root = att.root;
1459    xev.xbutton.subwindow = win;
1460    xev.xbutton.time = _ecore_x_event_last_time;
1461    xev.xbutton.x = x;
1462    xev.xbutton.y = y;
1463    xev.xbutton.x_root = rx;
1464    xev.xbutton.y_root = ry;
1465    xev.xbutton.state = 0;
1466    xev.xbutton.button = b;
1467    xev.xbutton.same_screen = 1;
1468    return XSendEvent(_ecore_x_disp, win, True, ButtonReleaseMask, &xev);
1469 }
1470
1471 EAPI void
1472 ecore_x_focus_reset(void)
1473 {
1474    XSetInputFocus(_ecore_x_disp, PointerRoot, RevertToPointerRoot, CurrentTime);
1475 }
1476
1477 EAPI void
1478 ecore_x_events_allow_all(void)
1479 {
1480    XAllowEvents(_ecore_x_disp, AsyncBoth, CurrentTime);
1481 }
1482
1483 EAPI void
1484 ecore_x_pointer_last_xy_get(int *x, int *y)
1485 {
1486    if (x) *x = _ecore_x_event_last_root_x;
1487    if (y) *y = _ecore_x_event_last_root_y;
1488 }
1489
1490 EAPI void
1491 ecore_x_pointer_xy_get(Ecore_X_Window win, int *x, int *y)
1492 {
1493    Window rwin, cwin;
1494    int rx, ry, wx, wy, ret;
1495    unsigned int mask;
1496    
1497    ret = XQueryPointer(_ecore_x_disp, win, &rwin, &cwin, &rx, &ry, &wx, &wy, &mask);
1498    if (!ret) wx = wy = -1;
1499    if (x) *x = wx;
1500    if (y) *y = wy;
1501 }
1502 /*****************************************************************************/
1503 /*****************************************************************************/
1504 /*****************************************************************************/