Skip to content

Commit

Permalink
Notify DragController of the view drag start
Browse files Browse the repository at this point in the history
This CL adds a views::DragController API that gets called when view
drag will start.

This CL should not bring any noticeable UI difference.

Bug: b/271490637
Change-Id: Ideedd9c11a2f344b4b485fdd9000c708f24aeccc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4327347
Reviewed-by: Scott Violet <sky@chromium.org>
Commit-Queue: Andrew Xu <andrewxu@chromium.org>
Reviewed-by: Allen Bauer <kylixrd@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1115834}
  • Loading branch information
andrewxu authored and Chromium LUCI CQ committed Mar 10, 2023
1 parent 051a822 commit 088b85c
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 0 deletions.
2 changes: 2 additions & 0 deletions ui/views/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -1001,6 +1001,8 @@ source_set("test_support") {
"test/menu_runner_test_api.h",
"test/menu_test_utils.cc",
"test/menu_test_utils.h",
"test/mock_drag_controller.cc",
"test/mock_drag_controller.h",
"test/mock_input_event_activation_protector.cc",
"test/mock_input_event_activation_protector.h",
"test/native_widget_factory.cc",
Expand Down
3 changes: 3 additions & 0 deletions ui/views/drag_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ class VIEWS_EXPORT DragController {
const gfx::Point& press_pt,
const gfx::Point& p) = 0;

// Called when the drag on view will start.
virtual void OnWillStartDragForView(View* dragged_view) {}

protected:
virtual ~DragController() = default;
};
Expand Down
33 changes: 33 additions & 0 deletions ui/views/test/mock_drag_controller.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/views/test/mock_drag_controller.h"

#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/os_exchange_data.h"

namespace views {

MockDragController::MockDragController() = default;

MockDragController::~MockDragController() = default;

void MockDragController::WriteDragDataForView(View* sender,
const gfx::Point& press_pt,
ui::OSExchangeData* data) {
data->SetString(u"test");
}

int MockDragController::GetDragOperationsForView(View* sender,
const gfx::Point& p) {
return ui::DragDropTypes::DRAG_COPY;
}

bool MockDragController::CanStartDragForView(View* sender,
const gfx::Point& press_pt,
const gfx::Point& p) {
return true;
}

} // namespace views
44 changes: 44 additions & 0 deletions ui/views/test/mock_drag_controller.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2023 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_VIEWS_TEST_MOCK_DRAG_CONTROLLER_H_
#define UI_VIEWS_TEST_MOCK_DRAG_CONTROLLER_H_

#include "ui/views/drag_controller.h"

#include "testing/gmock/include/gmock/gmock.h"

namespace gfx {
class Point;
} // namespace gfx

namespace ui {
class OSExchangeData;
} // namespace ui

namespace views {
class View;

// A mocked drag controller for testing.
class MockDragController : public DragController {
public:
MockDragController();
MockDragController(const MockDragController&) = delete;
MockDragController& operator=(const MockDragController&) = delete;
~MockDragController() override;

// DragController:
void WriteDragDataForView(View* sender,
const gfx::Point& press_pt,
ui::OSExchangeData* data) override;
int GetDragOperationsForView(View* sender, const gfx::Point& p) override;
bool CanStartDragForView(View* sender,
const gfx::Point& press_pt,
const gfx::Point& p) override;
MOCK_METHOD(void, OnWillStartDragForView, (View * dragged_view), (override));
};

} // namespace views

#endif // UI_VIEWS_TEST_MOCK_DRAG_CONTROLLER_H_
5 changes: 5 additions & 0 deletions ui/views/widget/widget.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "ui/events/event_utils.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/drag_controller.h"
#include "ui/views/event_monitor.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/focus/focus_manager_factory.h"
Expand Down Expand Up @@ -1032,6 +1033,10 @@ void Widget::RunShellDrag(View* view,
for (WidgetObserver& observer : observers_)
observer.OnWidgetDragWillStart(this);

if (view && view->drag_controller()) {
view->drag_controller()->OnWillStartDragForView(view);
}

WidgetDeletionObserver widget_deletion_observer(this);
native_widget_->RunShellDrag(view, std::move(data), location, operation,
source);
Expand Down
33 changes: 33 additions & 0 deletions ui/views/widget/widget_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "ui/views/event_monitor.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/style/platform_style.h"
#include "ui/views/test/mock_drag_controller.h"
#include "ui/views/test/native_widget_factory.h"
#include "ui/views/test/test_views.h"
#include "ui/views/test/test_widget_observer.h"
Expand All @@ -53,6 +54,7 @@
#include "ui/views/widget/native_widget_delegate.h"
#include "ui/views/widget/native_widget_private.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/unique_widget_ptr.h"
#include "ui/views/widget/widget_deletion_observer.h"
#include "ui/views/widget/widget_interactive_uitest_utils.h"
#include "ui/views/widget/widget_removals_observer.h"
Expand Down Expand Up @@ -4304,6 +4306,37 @@ TEST_F(WidgetTest, ScrollGestureEventDispatch) {
widget->Close();
}

// TODO(b/271490637): on Mac a drag controller should still be notified when
// drag will start. Figure out how to write a unit test for Mac. Then remove
// this build flag check.
#if !BUILDFLAG(IS_MAC)

// Verifies that the drag controller is notified when the view drag will start.
TEST_F(WidgetTest, NotifyDragControllerWhenDragWillStart) {
// Create a widget whose contents view is draggable.
UniqueWidgetPtr widget(std::make_unique<Widget>());
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
params.bounds = gfx::Rect(/*width=*/650, /*height=*/650);
widget->Init(std::move(params));
widget->Show();
MockDragController mock_drag_controller;
views::View contents_view;
contents_view.set_drag_controller(&mock_drag_controller);
widget->SetContentsView(&contents_view);

// Expect the drag controller is notified of the drag start.
EXPECT_CALL(mock_drag_controller, OnWillStartDragForView(&contents_view));

// Drag-and-drop `contents_view` by mouse.
ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
generator.MoveMouseTo(contents_view.GetBoundsInScreen().CenterPoint());
generator.PressLeftButton();
generator.MoveMouseBy(/*x=*/200, /*y=*/0);
generator.ReleaseLeftButton();
}

#endif // !BUILDFLAG(IS_MAC)

// A class used in WidgetTest.GestureEventLocationWhileBubbling to verify
// that when a gesture event bubbles up a View hierarchy, the location
// of a gesture event seen by each View is in the local coordinate space
Expand Down

0 comments on commit 088b85c

Please sign in to comment.