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