Commit e3a08235 authored by Julie Jeongeun Kim's avatar Julie Jeongeun Kim Committed by Commit Bot

[ozone/wayland] Implement 'Drag and Drop' on Wayland

This CL is a part of changes for 'Drag and Drop' on wayland and
extends WaylandDataDevice, WaylandDataSource and WaylandDataOffer.

WaylandDataDevice registers event listeners for 'drag and drop',
has 'StartDrag' API connected with 'wl_data_device_start_drag' and
includes reading the data from Wayland.

WaylandDataSource registers event listeners for 'drag and drop' to
handle at a source side and writes the data to the fd delivered
from Wayland when it gets 'OnSend' event.

WaylandDataOffer gets the operation decided by Wayland and requests
the offered data by Wayland.

FakeServer is also extended to support the various compositor side
functionalities needed so that tests 'drag-and-drop' in
wayland_data_device_unittest.cc run. MockDataDevice, MockDataOffer
and MockDataSource classes are extended, implementing the respective
Wayland compositor hooks to communicate with Wayland clients
(eg Ozone/Wayland).

Flow:
1) Sending dragging
'WaylandDataDevice::StartDrag' triggers the drag action to Wayland,
Wayland requests the data through 'WaylandDataSource::OnSend' and
'WaylandDataSource' listens the status through 'OnCancel' or
'OnDnDDropPerformed'.

2) Getting dragging
'WaylandDataDevice' listens drag-and-drop status such as entered/
moved/dropped/left. When the drop action is performed,
'WaylandDataDevice' reads the data using 'WaylandDataOffer'.

BUG=875164
TEST=ozone_unittests

Change-Id: Ic1ad80fce4ac396385f3ba6780839ef31d717683
Reviewed-on: https://chromium-review.googlesource.com/1176891Reviewed-by: default avatarRobert Kroeger <rjkroege@chromium.org>
Reviewed-by: default avatarSadrul Chowdhury <sadrul@chromium.org>
Reviewed-by: default avatarAntonio Gomes <tonikitoo@igalia.com>
Reviewed-by: default avatarMaksim Sisov <msisov@igalia.com>
Commit-Queue: Julie Jeongeun Kim <jkim@igalia.com>
Cr-Commit-Position: refs/heads/master@{#589375}
parent 52228bc7
...@@ -157,6 +157,7 @@ source_set("wayland_unittests") { ...@@ -157,6 +157,7 @@ source_set("wayland_unittests") {
"//testing/gtest", "//testing/gtest",
"//third_party/wayland:wayland_server", "//third_party/wayland:wayland_server",
"//third_party/wayland-protocols:xdg_shell_protocol", "//third_party/wayland-protocols:xdg_shell_protocol",
"//ui/base",
"//ui/base:ui_features", "//ui/base:ui_features",
"//ui/events/ozone:events_ozone_layout", "//ui/events/ozone:events_ozone_layout",
"//ui/ozone:platform", "//ui/ozone:platform",
......
include_rules = [ include_rules = [
"+ui/base/ui_features.h", # UI features doesn't bring in all of ui/base. "+ui/base/ui_features.h", # UI features doesn't bring in all of ui/base.
"+mojo/public", "+mojo/public",
"+ui/base/dragdrop/drag_drop_types.h",
"+ui/base/dragdrop/os_exchange_data.h",
"+ui/base/dragdrop/os_exchange_data_provider_aura.h",
] ]
...@@ -290,6 +290,15 @@ const struct zxdg_positioner_v6_interface zxdg_positioner_v6_impl = { ...@@ -290,6 +290,15 @@ const struct zxdg_positioner_v6_interface zxdg_positioner_v6_impl = {
// wl_data_device // wl_data_device
void DataDeviceStartDrag(wl_client* client,
wl_resource* resource,
wl_resource* source,
wl_resource* origin,
wl_resource* icon,
uint32_t serial) {
NOTIMPLEMENTED();
}
void DataDeviceSetSelection(wl_client* client, void DataDeviceSetSelection(wl_client* client,
wl_resource* resource, wl_resource* resource,
wl_resource* data_source, wl_resource* data_source,
...@@ -304,8 +313,7 @@ void DataDeviceRelease(wl_client* client, wl_resource* resource) { ...@@ -304,8 +313,7 @@ void DataDeviceRelease(wl_client* client, wl_resource* resource) {
} }
const struct wl_data_device_interface data_device_impl = { const struct wl_data_device_interface data_device_impl = {
nullptr /*data_device_start_drag*/, &DataDeviceSetSelection, &DataDeviceStartDrag, &DataDeviceSetSelection, &DataDeviceRelease};
&DataDeviceRelease};
// wl_data_device_manager // wl_data_device_manager
...@@ -347,6 +355,13 @@ const struct wl_data_device_manager_interface data_device_manager_impl = { ...@@ -347,6 +355,13 @@ const struct wl_data_device_manager_interface data_device_manager_impl = {
// wl_data_offer // wl_data_offer
void DataOfferAccept(wl_client* client,
wl_resource* resource,
uint32_t serial,
const char* mime_type) {
NOTIMPLEMENTED();
}
void DataOfferReceive(wl_client* client, void DataOfferReceive(wl_client* client,
wl_resource* resource, wl_resource* resource,
const char* mime_type, const char* mime_type,
...@@ -359,10 +374,20 @@ void DataOfferDestroy(wl_client* client, wl_resource* resource) { ...@@ -359,10 +374,20 @@ void DataOfferDestroy(wl_client* client, wl_resource* resource) {
wl_resource_destroy(resource); wl_resource_destroy(resource);
} }
void DataOfferFinish(wl_client* client, wl_resource* resource) {
NOTIMPLEMENTED();
}
void DataOfferSetActions(wl_client* client,
wl_resource* resource,
uint32_t dnd_actions,
uint32_t preferred_action) {
NOTIMPLEMENTED();
}
const struct wl_data_offer_interface data_offer_impl = { const struct wl_data_offer_interface data_offer_impl = {
nullptr /* data_offer_accept*/, DataOfferReceive, DataOfferAccept, DataOfferReceive, DataOfferDestroy, DataOfferFinish,
nullptr /*data_offer_finish*/, DataOfferDestroy, DataOfferSetActions};
nullptr /*data_offer_set_actions*/};
// wl_data_source // wl_data_source
...@@ -376,8 +401,14 @@ void DataSourceDestroy(wl_client* client, wl_resource* resource) { ...@@ -376,8 +401,14 @@ void DataSourceDestroy(wl_client* client, wl_resource* resource) {
wl_resource_destroy(resource); wl_resource_destroy(resource);
} }
void SetActions(wl_client* client,
wl_resource* resource,
uint32_t dnd_actions) {
NOTIMPLEMENTED();
}
const struct wl_data_source_interface data_source_impl = { const struct wl_data_source_interface data_source_impl = {
DataSourceOffer, DataSourceDestroy, nullptr /*data_source_set_actions*/}; DataSourceOffer, DataSourceDestroy, SetActions};
// wl_seat // wl_seat
...@@ -784,10 +815,15 @@ MockDataOffer::~MockDataOffer() {} ...@@ -784,10 +815,15 @@ MockDataOffer::~MockDataOffer() {}
void MockDataOffer::Receive(const std::string& mime_type, base::ScopedFD fd) { void MockDataOffer::Receive(const std::string& mime_type, base::ScopedFD fd) {
DCHECK(fd.is_valid()); DCHECK(fd.is_valid());
std::string text_utf8(kSampleClipboardText); std::string text_data;
if (mime_type == kTextMimeTypeUtf8)
text_data = kSampleClipboardText;
else if (mime_type == kTextMimeTypeText)
text_data = kSampleTextForDragAndDrop;
io_thread_.task_runner()->PostTask( io_thread_.task_runner()->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&WriteDataOnWorkerThread, std::move(fd), text_utf8)); base::BindOnce(&WriteDataOnWorkerThread, std::move(fd), text_data));
} }
void MockDataOffer::OnOffer(const std::string& mime_type) { void MockDataOffer::OnOffer(const std::string& mime_type) {
...@@ -816,6 +852,27 @@ MockDataOffer* MockDataDevice::OnDataOffer() { ...@@ -816,6 +852,27 @@ MockDataOffer* MockDataDevice::OnDataOffer() {
return GetUserDataAs<MockDataOffer>(data_offer_resource); return GetUserDataAs<MockDataOffer>(data_offer_resource);
} }
void MockDataDevice::OnEnter(uint32_t serial,
wl_resource* surface,
wl_fixed_t x,
wl_fixed_t y,
MockDataOffer& data_offer) {
wl_data_device_send_enter(resource(), serial, surface, x, y,
data_offer.resource());
}
void MockDataDevice::OnLeave() {
wl_data_device_send_leave(resource());
}
void MockDataDevice::OnMotion(uint32_t time, wl_fixed_t x, wl_fixed_t y) {
wl_data_device_send_motion(resource(), time, x, y);
}
void MockDataDevice::OnDrop() {
wl_data_device_send_drop(resource());
}
void MockDataDevice::OnSelection(MockDataOffer& data_offer) { void MockDataDevice::OnSelection(MockDataOffer& data_offer) {
wl_data_device_send_selection(resource(), data_offer.resource()); wl_data_device_send_selection(resource(), data_offer.resource());
} }
......
...@@ -24,7 +24,10 @@ struct wl_resource; ...@@ -24,7 +24,10 @@ struct wl_resource;
namespace wl { namespace wl {
constexpr char kTextMimeTypeUtf8[] = "text/plain;charset=utf-8"; constexpr char kTextMimeTypeUtf8[] = "text/plain;charset=utf-8";
constexpr char kTextMimeTypeText[] = "text/plain";
constexpr char kSampleClipboardText[] = "This is a sample text for clipboard."; constexpr char kSampleClipboardText[] = "This is a sample text for clipboard.";
constexpr char kSampleTextForDragAndDrop[] =
"This is a sample text for drag-and-drop.";
// Base class for managing the life cycle of server objects. // Base class for managing the life cycle of server objects.
class ServerObject { class ServerObject {
...@@ -222,6 +225,14 @@ class MockDataDevice : public ServerObject { ...@@ -222,6 +225,14 @@ class MockDataDevice : public ServerObject {
void SetSelection(MockDataSource* data_source, uint32_t serial); void SetSelection(MockDataSource* data_source, uint32_t serial);
MockDataOffer* OnDataOffer(); MockDataOffer* OnDataOffer();
void OnEnter(uint32_t serial,
wl_resource* surface,
wl_fixed_t x,
wl_fixed_t y,
MockDataOffer& data_offer);
void OnLeave();
void OnMotion(uint32_t time, wl_fixed_t x, wl_fixed_t y);
void OnDrop();
void OnSelection(MockDataOffer& data_offer); void OnSelection(MockDataOffer& data_offer);
private: private:
......
...@@ -28,6 +28,14 @@ const uint32_t kMaxLinuxDmabufVersion = 1; ...@@ -28,6 +28,14 @@ const uint32_t kMaxLinuxDmabufVersion = 1;
const uint32_t kMaxSeatVersion = 4; const uint32_t kMaxSeatVersion = 4;
const uint32_t kMaxShmVersion = 1; const uint32_t kMaxShmVersion = 1;
const uint32_t kMaxXdgShellVersion = 1; const uint32_t kMaxXdgShellVersion = 1;
const uint32_t kMaxDeviceManagerVersion = 3;
std::unique_ptr<WaylandDataSource> CreateWaylandDataSource(
WaylandDataDeviceManager* data_device_manager,
WaylandConnection* connection) {
wl_data_source* data_source = data_device_manager->CreateSource();
return std::make_unique<WaylandDataSource>(data_source, connection);
}
} // namespace } // namespace
WaylandConnection::WaylandConnection() WaylandConnection::WaylandConnection()
...@@ -190,9 +198,7 @@ void WaylandConnection::OfferClipboardData( ...@@ -190,9 +198,7 @@ void WaylandConnection::OfferClipboardData(
const ClipboardDelegate::DataMap& data_map, const ClipboardDelegate::DataMap& data_map,
ClipboardDelegate::OfferDataClosure callback) { ClipboardDelegate::OfferDataClosure callback) {
if (!data_source_) { if (!data_source_) {
wl_data_source* data_source = data_device_manager_->CreateSource(); data_source_ = CreateWaylandDataSource(data_device_manager_.get(), this);
data_source_.reset(new WaylandDataSource(data_source));
data_source_->set_connection(this);
data_source_->WriteToClipboard(data_map); data_source_->WriteToClipboard(data_map);
} }
data_source_->UpdataDataMap(data_map); data_source_->UpdataDataMap(data_map);
...@@ -234,6 +240,36 @@ void WaylandConnection::SetTerminateGpuCallback( ...@@ -234,6 +240,36 @@ void WaylandConnection::SetTerminateGpuCallback(
terminate_gpu_cb_ = std::move(terminate_callback); terminate_gpu_cb_ = std::move(terminate_callback);
} }
void WaylandConnection::StartDrag(const ui::OSExchangeData& data,
int operation) {
if (!drag_data_source_) {
drag_data_source_ =
CreateWaylandDataSource(data_device_manager_.get(), this);
}
drag_data_source_->Offer(data);
drag_data_source_->SetAction(operation);
data_device_->StartDrag(*(drag_data_source_->data_source()), data);
}
void WaylandConnection::FinishDragSession(uint32_t dnd_action,
WaylandWindow* source_window) {
if (source_window)
source_window->OnDragSessionClose(dnd_action);
data_device_->ResetSourceData();
drag_data_source_.reset();
}
void WaylandConnection::DeliverDragData(const std::string& mime_type,
std::string* buffer) {
data_device_->DeliverDragData(mime_type, buffer);
}
void WaylandConnection::RequestDragData(
const std::string& mime_type,
base::OnceCallback<void(const std::string&)> callback) {
data_device_->RequestDragData(mime_type, std::move(callback));
}
void WaylandConnection::GetAvailableMimeTypes( void WaylandConnection::GetAvailableMimeTypes(
ClipboardDelegate::GetMimeTypesClosure callback) { ClipboardDelegate::GetMimeTypesClosure callback) {
std::move(callback).Run(data_device_->GetAvailableMimeTypes()); std::move(callback).Run(data_device_->GetAvailableMimeTypes());
...@@ -383,7 +419,8 @@ void WaylandConnection::Global(void* data, ...@@ -383,7 +419,8 @@ void WaylandConnection::Global(void* data,
} else if (!connection->data_device_manager_ && } else if (!connection->data_device_manager_ &&
strcmp(interface, "wl_data_device_manager") == 0) { strcmp(interface, "wl_data_device_manager") == 0) {
wl::Object<wl_data_device_manager> data_device_manager = wl::Object<wl_data_device_manager> data_device_manager =
wl::Bind<wl_data_device_manager>(registry, name, 1); wl::Bind<wl_data_device_manager>(
registry, name, std::min(version, kMaxDeviceManagerVersion));
if (!data_device_manager) { if (!data_device_manager) {
LOG(ERROR) << "Failed to bind to wl_data_device_manager global"; LOG(ERROR) << "Failed to bind to wl_data_device_manager global";
return; return;
......
...@@ -94,6 +94,8 @@ class WaylandConnection : public PlatformEventSource, ...@@ -94,6 +94,8 @@ class WaylandConnection : public PlatformEventSource,
// Returns the current pointer, which may be null. // Returns the current pointer, which may be null.
WaylandPointer* pointer() { return pointer_.get(); } WaylandPointer* pointer() { return pointer_.get(); }
WaylandDataSource* drag_data_source() { return drag_data_source_.get(); }
// Clipboard implementation. // Clipboard implementation.
ClipboardDelegate* GetClipboardDelegate(); ClipboardDelegate* GetClipboardDelegate();
void DataSourceCancelled(); void DataSourceCancelled();
...@@ -120,6 +122,23 @@ class WaylandConnection : public PlatformEventSource, ...@@ -120,6 +122,23 @@ class WaylandConnection : public PlatformEventSource,
void SetTerminateGpuCallback( void SetTerminateGpuCallback(
base::OnceCallback<void(std::string)> terminate_gpu_cb); base::OnceCallback<void(std::string)> terminate_gpu_cb);
// Starts drag with |data| to be delivered, |operation| supported by the
// source side initiated the dragging.
void StartDrag(const ui::OSExchangeData& data, int operation);
// Finishes drag and drop session. It happens when WaylandDataSource gets
// 'OnDnDFinished' or 'OnCancel', which means the drop is performed or
// canceled on others.
void FinishDragSession(uint32_t dnd_action, WaylandWindow* source_window);
// Delivers the data owned by Chromium which initiates drag-and-drop. |buffer|
// is an output parameter and it should be filled with the data corresponding
// to mime_type.
void DeliverDragData(const std::string& mime_type, std::string* buffer);
// Requests the data to the platform when Chromium gets drag-and-drop started
// by others. Once reading the data from platform is done, |callback| should
// be called with the data.
void RequestDragData(const std::string& mime_type,
base::OnceCallback<void(const std::string&)> callback);
private: private:
void Flush(); void Flush();
void DispatchUiEvent(Event* event); void DispatchUiEvent(Event* event);
...@@ -166,6 +185,7 @@ class WaylandConnection : public PlatformEventSource, ...@@ -166,6 +185,7 @@ class WaylandConnection : public PlatformEventSource,
std::unique_ptr<WaylandDataDeviceManager> data_device_manager_; std::unique_ptr<WaylandDataDeviceManager> data_device_manager_;
std::unique_ptr<WaylandDataDevice> data_device_; std::unique_ptr<WaylandDataDevice> data_device_;
std::unique_ptr<WaylandDataSource> data_source_; std::unique_ptr<WaylandDataSource> data_source_;
std::unique_ptr<WaylandDataSource> drag_data_source_;
std::unique_ptr<WaylandPointer> pointer_; std::unique_ptr<WaylandPointer> pointer_;
std::unique_ptr<WaylandKeyboard> keyboard_; std::unique_ptr<WaylandKeyboard> keyboard_;
std::unique_ptr<WaylandTouch> touch_; std::unique_ptr<WaylandTouch> touch_;
......
...@@ -6,23 +6,31 @@ ...@@ -6,23 +6,31 @@
#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_DATA_DEVICE_H_ #define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_DATA_DEVICE_H_
#include <wayland-client.h> #include <wayland-client.h>
#include <list>
#include <string> #include <string>
#include "base/callback.h" #include "base/callback.h"
#include "base/files/scoped_file.h" #include "base/files/scoped_file.h"
#include "base/macros.h" #include "base/macros.h"
#include "ui/gfx/geometry/size.h"
#include "ui/ozone/platform/wayland/wayland_data_offer.h" #include "ui/ozone/platform/wayland/wayland_data_offer.h"
#include "ui/ozone/platform/wayland/wayland_object.h" #include "ui/ozone/platform/wayland/wayland_object.h"
class SkBitmap;
namespace base {
class SharedMemory;
}
namespace ui { namespace ui {
class OSExchangeData;
class WaylandDataOffer; class WaylandDataOffer;
class WaylandConnection; class WaylandConnection;
class WaylandWindow;
// This class provides access to inter-client data transfer mechanisms // This class provides access to inter-client data transfer mechanisms
// such as copy-and-paste and drag-and-drop mechanisms. // such as copy-and-paste and drag-and-drop mechanisms.
//
// TODO(tonikitoo,msisov): Add drag&drop support.
class WaylandDataDevice { class WaylandDataDevice {
public: public:
WaylandDataDevice(WaylandConnection* connection, wl_data_device* data_device); WaylandDataDevice(WaylandConnection* connection, wl_data_device* data_device);
...@@ -30,23 +38,66 @@ class WaylandDataDevice { ...@@ -30,23 +38,66 @@ class WaylandDataDevice {
void RequestSelectionData(const std::string& mime_type); void RequestSelectionData(const std::string& mime_type);
wl_data_device* data_device() { return data_device_.get(); } // Requests the data to the platform when Chromium gets drag-and-drop started
// by others. Once reading the data from platform is done, |callback| should
// be called with the data.
void RequestDragData(const std::string& mime_type,
base::OnceCallback<void(const std::string&)> callback);
// Delivers the data owned by Chromium which initiates drag-and-drop. |buffer|
// is an output parameter and it should be filled with the data corresponding
// to mime_type.
void DeliverDragData(const std::string& mime_type, std::string* buffer);
// Starts drag with |data| to be delivered, |operation| supported by the
// source side initiated the dragging.
void StartDrag(const wl_data_source& data_source,
const ui::OSExchangeData& data);
// Resets |source_data_| when the dragging is finished.
void ResetSourceData();
std::vector<std::string> GetAvailableMimeTypes(); std::vector<std::string> GetAvailableMimeTypes();
wl_data_device* data_device() const { return data_device_.get(); }
private: private:
void ReadClipboardDataFromFD(base::ScopedFD fd, const std::string& mime_type); void ReadClipboardDataFromFD(base::ScopedFD fd, const std::string& mime_type);
void ReadDragDataFromFD(
base::ScopedFD fd,
base::OnceCallback<void(const std::string&)> callback);
// Registers display sync callback. Once it's called, it's reset. // Registers display sync callback. Once it's called, it's reset.
void RegisterSyncCallback(); void RegisterSyncCallback();
// Helper function to read data from fd. // Helper function to read data from fd.
void ReadDataFromFD(base::ScopedFD fd, std::string* contents); void ReadDataFromFD(base::ScopedFD fd, std::string* contents);
// If OnLeave event occurs while it's reading drag data, it defers handling
// it. Once reading data is completed, it's handled.
void HandleDeferredLeaveIfNeeded();
// wl_data_device_listener callbacks // wl_data_device_listener callbacks
static void OnDataOffer(void* data, static void OnDataOffer(void* data,
wl_data_device* data_device, wl_data_device* data_device,
wl_data_offer* id); wl_data_offer* id);
static void OnEnter(void* data,
wl_data_device* data_device,
uint32_t serial,
wl_surface* surface,
wl_fixed_t x,
wl_fixed_t y,
wl_data_offer* offer);
static void OnMotion(void* data,
struct wl_data_device* data_device,
uint32_t time,
wl_fixed_t x,
wl_fixed_t y);
static void OnDrop(void* data, struct wl_data_device* data_device);
static void OnLeave(void* data, struct wl_data_device* data_device);
// Called by the compositor when the window gets pointer or keyboard focus, // Called by the compositor when the window gets pointer or keyboard focus,
// or clipboard content changes behind the scenes. // or clipboard content changes behind the scenes.
// //
...@@ -57,6 +108,22 @@ class WaylandDataDevice { ...@@ -57,6 +108,22 @@ class WaylandDataDevice {
static void SyncCallback(void* data, struct wl_callback* cb, uint32_t time); static void SyncCallback(void* data, struct wl_callback* cb, uint32_t time);
bool CreateSHMBuffer(const gfx::Size& size);
void CreateDragImage(const SkBitmap* bitmap);
void OnDragDataReceived(const std::string& contents);
void OnDragDataCollected();
// Returns the next MIME type to be received from the source process, or an
// empty string if there are no more interesting MIME types left to process.
std::string SelectNextMimeType();
// If it has |unprocessed_mime_types_|, it takes the mime type in front and
// requests the data corresponding to the mime type to wayland.
void HandleNextMimeType();
// Set drag operation decided by client.
void SetOperation(const int operation);
// The wl_data_device wrapped by this WaylandDataDevice. // The wl_data_device wrapped by this WaylandDataDevice.
wl::Object<wl_data_device> data_device_; wl::Object<wl_data_device> data_device_;
...@@ -75,11 +142,36 @@ class WaylandDataDevice { ...@@ -75,11 +142,36 @@ class WaylandDataDevice {
// clipboard data is available. // clipboard data is available.
std::unique_ptr<WaylandDataOffer> selection_offer_; std::unique_ptr<WaylandDataOffer> selection_offer_;
// Offer to receive data from another process via drag-and-drop, or null if no
// drag-and-drop from another process is in progress.
std::unique_ptr<WaylandDataOffer> drag_offer_;
WaylandWindow* window_ = nullptr;
// Make sure server has written data on the pipe, before block on read(). // Make sure server has written data on the pipe, before block on read().
static const wl_callback_listener callback_listener_; static const wl_callback_listener callback_listener_;
base::OnceClosure read_from_fd_closure_; base::OnceClosure read_from_fd_closure_;
wl::Object<wl_callback> sync_callback_; wl::Object<wl_callback> sync_callback_;
bool is_handling_dropped_data_ = false;
bool is_leaving_ = false;
std::unique_ptr<base::SharedMemory> shared_memory_;
wl::Object<wl_buffer> buffer_;
wl::Object<wl_surface> icon_surface_;
gfx::Size icon_buffer_size_;
// Mime types to be handled.
std::list<std::string> unprocessed_mime_types_;
// The data delivered from Wayland
std::unique_ptr<ui::OSExchangeData> received_data_;
// When dragging is started from Chromium, |source_data_| is forwarded to
// Wayland when they are ready to get the data.
std::unique_ptr<ui::OSExchangeData> source_data_;
DISALLOW_COPY_AND_ASSIGN(WaylandDataDevice); DISALLOW_COPY_AND_ASSIGN(WaylandDataDevice);
}; };
......
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
#include <wayland-server.h> #include <wayland-server.h>
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/events/base_event_utils.h"
#include "ui/ozone/platform/wayland/fake_server.h" #include "ui/ozone/platform/wayland/fake_server.h"
#include "ui/ozone/platform/wayland/wayland_test.h" #include "ui/ozone/platform/wayland/wayland_test.h"
#include "ui/ozone/public/clipboard_delegate.h" #include "ui/ozone/public/clipboard_delegate.h"
...@@ -131,6 +134,63 @@ TEST_P(WaylandDataDeviceManagerTest, IsSelectionOwner) { ...@@ -131,6 +134,63 @@ TEST_P(WaylandDataDeviceManagerTest, IsSelectionOwner) {
ASSERT_FALSE(clipboard_client_->IsSelectionOwner()); ASSERT_FALSE(clipboard_client_->IsSelectionOwner());
} }
TEST_P(WaylandDataDeviceManagerTest, StartDrag) {
bool restored_focus = window_->has_pointer_focus();
window_->set_pointer_focus(true);
// The client starts dragging.
std::unique_ptr<OSExchangeData> os_exchange_data =
std::make_unique<OSExchangeData>();
int operation = DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_MOVE;
connection_->StartDrag(*os_exchange_data, operation);
WaylandDataSource::DragDataMap data;
data[wl::kTextMimeTypeText] = wl::kSampleTextForDragAndDrop;
connection_->drag_data_source()->SetDragData(data);
Sync();
// The server reads the data and the callback gets it.
data_device_manager_->data_source()->ReadData(
base::BindOnce([](const std::vector<uint8_t>& data) {
std::string string_data(data.begin(), data.end());
EXPECT_EQ(wl::kSampleTextForDragAndDrop, string_data);
}));
window_->set_pointer_focus(restored_focus);
}
TEST_P(WaylandDataDeviceManagerTest, ReceiveDrag) {
auto* data_offer = data_device_manager_->data_device()->OnDataOffer();
data_offer->OnOffer(wl::kTextMimeTypeText);
gfx::Point entered_point(10, 10);
// The server sends an enter event.
data_device_manager_->data_device()->OnEnter(
1002, surface_->resource(), wl_fixed_from_int(entered_point.x()),
wl_fixed_from_int(entered_point.y()), *data_offer);
int64_t time =
(ui::EventTimeForNow() - base::TimeTicks()).InMilliseconds() & UINT32_MAX;
gfx::Point motion_point(11, 11);
// The server sends an motion event.
data_device_manager_->data_device()->OnMotion(
time, wl_fixed_from_int(motion_point.x()),
wl_fixed_from_int(motion_point.y()));
Sync();
auto callback = base::BindOnce([](const std::string& contents) {
EXPECT_EQ(wl::kSampleTextForDragAndDrop, contents);
});
// The client requests the data and gets callback with it.
connection_->RequestDragData(wl::kTextMimeTypeText, std::move(callback));
Sync();
data_device_manager_->data_device()->OnLeave();
}
INSTANTIATE_TEST_CASE_P(XdgVersionV5Test, INSTANTIATE_TEST_CASE_P(XdgVersionV5Test,
WaylandDataDeviceManagerTest, WaylandDataDeviceManagerTest,
::testing::Values(kXdgShellV5)); ::testing::Values(kXdgShellV5));
......
...@@ -30,9 +30,12 @@ void CreatePipe(base::ScopedFD* read_pipe, base::ScopedFD* write_pipe) { ...@@ -30,9 +30,12 @@ void CreatePipe(base::ScopedFD* read_pipe, base::ScopedFD* write_pipe) {
} // namespace } // namespace
WaylandDataOffer::WaylandDataOffer(wl_data_offer* data_offer) WaylandDataOffer::WaylandDataOffer(wl_data_offer* data_offer)
: data_offer_(data_offer) { : data_offer_(data_offer),
source_actions_(WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE),
dnd_action_(WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE) {
static const struct wl_data_offer_listener kDataOfferListener = { static const struct wl_data_offer_listener kDataOfferListener = {
WaylandDataOffer::OnOffer}; WaylandDataOffer::OnOffer, WaylandDataOffer::OnSourceAction,
WaylandDataOffer::OnAction};
wl_data_offer_add_listener(data_offer, &kDataOfferListener, this); wl_data_offer_add_listener(data_offer, &kDataOfferListener, this);
} }
...@@ -40,6 +43,23 @@ WaylandDataOffer::~WaylandDataOffer() { ...@@ -40,6 +43,23 @@ WaylandDataOffer::~WaylandDataOffer() {
data_offer_.reset(); data_offer_.reset();
} }
void WaylandDataOffer::SetAction(uint32_t dnd_actions,
uint32_t preferred_action) {
if (wl_data_offer_get_version(data_offer_.get()) >=
WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION) {
wl_data_offer_set_actions(data_offer_.get(), dnd_actions, preferred_action);
}
}
void WaylandDataOffer::Accept(uint32_t serial, const std::string& mime_type) {
wl_data_offer_accept(data_offer_.get(), serial, mime_type.c_str());
}
void WaylandDataOffer::Reject(uint32_t serial) {
// Passing a null MIME type means "reject."
wl_data_offer_accept(data_offer_.get(), serial, nullptr);
}
void WaylandDataOffer::EnsureTextMimeTypeIfNeeded() { void WaylandDataOffer::EnsureTextMimeTypeIfNeeded() {
if (base::ContainsValue(mime_types_, kTextPlain)) if (base::ContainsValue(mime_types_, kTextPlain))
return; return;
...@@ -76,6 +96,20 @@ base::ScopedFD WaylandDataOffer::Receive(const std::string& mime_type) { ...@@ -76,6 +96,20 @@ base::ScopedFD WaylandDataOffer::Receive(const std::string& mime_type) {
return read_fd; return read_fd;
} }
void WaylandDataOffer::FinishOffer() {
if (wl_data_offer_get_version(data_offer_.get()) >=
WL_DATA_OFFER_FINISH_SINCE_VERSION)
wl_data_offer_finish(data_offer_.get());
}
uint32_t WaylandDataOffer::source_actions() const {
return source_actions_;
}
uint32_t WaylandDataOffer::dnd_action() const {
return dnd_action_;
}
// static // static
void WaylandDataOffer::OnOffer(void* data, void WaylandDataOffer::OnOffer(void* data,
wl_data_offer* data_offer, wl_data_offer* data_offer,
...@@ -84,4 +118,18 @@ void WaylandDataOffer::OnOffer(void* data, ...@@ -84,4 +118,18 @@ void WaylandDataOffer::OnOffer(void* data,
self->mime_types_.push_back(mime_type); self->mime_types_.push_back(mime_type);
} }
void WaylandDataOffer::OnSourceAction(void* data,
wl_data_offer* offer,
uint32_t source_actions) {
auto* self = static_cast<WaylandDataOffer*>(data);
self->source_actions_ = source_actions;
}
void WaylandDataOffer::OnAction(void* data,
wl_data_offer* offer,
uint32_t dnd_action) {
auto* self = static_cast<WaylandDataOffer*>(data);
self->dnd_action_ = dnd_action;
}
} // namespace ui } // namespace ui
...@@ -23,8 +23,6 @@ namespace ui { ...@@ -23,8 +23,6 @@ namespace ui {
// The offer describes the different mime types that the data can be // The offer describes the different mime types that the data can be
// converted to and provides the mechanism for transferring the data // converted to and provides the mechanism for transferring the data
// directly from the source client. // directly from the source client.
//
// TODO(tonikitoo,msisov): Add drag&drop support.
class WaylandDataOffer { class WaylandDataOffer {
public: public:
// Takes ownership of data_offer. // Takes ownership of data_offer.
...@@ -42,20 +40,36 @@ class WaylandDataOffer { ...@@ -42,20 +40,36 @@ class WaylandDataOffer {
// list of provided mime types so that Chrome clipboard's machinery // list of provided mime types so that Chrome clipboard's machinery
// works fine. // works fine.
void EnsureTextMimeTypeIfNeeded(); void EnsureTextMimeTypeIfNeeded();
void SetAction(uint32_t dnd_actions, uint32_t preferred_action);
void Accept(uint32_t serial, const std::string& mime_type);
void Reject(uint32_t serial);
// Creates a pipe (read & write FDs), passing the write-end of to pipe // Creates a pipe (read & write FDs), passing the write-end of to pipe
// to the compositor (via wl_data_offer_receive) and returning the // to the compositor (via wl_data_offer_receive) and returning the
// read-end to the pipe. // read-end to the pipe.
base::ScopedFD Receive(const std::string& mime_type); base::ScopedFD Receive(const std::string& mime_type);
void FinishOffer();
uint32_t source_actions() const;
uint32_t dnd_action() const;
private: private:
// wl_data_offer_listener callbacks. // wl_data_offer_listener callbacks.
static void OnOffer(void* data, static void OnOffer(void* data,
wl_data_offer* data_offer, wl_data_offer* data_offer,
const char* mime_type); const char* mime_type);
// Notifies the source-side available actions
static void OnSourceAction(void* data,
wl_data_offer* offer,
uint32_t source_actions);
// Notifies the selected action
static void OnAction(void* data, wl_data_offer* offer, uint32_t dnd_action);
wl::Object<wl_data_offer> data_offer_; wl::Object<wl_data_offer> data_offer_;
std::vector<std::string> mime_types_; std::vector<std::string> mime_types_;
// Actions offered by the data source
uint32_t source_actions_;
// Action selected by the compositor
uint32_t dnd_action_;
bool text_plain_mime_type_inserted_ = false; bool text_plain_mime_type_inserted_ = false;
......
...@@ -5,17 +5,22 @@ ...@@ -5,17 +5,22 @@
#include "ui/ozone/platform/wayland/wayland_data_source.h" #include "ui/ozone/platform/wayland/wayland_data_source.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/ozone/platform/wayland/wayland_connection.h" #include "ui/ozone/platform/wayland/wayland_connection.h"
#include "ui/ozone/platform/wayland/wayland_window.h"
namespace ui { namespace ui {
constexpr char kTextMimeType[] = "text/plain";
constexpr char kTextMimeTypeUtf8[] = "text/plain;charset=utf-8"; constexpr char kTextMimeTypeUtf8[] = "text/plain;charset=utf-8";
WaylandDataSource::WaylandDataSource(wl_data_source* data_source) WaylandDataSource::WaylandDataSource(wl_data_source* data_source,
: data_source_(data_source) { WaylandConnection* connection)
: data_source_(data_source), connection_(connection) {
static const struct wl_data_source_listener kDataSourceListener = { static const struct wl_data_source_listener kDataSourceListener = {
WaylandDataSource::OnTarget, WaylandDataSource::OnSend, WaylandDataSource::OnTarget, WaylandDataSource::OnSend,
WaylandDataSource::OnCancel}; WaylandDataSource::OnCancel, WaylandDataSource::OnDnDDropPerformed,
WaylandDataSource::OnDnDFinished, WaylandDataSource::OnAction};
wl_data_source_add_listener(data_source, &kDataSourceListener, this); wl_data_source_add_listener(data_source, &kDataSourceListener, this);
} }
...@@ -25,7 +30,7 @@ void WaylandDataSource::WriteToClipboard( ...@@ -25,7 +30,7 @@ void WaylandDataSource::WriteToClipboard(
const ClipboardDelegate::DataMap& data_map) { const ClipboardDelegate::DataMap& data_map) {
for (const auto& data : data_map) { for (const auto& data : data_map) {
wl_data_source_offer(data_source_.get(), data.first.c_str()); wl_data_source_offer(data_source_.get(), data.first.c_str());
if (strcmp(data.first.c_str(), "text/plain") == 0) if (strcmp(data.first.c_str(), kTextMimeType) == 0)
wl_data_source_offer(data_source_.get(), kTextMimeTypeUtf8); wl_data_source_offer(data_source_.get(), kTextMimeTypeUtf8);
} }
wl_data_device_set_selection(connection_->data_device(), data_source_.get(), wl_data_device_set_selection(connection_->data_device(), data_source_.get(),
...@@ -39,11 +44,39 @@ void WaylandDataSource::UpdataDataMap( ...@@ -39,11 +44,39 @@ void WaylandDataSource::UpdataDataMap(
data_map_ = data_map; data_map_ = data_map;
} }
void WaylandDataSource::Offer(const ui::OSExchangeData& data) {
// TODO(jkim): Handle mime types based on data.
std::vector<std::string> mime_types;
mime_types.push_back(kTextMimeType);
mime_types.push_back(kTextMimeTypeUtf8);
source_window_ = connection_->GetCurrentFocusedWindow();
for (auto& mime_type : mime_types)
wl_data_source_offer(data_source_.get(), mime_type.data());
}
void WaylandDataSource::SetDragData(const DragDataMap& data_map) {
DCHECK(drag_data_map_.empty());
drag_data_map_ = data_map;
}
void WaylandDataSource::SetAction(int operation) {
if (wl_data_source_get_version(data_source_.get()) >=
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION) {
uint32_t dnd_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
if (operation & DragDropTypes::DRAG_COPY)
dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
if (operation & DragDropTypes::DRAG_MOVE)
dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
wl_data_source_set_actions(data_source_.get(), dnd_actions);
}
}
// static // static
void WaylandDataSource::OnTarget(void* data, void WaylandDataSource::OnTarget(void* data,
wl_data_source* source, wl_data_source* source,
const char* mime_type) { const char* mime_type) {
NOTIMPLEMENTED(); NOTIMPLEMENTED_LOG_ONCE();
} }
// static // static
...@@ -52,12 +85,18 @@ void WaylandDataSource::OnSend(void* data, ...@@ -52,12 +85,18 @@ void WaylandDataSource::OnSend(void* data,
const char* mime_type, const char* mime_type,
int32_t fd) { int32_t fd) {
WaylandDataSource* self = static_cast<WaylandDataSource*>(data); WaylandDataSource* self = static_cast<WaylandDataSource*>(data);
base::Optional<std::vector<uint8_t>> mime_data; std::string contents;
self->GetClipboardData(mime_type, &mime_data); if (self->source_window_) {
if (!mime_data.has_value() && strcmp(mime_type, kTextMimeTypeUtf8) == 0) // If |source_window_| is valid when OnSend() is called, it means that DnD
self->GetClipboardData("text/plain", &mime_data); // is working.
self->GetDragData(mime_type, &contents);
std::string contents(mime_data->begin(), mime_data->end()); } else {
base::Optional<std::vector<uint8_t>> mime_data;
self->GetClipboardData(mime_type, &mime_data);
if (!mime_data.has_value() && strcmp(mime_type, kTextMimeTypeUtf8) == 0)
self->GetClipboardData(kTextMimeType, &mime_data);
contents.assign(mime_data->begin(), mime_data->end());
}
bool result = bool result =
base::WriteFileDescriptor(fd, contents.data(), contents.length()); base::WriteFileDescriptor(fd, contents.data(), contents.length());
DCHECK(result); DCHECK(result);
...@@ -67,7 +106,30 @@ void WaylandDataSource::OnSend(void* data, ...@@ -67,7 +106,30 @@ void WaylandDataSource::OnSend(void* data,
// static // static
void WaylandDataSource::OnCancel(void* data, wl_data_source* source) { void WaylandDataSource::OnCancel(void* data, wl_data_source* source) {
WaylandDataSource* self = static_cast<WaylandDataSource*>(data); WaylandDataSource* self = static_cast<WaylandDataSource*>(data);
self->connection_->DataSourceCancelled(); if (self->source_window_) {
// If it has |source_window_|, it is in the middle of 'drag and drop'. it
// cancels 'drag and drop'.
self->connection_->FinishDragSession(self->dnd_action_,
self->source_window_);
} else {
self->connection_->DataSourceCancelled();
}
}
void WaylandDataSource::OnDnDDropPerformed(void* data, wl_data_source* source) {
NOTIMPLEMENTED_LOG_ONCE();
}
void WaylandDataSource::OnDnDFinished(void* data, wl_data_source* source) {
WaylandDataSource* self = static_cast<WaylandDataSource*>(data);
self->connection_->FinishDragSession(self->dnd_action_, self->source_window_);
}
void WaylandDataSource::OnAction(void* data,
wl_data_source* source,
uint32_t dnd_action) {
WaylandDataSource* self = static_cast<WaylandDataSource*>(data);
self->dnd_action_ = dnd_action;
} }
void WaylandDataSource::GetClipboardData( void WaylandDataSource::GetClipboardData(
...@@ -81,4 +143,15 @@ void WaylandDataSource::GetClipboardData( ...@@ -81,4 +143,15 @@ void WaylandDataSource::GetClipboardData(
} }
} }
void WaylandDataSource::GetDragData(const std::string& mime_type,
std::string* contents) {
auto it = drag_data_map_.find(mime_type);
if (it != drag_data_map_.end()) {
*contents = it->second;
return;
}
connection_->DeliverDragData(mime_type, contents);
}
} // namespace ui } // namespace ui
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
#include <wayland-client.h> #include <wayland-client.h>
#include <map>
#include <string> #include <string>
#include <unordered_map>
#include <vector> #include <vector>
#include "base/logging.h" #include "base/logging.h"
...@@ -19,7 +19,9 @@ ...@@ -19,7 +19,9 @@
namespace ui { namespace ui {
class OSExchangeData;
class WaylandConnection; class WaylandConnection;
class WaylandWindow;
// The WaylandDataSource object represents the source side of a // The WaylandDataSource object represents the source side of a
// WaylandDataOffer. It is created by the source client in a data // WaylandDataOffer. It is created by the source client in a data
...@@ -28,8 +30,11 @@ class WaylandConnection; ...@@ -28,8 +30,11 @@ class WaylandConnection;
// transfer the data (OnSend listener). // transfer the data (OnSend listener).
class WaylandDataSource { class WaylandDataSource {
public: public:
using DragDataMap = std::map<std::string, std::string>;
// Takes ownership of data_source. // Takes ownership of data_source.
explicit WaylandDataSource(wl_data_source* data_source); explicit WaylandDataSource(wl_data_source* data_source,
WaylandConnection* connection);
~WaylandDataSource(); ~WaylandDataSource();
void set_connection(WaylandConnection* connection) { void set_connection(WaylandConnection* connection) {
...@@ -39,6 +44,11 @@ class WaylandDataSource { ...@@ -39,6 +44,11 @@ class WaylandDataSource {
void WriteToClipboard(const ClipboardDelegate::DataMap& data_map); void WriteToClipboard(const ClipboardDelegate::DataMap& data_map);
void UpdataDataMap(const ClipboardDelegate::DataMap& data_map); void UpdataDataMap(const ClipboardDelegate::DataMap& data_map);
void Offer(const ui::OSExchangeData& data);
void SetAction(int operation);
void SetDragData(const DragDataMap& data_map);
const wl_data_source* data_source() const { return data_source_.get(); }
private: private:
static void OnTarget(void* data, static void OnTarget(void* data,
...@@ -49,14 +59,22 @@ class WaylandDataSource { ...@@ -49,14 +59,22 @@ class WaylandDataSource {
const char* mime_type, const char* mime_type,
int32_t fd); int32_t fd);
static void OnCancel(void* data, wl_data_source* source); static void OnCancel(void* data, wl_data_source* source);
static void OnDnDDropPerformed(void* data, wl_data_source* source);
static void OnDnDFinished(void* data, wl_data_source* source);
static void OnAction(void* data, wl_data_source* source, uint32_t dnd_action);
void GetClipboardData(const std::string& mime_type, void GetClipboardData(const std::string& mime_type,
base::Optional<std::vector<uint8_t>>* data); base::Optional<std::vector<uint8_t>>* data);
void GetDragData(const std::string& mime_type, std::string* contents);
wl::Object<wl_data_source> data_source_; wl::Object<wl_data_source> data_source_;
WaylandConnection* connection_ = nullptr; WaylandConnection* connection_ = nullptr;
WaylandWindow* source_window_ = nullptr;
ClipboardDelegate::DataMap data_map_; ClipboardDelegate::DataMap data_map_;
DragDataMap drag_data_map_;
// Action selected by the compositor
uint32_t dnd_action_;
DISALLOW_COPY_AND_ASSIGN(WaylandDataSource); DISALLOW_COPY_AND_ASSIGN(WaylandDataSource);
}; };
......
...@@ -40,6 +40,15 @@ void delete_touch(wl_touch* touch) { ...@@ -40,6 +40,15 @@ void delete_touch(wl_touch* touch) {
wl_touch_destroy(touch); wl_touch_destroy(touch);
} }
void delete_data_device(wl_data_device* data_device) {
if (wl_data_device_get_version(data_device) >=
WL_DATA_DEVICE_RELEASE_SINCE_VERSION) {
wl_data_device_release(data_device);
} else {
wl_data_device_destroy(data_device);
}
}
} // namespace } // namespace
const wl_interface* ObjectTraits<wl_buffer>::interface = &wl_buffer_interface; const wl_interface* ObjectTraits<wl_buffer>::interface = &wl_buffer_interface;
...@@ -62,7 +71,7 @@ void (*ObjectTraits<wl_data_device_manager>::deleter)(wl_data_device_manager*) = ...@@ -62,7 +71,7 @@ void (*ObjectTraits<wl_data_device_manager>::deleter)(wl_data_device_manager*) =
const wl_interface* ObjectTraits<wl_data_device>::interface = const wl_interface* ObjectTraits<wl_data_device>::interface =
&wl_data_device_interface; &wl_data_device_interface;
void (*ObjectTraits<wl_data_device>::deleter)(wl_data_device*) = void (*ObjectTraits<wl_data_device>::deleter)(wl_data_device*) =
&wl_data_device_destroy; &delete_data_device;
const wl_interface* ObjectTraits<wl_data_offer>::interface = const wl_interface* ObjectTraits<wl_data_offer>::interface =
&wl_data_offer_interface; &wl_data_offer_interface;
......
...@@ -8,9 +8,11 @@ ...@@ -8,9 +8,11 @@
#include "base/bind.h" #include "base/bind.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h" #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/events/event.h" #include "ui/events/event.h"
#include "ui/events/event_utils.h" #include "ui/events/event_utils.h"
#include "ui/events/ozone/events_ozone.h" #include "ui/events/ozone/events_ozone.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/ozone/platform/wayland/wayland_connection.h" #include "ui/ozone/platform/wayland/wayland_connection.h"
#include "ui/ozone/platform/wayland/wayland_pointer.h" #include "ui/ozone/platform/wayland/wayland_pointer.h"
#include "ui/ozone/platform/wayland/xdg_popup_wrapper_v5.h" #include "ui/ozone/platform/wayland/xdg_popup_wrapper_v5.h"
...@@ -510,6 +512,31 @@ void WaylandWindow::OnCloseRequest() { ...@@ -510,6 +512,31 @@ void WaylandWindow::OnCloseRequest() {
delegate_->OnCloseRequest(); delegate_->OnCloseRequest();
} }
void WaylandWindow::OnDragEnter(const gfx::PointF& point,
std::unique_ptr<OSExchangeData> data,
int operation) {
NOTIMPLEMENTED_LOG_ONCE();
}
int WaylandWindow::OnDragMotion(const gfx::PointF& point,
uint32_t time,
int operation) {
NOTIMPLEMENTED_LOG_ONCE();
return 0;
}
void WaylandWindow::OnDragDrop(std::unique_ptr<OSExchangeData> data) {
NOTIMPLEMENTED_LOG_ONCE();
}
void WaylandWindow::OnDragLeave() {
NOTIMPLEMENTED_LOG_ONCE();
}
void WaylandWindow::OnDragSessionClose(uint32_t dnd_action) {
NOTIMPLEMENTED_LOG_ONCE();
}
bool WaylandWindow::IsMinimized() const { bool WaylandWindow::IsMinimized() const {
return state_ == PlatformWindowState::PLATFORM_WINDOW_STATE_MINIMIZED; return state_ == PlatformWindowState::PLATFORM_WINDOW_STATE_MINIMIZED;
} }
......
...@@ -13,9 +13,14 @@ ...@@ -13,9 +13,14 @@
#include "ui/platform_window/platform_window.h" #include "ui/platform_window/platform_window.h"
#include "ui/platform_window/platform_window_delegate.h" #include "ui/platform_window/platform_window_delegate.h"
namespace gfx {
class PointF;
}
namespace ui { namespace ui {
class BitmapCursorOzone; class BitmapCursorOzone;
class OSExchangeData;
class PlatformWindowDelegate; class PlatformWindowDelegate;
class WaylandConnection; class WaylandConnection;
class XDGPopupWrapper; class XDGPopupWrapper;
...@@ -101,6 +106,14 @@ class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher { ...@@ -101,6 +106,14 @@ class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher {
void OnCloseRequest(); void OnCloseRequest();
void OnDragEnter(const gfx::PointF& point,
std::unique_ptr<OSExchangeData> data,
int operation);
int OnDragMotion(const gfx::PointF& point, uint32_t time, int operation);
void OnDragDrop(std::unique_ptr<OSExchangeData> data);
void OnDragLeave();
void OnDragSessionClose(uint32_t dnd_action);
private: private:
bool IsMinimized() const; bool IsMinimized() const;
bool IsMaximized() const; bool IsMaximized() const;
......
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