OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/views/frame/immersive_mode_controller_ash.h" | 5 #include "chrome/browser/ui/views/frame/immersive_mode_controller_ash.h" |
6 | 6 |
7 #include "ash/ash_switches.h" | 7 #include "ash/ash_switches.h" |
8 #include "ash/shell.h" | 8 #include "ash/shell.h" |
9 #include "ash/wm/window_properties.h" | 9 #include "ash/wm/window_properties.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 27 matching lines...) Expand all Loading... | |
38 // few pixels before the view goes completely off the screen, which reduces | 38 // few pixels before the view goes completely off the screen, which reduces |
39 // the visual "pop" as the 2-pixel tall immersive-style tabs become visible. | 39 // the visual "pop" as the 2-pixel tall immersive-style tabs become visible. |
40 const int kAnimationOffsetY = 3; | 40 const int kAnimationOffsetY = 3; |
41 | 41 |
42 // Duration for the reveal show/hide slide animation. The slower duration is | 42 // Duration for the reveal show/hide slide animation. The slower duration is |
43 // used for the initial slide out to give the user more change to see what | 43 // used for the initial slide out to give the user more change to see what |
44 // happened. | 44 // happened. |
45 const int kRevealSlowAnimationDurationMs = 400; | 45 const int kRevealSlowAnimationDurationMs = 400; |
46 const int kRevealFastAnimationDurationMs = 200; | 46 const int kRevealFastAnimationDurationMs = 200; |
47 | 47 |
48 // If |hovered| is true, moves the mouse above |view|. Moves it outside of | |
49 // |view| otherwise. | |
50 // Should not be called outside of tests. | |
51 void MoveMouse(views::View* view, bool hovered) { | |
52 gfx::Point cursor_pos; | |
53 if (!hovered) { | |
54 int bottom_edge = view->bounds().bottom(); | |
55 cursor_pos = gfx::Point(0, bottom_edge + 100); | |
56 } | |
57 views::View::ConvertPointToScreen(view, &cursor_pos); | |
58 aura::Env::GetInstance()->set_last_mouse_location(cursor_pos); | |
59 } | |
60 | |
48 // Returns true if the currently active window is a transient child of | 61 // Returns true if the currently active window is a transient child of |
49 // |toplevel|. | 62 // |toplevel|. |
50 bool IsActiveWindowTransientChildOf(gfx::NativeWindow toplevel) { | 63 bool IsActiveWindowTransientChildOf(aura::Window* toplevel) { |
51 aura::Window* active_window = aura::client::GetActivationClient( | 64 aura::Window* active_window = aura::client::GetActivationClient( |
52 toplevel->GetRootWindow())->GetActiveWindow(); | 65 toplevel->GetRootWindow())->GetActiveWindow(); |
53 | 66 |
54 if (!toplevel || !active_window) | 67 if (!toplevel || !active_window) |
55 return false; | 68 return false; |
56 | 69 |
57 for (aura::Window* window = active_window; window; | 70 for (aura::Window* window = active_window; window; |
58 window = window->transient_parent()) { | 71 window = window->transient_parent()) { |
59 if (window == toplevel) | 72 if (window == toplevel) |
60 return true; | 73 return true; |
(...skipping 16 matching lines...) Expand all Loading... | |
77 if (controller_) | 90 if (controller_) |
78 controller_->UnlockRevealedState(); | 91 controller_->UnlockRevealedState(); |
79 } | 92 } |
80 | 93 |
81 private: | 94 private: |
82 base::WeakPtr<ImmersiveModeControllerAsh> controller_; | 95 base::WeakPtr<ImmersiveModeControllerAsh> controller_; |
83 | 96 |
84 DISALLOW_COPY_AND_ASSIGN(RevealedLockAsh); | 97 DISALLOW_COPY_AND_ASSIGN(RevealedLockAsh); |
85 }; | 98 }; |
86 | 99 |
100 //////////////////////////////////////////////////////////////////////////////// | |
101 | |
102 // Manages widgets which should move in sync with the top-of-window views. | |
103 class AnchoredWidgetManager : public views::WidgetObserver { | |
104 public: | |
105 AnchoredWidgetManager(ImmersiveModeControllerAsh* controller, | |
106 BrowserView* browser_view); | |
107 virtual ~AnchoredWidgetManager(); | |
108 | |
109 // Anchors |widget| such that it stays |y_offset| below the top-of-window | |
110 // views. |widget| will be repositioned whenever the top-of-window views are | |
111 // animated (top-of-window views revealing / unrevealing) or the top-of-window | |
112 // bounds change (eg the bookmark bar is shown). | |
113 // If the top-of-window views are revealed (or become revealed), |widget| will | |
114 // keep the top-of-window views revealed till |widget| is hidden or | |
115 // RemoveAnchoredWidget() is called. | |
116 void AddAnchoredWidget(views::Widget* widget, int y_offset); | |
117 | |
118 // Stops managing |widget|'s y position. | |
119 // Closes the top-of-window views if no locks or other anchored widgets are | |
120 // keeping the top-of-window views revealed. | |
121 void RemoveAnchoredWidget(views::Widget* widget); | |
122 | |
123 // Adjusts the y positions of the anchored widgets for the new top container | |
124 // bounds. | |
125 void OnTopContainerBoundsChanged(); | |
126 | |
127 const std::set<views::Widget*>& visible_anchored_widgets() const { | |
128 return visible_; | |
129 } | |
130 private: | |
James Cook
2013/04/09 22:22:03
nit: blank line above private:
| |
131 // Updates |revealed_lock_| based on the visible anchored widgets. | |
132 void UpdateRevealedLock(); | |
133 | |
134 // Updates the y position of |widget| given |y_offset| and the top | |
135 // container's target bounds. | |
136 void UpdateWidgetBounds(views::Widget* widget, int y_offset); | |
137 | |
138 // views::WidgetObserver overrides: | |
139 virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE; | |
140 virtual void OnWidgetVisibilityChanged(views::Widget* widget, | |
141 bool visible) OVERRIDE; | |
142 | |
143 ImmersiveModeControllerAsh* controller_; | |
144 | |
145 BrowserView* browser_view_; | |
146 | |
147 // Mapping of anchored widgets to the y offset below the top-of-window views | |
148 // that they should be positioned at. | |
149 std::map<views::Widget*, int> widgets_; | |
150 | |
151 // The subset of |widgets_| which are visible. | |
152 std::set<views::Widget*> visible_; | |
James Cook
2013/04/09 22:22:03
Would it be simpler to just iterate through the st
pkotwicz
2013/04/11 01:37:16
Having a separate variable makes AnchoredWidgetMan
James Cook
2013/04/11 17:33:53
OK, that may be true.
| |
153 | |
154 // Lock which keeps the top-of-window views revealed based on the visible | |
155 // anchored widgets. | |
156 scoped_ptr<ImmersiveModeController::RevealedLock> revealed_lock_; | |
157 | |
158 DISALLOW_COPY_AND_ASSIGN(AnchoredWidgetManager); | |
159 }; | |
160 | |
161 AnchoredWidgetManager::AnchoredWidgetManager( | |
162 ImmersiveModeControllerAsh* controller, | |
163 BrowserView* browser_view) | |
164 : controller_(controller), | |
165 browser_view_(browser_view) { | |
166 } | |
167 | |
168 AnchoredWidgetManager::~AnchoredWidgetManager() { | |
169 for (std::map<views::Widget*, int>::iterator it = widgets_.begin(); | |
170 it != widgets_.end(); ++it) { | |
171 RemoveAnchoredWidget(it->first); | |
172 } | |
173 } | |
174 | |
175 void AnchoredWidgetManager::AddAnchoredWidget(views::Widget* widget, | |
176 int y_offset) { | |
177 DCHECK(widget); | |
178 bool already_added = widgets_.count(widget); | |
179 widgets_[widget] = y_offset; | |
180 | |
181 if (already_added) | |
182 return; | |
183 | |
184 widget->AddObserver(this); | |
185 | |
186 if (widget->IsVisible()) | |
187 visible_.insert(widget); | |
188 | |
189 UpdateRevealedLock(); | |
190 UpdateWidgetBounds(widget, y_offset); | |
191 } | |
192 | |
193 void AnchoredWidgetManager::RemoveAnchoredWidget(views::Widget* widget) { | |
194 if (!widgets_.count(widget)) | |
195 return; | |
196 | |
197 widget->RemoveObserver(this); | |
198 widgets_.erase(widget); | |
199 visible_.erase(widget); | |
200 | |
201 UpdateRevealedLock(); | |
James Cook
2013/04/09 22:22:03
Do you need to put the widget's bounds back to off
pkotwicz
2013/04/11 01:37:16
We could cache the y position of |widget| before w
| |
202 } | |
203 | |
204 void AnchoredWidgetManager::OnTopContainerBoundsChanged() { | |
205 for (std::map<views::Widget*, int>::iterator it = widgets_.begin(); | |
206 it != widgets_.end(); ++it) { | |
207 UpdateWidgetBounds(it->first, it->second); | |
208 } | |
209 | |
210 UpdateRevealedLock(); | |
211 } | |
212 | |
213 void AnchoredWidgetManager::UpdateRevealedLock() { | |
214 if (visible_.empty()) { | |
215 revealed_lock_.reset(); | |
216 } else if (controller_->IsRevealed()) { | |
217 // It is hard to determine the required initial transforms and the required | |
218 // durations of the animations of |widgets_| such that they appear to be | |
219 // anchored to the top-of-window views while the top-of-window views are | |
220 // animating. Skip to the end of the reveal animation instead. | |
221 if (controller_->is_animating()) | |
222 controller_->MaybeRevealWithoutAnimation(); | |
223 | |
224 if (!revealed_lock_.get()) | |
225 revealed_lock_.reset(controller_->GetRevealedLock()); | |
226 } | |
227 } | |
228 | |
229 void AnchoredWidgetManager::UpdateWidgetBounds(views::Widget* widget, | |
230 int y_offset) { | |
231 if (!widget->IsVisible()) | |
232 return; | |
233 | |
234 gfx::Rect top_container_target_bounds = | |
235 browser_view_->top_container()->GetTargetBoundsInScreen(); | |
236 gfx::Rect bounds(widget->GetWindowBoundsInScreen()); | |
237 bounds.set_y( | |
238 top_container_target_bounds.bottom() + y_offset); | |
239 widget->SetBounds(bounds); | |
240 } | |
241 | |
242 void AnchoredWidgetManager::OnWidgetDestroying(views::Widget* widget) { | |
243 RemoveAnchoredWidget(widget); | |
244 } | |
245 | |
246 void AnchoredWidgetManager::OnWidgetVisibilityChanged(views::Widget* widget, | |
247 bool visible) { | |
248 if (visible) | |
249 visible_.insert(widget); | |
250 else | |
251 visible_.erase(widget); | |
252 | |
253 UpdateRevealedLock(); | |
254 | |
255 std::map<views::Widget*, int>::iterator it = widgets_.find(widget); | |
256 DCHECK(it != widgets_.end()); | |
257 UpdateWidgetBounds(it->first, it->second); | |
258 } | |
259 | |
87 } // namespace | 260 } // namespace |
88 | 261 |
89 //////////////////////////////////////////////////////////////////////////////// | 262 //////////////////////////////////////////////////////////////////////////////// |
90 | 263 |
91 // Observer to watch for window restore. views::Widget does not provide a hook | 264 // Observer to watch for window restore. views::Widget does not provide a hook |
92 // to observe for window restore, so do this at the Aura level. | 265 // to observe for window restore, so do this at the Aura level. |
93 class ImmersiveModeControllerAsh::WindowObserver : public aura::WindowObserver { | 266 class ImmersiveModeControllerAsh::WindowObserver : public aura::WindowObserver { |
94 public: | 267 public: |
95 explicit WindowObserver(ImmersiveModeControllerAsh* controller) | 268 explicit WindowObserver(ImmersiveModeControllerAsh* controller) |
96 : controller_(controller) { | 269 : controller_(controller) { |
(...skipping 29 matching lines...) Expand all Loading... | |
126 } | 299 } |
127 | 300 |
128 private: | 301 private: |
129 ImmersiveModeControllerAsh* controller_; // Not owned. | 302 ImmersiveModeControllerAsh* controller_; // Not owned. |
130 | 303 |
131 DISALLOW_COPY_AND_ASSIGN(WindowObserver); | 304 DISALLOW_COPY_AND_ASSIGN(WindowObserver); |
132 }; | 305 }; |
133 | 306 |
134 //////////////////////////////////////////////////////////////////////////////// | 307 //////////////////////////////////////////////////////////////////////////////// |
135 | 308 |
136 class ImmersiveModeControllerAsh::AnimationObserver | |
137 : public ui::ImplicitAnimationObserver { | |
138 public: | |
139 enum AnimationType { | |
140 SLIDE_OPEN, | |
141 SLIDE_CLOSED, | |
142 }; | |
143 | |
144 AnimationObserver(ImmersiveModeControllerAsh* controller, AnimationType type) | |
145 : controller_(controller), animation_type_(type) {} | |
146 virtual ~AnimationObserver() {} | |
147 | |
148 // ui::ImplicitAnimationObserver overrides: | |
149 virtual void OnImplicitAnimationsCompleted() OVERRIDE { | |
150 if (animation_type_ == SLIDE_OPEN) | |
151 controller_->OnSlideOpenAnimationCompleted(); | |
152 else if (animation_type_ == SLIDE_CLOSED) | |
153 controller_->OnSlideClosedAnimationCompleted(); | |
154 else | |
155 NOTREACHED(); | |
156 } | |
157 | |
158 private: | |
159 ImmersiveModeControllerAsh* controller_; | |
160 AnimationType animation_type_; | |
161 | |
162 DISALLOW_COPY_AND_ASSIGN(AnimationObserver); | |
163 }; | |
164 | |
165 //////////////////////////////////////////////////////////////////////////////// | |
166 | |
167 ImmersiveModeControllerAsh::ImmersiveModeControllerAsh() | 309 ImmersiveModeControllerAsh::ImmersiveModeControllerAsh() |
168 : browser_view_(NULL), | 310 : browser_view_(NULL), |
169 enabled_(false), | 311 enabled_(false), |
170 reveal_state_(CLOSED), | 312 reveal_state_(CLOSED), |
313 is_animating_(false), | |
171 revealed_lock_count_(0), | 314 revealed_lock_count_(0), |
172 hide_tab_indicators_(false), | 315 hide_tab_indicators_(false), |
173 native_window_(NULL), | 316 native_window_(NULL), |
174 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 317 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
175 } | 318 } |
176 | 319 |
177 ImmersiveModeControllerAsh::~ImmersiveModeControllerAsh() { | 320 ImmersiveModeControllerAsh::~ImmersiveModeControllerAsh() { |
178 // The browser view is being destroyed so there's no need to update its | 321 // The browser view is being destroyed so there's no need to update its |
179 // layout or layers, even if the top views are revealed. But the window | 322 // layout or layers, even if the top views are revealed. But the window |
180 // observers still need to be removed. | 323 // observers still need to be removed. |
181 EnableWindowObservers(false); | 324 EnableWindowObservers(false); |
182 } | 325 } |
183 | 326 |
184 void ImmersiveModeControllerAsh::LockRevealedState() { | 327 void ImmersiveModeControllerAsh::LockRevealedState() { |
185 ++revealed_lock_count_; | 328 ++revealed_lock_count_; |
186 if (revealed_lock_count_ == 1) | 329 if (revealed_lock_count_ == 1) |
187 MaybeStartReveal(); | 330 MaybeStartReveal(); |
188 } | 331 } |
189 | 332 |
190 void ImmersiveModeControllerAsh::UnlockRevealedState() { | 333 void ImmersiveModeControllerAsh::UnlockRevealedState() { |
191 --revealed_lock_count_; | 334 --revealed_lock_count_; |
192 DCHECK_GE(revealed_lock_count_, 0); | 335 DCHECK_GE(revealed_lock_count_, 0); |
193 if (revealed_lock_count_ == 0) | 336 if (revealed_lock_count_ == 0) |
194 MaybeEndReveal(ANIMATE_FAST); | 337 MaybeEndReveal(ANIMATE_FAST); |
195 } | 338 } |
196 | 339 |
340 void ImmersiveModeControllerAsh::MaybeRevealWithoutAnimation() { | |
341 MaybeStartReveal(ANIMATE_NO); | |
342 } | |
343 | |
197 void ImmersiveModeControllerAsh::Init(BrowserView* browser_view) { | 344 void ImmersiveModeControllerAsh::Init(BrowserView* browser_view) { |
198 browser_view_ = browser_view; | 345 browser_view_ = browser_view; |
199 // Browser view is detached from its widget during destruction. Cache the | 346 // Browser view is detached from its widget during destruction. Cache the |
200 // window pointer so |this| can stop observing during destruction. | 347 // window pointer so |this| can stop observing during destruction. |
201 native_window_ = browser_view_->GetNativeWindow(); | 348 native_window_ = browser_view_->GetNativeWindow(); |
202 DCHECK(native_window_); | 349 DCHECK(native_window_); |
203 EnableWindowObservers(true); | 350 EnableWindowObservers(true); |
204 | 351 |
205 slide_open_observer_.reset( | |
206 new AnimationObserver(this, AnimationObserver::SLIDE_OPEN)); | |
207 slide_closed_observer_.reset( | |
208 new AnimationObserver(this, AnimationObserver::SLIDE_CLOSED)); | |
209 | |
210 // Optionally allow the tab indicators to be hidden. | 352 // Optionally allow the tab indicators to be hidden. |
211 hide_tab_indicators_ = CommandLine::ForCurrentProcess()-> | 353 hide_tab_indicators_ = CommandLine::ForCurrentProcess()-> |
212 HasSwitch(ash::switches::kAshImmersiveHideTabIndicators); | 354 HasSwitch(ash::switches::kAshImmersiveHideTabIndicators); |
355 | |
356 anchored_widget_manager_.reset( | |
357 new AnchoredWidgetManager(this, browser_view_)); | |
213 } | 358 } |
214 | 359 |
215 void ImmersiveModeControllerAsh::SetEnabled(bool enabled) { | 360 void ImmersiveModeControllerAsh::SetEnabled(bool enabled) { |
216 DCHECK(browser_view_) << "Must initialize before enabling"; | 361 DCHECK(browser_view_) << "Must initialize before enabling"; |
217 if (enabled_ == enabled) | 362 if (enabled_ == enabled) |
218 return; | 363 return; |
219 enabled_ = enabled; | 364 enabled_ = enabled; |
220 | 365 |
221 if (enabled_) { | 366 if (enabled_) { |
222 // Animate enabling immersive mode by sliding out the top-of-window views. | 367 // Animate enabling immersive mode by sliding out the top-of-window views. |
223 // No animation occurs if a lock is holding the top-of-window views open. | 368 // No animation occurs if a lock is holding the top-of-window views open. |
224 | 369 |
225 // Do a reveal to set the initial state for the animation. (And any | 370 // Do a reveal to set the initial state for the animation. (And any |
226 // required state in case the animation cannot run because of a lock holding | 371 // required state in case the animation cannot run because of a lock holding |
227 // the top-of-window views open.) | 372 // the top-of-window views open.) |
228 StartReveal(ANIMATE_NO); | 373 MaybeStartReveal(ANIMATE_NO); |
229 | 374 |
230 // Reset the mouse and the focus revealed locks so that they do not affect | 375 // Reset the mouse and the focus revealed locks so that they do not affect |
231 // whether the top-of-window views are hidden. Reacquire the locks if ending | 376 // whether the top-of-window views are hidden. Reacquire the locks if ending |
232 // the reveal is unsuccessful. | 377 // the reveal is unsuccessful. |
233 bool had_mouse_revealed_lock = (mouse_revealed_lock_.get() != NULL); | 378 bool had_mouse_revealed_lock = (mouse_revealed_lock_.get() != NULL); |
234 bool had_focus_revealed_lock = (focus_revealed_lock_.get() != NULL); | 379 bool had_focus_revealed_lock = (focus_revealed_lock_.get() != NULL); |
235 mouse_revealed_lock_.reset(); | 380 mouse_revealed_lock_.reset(); |
236 focus_revealed_lock_.reset(); | 381 focus_revealed_lock_.reset(); |
237 | 382 |
238 // Try doing the animation. | 383 // Try doing the animation. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
284 | 429 |
285 void ImmersiveModeControllerAsh::MaybeStackViewAtTop() { | 430 void ImmersiveModeControllerAsh::MaybeStackViewAtTop() { |
286 if (enabled_ && reveal_state_ != CLOSED) { | 431 if (enabled_ && reveal_state_ != CLOSED) { |
287 ui::Layer* reveal_layer = browser_view_->top_container()->layer(); | 432 ui::Layer* reveal_layer = browser_view_->top_container()->layer(); |
288 if (reveal_layer) | 433 if (reveal_layer) |
289 reveal_layer->parent()->StackAtTop(reveal_layer); | 434 reveal_layer->parent()->StackAtTop(reveal_layer); |
290 } | 435 } |
291 } | 436 } |
292 | 437 |
293 void ImmersiveModeControllerAsh::MaybeStartReveal() { | 438 void ImmersiveModeControllerAsh::MaybeStartReveal() { |
294 if (enabled_ && reveal_state_ != REVEALED) | 439 MaybeStartReveal(ANIMATE_FAST); |
295 StartReveal(ANIMATE_FAST); | |
296 } | 440 } |
297 | 441 |
298 void ImmersiveModeControllerAsh::CancelReveal() { | 442 void ImmersiveModeControllerAsh::CancelReveal() { |
299 // Reset the mouse revealed lock so that it does not affect whether | 443 // Reset the mouse revealed lock so that it does not affect whether |
300 // the top-of-window views are hidden. Reaquire the lock if ending the reveal | 444 // the top-of-window views are hidden. Reaquire the lock if ending the reveal |
301 // is unsuccessful. | 445 // is unsuccessful. |
302 bool had_mouse_revealed_lock = (mouse_revealed_lock_.get() != NULL); | 446 bool had_mouse_revealed_lock = (mouse_revealed_lock_.get() != NULL); |
303 mouse_revealed_lock_.reset(); | 447 mouse_revealed_lock_.reset(); |
304 MaybeEndReveal(ANIMATE_NO); | 448 MaybeEndReveal(ANIMATE_NO); |
305 if (IsRevealed() && had_mouse_revealed_lock) | 449 if (IsRevealed() && had_mouse_revealed_lock) |
306 mouse_revealed_lock_.reset(GetRevealedLock()); | 450 mouse_revealed_lock_.reset(GetRevealedLock()); |
307 } | 451 } |
308 | 452 |
309 ImmersiveModeControllerAsh::RevealedLock* | 453 ImmersiveModeControllerAsh::RevealedLock* |
310 ImmersiveModeControllerAsh::GetRevealedLock() { | 454 ImmersiveModeControllerAsh::GetRevealedLock() { |
311 return new RevealedLockAsh(weak_ptr_factory_.GetWeakPtr()); | 455 return new RevealedLockAsh(weak_ptr_factory_.GetWeakPtr()); |
312 } | 456 } |
313 | 457 |
458 void ImmersiveModeControllerAsh::AnchorWidgetToTopContainer( | |
459 views::Widget* widget, | |
460 int y_offset) { | |
461 anchored_widget_manager_->AddAnchoredWidget(widget, y_offset); | |
462 } | |
463 | |
464 void ImmersiveModeControllerAsh::UnanchorWidgetFromTopContainer( | |
465 views::Widget* widget) { | |
466 anchored_widget_manager_->RemoveAnchoredWidget(widget); | |
467 } | |
468 | |
469 void ImmersiveModeControllerAsh::OnTopContainerBoundsChanged() { | |
470 anchored_widget_manager_->OnTopContainerBoundsChanged(); | |
471 } | |
472 | |
314 //////////////////////////////////////////////////////////////////////////////// | 473 //////////////////////////////////////////////////////////////////////////////// |
315 // Observers: | 474 // Observers: |
316 | 475 |
317 void ImmersiveModeControllerAsh::OnMouseEvent(ui::MouseEvent* event) { | 476 void ImmersiveModeControllerAsh::OnMouseEvent(ui::MouseEvent* event) { |
318 if (!enabled_) | 477 if (!enabled_) |
319 return; | 478 return; |
320 | 479 |
321 if (event->flags() & ui::EF_IS_SYNTHESIZED) | 480 if (event->flags() & ui::EF_IS_SYNTHESIZED) |
322 return; | 481 return; |
323 | 482 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
377 bool active) { | 536 bool active) { |
378 // Mouse hover should not initiate revealing the top-of-window views while | 537 // Mouse hover should not initiate revealing the top-of-window views while |
379 // |native_window_| is inactive. | 538 // |native_window_| is inactive. |
380 top_timer_.Stop(); | 539 top_timer_.Stop(); |
381 | 540 |
382 UpdateMouseRevealedLock(true); | 541 UpdateMouseRevealedLock(true); |
383 UpdateFocusRevealedLock(); | 542 UpdateFocusRevealedLock(); |
384 } | 543 } |
385 | 544 |
386 //////////////////////////////////////////////////////////////////////////////// | 545 //////////////////////////////////////////////////////////////////////////////// |
546 // Animation observer: | |
547 | |
548 void ImmersiveModeControllerAsh::OnImplicitAnimationsCompleted() { | |
James Cook
2013/04/09 22:22:03
I presume you can do this instead of having two ob
pkotwicz
2013/04/11 01:37:16
Yes.
IMMEDIATELY_ANIMATE_TO_NEW_TARGET preemption
| |
549 is_animating_ = false; | |
550 if (reveal_state_ == SLIDING_OPEN) | |
551 OnSlideOpenAnimationCompleted(); | |
552 else if (reveal_state_ == SLIDING_CLOSED) | |
553 OnSlideClosedAnimationCompleted(); | |
554 } | |
555 | |
556 //////////////////////////////////////////////////////////////////////////////// | |
387 // Testing interface: | 557 // Testing interface: |
388 | 558 |
389 void ImmersiveModeControllerAsh::SetHideTabIndicatorsForTest(bool hide) { | 559 void ImmersiveModeControllerAsh::SetHideTabIndicatorsForTest(bool hide) { |
390 hide_tab_indicators_ = hide; | 560 hide_tab_indicators_ = hide; |
391 } | 561 } |
392 | 562 |
393 void ImmersiveModeControllerAsh::StartRevealForTest(bool hovered) { | 563 void ImmersiveModeControllerAsh::StartRevealForTest(bool hovered) { |
394 StartReveal(ANIMATE_NO); | 564 MaybeStartReveal(ANIMATE_NO); |
395 SetMouseHoveredForTest(hovered); | 565 MoveMouse(browser_view_->top_container(), hovered); |
566 UpdateMouseRevealedLock(true); | |
396 } | 567 } |
397 | 568 |
398 void ImmersiveModeControllerAsh::SetMouseHoveredForTest(bool hovered) { | 569 void ImmersiveModeControllerAsh::SetMouseHoveredForTest(bool hovered) { |
399 views::View* top_container = browser_view_->top_container(); | 570 MoveMouse(browser_view_->top_container(), hovered); |
400 gfx::Point cursor_pos; | |
401 if (!hovered) { | |
402 int bottom_edge = top_container->bounds().bottom(); | |
403 cursor_pos = gfx::Point(0, bottom_edge + 100); | |
404 } | |
405 views::View::ConvertPointToScreen(top_container, &cursor_pos); | |
406 aura::Env::GetInstance()->set_last_mouse_location(cursor_pos); | |
407 | |
408 UpdateMouseRevealedLock(true); | 571 UpdateMouseRevealedLock(true); |
409 } | 572 } |
410 | 573 |
411 //////////////////////////////////////////////////////////////////////////////// | 574 //////////////////////////////////////////////////////////////////////////////// |
412 // private: | 575 // private: |
413 | 576 |
414 void ImmersiveModeControllerAsh::EnableWindowObservers(bool enable) { | 577 void ImmersiveModeControllerAsh::EnableWindowObservers(bool enable) { |
415 if (!native_window_) { | 578 if (!native_window_) { |
416 DCHECK(!enable) << "ImmersiveModeControllerAsh not initialized"; | 579 DCHECK(!enable) << "ImmersiveModeControllerAsh not initialized"; |
417 return; | 580 return; |
(...skipping 10 matching lines...) Expand all Loading... | |
428 focus_manager->RemoveFocusChangeListener(this); | 591 focus_manager->RemoveFocusChangeListener(this); |
429 } | 592 } |
430 | 593 |
431 if (enable) | 594 if (enable) |
432 native_window_->AddPreTargetHandler(this); | 595 native_window_->AddPreTargetHandler(this); |
433 else | 596 else |
434 native_window_->RemovePreTargetHandler(this); | 597 native_window_->RemovePreTargetHandler(this); |
435 | 598 |
436 // The window observer adds and removes itself from the native window. | 599 // The window observer adds and removes itself from the native window. |
437 window_observer_.reset(enable ? new WindowObserver(this) : NULL); | 600 window_observer_.reset(enable ? new WindowObserver(this) : NULL); |
601 | |
602 if (!enable) | |
603 StopObservingImplicitAnimations(); | |
438 } | 604 } |
439 | 605 |
440 void ImmersiveModeControllerAsh::UpdateMouseRevealedLock(bool maybe_drag) { | 606 void ImmersiveModeControllerAsh::UpdateMouseRevealedLock(bool maybe_drag) { |
441 if (!enabled_) | 607 if (!enabled_) |
442 return; | 608 return; |
443 | 609 |
444 // Hover cannot initiate a reveal when the top-of-window views are sliding | 610 // Hover cannot initiate a reveal when the top-of-window views are sliding |
445 // closed or are closed. (With the exception of hovering at y = 0 which is | 611 // closed or are closed. (With the exception of hovering at y = 0 which is |
446 // handled in OnMouseEvent() ). | 612 // handled in OnMouseEvent() ). |
447 if (reveal_state_ == SLIDING_CLOSED || reveal_state_ == CLOSED) | 613 if (reveal_state_ == SLIDING_CLOSED || reveal_state_ == CLOSED) |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
515 return 0; | 681 return 0; |
516 case ANIMATE_SLOW: | 682 case ANIMATE_SLOW: |
517 return kRevealSlowAnimationDurationMs; | 683 return kRevealSlowAnimationDurationMs; |
518 case ANIMATE_FAST: | 684 case ANIMATE_FAST: |
519 return kRevealFastAnimationDurationMs; | 685 return kRevealFastAnimationDurationMs; |
520 } | 686 } |
521 NOTREACHED(); | 687 NOTREACHED(); |
522 return 0; | 688 return 0; |
523 } | 689 } |
524 | 690 |
525 void ImmersiveModeControllerAsh::StartReveal(Animate animate) { | 691 void ImmersiveModeControllerAsh::MaybeStartReveal(Animate animate) { |
James Cook
2013/04/09 22:22:03
I don't like function overloading. Can this be cal
pkotwicz
2013/04/11 01:37:16
I removed MaybeStartReveal() altogether :)
| |
526 if (reveal_state_ == CLOSED) { | 692 if (!enabled_) |
527 reveal_state_ = SLIDING_OPEN; | 693 return; |
694 | |
695 if (reveal_state_ == REVEALED || | |
696 (reveal_state_ == SLIDING_OPEN && animate != ANIMATE_NO)) { | |
James Cook
2013/04/09 22:22:03
Maybe comment on why this function now needs to ru
| |
697 return; | |
698 } | |
699 | |
700 RevealState previous_reveal_state = reveal_state_; | |
701 reveal_state_ = SLIDING_OPEN; | |
702 if (previous_reveal_state == CLOSED) { | |
528 // Turn on layer painting so we can smoothly animate. | 703 // Turn on layer painting so we can smoothly animate. |
529 EnablePaintToLayer(true); | 704 EnablePaintToLayer(true); |
530 | 705 |
531 // Ensure window caption buttons are updated and the view bounds are | 706 // Ensure window caption buttons are updated and the view bounds are |
532 // computed at normal (non-immersive-style) size. | 707 // computed at normal (non-immersive-style) size. |
533 LayoutBrowserView(false); | 708 LayoutBrowserView(false); |
534 | 709 |
535 if (animate != ANIMATE_NO) { | 710 if (animate != ANIMATE_NO) { |
536 // Now that we have a layer, move it to the initial offscreen position. | 711 // Now that we have a layer, move it to the initial offscreen position. |
537 ui::Layer* layer = browser_view_->top_container()->layer(); | 712 ui::Layer* layer = browser_view_->top_container()->layer(); |
538 gfx::Transform transform; | 713 gfx::Transform transform; |
539 transform.Translate(0, -layer->bounds().height() + kAnimationOffsetY); | 714 transform.Translate(0, -layer->bounds().height() + kAnimationOffsetY); |
540 layer->SetTransform(transform); | 715 layer->SetTransform(transform); |
716 | |
717 typedef std::set<views::Widget*> WidgetSet; | |
718 const WidgetSet& visible_widgets = | |
719 anchored_widget_manager_->visible_anchored_widgets(); | |
720 for (WidgetSet::const_iterator it = visible_widgets.begin(); | |
721 it != visible_widgets.end(); ++it) { | |
722 (*it)->GetNativeWindow()->SetTransform(transform); | |
723 } | |
541 } | 724 } |
542 // Slide in the reveal view. | |
543 AnimateSlideOpen(GetAnimationDuration(animate)); | |
544 } else if (reveal_state_ == SLIDING_CLOSED) { | |
545 reveal_state_ = SLIDING_OPEN; | |
546 // Reverse the animation. | |
547 AnimateSlideOpen(GetAnimationDuration(animate)); | |
548 } | 725 } |
726 // Slide in the reveal view. | |
727 DoAnimation(gfx::Transform(), GetAnimationDuration(animate)); | |
549 } | 728 } |
550 | 729 |
551 void ImmersiveModeControllerAsh::EnablePaintToLayer(bool enable) { | 730 void ImmersiveModeControllerAsh::EnablePaintToLayer(bool enable) { |
552 browser_view_->top_container()->SetPaintToLayer(enable); | 731 browser_view_->top_container()->SetPaintToLayer(enable); |
553 | 732 |
554 // Views software compositing is not fully layer aware. If the bookmark bar | 733 // Views software compositing is not fully layer aware. If the bookmark bar |
555 // is detached while the top container layer slides on or off the screen, | 734 // is detached while the top container layer slides on or off the screen, |
556 // the pixels that become exposed are the remnants of the last software | 735 // the pixels that become exposed are the remnants of the last software |
557 // composite of the BrowserView, not the freshly-exposed bookmark bar. | 736 // composite of the BrowserView, not the freshly-exposed bookmark bar. |
558 // Force the bookmark bar to paint to a layer so the views composite | 737 // Force the bookmark bar to paint to a layer so the views composite |
559 // properly. The infobar container does not need this treatment because | 738 // properly. The infobar container does not need this treatment because |
560 // BrowserView::PaintChildren() always draws it last when it is visible. | 739 // BrowserView::PaintChildren() always draws it last when it is visible. |
561 BookmarkBarView* bookmark_bar = browser_view_->bookmark_bar(); | 740 BookmarkBarView* bookmark_bar = browser_view_->bookmark_bar(); |
562 if (!bookmark_bar) | 741 if (!bookmark_bar) |
563 return; | 742 return; |
564 if (enable && bookmark_bar->IsDetached()) | 743 if (enable && bookmark_bar->IsDetached()) |
565 bookmark_bar->SetPaintToLayer(true); | 744 bookmark_bar->SetPaintToLayer(true); |
566 else | 745 else |
567 bookmark_bar->SetPaintToLayer(false); | 746 bookmark_bar->SetPaintToLayer(false); |
568 } | 747 } |
569 | 748 |
570 void ImmersiveModeControllerAsh::LayoutBrowserView(bool immersive_style) { | 749 void ImmersiveModeControllerAsh::LayoutBrowserView(bool immersive_style) { |
571 // Update the window caption buttons. | 750 // Update the window caption buttons. |
572 browser_view_->GetWidget()->non_client_view()->frame_view()-> | 751 browser_view_->GetWidget()->non_client_view()->frame_view()-> |
573 ResetWindowControls(); | 752 ResetWindowControls(); |
574 browser_view_->tabstrip()->SetImmersiveStyle(immersive_style); | 753 browser_view_->tabstrip()->SetImmersiveStyle(immersive_style); |
575 browser_view_->frame()->GetRootView()->Layout(); | 754 browser_view_->frame()->GetRootView()->Layout(); |
576 } | 755 } |
577 | 756 |
578 void ImmersiveModeControllerAsh::AnimateSlideOpen(int duration_ms) { | 757 void ImmersiveModeControllerAsh::OnSlideOpenAnimationCompleted() { |
579 ui::Layer* layer = browser_view_->top_container()->layer(); | 758 DCHECK_EQ(SLIDING_OPEN, reveal_state_); |
580 // Stop any slide closed animation in progress. | 759 reveal_state_ = REVEALED; |
581 layer->GetAnimator()->AbortAllAnimations(); | |
582 | 760 |
583 ui::ScopedLayerAnimationSettings settings(layer->GetAnimator()); | 761 // The user may not have moved the mouse since the reveal was initiated. |
584 settings.AddObserver(slide_open_observer_.get()); | 762 // Update the revealed lock to reflect the mouse's current state. |
585 settings.SetTweenType(ui::Tween::EASE_OUT); | 763 UpdateMouseRevealedLock(true); |
586 settings.SetTransitionDuration( | |
587 base::TimeDelta::FromMilliseconds(duration_ms)); | |
588 layer->SetTransform(gfx::Transform()); | |
589 } | 764 } |
590 | 765 |
591 void ImmersiveModeControllerAsh::OnSlideOpenAnimationCompleted() { | 766 void ImmersiveModeControllerAsh::MaybeEndReveal(Animate animate) { |
592 if (reveal_state_ == SLIDING_OPEN) { | 767 if (!enabled_ || revealed_lock_count_ != 0) |
593 reveal_state_ = REVEALED; | 768 return; |
594 | 769 |
595 // The user may not have moved the mouse since the reveal was initiated. | 770 if (reveal_state_ == CLOSED || |
596 // Update the revealed lock to reflect the mouse's current state. | 771 (reveal_state_ == SLIDING_CLOSED && animate != ANIMATE_NO)) { |
597 UpdateMouseRevealedLock(true); | 772 return; |
773 } | |
774 | |
775 reveal_state_ = SLIDING_CLOSED; | |
776 int duration_ms = GetAnimationDuration(animate); | |
777 if (duration_ms > 0) { | |
778 // The bookmark bar may have become detached during the reveal so ensure | |
779 // layers are available. This is a no-op for the top container. | |
780 EnablePaintToLayer(true); | |
781 | |
782 ui::Layer* top_container_layer = browser_view_->top_container()->layer(); | |
783 gfx::Transform target_transform; | |
784 target_transform.Translate(0, | |
785 -top_container_layer->bounds().height() + kAnimationOffsetY); | |
786 | |
787 // Visible anchored widgets keep the top-of-window views revealed. | |
788 DCHECK(anchored_widget_manager_->visible_anchored_widgets().empty()); | |
789 | |
790 DoAnimation(target_transform, duration_ms); | |
791 } else { | |
792 OnSlideClosedAnimationCompleted(); | |
598 } | 793 } |
599 } | 794 } |
600 | 795 |
601 void ImmersiveModeControllerAsh::MaybeEndReveal(Animate animate) { | 796 void ImmersiveModeControllerAsh::OnSlideClosedAnimationCompleted() { |
602 if (enabled_ && reveal_state_ != CLOSED && revealed_lock_count_ == 0) | 797 DCHECK_EQ(SLIDING_CLOSED, reveal_state_); |
603 EndReveal(animate); | 798 reveal_state_ = CLOSED; |
799 // Layers aren't needed after animation completes. | |
800 EnablePaintToLayer(false); | |
801 // Update tabstrip for closed state. | |
802 LayoutBrowserView(true); | |
604 } | 803 } |
605 | 804 |
606 void ImmersiveModeControllerAsh::EndReveal(Animate animate) { | 805 void ImmersiveModeControllerAsh::DoAnimation( |
607 if (reveal_state_ == SLIDING_OPEN || reveal_state_ == REVEALED) { | 806 const gfx::Transform& target_transform, |
608 reveal_state_ = SLIDING_CLOSED; | 807 int duration_ms) { |
609 int duration_ms = GetAnimationDuration(animate); | 808 is_animating_ = true; |
610 if (duration_ms > 0) { | 809 StopObservingImplicitAnimations(); |
611 // Bookmark bar have become detached during the reveal so ensure | 810 DoAnimation(browser_view_->top_container()->layer(), target_transform, |
612 // layers are available. This is a no-op for top container. | 811 duration_ms, this); |
613 EnablePaintToLayer(true); | 812 |
614 AnimateSlideClosed(duration_ms); | 813 typedef std::set<views::Widget*> WidgetSet; |
615 } else { | 814 const WidgetSet& visible_widgets = |
616 OnSlideClosedAnimationCompleted(); | 815 anchored_widget_manager_->visible_anchored_widgets(); |
617 } | 816 for (WidgetSet::const_iterator it = visible_widgets.begin(); |
817 it != visible_widgets.end(); ++it) { | |
818 // The anchored widget's bounds are set to the target bounds right when the | |
819 // animation starts. The transform is used to animate the widget's position. | |
820 // Using the target bounds allows us to "stay anchored" if other code | |
821 // changes the widget bounds in the middle of the animation. (This is the | |
822 // case if the fullscreen exit bubble type is changed during the immersive | |
823 // reveal animation). | |
824 DoAnimation((*it)->GetNativeWindow()->layer(), gfx::Transform(), | |
825 duration_ms, NULL); | |
618 } | 826 } |
619 } | 827 } |
620 | 828 |
621 void ImmersiveModeControllerAsh::AnimateSlideClosed(int duration_ms) { | 829 void ImmersiveModeControllerAsh::DoAnimation( |
622 // Stop any slide open animation in progress, but don't skip to the end. This | 830 ui::Layer* layer, |
623 // avoids a visual "pop" when starting a hide in the middle of a show. | 831 const gfx::Transform& target_transform, |
624 ui::Layer* layer = browser_view_->top_container()->layer(); | 832 int duration_ms, |
625 layer->GetAnimator()->AbortAllAnimations(); | 833 ui::ImplicitAnimationObserver* observer) { |
626 | |
627 ui::ScopedLayerAnimationSettings settings(layer->GetAnimator()); | 834 ui::ScopedLayerAnimationSettings settings(layer->GetAnimator()); |
628 settings.SetTweenType(ui::Tween::EASE_OUT); | 835 settings.SetTweenType(ui::Tween::EASE_OUT); |
629 settings.SetTransitionDuration( | 836 settings.SetTransitionDuration( |
630 base::TimeDelta::FromMilliseconds(duration_ms)); | 837 base::TimeDelta::FromMilliseconds(duration_ms)); |
631 settings.AddObserver(slide_closed_observer_.get()); | 838 settings.SetPreemptionStrategy( |
632 gfx::Transform transform; | 839 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
633 transform.Translate(0, -layer->bounds().height() + kAnimationOffsetY); | 840 if (observer) |
634 layer->SetTransform(transform); | 841 settings.AddObserver(observer); |
842 layer->SetTransform(target_transform); | |
635 } | 843 } |
636 | |
637 void ImmersiveModeControllerAsh::OnSlideClosedAnimationCompleted() { | |
638 if (reveal_state_ == SLIDING_CLOSED) { | |
639 reveal_state_ = CLOSED; | |
640 // Layers aren't needed after animation completes. | |
641 EnablePaintToLayer(false); | |
642 // Update tabstrip for closed state. | |
643 LayoutBrowserView(true); | |
644 } | |
645 } | |
OLD | NEW |