[gtk+/client-side-windows: 215/284] Handle crossing events with subwindows unknown to gdk
- From: Alexander Larsson <alexl src gnome org>
- To: svn-commits-list gnome org
- Subject: [gtk+/client-side-windows: 215/284] Handle crossing events with subwindows unknown to gdk
- Date: Thu, 2 Apr 2009 14:18:00 -0400 (EDT)
commit 53269a5042878a55ee19915c52207b278849f031
Author: Alexander Larsson <alexl redhat com>
Date: Tue Feb 3 12:24:30 2009 +0100
Handle crossing events with subwindows unknown to gdk
If we get crossing events with subwindow unexpectedly being NULL
that means there is a native subwindow that gdk doesn't know about.
We track these and forward them, with the correct virtual window
events inbetween.
This is important to get right, as metacity uses gdk for the frame
windows, but gdk doesn't know about the client windows reparented
into the frame.
---
gdk/gdkwindow.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 142 insertions(+), 22 deletions(-)
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index e3500bc..9b18240 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -7549,6 +7549,32 @@ point_in_window (GdkWindowObject *window,
x, y));
}
+static GdkWindow *
+convert_coords_to_toplevel (GdkWindow *window,
+ double child_x, double child_y,
+ double *toplevel_x, double *toplevel_y)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ gdouble x, y;
+
+ x = child_x;
+ y = child_y;
+
+ while (private->parent != NULL &&
+ (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
+ {
+ x += private->x;
+ y += private->y;
+ private = private->parent;
+ }
+
+ *toplevel_x = x;
+ *toplevel_y = y;
+
+ return (GdkWindow *)private;
+}
+
+
static void
convert_toplevel_coords_to_window (GdkWindow *window,
gdouble toplevel_x,
@@ -8226,25 +8252,110 @@ proxy_pointer_event (GdkDisplay *display,
GdkEvent *source_event,
gulong serial)
{
- GdkWindow *toplevel_window;
+ GdkWindow *toplevel_window, *event_window;
GdkWindow *pointer_window;
GdkEvent *event;
guint state;
gdouble toplevel_x, toplevel_y;
guint32 time_;
- toplevel_window = source_event->any.window;
+ event_window = source_event->any.window;
gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
gdk_event_get_state (source_event, &state);
time_ = gdk_event_get_time (source_event);
+ toplevel_window = convert_coords_to_toplevel (event_window,
+ toplevel_x, toplevel_y,
+ &toplevel_x, &toplevel_y);
+
+
+ /* If we get crossing events with subwindow unexpectedly being NULL
+ that means there is a native subwindow that gdk doesn't know about.
+ We track these and forward them, with the correct virtual window
+ events inbetween.
+ This is important to get right, as metacity uses gdk for the frame
+ windows, but gdk doesn't know about the client windows reparented
+ into the frame. */
+ if (((source_event->type == GDK_LEAVE_NOTIFY &&
+ source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
+ (source_event->type == GDK_ENTER_NOTIFY &&
+ (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
+ source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
+ source_event->crossing.subwindow == NULL)
+ {
+ /* Left for an unknown (to gdk) subwindow */
+
+ /* Send leave events from window under pointer to event window
+ that will get the subwindow == NULL window */
+ _gdk_syntesize_crossing_events (display,
+ display->pointer_info.window_under_pointer,
+ event_window,
+ source_event->crossing.mode,
+ toplevel_x, toplevel_y,
+ state, time_,
+ source_event,
+ serial);
+
+ /* Send subwindow == NULL event */
+ send_crossing_event (display,
+ (GdkWindowObject *)toplevel_window,
+ (GdkWindowObject *)event_window,
+ source_event->type,
+ source_event->crossing.mode,
+ source_event->crossing.detail,
+ NULL,
+ toplevel_x, toplevel_y,
+ state, time_,
+ source_event,
+ serial);
+
+ _gdk_display_set_window_under_pointer (display, NULL);
+ return TRUE;
+ }
+
+ pointer_window = get_pointer_window (display, toplevel_window,
+ toplevel_x, toplevel_y, serial);
+
+ if (((source_event->type == GDK_ENTER_NOTIFY &&
+ source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
+ (source_event->type == GDK_LEAVE_NOTIFY &&
+ (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
+ source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
+ source_event->crossing.subwindow == NULL)
+ {
+ /* Entered from an unknown (to gdk) subwindow */
+
+ /* Send subwindow == NULL event */
+ send_crossing_event (display,
+ (GdkWindowObject *)toplevel_window,
+ (GdkWindowObject *)event_window,
+ source_event->type,
+ source_event->crossing.mode,
+ source_event->crossing.detail,
+ NULL,
+ toplevel_x, toplevel_y,
+ state, time_,
+ source_event,
+ serial);
+
+ /* Send enter events from event window to pointer_window */
+ _gdk_syntesize_crossing_events (display,
+ event_window,
+ pointer_window,
+ source_event->crossing.mode,
+ toplevel_x, toplevel_y,
+ state, time_,
+ source_event,
+ serial);
+ _gdk_display_set_window_under_pointer (display, pointer_window);
+ return TRUE;
+ }
- pointer_window = get_pointer_window (display, toplevel_window, toplevel_x, toplevel_y, serial);
if (display->pointer_info.window_under_pointer != pointer_window)
{
/* Either a toplevel crossing notify that ended up inside a child window,
or a motion notify that got into another child window */
+
/* Different than last time, send crossing events */
-
_gdk_syntesize_crossing_events (display,
display->pointer_info.window_under_pointer,
pointer_window,
@@ -8253,10 +8364,9 @@ proxy_pointer_event (GdkDisplay *display,
state, time_,
source_event,
serial);
-
_gdk_display_set_window_under_pointer (display, pointer_window);
}
- else if (source_event->type == GDK_MOTION_NOTIFY)
+ else
{
GdkWindow *event_win;
guint evmask;
@@ -8483,6 +8593,7 @@ _gdk_windowing_got_event (GdkDisplay *display,
gboolean unlink_event;
guint old_state, old_button;
GdkPointerGrabInfo *button_release_grab;
+ gboolean is_toplevel;
if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
display->last_event_time = gdk_event_get_time (event);
@@ -8511,8 +8622,12 @@ _gdk_windowing_got_event (GdkDisplay *display,
GDK_WINDOW_TYPE (event_private) == GDK_WINDOW_ROOT)
return;
- if (event_private->parent != NULL &&
- GDK_WINDOW_TYPE (event_private->parent) != GDK_WINDOW_ROOT)
+ is_toplevel =
+ event_private->parent == NULL ||
+ GDK_WINDOW_TYPE (event_private->parent) == GDK_WINDOW_ROOT;
+
+ if (!is_toplevel &&
+ (event->type != GDK_ENTER_NOTIFY && event->type != GDK_LEAVE_NOTIFY))
{
GEnumValue *event_type_value, *window_type_value;
@@ -8532,27 +8647,32 @@ _gdk_windowing_got_event (GdkDisplay *display,
return;
}
- /* Store last pointer window and position/state */
- if (event->type == GDK_ENTER_NOTIFY &&
- event->crossing.detail != GDK_NOTIFY_INFERIOR)
+ /* Track toplevel_under_pointer */
+ if (is_toplevel)
{
- if (display->pointer_info.toplevel_under_pointer)
- g_object_unref (display->pointer_info.toplevel_under_pointer);
- display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
- }
- else if (event->type == GDK_LEAVE_NOTIFY &&
- event->crossing.detail != GDK_NOTIFY_INFERIOR &&
- display->pointer_info.toplevel_under_pointer == event_window)
- {
- if (display->pointer_info.toplevel_under_pointer)
- g_object_unref (display->pointer_info.toplevel_under_pointer);
- display->pointer_info.toplevel_under_pointer = NULL;
+ if (event->type == GDK_ENTER_NOTIFY &&
+ event->crossing.detail != GDK_NOTIFY_INFERIOR)
+ {
+ if (display->pointer_info.toplevel_under_pointer)
+ g_object_unref (display->pointer_info.toplevel_under_pointer);
+ display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
+ }
+ else if (event->type == GDK_LEAVE_NOTIFY &&
+ event->crossing.detail != GDK_NOTIFY_INFERIOR &&
+ display->pointer_info.toplevel_under_pointer == event_window)
+ {
+ if (display->pointer_info.toplevel_under_pointer)
+ g_object_unref (display->pointer_info.toplevel_under_pointer);
+ display->pointer_info.toplevel_under_pointer = NULL;
+ }
}
+ /* Store last pointer window and position/state */
old_state = display->pointer_info.state;
old_button = display->pointer_info.button;
gdk_event_get_coords (event, &x, &y);
+ convert_coords_to_toplevel (event_window, x, y, &x, &y);
display->pointer_info.toplevel_x = x;
display->pointer_info.toplevel_y = y;
gdk_event_get_state (event, &display->pointer_info.state);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]