Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ash/wm/workspace/auto_window_management.h" | |
| 6 | |
| 7 #include "ash/ash_switches.h" | |
| 8 #include "ash/shell.h" | |
| 9 #include "ash/wm/window_animations.h" | |
| 10 #include "ash/wm/window_util.h" | |
| 11 #include "base/command_line.h" | |
| 12 #include "ui/aura/window.h" | |
| 13 #include "ui/aura/client/aura_constants.h" | |
| 14 #include "ui/compositor/layer_animator.h" | |
| 15 #include "ui/compositor/scoped_layer_animation_settings.h" | |
| 16 #include "ui/gfx/screen.h" | |
| 17 | |
| 18 namespace ash { | |
| 19 namespace internal { | |
| 20 | |
| 21 namespace { | |
| 22 | |
| 23 // The time in milliseconds which should be used to visually move a window | |
| 24 // through an automatic "intelligent" window management option. | |
| 25 const int kWindowAutoMoveDurationMS = 125; | |
| 26 | |
| 27 // Check if the given |window| is marked to get managed. | |
| 28 bool WindowIsManaged(const aura::Window* window) { | |
| 29 return wm::IsWindowPositionManaged(window); | |
| 30 } | |
| 31 | |
| 32 // Check if a given |window| can be managed. This includes that it's state is | |
| 33 // not minimized/maximized/the user has changed it's size by hand already. | |
| 34 // It furthermore checks for the WindowIsManaged status. | |
| 35 bool WindowPositionCanBeManaged(const aura::Window* window) { | |
| 36 return (WindowIsManaged(window) && | |
| 37 !wm::IsWindowMinimized(window) && | |
| 38 !wm::IsWindowMaximized(window) && | |
| 39 !wm::HasUserChangedWindowPositionOrSize(window)); | |
| 40 } | |
| 41 | |
| 42 // Given a |window|, return the |work_area| of the desktop on which it is | |
| 43 // located as well as the only |other_window| which has an impact on the | |
| 44 // automated windows location management. If there is more then one windows, | |
|
sky
2012/10/22 16:40:50
windows -> window
Mr4D (OOO till 08-26)
2012/10/22 20:27:23
Done.
| |
| 45 // false is returned, but the |other_window| will be set to the first one | |
| 46 // found. | |
| 47 // If the return value is true a single window was found. | |
| 48 // Note: |work_area| is undefined if false is returned and |other_window| is | |
|
sky
2012/10/22 16:40:50
This code doesn't even use the work_area. Is there
Mr4D (OOO till 08-26)
2012/10/22 20:27:23
After the rest of the code got so drastically chan
| |
| 49 // NULL. | |
| 50 bool GetOtherVisibleAndManageableWindow(const aura::Window* window, | |
| 51 gfx::Rect* work_area, | |
| 52 aura::Window** other_window) { | |
| 53 *other_window = NULL; | |
| 54 // If the given window was not manageable, it cannot have caused a management | |
| 55 // operation earlier. | |
| 56 if (!WindowIsManaged(window)) | |
| 57 return false; | |
| 58 | |
| 59 // Get our work area. | |
| 60 *work_area = gfx::Rect(window->parent()->bounds().size()); | |
| 61 work_area->Inset(Shell::GetScreen()->GetDisplayMatching( | |
| 62 *work_area).GetWorkAreaInsets()); | |
| 63 | |
| 64 const aura::Window::Windows& windows = window->parent()->children(); | |
| 65 // Find a single open managed window. | |
| 66 for (size_t i = 0; i < windows.size(); i++) { | |
| 67 aura::Window* iterated_window = windows[i]; | |
| 68 if (window != iterated_window && | |
| 69 iterated_window->type() == aura::client::WINDOW_TYPE_NORMAL && | |
| 70 iterated_window->TargetVisibility() && | |
| 71 WindowIsManaged(iterated_window)) { | |
| 72 // Bail if we find a second usable window. | |
| 73 if (*other_window) | |
| 74 return false; | |
| 75 *other_window = iterated_window; | |
| 76 } | |
| 77 } | |
| 78 return *other_window != NULL; | |
| 79 } | |
| 80 | |
| 81 // Move the given |bounds| on the available |parent_width| to the | |
| 82 // direction. If |move_right| is true, the rectangle gets moved to the right | |
| 83 // corner, otherwise to the left one. | |
| 84 bool MoveRectToOneSide(int parent_width, bool move_right, gfx::Rect* bounds) { | |
| 85 if (move_right) { | |
| 86 if (parent_width > bounds->right()) { | |
| 87 bounds->set_x(parent_width - bounds->width()); | |
| 88 return true; | |
| 89 } | |
| 90 } else { | |
| 91 if (0 < bounds->x()) { | |
| 92 bounds->set_x(0); | |
| 93 return true; | |
| 94 } | |
| 95 } | |
| 96 return false; | |
| 97 } | |
| 98 | |
| 99 ui::ScopedLayerAnimationSettings* CreateAnimationSettings( | |
| 100 aura::Window* window) { | |
| 101 if (!window->GetProperty(aura::client::kAnimationsDisabledKey) && | |
| 102 !CommandLine::ForCurrentProcess()->HasSwitch( | |
| 103 ash::switches::kAshWindowAnimationsDisabled)) { | |
| 104 ui::LayerAnimator* animator = window->layer()->GetAnimator(); | |
| 105 return new ui::ScopedLayerAnimationSettings(animator); | |
| 106 } | |
| 107 return NULL; | |
| 108 } | |
| 109 | |
| 110 } // namespace | |
| 111 | |
| 112 void RearrangeVisibleWindowOnHideOrRemove(const aura::Window* removed_window) { | |
| 113 // Early bail out if the window isn't visible of the feature is unwanted. | |
| 114 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
| 115 switches::kAshDisableAutoWindowPlacement)) | |
| 116 return; | |
| 117 // Find a single open browser window. | |
| 118 aura::Window* other_shown_window = NULL; | |
| 119 gfx::Rect work_area; | |
| 120 if (!GetOtherVisibleAndManageableWindow(removed_window, | |
| 121 &work_area, | |
| 122 &other_shown_window)) | |
| 123 return; | |
|
sky
2012/10/22 16:40:50
nit: Move !WindowPositionCanBeManaged here too so
Mr4D (OOO till 08-26)
2012/10/22 20:27:23
Done.
| |
| 124 | |
| 125 if (WindowPositionCanBeManaged(other_shown_window)) { | |
| 126 // Center the window (only in x). | |
| 127 gfx::Rect bounds = other_shown_window->bounds(); | |
| 128 bounds.set_x((work_area.width() - bounds.width()) / 2); | |
| 129 if (bounds != other_shown_window->GetTargetBounds()) { | |
| 130 ui::ScopedLayerAnimationSettings* settings = CreateAnimationSettings( | |
| 131 other_shown_window); | |
| 132 settings->SetTransitionDuration( | |
|
sky
2012/10/22 16:40:50
You need a null check here for settings. Or move S
Mr4D (OOO till 08-26)
2012/10/22 20:27:23
You know that this contradicts somehow your previo
sky
2012/10/22 21:26:21
This suggestion:
ui::ScopedLayerAnimationSettings*
| |
| 133 base::TimeDelta::FromMilliseconds(kWindowAutoMoveDurationMS)); | |
| 134 other_shown_window->SetBounds(bounds); | |
| 135 } | |
| 136 } | |
| 137 } | |
| 138 | |
| 139 void RearrangeVisibleWindowOnShow(aura::Window* added_window) { | |
| 140 // Early bail out if the window isn't visible of the feature is unwanted. | |
|
sky
2012/10/22 16:40:50
of -> or
unwanted -> disabled
But this descriptio
Mr4D (OOO till 08-26)
2012/10/22 20:27:23
Done.
| |
| 141 if (!added_window->TargetVisibility() || | |
| 142 CommandLine::ForCurrentProcess()->HasSwitch( | |
| 143 switches::kAshDisableAutoWindowPlacement)) | |
| 144 return; | |
| 145 // Find a single open managed window. | |
| 146 aura::Window* other_shown_window = NULL; | |
| 147 gfx::Rect work_area; | |
| 148 if (!GetOtherVisibleAndManageableWindow(added_window, | |
| 149 &work_area, | |
| 150 &other_shown_window)) { | |
| 151 // It could be that this window is the first window joining the workspace. | |
| 152 if (!WindowPositionCanBeManaged(added_window) || other_shown_window) | |
| 153 return; | |
| 154 // If so we have to make sure it is centered. | |
| 155 gfx::Rect bounds = added_window->bounds(); | |
| 156 bounds.set_x((work_area.width() - bounds.width()) / 2); | |
| 157 added_window->SetBounds(bounds); | |
| 158 return; | |
| 159 } | |
| 160 | |
| 161 // When going from one to two windows both windows loose their "positioned | |
| 162 // by user" flags. | |
| 163 ash::wm::SetUserHasChangedWindowPositionOrSize(added_window, false); | |
| 164 ash::wm::SetUserHasChangedWindowPositionOrSize(other_shown_window, false); | |
| 165 | |
| 166 if (WindowPositionCanBeManaged(other_shown_window)) { | |
| 167 // Push away the other window. | |
| 168 gfx::Rect other_bounds = other_shown_window->bounds(); | |
| 169 bool move_right = other_bounds.CenterPoint().x() < work_area.width() / 2; | |
| 170 if (MoveRectToOneSide(work_area.width(), move_right, &other_bounds)) { | |
| 171 if (other_bounds != other_shown_window->GetTargetBounds()) { | |
| 172 ui::ScopedLayerAnimationSettings* settings = CreateAnimationSettings( | |
| 173 other_shown_window); | |
| 174 settings->SetTransitionDuration( | |
| 175 base::TimeDelta::FromMilliseconds(kWindowAutoMoveDurationMS)); | |
| 176 other_shown_window->SetBounds(other_bounds); | |
| 177 } | |
| 178 } | |
| 179 // Push the new window also to the opposite location (if needed). | |
| 180 // Since it is just coming into view, we do not need to animate it. | |
| 181 gfx::Rect added_bounds = added_window->bounds(); | |
| 182 if (MoveRectToOneSide(work_area.width(), !move_right, &added_bounds)) | |
| 183 added_window->SetBounds(added_bounds); | |
| 184 } | |
| 185 } | |
| 186 | |
| 187 } // namespace internal | |
| 188 } // namespace ash | |
| 189 | |
| OLD | NEW |