blob: d9d85bf7c7afe33aaa1250b0de0eb7924b82b33d [file] [log] [blame]
// Copyright 2020 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_DRAG_CONTROLLER_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_DATA_DRAG_CONTROLLER_H_
#include <list>
#include <memory>
#include <string>
#include "base/gtest_prod_util.h"
#include "base/memory/weak_ptr.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h"
#include "ui/ozone/platform/wayland/host/wayland_data_device.h"
#include "ui/ozone/platform/wayland/host/wayland_data_source.h"
struct wl_surface;
class SkBitmap;
namespace ui {
class OSExchangeData;
class WaylandConnection;
class WaylandDataDeviceManager;
class WaylandDataOffer;
class WaylandWindow;
class WaylandWindowManager;
class WaylandShmBuffer;
// WaylandDataDragController implements regular data exchanging between Chromium
// and other client applications on top of the Wayland Drag and Drop protocol.
// By implementing both DataDevice::DragDelegate and DataSource::DragDelegate,
// it is responsible for handling both DND sessions initiated from Chromium
// windows as well as those triggered by other clients.
class WaylandDataDragController : public WaylandDataDevice::DragDelegate,
public WaylandDataSource::DragDelegate {
public:
enum class State { kIdle, kStarted, kTransferring };
explicit WaylandDataDragController(WaylandConnection* connection);
WaylandDataDragController(const WaylandDataDragController&) = delete;
WaylandDataDragController& operator=(const WaylandDataDragController&) =
delete;
~WaylandDataDragController() override;
// Starts a data drag and drop session for |data|. Only one DND session can
// run at a given time.
void StartSession(const ui::OSExchangeData& data, int operation);
State state() const { return state_; }
// TODO(crbug.com/896640): Remove once focus is fixed during DND sessions.
WaylandWindow* entered_window() const { return window_; }
private:
FRIEND_TEST_ALL_PREFIXES(WaylandDataDragControllerTest, ReceiveDrag);
FRIEND_TEST_ALL_PREFIXES(WaylandDataDragControllerTest, StartDrag);
FRIEND_TEST_ALL_PREFIXES(WaylandDataDragControllerTest,
StartDragWithWrongMimeType);
// WaylandDataDevice::DragDelegate:
bool IsDragSource() const override;
void DrawIcon() override;
void OnDragOffer(std::unique_ptr<WaylandDataOffer> offer) override;
void OnDragEnter(WaylandWindow* window,
const gfx::PointF& location,
uint32_t serial) override;
void OnDragMotion(const gfx::PointF& location) override;
void OnDragLeave() override;
void OnDragDrop() override;
// WaylandDataSource::DragDelegate:
void OnDragSourceFinish(bool completed) override;
void OnDragSourceSend(const std::string& mime_type,
std::string* contents) override;
wl_surface* CreateIconSurfaceIfNeeded(const OSExchangeData& data);
void HandleUnprocessedMimeTypes();
void OnMimeTypeDataTransferred(const PlatformClipboard::Data& contents);
void OnDataTransferFinished(
std::unique_ptr<ui::OSExchangeData> received_data);
std::string GetNextUnprocessedMimeType();
void SetOperation(const int operation);
WaylandConnection* const connection_;
WaylandDataDevice* const data_device_;
WaylandDataDeviceManager* const data_device_manager_;
WaylandWindowManager* const window_manager_;
State state_ = State::kIdle;
std::unique_ptr<WaylandDataSource> data_source_;
// When dragging is started from Chromium, |data_| holds the data to be sent
// through wl_data_device instance.
std::unique_ptr<ui::OSExchangeData> data_;
// Offer to receive data from another process via drag-and-drop, or null if
// no drag-and-drop from another process is in progress.
//
// The data offer from another Wayland client through wl_data_device, that
// triggered the current drag and drop session. If null, either there is no
// dnd session running or Chromium is the data source.
std::unique_ptr<WaylandDataOffer> data_offer_;
// Mime types to be handled.
std::list<std::string> unprocessed_mime_types_;
// The window that initiated the drag session. Can be null when the session
// has been started by an external Wayland client.
WaylandWindow* origin_window_ = nullptr;
// Current window under pointer.
WaylandWindow* window_ = nullptr;
// The data delivered from Wayland
std::unique_ptr<ui::OSExchangeData> received_data_;
// Set when 'leave' event is fired while data is being transferred.
bool is_leave_pending_ = false;
// Drag icon related variables.
wl::Object<wl_surface> icon_surface_;
std::unique_ptr<WaylandShmBuffer> shm_buffer_;
const SkBitmap* icon_bitmap_ = nullptr;
base::WeakPtrFactory<WaylandDataDragController> weak_factory_{this};
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_DATA_DRAG_CONTROLLER_H_