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

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