diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c index f89061a002..3a03292251 100644 --- a/gdk/gdksurface.c +++ b/gdk/gdksurface.c @@ -2338,6 +2338,43 @@ gdk_drag_begin (GdkSurface *surface, return GDK_SURFACE_GET_CLASS (surface)->drag_begin (surface, device, content, actions, dx, dy); } +static void +gdk_surface_ensure_motion (GdkSurface *surface) +{ + GdkDisplay *display; + GdkSeat *seat; + GdkDevice *device; + GdkEvent *event; + double x, y; + GdkModifierType state; + + if (!surface->request_motion) + return; + + surface->request_motion = FALSE; + + display = gdk_surface_get_display (surface); + seat = gdk_display_get_default_seat (display); + if (!seat) + return; + + device = gdk_seat_get_pointer (seat); + + if (!gdk_surface_get_device_position (surface, device, &x, &y, &state)) + return; + + event = gdk_motion_event_new (surface, + device, + NULL, + GDK_CURRENT_TIME, + state, + x, y, + NULL); + + gdk_surface_handle_event (event); + gdk_event_unref (event); +} + static void gdk_surface_flush_events (GdkFrameClock *clock, void *data) @@ -2345,6 +2382,7 @@ gdk_surface_flush_events (GdkFrameClock *clock, GdkSurface *surface = GDK_SURFACE (data); _gdk_event_queue_flush (surface->display); + gdk_surface_ensure_motion (surface); _gdk_display_pause_events (surface->display); gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_RESUME_EVENTS); @@ -2806,7 +2844,12 @@ gdk_surface_handle_event (GdkEvent *event) } else { - g_signal_emit (gdk_event_get_surface (event), signals[EVENT], 0, event, &handled); + GdkSurface *surface = gdk_event_get_surface (event); + + if (gdk_event_get_event_type (event) == GDK_MOTION_NOTIFY) + surface->request_motion = FALSE; + + g_signal_emit (surface, signals[EVENT], 0, event, &handled); } if (GDK_PROFILER_IS_RUNNING) @@ -2815,6 +2858,27 @@ gdk_surface_handle_event (GdkEvent *event) return handled; } +/* + * gdk_surface_request_motion: + * @surface: a #GdkSurface + * + * Request that the next frame cycle should deliver a motion + * event for @surface if the pointer is over it, regardless + * whether the pointer has moved or not. This is used by GTK + * after moving widgets around. + */ +void +gdk_surface_request_motion (GdkSurface *surface) +{ + GdkFrameClock *frame_clock; + + surface->request_motion = TRUE; + + frame_clock = gdk_surface_get_frame_clock (surface); + if (frame_clock) + gdk_frame_clock_request_phase (frame_clock, GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS); +} + /** * gdk_surface_translate_coordinates: * @from: the origin surface diff --git a/gdk/gdksurfaceprivate.h b/gdk/gdksurfaceprivate.h index 50c39d5cc1..f84f996f70 100644 --- a/gdk/gdksurfaceprivate.h +++ b/gdk/gdksurfaceprivate.h @@ -72,6 +72,7 @@ struct _GdkSurface guint frame_clock_events_paused : 1; guint autohide : 1; guint shortcuts_inhibited : 1; + guint request_motion : 1; struct { GdkGravity surface_anchor; @@ -327,6 +328,9 @@ void gdk_surface_constrain_size (GdkGeometry *geometry, int *new_width, int *new_height); +GDK_AVAILABLE_IN_ALL +void gdk_surface_request_motion (GdkSurface *surface); + G_END_DECLS #endif /* __GDK_SURFACE_PRIVATE_H__ */ diff --git a/gtk/gtkroot.c b/gtk/gtkroot.c index 24d3860b1d..33000c28fc 100644 --- a/gtk/gtkroot.c +++ b/gtk/gtkroot.c @@ -199,7 +199,25 @@ gtk_root_layout_cb (GdkFrameClock *clock, * since it doesn't cause any actual harm. */ if (gtk_widget_needs_allocate (widget)) - gtk_native_check_resize (GTK_NATIVE (self)); + { + gtk_native_check_resize (GTK_NATIVE (self)); + if (GTK_IS_WINDOW (widget)) + { + GdkSeat *seat; + + seat = gdk_display_get_default_seat (gtk_widget_get_display (widget)); + if (seat) + { + GdkDevice *device; + GtkWidget *focus; + + device = gdk_seat_get_pointer (seat); + focus = gtk_window_lookup_pointer_focus_widget (GTK_WINDOW (widget), device, NULL); + if (focus) + gdk_surface_request_motion (gtk_native_get_surface (gtk_widget_get_native (focus))); + } + } + } if (!gtk_root_needs_layout (self)) gtk_root_stop_layout (self);