diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c index 399d193999..ff11f086fc 100644 --- a/gdk/gdkdisplay.c +++ b/gdk/gdkdisplay.c @@ -903,6 +903,42 @@ synthesize_crossing_events (GdkDisplay *display, } } +static GdkWindow * +get_current_toplevel (GdkDisplay *display, + int *x_out, int *y_out, + GdkModifierType *state_out) +{ + GdkWindow *pointer_window; + GdkWindowObject *w; + int x, y; + GdkModifierType state; + + pointer_window = _gdk_windowing_window_at_pointer (display, &x, &y, &state); + if (pointer_window != NULL && + (GDK_WINDOW_DESTROYED (pointer_window) || + GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT || + GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN)) + pointer_window = NULL; + + w = (GdkWindowObject *)pointer_window; + if (w) + { + /* Convert to toplevel */ + while (w->parent != NULL && + w->parent->window_type != GDK_WINDOW_ROOT) + { + x += w->x; + y += w->y; + w = w->parent; + } + } + + *x_out = x; + *y_out = y; + *state_out = state; + return (GdkWindow *)w; +} + static void switch_to_pointer_grab (GdkDisplay *display, GdkPointerGrabInfo *grab, @@ -910,8 +946,7 @@ switch_to_pointer_grab (GdkDisplay *display, guint32 time, gulong serial) { - GdkWindow *src_window, *pointer_window; - GdkWindowObject *w; + GdkWindow *src_window, *pointer_window, *new_toplevel; GList *old_grabs; GdkModifierType state; int x, y; @@ -944,66 +979,66 @@ switch_to_pointer_grab (GdkDisplay *display, src_window, grab->window, GDK_CROSSING_GRAB, time, serial); } - + /* !owner_event Grabbing a window that we're not inside, current status is now NULL (i.e. outside grabbed window) */ if (!grab->owner_events && display->pointer_info.window_under_pointer != grab->window) _gdk_display_set_window_under_pointer (display, NULL); } - + grab->activated = TRUE; } - else if (last_grab) + + if (last_grab) { - pointer_window = _gdk_windowing_window_at_pointer (display, &x, &y, &state); - if (pointer_window != NULL && - (GDK_WINDOW_DESTROYED (pointer_window) || - GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT || - GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN)) - pointer_window = NULL; - - /* We force checked what window we're in, so we need to - * update the toplevel_under_pointer info, as that won't get told of - * this change. - */ - if (display->pointer_info.toplevel_under_pointer) - g_object_unref (display->pointer_info.toplevel_under_pointer); - display->pointer_info.toplevel_under_pointer = NULL; - - if (pointer_window) + new_toplevel = NULL; + + if (grab == NULL /* ungrab */ || + (!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ ) { - /* Convert to toplevel */ - w = (GdkWindowObject *)pointer_window; - while (/*w->parent != NULL && */ - w->parent->window_type != GDK_WINDOW_ROOT) + /* We force check what window we're in, and update the toplevel_under_pointer info, + * as that won't get told of this change with toplevel enter events. + */ + if (display->pointer_info.toplevel_under_pointer) + g_object_unref (display->pointer_info.toplevel_under_pointer); + display->pointer_info.toplevel_under_pointer = NULL; + + new_toplevel = get_current_toplevel (display, &x, &y, &state); + if (new_toplevel) { - x += w->x; - y += w->y; - w = w->parent; + /* w is now toplevel and x,y in toplevel coords */ + display->pointer_info.toplevel_under_pointer = g_object_ref (new_toplevel); + display->pointer_info.toplevel_x = x; + display->pointer_info.toplevel_y = y; + display->pointer_info.state = state; } - - /* w is now toplevel and x,y in toplevel coords */ - display->pointer_info.toplevel_under_pointer = g_object_ref (w); - - /* Find (possibly virtual) child window */ - pointer_window = - _gdk_window_find_descendant_at ((GdkWindow *)w, - x, y, - NULL, NULL); } - if (pointer_window != last_grab->window) - synthesize_crossing_events (display, - last_grab->window, pointer_window, - GDK_CROSSING_UNGRAB, time, serial); - - /* We're now ungrabbed, update the window_under_pointer */ - _gdk_display_set_window_under_pointer (display, pointer_window); - - if (last_grab->implicit_ungrab) - generate_grab_broken_event (last_grab->window, - FALSE, TRUE, - NULL); + if (grab == NULL) /* Ungrabbed, send events */ + { + pointer_window = NULL; + if (new_toplevel) + { + /* Find (possibly virtual) child window */ + pointer_window = + _gdk_window_find_descendant_at (new_toplevel, + x, y, + NULL, NULL); + } + + if (pointer_window != last_grab->window) + synthesize_crossing_events (display, + last_grab->window, pointer_window, + GDK_CROSSING_UNGRAB, time, serial); + + /* We're now ungrabbed, update the window_under_pointer */ + _gdk_display_set_window_under_pointer (display, pointer_window); + + if (last_grab->implicit_ungrab) + generate_grab_broken_event (last_grab->window, + FALSE, TRUE, + NULL); + } } display->pointer_grabs = old_grabs;