svn update: 48958 (latest:48959)
[framework/uifw/ecore.git] / src / lib / ecore_x / xcb / ecore_xcb_events.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif
8
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12
13 #include <Ecore.h>
14 #include <Ecore_Input.h>
15
16 #include "ecore_xcb_private.h"
17 #include "Ecore_X_Atoms.h"
18
19
20 /** OpenBSD does not define CODESET
21  * FIXME ??
22  */
23
24 #ifndef CODESET
25 #define CODESET "INVALID"
26 #endif
27
28 #if 0
29 static void _ecore_x_event_free_window_prop_name_class_change(void *data, void *ev);
30 static void _ecore_x_event_free_window_prop_title_change(void *data, void *ev);
31 static void _ecore_x_event_free_window_prop_visible_title_change(void *data, void *ev);
32 static void _ecore_x_event_free_window_prop_icon_name_change(void *data, void *ev);
33 static void _ecore_x_event_free_window_prop_visible_icon_name_change(void *data, void *ev);
34 static void _ecore_x_event_free_window_prop_client_machine_change(void *data, void *ev);
35 #endif
36
37 static Ecore_X_Window _ecore_xcb_mouse_down_last_window = 0;
38 static Ecore_X_Window _ecore_xcb_mouse_down_last_last_window = 0;
39 static Ecore_X_Window _ecore_xcb_mouse_down_last_event_window = 0;
40 static Ecore_X_Window _ecore_xcb_mouse_down_last_last_event_window = 0;
41 static Ecore_X_Time   _ecore_xcb_mouse_down_last_time = 0;
42 static Ecore_X_Time   _ecore_xcb_mouse_down_last_last_time = 0;
43 static int            _ecore_xcb_mouse_up_count = 0;
44 static int            _ecore_xcb_mouse_down_did_triple = 0;
45 static int            _ecore_xcb_last_event_mouse_move = 0;
46 static Ecore_Event   *_ecore_xcb_last_event_mouse_move_event = NULL;
47
48 static void
49 _ecore_x_event_free_mouse_move(void *data __UNUSED__, void *ev)
50 {
51    Ecore_Event_Mouse_Move *e;
52
53    e = ev;
54    if (_ecore_xcb_last_event_mouse_move)
55      {
56         _ecore_xcb_last_event_mouse_move_event = NULL;
57         _ecore_xcb_last_event_mouse_move = 0;
58      }
59    free(e);
60 }
61
62
63 /* FIXME: roundtrip */
64 EAPI void
65 ecore_x_event_mask_set(Ecore_X_Window     window,
66                        Ecore_X_Event_Mask mask)
67 {
68    xcb_get_window_attributes_cookie_t cookie;
69    xcb_get_window_attributes_reply_t *reply;
70    uint32_t                           value_list;
71
72    if (!window)
73       window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
74
75    cookie = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window);
76    reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL);
77    if (!reply) return;
78
79    value_list = mask | reply->your_event_mask;
80    xcb_change_window_attributes(_ecore_xcb_conn, window, XCB_CW_EVENT_MASK, &value_list);
81    free(reply);
82 }
83
84 /* FIXME: roundtrip */
85 EAPI void
86 ecore_x_event_mask_unset(Ecore_X_Window     window,
87                          Ecore_X_Event_Mask mask)
88 {
89    xcb_get_window_attributes_cookie_t cookie;
90    xcb_get_window_attributes_reply_t *reply;
91    uint32_t value_list;
92
93    if (!window)
94       window = ((xcb_screen_t *)_ecore_xcb_screen)->root;
95
96    cookie = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window);
97    reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL);
98    if (!reply) return;
99
100    value_list = reply->your_event_mask & ~mask;
101    xcb_change_window_attributes(_ecore_xcb_conn, window, XCB_CW_EVENT_MASK, &value_list);
102    free(reply);
103 }
104
105 #if 0
106 static void
107 _ecore_x_event_free_window_prop_name_class_change(void *data, void *ev)
108 {
109    Ecore_X_Event_Window_Prop_Name_Class_Change *e;
110
111    e = ev;
112    if (e->name) free(e->name);
113    if (e->clas) free(e->clas);
114    free(e);
115 }
116
117 static void
118 _ecore_x_event_free_window_prop_title_change(void *data, void *ev)
119 {
120    Ecore_X_Event_Window_Prop_Title_Change *e;
121
122    e = ev;
123    if (e->title) free(e->title);
124    free(e);
125 }
126
127 static void
128 _ecore_x_event_free_window_prop_visible_title_change(void *data, void *ev)
129 {
130    Ecore_X_Event_Window_Prop_Visible_Title_Change *e;
131
132    e = ev;
133    if (e->title) free(e->title);
134    free(e);
135 }
136
137 static void
138 _ecore_x_event_free_window_prop_icon_name_change(void *data, void *ev)
139 {
140    Ecore_X_Event_Window_Prop_Icon_Name_Change *e;
141
142    e = ev;
143    if (e->name) free(e->name);
144    free(e);
145 }
146
147 static void
148 _ecore_x_event_free_window_prop_visible_icon_name_change(void *data, void *ev)
149 {
150    Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change *e;
151
152    e = ev;
153    if (e->name) free(e->name);
154    free(e);
155 }
156
157 static void
158 _ecore_x_event_free_window_prop_client_machine_change(void *data, void *ev)
159 {
160    Ecore_X_Event_Window_Prop_Client_Machine_Change *e;
161
162    e = ev;
163    if (e->name) free(e->name);
164    free(e);
165 }
166 #endif
167
168 static void
169 _ecore_x_event_free_xdnd_enter(void *data __UNUSED__, void *ev)
170 {
171    Ecore_X_Event_Xdnd_Enter *e;
172    int                       i;
173
174    e = ev;
175    for (i = 0; i < e->num_types; i++)
176      free(e->types[i]);
177    free(e->types);
178    free(e);
179 }
180
181 static void
182 _ecore_x_event_free_selection_notify(void *data __UNUSED__, void *ev)
183 {
184    Ecore_X_Event_Selection_Notify *e;
185    Ecore_X_Selection_Data         *sel;
186
187    e = ev;
188    sel = e->data;
189    if (sel->free)
190      sel->free(sel);
191    free(e->target);
192    free(e);
193 }
194
195 static unsigned int
196 _ecore_x_event_modifiers(unsigned int state)
197 {
198    unsigned int modifiers = 0;
199
200    if (state & ECORE_X_MODIFIER_SHIFT) modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
201    if (state & ECORE_X_MODIFIER_CTRL) modifiers |= ECORE_EVENT_MODIFIER_CTRL;
202    if (state & ECORE_X_MODIFIER_ALT) modifiers |= ECORE_EVENT_MODIFIER_ALT;
203    if (state & ECORE_X_MODIFIER_WIN) modifiers |= ECORE_EVENT_MODIFIER_WIN;
204    if (state & ECORE_X_LOCK_SCROLL) modifiers |= ECORE_EVENT_LOCK_SCROLL;
205    if (state & ECORE_X_LOCK_NUM) modifiers |= ECORE_EVENT_LOCK_NUM;
206    if (state & ECORE_X_LOCK_CAPS) modifiers |= ECORE_EVENT_LOCK_CAPS;
207
208    return modifiers;
209 }
210
211 static void
212 _ecore_mouse_move(unsigned int timestamp, unsigned int xmodifiers,
213                   int x, int y,
214                   int x_root, int y_root,
215                   unsigned int event_window,
216                   unsigned int window,
217                   unsigned int root_win,
218                   int same_screen)
219 {
220    Ecore_Event_Mouse_Move *e;
221    Ecore_Event            *event;
222
223    e = malloc(sizeof(Ecore_Event_Mouse_Move));
224    if (!e) return ;
225
226    e->window = window;
227    e->root_window = root_win;
228    e->timestamp = timestamp;
229    e->same_screen = same_screen;
230    e->event_window = event_window;
231
232    e->modifiers = _ecore_x_event_modifiers(xmodifiers);
233    e->x = x;
234    e->y = y;
235    e->root.x = x_root;
236    e->root.y = y_root;
237
238    event = ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, _ecore_x_event_free_mouse_move, NULL);
239
240    _ecore_xcb_event_last_time = timestamp;
241    _ecore_xcb_event_last_window = window;
242    _ecore_xcb_event_last_root_x = x_root;
243    _ecore_xcb_event_last_root_y = y_root;
244
245    _ecore_xcb_last_event_mouse_move_event = event;
246 }
247
248 static void
249 _ecore_key_press(int                  event,
250                  xcb_generic_event_t *ev)
251 {
252   /*
253    Ecore_Event_Key *e;
254    const char *compose = NULL;
255    char *tmp = NULL;
256    char *keyname;
257    char *key;
258    char keyname_buffer[256];
259    char compose_buffer[256];
260    KeySym sym;
261    XComposeStatus status;
262    int val;
263
264    _ecore_xcb_last_event_mouse_move = 0;
265    keyname = XKeysymToString(XKeycodeToKeysym(xevent->display,
266                                               xevent->keycode, 0));
267    if (!keyname)
268      {
269         snprintf(keyname_buffer, sizeof(keyname_buffer), "Keycode-%i", xevent->keycode);
270         keyname = keyname_buffer;
271         if (!keyname) return ;
272      }
273
274    sym = 0;
275    key = NULL;
276    compose = NULL;
277    if (_ecore_x_ic)
278      {
279         Status mbstatus;
280 #ifdef X_HAVE_UTF8_STRING
281         val = Xutf8LookupString(_ecore_x_ic, (XKeyEvent *)xevent, compose_buffer, sizeof(compose_buffer) - 1, &sym, &mbstatus);
282 #else
283         val = XmbLookupString(_ecore_x_ic, (XKeyEvent *)xevent, compose_buffer, sizeof(compose_buffer) - 1, &sym, &mbstatus);
284 #endif
285         if (mbstatus == XBufferOverflow)
286           {
287              tmp = malloc(sizeof (char) * (val + 1));
288              if (!tmp) return ;
289
290              compose = tmp;
291
292 #ifdef X_HAVE_UTF8_STRING
293              val = Xutf8LookupString(_ecore_x_ic, (XKeyEvent *)xevent, tmp, val, &sym, &mbstatus);
294 #else
295              val = XmbLookupString(_ecore_x_ic, (XKeyEvent *)xevent, tmp, val, &sym, &mbstatus);
296 #endif
297              if (val > 0)
298                {
299                   tmp[val] = 0;
300
301 #ifndef X_HAVE_UTF8_STRING
302                   compose = eina_str_convert(nl_langinfo(CODESET), "UTF-8", tmp);
303                   free(tmp);
304                   tmp = compose;
305 #endif
306                }
307              else compose = NULL;
308           }
309         else
310           if (val > 0)
311             {
312                compose_buffer[val] = 0;
313 #ifdef X_HAVE_UTF8_STRING
314                compose = compose_buffer;
315 #else
316                compose = eina_str_convert(nl_langinfo(CODESET), "UTF-8", compose_buffer);
317                tmp = compose;
318 #endif
319             }
320      }
321    else
322      {
323         val = XLookupString(xevent, compose_buffer, sizeof(compose_buffer), &sym, &status);
324         if (val > 0)
325           {
326              compose_buffer[val] = 0;
327              compose = eina_str_convert(nl_langinfo(CODESET), "UTF-8", compose_buffer);
328              tmp = compose;
329           }
330      }
331
332    key = XKeysymToString(sym);
333    if (!key) key = keyname;
334    if (!key) goto on_error;
335
336    e = malloc(sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) + (compose ? strlen(compose) : 0) + 3);
337    if (!e) goto on_error;
338
339    e->keyname = (char*) (e + 1);
340    e->key = e->keyname + strlen(keyname) + 1;
341    e->compose = (compose) ? e->key + strlen(key) + 1 : NULL;
342    e->string = e->compose;
343
344    strcpy((char *) e->keyname, keyname);
345    strcpy((char *) e->key, key);
346    if (compose) strcpy((char *) e->compose, compose);
347
348    e->modifiers = _ecore_x_event_modifiers(xevent->state);
349
350    e->timestamp = xevent->time;
351    e->window = xevent->subwindow ? xevent->subwindow : xevent->window;
352    e->event_window = xevent->window;
353    e->same_screen = xevent->same_screen;
354    e->root_window = xevent->root;
355
356    ecore_event_add(event, e, NULL, NULL);
357
358    _ecore_xcb_event_last_time = e->timestamp;
359
360  on_error:
361    if (tmp) free(tmp);
362   */
363 }
364
365 static Ecore_Event_Mouse_Button*
366 _ecore_mouse_button(int event,
367                     unsigned int timestamp, unsigned int xmodifiers,
368                     unsigned int buttons,
369                     int x, int y,
370                     int x_root, int y_root,
371                     unsigned int event_window,
372                     unsigned int window,
373                     unsigned int root_win,
374                     int same_screen)
375 {
376    Ecore_Event_Mouse_Button *e;
377
378    e = malloc(sizeof(Ecore_Event_Mouse_Button));
379    if (!e) return NULL;
380
381    e->window = window;
382    e->root_window = root_win;
383    e->timestamp = timestamp;
384    e->same_screen = same_screen;
385    e->event_window = event_window;
386
387    e->buttons = buttons;
388    e->modifiers = _ecore_x_event_modifiers(xmodifiers);
389    e->double_click = 0;
390    e->triple_click = 0;
391    e->x = x;
392    e->y = y;
393    e->root.x = x_root;
394    e->root.y = y_root;
395
396    if (event_window == window)
397      {
398         if (((int)(timestamp - _ecore_xcb_mouse_down_last_time) <=
399              (int)(1000 * _ecore_xcb_double_click_time)) &&
400             (window == _ecore_xcb_mouse_down_last_window) &&
401             (event_window == _ecore_xcb_mouse_down_last_event_window)
402             )
403           e->double_click = 1;
404         if (((int)(timestamp - _ecore_xcb_mouse_down_last_last_time) <=
405              (int)(2 * 1000 * _ecore_xcb_double_click_time)) &&
406             (window == _ecore_xcb_mouse_down_last_window) &&
407             (window == _ecore_xcb_mouse_down_last_last_window) &&
408             (event_window == _ecore_xcb_mouse_down_last_event_window) &&
409             (event_window == _ecore_xcb_mouse_down_last_last_event_window)
410             )
411           {
412              e->triple_click = 1;
413              _ecore_xcb_mouse_down_did_triple = 1;
414           }
415         else
416           _ecore_xcb_mouse_down_did_triple = 0;
417      }
418
419    if (event == ECORE_EVENT_MOUSE_BUTTON_DOWN
420        && !e->double_click
421        && !e->triple_click)
422      _ecore_xcb_mouse_up_count = 0;
423
424    _ecore_xcb_event_last_time = e->timestamp;
425    _ecore_xcb_event_last_window = e->window;
426    _ecore_xcb_event_last_root_x = x_root;
427    _ecore_xcb_event_last_root_y = y_root;
428
429    ecore_event_add(event, e, NULL, NULL);
430
431    return e;
432 }
433
434 void
435 _ecore_x_event_handle_any_event(xcb_generic_event_t *event)
436 {
437    xcb_generic_event_t* ev = malloc(sizeof(xcb_generic_event_t));
438    memcpy(ev, event, sizeof(xcb_generic_event_t));
439
440    ecore_event_add(ECORE_X_EVENT_ANY, ev, NULL, NULL);
441 }
442
443 /* FIXME: handle this event */
444 void
445 _ecore_x_event_handle_key_press(xcb_generic_event_t *event)
446 {
447    _ecore_key_press(ECORE_EVENT_KEY_DOWN, event);
448
449    free(event);
450 }
451
452 /* FIXME: handle this event */
453 void
454 _ecore_x_event_handle_key_release(xcb_generic_event_t *event)
455 {
456    _ecore_key_press(ECORE_EVENT_KEY_DOWN, event);
457
458    free(event);
459 }
460
461 void
462 _ecore_x_event_handle_button_press(xcb_generic_event_t *event)
463 {
464    xcb_button_press_event_t *ev;
465    int                       i;
466
467    ev = (xcb_button_press_event_t *)event;
468    if ((ev->detail > 3) && (ev->detail < 8))
469      {
470         Ecore_Event_Mouse_Wheel *e;
471
472         e = malloc(sizeof(Ecore_Event_Mouse_Wheel));
473         if (!e) return;
474
475         e->timestamp = ev->time;
476         e->modifiers = _ecore_x_event_modifiers(ev->state);
477         switch (ev->detail)
478           {
479            case 4: e->direction = 0; e->z = -1; break;
480            case 5: e->direction = 0; e->z = 1; break;
481            case 6: e->direction = 1; e->z = -1; break;
482            case 7: e->direction = 1; e->z = 1; break;
483            default: e->direction = 0; e->z = 0; break;
484           }
485
486         e->x = ev->event_x;
487         e->y = ev->event_y;
488         e->root.x = ev->root_x;
489         e->root.y = ev->root_y;
490
491         if (ev->child)
492           e->window = ev->child;
493         else
494           e->window = ev->event;
495
496         e->event_window = ev->event;
497         e->same_screen = ev->same_screen;
498         e->root_window = ev->root;
499         _ecore_xcb_event_last_time = e->timestamp;
500         _ecore_xcb_event_last_window = e->window;
501         _ecore_xcb_event_last_root_x = e->root.x;
502         _ecore_xcb_event_last_root_y = e->root.y;
503         ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, e, NULL, NULL);
504         for (i = 0; i < _ecore_window_grabs_num; i++)
505           {
506              if ((_ecore_window_grabs[i] == ev->event) ||
507                  (_ecore_window_grabs[i] == ev->child))
508                {
509                   int replay = 0;
510
511                   if (_ecore_window_grab_replay_func)
512                     replay = _ecore_window_grab_replay_func(_ecore_window_grab_replay_data,
513                                                             ECORE_EVENT_MOUSE_WHEEL,
514                                                             e);
515                   /* FIXME: xcb_key_press_event_t does not save the */
516                   /* connection. So I use the current one */
517                   if (replay)
518                     xcb_allow_events(_ecore_xcb_conn,
519                                      XCB_ALLOW_REPLAY_POINTER,
520                                      ev->time);
521                   else
522                     xcb_allow_events(_ecore_xcb_conn,
523                                      XCB_ALLOW_ASYNC_POINTER,
524                                      ev->time);
525                   break;
526                }
527           }
528      }
529    else
530      {
531         {
532            _ecore_mouse_move(ev->time, ev->state,
533                              ev->event_x, ev->event_y,
534                              ev->root_x, ev->root_y,
535                              ev->event,
536                              (ev->child ? ev->child : ev->event),
537                              ev->root,
538                              ev->same_screen);
539         }
540         {
541            Ecore_Event_Mouse_Button *e;
542            Ecore_X_Window            event_window;
543            Ecore_X_Window            child_window;
544
545            if (_ecore_xcb_mouse_down_did_triple)
546              {
547                 _ecore_xcb_mouse_down_last_window = 0;
548                 _ecore_xcb_mouse_down_last_last_window = 0;
549                 _ecore_xcb_mouse_down_last_event_window = 0;
550                 _ecore_xcb_mouse_down_last_last_event_window = 0;
551                 _ecore_xcb_mouse_down_last_time = 0;
552                 _ecore_xcb_mouse_down_last_last_time = 0;
553              }
554            event_window = ev->child;
555            child_window = ev->child ? ev->child : ev->event;
556
557            e = _ecore_mouse_button(ECORE_EVENT_MOUSE_BUTTON_DOWN,
558                                    ev->time, ev->state,
559                                    ev->detail,
560                                    ev->event_x, ev->event_y,
561                                    ev->root_x, ev->root_y,
562                                    event_window, child_window,
563                                    ev->root, ev->same_screen);
564
565            if (!e) return;
566            for (i = 0; i < _ecore_window_grabs_num; i++)
567              {
568                 if ((_ecore_window_grabs[i] == ev->event) ||
569                     (_ecore_window_grabs[i] == ev->child))
570                   {
571                      int replay = 0;
572
573                      if (_ecore_window_grab_replay_func)
574                        replay = _ecore_window_grab_replay_func(_ecore_window_grab_replay_data,
575                                                                ECORE_EVENT_MOUSE_BUTTON_DOWN,
576                                                                e);
577                      /* FIXME: xcb_key_press_event_t does not save the */
578                      /* connection. So I use the current one */
579                      if (replay)
580                        xcb_allow_events(_ecore_xcb_conn,
581                                         XCB_ALLOW_REPLAY_POINTER,
582                                         ev->time);
583                      else
584                        xcb_allow_events(_ecore_xcb_conn,
585                                         XCB_ALLOW_ASYNC_POINTER,
586                                         ev->time);
587                      break;
588                   }
589              }
590            if (child_window == event_window)
591              {
592                 if (!_ecore_xcb_mouse_down_did_triple)
593                   {
594                      _ecore_xcb_mouse_down_last_last_window = _ecore_xcb_mouse_down_last_window;
595                      if (ev->child)
596                        _ecore_xcb_mouse_down_last_window = ev->child;
597                      else
598                        _ecore_xcb_mouse_down_last_window = ev->event;
599                      _ecore_xcb_mouse_down_last_last_event_window = _ecore_xcb_mouse_down_last_event_window;
600                      _ecore_xcb_mouse_down_last_event_window = ev->event;
601                      _ecore_xcb_mouse_down_last_last_time = _ecore_xcb_mouse_down_last_time;
602                      _ecore_xcb_mouse_down_last_time = ev->time;
603                   }
604              }
605         }
606      }
607
608    free(event);
609 }
610
611 void
612 _ecore_x_event_handle_button_release(xcb_generic_event_t *event)
613 {
614    xcb_button_release_event_t *ev;
615
616    ev = (xcb_button_release_event_t *)event;
617    _ecore_xcb_last_event_mouse_move = 0;
618    /* filter out wheel buttons */
619    if ((ev->detail <= 3) || (ev->detail > 7))
620      {
621         _ecore_mouse_move(ev->time, ev->state,
622                           ev->event_x, ev->event_y,
623                           ev->root_x, ev->root_y,
624                           ev->event,
625                           (ev->child ? ev->child : ev->event),
626                           ev->root,
627                           ev->same_screen);
628
629         _ecore_mouse_button(ECORE_EVENT_MOUSE_BUTTON_UP,
630                             ev->time, ev->state,
631                             ev->detail,
632                             ev->event_x, ev->event_y,
633                             ev->root_x, ev->root_y,
634                             ev->event,
635                             (ev->child ? ev->child : ev->event),
636                             ev->root,
637                             ev->same_screen);
638      }
639
640    free(event);
641 }
642
643 void
644 _ecore_x_event_handle_motion_notify(xcb_generic_event_t *event)
645 {
646    xcb_motion_notify_event_t *ev;
647
648    ev = (xcb_motion_notify_event_t *)event;
649    if (_ecore_xcb_last_event_mouse_move)
650      {
651         ecore_event_del(_ecore_xcb_last_event_mouse_move_event);
652         _ecore_xcb_last_event_mouse_move = 0;
653         _ecore_xcb_last_event_mouse_move_event = NULL;
654      }
655
656    _ecore_mouse_move(ev->time, ev->state,
657                      ev->event_x, ev->event_y,
658                      ev->root_x, ev->root_y,
659                      ev->event,
660                      (ev->child ? ev->child : ev->event),
661                      ev->root,
662                      ev->same_screen);
663
664    _ecore_xcb_last_event_mouse_move = 1;
665
666    /* Xdnd handling */
667    _ecore_x_dnd_drag(ev->root, ev->root_x, ev->root_y);
668
669    free(event);
670 }
671
672 void
673 _ecore_x_event_handle_enter_notify(xcb_generic_event_t *event)
674 {
675    xcb_enter_notify_event_t *ev;
676
677    ev = (xcb_enter_notify_event_t *)event;
678    _ecore_xcb_last_event_mouse_move = 0;
679
680    {
681       _ecore_mouse_move(ev->time, ev->state,
682                         ev->event_x, ev->event_y,
683                         ev->root_x, ev->root_y,
684                         ev->event,
685                         (ev->child ? ev->child : ev->event),
686                         ev->root,
687                         ev->same_screen_focus);
688    }
689    {
690       Ecore_X_Event_Mouse_In *e;
691
692       e = calloc(1, sizeof(Ecore_X_Event_Mouse_In));
693       if (!e) return;
694       e->modifiers = _ecore_x_event_modifiers(ev->state);
695       e->x = ev->event_x;
696       e->y = ev->event_y;
697       e->root.x = ev->root_x;
698       e->root.y = ev->root_y;
699       if (ev->child) e->win = ev->child;
700       else e->win = ev->event;
701       e->same_screen = ev->same_screen_focus;
702       e->root_win = ev->root;
703       e->event_win = ev->event;
704       switch (ev->mode) {
705       case XCB_NOTIFY_MODE_NORMAL:
706         e->mode = ECORE_X_EVENT_MODE_NORMAL;
707         break;
708       case XCB_NOTIFY_MODE_GRAB:
709         e->mode = ECORE_X_EVENT_MODE_GRAB;
710         break;
711       case XCB_NOTIFY_MODE_UNGRAB:
712         e->mode = ECORE_X_EVENT_MODE_UNGRAB;
713         break;
714       default:
715         e->mode = ECORE_X_EVENT_MODE_NORMAL;
716         break;
717       }
718       switch (ev->detail) {
719       case XCB_NOTIFY_DETAIL_ANCESTOR:
720         e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
721         break;
722       case XCB_NOTIFY_DETAIL_VIRTUAL:
723         e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL;
724         break;
725       case XCB_NOTIFY_DETAIL_INFERIOR:
726         e->detail = ECORE_X_EVENT_DETAIL_INFERIOR;
727         break;
728       case XCB_NOTIFY_DETAIL_NONLINEAR:
729         e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR;
730         break;
731       case XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL:
732         e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL;
733         break;
734       default:
735         e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
736         break;
737       }
738       e->time = ev->time;
739       _ecore_xcb_event_last_time = e->time;
740       ecore_event_add(ECORE_X_EVENT_MOUSE_IN, e, NULL, NULL);
741    }
742
743    free(event);
744 }
745
746 void
747 _ecore_x_event_handle_leave_notify(xcb_generic_event_t *event)
748 {
749    xcb_leave_notify_event_t *ev;
750
751    ev = (xcb_leave_notify_event_t *)event;
752    _ecore_xcb_last_event_mouse_move = 0;
753
754    {
755       _ecore_mouse_move(ev->time, ev->state,
756                         ev->event_x, ev->event_y,
757                         ev->root_x, ev->root_y,
758                         ev->event,
759                         (ev->child ? ev->child : ev->event),
760                         ev->root,
761                         ev->same_screen_focus);
762    }
763    {
764       Ecore_X_Event_Mouse_Out *e;
765
766       e = calloc(1, sizeof(Ecore_X_Event_Mouse_Out));
767       if (!e) return;
768       e->modifiers = _ecore_x_event_modifiers(ev->state);
769       e->x = ev->event_x;
770       e->y = ev->event_y;
771       e->root.x = ev->root_x;
772       e->root.y = ev->root_y;
773       if (ev->child) e->win = ev->child;
774       else e->win = ev->event;
775       e->same_screen = ev->same_screen_focus;
776       e->root_win = ev->root;
777       e->event_win = ev->event;
778       switch (ev->mode) {
779       case XCB_NOTIFY_MODE_NORMAL:
780         e->mode = ECORE_X_EVENT_MODE_NORMAL;
781         break;
782       case XCB_NOTIFY_MODE_GRAB:
783         e->mode = ECORE_X_EVENT_MODE_GRAB;
784         break;
785       case XCB_NOTIFY_MODE_UNGRAB:
786         e->mode = ECORE_X_EVENT_MODE_UNGRAB;
787         break;
788       default:
789         e->mode = ECORE_X_EVENT_MODE_NORMAL;
790         break;
791       }
792       switch (ev->detail) {
793       case XCB_NOTIFY_DETAIL_ANCESTOR:
794         e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
795         break;
796       case XCB_NOTIFY_DETAIL_VIRTUAL:
797         e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL;
798         break;
799       case XCB_NOTIFY_DETAIL_INFERIOR:
800         e->detail = ECORE_X_EVENT_DETAIL_INFERIOR;
801         break;
802       case XCB_NOTIFY_DETAIL_NONLINEAR:
803         e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR;
804         break;
805       case XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL:
806         e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL;
807         break;
808       default:
809         e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
810         break;
811       }
812       e->time = ev->time;
813       _ecore_xcb_event_last_time = e->time;
814       _ecore_xcb_event_last_window = e->win;
815       _ecore_xcb_event_last_root_x = e->root.x;
816       _ecore_xcb_event_last_root_y = e->root.y;
817       ecore_event_add(ECORE_X_EVENT_MOUSE_OUT, e, NULL, NULL);
818    }
819
820    free(event);
821 }
822
823 void
824 _ecore_x_event_handle_focus_in(xcb_generic_event_t *event)
825 {
826    xcb_focus_in_event_t          *ev;
827    Ecore_X_Event_Window_Focus_In *e;
828
829    ev = (xcb_focus_in_event_t *)event;
830    e = calloc(1, sizeof(Ecore_X_Event_Window_Focus_In));
831    if (!e) return;
832    e->win = ev->event;
833    switch (ev->mode) {
834    case XCB_NOTIFY_MODE_NORMAL:
835      e->mode = ECORE_X_EVENT_MODE_NORMAL;
836      break;
837    case XCB_NOTIFY_MODE_GRAB:
838      e->mode = ECORE_X_EVENT_MODE_GRAB;
839      break;
840    case XCB_NOTIFY_MODE_UNGRAB:
841      e->mode = ECORE_X_EVENT_MODE_UNGRAB;
842      break;
843    case XCB_NOTIFY_MODE_WHILE_GRABBED:
844      e->mode = ECORE_X_EVENT_MODE_WHILE_GRABBED;
845      break;
846    }
847    switch (ev->detail) {
848    case XCB_NOTIFY_DETAIL_ANCESTOR:
849      e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
850      break;
851    case XCB_NOTIFY_DETAIL_VIRTUAL:
852      e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL;
853      break;
854    case XCB_NOTIFY_DETAIL_INFERIOR:
855      e->detail = ECORE_X_EVENT_DETAIL_INFERIOR;
856      break;
857    case XCB_NOTIFY_DETAIL_NONLINEAR:
858      e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR;
859      break;
860    case XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL:
861      e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL;
862      break;
863    case XCB_NOTIFY_DETAIL_POINTER:
864      e->detail = ECORE_X_EVENT_DETAIL_POINTER;
865      break;
866    case XCB_NOTIFY_DETAIL_POINTER_ROOT:
867      e->detail = ECORE_X_EVENT_DETAIL_POINTER_ROOT;
868      break;
869    case XCB_NOTIFY_DETAIL_NONE:
870      e->detail = ECORE_X_EVENT_DETAIL_DETAIL_NONE;
871      break;
872    }
873    e->time = _ecore_xcb_event_last_time;
874    _ecore_xcb_event_last_time = e->time;
875    ecore_event_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, e, NULL, NULL);
876
877    free(event);
878 }
879
880 void
881 _ecore_x_event_handle_focus_out(xcb_generic_event_t *event)
882 {
883    xcb_focus_out_event_t            *ev;
884    Ecore_X_Event_Window_Focus_Out *e;
885
886    ev = (xcb_focus_out_event_t *)event;
887    e = calloc(1, sizeof(Ecore_X_Event_Window_Focus_Out));
888    if (!e) return;
889    e->win = ev->event;
890    switch (ev->mode) {
891    case XCB_NOTIFY_MODE_NORMAL:
892      e->mode = ECORE_X_EVENT_MODE_NORMAL;
893      break;
894    case XCB_NOTIFY_MODE_GRAB:
895      e->mode = ECORE_X_EVENT_MODE_GRAB;
896      break;
897    case XCB_NOTIFY_MODE_UNGRAB:
898      e->mode = ECORE_X_EVENT_MODE_UNGRAB;
899      break;
900    case XCB_NOTIFY_MODE_WHILE_GRABBED:
901      e->mode = ECORE_X_EVENT_MODE_WHILE_GRABBED;
902      break;
903    }
904    switch (ev->detail) {
905    case XCB_NOTIFY_DETAIL_ANCESTOR:
906      e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR;
907      break;
908    case XCB_NOTIFY_DETAIL_VIRTUAL:
909      e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL;
910      break;
911    case XCB_NOTIFY_DETAIL_INFERIOR:
912      e->detail = ECORE_X_EVENT_DETAIL_INFERIOR;
913      break;
914    case XCB_NOTIFY_DETAIL_NONLINEAR:
915      e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR;
916      break;
917    case XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL:
918      e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL;
919      break;
920    case XCB_NOTIFY_DETAIL_POINTER:
921      e->detail = ECORE_X_EVENT_DETAIL_POINTER;
922      break;
923    case XCB_NOTIFY_DETAIL_POINTER_ROOT:
924      e->detail = ECORE_X_EVENT_DETAIL_POINTER_ROOT;
925      break;
926    case XCB_NOTIFY_DETAIL_NONE:
927      e->detail = ECORE_X_EVENT_DETAIL_DETAIL_NONE;
928      break;
929    }
930    e->time = _ecore_xcb_event_last_time;
931    _ecore_xcb_event_last_time = e->time;
932    ecore_event_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, e, NULL, NULL);
933
934    free(event);
935 }
936
937 void
938 _ecore_x_event_handle_keymap_notify(xcb_generic_event_t *event)
939 {
940    /* FIXME: handle this event type */
941
942    free(event);
943 }
944
945 void
946 _ecore_x_event_handle_expose(xcb_generic_event_t *event)
947 {
948    xcb_expose_event_t            *ev;
949    Ecore_X_Event_Window_Damage *e;
950
951    ev = (xcb_expose_event_t *)event,
952    e = calloc(1, sizeof(Ecore_X_Event_Window_Damage));
953    if (!e) return;
954    e->win = ev->window;
955    e->time = _ecore_xcb_event_last_time;
956    e->x = ev->x;
957    e->y = ev->y;
958    e->w = ev->width;
959    e->h = ev->height;
960    e->count = ev->count;
961    ecore_event_add(ECORE_X_EVENT_WINDOW_DAMAGE, e, NULL, NULL);
962
963    free(event);
964 }
965
966 void
967 _ecore_x_event_handle_graphics_expose(xcb_generic_event_t *event)
968 {
969    xcb_graphics_exposure_event_t *ev;
970    Ecore_X_Event_Window_Damage *e;
971
972    ev = (xcb_graphics_exposure_event_t *)event;
973    e = calloc(1, sizeof(Ecore_X_Event_Window_Damage));
974    if (!e) return;
975    e->win = ev->drawable;
976    e->time = _ecore_xcb_event_last_time;
977    e->x = ev->x;
978    e->y = ev->y;
979    e->w = ev->width;
980    e->h = ev->height;
981    e->count = ev->count;
982    ecore_event_add(ECORE_X_EVENT_WINDOW_DAMAGE, e, NULL, NULL);
983
984    free(event);
985 }
986
987 void
988 _ecore_x_event_handle_visibility_notify(xcb_generic_event_t *event)
989 {
990    xcb_visibility_notify_event_t *ev;
991
992    ev = (xcb_visibility_notify_event_t *)event;
993    if (ev->state != XCB_VISIBILITY_PARTIALLY_OBSCURED)
994    {
995       Ecore_X_Event_Window_Visibility_Change *e;
996
997       e = calloc(1, sizeof(Ecore_X_Event_Window_Visibility_Change));
998       if (!e) return;
999       e->win = ev->window;
1000       e->time = _ecore_xcb_event_last_time;
1001       if (ev->state == XCB_VISIBILITY_FULLY_OBSCURED)
1002          e->fully_obscured = 1;
1003       else
1004          e->fully_obscured = 0;
1005       ecore_event_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE, e, NULL, NULL);
1006    }
1007
1008    free(event);
1009 }
1010
1011 void
1012 _ecore_x_event_handle_create_notify(xcb_generic_event_t *event)
1013 {
1014    xcb_create_notify_event_t     *ev;
1015    Ecore_X_Event_Window_Create *e;
1016
1017    ev = (xcb_create_notify_event_t *)event;
1018    e = calloc(1, sizeof(Ecore_X_Event_Window_Create));
1019    if (!e) return;
1020    e->win = ev->window;
1021    if (ev->override_redirect)
1022       e->override = 1;
1023    else
1024       e->override = 0;
1025    e->time = _ecore_xcb_event_last_time;
1026    ecore_event_add(ECORE_X_EVENT_WINDOW_CREATE, e, NULL, NULL);
1027
1028    free(event);
1029 }
1030
1031 void
1032 _ecore_x_event_handle_destroy_notify(xcb_generic_event_t *event)
1033 {
1034    xcb_destroy_notify_event_t     *ev;
1035    Ecore_X_Event_Window_Destroy *e;
1036
1037    ev = (xcb_destroy_notify_event_t *)event;
1038    e = calloc(1, sizeof(Ecore_X_Event_Window_Destroy));
1039    if (!e) return;
1040    e->win =  ev->window;
1041    e->time = _ecore_xcb_event_last_time;
1042    if (e->win == _ecore_xcb_event_last_window) _ecore_xcb_event_last_window = 0;
1043    ecore_event_add(ECORE_X_EVENT_WINDOW_DESTROY, e, NULL, NULL);
1044
1045    free(event);
1046 }
1047
1048 void
1049 _ecore_x_event_handle_unmap_notify(xcb_generic_event_t *event)
1050 {
1051    xcb_unmap_notify_event_t    *ev;
1052    Ecore_X_Event_Window_Hide *e;
1053
1054    ev = (xcb_unmap_notify_event_t *)event;
1055    e = calloc(1, sizeof(Ecore_X_Event_Window_Hide));
1056    if (!e) return;
1057    e->win = ev->window;
1058    e->time = _ecore_xcb_event_last_time;
1059    ecore_event_add(ECORE_X_EVENT_WINDOW_HIDE, e, NULL, NULL);
1060
1061    free(event);
1062 }
1063
1064 void
1065 _ecore_x_event_handle_map_notify(xcb_generic_event_t *event)
1066 {
1067    xcb_map_notify_event_t      *ev;
1068    Ecore_X_Event_Window_Show *e;
1069
1070    ev = (xcb_map_notify_event_t *)event;
1071    e = calloc(1, sizeof(Ecore_X_Event_Window_Show));
1072    if (!e) return;
1073    e->win = ev->window;
1074    e->time = _ecore_xcb_event_last_time;
1075    ecore_event_add(ECORE_X_EVENT_WINDOW_SHOW, e, NULL, NULL);
1076
1077    free(event);
1078 }
1079
1080 void
1081 _ecore_x_event_handle_map_request(xcb_generic_event_t *event)
1082 {
1083    xcb_map_request_event_t             *ev;
1084    Ecore_X_Event_Window_Show_Request *e;
1085
1086    ev = (xcb_map_request_event_t *)event;
1087    e = calloc(1, sizeof(Ecore_X_Event_Window_Show_Request));
1088    if (!e) return;
1089    e->win = ev->window;
1090    e->parent = ev->parent;
1091    e->time = _ecore_xcb_event_last_time;
1092    ecore_event_add(ECORE_X_EVENT_WINDOW_SHOW_REQUEST, e, NULL, NULL);
1093
1094    free(event);
1095 }
1096
1097 void
1098 _ecore_x_event_handle_reparent_notify(xcb_generic_event_t *event)
1099 {
1100    xcb_reparent_notify_event_t     *ev;
1101    Ecore_X_Event_Window_Reparent *e;
1102
1103    ev = (xcb_reparent_notify_event_t *)event;
1104    e = calloc(1, sizeof(Ecore_X_Event_Window_Reparent));
1105    if (!e) return;
1106    e->win = ev->window;
1107    e->parent = ev->parent;
1108    e->time = _ecore_xcb_event_last_time;
1109    ecore_event_add(ECORE_X_EVENT_WINDOW_REPARENT, e, NULL, NULL);
1110
1111    free(event);
1112 }
1113
1114 void
1115 _ecore_x_event_handle_configure_notify(xcb_generic_event_t *event)
1116 {
1117    xcb_configure_notify_event_t     *ev;
1118    Ecore_X_Event_Window_Configure *e;
1119
1120    ev = (xcb_configure_notify_event_t *)event;
1121    e = calloc(1, sizeof(Ecore_X_Event_Window_Configure));
1122    if (!e) return;
1123    e->win = ev->window;
1124    e->abovewin = ev->above_sibling;
1125    e->x = ev->x;
1126    e->y = ev->y;
1127    e->w = ev->width;
1128    e->h = ev->height;
1129    e->border = ev->border_width;
1130    e->override = ev->override_redirect;
1131    /* send_event is bit 7 (0x80) of response_type */
1132    e->from_wm = (ev->response_type & 0x80) ? 1 : 0;
1133    e->time = _ecore_xcb_event_last_time;
1134    ecore_event_add(ECORE_X_EVENT_WINDOW_CONFIGURE, e, NULL, NULL);
1135
1136    free(event);
1137 }
1138
1139 void
1140 _ecore_x_event_handle_configure_request(xcb_generic_event_t *event)
1141 {
1142    xcb_configure_request_event_t            *ev;
1143    Ecore_X_Event_Window_Configure_Request *e;
1144
1145    ev = (xcb_configure_request_event_t *)event;
1146    e = calloc(1, sizeof(Ecore_X_Event_Window_Configure_Request));
1147    if (!e) return;
1148    e->win = ev->window;
1149    e->abovewin = ev->sibling;
1150    e->x = ev->x;
1151    e->y = ev->y;
1152    e->w = ev->width;
1153    e->h = ev->height;
1154    e->border = ev->border_width;
1155    e->value_mask = ev->value_mask;
1156    switch (ev->stack_mode) {
1157    case XCB_STACK_MODE_ABOVE:
1158      e->detail = ECORE_X_WINDOW_STACK_ABOVE;
1159      break;
1160    case XCB_STACK_MODE_BELOW:
1161      e->detail = ECORE_X_WINDOW_STACK_BELOW;
1162      break;
1163    case XCB_STACK_MODE_TOP_IF:
1164      e->detail = ECORE_X_WINDOW_STACK_TOP_IF;
1165      break;
1166    case XCB_STACK_MODE_BOTTOM_IF:
1167      e->detail = ECORE_X_WINDOW_STACK_BOTTOM_IF;
1168      break;
1169    case XCB_STACK_MODE_OPPOSITE:
1170      e->detail = ECORE_X_WINDOW_STACK_OPPOSITE;
1171      break;
1172    }
1173    e->time = _ecore_xcb_event_last_time;
1174    ecore_event_add(ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST, e, NULL, NULL);
1175
1176    free(event);
1177 }
1178
1179 void
1180 _ecore_x_event_handle_gravity_notify(xcb_generic_event_t *event)
1181 {
1182    /* FIXME: handle this event type */
1183
1184    free(event);
1185 }
1186
1187 void
1188 _ecore_x_event_handle_resize_request(xcb_generic_event_t *event)
1189 {
1190    xcb_resize_request_event_t            *ev;
1191    Ecore_X_Event_Window_Resize_Request *e;
1192
1193    ev = (xcb_resize_request_event_t *)event;
1194    e = calloc(1, sizeof(Ecore_X_Event_Window_Resize_Request));
1195    if (!e) return;
1196    e->win = ev->window;
1197    e->w = ev->width;
1198    e->h = ev->height;
1199    e->time = _ecore_xcb_event_last_time;
1200    ecore_event_add(ECORE_X_EVENT_WINDOW_RESIZE_REQUEST, e, NULL, NULL);
1201
1202    free(event);
1203 }
1204
1205 void
1206 _ecore_x_event_handle_circulate_notify(xcb_generic_event_t *event)
1207 {
1208    xcb_circulate_notify_event_t *ev;
1209    Ecore_X_Event_Window_Stack *e;
1210
1211    ev = (xcb_circulate_notify_event_t *)event;
1212    e = calloc(1, sizeof(Ecore_X_Event_Window_Stack));
1213    if (!e) return;
1214    e->win = ev->window;
1215    e->event_win = ev->event;
1216    if (ev->place == XCB_PLACE_ON_TOP)
1217      e->detail = ECORE_X_WINDOW_STACK_ABOVE;
1218    else
1219      e->detail = ECORE_X_WINDOW_STACK_BELOW;
1220    e->time = _ecore_xcb_event_last_time;
1221    ecore_event_add(ECORE_X_EVENT_WINDOW_STACK, e, NULL, NULL);
1222
1223    free(event);
1224 }
1225
1226 void
1227 _ecore_x_event_handle_circulate_request(xcb_generic_event_t *event)
1228 {
1229    xcb_circulate_request_event_t        *ev;
1230    Ecore_X_Event_Window_Stack_Request *e;
1231
1232    ev = (xcb_circulate_request_event_t *)event;
1233    e = calloc(1, sizeof(Ecore_X_Event_Window_Stack_Request));
1234    if (!e) return;
1235    e->win = ev->window;
1236    e->parent = ev->event;
1237    if (ev->place == XCB_PLACE_ON_TOP)
1238      e->detail = ECORE_X_WINDOW_STACK_ABOVE;
1239    else
1240      e->detail = ECORE_X_WINDOW_STACK_BELOW;
1241    e->time = _ecore_xcb_event_last_time;
1242    ecore_event_add(ECORE_X_EVENT_WINDOW_STACK_REQUEST, e, NULL, NULL);
1243
1244    free(event);
1245 }
1246
1247 void
1248 _ecore_x_event_handle_property_notify(xcb_generic_event_t *event)
1249 {
1250 #if 0 /* for now i disabled this. nice idea though this is - it leaves a lot
1251        * to be desired for efficiency that is better left to the app layer
1252        */
1253    if (xevent->xproperty.atom == ECORE_X_ATOM_WM_CLASS)
1254      {
1255         Ecore_X_Event_Window_Prop_Name_Class_Change *e;
1256
1257         e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Name_Class_Change));
1258         if (!e) return;
1259         ecore_x_window_prop_name_class_get(xevent->xproperty.window,
1260                                            &(e->name), &(e->clas));
1261    e->time = xevent->xproperty.time;
1262    _ecore_x_event_last_time = e->time;
1263         ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE, e, _ecore_x_event_free_window_prop_name_class_change, NULL);
1264      }
1265    else if ((xevent->xproperty.atom == ECORE_X_ATOM_WM_NAME) || (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_NAME))
1266      {
1267         Ecore_X_Event_Window_Prop_Title_Change *e;
1268
1269         e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Title_Change));
1270         if (!e) return;
1271         e->title = ecore_x_window_prop_title_get(xevent->xproperty.window);
1272    e->time = xevent->xproperty.time;
1273    _ecore_x_event_last_time = e->time;
1274         ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE, e, _ecore_x_event_free_window_prop_title_change, NULL);
1275      }
1276    else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_VISIBLE_NAME)
1277      {
1278         Ecore_X_Event_Window_Prop_Visible_Title_Change *e;
1279
1280         e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Visible_Title_Change));
1281         if (!e) return;
1282         e->title = ecore_x_window_prop_visible_title_get(xevent->xproperty.window);
1283    e->time = xevent->xproperty.time;
1284    _ecore_x_event_last_time = e->time;
1285         ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE, e, _ecore_x_event_free_window_prop_visible_title_change, NULL);
1286      }
1287    else if ((xevent->xproperty.atom == ECORE_X_ATOM_WM_ICON_NAME) || (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_ICON_NAME))
1288      {
1289         Ecore_X_Event_Window_Prop_Icon_Name_Change *e;
1290
1291         e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Icon_Name_Change));
1292         if (!e) return;
1293         e->name = ecore_x_window_prop_icon_name_get(xevent->xproperty.window);
1294    e->time = xevent->xproperty.time;
1295    _ecore_x_event_last_time = e->time;
1296         ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE, e, _ecore_x_event_free_window_prop_icon_name_change, NULL);
1297      }
1298    else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME)
1299      {
1300         Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change *e;
1301
1302         e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change));
1303         if (!e) return;
1304         e->name = ecore_x_window_prop_visible_icon_name_get(xevent->xproperty.window);
1305    e->time = xevent->xproperty.time;
1306    _ecore_x_event_last_time = e->time;
1307         ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE, e, _ecore_x_event_free_window_prop_visible_icon_name_change, NULL);
1308      }
1309    else if (xevent->xproperty.atom == ECORE_X_ATOM_WM_CLIENT_MACHINE)
1310      {
1311         Ecore_X_Event_Window_Prop_Client_Machine_Change *e;
1312
1313         e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Client_Machine_Change));
1314         if (!e) return;
1315         e->name = ecore_x_window_prop_client_machine_get(xevent->xproperty.window);
1316    e->time = xevent->xproperty.time;
1317    _ecore_x_event_last_time = e->time;
1318         ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE, e, _ecore_x_event_free_window_prop_client_machine_change, NULL);
1319      }
1320    else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_PID)
1321      {
1322         Ecore_X_Event_Window_Prop_Pid_Change *e;
1323
1324         e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Pid_Change));
1325         if (!e) return;
1326         e->pid = ecore_x_window_prop_pid_get(xevent->xproperty.window);
1327    e->time = xevent->xproperty.time;
1328    _ecore_x_event_last_time = e->time;
1329         ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE, e, NULL, NULL);
1330      }
1331    else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_DESKTOP)
1332      {
1333         Ecore_X_Event_Window_Prop_Desktop_Change *e;
1334
1335         e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Desktop_Change));
1336         if (!e) return;
1337         e->desktop = ecore_x_window_prop_desktop_get(xevent->xproperty.window);
1338         ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE, e, NULL, NULL);
1339      }
1340    else
1341 #endif
1342    {
1343       xcb_property_notify_event_t     *ev;
1344       Ecore_X_Event_Window_Property *e;
1345
1346       ev = (xcb_property_notify_event_t *)event;
1347       e = calloc(1,sizeof(Ecore_X_Event_Window_Property));
1348       if (!e) return;
1349       e->win = ev->window;
1350       e->atom = ev->atom;
1351       e->time = ev->time;
1352       _ecore_xcb_event_last_time = e->time;
1353       ecore_event_add(ECORE_X_EVENT_WINDOW_PROPERTY, e, NULL, NULL);
1354    }
1355
1356    free(event);
1357 }
1358
1359 void
1360 _ecore_x_event_handle_selection_clear(xcb_generic_event_t *event)
1361 {
1362    xcb_selection_clear_event_t     *ev;
1363    Ecore_X_Selection_Intern      *d;
1364    Ecore_X_Event_Selection_Clear *e;
1365    Ecore_X_Atom                   sel;
1366
1367    ev = (xcb_selection_clear_event_t *)event;
1368    d = _ecore_x_selection_get(ev->selection);
1369    if (d && (ev->time > d->time))
1370      {
1371         _ecore_x_selection_set(XCB_NONE, NULL, 0,
1372                                ev->selection);
1373      }
1374
1375    /* Generate event for app cleanup */
1376    e = malloc(sizeof(Ecore_X_Event_Selection_Clear));
1377    e->win = ev->owner;
1378    e->time = ev->time;
1379    e->atom = sel = ev->selection;
1380    if (sel == ECORE_X_ATOM_SELECTION_PRIMARY)
1381      e->selection = ECORE_X_SELECTION_PRIMARY;
1382    else if (sel == ECORE_X_ATOM_SELECTION_SECONDARY)
1383      e->selection = ECORE_X_SELECTION_SECONDARY;
1384    else if (sel == ECORE_X_ATOM_SELECTION_CLIPBOARD)
1385      e->selection = ECORE_X_SELECTION_CLIPBOARD;
1386    else
1387      e->selection = ECORE_X_SELECTION_OTHER;
1388    ecore_event_add(ECORE_X_EVENT_SELECTION_CLEAR, e, NULL, NULL);
1389
1390    free(event);
1391 }
1392
1393 void
1394 _ecore_x_event_handle_selection_request(xcb_generic_event_t *event)
1395 {
1396    xcb_selection_request_event_t *ev;
1397    Ecore_X_Selection_Intern    *sd;
1398    xcb_selection_notify_event_t   sn_event;
1399    void                          *data;
1400
1401    ev = (xcb_selection_request_event_t *)event;
1402    /* FIXME: is it the correct value ? */
1403    sn_event.response_type = XCB_SELECTION_NOTIFY;
1404    sn_event.pad0 = 0;
1405    /* FIXME: is it the correct value ? */
1406    sn_event.sequence = 0;
1407    sn_event.time = XCB_CURRENT_TIME;
1408    sn_event.requestor = ev->requestor;
1409    sn_event.selection = ev->selection;
1410    sn_event.target = ev->target;
1411
1412    if ((sd = _ecore_x_selection_get(ev->selection)) &&
1413        (sd->win == ev->owner))
1414      {
1415         if (!ecore_x_selection_convert(ev->selection, ev->target,
1416                                        &data))
1417           {
1418              /* Refuse selection, conversion to requested target failed */
1419              sn_event.property = XCB_NONE;
1420           }
1421         else
1422           {
1423              /* FIXME: This does not properly handle large data transfers */
1424              ecore_x_window_prop_property_set(ev->requestor,
1425                                               ev->property,
1426                                               ev->target,
1427                                               8, data, sd->length);
1428              sn_event.property = ev->property;
1429              free(data);
1430           }
1431      }
1432    else
1433      {
1434         sn_event.property = XCB_NONE;
1435         return;
1436      }
1437
1438    /* FIXME: I use _ecore_xcb_conn, as ev has no information on the connection */
1439    xcb_send_event(_ecore_xcb_conn, 0,
1440                   ev->requestor, 0, (const char *)&sn_event);
1441
1442    free(event);
1443 }
1444
1445 /* FIXME: round trip */
1446 void
1447 _ecore_x_event_handle_selection_notify(xcb_generic_event_t *event)
1448 {
1449    xcb_selection_notify_event_t   *ev;
1450    Ecore_X_Event_Selection_Notify *e;
1451    unsigned char                 *data = NULL;
1452    Ecore_X_Atom                   selection;
1453    int                            num_ret;
1454    uint8_t                        format;
1455
1456    ev = (xcb_selection_notify_event_t *)event;
1457    selection = ev->selection;
1458
1459    if (ev->target == ECORE_X_ATOM_SELECTION_TARGETS)
1460      {
1461         ecore_x_window_prop_property_get_prefetch(ev->requestor,
1462                                                   ev->property,
1463                                                   ECORE_X_ATOM_ATOM);
1464         ecore_x_window_prop_property_get_fetch();
1465         format = ecore_x_window_prop_property_get(ev->requestor,
1466                                                   ev->property,
1467                                                   ECORE_X_ATOM_ATOM,
1468                                                   32,
1469                                                   &data,
1470                                                   &num_ret);
1471         if (!format) return;
1472      }
1473    else
1474      {
1475         ecore_x_window_prop_property_get_prefetch(ev->requestor,
1476                                                   ev->property,
1477                                                   XCB_GET_PROPERTY_TYPE_ANY);
1478         ecore_x_window_prop_property_get_fetch();
1479         format = ecore_x_window_prop_property_get(ev->requestor,
1480                                                   ev->property,
1481                                                   ECORE_X_ATOM_ATOM,
1482                                                   8,
1483                                                   &data,
1484                                                   &num_ret);
1485         if (!format) return;
1486      }
1487
1488    e = calloc(1, sizeof(Ecore_X_Event_Selection_Notify));
1489    if (!e) return;
1490    e->win = ev->requestor;
1491    e->time = ev->time;
1492    e->atom = selection;
1493    e->target = _ecore_x_selection_target_get(ev->target);
1494
1495    if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
1496      e->selection = ECORE_X_SELECTION_PRIMARY;
1497    else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
1498      e->selection = ECORE_X_SELECTION_SECONDARY;
1499    else if (selection == ECORE_X_ATOM_SELECTION_XDND)
1500      e->selection = ECORE_X_SELECTION_XDND;
1501    else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
1502      e->selection = ECORE_X_SELECTION_CLIPBOARD;
1503    else
1504      e->selection = ECORE_X_SELECTION_OTHER;
1505
1506    e->data = _ecore_x_selection_parse(e->target, data, num_ret, format);
1507
1508    ecore_event_add(ECORE_X_EVENT_SELECTION_NOTIFY, e, _ecore_x_event_free_selection_notify, NULL);
1509
1510    free(event);
1511 }
1512
1513 void
1514 _ecore_x_event_handle_colormap_notify(xcb_generic_event_t *event)
1515 {
1516    xcb_colormap_notify_event_t     *ev;
1517    Ecore_X_Event_Window_Colormap *e;
1518
1519    ev = (xcb_colormap_notify_event_t *)event;
1520    e = calloc(1,sizeof(Ecore_X_Event_Window_Colormap));
1521    if (!e) return;
1522    e->win = ev->window;
1523    e->cmap = ev->colormap;
1524    if (ev->state == XCB_COLORMAP_STATE_INSTALLED)
1525       e->installed = 1;
1526    else
1527       e->installed = 0;
1528    e->time = _ecore_xcb_event_last_time;
1529    ecore_event_add(ECORE_X_EVENT_WINDOW_COLORMAP, e, NULL, NULL);
1530
1531    free(event);
1532 }
1533
1534 void
1535 _ecore_x_event_handle_client_message(xcb_generic_event_t *event)
1536 {
1537    /* Special client message event handling here. need to put LOTS of if */
1538    /* checks here and generate synthetic events per special message known */
1539    /* otherwise generate generic client message event. this would handle*/
1540    /* netwm, ICCCM, gnomewm, old kde and mwm hint client message protocols */
1541
1542    xcb_client_message_event_t *ev;
1543
1544    ev = (xcb_client_message_event_t *)event;
1545    if ((ev->type == ECORE_X_ATOM_WM_PROTOCOLS) &&
1546        (ev->format == 32) &&
1547        (ev->data.data32[0] == (uint32_t)ECORE_X_ATOM_WM_DELETE_WINDOW))
1548      {
1549         Ecore_X_Event_Window_Delete_Request *e;
1550
1551         e = calloc(1, sizeof(Ecore_X_Event_Window_Delete_Request));
1552         if (!e) return;
1553         e->win = ev->window;
1554         e->time = _ecore_xcb_event_last_time;
1555         ecore_event_add(ECORE_X_EVENT_WINDOW_DELETE_REQUEST, e, NULL, NULL);
1556      }
1557
1558    else if ((ev->type == ECORE_X_ATOM_NET_WM_MOVERESIZE) &&
1559             (ev->format == 32) &&
1560             /* Ignore move and resize with keyboard */
1561             (ev->data.data32[2] < 9))
1562      {
1563         Ecore_X_Event_Window_Move_Resize_Request *e;
1564
1565         e = calloc(1, sizeof(Ecore_X_Event_Window_Move_Resize_Request));
1566         if (!e) return;
1567         e->win = ev->window;
1568         e->x = ev->data.data32[0];
1569         e->y = ev->data.data32[1];
1570         e->direction = ev->data.data32[2];
1571         e->button = ev->data.data32[3];
1572         e->source = ev->data.data32[4];
1573         ecore_event_add(ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST, e, NULL, NULL);
1574      }
1575
1576    /* Xdnd Client Message Handling Begin */
1577    /* Message Type: XdndEnter target */
1578    else if (ev->type == ECORE_X_ATOM_XDND_ENTER)
1579      {
1580         Ecore_X_Event_Xdnd_Enter *e;
1581         Ecore_X_DND_Target       *target;
1582         uint32_t                  three;
1583
1584         e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Enter));
1585         if (!e) return;
1586
1587         target = _ecore_x_dnd_target_get();
1588         target->state = ECORE_X_DND_TARGET_ENTERED;
1589
1590         target = _ecore_x_dnd_target_get();
1591         target->source = ev->data.data32[0];
1592         target->win = ev->window;
1593         target->version = ev->data.data32[1] >> 24;
1594         if (target->version > ECORE_X_DND_VERSION)
1595           {
1596              WRN("DND: Requested version %d, we only support up to %d", target->version,
1597                     ECORE_X_DND_VERSION);
1598              return;
1599           }
1600
1601         /* FIXME: roud trip, but I don't know how to suppress it */
1602         if ((three = ev->data.data32[1] & 0x1UL))
1603           {
1604              /* source supports more than 3 types, fetch property */
1605              unsigned char *data;
1606              Ecore_X_Atom  *types;
1607              int            num_ret;
1608              int            i;
1609              uint8_t        format;
1610
1611              ecore_x_window_prop_property_get_prefetch(target->source,
1612                                                        ECORE_X_ATOM_XDND_TYPE_LIST,
1613                                                        ECORE_X_ATOM_ATOM);
1614              ecore_x_window_prop_property_get_fetch();
1615              format = ecore_x_window_prop_property_get(target->source,
1616                                                        ECORE_X_ATOM_XDND_TYPE_LIST,
1617                                                        ECORE_X_ATOM_ATOM,
1618                                                        32,
1619                                                        &data,
1620                                                        &num_ret);
1621              if (!format)
1622                {
1623                   ERR("DND: Could not fetch data type list from source window, aborting.");
1624                   return;
1625                }
1626              types = (Ecore_X_Atom *)data;
1627              e->types = calloc(num_ret, sizeof(char *));
1628              if (e->types)
1629                {
1630                   xcb_get_atom_name_cookie_t *cookies;
1631
1632                   cookies = (xcb_get_atom_name_cookie_t *)malloc(sizeof(xcb_get_atom_name_cookie_t) * num_ret);
1633                   for (i = 0; i < num_ret; i++)
1634                     cookies[i] = xcb_get_atom_name_unchecked(_ecore_xcb_conn, types[i]);
1635                   for (i = 0; i < num_ret; i++)
1636                     {
1637                        xcb_get_atom_name_reply_t *reply;
1638                        char                      *name;
1639
1640                        reply = xcb_get_atom_name_reply(_ecore_xcb_conn, cookies[i], NULL);
1641                        if (reply)
1642                          {
1643                             name = (char *)malloc(sizeof (char) * (reply->name_len + 1));
1644                             memcpy(name,
1645                                    xcb_get_atom_name_name(reply),
1646                                    reply->name_len);
1647                             name[reply->name_len] = '\0';
1648                             e->types[i] = name;
1649                             free(reply);
1650                          }
1651                     }
1652                   free(cookies);
1653                }
1654              e->num_types = num_ret;
1655           }
1656         else
1657           {
1658              int i = 0;
1659
1660              e->types = calloc(3, sizeof(char *));
1661              if (e->types)
1662                {
1663                   xcb_get_atom_name_cookie_t cookies[3];
1664
1665                   for (i = 0; i < 3; i++)
1666                     cookies[i] = xcb_get_atom_name_unchecked(_ecore_xcb_conn, ev->data.data32[i + 2]);
1667                   for (i = 0; i < 3; i++)
1668                     {
1669                        xcb_get_atom_name_reply_t *reply;
1670                        char                      *name;
1671
1672                        reply = xcb_get_atom_name_reply(_ecore_xcb_conn, cookies[i], NULL);
1673                        if (reply && (ev->data.data32[i + 2]))
1674                          {
1675                             name = (char *)malloc(sizeof (char) * (reply->name_len + 1));
1676                             memcpy(name,
1677                                    xcb_get_atom_name_name(reply),
1678                                    reply->name_len);
1679                             name[reply->name_len] = '\0';
1680                             e->types[i] = name;
1681                          }
1682                        if (reply) free(reply);
1683                     }
1684                }
1685              e->num_types = i;
1686           }
1687
1688         e->win = target->win;
1689         e->source = target->source;
1690         ecore_event_add(ECORE_X_EVENT_XDND_ENTER, e, _ecore_x_event_free_xdnd_enter, NULL);
1691      }
1692
1693    /* Message Type: XdndPosition target */
1694    else if (ev->type == ECORE_X_ATOM_XDND_POSITION)
1695      {
1696         Ecore_X_Event_Xdnd_Position *e;
1697         Ecore_X_DND_Target          *target;
1698
1699         target = _ecore_x_dnd_target_get();
1700         if ((target->source != (Ecore_X_Window)ev->data.data32[0]) ||
1701             (target->win != ev->window))
1702           return;
1703
1704         target->pos.x = (int16_t)ev->data.data32[2] >> 16;
1705         target->pos.y = (int16_t)ev->data.data32[2] & 0xFFFFUL;
1706         target->action = ev->data.data32[4]; /* Version 2 */
1707
1708         target->time = (target->version >= 1) ?
1709            ev->data.data32[3] : XCB_CURRENT_TIME;
1710
1711         e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Position));
1712         if (!e) return;
1713         e->win = target->win;
1714         e->source = target->source;
1715         e->position.x = target->pos.x;
1716         e->position.y = target->pos.y;
1717         e->action = target->action;
1718         ecore_event_add(ECORE_X_EVENT_XDND_POSITION, e, NULL, NULL);
1719      }
1720
1721    /* Message Type: XdndStatus source */
1722    else if (ev->type == ECORE_X_ATOM_XDND_STATUS)
1723      {
1724         Ecore_X_Event_Xdnd_Status *e;
1725         Ecore_X_DND_Source        *source;
1726
1727         source = _ecore_x_dnd_source_get();
1728         /* Make sure source/target match */
1729         if ((source->win != ev->window ) ||
1730             (source->dest != ev->data.data32[0]))
1731           return;
1732
1733         source->await_status = 0;
1734
1735         source->will_accept = ev->data.data32[1] & 0x1UL;
1736         source->suppress = (ev->data.data32[1] & 0x2UL) ? 0 : 1;
1737
1738         source->rectangle.x = (int16_t)ev->data.data32[2] >> 16;
1739         source->rectangle.y = (int16_t)ev->data.data32[2] & 0xFFFFUL;
1740         source->rectangle.width = (uint16_t)ev->data.data32[3] >> 16;
1741         source->rectangle.height = (uint16_t)ev->data.data32[3] & 0xFFFFUL;
1742
1743         source->accepted_action = ev->data.data32[4];
1744
1745         e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Status));
1746         if (!e) return;
1747         e->win = source->win;
1748         e->target = source->dest;
1749         e->will_accept = source->will_accept;
1750         e->rectangle.x = source->rectangle.x;
1751         e->rectangle.y = source->rectangle.y;
1752         e->rectangle.width = source->rectangle.width;
1753         e->rectangle.height = source->rectangle.height;
1754         e->action = source->accepted_action;
1755
1756         ecore_event_add(ECORE_X_EVENT_XDND_STATUS, e, NULL, NULL);
1757      }
1758
1759    /* Message Type: XdndLeave target */
1760    /* Pretend the whole thing never happened, sort of */
1761    else if (ev->type == ECORE_X_ATOM_XDND_LEAVE)
1762      {
1763         Ecore_X_Event_Xdnd_Leave *e;
1764         Ecore_X_DND_Target       *target;
1765
1766         target = _ecore_x_dnd_target_get();
1767         if ((target->source != (Ecore_X_Window)ev->data.data32[0]) ||
1768             (target->win != ev->window))
1769           return;
1770
1771         target->state = ECORE_X_DND_TARGET_IDLE;
1772
1773         e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Leave));
1774         if (!e) return;
1775         e->win = ev->window;
1776         e->source = ev->data.data32[0];
1777         ecore_event_add(ECORE_X_EVENT_XDND_LEAVE, e, NULL, NULL);
1778      }
1779
1780    /* Message Type: XdndDrop target */
1781    else if (ev->type == ECORE_X_ATOM_XDND_DROP)
1782      {
1783         Ecore_X_Event_Xdnd_Drop *e;
1784         Ecore_X_DND_Target      *target;
1785
1786         target = _ecore_x_dnd_target_get();
1787         /* Match source/target */
1788         if ((target->source != (Ecore_X_Window)ev->data.data32[0]) ||
1789             (target->win != ev->window))
1790           return;
1791
1792         target->time = (target->version >= 1) ?
1793            ev->data.data32[2] : _ecore_xcb_event_last_time;
1794
1795         e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Drop));
1796         if (!e) return;
1797         e->win = target->win;
1798         e->source = target->source;
1799         e->action = target->action;
1800         e->position.x = target->pos.x;
1801         e->position.y = target->pos.y;
1802         ecore_event_add(ECORE_X_EVENT_XDND_DROP, e, NULL, NULL);
1803      }
1804
1805    /* Message Type: XdndFinished source */
1806    else if (ev->type == ECORE_X_ATOM_XDND_FINISHED)
1807      {
1808         Ecore_X_Event_Xdnd_Finished *e;
1809         Ecore_X_DND_Source          *source;
1810         uint8_t                        completed = 1;
1811
1812         source = _ecore_x_dnd_source_get();
1813         /* Match source/target */
1814         if ((source->win != ev->window) ||
1815             (source->dest != ev->data.data32[0]))
1816           return;
1817
1818         if ((source->version >= 5) && (ev->data.data32[1] & 0x1UL))
1819           {
1820              /* Target successfully performed drop action */
1821              ecore_x_selection_xdnd_clear();
1822              source->state = ECORE_X_DND_SOURCE_IDLE;
1823           }
1824         else
1825           {
1826                completed = 0;
1827                source->state = ECORE_X_DND_SOURCE_CONVERTING;
1828
1829                /* FIXME: Probably need to add a timer to switch back to idle
1830                 * and discard the selection data */
1831           }
1832
1833         e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Finished));
1834         if (!e) return;
1835         e->win = source->win;
1836         e->target = source->dest;
1837         e->completed = completed;
1838         if (source->version >= 5)
1839           {
1840              source->accepted_action = ev->data.data32[2];
1841              e->action = source->accepted_action;
1842           }
1843         else
1844           {
1845              source->accepted_action = 0;
1846              e->action = source->action;
1847           }
1848
1849         ecore_event_add(ECORE_X_EVENT_XDND_FINISHED, e, NULL, NULL);
1850      }
1851    else if (ev->type == ECORE_X_ATOM_NET_WM_STATE)
1852      {
1853         Ecore_X_Event_Window_State_Request *e;
1854
1855         e = calloc(1, sizeof(Ecore_X_Event_Window_State_Request));
1856         if (!e) return;
1857         e->win = ev->window;
1858         if (ev->data.data32[0] == 0)
1859           e->action = ECORE_X_WINDOW_STATE_ACTION_REMOVE;
1860         else if (ev->data.data32[0] == 1)
1861           e->action = ECORE_X_WINDOW_STATE_ACTION_ADD;
1862         else if (ev->data.data32[0] == 2)
1863           e->action = ECORE_X_WINDOW_STATE_ACTION_TOGGLE;
1864         else
1865           {
1866              free(e);
1867              return;
1868           }
1869         e->state[0] = _ecore_x_netwm_state_get(ev->data.data32[1]);
1870         if (e->state[0] == ECORE_X_WINDOW_STATE_UNKNOWN)
1871           {
1872              xcb_get_atom_name_reply_t *reply;
1873              char                      *name;
1874
1875              /* FIXME: round trip */
1876              reply = xcb_get_atom_name_reply(_ecore_xcb_conn,
1877                                              xcb_get_atom_name_unchecked(_ecore_xcb_conn, ev->data.data32[1]),
1878                                              NULL);
1879              if (reply)
1880                {
1881                  name = (char *)malloc(sizeof (char) * (reply->name_len + 1));
1882                  memcpy(name,
1883                         xcb_get_atom_name_name(reply),
1884                         reply->name_len);
1885                  name[reply->name_len] = '\0';
1886                  ERR("Unknown state: %s", name);
1887                  free(name);
1888                  free(reply);
1889                }
1890           }
1891         e->state[1] = _ecore_x_netwm_state_get(ev->data.data32[2]);
1892         if (e->state[1] == ECORE_X_WINDOW_STATE_UNKNOWN)
1893           {
1894              xcb_get_atom_name_reply_t *reply;
1895              char                      *name;
1896
1897              reply = xcb_get_atom_name_reply(_ecore_xcb_conn,
1898                                              xcb_get_atom_name_unchecked(_ecore_xcb_conn, ev->data.data32[2]),
1899                                              NULL);
1900              if (reply)
1901                {
1902                  name = (char *)malloc(sizeof (char) * (reply->name_len + 1));
1903                  memcpy(name,
1904                         xcb_get_atom_name_name(reply),
1905                         reply->name_len);
1906                  name[reply->name_len] = '\0';
1907                  WRN("Unknown state: %s", name);
1908                  free(name);
1909                }
1910           }
1911         e->source = ev->data.data32[3];
1912
1913         ecore_event_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, e, NULL, NULL);
1914      }
1915    else if ((ev->type == ECORE_X_ATOM_WM_CHANGE_STATE)
1916             && (ev->format == 32)
1917             && (ev->data.data32[0] == XCB_WM_HINT_STATE))
1918      {
1919         Ecore_X_Event_Window_State_Request *e;
1920
1921         e = calloc(1, sizeof(Ecore_X_Event_Window_State_Request));
1922         if (!e) return;
1923         e->win = ev->window;
1924         e->action = ECORE_X_WINDOW_STATE_ACTION_ADD;
1925         e->state[0] = ECORE_X_WINDOW_STATE_ICONIFIED;
1926
1927         ecore_event_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, e, NULL, NULL);
1928      }
1929    else if ((ev->type == ECORE_X_ATOM_NET_WM_DESKTOP)
1930             && (ev->format == 32))
1931      {
1932         Ecore_X_Event_Desktop_Change *e;
1933
1934         e = calloc(1, sizeof(Ecore_X_Event_Desktop_Change));
1935         if (!e) return;
1936         e->win = ev->window;
1937         e->desk = ev->data.data32[0];
1938         e->source = ev->data.data32[1];
1939
1940         ecore_event_add(ECORE_X_EVENT_DESKTOP_CHANGE, e, NULL, NULL);
1941      }
1942    else if ((ev->type == ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS))
1943      {
1944         Ecore_X_Event_Frame_Extents_Request *e;
1945
1946         e = calloc(1, sizeof(Ecore_X_Event_Frame_Extents_Request));
1947         if (!e) return;
1948         e->win = ev->window;
1949
1950         ecore_event_add(ECORE_X_EVENT_FRAME_EXTENTS_REQUEST, e, NULL, NULL);
1951      }
1952    else if ((ev->type == ECORE_X_ATOM_WM_PROTOCOLS)
1953             && ((Ecore_X_Atom)ev->data.data32[0] == ECORE_X_ATOM_NET_WM_PING)
1954             && (ev->format == 32))
1955      {
1956         Ecore_X_Event_Ping *e;
1957
1958         e = calloc(1, sizeof(Ecore_X_Event_Ping));
1959         if (!e) return;
1960         e->win = ev->window;
1961         e->time = ev->data.data32[1];
1962         e->event_win = ev->data.data32[2];
1963
1964         ecore_event_add(ECORE_X_EVENT_PING, e, NULL, NULL);
1965      }
1966    else if ((ev->type == ECORE_X_ATOM_NET_STARTUP_INFO_BEGIN) &&
1967             (ev->format == 8))
1968      {
1969         _ecore_x_netwm_startup_info_begin(ev->window, (char *)ev->data.data8);
1970      }
1971    else if ((ev->type == ECORE_X_ATOM_NET_STARTUP_INFO) &&
1972             (ev->format == 8))
1973      {
1974         _ecore_x_netwm_startup_info(ev->window, (char *)ev->data.data8);
1975      }
1976    else if ((ev->type == 27777)
1977             && (ev->data.data32[0] == 0x7162534)
1978             && (ev->format == 32)
1979             && (ev->window == _ecore_xcb_private_window))
1980      {
1981         /* a grab sync marker */
1982         if (ev->data.data32[1] == 0x10000001)
1983           _ecore_x_window_grab_remove(ev->data.data32[2]);
1984         else if (ev->data.data32[1] == 0x10000002)
1985           _ecore_x_key_grab_remove(ev->data.data32[2]);
1986      }
1987    else
1988      {
1989         Ecore_X_Event_Client_Message *e;
1990         int i;
1991
1992         e = calloc(1, sizeof(Ecore_X_Event_Client_Message));
1993         if (!e) return;
1994         e->win = ev->window;
1995         e->message_type = ev->type;
1996         e->format = ev->format;
1997         for (i = 0; i < 5; i++)
1998           e->data.l[i] = ev->data.data32[i];
1999
2000         ecore_event_add(ECORE_X_EVENT_CLIENT_MESSAGE, e, NULL, NULL);
2001      }
2002
2003    free(event);
2004 }
2005
2006 void
2007 _ecore_x_event_handle_mapping_notify(xcb_generic_event_t *event)
2008 {
2009    /* FIXME: handle this event type */
2010
2011    free(event);
2012 }
2013
2014 void
2015 _ecore_x_event_handle_shape_change(xcb_generic_event_t *event)
2016 {
2017 #ifdef ECORE_X_SHAPE
2018    xcb_shape_notify_event_t     *ev;
2019    Ecore_X_Event_Window_Shape *e;
2020
2021    ev = (xcb_shape_notify_event_t *)event;
2022    e = calloc(1, sizeof(Ecore_X_Event_Window_Shape));
2023    if (!e) return;
2024    e->win = ev->affected_window;
2025    e->time = ev->server_time;
2026    ecore_event_add(ECORE_X_EVENT_WINDOW_SHAPE, e, NULL, NULL);
2027 #endif /* ECORE_X_SHAPE */
2028
2029    free(event);
2030 }
2031
2032 void
2033 _ecore_x_event_handle_screensaver_notify(xcb_generic_event_t *event)
2034 {
2035 #ifdef ECORE_X_SCREENSAVER
2036    xcb_screensaver_notify_event_t     *ev;
2037    Ecore_X_Event_Screensaver_Notify *e;
2038
2039    ev = (xcb_screensaver_notify_event_t *)event;
2040    e = calloc(1, sizeof(Ecore_X_Event_Screensaver_Notify));
2041    if (!e) return;
2042    e->win = ev->window;
2043    if (ev->state == XCB_SCREENSAVER_STATE_ON)
2044      e->on = 1;
2045    else
2046      e->on = 0;
2047    e->time = ev->time;
2048    ecore_event_add(ECORE_X_EVENT_SCREENSAVER_NOTIFY, e, NULL, NULL);
2049 #endif /* ECORE_X_SCREENSAVER */
2050
2051    free(event);
2052 }
2053
2054 void
2055 _ecore_x_event_handle_sync_counter(xcb_generic_event_t *event)
2056 {
2057 #ifdef ECORE_X_SYNC
2058    xcb_sync_counter_notify_event_t *ev;
2059    Ecore_X_Event_Sync_Counter    *e;
2060
2061    ev = (xcb_sync_counter_notify_event_t *)event;
2062    e = calloc(1, sizeof(Ecore_X_Event_Sync_Counter));
2063    if (!e) return;
2064    e->time = ev->timestamp;
2065    ecore_event_add(ECORE_X_EVENT_SYNC_COUNTER, e, NULL, NULL);
2066 #endif /* ECORE_X_SYNC */
2067
2068    free(event);
2069 }
2070
2071 void
2072 _ecore_x_event_handle_sync_alarm(xcb_generic_event_t *event)
2073 {
2074 #ifdef ECORE_X_SYNC
2075    xcb_sync_alarm_notify_event_t *ev;
2076    Ecore_X_Event_Sync_Alarm    *e;
2077
2078    ev = (xcb_sync_alarm_notify_event_t *)event;
2079    e = calloc(1, sizeof(Ecore_X_Event_Sync_Alarm));
2080    if (!e) return;
2081    e->time = ev->timestamp;
2082    e->alarm = ev->alarm;
2083    ecore_event_add(ECORE_X_EVENT_SYNC_ALARM, e, NULL, NULL);
2084 #endif /* ECORE_X_SYNC */
2085
2086    free(event);
2087 }
2088
2089 /* FIXME: round trip */
2090 void
2091 _ecore_x_event_handle_randr_change(xcb_generic_event_t *event)
2092 {
2093 #ifdef ECORE_X_RANDR
2094    xcb_randr_screen_change_notify_event_t *ev;
2095    Ecore_X_Event_Screen_Change            *e;
2096
2097    ev = (xcb_randr_screen_change_notify_event_t *)event;
2098
2099    if ((ev->response_type & ~0x80) != XCB_CONFIGURE_NOTIFY)
2100      {
2101        xcb_query_extension_reply_t *rep;
2102
2103        rep = xcb_query_extension_reply(_ecore_xcb_conn,
2104                                        xcb_query_extension_unchecked(_ecore_xcb_conn,
2105                                                                      strlen("randr"),
2106                                                                      "randr"),
2107                                        NULL);
2108
2109      if ((!rep) ||
2110          (((ev->response_type & ~0x80) - rep->first_event) != XCB_RANDR_SCREEN_CHANGE_NOTIFY))
2111        WRN("ERROR: Can't update RandR config!");
2112      if (rep)
2113        free(rep);
2114      }
2115
2116    e = calloc(1, sizeof(Ecore_X_Event_Screen_Change));
2117    if (!e) return;
2118    e->win = ev->request_window;
2119    e->root = ev->root;
2120    e->width = ev->width;
2121    e->height = ev->height;
2122    ecore_event_add(ECORE_X_EVENT_SCREEN_CHANGE, e, NULL, NULL);
2123 #endif /* ECORE_X_RANDR */
2124
2125    free(event);
2126 }
2127
2128 void
2129 _ecore_x_event_handle_fixes_selection_notify(xcb_generic_event_t *event)
2130 {
2131 #ifdef ECORE_X_FIXES
2132    /* Nothing here yet */
2133 #endif /* ECORE_X_FIXES */
2134
2135    free(event);
2136 }
2137
2138 void
2139 _ecore_x_event_handle_damage_notify(xcb_generic_event_t *event)
2140 {
2141 #ifdef ECORE_XCBDAMAGE
2142    xcb_damage_notify_event_t *ev;
2143    Ecore_X_Event_Damage      *e;
2144
2145    ev = (xcb_damage_notify_event_t *)event;
2146    e = calloc(1, sizeof(Ecore_X_Event_Damage));
2147    if (!e) return;
2148
2149    e->level = ev->level;
2150    e->drawable = ev->drawable;
2151    e->damage = ev->damage;
2152    /* FIXME: XCB has no 'more' member in xcb_damage_notify_event_t */
2153 /*    e->more = ev->more; */
2154    e->time = ev->timestamp;
2155    e->area.x = ev->area.x;
2156    e->area.y = ev->area.y;
2157    e->area.width = ev->area.width;
2158    e->area.height = ev->area.height;
2159    e->geometry.x = ev->geometry.x;
2160    e->geometry.y = ev->geometry.y;
2161    e->geometry.width = ev->geometry.width;
2162    e->geometry.height = ev->geometry.height;
2163
2164    ecore_event_add(ECORE_X_EVENT_DAMAGE_NOTIFY, e, NULL, NULL);
2165 #endif /* ECORE_XCBDAMAGE */
2166
2167    free(event);
2168 }