| 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 e9599b1bae16833fa80e066823c57c6e8ea3b348..d9a84eb665257706275c62d95784752b36da81c5 100644
|
| --- a/chrome/browser/ui/views/fullscreen_exit_bubble_views.cc
|
| +++ b/chrome/browser/ui/views/fullscreen_exit_bubble_views.cc
|
| @@ -7,6 +7,12 @@
|
| #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/browser_view.h"
|
| +#include "chrome/browser/ui/views/frame/immersive_mode_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"
|
| @@ -249,19 +255,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_);
|
| @@ -273,7 +280,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();
|
| @@ -286,10 +293,25 @@ 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);
|
| + ImmersiveModeController* immersive_controller =
|
| + browser_view_->immersive_mode_controller();
|
| + // |immersive_controller| may already have been destroyed.
|
| + if (immersive_controller)
|
| + immersive_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
|
| @@ -319,12 +341,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);
|
| + } else {
|
| + immersive_controller->UnanchorWidgetFromTopContainer(popup_);
|
| + }
|
| +
|
| + UpdateMouseWatcher();
|
| +}
|
| +
|
| +void FullscreenExitBubbleViews::UpdateBounds() {
|
| gfx::Rect popup_rect(GetPopupRect(false));
|
| if (popup_rect.IsEmpty()) {
|
| popup_->Hide();
|
| @@ -335,6 +413,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);
|
| @@ -343,56 +440,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();
|
| }
|
|
|