summaryrefslogtreecommitdiff
path: root/chromium/ui/ozone/platform/wayland/host/wayland_data_device.h
blob: 5512f4c448054c6e2a6defe8aabb865e9464c676 (plain)
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
// Copyright 2018 The Chromium Authors. All rights reserved.
// 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 <wayland-client.h>

#include <cstdint>
#include <memory>
#include <string>

#include "base/callback.h"
#include "base/files/scoped_file.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:
  using RequestDataCallback =
      base::OnceCallback<void(const PlatformClipboard::Data&)>;

  // 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,
                             uint32_t serial) = 0;
    virtual void OnDragMotion(const gfx::PointF& location) = 0;
    virtual void OnDragLeave() = 0;
    virtual void OnDragDrop() = 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,
                 wl_surface* icon_surface,
                 DragDelegate* delegate);

  // Reset 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();

  // Requests data for an |offer| in a format specified by |mime_type|. The
  // transfer happens asynchronously and |callback| is called when it is done.
  void RequestData(WaylandDataOffer* offer,
                   const std::string& mime_type,
                   RequestDataCallback callback);

  // Returns the underlying wl_data_device singleton object.
  wl_data_device* data_device() const { return data_device_.get(); }

  void SetSelectionSource(WaylandDataSource* source);

 private:
  void ReadDragDataFromFD(base::ScopedFD fd, RequestDataCallback callback);

  // wl_data_device_listener callbacks
  static void OnOffer(void* data,
                      wl_data_device* data_device,
                      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,
  // or clipboard content changes behind the scenes.
  //
  // https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_data_device
  static void OnSelection(void* data,
                          wl_data_device* data_device,
                          wl_data_offer* id);

  // The wl_data_device wrapped by this WaylandDataDevice.
  wl::Object<wl_data_device> data_device_;

  DragDelegate* 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_