]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdevicemanager-core-x11.c
wayland: Synthesize fullscreen window state change
[~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_keymap_get_group_for_state (keymap, 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           event->scroll.delta_x = 0;
469           event->scroll.delta_y = 0;
470
471           if (!set_screen_from_root (display, event, xevent->xbutton.root))
472             {
473               return_val = FALSE;
474               break;
475             }
476
477           break;
478
479         default:
480           event->button.type = GDK_BUTTON_PRESS;
481           event->button.window = window;
482           event->button.time = xevent->xbutton.time;
483           event->button.x = (gdouble) xevent->xbutton.x;
484           event->button.y = (gdouble) xevent->xbutton.y;
485           event->button.x_root = (gdouble) xevent->xbutton.x_root;
486           event->button.y_root = (gdouble) xevent->xbutton.y_root;
487           event->button.axes = NULL;
488           event->button.state = (GdkModifierType) xevent->xbutton.state;
489           event->button.button = xevent->xbutton.button;
490           event->button.device = device_manager->core_pointer;
491
492           if (!set_screen_from_root (display, event, xevent->xbutton.root))
493             return_val = FALSE;
494
495           break;
496         }
497
498       set_user_time (window, event);
499
500       break;
501
502     case ButtonRelease:
503       GDK_NOTE (EVENTS,
504                 g_message ("button release:\twindow: %ld  x,y: %d %d  button: %d",
505                            xevent->xbutton.window,
506                            xevent->xbutton.x, xevent->xbutton.y,
507                            xevent->xbutton.button));
508
509       if (window == NULL)
510         {
511           return_val = FALSE;
512           break;
513         }
514
515       /* We treat button presses as scroll wheel events, so ignore the release */
516       if (xevent->xbutton.button == 4 || xevent->xbutton.button == 5 ||
517           xevent->xbutton.button == 6 || xevent->xbutton.button == 7)
518         {
519           return_val = FALSE;
520           break;
521         }
522
523       event->button.type = GDK_BUTTON_RELEASE;
524       event->button.window = window;
525       event->button.time = xevent->xbutton.time;
526       event->button.x = (gdouble) xevent->xbutton.x;
527       event->button.y = (gdouble) xevent->xbutton.y;
528       event->button.x_root = (gdouble) xevent->xbutton.x_root;
529       event->button.y_root = (gdouble) xevent->xbutton.y_root;
530       event->button.axes = NULL;
531       event->button.state = (GdkModifierType) xevent->xbutton.state;
532       event->button.button = xevent->xbutton.button;
533       event->button.device = device_manager->core_pointer;
534
535       if (!set_screen_from_root (display, event, xevent->xbutton.root))
536         return_val = FALSE;
537
538       break;
539
540     case MotionNotify:
541       GDK_NOTE (EVENTS,
542                 g_message ("motion notify:\t\twindow: %ld  x,y: %d %d  hint: %s",
543                            xevent->xmotion.window,
544                            xevent->xmotion.x, xevent->xmotion.y,
545                            (xevent->xmotion.is_hint) ? "true" : "false"));
546
547       if (window == NULL)
548         {
549           return_val = FALSE;
550           break;
551         }
552
553       event->motion.type = GDK_MOTION_NOTIFY;
554       event->motion.window = window;
555       event->motion.time = xevent->xmotion.time;
556       event->motion.x = (gdouble) xevent->xmotion.x;
557       event->motion.y = (gdouble) xevent->xmotion.y;
558       event->motion.x_root = (gdouble) xevent->xmotion.x_root;
559       event->motion.y_root = (gdouble) xevent->xmotion.y_root;
560       event->motion.axes = NULL;
561       event->motion.state = (GdkModifierType) xevent->xmotion.state;
562       event->motion.is_hint = xevent->xmotion.is_hint;
563       event->motion.device = device_manager->core_pointer;
564
565       if (!set_screen_from_root (display, event, xevent->xbutton.root))
566         {
567           return_val = FALSE;
568           break;
569         }
570
571       break;
572
573     case EnterNotify:
574       GDK_NOTE (EVENTS,
575                 g_message ("enter notify:\t\twindow: %ld  detail: %d subwin: %ld",
576                            xevent->xcrossing.window,
577                            xevent->xcrossing.detail,
578                            xevent->xcrossing.subwindow));
579
580       if (window == NULL)
581         {
582           return_val = FALSE;
583           break;
584         }
585
586       if (!set_screen_from_root (display, event, xevent->xbutton.root))
587         {
588           return_val = FALSE;
589           break;
590         }
591
592       event->crossing.type = GDK_ENTER_NOTIFY;
593       event->crossing.window = window;
594       gdk_event_set_device (event, device_manager->core_pointer);
595
596       /* If the subwindow field of the XEvent is non-NULL, then
597        *  lookup the corresponding GdkWindow.
598        */
599       if (xevent->xcrossing.subwindow != None)
600         event->crossing.subwindow = gdk_x11_window_lookup_for_display (display, xevent->xcrossing.subwindow);
601       else
602         event->crossing.subwindow = NULL;
603
604       event->crossing.time = xevent->xcrossing.time;
605       event->crossing.x = (gdouble) xevent->xcrossing.x;
606       event->crossing.y = (gdouble) xevent->xcrossing.y;
607       event->crossing.x_root = (gdouble) xevent->xcrossing.x_root;
608       event->crossing.y_root = (gdouble) xevent->xcrossing.y_root;
609
610       event->crossing.mode = translate_crossing_mode (xevent->xcrossing.mode);
611       event->crossing.detail = translate_notify_type (xevent->xcrossing.detail);
612
613       event->crossing.focus = xevent->xcrossing.focus;
614       event->crossing.state = xevent->xcrossing.state;
615
616       break;
617
618     case LeaveNotify:
619       GDK_NOTE (EVENTS,
620                 g_message ("leave notify:\t\twindow: %ld  detail: %d subwin: %ld",
621                            xevent->xcrossing.window,
622                            xevent->xcrossing.detail, xevent->xcrossing.subwindow));
623
624       if (window == NULL)
625         {
626           return_val = FALSE;
627           break;
628         }
629
630       if (!set_screen_from_root (display, event, xevent->xbutton.root))
631         {
632           return_val = FALSE;
633           break;
634         }
635
636       event->crossing.type = GDK_LEAVE_NOTIFY;
637       event->crossing.window = window;
638       gdk_event_set_device (event, device_manager->core_pointer);
639
640       /* If the subwindow field of the XEvent is non-NULL, then
641        *  lookup the corresponding GdkWindow.
642        */
643       if (xevent->xcrossing.subwindow != None)
644         event->crossing.subwindow = gdk_x11_window_lookup_for_display (display, xevent->xcrossing.subwindow);
645       else
646         event->crossing.subwindow = NULL;
647
648       event->crossing.time = xevent->xcrossing.time;
649       event->crossing.x = (gdouble) xevent->xcrossing.x;
650       event->crossing.y = (gdouble) xevent->xcrossing.y;
651       event->crossing.x_root = (gdouble) xevent->xcrossing.x_root;
652       event->crossing.y_root = (gdouble) xevent->xcrossing.y_root;
653
654       event->crossing.mode = translate_crossing_mode (xevent->xcrossing.mode);
655       event->crossing.detail = translate_notify_type (xevent->xcrossing.detail);
656
657       event->crossing.focus = xevent->xcrossing.focus;
658       event->crossing.state = xevent->xcrossing.state;
659
660       break;
661
662     case FocusIn:
663     case FocusOut:
664       if (window)
665         _gdk_device_manager_core_handle_focus (window,
666                                                xevent->xfocus.window,
667                                                device_manager->core_keyboard,
668                                                NULL,
669                                                xevent->type == FocusIn,
670                                                xevent->xfocus.detail,
671                                                xevent->xfocus.mode);
672       return_val = FALSE;
673       break;
674                                               
675     default:
676         return_val = FALSE;
677     }
678
679  done:
680   if (return_val)
681     {
682       if (event->any.window)
683         g_object_ref (event->any.window);
684
685       if (((event->any.type == GDK_ENTER_NOTIFY) ||
686            (event->any.type == GDK_LEAVE_NOTIFY)) &&
687           (event->crossing.subwindow != NULL))
688         g_object_ref (event->crossing.subwindow);
689     }
690   else
691     {
692       /* Mark this event as having no resources to be freed */
693       event->any.window = NULL;
694       event->any.type = GDK_NOTHING;
695     }
696
697   if (window)
698     g_object_unref (window);
699
700   return return_val;
701 }
702
703 static GList *
704 gdk_x11_device_manager_core_list_devices (GdkDeviceManager *device_manager,
705                                           GdkDeviceType     type)
706 {
707   GdkX11DeviceManagerCore *device_manager_core;
708   GList *devices = NULL;
709
710   if (type == GDK_DEVICE_TYPE_MASTER)
711     {
712       device_manager_core = (GdkX11DeviceManagerCore *) device_manager;
713       devices = g_list_prepend (devices, device_manager_core->core_keyboard);
714       devices = g_list_prepend (devices, device_manager_core->core_pointer);
715     }
716
717   return devices;
718 }
719
720 static GdkDevice *
721 gdk_x11_device_manager_core_get_client_pointer (GdkDeviceManager *device_manager)
722 {
723   GdkX11DeviceManagerCore *device_manager_core;
724
725   device_manager_core = (GdkX11DeviceManagerCore *) device_manager;
726   return device_manager_core->core_pointer;
727 }
728
729 void
730 _gdk_x11_event_translate_keyboard_string (GdkEventKey *event)
731 {
732   gunichar c = 0;
733   gchar buf[7];
734
735   /* Fill in event->string crudely, since various programs
736    * depend on it.
737    */
738   event->string = NULL;
739
740   if (event->keyval != GDK_KEY_VoidSymbol)
741     c = gdk_keyval_to_unicode (event->keyval);
742
743   if (c)
744     {
745       gsize bytes_written;
746       gint len;
747
748       /* Apply the control key - Taken from Xlib
749        */
750       if (event->state & GDK_CONTROL_MASK)
751         {
752           if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
753           else if (c == '2')
754             {
755               event->string = g_memdup ("\0\0", 2);
756               event->length = 1;
757               buf[0] = '\0';
758               return;
759             }
760           else if (c >= '3' && c <= '7') c -= ('3' - '\033');
761           else if (c == '8') c = '\177';
762           else if (c == '/') c = '_' & 0x1F;
763         }
764
765       len = g_unichar_to_utf8 (c, buf);
766       buf[len] = '\0';
767
768       event->string = g_locale_from_utf8 (buf, len,
769                                           NULL, &bytes_written,
770                                           NULL);
771       if (event->string)
772         event->length = bytes_written;
773     }
774   else if (event->keyval == GDK_KEY_Escape)
775     {
776       event->length = 1;
777       event->string = g_strdup ("\033");
778     }
779   else if (event->keyval == GDK_KEY_Return ||
780           event->keyval == GDK_KEY_KP_Enter)
781     {
782       event->length = 1;
783       event->string = g_strdup ("\r");
784     }
785
786   if (!event->string)
787     {
788       event->length = 0;
789       event->string = g_strdup ("");
790     }
791 }
792
793 /* We only care about focus events that indicate that _this_
794  * window (not a ancestor or child) got or lost the focus
795  */
796 void
797 _gdk_device_manager_core_handle_focus (GdkWindow *window,
798                                        Window     original,
799                                        GdkDevice *device,
800                                        GdkDevice *source_device,
801                                        gboolean   focus_in,
802                                        int        detail,
803                                        int        mode)
804 {
805   GdkToplevelX11 *toplevel;
806   gboolean had_focus;
807
808   g_return_if_fail (GDK_IS_WINDOW (window));
809   g_return_if_fail (GDK_IS_DEVICE (device));
810   g_return_if_fail (source_device == NULL || GDK_IS_DEVICE (source_device));
811
812   GDK_NOTE (EVENTS,
813             g_message ("focus out:\t\twindow: %ld, detail: %s, mode: %s",
814                        GDK_WINDOW_XID (window),
815                        notify_details[detail],
816                        notify_modes[mode]));
817
818   toplevel = _gdk_x11_window_get_toplevel (window);
819
820   if (!toplevel)
821     return;
822
823   if (toplevel->focus_window == original)
824     return;
825
826   had_focus = HAS_FOCUS (toplevel);
827
828   switch (detail)
829     {
830     case NotifyAncestor:
831     case NotifyVirtual:
832       /* When the focus moves from an ancestor of the window to
833        * the window or a descendent of the window, *and* the
834        * pointer is inside the window, then we were previously
835        * receiving keystroke events in the has_pointer_focus
836        * case and are now receiving them in the
837        * has_focus_window case.
838        */
839       if (toplevel->has_pointer &&
840           mode != NotifyGrab &&
841           mode != NotifyUngrab)
842         toplevel->has_pointer_focus = (focus_in) ? FALSE : TRUE;
843
844       /* fall through */
845     case NotifyNonlinear:
846     case NotifyNonlinearVirtual:
847       if (mode != NotifyGrab &&
848           mode != NotifyUngrab)
849         toplevel->has_focus_window = (focus_in) ? TRUE : FALSE;
850       /* We pretend that the focus moves to the grab
851        * window, so we pay attention to NotifyGrab
852        * NotifyUngrab, and ignore NotifyWhileGrabbed
853        */
854       if (mode != NotifyWhileGrabbed)
855         toplevel->has_focus = (focus_in) ? TRUE : FALSE;
856       break;
857     case NotifyPointer:
858       /* The X server sends NotifyPointer/NotifyGrab,
859        * but the pointer focus is ignored while a
860        * grab is in effect
861        */
862       if (mode != NotifyGrab &&
863           mode != NotifyUngrab)
864         toplevel->has_pointer_focus = (focus_in) ? TRUE : FALSE;
865       break;
866     case NotifyInferior:
867     case NotifyPointerRoot:
868     case NotifyDetailNone:
869     default:
870       break;
871     }
872
873   if (HAS_FOCUS (toplevel) != had_focus)
874     {
875       GdkEvent *event;
876
877       event = gdk_event_new (GDK_FOCUS_CHANGE);
878       event->focus_change.window = g_object_ref (window);
879       event->focus_change.send_event = FALSE;
880       event->focus_change.in = focus_in;
881       gdk_event_set_device (event, device);
882       if (source_device)
883         gdk_event_set_source_device (event, source_device);
884
885       gdk_event_put (event);
886       gdk_event_free (event);
887     }
888 }
889