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

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

Powered by Google App Engine
This is Rietveld 408576698