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