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

Unified Diff: chrome/browser/ui/views/fullscreen_exit_bubble_views.cc

Issue 13866033: Animate the fullscreen exit bubble's opacity instead of its bounds when in immersive fullscreen (Closed) Base URL: http://git.chromium.org/chromium/src.git@exit_bubble
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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/views/fullscreen_exit_bubble_views.cc
diff --git a/chrome/browser/ui/views/fullscreen_exit_bubble_views.cc b/chrome/browser/ui/views/fullscreen_exit_bubble_views.cc
index f0be06d4f394b89f7e7fa57b9f4751335d2d3d63..981063144bf58d6dbdd4140e0e5109668ed02cc2 100644
--- a/chrome/browser/ui/views/fullscreen_exit_bubble_views.cc
+++ b/chrome/browser/ui/views/fullscreen_exit_bubble_views.cc
@@ -7,6 +7,10 @@
#include "base/message_loop.h"
#include "base/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
+#include "chrome/browser/ui/views/frame/top_container_view.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "content/public/browser/notification_service.h"
#include "googleurl/src/gurl.h"
#include "grit/generated_resources.h"
#include "grit/ui_strings.h"
@@ -243,19 +247,20 @@ void FullscreenExitBubbleViews::FullscreenExitView::UpdateContent(
// FullscreenExitBubbleViews ---------------------------------------------------
FullscreenExitBubbleViews::FullscreenExitBubbleViews(
- views::Widget* frame,
- Browser* browser,
+ BrowserView* browser_view,
const GURL& url,
FullscreenExitBubbleType bubble_type)
- : FullscreenExitBubble(browser, url, bubble_type),
- root_view_(frame->GetRootView()),
+ : FullscreenExitBubble(browser_view->browser(), url, bubble_type),
+ browser_view_(browser_view),
popup_(NULL),
- size_animation_(new ui::SlideAnimation(this)) {
- size_animation_->Reset(1);
+ animation_(new ui::SlideAnimation(this)),
+ animated_attribute_(ANIMATED_ATTRIBUTE_BOUNDS) {
+ animation_->Reset(1);
// Create the contents view.
ui::Accelerator accelerator(ui::VKEY_UNKNOWN, ui::EF_NONE);
- bool got_accelerator = frame->GetAccelerator(IDC_FULLSCREEN, &accelerator);
+ bool got_accelerator = browser_view_->GetWidget()->GetAccelerator(
+ IDC_FULLSCREEN, &accelerator);
DCHECK(got_accelerator);
view_ = new FullscreenExitView(
this, accelerator.GetShortcutText(), url, bubble_type_);
@@ -267,7 +272,7 @@ FullscreenExitBubbleViews::FullscreenExitBubbleViews(
params.transparent = true;
params.can_activate = false;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.parent = frame->GetNativeView();
+ params.parent = browser_view_->GetWidget()->GetNativeView();
params.bounds = GetPopupRect(false);
popup_->Init(params);
gfx::Size size = GetPopupRect(true).size();
@@ -280,10 +285,22 @@ FullscreenExitBubbleViews::FullscreenExitBubbleViews(
view_->SetBounds(0, 0, size.width(), size.height());
popup_->Show(); // This does not activate the popup.
- StartWatchingMouseIfNecessary();
+ popup_->AddObserver(this);
+
+ registrar_.Add(
+ this,
+ chrome::NOTIFICATION_FULLSCREEN_CHANGED,
+ content::Source<FullscreenController>(
+ browser_view_->browser()->fullscreen_controller()));
+
+ UpdateForImmersiveState();
}
FullscreenExitBubbleViews::~FullscreenExitBubbleViews() {
+ popup_->RemoveObserver(this);
+ browser_view_->immersive_mode_controller()->UnanchorWidgetFromTopContainer(
+ popup_);
+
// This is tricky. We may be in an ATL message handler stack, in which case
// the popup cannot be deleted yet. We also can't set the popup's ownership
// model to NATIVE_WIDGET_OWNS_WIDGET because if the user closed the last tab
@@ -313,12 +330,68 @@ void FullscreenExitBubbleViews::UpdateContent(
popup_->SetBounds(GetPopupRect(false));
Show();
+ // Stop watching the mouse even if UpdateMouseWatcher() will start watching
+ // it again so that the popup with the new content is visible for at least
+ // |kInitialDelayMs|.
StopWatchingMouse();
- StartWatchingMouseIfNecessary();
+
+ UpdateMouseWatcher();
}
-void FullscreenExitBubbleViews::AnimationProgressed(
- const ui::Animation* animation) {
+void FullscreenExitBubbleViews::UpdateMouseWatcher() {
+ bool should_watch_mouse = false;
+ if (popup_->IsVisible())
+ should_watch_mouse = !fullscreen_bubble::ShowButtonsForType(bubble_type_);
+ else
+ should_watch_mouse = CanMouseTriggerSlideIn();
+
+ if (should_watch_mouse == IsWatchingMouse())
+ return;
+
+ if (should_watch_mouse)
+ StartWatchingMouse();
+ else
+ StopWatchingMouse();
+}
+
+void FullscreenExitBubbleViews::UpdateForImmersiveState() {
+ ImmersiveModeController* immersive_controller =
+ browser_view_->immersive_mode_controller();
+
+ AnimatedAttribute expected_animated_attribute =
+ immersive_controller->IsEnabled() ?
+ ANIMATED_ATTRIBUTE_OPACITY : ANIMATED_ATTRIBUTE_BOUNDS;
+ if (animated_attribute_ != expected_animated_attribute) {
+ // If an animation is currently in progress, skip to the end because
+ // switching the animated attribute midway through the animation looks
+ // weird.
+ animation_->End();
+
+ animated_attribute_ = expected_animated_attribute;
+
+ // We may have finished hiding |popup_|. However, the bounds animation
+ // assumes |popup_| has the opacity when it is fully shown and the opacity
+ // animation assumes |popup_| has the bounds when |popup_| is fully shown.
+ if (animated_attribute_ == ANIMATED_ATTRIBUTE_BOUNDS)
+ popup_->SetOpacity(255);
+ else
+ UpdateBounds();
+ }
+
+ if (immersive_controller->IsEnabled()) {
+ // In immersive mode, anchor |popup_| to the top container. This repositions
+ // the top container so that it stays |kPopupTopPx| below the top container
+ // when the top container animates its position (top container reveals /
+ // unreveals) or the top container bounds change (eg bookmark bar is shown).
+ immersive_controller->AnchorWidgetToTopContainer(popup_, kPopupTopPx);
scheib 2013/04/10 22:23:19 I havn't fixed http://crbug.com/130098 because of
pkotwicz 2013/04/11 03:31:55 By design, AnchorWidgetToTopContainer() is a noop
+ } else {
+ immersive_controller->UnanchorWidgetFromTopContainer(popup_);
+ }
+
+ UpdateMouseWatcher();
+}
+
+void FullscreenExitBubbleViews::UpdateBounds() {
gfx::Rect popup_rect(GetPopupRect(false));
if (popup_rect.IsEmpty()) {
popup_->Hide();
@@ -329,6 +402,25 @@ void FullscreenExitBubbleViews::AnimationProgressed(
}
}
+views::View* FullscreenExitBubbleViews::GetBrowserRootView() const {
+ return browser_view_->GetWidget()->GetRootView();
+}
+
+void FullscreenExitBubbleViews::AnimationProgressed(
+ const ui::Animation* animation) {
+ if (animated_attribute_ == ANIMATED_ATTRIBUTE_OPACITY) {
+ int opacity = animation_->CurrentValueBetween(0, 255);
+ if (opacity == 0) {
+ popup_->Hide();
+ } else {
+ popup_->Show();
+ popup_->SetOpacity(opacity);
+ }
+ } else {
+ UpdateBounds();
+ }
+}
+
void FullscreenExitBubbleViews::AnimationEnded(
const ui::Animation* animation) {
AnimationProgressed(animation);
@@ -337,56 +429,84 @@ void FullscreenExitBubbleViews::AnimationEnded(
gfx::Rect FullscreenExitBubbleViews::GetPopupRect(
bool ignore_animation_state) const {
gfx::Size size(view_->GetPreferredSize());
- // NOTE: don't use the bounds of the root_view_. On linux changing window
+ // NOTE: don't use the bounds of the root_view_. On linux GTK changing window
// size is async. Instead we use the size of the screen.
gfx::Screen* screen =
- gfx::Screen::GetScreenFor(root_view_->GetWidget()->GetNativeView());
+ gfx::Screen::GetScreenFor(browser_view_->GetWidget()->GetNativeView());
gfx::Rect screen_bounds = screen->GetDisplayNearestWindow(
- root_view_->GetWidget()->GetNativeView()).bounds();
- gfx::Point origin(screen_bounds.x() +
- (screen_bounds.width() - size.width()) / 2,
- kPopupTopPx + screen_bounds.y());
- if (!ignore_animation_state) {
+ browser_view_->GetWidget()->GetNativeView()).bounds();
+ int x = screen_bounds.x() + (screen_bounds.width() - size.width()) / 2;
+
+ int top_container_bottom = screen_bounds.y();
+ if (browser_view_->immersive_mode_controller()->IsEnabled()) {
+ // Skip querying the top container height in non-immersive fullscreen
+ // because:
+ // - The top container height is always zero in non-immersive fullscreen.
+ // - Querying the top container height may return the height before entering
+ // fullscreen because layout is disabled while entering fullscreen.
+ // A visual glitch due to the delayed layout is avoided in immersive
+ // fullscreen because entering fullscreen starts with the top container
+ // revealed. When revealed, the top container has the same height as before
+ // entering fullscreen.
+ top_container_bottom =
+ browser_view_->top_container()->GetTargetBoundsInScreen().bottom();
+ }
+ int y = top_container_bottom + kPopupTopPx;
+
+ if (!ignore_animation_state &&
+ animated_attribute_ == ANIMATED_ATTRIBUTE_BOUNDS) {
int total_height = size.height() + kPopupTopPx;
- int popup_bottom = size_animation_->CurrentValueBetween(
- static_cast<double>(total_height), 0.0f);
+ int popup_bottom = animation_->CurrentValueBetween(total_height, 0);
int y_offset = std::min(popup_bottom, kPopupTopPx);
size.set_height(size.height() - popup_bottom + y_offset);
- origin.set_y(origin.y() - y_offset);
+ y -= y_offset;
}
- return gfx::Rect(origin, size);
+ return gfx::Rect(gfx::Point(x, y), size);
}
gfx::Point FullscreenExitBubbleViews::GetCursorScreenPoint() {
gfx::Point cursor_pos = gfx::Screen::GetScreenFor(
- root_view_->GetWidget()->GetNativeView())->GetCursorScreenPoint();
- views::View::ConvertPointToTarget(NULL, root_view_, &cursor_pos);
+ browser_view_->GetWidget()->GetNativeView())->GetCursorScreenPoint();
+ views::View::ConvertPointToTarget(NULL, GetBrowserRootView(), &cursor_pos);
return cursor_pos;
}
bool FullscreenExitBubbleViews::WindowContainsPoint(gfx::Point pos) {
- return root_view_->HitTestPoint(pos);
+ return GetBrowserRootView()->HitTestPoint(pos);
}
bool FullscreenExitBubbleViews::IsWindowActive() {
- return root_view_->GetWidget()->IsActive();
+ return browser_view_->GetWidget()->IsActive();
}
void FullscreenExitBubbleViews::Hide() {
- size_animation_->SetSlideDuration(kSlideOutDurationMs);
- size_animation_->Hide();
+ animation_->SetSlideDuration(kSlideOutDurationMs);
+ animation_->Hide();
}
void FullscreenExitBubbleViews::Show() {
- size_animation_->SetSlideDuration(kSlideInDurationMs);
- size_animation_->Show();
+ animation_->SetSlideDuration(kSlideInDurationMs);
+ animation_->Show();
}
bool FullscreenExitBubbleViews::IsAnimating() {
- return size_animation_->GetCurrentValue() != 0;
+ return animation_->is_animating();
}
-void FullscreenExitBubbleViews::StartWatchingMouseIfNecessary() {
- if (!fullscreen_bubble::ShowButtonsForType(bubble_type_))
- StartWatchingMouse();
+bool FullscreenExitBubbleViews::CanMouseTriggerSlideIn() const {
+ return !browser_view_->immersive_mode_controller()->IsEnabled();
+}
+
+ void FullscreenExitBubbleViews::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ DCHECK_EQ(chrome::NOTIFICATION_FULLSCREEN_CHANGED, type);
+ UpdateForImmersiveState();
+}
+
+void FullscreenExitBubbleViews::OnWidgetVisibilityChanged(
+ views::Widget* widget,
+ bool visible) {
+ UpdateMouseWatcher();
}

Powered by Google App Engine
This is Rietveld 408576698