Add LockLayoutManager responsible for lock container (login/lock).

Previously WorkspaceManager was used for this container which resulted in various
issues when login screen window was not full screen and was supposed to be resized
only by virtual keyboard container. Otherwise panels and shelf were taken into account
even though they are stacked below the lock container.

This CL improves previous fix
https://codereview.chromium.org/231123002

Disable this layout manager with --ash-disable-lock-layout-manager

Verified that existing out-of-box/login/multi-profiles login/lock* virtual keyboard
overscroll/non-overscroll configurations work fine.

Non-overscroll lock screen configuration is updated to use the same behavior as
login in https://codereview.chromium.org/320523003

BUG=375666
TEST=LockLayoutManager.*, existing tests

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@275431 0039d316-1c4b-4281-b951-d872f2087c98
parent 7a2a6d80
...@@ -564,9 +564,13 @@ ...@@ -564,9 +564,13 @@
'wm/immersive_fullscreen_controller.h', 'wm/immersive_fullscreen_controller.h',
'wm/immersive_revealed_lock.cc', 'wm/immersive_revealed_lock.cc',
'wm/immersive_revealed_lock.h', 'wm/immersive_revealed_lock.h',
'wm/lock_layout_manager.cc',
'wm/lock_layout_manager.h',
'wm/lock_state_controller.cc', 'wm/lock_state_controller.cc',
'wm/lock_state_controller.h', 'wm/lock_state_controller.h',
'wm/lock_state_observer.h', 'wm/lock_state_observer.h',
'wm/lock_window_state.cc',
'wm/lock_window_state.h',
'wm/maximize_mode/internal_input_device_list.h', 'wm/maximize_mode/internal_input_device_list.h',
'wm/maximize_mode/internal_input_device_list_x11.cc', 'wm/maximize_mode/internal_input_device_list_x11.cc',
'wm/maximize_mode/internal_input_device_list_x11.h', 'wm/maximize_mode/internal_input_device_list_x11.h',
...@@ -996,6 +1000,7 @@ ...@@ -996,6 +1000,7 @@
'wm/drag_window_resizer_unittest.cc', 'wm/drag_window_resizer_unittest.cc',
'wm/gestures/overview_gesture_handler_unittest.cc', 'wm/gestures/overview_gesture_handler_unittest.cc',
'wm/immersive_fullscreen_controller_unittest.cc', 'wm/immersive_fullscreen_controller_unittest.cc',
'wm/lock_layout_manager_unittest.cc',
'wm/lock_state_controller_unittest.cc', 'wm/lock_state_controller_unittest.cc',
'wm/maximize_mode/accelerometer_test_data_literals.cc', 'wm/maximize_mode/accelerometer_test_data_literals.cc',
'wm/maximize_mode/maximize_mode_controller_unittest.cc', 'wm/maximize_mode/maximize_mode_controller_unittest.cc',
......
...@@ -38,6 +38,10 @@ const char kAshDefaultWallpaperIsOem[] = "ash-default-wallpaper-is-oem"; ...@@ -38,6 +38,10 @@ const char kAshDefaultWallpaperIsOem[] = "ash-default-wallpaper-is-oem";
const char kAshDefaultWallpaperLarge[] = "ash-default-wallpaper-large"; const char kAshDefaultWallpaperLarge[] = "ash-default-wallpaper-large";
const char kAshDefaultWallpaperSmall[] = "ash-default-wallpaper-small"; const char kAshDefaultWallpaperSmall[] = "ash-default-wallpaper-small";
// Disables LockLayoutManager used for LockScreenContainer, return back to
// WorkspaceLayoutManager.
const char kAshDisableLockLayoutManager[] = "ash-disable-lock-layout-manager";
// Disable the Touch Exploration Mode. Touch Exploration Mode will no longer be // Disable the Touch Exploration Mode. Touch Exploration Mode will no longer be
// turned on automatically when spoken feedback is enabled when this flag is // turned on automatically when spoken feedback is enabled when this flag is
// set. // set.
......
...@@ -24,6 +24,7 @@ ASH_EXPORT extern const char kAshDebugShortcuts[]; ...@@ -24,6 +24,7 @@ ASH_EXPORT extern const char kAshDebugShortcuts[];
ASH_EXPORT extern const char kAshDefaultWallpaperIsOem[]; ASH_EXPORT extern const char kAshDefaultWallpaperIsOem[];
ASH_EXPORT extern const char kAshDefaultWallpaperLarge[]; ASH_EXPORT extern const char kAshDefaultWallpaperLarge[];
ASH_EXPORT extern const char kAshDefaultWallpaperSmall[]; ASH_EXPORT extern const char kAshDefaultWallpaperSmall[];
ASH_EXPORT extern const char kAshDisableLockLayoutManager[];
ASH_EXPORT extern const char kAshDisableTouchExplorationMode[]; ASH_EXPORT extern const char kAshDisableTouchExplorationMode[];
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
ASH_EXPORT extern const char kAshEnableMagnifierKeyScroller[]; ASH_EXPORT extern const char kAshEnableMagnifierKeyScroller[];
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "ash/touch/touch_observer_hud.h" #include "ash/touch/touch_observer_hud.h"
#include "ash/wm/always_on_top_controller.h" #include "ash/wm/always_on_top_controller.h"
#include "ash/wm/dock/docked_window_layout_manager.h" #include "ash/wm/dock/docked_window_layout_manager.h"
#include "ash/wm/lock_layout_manager.h"
#include "ash/wm/panels/attached_panel_window_targeter.h" #include "ash/wm/panels/attached_panel_window_targeter.h"
#include "ash/wm/panels/panel_layout_manager.h" #include "ash/wm/panels/panel_layout_manager.h"
#include "ash/wm/panels/panel_window_event_handler.h" #include "ash/wm/panels/panel_window_event_handler.h"
...@@ -1011,7 +1012,13 @@ void RootWindowController::CreateContainersInRootWindow( ...@@ -1011,7 +1012,13 @@ void RootWindowController::CreateContainersInRootWindow(
kShellWindowId_LockScreenContainer, kShellWindowId_LockScreenContainer,
"LockScreenContainer", "LockScreenContainer",
lock_screen_containers); lock_screen_containers);
lock_container->SetLayoutManager(new WorkspaceLayoutManager(lock_container)); if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kAshDisableLockLayoutManager)) {
lock_container->SetLayoutManager(
new WorkspaceLayoutManager(lock_container));
} else {
lock_container->SetLayoutManager(new LockLayoutManager(lock_container));
}
SetUsesScreenCoordinates(lock_container); SetUsesScreenCoordinates(lock_container);
// TODO(beng): stopsevents // TODO(beng): stopsevents
......
...@@ -123,14 +123,19 @@ keyboard::KeyboardControllerProxy* ...@@ -123,14 +123,19 @@ keyboard::KeyboardControllerProxy*
} }
void TestShellDelegate::VirtualKeyboardActivated(bool activated) { void TestShellDelegate::VirtualKeyboardActivated(bool activated) {
FOR_EACH_OBSERVER(ash::VirtualKeyboardStateObserver,
keyboard_state_observer_list_,
OnVirtualKeyboardStateChanged(activated));
} }
void TestShellDelegate::AddVirtualKeyboardStateObserver( void TestShellDelegate::AddVirtualKeyboardStateObserver(
VirtualKeyboardStateObserver* observer) { VirtualKeyboardStateObserver* observer) {
keyboard_state_observer_list_.AddObserver(observer);
} }
void TestShellDelegate::RemoveVirtualKeyboardStateObserver( void TestShellDelegate::RemoveVirtualKeyboardStateObserver(
VirtualKeyboardStateObserver* observer) { VirtualKeyboardStateObserver* observer) {
keyboard_state_observer_list_.RemoveObserver(observer);
} }
content::BrowserContext* TestShellDelegate::GetActiveBrowserContext() { content::BrowserContext* TestShellDelegate::GetActiveBrowserContext() {
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "ash/shell_delegate.h" #include "ash/shell_delegate.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
namespace keyboard { namespace keyboard {
class KeyboardControllerProxy; class KeyboardControllerProxy;
...@@ -76,6 +77,8 @@ class TestShellDelegate : public ShellDelegate { ...@@ -76,6 +77,8 @@ class TestShellDelegate : public ShellDelegate {
scoped_ptr<content::BrowserContext> active_browser_context_; scoped_ptr<content::BrowserContext> active_browser_context_;
ObserverList<ash::VirtualKeyboardStateObserver> keyboard_state_observer_list_;
TestSessionStateDelegate* test_session_state_delegate_; // Not owned. TestSessionStateDelegate* test_session_state_delegate_; // Not owned.
DISALLOW_COPY_AND_ASSIGN(TestShellDelegate); DISALLOW_COPY_AND_ASSIGN(TestShellDelegate);
......
// Copyright 2014 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/lock_layout_manager.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/wm/lock_window_state.h"
#include "ash/wm/window_state.h"
#include "ash/wm/wm_event.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/events/event.h"
#include "ui/keyboard/keyboard_controller.h"
#include "ui/keyboard/keyboard_util.h"
namespace ash {
LockLayoutManager::LockLayoutManager(aura::Window* window)
: window_(window),
root_window_(window->GetRootWindow()),
is_observing_keyboard_(false) {
Shell::GetInstance()->delegate()->AddVirtualKeyboardStateObserver(this);
root_window_->AddObserver(this);
if (keyboard::KeyboardController::GetInstance()) {
keyboard::KeyboardController::GetInstance()->AddObserver(this);
is_observing_keyboard_ = true;
}
}
LockLayoutManager::~LockLayoutManager() {
if (root_window_)
root_window_->RemoveObserver(this);
for (aura::Window::Windows::const_iterator it = window_->children().begin();
it != window_->children().end(); ++it) {
(*it)->RemoveObserver(this);
}
Shell::GetInstance()->delegate()->RemoveVirtualKeyboardStateObserver(this);
if (keyboard::KeyboardController::GetInstance() && is_observing_keyboard_) {
keyboard::KeyboardController::GetInstance()->RemoveObserver(this);
is_observing_keyboard_ = false;
}
}
void LockLayoutManager::OnWindowResized() {
const wm::WMEvent event(wm::WM_EVENT_WORKAREA_BOUNDS_CHANGED);
AdjustWindowsForWorkAreaChange(&event);
}
void LockLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
child->AddObserver(this);
// LockWindowState replaces default WindowState of a child.
wm::WindowState* window_state = LockWindowState::SetLockWindowState(child);
wm::WMEvent event(wm::WM_EVENT_ADDED_TO_WORKSPACE);
window_state->OnWMEvent(&event);
}
void LockLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
child->RemoveObserver(this);
}
void LockLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
}
void LockLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
bool visible) {
}
void LockLayoutManager::SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) {
wm::WindowState* window_state = wm::GetWindowState(child);
wm::SetBoundsEvent event(wm::WM_EVENT_SET_BOUNDS, requested_bounds);
window_state->OnWMEvent(&event);
}
void LockLayoutManager::OnWindowHierarchyChanged(
const WindowObserver::HierarchyChangeParams& params) {
}
void LockLayoutManager::OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) {
}
void LockLayoutManager::OnWindowStackingChanged(aura::Window* window) {
}
void LockLayoutManager::OnWindowDestroying(aura::Window* window) {
window->RemoveObserver(this);
if (root_window_ == window)
root_window_ = NULL;
}
void LockLayoutManager::OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) {
if (root_window_ == window) {
const wm::WMEvent wm_event(wm::WM_EVENT_DISPLAY_BOUNDS_CHANGED);
AdjustWindowsForWorkAreaChange(&wm_event);
}
}
void LockLayoutManager::OnVirtualKeyboardStateChanged(bool activated) {
if (keyboard::KeyboardController::GetInstance()) {
if (activated) {
if (!is_observing_keyboard_) {
keyboard::KeyboardController::GetInstance()->AddObserver(this);
is_observing_keyboard_ = true;
}
} else {
keyboard::KeyboardController::GetInstance()->RemoveObserver(this);
is_observing_keyboard_ = false;
}
}
}
void LockLayoutManager::OnKeyboardBoundsChanging(const gfx::Rect& new_bounds) {
keyboard_bounds_ = new_bounds;
OnWindowResized();
}
void LockLayoutManager::AdjustWindowsForWorkAreaChange(
const wm::WMEvent* event) {
DCHECK(event->type() == wm::WM_EVENT_DISPLAY_BOUNDS_CHANGED ||
event->type() == wm::WM_EVENT_WORKAREA_BOUNDS_CHANGED);
for (aura::Window::Windows::const_iterator it = window_->children().begin();
it != window_->children().end();
++it) {
wm::GetWindowState(*it)->OnWMEvent(event);
}
}
} // namespace ash
// Copyright 2014 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.
#ifndef ASH_WM_LOCK_LAYOUT_MANAGER_H_
#define ASH_WM_LOCK_LAYOUT_MANAGER_H_
#include "ash/ash_export.h"
#include "ash/shell_delegate.h"
#include "ash/wm/wm_types.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "ui/aura/layout_manager.h"
#include "ui/aura/window_observer.h"
#include "ui/gfx/rect.h"
#include "ui/keyboard/keyboard_controller.h"
#include "ui/keyboard/keyboard_controller_observer.h"
namespace aura {
class RootWindow;
class Window;
}
namespace ui {
class Layer;
}
namespace ash {
namespace wm {
class WindowState;
class WMEvent;
}
// LockLayoutManager is used for the windows created in LockScreenContainer.
// For Chrome OS this includes out-of-box/login/lock/multi-profile login use
// cases. LockScreenContainer does not use default work area definition.
// By default work area is defined as display area minus shelf, docked windows
// and minus virtual keyboard bounds.
// For windows in LockScreenContainer work area is display area minus virtual
// keyboard bounds (only if keyboard overscroll is disabled). If keyboard
// overscroll is enabled then work area always equals to display area size since
// virtual keyboard changes inner workspace of each WebContents.
// For all windows in LockScreenContainer default wm::WindowState is replaced
// with LockWindowState.
class ASH_EXPORT LockLayoutManager
: public aura::LayoutManager,
public aura::WindowObserver,
public VirtualKeyboardStateObserver,
public keyboard::KeyboardControllerObserver {
public:
explicit LockLayoutManager(aura::Window* window);
virtual ~LockLayoutManager();
// Overridden from aura::LayoutManager:
virtual void OnWindowResized() OVERRIDE;
virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE;
virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE;
virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE;
virtual void OnChildWindowVisibilityChanged(aura::Window* child,
bool visibile) OVERRIDE;
virtual void SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) OVERRIDE;
// Overriden from aura::WindowObserver:
virtual void OnWindowHierarchyChanged(
const WindowObserver::HierarchyChangeParams& params) OVERRIDE;
virtual void OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) OVERRIDE;
virtual void OnWindowStackingChanged(aura::Window* window) OVERRIDE;
virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
virtual void OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) OVERRIDE;
// VirtualKeyboardStateObserver overrides:
virtual void OnVirtualKeyboardStateChanged(bool activated) OVERRIDE;
// keyboard::KeyboardControllerObserver overrides:
virtual void OnKeyboardBoundsChanging(const gfx::Rect& new_bounds) OVERRIDE;
private:
// Adjusts the bounds of all managed windows when the display area changes.
// This happens when the display size, work area insets has changed.
void AdjustWindowsForWorkAreaChange(const wm::WMEvent* event);
aura::Window* window_;
aura::Window* root_window_;
// True is subscribed as keyboard controller observer.
bool is_observing_keyboard_;
// The bounds of the keyboard.
gfx::Rect keyboard_bounds_;
DISALLOW_COPY_AND_ASSIGN(LockLayoutManager);
};
} // namespace ash
#endif // ASH_WM_LOCK_LAYOUT_MANAGER_H_
// Copyright 2014 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/root_window_controller.h"
#include "ash/screen_util.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/test/ash_test_base.h"
#include "ash/wm/window_state.h"
#include "base/basictypes.h"
#include "base/command_line.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/gfx/screen.h"
#include "ui/keyboard/keyboard_controller.h"
#include "ui/keyboard/keyboard_controller_proxy.h"
#include "ui/keyboard/keyboard_switches.h"
#include "ui/keyboard/keyboard_util.h"
#include "ui/views/widget/widget.h"
namespace ash {
namespace test {
namespace {
const int kVirtualKeyboardHeight = 100;
} // namespace
class LockLayoutManagerTest : public AshTestBase {
public:
virtual void SetUp() OVERRIDE {
// Allow a virtual keyboard (and initialize it per default).
CommandLine::ForCurrentProcess()->AppendSwitch(
keyboard::switches::kEnableVirtualKeyboard);
AshTestBase::SetUp();
Shell::GetPrimaryRootWindowController()->ActivateKeyboard(
keyboard::KeyboardController::GetInstance());
}
virtual void TearDown() OVERRIDE {
Shell::GetPrimaryRootWindowController()->DeactivateKeyboard(
keyboard::KeyboardController::GetInstance());
AshTestBase::TearDown();
}
aura::Window* CreateTestLoginWindowWithBounds(const gfx::Rect& bounds) {
aura::Window* parent = Shell::GetPrimaryRootWindowController()->
GetContainer(ash::kShellWindowId_LockScreenContainer);
views::Widget* widget =
views::Widget::CreateWindowWithParentAndBounds(NULL, parent, bounds);
widget->Show();
return widget->GetNativeView();
}
// Show or hide the keyboard.
void ShowKeyboard(bool show) {
keyboard::KeyboardController* keyboard =
keyboard::KeyboardController::GetInstance();
ASSERT_TRUE(keyboard);
if (show == keyboard->keyboard_visible())
return;
if (show) {
keyboard->ShowKeyboard(true);
if (keyboard->proxy()->GetKeyboardWindow()->bounds().height() == 0) {
keyboard->proxy()->GetKeyboardWindow()->SetBounds(
keyboard::KeyboardBoundsFromWindowBounds(
keyboard->GetContainerWindow()->bounds(),
kVirtualKeyboardHeight));
}
} else {
keyboard->HideKeyboard(keyboard::KeyboardController::HIDE_REASON_MANUAL);
}
DCHECK_EQ(show, keyboard->keyboard_visible());
}
};
TEST_F(LockLayoutManagerTest, WindowBoundsAreEqualToScreen) {
gfx::Rect screen_bounds = Shell::GetScreen()->GetPrimaryDisplay().bounds();
scoped_ptr<aura::Window> window(
CreateTestLoginWindowWithBounds(gfx::Rect(10, 10, 300, 300)));
EXPECT_EQ(screen_bounds.ToString(), window->GetBoundsInScreen().ToString());
gfx::Rect work_area =
ScreenUtil::GetDisplayWorkAreaBoundsInParent(window.get());
window->SetBounds(work_area);
// Usually work_area takes Shelf into account but that doesn't affect
// LockScreen container windows.
EXPECT_NE(work_area.ToString(), window->GetBoundsInScreen().ToString());
EXPECT_EQ(screen_bounds.ToString(), window->GetBoundsInScreen().ToString());
window->SetBounds(gfx::Rect(100, 100, 200, 200));
EXPECT_EQ(screen_bounds.ToString(), window->GetBoundsInScreen().ToString());
}
TEST_F(LockLayoutManagerTest, KeyboardBounds) {
gfx::Rect screen_bounds = Shell::GetScreen()->GetPrimaryDisplay().bounds();
scoped_ptr<aura::Window> window(CreateTestLoginWindowWithBounds(gfx::Rect()));
EXPECT_EQ(screen_bounds.ToString(), window->GetBoundsInScreen().ToString());
// When virtual keyboard overscroll is enabled keyboard bounds should not
// affect window bounds.
keyboard::SetKeyboardOverscrollOverride(
keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_ENABLED);
ShowKeyboard(true);
EXPECT_EQ(screen_bounds.ToString(), window->GetBoundsInScreen().ToString());
ShowKeyboard(false);
// When virtual keyboard overscroll is disabled keyboard bounds do
// affect window bounds.
keyboard::SetKeyboardOverscrollOverride(
keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_DISABLED);
ShowKeyboard(true);
keyboard::KeyboardController* keyboard =
keyboard::KeyboardController::GetInstance();
gfx::Rect target_bounds(screen_bounds);
target_bounds.set_height(target_bounds.height() -
keyboard->proxy()->GetKeyboardWindow()->bounds().height());
EXPECT_EQ(target_bounds.ToString(), window->GetBoundsInScreen().ToString());
ShowKeyboard(false);
keyboard::SetKeyboardOverscrollOverride(
keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_NONE);
}
TEST_F(LockLayoutManagerTest, MultipleMonitors) {
if (!SupportsMultipleDisplays())
return;
UpdateDisplay("300x400,400x500");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
gfx::Rect screen_bounds = Shell::GetScreen()->GetPrimaryDisplay().bounds();
scoped_ptr<aura::Window> window(CreateTestLoginWindowWithBounds(gfx::Rect()));
EXPECT_EQ(screen_bounds.ToString(), window->GetBoundsInScreen().ToString());
EXPECT_EQ(root_windows[0], window->GetRootWindow());
wm::WindowState* window_state = wm::GetWindowState(window.get());
window_state->SetRestoreBoundsInScreen(gfx::Rect(400, 0, 30, 40));
// Maximize the window with as the restore bounds is inside 2nd display but
// lock container windows are always on primary display.
window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
EXPECT_EQ(root_windows[0], window->GetRootWindow());
EXPECT_EQ("0,0 300x400", window->GetBoundsInScreen().ToString());
window_state->Restore();
EXPECT_EQ(root_windows[0], window->GetRootWindow());
EXPECT_EQ("0,0 300x400", window->GetBoundsInScreen().ToString());
window_state->SetRestoreBoundsInScreen(gfx::Rect(280, 0, 30, 40));
window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
EXPECT_EQ(root_windows[0], window->GetRootWindow());
EXPECT_EQ("0,0 300x400", window->GetBoundsInScreen().ToString());
window_state->Restore();
EXPECT_EQ(root_windows[0], window->GetRootWindow());
EXPECT_EQ("0,0 300x400", window->GetBoundsInScreen().ToString());
gfx::Rect work_area =
ScreenUtil::GetDisplayWorkAreaBoundsInParent(window.get());
window->SetBounds(work_area);
// Usually work_area takes Shelf into account but that doesn't affect
// LockScreen container windows.
EXPECT_NE(work_area.ToString(), window->GetBoundsInScreen().ToString());
EXPECT_EQ(screen_bounds.ToString(), window->GetBoundsInScreen().ToString());
}
} // namespace test
} // namespace ash
// Copyright 2014 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/lock_window_state.h"
#include "ash/screen_util.h"
#include "ash/shell.h"
#include "ash/wm/lock_layout_manager.h"
#include "ash/wm/window_animations.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_state_delegate.h"
#include "ash/wm/window_state_util.h"
#include "ash/wm/window_util.h"
#include "ash/wm/wm_event.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/gfx/rect.h"
#include "ui/keyboard/keyboard_controller.h"
#include "ui/keyboard/keyboard_util.h"
#include "ui/wm/core/window_animations.h"
namespace ash {
LockWindowState::LockWindowState(aura::Window* window)
: current_state_type_(wm::GetWindowState(window)->GetStateType()) {
}
LockWindowState::~LockWindowState() {
}
void LockWindowState::OnWMEvent(wm::WindowState* window_state,
const wm::WMEvent* event) {
aura::Window* window = window_state->window();
gfx::Rect bounds = window->bounds();
switch (event->type()) {
case wm::WM_EVENT_TOGGLE_FULLSCREEN:
ToggleFullScreen(window_state, window_state->delegate());
break;
case wm::WM_EVENT_FULLSCREEN:
UpdateWindow(window_state, wm::WINDOW_STATE_TYPE_FULLSCREEN);
break;
case wm::WM_EVENT_TOGGLE_MAXIMIZE_CAPTION:
case wm::WM_EVENT_TOGGLE_VERTICAL_MAXIMIZE:
case wm::WM_EVENT_TOGGLE_HORIZONTAL_MAXIMIZE:
case wm::WM_EVENT_TOGGLE_MAXIMIZE:
case wm::WM_EVENT_CENTER:
case wm::WM_EVENT_SNAP_LEFT:
case wm::WM_EVENT_SNAP_RIGHT:
case wm::WM_EVENT_NORMAL:
case wm::WM_EVENT_MAXIMIZE:
UpdateWindow(window_state,
GetMaximizedOrCenteredWindowType(window_state));
return;
case wm::WM_EVENT_MINIMIZE:
UpdateWindow(window_state, wm::WINDOW_STATE_TYPE_MINIMIZED);
return;
case wm::WM_EVENT_SHOW_INACTIVE:
return;
case wm::WM_EVENT_SET_BOUNDS:
UpdateBounds(window_state);
break;
case wm::WM_EVENT_ADDED_TO_WORKSPACE:
if (current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED &&
current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED &&
current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN) {
UpdateWindow(window_state,
GetMaximizedOrCenteredWindowType(window_state));
}
break;
case wm::WM_EVENT_WORKAREA_BOUNDS_CHANGED:
case wm::WM_EVENT_DISPLAY_BOUNDS_CHANGED:
UpdateBounds(window_state);
break;
}
}
wm::WindowStateType LockWindowState::GetType() const {
return current_state_type_;
}
void LockWindowState::AttachState(wm::WindowState* window_state,
wm::WindowState::State* previous_state) {
current_state_type_ = previous_state->GetType();
// Initialize the state to a good preset.
if (current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED &&
current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED &&
current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN) {
UpdateWindow(window_state,
GetMaximizedOrCenteredWindowType(window_state));
}
}
void LockWindowState::DetachState(wm::WindowState* window_state) {
}
// static
wm::WindowState* LockWindowState::SetLockWindowState(aura::Window* window) {
scoped_ptr<wm::WindowState::State> lock_state(new LockWindowState(window));
scoped_ptr<wm::WindowState::State> old_state(
wm::GetWindowState(window)->SetStateObject(lock_state.Pass()));
return wm::GetWindowState(window);
}
void LockWindowState::UpdateWindow(wm::WindowState* window_state,
wm::WindowStateType target_state) {
DCHECK(target_state == wm::WINDOW_STATE_TYPE_MINIMIZED ||
target_state == wm::WINDOW_STATE_TYPE_MAXIMIZED ||
(target_state == wm::WINDOW_STATE_TYPE_NORMAL &&
!window_state->CanMaximize()) ||
target_state == wm::WINDOW_STATE_TYPE_FULLSCREEN);
if (target_state == wm::WINDOW_STATE_TYPE_MINIMIZED) {
if (current_state_type_ == wm::WINDOW_STATE_TYPE_MINIMIZED)
return;
current_state_type_ = target_state;
::wm::SetWindowVisibilityAnimationType(
window_state->window(), WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE);
window_state->window()->Hide();
if (window_state->IsActive())
window_state->Deactivate();
return;
}
if (current_state_type_ == target_state) {
// If the state type did not change, update it accordingly.
UpdateBounds(window_state);
return;
}
const wm::WindowStateType old_state_type = current_state_type_;
current_state_type_ = target_state;
window_state->UpdateWindowShowStateFromStateType();
window_state->NotifyPreStateTypeChange(old_state_type);
UpdateBounds(window_state);
window_state->NotifyPostStateTypeChange(old_state_type);
if ((window_state->window()->TargetVisibility() ||
old_state_type == wm::WINDOW_STATE_TYPE_MINIMIZED) &&
!window_state->window()->layer()->visible()) {
// The layer may be hidden if the window was previously minimized. Make
// sure it's visible.
window_state->window()->Show();
}
}
wm::WindowStateType LockWindowState::GetMaximizedOrCenteredWindowType(
wm::WindowState* window_state) {
return window_state->CanMaximize() ? wm::WINDOW_STATE_TYPE_MAXIMIZED :
wm::WINDOW_STATE_TYPE_NORMAL;
}
void LockWindowState::UpdateBounds(wm::WindowState* window_state) {
keyboard::KeyboardController* keyboard_controller =
keyboard::KeyboardController::GetInstance();
gfx::Rect keyboard_bounds;
if (keyboard_controller && !keyboard::IsKeyboardOverscrollEnabled())
keyboard_bounds = keyboard_controller->current_keyboard_bounds();
gfx::Rect bounds =
ScreenUtil::GetDisplayBoundsInParent(window_state->window());
bounds.set_height(bounds.height() - keyboard_bounds.height());
window_state->SetBoundsDirect(bounds);
}
} // namespace ash
// Copyright 2014 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.
#ifndef ASH_WM_LOCK_WINDOW_STATE_H_
#define ASH_WM_LOCK_WINDOW_STATE_H_
#include "ash/wm/window_state.h"
namespace ash {
// The LockWindowState implementation which reduces all possible window
// states to maximized (or normal if can't be maximized)/minimized/full-screen
// and is applied only on lock (login) window container.
// LockWindowState implements Ash behavior without state machine.
class LockWindowState : public wm::WindowState::State {
public:
// The |window|'s state object will be modified to use this new window mode
// state handler.
explicit LockWindowState(aura::Window* window);
virtual ~LockWindowState();
// WindowState::State overrides:
virtual void OnWMEvent(wm::WindowState* window_state,
const wm::WMEvent* event) OVERRIDE;
virtual wm::WindowStateType GetType() const OVERRIDE;
virtual void AttachState(wm::WindowState* window_state,
wm::WindowState::State* previous_state) OVERRIDE;
virtual void DetachState(wm::WindowState* window_state) OVERRIDE;
// Creates new LockWindowState instance and attaches it to |window|.
static wm::WindowState* SetLockWindowState(aura::Window* window);
private:
// Updates the window to |new_state_type| and resulting bounds:
// Either full screen, maximized centered or minimized. If the state does not
// change, only the bounds will be changed.
void UpdateWindow(wm::WindowState* window_state,
wm::WindowStateType new_state_type);
// Depending on the capabilities of the window we either return
// |WINDOW_STATE_TYPE_MAXIMIZED| or |WINDOW_STATE_TYPE_NORMAL|.
wm::WindowStateType GetMaximizedOrCenteredWindowType(
wm::WindowState* window_state);
// Updates the bounds taking virtual keyboard bounds into consideration.
void UpdateBounds(wm::WindowState* window_state);
// The current state type. Due to the nature of this state, this can only be
// WM_STATE_TYPE{NORMAL, MINIMIZED, MAXIMIZED}.
wm::WindowStateType current_state_type_;
DISALLOW_COPY_AND_ASSIGN(LockWindowState);
};
} // namespace ash
#endif // ASH_WM_LOCK_WINDOW_STATE_H_
...@@ -25,6 +25,7 @@ class Rect; ...@@ -25,6 +25,7 @@ class Rect;
namespace ash { namespace ash {
class WorkspaceLayoutManager; class WorkspaceLayoutManager;
class LockWindowState;
class MaximizeModeWindowState; class MaximizeModeWindowState;
namespace wm { namespace wm {
...@@ -303,6 +304,7 @@ class ASH_EXPORT WindowState : public aura::WindowObserver { ...@@ -303,6 +304,7 @@ class ASH_EXPORT WindowState : public aura::WindowObserver {
private: private:
friend class DefaultState; friend class DefaultState;
friend class ash::LockWindowState;
friend class ash::MaximizeModeWindowState; friend class ash::MaximizeModeWindowState;
FRIEND_TEST_ALL_PREFIXES(WindowAnimationsTest, CrossFadeToBounds); FRIEND_TEST_ALL_PREFIXES(WindowAnimationsTest, CrossFadeToBounds);
......
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