blob: 1328fa41689d143536792667fc6bee702fbe8be1 [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 "ash/wm/tablet_mode/tablet_mode_app_window_drag_controller.h"
#include "ash/shell.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/splitview/split_view_drag_indicators.h"
#include "ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h"
#include "ash/wm/window_state.h"
#include "ui/base/hit_test.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/coordinate_conversion.h"
namespace ash {
namespace {
// The drag delegate for app windows. It not only includes the logic in
// TabletModeWindowDragDelegate, but also has special logic for app windows.
class TabletModeAppWindowDragDelegate : public TabletModeWindowDragDelegate {
public:
TabletModeAppWindowDragDelegate() = default;
~TabletModeAppWindowDragDelegate() override = default;
private:
// TabletModeWindowDragDelegate:
void PrepareWindowDrag(const gfx::Point& location_in_screen) override {
wm::GetWindowState(dragged_window_)
->CreateDragDetails(location_in_screen, HTCLIENT,
::wm::WINDOW_MOVE_SOURCE_TOUCH);
}
void UpdateWindowDrag(const gfx::Point& location_in_screen) override {}
void EndingWindowDrag(wm::WmToplevelWindowEventHandler::DragResult result,
const gfx::Point& location_in_screen) override {
wm::GetWindowState(dragged_window_)->DeleteDragDetails();
}
void EndedWindowDrag(const gfx::Point& location_in_screen) override {}
void StartFling(const ui::GestureEvent* event) override {
if (ShouldFlingIntoOverview(event)) {
DCHECK(Shell::Get()->overview_controller()->IsSelecting());
Shell::Get()->overview_controller()->overview_session()->AddItem(
dragged_window_, /*reposition=*/true, /*animate=*/false);
}
}
DISALLOW_COPY_AND_ASSIGN(TabletModeAppWindowDragDelegate);
};
} // namespace
TabletModeAppWindowDragController::TabletModeAppWindowDragController()
: drag_delegate_(std::make_unique<TabletModeAppWindowDragDelegate>()) {
display::Screen::GetScreen()->AddObserver(this);
}
TabletModeAppWindowDragController::~TabletModeAppWindowDragController() {
display::Screen::GetScreen()->RemoveObserver(this);
}
bool TabletModeAppWindowDragController::DragWindowFromTop(
ui::GestureEvent* event) {
previous_location_in_screen_ =
drag_delegate_->GetEventLocationInScreen(event);
if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN)
return StartWindowDrag(event);
if (!drag_delegate_->dragged_window())
return false;
if (event->type() == ui::ET_GESTURE_SCROLL_UPDATE) {
UpdateWindowDrag(event);
return true;
}
if (event->type() == ui::ET_GESTURE_SCROLL_END) {
EndWindowDrag(event, wm::WmToplevelWindowEventHandler::DragResult::SUCCESS);
return true;
}
if (event->type() == ui::ET_SCROLL_FLING_START) {
FlingOrSwipe(event);
return true;
}
EndWindowDrag(event, wm::WmToplevelWindowEventHandler::DragResult::REVERT);
return false;
}
bool TabletModeAppWindowDragController::StartWindowDrag(
ui::GestureEvent* event) {
views::Widget* widget = views::Widget::GetTopLevelWidgetForNativeView(
static_cast<aura::Window*>(event->target()));
if (!widget)
return false;
drag_delegate_->StartWindowDrag(
widget->GetNativeWindow(),
drag_delegate_->GetEventLocationInScreen(event));
return true;
}
void TabletModeAppWindowDragController::UpdateWindowDrag(
ui::GestureEvent* event) {
// Update the dragged window's tranform during dragging.
drag_delegate_->ContinueWindowDrag(
drag_delegate_->GetEventLocationInScreen(event),
TabletModeWindowDragDelegate::UpdateDraggedWindowType::UPDATE_TRANSFORM);
}
void TabletModeAppWindowDragController::EndWindowDrag(
ui::GestureEvent* event,
wm::WmToplevelWindowEventHandler::DragResult result) {
drag_delegate_->EndWindowDrag(
result, drag_delegate_->GetEventLocationInScreen(event));
}
void TabletModeAppWindowDragController::FlingOrSwipe(ui::GestureEvent* event) {
drag_delegate_->FlingOrSwipe(event);
}
void TabletModeAppWindowDragController::OnDisplayMetricsChanged(
const display::Display& display,
uint32_t metrics) {
if (!drag_delegate_->dragged_window() || !(metrics & DISPLAY_METRIC_ROTATION))
return;
display::Display current_display =
display::Screen::GetScreen()->GetDisplayNearestWindow(
drag_delegate_->dragged_window());
if (display.id() != current_display.id())
return;
drag_delegate_->EndWindowDrag(
wm::WmToplevelWindowEventHandler::DragResult::REVERT,
previous_location_in_screen_);
}
} // namespace ash