Commit f2ffbf8d authored by Min Chen's avatar Min Chen Committed by Commit Bot

Use native window of target's top level widget for drag a window from top.

event->target() is different from
GetTopLevelWidgetForNativeView(event->target()))->GetNativeWindow()
for arc apps, but the same for chromeos apps.
Use native window of target's top level widget instead, then CanDrag
can get the correct value for arc apps, then we can drag the arc apps
from the top.

Bug: 847587
Change-Id: I9b0df4021b5872b823130450af43d93c0c97f6c8
Reviewed-on: https://chromium-review.googlesource.com/1157561Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Commit-Queue: Min Chen <minch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#580931}
parent 454bc4b9
......@@ -718,7 +718,6 @@ TEST_F(ImmersiveFullscreenControllerTest, WindowsInTabletMode) {
// Top-of-window views will not be revealed for snapped window in splitview
// mode either.
EnableTabletMode(true);
Shell::Get()->split_view_controller()->SnapWindow(window(),
SplitViewController::LEFT);
EXPECT_TRUE(wm::GetWindowState(window())->IsSnapped());
......
......@@ -66,8 +66,13 @@ bool ImmersiveGestureHandlerClassic::CanDrag(ui::GestureEvent* event) {
if (!base::FeatureList::IsEnabled(ash::features::kDragAppsInTabletMode))
return false;
aura::Window* window(static_cast<aura::Window*>(event->target()));
// Only process the event if its target is the native window of
views::Widget* widget = views::Widget::GetTopLevelWidgetForNativeView(
static_cast<aura::Window*>(event->target()));
if (!widget)
return false;
aura::Window* window = widget->GetNativeWindow();
// Only process the event if its target has the same native window as
// |immersive_fullscreen_controller_->widget()|.
if (window != immersive_fullscreen_controller_->widget()->GetNativeWindow())
return false;
......
......@@ -2154,6 +2154,30 @@ TEST_F(SplitViewTabDraggingTest, ShowNewWindowItemWhenDragStarts) {
EXPECT_FALSE(current_grid->new_selector_item_widget_for_testing());
}
class TestWindowDelegateWithWidget : public views::WidgetDelegate {
public:
TestWindowDelegateWithWidget(bool can_activate)
: can_activate_(can_activate) {}
~TestWindowDelegateWithWidget() override = default;
// views::WidgetDelegate:
void DeleteDelegate() override { delete this; }
views::Widget* GetWidget() override { return widget_; }
const views::Widget* GetWidget() const override { return widget_; }
bool CanActivate() const override { return can_activate_; }
bool CanResize() const override { return true; }
bool CanMaximize() const override { return true; }
bool ShouldAdvanceFocusToTopLevelWidget() const override { return true; }
void set_widget(views::Widget* widget) { widget_ = widget; }
private:
bool can_activate_ = false;
views::Widget* widget_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(TestWindowDelegateWithWidget);
};
class SplitViewAppDraggingTest : public SplitViewControllerTest {
public:
SplitViewAppDraggingTest() = default;
......@@ -2172,11 +2196,18 @@ class SplitViewAppDraggingTest : public SplitViewControllerTest {
}
protected:
aura::Window* CreateAppWindow(const gfx::Rect& bounds) {
aura::Window* window = CreateWindow(bounds);
window->SetProperty(aura::client::kAppType,
static_cast<int>(ash::AppType::CHROME_APP));
return window;
std::unique_ptr<aura::Window> CreateTestWindowWithWidget(
bool can_activate = true) {
views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
params.show_state = ui::SHOW_STATE_MAXIMIZED;
views::Widget* widget = new views::Widget;
std::unique_ptr<TestWindowDelegateWithWidget> widget_delegate =
std::make_unique<TestWindowDelegateWithWidget>(can_activate);
widget_delegate->set_widget(widget);
params.delegate = widget_delegate.release();
widget->Init(params);
widget->Show();
return base::WrapUnique<aura::Window>(widget->GetNativeView());
}
// Sends a gesture scroll sequence to TabletModeAppWindowDragController.
......@@ -2236,13 +2267,38 @@ class SplitViewAppDraggingTest : public SplitViewControllerTest {
DISALLOW_COPY_AND_ASSIGN(SplitViewAppDraggingTest);
};
// Tests that drag the window that cannot be snapped from top of the display
// will not snap the window into splitscreen.
TEST_F(SplitViewAppDraggingTest, DragNoneActiveMaximizedWindow) {
UpdateDisplay("800x600");
std::unique_ptr<aura::Window> window = CreateTestWindowWithWidget(false);
EXPECT_TRUE(wm::GetWindowState(window.get())->IsMaximized());
gfx::Rect display_bounds =
split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window.get());
const float long_scroll_delta = display_bounds.height() / 4 + 5;
gfx::Point start = gfx::Point(0, 0);
// Drag the window that cannot be snapped long enough, the window will be
// restored back to maximized.
base::TimeTicks timestamp = base::TimeTicks::Now();
SendScrollStartAndUpdate(start, long_scroll_delta, timestamp, window.get());
WindowSelectorController* window_selector_controller =
Shell::Get()->window_selector_controller();
EXPECT_TRUE(window_selector_controller->IsSelecting());
EXPECT_FALSE(
window_selector_controller->window_selector()->IsWindowInOverview(
window.get()));
EndScrollSequence(start, long_scroll_delta, timestamp, window.get());
EXPECT_FALSE(window_selector_controller->IsSelecting());
EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
EXPECT_TRUE(wm::GetWindowState(window.get())->IsMaximized());
}
// Tests the functionalities that are related to dragging a maximized window
// into splitscreen.
TEST_F(SplitViewAppDraggingTest, DragMaximizedWindow) {
TEST_F(SplitViewAppDraggingTest, DragActiveMaximizedWindow) {
UpdateDisplay("800x600");
std::unique_ptr<aura::Window> window(
CreateAppWindow(gfx::Rect(0, 0, 500, 500)));
wm::GetWindowState(window.get())->Maximize();
std::unique_ptr<aura::Window> window = CreateTestWindowWithWidget();
EXPECT_TRUE(wm::GetWindowState(window.get())->IsMaximized());
gfx::Rect display_bounds =
split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window.get());
......@@ -2272,24 +2328,6 @@ TEST_F(SplitViewAppDraggingTest, DragMaximizedWindow) {
SplitViewController::LEFT_SNAPPED);
EXPECT_TRUE(wm::GetWindowState(window.get())->IsSnapped());
// Drag the window that cannot be snapped long enough, the window will be
// restored back to maximized.
aura::test::TestWindowDelegate* delegate =
static_cast<aura::test::TestWindowDelegate*>(window->delegate());
delegate->set_minimum_size(
gfx::Size(display_bounds.width() * 0.67f, display_bounds.height()));
timestamp = base::TimeTicks::Now();
SendScrollStartAndUpdate(start, long_scroll_delta, timestamp, window.get());
window_selector_controller = Shell::Get()->window_selector_controller();
EXPECT_TRUE(window_selector_controller->IsSelecting());
EXPECT_FALSE(
window_selector_controller->window_selector()->IsWindowInOverview(
window.get()));
EndScrollSequence(start, long_scroll_delta, timestamp, window.get());
EXPECT_FALSE(window_selector_controller->IsSelecting());
EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
EXPECT_TRUE(wm::GetWindowState(window.get())->IsMaximized());
// FLING the window with small velocity (smaller than
// kFlingToOverviewThreshold) will not able to drop the window into overview.
timestamp = base::TimeTicks::Now();
......@@ -2318,8 +2356,7 @@ TEST_F(SplitViewAppDraggingTest, DragMaximizedWindow) {
// Tests the shelf visibility when a fullscreened window is being dragged.
TEST_F(SplitViewAppDraggingTest, ShelfVisibilityIfDraggingFullscreenedWindow) {
UpdateDisplay("800x600");
std::unique_ptr<aura::Window> window(
CreateAppWindow(gfx::Rect(0, 0, 500, 500)));
std::unique_ptr<aura::Window> window = CreateTestWindowWithWidget();
ShelfLayoutManager* shelf_layout_manager =
AshTestBase::GetPrimaryShelf()->shelf_layout_manager();
gfx::Rect display_bounds =
......
......@@ -60,10 +60,8 @@ TabletModeAppWindowDragController::~TabletModeAppWindowDragController() =
bool TabletModeAppWindowDragController::DragWindowFromTop(
ui::GestureEvent* event) {
if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN) {
StartWindowDrag(event);
return true;
}
if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN)
return StartWindowDrag(event);
if (!drag_delegate_->dragged_window())
return false;
......@@ -83,10 +81,16 @@ bool TabletModeAppWindowDragController::DragWindowFromTop(
return false;
}
void TabletModeAppWindowDragController::StartWindowDrag(
bool TabletModeAppWindowDragController::StartWindowDrag(
ui::GestureEvent* event) {
drag_delegate_->StartWindowDrag(static_cast<aura::Window*>(event->target()),
views::Widget* widget = views::Widget::GetTopLevelWidgetForNativeView(
static_cast<aura::Window*>(event->target()));
if (!widget)
return false;
drag_delegate_->StartWindowDrag(widget->GetNativeWindow(),
GetEventLocationInScreen(event));
return true;
}
void TabletModeAppWindowDragController::UpdateWindowDrag(
......
......@@ -33,7 +33,7 @@ class ASH_EXPORT TabletModeAppWindowDragController {
private:
// Gesture window drag related functions. Used in DragWindowFromTop.
void StartWindowDrag(ui::GestureEvent* event);
bool StartWindowDrag(ui::GestureEvent* event);
void UpdateWindowDrag(ui::GestureEvent* event);
void EndWindowDrag(ui::GestureEvent* event,
wm::WmToplevelWindowEventHandler::DragResult result);
......
......@@ -18,7 +18,9 @@
#include "ash/system/tray/system_tray.h"
#include "ash/system/unified/unified_system_tray.h"
#include "ash/wm/drag_window_resizer.h"
#include "ash/wm/overview/window_selector_controller.h"
#include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/tablet_mode/tablet_mode_app_window_drag_controller.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "ash/wm/window_positioning_utils.h"
#include "ash/wm/window_resizer.h"
......@@ -26,8 +28,8 @@
#include "ash/wm/window_util.h"
#include "ash/wm/wm_event.h"
#include "ash/wm/workspace_controller_test_api.h"
#include "base/debug/stack_trace.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "cc/paint/display_item_list.h"
#include "components/exo/buffer.h"
#include "components/exo/display.h"
......@@ -1064,6 +1066,65 @@ TEST_F(ClientControlledShellSurfaceTest, ClientIniatedResize) {
ASSERT_FALSE(window_state->is_dragged());
}
// Test the functionalities of dragging a window from top in tablet mode.
TEST_F(ClientControlledShellSurfaceTest, DragWindowFromTopInTabletMode) {
UpdateDisplay("800x600");
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(ash::features::kDragAppsInTabletMode);
ash::Shell* shell = ash::Shell::Get();
shell->tablet_mode_controller()->EnableTabletModeWindowManager(true);
std::unique_ptr<Surface> surface(new Surface());
const gfx::Size window_size(800, 552);
std::unique_ptr<Buffer> buffer(
new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(window_size)));
auto shell_surface =
exo_test_helper()->CreateClientControlledShellSurface(surface.get());
shell_surface->SetMaximized();
surface->Attach(buffer.get());
shell_surface->SetGeometry(gfx::Rect(window_size));
surface->Commit();
aura::Window* window = shell_surface->GetWidget()->GetNativeWindow();
ASSERT_TRUE(ash::wm::GetWindowState(window)->IsMaximized());
surface->SetFrame(SurfaceFrameType::AUTOHIDE);
surface->Commit();
ui::test::EventGenerator* event_generator = GetEventGenerator();
// Drag the window by a small amount of distance will maximize the window
// again.
const gfx::Point start(0, 0);
gfx::Point end(0, 10);
event_generator->GestureScrollSequence(
start, end, base::TimeDelta::FromMilliseconds(100), 2);
EXPECT_TRUE(ash::wm::GetWindowState(window)->IsMaximized());
// FLING the window with large veloicty (larger than
// kFlingToOverviewThreshold) will drop the window into overview.
EXPECT_FALSE(shell->window_selector_controller()->IsSelecting());
end = gfx::Point(0, 210);
const base::TimeDelta duration =
event_generator->CalculateScrollDurationForFlingVelocity(
start, end,
ash::TabletModeAppWindowDragController::kFlingToOverviewThreshold +
10.f,
200);
event_generator->GestureScrollSequence(start, end, duration, 200);
EXPECT_TRUE(shell->window_selector_controller()->IsSelecting());
EXPECT_TRUE(shell->window_selector_controller()
->window_selector()
->IsWindowInOverview(window));
// Drag the window long enough (pass one fourth of the screen vertical
// height) to snap the window to splitscreen.
shell->window_selector_controller()->ToggleOverview();
EXPECT_FALSE(shell->window_selector_controller()->IsSelecting());
EXPECT_TRUE(ash::wm::GetWindowState(window)->IsMaximized());
event_generator->GestureScrollSequence(
start, end, base::TimeDelta::FromMilliseconds(100), 20);
EXPECT_EQ(ash::wm::GetWindowState(window)->GetStateType(),
ash::mojom::WindowStateType::LEFT_SNAPPED);
}
namespace {
class ClientControlledShellSurfaceDisplayTest : public test::ExoTestBase {
......
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