Commit b46512e6 authored by Avery Musbach's avatar Avery Musbach Committed by Commit Bot

workspace: Exclude non-resizeable windows from the multi-resize feature.

Before this change, a supposedly non-resizeable window could participate
in a multi-resize. Non-resizeable should mean the user has no way to
resize the window.

Test: ash_unittests MultiWindowResizeControllerTest.*NonResizeable*
Bug: 921810
Change-Id: I1e3a24b1267b6afd6b68d666e6ab033ddbd7543c
Reviewed-on: https://chromium-review.googlesource.com/c/1423746
Commit-Queue: Avery Musbach <amusbach@chromium.org>
Reviewed-by: default avatarRobert Flack <flackr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#625246}
parent 7db2e8fe
......@@ -9,6 +9,8 @@
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "ash/wm/workspace/workspace_window_resizer.h"
#include "services/ws/public/mojom/window_tree_constants.mojom.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/base/cursor/cursor.h"
......@@ -76,6 +78,25 @@ bool ContainsScreenY(aura::Window* window, int y_in_screen) {
return ContainsY(window, window_loc.y());
}
// Returns true if |p| is on the edge |edge_want| of |window|.
bool PointOnWindowEdge(aura::Window* window,
int edge_want,
const gfx::Point& p) {
switch (edge_want) {
case HTLEFT:
return ContainsY(window, p.y()) && p.x() == 0;
case HTRIGHT:
return ContainsY(window, p.y()) && p.x() == window->bounds().width();
case HTTOP:
return ContainsX(window, p.x()) && p.y() == 0;
case HTBOTTOM:
return ContainsX(window, p.x()) && p.y() == window->bounds().height();
default:
NOTREACHED();
return false;
}
}
bool Intersects(int x1, int max_1, int x2, int max_2) {
return x2 <= max_1 && max_2 > x1;
}
......@@ -238,6 +259,15 @@ void MultiWindowResizeController::MouseMovedOutOfHost() {
Hide();
}
void MultiWindowResizeController::OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) {
// If the window is now non-resizeable, make sure the resizer is not showing.
if ((window->GetProperty(aura::client::kResizeBehaviorKey) &
ws::mojom::kResizeBehaviorCanResize) == 0)
ResetResizer();
}
void MultiWindowResizeController::OnWindowVisibilityChanged(
aura::Window* window,
bool visible) {
......@@ -282,6 +312,12 @@ MultiWindowResizeController::DetermineWindows(aura::Window* window,
int window_component,
const gfx::Point& point) const {
ResizeWindows result;
// Check if the window is non-resizeable.
if ((window->GetProperty(aura::client::kResizeBehaviorKey) &
ws::mojom::kResizeBehaviorCanResize) == 0)
return result;
gfx::Point point_in_parent =
ConvertPointToTarget(window, window->parent(), point);
switch (window_component) {
......@@ -331,30 +367,19 @@ aura::Window* MultiWindowResizeController::FindWindowByEdge(
if (!window->delegate())
continue;
gfx::Point p = ConvertPointToTarget(parent, window,
gfx::Point(x_in_parent, y_in_parent));
switch (edge_want) {
case HTLEFT:
if (ContainsY(window, p.y()) && p.x() == 0)
return window;
break;
case HTRIGHT:
if (ContainsY(window, p.y()) && p.x() == window->bounds().width())
return window;
break;
case HTTOP:
if (ContainsX(window, p.x()) && p.y() == 0)
return window;
break;
case HTBOTTOM:
if (ContainsX(window, p.x()) && p.y() == window->bounds().height())
return window;
break;
default:
NOTREACHED();
// Return the window if it is resizeable and the wanted edge has the point.
if ((window->GetProperty(aura::client::kResizeBehaviorKey) &
ws::mojom::kResizeBehaviorCanResize) != 0 &&
PointOnWindowEdge(
window, edge_want,
ConvertPointToTarget(parent, window,
gfx::Point(x_in_parent, y_in_parent)))) {
return window;
}
// Window doesn't contain the edge, but if window contains |point|
// it's obscuring any other window that could be at the location.
// Having determined that the window is not a suitable return value, if it
// contains the point, then it is obscuring that point on any remaining
// window that also contains the point.
if (window->bounds().Contains(x_in_parent, y_in_parent))
return NULL;
}
......
......@@ -49,6 +49,9 @@ class ASH_EXPORT MultiWindowResizeController
void MouseMovedOutOfHost() override;
// WindowObserver:
void OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) override;
void OnWindowVisibilityChanged(aura::Window* window, bool visible) override;
void OnWindowDestroying(aura::Window* window) override;
......
......@@ -429,6 +429,94 @@ TEST_F(MultiWindowResizeControllerTest, HideWindowTest) {
EXPECT_FALSE(IsShowing());
}
// Tests that the resizer does not appear while the mouse resides in a
// non-resizeable window.
TEST_F(MultiWindowResizeControllerTest, NonResizeableWindowTestA) {
aura::test::TestWindowDelegate delegate1;
std::unique_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate(
&delegate1, -1, gfx::Rect(0, 0, 100, 100)));
delegate1.set_window_component(HTRIGHT);
aura::test::TestWindowDelegate delegate2;
std::unique_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegate(
&delegate2, -2, gfx::Rect(0, 0, 100, 100)));
w2->SetProperty(aura::client::kResizeBehaviorKey, 0);
delegate2.set_window_component(HTRIGHT);
aura::test::TestWindowDelegate delegate3;
std::unique_ptr<aura::Window> w3(CreateTestWindowInShellWithDelegate(
&delegate3, -3, gfx::Rect(100, 0, 100, 100)));
delegate3.set_window_component(HTRIGHT);
ui::test::EventGenerator* generator = GetEventGenerator();
generator->MoveMouseTo(w1->bounds().CenterPoint());
EXPECT_FALSE(HasPendingShow());
}
// Tests that the resizer does not appear while the mouse resides in a window
// bordering two other windows, one of which is non-resizeable and obscures the
// other.
TEST_F(MultiWindowResizeControllerTest, NonResizeableWindowTestB) {
aura::test::TestWindowDelegate delegate1;
std::unique_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate(
&delegate1, -1, gfx::Rect(0, 0, 100, 100)));
delegate1.set_window_component(HTRIGHT);
aura::test::TestWindowDelegate delegate2;
std::unique_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegate(
&delegate2, -2, gfx::Rect(100, 0, 100, 100)));
delegate2.set_window_component(HTRIGHT);
aura::test::TestWindowDelegate delegate3;
std::unique_ptr<aura::Window> w3(CreateTestWindowInShellWithDelegate(
&delegate3, -3, gfx::Rect(100, 0, 100, 100)));
w3->SetProperty(aura::client::kResizeBehaviorKey, 0);
delegate3.set_window_component(HTRIGHT);
ui::test::EventGenerator* generator = GetEventGenerator();
generator->MoveMouseTo(w1->bounds().CenterPoint());
EXPECT_FALSE(HasPendingShow());
}
// Tests that the resizer appears while the mouse resides in a window bordering
// two other windows, one of which is non-resizeable but obscured by the other.
TEST_F(MultiWindowResizeControllerTest, NonResizeableWindowTestC) {
aura::test::TestWindowDelegate delegate1;
std::unique_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate(
&delegate1, -1, gfx::Rect(0, 0, 100, 100)));
delegate1.set_window_component(HTRIGHT);
aura::test::TestWindowDelegate delegate2;
std::unique_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegate(
&delegate2, -2, gfx::Rect(100, 0, 100, 100)));
w2->SetProperty(aura::client::kResizeBehaviorKey, 0);
delegate2.set_window_component(HTRIGHT);
aura::test::TestWindowDelegate delegate3;
std::unique_ptr<aura::Window> w3(CreateTestWindowInShellWithDelegate(
&delegate3, -3, gfx::Rect(100, 0, 100, 100)));
delegate3.set_window_component(HTRIGHT);
ui::test::EventGenerator* generator = GetEventGenerator();
generator->MoveMouseTo(w1->bounds().CenterPoint());
EXPECT_TRUE(HasPendingShow());
EXPECT_FALSE(HasTarget(w2.get()));
}
// Tests that the resizer is dismissed when one of the resized windows becomes
// non-resizeable.
TEST_F(MultiWindowResizeControllerTest, MakeWindowNonResizeable) {
aura::test::TestWindowDelegate delegate1;
std::unique_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate(
&delegate1, -1, gfx::Rect(0, 0, 100, 100)));
delegate1.set_window_component(HTRIGHT);
aura::test::TestWindowDelegate delegate2;
std::unique_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegate(
&delegate2, -2, gfx::Rect(100, 0, 100, 100)));
delegate2.set_window_component(HTLEFT);
ui::test::EventGenerator* generator = GetEventGenerator();
gfx::Point w1_center_in_screen = w1->GetBoundsInScreen().CenterPoint();
generator->MoveMouseTo(w1_center_in_screen);
ShowNow();
EXPECT_TRUE(IsShowing());
// Making one window non-resizeable should dismiss the resizer.
w1->SetProperty(aura::client::kResizeBehaviorKey, 0);
EXPECT_FALSE(IsShowing());
}
namespace {
class TestWindowStateDelegate : public wm::WindowStateDelegate {
......
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