Commit bcdf53ae authored by Nick Diego Yamane's avatar Nick Diego Yamane Committed by Commit Bot

exo: extended-drag: Implement shell surface dragging

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

This is the first of a patch series which implements extended-drag in
Exo compositor. More specifically, this implements the core feature of
the protocol: Making it possible to drag toplevel shell surfaces during
DND sessions. It does it by making ExtendedDragSource an implementation
of the ash::ToplevelWindowDragDelegate interface and plumbing it into
ash's ToplevelWindowEventHandler, delegating to it the actual toplevel
window drag handling. Refer to the design doc for more details.

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

R=oshima@chromium.org

Bug: 1099418
Test: exo_unittests --gtest_filter='ExtendedDragSourceTest.*'
Change-Id: I43908dda9f542e5813d96a2e331af8df0a703efb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2401280Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Commit-Queue: Nick Yamane <nickdiego@igalia.com>
Cr-Commit-Position: refs/heads/master@{#822682}
parent 3129eaf9
...@@ -281,6 +281,7 @@ source_set("unit_tests") { ...@@ -281,6 +281,7 @@ source_set("unit_tests") {
"data_source_unittest.cc", "data_source_unittest.cc",
"display_unittest.cc", "display_unittest.cc",
"drag_drop_operation_unittest.cc", "drag_drop_operation_unittest.cc",
"extended_drag_source_unittest.cc",
"gamepad_unittest.cc", "gamepad_unittest.cc",
"gaming_seat_unittest.cc", "gaming_seat_unittest.cc",
"input_method_surface_unittest.cc", "input_method_surface_unittest.cc",
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/sequenced_task_runner_handle.h"
#include "components/exo/data_offer.h" #include "components/exo/data_offer.h"
#include "components/exo/data_source.h" #include "components/exo/data_source.h"
#include "components/exo/extended_drag_source.h"
#include "components/exo/seat.h" #include "components/exo/seat.h"
#include "components/exo/surface.h" #include "components/exo/surface.h"
#include "components/viz/common/frame_sinks/copy_output_request.h" #include "components/viz/common/frame_sinks/copy_output_request.h"
...@@ -116,6 +117,13 @@ DragDropOperation::DragDropOperation(DataSource* source, ...@@ -116,6 +117,13 @@ DragDropOperation::DragDropOperation(DataSource* source,
drag_drop_controller_->AddObserver(this); drag_drop_controller_->AddObserver(this);
if (auto* ext_drag_source = source_->get()->extended_drag_source()) {
#if defined(OS_CHROMEOS)
drag_drop_controller_->set_toplevel_window_drag_delegate(ext_drag_source);
#endif
ext_drag_source->AddObserver(this);
}
if (icon) if (icon)
icon_ = std::make_unique<ScopedSurface>(icon, this); icon_ = std::make_unique<ScopedSurface>(icon, this);
...@@ -272,13 +280,20 @@ void DragDropOperation::StartDragDropOperation() { ...@@ -272,13 +280,20 @@ void DragDropOperation::StartDragDropOperation() {
source_->get()->DndFinished(); source_->get()->DndFinished();
// Reset |source_| so it the destructor doesn't try to cancel it. // Reset |source_| so it the destructor doesn't try to cancel it.
source_.reset(); ResetSource();
} }
// On failure the destructor will handle canceling the data source. // On failure the destructor will handle canceling the data source.
delete this; delete this;
} }
void DragDropOperation::ResetSource() {
DCHECK(source_);
if (source_->get()->extended_drag_source())
source_->get()->extended_drag_source()->RemoveObserver(this);
source_.reset();
}
void DragDropOperation::OnDragStarted() { void DragDropOperation::OnDragStarted() {
if (!started_by_this_object_) if (!started_by_this_object_)
delete this; delete this;
...@@ -305,6 +320,17 @@ void DragDropOperation::OnDragActionsChanged(int actions) { ...@@ -305,6 +320,17 @@ void DragDropOperation::OnDragActionsChanged(int actions) {
} }
#endif #endif
void DragDropOperation::OnExtendedDragSourceDestroying(
ExtendedDragSource* source) {
#if defined(OS_CHROMEOS)
drag_drop_controller_->set_toplevel_window_drag_delegate(nullptr);
#endif
if (source_) {
DCHECK(source_->get()->extended_drag_source());
source_->get()->extended_drag_source()->RemoveObserver(this);
}
}
void DragDropOperation::OnSurfaceDestroying(Surface* surface) { void DragDropOperation::OnSurfaceDestroying(Surface* surface) {
if (surface == origin_->get() || surface == icon_->get()) { if (surface == origin_->get() || surface == icon_->get()) {
delete this; delete this;
...@@ -315,7 +341,7 @@ void DragDropOperation::OnSurfaceDestroying(Surface* surface) { ...@@ -315,7 +341,7 @@ void DragDropOperation::OnSurfaceDestroying(Surface* surface) {
void DragDropOperation::OnDataSourceDestroying(DataSource* source) { void DragDropOperation::OnDataSourceDestroying(DataSource* source) {
if (source == source_->get()) { if (source == source_->get()) {
source_.reset(); ResetSource();
delete this; delete this;
} else { } else {
NOTREACHED(); NOTREACHED();
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "components/exo/data_device.h" #include "components/exo/data_device.h"
#include "components/exo/data_offer_observer.h" #include "components/exo/data_offer_observer.h"
#include "components/exo/data_source_observer.h" #include "components/exo/data_source_observer.h"
#include "components/exo/extended_drag_source.h"
#include "components/exo/surface_observer.h" #include "components/exo/surface_observer.h"
#include "components/exo/surface_tree_host.h" #include "components/exo/surface_tree_host.h"
#include "components/exo/wm_helper.h" #include "components/exo/wm_helper.h"
...@@ -44,7 +45,8 @@ class ScopedDataSource; ...@@ -44,7 +45,8 @@ class ScopedDataSource;
class DragDropOperation : public DataSourceObserver, class DragDropOperation : public DataSourceObserver,
public SurfaceTreeHost, public SurfaceTreeHost,
public SurfaceObserver, public SurfaceObserver,
public aura::client::DragDropClientObserver { public aura::client::DragDropClientObserver,
public ExtendedDragSource::Observer {
public: public:
// Create an operation for a drag-drop originating from a wayland app. // Create an operation for a drag-drop originating from a wayland app.
static base::WeakPtr<DragDropOperation> Create( static base::WeakPtr<DragDropOperation> Create(
...@@ -73,6 +75,9 @@ class DragDropOperation : public DataSourceObserver, ...@@ -73,6 +75,9 @@ class DragDropOperation : public DataSourceObserver,
void OnDragActionsChanged(int actions) override; void OnDragActionsChanged(int actions) override;
#endif #endif
// ExtendedDragSource::Observer:
void OnExtendedDragSourceDestroying(ExtendedDragSource* source) override;
private: private:
// A private constructor and destructor are used to prevent anyone else from // A private constructor and destructor are used to prevent anyone else from
// attempting to manage the lifetime of a DragDropOperation. // attempting to manage the lifetime of a DragDropOperation.
...@@ -95,6 +100,8 @@ class DragDropOperation : public DataSourceObserver, ...@@ -95,6 +100,8 @@ class DragDropOperation : public DataSourceObserver,
// directly. Use ScheduleStartDragDropOperation instead. // directly. Use ScheduleStartDragDropOperation instead.
void StartDragDropOperation(); void StartDragDropOperation();
void ResetSource();
std::unique_ptr<ScopedDataSource> source_; std::unique_ptr<ScopedDataSource> source_;
std::unique_ptr<ScopedSurface> icon_; std::unique_ptr<ScopedSurface> icon_;
std::unique_ptr<ScopedSurface> origin_; std::unique_ptr<ScopedSurface> origin_;
......
...@@ -4,24 +4,104 @@ ...@@ -4,24 +4,104 @@
#include "components/exo/extended_drag_source.h" #include "components/exo/extended_drag_source.h"
#include <memory>
#include <string>
#include "ash/shell.h"
#include "ash/wm/toplevel_window_event_handler.h"
#include "base/check_op.h" #include "base/check_op.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/notreached.h"
#include "base/optional.h"
#include "components/exo/data_source.h" #include "components/exo/data_source.h"
#include "components/exo/seat.h"
#include "components/exo/surface.h" #include "components/exo/surface.h"
#include "ui/aura/window_observer.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
#include "ui/base/hit_test.h"
#include "ui/events/event.h"
#include "ui/events/event_target.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/vector2d.h" #include "ui/gfx/geometry/vector2d.h"
#include "ui/wm/core/coordinate_conversion.h"
#include "ui/wm/public/window_move_client.h"
namespace exo { namespace exo {
ExtendedDragSource::ExtendedDragSource(DataSource* source, // Internal representation of a toplevel window, backed by an Exo shell surface,
Seat* seat, // which is being dragged. It supports both already mapped/visible windows as
Delegate* delegate) // well as newly created ones (i.e: not added to a root window yet), in which
: delegate_(delegate), seat_(seat), source_(source) { // case OnDraggedWindowVisibilityChanging callback is called to notify when it
// is about to get visible.
class ExtendedDragSource::DraggedWindowHolder : public aura::WindowObserver {
public:
DraggedWindowHolder(Surface* surface,
const gfx::Vector2d& drag_offset,
ExtendedDragSource* source)
: surface_(surface), drag_offset_(drag_offset), source_(source) {
DCHECK(surface_);
DCHECK(surface_->window());
if (!FindToplevelWindow()) {
DVLOG(1) << "Dragged window not added to root window yet.";
surface_->window()->AddObserver(this);
}
}
DraggedWindowHolder(const DraggedWindowHolder&) = delete;
DraggedWindowHolder& operator=(const DraggedWindowHolder&) = delete;
~DraggedWindowHolder() override {
if (toplevel_window_) {
toplevel_window_->RemoveObserver(this);
toplevel_window_ = nullptr;
} else {
surface_->window()->RemoveObserver(this);
}
}
aura::Window* toplevel_window() { return toplevel_window_; }
const gfx::Vector2d& offset() const { return drag_offset_; }
private:
// aura::WindowObserver:
void OnWindowAddedToRootWindow(aura::Window* window) override {
DCHECK_EQ(window, surface_->window());
FindToplevelWindow();
DCHECK(toplevel_window_);
surface_->window()->RemoveObserver(this);
}
void OnWindowVisibilityChanging(aura::Window* window, bool visible) override {
DCHECK(window);
if (window == toplevel_window_)
source_->OnDraggedWindowVisibilityChanging(visible);
}
bool FindToplevelWindow() {
if (!surface_->window()->GetRootWindow())
return false;
toplevel_window_ = surface_->window()->GetToplevelWindow();
toplevel_window_->AddObserver(this);
return true;
}
Surface* const surface_;
gfx::Vector2d drag_offset_;
ExtendedDragSource* const source_;
aura::Window* toplevel_window_ = nullptr;
};
ExtendedDragSource::ExtendedDragSource(DataSource* source, Delegate* delegate)
: delegate_(delegate), source_(source) {
DCHECK(source_); DCHECK(source_);
DCHECK(seat_);
DCHECK(delegate_); DCHECK(delegate_);
DVLOG(1) << "ExtendedDragSource created. wl_source=" << source_; DVLOG(1) << "ExtendedDragSource created. wl_source=" << source_;
source_->set_extended_drag_source(this);
source_->AddObserver(this); source_->AddObserver(this);
} }
...@@ -30,8 +110,10 @@ ExtendedDragSource::~ExtendedDragSource() { ...@@ -30,8 +110,10 @@ ExtendedDragSource::~ExtendedDragSource() {
for (auto& observer : observers_) for (auto& observer : observers_)
observer.OnExtendedDragSourceDestroying(this); observer.OnExtendedDragSourceDestroying(this);
if (source_) if (source_) {
source_->set_extended_drag_source(nullptr);
source_->RemoveObserver(this); source_->RemoveObserver(this);
}
} }
void ExtendedDragSource::AddObserver(Observer* observer) { void ExtendedDragSource::AddObserver(Observer* observer) {
...@@ -50,16 +132,65 @@ void ExtendedDragSource::Drag(Surface* dragged_surface, ...@@ -50,16 +132,65 @@ void ExtendedDragSource::Drag(Surface* dragged_surface,
if (!source_) if (!source_)
return; return;
if (dragged_surface == dragged_surface_ && drag_offset == drag_offset_) if (!dragged_surface) {
DVLOG(1) << "Unsetting dragged surface.";
dragged_window_holder_.reset();
return; return;
}
dragged_surface_ = dragged_surface; DVLOG(1) << "Dragged surface changed:"
drag_offset_ = drag_offset; << " surface=" << dragged_surface
DVLOG(1) << "Dragged surface changed: surface=" << dragged_surface_ << " offset=" << drag_offset.ToString();
<< " offset=" << drag_offset_.ToString();
for (auto& observer : observers_) // Ensure that the surface already has a "role" assigned.
observer.OnDraggedSurfaceChanged(this); DCHECK(dragged_surface->HasSurfaceDelegate());
dragged_window_holder_ =
std::make_unique<DraggedWindowHolder>(dragged_surface, drag_offset, this);
// Drag process will be started once OnDragStarted gets called.
}
bool ExtendedDragSource::IsActive() const {
return !!source_;
}
void ExtendedDragSource::OnToplevelWindowDragStarted(
const gfx::PointF& start_location,
ui::mojom::DragEventSource source) {
pointer_location_ = start_location;
drag_event_source_ = source;
if (dragged_window_holder_ && dragged_window_holder_->toplevel_window())
StartDrag(dragged_window_holder_->toplevel_window(), start_location);
}
int ExtendedDragSource::OnToplevelWindowDragDropped() {
DVLOG(1) << "OnDragDropped()";
Cleanup();
return delegate_->ShouldAllowDropAnywhere() ? ui::DragDropTypes::DRAG_MOVE
: ui::DragDropTypes::DRAG_NONE;
}
void ExtendedDragSource::OnToplevelWindowDragCancelled() {
DVLOG(1) << "OnDragCancelled()";
// TODO(crbug.com/1099418): Handle cancellation/revert.
Cleanup();
}
void ExtendedDragSource::OnToplevelWindowDragEvent(ui::LocatedEvent* event) {
DCHECK(event);
pointer_location_ = event->root_location_f();
if (!dragged_window_holder_)
return;
auto* handler = ash::Shell::Get()->toplevel_window_event_handler();
if (event->IsMouseEvent()) {
handler->OnMouseEvent(event->AsMouseEvent());
return;
}
// TODO(crbug.com/1099418): Support touch move source.
NOTIMPLEMENTED() << "Non-mouse window dragging not supported yet.";
} }
void ExtendedDragSource::OnDataSourceDestroying(DataSource* source) { void ExtendedDragSource::OnDataSourceDestroying(DataSource* source) {
...@@ -68,4 +199,71 @@ void ExtendedDragSource::OnDataSourceDestroying(DataSource* source) { ...@@ -68,4 +199,71 @@ void ExtendedDragSource::OnDataSourceDestroying(DataSource* source) {
source_ = nullptr; source_ = nullptr;
} }
void ExtendedDragSource::StartDrag(aura::Window* toplevel,
const gfx::PointF& pointer_location) {
// Ensure |toplevel| window does skip events while it's being dragged.
event_blocker_ =
std::make_unique<aura::ScopedWindowEventTargetingBlocker>(toplevel);
DVLOG(1) << "Starting drag. pointer_loc=" << pointer_location.ToString();
auto* toplevel_handler = ash::Shell::Get()->toplevel_window_event_handler();
auto move_source = drag_event_source_ == ui::mojom::DragEventSource::kTouch
? ::wm::WINDOW_MOVE_SOURCE_TOUCH
: ::wm::WINDOW_MOVE_SOURCE_MOUSE;
toplevel_handler->AttemptToStartDrag(
toplevel, pointer_location, HTCAPTION, move_source,
ash::ToplevelWindowEventHandler::EndClosure(),
/*update_gesture_target=*/true, /*grab_capture=*/false);
}
void ExtendedDragSource::OnDraggedWindowVisibilityChanging(bool visible) {
DCHECK(dragged_window_holder_);
DVLOG(1) << "Dragged window visibility changed. visible=" << visible;
if (!visible) {
dragged_window_holder_.reset();
return;
}
aura::Window* toplevel = dragged_window_holder_->toplevel_window();
DCHECK(toplevel);
// The |toplevel| window for the dragged surface has just been created and
// it's about to be mapped. Calculate and set its position based on
// |drag_offset_| and |pointer_location_| before starting the actual drag.
auto screen_location = CalculateOrigin(toplevel);
toplevel->SetBounds({screen_location, toplevel->bounds().size()});
DVLOG(1) << "Dragged window mapped. toplevel=" << toplevel
<< " origin=" << screen_location.ToString();
gfx::PointF pointer_location(screen_location +
dragged_window_holder_->offset());
StartDrag(toplevel, pointer_location);
}
gfx::Point ExtendedDragSource::CalculateOrigin(aura::Window* target) const {
DCHECK(dragged_window_holder_);
gfx::Point screen_location = gfx::ToRoundedPoint(pointer_location_);
wm::ConvertPointToScreen(target->GetRootWindow(), &screen_location);
return screen_location - dragged_window_holder_->offset();
}
void ExtendedDragSource::Cleanup() {
event_blocker_.reset();
dragged_window_holder_.reset();
}
aura::Window* ExtendedDragSource::GetDraggedWindowForTesting() {
return dragged_window_holder_ ? dragged_window_holder_->toplevel_window()
: nullptr;
}
base::Optional<gfx::Vector2d> ExtendedDragSource::GetDragOffsetForTesting()
const {
return dragged_window_holder_
? base::Optional<gfx::Vector2d>(dragged_window_holder_->offset())
: base::nullopt;
}
} // namespace exo } // namespace exo
...@@ -5,20 +5,38 @@ ...@@ -5,20 +5,38 @@
#ifndef COMPONENTS_EXO_EXTENDED_DRAG_SOURCE_H_ #ifndef COMPONENTS_EXO_EXTENDED_DRAG_SOURCE_H_
#define COMPONENTS_EXO_EXTENDED_DRAG_SOURCE_H_ #define COMPONENTS_EXO_EXTENDED_DRAG_SOURCE_H_
#include <memory>
#include <string> #include <string>
#include "ash/drag_drop/toplevel_window_drag_delegate.h"
#include "ash/wm/toplevel_window_event_handler.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "base/optional.h" #include "base/optional.h"
#include "components/exo/data_source_observer.h" #include "components/exo/data_source_observer.h"
#include "ui/gfx/geometry/vector2d.h" #include "ui/aura/scoped_window_event_targeting_blocker.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point_f.h"
namespace aura {
class Window;
}
namespace gfx {
class Vector2d;
}
namespace ui {
class LocatedEvent;
}
namespace exo { namespace exo {
class DataSource; class DataSource;
class Seat;
class Surface; class Surface;
class ExtendedDragSource : public DataSourceObserver { class ExtendedDragSource : public DataSourceObserver,
public ash::ToplevelWindowDragDelegate {
public: public:
class Delegate { class Delegate {
public: public:
...@@ -36,13 +54,12 @@ class ExtendedDragSource : public DataSourceObserver { ...@@ -36,13 +54,12 @@ class ExtendedDragSource : public DataSourceObserver {
class Observer { class Observer {
public: public:
virtual void OnExtendedDragSourceDestroying(ExtendedDragSource* source) = 0; virtual void OnExtendedDragSourceDestroying(ExtendedDragSource* source) = 0;
virtual void OnDraggedSurfaceChanged(ExtendedDragSource* source) = 0;
protected: protected:
virtual ~Observer() = default; virtual ~Observer() = default;
}; };
ExtendedDragSource(DataSource* source, Seat* seat, Delegate* delegate); ExtendedDragSource(DataSource* source, Delegate* delegate);
ExtendedDragSource(const ExtendedDragSource&) = delete; ExtendedDragSource(const ExtendedDragSource&) = delete;
ExtendedDragSource& operator=(const ExtendedDragSource&) = delete; ExtendedDragSource& operator=(const ExtendedDragSource&) = delete;
~ExtendedDragSource() override; ~ExtendedDragSource() override;
...@@ -50,28 +67,46 @@ class ExtendedDragSource : public DataSourceObserver { ...@@ -50,28 +67,46 @@ class ExtendedDragSource : public DataSourceObserver {
void AddObserver(Observer* observer); void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer); void RemoveObserver(Observer* observer);
bool should_allow_drop_anywhere() const { void Drag(Surface* surface, const gfx::Vector2d& offset);
return delegate_->ShouldAllowDropAnywhere();
}
bool should_lock_cursor() const { return delegate_->ShouldLockCursor(); }
const gfx::Vector2d& drag_offset() const { return drag_offset_; } bool IsActive() const;
void Drag(Surface* surface, const gfx::Vector2d& offset); // ash::ToplevelWindowDragDelegate:
void OnToplevelWindowDragStarted(const gfx::PointF& start_location,
ui::mojom::DragEventSource source) override;
int OnToplevelWindowDragDropped() override;
void OnToplevelWindowDragCancelled() override;
void OnToplevelWindowDragEvent(ui::LocatedEvent* event) override;
private:
// DataSourceObserver: // DataSourceObserver:
void OnDataSourceDestroying(DataSource* source) override; void OnDataSourceDestroying(DataSource* source) override;
aura::Window* GetDraggedWindowForTesting();
base::Optional<gfx::Vector2d> GetDragOffsetForTesting() const;
private:
class DraggedWindowHolder;
void StartDrag(aura::Window* toplevel,
const gfx::PointF& pointer_location_in_screen);
void OnDraggedWindowVisibilityChanging(bool visible);
gfx::Point CalculateOrigin(aura::Window* target) const;
void Cleanup();
// Created and destroyed at wayland/zcr_extended_drag.cc and its lifetime is // Created and destroyed at wayland/zcr_extended_drag.cc and its lifetime is
// tied to the zcr_extended_drag_source_v1 object it's attached to. // tied to the zcr_extended_drag_source_v1 object it's attached to.
Delegate* const delegate_; Delegate* const delegate_;
Seat* const seat_;
DataSource* source_ = nullptr; DataSource* source_ = nullptr;
Surface* dragged_surface_ = nullptr; gfx::PointF pointer_location_;
gfx::Vector2d drag_offset_; ui::mojom::DragEventSource drag_event_source_;
std::unique_ptr<DraggedWindowHolder> dragged_window_holder_;
std::unique_ptr<aura::ScopedWindowEventTargetingBlocker> event_blocker_;
base::ObserverList<Observer>::Unchecked observers_; base::ObserverList<Observer>::Unchecked observers_;
base::WeakPtrFactory<ExtendedDragSource> weak_factory_{this};
}; };
} // namespace exo } // namespace exo
......
This diff is collapsed.
...@@ -143,7 +143,6 @@ void extended_drag_get_extended_drag_source(wl_client* client, ...@@ -143,7 +143,6 @@ void extended_drag_get_extended_drag_source(wl_client* client,
uint32_t id, uint32_t id,
wl_resource* data_source_resource, wl_resource* data_source_resource,
uint32_t settings) { uint32_t settings) {
Display* display = GetUserDataAs<Display>(resource);
DataSource* source = GetUserDataAs<DataSource>(data_source_resource); DataSource* source = GetUserDataAs<DataSource>(data_source_resource);
wl_resource* extended_drag_source_resource = wl_resource* extended_drag_source_resource =
...@@ -153,8 +152,7 @@ void extended_drag_get_extended_drag_source(wl_client* client, ...@@ -153,8 +152,7 @@ void extended_drag_get_extended_drag_source(wl_client* client,
SetImplementation(extended_drag_source_resource, SetImplementation(extended_drag_source_resource,
&extended_drag_source_implementation, &extended_drag_source_implementation,
std::make_unique<ExtendedDragSource>( std::make_unique<ExtendedDragSource>(
source, display->seat(), source, new ZcrExtendedDragSourceDelegate(
new ZcrExtendedDragSourceDelegate(
extended_drag_source_resource, settings))); extended_drag_source_resource, settings)));
} }
......
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