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

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 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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698