Compare commits

...

2 Commits

Author SHA1 Message Date
Matthias Clasen
1c74e4a509 idle sizer: Request a motion event after layout
When we are reallocating widgets, make sure that
we get a motion event in the next frame cycle,
so the hover state gets updated.
2020-08-26 19:43:13 -04:00
Matthias Clasen
686ced2a79 Add a function to request motion events
We want to ensure that the pointer position is reflected
when widget geometry changes, so add a function that tells
GDK "please create a motion event at the current position
on this surface, if one doesn't happen already".
2020-08-26 19:42:09 -04:00
4 changed files with 72 additions and 2 deletions

View File

@@ -2338,6 +2338,40 @@ 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);
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 +2379,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 +2841,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 +2855,18 @@ gdk_surface_handle_event (GdkEvent *event)
return handled;
}
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

View File

@@ -230,6 +230,9 @@ GdkVulkanContext *
gdk_surface_create_vulkan_context(GdkSurface *surface,
GError **error);
GDK_AVAILABLE_IN_ALL
void gdk_surface_request_motion (GdkSurface *surface);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GdkSurface, g_object_unref)
G_END_DECLS

View File

@@ -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;

View File

@@ -199,7 +199,21 @@ 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))
{
GtkWidget *focus;
GdkSeat *seat;
GdkDevice *device;
seat = gdk_display_get_default_seat (gtk_widget_get_display (widget));
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);