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