summaryrefslogtreecommitdiff
path: root/chromium/ash/wm/window_state.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ash/wm/window_state.cc')
-rw-r--r--chromium/ash/wm/window_state.cc344
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