1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_DATA_DEVICE_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_DATA_DEVICE_H_
#include <cstdint>
#include <memory>
#include <string>
#include "base/files/scoped_file.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h"
#include "ui/ozone/platform/wayland/host/wayland_data_device_base.h"
#include "ui/ozone/platform/wayland/host/wayland_data_source.h"
#include "ui/ozone/public/platform_clipboard.h"
namespace gfx {
class PointF;
} // namespace gfx
namespace ui {
class WaylandDataOffer;
class WaylandConnection;
class WaylandWindow;
// This class provides access to inter-client data transfer mechanisms
// such as copy-and-paste and drag-and-drop mechanisms.
class WaylandDataDevice : public WaylandDataDeviceBase {
public:
// DragDelegate is responsible for handling drag and drop sessions.
class DragDelegate {
public:
virtual bool IsDragSource() const = 0;
virtual void DrawIcon() = 0;
virtual void OnDragOffer(std::unique_ptr<WaylandDataOffer> offer) = 0;
virtual void OnDragEnter(WaylandWindow* window,
const gfx::PointF& location,
base::TimeTicks timestamp,
uint32_t serial) = 0;
virtual void OnDragMotion(const gfx::PointF& location,
base::TimeTicks timestamp) = 0;
virtual void OnDragLeave(base::TimeTicks timestamp) = 0;
virtual void OnDragDrop(base::TimeTicks timestamp) = 0;
protected:
virtual ~DragDelegate() = default;
};
WaylandDataDevice(WaylandConnection* connection, wl_data_device* data_device);
WaylandDataDevice(const WaylandDataDevice&) = delete;
WaylandDataDevice& operator=(const WaylandDataDevice&) = delete;
~WaylandDataDevice() override;
// Starts a wayland drag and drop session, controlled by |delegate|.
void StartDrag(const WaylandDataSource& data_source,
const WaylandWindow& origin_window,
uint32_t serial,
wl_surface* icon_surface,
DragDelegate* delegate);
// Resets the drag delegate, assuming there is one set. Any wl_data_device
// event received after this will be ignored until a new delegate is set.
void ResetDragDelegate();
// Resets the drag delegate, only under certain conditions, eg: if it is set
// and running an incoming dnd session.
// TODO(crbug.com/40884328): Drop once drag delegate improvements are done.
void ResetDragDelegateIfNotDragSource();
// Returns the underlying wl_data_device singleton object.
wl_data_device* data_device() const { return data_device_.get(); }
// wl_data_device::set_selection makes the corresponding wl_data_source the
// target of future wl_data_device::data_offer events. In non-Wayland terms,
// this is equivalent to "writing" to the clipboard, although the actual
// transfer of data happens asynchronously, on-demand-only.
void SetSelectionSource(WaylandDataSource* source, uint32_t serial);
// Returns true if there is an active wayland drag session.
bool IsDragInProgress() const;
void set_drag_delegate_for_testing(DragDelegate* drag_delegate) {
drag_delegate_ = drag_delegate;
}
private:
FRIEND_TEST_ALL_PREFIXES(WaylandDataDragControllerTest, StartDrag);
FRIEND_TEST_ALL_PREFIXES(WaylandDataDragControllerTest, ReceiveDrag);
FRIEND_TEST_ALL_PREFIXES(WaylandDataDragControllerTest, CancelIncomingDrag);
FRIEND_TEST_ALL_PREFIXES(WaylandDataDragControllerTest,
DestroyWindowWhileFetchingForeignData);
FRIEND_TEST_ALL_PREFIXES(WaylandDataDragControllerTest,
LeaveWindowWhileFetchingData);
// wl_data_device_listener callbacks:
static void OnDataOffer(void* data,
wl_data_device* data_device,
wl_data_offer* offer);
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 when either keyboard/pointer focus or clipboard content changes.
static void OnSelection(void* data,
wl_data_device* data_device,
wl_data_offer* offer);
// The wl_data_device wrapped by this WaylandDataDevice.
wl::Object<wl_data_device> data_device_;
raw_ptr<DragDelegate, DanglingUntriaged> drag_delegate_ = nullptr;
// There are two separate data offers at a time, the drag offer and the
// selection offer, each with independent lifetimes. When we receive a new
// offer, it is not immediately possible to know whether the new offer is
// the drag offer or the selection offer. This variable is used to store
// new data offers temporarily until it is possible to determine which kind
// session it belongs to.
std::unique_ptr<WaylandDataOffer> new_offer_;
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_DATA_DEVICE_H_
|