[gtk+/events-refactor: 322/1085] Rip out some gdkevents-x11 code into GdkDeviceManagerCore.
- From: Carlos Garnacho <carlosg src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gtk+/events-refactor: 322/1085] Rip out some gdkevents-x11 code into GdkDeviceManagerCore.
- Date: Tue, 29 Sep 2009 10:45:10 +0000 (UTC)
commit 7dfbe5cc85b5140f5619f5533cf4ffd9cace38f7
Author: Carlos Garnacho <carlosg gnome org>
Date: Thu May 28 01:45:02 2009 +0200
Rip out some gdkevents-x11 code into GdkDeviceManagerCore.
GdkDeviceManagerCore now implements the GdkEventTranslator interface, code was
taken from gdkevents-x11.c so it translates XEvents related to input devices
into GdkEvents.
gdk/x11/gdkdevicemanager-core.c | 1027 ++++++++++++++++++++++++++++++++++++++-
1 files changed, 1026 insertions(+), 1 deletions(-)
---
diff --git a/gdk/x11/gdkdevicemanager-core.c b/gdk/x11/gdkdevicemanager-core.c
index 37cdb87..2624847 100644
--- a/gdk/x11/gdkdevicemanager-core.c
+++ b/gdk/x11/gdkdevicemanager-core.c
@@ -20,7 +20,17 @@
#include <gdk/gdktypes.h>
#include <gdk/gdkdevicemanager.h>
#include "gdkdevicemanager-core.h"
+#include "gdkeventtranslator.h"
#include "gdkinputprivate.h"
+#include "gdkkeysyms.h"
+
+#ifdef HAVE_XKB
+#include <X11/XKBlib.h>
+#endif
+
+
+#define HAS_FOCUS(toplevel) \
+ ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
static GdkDeviceAxis gdk_input_core_axes[] = {
{ GDK_AXIS_X, 0, 0 },
@@ -30,8 +40,17 @@ static GdkDeviceAxis gdk_input_core_axes[] = {
static GList * gdk_device_manager_core_get_devices (GdkDeviceManager *device_manager,
GdkDeviceType type);
+static void gdk_device_manager_event_translator_init (GdkEventTranslatorIface *iface);
+
+static gboolean gdk_device_manager_translate_event (GdkEventTranslator *translator,
+ GdkDisplay *display,
+ GdkEvent *event,
+ XEvent *xevent);
-G_DEFINE_TYPE (GdkDeviceManagerCore, gdk_device_manager_core, GDK_TYPE_DEVICE_MANAGER)
+
+G_DEFINE_TYPE_WITH_CODE (GdkDeviceManagerCore, gdk_device_manager_core, GDK_TYPE_DEVICE_MANAGER,
+ G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
+ gdk_device_manager_event_translator_init))
static void
gdk_device_manager_core_class_init (GdkDeviceManagerCoreClass *klass)
@@ -41,6 +60,12 @@ gdk_device_manager_core_class_init (GdkDeviceManagerCoreClass *klass)
device_manager_class->get_devices = gdk_device_manager_core_get_devices;
}
+static void
+gdk_device_manager_event_translator_init (GdkEventTranslatorIface *iface)
+{
+ iface->translate_event = gdk_device_manager_translate_event;
+}
+
static GdkDevice *
create_core_pointer (GdkDisplay *display)
{
@@ -73,6 +98,1006 @@ gdk_device_manager_core_init (GdkDeviceManagerCore *device_manager)
device_manager->core_pointer = create_core_pointer (display);
}
+static void
+get_real_window (GdkDisplay *display,
+ XEvent *event,
+ GdkWindow **event_window,
+ GdkWindow **filter_window)
+{
+ Window event_xwindow, filter_xwindow;
+
+ event_xwindow = None;
+ filter_xwindow = None;
+
+ /* Core events all have an event->xany.window field, but that's
+ * not true for extension events
+ */
+ if (event->type >= KeyPress &&
+ event->type <= MappingNotify)
+ {
+ filter_xwindow = event->xany.window;
+ switch (event->type)
+ {
+ case CreateNotify:
+ event_xwindow = event->xcreatewindow.window;
+ break;
+ case DestroyNotify:
+ event_xwindow = event->xdestroywindow.window;
+ break;
+ case UnmapNotify:
+ event_xwindow = event->xunmap.window;
+ break;
+ case MapNotify:
+ event_xwindow = event->xmap.window;
+ break;
+ case MapRequest:
+ event_xwindow = event->xmaprequest.window;
+ break;
+ case ReparentNotify:
+ event_xwindow = event->xreparent.window;
+ break;
+ case ConfigureNotify:
+ event_xwindow = event->xconfigure.window;
+ break;
+ case ConfigureRequest:
+ event_xwindow = event->xconfigurerequest.window;
+ break;
+ case GravityNotify:
+ event_xwindow = event->xgravity.window;
+ break;
+ case CirculateNotify:
+ event_xwindow = event->xcirculate.window;
+ break;
+ case CirculateRequest:
+ event_xwindow = event->xcirculaterequest.window;
+ break;
+ default:
+ event_xwindow = event->xany.window;
+ }
+ }
+#if 0
+ else
+ {
+ GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+ GSList *tmp_list;
+
+ for (tmp_list = display_x11->event_types;
+ tmp_list;
+ tmp_list = tmp_list->next)
+ {
+ GdkEventTypeX11 *event_type = tmp_list->data;
+
+ if (event->type >= event_type->base &&
+ event->type < event_type->base + event_type->n_events)
+ {
+ *event_xwindow = event->xany.window;
+ *filter_xwindow = event->xany.window;
+ }
+ }
+ }
+#endif
+
+ /* Now find out the corresponding GdkWindows */
+ *event_window = gdk_window_lookup_for_display (display, event_xwindow);
+
+ /* We may receive events such as NoExpose/GraphicsExpose
+ * and ShmCompletion for pixmaps
+ */
+ if (*event_window && !GDK_IS_WINDOW (*event_window))
+ *event_window = NULL;
+
+ /* We always run the filters for the window where the event
+ * is delivered, not the window that it relates to
+ */
+ if (filter_xwindow == event_xwindow)
+ *filter_window = *event_window;
+ else
+ {
+ *filter_window = gdk_window_lookup_for_display (display, filter_xwindow);
+
+ if (*filter_window && !GDK_IS_WINDOW (*filter_window))
+ *filter_window = NULL;
+ }
+}
+
+static void
+translate_key_event (GdkDisplay *display,
+ GdkEvent *event,
+ XEvent *xevent)
+{
+ GdkKeymap *keymap = gdk_keymap_get_for_display (display);
+ gunichar c = 0;
+ gchar buf[7];
+
+ event->key.type = xevent->xany.type == KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
+ event->key.time = xevent->xkey.time;
+
+ event->key.state = (GdkModifierType) xevent->xkey.state;
+ event->key.group = _gdk_x11_get_group_for_state (display, xevent->xkey.state);
+ event->key.hardware_keycode = xevent->xkey.keycode;
+
+ event->key.keyval = GDK_VoidSymbol;
+
+ gdk_keymap_translate_keyboard_state (keymap,
+ event->key.hardware_keycode,
+ event->key.state,
+ event->key.group,
+ &event->key.keyval,
+ NULL, NULL, NULL);
+
+ _gdk_keymap_add_virtual_modifiers (keymap, &event->key.state);
+ event->key.is_modifier = _gdk_keymap_key_is_modifier (keymap, event->key.hardware_keycode);
+
+ /* Fill in event->string crudely, since various programs
+ * depend on it.
+ */
+ event->key.string = NULL;
+
+ if (event->key.keyval != GDK_VoidSymbol)
+ c = gdk_keyval_to_unicode (event->key.keyval);
+
+ if (c)
+ {
+ gsize bytes_written;
+ gint len;
+
+ /* Apply the control key - Taken from Xlib
+ */
+ if (event->key.state & GDK_CONTROL_MASK)
+ {
+ if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
+ else if (c == '2')
+ {
+ event->key.string = g_memdup ("\0\0", 2);
+ event->key.length = 1;
+ buf[0] = '\0';
+ goto out;
+ }
+ else if (c >= '3' && c <= '7') c -= ('3' - '\033');
+ else if (c == '8') c = '\177';
+ else if (c == '/') c = '_' & 0x1F;
+ }
+
+ len = g_unichar_to_utf8 (c, buf);
+ buf[len] = '\0';
+
+ event->key.string = g_locale_from_utf8 (buf, len,
+ NULL, &bytes_written,
+ NULL);
+ if (event->key.string)
+ event->key.length = bytes_written;
+ }
+ else if (event->key.keyval == GDK_Escape)
+ {
+ event->key.length = 1;
+ event->key.string = g_strdup ("\033");
+ }
+ else if (event->key.keyval == GDK_Return ||
+ event->key.keyval == GDK_KP_Enter)
+ {
+ event->key.length = 1;
+ event->key.string = g_strdup ("\r");
+ }
+
+ if (!event->key.string)
+ {
+ event->key.length = 0;
+ event->key.string = g_strdup ("");
+ }
+
+ out:
+#ifdef G_ENABLE_DEBUG
+ if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
+ {
+ g_message ("%s:\t\twindow: %ld key: %12s %d",
+ event->type == GDK_KEY_PRESS ? "key press " : "key release",
+ xevent->xkey.window,
+ event->key.keyval ? gdk_keyval_name (event->key.keyval) : "(none)",
+ event->key.keyval);
+
+ if (event->key.length > 0)
+ g_message ("\t\tlength: %4d string: \"%s\"",
+ event->key.length, buf);
+ }
+#endif /* G_ENABLE_DEBUG */
+ return;
+}
+
+#ifdef G_ENABLE_DEBUG
+static const char notify_modes[][19] = {
+ "NotifyNormal",
+ "NotifyGrab",
+ "NotifyUngrab",
+ "NotifyWhileGrabbed"
+};
+
+static const char notify_details[][23] = {
+ "NotifyAncestor",
+ "NotifyVirtual",
+ "NotifyInferior",
+ "NotifyNonlinear",
+ "NotifyNonlinearVirtual",
+ "NotifyPointer",
+ "NotifyPointerRoot",
+ "NotifyDetailNone"
+};
+#endif
+
+static void
+set_user_time (GdkWindow *window,
+ GdkEvent *event)
+{
+ g_return_if_fail (event != NULL);
+
+ window = gdk_window_get_toplevel (event->client.window);
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ /* If an event doesn't have a valid timestamp, we shouldn't use it
+ * to update the latest user interaction time.
+ */
+ if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
+ gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+ gdk_event_get_time (event));
+}
+
+static void
+generate_focus_event (GdkWindow *window,
+ gboolean in)
+{
+ GdkEvent event;
+
+ event.type = GDK_FOCUS_CHANGE;
+ event.focus_change.window = window;
+ event.focus_change.send_event = FALSE;
+ event.focus_change.in = in;
+
+ gdk_event_put (&event);
+}
+
+static gboolean
+set_screen_from_root (GdkDisplay *display,
+ GdkEvent *event,
+ Window xrootwin)
+{
+ GdkScreen *screen;
+
+ screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
+
+ if (screen)
+ {
+ gdk_event_set_screen (event, screen);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+gdk_device_manager_translate_event (GdkEventTranslator *translator,
+ GdkDisplay *display,
+ GdkEvent *event,
+ XEvent *xevent)
+{
+ GdkDeviceManagerCore *device_manager;
+ GdkWindow *window;
+ GdkWindowObject *window_private;
+ GdkWindow *filter_window;
+ GdkWindowImplX11 *window_impl = NULL;
+ gboolean return_val;
+ gint xoffset = 0, yoffset = 0;
+ GdkScreen *screen = NULL;
+ GdkScreenX11 *screen_x11 = NULL;
+ GdkToplevelX11 *toplevel = NULL;
+ GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+
+ device_manager = GDK_DEVICE_MANAGER_CORE (translator);
+ return_val = FALSE;
+
+ /* init these, since the done: block uses them */
+ window = NULL;
+ window_private = NULL;
+ event->any.window = NULL;
+
+ /* Run default filters */
+#if 0
+ if (_gdk_default_filters)
+ {
+ /* Apply global filters */
+ GdkFilterReturn result;
+ result = gdk_event_apply_filters (xevent, event,
+ _gdk_default_filters);
+
+ if (result != GDK_FILTER_CONTINUE)
+ {
+ return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
+ goto done;
+ }
+ }
+#endif
+
+ /* Find the GdkWindow that this event relates to.
+ * Basically this means substructure events
+ * are reported same as structure events
+ */
+ get_real_window (display, xevent, &window, &filter_window);
+ window_private = (GdkWindowObject *) window;
+
+ if (window)
+ {
+ screen = GDK_WINDOW_SCREEN (window);
+ screen_x11 = GDK_SCREEN_X11 (screen);
+ toplevel = _gdk_x11_window_get_toplevel (window);
+
+ window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
+
+ /* Move key events on focus window to the real toplevel, and
+ * filter out all other events on focus window
+ */
+ /* FIXME: is this needed? */
+#if 0
+ if (toplevel && xwindow == toplevel->focus_window)
+ {
+ switch (xevent->type)
+ {
+ case KeyPress:
+ case KeyRelease:
+ xwindow = GDK_WINDOW_XID (window);
+ xevent->xany.window = xwindow;
+ break;
+ default:
+ return FALSE;
+ }
+ }
+#endif
+
+ g_object_ref (window);
+ }
+
+ event->any.window = window;
+ event->any.send_event = xevent->xany.send_event ? TRUE : FALSE;
+
+ if (window_private && GDK_WINDOW_DESTROYED (window))
+ {
+ if (xevent->type != DestroyNotify)
+ {
+ return_val = FALSE;
+ goto done;
+ }
+ }
+#if 0
+ else if (filter_window)
+ {
+ /* Apply per-window filters */
+ GdkWindowObject *filter_private = (GdkWindowObject *) filter_window;
+ GdkFilterReturn result;
+
+ if (filter_private->filters)
+ {
+ g_object_ref (filter_window);
+
+ result = gdk_event_apply_filters (xevent, event,
+ filter_private->filters);
+
+ g_object_unref (filter_window);
+
+ if (result != GDK_FILTER_CONTINUE)
+ {
+ return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
+ goto done;
+ }
+ }
+ }
+#endif
+
+#if 0
+ if (screen_x11 && screen_x11->wmspec_check_window != None &&
+ xwindow == screen_x11->wmspec_check_window)
+ {
+ if (xevent->type == DestroyNotify)
+ {
+ screen_x11->wmspec_check_window = None;
+ g_free (screen_x11->window_manager_name);
+ screen_x11->window_manager_name = g_strdup ("unknown");
+
+ /* careful, reentrancy */
+ _gdk_x11_screen_window_manager_changed (GDK_SCREEN (screen_x11));
+ }
+
+ /* Eat events on this window unless someone had wrapped
+ * it as a foreign window
+ */
+ if (window == NULL)
+ {
+ return_val = FALSE;
+ goto done;
+ }
+ }
+#endif
+
+ if (window &&
+ (xevent->type == MotionNotify ||
+ xevent->type == ButtonRelease))
+ {
+ if (_gdk_moveresize_handle_event (xevent))
+ {
+ return_val = FALSE;
+ goto done;
+ }
+ }
+
+ /* We do a "manual" conversion of the XEvent to a
+ * GdkEvent. The structures are mostly the same so
+ * the conversion is fairly straightforward. We also
+ * optionally print debugging info regarding events
+ * received.
+ */
+
+ return_val = TRUE;
+
+ if (window)
+ _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
+
+ switch (xevent->type)
+ {
+ case KeyPress:
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+ translate_key_event (display, event, xevent);
+ set_user_time (window, event);
+ break;
+
+ case KeyRelease:
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ /* Emulate detectable auto-repeat by checking to see
+ * if the next event is a key press with the same
+ * keycode and timestamp, and if so, ignoring the event.
+ */
+
+ if (!display_x11->have_xkb_autorepeat && XPending (xevent->xkey.display))
+ {
+ XEvent next_event;
+
+ XPeekEvent (xevent->xkey.display, &next_event);
+
+ if (next_event.type == KeyPress &&
+ next_event.xkey.keycode == xevent->xkey.keycode &&
+ next_event.xkey.time == xevent->xkey.time)
+ {
+ return_val = FALSE;
+ break;
+ }
+ }
+
+ translate_key_event (display, event, xevent);
+ break;
+
+ case ButtonPress:
+ GDK_NOTE (EVENTS,
+ g_message ("button press:\t\twindow: %ld x,y: %d %d button: %d",
+ xevent->xbutton.window,
+ xevent->xbutton.x, xevent->xbutton.y,
+ xevent->xbutton.button));
+
+ if (window_private == NULL ||
+ ((window_private->extension_events != 0) &&
+ display_x11->input_ignore_core))
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ /* If we get a ButtonPress event where the button is 4 or 5,
+ it's a Scroll event */
+ switch (xevent->xbutton.button)
+ {
+ case 4: /* up */
+ case 5: /* down */
+ case 6: /* left */
+ case 7: /* right */
+ event->scroll.type = GDK_SCROLL;
+
+ if (xevent->xbutton.button == 4)
+ event->scroll.direction = GDK_SCROLL_UP;
+ else if (xevent->xbutton.button == 5)
+ event->scroll.direction = GDK_SCROLL_DOWN;
+ else if (xevent->xbutton.button == 6)
+ event->scroll.direction = GDK_SCROLL_LEFT;
+ else
+ event->scroll.direction = GDK_SCROLL_RIGHT;
+
+ event->scroll.window = window;
+ event->scroll.time = xevent->xbutton.time;
+ event->scroll.x = xevent->xbutton.x + xoffset;
+ event->scroll.y = xevent->xbutton.y + yoffset;
+ event->scroll.x_root = (gfloat) xevent->xbutton.x_root;
+ event->scroll.y_root = (gfloat) xevent->xbutton.y_root;
+ event->scroll.state = (GdkModifierType) xevent->xbutton.state;
+ event->scroll.device = device_manager->core_pointer;
+
+ if (!set_screen_from_root (display, event, xevent->xbutton.root))
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ break;
+
+ default:
+ event->button.type = GDK_BUTTON_PRESS;
+ event->button.window = window;
+ event->button.time = xevent->xbutton.time;
+ event->button.x = xevent->xbutton.x + xoffset;
+ event->button.y = xevent->xbutton.y + yoffset;
+ event->button.x_root = (gfloat) xevent->xbutton.x_root;
+ event->button.y_root = (gfloat) xevent->xbutton.y_root;
+ event->button.axes = NULL;
+ event->button.state = (GdkModifierType) xevent->xbutton.state;
+ event->button.button = xevent->xbutton.button;
+ event->button.device = device_manager->core_pointer;
+
+ if (!set_screen_from_root (display, event, xevent->xbutton.root))
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ _gdk_event_button_generate (display, event);
+ break;
+ }
+
+ set_user_time (window, event);
+
+ _gdk_xgrab_check_button_event (window, xevent);
+ break;
+
+ case ButtonRelease:
+ GDK_NOTE (EVENTS,
+ g_message ("button release:\twindow: %ld x,y: %d %d button: %d",
+ xevent->xbutton.window,
+ xevent->xbutton.x, xevent->xbutton.y,
+ xevent->xbutton.button));
+
+ if (window_private == NULL ||
+ ((window_private->extension_events != 0) &&
+ display_x11->input_ignore_core))
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ /* We treat button presses as scroll wheel events, so ignore the release */
+ if (xevent->xbutton.button == 4 || xevent->xbutton.button == 5 ||
+ xevent->xbutton.button == 6 || xevent->xbutton.button == 7)
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ event->button.type = GDK_BUTTON_RELEASE;
+ event->button.window = window;
+ event->button.time = xevent->xbutton.time;
+ event->button.x = xevent->xbutton.x + xoffset;
+ event->button.y = xevent->xbutton.y + yoffset;
+ event->button.x_root = (gfloat) xevent->xbutton.x_root;
+ event->button.y_root = (gfloat) xevent->xbutton.y_root;
+ event->button.axes = NULL;
+ event->button.state = (GdkModifierType) xevent->xbutton.state;
+ event->button.button = xevent->xbutton.button;
+ event->button.device = device_manager->core_pointer;
+
+ if (!set_screen_from_root (display, event, xevent->xbutton.root))
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ _gdk_xgrab_check_button_event (window, xevent);
+ break;
+
+ case MotionNotify:
+ GDK_NOTE (EVENTS,
+ g_message ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s",
+ xevent->xmotion.window,
+ xevent->xmotion.x, xevent->xmotion.y,
+ (xevent->xmotion.is_hint) ? "true" : "false"));
+
+ if (window_private == NULL ||
+ ((window_private->extension_events != 0) &&
+ display_x11->input_ignore_core))
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ event->motion.type = GDK_MOTION_NOTIFY;
+ event->motion.window = window;
+ event->motion.time = xevent->xmotion.time;
+ event->motion.x = xevent->xmotion.x + xoffset;
+ event->motion.y = xevent->xmotion.y + yoffset;
+ event->motion.x_root = (gfloat) xevent->xmotion.x_root;
+ event->motion.y_root = (gfloat) xevent->xmotion.y_root;
+ event->motion.axes = NULL;
+ event->motion.state = (GdkModifierType) xevent->xmotion.state;
+ event->motion.is_hint = xevent->xmotion.is_hint;
+ event->motion.device = device_manager->core_pointer;
+
+ if (!set_screen_from_root (display, event, xevent->xbutton.root))
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ break;
+
+ case EnterNotify:
+ GDK_NOTE (EVENTS,
+ g_message ("enter notify:\t\twindow: %ld detail: %d subwin: %ld",
+ xevent->xcrossing.window,
+ xevent->xcrossing.detail,
+ xevent->xcrossing.subwindow));
+
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ if (!set_screen_from_root (display, event, xevent->xbutton.root))
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ /* Handle focusing (in the case where no window manager is running */
+ if (toplevel && xevent->xcrossing.detail != NotifyInferior)
+ {
+ toplevel->has_pointer = TRUE;
+
+ if (xevent->xcrossing.focus && !toplevel->has_focus_window)
+ {
+ gboolean had_focus = HAS_FOCUS (toplevel);
+
+ toplevel->has_pointer_focus = TRUE;
+
+ if (HAS_FOCUS (toplevel) != had_focus)
+ generate_focus_event (window, TRUE);
+ }
+ }
+
+ /* Tell XInput stuff about it if appropriate */
+ if (window_private &&
+ !GDK_WINDOW_DESTROYED (window) &&
+ window_private->extension_events != 0)
+ _gdk_input_enter_event (&xevent->xcrossing, window);
+
+ event->crossing.type = GDK_ENTER_NOTIFY;
+ event->crossing.window = window;
+
+ /* If the subwindow field of the XEvent is non-NULL, then
+ * lookup the corresponding GdkWindow.
+ */
+ if (xevent->xcrossing.subwindow != None)
+ event->crossing.subwindow = gdk_window_lookup_for_display (display, xevent->xcrossing.subwindow);
+ else
+ event->crossing.subwindow = NULL;
+
+ event->crossing.time = xevent->xcrossing.time;
+ event->crossing.x = xevent->xcrossing.x + xoffset;
+ event->crossing.y = xevent->xcrossing.y + yoffset;
+ event->crossing.x_root = xevent->xcrossing.x_root;
+ event->crossing.y_root = xevent->xcrossing.y_root;
+
+ /* Translate the crossing mode into Gdk terms.
+ */
+ switch (xevent->xcrossing.mode)
+ {
+ case NotifyNormal:
+ event->crossing.mode = GDK_CROSSING_NORMAL;
+ break;
+ case NotifyGrab:
+ event->crossing.mode = GDK_CROSSING_GRAB;
+ break;
+ case NotifyUngrab:
+ event->crossing.mode = GDK_CROSSING_UNGRAB;
+ break;
+ };
+
+ /* Translate the crossing detail into Gdk terms.
+ */
+ switch (xevent->xcrossing.detail)
+ {
+ case NotifyInferior:
+ event->crossing.detail = GDK_NOTIFY_INFERIOR;
+ break;
+ case NotifyAncestor:
+ event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+ break;
+ case NotifyVirtual:
+ event->crossing.detail = GDK_NOTIFY_VIRTUAL;
+ break;
+ case NotifyNonlinear:
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR;
+ break;
+ case NotifyNonlinearVirtual:
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+ break;
+ default:
+ event->crossing.detail = GDK_NOTIFY_UNKNOWN;
+ break;
+ }
+
+ event->crossing.focus = xevent->xcrossing.focus;
+ event->crossing.state = xevent->xcrossing.state;
+
+ break;
+
+ case LeaveNotify:
+ GDK_NOTE (EVENTS,
+ g_message ("leave notify:\t\twindow: %ld detail: %d subwin: %ld",
+ xevent->xcrossing.window,
+ xevent->xcrossing.detail, xevent->xcrossing.subwindow));
+
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ if (!set_screen_from_root (display, event, xevent->xbutton.root))
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ /* Handle focusing (in the case where no window manager is running */
+ if (toplevel && xevent->xcrossing.detail != NotifyInferior)
+ {
+ toplevel->has_pointer = FALSE;
+
+ if (xevent->xcrossing.focus && !toplevel->has_focus_window)
+ {
+ gboolean had_focus = HAS_FOCUS (toplevel);
+
+ toplevel->has_pointer_focus = FALSE;
+
+ if (HAS_FOCUS (toplevel) != had_focus)
+ generate_focus_event (window, FALSE);
+ }
+ }
+
+ event->crossing.type = GDK_LEAVE_NOTIFY;
+ event->crossing.window = window;
+
+ /* If the subwindow field of the XEvent is non-NULL, then
+ * lookup the corresponding GdkWindow.
+ */
+ if (xevent->xcrossing.subwindow != None)
+ event->crossing.subwindow = gdk_window_lookup_for_display (display, xevent->xcrossing.subwindow);
+ else
+ event->crossing.subwindow = NULL;
+
+ event->crossing.time = xevent->xcrossing.time;
+ event->crossing.x = xevent->xcrossing.x + xoffset;
+ event->crossing.y = xevent->xcrossing.y + yoffset;
+ event->crossing.x_root = xevent->xcrossing.x_root;
+ event->crossing.y_root = xevent->xcrossing.y_root;
+
+ /* Translate the crossing mode into Gdk terms.
+ */
+ switch (xevent->xcrossing.mode)
+ {
+ case NotifyNormal:
+ event->crossing.mode = GDK_CROSSING_NORMAL;
+ break;
+ case NotifyGrab:
+ event->crossing.mode = GDK_CROSSING_GRAB;
+ break;
+ case NotifyUngrab:
+ event->crossing.mode = GDK_CROSSING_UNGRAB;
+ break;
+ };
+
+ /* Translate the crossing detail into Gdk terms.
+ */
+ switch (xevent->xcrossing.detail)
+ {
+ case NotifyInferior:
+ event->crossing.detail = GDK_NOTIFY_INFERIOR;
+ break;
+ case NotifyAncestor:
+ event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+ break;
+ case NotifyVirtual:
+ event->crossing.detail = GDK_NOTIFY_VIRTUAL;
+ break;
+ case NotifyNonlinear:
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR;
+ break;
+ case NotifyNonlinearVirtual:
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+ break;
+ default:
+ event->crossing.detail = GDK_NOTIFY_UNKNOWN;
+ break;
+ }
+
+ event->crossing.focus = xevent->xcrossing.focus;
+ event->crossing.state = xevent->xcrossing.state;
+
+ break;
+
+ /* We only care about focus events that indicate that _this_
+ * window (not a ancestor or child) got or lost the focus
+ */
+ case FocusIn:
+ GDK_NOTE (EVENTS,
+ g_message ("focus in:\t\twindow: %ld, detail: %s, mode: %s",
+ xevent->xfocus.window,
+ notify_details[xevent->xfocus.detail],
+ notify_modes[xevent->xfocus.mode]));
+
+ if (toplevel)
+ {
+ gboolean had_focus = HAS_FOCUS (toplevel);
+
+ switch (xevent->xfocus.detail)
+ {
+ case NotifyAncestor:
+ case NotifyVirtual:
+ /* When the focus moves from an ancestor of the window to
+ * the window or a descendent of the window, *and* the
+ * pointer is inside the window, then we were previously
+ * receiving keystroke events in the has_pointer_focus
+ * case and are now receiving them in the
+ * has_focus_window case.
+ */
+ if (toplevel->has_pointer &&
+ xevent->xfocus.mode != NotifyGrab &&
+ xevent->xfocus.mode != NotifyUngrab)
+ toplevel->has_pointer_focus = FALSE;
+
+ /* fall through */
+ case NotifyNonlinear:
+ case NotifyNonlinearVirtual:
+ if (xevent->xfocus.mode != NotifyGrab &&
+ xevent->xfocus.mode != NotifyUngrab)
+ toplevel->has_focus_window = TRUE;
+ /* We pretend that the focus moves to the grab
+ * window, so we pay attention to NotifyGrab
+ * NotifyUngrab, and ignore NotifyWhileGrabbed
+ */
+ if (xevent->xfocus.mode != NotifyWhileGrabbed)
+ toplevel->has_focus = TRUE;
+ break;
+ case NotifyPointer:
+ /* The X server sends NotifyPointer/NotifyGrab,
+ * but the pointer focus is ignored while a
+ * grab is in effect
+ */
+ if (xevent->xfocus.mode != NotifyGrab &&
+ xevent->xfocus.mode != NotifyUngrab)
+ toplevel->has_pointer_focus = TRUE;
+ break;
+ case NotifyInferior:
+ case NotifyPointerRoot:
+ case NotifyDetailNone:
+ break;
+ }
+
+ if (HAS_FOCUS (toplevel) != had_focus)
+ generate_focus_event (window, TRUE);
+ }
+ break;
+ case FocusOut:
+ GDK_NOTE (EVENTS,
+ g_message ("focus out:\t\twindow: %ld, detail: %s, mode: %s",
+ xevent->xfocus.window,
+ notify_details[xevent->xfocus.detail],
+ notify_modes[xevent->xfocus.mode]));
+
+ if (toplevel)
+ {
+ gboolean had_focus = HAS_FOCUS (toplevel);
+
+ switch (xevent->xfocus.detail)
+ {
+ case NotifyAncestor:
+ case NotifyVirtual:
+ /* When the focus moves from the window or a descendent
+ * of the window to an ancestor of the window, *and* the
+ * pointer is inside the window, then we were previously
+ * receiving keystroke events in the has_focus_window
+ * case and are now receiving them in the
+ * has_pointer_focus case.
+ */
+ if (toplevel->has_pointer &&
+ xevent->xfocus.mode != NotifyGrab &&
+ xevent->xfocus.mode != NotifyUngrab)
+ toplevel->has_pointer_focus = TRUE;
+
+ /* fall through */
+ case NotifyNonlinear:
+ case NotifyNonlinearVirtual:
+ if (xevent->xfocus.mode != NotifyGrab &&
+ xevent->xfocus.mode != NotifyUngrab)
+ toplevel->has_focus_window = FALSE;
+ if (xevent->xfocus.mode != NotifyWhileGrabbed)
+ toplevel->has_focus = FALSE;
+ break;
+ case NotifyPointer:
+ if (xevent->xfocus.mode != NotifyGrab &&
+ xevent->xfocus.mode != NotifyUngrab)
+ toplevel->has_pointer_focus = FALSE;
+ break;
+ case NotifyInferior:
+ case NotifyPointerRoot:
+ case NotifyDetailNone:
+ break;
+ }
+
+ if (HAS_FOCUS (toplevel) != had_focus)
+ generate_focus_event (window, FALSE);
+ }
+ break;
+
+ default:
+#ifdef HAVE_XKB
+ if (xevent->type == display_x11->xkb_event_type)
+ {
+ XkbEvent *xkb_event = (XkbEvent *)xevent;
+
+ switch (xkb_event->any.xkb_type)
+ {
+ case XkbNewKeyboardNotify:
+ case XkbMapNotify:
+ _gdk_keymap_keys_changed (display);
+
+ return_val = FALSE;
+ break;
+
+ case XkbStateNotify:
+ _gdk_keymap_state_changed (display, xevent);
+ break;
+ }
+ }
+ else
+#endif
+ return_val = FALSE;
+ }
+
+ done:
+ if (return_val)
+ {
+ if (event->any.window)
+ g_object_ref (event->any.window);
+
+ if (((event->any.type == GDK_ENTER_NOTIFY) ||
+ (event->any.type == GDK_LEAVE_NOTIFY)) &&
+ (event->crossing.subwindow != NULL))
+ g_object_ref (event->crossing.subwindow);
+ }
+ else
+ {
+ /* Mark this event as having no resources to be freed */
+ event->any.window = NULL;
+ event->any.type = GDK_NOTHING;
+ }
+
+ if (window)
+ g_object_unref (window);
+
+ return return_val;
+}
+
static GList *
gdk_device_manager_core_get_devices (GdkDeviceManager *device_manager,
GdkDeviceType type)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]