Skip to content

Commit

Permalink
Make always-on-top windows free-floating in Ash maximize mode
Browse files Browse the repository at this point in the history
Currently windows in maximize mode are forced to be
maximized/centered, non-draggable, and non-resizable.
Applying these properties for always-on-top windows
leads to occlusion of content in other windows and thus
gives a poor user experience. This CL changes the behaviour
of MaximizeModeWindowManager to never manage windows
with the always-on-top property. As a result, any such
windows will be free-floating like in regular Ash.

BUG=458141
TEST=MaximizeModeWindowManagerTest.AlwaysOnTopWindows

Review URL: https://codereview.chromium.org/1063613003

Cr-Commit-Position: refs/heads/master@{#325749}
  • Loading branch information
tdanderson authored and Commit bot committed Apr 18, 2015
1 parent cb655c2 commit b7803ca
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 1 deletion.
19 changes: 18 additions & 1 deletion ash/wm/maximize_mode/maximize_mode_window_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "ash/wm/wm_event.h"
#include "ash/wm/workspace_controller.h"
#include "base/command_line.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/gfx/screen.h"

Expand Down Expand Up @@ -122,6 +123,16 @@ void MaximizeModeWindowManager::OnWindowAdded(aura::Window* window) {
}
}

void MaximizeModeWindowManager::OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) {
// Stop managing |window| if the always-on-top property is added.
if (key == aura::client::kAlwaysOnTopKey &&
window->GetProperty(aura::client::kAlwaysOnTopKey)) {
ForgetWindow(window);
}
}

void MaximizeModeWindowManager::OnWindowBoundsChanged(
aura::Window* window,
const gfx::Rect& old_bounds,
Expand Down Expand Up @@ -236,13 +247,19 @@ void MaximizeModeWindowManager::ForgetWindow(aura::Window* window) {
window->RemoveObserver(this);

// By telling the state object to revert, it will switch back the old
// State object and destroy itself, calling WindowStateDerstroyed().
// State object and destroy itself, calling WindowStateDestroyed().
it->second->LeaveMaximizeMode(wm::GetWindowState(it->first));
DCHECK(window_state_map_.find(window) == window_state_map_.end());
}

bool MaximizeModeWindowManager::ShouldHandleWindow(aura::Window* window) {
DCHECK(window);

// Windows with the always-on-top property should be free-floating and thus
// not managed by us.
if (window->GetProperty(aura::client::kAlwaysOnTopKey))
return false;

return window->type() == ui::wm::WINDOW_TYPE_NORMAL;
}

Expand Down
3 changes: 3 additions & 0 deletions ash/wm/maximize_mode/maximize_mode_window_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class ASH_EXPORT MaximizeModeWindowManager : public aura::WindowObserver,
// Overridden from WindowObserver:
void OnWindowDestroying(aura::Window* window) override;
void OnWindowAdded(aura::Window* window) override;
void OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) override;
void OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) override;
Expand Down
70 changes: 70 additions & 0 deletions ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1297,6 +1297,76 @@ TEST_F(MaximizeModeWindowManagerTest,
DestroyMaximizeModeWindowManager();
}

// Tests that windows with the always-on-top property are not managed by
// the MaximizeModeWindowManager while maximize mode is engaged (i.e.,
// they remain free-floating).
TEST_F(MaximizeModeWindowManagerTest, AlwaysOnTopWindows) {
gfx::Rect rect1(10, 10, 200, 50);
gfx::Rect rect2(20, 140, 100, 100);

// Create two windows with the always-on-top property.
scoped_ptr<aura::Window> w1(CreateWindow(ui::wm::WINDOW_TYPE_NORMAL, rect1));
scoped_ptr<aura::Window> w2(
CreateFixedSizeNonMaximizableWindow(ui::wm::WINDOW_TYPE_NORMAL, rect2));
w1->SetProperty(aura::client::kAlwaysOnTopKey, true);
w2->SetProperty(aura::client::kAlwaysOnTopKey, true);
EXPECT_FALSE(wm::GetWindowState(w1.get())->IsMaximized());
EXPECT_FALSE(wm::GetWindowState(w2.get())->IsMaximized());
EXPECT_EQ(rect1.ToString(), w1->bounds().ToString());
EXPECT_EQ(rect2.ToString(), w2->bounds().ToString());
EXPECT_TRUE(wm::GetWindowState(w1.get())->can_be_dragged());
EXPECT_TRUE(wm::GetWindowState(w2.get())->can_be_dragged());

// Enter maximize mode. Neither window should be managed because they have
// the always-on-top property set, which means that none of their properties
// should change.
ash::MaximizeModeWindowManager* manager = CreateMaximizeModeWindowManager();
ASSERT_TRUE(manager);
EXPECT_EQ(0, manager->GetNumberOfManagedWindows());
EXPECT_FALSE(wm::GetWindowState(w1.get())->IsMaximized());
EXPECT_FALSE(wm::GetWindowState(w2.get())->IsMaximized());
EXPECT_EQ(rect1.ToString(), w1->bounds().ToString());
EXPECT_EQ(rect2.ToString(), w2->bounds().ToString());
EXPECT_TRUE(wm::GetWindowState(w1.get())->can_be_dragged());
EXPECT_TRUE(wm::GetWindowState(w2.get())->can_be_dragged());

// Remove the always-on-top property from both windows while in maximize
// mode. The windows should become managed, which means they should be
// maximized/centered and no longer be draggable.
w1->SetProperty(aura::client::kAlwaysOnTopKey, false);
w2->SetProperty(aura::client::kAlwaysOnTopKey, false);
EXPECT_EQ(2, manager->GetNumberOfManagedWindows());
EXPECT_TRUE(wm::GetWindowState(w1.get())->IsMaximized());
EXPECT_FALSE(wm::GetWindowState(w2.get())->IsMaximized());
EXPECT_NE(rect1.origin().ToString(), w1->bounds().origin().ToString());
EXPECT_NE(rect1.size().ToString(), w1->bounds().size().ToString());
EXPECT_NE(rect2.origin().ToString(), w2->bounds().origin().ToString());
EXPECT_EQ(rect2.size().ToString(), w2->bounds().size().ToString());
EXPECT_FALSE(wm::GetWindowState(w1.get())->can_be_dragged());
EXPECT_FALSE(wm::GetWindowState(w2.get())->can_be_dragged());

// Applying the always-on-top property to both windows while in maximize
// mode should cause both windows to return to their original size,
// position, and state.
w1->SetProperty(aura::client::kAlwaysOnTopKey, true);
w2->SetProperty(aura::client::kAlwaysOnTopKey, true);
EXPECT_EQ(0, manager->GetNumberOfManagedWindows());
EXPECT_FALSE(wm::GetWindowState(w1.get())->IsMaximized());
EXPECT_FALSE(wm::GetWindowState(w2.get())->IsMaximized());
EXPECT_EQ(rect1.ToString(), w1->bounds().ToString());
EXPECT_EQ(rect2.ToString(), w2->bounds().ToString());
EXPECT_TRUE(wm::GetWindowState(w1.get())->can_be_dragged());
EXPECT_TRUE(wm::GetWindowState(w2.get())->can_be_dragged());

// The always-on-top windows should not change when leaving maximize mode.
DestroyMaximizeModeWindowManager();
EXPECT_FALSE(wm::GetWindowState(w1.get())->IsMaximized());
EXPECT_FALSE(wm::GetWindowState(w2.get())->IsMaximized());
EXPECT_EQ(rect1.ToString(), w1->bounds().ToString());
EXPECT_EQ(rect2.ToString(), w2->bounds().ToString());
EXPECT_TRUE(wm::GetWindowState(w1.get())->can_be_dragged());
EXPECT_TRUE(wm::GetWindowState(w2.get())->can_be_dragged());
}
#endif // OS_WIN

} // namespace ash

0 comments on commit b7803ca

Please sign in to comment.