blob: da2e71640a1145101dc902d443b1d71e4b614b0f [file] [log] [blame]
// 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 "services/ws/test_ws/test_drag_drop_client.h"
#include "base/logging.h"
#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/aura/window.h"
#include "ui/base/dragdrop/drop_target_event.h"
namespace ws {
namespace test {
TestDragDropClient::TestDragDropClient() = default;
TestDragDropClient::~TestDragDropClient() = default;
int TestDragDropClient::StartDragAndDrop(
const ui::OSExchangeData& data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& screen_location,
int operation,
ui::DragDropTypes::DragEventSource source) {
if (IsDragDropInProgress())
return ui::DragDropTypes::DRAG_NONE;
DCHECK(!root_window_);
root_window_ = root_window;
root_window_->AddObserver(this);
root_window_->AddPreTargetHandler(this, ui::EventTarget::Priority::kSystem);
drag_data_ = &data;
drag_operation_ = operation;
drag_loop_ = std::make_unique<base::RunLoop>(
base::RunLoop::Type::kNestableTasksAllowed);
drag_loop_->Run();
drag_loop_.reset();
if (root_window_) {
root_window_->RemovePreTargetHandler(this);
root_window_->RemoveObserver(this);
root_window_ = nullptr;
}
return drag_operation_;
}
void TestDragDropClient::DragCancel() {
if (!IsDragDropInProgress())
return;
drag_operation_ = ui::DragDropTypes::DRAG_NONE;
drag_loop_->Quit();
}
bool TestDragDropClient::IsDragDropInProgress() {
return !!drag_loop_;
}
void TestDragDropClient::OnWindowDestroyed(aura::Window* window) {
DCHECK_EQ(root_window_, window);
root_window_ = nullptr;
DragCancel();
}
void TestDragDropClient::OnMouseEvent(ui::MouseEvent* event) {
DCHECK(IsDragDropInProgress());
DCHECK(root_window_);
aura::Window* target =
root_window_->GetEventHandlerForPoint(event->location());
if (!target) {
NOTREACHED() << "No target found for drag and drop mouse event.";
event->StopPropagation();
return;
}
event->ConvertLocationToTarget(root_window_, target);
switch (event->type()) {
case ui::ET_MOUSE_DRAGGED:
DragUpdate(target, *event);
break;
case ui::ET_MOUSE_RELEASED:
Drop(target, *event);
break;
default:
break;
}
event->StopPropagation();
}
void TestDragDropClient::DragUpdate(aura::Window* target,
const ui::LocatedEvent& event) {
if (target != drag_window_) {
if (drag_window_) {
aura::client::DragDropDelegate* delegate =
aura::client::GetDragDropDelegate(drag_window_);
if (delegate)
delegate->OnDragExited();
}
drag_window_ = target;
if (drag_window_) {
aura::client::DragDropDelegate* delegate =
aura::client::GetDragDropDelegate(drag_window_);
if (delegate) {
ui::DropTargetEvent e(*drag_data_, event.location_f(),
event.root_location_f(), drag_operation_);
e.set_flags(event.flags());
ui::Event::DispatcherApi(&e).set_target(target);
delegate->OnDragEntered(e);
}
}
} else {
aura::client::DragDropDelegate* delegate =
aura::client::GetDragDropDelegate(drag_window_);
if (delegate) {
ui::DropTargetEvent e(*drag_data_, event.location_f(),
event.root_location_f(), drag_operation_);
e.set_flags(event.flags());
ui::Event::DispatcherApi(&e).set_target(target);
delegate->OnDragUpdated(e);
}
}
}
void TestDragDropClient::Drop(aura::Window* target,
const ui::LocatedEvent& event) {
if (target != drag_window_)
DragUpdate(target, event);
aura::client::DragDropDelegate* delegate =
aura::client::GetDragDropDelegate(target);
if (delegate) {
ui::DropTargetEvent e(*drag_data_, event.location_f(),
event.root_location_f(), drag_operation_);
e.set_flags(event.flags());
ui::Event::DispatcherApi(&e).set_target(target);
drag_operation_ = delegate->OnPerformDrop(e);
}
drag_loop_->Quit();
}
} // namespace test
} // namespace ws