| 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 c48a4565b0a0394d04cb636789351b5968aebe6b..3fcb352a1322322f3c6ccfe9d22aebf8756bd908 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/bubble/bubble.h"
|
| #include "grit/generated_resources.h"
|
| #include "ui/base/animation/slide_animation.h"
|
| #include "ui/base/keycodes/keyboard_codes.h"
|
| @@ -14,6 +15,8 @@
|
| #include "ui/base/resource/resource_bundle.h"
|
| #include "ui/gfx/canvas_skia.h"
|
| #include "ui/gfx/screen.h"
|
| +#include "views/bubble/bubble_border.h"
|
| +#include "views/controls/button/text_button.h"
|
| #include "views/controls/link.h"
|
| #include "views/widget/widget.h"
|
|
|
| @@ -23,99 +26,199 @@
|
|
|
| // FullscreenExitView ----------------------------------------------------------
|
|
|
| -class FullscreenExitBubbleViews::FullscreenExitView : public views::View {
|
| +namespace {
|
| +// Space between the site info label and the buttons / link.
|
| +const int kMiddlePaddingPx = 30;
|
| +} // namespace
|
| +
|
| +class FullscreenExitBubbleViews::FullscreenExitView
|
| + : public views::View,
|
| + public views::ButtonListener {
|
| public:
|
| FullscreenExitView(FullscreenExitBubbleViews* bubble,
|
| - const std::wstring& accelerator);
|
| + const string16& accelerator,
|
| + const GURL& url,
|
| + bool ask_permission);
|
| virtual ~FullscreenExitView();
|
|
|
| // views::View
|
| virtual gfx::Size GetPreferredSize();
|
|
|
| + // views::ButtonListener
|
| + virtual void ButtonPressed(views::Button* sender, const views::Event& event);
|
| +
|
| + // Hide the accept and deny buttons, exposing the exit link.
|
| + void HideButtons();
|
| +
|
| private:
|
| + string16 GetMessage(const GURL& url);
|
| +
|
| // views::View
|
| virtual void Layout();
|
| - virtual void OnPaint(gfx::Canvas* canvas);
|
| +
|
| + FullscreenExitBubbleViews* bubble_;
|
|
|
| // Clickable hint text to show in the bubble.
|
| views::Link link_;
|
| + views::Label message_label_;
|
| + views::NativeTextButton* accept_button_;
|
| + views::NativeTextButton* deny_button_;
|
| +
|
| + bool show_buttons_;
|
| };
|
|
|
| FullscreenExitBubbleViews::FullscreenExitView::FullscreenExitView(
|
| FullscreenExitBubbleViews* bubble,
|
| - const std::wstring& accelerator) {
|
| + const string16& accelerator,
|
| + const GURL& url,
|
| + bool ask_permission)
|
| + : bubble_(bubble),
|
| + accept_button_(NULL),
|
| + deny_button_(NULL),
|
| + show_buttons_(ask_permission) {
|
| + views::BubbleBorder* bubble_border =
|
| + new views::BubbleBorder(views::BubbleBorder::NONE);
|
| + bubble_border->set_background_color(Bubble::kBackgroundColor);
|
| + set_background(new views::BubbleBackground(bubble_border));
|
| + set_border(bubble_border);
|
| + set_focusable(false);
|
| +
|
| + message_label_.set_parent_owned(false);
|
| + message_label_.SetText(GetMessage(url));
|
| + message_label_.SetFont(ResourceBundle::GetSharedInstance().GetFont(
|
| + ResourceBundle::MediumFont));
|
| +
|
| link_.set_parent_owned(false);
|
| + link_.set_collapse_when_hidden(false);
|
| + link_.set_focusable(false);
|
| #if !defined(OS_CHROMEOS)
|
| link_.SetText(
|
| l10n_util::GetStringFUTF16(IDS_EXIT_FULLSCREEN_MODE,
|
| - WideToUTF16(accelerator)));
|
| + accelerator));
|
| #else
|
| link_.SetText(l10n_util::GetStringUTF16(IDS_EXIT_FULLSCREEN_MODE));
|
| #endif
|
| link_.set_listener(bubble);
|
| link_.SetFont(ResourceBundle::GetSharedInstance().GetFont(
|
| - ResourceBundle::LargeFont));
|
| - link_.SetBackgroundColor(SK_ColorBLACK);
|
| - link_.SetEnabledColor(SK_ColorWHITE);
|
| - link_.SetPressedColor(SK_ColorWHITE);
|
| + ResourceBundle::MediumFont));
|
| + link_.SetPressedColor(message_label_.enabled_color());
|
| + link_.SetEnabledColor(message_label_.enabled_color());
|
| + link_.SetVisible(false);
|
| +
|
| + link_.SetBackgroundColor(background()->get_color());
|
| + message_label_.SetBackgroundColor(background()->get_color());
|
| + AddChildView(&message_label_);
|
| AddChildView(&link_);
|
| +
|
| + accept_button_ = new views::NativeTextButton(this,
|
| + UTF16ToWide(l10n_util::GetStringUTF16(IDS_FULLSCREEN_INFOBAR_ALLOW)));
|
| + accept_button_->set_focusable(false);
|
| + AddChildView(accept_button_);
|
| +
|
| + deny_button_ = new views::NativeTextButton(this,
|
| + UTF16ToWide(l10n_util::GetStringUTF16(IDS_FULLSCREEN_INFOBAR_DENY)));
|
| + deny_button_->set_focusable(false);
|
| + AddChildView(deny_button_);
|
| +
|
| + if (!show_buttons_)
|
| + HideButtons();
|
| +}
|
| +
|
| +string16 FullscreenExitBubbleViews::FullscreenExitView::GetMessage(
|
| + const GURL& url) {
|
| + if (url.is_empty()) {
|
| + return l10n_util::GetStringUTF16(
|
| + IDS_FULLSCREEN_INFOBAR_USER_ENTERED_FULLSCREEN);
|
| + }
|
| + if (url.SchemeIsFile())
|
| + return l10n_util::GetStringUTF16(IDS_FULLSCREEN_INFOBAR_FILE_PAGE_NAME);
|
| + return l10n_util::GetStringFUTF16(IDS_FULLSCREEN_INFOBAR_REQUEST_PERMISSION,
|
| + UTF8ToUTF16(url.host()));
|
| }
|
|
|
| FullscreenExitBubbleViews::FullscreenExitView::~FullscreenExitView() {
|
| }
|
|
|
| +void FullscreenExitBubbleViews::FullscreenExitView::ButtonPressed(
|
| + views::Button* sender, const views::Event& event) {
|
| + if (sender == accept_button_)
|
| + bubble_->OnAcceptFullscreen();
|
| + else
|
| + bubble_->OnCancelFullscreen();
|
| +}
|
| +
|
| +void FullscreenExitBubbleViews::FullscreenExitView::HideButtons() {
|
| + show_buttons_ = false;
|
| + accept_button_->SetVisible(false);
|
| + deny_button_->SetVisible(false);
|
| + link_.SetVisible(true);
|
| +}
|
| +
|
| gfx::Size FullscreenExitBubbleViews::FullscreenExitView::GetPreferredSize() {
|
| - gfx::Size preferred_size(link_.GetPreferredSize());
|
| - preferred_size.Enlarge(kPaddingPx * 2, kPaddingPx * 2);
|
| - return preferred_size;
|
| + gfx::Size link_size(link_.GetPreferredSize());
|
| + gfx::Size message_label_size(message_label_.GetPreferredSize());
|
| + gfx::Size accept_size(accept_button_->GetPreferredSize());
|
| + gfx::Size deny_size(deny_button_->GetPreferredSize());
|
| + gfx::Insets insets(GetInsets());
|
| +
|
| + int buttons_width = accept_size.width() + kPaddingPx +
|
| + deny_size.width();
|
| + int button_box_width = std::max(buttons_width, link_size.width());
|
| + int width = kPaddingPx + message_label_size.width() + kMiddlePaddingPx +
|
| + button_box_width + kPaddingPx;
|
| +
|
| + gfx::Size result(width + insets.width(),
|
| + kPaddingPx * 2 + accept_size.height() + insets.height());
|
| + return result;
|
| }
|
|
|
| void FullscreenExitBubbleViews::FullscreenExitView::Layout() {
|
| - gfx::Size link_preferred_size(link_.GetPreferredSize());
|
| - link_.SetBounds(kPaddingPx,
|
| - height() - kPaddingPx - link_preferred_size.height(),
|
| - link_preferred_size.width(), link_preferred_size.height());
|
| -}
|
| -
|
| -void FullscreenExitBubbleViews::FullscreenExitView::OnPaint(
|
| - gfx::Canvas* canvas) {
|
| - // Create a round-bottomed rect to fill the whole View.
|
| - SkRect rect;
|
| - SkScalar padding = SkIntToScalar(kPaddingPx);
|
| - // The "-padding" top coordinate ensures that the rect is always tall enough
|
| - // to contain the complete rounded corner radius. If we set this to 0, as the
|
| - // popup slides offscreen (in reality, squishes to 0 height), the corners will
|
| - // flatten out as the height becomes less than the corner radius.
|
| - rect.set(0, -padding, SkIntToScalar(width()), SkIntToScalar(height()));
|
| - SkScalar rad[8] = { 0, 0, 0, 0, padding, padding, padding, padding };
|
| - SkPath path;
|
| - path.addRoundRect(rect, rad, SkPath::kCW_Direction);
|
| -
|
| - // Fill it black.
|
| - SkPaint paint;
|
| - paint.setStyle(SkPaint::kFill_Style);
|
| - paint.setFlags(SkPaint::kAntiAlias_Flag);
|
| - paint.setColor(SK_ColorBLACK);
|
| - canvas->GetSkCanvas()->drawPath(path, paint);
|
| + gfx::Size link_size(link_.GetPreferredSize());
|
| + gfx::Size message_label_size(message_label_.GetPreferredSize());
|
| + gfx::Size accept_size(accept_button_->GetPreferredSize());
|
| + gfx::Size deny_size(deny_button_->GetPreferredSize());
|
| + gfx::Insets insets(GetInsets());
|
| +
|
| + int inner_height = height() - insets.height();
|
| + int button_box_x = insets.left() + kPaddingPx +
|
| + message_label_size.width() + kMiddlePaddingPx;
|
| + int message_label_y = insets.top() +
|
| + (inner_height - message_label_size.height()) / 2;
|
| + int link_x = width() - insets.right() - kPaddingPx -
|
| + link_size.width();
|
| + int link_y = insets.top() + (inner_height - link_size.height()) / 2;
|
| +
|
| + message_label_.SetPosition(gfx::Point(insets.left() + kPaddingPx,
|
| + message_label_y));
|
| + link_.SetPosition(gfx::Point(link_x, link_y));
|
| + if (show_buttons_) {
|
| + accept_button_->SetPosition(gfx::Point(button_box_x,
|
| + insets.top() + kPaddingPx));
|
| + deny_button_->SetPosition(gfx::Point(
|
| + button_box_x + accept_size.width() + kPaddingPx,
|
| + insets.top() + kPaddingPx));
|
| + }
|
| }
|
|
|
| // FullscreenExitBubbleViews ---------------------------------------------------
|
|
|
| -FullscreenExitBubbleViews::FullscreenExitBubbleViews(
|
| - views::Widget* frame,
|
| - CommandUpdater::CommandUpdaterDelegate* delegate)
|
| - : FullscreenExitBubble(delegate),
|
| +FullscreenExitBubbleViews::FullscreenExitBubbleViews(views::Widget* frame,
|
| + Browser* browser,
|
| + const GURL& url,
|
| + bool ask_permission)
|
| + : FullscreenExitBubble(browser),
|
| root_view_(frame->GetRootView()),
|
| popup_(NULL),
|
| - size_animation_(new ui::SlideAnimation(this)) {
|
| + size_animation_(new ui::SlideAnimation(this)),
|
| + url_(url) {
|
| size_animation_->Reset(1);
|
|
|
| // Create the contents view.
|
| views::Accelerator accelerator(ui::VKEY_UNKNOWN, false, false, false);
|
| bool got_accelerator = frame->GetAccelerator(IDC_FULLSCREEN, &accelerator);
|
| DCHECK(got_accelerator);
|
| - view_ = new FullscreenExitView(
|
| - this, UTF16ToWideHack(accelerator.GetShortcutText()));
|
| + view_ = new FullscreenExitView(this,
|
| + accelerator.GetShortcutText(), url, ask_permission);
|
|
|
| // Initialize the popup.
|
| popup_ = new views::Widget;
|
| @@ -126,11 +229,18 @@ FullscreenExitBubbleViews::FullscreenExitBubbleViews(
|
| params.parent = frame->GetNativeView();
|
| params.bounds = GetPopupRect(false);
|
| popup_->Init(params);
|
| + gfx::Size size = GetPopupRect(true).size();
|
| popup_->SetContentsView(view_);
|
| - popup_->SetOpacity(static_cast<unsigned char>(0xff * kOpacity));
|
| + // 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.
|
|
|
| - StartWatchingMouse();
|
| + if (!ask_permission)
|
| + StartWatchingMouse();
|
| }
|
|
|
| FullscreenExitBubbleViews::~FullscreenExitBubbleViews() {
|
| @@ -152,6 +262,16 @@ void FullscreenExitBubbleViews::LinkClicked(
|
| ToggleFullscreen();
|
| }
|
|
|
| +void FullscreenExitBubbleViews::OnAcceptFullscreen() {
|
| + AcceptFullscreen(url_);
|
| + view_->HideButtons();
|
| + StartWatchingMouse();
|
| +}
|
| +
|
| +void FullscreenExitBubbleViews::OnCancelFullscreen() {
|
| + CancelFullscreen();
|
| +}
|
| +
|
| void FullscreenExitBubbleViews::AnimationProgressed(
|
| const ui::Animation* animation) {
|
| gfx::Rect popup_rect(GetPopupRect(false));
|
| @@ -159,9 +279,11 @@ void FullscreenExitBubbleViews::AnimationProgressed(
|
| popup_->Hide();
|
| } else {
|
| popup_->SetBounds(popup_rect);
|
| + view_->SetY(popup_rect.height() - view_->height());
|
| popup_->Show();
|
| }
|
| }
|
| +
|
| void FullscreenExitBubbleViews::AnimationEnded(
|
| const ui::Animation* animation) {
|
| AnimationProgressed(animation);
|
| @@ -199,16 +321,20 @@ gfx::Point FullscreenExitBubbleViews::GetCursorScreenPoint() {
|
| gfx::Rect FullscreenExitBubbleViews::GetPopupRect(
|
| bool ignore_animation_state) const {
|
| gfx::Size size(view_->GetPreferredSize());
|
| - if (!ignore_animation_state) {
|
| - size.set_height(static_cast<int>(static_cast<double>(size.height()) *
|
| - size_animation_->GetCurrentValue()));
|
| - }
|
| // 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::Rect screen_bounds = gfx::Screen::GetMonitorAreaNearestWindow(
|
| root_view_->GetWidget()->GetNativeView());
|
| gfx::Point origin(screen_bounds.x() +
|
| (screen_bounds.width() - size.width()) / 2,
|
| - screen_bounds.y());
|
| + 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);
|
| + }
|
| return gfx::Rect(origin, size);
|
| }
|
|
|