• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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/window_state.h"
6 
7 #include "ash/ash_switches.h"
8 #include "ash/root_window_controller.h"
9 #include "ash/screen_ash.h"
10 #include "ash/shell_window_ids.h"
11 #include "ash/wm/window_properties.h"
12 #include "ash/wm/window_state_delegate.h"
13 #include "ash/wm/window_state_observer.h"
14 #include "ash/wm/window_util.h"
15 #include "ash/wm/wm_types.h"
16 #include "base/auto_reset.h"
17 #include "base/command_line.h"
18 #include "ui/aura/client/aura_constants.h"
19 #include "ui/aura/window.h"
20 #include "ui/aura/window_delegate.h"
21 #include "ui/gfx/display.h"
22 #include "ui/views/corewm/window_util.h"
23 
24 namespace ash {
25 namespace wm {
26 
27 // static
IsMaximizedOrFullscreenState(ui::WindowShowState show_state)28 bool WindowState::IsMaximizedOrFullscreenState(ui::WindowShowState show_state) {
29   return show_state == ui::SHOW_STATE_FULLSCREEN ||
30       show_state == ui::SHOW_STATE_MAXIMIZED;
31 }
32 
WindowState(aura::Window * window)33 WindowState::WindowState(aura::Window* window)
34     : window_(window),
35       window_position_managed_(false),
36       bounds_changed_by_user_(false),
37       panel_attached_(true),
38       continue_drag_after_reparent_(false),
39       ignored_by_shelf_(false),
40       can_consume_system_keys_(false),
41       top_row_keys_are_function_keys_(false),
42       window_resizer_(NULL),
43       always_restores_to_restore_bounds_(false),
44       hide_shelf_when_fullscreen_(true),
45       animate_to_fullscreen_(true),
46       minimum_visibility_(false),
47       in_set_window_show_type_(false),
48       window_show_type_(ToWindowShowType(GetShowState())) {
49   window_->AddObserver(this);
50 
51 #if defined(OS_CHROMEOS)
52   // NOTE(pkotwicz): Animating to immersive fullscreen does not look good. When
53   // the kAshEnableImmersiveFullscreenForAllWindows flag is set most windows
54   // can be put into immersive fullscreen. It is not worth the added complexity
55   // to only animate to fullscreen if the window is put into immersive
56   // fullscreen.
57   animate_to_fullscreen_ = !CommandLine::ForCurrentProcess()->HasSwitch(
58       switches::kAshEnableImmersiveFullscreenForAllWindows);
59 #endif
60 }
61 
~WindowState()62 WindowState::~WindowState() {
63 }
64 
HasDelegate() const65 bool WindowState::HasDelegate() const {
66   return delegate_;
67 }
68 
SetDelegate(scoped_ptr<WindowStateDelegate> delegate)69 void WindowState::SetDelegate(scoped_ptr<WindowStateDelegate> delegate) {
70   DCHECK(!delegate_.get());
71   delegate_ = delegate.Pass();
72 }
73 
GetShowState() const74 ui::WindowShowState WindowState::GetShowState() const {
75   return window_->GetProperty(aura::client::kShowStateKey);
76 }
77 
IsMinimized() const78 bool WindowState::IsMinimized() const {
79   return GetShowState() == ui::SHOW_STATE_MINIMIZED;
80 }
81 
IsMaximized() const82 bool WindowState::IsMaximized() const {
83   return GetShowState() == ui::SHOW_STATE_MAXIMIZED;
84 }
85 
IsFullscreen() const86 bool WindowState::IsFullscreen() const {
87   return GetShowState() == ui::SHOW_STATE_FULLSCREEN;
88 }
89 
IsMaximizedOrFullscreen() const90 bool WindowState::IsMaximizedOrFullscreen() const {
91   return IsMaximizedOrFullscreenState(GetShowState());
92 }
93 
IsNormalShowState() const94 bool WindowState::IsNormalShowState() const {
95   ui::WindowShowState state = window_->GetProperty(aura::client::kShowStateKey);
96   return state == ui::SHOW_STATE_NORMAL || state == ui::SHOW_STATE_DEFAULT;
97 }
98 
IsActive() const99 bool WindowState::IsActive() const {
100   return IsActiveWindow(window_);
101 }
102 
IsDocked() const103 bool WindowState::IsDocked() const {
104   return window_->parent() &&
105       window_->parent()->id() == internal::kShellWindowId_DockedContainer;
106 }
107 
IsSnapped() const108 bool WindowState::IsSnapped() const {
109   return window_show_type_ == SHOW_TYPE_LEFT_SNAPPED ||
110       window_show_type_ == SHOW_TYPE_RIGHT_SNAPPED;
111 }
112 
CanMaximize() const113 bool WindowState::CanMaximize() const {
114   return window_->GetProperty(aura::client::kCanMaximizeKey);
115 }
116 
CanMinimize() const117 bool WindowState::CanMinimize() const {
118   internal::RootWindowController* controller =
119       internal::RootWindowController::ForWindow(window_);
120   if (!controller)
121     return false;
122   aura::Window* lockscreen = controller->GetContainer(
123       internal::kShellWindowId_LockScreenContainersContainer);
124   if (lockscreen->Contains(window_))
125     return false;
126 
127   return true;
128 }
129 
CanResize() const130 bool WindowState::CanResize() const {
131   return window_->GetProperty(aura::client::kCanResizeKey);
132 }
133 
CanActivate() const134 bool WindowState::CanActivate() const {
135   return views::corewm::CanActivateWindow(window_);
136 }
137 
CanSnap() const138 bool WindowState::CanSnap() const {
139   if (!CanResize() ||
140       window_->type() == aura::client::WINDOW_TYPE_PANEL ||
141       window_->transient_parent())
142     return false;
143   // If a window has a maximum size defined, snapping may make it too big.
144   return window_->delegate() ? window_->delegate()->GetMaximumSize().IsEmpty() :
145                               true;
146 }
147 
HasRestoreBounds() const148 bool WindowState::HasRestoreBounds() const {
149   return window_->GetProperty(aura::client::kRestoreBoundsKey) != NULL;
150 }
151 
Maximize()152 void WindowState::Maximize() {
153   window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
154 }
155 
SnapLeft(const gfx::Rect & bounds)156 void WindowState::SnapLeft(const gfx::Rect& bounds) {
157   SnapWindow(SHOW_TYPE_LEFT_SNAPPED, bounds);
158 }
159 
SnapRight(const gfx::Rect & bounds)160 void WindowState::SnapRight(const gfx::Rect& bounds) {
161   SnapWindow(SHOW_TYPE_RIGHT_SNAPPED, bounds);
162 }
163 
Minimize()164 void WindowState::Minimize() {
165   window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
166 }
167 
Unminimize()168 void WindowState::Unminimize() {
169   window_->SetProperty(
170       aura::client::kShowStateKey,
171       window_->GetProperty(aura::client::kRestoreShowStateKey));
172   window_->ClearProperty(aura::client::kRestoreShowStateKey);
173 }
174 
Activate()175 void WindowState::Activate() {
176   ActivateWindow(window_);
177 }
178 
Deactivate()179 void WindowState::Deactivate() {
180   DeactivateWindow(window_);
181 }
182 
Restore()183 void WindowState::Restore() {
184   window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
185 }
186 
ToggleMaximized()187 void WindowState::ToggleMaximized() {
188   if (IsMaximized())
189     Restore();
190   else if (CanMaximize())
191     Maximize();
192 }
193 
ToggleFullscreen()194 void WindowState::ToggleFullscreen() {
195   // Window which cannot be maximized should not be fullscreened.
196   // It can, however, be restored if it was fullscreened.
197   bool is_fullscreen = IsFullscreen();
198   if (!is_fullscreen && !CanMaximize())
199     return;
200   if (delegate_ && delegate_->ToggleFullscreen(this))
201     return;
202   if (is_fullscreen) {
203     Restore();
204   } else {
205     window_->SetProperty(aura::client::kShowStateKey,
206                          ui::SHOW_STATE_FULLSCREEN);
207   }
208 }
209 
SetBoundsInScreen(const gfx::Rect & bounds_in_screen)210 void WindowState::SetBoundsInScreen(
211     const gfx::Rect& bounds_in_screen) {
212   gfx::Rect bounds_in_parent =
213       ScreenAsh::ConvertRectFromScreen(window_->parent(),
214                                        bounds_in_screen);
215   window_->SetBounds(bounds_in_parent);
216 }
217 
SaveCurrentBoundsForRestore()218 void WindowState::SaveCurrentBoundsForRestore() {
219   gfx::Rect bounds_in_screen =
220       ScreenAsh::ConvertRectToScreen(window_->parent(),
221                                      window_->bounds());
222   SetRestoreBoundsInScreen(bounds_in_screen);
223 }
224 
GetRestoreBoundsInScreen() const225 gfx::Rect WindowState::GetRestoreBoundsInScreen() const {
226   return *window_->GetProperty(aura::client::kRestoreBoundsKey);
227 }
228 
GetRestoreBoundsInParent() const229 gfx::Rect WindowState::GetRestoreBoundsInParent() const {
230   return ScreenAsh::ConvertRectFromScreen(window_->parent(),
231                                           GetRestoreBoundsInScreen());
232 }
233 
SetRestoreBoundsInScreen(const gfx::Rect & bounds)234 void WindowState::SetRestoreBoundsInScreen(const gfx::Rect& bounds) {
235   window_->SetProperty(aura::client::kRestoreBoundsKey, new gfx::Rect(bounds));
236 }
237 
SetRestoreBoundsInParent(const gfx::Rect & bounds)238 void WindowState::SetRestoreBoundsInParent(const gfx::Rect& bounds) {
239   SetRestoreBoundsInScreen(
240       ScreenAsh::ConvertRectToScreen(window_->parent(), bounds));
241 }
242 
ClearRestoreBounds()243 void WindowState::ClearRestoreBounds() {
244   window_->ClearProperty(aura::client::kRestoreBoundsKey);
245 }
246 
SetPreAutoManageWindowBounds(const gfx::Rect & bounds)247 void WindowState::SetPreAutoManageWindowBounds(
248     const gfx::Rect& bounds) {
249   pre_auto_manage_window_bounds_.reset(new gfx::Rect(bounds));
250 }
251 
AddObserver(WindowStateObserver * observer)252 void WindowState::AddObserver(WindowStateObserver* observer) {
253   observer_list_.AddObserver(observer);
254 }
255 
RemoveObserver(WindowStateObserver * observer)256 void WindowState::RemoveObserver(WindowStateObserver* observer) {
257   observer_list_.RemoveObserver(observer);
258 }
259 
OnWindowPropertyChanged(aura::Window * window,const void * key,intptr_t old)260 void WindowState::OnWindowPropertyChanged(aura::Window* window,
261                                           const void* key,
262                                           intptr_t old) {
263   DCHECK_EQ(window, window_);
264   if (key == aura::client::kShowStateKey)
265     SetWindowShowType(ToWindowShowType(GetShowState()));
266 }
267 
SnapWindow(WindowShowType left_or_right,const gfx::Rect & bounds)268 void WindowState::SnapWindow(WindowShowType left_or_right,
269                              const gfx::Rect& bounds) {
270   if (window_show_type_ == left_or_right) {
271     window_->SetBounds(bounds);
272     return;
273   }
274 
275   // Compute the bounds that the window will restore to. If the window does not
276   // already have restore bounds, it will be restored (when un-snapped) to the
277   // last bounds that it had before getting snapped.
278   gfx::Rect restore_bounds_in_screen(HasRestoreBounds() ?
279       GetRestoreBoundsInScreen() : window_->GetBoundsInScreen());
280   // Set the window's restore bounds so that WorkspaceLayoutManager knows
281   // which width to use when the snapped window is moved to the edge.
282   SetRestoreBoundsInParent(bounds);
283 
284   bool was_maximized = IsMaximizedOrFullscreen();
285   // Before we can set the bounds we need to restore the window.
286   // Restoring the window will set the window to its restored bounds set above.
287   // Restore will cause OnWindowPropertyChanged() so it needs to be done
288   // before notifying that the WindowShowType has changed to |left_or_right|.
289   if (was_maximized)
290     Restore();
291   DCHECK(left_or_right == SHOW_TYPE_LEFT_SNAPPED ||
292          left_or_right == SHOW_TYPE_RIGHT_SNAPPED);
293   SetWindowShowType(left_or_right);
294   // TODO(varkha): Ideally the bounds should be changed in a LayoutManager upon
295   // observing the WindowShowType change.
296   // If the window is a child of kShellWindowId_DockedContainer such as during
297   // a drag, the window's bounds are not set in
298   // WorkspaceLayoutManager::OnWindowShowTypeChanged(). Set them here. Skip
299   // setting the bounds otherwise to avoid stopping the slide animation which
300   // was started as a result of OnWindowShowTypeChanged().
301   if (IsDocked())
302     window_->SetBounds(bounds);
303   SetRestoreBoundsInScreen(restore_bounds_in_screen);
304 }
305 
SetWindowShowType(WindowShowType new_window_show_type)306 void WindowState::SetWindowShowType(WindowShowType new_window_show_type) {
307   if (in_set_window_show_type_)
308     return;
309   base::AutoReset<bool> resetter(&in_set_window_show_type_, true);
310 
311   ui::WindowShowState new_window_state =
312       ToWindowShowState(new_window_show_type);
313   if (new_window_state != GetShowState())
314     window_->SetProperty(aura::client::kShowStateKey, new_window_state);
315   WindowShowType old_window_show_type = window_show_type_;
316   window_show_type_ = new_window_show_type;
317   if (old_window_show_type != window_show_type_) {
318     FOR_EACH_OBSERVER(WindowStateObserver, observer_list_,
319                       OnWindowShowTypeChanged(this, old_window_show_type));
320   }
321 }
322 
GetActiveWindowState()323 WindowState* GetActiveWindowState() {
324   aura::Window* active = GetActiveWindow();
325   return active ? GetWindowState(active) : NULL;
326 }
327 
GetWindowState(aura::Window * window)328 WindowState* GetWindowState(aura::Window* window) {
329   if (!window)
330     return NULL;
331   WindowState* settings = window->GetProperty(internal::kWindowStateKey);
332   if(!settings) {
333     settings = new WindowState(window);
334     window->SetProperty(internal::kWindowStateKey, settings);
335   }
336   return settings;
337 }
338 
GetWindowState(const aura::Window * window)339 const WindowState* GetWindowState(const aura::Window* window) {
340   return GetWindowState(const_cast<aura::Window*>(window));
341 }
342 
343 }  // namespace wm
344 }  // namespace ash
345