1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
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.
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.
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.
22 #include "gdkdevicemanager-core.h"
25 #include "gdkdevicemanager.h"
26 #include "gdkeventtranslator.h"
27 #include "gdkdevice-core.h"
28 #include "gdkkeysyms.h"
29 #include "gdkprivate-x11.h"
33 #include <X11/XKBlib.h>
37 #define HAS_FOCUS(toplevel) \
38 ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
40 static void gdk_device_manager_core_finalize (GObject *object);
41 static void gdk_device_manager_core_constructed (GObject *object);
43 static GList * gdk_device_manager_core_list_devices (GdkDeviceManager *device_manager,
45 static GdkDevice * gdk_device_manager_core_get_client_pointer (GdkDeviceManager *device_manager);
47 static void gdk_device_manager_event_translator_init (GdkEventTranslatorIface *iface);
49 static gboolean gdk_device_manager_core_translate_event (GdkEventTranslator *translator,
55 G_DEFINE_TYPE_WITH_CODE (GdkDeviceManagerCore, gdk_device_manager_core, GDK_TYPE_DEVICE_MANAGER,
56 G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
57 gdk_device_manager_event_translator_init))
60 gdk_device_manager_core_class_init (GdkDeviceManagerCoreClass *klass)
62 GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
63 GObjectClass *object_class = G_OBJECT_CLASS (klass);
65 object_class->finalize = gdk_device_manager_core_finalize;
66 object_class->constructed = gdk_device_manager_core_constructed;
67 device_manager_class->list_devices = gdk_device_manager_core_list_devices;
68 device_manager_class->get_client_pointer = gdk_device_manager_core_get_client_pointer;
72 gdk_device_manager_event_translator_init (GdkEventTranslatorIface *iface)
74 iface->translate_event = gdk_device_manager_core_translate_event;
78 create_core_pointer (GdkDeviceManager *device_manager,
81 return g_object_new (GDK_TYPE_DEVICE_CORE,
82 "name", "Core Pointer",
83 "type", GDK_DEVICE_TYPE_MASTER,
84 "input-source", GDK_SOURCE_MOUSE,
85 "input-mode", GDK_MODE_SCREEN,
88 "device-manager", device_manager,
93 create_core_keyboard (GdkDeviceManager *device_manager,
96 return g_object_new (GDK_TYPE_DEVICE_CORE,
97 "name", "Core Keyboard",
98 "type", GDK_DEVICE_TYPE_MASTER,
99 "input-source", GDK_SOURCE_KEYBOARD,
100 "input-mode", GDK_MODE_SCREEN,
103 "device-manager", device_manager,
108 gdk_device_manager_core_init (GdkDeviceManagerCore *device_manager)
113 gdk_device_manager_core_finalize (GObject *object)
115 GdkDeviceManagerCore *device_manager_core;
117 device_manager_core = GDK_DEVICE_MANAGER_CORE (object);
119 g_object_unref (device_manager_core->core_pointer);
120 g_object_unref (device_manager_core->core_keyboard);
122 G_OBJECT_CLASS (gdk_device_manager_core_parent_class)->finalize (object);
126 gdk_device_manager_core_constructed (GObject *object)
128 GdkDeviceManagerCore *device_manager;
131 device_manager = GDK_DEVICE_MANAGER_CORE (object);
132 display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (object));
133 device_manager->core_pointer = create_core_pointer (GDK_DEVICE_MANAGER (device_manager), display);
134 device_manager->core_keyboard = create_core_keyboard (GDK_DEVICE_MANAGER (device_manager), display);
136 _gdk_device_set_associated_device (device_manager->core_pointer, device_manager->core_keyboard);
137 _gdk_device_set_associated_device (device_manager->core_keyboard, device_manager->core_pointer);
141 translate_key_event (GdkDisplay *display,
142 GdkDeviceManagerCore *device_manager,
146 GdkKeymap *keymap = gdk_keymap_get_for_display (display);
147 GdkModifierType consumed, state;
151 event->key.type = xevent->xany.type == KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
152 event->key.time = xevent->xkey.time;
153 gdk_event_set_device (event, device_manager->core_keyboard);
155 event->key.state = (GdkModifierType) xevent->xkey.state;
156 event->key.group = _gdk_x11_get_group_for_state (display, xevent->xkey.state);
157 event->key.hardware_keycode = xevent->xkey.keycode;
159 event->key.keyval = GDK_KEY_VoidSymbol;
161 gdk_keymap_translate_keyboard_state (keymap,
162 event->key.hardware_keycode,
166 NULL, NULL, &consumed);
168 state = event->key.state & ~consumed;
169 _gdk_keymap_add_virtual_modifiers_compat (keymap, &state);
170 event->key.state |= state;
172 event->key.is_modifier = _gdk_keymap_key_is_modifier (keymap, event->key.hardware_keycode);
174 /* Fill in event->string crudely, since various programs
177 event->key.string = NULL;
179 if (event->key.keyval != GDK_KEY_VoidSymbol)
180 c = gdk_keyval_to_unicode (event->key.keyval);
187 /* Apply the control key - Taken from Xlib
189 if (event->key.state & GDK_CONTROL_MASK)
191 if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
194 event->key.string = g_memdup ("\0\0", 2);
195 event->key.length = 1;
199 else if (c >= '3' && c <= '7') c -= ('3' - '\033');
200 else if (c == '8') c = '\177';
201 else if (c == '/') c = '_' & 0x1F;
204 len = g_unichar_to_utf8 (c, buf);
207 event->key.string = g_locale_from_utf8 (buf, len,
208 NULL, &bytes_written,
210 if (event->key.string)
211 event->key.length = bytes_written;
213 else if (event->key.keyval == GDK_KEY_Escape)
215 event->key.length = 1;
216 event->key.string = g_strdup ("\033");
218 else if (event->key.keyval == GDK_KEY_Return ||
219 event->key.keyval == GDK_KEY_KP_Enter)
221 event->key.length = 1;
222 event->key.string = g_strdup ("\r");
225 if (!event->key.string)
227 event->key.length = 0;
228 event->key.string = g_strdup ("");
232 #ifdef G_ENABLE_DEBUG
233 if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
235 g_message ("%s:\t\twindow: %ld key: %12s %d",
236 event->type == GDK_KEY_PRESS ? "key press " : "key release",
238 event->key.keyval ? gdk_keyval_name (event->key.keyval) : "(none)",
241 if (event->key.length > 0)
242 g_message ("\t\tlength: %4d string: \"%s\"",
243 event->key.length, buf);
245 #endif /* G_ENABLE_DEBUG */
249 #ifdef G_ENABLE_DEBUG
250 static const char notify_modes[][19] = {
257 static const char notify_details[][23] = {
262 "NotifyNonlinearVirtual",
270 set_user_time (GdkWindow *window,
273 g_return_if_fail (event != NULL);
275 window = gdk_window_get_toplevel (event->client.window);
276 g_return_if_fail (GDK_IS_WINDOW (window));
278 /* If an event doesn't have a valid timestamp, we shouldn't use it
279 * to update the latest user interaction time.
281 if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
282 gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
283 gdk_event_get_time (event));
287 generate_focus_event (GdkDeviceManagerCore *device_manager,
293 event = gdk_event_new (GDK_FOCUS_CHANGE);
294 event->focus_change.window = g_object_ref (window);
295 event->focus_change.send_event = FALSE;
296 event->focus_change.in = in;
297 gdk_event_set_device (event, device_manager->core_keyboard);
299 gdk_event_put (event);
300 gdk_event_free (event);
304 set_screen_from_root (GdkDisplay *display,
310 screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
314 gdk_event_set_screen (event, screen);
322 static GdkCrossingMode
323 translate_crossing_mode (int mode)
328 return GDK_CROSSING_NORMAL;
330 return GDK_CROSSING_GRAB;
332 return GDK_CROSSING_UNGRAB;
334 g_assert_not_reached ();
339 translate_notify_type (int detail)
344 return GDK_NOTIFY_INFERIOR;
346 return GDK_NOTIFY_ANCESTOR;
348 return GDK_NOTIFY_VIRTUAL;
349 case NotifyNonlinear:
350 return GDK_NOTIFY_NONLINEAR;
351 case NotifyNonlinearVirtual:
352 return GDK_NOTIFY_NONLINEAR_VIRTUAL;
354 g_assert_not_reached ();
359 is_parent_of (GdkWindow *parent,
370 w = gdk_window_get_parent (w);
377 get_event_window (GdkEventTranslator *translator,
380 GdkDeviceManager *device_manager;
384 device_manager = GDK_DEVICE_MANAGER (translator);
385 display = gdk_device_manager_get_display (device_manager);
386 window = gdk_window_lookup_for_display (display, xevent->xany.window);
388 /* Apply keyboard grabs to non-native windows */
389 if (xevent->type == KeyPress || xevent->type == KeyRelease)
391 GdkDeviceGrabInfo *info;
394 serial = _gdk_windowing_window_get_next_serial (display);
395 info = _gdk_display_has_device_grab (display,
396 GDK_DEVICE_MANAGER_CORE (device_manager)->core_keyboard,
399 (!is_parent_of (info->window, window) ||
400 !info->owner_events))
402 /* Report key event against grab window */
403 window = info->window;
411 gdk_device_manager_core_translate_event (GdkEventTranslator *translator,
416 GdkDeviceManagerCore *device_manager;
418 GdkWindowObject *window_private;
419 GdkWindowImplX11 *window_impl = NULL;
421 GdkToplevelX11 *toplevel = NULL;
422 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
424 device_manager = GDK_DEVICE_MANAGER_CORE (translator);
427 window = get_event_window (translator, xevent);
428 window_private = (GdkWindowObject *) window;
432 if (GDK_WINDOW_DESTROYED (window) || !GDK_IS_WINDOW (window))
435 toplevel = _gdk_x11_window_get_toplevel (window);
436 window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
437 g_object_ref (window);
440 event->any.window = window;
441 event->any.send_event = xevent->xany.send_event ? TRUE : FALSE;
443 if (window_private && GDK_WINDOW_DESTROYED (window))
445 if (xevent->type != DestroyNotify)
453 (xevent->type == MotionNotify ||
454 xevent->type == ButtonRelease))
456 if (_gdk_moveresize_handle_event (xevent))
463 /* We do a "manual" conversion of the XEvent to a
464 * GdkEvent. The structures are mostly the same so
465 * the conversion is fairly straightforward. We also
466 * optionally print debugging info regarding events
472 switch (xevent->type)
475 if (window_private == NULL)
480 translate_key_event (display, device_manager, event, xevent);
481 set_user_time (window, event);
485 if (window_private == NULL)
491 /* Emulate detectable auto-repeat by checking to see
492 * if the next event is a key press with the same
493 * keycode and timestamp, and if so, ignoring the event.
496 if (!display_x11->have_xkb_autorepeat && XPending (xevent->xkey.display))
500 XPeekEvent (xevent->xkey.display, &next_event);
502 if (next_event.type == KeyPress &&
503 next_event.xkey.keycode == xevent->xkey.keycode &&
504 next_event.xkey.time == xevent->xkey.time)
511 translate_key_event (display, device_manager, event, xevent);
516 g_message ("button press:\t\twindow: %ld x,y: %d %d button: %d",
517 xevent->xbutton.window,
518 xevent->xbutton.x, xevent->xbutton.y,
519 xevent->xbutton.button));
521 if (window_private == NULL)
527 /* If we get a ButtonPress event where the button is 4 or 5,
528 it's a Scroll event */
529 switch (xevent->xbutton.button)
535 event->scroll.type = GDK_SCROLL;
537 if (xevent->xbutton.button == 4)
538 event->scroll.direction = GDK_SCROLL_UP;
539 else if (xevent->xbutton.button == 5)
540 event->scroll.direction = GDK_SCROLL_DOWN;
541 else if (xevent->xbutton.button == 6)
542 event->scroll.direction = GDK_SCROLL_LEFT;
544 event->scroll.direction = GDK_SCROLL_RIGHT;
546 event->scroll.window = window;
547 event->scroll.time = xevent->xbutton.time;
548 event->scroll.x = (gdouble) xevent->xbutton.x;
549 event->scroll.y = (gdouble) xevent->xbutton.y;
550 event->scroll.x_root = (gdouble) xevent->xbutton.x_root;
551 event->scroll.y_root = (gdouble) xevent->xbutton.y_root;
552 event->scroll.state = (GdkModifierType) xevent->xbutton.state;
553 event->scroll.device = device_manager->core_pointer;
555 if (!set_screen_from_root (display, event, xevent->xbutton.root))
564 event->button.type = GDK_BUTTON_PRESS;
565 event->button.window = window;
566 event->button.time = xevent->xbutton.time;
567 event->button.x = (gdouble) xevent->xbutton.x;
568 event->button.y = (gdouble) xevent->xbutton.y;
569 event->button.x_root = (gdouble) xevent->xbutton.x_root;
570 event->button.y_root = (gdouble) xevent->xbutton.y_root;
571 event->button.axes = NULL;
572 event->button.state = (GdkModifierType) xevent->xbutton.state;
573 event->button.button = xevent->xbutton.button;
574 event->button.device = device_manager->core_pointer;
576 if (!set_screen_from_root (display, event, xevent->xbutton.root))
582 set_user_time (window, event);
588 g_message ("button release:\twindow: %ld x,y: %d %d button: %d",
589 xevent->xbutton.window,
590 xevent->xbutton.x, xevent->xbutton.y,
591 xevent->xbutton.button));
593 if (window_private == NULL)
599 /* We treat button presses as scroll wheel events, so ignore the release */
600 if (xevent->xbutton.button == 4 || xevent->xbutton.button == 5 ||
601 xevent->xbutton.button == 6 || xevent->xbutton.button == 7)
607 event->button.type = GDK_BUTTON_RELEASE;
608 event->button.window = window;
609 event->button.time = xevent->xbutton.time;
610 event->button.x = (gdouble) xevent->xbutton.x;
611 event->button.y = (gdouble) xevent->xbutton.y;
612 event->button.x_root = (gdouble) xevent->xbutton.x_root;
613 event->button.y_root = (gdouble) xevent->xbutton.y_root;
614 event->button.axes = NULL;
615 event->button.state = (GdkModifierType) xevent->xbutton.state;
616 event->button.button = xevent->xbutton.button;
617 event->button.device = device_manager->core_pointer;
619 if (!set_screen_from_root (display, event, xevent->xbutton.root))
626 g_message ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s",
627 xevent->xmotion.window,
628 xevent->xmotion.x, xevent->xmotion.y,
629 (xevent->xmotion.is_hint) ? "true" : "false"));
631 if (window_private == NULL)
637 event->motion.type = GDK_MOTION_NOTIFY;
638 event->motion.window = window;
639 event->motion.time = xevent->xmotion.time;
640 event->motion.x = (gdouble) xevent->xmotion.x;
641 event->motion.y = (gdouble) xevent->xmotion.y;
642 event->motion.x_root = (gdouble) xevent->xmotion.x_root;
643 event->motion.y_root = (gdouble) xevent->xmotion.y_root;
644 event->motion.axes = NULL;
645 event->motion.state = (GdkModifierType) xevent->xmotion.state;
646 event->motion.is_hint = xevent->xmotion.is_hint;
647 event->motion.device = device_manager->core_pointer;
649 if (!set_screen_from_root (display, event, xevent->xbutton.root))
659 g_message ("enter notify:\t\twindow: %ld detail: %d subwin: %ld",
660 xevent->xcrossing.window,
661 xevent->xcrossing.detail,
662 xevent->xcrossing.subwindow));
664 if (window_private == NULL)
670 if (!set_screen_from_root (display, event, xevent->xbutton.root))
676 event->crossing.type = GDK_ENTER_NOTIFY;
677 event->crossing.window = window;
678 gdk_event_set_device (event, device_manager->core_pointer);
680 /* If the subwindow field of the XEvent is non-NULL, then
681 * lookup the corresponding GdkWindow.
683 if (xevent->xcrossing.subwindow != None)
684 event->crossing.subwindow = gdk_window_lookup_for_display (display, xevent->xcrossing.subwindow);
686 event->crossing.subwindow = NULL;
688 event->crossing.time = xevent->xcrossing.time;
689 event->crossing.x = (gdouble) xevent->xcrossing.x;
690 event->crossing.y = (gdouble) xevent->xcrossing.y;
691 event->crossing.x_root = (gdouble) xevent->xcrossing.x_root;
692 event->crossing.y_root = (gdouble) xevent->xcrossing.y_root;
694 event->crossing.mode = translate_crossing_mode (xevent->xcrossing.mode);
695 event->crossing.detail = translate_notify_type (xevent->xcrossing.detail);
697 event->crossing.focus = xevent->xcrossing.focus;
698 event->crossing.state = xevent->xcrossing.state;
704 g_message ("leave notify:\t\twindow: %ld detail: %d subwin: %ld",
705 xevent->xcrossing.window,
706 xevent->xcrossing.detail, xevent->xcrossing.subwindow));
708 if (window_private == NULL)
714 if (!set_screen_from_root (display, event, xevent->xbutton.root))
720 event->crossing.type = GDK_LEAVE_NOTIFY;
721 event->crossing.window = window;
722 gdk_event_set_device (event, device_manager->core_pointer);
724 /* If the subwindow field of the XEvent is non-NULL, then
725 * lookup the corresponding GdkWindow.
727 if (xevent->xcrossing.subwindow != None)
728 event->crossing.subwindow = gdk_window_lookup_for_display (display, xevent->xcrossing.subwindow);
730 event->crossing.subwindow = NULL;
732 event->crossing.time = xevent->xcrossing.time;
733 event->crossing.x = (gdouble) xevent->xcrossing.x;
734 event->crossing.y = (gdouble) xevent->xcrossing.y;
735 event->crossing.x_root = (gdouble) xevent->xcrossing.x_root;
736 event->crossing.y_root = (gdouble) xevent->xcrossing.y_root;
738 event->crossing.mode = translate_crossing_mode (xevent->xcrossing.mode);
739 event->crossing.detail = translate_notify_type (xevent->xcrossing.detail);
741 event->crossing.focus = xevent->xcrossing.focus;
742 event->crossing.state = xevent->xcrossing.state;
746 /* We only care about focus events that indicate that _this_
747 * window (not a ancestor or child) got or lost the focus
751 g_message ("focus in:\t\twindow: %ld, detail: %s, mode: %s",
752 xevent->xfocus.window,
753 notify_details[xevent->xfocus.detail],
754 notify_modes[xevent->xfocus.mode]));
758 gboolean had_focus = HAS_FOCUS (toplevel);
760 switch (xevent->xfocus.detail)
764 /* When the focus moves from an ancestor of the window to
765 * the window or a descendent of the window, *and* the
766 * pointer is inside the window, then we were previously
767 * receiving keystroke events in the has_pointer_focus
768 * case and are now receiving them in the
769 * has_focus_window case.
771 if (toplevel->has_pointer &&
772 xevent->xfocus.mode != NotifyGrab &&
773 xevent->xfocus.mode != NotifyUngrab)
774 toplevel->has_pointer_focus = FALSE;
777 case NotifyNonlinear:
778 case NotifyNonlinearVirtual:
779 if (xevent->xfocus.mode != NotifyGrab &&
780 xevent->xfocus.mode != NotifyUngrab)
781 toplevel->has_focus_window = TRUE;
782 /* We pretend that the focus moves to the grab
783 * window, so we pay attention to NotifyGrab
784 * NotifyUngrab, and ignore NotifyWhileGrabbed
786 if (xevent->xfocus.mode != NotifyWhileGrabbed)
787 toplevel->has_focus = TRUE;
790 /* The X server sends NotifyPointer/NotifyGrab,
791 * but the pointer focus is ignored while a
794 if (xevent->xfocus.mode != NotifyGrab &&
795 xevent->xfocus.mode != NotifyUngrab)
796 toplevel->has_pointer_focus = TRUE;
799 case NotifyPointerRoot:
800 case NotifyDetailNone:
804 if (HAS_FOCUS (toplevel) != had_focus)
805 generate_focus_event (device_manager, window, TRUE);
810 g_message ("focus out:\t\twindow: %ld, detail: %s, mode: %s",
811 xevent->xfocus.window,
812 notify_details[xevent->xfocus.detail],
813 notify_modes[xevent->xfocus.mode]));
817 gboolean had_focus = HAS_FOCUS (toplevel);
819 switch (xevent->xfocus.detail)
823 /* When the focus moves from the window or a descendent
824 * of the window to an ancestor of the window, *and* the
825 * pointer is inside the window, then we were previously
826 * receiving keystroke events in the has_focus_window
827 * case and are now receiving them in the
828 * has_pointer_focus case.
830 if (toplevel->has_pointer &&
831 xevent->xfocus.mode != NotifyGrab &&
832 xevent->xfocus.mode != NotifyUngrab)
833 toplevel->has_pointer_focus = TRUE;
836 case NotifyNonlinear:
837 case NotifyNonlinearVirtual:
838 if (xevent->xfocus.mode != NotifyGrab &&
839 xevent->xfocus.mode != NotifyUngrab)
840 toplevel->has_focus_window = FALSE;
841 if (xevent->xfocus.mode != NotifyWhileGrabbed)
842 toplevel->has_focus = FALSE;
845 if (xevent->xfocus.mode != NotifyGrab &&
846 xevent->xfocus.mode != NotifyUngrab)
847 toplevel->has_pointer_focus = FALSE;
850 case NotifyPointerRoot:
851 case NotifyDetailNone:
855 if (HAS_FOCUS (toplevel) != had_focus)
856 generate_focus_event (device_manager, window, FALSE);
867 if (event->any.window)
868 g_object_ref (event->any.window);
870 if (((event->any.type == GDK_ENTER_NOTIFY) ||
871 (event->any.type == GDK_LEAVE_NOTIFY)) &&
872 (event->crossing.subwindow != NULL))
873 g_object_ref (event->crossing.subwindow);
877 /* Mark this event as having no resources to be freed */
878 event->any.window = NULL;
879 event->any.type = GDK_NOTHING;
883 g_object_unref (window);
889 gdk_device_manager_core_list_devices (GdkDeviceManager *device_manager,
892 GdkDeviceManagerCore *device_manager_core;
893 GList *devices = NULL;
895 if (type == GDK_DEVICE_TYPE_MASTER)
897 device_manager_core = (GdkDeviceManagerCore *) device_manager;
898 devices = g_list_prepend (devices, device_manager_core->core_keyboard);
899 devices = g_list_prepend (devices, device_manager_core->core_pointer);
906 gdk_device_manager_core_get_client_pointer (GdkDeviceManager *device_manager)
908 GdkDeviceManagerCore *device_manager_core;
910 device_manager_core = (GdkDeviceManagerCore *) device_manager;
911 return device_manager_core->core_pointer;