Commit 67a7e39e authored by Julie Jeongeun Kim's avatar Julie Jeongeun Kim Committed by Commit Bot

[Ozone] Implement starting dragging with ozone

It introduces DesktopDragDropClientOzone class to manage
drag-and-drop. 'DesktopWindowTreeHostPlatform::CreateDragDropClient'
creates DesktopDragDropClientOzone and it's connected to platform
windows and has an internal runloop like other DragDropClients.

It adds WmDragHandler and sets the platform window as a WmDragHandler.
When DesktopWindowTreeHostPlatform starts dragging, it gets
WmDragHandler through the platform window and sends the dragging
request to the platform layer.

It implements 'StartDragAndDrop' of 'DragDropClient' for Ozone
and adds 'OnDragSessionClosed' to DesktopDragDropClientOzone to
finish dragging session.

As Wayland platform window has the drag and drop implementation
at the platform layer already, it extends WaylandWindow interfaces,
StartDrag.

With this change, Ozone/Wayland build can start dragging from an
application to the Chromium browser.

Test=DesktopDragDropClientOzoneTest.StartDrag
BUG=875164

Change-Id: I4ebaedfae5f6affb80b4d6c7c6d8ed3ba86ef4ca
Reviewed-on: https://chromium-review.googlesource.com/c/1218446Reviewed-by: default avatarSadrul Chowdhury <sadrul@chromium.org>
Commit-Queue: Julie Jeongeun Kim <jkim@igalia.com>
Cr-Commit-Position: refs/heads/master@{#603024}
parent 6dd55cc4
......@@ -88,7 +88,11 @@ TestCompositorHostOzone::TestCompositorHostOzone(
false /* enable_surface_synchronization */,
false /* enable_pixel_canvas */) {}
TestCompositorHostOzone::~TestCompositorHostOzone() {}
TestCompositorHostOzone::~TestCompositorHostOzone() {
// |window_| should be destroyed earlier than |window_delegate_| as it refers
// to its delegate on destroying.
window_.reset();
}
void TestCompositorHostOzone::Show() {
ui::PlatformWindowInitProperties properties;
......
......@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/hit_test.h"
#include "ui/events/event.h"
......@@ -79,9 +80,17 @@ WaylandWindow::WaylandWindow(PlatformWindowDelegate* delegate,
// Set a class property key, which allows |this| to be used for interactive
// events, e.g. move or resize.
SetWmMoveResizeHandler(this, AsWmMoveResizeHandler());
// Set a class property key, which allows |this| to be used for drag action.
SetWmDragHandler(this, this);
}
WaylandWindow::~WaylandWindow() {
if (drag_closed_callback_) {
std::move(drag_closed_callback_)
.Run(DragDropTypes::DragOperation::DRAG_NONE);
}
PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
connection_->RemoveWindow(surface_.id());
......@@ -216,6 +225,15 @@ void WaylandWindow::DispatchHostWindowDragMovement(
connection_->ScheduleFlush();
}
void WaylandWindow::StartDrag(const ui::OSExchangeData& data,
int operation,
gfx::NativeCursor cursor,
base::OnceCallback<void(int)> callback) {
DCHECK(!drag_closed_callback_);
drag_closed_callback_ = std::move(callback);
connection_->StartDrag(data, operation);
}
void WaylandWindow::Show() {
if (!is_tooltip_) // Tooltip windows should not get keyboard focus
set_keyboard_focus(true);
......@@ -570,7 +588,7 @@ void WaylandWindow::OnDragLeave() {
}
void WaylandWindow::OnDragSessionClose(uint32_t dnd_action) {
NOTIMPLEMENTED_LOG_ONCE();
std::move(drag_closed_callback_).Run(dnd_action);
}
bool WaylandWindow::IsMinimized() const {
......
......@@ -5,6 +5,7 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_WAYLAND_WINDOW_H_
#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_WINDOW_H_
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "ui/events/platform/platform_event_dispatcher.h"
#include "ui/gfx/geometry/rect.h"
......@@ -12,6 +13,7 @@
#include "ui/ozone/platform/wayland/wayland_object.h"
#include "ui/platform_window/platform_window.h"
#include "ui/platform_window/platform_window_delegate.h"
#include "ui/platform_window/platform_window_handler/wm_drag_handler.h"
#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h"
namespace gfx {
......@@ -35,7 +37,8 @@ class XDGShellObjectFactory;
class WaylandWindow : public PlatformWindow,
public PlatformEventDispatcher,
public WmMoveResizeHandler {
public WmMoveResizeHandler,
public WmDragHandler {
public:
WaylandWindow(PlatformWindowDelegate* delegate,
WaylandConnection* connection);
......@@ -81,6 +84,12 @@ class WaylandWindow : public PlatformWindow,
int hittest,
const gfx::Point& pointer_location) override;
// WmDragHandler
void StartDrag(const ui::OSExchangeData& data,
int operation,
gfx::NativeCursor cursor,
base::OnceCallback<void(int)> callback) override;
// PlatformWindow
void Show() override;
void Hide() override;
......@@ -162,6 +171,8 @@ class WaylandWindow : public PlatformWindow,
// The current cursor bitmap (immutable).
scoped_refptr<BitmapCursorOzone> bitmap_;
base::OnceCallback<void(int)> drag_closed_callback_;
gfx::Rect bounds_;
gfx::Rect pending_bounds_;
// The bounds of our window before we were maximized or fullscreen.
......
......@@ -8,6 +8,8 @@ jumbo_component("platform_window_handler") {
output_name = "platform_window_handler_libs"
sources = [
"wm_drag_handler.cc",
"wm_drag_handler.h",
"wm_move_resize_handler.cc",
"wm_move_resize_handler.h",
"wm_platform_export.h",
......
// 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.
#include "ui/platform_window/platform_window_handler/wm_drag_handler.h"
#include "ui/base/class_property.h"
#include "ui/platform_window/platform_window.h"
DEFINE_UI_CLASS_PROPERTY_TYPE(ui::WmDragHandler*)
namespace ui {
DEFINE_UI_CLASS_PROPERTY_KEY(WmDragHandler*, kWmDragHandlerKey, nullptr);
void SetWmDragHandler(PlatformWindow* platform_window,
WmDragHandler* drag_handler) {
platform_window->SetProperty(kWmDragHandlerKey, drag_handler);
}
WmDragHandler* GetWmDragHandler(const PlatformWindow& platform_window) {
return platform_window.GetProperty(kWmDragHandlerKey);
}
} // namespace ui
// 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_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_DRAG_HANDLER_H_
#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_DRAG_HANDLER_H_
#include "base/bind.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/platform_window/platform_window_handler/wm_platform_export.h"
namespace ui {
class OSExchangeData;
class PlatformWindow;
class WM_PLATFORM_EXPORT WmDragHandler {
public:
// Starts dragging with |data| which it wants to deliver to the destination.
// |operation| is the suggested operation which is bitmask of DRAG_NONE,
// DRAG_MOVE, DRAG_COPY and DRAG_LINK in DragDropTypes::DragOperation to the
// destination and the destination sets the final operation when the drop
// action is performed.
virtual void StartDrag(const OSExchangeData& data,
int operation,
gfx::NativeCursor cursor,
base::OnceCallback<void(int)> callback) = 0;
protected:
virtual ~WmDragHandler() {}
};
WM_PLATFORM_EXPORT void SetWmDragHandler(PlatformWindow* platform_window,
WmDragHandler* drag_handler);
WM_PLATFORM_EXPORT WmDragHandler* GetWmDragHandler(
const PlatformWindow& platform_window);
} // namespace ui
#endif // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_DRAG_HANDLER_H_
......@@ -721,8 +721,12 @@ jumbo_component("views") {
]
deps += [ "//ui/events:dom_keyboard_layout" ]
} else if (use_ozone) {
public += [ "widget/desktop_aura/desktop_screen_ozone.h" ]
sources += [ "widget/desktop_aura/desktop_screen_ozone.cc" ]
sources += [
"widget/desktop_aura/desktop_drag_drop_client_ozone.cc",
"widget/desktop_aura/desktop_drag_drop_client_ozone.h",
"widget/desktop_aura/desktop_screen_ozone.cc",
"widget/desktop_aura/desktop_screen_ozone.h",
]
}
if (is_linux) {
sources += [
......@@ -1180,8 +1184,10 @@ test("views_unittests") {
}
if (is_linux && !is_chromeos && !use_x11) {
sources +=
[ "widget/desktop_aura/desktop_window_tree_host_platform_unittest.cc" ]
sources += [
"widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc",
"widget/desktop_aura/desktop_window_tree_host_platform_unittest.cc",
]
}
if (!is_chromeos) {
......@@ -1192,6 +1198,7 @@ test("views_unittests") {
":test_support",
":views_unittests_sources",
"//mojo/core/embedder",
"//ui/platform_window/platform_window_handler",
]
}
......
// 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.
#include "ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h"
#include "base/bind.h"
#include "base/run_loop.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/dragdrop/os_exchange_data_provider_aura.h"
#include "ui/platform_window/platform_window_delegate.h"
#include "ui/platform_window/platform_window_handler/wm_drag_handler.h"
#include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
namespace views {
DesktopDragDropClientOzone::DesktopDragDropClientOzone(
aura::Window* root_window,
views::DesktopNativeCursorManager* cursor_manager,
ui::WmDragHandler* drag_handler)
: root_window_(root_window),
cursor_manager_(cursor_manager),
drag_handler_(drag_handler) {}
DesktopDragDropClientOzone::~DesktopDragDropClientOzone() {
if (in_move_loop_)
DragCancel();
}
int DesktopDragDropClientOzone::StartDragAndDrop(
const ui::OSExchangeData& data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& root_location,
int operation,
ui::DragDropTypes::DragEventSource source) {
if (!drag_handler_)
return ui::DragDropTypes::DragOperation::DRAG_NONE;
DCHECK(!in_move_loop_);
base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
quit_closure_ = run_loop.QuitClosure();
// Chrome expects starting drag and drop to release capture.
aura::Window* capture_window =
aura::client::GetCaptureClient(root_window)->GetGlobalCaptureWindow();
if (capture_window)
capture_window->ReleaseCapture();
aura::client::CursorClient* cursor_client =
aura::client::GetCursorClient(root_window);
initial_cursor_ = source_window->GetHost()->last_cursor();
drag_operation_ = operation;
cursor_client->SetCursor(
cursor_manager_->GetInitializedCursor(ui::CursorType::kGrabbing));
drag_handler_->StartDrag(
data, operation, cursor_client->GetCursor(),
base::BindOnce(&DesktopDragDropClientOzone::OnDragSessionClosed,
base::Unretained(this)));
in_move_loop_ = true;
run_loop.Run();
DragDropSessionCompleted();
return drag_operation_;
}
void DesktopDragDropClientOzone::DragCancel() {
QuitRunLoop();
}
bool DesktopDragDropClientOzone::IsDragDropInProgress() {
return in_move_loop_;
}
void DesktopDragDropClientOzone::AddObserver(
aura::client::DragDropClientObserver* observer) {
NOTIMPLEMENTED_LOG_ONCE();
}
void DesktopDragDropClientOzone::RemoveObserver(
aura::client::DragDropClientObserver* observer) {
NOTIMPLEMENTED_LOG_ONCE();
}
void DesktopDragDropClientOzone::OnDragSessionClosed(int dnd_action) {
drag_operation_ = dnd_action;
QuitRunLoop();
}
void DesktopDragDropClientOzone::DragDropSessionCompleted() {
aura::client::CursorClient* cursor_client =
aura::client::GetCursorClient(root_window_);
if (!cursor_client)
return;
cursor_client->SetCursor(initial_cursor_);
}
void DesktopDragDropClientOzone::QuitRunLoop() {
in_move_loop_ = false;
if (quit_closure_.is_null())
return;
std::move(quit_closure_).Run();
}
} // namespace views
// 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_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DRAG_DROP_CLIENT_OZONE_H_
#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DRAG_DROP_CLIENT_OZONE_H_
#include "base/callback.h"
#include "ui/aura/client/drag_drop_client.h"
#include "ui/base/cursor/cursor.h"
#include "ui/platform_window/platform_window_handler/wm_drag_handler.h"
#include "ui/views/views_export.h"
namespace views {
class DesktopNativeCursorManager;
class VIEWS_EXPORT DesktopDragDropClientOzone
: public aura::client::DragDropClient {
public:
DesktopDragDropClientOzone(aura::Window* root_window,
views::DesktopNativeCursorManager* cursor_manager,
ui::WmDragHandler* drag_handler);
~DesktopDragDropClientOzone() override;
void OnDragSessionClosed(int operation);
// Overridden from aura::client::DragDropClient:
int StartDragAndDrop(const ui::OSExchangeData& data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& root_location,
int operation,
ui::DragDropTypes::DragEventSource source) override;
void DragCancel() override;
bool IsDragDropInProgress() override;
void AddObserver(aura::client::DragDropClientObserver* observer) override;
void RemoveObserver(aura::client::DragDropClientObserver* observer) override;
private:
void DragDropSessionCompleted();
void QuitRunLoop();
aura::Window* const root_window_;
DesktopNativeCursorManager* cursor_manager_;
ui::WmDragHandler* const drag_handler_;
// Cursor in use prior to the move loop starting. Restored when the move loop
// quits.
gfx::NativeCursor initial_cursor_;
base::OnceClosure quit_closure_;
// The operation bitfield.
int drag_operation_ = 0;
// The flag that controls whether it has a nested run loop.
bool in_move_loop_ = false;
DISALLOW_COPY_AND_ASSIGN(DesktopDragDropClientOzone);
};
} // namespace views
#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DRAG_DROP_CLIENT_OZONE_H_
// 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.
#include "ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/platform_window/platform_window_handler/wm_drag_handler.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/views_delegate.h"
#include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h"
namespace views {
namespace {
class FakeWmDragHandler;
// A fake handler, which initiates dragging.
class FakeWmDragHandler : public ui::WmDragHandler {
public:
FakeWmDragHandler() : weak_ptr_factory_(this) {}
~FakeWmDragHandler() override = default;
// ui::WmDragHandler
void StartDrag(const OSExchangeData& data,
const int operation,
gfx::NativeCursor cursor,
base::OnceCallback<void(int)> callback) override {
callback_ = std::move(callback);
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(
[](base::OnceCallback<void(int)> callback) {
std::move(callback).Run(ui::DragDropTypes::DRAG_COPY);
},
std::move(callback_)));
}
private:
base::OnceCallback<void(int)> callback_;
base::WeakPtrFactory<FakeWmDragHandler> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(FakeWmDragHandler);
};
} // namespace
class DesktopDragDropClientOzoneTest : public ViewsTestBase {
public:
DesktopDragDropClientOzoneTest() = default;
~DesktopDragDropClientOzoneTest() override = default;
int StartDragAndDrop() {
ui::OSExchangeData data;
data.SetString(base::ASCIIToUTF16("Test"));
SkBitmap drag_bitmap;
drag_bitmap.allocN32Pixels(10, 10);
drag_bitmap.eraseARGB(0xFF, 0, 0, 0);
gfx::ImageSkia drag_image(gfx::ImageSkia::CreateFrom1xBitmap(drag_bitmap));
data.provider().SetDragImage(drag_image, gfx::Vector2d());
return client_->StartDragAndDrop(
data, widget_->GetNativeWindow()->GetRootWindow(),
widget_->GetNativeWindow(), gfx::Point(),
ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE,
ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
}
// ViewsTestBase:
void SetUp() override {
ViewsTestBase::SetUp();
test_views_delegate()->set_use_desktop_native_widgets(true);
// Create widget to initiate the drags.
widget_ = std::make_unique<Widget>();
Widget::InitParams params(Widget::InitParams::TYPE_WINDOW);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.native_widget = new DesktopNativeWidgetAura(widget_.get());
params.bounds = gfx::Rect(100, 100);
widget_->Init(params);
widget_->Show();
aura::Window* window = widget_->GetNativeWindow();
cursor_manager_ = std::make_unique<DesktopNativeCursorManager>();
drag_handler_ = std::make_unique<FakeWmDragHandler>();
client_ = std::make_unique<DesktopDragDropClientOzone>(
window, cursor_manager_.get(), drag_handler_.get());
}
void TearDown() override {
client_.reset();
cursor_manager_.reset();
drag_handler_.reset();
widget_.reset();
ViewsTestBase::TearDown();
}
private:
std::unique_ptr<DesktopDragDropClientOzone> client_;
std::unique_ptr<DesktopNativeCursorManager> cursor_manager_;
std::unique_ptr<FakeWmDragHandler> drag_handler_;
// The widget used to initiate drags.
std::unique_ptr<Widget> widget_;
DISALLOW_COPY_AND_ASSIGN(DesktopDragDropClientOzoneTest);
};
TEST_F(DesktopDragDropClientOzoneTest, StartDrag) {
int result = StartDragAndDrop();
EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, result);
}
} // namespace views
......@@ -15,6 +15,7 @@
#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h"
#include "ui/platform_window/platform_window_init_properties.h"
#include "ui/views/corewm/tooltip_aura.h"
#include "ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h"
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#include "ui/views/widget/desktop_aura/window_event_filter.h"
#include "ui/views/widget/widget_aura_utils.h"
......@@ -124,9 +125,9 @@ DesktopWindowTreeHostPlatform::CreateTooltip() {
std::unique_ptr<aura::client::DragDropClient>
DesktopWindowTreeHostPlatform::CreateDragDropClient(
DesktopNativeCursorManager* cursor_manager) {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
return nullptr;
ui::WmDragHandler* drag_handler = ui::GetWmDragHandler(*(platform_window()));
return std::make_unique<DesktopDragDropClientOzone>(window(), cursor_manager,
drag_handler);
}
void DesktopWindowTreeHostPlatform::Close() {
......
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