Index: ash/wm/default_state.cc |
diff --git a/ash/wm/default_state.cc b/ash/wm/default_state.cc |
index 3787f7f30f46aeaed6eb4579146baa5a6fe73e5c..382ede257f7fde97eb9452eea838805ece1aa09f 100644 |
--- a/ash/wm/default_state.cc |
+++ b/ash/wm/default_state.cc |
@@ -4,10 +4,16 @@ |
#include "ash/wm/default_state.h" |
+#include "ash/display/display_controller.h" |
#include "ash/screen_util.h" |
#include "ash/shell.h" |
#include "ash/wm/coordinate_conversion.h" |
+#include "ash/wm/window_animations.h" |
#include "ash/wm/window_state.h" |
+#include "ash/wm/window_state_delegate.h" |
+#include "ash/wm/window_util.h" |
+#include "ash/wm/workspace/workspace_window_resizer.h" |
+#include "ui/aura/client/aura_constants.h" |
#include "ui/aura/window.h" |
#include "ui/aura/window_delegate.h" |
#include "ui/gfx/display.h" |
@@ -15,12 +21,104 @@ |
namespace ash { |
namespace wm { |
+namespace { |
+ |
+gfx::Rect BoundsWithScreenEdgeVisible( |
+ aura::Window* window, |
+ const gfx::Rect& restore_bounds) { |
+ gfx::Rect max_bounds = |
+ ash::ScreenUtil::GetMaximizedWindowBoundsInParent(window); |
+ // If the restore_bounds are more than 1 grid step away from the size the |
+ // window would be when maximized, inset it. |
+ max_bounds.Inset(ash::internal::WorkspaceWindowResizer::kScreenEdgeInset, |
+ ash::internal::WorkspaceWindowResizer::kScreenEdgeInset); |
+ if (restore_bounds.Contains(max_bounds)) |
+ return max_bounds; |
+ return restore_bounds; |
+} |
+ |
+void MoveToDisplayForRestore(wm::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 = Shell::GetScreen()->GetDisplayNearestWindow( |
+ window_state->window()).bounds(); |
+ |
+ if (!display_area.Intersects(restore_bounds)) { |
+ const gfx::Display& display = |
+ Shell::GetScreen()->GetDisplayMatching(restore_bounds); |
+ DisplayController* display_controller = |
+ Shell::GetInstance()->display_controller(); |
+ aura::Window* new_root = |
+ display_controller->GetRootWindowForDisplayId(display.id()); |
+ if (new_root != window_state->window()->GetRootWindow()) { |
+ aura::Window* new_container = |
+ Shell::GetContainer(new_root, window_state->window()->parent()->id()); |
+ new_container->AddChild(window_state->window()); |
+ } |
+ } |
+} |
+ |
+} // namespace; |
DefaultState::DefaultState() {} |
DefaultState::~DefaultState() {} |
void DefaultState::OnWMEvent(WindowState* window_state, |
WMEvent event) { |
+ if (ProcessCompoundEvents(window_state, event)) |
+ return; |
+ |
+ WindowShowType next_show_type; |
+ |
+ switch (event) { |
+ case NORMAL: |
+ next_show_type = SHOW_TYPE_NORMAL; |
+ break; |
+ case MAXIMIZE: |
+ next_show_type = SHOW_TYPE_MAXIMIZED; |
+ break; |
+ case MINIMIZE: |
+ next_show_type = SHOW_TYPE_MINIMIZED; |
+ break; |
+ case FULLSCREEN: |
+ next_show_type = SHOW_TYPE_FULLSCREEN; |
+ break; |
+ case SNAP_LEFT: |
+ next_show_type = SHOW_TYPE_LEFT_SNAPPED; |
+ break; |
+ case SNAP_RIGHT: |
+ next_show_type = SHOW_TYPE_RIGHT_SNAPPED; |
+ break; |
+ case TOGGLE_MAXIMIZE_CAPTION: |
+ case TOGGLE_MAXIMIZE: |
+ case TOGGLE_VERTICAL_MAXIMIZE: |
+ case TOGGLE_HORIZONTAL_MAXIMIZE: |
+ case TOGGLE_FULLSCREEN: |
+ NOTREACHED() << "Compound event should not reach here:" << event; |
+ return; |
+ } |
+ |
+ WindowShowType current = window_state->window_show_type(); |
+ if (current != next_show_type) { |
+ window_state->UpdateWindowShowType(next_show_type); |
+ window_state->NotifyPreShowTypeChange(current); |
+ if (!window_state->IsDocked()) |
+ UpdateBoundsFromShowType(window_state, current); |
+ window_state->NotifyPostShowTypeChange(current); |
+ } |
+}; |
+ |
+// static |
+bool DefaultState::ProcessCompoundEvents(WindowState* window_state, |
+ WMEvent event) { |
aura::Window* window = window_state->window(); |
switch (event) { |
@@ -34,8 +132,7 @@ void DefaultState::OnWMEvent(WindowState* window_state, |
if (window_state->CanMaximize()) |
window_state->Maximize(); |
} |
- break; |
- |
+ return true; |
case TOGGLE_MAXIMIZE: |
if (window_state->IsFullscreen()) |
window_state->ToggleFullscreen(); |
@@ -43,8 +140,7 @@ void DefaultState::OnWMEvent(WindowState* window_state, |
window_state->Restore(); |
else if (window_state->CanMaximize()) |
window_state->Maximize(); |
- break; |
- |
+ return true; |
case TOGGLE_VERTICAL_MAXIMIZE: { |
gfx::Rect work_area = |
ScreenUtil::GetDisplayWorkAreaBoundsInParent(window); |
@@ -56,7 +152,7 @@ void DefaultState::OnWMEvent(WindowState* window_state, |
// restored bounds looks weird. |
if (window->delegate()->GetMaximumSize().height() != 0 || |
!window_state->IsNormalShowType()) { |
- return; |
+ return true; |
} |
if (window_state->HasRestoreBounds() && |
(window->bounds().height() == work_area.height() && |
@@ -69,20 +165,18 @@ void DefaultState::OnWMEvent(WindowState* window_state, |
window->bounds().width(), |
work_area.height())); |
} |
- break; |
+ return true; |
} |
case TOGGLE_HORIZONTAL_MAXIMIZE: { |
// Maximize horizontally if: |
// - The window does not have a max width defined. |
// - The window is snapped or has the normal show type. |
if (window->delegate()->GetMaximumSize().width() != 0) |
- return; |
+ return true; |
if (!window_state->IsNormalShowType() && !window_state->IsSnapped()) |
- return; |
- |
+ return true; |
gfx::Rect work_area = |
ScreenUtil::GetDisplayWorkAreaBoundsInParent(window); |
- |
if (window_state->IsNormalShowType() && |
window_state->HasRestoreBounds() && |
(window->bounds().width() == work_area.width() && |
@@ -107,9 +201,157 @@ void DefaultState::OnWMEvent(WindowState* window_state, |
window_state->SetRestoreBoundsInParent(restore_bounds); |
window->SetBounds(new_bounds); |
} |
+ return true; |
+ } |
+ case TOGGLE_FULLSCREEN: { |
+ // Window which cannot be maximized should not be fullscreened. |
+ // It can, however, be restored if it was fullscreened. |
+ bool is_fullscreen = window_state->IsFullscreen(); |
+ if (!is_fullscreen && !window_state->CanMaximize()) |
+ return true; |
+ if (window_state->delegate() && |
+ window_state->delegate()->ToggleFullscreen(window_state)) { |
+ return true; |
+ } |
+ if (is_fullscreen) { |
+ window_state->Restore(); |
+ } else { |
+ // |
+ window_state->window()->SetProperty(aura::client::kShowStateKey, |
+ ui::SHOW_STATE_FULLSCREEN); |
+ } |
+ return true; |
} |
+ case NORMAL: |
+ case MAXIMIZE: |
+ case MINIMIZE: |
+ case FULLSCREEN: |
+ case SNAP_LEFT: |
+ case SNAP_RIGHT: |
+ break; |
} |
-}; |
+ return false; |
+} |
+ |
+// static |
+void DefaultState::UpdateBoundsFromShowType(wm::WindowState* window_state, |
oshima
2014/02/11 21:49:35
The code that updates window state in OnWindowShow
|
+ wm::WindowShowType old_show_type) { |
+ if (old_show_type != wm::SHOW_TYPE_MINIMIZED && |
+ !window_state->HasRestoreBounds() && |
+ window_state->IsMaximizedOrFullscreen() && |
+ !wm::IsMaximizedOrFullscreenWindowShowType(old_show_type)) { |
+ 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; |
+ if (old_show_type == wm::SHOW_TYPE_MINIMIZED && |
+ window_state->IsNormalShowState() && |
+ window_state->HasRestoreBounds() && |
+ !window_state->unminimize_to_restore_bounds()) { |
+ restore = window_state->GetRestoreBoundsInScreen(); |
+ window_state->SaveCurrentBoundsForRestore(); |
+ } |
+ |
+ aura::Window* window = window_state->window(); |
+ if (window_state->IsMaximizedOrFullscreen()) |
+ MoveToDisplayForRestore(window_state); |
+ |
+ gfx::Rect work_area_in_parent = |
+ ScreenUtil::GetDisplayWorkAreaBoundsInParent(window_state->window()); |
+ |
+ wm::WindowShowType show_type = window_state->window_show_type(); |
+ gfx::Rect bounds_in_parent; |
+ switch (show_type) { |
+ case wm::SHOW_TYPE_DEFAULT: |
+ case wm::SHOW_TYPE_NORMAL: |
+ case wm::SHOW_TYPE_LEFT_SNAPPED: |
+ case wm::SHOW_TYPE_RIGHT_SNAPPED: |
+ if (window_state->HasRestoreBounds()) |
+ bounds_in_parent = window_state->GetRestoreBoundsInParent(); |
+ else |
+ bounds_in_parent = window->bounds(); |
+ // Make sure that part of the window is always visible. |
+ wm::AdjustBoundsToEnsureMinimumWindowVisibility( |
+ work_area_in_parent, &bounds_in_parent); |
+ |
+ if (show_type == wm::SHOW_TYPE_LEFT_SNAPPED || |
+ show_type == wm::SHOW_TYPE_RIGHT_SNAPPED) { |
+ window_state->AdjustSnappedBounds(&bounds_in_parent); |
+ } else { |
+ bounds_in_parent = BoundsWithScreenEdgeVisible( |
+ window, |
+ bounds_in_parent); |
+ } |
+ break; |
+ |
+ case wm::SHOW_TYPE_MAXIMIZED: |
+ bounds_in_parent = ScreenUtil::GetMaximizedWindowBoundsInParent(window); |
+ break; |
+ |
+ case wm::SHOW_TYPE_FULLSCREEN: |
+ bounds_in_parent = ScreenUtil::GetDisplayBoundsInParent(window); |
+ break; |
+ |
+ case wm::SHOW_TYPE_MINIMIZED: |
+ break; |
+ case wm::SHOW_TYPE_INACTIVE: |
+ case wm::SHOW_TYPE_DETACHED: |
+ case wm::SHOW_TYPE_END: |
+ case wm::SHOW_TYPE_AUTO_POSITIONED: |
+ return; |
+ } |
+ |
+ if (show_type != wm::SHOW_TYPE_MINIMIZED) { |
+ if (old_show_type == wm::SHOW_TYPE_MINIMIZED || |
+ (window_state->IsFullscreen() && |
+ !window_state->animate_to_fullscreen())) { |
+ window_state->SetBoundsDirect(bounds_in_parent); |
+ } else if (window_state->IsMaximizedOrFullscreen() || |
+ IsMaximizedOrFullscreenWindowShowType(old_show_type)) { |
+ CrossFadeToBounds(window, bounds_in_parent); |
+ } else { |
+ window_state->SetBoundsDirectAnimated(bounds_in_parent); |
+ } |
+ } |
+ |
+ if (window_state->IsMinimized()) { |
+ if (old_show_type == wm::SHOW_TYPE_MINIMIZED) |
+ return; |
+ |
+ // Save the previous show state so that we can correctly restore it. |
+ window_state->window()->SetProperty(aura::client::kRestoreShowStateKey, |
+ wm::ToWindowShowState(old_show_type)); |
+ views::corewm::SetWindowVisibilityAnimationType( |
+ window_state->window(), WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE); |
+ |
+ // Hide the window. |
+ window_state->window()->Hide(); |
+ // Activate another window. |
+ if (window_state->IsActive()) |
+ window_state->Deactivate(); |
+ } else if ((window_state->window()->TargetVisibility() || |
+ old_show_type == wm::SHOW_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(); |
+ if (old_show_type == wm::SHOW_TYPE_MINIMIZED && |
+ !window_state->IsMaximizedOrFullscreen()) { |
+ window_state->set_unminimize_to_restore_bounds(false); |
+ } |
+ } |
+ |
+ if (window_state->IsNormalShowState()) |
+ window_state->ClearRestoreBounds(); |
+ |
+ // Set the restore rectangle to the previously set restore rectangle. |
+ if (!restore.IsEmpty()) |
+ window_state->SetRestoreBoundsInScreen(restore); |
+} |
} // namespace wm |
} // namespace ash |