diff options
Diffstat (limited to 'chromium/ash/wm/window_state.cc')
-rw-r--r-- | chromium/ash/wm/window_state.cc | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/chromium/ash/wm/window_state.cc b/chromium/ash/wm/window_state.cc new file mode 100644 index 00000000000..4bc1484f9b8 --- /dev/null +++ b/chromium/ash/wm/window_state.cc @@ -0,0 +1,344 @@ +// Copyright 2013 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/window_state.h" + +#include "ash/ash_switches.h" +#include "ash/root_window_controller.h" +#include "ash/screen_ash.h" +#include "ash/shell_window_ids.h" +#include "ash/wm/window_properties.h" +#include "ash/wm/window_state_delegate.h" +#include "ash/wm/window_state_observer.h" +#include "ash/wm/window_util.h" +#include "ash/wm/wm_types.h" +#include "base/auto_reset.h" +#include "base/command_line.h" +#include "ui/aura/client/aura_constants.h" +#include "ui/aura/window.h" +#include "ui/aura/window_delegate.h" +#include "ui/gfx/display.h" +#include "ui/views/corewm/window_util.h" + +namespace ash { +namespace wm { + +// static +bool WindowState::IsMaximizedOrFullscreenState(ui::WindowShowState show_state) { + return show_state == ui::SHOW_STATE_FULLSCREEN || + show_state == ui::SHOW_STATE_MAXIMIZED; +} + +WindowState::WindowState(aura::Window* window) + : window_(window), + window_position_managed_(false), + bounds_changed_by_user_(false), + panel_attached_(true), + continue_drag_after_reparent_(false), + ignored_by_shelf_(false), + can_consume_system_keys_(false), + top_row_keys_are_function_keys_(false), + window_resizer_(NULL), + always_restores_to_restore_bounds_(false), + hide_shelf_when_fullscreen_(true), + animate_to_fullscreen_(true), + minimum_visibility_(false), + in_set_window_show_type_(false), + window_show_type_(ToWindowShowType(GetShowState())) { + window_->AddObserver(this); + +#if defined(OS_CHROMEOS) + // NOTE(pkotwicz): Animating to immersive fullscreen does not look good. When + // the kAshEnableImmersiveFullscreenForAllWindows flag is set most windows + // can be put into immersive fullscreen. It is not worth the added complexity + // to only animate to fullscreen if the window is put into immersive + // fullscreen. + animate_to_fullscreen_ = !CommandLine::ForCurrentProcess()->HasSwitch( + switches::kAshEnableImmersiveFullscreenForAllWindows); +#endif +} + +WindowState::~WindowState() { +} + +bool WindowState::HasDelegate() const { + return delegate_; +} + +void WindowState::SetDelegate(scoped_ptr<WindowStateDelegate> delegate) { + DCHECK(!delegate_.get()); + delegate_ = delegate.Pass(); +} + +ui::WindowShowState WindowState::GetShowState() const { + return window_->GetProperty(aura::client::kShowStateKey); +} + +bool WindowState::IsMinimized() const { + return GetShowState() == ui::SHOW_STATE_MINIMIZED; +} + +bool WindowState::IsMaximized() const { + return GetShowState() == ui::SHOW_STATE_MAXIMIZED; +} + +bool WindowState::IsFullscreen() const { + return GetShowState() == ui::SHOW_STATE_FULLSCREEN; +} + +bool WindowState::IsMaximizedOrFullscreen() const { + return IsMaximizedOrFullscreenState(GetShowState()); +} + +bool WindowState::IsNormalShowState() const { + ui::WindowShowState state = window_->GetProperty(aura::client::kShowStateKey); + return state == ui::SHOW_STATE_NORMAL || state == ui::SHOW_STATE_DEFAULT; +} + +bool WindowState::IsActive() const { + return IsActiveWindow(window_); +} + +bool WindowState::IsDocked() const { + return window_->parent() && + window_->parent()->id() == internal::kShellWindowId_DockedContainer; +} + +bool WindowState::IsSnapped() const { + return window_show_type_ == SHOW_TYPE_LEFT_SNAPPED || + window_show_type_ == SHOW_TYPE_RIGHT_SNAPPED; +} + +bool WindowState::CanMaximize() const { + return window_->GetProperty(aura::client::kCanMaximizeKey); +} + +bool WindowState::CanMinimize() const { + internal::RootWindowController* controller = + internal::RootWindowController::ForWindow(window_); + if (!controller) + return false; + aura::Window* lockscreen = controller->GetContainer( + internal::kShellWindowId_LockScreenContainersContainer); + if (lockscreen->Contains(window_)) + return false; + + return true; +} + +bool WindowState::CanResize() const { + return window_->GetProperty(aura::client::kCanResizeKey); +} + +bool WindowState::CanActivate() const { + return views::corewm::CanActivateWindow(window_); +} + +bool WindowState::CanSnap() const { + if (!CanResize() || + window_->type() == aura::client::WINDOW_TYPE_PANEL || + window_->transient_parent()) + return false; + // If a window has a maximum size defined, snapping may make it too big. + return window_->delegate() ? window_->delegate()->GetMaximumSize().IsEmpty() : + true; +} + +bool WindowState::HasRestoreBounds() const { + return window_->GetProperty(aura::client::kRestoreBoundsKey) != NULL; +} + +void WindowState::Maximize() { + window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); +} + +void WindowState::SnapLeft(const gfx::Rect& bounds) { + SnapWindow(SHOW_TYPE_LEFT_SNAPPED, bounds); +} + +void WindowState::SnapRight(const gfx::Rect& bounds) { + SnapWindow(SHOW_TYPE_RIGHT_SNAPPED, bounds); +} + +void WindowState::Minimize() { + window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); +} + +void WindowState::Unminimize() { + window_->SetProperty( + aura::client::kShowStateKey, + window_->GetProperty(aura::client::kRestoreShowStateKey)); + window_->ClearProperty(aura::client::kRestoreShowStateKey); +} + +void WindowState::Activate() { + ActivateWindow(window_); +} + +void WindowState::Deactivate() { + DeactivateWindow(window_); +} + +void WindowState::Restore() { + window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); +} + +void WindowState::ToggleMaximized() { + if (IsMaximized()) + Restore(); + else if (CanMaximize()) + Maximize(); +} + +void WindowState::ToggleFullscreen() { + // Window which cannot be maximized should not be fullscreened. + // It can, however, be restored if it was fullscreened. + bool is_fullscreen = IsFullscreen(); + if (!is_fullscreen && !CanMaximize()) + return; + if (delegate_ && delegate_->ToggleFullscreen(this)) + return; + if (is_fullscreen) { + Restore(); + } else { + window_->SetProperty(aura::client::kShowStateKey, + ui::SHOW_STATE_FULLSCREEN); + } +} + +void WindowState::SetBoundsInScreen( + const gfx::Rect& bounds_in_screen) { + gfx::Rect bounds_in_parent = + ScreenAsh::ConvertRectFromScreen(window_->parent(), + bounds_in_screen); + window_->SetBounds(bounds_in_parent); +} + +void WindowState::SaveCurrentBoundsForRestore() { + gfx::Rect bounds_in_screen = + ScreenAsh::ConvertRectToScreen(window_->parent(), + window_->bounds()); + SetRestoreBoundsInScreen(bounds_in_screen); +} + +gfx::Rect WindowState::GetRestoreBoundsInScreen() const { + return *window_->GetProperty(aura::client::kRestoreBoundsKey); +} + +gfx::Rect WindowState::GetRestoreBoundsInParent() const { + return ScreenAsh::ConvertRectFromScreen(window_->parent(), + GetRestoreBoundsInScreen()); +} + +void WindowState::SetRestoreBoundsInScreen(const gfx::Rect& bounds) { + window_->SetProperty(aura::client::kRestoreBoundsKey, new gfx::Rect(bounds)); +} + +void WindowState::SetRestoreBoundsInParent(const gfx::Rect& bounds) { + SetRestoreBoundsInScreen( + ScreenAsh::ConvertRectToScreen(window_->parent(), bounds)); +} + +void WindowState::ClearRestoreBounds() { + window_->ClearProperty(aura::client::kRestoreBoundsKey); +} + +void WindowState::SetPreAutoManageWindowBounds( + const gfx::Rect& bounds) { + pre_auto_manage_window_bounds_.reset(new gfx::Rect(bounds)); +} + +void WindowState::AddObserver(WindowStateObserver* observer) { + observer_list_.AddObserver(observer); +} + +void WindowState::RemoveObserver(WindowStateObserver* observer) { + observer_list_.RemoveObserver(observer); +} + +void WindowState::OnWindowPropertyChanged(aura::Window* window, + const void* key, + intptr_t old) { + DCHECK_EQ(window, window_); + if (key == aura::client::kShowStateKey) + SetWindowShowType(ToWindowShowType(GetShowState())); +} + +void WindowState::SnapWindow(WindowShowType left_or_right, + const gfx::Rect& bounds) { + if (window_show_type_ == left_or_right) { + window_->SetBounds(bounds); + return; + } + + // Compute the bounds that the window will restore to. If the window does not + // already have restore bounds, it will be restored (when un-snapped) to the + // last bounds that it had before getting snapped. + gfx::Rect restore_bounds_in_screen(HasRestoreBounds() ? + GetRestoreBoundsInScreen() : window_->GetBoundsInScreen()); + // Set the window's restore bounds so that WorkspaceLayoutManager knows + // which width to use when the snapped window is moved to the edge. + SetRestoreBoundsInParent(bounds); + + bool was_maximized = IsMaximizedOrFullscreen(); + // Before we can set the bounds we need to restore the window. + // Restoring the window will set the window to its restored bounds set above. + // Restore will cause OnWindowPropertyChanged() so it needs to be done + // before notifying that the WindowShowType has changed to |left_or_right|. + if (was_maximized) + Restore(); + DCHECK(left_or_right == SHOW_TYPE_LEFT_SNAPPED || + left_or_right == SHOW_TYPE_RIGHT_SNAPPED); + SetWindowShowType(left_or_right); + // TODO(varkha): Ideally the bounds should be changed in a LayoutManager upon + // observing the WindowShowType change. + // If the window is a child of kShellWindowId_DockedContainer such as during + // a drag, the window's bounds are not set in + // WorkspaceLayoutManager::OnWindowShowTypeChanged(). Set them here. Skip + // setting the bounds otherwise to avoid stopping the slide animation which + // was started as a result of OnWindowShowTypeChanged(). + if (IsDocked()) + window_->SetBounds(bounds); + SetRestoreBoundsInScreen(restore_bounds_in_screen); +} + +void WindowState::SetWindowShowType(WindowShowType new_window_show_type) { + if (in_set_window_show_type_) + return; + base::AutoReset<bool> resetter(&in_set_window_show_type_, true); + + ui::WindowShowState new_window_state = + ToWindowShowState(new_window_show_type); + if (new_window_state != GetShowState()) + window_->SetProperty(aura::client::kShowStateKey, new_window_state); + WindowShowType old_window_show_type = window_show_type_; + window_show_type_ = new_window_show_type; + if (old_window_show_type != window_show_type_) { + FOR_EACH_OBSERVER(WindowStateObserver, observer_list_, + OnWindowShowTypeChanged(this, old_window_show_type)); + } +} + +WindowState* GetActiveWindowState() { + aura::Window* active = GetActiveWindow(); + return active ? GetWindowState(active) : NULL; +} + +WindowState* GetWindowState(aura::Window* window) { + if (!window) + return NULL; + WindowState* settings = window->GetProperty(internal::kWindowStateKey); + if(!settings) { + settings = new WindowState(window); + window->SetProperty(internal::kWindowStateKey, settings); + } + return settings; +} + +const WindowState* GetWindowState(const aura::Window* window) { + return GetWindowState(const_cast<aura::Window*>(window)); +} + +} // namespace wm +} // namespace ash |