Index: ash/common/wm/default_state.cc |
diff --git a/ash/common/wm/default_state.cc b/ash/common/wm/default_state.cc |
deleted file mode 100644 |
index 8149d7f856fc21a1871835fbd425b90fb7595c3e..0000000000000000000000000000000000000000 |
--- a/ash/common/wm/default_state.cc |
+++ /dev/null |
@@ -1,823 +0,0 @@ |
-// 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/common/wm/default_state.h" |
- |
-#include "ash/common/ash_switches.h" |
-#include "ash/common/wm/dock/docked_window_layout_manager.h" |
-#include "ash/common/wm/window_animation_types.h" |
-#include "ash/common/wm/window_parenting_utils.h" |
-#include "ash/common/wm/window_positioning_utils.h" |
-#include "ash/common/wm/window_state.h" |
-#include "ash/common/wm/window_state_delegate.h" |
-#include "ash/common/wm/window_state_util.h" |
-#include "ash/common/wm/wm_event.h" |
-#include "ash/common/wm/wm_screen_util.h" |
-#include "ash/common/wm_shell.h" |
-#include "ash/common/wm_window.h" |
-#include "ash/public/cpp/shell_window_ids.h" |
-#include "ash/root_window_controller.h" |
-#include "ui/display/display.h" |
-#include "ui/display/screen.h" |
- |
-namespace ash { |
-namespace wm { |
-namespace { |
- |
-// This specifies how much percent (30%) of a window rect |
-// must be visible when the window is added to the workspace. |
-const float kMinimumPercentOnScreenArea = 0.3f; |
- |
-// When a window that has restore bounds at least as large as a work area is |
-// unmaximized, inset the bounds slightly so that they are not exactly the same. |
-// This makes it easier to resize the window. |
-const int kMaximizedWindowInset = 10; // DIPs. |
- |
-bool IsMinimizedWindowState(const WindowStateType state_type) { |
- return state_type == WINDOW_STATE_TYPE_MINIMIZED || |
- state_type == WINDOW_STATE_TYPE_DOCKED_MINIMIZED; |
-} |
- |
-void MoveToDisplayForRestore(WindowState* window_state) { |
- if (!window_state->HasRestoreBounds()) |
- return; |
- const gfx::Rect restore_bounds = window_state->GetRestoreBoundsInScreen(); |
- |
- // Move only if the restore bounds is outside of |
- // the display. There is no information about in which |
- // display it should be restored, so this is best guess. |
- // TODO(oshima): Restore information should contain the |
- // work area information like WindowResizer does for the |
- // last window location. |
- gfx::Rect display_area = |
- window_state->window()->GetDisplayNearestWindow().bounds(); |
- |
- if (!display_area.Intersects(restore_bounds)) { |
- const display::Display& display = |
- display::Screen::GetScreen()->GetDisplayMatching(restore_bounds); |
- WmShell* shell = window_state->window()->GetShell(); |
- WmWindow* new_root = shell->GetRootWindowForDisplayId(display.id()); |
- if (new_root != window_state->window()->GetRootWindow()) { |
- WmWindow* new_container = new_root->GetChildByShellWindowId( |
- window_state->window()->GetParent()->GetShellWindowId()); |
- new_container->AddChild(window_state->window()); |
- } |
- } |
-} |
- |
-DockedWindowLayoutManager* GetDockedWindowLayoutManager(WmShell* shell) { |
- return DockedWindowLayoutManager::Get(shell->GetActiveWindow()); |
-} |
- |
-class ScopedPreferredAlignmentResetter { |
- public: |
- ScopedPreferredAlignmentResetter(DockedAlignment dock_alignment, |
- DockedWindowLayoutManager* dock_layout) |
- : docked_window_layout_manager_(dock_layout) { |
- docked_window_layout_manager_->set_preferred_alignment(dock_alignment); |
- } |
- ~ScopedPreferredAlignmentResetter() { |
- docked_window_layout_manager_->set_preferred_alignment( |
- DOCKED_ALIGNMENT_NONE); |
- } |
- |
- private: |
- DockedWindowLayoutManager* docked_window_layout_manager_; |
- |
- DISALLOW_COPY_AND_ASSIGN(ScopedPreferredAlignmentResetter); |
-}; |
- |
-class ScopedDockedLayoutEventSourceResetter { |
- public: |
- ScopedDockedLayoutEventSourceResetter(DockedWindowLayoutManager* dock_layout) |
- : docked_window_layout_manager_(dock_layout) { |
- docked_window_layout_manager_->set_event_source( |
- DOCKED_ACTION_SOURCE_KEYBOARD); |
- } |
- ~ScopedDockedLayoutEventSourceResetter() { |
- docked_window_layout_manager_->set_event_source( |
- DOCKED_ACTION_SOURCE_UNKNOWN); |
- } |
- |
- private: |
- DockedWindowLayoutManager* docked_window_layout_manager_; |
- |
- DISALLOW_COPY_AND_ASSIGN(ScopedDockedLayoutEventSourceResetter); |
-}; |
- |
-void CycleSnap(WindowState* window_state, WMEventType event) { |
- DCHECK(!ash::switches::DockedWindowsEnabled()); |
- |
- wm::WindowStateType desired_snap_state = |
- event == WM_EVENT_CYCLE_SNAP_DOCK_LEFT |
- ? wm::WINDOW_STATE_TYPE_LEFT_SNAPPED |
- : wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED; |
- |
- if (window_state->CanSnap() && |
- window_state->GetStateType() != desired_snap_state && |
- window_state->window()->GetType() != ui::wm::WINDOW_TYPE_PANEL) { |
- const wm::WMEvent event(desired_snap_state == |
- wm::WINDOW_STATE_TYPE_LEFT_SNAPPED |
- ? wm::WM_EVENT_SNAP_LEFT |
- : wm::WM_EVENT_SNAP_RIGHT); |
- window_state->OnWMEvent(&event); |
- return; |
- } |
- |
- if (window_state->IsSnapped()) { |
- window_state->Restore(); |
- return; |
- } |
- window_state->window()->Animate(::wm::WINDOW_ANIMATION_TYPE_BOUNCE); |
-} |
- |
-void CycleSnapDock(WindowState* window_state, WMEventType event) { |
- DCHECK(ash::switches::DockedWindowsEnabled()); |
- |
- DockedWindowLayoutManager* dock_layout = |
- GetDockedWindowLayoutManager(window_state->window()->GetShell()); |
- wm::WindowStateType desired_snap_state = |
- event == WM_EVENT_CYCLE_SNAP_DOCK_LEFT |
- ? wm::WINDOW_STATE_TYPE_LEFT_SNAPPED |
- : wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED; |
- DockedAlignment desired_dock_alignment = |
- event == WM_EVENT_CYCLE_SNAP_DOCK_LEFT ? DOCKED_ALIGNMENT_LEFT |
- : DOCKED_ALIGNMENT_RIGHT; |
- DockedAlignment current_dock_alignment = |
- dock_layout ? dock_layout->CalculateAlignment() : DOCKED_ALIGNMENT_NONE; |
- |
- if (!window_state->IsDocked() || |
- (current_dock_alignment != DOCKED_ALIGNMENT_NONE && |
- current_dock_alignment != desired_dock_alignment)) { |
- if (window_state->CanSnap() && |
- window_state->GetStateType() != desired_snap_state && |
- window_state->window()->GetType() != ui::wm::WINDOW_TYPE_PANEL) { |
- const wm::WMEvent event(desired_snap_state == |
- wm::WINDOW_STATE_TYPE_LEFT_SNAPPED |
- ? wm::WM_EVENT_SNAP_LEFT |
- : wm::WM_EVENT_SNAP_RIGHT); |
- window_state->OnWMEvent(&event); |
- return; |
- } |
- |
- if (dock_layout && |
- dock_layout->CanDockWindow(window_state->window(), |
- desired_dock_alignment)) { |
- if (window_state->IsDocked()) { |
- dock_layout->MaybeSetDesiredDockedAlignment(desired_dock_alignment); |
- return; |
- } |
- |
- ScopedDockedLayoutEventSourceResetter event_source_resetter(dock_layout); |
- ScopedPreferredAlignmentResetter alignmentResetter(desired_dock_alignment, |
- dock_layout); |
- const wm::WMEvent event(wm::WM_EVENT_DOCK); |
- window_state->OnWMEvent(&event); |
- return; |
- } |
- } |
- |
- if (window_state->IsDocked() || window_state->IsSnapped()) { |
- ScopedDockedLayoutEventSourceResetter event_source_resetter(dock_layout); |
- window_state->Restore(); |
- return; |
- } |
- window_state->window()->Animate(::wm::WINDOW_ANIMATION_TYPE_BOUNCE); |
-} |
- |
-} // namespace |
- |
-DefaultState::DefaultState(WindowStateType initial_state_type) |
- : state_type_(initial_state_type), stored_window_state_(nullptr) {} |
-DefaultState::~DefaultState() {} |
- |
-void DefaultState::OnWMEvent(WindowState* window_state, const WMEvent* event) { |
- if (ProcessWorkspaceEvents(window_state, event)) |
- return; |
- |
- // Do not change the PINNED window state if this is not unpin event. |
- if (window_state->IsTrustedPinned() && event->type() != WM_EVENT_NORMAL) |
- return; |
- |
- if (ProcessCompoundEvents(window_state, event)) |
- return; |
- |
- WindowStateType current_state_type = window_state->GetStateType(); |
- WindowStateType next_state_type = WINDOW_STATE_TYPE_NORMAL; |
- switch (event->type()) { |
- case WM_EVENT_NORMAL: |
- next_state_type = current_state_type == WINDOW_STATE_TYPE_DOCKED_MINIMIZED |
- ? WINDOW_STATE_TYPE_DOCKED |
- : WINDOW_STATE_TYPE_NORMAL; |
- break; |
- case WM_EVENT_MAXIMIZE: |
- next_state_type = WINDOW_STATE_TYPE_MAXIMIZED; |
- break; |
- case WM_EVENT_MINIMIZE: |
- next_state_type = current_state_type == WINDOW_STATE_TYPE_DOCKED |
- ? WINDOW_STATE_TYPE_DOCKED_MINIMIZED |
- : WINDOW_STATE_TYPE_MINIMIZED; |
- break; |
- case WM_EVENT_FULLSCREEN: |
- next_state_type = WINDOW_STATE_TYPE_FULLSCREEN; |
- break; |
- case WM_EVENT_SNAP_LEFT: |
- next_state_type = WINDOW_STATE_TYPE_LEFT_SNAPPED; |
- break; |
- case WM_EVENT_SNAP_RIGHT: |
- next_state_type = WINDOW_STATE_TYPE_RIGHT_SNAPPED; |
- break; |
- case WM_EVENT_DOCK: |
- next_state_type = WINDOW_STATE_TYPE_DOCKED; |
- break; |
- case WM_EVENT_SET_BOUNDS: |
- SetBounds(window_state, static_cast<const SetBoundsEvent*>(event)); |
- return; |
- case WM_EVENT_SHOW_INACTIVE: |
- next_state_type = WINDOW_STATE_TYPE_INACTIVE; |
- break; |
- case WM_EVENT_PIN: |
- case WM_EVENT_TRUSTED_PIN: |
- // If there already is a pinned window, it is not allowed to set it |
- // to this window. |
- // TODO(hidehiko): If a system modal window is openening, the pinning |
- // probably should fail. |
- if (WmShell::Get()->IsPinned()) { |
- LOG(ERROR) << "An PIN event will be failed since another window is " |
- << "already in pinned mode."; |
- next_state_type = current_state_type; |
- } else { |
- next_state_type = event->type() == WM_EVENT_PIN |
- ? WINDOW_STATE_TYPE_PINNED |
- : WINDOW_STATE_TYPE_TRUSTED_PINNED; |
- } |
- break; |
- case WM_EVENT_TOGGLE_MAXIMIZE_CAPTION: |
- case WM_EVENT_TOGGLE_MAXIMIZE: |
- case WM_EVENT_TOGGLE_VERTICAL_MAXIMIZE: |
- case WM_EVENT_TOGGLE_HORIZONTAL_MAXIMIZE: |
- case WM_EVENT_TOGGLE_FULLSCREEN: |
- case WM_EVENT_CYCLE_SNAP_DOCK_LEFT: |
- case WM_EVENT_CYCLE_SNAP_DOCK_RIGHT: |
- case WM_EVENT_CENTER: |
- NOTREACHED() << "Compound event should not reach here:" << event; |
- return; |
- case WM_EVENT_ADDED_TO_WORKSPACE: |
- case WM_EVENT_WORKAREA_BOUNDS_CHANGED: |
- case WM_EVENT_DISPLAY_BOUNDS_CHANGED: |
- NOTREACHED() << "Workspace event should not reach here:" << event; |
- return; |
- } |
- |
- if (next_state_type == current_state_type && window_state->IsSnapped()) { |
- gfx::Rect snapped_bounds = |
- event->type() == WM_EVENT_SNAP_LEFT |
- ? GetDefaultLeftSnappedWindowBoundsInParent(window_state->window()) |
- : GetDefaultRightSnappedWindowBoundsInParent( |
- window_state->window()); |
- window_state->SetBoundsDirectAnimated(snapped_bounds); |
- return; |
- } |
- |
- if (event->type() == WM_EVENT_SNAP_LEFT || |
- event->type() == WM_EVENT_SNAP_RIGHT) { |
- window_state->set_bounds_changed_by_user(true); |
- } |
- |
- EnterToNextState(window_state, next_state_type); |
-} |
- |
-WindowStateType DefaultState::GetType() const { |
- return state_type_; |
-} |
- |
-void DefaultState::AttachState(WindowState* window_state, |
- WindowState::State* state_in_previous_mode) { |
- DCHECK_EQ(stored_window_state_, window_state); |
- |
- ReenterToCurrentState(window_state, state_in_previous_mode); |
- |
- // If the display has changed while in the another mode, |
- // we need to let windows know the change. |
- display::Display current_display = |
- window_state->window()->GetDisplayNearestWindow(); |
- if (stored_display_state_.bounds() != current_display.bounds()) { |
- const WMEvent event(wm::WM_EVENT_DISPLAY_BOUNDS_CHANGED); |
- window_state->OnWMEvent(&event); |
- } else if (stored_display_state_.work_area() != current_display.work_area()) { |
- const WMEvent event(wm::WM_EVENT_WORKAREA_BOUNDS_CHANGED); |
- window_state->OnWMEvent(&event); |
- } |
-} |
- |
-void DefaultState::DetachState(WindowState* window_state) { |
- stored_window_state_ = window_state; |
- stored_bounds_ = window_state->window()->GetBounds(); |
- stored_restore_bounds_ = window_state->HasRestoreBounds() |
- ? window_state->GetRestoreBoundsInParent() |
- : gfx::Rect(); |
- // Remember the display state so that in case of the display change |
- // while in the other mode, we can perform necessary action to |
- // restore the window state to the proper state for the current |
- // display. |
- stored_display_state_ = window_state->window()->GetDisplayNearestWindow(); |
-} |
- |
-// static |
-bool DefaultState::ProcessCompoundEvents(WindowState* window_state, |
- const WMEvent* event) { |
- WmWindow* window = window_state->window(); |
- |
- switch (event->type()) { |
- case WM_EVENT_TOGGLE_MAXIMIZE_CAPTION: |
- if (window_state->IsFullscreen()) { |
- const wm::WMEvent event(wm::WM_EVENT_TOGGLE_FULLSCREEN); |
- window_state->OnWMEvent(&event); |
- } else if (window_state->IsMaximized()) { |
- window_state->Restore(); |
- } else if (window_state->IsNormalOrSnapped()) { |
- if (window_state->CanMaximize()) |
- window_state->Maximize(); |
- } |
- return true; |
- case WM_EVENT_TOGGLE_MAXIMIZE: |
- if (window_state->IsFullscreen()) { |
- const wm::WMEvent event(wm::WM_EVENT_TOGGLE_FULLSCREEN); |
- window_state->OnWMEvent(&event); |
- } else if (window_state->IsMaximized()) { |
- window_state->Restore(); |
- } else if (window_state->CanMaximize()) { |
- window_state->Maximize(); |
- } |
- return true; |
- case WM_EVENT_TOGGLE_VERTICAL_MAXIMIZE: { |
- gfx::Rect work_area = GetDisplayWorkAreaBoundsInParent(window); |
- |
- // Maximize vertically if: |
- // - The window does not have a max height defined. |
- // - The window has the normal state type. Snapped windows are excluded |
- // because they are already maximized vertically and reverting to the |
- // restored bounds looks weird. |
- if (window->GetMaximumSize().height() != 0 || |
- !window_state->IsNormalStateType()) { |
- return true; |
- } |
- if (window_state->HasRestoreBounds() && |
- (window->GetBounds().height() == work_area.height() && |
- window->GetBounds().y() == work_area.y())) { |
- window_state->SetAndClearRestoreBounds(); |
- } else { |
- window_state->SaveCurrentBoundsForRestore(); |
- window->SetBounds(gfx::Rect(window->GetBounds().x(), work_area.y(), |
- window->GetBounds().width(), |
- work_area.height())); |
- } |
- return true; |
- } |
- case WM_EVENT_TOGGLE_HORIZONTAL_MAXIMIZE: { |
- // Maximize horizontally if: |
- // - The window does not have a max width defined. |
- // - The window is snapped or has the normal state type. |
- if (window->GetMaximumSize().width() != 0) |
- return true; |
- if (!window_state->IsNormalOrSnapped()) |
- return true; |
- gfx::Rect work_area = GetDisplayWorkAreaBoundsInParent(window); |
- if (window_state->IsNormalStateType() && |
- window_state->HasRestoreBounds() && |
- (window->GetBounds().width() == work_area.width() && |
- window->GetBounds().x() == work_area.x())) { |
- window_state->SetAndClearRestoreBounds(); |
- } else { |
- gfx::Rect new_bounds(work_area.x(), window->GetBounds().y(), |
- work_area.width(), window->GetBounds().height()); |
- |
- gfx::Rect restore_bounds = window->GetBounds(); |
- if (window_state->IsSnapped()) { |
- window_state->SetRestoreBoundsInParent(new_bounds); |
- window_state->Restore(); |
- |
- // The restore logic prevents a window from being restored to bounds |
- // which match the workspace bounds exactly so it is necessary to set |
- // the bounds again below. |
- } |
- |
- window_state->SetRestoreBoundsInParent(restore_bounds); |
- window->SetBounds(new_bounds); |
- } |
- return true; |
- } |
- case WM_EVENT_TOGGLE_FULLSCREEN: |
- ToggleFullScreen(window_state, window_state->delegate()); |
- return true; |
- case WM_EVENT_CYCLE_SNAP_DOCK_LEFT: |
- case WM_EVENT_CYCLE_SNAP_DOCK_RIGHT: |
- if (ash::switches::DockedWindowsEnabled()) |
- CycleSnapDock(window_state, event->type()); |
- else |
- CycleSnap(window_state, event->type()); |
- return true; |
- case WM_EVENT_CENTER: |
- CenterWindow(window_state); |
- return true; |
- case WM_EVENT_NORMAL: |
- case WM_EVENT_MAXIMIZE: |
- case WM_EVENT_MINIMIZE: |
- case WM_EVENT_FULLSCREEN: |
- case WM_EVENT_PIN: |
- case WM_EVENT_TRUSTED_PIN: |
- case WM_EVENT_SNAP_LEFT: |
- case WM_EVENT_SNAP_RIGHT: |
- case WM_EVENT_SET_BOUNDS: |
- case WM_EVENT_SHOW_INACTIVE: |
- case WM_EVENT_DOCK: |
- break; |
- case WM_EVENT_ADDED_TO_WORKSPACE: |
- case WM_EVENT_WORKAREA_BOUNDS_CHANGED: |
- case WM_EVENT_DISPLAY_BOUNDS_CHANGED: |
- NOTREACHED() << "Workspace event should not reach here:" << event; |
- break; |
- } |
- return false; |
-} |
- |
-bool DefaultState::ProcessWorkspaceEvents(WindowState* window_state, |
- const WMEvent* event) { |
- switch (event->type()) { |
- case WM_EVENT_ADDED_TO_WORKSPACE: { |
- // When a window is dragged and dropped onto a different |
- // root window, the bounds will be updated after they are added |
- // to the root window. |
- // If a window is opened as maximized or fullscreen, its bounds may be |
- // empty, so update the bounds now before checking empty. |
- if (window_state->is_dragged() || |
- SetMaximizedOrFullscreenBounds(window_state)) { |
- return true; |
- } |
- |
- WmWindow* window = window_state->window(); |
- gfx::Rect bounds = window->GetBounds(); |
- |
- // Don't adjust window bounds if the bounds are empty as this |
- // happens when a new views::Widget is created. |
- if (bounds.IsEmpty()) |
- return true; |
- |
- // Only windows of type WINDOW_TYPE_NORMAL or WINDOW_TYPE_PANEL need to be |
- // adjusted to have minimum visibility, because they are positioned by the |
- // user and user should always be able to interact with them. Other |
- // windows are positioned programmatically. |
- if (!window_state->IsUserPositionable()) |
- return true; |
- |
- // Use entire display instead of workarea because the workarea can |
- // be further shrunk by the docked area. The logic ensures 30% |
- // visibility which should be enough to see where the window gets |
- // moved. |
- gfx::Rect display_area = GetDisplayBoundsInParent(window); |
- int min_width = bounds.width() * wm::kMinimumPercentOnScreenArea; |
- int min_height = bounds.height() * wm::kMinimumPercentOnScreenArea; |
- wm::AdjustBoundsToEnsureWindowVisibility(display_area, min_width, |
- min_height, &bounds); |
- window_state->AdjustSnappedBounds(&bounds); |
- if (window->GetBounds() != bounds) |
- window_state->SetBoundsConstrained(bounds); |
- return true; |
- } |
- case WM_EVENT_DISPLAY_BOUNDS_CHANGED: { |
- if (window_state->is_dragged() || |
- SetMaximizedOrFullscreenBounds(window_state)) { |
- return true; |
- } |
- gfx::Rect work_area_in_parent = |
- GetDisplayWorkAreaBoundsInParent(window_state->window()); |
- gfx::Rect bounds = window_state->window()->GetTargetBounds(); |
- // When display bounds has changed, make sure the entire window is fully |
- // visible. |
- bounds.AdjustToFit(work_area_in_parent); |
- window_state->AdjustSnappedBounds(&bounds); |
- if (window_state->window()->GetTargetBounds() != bounds) |
- window_state->SetBoundsDirectAnimated(bounds); |
- return true; |
- } |
- case WM_EVENT_WORKAREA_BOUNDS_CHANGED: { |
- // Don't resize the maximized window when the desktop is covered |
- // by fullscreen window. crbug.com/504299. |
- bool in_fullscreen = |
- window_state->window() |
- ->GetRootWindowController() |
- ->GetWorkspaceWindowState() == WORKSPACE_WINDOW_STATE_FULL_SCREEN; |
- if (in_fullscreen && window_state->IsMaximized()) |
- return true; |
- |
- if (window_state->is_dragged() || |
- SetMaximizedOrFullscreenBounds(window_state)) { |
- return true; |
- } |
- gfx::Rect work_area_in_parent = |
- GetDisplayWorkAreaBoundsInParent(window_state->window()); |
- gfx::Rect bounds = window_state->window()->GetTargetBounds(); |
- if (!window_state->window()->GetTransientParent()) { |
- wm::AdjustBoundsToEnsureMinimumWindowVisibility(work_area_in_parent, |
- &bounds); |
- } |
- window_state->AdjustSnappedBounds(&bounds); |
- if (window_state->window()->GetTargetBounds() != bounds) |
- window_state->SetBoundsDirectAnimated(bounds); |
- return true; |
- } |
- case WM_EVENT_TOGGLE_MAXIMIZE_CAPTION: |
- case WM_EVENT_TOGGLE_MAXIMIZE: |
- case WM_EVENT_TOGGLE_VERTICAL_MAXIMIZE: |
- case WM_EVENT_TOGGLE_HORIZONTAL_MAXIMIZE: |
- case WM_EVENT_TOGGLE_FULLSCREEN: |
- case WM_EVENT_CYCLE_SNAP_DOCK_LEFT: |
- case WM_EVENT_CYCLE_SNAP_DOCK_RIGHT: |
- case WM_EVENT_CENTER: |
- case WM_EVENT_NORMAL: |
- case WM_EVENT_MAXIMIZE: |
- case WM_EVENT_MINIMIZE: |
- case WM_EVENT_FULLSCREEN: |
- case WM_EVENT_PIN: |
- case WM_EVENT_TRUSTED_PIN: |
- case WM_EVENT_SNAP_LEFT: |
- case WM_EVENT_SNAP_RIGHT: |
- case WM_EVENT_SET_BOUNDS: |
- case WM_EVENT_SHOW_INACTIVE: |
- case WM_EVENT_DOCK: |
- break; |
- } |
- return false; |
-} |
- |
-// static |
-bool DefaultState::SetMaximizedOrFullscreenBounds(WindowState* window_state) { |
- DCHECK(!window_state->is_dragged()); |
- if (window_state->IsMaximized()) { |
- window_state->SetBoundsDirect( |
- GetMaximizedWindowBoundsInParent(window_state->window())); |
- return true; |
- } |
- if (window_state->IsFullscreen()) { |
- window_state->SetBoundsDirect( |
- GetDisplayBoundsInParent(window_state->window())); |
- return true; |
- } |
- return false; |
-} |
- |
-// static |
-void DefaultState::SetBounds(WindowState* window_state, |
- const SetBoundsEvent* event) { |
- if (window_state->is_dragged()) { |
- // TODO(oshima|varkha): This may be no longer needed, as the dragging |
- // happens in docked window container. crbug.com/485612. |
- window_state->SetBoundsDirect(event->requested_bounds()); |
- } else if (window_state->IsSnapped()) { |
- gfx::Rect work_area_in_parent = |
- GetDisplayWorkAreaBoundsInParent(window_state->window()); |
- gfx::Rect child_bounds(event->requested_bounds()); |
- wm::AdjustBoundsSmallerThan(work_area_in_parent.size(), &child_bounds); |
- window_state->AdjustSnappedBounds(&child_bounds); |
- window_state->SetBoundsDirect(child_bounds); |
- } else if (!SetMaximizedOrFullscreenBounds(window_state) || |
- window_state->allow_set_bounds_in_maximized()) { |
- window_state->SetBoundsConstrained(event->requested_bounds()); |
- } |
-} |
- |
-void DefaultState::EnterToNextState(WindowState* window_state, |
- WindowStateType next_state_type) { |
- // Do nothing if we're already in the same state. |
- if (state_type_ == next_state_type) |
- return; |
- |
- WindowStateType previous_state_type = state_type_; |
- state_type_ = next_state_type; |
- |
- window_state->UpdateWindowShowStateFromStateType(); |
- window_state->NotifyPreStateTypeChange(previous_state_type); |
- |
- if (window_state->window()->GetParent()) { |
- if (!window_state->HasRestoreBounds() && |
- (previous_state_type == WINDOW_STATE_TYPE_DEFAULT || |
- previous_state_type == WINDOW_STATE_TYPE_NORMAL) && |
- !window_state->IsMinimized() && !window_state->IsNormalStateType()) { |
- window_state->SaveCurrentBoundsForRestore(); |
- } |
- |
- // When restoring from a minimized state, we want to restore to the |
- // previous bounds. However, we want to maintain the restore bounds. |
- // (The restore bounds are set if a user maximized the window in one |
- // axis by double clicking the window border for example). |
- gfx::Rect restore_bounds_in_screen; |
- if (previous_state_type == WINDOW_STATE_TYPE_MINIMIZED && |
- window_state->IsNormalStateType() && window_state->HasRestoreBounds() && |
- !window_state->unminimize_to_restore_bounds()) { |
- restore_bounds_in_screen = window_state->GetRestoreBoundsInScreen(); |
- window_state->SaveCurrentBoundsForRestore(); |
- } |
- |
- if (window_state->IsMaximizedOrFullscreenOrPinned()) |
- MoveToDisplayForRestore(window_state); |
- |
- UpdateBoundsFromState(window_state, previous_state_type); |
- |
- // Normal state should have no restore bounds unless it's |
- // unminimized. |
- if (!restore_bounds_in_screen.IsEmpty()) |
- window_state->SetRestoreBoundsInScreen(restore_bounds_in_screen); |
- else if (window_state->IsNormalStateType()) |
- window_state->ClearRestoreBounds(); |
- } |
- window_state->NotifyPostStateTypeChange(previous_state_type); |
- |
- if (next_state_type == WINDOW_STATE_TYPE_PINNED || |
- previous_state_type == WINDOW_STATE_TYPE_PINNED || |
- next_state_type == WINDOW_STATE_TYPE_TRUSTED_PINNED || |
- previous_state_type == WINDOW_STATE_TYPE_TRUSTED_PINNED) { |
- WmShell::Get()->SetPinnedWindow(window_state->window()); |
- } |
-} |
- |
-void DefaultState::ReenterToCurrentState( |
- WindowState* window_state, |
- WindowState::State* state_in_previous_mode) { |
- WindowStateType previous_state_type = state_in_previous_mode->GetType(); |
- |
- // A state change should not move a window into or out of full screen or |
- // pinned since these are "special mode" the user wanted to be in and |
- // should be respected as such. |
- if (previous_state_type == wm::WINDOW_STATE_TYPE_FULLSCREEN || |
- previous_state_type == wm::WINDOW_STATE_TYPE_PINNED || |
- previous_state_type == wm::WINDOW_STATE_TYPE_TRUSTED_PINNED) { |
- state_type_ = previous_state_type; |
- } else if (state_type_ == wm::WINDOW_STATE_TYPE_FULLSCREEN || |
- state_type_ == wm::WINDOW_STATE_TYPE_PINNED || |
- state_type_ == wm::WINDOW_STATE_TYPE_TRUSTED_PINNED) { |
- state_type_ = previous_state_type; |
- } |
- |
- window_state->UpdateWindowShowStateFromStateType(); |
- window_state->NotifyPreStateTypeChange(previous_state_type); |
- |
- if ((state_type_ == wm::WINDOW_STATE_TYPE_NORMAL || |
- state_type_ == wm::WINDOW_STATE_TYPE_DEFAULT) && |
- !stored_bounds_.IsEmpty()) { |
- // Use the restore mechanism to set the bounds for |
- // the window in normal state. This also covers unminimize case. |
- window_state->SetRestoreBoundsInParent(stored_bounds_); |
- } |
- |
- UpdateBoundsFromState(window_state, state_in_previous_mode->GetType()); |
- |
- // Then restore the restore bounds to their previous value. |
- if (!stored_restore_bounds_.IsEmpty()) |
- window_state->SetRestoreBoundsInParent(stored_restore_bounds_); |
- else |
- window_state->ClearRestoreBounds(); |
- |
- window_state->NotifyPostStateTypeChange(previous_state_type); |
-} |
- |
-void DefaultState::UpdateBoundsFromState(WindowState* window_state, |
- WindowStateType previous_state_type) { |
- WmWindow* window = window_state->window(); |
- gfx::Rect bounds_in_parent; |
- switch (state_type_) { |
- case WINDOW_STATE_TYPE_LEFT_SNAPPED: |
- case WINDOW_STATE_TYPE_RIGHT_SNAPPED: |
- bounds_in_parent = |
- state_type_ == WINDOW_STATE_TYPE_LEFT_SNAPPED |
- ? GetDefaultLeftSnappedWindowBoundsInParent(window) |
- : GetDefaultRightSnappedWindowBoundsInParent(window); |
- break; |
- case WINDOW_STATE_TYPE_DOCKED: { |
- // TODO(afakhry): Remove in M58. |
- DCHECK(ash::switches::DockedWindowsEnabled()); |
- if (window->GetParent()->GetShellWindowId() != |
- kShellWindowId_DockedContainer) { |
- WmWindow* docked_container = |
- window->GetRootWindow()->GetChildByShellWindowId( |
- kShellWindowId_DockedContainer); |
- ReparentChildWithTransientChildren(window, window->GetParent(), |
- docked_container); |
- } |
- // Return early because we don't want to update the bounds of the |
- // window below; as the bounds are managed by the dock layout. |
- return; |
- } |
- case WINDOW_STATE_TYPE_DEFAULT: |
- case WINDOW_STATE_TYPE_NORMAL: { |
- gfx::Rect work_area_in_parent = GetDisplayWorkAreaBoundsInParent(window); |
- if (window_state->HasRestoreBounds()) { |
- bounds_in_parent = window_state->GetRestoreBoundsInParent(); |
- // Check if the |window|'s restored size is bigger than the working area |
- // This may happen if a window was resized to maximized bounds or if the |
- // display resolution changed while the window was maximized. |
- if (previous_state_type == WINDOW_STATE_TYPE_MAXIMIZED && |
- bounds_in_parent.width() >= work_area_in_parent.width() && |
- bounds_in_parent.height() >= work_area_in_parent.height()) { |
- bounds_in_parent = work_area_in_parent; |
- bounds_in_parent.Inset(kMaximizedWindowInset, kMaximizedWindowInset, |
- kMaximizedWindowInset, kMaximizedWindowInset); |
- } |
- } else { |
- bounds_in_parent = window->GetBounds(); |
- } |
- // Make sure that part of the window is always visible. |
- if (!window_state->is_dragged()) { |
- // Avoid doing this while the window is being dragged as its root |
- // window hasn't been updated yet in the case of dragging to another |
- // display. crbug.com/666836. |
- wm::AdjustBoundsToEnsureMinimumWindowVisibility(work_area_in_parent, |
- &bounds_in_parent); |
- } |
- break; |
- } |
- case WINDOW_STATE_TYPE_MAXIMIZED: |
- bounds_in_parent = GetMaximizedWindowBoundsInParent(window); |
- break; |
- |
- case WINDOW_STATE_TYPE_FULLSCREEN: |
- case WINDOW_STATE_TYPE_PINNED: |
- case WINDOW_STATE_TYPE_TRUSTED_PINNED: |
- bounds_in_parent = GetDisplayBoundsInParent(window); |
- break; |
- |
- case WINDOW_STATE_TYPE_DOCKED_MINIMIZED: |
- case WINDOW_STATE_TYPE_MINIMIZED: |
- break; |
- case WINDOW_STATE_TYPE_INACTIVE: |
- case WINDOW_STATE_TYPE_END: |
- case WINDOW_STATE_TYPE_AUTO_POSITIONED: |
- return; |
- } |
- |
- if (!window_state->IsMinimized()) { |
- if (IsMinimizedWindowState(previous_state_type) || |
- window_state->IsFullscreen() || window_state->IsPinned()) { |
- window_state->SetBoundsDirect(bounds_in_parent); |
- } else if (window_state->IsMaximized() || |
- IsMaximizedOrFullscreenOrPinnedWindowStateType( |
- previous_state_type)) { |
- window_state->SetBoundsDirectCrossFade(bounds_in_parent); |
- } else if (window_state->is_dragged()) { |
- // SetBoundsDirectAnimated does not work when the window gets reparented. |
- // TODO(oshima): Consider fixing it and reenable the animation. |
- window_state->SetBoundsDirect(bounds_in_parent); |
- } else { |
- window_state->SetBoundsDirectAnimated(bounds_in_parent); |
- } |
- } |
- |
- if (window_state->IsMinimized()) { |
- // Save the previous show state so that we can correctly restore it after |
- // exiting the minimized mode. |
- window->SetPreMinimizedShowState(ToWindowShowState(previous_state_type)); |
- window->SetVisibilityAnimationType( |
- WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE); |
- |
- // Hide the window. |
- window->Hide(); |
- // Activate another window. |
- if (window_state->IsActive()) |
- window_state->Deactivate(); |
- } else if ((window->GetTargetVisibility() || |
- IsMinimizedWindowState(previous_state_type)) && |
- !window->GetLayerVisible()) { |
- // The layer may be hidden if the window was previously minimized. Make |
- // sure it's visible. |
- window->Show(); |
- if (IsMinimizedWindowState(previous_state_type) && |
- !window_state->IsMaximizedOrFullscreenOrPinned()) { |
- window_state->set_unminimize_to_restore_bounds(false); |
- } |
- } |
-} |
- |
-// static |
-void DefaultState::CenterWindow(WindowState* window_state) { |
- if (!window_state->IsNormalOrSnapped()) |
- return; |
- WmWindow* window = window_state->window(); |
- if (window_state->IsSnapped()) { |
- gfx::Rect center_in_screen = window->GetDisplayNearestWindow().work_area(); |
- gfx::Size size = window_state->HasRestoreBounds() |
- ? window_state->GetRestoreBoundsInScreen().size() |
- : window->GetBounds().size(); |
- center_in_screen.ClampToCenteredSize(size); |
- window_state->SetRestoreBoundsInScreen(center_in_screen); |
- window_state->Restore(); |
- } else { |
- gfx::Rect center_in_parent = GetDisplayWorkAreaBoundsInParent(window); |
- center_in_parent.ClampToCenteredSize(window->GetBounds().size()); |
- window_state->SetBoundsDirectAnimated(center_in_parent); |
- } |
- // Centering window is treated as if a user moved and resized the window. |
- window_state->set_bounds_changed_by_user(true); |
-} |
- |
-} // namespace wm |
-} // namespace ash |