Commit 83d5cd42 authored by Nick Diego Yamane's avatar Nick Diego Yamane Committed by Commit Bot

ozone/wayland: tabdrag: Start using zcr_extended_drag extension

Context: Wayland Protocol needed to be extended to make it possible to
properly support full Chromium's tab dragging experience. Further
details in the Design document [1].

This patch contains the first round of Wayland Ozone backend (client
side) changes needed to leverage the extended-drag protocol extension to
implement the remaining tab/window dragging missing features, whereas
the main one is the ability to set a toplevel shell surface (browser
window) as the "dragged surface", making it to be anchored to the
pointer cursor as it's dragged around, as well as being smoothly
droppable anywhere in the workspace, which is not possible with the
standard Wayland DND protocol.

[1] https://docs.google.com/document/d/1s6OwTi_WC-pS21WLGQYI39yw2m42ZlVolUXBclljXB4/edit?usp=sharing

R=msisov@chromium.org

Bug: 896640, 1099418
Change-Id: I8a19670fd4ad64d49a9aa202548c22065870dd90
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2401319
Commit-Queue: Nick Yamane <nickdiego@igalia.com>
Reviewed-by: default avatarMaksim Sisov (GMT+2) <msisov@igalia.com>
Reviewed-by: default avatarAntonio Gomes <tonikitoo@igalia.com>
Cr-Commit-Position: refs/heads/master@{#823987}
parent a1975778
...@@ -165,6 +165,7 @@ source_set("wayland") { ...@@ -165,6 +165,7 @@ source_set("wayland") {
"//mojo/public/cpp/system", "//mojo/public/cpp/system",
"//skia", "//skia",
"//third_party/wayland-protocols:cursor_shapes_protocol", "//third_party/wayland-protocols:cursor_shapes_protocol",
"//third_party/wayland-protocols:extended_drag",
"//third_party/wayland-protocols:gtk_primary_selection_protocol", "//third_party/wayland-protocols:gtk_primary_selection_protocol",
"//third_party/wayland-protocols:keyboard_extension_protocol", "//third_party/wayland-protocols:keyboard_extension_protocol",
"//third_party/wayland-protocols:linux_dmabuf_protocol", "//third_party/wayland-protocols:linux_dmabuf_protocol",
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <aura-shell-client-protocol.h> #include <aura-shell-client-protocol.h>
#include <cursor-shapes-unstable-v1-client-protocol.h> #include <cursor-shapes-unstable-v1-client-protocol.h>
#include <extended-drag-unstable-v1-client-protocol.h>
#include <gtk-primary-selection-client-protocol.h> #include <gtk-primary-selection-client-protocol.h>
#include <keyboard-extension-unstable-v1-client-protocol.h> #include <keyboard-extension-unstable-v1-client-protocol.h>
#include <linux-dmabuf-unstable-v1-client-protocol.h> #include <linux-dmabuf-unstable-v1-client-protocol.h>
...@@ -253,6 +254,21 @@ const wl_interface* ObjectTraits<zcr_cursor_shapes_v1>::interface = ...@@ -253,6 +254,21 @@ const wl_interface* ObjectTraits<zcr_cursor_shapes_v1>::interface =
void (*ObjectTraits<zcr_cursor_shapes_v1>::deleter)(zcr_cursor_shapes_v1*) = void (*ObjectTraits<zcr_cursor_shapes_v1>::deleter)(zcr_cursor_shapes_v1*) =
&zcr_cursor_shapes_v1_destroy; &zcr_cursor_shapes_v1_destroy;
const wl_interface* ObjectTraits<zcr_extended_drag_v1>::interface =
&zcr_extended_drag_v1_interface;
void (*ObjectTraits<zcr_extended_drag_v1>::deleter)(zcr_extended_drag_v1*) =
&zcr_extended_drag_v1_destroy;
const wl_interface* ObjectTraits<zcr_extended_drag_source_v1>::interface =
&zcr_extended_drag_source_v1_interface;
void (*ObjectTraits<zcr_extended_drag_source_v1>::deleter)(
zcr_extended_drag_source_v1*) = &zcr_extended_drag_source_v1_destroy;
const wl_interface* ObjectTraits<zcr_extended_drag_offer_v1>::interface =
&zcr_extended_drag_offer_v1_interface;
void (*ObjectTraits<zcr_extended_drag_offer_v1>::deleter)(
zcr_extended_drag_offer_v1*) = &zcr_extended_drag_offer_v1_destroy;
const wl_interface* ObjectTraits<zcr_keyboard_extension_v1>::interface = const wl_interface* ObjectTraits<zcr_keyboard_extension_v1>::interface =
&zcr_keyboard_extension_v1_interface; &zcr_keyboard_extension_v1_interface;
void (*ObjectTraits<zcr_keyboard_extension_v1>::deleter)( void (*ObjectTraits<zcr_keyboard_extension_v1>::deleter)(
......
...@@ -51,6 +51,9 @@ struct zaura_surface; ...@@ -51,6 +51,9 @@ struct zaura_surface;
struct zcr_cursor_shapes_v1; struct zcr_cursor_shapes_v1;
struct zcr_keyboard_extension_v1; struct zcr_keyboard_extension_v1;
struct zcr_extended_keyboard_v1; struct zcr_extended_keyboard_v1;
struct zcr_extended_drag_v1;
struct zcr_extended_drag_source_v1;
struct zcr_extended_drag_offer_v1;
struct zwp_linux_dmabuf_v1; struct zwp_linux_dmabuf_v1;
struct zwp_linux_buffer_release_v1; struct zwp_linux_buffer_release_v1;
struct zwp_linux_explicit_synchronization_v1; struct zwp_linux_explicit_synchronization_v1;
...@@ -330,6 +333,24 @@ struct ObjectTraits<zcr_cursor_shapes_v1> { ...@@ -330,6 +333,24 @@ struct ObjectTraits<zcr_cursor_shapes_v1> {
static void (*deleter)(zcr_cursor_shapes_v1*); static void (*deleter)(zcr_cursor_shapes_v1*);
}; };
template <>
struct ObjectTraits<zcr_extended_drag_v1> {
static const wl_interface* interface;
static void (*deleter)(zcr_extended_drag_v1*);
};
template <>
struct ObjectTraits<zcr_extended_drag_source_v1> {
static const wl_interface* interface;
static void (*deleter)(zcr_extended_drag_source_v1*);
};
template <>
struct ObjectTraits<zcr_extended_drag_offer_v1> {
static const wl_interface* interface;
static void (*deleter)(zcr_extended_drag_offer_v1*);
};
template <> template <>
struct ObjectTraits<zcr_keyboard_extension_v1> { struct ObjectTraits<zcr_keyboard_extension_v1> {
static const wl_interface* interface; static const wl_interface* interface;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "ui/ozone/platform/wayland/host/wayland_connection.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include <extended-drag-unstable-v1-client-protocol.h>
#include <xdg-shell-client-protocol.h> #include <xdg-shell-client-protocol.h>
#include <xdg-shell-unstable-v6-client-protocol.h> #include <xdg-shell-unstable-v6-client-protocol.h>
...@@ -69,6 +70,7 @@ constexpr uint32_t kMinAuraShellVersion = 11; ...@@ -69,6 +70,7 @@ constexpr uint32_t kMinAuraShellVersion = 11;
constexpr uint32_t kMinWlDrmVersion = 2; constexpr uint32_t kMinWlDrmVersion = 2;
constexpr uint32_t kMinWlOutputVersion = 2; constexpr uint32_t kMinWlOutputVersion = 2;
constexpr uint32_t kMaxXdgDecorationVersion = 1; constexpr uint32_t kMaxXdgDecorationVersion = 1;
constexpr uint32_t kMaxExtendedDragVersion = 1;
} // namespace } // namespace
WaylandConnection::WaylandConnection() = default; WaylandConnection::WaylandConnection() = default;
...@@ -447,6 +449,14 @@ void WaylandConnection::Global(void* data, ...@@ -447,6 +449,14 @@ void WaylandConnection::Global(void* data,
connection->xdg_decoration_manager_ = connection->xdg_decoration_manager_ =
wl::Bind<struct zxdg_decoration_manager_v1>(registry, name, wl::Bind<struct zxdg_decoration_manager_v1>(registry, name,
kMaxXdgDecorationVersion); kMaxXdgDecorationVersion);
} else if (!connection->extended_drag_v1_ &&
strcmp(interface, "zcr_extended_drag_v1") == 0) {
connection->extended_drag_v1_ =
wl::Bind<zcr_extended_drag_v1>(registry, name, kMaxExtendedDragVersion);
if (!connection->extended_drag_v1_) {
LOG(ERROR) << "Failed to bind to zcr_extended_drag_v1 global";
return;
}
} }
connection->ScheduleFlush(); connection->ScheduleFlush();
......
...@@ -82,6 +82,9 @@ class WaylandConnection { ...@@ -82,6 +82,9 @@ class WaylandConnection {
zxdg_decoration_manager_v1* xdg_decoration_manager_v1() const { zxdg_decoration_manager_v1* xdg_decoration_manager_v1() const {
return xdg_decoration_manager_.get(); return xdg_decoration_manager_.get();
} }
zcr_extended_drag_v1* extended_drag_v1() const {
return extended_drag_v1_.get();
}
void set_serial(uint32_t serial, EventType event_type) { void set_serial(uint32_t serial, EventType event_type) {
serial_ = {serial, event_type}; serial_ = {serial, event_type};
...@@ -209,6 +212,7 @@ class WaylandConnection { ...@@ -209,6 +212,7 @@ class WaylandConnection {
wl::Object<zwp_linux_explicit_synchronization_v1> wl::Object<zwp_linux_explicit_synchronization_v1>
linux_explicit_synchronization_; linux_explicit_synchronization_;
wl::Object<zxdg_decoration_manager_v1> xdg_decoration_manager_; wl::Object<zxdg_decoration_manager_v1> xdg_decoration_manager_;
wl::Object<zcr_extended_drag_v1> extended_drag_v1_;
// Event source instance. Must be declared before input objects so it // Event source instance. Must be declared before input objects so it
// outlives them so thus being able to properly handle their destruction. // outlives them so thus being able to properly handle their destruction.
......
...@@ -132,6 +132,9 @@ void WaylandToplevelWindow::Show(bool inactive) { ...@@ -132,6 +132,9 @@ void WaylandToplevelWindow::Show(bool inactive) {
} }
UpdateBufferScale(false); UpdateBufferScale(false);
if (auto* drag_controller = connection()->window_drag_controller())
drag_controller->OnToplevelWindowCreated(this);
} }
void WaylandToplevelWindow::Hide() { void WaylandToplevelWindow::Hide() {
......
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
#include "ui/ozone/platform/wayland/host/wayland_window_drag_controller.h" #include "ui/ozone/platform/wayland/host/wayland_window_drag_controller.h"
#include <extended-drag-unstable-v1-client-protocol.h>
#include <wayland-client-protocol.h>
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <ostream> #include <ostream>
...@@ -23,8 +26,11 @@ ...@@ -23,8 +26,11 @@
#include "ui/events/platform/scoped_event_dispatcher.h" #include "ui/events/platform/scoped_event_dispatcher.h"
#include "ui/events/platform_event.h" #include "ui/events/platform_event.h"
#include "ui/events/types/event_type.h" #include "ui/events/types/event_type.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/geometry/vector2d.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_cursor_position.h" #include "ui/ozone/platform/wayland/host/wayland_cursor_position.h"
#include "ui/ozone/platform/wayland/host/wayland_data_device_manager.h" #include "ui/ozone/platform/wayland/host/wayland_data_device_manager.h"
...@@ -35,6 +41,7 @@ ...@@ -35,6 +41,7 @@
#include "ui/ozone/platform/wayland/host/wayland_surface.h" #include "ui/ozone/platform/wayland/host/wayland_surface.h"
#include "ui/ozone/platform/wayland/host/wayland_window.h" #include "ui/ozone/platform/wayland/host/wayland_window.h"
#include "ui/ozone/platform/wayland/host/wayland_window_manager.h" #include "ui/ozone/platform/wayland/host/wayland_window_manager.h"
#include "ui/platform_window/platform_window_init_properties.h"
namespace ui { namespace ui {
...@@ -49,6 +56,30 @@ constexpr uint32_t kDndActionWindowDrag = ...@@ -49,6 +56,30 @@ constexpr uint32_t kDndActionWindowDrag =
} // namespace } // namespace
class WaylandWindowDragController::ExtendedDragSource {
public:
ExtendedDragSource(const WaylandConnection& connection,
wl_data_source* source) {
DCHECK(connection.extended_drag_v1());
uint32_t options = ZCR_EXTENDED_DRAG_V1_OPTIONS_ALLOW_SWALLOW |
ZCR_EXTENDED_DRAG_V1_OPTIONS_ALLOW_DROP_NO_TARGET |
ZCR_EXTENDED_DRAG_V1_OPTIONS_LOCK_CURSOR;
source_.reset(zcr_extended_drag_v1_get_extended_drag_source(
connection.extended_drag_v1(), source, options));
DCHECK(source_);
}
void SetDraggedWindow(WaylandToplevelWindow* window,
const gfx::Vector2d& offset) {
auto* surface = window ? window->root_surface()->surface() : nullptr;
zcr_extended_drag_source_v1_drag(source_.get(), surface, offset.x(),
offset.y());
}
private:
wl::Object<zcr_extended_drag_source_v1> source_;
};
WaylandWindowDragController::WaylandWindowDragController( WaylandWindowDragController::WaylandWindowDragController(
WaylandConnection* connection, WaylandConnection* connection,
WaylandDataDeviceManager* device_manager, WaylandDataDeviceManager* device_manager,
...@@ -82,11 +113,16 @@ bool WaylandWindowDragController::StartDragSession() { ...@@ -82,11 +113,16 @@ bool WaylandWindowDragController::StartDragSession() {
data_source_->Offer({kMimeTypeChromiumWindow}); data_source_->Offer({kMimeTypeChromiumWindow});
data_source_->SetAction(DragDropTypes::DRAG_MOVE); data_source_->SetAction(DragDropTypes::DRAG_MOVE);
// TODO(crbug.com/1099418): Use dragged window's surface as icon surface if (IsExtendedDragAvailable()) {
// once "immediate drag" protocol extensions are available. extended_drag_source_ = std::make_unique<ExtendedDragSource>(
*connection_, data_source_->data_source());
} else {
LOG(ERROR) << "zcr_extended_drag_v1 extension not available! "
<< "Window/Tab dragging won't be fully functional.";
}
data_device_->StartDrag(*data_source_, *origin_window_, data_device_->StartDrag(*data_source_, *origin_window_,
/*icon_surface=*/nullptr, this); /*icon_surface=*/nullptr, this);
pointer_grab_owner_ = origin_window_; pointer_grab_owner_ = origin_window_;
// Observe window so we can take ownership of the origin surface in case it // Observe window so we can take ownership of the origin surface in case it
...@@ -97,14 +133,13 @@ bool WaylandWindowDragController::StartDragSession() { ...@@ -97,14 +133,13 @@ bool WaylandWindowDragController::StartDragSession() {
bool WaylandWindowDragController::Drag(WaylandToplevelWindow* window, bool WaylandWindowDragController::Drag(WaylandToplevelWindow* window,
const gfx::Vector2d& offset) { const gfx::Vector2d& offset) {
DCHECK_EQ(state_, State::kAttached); DCHECK_GE(state_, State::kAttached);
DCHECK(window); DCHECK(window);
dragged_window_ = window;
drag_offset_ = offset;
SetDraggedWindow(window, offset);
state_ = State::kDetached;
RunLoop(); RunLoop();
SetDraggedWindow(nullptr, {});
dragged_window_ = nullptr;
DCHECK(state_ == State::kAttached || state_ == State::kDropped); DCHECK(state_ == State::kAttached || state_ == State::kDropped);
bool dropped = state_ == State::kDropped; bool dropped = state_ == State::kDropped;
...@@ -141,6 +176,8 @@ void WaylandWindowDragController::OnDragOffer( ...@@ -141,6 +176,8 @@ void WaylandWindowDragController::OnDragOffer(
DCHECK_GE(state_, State::kAttached); DCHECK_GE(state_, State::kAttached);
DCHECK(offer); DCHECK(offer);
DCHECK(!data_offer_); DCHECK(!data_offer_);
VLOG(1) << "OnOffer. mime_types=" << offer->mime_types().size();
data_offer_ = std::move(offer); data_offer_ = std::move(offer);
} }
...@@ -246,6 +283,7 @@ void WaylandWindowDragController::OnDataSourceFinish(bool completed) { ...@@ -246,6 +283,7 @@ void WaylandWindowDragController::OnDataSourceFinish(bool completed) {
// Release DND objects. // Release DND objects.
data_offer_.reset(); data_offer_.reset();
data_source_.reset(); data_source_.reset();
extended_drag_source_.reset();
origin_surface_.reset(); origin_surface_.reset();
origin_window_ = nullptr; origin_window_ = nullptr;
dragged_window_ = nullptr; dragged_window_ = nullptr;
...@@ -287,8 +325,27 @@ uint32_t WaylandWindowDragController::DispatchEvent( ...@@ -287,8 +325,27 @@ uint32_t WaylandWindowDragController::DispatchEvent(
return POST_DISPATCH_PERFORM_DEFAULT; return POST_DISPATCH_PERFORM_DEFAULT;
} }
void WaylandWindowDragController::OnToplevelWindowCreated(
WaylandToplevelWindow* window) {
// Skip unless a toplevel window is getting visible while in attached mode.
// E.g: A window/tab is being detached in a tab dragging session.
if (state_ != State::kAttached)
return;
DCHECK(window);
auto origin = window->GetBounds().origin();
gfx::Vector2d offset = gfx::ToFlooredPoint(pointer_location_) - origin;
VLOG(1) << "Toplevel window created (detached)."
<< " widget=" << window->GetWidget()
<< " calculated_offset=" << offset.ToString();
SetDraggedWindow(window, offset);
state_ = State::kDetached;
}
void WaylandWindowDragController::OnWindowRemoved(WaylandWindow* window) { void WaylandWindowDragController::OnWindowRemoved(WaylandWindow* window) {
DCHECK_NE(state_, State::kIdle); DCHECK_NE(state_, State::kIdle);
DCHECK_NE(window, dragged_window_);
if (window == origin_window_) if (window == origin_window_)
origin_surface_ = origin_window_->TakeWaylandSurface(); origin_surface_ = origin_window_->TakeWaylandSurface();
} }
...@@ -334,20 +391,18 @@ void WaylandWindowDragController::HandleDropAndResetState() { ...@@ -334,20 +391,18 @@ void WaylandWindowDragController::HandleDropAndResetState() {
} }
void WaylandWindowDragController::RunLoop() { void WaylandWindowDragController::RunLoop() {
DCHECK_EQ(state_, State::kAttached); DCHECK_EQ(state_, State::kDetached);
DCHECK(dragged_window_); DCHECK(dragged_window_);
VLOG(1) << "Starting drag loop. widget=" << dragged_window_->GetWidget() VLOG(1) << "Starting drag loop. widget=" << dragged_window_->GetWidget()
<< " offset=" << drag_offset_.ToString(); << " offset=" << drag_offset_.ToString();
// TODO(crbug.com/896640): Handle cursor
auto old_dispatcher = std::move(nested_dispatcher_); auto old_dispatcher = std::move(nested_dispatcher_);
nested_dispatcher_ = nested_dispatcher_ =
PlatformEventSource::GetInstance()->OverrideDispatcher(this); PlatformEventSource::GetInstance()->OverrideDispatcher(this);
base::WeakPtr<WaylandWindowDragController> alive(weak_factory_.GetWeakPtr()); base::WeakPtr<WaylandWindowDragController> alive(weak_factory_.GetWeakPtr());
state_ = State::kDetached;
base::RunLoop loop(base::RunLoop::Type::kNestableTasksAllowed); base::RunLoop loop(base::RunLoop::Type::kNestableTasksAllowed);
quit_loop_closure_ = loop.QuitClosure(); quit_loop_closure_ = loop.QuitClosure();
loop.Run(); loop.Run();
...@@ -367,6 +422,24 @@ void WaylandWindowDragController::QuitLoop() { ...@@ -367,6 +422,24 @@ void WaylandWindowDragController::QuitLoop() {
std::move(quit_loop_closure_).Run(); std::move(quit_loop_closure_).Run();
} }
void WaylandWindowDragController::SetDraggedWindow(
WaylandToplevelWindow* window,
const gfx::Vector2d& offset) {
if (dragged_window_ == window && offset == drag_offset_)
return;
dragged_window_ = window;
drag_offset_ = offset;
// TODO(crbug.com/896640): Fallback when extended-drag is not available.
if (extended_drag_source_)
extended_drag_source_->SetDraggedWindow(dragged_window_, drag_offset_);
}
bool WaylandWindowDragController::IsExtendedDragAvailable() const {
return !!connection_->extended_drag_v1();
}
std::ostream& operator<<(std::ostream& out, std::ostream& operator<<(std::ostream& out,
WaylandWindowDragController::State state) { WaylandWindowDragController::State state) {
return out << static_cast<int>(state); return out << static_cast<int>(state);
......
...@@ -15,7 +15,9 @@ ...@@ -15,7 +15,9 @@
#include "ui/events/event.h" #include "ui/events/event.h"
#include "ui/events/platform/platform_event_dispatcher.h" #include "ui/events/platform/platform_event_dispatcher.h"
#include "ui/events/platform/scoped_event_dispatcher.h" #include "ui/events/platform/scoped_event_dispatcher.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/geometry/vector2d.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h"
#include "ui/ozone/platform/wayland/gpu/wayland_surface_factory.h" #include "ui/ozone/platform/wayland/gpu/wayland_surface_factory.h"
#include "ui/ozone/platform/wayland/host/wayland_data_device.h" #include "ui/ozone/platform/wayland/host/wayland_data_device.h"
#include "ui/ozone/platform/wayland/host/wayland_data_source.h" #include "ui/ozone/platform/wayland/host/wayland_data_source.h"
...@@ -68,7 +70,11 @@ class WaylandWindowDragController : public WaylandDataDevice::DragDelegate, ...@@ -68,7 +70,11 @@ class WaylandWindowDragController : public WaylandDataDevice::DragDelegate,
State state() const { return state_; } State state() const { return state_; }
void OnToplevelWindowCreated(WaylandToplevelWindow* window);
private: private:
class ExtendedDragSource;
// WaylandDataDevice::DragDelegate: // WaylandDataDevice::DragDelegate:
bool IsDragSource() const override; bool IsDragSource() const override;
void DrawIcon() override; void DrawIcon() override;
...@@ -103,6 +109,13 @@ class WaylandWindowDragController : public WaylandDataDevice::DragDelegate, ...@@ -103,6 +109,13 @@ class WaylandWindowDragController : public WaylandDataDevice::DragDelegate,
void RunLoop(); void RunLoop();
// Unregisters the internal event dispatcher and asks to quit the nested loop. // Unregisters the internal event dispatcher and asks to quit the nested loop.
void QuitLoop(); void QuitLoop();
// Set |window| as the current dragged window and |offset| as the drag offset,
// which makes |window| to appear anchored to the pointer cursor, if
// extended-drag extension is available.
void SetDraggedWindow(WaylandToplevelWindow* window,
const gfx::Vector2d& offset);
// Tells if "extended drag" extension is available.
bool IsExtendedDragAvailable() const;
WaylandConnection* const connection_; WaylandConnection* const connection_;
WaylandDataDeviceManager* const data_device_manager_; WaylandDataDeviceManager* const data_device_manager_;
...@@ -119,6 +132,8 @@ class WaylandWindowDragController : public WaylandDataDevice::DragDelegate, ...@@ -119,6 +132,8 @@ class WaylandWindowDragController : public WaylandDataDevice::DragDelegate,
std::unique_ptr<WaylandDataSource> data_source_; std::unique_ptr<WaylandDataSource> data_source_;
std::unique_ptr<WaylandDataOffer> data_offer_; std::unique_ptr<WaylandDataOffer> data_offer_;
std::unique_ptr<ExtendedDragSource> extended_drag_source_;
// The current toplevel window being dragged, when in detached mode. // The current toplevel window being dragged, when in detached mode.
WaylandToplevelWindow* dragged_window_ = nullptr; WaylandToplevelWindow* dragged_window_ = nullptr;
......
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