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, see <http://www.gnu.org/licenses/>.
20 #include "gdkx11devicemanager-core.h"
21 #include "gdkdevicemanagerprivate-core.h"
22 #include "gdkx11device-core.h"
24 #include "gdkdeviceprivate.h"
25 #include "gdkdisplayprivate.h"
26 #include "gdkeventtranslator.h"
27 #include "gdkprivate-x11.h"
28 #include "gdkkeysyms.h"
31 #define HAS_FOCUS(toplevel) \
32 ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
34 static void gdk_x11_device_manager_core_finalize (GObject *object);
35 static void gdk_x11_device_manager_core_constructed (GObject *object);
37 static GList * gdk_x11_device_manager_core_list_devices (GdkDeviceManager *device_manager,
39 static GdkDevice * gdk_x11_device_manager_core_get_client_pointer (GdkDeviceManager *device_manager);
41 static void gdk_x11_device_manager_event_translator_init (GdkEventTranslatorIface *iface);
43 static gboolean gdk_x11_device_manager_core_translate_event (GdkEventTranslator *translator,
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))
54 gdk_x11_device_manager_core_class_init (GdkX11DeviceManagerCoreClass *klass)
56 GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
57 GObjectClass *object_class = G_OBJECT_CLASS (klass);
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;
66 gdk_x11_device_manager_event_translator_init (GdkEventTranslatorIface *iface)
68 iface->translate_event = gdk_x11_device_manager_core_translate_event;
72 create_core_pointer (GdkDeviceManager *device_manager,
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,
82 "device-manager", device_manager,
87 create_core_keyboard (GdkDeviceManager *device_manager,
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,
97 "device-manager", device_manager,
102 gdk_x11_device_manager_core_init (GdkX11DeviceManagerCore *device_manager)
107 gdk_x11_device_manager_core_finalize (GObject *object)
109 GdkX11DeviceManagerCore *device_manager_core;
111 device_manager_core = GDK_X11_DEVICE_MANAGER_CORE (object);
113 g_object_unref (device_manager_core->core_pointer);
114 g_object_unref (device_manager_core->core_keyboard);
116 G_OBJECT_CLASS (gdk_x11_device_manager_core_parent_class)->finalize (object);
120 gdk_x11_device_manager_core_constructed (GObject *object)
122 GdkX11DeviceManagerCore *device_manager;
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);
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);
135 translate_key_event (GdkDisplay *display,
136 GdkX11DeviceManagerCore *device_manager,
140 GdkKeymap *keymap = gdk_keymap_get_for_display (display);
141 GdkModifierType consumed, state;
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);
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;
151 event->key.keyval = GDK_KEY_VoidSymbol;
153 gdk_keymap_translate_keyboard_state (keymap,
154 event->key.hardware_keycode,
158 NULL, NULL, &consumed);
160 state = event->key.state & ~consumed;
161 _gdk_x11_keymap_add_virt_mods (keymap, &state);
162 event->key.state |= state;
164 event->key.is_modifier = gdk_x11_keymap_key_is_modifier (keymap, event->key.hardware_keycode);
166 _gdk_x11_event_translate_keyboard_string (&event->key);
168 #ifdef G_ENABLE_DEBUG
169 if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
171 g_message ("%s:\t\twindow: %ld key: %12s %d",
172 event->type == GDK_KEY_PRESS ? "key press " : "key release",
174 event->key.keyval ? gdk_keyval_name (event->key.keyval) : "(none)",
177 if (event->key.length > 0)
178 g_message ("\t\tlength: %4d string: \"%s\"",
179 event->key.length, event->key.string);
181 #endif /* G_ENABLE_DEBUG */
185 #ifdef G_ENABLE_DEBUG
186 static const char notify_modes[][19] = {
193 static const char notify_details[][23] = {
198 "NotifyNonlinearVirtual",
206 set_user_time (GdkWindow *window,
209 g_return_if_fail (event != NULL);
211 window = gdk_window_get_toplevel (event->any.window);
212 g_return_if_fail (GDK_IS_WINDOW (window));
214 /* If an event doesn't have a valid timestamp, we shouldn't use it
215 * to update the latest user interaction time.
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));
223 set_screen_from_root (GdkDisplay *display,
229 screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
233 gdk_event_set_screen (event, screen);
241 static GdkCrossingMode
242 translate_crossing_mode (int mode)
247 return GDK_CROSSING_NORMAL;
249 return GDK_CROSSING_GRAB;
251 return GDK_CROSSING_UNGRAB;
253 g_assert_not_reached ();
258 translate_notify_type (int detail)
263 return GDK_NOTIFY_INFERIOR;
265 return GDK_NOTIFY_ANCESTOR;
267 return GDK_NOTIFY_VIRTUAL;
268 case NotifyNonlinear:
269 return GDK_NOTIFY_NONLINEAR;
270 case NotifyNonlinearVirtual:
271 return GDK_NOTIFY_NONLINEAR_VIRTUAL;
273 g_assert_not_reached ();
278 is_parent_of (GdkWindow *parent,
289 w = gdk_window_get_parent (w);
296 get_event_window (GdkEventTranslator *translator,
299 GdkDeviceManager *device_manager;
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);
307 /* Apply keyboard grabs to non-native windows */
308 if (xevent->type == KeyPress || xevent->type == KeyRelease)
310 GdkDeviceGrabInfo *info;
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,
318 (!is_parent_of (info->window, window) ||
319 !info->owner_events))
321 /* Report key event against grab window */
322 window = info->window;
330 gdk_x11_device_manager_core_translate_event (GdkEventTranslator *translator,
335 GdkX11DeviceManagerCore *device_manager;
338 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
340 device_manager = GDK_X11_DEVICE_MANAGER_CORE (translator);
343 window = get_event_window (translator, xevent);
347 if (GDK_WINDOW_DESTROYED (window) || !GDK_IS_WINDOW (window))
350 g_object_ref (window);
353 event->any.window = window;
354 event->any.send_event = xevent->xany.send_event ? TRUE : FALSE;
356 if (window && GDK_WINDOW_DESTROYED (window))
358 if (xevent->type != DestroyNotify)
366 (xevent->type == MotionNotify ||
367 xevent->type == ButtonRelease))
369 if (_gdk_x11_moveresize_handle_event (xevent))
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
385 switch (xevent->type)
393 translate_key_event (display, device_manager, event, xevent);
394 set_user_time (window, event);
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.
409 if (!display_x11->have_xkb_autorepeat && XPending (xevent->xkey.display))
413 XPeekEvent (xevent->xkey.display, &next_event);
415 if (next_event.type == KeyPress &&
416 next_event.xkey.keycode == xevent->xkey.keycode &&
417 next_event.xkey.time == xevent->xkey.time)
424 translate_key_event (display, device_manager, event, xevent);
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));
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)
448 event->scroll.type = GDK_SCROLL;
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;
457 event->scroll.direction = GDK_SCROLL_RIGHT;
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;
468 event->scroll.delta_x = 0;
469 event->scroll.delta_y = 0;
471 if (!set_screen_from_root (display, event, xevent->xbutton.root))
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;
492 if (!set_screen_from_root (display, event, xevent->xbutton.root))
498 set_user_time (window, event);
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));
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)
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;
535 if (!set_screen_from_root (display, event, xevent->xbutton.root))
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"));
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;
565 if (!set_screen_from_root (display, event, xevent->xbutton.root))
575 g_message ("enter notify:\t\twindow: %ld detail: %d subwin: %ld",
576 xevent->xcrossing.window,
577 xevent->xcrossing.detail,
578 xevent->xcrossing.subwindow));
586 if (!set_screen_from_root (display, event, xevent->xbutton.root))
592 event->crossing.type = GDK_ENTER_NOTIFY;
593 event->crossing.window = window;
594 gdk_event_set_device (event, device_manager->core_pointer);
596 /* If the subwindow field of the XEvent is non-NULL, then
597 * lookup the corresponding GdkWindow.
599 if (xevent->xcrossing.subwindow != None)
600 event->crossing.subwindow = gdk_x11_window_lookup_for_display (display, xevent->xcrossing.subwindow);
602 event->crossing.subwindow = NULL;
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;
610 event->crossing.mode = translate_crossing_mode (xevent->xcrossing.mode);
611 event->crossing.detail = translate_notify_type (xevent->xcrossing.detail);
613 event->crossing.focus = xevent->xcrossing.focus;
614 event->crossing.state = xevent->xcrossing.state;
620 g_message ("leave notify:\t\twindow: %ld detail: %d subwin: %ld",
621 xevent->xcrossing.window,
622 xevent->xcrossing.detail, xevent->xcrossing.subwindow));
630 if (!set_screen_from_root (display, event, xevent->xbutton.root))
636 event->crossing.type = GDK_LEAVE_NOTIFY;
637 event->crossing.window = window;
638 gdk_event_set_device (event, device_manager->core_pointer);
640 /* If the subwindow field of the XEvent is non-NULL, then
641 * lookup the corresponding GdkWindow.
643 if (xevent->xcrossing.subwindow != None)
644 event->crossing.subwindow = gdk_x11_window_lookup_for_display (display, xevent->xcrossing.subwindow);
646 event->crossing.subwindow = NULL;
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;
654 event->crossing.mode = translate_crossing_mode (xevent->xcrossing.mode);
655 event->crossing.detail = translate_notify_type (xevent->xcrossing.detail);
657 event->crossing.focus = xevent->xcrossing.focus;
658 event->crossing.state = xevent->xcrossing.state;
665 _gdk_device_manager_core_handle_focus (window,
666 xevent->xfocus.window,
667 device_manager->core_keyboard,
669 xevent->type == FocusIn,
670 xevent->xfocus.detail,
671 xevent->xfocus.mode);
682 if (event->any.window)
683 g_object_ref (event->any.window);
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);
692 /* Mark this event as having no resources to be freed */
693 event->any.window = NULL;
694 event->any.type = GDK_NOTHING;
698 g_object_unref (window);
704 gdk_x11_device_manager_core_list_devices (GdkDeviceManager *device_manager,
707 GdkX11DeviceManagerCore *device_manager_core;
708 GList *devices = NULL;
710 if (type == GDK_DEVICE_TYPE_MASTER)
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);
721 gdk_x11_device_manager_core_get_client_pointer (GdkDeviceManager *device_manager)
723 GdkX11DeviceManagerCore *device_manager_core;
725 device_manager_core = (GdkX11DeviceManagerCore *) device_manager;
726 return device_manager_core->core_pointer;
730 _gdk_x11_event_translate_keyboard_string (GdkEventKey *event)
735 /* Fill in event->string crudely, since various programs
738 event->string = NULL;
740 if (event->keyval != GDK_KEY_VoidSymbol)
741 c = gdk_keyval_to_unicode (event->keyval);
748 /* Apply the control key - Taken from Xlib
750 if (event->state & GDK_CONTROL_MASK)
752 if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
755 event->string = g_memdup ("\0\0", 2);
760 else if (c >= '3' && c <= '7') c -= ('3' - '\033');
761 else if (c == '8') c = '\177';
762 else if (c == '/') c = '_' & 0x1F;
765 len = g_unichar_to_utf8 (c, buf);
768 event->string = g_locale_from_utf8 (buf, len,
769 NULL, &bytes_written,
772 event->length = bytes_written;
774 else if (event->keyval == GDK_KEY_Escape)
777 event->string = g_strdup ("\033");
779 else if (event->keyval == GDK_KEY_Return ||
780 event->keyval == GDK_KEY_KP_Enter)
783 event->string = g_strdup ("\r");
789 event->string = g_strdup ("");
793 /* We only care about focus events that indicate that _this_
794 * window (not a ancestor or child) got or lost the focus
797 _gdk_device_manager_core_handle_focus (GdkWindow *window,
800 GdkDevice *source_device,
805 GdkToplevelX11 *toplevel;
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));
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]));
818 toplevel = _gdk_x11_window_get_toplevel (window);
823 if (toplevel->focus_window == original)
826 had_focus = HAS_FOCUS (toplevel);
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.
839 if (toplevel->has_pointer &&
840 mode != NotifyGrab &&
841 mode != NotifyUngrab)
842 toplevel->has_pointer_focus = (focus_in) ? FALSE : TRUE;
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
854 if (mode != NotifyWhileGrabbed)
855 toplevel->has_focus = (focus_in) ? TRUE : FALSE;
858 /* The X server sends NotifyPointer/NotifyGrab,
859 * but the pointer focus is ignored while a
862 if (mode != NotifyGrab &&
863 mode != NotifyUngrab)
864 toplevel->has_pointer_focus = (focus_in) ? TRUE : FALSE;
867 case NotifyPointerRoot:
868 case NotifyDetailNone:
873 if (HAS_FOCUS (toplevel) != had_focus)
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);
883 gdk_event_set_source_device (event, source_device);
885 gdk_event_put (event);
886 gdk_event_free (event);