| 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..23ebda358721a038f0f7365271110db47ccaf25c 100644
|
| --- a/chrome/browser/ui/views/fullscreen_exit_bubble_views.cc
|
| +++ b/chrome/browser/ui/views/fullscreen_exit_bubble_views.cc
|
| @@ -7,6 +7,7 @@
|
| #include "base/message_loop.h"
|
| #include "base/utf_string_conversions.h"
|
| #include "chrome/app/chrome_command_ids.h"
|
| +#include "chrome/browser/ui/views/frame/browser_view.h"
|
| #include "googleurl/src/gurl.h"
|
| #include "grit/generated_resources.h"
|
| #include "grit/ui_strings.h"
|
| @@ -16,14 +17,13 @@
|
| #include "ui/base/resource/resource_bundle.h"
|
| #include "ui/gfx/canvas.h"
|
| #include "ui/gfx/screen.h"
|
| -#include "ui/views/bubble/bubble_border.h"
|
| +#include "ui/views/bubble/bubble_delegate.h"
|
| +#include "ui/views/bubble/bubble_frame_view.h"
|
| #include "ui/views/controls/button/text_button.h"
|
| #include "ui/views/controls/link.h"
|
| #include "ui/views/controls/link_listener.h"
|
| #include "ui/views/layout/box_layout.h"
|
| #include "ui/views/layout/grid_layout.h"
|
| -#include "ui/views/view.h"
|
| -#include "ui/views/widget/widget.h"
|
|
|
| #if defined(OS_WIN)
|
| #include "ui/base/l10n/l10n_util_win.h"
|
| @@ -73,19 +73,63 @@ gfx::Size ButtonView::GetPreferredSize() {
|
| return visible() ? views::View::GetPreferredSize() : gfx::Size();
|
| }
|
|
|
| +// A custom BubbleFrameView that clips its drawing area to a specific display.
|
| +class ClippedBubbleFrameView : public views::BubbleFrameView {
|
| + public:
|
| + explicit ClippedBubbleFrameView(const gfx::Insets& margins,
|
| + const gfx::Rect display);
|
| + ~ClippedBubbleFrameView();
|
| +
|
| + // views::BubbleFrameView
|
| + virtual void Paint(gfx::Canvas* canvas) OVERRIDE;
|
| +
|
| + private:
|
| + // The display bounds to which this view is clipped, in screen coordinates.
|
| + gfx::Rect display_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ClippedBubbleFrameView);
|
| +};
|
| +
|
| +ClippedBubbleFrameView::ClippedBubbleFrameView(const gfx::Insets& margins,
|
| + const gfx::Rect display)
|
| + : BubbleFrameView(margins),
|
| + display_(display) {
|
| +}
|
| +
|
| +ClippedBubbleFrameView::~ClippedBubbleFrameView() {}
|
| +
|
| +void ClippedBubbleFrameView::Paint(gfx::Canvas* canvas) {
|
| + gfx::Point screen_top = display_.origin();
|
| + ConvertPointToTarget(NULL, this, &screen_top);
|
| + if (screen_top.y() > 0) {
|
| + // Clip the canvas to avoid drawing the bubble frame on other displays.
|
| + canvas->Save();
|
| + canvas->ClipRect(gfx::Rect(0, screen_top.y(), width(), height()));
|
| + BubbleFrameView::Paint(canvas);
|
| + canvas->Restore();
|
| + } else {
|
| + BubbleFrameView::Paint(canvas);
|
| + }
|
| +}
|
| +
|
| } // namespace
|
|
|
| class FullscreenExitBubbleViews::FullscreenExitView
|
| - : public views::View,
|
| + : public views::BubbleDelegateView,
|
| public views::ButtonListener,
|
| public views::LinkListener {
|
| public:
|
| FullscreenExitView(FullscreenExitBubbleViews* bubble,
|
| - const string16& accelerator,
|
| + views::Widget* frame,
|
| const GURL& url,
|
| FullscreenExitBubbleType bubble_type);
|
| virtual ~FullscreenExitView();
|
|
|
| + // views::BubbleDelegateView
|
| + virtual views::NonClientFrameView* CreateNonClientFrameView(
|
| + views::Widget* widget) OVERRIDE;
|
| + virtual void Paint(gfx::Canvas* canvas) OVERRIDE;
|
| +
|
| // views::ButtonListener
|
| virtual void ButtonPressed(views::Button* sender,
|
| const ui::Event& event) OVERRIDE;
|
| @@ -95,6 +139,10 @@ class FullscreenExitBubbleViews::FullscreenExitView
|
|
|
| void UpdateContent(const GURL& url, FullscreenExitBubbleType bubble_type);
|
|
|
| + // Schedule a paint to update the clip rects and properly clip the bubble view
|
| + // and bubble frame to the bounds of the fullscreen display.
|
| + void ScheduleClippedPaint();
|
| +
|
| private:
|
| FullscreenExitBubbleViews* bubble_;
|
|
|
| @@ -105,27 +153,26 @@ class FullscreenExitBubbleViews::FullscreenExitView
|
| // Informational label: 'www.foo.com has gone fullscreen'.
|
| views::Label* message_label_;
|
| ButtonView* button_view_;
|
| - const string16 browser_fullscreen_exit_accelerator_;
|
| + string16 browser_fullscreen_exit_accelerator_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(FullscreenExitView);
|
| };
|
|
|
| FullscreenExitBubbleViews::FullscreenExitView::FullscreenExitView(
|
| FullscreenExitBubbleViews* bubble,
|
| - const string16& accelerator,
|
| + views::Widget* frame,
|
| const GURL& url,
|
| FullscreenExitBubbleType bubble_type)
|
| : bubble_(bubble),
|
| link_(NULL),
|
| mouse_lock_exit_instruction_(NULL),
|
| message_label_(NULL),
|
| - button_view_(NULL),
|
| - browser_fullscreen_exit_accelerator_(accelerator) {
|
| - views::BubbleBorder* bubble_border = new views::BubbleBorder(
|
| - views::BubbleBorder::NONE, views::BubbleBorder::SHADOW, SK_ColorWHITE);
|
| - set_background(new views::BubbleBackground(bubble_border));
|
| - set_border(bubble_border);
|
| - set_focusable(false);
|
| + button_view_(NULL) {
|
| + set_parent_window(frame->GetNativeView());
|
| + set_arrow_location(views::BubbleBorder::NONE);
|
| + set_shadow(views::BubbleBorder::SHADOW);
|
| + set_adjust_if_offscreen(false);
|
| + set_use_focusless(true);
|
|
|
| ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| message_label_ = new views::Label();
|
| @@ -180,12 +227,41 @@ FullscreenExitBubbleViews::FullscreenExitView::FullscreenExitView(
|
| layout->SetInsets(padding);
|
| SetLayoutManager(layout);
|
|
|
| + ui::Accelerator accelerator;
|
| + bool got_accelerator = frame->GetAccelerator(IDC_FULLSCREEN, &accelerator);
|
| + DCHECK(got_accelerator);
|
| + browser_fullscreen_exit_accelerator_ = accelerator.GetShortcutText();
|
| +
|
| UpdateContent(url, bubble_type);
|
| }
|
|
|
| FullscreenExitBubbleViews::FullscreenExitView::~FullscreenExitView() {
|
| }
|
|
|
| +views::NonClientFrameView*
|
| +FullscreenExitBubbleViews::FullscreenExitView::CreateNonClientFrameView(
|
| + views::Widget* widget) {
|
| + ClippedBubbleFrameView* frame =
|
| + new ClippedBubbleFrameView(margins(), bubble_->display_bounds());
|
| + frame->SetBubbleBorder(
|
| + new views::BubbleBorder(arrow_location(), shadow(), color()));
|
| + return frame;
|
| +}
|
| +
|
| +void FullscreenExitBubbleViews::FullscreenExitView::Paint(gfx::Canvas* canvas) {
|
| + gfx::Point screen_top = bubble_->display_bounds().origin();
|
| + ConvertPointFromScreen(this, &screen_top);
|
| + if (screen_top.y() > 0) {
|
| + // Clip the canvas to avoid drawing the bubble contents on other displays.
|
| + canvas->Save();
|
| + canvas->ClipRect(gfx::Rect(0, screen_top.y(), width(), height()));
|
| + BubbleDelegateView::Paint(canvas);
|
| + canvas->Restore();
|
| + } else {
|
| + BubbleDelegateView::Paint(canvas);
|
| + }
|
| +}
|
| +
|
| void FullscreenExitBubbleViews::FullscreenExitView::ButtonPressed(
|
| views::Button* sender,
|
| const ui::Event& event) {
|
| @@ -239,62 +315,36 @@ void FullscreenExitBubbleViews::FullscreenExitView::UpdateContent(
|
| }
|
| }
|
|
|
| +void FullscreenExitBubbleViews::FullscreenExitView::ScheduleClippedPaint() {
|
| + SchedulePaint();
|
| + GetBubbleFrameView()->SchedulePaint();
|
| +}
|
|
|
| // 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()),
|
| - popup_(NULL),
|
| - size_animation_(new ui::SlideAnimation(this)) {
|
| - size_animation_->Reset(1);
|
| -
|
| - // Create the contents view.
|
| - ui::Accelerator accelerator(ui::VKEY_UNKNOWN, ui::EF_NONE);
|
| - bool got_accelerator = frame->GetAccelerator(IDC_FULLSCREEN, &accelerator);
|
| - DCHECK(got_accelerator);
|
| + : FullscreenExitBubble(browser_view->browser(), url, bubble_type),
|
| + browser_view_(browser_view),
|
| + animation_(new ui::SlideAnimation(this)) {
|
| + // Cache the display bounds for popup rect calculations.
|
| + const gfx::NativeView view = browser_view->GetWidget()->GetNativeView();
|
| + const gfx::Screen* screen = gfx::Screen::GetScreenFor(view);
|
| + display_ = screen->GetDisplayNearestWindow(view).bounds();
|
| +
|
| + animation_->Reset(1);
|
| view_ = new FullscreenExitView(
|
| - this, accelerator.GetShortcutText(), url, bubble_type_);
|
| -
|
| - // TODO(yzshen): Change to use the new views bubble, BubbleDelegateView.
|
| - // Initialize the popup.
|
| - popup_ = new views::Widget;
|
| - views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
|
| - params.transparent = true;
|
| - params.can_activate = false;
|
| - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
|
| - params.parent = frame->GetNativeView();
|
| - params.bounds = GetPopupRect(false);
|
| - popup_->Init(params);
|
| - gfx::Size size = GetPopupRect(true).size();
|
| - popup_->SetContentsView(view_);
|
| - // We set layout manager to NULL to prevent the widget from sizing its
|
| - // contents to the same size as itself. This prevents the widget contents from
|
| - // shrinking while we animate the height of the popup to give the impression
|
| - // that it is sliding off the top of the screen.
|
| - popup_->GetRootView()->SetLayoutManager(NULL);
|
| - view_->SetBounds(0, 0, size.width(), size.height());
|
| - popup_->Show(); // This does not activate the popup.
|
| -
|
| + this, browser_view->GetWidget(), url, bubble_type_);
|
| + views::Widget* bubble = views::BubbleDelegateView::CreateBubble(view_);
|
| + bubble->Show();
|
| + bubble->SetBounds(GetPopupRect(true));
|
| StartWatchingMouseIfNecessary();
|
| }
|
|
|
| FullscreenExitBubbleViews::~FullscreenExitBubbleViews() {
|
| - // 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
|
| - // while in fullscreen mode, Windows has already destroyed the popup HWND by
|
| - // the time we get here, and thus either the popup will already have been
|
| - // deleted (if we set this in our constructor) or the popup will never get
|
| - // another OnFinalMessage() call (if not, as currently). So instead, we tell
|
| - // the popup to synchronously hide, and then asynchronously close and delete
|
| - // itself.
|
| - popup_->Close();
|
| - MessageLoop::current()->DeleteSoon(FROM_HERE, popup_);
|
| + view_->GetWidget()->Close();
|
| }
|
|
|
| void FullscreenExitBubbleViews::UpdateContent(
|
| @@ -307,10 +357,6 @@ void FullscreenExitBubbleViews::UpdateContent(
|
| url_ = url;
|
| bubble_type_ = bubble_type;
|
| view_->UpdateContent(url_, bubble_type_);
|
| -
|
| - gfx::Size size = GetPopupRect(true).size();
|
| - view_->SetSize(size);
|
| - popup_->SetBounds(GetPopupRect(false));
|
| Show();
|
|
|
| StopWatchingMouse();
|
| @@ -319,14 +365,8 @@ void FullscreenExitBubbleViews::UpdateContent(
|
|
|
| void FullscreenExitBubbleViews::AnimationProgressed(
|
| const ui::Animation* animation) {
|
| - gfx::Rect popup_rect(GetPopupRect(false));
|
| - if (popup_rect.IsEmpty()) {
|
| - popup_->Hide();
|
| - } else {
|
| - popup_->SetBounds(popup_rect);
|
| - view_->SetY(popup_rect.height() - view_->height());
|
| - popup_->Show();
|
| - }
|
| + view_->GetWidget()->SetBounds(GetPopupRect(false));
|
| + view_->ScheduleClippedPaint();
|
| }
|
|
|
| void FullscreenExitBubbleViews::AnimationEnded(
|
| @@ -336,54 +376,41 @@ 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
|
| - // size is async. Instead we use the size of the screen.
|
| - gfx::Screen* screen =
|
| - gfx::Screen::GetScreenFor(root_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) {
|
| - int total_height = size.height() + kPopupTopPx;
|
| - int popup_bottom = size_animation_->CurrentValueBetween(
|
| - static_cast<double>(total_height), 0.0f);
|
| - int y_offset = std::min(popup_bottom, kPopupTopPx);
|
| - size.set_height(size.height() - popup_bottom + y_offset);
|
| - origin.set_y(origin.y() - y_offset);
|
| - }
|
| + const gfx::Size size(view_->GetWidget()->GetWindowBoundsInScreen().size());
|
| + const int offset = ignore_animation_state ? 0 :
|
| + animation_->CurrentValueBetween(size.height() + kPopupTopPx, 0);
|
| + const gfx::Point origin(display_.x() + (display_.width() - size.width()) / 2,
|
| + kPopupTopPx + display_.y() - offset);
|
| return gfx::Rect(origin, 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, browser_view_, &cursor_pos);
|
| return cursor_pos;
|
| }
|
|
|
| bool FullscreenExitBubbleViews::WindowContainsPoint(gfx::Point pos) {
|
| - return root_view_->HitTestPoint(pos);
|
| + return browser_view_->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_->GetCurrentValue() != 0;
|
| }
|
|
|
| void FullscreenExitBubbleViews::StartWatchingMouseIfNecessary() {
|
|
|