Commit 6213b9d5 authored by Nick Diego Yamane's avatar Nick Diego Yamane Committed by Commit Bot

ozone/wayland: Destroy offer if its target surface gets destroyed before enter event

During Chrome's tab dragging, when a browser window is quickly snapped
in and out, its surface and xdg surface might get destroyed before the
wl_data_device::enter event is processed for the drag offer for that
give surface.

If that happens, the offer object must be destroyed right away, as there
will be no wl_data_device::leave event for that surface (where it would
destroyed otherwise) and some compositors usually assume there is no
active data offer when a new surface is entered. Such behavior has been
observed in Exosphere compositor, for example [1].

[1] https://source.chromium.org/chromium/chromium/src/+/master:components/exo/data_device.cc;l=77;drc=abf7a4e9b3d2151e0c5c05cf8603e9029f4e006d

R=msisov@igalia.com

Bug: 896640
Change-Id: I88668d44ccdc1507fdebc4fdbe2b676d8848c978
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2378620
Commit-Queue: Maksim Sisov (GMT+3) <msisov@igalia.com>
Reviewed-by: default avatarMaksim Sisov (GMT+3) <msisov@igalia.com>
Cr-Commit-Position: refs/heads/master@{#802139}
parent 58750844
...@@ -109,14 +109,20 @@ void WaylandDataDevice::OnEnter(void* data, ...@@ -109,14 +109,20 @@ void WaylandDataDevice::OnEnter(void* data,
wl_fixed_t x, wl_fixed_t x,
wl_fixed_t y, wl_fixed_t y,
wl_data_offer* offer) { wl_data_offer* offer) {
auto* self = static_cast<WaylandDataDevice*>(data);
WaylandWindow* window = wl::RootWindowFromWlSurface(surface); WaylandWindow* window = wl::RootWindowFromWlSurface(surface);
// During Chrome's tab dragging, when a browser window is quickly snapped in
// and out, it might get destroyed before the wl_data_device::enter event is
// processed for a drag offer. If this happens, |window| will be null here, so
// destroy |new_offer_| here, as some compositors assume it. Such behavior has
// been observed in Exosphere compositor, for example.
if (!window) { if (!window) {
LOG(ERROR) << "Failed to get window."; self->new_offer_.reset();
VLOG(1) << "Failed to get window.";
return; return;
} }
auto* self = static_cast<WaylandDataDevice*>(data);
// Null |drag_delegate_| here means that the DND session has been initiated by // Null |drag_delegate_| here means that the DND session has been initiated by
// an external application. In this case, use the default data drag delegate. // an external application. In this case, use the default data drag delegate.
if (!self->drag_delegate_) if (!self->drag_delegate_)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment