ecore: Fix support for intl keyboards
[framework/uifw/ecore.git] / src / lib / ecore_x / xlib / ecore_x_events.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif /* ifdef HAVE_CONFIG_H */
4
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8
9 #include <langinfo.h>
10
11 #include "Ecore.h"
12 #include "ecore_private.h"
13 #include "ecore_x_private.h"
14 #include "Ecore_X.h"
15 #include "Ecore_X_Atoms.h"
16
17 /** OpenBSD does not define CODESET
18  * FIXME ??
19  */
20
21 #ifndef CODESET
22 #define CODESET "INVALID"
23 #endif /* ifndef CODESET */
24
25 typedef struct _Ecore_X_Mouse_Down_Info
26 {
27    EINA_INLIST;
28    int       dev;
29    Window    last_win;
30    Window    last_last_win;
31    Window    last_event_win;
32    Window    last_last_event_win;
33    Time      last_time;
34    Time      last_last_time;
35    Eina_Bool did_double : 1;
36    Eina_Bool did_triple : 1;
37 } Ecore_X_Mouse_Down_Info;
38
39 static int _ecore_x_last_event_mouse_move = 0;
40 static Ecore_Event *_ecore_x_last_event_mouse_move_event = NULL;
41 static Eina_Inlist *_ecore_x_mouse_down_info_list = NULL;
42
43 static void
44 _ecore_x_mouse_down_info_clear(void)
45 {
46    Eina_Inlist *l = _ecore_x_mouse_down_info_list;
47    Ecore_X_Mouse_Down_Info *info = NULL;
48    while (l)
49      {
50         info = EINA_INLIST_CONTAINER_GET(l, Ecore_X_Mouse_Down_Info);
51         l = eina_inlist_remove(l, l);
52         free(info);
53      }
54    _ecore_x_mouse_down_info_list = NULL;
55 }
56
57 void
58 _ecore_x_events_init(void)
59 {
60    //Actually, Nothing to do.
61 }
62
63 void
64 _ecore_x_events_shutdown(void)
65 {
66    _ecore_x_mouse_down_info_clear();
67 }
68
69 static Ecore_X_Mouse_Down_Info *
70 _ecore_x_mouse_down_info_get(int dev)
71 {
72    Eina_Inlist *l = _ecore_x_mouse_down_info_list;
73    Ecore_X_Mouse_Down_Info *info = NULL;
74
75    //Return the exist info
76    EINA_INLIST_FOREACH(l, info)
77      if (info->dev == dev) return info;
78
79    //New Device. Add it.
80    info = calloc(1, sizeof(Ecore_X_Mouse_Down_Info));
81    if (!info) return NULL;
82
83    info->dev = dev;
84    l = eina_inlist_append(l, (Eina_Inlist *)info);
85    _ecore_x_mouse_down_info_list = l;
86    return info;
87 }
88
89 static void
90 _ecore_x_event_free_mouse_move(void *data __UNUSED__,
91                                void *ev)
92 {
93    Ecore_Event_Mouse_Move *e;
94
95    e = ev;
96    if (_ecore_x_last_event_mouse_move)
97      {
98         _ecore_x_last_event_mouse_move_event = NULL;
99         _ecore_x_last_event_mouse_move = 0;
100      }
101
102    free(e);
103 }
104
105 EAPI void
106 ecore_x_event_mask_set(Ecore_X_Window w,
107                        Ecore_X_Event_Mask mask)
108 {
109    XWindowAttributes attr;
110    XSetWindowAttributes s_attr;
111
112    LOGFN(__FILE__, __LINE__, __FUNCTION__);
113    if (!w)
114      w = DefaultRootWindow(_ecore_x_disp);
115
116    memset(&attr, 0, sizeof(XWindowAttributes));
117    XGetWindowAttributes(_ecore_x_disp, w, &attr);
118    s_attr.event_mask = mask | attr.your_event_mask;
119    XChangeWindowAttributes(_ecore_x_disp, w, CWEventMask, &s_attr);
120 }
121
122 EAPI void
123 ecore_x_event_mask_unset(Ecore_X_Window w,
124                          Ecore_X_Event_Mask mask)
125 {
126    XWindowAttributes attr;
127    XSetWindowAttributes s_attr;
128
129    LOGFN(__FILE__, __LINE__, __FUNCTION__);
130    if (!w)
131      w = DefaultRootWindow(_ecore_x_disp);
132
133    memset(&attr, 0, sizeof(XWindowAttributes));
134    XGetWindowAttributes(_ecore_x_disp, w, &attr);
135    s_attr.event_mask = attr.your_event_mask & ~mask;
136    XChangeWindowAttributes(_ecore_x_disp, w, CWEventMask, &s_attr);
137 }
138
139 static void
140 _ecore_x_event_free_xdnd_enter(void *data __UNUSED__,
141                                void *ev)
142 {
143    Ecore_X_Event_Xdnd_Enter *e;
144    int i;
145
146    e = ev;
147    for (i = 0; i < e->num_types; i++)
148      XFree(e->types[i]);
149    free(e->types);
150    free(e);
151 }
152
153 static void
154 _ecore_x_event_free_selection_notify(void *data __UNUSED__,
155                                      void *ev)
156 {
157    Ecore_X_Event_Selection_Notify *e;
158    Ecore_X_Selection_Data *sel;
159
160    e = ev;
161    sel = e->data;
162    if (sel->free)
163      sel->free(sel);
164
165    free(e->target);
166    free(e);
167 }
168
169 static unsigned int
170 _ecore_x_event_modifiers(unsigned int state)
171 {
172    unsigned int modifiers = 0;
173
174    if (state & ECORE_X_MODIFIER_SHIFT)
175      modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
176
177    if (state & ECORE_X_MODIFIER_CTRL)
178      modifiers |= ECORE_EVENT_MODIFIER_CTRL;
179
180    if (state & ECORE_X_MODIFIER_ALT)
181      modifiers |= ECORE_EVENT_MODIFIER_ALT;
182
183    if (state & ECORE_X_MODIFIER_WIN)
184      modifiers |= ECORE_EVENT_MODIFIER_WIN;
185
186    if (state & ECORE_X_MODIFIER_MODE)
187      modifiers |= ECORE_EVENT_MODIFIER_MODE;
188
189    if (state & ECORE_X_LOCK_SCROLL)
190      modifiers |= ECORE_EVENT_LOCK_SCROLL;
191
192    if (state & ECORE_X_LOCK_NUM)
193      modifiers |= ECORE_EVENT_LOCK_NUM;
194
195    if (state & ECORE_X_LOCK_CAPS)
196      modifiers |= ECORE_EVENT_LOCK_CAPS;
197
198    if (state & ECORE_X_LOCK_SHIFT)
199      modifiers |= ECORE_EVENT_LOCK_SHIFT;
200
201    return modifiers;
202 }
203
204 void
205 _ecore_mouse_move(unsigned int timestamp,
206                   unsigned int xmodifiers,
207                   int x,
208                   int y,
209                   int x_root,
210                   int y_root,
211                   unsigned int event_window,
212                   unsigned int window,
213                   unsigned int root_win,
214                   int same_screen,
215                   int dev,
216                   double radx,
217                   double rady,
218                   double pressure,
219                   double angle,
220                   double mx,
221                   double my,
222                   double mrx,
223                   double mry)
224 {
225    Ecore_Event_Mouse_Move *e;
226    Ecore_Event *event;
227
228    e = malloc(sizeof(Ecore_Event_Mouse_Move));
229    if (!e)
230      return;
231
232    e->window = window;
233    e->root_window = root_win;
234    e->timestamp = timestamp;
235    e->same_screen = same_screen;
236    e->event_window = event_window;
237
238    e->modifiers = _ecore_x_event_modifiers(xmodifiers);
239    e->x = x;
240    e->y = y;
241    e->root.x = x_root;
242    e->root.y = y_root;
243
244    e->multi.device = dev;
245    e->multi.radius = (radx + rady) / 2;
246    e->multi.radius_x = radx;
247    e->multi.radius_y = rady;
248    e->multi.pressure = pressure;
249    e->multi.angle = angle;
250    e->multi.x = mx;
251    e->multi.y = my;
252    e->multi.root.x = mrx;
253    e->multi.root.y = mry;
254
255    event = ecore_event_add(ECORE_EVENT_MOUSE_MOVE,
256                            e,
257                            _ecore_x_event_free_mouse_move,
258                            NULL);
259
260    _ecore_x_event_last_time = timestamp;
261    _ecore_x_event_last_win = window;
262    _ecore_x_event_last_root_x = x_root;
263    _ecore_x_event_last_root_y = y_root;
264
265    _ecore_x_last_event_mouse_move_event = event;
266 }
267
268 static void
269 _ecore_key_press(int event,
270                  XKeyEvent *xevent)
271 {
272    Ecore_Event_Key *e;
273    char *compose = NULL;
274    char *tmp = NULL;
275    char *keyname;
276    char *key;
277    char keyname_buffer[256];
278    char compose_buffer[256];
279    KeySym sym;
280    XComposeStatus status;
281    int val;
282
283    _ecore_x_last_event_mouse_move = 0;
284    keyname = XKeysymToString(_ecore_x_XKeycodeToKeysym(xevent->display,
285                                                        xevent->keycode, 0));
286    if (!keyname)
287      {
288         snprintf(keyname_buffer,
289                  sizeof(keyname_buffer),
290                  "Keycode-%i",
291                  xevent->keycode);
292         keyname = keyname_buffer;
293      }
294
295    sym = 0;
296    key = NULL;
297    compose = NULL;
298    val = XLookupString(xevent,
299                        compose_buffer,
300                        sizeof(compose_buffer),
301                        &sym,
302                        &status);
303    if (val > 0)
304      {
305         compose_buffer[val] = 0;
306         compose = eina_str_convert(nl_langinfo(CODESET), "UTF-8",
307                                    compose_buffer);
308         if (!compose)
309           ERR("Ecore_X cannot convert input key string '%s' to UTF-8. "
310               "Is Eina built with iconv support?", compose_buffer);
311         tmp = compose;
312      }
313
314    key = XKeysymToString(sym);
315    if (!key)
316      key = keyname;
317
318    e =
319      malloc(sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) +
320             (compose ? strlen(compose) : 0) + 3);
321    if (!e)
322      goto on_error;
323
324    e->keyname = (char *)(e + 1);
325    e->key = e->keyname + strlen(keyname) + 1;
326    e->compose = (compose) ? e->key + strlen(key) + 1 : NULL;
327    e->string = e->compose;
328
329    strcpy((char *)e->keyname, keyname);
330    strcpy((char *)e->key, key);
331    if (compose)
332      strcpy((char *)e->compose, compose);
333
334    e->modifiers = _ecore_x_event_modifiers(xevent->state);
335
336    e->timestamp = xevent->time;
337    e->window = xevent->subwindow ? xevent->subwindow : xevent->window;
338    e->event_window = xevent->window;
339    e->same_screen = xevent->same_screen;
340    e->root_window = xevent->root;
341
342    ecore_event_add(event, e, NULL, NULL);
343
344    _ecore_x_event_last_time = e->timestamp;
345
346 on_error:
347    if (tmp)
348      free(tmp);
349 }
350
351 Ecore_Event_Mouse_Button *
352 _ecore_mouse_button(int event,
353                     unsigned int timestamp,
354                     unsigned int xmodifiers,
355                     unsigned int buttons,
356                     int x,
357                     int y,
358                     int x_root,
359                     int y_root,
360                     unsigned int event_window,
361                     unsigned int window,
362                     unsigned int root_win,
363                     int same_screen,
364                     int dev,
365                     double radx,
366                     double rady,
367                     double pressure,
368                     double angle,
369                     double mx,
370                     double my,
371                     double mrx,
372                     double mry)
373 {
374    Ecore_Event_Mouse_Button *e;
375
376    e = malloc(sizeof(Ecore_Event_Mouse_Button));
377    if (!e)
378      return NULL;
379
380    e->window = window;
381    e->root_window = root_win;
382    e->timestamp = timestamp;
383    e->same_screen = same_screen;
384    e->event_window = event_window;
385
386    e->buttons = buttons;
387    e->modifiers = _ecore_x_event_modifiers(xmodifiers);
388    e->double_click = 0;
389    e->triple_click = 0;
390    e->x = x;
391    e->y = y;
392    e->root.x = x_root;
393    e->root.y = y_root;
394
395    Ecore_X_Mouse_Down_Info *down_info = _ecore_x_mouse_down_info_get(dev);
396
397    if (down_info)
398      {
399         if ((event == ECORE_EVENT_MOUSE_BUTTON_DOWN) &&
400             down_info->did_triple)
401           {
402              down_info->last_win = 0;
403              down_info->last_last_win = 0;
404              down_info->last_event_win = 0;
405              down_info->last_last_event_win = 0;
406              down_info->last_time = 0;
407              down_info->last_last_time = 0;
408           }
409         if (event_window == window)
410           {
411              if (event == ECORE_EVENT_MOUSE_BUTTON_DOWN)
412                {
413                   //Check Double Clicked
414                   if (((int)(timestamp - down_info->last_time) <=
415                        (int)(1000 * _ecore_x_double_click_time)) &&
416                       (window == down_info->last_win) &&
417                       (event_window == down_info->last_event_win))
418                     {
419                        e->double_click = 1;
420                        down_info->did_double = EINA_TRUE;
421                     }
422                   else
423                     {
424                        down_info->did_double = EINA_FALSE;
425                        down_info->did_triple = EINA_FALSE;
426                     }
427
428                   //Check Triple Clicked
429                   if (((int)(timestamp - down_info->last_last_time) <=
430                        (int)(2 * 1000 * _ecore_x_double_click_time)) &&
431                       (window == down_info->last_win) &&
432                       (window == down_info->last_last_win) &&
433                       (event_window == down_info->last_event_win) &&
434                       (event_window == down_info->last_last_event_win)
435                       )
436                     {
437                        e->triple_click = 1;
438                        down_info->did_triple = EINA_TRUE;
439                     }
440                   else
441                     {
442                        down_info->did_triple = EINA_FALSE;
443                     }
444                }
445              else
446                {
447                   if (down_info->did_double)
448                     e->double_click = 1;
449                   if (down_info->did_triple)
450                     e->triple_click = 1;
451                }
452           }
453      }
454
455    /* NB: Block commented out as _ecore_x_mouse_up_count appears to have
456     * no use. The variable is also commented out above. This code block is
457     * the only place that this variable is used, and appears to serve no
458     * purpose. - dh
459       if (event == ECORE_EVENT_MOUSE_BUTTON_DOWN
460        && !e->double_click
461        && !e->triple_click)
462       _ecore_x_mouse_up_count = 0;
463     */
464
465    e->multi.device = dev;
466    e->multi.radius = (radx + rady) / 2;
467    e->multi.radius_x = radx;
468    e->multi.radius_y = rady;
469    e->multi.pressure = pressure;
470    e->multi.angle = angle;
471    e->multi.x = mx;
472    e->multi.y = my;
473    e->multi.root.x = mrx;
474    e->multi.root.y = mry;
475
476    _ecore_x_event_last_time = e->timestamp;
477    _ecore_x_event_last_win = e->window;
478    _ecore_x_event_last_root_x = x_root;
479    _ecore_x_event_last_root_y = y_root;
480
481    ecore_event_add(event, e, NULL, NULL);
482
483    if ((down_info) &&
484        (event == ECORE_EVENT_MOUSE_BUTTON_DOWN) &&
485        (window == event_window) &&
486        (!down_info->did_triple))
487      {
488         down_info->last_last_win = down_info->last_win;
489         down_info->last_win = window;
490         down_info->last_last_event_win = down_info->last_event_win;
491         down_info->last_event_win = event_window;
492         down_info->last_last_time = down_info->last_time;
493         down_info->last_time = timestamp;
494      }
495
496    return e;
497 }
498
499 void
500 _ecore_x_event_handle_any_event(XEvent *xevent)
501 {
502    XEvent *ev = malloc(sizeof(XEvent));
503    if (!ev) return;
504    memcpy(ev, xevent, sizeof(XEvent));
505    ecore_event_add(ECORE_X_EVENT_ANY, ev, NULL, NULL);
506 }
507
508 void
509 _ecore_x_event_handle_key_press(XEvent *xevent)
510 {
511    _ecore_key_press(ECORE_EVENT_KEY_DOWN, (XKeyEvent *)xevent);
512 }
513
514 void
515 _ecore_x_event_handle_key_release(XEvent *xevent)
516 {
517    _ecore_key_press(ECORE_EVENT_KEY_UP, (XKeyEvent *)xevent);
518 }
519
520 void
521 _ecore_x_event_handle_button_press(XEvent *xevent)
522 {
523    int i;
524
525    _ecore_x_last_event_mouse_move = 0;
526    if ((xevent->xbutton.button > 3) && (xevent->xbutton.button < 8))
527      {
528         Ecore_Event_Mouse_Wheel *e;
529
530         e = malloc(sizeof(Ecore_Event_Mouse_Wheel));
531         if (!e)
532           return;
533
534         e->timestamp = xevent->xbutton.time;
535         e->modifiers = _ecore_x_event_modifiers(xevent->xbutton.state);
536         switch (xevent->xbutton.button)
537           {
538            case 4: e->direction = 0; e->z = -1; break;
539
540            case 5: e->direction = 0; e->z = 1; break;
541
542            case 6: e->direction = 1; e->z = -1; break;
543
544            case 7: e->direction = 1; e->z = 1; break;
545
546            default: e->direction = 0; e->z = 0; break;
547           }
548
549         e->x = xevent->xbutton.x;
550         e->y = xevent->xbutton.y;
551         e->root.x = xevent->xbutton.x_root;
552         e->root.y = xevent->xbutton.y_root;
553
554         if (xevent->xbutton.subwindow)
555           e->window = xevent->xbutton.subwindow;
556         else
557           e->window = xevent->xbutton.window;
558
559         e->event_window = xevent->xbutton.window;
560         e->same_screen = xevent->xbutton.same_screen;
561         e->root_window = xevent->xbutton.root;
562
563         _ecore_x_event_last_time = e->timestamp;
564         _ecore_x_event_last_win = e->window;
565         _ecore_x_event_last_root_x = xevent->xbutton.x_root;
566         _ecore_x_event_last_root_y = xevent->xbutton.y_root;
567         ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, e, NULL, NULL);
568
569         for (i = 0; i < _ecore_window_grabs_num; i++)
570           {
571              if ((_ecore_window_grabs[i] == xevent->xbutton.window) ||
572                  (_ecore_window_grabs[i] == xevent->xbutton.subwindow))
573                {
574                   Eina_Bool replay = EINA_FALSE;
575
576                   if (_ecore_window_grab_replay_func)
577                     replay = _ecore_window_grab_replay_func(
578                         _ecore_window_grab_replay_data,
579                         ECORE_EVENT_MOUSE_WHEEL,
580                         e);
581
582                   if (replay)
583                     XAllowEvents(xevent->xbutton.display,
584                                  ReplayPointer, xevent->xbutton.time);
585                   else
586                     XAllowEvents(xevent->xbutton.display,
587                                  AsyncPointer, xevent->xbutton.time);
588
589                   break;
590                }
591           }
592      }
593    else
594      {
595         {
596            _ecore_mouse_move(xevent->xbutton.time, xevent->xbutton.state,
597                              xevent->xbutton.x, xevent->xbutton.y,
598                              xevent->xbutton.x_root, xevent->xbutton.y_root,
599                              xevent->xbutton.window,
600                              (xevent->xbutton.subwindow ? xevent->xbutton.
601                               subwindow : xevent->xbutton.window),
602                              xevent->xbutton.root,
603                              xevent->xbutton.same_screen,
604                              0, 1, 1,
605                              1.0, // pressure
606                              0.0, // angle
607                              xevent->xbutton.x, xevent->xbutton.y,
608                              xevent->xbutton.x_root, xevent->xbutton.y_root);
609         }
610         {
611            Ecore_Event_Mouse_Button *e;
612            int event_window;
613            int window;
614
615            window =
616              (xevent->xbutton.subwindow ? xevent->xbutton.subwindow : xevent->
617               xbutton.window);
618            event_window = xevent->xbutton.window;
619
620            e = _ecore_mouse_button(ECORE_EVENT_MOUSE_BUTTON_DOWN,
621                                    xevent->xbutton.time,
622                                    xevent->xbutton.state,
623                                    xevent->xbutton.button,
624                                    xevent->xbutton.x,
625                                    xevent->xbutton.y,
626                                    xevent->xbutton.x_root,
627                                    xevent->xbutton.y_root,
628                                    event_window,
629                                    window,
630                                    xevent->xbutton.root,
631                                    xevent->xbutton.same_screen,
632                                    0,
633                                    1,
634                                    1,
635                                    1.0,
636 // pressure
637                                    0.0,
638 // angle
639                                    xevent->xbutton.x,
640                                    xevent->xbutton.y,
641                                    xevent->xbutton.x_root,
642                                    xevent->xbutton.y_root);
643            if (e)
644              for (i = 0; i < _ecore_window_grabs_num; i++)
645                {
646                   if ((_ecore_window_grabs[i] == xevent->xbutton.window) ||
647                       (_ecore_window_grabs[i] == xevent->xbutton.subwindow))
648                     {
649                        Eina_Bool replay = EINA_FALSE;
650
651                        if (_ecore_window_grab_replay_func)
652                          replay = _ecore_window_grab_replay_func(
653                              _ecore_window_grab_replay_data,
654                              ECORE_EVENT_MOUSE_BUTTON_DOWN,
655                              e);
656
657                        if (replay)
658                          XAllowEvents(xevent->xbutton.display,
659                                       ReplayPointer, xevent->xbutton.time);
660                        else
661                          XAllowEvents(xevent->xbutton.display,
662                                       AsyncPointer, xevent->xbutton.time);
663
664                        break;
665                     }
666                }
667         }
668      }
669 }
670
671 void
672 _ecore_x_event_handle_button_release(XEvent *xevent)
673 {
674    _ecore_x_last_event_mouse_move = 0;
675    /* filter out wheel buttons */
676    if ((xevent->xbutton.button <= 3) || (xevent->xbutton.button > 7))
677      {
678         _ecore_mouse_move(xevent->xbutton.time, xevent->xbutton.state,
679                           xevent->xbutton.x, xevent->xbutton.y,
680                           xevent->xbutton.x_root, xevent->xbutton.y_root,
681                           xevent->xbutton.window,
682                           (xevent->xbutton.subwindow ? xevent->xbutton.
683                            subwindow : xevent->xbutton.window),
684                           xevent->xbutton.root,
685                           xevent->xbutton.same_screen,
686                           0, 1, 1,
687                           1.0, // pressure
688                           0.0, // angle
689                           xevent->xbutton.x, xevent->xbutton.y,
690                           xevent->xbutton.x_root, xevent->xbutton.y_root);
691
692         _ecore_mouse_button(ECORE_EVENT_MOUSE_BUTTON_UP,
693                             xevent->xbutton.time, xevent->xbutton.state,
694                             xevent->xbutton.button,
695                             xevent->xbutton.x, xevent->xbutton.y,
696                             xevent->xbutton.x_root, xevent->xbutton.y_root,
697                             xevent->xbutton.window,
698                             (xevent->xbutton.subwindow ? xevent->xbutton.
699                              subwindow : xevent->xbutton.window),
700                             xevent->xbutton.root,
701                             xevent->xbutton.same_screen,
702                             0, 1, 1,
703                             1.0, // pressure
704                             0.0, // angle
705                             xevent->xbutton.x, xevent->xbutton.y,
706                             xevent->xbutton.x_root, xevent->xbutton.y_root);
707      }
708 }
709
710 void
711 _ecore_x_event_handle_motion_notify(XEvent *xevent)
712 {
713 /*
714    if (_ecore_x_last_event_mouse_move)
715      {
716         ecore_event_del(_ecore_x_last_event_mouse_move_event);
717         _ecore_x_last_event_mouse_move = 0;
718         _ecore_x_last_event_mouse_move_event = NULL;
719      }
720  */
721    _ecore_mouse_move(xevent->xmotion.time, xevent->xmotion.state,
722                      xevent->xmotion.x, xevent->xmotion.y,
723                      xevent->xmotion.x_root, xevent->xmotion.y_root,
724                      xevent->xmotion.window,
725                      (xevent->xmotion.subwindow ? xevent->xmotion.subwindow :
726                       xevent->xmotion.window),
727                      xevent->xmotion.root,
728                      xevent->xmotion.same_screen,
729                      0, 1, 1,
730                      1.0,   // pressure
731                      0.0,   // angle
732                      xevent->xmotion.x, xevent->xmotion.y,
733                      xevent->xmotion.x_root, xevent->xmotion.y_root);
734
735    _ecore_x_last_event_mouse_move = 1;
736
737    /* Xdnd handling */
738    _ecore_x_dnd_drag(xevent->xmotion.root,
739                      xevent->xmotion.x_root,
740                      xevent->xmotion.y_root);
741 }
742
743 void
744 _ecore_x_event_handle_enter_notify(XEvent *xevent)
745 {
746    _ecore_x_last_event_mouse_move = 0;
747    {
748       _ecore_mouse_move(xevent->xcrossing.time, xevent->xcrossing.state,
749                         xevent->xcrossing.x, xevent->xcrossing.y,
750                         xevent->xcrossing.x_root, xevent->xcrossing.y_root,
751                         xevent->xcrossing.window,
752                         (xevent->xcrossing.subwindow ? xevent->xcrossing.
753                          subwindow : xevent->xcrossing.window),
754                         xevent->xcrossing.root,
755                         xevent->xcrossing.same_screen,
756                         0, 1, 1,
757                         1.0, // pressure
758                         0.0, // angle
759                         xevent->xcrossing.x, xevent->xcrossing.y,
760                         xevent->xcrossing.x_root, xevent->xcrossing.y_root);
761    }
762    {
763       Ecore_X_Event_Mouse_In *e;
764
765       e = calloc(1, sizeof(Ecore_X_Event_Mouse_In));
766       if (!e)
767         return;
768
769       e->modifiers = _ecore_x_event_modifiers(xevent->xcrossing.state);
770       e->x = xevent->xcrossing.x;
771       e->y = xevent->xcrossing.y;
772       e->root.x = xevent->xcrossing.x_root;
773       e->root.y = xevent->xcrossing.y_root;
774       if (xevent->xcrossing.subwindow)
775         e->win = xevent->xcrossing.subwindow;
776       else
777         e->win = xevent->xcrossing.window;
778
779       e->same_screen = xevent->xcrossing.same_screen;
780       e->root_win = xevent->xcrossing.root;
781       e->event_win = xevent->xcrossing.window;
782
783       if (xevent->xcrossing.mode == NotifyNormal)
784         e->mode = ECORE_X_EVENT_MODE_NORMAL;
785       else if (xevent->xcrossing.mode == NotifyGrab)
786         e->mode = ECORE_X_EVENT_MODE_GRAB;
787       else if (xevent->xcrossing.mode == NotifyUngrab)
788         e->mode = ECORE_X_EVENT_MODE_UNGRAB;
789
790       if (xevent->xcrossing.detail == NotifyAncestor)
791         e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
792       else if (xevent->xcrossing.detail == NotifyVirtual)
793         e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL;
794       else if (xevent->xcrossing.detail == NotifyInferior)
795         e->detail = ECORE_X_EVENT_DETAIL_INFERIOR;
796       else if (xevent->xcrossing.detail == NotifyNonlinear)
797         e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR;
798       else if (xevent->xcrossing.detail == NotifyNonlinearVirtual)
799         e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL;
800
801       e->time = xevent->xcrossing.time;
802       _ecore_x_event_last_time = e->time;
803       ecore_event_add(ECORE_X_EVENT_MOUSE_IN, e, NULL, NULL);
804    }
805 }
806
807 void
808 _ecore_x_event_handle_leave_notify(XEvent *xevent)
809 {
810    _ecore_x_last_event_mouse_move = 0;
811    {
812       _ecore_mouse_move(xevent->xcrossing.time, xevent->xcrossing.state,
813                         xevent->xcrossing.x, xevent->xcrossing.y,
814                         xevent->xcrossing.x_root, xevent->xcrossing.y_root,
815                         xevent->xcrossing.window,
816                         (xevent->xcrossing.subwindow ? xevent->xcrossing.
817                          subwindow : xevent->xcrossing.window),
818                         xevent->xcrossing.root,
819                         xevent->xcrossing.same_screen,
820                         0, 1, 1,
821                         1.0, // pressure
822                         0.0, // angle
823                         xevent->xcrossing.x, xevent->xcrossing.y,
824                         xevent->xcrossing.x_root, xevent->xcrossing.y_root);
825    }
826    {
827       Ecore_X_Event_Mouse_Out *e;
828
829       e = calloc(1, sizeof(Ecore_X_Event_Mouse_Out));
830       if (!e)
831         return;
832
833       e->modifiers = _ecore_x_event_modifiers(xevent->xcrossing.state);
834       e->x = xevent->xcrossing.x;
835       e->y = xevent->xcrossing.y;
836       e->root.x = xevent->xcrossing.x_root;
837       e->root.y = xevent->xcrossing.y_root;
838       if (xevent->xcrossing.subwindow)
839         e->win = xevent->xcrossing.subwindow;
840       else
841         e->win = xevent->xcrossing.window;
842
843       e->same_screen = xevent->xcrossing.same_screen;
844       e->root_win = xevent->xcrossing.root;
845       e->event_win = xevent->xcrossing.window;
846
847       if (xevent->xcrossing.mode == NotifyNormal)
848         e->mode = ECORE_X_EVENT_MODE_NORMAL;
849       else if (xevent->xcrossing.mode == NotifyGrab)
850         e->mode = ECORE_X_EVENT_MODE_GRAB;
851       else if (xevent->xcrossing.mode == NotifyUngrab)
852         e->mode = ECORE_X_EVENT_MODE_UNGRAB;
853
854       if (xevent->xcrossing.detail == NotifyAncestor)
855         e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
856       else if (xevent->xcrossing.detail == NotifyVirtual)
857         e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL;
858       else if (xevent->xcrossing.detail == NotifyInferior)
859         e->detail = ECORE_X_EVENT_DETAIL_INFERIOR;
860       else if (xevent->xcrossing.detail == NotifyNonlinear)
861         e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR;
862       else if (xevent->xcrossing.detail == NotifyNonlinearVirtual)
863         e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL;
864
865       e->time = xevent->xcrossing.time;
866       _ecore_x_event_last_time = e->time;
867       _ecore_x_event_last_win = e->win;
868       _ecore_x_event_last_root_x = e->root.x;
869       _ecore_x_event_last_root_y = e->root.y;
870       ecore_event_add(ECORE_X_EVENT_MOUSE_OUT, e, NULL, NULL);
871    }
872 }
873
874 void
875 _ecore_x_event_handle_focus_in(XEvent *xevent)
876 {
877    Ecore_X_Event_Window_Focus_In *e;
878
879    _ecore_x_last_event_mouse_move = 0;
880
881    e = calloc(1, sizeof(Ecore_X_Event_Window_Focus_In));
882    if (!e)
883      return;
884
885    e->win = xevent->xfocus.window;
886
887    if (xevent->xfocus.mode == NotifyNormal)
888      e->mode = ECORE_X_EVENT_MODE_NORMAL;
889    else if (xevent->xfocus.mode == NotifyWhileGrabbed)
890      e->mode = ECORE_X_EVENT_MODE_WHILE_GRABBED;
891    else if (xevent->xfocus.mode == NotifyGrab)
892      e->mode = ECORE_X_EVENT_MODE_GRAB;
893    else if (xevent->xfocus.mode == NotifyUngrab)
894      e->mode = ECORE_X_EVENT_MODE_UNGRAB;
895
896    if (xevent->xfocus.detail == NotifyAncestor)
897      e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
898    else if (xevent->xfocus.detail == NotifyVirtual)
899      e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL;
900    else if (xevent->xfocus.detail == NotifyInferior)
901      e->detail = ECORE_X_EVENT_DETAIL_INFERIOR;
902    else if (xevent->xfocus.detail == NotifyNonlinear)
903      e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR;
904    else if (xevent->xfocus.detail == NotifyNonlinearVirtual)
905      e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL;
906    else if (xevent->xfocus.detail == NotifyPointer)
907      e->detail = ECORE_X_EVENT_DETAIL_POINTER;
908    else if (xevent->xfocus.detail == NotifyPointerRoot)
909      e->detail = ECORE_X_EVENT_DETAIL_POINTER_ROOT;
910    else if (xevent->xfocus.detail == NotifyDetailNone)
911      e->detail = ECORE_X_EVENT_DETAIL_DETAIL_NONE;
912
913    e->time = _ecore_x_event_last_time;
914    _ecore_x_event_last_time = e->time;
915    ecore_event_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, e, NULL, NULL);
916 }
917
918 void
919 _ecore_x_event_handle_focus_out(XEvent *xevent)
920 {
921    Ecore_X_Event_Window_Focus_Out *e;
922
923    _ecore_x_last_event_mouse_move = 0;
924
925    e = calloc(1, sizeof(Ecore_X_Event_Window_Focus_Out));
926    if (!e)
927      return;
928
929    e->win = xevent->xfocus.window;
930
931    if (xevent->xfocus.mode == NotifyNormal)
932      e->mode = ECORE_X_EVENT_MODE_NORMAL;
933    else if (xevent->xfocus.mode == NotifyWhileGrabbed)
934      e->mode = ECORE_X_EVENT_MODE_WHILE_GRABBED;
935    else if (xevent->xfocus.mode == NotifyGrab)
936      e->mode = ECORE_X_EVENT_MODE_GRAB;
937    else if (xevent->xfocus.mode == NotifyUngrab)
938      e->mode = ECORE_X_EVENT_MODE_UNGRAB;
939
940    if (xevent->xfocus.detail == NotifyAncestor)
941      e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
942    else if (xevent->xfocus.detail == NotifyVirtual)
943      e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL;
944    else if (xevent->xfocus.detail == NotifyInferior)
945      e->detail = ECORE_X_EVENT_DETAIL_INFERIOR;
946    else if (xevent->xfocus.detail == NotifyNonlinear)
947      e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR;
948    else if (xevent->xfocus.detail == NotifyNonlinearVirtual)
949      e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL;
950    else if (xevent->xfocus.detail == NotifyPointer)
951      e->detail = ECORE_X_EVENT_DETAIL_POINTER;
952    else if (xevent->xfocus.detail == NotifyPointerRoot)
953      e->detail = ECORE_X_EVENT_DETAIL_POINTER_ROOT;
954    else if (xevent->xfocus.detail == NotifyDetailNone)
955      e->detail = ECORE_X_EVENT_DETAIL_DETAIL_NONE;
956
957    e->time = _ecore_x_event_last_time;
958    _ecore_x_event_last_time = e->time;
959    ecore_event_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, e, NULL, NULL);
960 }
961
962 void
963 _ecore_x_event_handle_keymap_notify(XEvent *xevent __UNUSED__)
964 {
965    _ecore_x_last_event_mouse_move = 0;
966    /* FIXME: handle this event type */
967 }
968
969 void
970 _ecore_x_event_handle_expose(XEvent *xevent)
971 {
972    Ecore_X_Event_Window_Damage *e;
973
974    _ecore_x_last_event_mouse_move = 0;
975    e = calloc(1, sizeof(Ecore_X_Event_Window_Damage));
976    if (!e)
977      return;
978
979    e->win = xevent->xexpose.window;
980    e->time = _ecore_x_event_last_time;
981    e->x = xevent->xexpose.x;
982    e->y = xevent->xexpose.y;
983    e->w = xevent->xexpose.width;
984    e->h = xevent->xexpose.height;
985    e->count = xevent->xexpose.count;
986    ecore_event_add(ECORE_X_EVENT_WINDOW_DAMAGE, e, NULL, NULL);
987 }
988
989 void
990 _ecore_x_event_handle_graphics_expose(XEvent *xevent)
991 {
992    Ecore_X_Event_Window_Damage *e;
993
994    _ecore_x_last_event_mouse_move = 0;
995    e = calloc(1, sizeof(Ecore_X_Event_Window_Damage));
996    if (!e)
997      return;
998
999    e->win = xevent->xgraphicsexpose.drawable;
1000    e->time = _ecore_x_event_last_time;
1001    e->x = xevent->xgraphicsexpose.x;
1002    e->y = xevent->xgraphicsexpose.y;
1003    e->w = xevent->xgraphicsexpose.width;
1004    e->h = xevent->xgraphicsexpose.height;
1005    e->count = xevent->xgraphicsexpose.count;
1006    ecore_event_add(ECORE_X_EVENT_WINDOW_DAMAGE, e, NULL, NULL);
1007 }
1008
1009 void
1010 _ecore_x_event_handle_visibility_notify(XEvent *xevent)
1011 {
1012    _ecore_x_last_event_mouse_move = 0;
1013 //   if (xevent->xvisibility.state != VisibilityPartiallyObscured)
1014    {
1015       Ecore_X_Event_Window_Visibility_Change *e;
1016
1017       e = calloc(1, sizeof(Ecore_X_Event_Window_Visibility_Change));
1018       if (!e)
1019         return;
1020
1021       e->win = xevent->xvisibility.window;
1022       e->time = _ecore_x_event_last_time;
1023       if (xevent->xvisibility.state == VisibilityFullyObscured)
1024         e->fully_obscured = 1;
1025       else
1026         e->fully_obscured = 0;
1027
1028       ecore_event_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE, e, NULL, NULL);
1029    }
1030 }
1031
1032 void
1033 _ecore_x_event_handle_create_notify(XEvent *xevent)
1034 {
1035    Ecore_X_Event_Window_Create *e;
1036
1037    _ecore_x_last_event_mouse_move = 0;
1038    e = calloc(1, sizeof(Ecore_X_Event_Window_Create));
1039    if (!e)
1040      return;
1041
1042    e->win = xevent->xcreatewindow.window;
1043    e->parent = xevent->xcreatewindow.parent;
1044    if (xevent->xcreatewindow.override_redirect)
1045      e->override = 1;
1046    else
1047      e->override = 0;
1048
1049    e->x = xevent->xcreatewindow.x;
1050    e->y = xevent->xcreatewindow.y;
1051    e->w = xevent->xcreatewindow.width;
1052    e->h = xevent->xcreatewindow.height;
1053    e->border = xevent->xcreatewindow.border_width;
1054    e->time = _ecore_x_event_last_time;
1055    ecore_event_add(ECORE_X_EVENT_WINDOW_CREATE, e, NULL, NULL);
1056 }
1057
1058 void
1059 _ecore_x_event_handle_destroy_notify(XEvent *xevent)
1060 {
1061    Ecore_X_Event_Window_Destroy *e;
1062
1063    _ecore_x_last_event_mouse_move = 0;
1064    e = calloc(1, sizeof(Ecore_X_Event_Window_Destroy));
1065    if (!e)
1066      return;
1067
1068    e->win = xevent->xdestroywindow.window;
1069    e->event_win = xevent->xdestroywindow.event;
1070    e->time = _ecore_x_event_last_time;
1071    if (e->win == _ecore_x_event_last_win)
1072      _ecore_x_event_last_win = 0;
1073
1074    ecore_event_add(ECORE_X_EVENT_WINDOW_DESTROY, e, NULL, NULL);
1075 }
1076
1077 void
1078 _ecore_x_event_handle_unmap_notify(XEvent *xevent)
1079 {
1080    Ecore_X_Event_Window_Hide *e;
1081
1082    _ecore_x_last_event_mouse_move = 0;
1083    e = calloc(1, sizeof(Ecore_X_Event_Window_Hide));
1084    if (!e)
1085      return;
1086
1087    e->win = xevent->xunmap.window;
1088    e->event_win = xevent->xunmap.event;
1089    e->time = _ecore_x_event_last_time;
1090    ecore_event_add(ECORE_X_EVENT_WINDOW_HIDE, e, NULL, NULL);
1091 }
1092
1093 void
1094 _ecore_x_event_handle_map_notify(XEvent *xevent)
1095 {
1096    Ecore_X_Event_Window_Show *e;
1097
1098    _ecore_x_last_event_mouse_move = 0;
1099    e = calloc(1, sizeof(Ecore_X_Event_Window_Show));
1100    if (!e)
1101      return;
1102
1103    e->win = xevent->xmap.window;
1104    e->event_win = xevent->xmap.event;
1105    e->time = _ecore_x_event_last_time;
1106    ecore_event_add(ECORE_X_EVENT_WINDOW_SHOW, e, NULL, NULL);
1107 }
1108
1109 void
1110 _ecore_x_event_handle_map_request(XEvent *xevent)
1111 {
1112    Ecore_X_Event_Window_Show_Request *e;
1113
1114    _ecore_x_last_event_mouse_move = 0;
1115    e = calloc(1, sizeof(Ecore_X_Event_Window_Show_Request));
1116    if (!e)
1117      return;
1118
1119    e->win = xevent->xmaprequest.window;
1120    e->time = _ecore_x_event_last_time;
1121    e->parent = xevent->xmaprequest.parent;
1122    ecore_event_add(ECORE_X_EVENT_WINDOW_SHOW_REQUEST, e, NULL, NULL);
1123 }
1124
1125 void
1126 _ecore_x_event_handle_reparent_notify(XEvent *xevent)
1127 {
1128    Ecore_X_Event_Window_Reparent *e;
1129
1130    _ecore_x_last_event_mouse_move = 0;
1131    e = calloc(1, sizeof(Ecore_X_Event_Window_Reparent));
1132    if (!e)
1133      return;
1134
1135    e->win = xevent->xreparent.window;
1136    e->event_win = xevent->xreparent.event;
1137    e->parent = xevent->xreparent.parent;
1138    e->time = _ecore_x_event_last_time;
1139    ecore_event_add(ECORE_X_EVENT_WINDOW_REPARENT, e, NULL, NULL);
1140 }
1141
1142 void
1143 _ecore_x_event_handle_configure_notify(XEvent *xevent)
1144 {
1145    Ecore_X_Event_Window_Configure *e;
1146
1147    _ecore_x_last_event_mouse_move = 0;
1148    e = calloc(1, sizeof(Ecore_X_Event_Window_Configure));
1149    if (!e)
1150      return;
1151
1152    e->win = xevent->xconfigure.window;
1153    e->event_win = xevent->xconfigure.event;
1154    e->abovewin = xevent->xconfigure.above;
1155    e->x = xevent->xconfigure.x;
1156    e->y = xevent->xconfigure.y;
1157    e->w = xevent->xconfigure.width;
1158    e->h = xevent->xconfigure.height;
1159    e->border = xevent->xconfigure.border_width;
1160    e->override = xevent->xconfigure.override_redirect;
1161    e->from_wm = xevent->xconfigure.send_event;
1162    e->time = _ecore_x_event_last_time;
1163    ecore_event_add(ECORE_X_EVENT_WINDOW_CONFIGURE, e, NULL, NULL);
1164 }
1165
1166 void
1167 _ecore_x_event_handle_configure_request(XEvent *xevent)
1168 {
1169    Ecore_X_Event_Window_Configure_Request *e;
1170
1171    _ecore_x_last_event_mouse_move = 0;
1172    e = calloc(1, sizeof(Ecore_X_Event_Window_Configure_Request));
1173    if (!e)
1174      return;
1175
1176    e->win = xevent->xconfigurerequest.window;
1177    e->parent_win = xevent->xconfigurerequest.parent;
1178    e->abovewin = xevent->xconfigurerequest.above;
1179    e->x = xevent->xconfigurerequest.x;
1180    e->y = xevent->xconfigurerequest.y;
1181    e->w = xevent->xconfigurerequest.width;
1182    e->h = xevent->xconfigurerequest.height;
1183    e->border = xevent->xconfigurerequest.border_width;
1184    e->value_mask = xevent->xconfigurerequest.value_mask;
1185    e->time = _ecore_x_event_last_time;
1186
1187    if (xevent->xconfigurerequest.detail == Above)
1188      e->detail = ECORE_X_WINDOW_STACK_ABOVE;
1189    else if (xevent->xconfigurerequest.detail == Below)
1190      e->detail = ECORE_X_WINDOW_STACK_BELOW;
1191    else if (xevent->xconfigurerequest.detail == TopIf)
1192      e->detail = ECORE_X_WINDOW_STACK_TOP_IF;
1193    else if (xevent->xconfigurerequest.detail == BottomIf)
1194      e->detail = ECORE_X_WINDOW_STACK_BOTTOM_IF;
1195    else if (xevent->xconfigurerequest.detail == Opposite)
1196      e->detail = ECORE_X_WINDOW_STACK_OPPOSITE;
1197
1198    ecore_event_add(ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST, e, NULL, NULL);
1199 }
1200
1201 void
1202 _ecore_x_event_handle_gravity_notify(XEvent *xevent __UNUSED__)
1203 {
1204    _ecore_x_last_event_mouse_move = 0;
1205    /* FIXME: handle this event type */
1206 }
1207
1208 void
1209 _ecore_x_event_handle_resize_request(XEvent *xevent)
1210 {
1211    Ecore_X_Event_Window_Resize_Request *e;
1212
1213    _ecore_x_last_event_mouse_move = 0;
1214    e = calloc(1, sizeof(Ecore_X_Event_Window_Resize_Request));
1215    if (!e)
1216      return;
1217
1218    e->win = xevent->xresizerequest.window;
1219    e->w = xevent->xresizerequest.width;
1220    e->h = xevent->xresizerequest.height;
1221    e->time = _ecore_x_event_last_time;
1222    ecore_event_add(ECORE_X_EVENT_WINDOW_RESIZE_REQUEST, e, NULL, NULL);
1223 }
1224
1225 void
1226 _ecore_x_event_handle_circulate_notify(XEvent *xevent)
1227 {
1228    Ecore_X_Event_Window_Stack *e;
1229
1230    _ecore_x_last_event_mouse_move = 0;
1231    e = calloc(1, sizeof(Ecore_X_Event_Window_Stack));
1232    if (!e)
1233      return;
1234
1235    e->win = xevent->xcirculate.window;
1236    e->event_win = xevent->xcirculate.event;
1237    if (xevent->xcirculate.place == PlaceOnTop)
1238      e->detail = ECORE_X_WINDOW_STACK_ABOVE;
1239    else
1240      e->detail = ECORE_X_WINDOW_STACK_BELOW;
1241
1242    e->time = _ecore_x_event_last_time;
1243    ecore_event_add(ECORE_X_EVENT_WINDOW_STACK, e, NULL, NULL);
1244 }
1245
1246 void
1247 _ecore_x_event_handle_circulate_request(XEvent *xevent)
1248 {
1249    Ecore_X_Event_Window_Stack_Request *e;
1250
1251    _ecore_x_last_event_mouse_move = 0;
1252    e = calloc(1, sizeof(Ecore_X_Event_Window_Stack_Request));
1253    if (!e)
1254      return;
1255
1256    e->win = xevent->xcirculaterequest.window;
1257    e->parent = xevent->xcirculaterequest.parent;
1258    if (xevent->xcirculaterequest.place == PlaceOnTop)
1259      e->detail = ECORE_X_WINDOW_STACK_ABOVE;
1260    else
1261      e->detail = ECORE_X_WINDOW_STACK_BELOW;
1262
1263    e->time = _ecore_x_event_last_time;
1264    ecore_event_add(ECORE_X_EVENT_WINDOW_STACK_REQUEST, e, NULL, NULL);
1265 }
1266
1267 void
1268 _ecore_x_event_handle_property_notify(XEvent *xevent)
1269 {
1270    _ecore_x_last_event_mouse_move = 0;
1271    {
1272       Ecore_X_Event_Window_Property *e;
1273
1274       e = calloc(1, sizeof(Ecore_X_Event_Window_Property));
1275       if (!e)
1276         return;
1277
1278       e->win = xevent->xproperty.window;
1279       e->atom = xevent->xproperty.atom;
1280       e->time = xevent->xproperty.time;
1281       _ecore_x_event_last_time = e->time;
1282       ecore_event_add(ECORE_X_EVENT_WINDOW_PROPERTY, e, NULL, NULL);
1283    }
1284 }
1285
1286 void
1287 _ecore_x_event_handle_selection_clear(XEvent *xevent)
1288 {
1289 //   Ecore_X_Selection_Intern *d;
1290    Ecore_X_Event_Selection_Clear *e;
1291    Ecore_X_Atom sel;
1292
1293    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1294    _ecore_x_last_event_mouse_move = 0;
1295 /* errr..... why? paranoia.
1296    d = _ecore_x_selection_get(xevent->xselectionclear.selection);
1297    if (d && (xevent->xselectionclear.time > d->time))
1298      {
1299         _ecore_x_selection_set(None, NULL, 0,
1300                                xevent->xselectionclear.selection);
1301      }
1302  */
1303 /* Generate event for app cleanup */
1304    e = malloc(sizeof(Ecore_X_Event_Selection_Clear));
1305    e->win = xevent->xselectionclear.window;
1306    e->time = xevent->xselectionclear.time;
1307    e->atom = sel = xevent->xselectionclear.selection;
1308    if (sel == ECORE_X_ATOM_SELECTION_PRIMARY)
1309      e->selection = ECORE_X_SELECTION_PRIMARY;
1310    else if (sel == ECORE_X_ATOM_SELECTION_SECONDARY)
1311      e->selection = ECORE_X_SELECTION_SECONDARY;
1312    else if (sel == ECORE_X_ATOM_SELECTION_CLIPBOARD)
1313      e->selection = ECORE_X_SELECTION_CLIPBOARD;
1314    else
1315      e->selection = ECORE_X_SELECTION_OTHER;
1316
1317    ecore_event_add(ECORE_X_EVENT_SELECTION_CLEAR, e, NULL, NULL);
1318 }
1319
1320 void
1321 _ecore_x_event_handle_selection_request(XEvent *xevent)
1322 {
1323    Ecore_X_Event_Selection_Request *e;
1324    Ecore_X_Selection_Intern *sd;
1325    void *data = NULL;
1326    int len;
1327    int typesize;
1328
1329    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1330    _ecore_x_last_event_mouse_move = 0;
1331    /*
1332     * Generate a selection request event.
1333     */
1334    e = malloc(sizeof(Ecore_X_Event_Selection_Request));
1335    e->owner = xevent->xselectionrequest.owner;
1336    e->requestor = xevent->xselectionrequest.requestor;
1337    e->time = xevent->xselectionrequest.time;
1338    e->selection = xevent->xselectionrequest.selection;
1339    e->target = xevent->xselectionrequest.target;
1340    e->property = xevent->xselectionrequest.property;
1341    ecore_event_add(ECORE_X_EVENT_SELECTION_REQUEST, e, NULL, NULL);
1342
1343    if ((sd = _ecore_x_selection_get(xevent->xselectionrequest.selection)) &&
1344        (sd->win == xevent->xselectionrequest.owner))
1345      {
1346         Ecore_X_Selection_Intern *si;
1347
1348         si = _ecore_x_selection_get(xevent->xselectionrequest.selection);
1349         if (si->data)
1350           {
1351              Ecore_X_Atom property = None;
1352              Ecore_X_Atom type;
1353
1354              /* Set up defaults for strings first */
1355              type = xevent->xselectionrequest.target;
1356              typesize = 8;
1357              len = sd->length;
1358
1359              if (!ecore_x_selection_convert(xevent->xselectionrequest.selection,
1360                                             xevent->xselectionrequest.target,
1361                                             &data, &len, &type, &typesize))
1362                /* Refuse selection, conversion to requested target failed */
1363                property = None;
1364              else if (data)
1365                {
1366                   /* FIXME: This does not properly handle large data transfers */
1367                   ecore_x_window_prop_property_set(
1368                     xevent->xselectionrequest.requestor,
1369                     xevent->xselectionrequest.
1370                     property,
1371                     type,
1372                     typesize,
1373                     data,
1374                     len);
1375                   property = xevent->xselectionrequest.property;
1376                   free(data);
1377                }
1378
1379              ecore_x_selection_notify_send(xevent->xselectionrequest.requestor,
1380                                            xevent->xselectionrequest.selection,
1381                                            xevent->xselectionrequest.target,
1382                                            property,
1383                                            xevent->xselectionrequest.time);
1384           }
1385      }
1386 }
1387
1388 void
1389 _ecore_x_event_handle_selection_notify(XEvent *xevent)
1390 {
1391    Ecore_X_Event_Selection_Notify *e;
1392    unsigned char *data = NULL;
1393    Ecore_X_Atom selection;
1394    int num_ret, format;
1395
1396    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1397    _ecore_x_last_event_mouse_move = 0;
1398    selection = xevent->xselection.selection;
1399
1400    if (xevent->xselection.target == ECORE_X_ATOM_SELECTION_TARGETS)
1401      {
1402         format = ecore_x_window_prop_property_get(xevent->xselection.requestor,
1403                                                   xevent->xselection.property,
1404                                                   XA_ATOM, 32, &data, &num_ret);
1405         if (!format)
1406           return;
1407      }
1408    else
1409      {
1410         format = ecore_x_window_prop_property_get(xevent->xselection.requestor,
1411                                                   xevent->xselection.property,
1412                                                   AnyPropertyType, 8, &data,
1413                                                   &num_ret);
1414         if (!format)
1415           return;
1416      }
1417
1418    e = calloc(1, sizeof(Ecore_X_Event_Selection_Notify));
1419    if (!e)
1420      return;
1421
1422    e->win = xevent->xselection.requestor;
1423    e->time = xevent->xselection.time;
1424    e->atom = selection;
1425    e->target = _ecore_x_selection_target_get(xevent->xselection.target);
1426
1427    if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
1428      e->selection = ECORE_X_SELECTION_PRIMARY;
1429    else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
1430      e->selection = ECORE_X_SELECTION_SECONDARY;
1431    else if (selection == ECORE_X_ATOM_SELECTION_XDND)
1432      e->selection = ECORE_X_SELECTION_XDND;
1433    else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
1434      e->selection = ECORE_X_SELECTION_CLIPBOARD;
1435    else
1436      e->selection = ECORE_X_SELECTION_OTHER;
1437
1438    e->data = _ecore_x_selection_parse(e->target, data, num_ret, format);
1439
1440    ecore_event_add(ECORE_X_EVENT_SELECTION_NOTIFY, e,
1441                    _ecore_x_event_free_selection_notify, NULL);
1442 }
1443
1444 void
1445 _ecore_x_event_handle_colormap_notify(XEvent *xevent)
1446 {
1447    Ecore_X_Event_Window_Colormap *e;
1448
1449    _ecore_x_last_event_mouse_move = 0;
1450    e = calloc(1, sizeof(Ecore_X_Event_Window_Colormap));
1451    if (!e)
1452      return;
1453
1454    e->win = xevent->xcolormap.window;
1455    e->cmap = xevent->xcolormap.colormap;
1456    e->time = _ecore_x_event_last_time;
1457    if (xevent->xcolormap.state == ColormapInstalled)
1458      e->installed = EINA_TRUE;
1459    else
1460      e->installed = EINA_FALSE;
1461
1462    ecore_event_add(ECORE_X_EVENT_WINDOW_COLORMAP, e, NULL, NULL);
1463 }
1464
1465 void
1466 _ecore_x_event_handle_client_message(XEvent *xevent)
1467 {
1468    _ecore_x_last_event_mouse_move = 0;
1469    /* Special client message event handling here. need to put LOTS of if */
1470    /* checks here and generate synthetic events per special message known */
1471    /* otherwise generate generic client message event. this would handle*/
1472    /* netwm, ICCCM, gnomewm, old kde and mwm hint client message protocols */
1473    if ((xevent->xclient.message_type == ECORE_X_ATOM_WM_PROTOCOLS) &&
1474        (xevent->xclient.format == 32) &&
1475        (xevent->xclient.data.l[0] == (long)ECORE_X_ATOM_WM_DELETE_WINDOW))
1476      {
1477         Ecore_X_Event_Window_Delete_Request *e;
1478
1479         e = calloc(1, sizeof(Ecore_X_Event_Window_Delete_Request));
1480         if (!e)
1481           return;
1482
1483         e->win = xevent->xclient.window;
1484         e->time = _ecore_x_event_last_time;
1485         ecore_event_add(ECORE_X_EVENT_WINDOW_DELETE_REQUEST, e, NULL, NULL);
1486      }
1487    else if ((xevent->xclient.message_type == ECORE_X_ATOM_NET_WM_MOVERESIZE) &&
1488             (xevent->xclient.format == 32) &&
1489 /* Ignore move and resize with keyboard */
1490             (xevent->xclient.data.l[2] < 9))
1491      {
1492         Ecore_X_Event_Window_Move_Resize_Request *e;
1493
1494         e = calloc(1, sizeof(Ecore_X_Event_Window_Move_Resize_Request));
1495         if (!e)
1496           return;
1497
1498         e->win = xevent->xclient.window;
1499         e->x = xevent->xclient.data.l[0];
1500         e->y = xevent->xclient.data.l[1];
1501         e->direction = xevent->xclient.data.l[2];
1502         e->button = xevent->xclient.data.l[3];
1503         e->source = xevent->xclient.data.l[4];
1504         ecore_event_add(ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST, e, NULL, NULL);
1505      }
1506    /* Xdnd Client Message Handling Begin */
1507    /* Message Type: XdndEnter target */
1508    else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_ENTER)
1509      {
1510         Ecore_X_Event_Xdnd_Enter *e;
1511         Ecore_X_DND_Target *target;
1512
1513         e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Enter));
1514         if (!e) return;
1515
1516         LOGFN(__FILE__, __LINE__, __FUNCTION__);
1517
1518         target = _ecore_x_dnd_target_get();
1519         target->state = ECORE_X_DND_TARGET_ENTERED;
1520         target->source = xevent->xclient.data.l[0];
1521         target->win = xevent->xclient.window;
1522         target->version = (int)(xevent->xclient.data.l[1] >> 24);
1523         if (target->version > ECORE_X_DND_VERSION)
1524           {
1525              WRN("DND: Requested version %d, we only support up to %d",
1526                  target->version, ECORE_X_DND_VERSION);
1527              free(e);
1528              return;
1529           }
1530
1531         if (xevent->xclient.data.l[1] & 0x1UL)
1532           {
1533              /* source supports more than 3 types, fetch property */
1534              unsigned char *data;
1535              Ecore_X_Atom *types;
1536              int i, num_ret;
1537
1538              LOGFN(__FILE__, __LINE__, __FUNCTION__);
1539              if (!(ecore_x_window_prop_property_get(target->source,
1540                                                     ECORE_X_ATOM_XDND_TYPE_LIST,
1541                                                     XA_ATOM,
1542                                                     32, &data, &num_ret)))
1543                {
1544                   WRN(
1545                     "DND: Could not fetch data type list from source window, aborting.");
1546                   free(e);
1547                   return;
1548                }
1549
1550              types = (Ecore_X_Atom *)data;
1551              e->types = calloc(num_ret, sizeof(char *));
1552              if (e->types)
1553                {
1554                   LOGFN(__FILE__, __LINE__, __FUNCTION__);
1555                   for (i = 0; i < num_ret; i++)
1556                     e->types[i] = XGetAtomName(_ecore_x_disp, types[i]);
1557                }
1558
1559              e->num_types = num_ret;
1560           }
1561         else
1562           {
1563              int i = 0;
1564
1565              e->types = calloc(3, sizeof(char *));
1566              if (e->types)
1567                {
1568                   LOGFN(__FILE__, __LINE__, __FUNCTION__);
1569                   while ((i < 3) && (xevent->xclient.data.l[i + 2]))
1570                     {
1571                        e->types[i] = XGetAtomName(_ecore_x_disp,
1572                                                   xevent->xclient.data.l[i + 2]);
1573                        i++;
1574                     }
1575                }
1576
1577              e->num_types = i;
1578           }
1579
1580         e->win = target->win;
1581         e->source = target->source;
1582         ecore_event_add(ECORE_X_EVENT_XDND_ENTER, e,
1583                         _ecore_x_event_free_xdnd_enter, NULL);
1584      }
1585    /* Message Type: XdndPosition target */
1586    else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_POSITION)
1587      {
1588         Ecore_X_Event_Xdnd_Position *e;
1589         Ecore_X_DND_Target *target;
1590
1591         LOGFN(__FILE__, __LINE__, __FUNCTION__);
1592
1593         target = _ecore_x_dnd_target_get();
1594         if ((target->source != (Ecore_X_Window)xevent->xclient.data.l[0]) ||
1595             (target->win != xevent->xclient.window))
1596           return;
1597
1598         target->pos.x = xevent->xclient.data.l[2] >> 16;
1599         target->pos.y = xevent->xclient.data.l[2] & 0xFFFFUL;
1600         target->action = xevent->xclient.data.l[4]; /* Version 2 */
1601
1602         target->time = (target->version >= 1) ?
1603           (Time)xevent->xclient.data.l[3] : CurrentTime;
1604
1605         e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Position));
1606         if (!e) return;
1607
1608         e->win = target->win;
1609         e->source = target->source;
1610         e->position.x = target->pos.x;
1611         e->position.y = target->pos.y;
1612         e->action = target->action;
1613         ecore_event_add(ECORE_X_EVENT_XDND_POSITION, e, NULL, NULL);
1614      }
1615    /* Message Type: XdndStatus source */
1616    else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_STATUS)
1617      {
1618         Ecore_X_Event_Xdnd_Status *e;
1619         Ecore_X_DND_Source *source;
1620
1621         LOGFN(__FILE__, __LINE__, __FUNCTION__);
1622
1623         source = _ecore_x_dnd_source_get();
1624         /* Make sure source/target match */
1625         if ((source->win != xevent->xclient.window) ||
1626             (source->dest != (Window)xevent->xclient.data.l[0]))
1627           return;
1628
1629         source->await_status = 0;
1630
1631         source->will_accept = xevent->xclient.data.l[1] & 0x1UL;
1632         source->suppress = (xevent->xclient.data.l[1] & 0x2UL) ? 0 : 1;
1633
1634         source->rectangle.x = xevent->xclient.data.l[2] >> 16;
1635         source->rectangle.y = xevent->xclient.data.l[2] & 0xFFFFUL;
1636         source->rectangle.width = xevent->xclient.data.l[3] >> 16;
1637         source->rectangle.height = xevent->xclient.data.l[3] & 0xFFFFUL;
1638
1639         source->accepted_action = xevent->xclient.data.l[4];
1640
1641         e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Status));
1642         if (!e) return;
1643
1644         e->win = source->win;
1645         e->target = source->dest;
1646         e->will_accept = source->will_accept;
1647         e->rectangle.x = source->rectangle.x;
1648         e->rectangle.y = source->rectangle.y;
1649         e->rectangle.width = source->rectangle.width;
1650         e->rectangle.height = source->rectangle.height;
1651         e->action = source->accepted_action;
1652
1653         ecore_event_add(ECORE_X_EVENT_XDND_STATUS, e, NULL, NULL);
1654      }
1655    /* Message Type: XdndLeave target */
1656    /* Pretend the whole thing never happened, sort of */
1657    else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_LEAVE)
1658      {
1659         Ecore_X_Event_Xdnd_Leave *e;
1660         Ecore_X_DND_Target *target;
1661
1662         LOGFN(__FILE__, __LINE__, __FUNCTION__);
1663
1664         target = _ecore_x_dnd_target_get();
1665         if ((target->source != (Ecore_X_Window)xevent->xclient.data.l[0]) ||
1666             (target->win != xevent->xclient.window))
1667           return;
1668
1669         target->state = ECORE_X_DND_TARGET_IDLE;
1670
1671         e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Leave));
1672         if (!e) return;
1673
1674         e->win = xevent->xclient.window;
1675         e->source = (Window)xevent->xclient.data.l[0];
1676         ecore_event_add(ECORE_X_EVENT_XDND_LEAVE, e, NULL, NULL);
1677      }
1678    /* Message Type: XdndDrop target */
1679    else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_DROP)
1680      {
1681         Ecore_X_Event_Xdnd_Drop *e;
1682         Ecore_X_DND_Target *target;
1683
1684         LOGFN(__FILE__, __LINE__, __FUNCTION__);
1685
1686         target = _ecore_x_dnd_target_get();
1687         /* Match source/target */
1688         if ((target->source != (Window)xevent->xclient.data.l[0]) ||
1689             (target->win != xevent->xclient.window))
1690           return;
1691
1692         target->time = (target->version >= 1) ?
1693           (Time)xevent->xclient.data.l[2] : _ecore_x_event_last_time;
1694
1695         e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Drop));
1696         if (!e) return;
1697
1698         e->win = target->win;
1699         e->source = target->source;
1700         e->action = target->action;
1701         e->position.x = target->pos.x;
1702         e->position.y = target->pos.y;
1703         ecore_event_add(ECORE_X_EVENT_XDND_DROP, e, NULL, NULL);
1704      }
1705    /* Message Type: XdndFinished source */
1706    else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_FINISHED)
1707      {
1708         Ecore_X_Event_Xdnd_Finished *e;
1709         Ecore_X_DND_Source *source;
1710         Eina_Bool completed = EINA_TRUE;
1711
1712         LOGFN(__FILE__, __LINE__, __FUNCTION__);
1713
1714         source = _ecore_x_dnd_source_get();
1715         /* Match source/target */
1716         if ((source->win != xevent->xclient.window) ||
1717             (source->dest != (Window)xevent->xclient.data.l[0]))
1718           return;
1719
1720         if ((source->version < 5) || (xevent->xclient.data.l[1] & 0x1UL))
1721           {
1722              LOGFN(__FILE__, __LINE__, __FUNCTION__);
1723              /* Target successfully performed drop action */
1724              ecore_x_selection_xdnd_clear();
1725              source->state = ECORE_X_DND_SOURCE_IDLE;
1726           }
1727         else if (source->version >= 5)
1728           {
1729              completed = EINA_FALSE;
1730              source->state = ECORE_X_DND_SOURCE_CONVERTING;
1731
1732              /* FIXME: Probably need to add a timer to switch back to idle
1733               * and discard the selection data */
1734           }
1735
1736         e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Finished));
1737         if (!e) return;
1738
1739         e->win = source->win;
1740         e->target = source->dest;
1741         e->completed = completed;
1742         if (source->version >= 5)
1743           {
1744              source->accepted_action = xevent->xclient.data.l[2];
1745              e->action = source->accepted_action;
1746           }
1747         else
1748           {
1749              source->accepted_action = 0;
1750              e->action = source->action;
1751           }
1752
1753         ecore_event_add(ECORE_X_EVENT_XDND_FINISHED, e, NULL, NULL);
1754      }
1755    else if (xevent->xclient.message_type == ECORE_X_ATOM_NET_WM_STATE)
1756      {
1757         Ecore_X_Event_Window_State_Request *e;
1758
1759         e = calloc(1, sizeof(Ecore_X_Event_Window_State_Request));
1760         if (!e) return;
1761
1762         e->win = xevent->xclient.window;
1763         if (xevent->xclient.data.l[0] == 0)
1764           e->action = ECORE_X_WINDOW_STATE_ACTION_REMOVE;
1765         else if (xevent->xclient.data.l[0] == 1)
1766           e->action = ECORE_X_WINDOW_STATE_ACTION_ADD;
1767         else if (xevent->xclient.data.l[0] == 2)
1768           e->action = ECORE_X_WINDOW_STATE_ACTION_TOGGLE;
1769         else
1770           {
1771              free(e);
1772              return;
1773           }
1774
1775         LOGFN(__FILE__, __LINE__, __FUNCTION__);
1776         e->state[0] = _ecore_x_netwm_state_get(xevent->xclient.data.l[1]);
1777         if (e->state[0] == ECORE_X_WINDOW_STATE_UNKNOWN)
1778           {
1779 //           char *name;
1780              LOGFN(__FILE__, __LINE__, __FUNCTION__);
1781
1782 //           name = XGetAtomName(_ecore_x_disp, xevent->xclient.data.l[1]);
1783 //           if (name) ERR("Unknown state: %s", name);
1784 //           XFree(name);
1785           }
1786         e->state[1] = _ecore_x_netwm_state_get(xevent->xclient.data.l[2]);
1787         if (e->state[1] == ECORE_X_WINDOW_STATE_UNKNOWN)
1788           {
1789 //           char *name;
1790              LOGFN(__FILE__, __LINE__, __FUNCTION__);
1791
1792 //           name = XGetAtomName(_ecore_x_disp, xevent->xclient.data.l[2]);
1793 //           if (name) ERR("Unknown state: %s", name);
1794 //           XFree(name);
1795           }
1796
1797         e->source = xevent->xclient.data.l[3];
1798
1799         ecore_event_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, e, NULL, NULL);
1800      }
1801    else if ((xevent->xclient.message_type == ECORE_X_ATOM_WM_CHANGE_STATE)
1802             && (xevent->xclient.format == 32)
1803             && (xevent->xclient.data.l[0] == IconicState))
1804      {
1805         Ecore_X_Event_Window_State_Request *e;
1806
1807         e = calloc(1, sizeof(Ecore_X_Event_Window_State_Request));
1808         if (!e)
1809           return;
1810
1811         e->win = xevent->xclient.window;
1812         e->action = ECORE_X_WINDOW_STATE_ACTION_ADD;
1813         e->state[0] = ECORE_X_WINDOW_STATE_ICONIFIED;
1814
1815         ecore_event_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, e, NULL, NULL);
1816      }
1817    else if ((xevent->xclient.message_type == ECORE_X_ATOM_NET_WM_DESKTOP)
1818             && (xevent->xclient.format == 32))
1819      {
1820         Ecore_X_Event_Desktop_Change *e;
1821
1822         e = calloc(1, sizeof(Ecore_X_Event_Desktop_Change));
1823         if (!e)
1824           return;
1825
1826         e->win = xevent->xclient.window;
1827         e->desk = xevent->xclient.data.l[0];
1828         e->source = xevent->xclient.data.l[1];
1829
1830         ecore_event_add(ECORE_X_EVENT_DESKTOP_CHANGE, e, NULL, NULL);
1831      }
1832    else if ((xevent->xclient.message_type ==
1833              ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS))
1834      {
1835         Ecore_X_Event_Frame_Extents_Request *e;
1836
1837         e = calloc(1, sizeof(Ecore_X_Event_Frame_Extents_Request));
1838         if (!e)
1839           return;
1840
1841         e->win = xevent->xclient.window;
1842
1843         ecore_event_add(ECORE_X_EVENT_FRAME_EXTENTS_REQUEST, e, NULL, NULL);
1844      }
1845    else if ((xevent->xclient.message_type == ECORE_X_ATOM_WM_PROTOCOLS)
1846             && ((Ecore_X_Atom)xevent->xclient.data.l[0] ==
1847                 ECORE_X_ATOM_NET_WM_PING)
1848             && (xevent->xclient.format == 32))
1849      {
1850         Ecore_X_Event_Ping *e;
1851         Ecore_X_Window root = 0;
1852
1853         e = calloc(1, sizeof(Ecore_X_Event_Ping));
1854         if (!e)
1855           return;
1856
1857         e->win = xevent->xclient.window;
1858         e->time = xevent->xclient.data.l[1];
1859         e->event_win = xevent->xclient.data.l[2];
1860
1861         /* send a reply anyway - we are alive... eventloop at least */
1862         ecore_event_add(ECORE_X_EVENT_PING, e, NULL, NULL);
1863         if (ScreenCount(_ecore_x_disp) > 1)
1864           {
1865              LOGFN(__FILE__, __LINE__, __FUNCTION__);
1866              root = ecore_x_window_root_get(e->win);
1867           }
1868         else
1869           root = DefaultRootWindow(_ecore_x_disp);
1870
1871         if (xevent->xclient.window != root)
1872           {
1873              xevent->xclient.window = root;
1874              XSendEvent(_ecore_x_disp, root, False,
1875                         SubstructureRedirectMask | SubstructureNotifyMask,
1876                         xevent);
1877           }
1878      }
1879    else if ((xevent->xclient.message_type ==
1880              ECORE_X_ATOM_NET_STARTUP_INFO_BEGIN) &&
1881             (xevent->xclient.format == 8))
1882      _ecore_x_netwm_startup_info_begin(xevent->xclient.window,
1883                                        xevent->xclient.data.b);
1884    else if ((xevent->xclient.message_type == ECORE_X_ATOM_NET_STARTUP_INFO) &&
1885             (xevent->xclient.format == 8))
1886      _ecore_x_netwm_startup_info(xevent->xclient.window,
1887                                  xevent->xclient.data.b);
1888    else if ((xevent->xclient.message_type == 27777)
1889             && (xevent->xclient.data.l[0] == 0x7162534)
1890             && (xevent->xclient.format == 32)
1891             && (xevent->xclient.window == _ecore_x_private_win))
1892      {
1893         /* a grab sync marker */
1894         if (xevent->xclient.data.l[1] == 0x10000001)
1895           _ecore_x_window_grab_remove(xevent->xclient.data.l[2]);
1896         else if (xevent->xclient.data.l[1] == 0x10000002)
1897           _ecore_x_key_grab_remove(xevent->xclient.data.l[2]);
1898      }
1899    else
1900      {
1901         Ecore_X_Event_Client_Message *e;
1902         int i;
1903
1904         e = calloc(1, sizeof(Ecore_X_Event_Client_Message));
1905         if (!e)
1906           return;
1907
1908         e->win = xevent->xclient.window;
1909         e->message_type = xevent->xclient.message_type;
1910         e->format = xevent->xclient.format;
1911         for (i = 0; i < 5; i++)
1912           e->data.l[i] = xevent->xclient.data.l[i];
1913
1914         ecore_event_add(ECORE_X_EVENT_CLIENT_MESSAGE, e, NULL, NULL);
1915      }
1916 }
1917
1918 void
1919 _ecore_x_event_handle_mapping_notify(XEvent *xevent)
1920 {
1921    Ecore_X_Event_Mapping_Change *e;
1922
1923    _ecore_x_last_event_mouse_move = 0;
1924    XRefreshKeyboardMapping((XMappingEvent *)xevent);
1925    _ecore_x_modifiers_get();
1926    e = calloc(1, sizeof(Ecore_X_Event_Mapping_Change));
1927    if (!e) return;
1928    switch (xevent->xmapping.request)
1929      {
1930       case MappingModifier:
1931         e->type = ECORE_X_MAPPING_MODIFIER;
1932         break;
1933
1934       case MappingKeyboard:
1935         e->type = ECORE_X_MAPPING_KEYBOARD;
1936         break;
1937
1938       case MappingPointer:
1939       default:
1940         e->type = ECORE_X_MAPPING_MOUSE;
1941         break;
1942      }
1943    e->keycode = xevent->xmapping.first_keycode;
1944    e->num = xevent->xmapping.count;
1945    ecore_event_add(ECORE_X_EVENT_MAPPING_CHANGE, e, NULL, NULL);
1946 }
1947
1948 void
1949 _ecore_x_event_handle_shape_change(XEvent *xevent)
1950 {
1951    XShapeEvent *shape_event;
1952    Ecore_X_Event_Window_Shape *e;
1953
1954    _ecore_x_last_event_mouse_move = 0;
1955    shape_event = (XShapeEvent *)xevent;
1956    e = calloc(1, sizeof(Ecore_X_Event_Window_Shape));
1957    if (!e)
1958      return;
1959
1960    e->win = shape_event->window;
1961    e->time = shape_event->time;
1962    switch (shape_event->kind)
1963      {
1964       case ShapeBounding:
1965         e->type = ECORE_X_SHAPE_BOUNDING;
1966         break;
1967
1968       case ShapeClip:
1969         e->type = ECORE_X_SHAPE_CLIP;
1970         break;
1971
1972       case ShapeInput:
1973         e->type = ECORE_X_SHAPE_INPUT;
1974         break;
1975
1976       default:
1977         break;
1978      }
1979    e->x = shape_event->x;
1980    e->y = shape_event->y;
1981    e->w = shape_event->width;
1982    e->h = shape_event->height;
1983    e->shaped = shape_event->shaped;
1984    ecore_event_add(ECORE_X_EVENT_WINDOW_SHAPE, e, NULL, NULL);
1985 }
1986
1987 void
1988 _ecore_x_event_handle_screensaver_notify(XEvent *xevent)
1989 {
1990 #ifdef ECORE_XSS
1991    XScreenSaverNotifyEvent *screensaver_event;
1992    Ecore_X_Event_Screensaver_Notify *e;
1993
1994    _ecore_x_last_event_mouse_move = 0;
1995    screensaver_event = (XScreenSaverNotifyEvent *)xevent;
1996    e = calloc(1, sizeof(Ecore_X_Event_Screensaver_Notify));
1997    if (!e)
1998      return;
1999
2000    e->win = screensaver_event->window;
2001    if (screensaver_event->state == ScreenSaverOn)
2002      e->on = EINA_TRUE;
2003    else
2004      e->on = EINA_FALSE;
2005
2006    e->time = screensaver_event->time;
2007    ecore_event_add(ECORE_X_EVENT_SCREENSAVER_NOTIFY, e, NULL, NULL);
2008 #else /* ifdef ECORE_XSS */
2009    xevent = NULL;
2010 #endif /* ifdef ECORE_XSS */
2011 }
2012
2013 void
2014 _ecore_x_event_handle_sync_counter(XEvent *xevent)
2015 {
2016    XSyncCounterNotifyEvent *sync_counter_event;
2017    Ecore_X_Event_Sync_Counter *e;
2018
2019    _ecore_x_last_event_mouse_move = 0;
2020    sync_counter_event = (XSyncCounterNotifyEvent *)xevent;
2021    e = calloc(1, sizeof(Ecore_X_Event_Sync_Counter));
2022    if (!e)
2023      return;
2024
2025    e->time = sync_counter_event->time;
2026    ecore_event_add(ECORE_X_EVENT_SYNC_COUNTER, e, NULL, NULL);
2027 }
2028
2029 void
2030 _ecore_x_event_handle_sync_alarm(XEvent *xevent)
2031 {
2032    XSyncAlarmNotifyEvent *sync_alarm_event;
2033    Ecore_X_Event_Sync_Alarm *e;
2034
2035    _ecore_x_last_event_mouse_move = 0;
2036    sync_alarm_event = (XSyncAlarmNotifyEvent *)xevent;
2037
2038    e = calloc(1, sizeof(Ecore_X_Event_Sync_Alarm));
2039    if (!e)
2040      return;
2041
2042    e->time = sync_alarm_event->time;
2043    e->alarm = sync_alarm_event->alarm;
2044    ecore_event_add(ECORE_X_EVENT_SYNC_ALARM, e, NULL, NULL);
2045 }
2046
2047 #ifdef ECORE_XRANDR
2048 void
2049 _ecore_x_event_handle_randr_change(XEvent *xevent)
2050 {
2051    XRRScreenChangeNotifyEvent *randr_event;
2052    Ecore_X_Event_Screen_Change *e;
2053
2054    _ecore_x_last_event_mouse_move = 0;
2055    randr_event = (XRRScreenChangeNotifyEvent *)xevent;
2056    if (!XRRUpdateConfiguration(xevent))
2057      ERR("Can't update RR config!");
2058
2059    e = calloc(1, sizeof(Ecore_X_Event_Screen_Change));
2060    if (!e)
2061      return;
2062
2063    e->win = randr_event->window;
2064    e->root = randr_event->root;
2065    e->size.width = randr_event->width;
2066    e->size.height = randr_event->height;
2067    e->time = randr_event->timestamp;
2068    e->config_time = randr_event->config_timestamp;
2069    e->size.width_mm = randr_event->mwidth;
2070    e->size.height_mm = randr_event->mheight;
2071    e->orientation = randr_event->rotation;
2072    e->subpixel_order = randr_event->subpixel_order;
2073    ecore_event_add(ECORE_X_EVENT_SCREEN_CHANGE, e, NULL, NULL);
2074 }
2075
2076 static void
2077 _ecore_x_event_handle_randr_notify_crtc_change(const XRRNotifyEvent *xevent)
2078 {
2079    const XRRCrtcChangeNotifyEvent *randr_event;
2080    Ecore_X_Event_Randr_Crtc_Change *e;
2081
2082    randr_event = (const XRRCrtcChangeNotifyEvent *)xevent;
2083
2084    e = calloc(1, sizeof(Ecore_X_Event_Randr_Crtc_Change));
2085    if (!e)
2086      return;
2087
2088    e->win = randr_event->window;
2089    e->crtc = randr_event->crtc;
2090    e->mode = randr_event->mode;
2091    e->orientation = randr_event->rotation;
2092    e->geo.x = randr_event->x;
2093    e->geo.y = randr_event->y;
2094    e->geo.w = randr_event->width;
2095    e->geo.h = randr_event->height;
2096    ecore_event_add(ECORE_X_EVENT_RANDR_CRTC_CHANGE, e, NULL, NULL);
2097 }
2098
2099 static void
2100 _ecore_x_event_handle_randr_notify_output_change(const XRRNotifyEvent *xevent)
2101 {
2102    const XRROutputChangeNotifyEvent *randr_event;
2103    Ecore_X_Event_Randr_Output_Change *e;
2104
2105    randr_event = (const XRROutputChangeNotifyEvent *)xevent;
2106
2107    e = calloc(1, sizeof(Ecore_X_Event_Randr_Output_Change));
2108    if (!e)
2109      return;
2110
2111    e->win = randr_event->window;
2112    e->output = randr_event->output;
2113    e->crtc = randr_event->crtc;
2114    e->mode = randr_event->mode;
2115    e->orientation = randr_event->rotation;
2116    e->connection = randr_event->connection;
2117    e->subpixel_order = randr_event->subpixel_order;
2118    ecore_event_add(ECORE_X_EVENT_RANDR_OUTPUT_CHANGE, e, NULL, NULL);
2119 }
2120
2121 static void
2122 _ecore_x_event_handle_randr_notify_output_property(const XRRNotifyEvent *xevent)
2123 {
2124    const XRROutputPropertyNotifyEvent *randr_event;
2125    Ecore_X_Event_Randr_Output_Property_Notify *e;
2126
2127    randr_event = (const XRROutputPropertyNotifyEvent *)xevent;
2128
2129    e = calloc(1, sizeof(Ecore_X_Event_Randr_Output_Property_Notify));
2130    if (!e)
2131      return;
2132
2133    e->win = randr_event->window;
2134    e->output = randr_event->output;
2135    e->property = randr_event->property;
2136    e->time = randr_event->timestamp;
2137    if (randr_event->state == PropertyNewValue)
2138      e->state = ECORE_X_RANDR_PROPERTY_CHANGE_ADD;
2139    else
2140      e->state = ECORE_X_RANDR_PROPERTY_CHANGE_DEL;
2141    ecore_event_add(ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY, e, NULL, NULL);
2142 }
2143
2144 void
2145 _ecore_x_event_handle_randr_notify(XEvent *xevent)
2146 {
2147    const XRRNotifyEvent *randr_event;
2148
2149    _ecore_x_last_event_mouse_move = 0;
2150    randr_event = (const XRRNotifyEvent *)xevent;
2151    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2152    switch (randr_event->subtype)
2153      {
2154       case RRNotify_CrtcChange:
2155         _ecore_x_event_handle_randr_notify_crtc_change(randr_event);
2156         break;
2157
2158       case RRNotify_OutputChange:
2159         _ecore_x_event_handle_randr_notify_output_change(randr_event);
2160         break;
2161
2162       case RRNotify_OutputProperty:
2163         _ecore_x_event_handle_randr_notify_output_property(randr_event);
2164         break;
2165
2166       default:
2167         ERR("Unknown XRandR RRNotify subtype: %d.",
2168             randr_event->subtype);
2169         break;
2170      }
2171 }
2172
2173 #endif /* ifdef ECORE_XRANDR */
2174
2175 #ifdef ECORE_XFIXES
2176 void
2177 _ecore_x_event_handle_fixes_selection_notify(XEvent *event)
2178 {
2179    XFixesSelectionNotifyEvent *notify_event =
2180      (XFixesSelectionNotifyEvent *)event;
2181    Ecore_X_Event_Fixes_Selection_Notify *e;
2182    Ecore_X_Atom sel;
2183
2184    _ecore_x_last_event_mouse_move = 0;
2185    /* Nothing here yet */
2186
2187    e = calloc(1, sizeof(*e));
2188    if (!e)
2189      return;
2190
2191    e->win = notify_event->window;
2192    e->owner = notify_event->owner;
2193    e->time = notify_event->timestamp;
2194    e->selection_time = notify_event->selection_timestamp;
2195    e->atom = sel = notify_event->selection;
2196    if (sel == ECORE_X_ATOM_SELECTION_PRIMARY)
2197      e->selection = ECORE_X_SELECTION_PRIMARY;
2198    else if (sel == ECORE_X_ATOM_SELECTION_SECONDARY)
2199      e->selection = ECORE_X_SELECTION_SECONDARY;
2200    else if (sel == ECORE_X_ATOM_SELECTION_CLIPBOARD)
2201      e->selection = ECORE_X_SELECTION_CLIPBOARD;
2202    else
2203      e->selection = ECORE_X_SELECTION_OTHER;
2204    e->reason = notify_event->subtype;
2205
2206    ecore_event_add(ECORE_X_EVENT_FIXES_SELECTION_NOTIFY, e, NULL, NULL);
2207 }
2208
2209 #endif /* ifdef ECORE_XFIXES */
2210
2211 #ifdef ECORE_XDAMAGE
2212 void
2213 _ecore_x_event_handle_damage_notify(XEvent *event)
2214 {
2215    XDamageNotifyEvent *damage_event;
2216    Ecore_X_Event_Damage *e;
2217
2218    _ecore_x_last_event_mouse_move = 0;
2219    damage_event = (XDamageNotifyEvent *)event;
2220
2221    e = calloc(1, sizeof(Ecore_X_Event_Damage));
2222    if (!e)
2223      return;
2224
2225    e->level = damage_event->level;
2226    e->drawable = damage_event->drawable;
2227    e->damage = damage_event->damage;
2228    e->more = damage_event->more;
2229    e->time = damage_event->timestamp;
2230    e->area.x = damage_event->area.x;
2231    e->area.y = damage_event->area.y;
2232    e->area.width = damage_event->area.width;
2233    e->area.height = damage_event->area.height;
2234    e->geometry.x = damage_event->geometry.x;
2235    e->geometry.y = damage_event->geometry.y;
2236    e->geometry.width = damage_event->geometry.width;
2237    e->geometry.height = damage_event->geometry.height;
2238
2239    ecore_event_add(ECORE_X_EVENT_DAMAGE_NOTIFY, e, NULL, NULL);
2240 }
2241
2242 #endif /* ifdef ECORE_XDAMAGE */
2243
2244 static void
2245 _ecore_x_event_free_generic_event(void *data,
2246                                   void *ev)
2247 {
2248 #ifdef ECORE_XI2
2249    Ecore_X_Event_Generic *e = (Ecore_X_Event_Generic *)ev;
2250
2251    if (data)
2252      {
2253         if (e->data)
2254           XFreeEventData(_ecore_x_disp, (XGenericEventCookie *)data);
2255         free(data);
2256      }
2257    free(e);
2258 #else
2259    return;
2260    data = NULL; ev = NULL;
2261 #endif /* ifdef ECORE_XI2 */
2262 }
2263
2264 void
2265 _ecore_x_event_handle_generic_event(XEvent *event)
2266 {
2267 #ifdef ECORE_XI2
2268    XGenericEvent *generic_event;
2269    Ecore_X_Event_Generic *e;
2270    XGenericEventCookie *data;
2271
2272    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2273    generic_event = (XGenericEvent *)event;
2274
2275    e = calloc(1, sizeof(Ecore_X_Event_Generic));
2276    if (!e)
2277      return;
2278
2279    if (XGetEventData(_ecore_x_disp, &(event->xcookie)))
2280      {
2281         e->cookie = event->xcookie.cookie;
2282         e->data = event->xcookie.data;
2283      }
2284    else
2285      {
2286         e->cookie = 0;
2287         e->data = NULL;
2288      }
2289
2290    e->extension = generic_event->extension;
2291    e->evtype = generic_event->evtype;
2292
2293    if (e->extension == _ecore_x_xi2_opcode)
2294      _ecore_x_input_handler(event);
2295
2296    data = malloc(sizeof(XGenericEventCookie));
2297    if (data) memcpy(data, &(event->xcookie), sizeof(XGenericEventCookie));
2298    ecore_event_add(ECORE_X_EVENT_GENERIC,
2299                    e,
2300                    _ecore_x_event_free_generic_event,
2301                    data);
2302 #else
2303    return;
2304    event = NULL;
2305 #endif /* ifdef ECORE_XI2 */
2306 }
2307
2308 #ifdef ECORE_XGESTURE
2309 void
2310 _ecore_x_event_handle_gesture_notify_flick(XEvent *xevent)
2311 {
2312    XGestureNotifyFlickEvent *xfe;
2313    Ecore_X_Event_Gesture_Notify_Flick *e;
2314
2315    _ecore_x_last_event_mouse_move = 0;
2316    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2317
2318    xfe = (XGestureNotifyFlickEvent *)xevent;
2319    e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_Flick));
2320    if (!e)
2321      return;
2322
2323    e->win = xfe->window;
2324    e->time = xfe->time;
2325    e->subtype = xfe->kind;
2326    e->num_fingers = xfe->num_finger;
2327    e->distance = xfe->distance;
2328    e->duration = xfe->duration;
2329    e->direction = xfe->direction;
2330    e->angle = XFixedToDouble(xfe->angle);
2331
2332    ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_FLICK, e, NULL, NULL);
2333 }
2334
2335 void
2336 _ecore_x_event_handle_gesture_notify_pan(XEvent *xevent)
2337 {
2338    XGestureNotifyPanEvent *xpe;
2339    Ecore_X_Event_Gesture_Notify_Pan *e;
2340
2341    _ecore_x_last_event_mouse_move = 0;
2342    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2343
2344    xpe = (XGestureNotifyPanEvent *)xevent;
2345    e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_Pan));
2346    if (!e)
2347      return;
2348
2349    e->win = xpe->window;
2350    e->time = xpe->time;
2351    e->subtype = xpe->kind;
2352    e->num_fingers = xpe->num_finger;
2353    e->dx = xpe->dx;
2354    e->dy = xpe->dy;
2355    e->distance = xpe->distance;
2356    e->duration = xpe->duration;
2357    e->direction = xpe->direction;
2358
2359    ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_PAN, e, NULL, NULL);
2360 }
2361
2362 void
2363 _ecore_x_event_handle_gesture_notify_pinchrotation(XEvent *xevent)
2364 {
2365    XGestureNotifyPinchRotationEvent *xpre;
2366    Ecore_X_Event_Gesture_Notify_PinchRotation *e;
2367
2368    _ecore_x_last_event_mouse_move = 0;
2369    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2370
2371    xpre = (XGestureNotifyPinchRotationEvent *)xevent;
2372    e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_PinchRotation));
2373    if (!e)
2374      return;
2375
2376    e->win = xpre->window;
2377    e->time = xpre->time;
2378    e->subtype = xpre->kind;
2379    e->num_fingers = xpre->num_finger;
2380    e->distance = xpre->distance;
2381    e->cx = xpre->cx;
2382    e->cy = xpre->cy;
2383    e->zoom = XFixedToDouble(xpre->zoom);
2384    e->angle = XFixedToDouble(xpre->angle);
2385
2386    ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_PINCHROTATION, e, NULL, NULL);
2387 }
2388
2389 void
2390 _ecore_x_event_handle_gesture_notify_tap(XEvent *xevent)
2391 {
2392    XGestureNotifyTapEvent *xte;
2393    Ecore_X_Event_Gesture_Notify_Tap *e;
2394
2395    _ecore_x_last_event_mouse_move = 0;
2396    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2397
2398    xte = (XGestureNotifyTapEvent *)xevent;
2399    e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_Tap));
2400    if (!e)
2401      return;
2402
2403    e->win = xte->window;
2404    e->time = xte->time;
2405    e->subtype = xte->kind;
2406    e->num_fingers = xte->num_finger;
2407    e->cx = xte->cx;
2408    e->cy = xte->cy;
2409    e->tap_repeat = xte->tap_repeat;
2410    e->interval = xte->interval;
2411
2412    ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_TAP, e, NULL, NULL);
2413 }
2414
2415 void
2416 _ecore_x_event_handle_gesture_notify_tapnhold(XEvent *xevent)
2417 {
2418    XGestureNotifyTapNHoldEvent *xthe;
2419    Ecore_X_Event_Gesture_Notify_TapNHold *e;
2420
2421    _ecore_x_last_event_mouse_move = 0;
2422    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2423
2424    xthe = (XGestureNotifyTapNHoldEvent *)xevent;
2425    e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_TapNHold));
2426    if (!e)
2427      return;
2428
2429    e->win = xthe->window;
2430    e->time = xthe->time;
2431    e->subtype = xthe->kind;
2432    e->num_fingers = xthe->num_finger;
2433    e->cx = xthe->cx;
2434    e->cy = xthe->cy;
2435    e->interval = xthe->interval;
2436    e->hold_time = xthe->holdtime;
2437
2438    ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_TAPNHOLD, e, NULL, NULL);
2439 }
2440
2441 void
2442 _ecore_x_event_handle_gesture_notify_hold(XEvent *xevent)
2443 {
2444    XGestureNotifyHoldEvent *xhe;
2445    Ecore_X_Event_Gesture_Notify_Hold *e;
2446
2447    _ecore_x_last_event_mouse_move = 0;
2448    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2449
2450    xhe = (XGestureNotifyHoldEvent *)xevent;
2451    e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_Hold));
2452    if (!e)
2453      return;
2454
2455    e->win = xhe->window;
2456    e->time = xhe->time;
2457    e->subtype = xhe->kind;
2458    e->num_fingers = xhe->num_finger;
2459    e->cx = xhe->cx;
2460    e->cy = xhe->cy;
2461    e->hold_time = xhe->holdtime;
2462
2463    ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_HOLD, e, NULL, NULL);
2464 }
2465
2466 void
2467 _ecore_x_event_handle_gesture_notify_group(XEvent *xevent)
2468 {
2469    XGestureNotifyGroupEvent *xge;
2470    Ecore_X_Event_Gesture_Notify_Group *e;
2471
2472    _ecore_x_last_event_mouse_move = 0;
2473    LOGFN(__FILE__, __LINE__, __FUNCTION__);
2474
2475    xge = (XGestureNotifyGroupEvent *)xevent;
2476    e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_Group));
2477    if (!e)
2478      return;
2479
2480    e->win = xge->window;
2481    e->time = xge->time;
2482    e->subtype = xge->kind;
2483    e->num_groups = xge->num_group;
2484    e->group_id = xge->groupid;
2485
2486    ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_GROUP, e, NULL, NULL);
2487 }
2488
2489 #endif /* ifdef ECORE_XGESTURE */
2490