]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdevicemanager-core.c
[introspection] add transfer none annotation to gdk_keyval_name return
[~andy/gtk] / gdk / x11 / gdkdevicemanager-core.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include "gdkdevicemanager-core.h"
23
24 #include "gdktypes.h"
25 #include "gdkdevicemanager.h"
26 #include "gdkeventtranslator.h"
27 #include "gdkdevice-core.h"
28 #include "gdkkeysyms.h"
29 #include "gdkprivate-x11.h"
30 #include "gdkx.h"
31
32 #ifdef HAVE_XKB
33 #include <X11/XKBlib.h>
34 #endif
35
36
37 #define HAS_FOCUS(toplevel)                           \
38   ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
39
40 static void    gdk_device_manager_core_finalize    (GObject *object);
41 static void    gdk_device_manager_core_constructed (GObject *object);
42
43 static GList * gdk_device_manager_core_list_devices (GdkDeviceManager *device_manager,
44                                                      GdkDeviceType     type);
45 static GdkDevice * gdk_device_manager_core_get_client_pointer (GdkDeviceManager *device_manager);
46
47 static void     gdk_device_manager_event_translator_init (GdkEventTranslatorIface *iface);
48
49 static gboolean gdk_device_manager_core_translate_event  (GdkEventTranslator *translator,
50                                                           GdkDisplay         *display,
51                                                           GdkEvent           *event,
52                                                           XEvent             *xevent);
53
54
55 G_DEFINE_TYPE_WITH_CODE (GdkDeviceManagerCore, gdk_device_manager_core, GDK_TYPE_DEVICE_MANAGER,
56                          G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
57                                                 gdk_device_manager_event_translator_init))
58
59 static void
60 gdk_device_manager_core_class_init (GdkDeviceManagerCoreClass *klass)
61 {
62   GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
63   GObjectClass *object_class = G_OBJECT_CLASS (klass);
64
65   object_class->finalize = gdk_device_manager_core_finalize;
66   object_class->constructed = gdk_device_manager_core_constructed;
67   device_manager_class->list_devices = gdk_device_manager_core_list_devices;
68   device_manager_class->get_client_pointer = gdk_device_manager_core_get_client_pointer;
69 }
70
71 static void
72 gdk_device_manager_event_translator_init (GdkEventTranslatorIface *iface)
73 {
74   iface->translate_event = gdk_device_manager_core_translate_event;
75 }
76
77 static GdkDevice *
78 create_core_pointer (GdkDeviceManager *device_manager,
79                      GdkDisplay       *display)
80 {
81   return g_object_new (GDK_TYPE_DEVICE_CORE,
82                        "name", "Core Pointer",
83                        "type", GDK_DEVICE_TYPE_MASTER,
84                        "input-source", GDK_SOURCE_MOUSE,
85                        "input-mode", GDK_MODE_SCREEN,
86                        "has-cursor", TRUE,
87                        "display", display,
88                        "device-manager", device_manager,
89                        NULL);
90 }
91
92 static GdkDevice *
93 create_core_keyboard (GdkDeviceManager *device_manager,
94                       GdkDisplay       *display)
95 {
96   return g_object_new (GDK_TYPE_DEVICE_CORE,
97                        "name", "Core Keyboard",
98                        "type", GDK_DEVICE_TYPE_MASTER,
99                        "input-source", GDK_SOURCE_KEYBOARD,
100                        "input-mode", GDK_MODE_SCREEN,
101                        "has-cursor", FALSE,
102                        "display", display,
103                        "device-manager", device_manager,
104                        NULL);
105 }
106
107 static void
108 gdk_device_manager_core_init (GdkDeviceManagerCore *device_manager)
109 {
110 }
111
112 static void
113 gdk_device_manager_core_finalize (GObject *object)
114 {
115   GdkDeviceManagerCore *device_manager_core;
116
117   device_manager_core = GDK_DEVICE_MANAGER_CORE (object);
118
119   g_object_unref (device_manager_core->core_pointer);
120   g_object_unref (device_manager_core->core_keyboard);
121
122   G_OBJECT_CLASS (gdk_device_manager_core_parent_class)->finalize (object);
123 }
124
125 static void
126 gdk_device_manager_core_constructed (GObject *object)
127 {
128   GdkDeviceManagerCore *device_manager;
129   GdkDisplay *display;
130
131   device_manager = GDK_DEVICE_MANAGER_CORE (object);
132   display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (object));
133   device_manager->core_pointer = create_core_pointer (GDK_DEVICE_MANAGER (device_manager), display);
134   device_manager->core_keyboard = create_core_keyboard (GDK_DEVICE_MANAGER (device_manager), display);
135
136   _gdk_device_set_associated_device (device_manager->core_pointer, device_manager->core_keyboard);
137   _gdk_device_set_associated_device (device_manager->core_keyboard, device_manager->core_pointer);
138 }
139
140 static void
141 translate_key_event (GdkDisplay           *display,
142                      GdkDeviceManagerCore *device_manager,
143                      GdkEvent             *event,
144                      XEvent               *xevent)
145 {
146   GdkKeymap *keymap = gdk_keymap_get_for_display (display);
147   GdkModifierType consumed, state;
148   gunichar c = 0;
149   gchar buf[7];
150
151   event->key.type = xevent->xany.type == KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
152   event->key.time = xevent->xkey.time;
153   gdk_event_set_device (event, device_manager->core_keyboard);
154
155   event->key.state = (GdkModifierType) xevent->xkey.state;
156   event->key.group = _gdk_x11_get_group_for_state (display, xevent->xkey.state);
157   event->key.hardware_keycode = xevent->xkey.keycode;
158
159   event->key.keyval = GDK_KEY_VoidSymbol;
160
161   gdk_keymap_translate_keyboard_state (keymap,
162                                        event->key.hardware_keycode,
163                                        event->key.state,
164                                        event->key.group,
165                                        &event->key.keyval,
166                                        NULL, NULL, &consumed);
167
168   state = event->key.state & ~consumed;
169   _gdk_keymap_add_virtual_modifiers_compat (keymap, &state);
170   event->key.state |= state;
171
172   event->key.is_modifier = _gdk_keymap_key_is_modifier (keymap, event->key.hardware_keycode);
173
174   /* Fill in event->string crudely, since various programs
175    * depend on it.
176    */
177   event->key.string = NULL;
178
179   if (event->key.keyval != GDK_KEY_VoidSymbol)
180     c = gdk_keyval_to_unicode (event->key.keyval);
181
182   if (c)
183     {
184       gsize bytes_written;
185       gint len;
186
187       /* Apply the control key - Taken from Xlib
188        */
189       if (event->key.state & GDK_CONTROL_MASK)
190         {
191           if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
192           else if (c == '2')
193             {
194               event->key.string = g_memdup ("\0\0", 2);
195               event->key.length = 1;
196               buf[0] = '\0';
197               goto out;
198             }
199           else if (c >= '3' && c <= '7') c -= ('3' - '\033');
200           else if (c == '8') c = '\177';
201           else if (c == '/') c = '_' & 0x1F;
202         }
203
204       len = g_unichar_to_utf8 (c, buf);
205       buf[len] = '\0';
206
207       event->key.string = g_locale_from_utf8 (buf, len,
208                                               NULL, &bytes_written,
209                                               NULL);
210       if (event->key.string)
211         event->key.length = bytes_written;
212     }
213   else if (event->key.keyval == GDK_KEY_Escape)
214     {
215       event->key.length = 1;
216       event->key.string = g_strdup ("\033");
217     }
218   else if (event->key.keyval == GDK_KEY_Return ||
219           event->key.keyval == GDK_KEY_KP_Enter)
220     {
221       event->key.length = 1;
222       event->key.string = g_strdup ("\r");
223     }
224
225   if (!event->key.string)
226     {
227       event->key.length = 0;
228       event->key.string = g_strdup ("");
229     }
230
231  out:
232 #ifdef G_ENABLE_DEBUG
233   if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
234     {
235       g_message ("%s:\t\twindow: %ld     key: %12s  %d",
236                  event->type == GDK_KEY_PRESS ? "key press  " : "key release",
237                  xevent->xkey.window,
238                  event->key.keyval ? gdk_keyval_name (event->key.keyval) : "(none)",
239                  event->key.keyval);
240
241       if (event->key.length > 0)
242         g_message ("\t\tlength: %4d string: \"%s\"",
243                    event->key.length, buf);
244     }
245 #endif /* G_ENABLE_DEBUG */
246   return;
247 }
248
249 #ifdef G_ENABLE_DEBUG
250 static const char notify_modes[][19] = {
251   "NotifyNormal",
252   "NotifyGrab",
253   "NotifyUngrab",
254   "NotifyWhileGrabbed"
255 };
256
257 static const char notify_details[][23] = {
258   "NotifyAncestor",
259   "NotifyVirtual",
260   "NotifyInferior",
261   "NotifyNonlinear",
262   "NotifyNonlinearVirtual",
263   "NotifyPointer",
264   "NotifyPointerRoot",
265   "NotifyDetailNone"
266 };
267 #endif
268
269 static void
270 set_user_time (GdkWindow *window,
271                GdkEvent  *event)
272 {
273   g_return_if_fail (event != NULL);
274
275   window = gdk_window_get_toplevel (event->client.window);
276   g_return_if_fail (GDK_IS_WINDOW (window));
277
278   /* If an event doesn't have a valid timestamp, we shouldn't use it
279    * to update the latest user interaction time.
280    */
281   if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
282     gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
283                                   gdk_event_get_time (event));
284 }
285
286 static void
287 generate_focus_event (GdkDeviceManagerCore *device_manager,
288                       GdkWindow            *window,
289                       gboolean              in)
290 {
291   GdkEvent *event;
292
293   event = gdk_event_new (GDK_FOCUS_CHANGE);
294   event->focus_change.window = g_object_ref (window);
295   event->focus_change.send_event = FALSE;
296   event->focus_change.in = in;
297   gdk_event_set_device (event, device_manager->core_keyboard);
298
299   gdk_event_put (event);
300   gdk_event_free (event);
301 }
302
303 static gboolean
304 set_screen_from_root (GdkDisplay *display,
305                       GdkEvent   *event,
306                       Window      xrootwin)
307 {
308   GdkScreen *screen;
309
310   screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
311
312   if (screen)
313     {
314       gdk_event_set_screen (event, screen);
315
316       return TRUE;
317     }
318
319   return FALSE;
320 }
321
322 static GdkCrossingMode
323 translate_crossing_mode (int mode)
324 {
325   switch (mode)
326     {
327     case NotifyNormal:
328       return GDK_CROSSING_NORMAL;
329     case NotifyGrab:
330       return GDK_CROSSING_GRAB;
331     case NotifyUngrab:
332       return GDK_CROSSING_UNGRAB;
333     default:
334       g_assert_not_reached ();
335     }
336 }
337
338 static GdkNotifyType
339 translate_notify_type (int detail)
340 {
341   switch (detail)
342     {
343     case NotifyInferior:
344       return GDK_NOTIFY_INFERIOR;
345     case NotifyAncestor:
346       return GDK_NOTIFY_ANCESTOR;
347     case NotifyVirtual:
348       return GDK_NOTIFY_VIRTUAL;
349     case NotifyNonlinear:
350       return GDK_NOTIFY_NONLINEAR;
351     case NotifyNonlinearVirtual:
352       return GDK_NOTIFY_NONLINEAR_VIRTUAL;
353     default:
354       g_assert_not_reached ();
355     }
356 }
357
358 static gboolean
359 is_parent_of (GdkWindow *parent,
360               GdkWindow *child)
361 {
362   GdkWindow *w;
363
364   w = child;
365   while (w != NULL)
366     {
367       if (w == parent)
368         return TRUE;
369
370       w = gdk_window_get_parent (w);
371     }
372
373   return FALSE;
374 }
375
376 static GdkWindow *
377 get_event_window (GdkEventTranslator *translator,
378                   XEvent             *xevent)
379 {
380   GdkDeviceManager *device_manager;
381   GdkDisplay *display;
382   GdkWindow *window;
383
384   device_manager = GDK_DEVICE_MANAGER (translator);
385   display = gdk_device_manager_get_display (device_manager);
386   window = gdk_window_lookup_for_display (display, xevent->xany.window);
387
388   /* Apply keyboard grabs to non-native windows */
389   if (xevent->type == KeyPress || xevent->type == KeyRelease)
390     {
391       GdkDeviceGrabInfo *info;
392       gulong serial;
393
394       serial = _gdk_windowing_window_get_next_serial (display);
395       info = _gdk_display_has_device_grab (display,
396                                            GDK_DEVICE_MANAGER_CORE (device_manager)->core_keyboard,
397                                            serial);
398       if (info &&
399           (!is_parent_of (info->window, window) ||
400            !info->owner_events))
401         {
402           /* Report key event against grab window */
403           window = info->window;
404         }
405     }
406
407   return window;
408 }
409
410 static gboolean
411 gdk_device_manager_core_translate_event (GdkEventTranslator *translator,
412                                          GdkDisplay         *display,
413                                          GdkEvent           *event,
414                                          XEvent             *xevent)
415 {
416   GdkDeviceManagerCore *device_manager;
417   GdkWindow *window;
418   GdkWindowObject *window_private;
419   GdkWindowImplX11 *window_impl = NULL;
420   gboolean return_val;
421   GdkToplevelX11 *toplevel = NULL;
422   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
423
424   device_manager = GDK_DEVICE_MANAGER_CORE (translator);
425   return_val = FALSE;
426
427   window = get_event_window (translator, xevent);
428   window_private = (GdkWindowObject *) window;
429
430   if (window)
431     {
432       if (GDK_WINDOW_DESTROYED (window) || !GDK_IS_WINDOW (window))
433         return FALSE;
434
435       toplevel = _gdk_x11_window_get_toplevel (window);
436       window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
437       g_object_ref (window);
438     }
439
440   event->any.window = window;
441   event->any.send_event = xevent->xany.send_event ? TRUE : FALSE;
442
443   if (window_private && GDK_WINDOW_DESTROYED (window))
444     {
445       if (xevent->type != DestroyNotify)
446         {
447           return_val = FALSE;
448           goto done;
449         }
450     }
451
452   if (window &&
453       (xevent->type == MotionNotify ||
454        xevent->type == ButtonRelease))
455     {
456       if (_gdk_moveresize_handle_event (xevent))
457         {
458           return_val = FALSE;
459           goto done;
460         }
461     }
462
463   /* We do a "manual" conversion of the XEvent to a
464    *  GdkEvent. The structures are mostly the same so
465    *  the conversion is fairly straightforward. We also
466    *  optionally print debugging info regarding events
467    *  received.
468    */
469
470   return_val = TRUE;
471
472   switch (xevent->type)
473     {
474     case KeyPress:
475       if (window_private == NULL)
476         {
477           return_val = FALSE;
478           break;
479         }
480       translate_key_event (display, device_manager, event, xevent);
481       set_user_time (window, event);
482       break;
483
484     case KeyRelease:
485       if (window_private == NULL)
486         {
487           return_val = FALSE;
488           break;
489         }
490
491       /* Emulate detectable auto-repeat by checking to see
492        * if the next event is a key press with the same
493        * keycode and timestamp, and if so, ignoring the event.
494        */
495
496       if (!display_x11->have_xkb_autorepeat && XPending (xevent->xkey.display))
497         {
498           XEvent next_event;
499
500           XPeekEvent (xevent->xkey.display, &next_event);
501
502           if (next_event.type == KeyPress &&
503               next_event.xkey.keycode == xevent->xkey.keycode &&
504               next_event.xkey.time == xevent->xkey.time)
505             {
506               return_val = FALSE;
507               break;
508             }
509         }
510
511       translate_key_event (display, device_manager, event, xevent);
512       break;
513
514     case ButtonPress:
515       GDK_NOTE (EVENTS,
516                 g_message ("button press:\t\twindow: %ld  x,y: %d %d  button: %d",
517                            xevent->xbutton.window,
518                            xevent->xbutton.x, xevent->xbutton.y,
519                            xevent->xbutton.button));
520
521       if (window_private == NULL)
522         {
523           return_val = FALSE;
524           break;
525         }
526
527       /* If we get a ButtonPress event where the button is 4 or 5,
528          it's a Scroll event */
529       switch (xevent->xbutton.button)
530         {
531         case 4: /* up */
532         case 5: /* down */
533         case 6: /* left */
534         case 7: /* right */
535           event->scroll.type = GDK_SCROLL;
536
537           if (xevent->xbutton.button == 4)
538             event->scroll.direction = GDK_SCROLL_UP;
539           else if (xevent->xbutton.button == 5)
540             event->scroll.direction = GDK_SCROLL_DOWN;
541           else if (xevent->xbutton.button == 6)
542             event->scroll.direction = GDK_SCROLL_LEFT;
543           else
544             event->scroll.direction = GDK_SCROLL_RIGHT;
545
546           event->scroll.window = window;
547           event->scroll.time = xevent->xbutton.time;
548           event->scroll.x = (gdouble) xevent->xbutton.x;
549           event->scroll.y = (gdouble) xevent->xbutton.y;
550           event->scroll.x_root = (gdouble) xevent->xbutton.x_root;
551           event->scroll.y_root = (gdouble) xevent->xbutton.y_root;
552           event->scroll.state = (GdkModifierType) xevent->xbutton.state;
553           event->scroll.device = device_manager->core_pointer;
554
555           if (!set_screen_from_root (display, event, xevent->xbutton.root))
556             {
557               return_val = FALSE;
558               break;
559             }
560
561           break;
562
563         default:
564           event->button.type = GDK_BUTTON_PRESS;
565           event->button.window = window;
566           event->button.time = xevent->xbutton.time;
567           event->button.x = (gdouble) xevent->xbutton.x;
568           event->button.y = (gdouble) xevent->xbutton.y;
569           event->button.x_root = (gdouble) xevent->xbutton.x_root;
570           event->button.y_root = (gdouble) xevent->xbutton.y_root;
571           event->button.axes = NULL;
572           event->button.state = (GdkModifierType) xevent->xbutton.state;
573           event->button.button = xevent->xbutton.button;
574           event->button.device = device_manager->core_pointer;
575
576           if (!set_screen_from_root (display, event, xevent->xbutton.root))
577             return_val = FALSE;
578
579           break;
580         }
581
582       set_user_time (window, event);
583
584       break;
585
586     case ButtonRelease:
587       GDK_NOTE (EVENTS,
588                 g_message ("button release:\twindow: %ld  x,y: %d %d  button: %d",
589                            xevent->xbutton.window,
590                            xevent->xbutton.x, xevent->xbutton.y,
591                            xevent->xbutton.button));
592
593       if (window_private == NULL)
594         {
595           return_val = FALSE;
596           break;
597         }
598
599       /* We treat button presses as scroll wheel events, so ignore the release */
600       if (xevent->xbutton.button == 4 || xevent->xbutton.button == 5 ||
601           xevent->xbutton.button == 6 || xevent->xbutton.button == 7)
602         {
603           return_val = FALSE;
604           break;
605         }
606
607       event->button.type = GDK_BUTTON_RELEASE;
608       event->button.window = window;
609       event->button.time = xevent->xbutton.time;
610       event->button.x = (gdouble) xevent->xbutton.x;
611       event->button.y = (gdouble) xevent->xbutton.y;
612       event->button.x_root = (gdouble) xevent->xbutton.x_root;
613       event->button.y_root = (gdouble) xevent->xbutton.y_root;
614       event->button.axes = NULL;
615       event->button.state = (GdkModifierType) xevent->xbutton.state;
616       event->button.button = xevent->xbutton.button;
617       event->button.device = device_manager->core_pointer;
618
619       if (!set_screen_from_root (display, event, xevent->xbutton.root))
620         return_val = FALSE;
621
622       break;
623
624     case MotionNotify:
625       GDK_NOTE (EVENTS,
626                 g_message ("motion notify:\t\twindow: %ld  x,y: %d %d  hint: %s",
627                            xevent->xmotion.window,
628                            xevent->xmotion.x, xevent->xmotion.y,
629                            (xevent->xmotion.is_hint) ? "true" : "false"));
630
631       if (window_private == NULL)
632         {
633           return_val = FALSE;
634           break;
635         }
636
637       event->motion.type = GDK_MOTION_NOTIFY;
638       event->motion.window = window;
639       event->motion.time = xevent->xmotion.time;
640       event->motion.x = (gdouble) xevent->xmotion.x;
641       event->motion.y = (gdouble) xevent->xmotion.y;
642       event->motion.x_root = (gdouble) xevent->xmotion.x_root;
643       event->motion.y_root = (gdouble) xevent->xmotion.y_root;
644       event->motion.axes = NULL;
645       event->motion.state = (GdkModifierType) xevent->xmotion.state;
646       event->motion.is_hint = xevent->xmotion.is_hint;
647       event->motion.device = device_manager->core_pointer;
648
649       if (!set_screen_from_root (display, event, xevent->xbutton.root))
650         {
651           return_val = FALSE;
652           break;
653         }
654
655       break;
656
657     case EnterNotify:
658       GDK_NOTE (EVENTS,
659                 g_message ("enter notify:\t\twindow: %ld  detail: %d subwin: %ld",
660                            xevent->xcrossing.window,
661                            xevent->xcrossing.detail,
662                            xevent->xcrossing.subwindow));
663
664       if (window_private == NULL)
665         {
666           return_val = FALSE;
667           break;
668         }
669
670       if (!set_screen_from_root (display, event, xevent->xbutton.root))
671         {
672           return_val = FALSE;
673           break;
674         }
675
676       event->crossing.type = GDK_ENTER_NOTIFY;
677       event->crossing.window = window;
678       gdk_event_set_device (event, device_manager->core_pointer);
679
680       /* If the subwindow field of the XEvent is non-NULL, then
681        *  lookup the corresponding GdkWindow.
682        */
683       if (xevent->xcrossing.subwindow != None)
684         event->crossing.subwindow = gdk_window_lookup_for_display (display, xevent->xcrossing.subwindow);
685       else
686         event->crossing.subwindow = NULL;
687
688       event->crossing.time = xevent->xcrossing.time;
689       event->crossing.x = (gdouble) xevent->xcrossing.x;
690       event->crossing.y = (gdouble) xevent->xcrossing.y;
691       event->crossing.x_root = (gdouble) xevent->xcrossing.x_root;
692       event->crossing.y_root = (gdouble) xevent->xcrossing.y_root;
693
694       event->crossing.mode = translate_crossing_mode (xevent->xcrossing.mode);
695       event->crossing.detail = translate_notify_type (xevent->xcrossing.detail);
696
697       event->crossing.focus = xevent->xcrossing.focus;
698       event->crossing.state = xevent->xcrossing.state;
699
700       break;
701
702     case LeaveNotify:
703       GDK_NOTE (EVENTS,
704                 g_message ("leave notify:\t\twindow: %ld  detail: %d subwin: %ld",
705                            xevent->xcrossing.window,
706                            xevent->xcrossing.detail, xevent->xcrossing.subwindow));
707
708       if (window_private == NULL)
709         {
710           return_val = FALSE;
711           break;
712         }
713
714       if (!set_screen_from_root (display, event, xevent->xbutton.root))
715         {
716           return_val = FALSE;
717           break;
718         }
719
720       event->crossing.type = GDK_LEAVE_NOTIFY;
721       event->crossing.window = window;
722       gdk_event_set_device (event, device_manager->core_pointer);
723
724       /* If the subwindow field of the XEvent is non-NULL, then
725        *  lookup the corresponding GdkWindow.
726        */
727       if (xevent->xcrossing.subwindow != None)
728         event->crossing.subwindow = gdk_window_lookup_for_display (display, xevent->xcrossing.subwindow);
729       else
730         event->crossing.subwindow = NULL;
731
732       event->crossing.time = xevent->xcrossing.time;
733       event->crossing.x = (gdouble) xevent->xcrossing.x;
734       event->crossing.y = (gdouble) xevent->xcrossing.y;
735       event->crossing.x_root = (gdouble) xevent->xcrossing.x_root;
736       event->crossing.y_root = (gdouble) xevent->xcrossing.y_root;
737
738       event->crossing.mode = translate_crossing_mode (xevent->xcrossing.mode);
739       event->crossing.detail = translate_notify_type (xevent->xcrossing.detail);
740
741       event->crossing.focus = xevent->xcrossing.focus;
742       event->crossing.state = xevent->xcrossing.state;
743
744       break;
745
746       /* We only care about focus events that indicate that _this_
747        * window (not a ancestor or child) got or lost the focus
748        */
749     case FocusIn:
750       GDK_NOTE (EVENTS,
751                 g_message ("focus in:\t\twindow: %ld, detail: %s, mode: %s",
752                            xevent->xfocus.window,
753                            notify_details[xevent->xfocus.detail],
754                            notify_modes[xevent->xfocus.mode]));
755
756       if (toplevel)
757         {
758           gboolean had_focus = HAS_FOCUS (toplevel);
759
760           switch (xevent->xfocus.detail)
761             {
762             case NotifyAncestor:
763             case NotifyVirtual:
764               /* When the focus moves from an ancestor of the window to
765                * the window or a descendent of the window, *and* the
766                * pointer is inside the window, then we were previously
767                * receiving keystroke events in the has_pointer_focus
768                * case and are now receiving them in the
769                * has_focus_window case.
770                */
771               if (toplevel->has_pointer &&
772                   xevent->xfocus.mode != NotifyGrab &&
773                   xevent->xfocus.mode != NotifyUngrab)
774                 toplevel->has_pointer_focus = FALSE;
775
776               /* fall through */
777             case NotifyNonlinear:
778             case NotifyNonlinearVirtual:
779               if (xevent->xfocus.mode != NotifyGrab &&
780                   xevent->xfocus.mode != NotifyUngrab)
781                 toplevel->has_focus_window = TRUE;
782               /* We pretend that the focus moves to the grab
783                * window, so we pay attention to NotifyGrab
784                * NotifyUngrab, and ignore NotifyWhileGrabbed
785                */
786               if (xevent->xfocus.mode != NotifyWhileGrabbed)
787                 toplevel->has_focus = TRUE;
788               break;
789             case NotifyPointer:
790               /* The X server sends NotifyPointer/NotifyGrab,
791                * but the pointer focus is ignored while a
792                * grab is in effect
793                */
794               if (xevent->xfocus.mode != NotifyGrab &&
795                   xevent->xfocus.mode != NotifyUngrab)
796                 toplevel->has_pointer_focus = TRUE;
797               break;
798             case NotifyInferior:
799             case NotifyPointerRoot:
800             case NotifyDetailNone:
801               break;
802             }
803
804           if (HAS_FOCUS (toplevel) != had_focus)
805             generate_focus_event (device_manager, window, TRUE);
806         }
807       break;
808     case FocusOut:
809       GDK_NOTE (EVENTS,
810                 g_message ("focus out:\t\twindow: %ld, detail: %s, mode: %s",
811                            xevent->xfocus.window,
812                            notify_details[xevent->xfocus.detail],
813                            notify_modes[xevent->xfocus.mode]));
814
815       if (toplevel)
816         {
817           gboolean had_focus = HAS_FOCUS (toplevel);
818
819           switch (xevent->xfocus.detail)
820             {
821             case NotifyAncestor:
822             case NotifyVirtual:
823               /* When the focus moves from the window or a descendent
824                * of the window to an ancestor of the window, *and* the
825                * pointer is inside the window, then we were previously
826                * receiving keystroke events in the has_focus_window
827                * case and are now receiving them in the
828                * has_pointer_focus case.
829                */
830               if (toplevel->has_pointer &&
831                   xevent->xfocus.mode != NotifyGrab &&
832                   xevent->xfocus.mode != NotifyUngrab)
833                 toplevel->has_pointer_focus = TRUE;
834
835               /* fall through */
836             case NotifyNonlinear:
837             case NotifyNonlinearVirtual:
838               if (xevent->xfocus.mode != NotifyGrab &&
839                   xevent->xfocus.mode != NotifyUngrab)
840                 toplevel->has_focus_window = FALSE;
841               if (xevent->xfocus.mode != NotifyWhileGrabbed)
842                 toplevel->has_focus = FALSE;
843               break;
844             case NotifyPointer:
845               if (xevent->xfocus.mode != NotifyGrab &&
846                   xevent->xfocus.mode != NotifyUngrab)
847                 toplevel->has_pointer_focus = FALSE;
848             break;
849             case NotifyInferior:
850             case NotifyPointerRoot:
851             case NotifyDetailNone:
852               break;
853             }
854
855           if (HAS_FOCUS (toplevel) != had_focus)
856             generate_focus_event (device_manager, window, FALSE);
857         }
858       break;
859
860     default:
861         return_val = FALSE;
862     }
863
864  done:
865   if (return_val)
866     {
867       if (event->any.window)
868         g_object_ref (event->any.window);
869
870       if (((event->any.type == GDK_ENTER_NOTIFY) ||
871            (event->any.type == GDK_LEAVE_NOTIFY)) &&
872           (event->crossing.subwindow != NULL))
873         g_object_ref (event->crossing.subwindow);
874     }
875   else
876     {
877       /* Mark this event as having no resources to be freed */
878       event->any.window = NULL;
879       event->any.type = GDK_NOTHING;
880     }
881
882   if (window)
883     g_object_unref (window);
884
885   return return_val;
886 }
887
888 static GList *
889 gdk_device_manager_core_list_devices (GdkDeviceManager *device_manager,
890                                       GdkDeviceType     type)
891 {
892   GdkDeviceManagerCore *device_manager_core;
893   GList *devices = NULL;
894
895   if (type == GDK_DEVICE_TYPE_MASTER)
896     {
897       device_manager_core = (GdkDeviceManagerCore *) device_manager;
898       devices = g_list_prepend (devices, device_manager_core->core_keyboard);
899       devices = g_list_prepend (devices, device_manager_core->core_pointer);
900     }
901
902   return devices;
903 }
904
905 static GdkDevice *
906 gdk_device_manager_core_get_client_pointer (GdkDeviceManager *device_manager)
907 {
908   GdkDeviceManagerCore *device_manager_core;
909
910   device_manager_core = (GdkDeviceManagerCore *) device_manager;
911   return device_manager_core->core_pointer;
912 }