diff --git a/gdk/gdkdrop.c b/gdk/gdkdrop.c index 6d40b79d93..b491eebfdb 100644 --- a/gdk/gdkdrop.c +++ b/gdk/gdkdrop.c @@ -962,6 +962,8 @@ gdk_drop_do_emit_event (GdkEvent *event, void gdk_drop_emit_enter_event (GdkDrop *self, gboolean dont_queue, + double x, + double y, guint32 time) { GdkDropPrivate *priv = gdk_drop_get_instance_private (self); diff --git a/gdk/gdkdropprivate.h b/gdk/gdkdropprivate.h index 5836c89b78..82b5e41945 100644 --- a/gdk/gdkdropprivate.h +++ b/gdk/gdkdropprivate.h @@ -61,6 +61,8 @@ void gdk_drop_set_actions (GdkDrop void gdk_drop_emit_enter_event (GdkDrop *self, gboolean dont_queue, + double x, + double y, guint32 time); void gdk_drop_emit_motion_event (GdkDrop *self, gboolean dont_queue, diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c index b16cfffb97..26c99684d6 100644 --- a/gdk/wayland/gdkdevice-wayland.c +++ b/gdk/wayland/gdkdevice-wayland.c @@ -1201,6 +1201,7 @@ data_device_enter (void *data, GdkWaylandSeat *seat = data; GdkSurface *dest_surface; GdkContentFormats *formats; + int origin_x, origin_y; GdkDevice *device; dest_surface = wl_surface_get_user_data (surface); @@ -1245,8 +1246,12 @@ data_device_enter (void *data, gdk_wayland_seat_discard_pending_offer (seat); + gdk_surface_get_origin (gdk_drop_get_surface (seat->drop), &origin_x, &origin_y); + gdk_drop_emit_enter_event (seat->drop, FALSE, + origin_x + seat->pointer_info.surface_x, + origin_y + seat->pointer_info.surface_y, GDK_CURRENT_TIME); } diff --git a/gdk/win32/gdkdrop-win32.c b/gdk/win32/gdkdrop-win32.c index 6ad6615442..3bcb92b89b 100644 --- a/gdk/win32/gdkdrop-win32.c +++ b/gdk/win32/gdkdrop-win32.c @@ -487,8 +487,7 @@ _gdk_win32_local_drop_target_dragenter (GdkDrag *drag, source_actions = set_source_actions_helper (drop, *actions, grfKeyState); - gdk_drop_emit_enter_event (drop, TRUE, time_); - gdk_drop_emit_motion_event (drop, TRUE, x_root, y_root, time_); + gdk_drop_emit_enter_event (drop, TRUE, x_root, y_root, time_); drop_win32->last_key_state = grfKeyState; drop_win32->last_x = x_root; drop_win32->last_y = y_root; @@ -559,8 +558,7 @@ idroptarget_dragenter (LPDROPTARGET This, set_data_object (&ctx->data_object, pDataObj); pt_x = pt.x / drop_win32->scale + _gdk_offset_x; pt_y = pt.y / drop_win32->scale + _gdk_offset_y; - gdk_drop_emit_enter_event (drop, TRUE, GDK_CURRENT_TIME); - gdk_drop_emit_motion_event (drop, TRUE, pt_x, pt_y, GDK_CURRENT_TIME); + gdk_drop_emit_enter_event (drop, TRUE, pt_x, pt_y, GDK_CURRENT_TIME); drop_win32->last_key_state = grfKeyState; drop_win32->last_x = pt_x; drop_win32->last_y = pt_y; diff --git a/gdk/x11/gdkdrop-x11.c b/gdk/x11/gdkdrop-x11.c index 4eb24d154f..c85c17be0f 100644 --- a/gdk/x11/gdkdrop-x11.c +++ b/gdk/x11/gdkdrop-x11.c @@ -70,6 +70,7 @@ struct _GdkX11Drop guint xdnd_targets_set : 1; /* Whether we've already set XdndTypeList */ guint xdnd_have_actions : 1; /* Whether an XdndActionList was provided */ + guint enter_emitted : 1; /* Set after gdk_drop_emit_enter() */ }; struct _GdkX11DropClass @@ -502,7 +503,12 @@ xdnd_enter_filter (GdkSurface *surface, return TRUE; } - g_clear_object (&display_x11->current_drop); + if (display_x11->current_drop) + { + if (GDK_X11_DROP (display_x11->current_drop)->enter_emitted) + gdk_drop_emit_leave_event (display_x11->current_drop, FALSE, GDK_CURRENT_TIME); + g_clear_object (&display_x11->current_drop); + } seat = gdk_display_get_default_seat (display); @@ -582,8 +588,6 @@ xdnd_enter_filter (GdkSurface *surface, display_x11->current_drop = drop; - gdk_drop_emit_enter_event (drop, FALSE, GDK_CURRENT_TIME); - gdk_content_formats_unref (content_formats); return TRUE; @@ -609,7 +613,8 @@ xdnd_leave_filter (GdkSurface *surface, if ((display_x11->current_drop != NULL) && (GDK_X11_DROP (display_x11->current_drop)->source_window == source_window)) { - gdk_drop_emit_leave_event (display_x11->current_drop, FALSE, GDK_CURRENT_TIME); + if (GDK_X11_DROP (display_x11->current_drop)->enter_emitted) + gdk_drop_emit_leave_event (display_x11->current_drop, FALSE, GDK_CURRENT_TIME); g_clear_object (&display_x11->current_drop); } @@ -656,7 +661,15 @@ xdnd_position_filter (GdkSurface *surface, drop_x11->last_x = x_root / impl->surface_scale; drop_x11->last_y = y_root / impl->surface_scale; - gdk_drop_emit_motion_event (drop, FALSE, drop_x11->last_x - surface->x, drop_x11->last_y - surface->y, time); + if (drop_x11->enter_emitted) + { + gdk_drop_emit_motion_event (drop, FALSE, drop_x11->last_x - surface->x, drop_x11->last_y - surface->y, time); + } + else + { + gdk_drop_emit_enter_event (drop, FALSE, drop_x11->last_x - surface->x, drop_x11->last_y - surface->y, time); + drop_x11->enter_emitted = TRUE; + } } return TRUE; diff --git a/gsk/gsktransform.c b/gsk/gsktransform.c index c8e0d321b7..2d94d7e7a5 100644 --- a/gsk/gsktransform.c +++ b/gsk/gsktransform.c @@ -1622,6 +1622,14 @@ gsk_transform_transform (GskTransform *next, if (other == NULL) return next; + if (gsk_transform_is_identity (next)) + { + /* ref before unref to avoid catastrophe when other == next */ + other = gsk_transform_ref (other); + gsk_transform_unref (next); + return other; + } + next = gsk_transform_transform (next, other->next); return other->transform_class->apply (other, next); } @@ -1677,8 +1685,11 @@ gsk_transform_equal (GskTransform *first, if (first == second) return TRUE; - if (first == NULL || second == NULL) - return FALSE; + if (first == NULL) + return gsk_transform_is_identity (second); + + if (second == NULL) + return gsk_transform_is_identity (first); if (first->transform_class != second->transform_class) return FALSE; diff --git a/gtk/gtkdragdest.c b/gtk/gtkdragdest.c index 51dcf37c96..8742dc6e8a 100644 --- a/gtk/gtkdragdest.c +++ b/gtk/gtkdragdest.c @@ -822,13 +822,11 @@ gtk_drag_dest_handle_event (GtkWidget *toplevel, switch ((guint) event_type) { - case GDK_DRAG_ENTER: - break; - case GDK_DRAG_LEAVE: gtk_drop_set_current_dest (drop, NULL); break; + case GDK_DRAG_ENTER: case GDK_DRAG_MOTION: case GDK_DROP_START: gtk_drop_set_current_dest (drop, NULL); diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 8ca682925f..20b232c5f6 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1812,13 +1812,13 @@ gtk_main_do_event (GdkEvent *event) /* Crossing event propagation happens during picking */ break; + case GDK_DRAG_ENTER: case GDK_DRAG_MOTION: case GDK_DROP_START: if (gtk_propagate_event (target_widget, event)) break; G_GNUC_FALLTHROUGH; - case GDK_DRAG_ENTER: case GDK_DRAG_LEAVE: gtk_drag_dest_handle_event (target_widget, event); break; diff --git a/testsuite/gsk/transform.c b/testsuite/gsk/transform.c index 605d6f53cd..b90e4f4bc0 100644 --- a/testsuite/gsk/transform.c +++ b/testsuite/gsk/transform.c @@ -332,6 +332,37 @@ test_identity (void) g_free (string); } +static void +test_identity_equal (void) +{ + GskTransform *id = gsk_transform_new (); + GskTransform *t; + + g_assert_true (gsk_transform_equal (NULL, NULL)); + g_assert_true (gsk_transform_equal (id, NULL)); + g_assert_true (gsk_transform_equal (NULL, id)); + g_assert_true (gsk_transform_equal (id, id)); + + t = gsk_transform_transform (NULL, NULL); + g_assert_true (gsk_transform_equal (t, NULL)); + gsk_transform_unref (t); + t = gsk_transform_transform (gsk_transform_new (), NULL); + g_assert_true (gsk_transform_equal (t, NULL)); + gsk_transform_unref (t); + t = gsk_transform_transform (NULL, id); + g_assert_true (gsk_transform_equal (t, NULL)); + gsk_transform_unref (t); + t = gsk_transform_transform (gsk_transform_new (), id); + g_assert_true (gsk_transform_equal (t, NULL)); + gsk_transform_unref (t); + t = gsk_transform_new (); + t = gsk_transform_transform (t, t); + g_assert_true (gsk_transform_equal (t, NULL)); + gsk_transform_unref (t); + + gsk_transform_unref (id); +} + static void test_print_parse (void) { @@ -381,6 +412,7 @@ main (int argc, g_test_add_func ("/transform/conversions/simple", test_conversions_simple); g_test_add_func ("/transform/conversions/transformed", test_conversions_transformed); g_test_add_func ("/transform/identity", test_identity); + g_test_add_func ("/transform/identity-equal", test_identity_equal); g_test_add_func ("/transform/invert", test_invert); g_test_add_func ("/transform/print-parse", test_print_parse);