Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(382)

Side by Side Diff: chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc

Issue 13866026: Adds functionality to anchor widgets to the top-of-window views in immersive mode (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rebased Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 20 matching lines...) Expand all
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
87 } // namespace 100 } // namespace
88 101
89 //////////////////////////////////////////////////////////////////////////////// 102 ////////////////////////////////////////////////////////////////////////////////
90 103
104 // Manages widgets which should move in sync with the top-of-window views.
105 class ImmersiveModeControllerAsh::AnchoredWidgetManager
106 : public views::WidgetObserver {
107 public:
108 explicit AnchoredWidgetManager(ImmersiveModeControllerAsh* controller);
109 virtual ~AnchoredWidgetManager();
110
111 // Anchors |widget| such that it stays |y_offset| below the top-of-window
112 // views. |widget| will be repositioned whenever the top-of-window views are
113 // animated (top-of-window views revealing / unrevealing) or the top-of-window
114 // bounds change (eg the bookmark bar is shown).
115 // If the top-of-window views are revealed (or become revealed), |widget| will
116 // keep the top-of-window views revealed till |widget| is hidden or
117 // RemoveAnchoredWidget() is called.
118 void AddAnchoredWidget(views::Widget* widget, int y_offset);
119
120 // Stops managing |widget|'s y position.
121 // Closes the top-of-window views if no locks or other anchored widgets are
122 // keeping the top-of-window views revealed.
123 void RemoveAnchoredWidget(views::Widget* widget);
124
125 // Adjusts the y positions of the anchored widgets for the new top container
126 // bounds.
127 void OnTopContainerBoundsChanged();
128
129 const std::set<views::Widget*>& visible_anchored_widgets() const {
130 return visible_;
131 }
132
133 private:
134 // Updates |revealed_lock_| based on the visible anchored widgets.
135 void UpdateRevealedLock();
136
137 // Updates the y position of |widget| given |y_offset| and the top
138 // container's target bounds.
139 void UpdateWidgetBounds(views::Widget* widget, int y_offset);
140
141 // views::WidgetObserver overrides:
142 virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE;
143 virtual void OnWidgetVisibilityChanged(views::Widget* widget,
144 bool visible) OVERRIDE;
145
146 ImmersiveModeControllerAsh* controller_;
147
148 // Mapping of anchored widgets to the y offset below the top-of-window views
149 // that they should be positioned at.
150 std::map<views::Widget*, int> widgets_;
151
152 // The subset of |widgets_| which are visible.
153 std::set<views::Widget*> visible_;
154
155 // Lock which keeps the top-of-window views revealed based on the visible
156 // anchored widgets.
157 scoped_ptr<ImmersiveModeController::RevealedLock> revealed_lock_;
158
159 DISALLOW_COPY_AND_ASSIGN(AnchoredWidgetManager);
160 };
161
162 ImmersiveModeControllerAsh::AnchoredWidgetManager::AnchoredWidgetManager(
163 ImmersiveModeControllerAsh* controller)
164 : controller_(controller) {
165 }
166
167 ImmersiveModeControllerAsh::AnchoredWidgetManager::~AnchoredWidgetManager() {
168 for (std::map<views::Widget*, int>::iterator it = widgets_.begin();
169 it != widgets_.end(); ++it) {
170 RemoveAnchoredWidget(it->first);
171 }
172 }
173
174 void ImmersiveModeControllerAsh::AnchoredWidgetManager::AddAnchoredWidget(
175 views::Widget* widget,
176 int y_offset) {
177 DCHECK(widget);
178 bool already_added = widgets_.count(widget) > 0;
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 ImmersiveModeControllerAsh::AnchoredWidgetManager::RemoveAnchoredWidget(
194 views::Widget* widget) {
195 if (!widgets_.count(widget))
196 return;
197
198 widget->RemoveObserver(this);
199 widgets_.erase(widget);
200 visible_.erase(widget);
201
202 UpdateRevealedLock();
203 }
204
205 void ImmersiveModeControllerAsh::AnchoredWidgetManager::
206 OnTopContainerBoundsChanged() {
207 for (std::map<views::Widget*, int>::iterator it = widgets_.begin();
208 it != widgets_.end(); ++it) {
209 UpdateWidgetBounds(it->first, it->second);
210 }
211
212 UpdateRevealedLock();
213 }
214
215 void ImmersiveModeControllerAsh::AnchoredWidgetManager::UpdateRevealedLock() {
216 if (visible_.empty()) {
217 revealed_lock_.reset();
218 } else if (controller_->IsRevealed()) {
219 // It is hard to determine the required initial transforms and the required
220 // durations of the animations of |visible_| such that they appear to be
221 // anchored to the top-of-window views while the top-of-window views are
222 // animating. Skip to the end of the reveal animation instead.
223 // We do not query the controller's reveal state because we may be called
224 // as a result of LayoutBrowserView() in MaybeStartReveal() when
225 // |reveal_state_| is SLIDING_OPEN but no animation is running yet.
226 ui::Layer* top_container_layer =
227 controller_->browser_view_->top_container()->layer();
228 if (top_container_layer &&
229 top_container_layer->GetAnimator()->is_animating()) {
230 controller_->MaybeRevealWithoutAnimation();
231 }
232
233 if (!revealed_lock_.get())
234 revealed_lock_.reset(controller_->GetRevealedLock());
235 }
236 }
237
238 void ImmersiveModeControllerAsh::AnchoredWidgetManager::UpdateWidgetBounds(
239 views::Widget* widget,
240 int y_offset) {
241 if (!widget->IsVisible())
242 return;
243
244 gfx::Rect top_container_target_bounds =
245 controller_->browser_view_->top_container()->GetTargetBoundsInScreen();
246 gfx::Rect bounds(widget->GetWindowBoundsInScreen());
247 bounds.set_y(
248 top_container_target_bounds.bottom() + y_offset);
249 widget->SetBounds(bounds);
250 }
251
252 void ImmersiveModeControllerAsh::AnchoredWidgetManager::OnWidgetDestroying(
253 views::Widget* widget) {
254 RemoveAnchoredWidget(widget);
255 }
256
257 void ImmersiveModeControllerAsh::AnchoredWidgetManager::
258 OnWidgetVisibilityChanged(
259 views::Widget* widget,
260 bool visible) {
261 if (visible)
262 visible_.insert(widget);
263 else
264 visible_.erase(widget);
265
266 UpdateRevealedLock();
267
268 std::map<views::Widget*, int>::iterator it = widgets_.find(widget);
269 DCHECK(it != widgets_.end());
270 UpdateWidgetBounds(it->first, it->second);
271 }
272
273 ////////////////////////////////////////////////////////////////////////////////
274
91 // Observer to watch for window restore. views::Widget does not provide a hook 275 // 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. 276 // to observe for window restore, so do this at the Aura level.
93 class ImmersiveModeControllerAsh::WindowObserver : public aura::WindowObserver { 277 class ImmersiveModeControllerAsh::WindowObserver : public aura::WindowObserver {
94 public: 278 public:
95 explicit WindowObserver(ImmersiveModeControllerAsh* controller) 279 explicit WindowObserver(ImmersiveModeControllerAsh* controller)
96 : controller_(controller) { 280 : controller_(controller) {
97 controller_->native_window_->AddObserver(this); 281 controller_->native_window_->AddObserver(this);
98 } 282 }
99 283
100 virtual ~WindowObserver() { 284 virtual ~WindowObserver() {
(...skipping 25 matching lines...) Expand all
126 } 310 }
127 311
128 private: 312 private:
129 ImmersiveModeControllerAsh* controller_; // Not owned. 313 ImmersiveModeControllerAsh* controller_; // Not owned.
130 314
131 DISALLOW_COPY_AND_ASSIGN(WindowObserver); 315 DISALLOW_COPY_AND_ASSIGN(WindowObserver);
132 }; 316 };
133 317
134 //////////////////////////////////////////////////////////////////////////////// 318 ////////////////////////////////////////////////////////////////////////////////
135 319
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() 320 ImmersiveModeControllerAsh::ImmersiveModeControllerAsh()
168 : browser_view_(NULL), 321 : browser_view_(NULL),
169 enabled_(false), 322 enabled_(false),
170 reveal_state_(CLOSED), 323 reveal_state_(CLOSED),
171 revealed_lock_count_(0), 324 revealed_lock_count_(0),
172 hide_tab_indicators_(false), 325 hide_tab_indicators_(false),
173 native_window_(NULL), 326 native_window_(NULL),
174 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { 327 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
175 } 328 }
176 329
177 ImmersiveModeControllerAsh::~ImmersiveModeControllerAsh() { 330 ImmersiveModeControllerAsh::~ImmersiveModeControllerAsh() {
178 // The browser view is being destroyed so there's no need to update its 331 // 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 332 // layout or layers, even if the top views are revealed. But the window
180 // observers still need to be removed. 333 // observers still need to be removed.
181 EnableWindowObservers(false); 334 EnableWindowObservers(false);
182 } 335 }
183 336
184 void ImmersiveModeControllerAsh::LockRevealedState() { 337 void ImmersiveModeControllerAsh::LockRevealedState() {
185 ++revealed_lock_count_; 338 ++revealed_lock_count_;
186 if (revealed_lock_count_ == 1) 339 if (revealed_lock_count_ == 1)
187 MaybeStartReveal(); 340 MaybeStartReveal(ANIMATE_FAST);
188 } 341 }
189 342
190 void ImmersiveModeControllerAsh::UnlockRevealedState() { 343 void ImmersiveModeControllerAsh::UnlockRevealedState() {
191 --revealed_lock_count_; 344 --revealed_lock_count_;
192 DCHECK_GE(revealed_lock_count_, 0); 345 DCHECK_GE(revealed_lock_count_, 0);
193 if (revealed_lock_count_ == 0) 346 if (revealed_lock_count_ == 0)
194 MaybeEndReveal(ANIMATE_FAST); 347 MaybeEndReveal(ANIMATE_FAST);
195 } 348 }
196 349
350 void ImmersiveModeControllerAsh::MaybeRevealWithoutAnimation() {
351 MaybeStartReveal(ANIMATE_NO);
352 }
353
197 void ImmersiveModeControllerAsh::Init(BrowserView* browser_view) { 354 void ImmersiveModeControllerAsh::Init(BrowserView* browser_view) {
198 browser_view_ = browser_view; 355 browser_view_ = browser_view;
199 // Browser view is detached from its widget during destruction. Cache the 356 // Browser view is detached from its widget during destruction. Cache the
200 // window pointer so |this| can stop observing during destruction. 357 // window pointer so |this| can stop observing during destruction.
201 native_window_ = browser_view_->GetNativeWindow(); 358 native_window_ = browser_view_->GetNativeWindow();
202 DCHECK(native_window_); 359 DCHECK(native_window_);
203 EnableWindowObservers(true); 360 EnableWindowObservers(true);
204 361
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. 362 // Optionally allow the tab indicators to be hidden.
211 hide_tab_indicators_ = CommandLine::ForCurrentProcess()-> 363 hide_tab_indicators_ = CommandLine::ForCurrentProcess()->
212 HasSwitch(ash::switches::kAshImmersiveHideTabIndicators); 364 HasSwitch(ash::switches::kAshImmersiveHideTabIndicators);
365
366 anchored_widget_manager_.reset(new AnchoredWidgetManager(this));
213 } 367 }
214 368
215 void ImmersiveModeControllerAsh::SetEnabled(bool enabled) { 369 void ImmersiveModeControllerAsh::SetEnabled(bool enabled) {
216 DCHECK(browser_view_) << "Must initialize before enabling"; 370 DCHECK(browser_view_) << "Must initialize before enabling";
217 if (enabled_ == enabled) 371 if (enabled_ == enabled)
218 return; 372 return;
219 enabled_ = enabled; 373 enabled_ = enabled;
220 374
221 if (enabled_) { 375 if (enabled_) {
222 // Animate enabling immersive mode by sliding out the top-of-window views. 376 // 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. 377 // No animation occurs if a lock is holding the top-of-window views open.
224 378
225 // Do a reveal to set the initial state for the animation. (And any 379 // 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 380 // required state in case the animation cannot run because of a lock holding
227 // the top-of-window views open.) 381 // the top-of-window views open.)
228 StartReveal(ANIMATE_NO); 382 MaybeStartReveal(ANIMATE_NO);
229 383
230 // Reset the mouse and the focus revealed locks so that they do not affect 384 // 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 385 // whether the top-of-window views are hidden. Reacquire the locks if ending
232 // the reveal is unsuccessful. 386 // the reveal is unsuccessful.
233 bool had_mouse_revealed_lock = (mouse_revealed_lock_.get() != NULL); 387 bool had_mouse_revealed_lock = (mouse_revealed_lock_.get() != NULL);
234 bool had_focus_revealed_lock = (focus_revealed_lock_.get() != NULL); 388 bool had_focus_revealed_lock = (focus_revealed_lock_.get() != NULL);
235 mouse_revealed_lock_.reset(); 389 mouse_revealed_lock_.reset();
236 focus_revealed_lock_.reset(); 390 focus_revealed_lock_.reset();
237 391
238 // Try doing the animation. 392 // Try doing the animation.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 if (reveal_layer) 442 if (reveal_layer)
289 reveal_layer->parent()->StackAtTop(reveal_layer); 443 reveal_layer->parent()->StackAtTop(reveal_layer);
290 } 444 }
291 } 445 }
292 446
293 ImmersiveModeControllerAsh::RevealedLock* 447 ImmersiveModeControllerAsh::RevealedLock*
294 ImmersiveModeControllerAsh::GetRevealedLock() { 448 ImmersiveModeControllerAsh::GetRevealedLock() {
295 return new RevealedLockAsh(weak_ptr_factory_.GetWeakPtr()); 449 return new RevealedLockAsh(weak_ptr_factory_.GetWeakPtr());
296 } 450 }
297 451
452 void ImmersiveModeControllerAsh::AnchorWidgetToTopContainer(
453 views::Widget* widget,
454 int y_offset) {
455 anchored_widget_manager_->AddAnchoredWidget(widget, y_offset);
456 }
457
458 void ImmersiveModeControllerAsh::UnanchorWidgetFromTopContainer(
459 views::Widget* widget) {
460 anchored_widget_manager_->RemoveAnchoredWidget(widget);
461 }
462
463 void ImmersiveModeControllerAsh::OnTopContainerBoundsChanged() {
464 anchored_widget_manager_->OnTopContainerBoundsChanged();
465 }
466
298 //////////////////////////////////////////////////////////////////////////////// 467 ////////////////////////////////////////////////////////////////////////////////
299 // Observers: 468 // Observers:
300 469
301 void ImmersiveModeControllerAsh::OnMouseEvent(ui::MouseEvent* event) { 470 void ImmersiveModeControllerAsh::OnMouseEvent(ui::MouseEvent* event) {
302 if (!enabled_) 471 if (!enabled_)
303 return; 472 return;
304 473
305 if (event->flags() & ui::EF_IS_SYNTHESIZED) 474 if (event->flags() & ui::EF_IS_SYNTHESIZED)
306 return; 475 return;
307 476
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 bool active) { 531 bool active) {
363 // Mouse hover should not initiate revealing the top-of-window views while 532 // Mouse hover should not initiate revealing the top-of-window views while
364 // |native_window_| is inactive. 533 // |native_window_| is inactive.
365 top_timer_.Stop(); 534 top_timer_.Stop();
366 535
367 UpdateMouseRevealedLock(true); 536 UpdateMouseRevealedLock(true);
368 UpdateFocusRevealedLock(); 537 UpdateFocusRevealedLock();
369 } 538 }
370 539
371 //////////////////////////////////////////////////////////////////////////////// 540 ////////////////////////////////////////////////////////////////////////////////
541 // Animation observer:
542
543 void ImmersiveModeControllerAsh::OnImplicitAnimationsCompleted() {
544 if (reveal_state_ == SLIDING_OPEN)
545 OnSlideOpenAnimationCompleted();
546 else if (reveal_state_ == SLIDING_CLOSED)
547 OnSlideClosedAnimationCompleted();
548 }
549
550 ////////////////////////////////////////////////////////////////////////////////
372 // Testing interface: 551 // Testing interface:
373 552
374 void ImmersiveModeControllerAsh::SetHideTabIndicatorsForTest(bool hide) { 553 void ImmersiveModeControllerAsh::SetHideTabIndicatorsForTest(bool hide) {
375 hide_tab_indicators_ = hide; 554 hide_tab_indicators_ = hide;
376 } 555 }
377 556
378 void ImmersiveModeControllerAsh::StartRevealForTest(bool hovered) { 557 void ImmersiveModeControllerAsh::StartRevealForTest(bool hovered) {
379 StartReveal(ANIMATE_NO); 558 MaybeStartReveal(ANIMATE_NO);
380 SetMouseHoveredForTest(hovered); 559 MoveMouse(browser_view_->top_container(), hovered);
560 UpdateMouseRevealedLock(false);
381 } 561 }
382 562
383 void ImmersiveModeControllerAsh::SetMouseHoveredForTest(bool hovered) { 563 void ImmersiveModeControllerAsh::SetMouseHoveredForTest(bool hovered) {
384 views::View* top_container = browser_view_->top_container(); 564 MoveMouse(browser_view_->top_container(), hovered);
385 gfx::Point cursor_pos;
386 if (!hovered) {
387 int bottom_edge = top_container->bounds().bottom();
388 cursor_pos = gfx::Point(0, bottom_edge + 100);
389 }
390 views::View::ConvertPointToScreen(top_container, &cursor_pos);
391 aura::Env::GetInstance()->set_last_mouse_location(cursor_pos);
392
393 UpdateMouseRevealedLock(false); 565 UpdateMouseRevealedLock(false);
394 } 566 }
395 567
396 //////////////////////////////////////////////////////////////////////////////// 568 ////////////////////////////////////////////////////////////////////////////////
397 // private: 569 // private:
398 570
399 void ImmersiveModeControllerAsh::EnableWindowObservers(bool enable) { 571 void ImmersiveModeControllerAsh::EnableWindowObservers(bool enable) {
400 if (!native_window_) { 572 if (!native_window_) {
401 DCHECK(!enable) << "ImmersiveModeControllerAsh not initialized"; 573 DCHECK(!enable) << "ImmersiveModeControllerAsh not initialized";
402 return; 574 return;
(...skipping 10 matching lines...) Expand all
413 focus_manager->RemoveFocusChangeListener(this); 585 focus_manager->RemoveFocusChangeListener(this);
414 } 586 }
415 587
416 if (enable) 588 if (enable)
417 native_window_->AddPreTargetHandler(this); 589 native_window_->AddPreTargetHandler(this);
418 else 590 else
419 native_window_->RemovePreTargetHandler(this); 591 native_window_->RemovePreTargetHandler(this);
420 592
421 // The window observer adds and removes itself from the native window. 593 // The window observer adds and removes itself from the native window.
422 window_observer_.reset(enable ? new WindowObserver(this) : NULL); 594 window_observer_.reset(enable ? new WindowObserver(this) : NULL);
595
596 if (!enable)
597 StopObservingImplicitAnimations();
423 } 598 }
424 599
425 void ImmersiveModeControllerAsh::UpdateMouseRevealedLock(bool maybe_drag) { 600 void ImmersiveModeControllerAsh::UpdateMouseRevealedLock(bool maybe_drag) {
426 if (!enabled_) 601 if (!enabled_)
427 return; 602 return;
428 603
429 // Hover cannot initiate a reveal when the top-of-window views are sliding 604 // Hover cannot initiate a reveal when the top-of-window views are sliding
430 // closed or are closed. (With the exception of hovering at y = 0 which is 605 // closed or are closed. (With the exception of hovering at y = 0 which is
431 // handled in OnMouseEvent() ). 606 // handled in OnMouseEvent() ).
432 if (reveal_state_ == SLIDING_CLOSED || reveal_state_ == CLOSED) 607 if (reveal_state_ == SLIDING_CLOSED || reveal_state_ == CLOSED)
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 return 0; 675 return 0;
501 case ANIMATE_SLOW: 676 case ANIMATE_SLOW:
502 return kRevealSlowAnimationDurationMs; 677 return kRevealSlowAnimationDurationMs;
503 case ANIMATE_FAST: 678 case ANIMATE_FAST:
504 return kRevealFastAnimationDurationMs; 679 return kRevealFastAnimationDurationMs;
505 } 680 }
506 NOTREACHED(); 681 NOTREACHED();
507 return 0; 682 return 0;
508 } 683 }
509 684
510 void ImmersiveModeControllerAsh::MaybeStartReveal() { 685 void ImmersiveModeControllerAsh::MaybeStartReveal(Animate animate) {
511 if (enabled_ && reveal_state_ != REVEALED) 686 if (!enabled_)
512 StartReveal(ANIMATE_FAST); 687 return;
513 }
514 688
515 void ImmersiveModeControllerAsh::StartReveal(Animate animate) { 689 // Callers with ANIMATE_NO expect this function to synchronously reveal the
516 if (reveal_state_ == CLOSED) { 690 // top-of-window views. In particular, this property is used to terminate the
517 reveal_state_ = SLIDING_OPEN; 691 // reveal animation if an equivalent animation for the anchored widgets
692 // cannot be created.
693 if (reveal_state_ == REVEALED ||
694 (reveal_state_ == SLIDING_OPEN && animate != ANIMATE_NO)) {
695 return;
696 }
697
698 RevealState previous_reveal_state = reveal_state_;
699 reveal_state_ = SLIDING_OPEN;
700 if (previous_reveal_state == CLOSED) {
518 // Turn on layer painting so we can smoothly animate. 701 // Turn on layer painting so we can smoothly animate.
519 EnablePaintToLayer(true); 702 EnablePaintToLayer(true);
520 703
521 // Ensure window caption buttons are updated and the view bounds are 704 // Ensure window caption buttons are updated and the view bounds are
522 // computed at normal (non-immersive-style) size. 705 // computed at normal (non-immersive-style) size.
523 LayoutBrowserView(false); 706 LayoutBrowserView(false);
524 707
708 // Do not do any more processing if LayoutBrowserView() changed
709 // |reveal_state_|.
710 if (reveal_state_ != SLIDING_OPEN)
711 return;
712
525 if (animate != ANIMATE_NO) { 713 if (animate != ANIMATE_NO) {
526 // Now that we have a layer, move it to the initial offscreen position. 714 // Now that we have a layer, move it to the initial offscreen position.
527 ui::Layer* layer = browser_view_->top_container()->layer(); 715 ui::Layer* layer = browser_view_->top_container()->layer();
528 gfx::Transform transform; 716 gfx::Transform transform;
529 transform.Translate(0, -layer->bounds().height() + kAnimationOffsetY); 717 transform.Translate(0, -layer->bounds().height() + kAnimationOffsetY);
530 layer->SetTransform(transform); 718 layer->SetTransform(transform);
719
720 typedef std::set<views::Widget*> WidgetSet;
721 const WidgetSet& visible_widgets =
722 anchored_widget_manager_->visible_anchored_widgets();
723 for (WidgetSet::const_iterator it = visible_widgets.begin();
724 it != visible_widgets.end(); ++it) {
725 (*it)->GetNativeWindow()->SetTransform(transform);
726 }
531 } 727 }
532 // Slide in the reveal view.
533 AnimateSlideOpen(GetAnimationDuration(animate));
534 } else if (reveal_state_ == SLIDING_CLOSED) {
535 reveal_state_ = SLIDING_OPEN;
536 // Reverse the animation.
537 AnimateSlideOpen(GetAnimationDuration(animate));
538 } 728 }
729 // Slide in the reveal view.
730 DoAnimation(gfx::Transform(), GetAnimationDuration(animate));
539 } 731 }
540 732
541 void ImmersiveModeControllerAsh::EnablePaintToLayer(bool enable) { 733 void ImmersiveModeControllerAsh::EnablePaintToLayer(bool enable) {
542 browser_view_->top_container()->SetPaintToLayer(enable); 734 browser_view_->top_container()->SetPaintToLayer(enable);
543 735
544 // Views software compositing is not fully layer aware. If the bookmark bar 736 // Views software compositing is not fully layer aware. If the bookmark bar
545 // is detached while the top container layer slides on or off the screen, 737 // is detached while the top container layer slides on or off the screen,
546 // the pixels that become exposed are the remnants of the last software 738 // the pixels that become exposed are the remnants of the last software
547 // composite of the BrowserView, not the freshly-exposed bookmark bar. 739 // composite of the BrowserView, not the freshly-exposed bookmark bar.
548 // Force the bookmark bar to paint to a layer so the views composite 740 // Force the bookmark bar to paint to a layer so the views composite
549 // properly. The infobar container does not need this treatment because 741 // properly. The infobar container does not need this treatment because
550 // BrowserView::PaintChildren() always draws it last when it is visible. 742 // BrowserView::PaintChildren() always draws it last when it is visible.
551 BookmarkBarView* bookmark_bar = browser_view_->bookmark_bar(); 743 BookmarkBarView* bookmark_bar = browser_view_->bookmark_bar();
552 if (!bookmark_bar) 744 if (!bookmark_bar)
553 return; 745 return;
554 if (enable && bookmark_bar->IsDetached()) 746 if (enable && bookmark_bar->IsDetached())
555 bookmark_bar->SetPaintToLayer(true); 747 bookmark_bar->SetPaintToLayer(true);
556 else 748 else
557 bookmark_bar->SetPaintToLayer(false); 749 bookmark_bar->SetPaintToLayer(false);
558 } 750 }
559 751
560 void ImmersiveModeControllerAsh::LayoutBrowserView(bool immersive_style) { 752 void ImmersiveModeControllerAsh::LayoutBrowserView(bool immersive_style) {
561 // Update the window caption buttons. 753 // Update the window caption buttons.
562 browser_view_->GetWidget()->non_client_view()->frame_view()-> 754 browser_view_->GetWidget()->non_client_view()->frame_view()->
563 ResetWindowControls(); 755 ResetWindowControls();
564 browser_view_->tabstrip()->SetImmersiveStyle(immersive_style); 756 browser_view_->tabstrip()->SetImmersiveStyle(immersive_style);
565 browser_view_->frame()->GetRootView()->Layout(); 757 browser_view_->frame()->GetRootView()->Layout();
566 } 758 }
567 759
568 void ImmersiveModeControllerAsh::AnimateSlideOpen(int duration_ms) { 760 void ImmersiveModeControllerAsh::OnSlideOpenAnimationCompleted() {
569 ui::Layer* layer = browser_view_->top_container()->layer(); 761 DCHECK_EQ(SLIDING_OPEN, reveal_state_);
570 // Stop any slide closed animation in progress. 762 reveal_state_ = REVEALED;
571 layer->GetAnimator()->AbortAllAnimations();
572 763
573 ui::ScopedLayerAnimationSettings settings(layer->GetAnimator()); 764 // The user may not have moved the mouse since the reveal was initiated.
574 settings.AddObserver(slide_open_observer_.get()); 765 // Update the revealed lock to reflect the mouse's current state.
575 settings.SetTweenType(ui::Tween::EASE_OUT); 766 UpdateMouseRevealedLock(true);
576 settings.SetTransitionDuration(
577 base::TimeDelta::FromMilliseconds(duration_ms));
578 layer->SetTransform(gfx::Transform());
579 } 767 }
580 768
581 void ImmersiveModeControllerAsh::OnSlideOpenAnimationCompleted() { 769 void ImmersiveModeControllerAsh::MaybeEndReveal(Animate animate) {
582 if (reveal_state_ == SLIDING_OPEN) { 770 if (!enabled_ || revealed_lock_count_ != 0)
583 reveal_state_ = REVEALED; 771 return;
584 772
585 // The user may not have moved the mouse since the reveal was initiated. 773 // Callers with ANIMATE_NO expect this function to synchronously close the
586 // Update the revealed lock to reflect the mouse's current state. 774 // top-of-window views.
587 UpdateMouseRevealedLock(true); 775 if (reveal_state_ == CLOSED ||
776 (reveal_state_ == SLIDING_CLOSED && animate != ANIMATE_NO)) {
777 return;
778 }
779
780 // Visible anchored widgets keep the top-of-window views revealed.
781 DCHECK(anchored_widget_manager_->visible_anchored_widgets().empty());
782
783 reveal_state_ = SLIDING_CLOSED;
784 int duration_ms = GetAnimationDuration(animate);
785 if (duration_ms > 0) {
786 // The bookmark bar may have become detached during the reveal so ensure
787 // layers are available. This is a no-op for the top container.
788 EnablePaintToLayer(true);
789
790 ui::Layer* top_container_layer = browser_view_->top_container()->layer();
791 gfx::Transform target_transform;
792 target_transform.Translate(0,
793 -top_container_layer->bounds().height() + kAnimationOffsetY);
794
795 DoAnimation(target_transform, duration_ms);
796 } else {
797 OnSlideClosedAnimationCompleted();
588 } 798 }
589 } 799 }
590 800
591 void ImmersiveModeControllerAsh::MaybeEndReveal(Animate animate) { 801 void ImmersiveModeControllerAsh::OnSlideClosedAnimationCompleted() {
592 if (enabled_ && reveal_state_ != CLOSED && revealed_lock_count_ == 0) 802 DCHECK_EQ(SLIDING_CLOSED, reveal_state_);
593 EndReveal(animate); 803 reveal_state_ = CLOSED;
804 // Layers aren't needed after animation completes.
805 EnablePaintToLayer(false);
806 // Update tabstrip for closed state.
807 LayoutBrowserView(true);
594 } 808 }
595 809
596 void ImmersiveModeControllerAsh::EndReveal(Animate animate) { 810 void ImmersiveModeControllerAsh::DoAnimation(
597 if (reveal_state_ == SLIDING_OPEN || reveal_state_ == REVEALED) { 811 const gfx::Transform& target_transform,
598 reveal_state_ = SLIDING_CLOSED; 812 int duration_ms) {
599 int duration_ms = GetAnimationDuration(animate); 813 StopObservingImplicitAnimations();
600 if (duration_ms > 0) { 814 DoLayerAnimation(browser_view_->top_container()->layer(), target_transform,
601 // Bookmark bar have become detached during the reveal so ensure 815 duration_ms, this);
602 // layers are available. This is a no-op for top container. 816
603 EnablePaintToLayer(true); 817 typedef std::set<views::Widget*> WidgetSet;
604 AnimateSlideClosed(duration_ms); 818 const WidgetSet& visible_widgets =
605 } else { 819 anchored_widget_manager_->visible_anchored_widgets();
606 OnSlideClosedAnimationCompleted(); 820 for (WidgetSet::const_iterator it = visible_widgets.begin();
607 } 821 it != visible_widgets.end(); ++it) {
822 // The anchored widget's bounds are set to the target bounds right when the
823 // animation starts. The transform is used to animate the widget's position.
824 // Using the target bounds allows us to "stay anchored" if other code
825 // changes the widget bounds in the middle of the animation. (This is the
826 // case if the fullscreen exit bubble type is changed during the immersive
827 // reveal animation).
828 DoLayerAnimation((*it)->GetNativeWindow()->layer(), gfx::Transform(),
829 duration_ms, NULL);
608 } 830 }
609 } 831 }
610 832
611 void ImmersiveModeControllerAsh::AnimateSlideClosed(int duration_ms) { 833 void ImmersiveModeControllerAsh::DoLayerAnimation(
612 // Stop any slide open animation in progress, but don't skip to the end. This 834 ui::Layer* layer,
613 // avoids a visual "pop" when starting a hide in the middle of a show. 835 const gfx::Transform& target_transform,
614 ui::Layer* layer = browser_view_->top_container()->layer(); 836 int duration_ms,
615 layer->GetAnimator()->AbortAllAnimations(); 837 ui::ImplicitAnimationObserver* observer) {
616
617 ui::ScopedLayerAnimationSettings settings(layer->GetAnimator()); 838 ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
618 settings.SetTweenType(ui::Tween::EASE_OUT); 839 settings.SetTweenType(ui::Tween::EASE_OUT);
619 settings.SetTransitionDuration( 840 settings.SetTransitionDuration(
620 base::TimeDelta::FromMilliseconds(duration_ms)); 841 base::TimeDelta::FromMilliseconds(duration_ms));
621 settings.AddObserver(slide_closed_observer_.get()); 842 settings.SetPreemptionStrategy(
622 gfx::Transform transform; 843 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
623 transform.Translate(0, -layer->bounds().height() + kAnimationOffsetY); 844 if (observer)
624 layer->SetTransform(transform); 845 settings.AddObserver(observer);
846 layer->SetTransform(target_transform);
625 } 847 }
626
627 void ImmersiveModeControllerAsh::OnSlideClosedAnimationCompleted() {
628 if (reveal_state_ == SLIDING_CLOSED) {
629 reveal_state_ = CLOSED;
630 // Layers aren't needed after animation completes.
631 EnablePaintToLayer(false);
632 // Update tabstrip for closed state.
633 LayoutBrowserView(true);
634 }
635 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698