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

Side by Side Diff: chrome/browser/ui/views/fullscreen_exit_bubble_views.cc

Issue 7740044: Implement fullscreen info bubble on Win and Mac (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: win work Created 9 years, 2 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/fullscreen_exit_bubble_views.h" 5 #include "chrome/browser/ui/views/fullscreen_exit_bubble_views.h"
6 6
7 #include "base/message_loop.h" 7 #include "base/message_loop.h"
8 #include "base/utf_string_conversions.h" 8 #include "base/utf_string_conversions.h"
9 #include "chrome/app/chrome_command_ids.h" 9 #include "chrome/app/chrome_command_ids.h"
10 #include "chrome/browser/ui/views/bubble/bubble.h"
10 #include "grit/generated_resources.h" 11 #include "grit/generated_resources.h"
11 #include "ui/base/animation/slide_animation.h" 12 #include "ui/base/animation/slide_animation.h"
12 #include "ui/base/keycodes/keyboard_codes.h" 13 #include "ui/base/keycodes/keyboard_codes.h"
13 #include "ui/base/l10n/l10n_util.h" 14 #include "ui/base/l10n/l10n_util.h"
14 #include "ui/base/resource/resource_bundle.h" 15 #include "ui/base/resource/resource_bundle.h"
15 #include "ui/gfx/canvas_skia.h" 16 #include "ui/gfx/canvas_skia.h"
16 #include "ui/gfx/screen.h" 17 #include "ui/gfx/screen.h"
18 #include "views/bubble/bubble_border.h"
19 #include "views/controls/button/text_button.h"
17 #include "views/controls/link.h" 20 #include "views/controls/link.h"
18 #include "views/widget/widget.h" 21 #include "views/widget/widget.h"
19 22
20 #if defined(OS_WIN) 23 #if defined(OS_WIN)
21 #include "ui/base/l10n/l10n_util_win.h" 24 #include "ui/base/l10n/l10n_util_win.h"
22 #endif 25 #endif
23 26
24 // FullscreenExitView ---------------------------------------------------------- 27 // FullscreenExitView ----------------------------------------------------------
25 28
26 class FullscreenExitBubbleViews::FullscreenExitView : public views::View { 29 class FullscreenExitBubbleViews::FullscreenExitView : public views::View,
30 public views::ButtonListener {
27 public: 31 public:
28 FullscreenExitView(FullscreenExitBubbleViews* bubble, 32 FullscreenExitView(FullscreenExitBubbleViews* bubble,
29 const std::wstring& accelerator); 33 const std::wstring& accelerator,
34 const GURL& url,
35 bool show_buttons);
30 virtual ~FullscreenExitView(); 36 virtual ~FullscreenExitView();
31 37
32 // views::View 38 // views::View
33 virtual gfx::Size GetPreferredSize(); 39 virtual gfx::Size GetPreferredSize();
34 40
41 // views::ButtonListener
42 virtual void ButtonPressed(views::Button* sender, const views::Event& event);
43
44 virtual void HideButtons();
45
35 private: 46 private:
47 // Space between the site info label and the buttons / link.
48 static const int kMiddlePaddingPx = 30;
36 // views::View 49 // views::View
37 virtual void Layout(); 50 virtual void Layout();
38 virtual void OnPaint(gfx::Canvas* canvas); 51 // virtual void OnPaint(gfx::Canvas* canvas);
52
53 FullscreenExitBubbleViews* bubble_;
39 54
40 // Clickable hint text to show in the bubble. 55 // Clickable hint text to show in the bubble.
41 views::Link link_; 56 views::Link link_;
57 views::Label site_info_;
58 views::NativeTextButton* accept_button_;
59 views::NativeTextButton* deny_button_;
60
61 bool show_buttons_;
42 }; 62 };
43 63
44 FullscreenExitBubbleViews::FullscreenExitView::FullscreenExitView( 64 FullscreenExitBubbleViews::FullscreenExitView::FullscreenExitView(
45 FullscreenExitBubbleViews* bubble, 65 FullscreenExitBubbleViews* bubble,
46 const std::wstring& accelerator) { 66 const std::wstring& accelerator,
67 const GURL& url,
68 bool show_buttons)
69 : bubble_(bubble),
70 accept_button_(NULL),
71 deny_button_(NULL),
72 show_buttons_(show_buttons) {
47 link_.set_parent_owned(false); 73 link_.set_parent_owned(false);
74 link_.set_collapse_when_hidden(false);
75 link_.set_focusable(false);
48 #if !defined(OS_CHROMEOS) 76 #if !defined(OS_CHROMEOS)
49 link_.SetText( 77 link_.SetText(
50 UTF16ToWide(l10n_util::GetStringFUTF16(IDS_EXIT_FULLSCREEN_MODE, 78 UTF16ToWide(l10n_util::GetStringFUTF16(IDS_EXIT_FULLSCREEN_MODE,
51 WideToUTF16(accelerator)))); 79 WideToUTF16(accelerator))));
52 #else 80 #else
53 link_.SetText( 81 link_.SetText(
54 UTF16ToWide(l10n_util::GetStringUTF16(IDS_EXIT_FULLSCREEN_MODE))); 82 UTF16ToWide(l10n_util::GetStringUTF16(IDS_EXIT_FULLSCREEN_MODE)));
55 #endif 83 #endif
56 link_.set_listener(bubble); 84 link_.set_listener(bubble);
57 link_.SetFont(ResourceBundle::GetSharedInstance().GetFont( 85 link_.SetFont(ResourceBundle::GetSharedInstance().GetFont(
58 ResourceBundle::LargeFont)); 86 ResourceBundle::MediumFont));
59 link_.SetNormalColor(SK_ColorWHITE); 87 link_.SetNormalColor(SK_ColorBLACK);
60 link_.SetHighlightedColor(SK_ColorWHITE); 88 link_.SetHighlightedColor(SK_ColorBLACK);
89
90 site_info_.set_parent_owned(false);
91 site_info_.SetText(
92 UTF16ToWide(l10n_util::GetStringFUTF16(IDS_FULLSCREEN_INFOBAR_REQUEST_PERMIS SION,
93 UTF8ToUTF16(url.host()))));
94 site_info_.SetFont(ResourceBundle::GetSharedInstance().GetFont(
95 ResourceBundle::MediumFont));
96 AddChildView(&site_info_);
61 AddChildView(&link_); 97 AddChildView(&link_);
98
99 views::BubbleBorder* bubble_border = new views::BubbleBorder(views::BubbleBord er::NONE);
100 bubble_border->set_background_color(Bubble::kBackgroundColor);
101 set_background(new views::BubbleBackground(bubble_border));
102 set_border(bubble_border);
103
104 accept_button_ = new views::NativeTextButton(this,
105 UTF16ToWide(l10n_util::GetStringUTF16(IDS_FULLSCREEN_INFOBAR_ALLOW)));
106 AddChildView(accept_button_);
107
108 deny_button_ = new views::NativeTextButton(this,
109 UTF16ToWide(l10n_util::GetStringUTF16(IDS_FULLSCREEN_INFOBAR_DENY)));
110 AddChildView(deny_button_);
111 accept_button_->set_focusable(false);
112 deny_button_->set_focusable(false);
113 link_.SetVisible(false);
114 if (!show_buttons_) {
115 HideButtons();
116 }
62 } 117 }
63 118
64 FullscreenExitBubbleViews::FullscreenExitView::~FullscreenExitView() { 119 FullscreenExitBubbleViews::FullscreenExitView::~FullscreenExitView() {
65 } 120 }
66 121
122 void FullscreenExitBubbleViews::FullscreenExitView::ButtonPressed(
123 views::Button* sender, const views::Event& event) {
124 if (sender == accept_button_)
125 bubble_->OnAcceptFullscreen();
126 else
127 bubble_->OnCancelFullscreen();
128 }
129
130 void FullscreenExitBubbleViews::FullscreenExitView::HideButtons() {
131 show_buttons_ = false;
132 accept_button_->SetVisible(false);
133 deny_button_->SetVisible(false);
134 link_.SetVisible(true);
135 }
136
67 gfx::Size FullscreenExitBubbleViews::FullscreenExitView::GetPreferredSize() { 137 gfx::Size FullscreenExitBubbleViews::FullscreenExitView::GetPreferredSize() {
68 gfx::Size preferred_size(link_.GetPreferredSize()); 138 gfx::Size link_preferred_size(link_.GetPreferredSize());
69 preferred_size.Enlarge(kPaddingPx * 2, kPaddingPx * 2); 139 gfx::Size site_info_preferred_size(site_info_.GetPreferredSize());
70 return preferred_size; 140 gfx::Size accept_preferred_size(accept_button_->GetPreferredSize());
141 gfx::Size deny_preferred_size(deny_button_->GetPreferredSize());
142 gfx::Insets insets(GetInsets());
143
144 int buttons_width = accept_preferred_size.width() + kPaddingPx +
145 deny_preferred_size.width();
146 int button_box_width = std::max(buttons_width, link_preferred_size.width());
147 int width = kPaddingPx + site_info_preferred_size.width() + kMiddlePaddingPx +
148 button_box_width + kPaddingPx;
149
150 gfx::Size result(width + insets.width(),
151 kPaddingPx * 2 + accept_preferred_size.height() + insets.height());
152 return result;
71 } 153 }
72 154
73 void FullscreenExitBubbleViews::FullscreenExitView::Layout() { 155 void FullscreenExitBubbleViews::FullscreenExitView::Layout() {
74 gfx::Size link_preferred_size(link_.GetPreferredSize()); 156 gfx::Size link_preferred_size(link_.GetPreferredSize());
75 link_.SetBounds(kPaddingPx, 157 gfx::Size site_info_preferred_size(site_info_.GetPreferredSize());
76 height() - kPaddingPx - link_preferred_size.height(), 158 gfx::Size accept_preferred_size(accept_button_->GetPreferredSize());
159 gfx::Size deny_preferred_size(deny_button_->GetPreferredSize());
160 gfx::Insets insets(GetInsets());
161
162 int inner_height = height() - insets.height();
163 int button_box_x = insets.left() + kPaddingPx + site_info_preferred_size.width () +
164 kMiddlePaddingPx;
165 int site_info_y = insets.top() +
166 (inner_height - site_info_preferred_size.height()) / 2;
167 int link_y = insets.top() + (inner_height - link_preferred_size.height()) / 2;
168
169 site_info_.SetBounds(insets.left() + kPaddingPx,
170 site_info_y,
171 site_info_preferred_size.width(),
172 site_info_preferred_size.height());
173 link_.SetBounds(width() - insets.right() - kPaddingPx - link_preferred_size.wi dth(),
174 link_y,
77 link_preferred_size.width(), link_preferred_size.height()); 175 link_preferred_size.width(), link_preferred_size.height());
78 } 176 if (show_buttons_) {
79 177 accept_button_->SetBounds(button_box_x,
80 void FullscreenExitBubbleViews::FullscreenExitView::OnPaint( 178 insets.top() + kPaddingPx,
81 gfx::Canvas* canvas) { 179 accept_preferred_size.width(),
82 // Create a round-bottomed rect to fill the whole View. 180 accept_preferred_size.height());
83 SkRect rect; 181 deny_button_->SetBounds(
84 SkScalar padding = SkIntToScalar(kPaddingPx); 182 button_box_x + accept_preferred_size.width() + kPaddingPx,
85 // The "-padding" top coordinate ensures that the rect is always tall enough 183 insets.top() + kPaddingPx,
86 // to contain the complete rounded corner radius. If we set this to 0, as the 184 deny_preferred_size.width(),
87 // popup slides offscreen (in reality, squishes to 0 height), the corners will 185 deny_preferred_size.height());
88 // flatten out as the height becomes less than the corner radius. 186 }
89 rect.set(0, -padding, SkIntToScalar(width()), SkIntToScalar(height()));
90 SkScalar rad[8] = { 0, 0, 0, 0, padding, padding, padding, padding };
91 SkPath path;
92 path.addRoundRect(rect, rad, SkPath::kCW_Direction);
93
94 // Fill it black.
95 SkPaint paint;
96 paint.setStyle(SkPaint::kFill_Style);
97 paint.setFlags(SkPaint::kAntiAlias_Flag);
98 paint.setColor(SK_ColorBLACK);
99 canvas->GetSkCanvas()->drawPath(path, paint);
100 } 187 }
101 188
102 // FullscreenExitBubbleViews --------------------------------------------------- 189 // FullscreenExitBubbleViews ---------------------------------------------------
103 190
104 FullscreenExitBubbleViews::FullscreenExitBubbleViews( 191 FullscreenExitBubbleViews::FullscreenExitBubbleViews(
105 views::Widget* frame, 192 views::Widget* frame,
106 CommandUpdater::CommandUpdaterDelegate* delegate) 193 Browser* browser,
107 : FullscreenExitBubble(delegate), 194 const GURL& url,
195 bool show_buttons)
196 : FullscreenExitBubble(browser),
108 root_view_(frame->GetRootView()), 197 root_view_(frame->GetRootView()),
109 popup_(NULL), 198 popup_(NULL),
110 size_animation_(new ui::SlideAnimation(this)) { 199 size_animation_(new ui::SlideAnimation(this)),
200 url_(url) {
111 size_animation_->Reset(1); 201 size_animation_->Reset(1);
112 202
113 // Create the contents view. 203 // Create the contents view.
114 views::Accelerator accelerator(ui::VKEY_UNKNOWN, false, false, false); 204 views::Accelerator accelerator(ui::VKEY_UNKNOWN, false, false, false);
115 bool got_accelerator = frame->GetAccelerator(IDC_FULLSCREEN, &accelerator); 205 bool got_accelerator = frame->GetAccelerator(IDC_FULLSCREEN, &accelerator);
116 DCHECK(got_accelerator); 206 DCHECK(got_accelerator);
117 view_ = new FullscreenExitView( 207 view_ = new FullscreenExitView(
118 this, UTF16ToWideHack(accelerator.GetShortcutText())); 208 this, UTF16ToWideHack(accelerator.GetShortcutText()), url, show_buttons);
119 209
120 // Initialize the popup. 210 // Initialize the popup.
121 popup_ = new views::Widget; 211 popup_ = new views::Widget;
122 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); 212 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
123 params.transparent = true; 213 params.transparent = true;
124 params.can_activate = false; 214 params.can_activate = false;
125 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 215 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
126 params.parent = frame->GetNativeView(); 216 params.parent = frame->GetNativeView();
127 params.bounds = GetPopupRect(false); 217 params.bounds = GetPopupRect(false);
128 popup_->Init(params); 218 popup_->Init(params);
219 gfx::Size size = GetPopupRect(true).size();
129 popup_->SetContentsView(view_); 220 popup_->SetContentsView(view_);
130 popup_->SetOpacity(static_cast<unsigned char>(0xff * kOpacity)); 221 popup_->GetRootView()->SetLayoutManager(NULL);
222 view_->SetBounds(0, 0, size.width(), size.height());
131 popup_->Show(); // This does not activate the popup. 223 popup_->Show(); // This does not activate the popup.
132 224
133 StartWatchingMouse(); 225 if (!show_buttons)
226 StartWatchingMouse();
134 } 227 }
135 228
136 FullscreenExitBubbleViews::~FullscreenExitBubbleViews() { 229 FullscreenExitBubbleViews::~FullscreenExitBubbleViews() {
137 // This is tricky. We may be in an ATL message handler stack, in which case 230 // This is tricky. We may be in an ATL message handler stack, in which case
138 // the popup cannot be deleted yet. We also can't set the popup's ownership 231 // the popup cannot be deleted yet. We also can't set the popup's ownership
139 // model to NATIVE_WIDGET_OWNS_WIDGET because if the user closed the last tab 232 // model to NATIVE_WIDGET_OWNS_WIDGET because if the user closed the last tab
140 // while in fullscreen mode, Windows has already destroyed the popup HWND by 233 // while in fullscreen mode, Windows has already destroyed the popup HWND by
141 // the time we get here, and thus either the popup will already have been 234 // the time we get here, and thus either the popup will already have been
142 // deleted (if we set this in our constructor) or the popup will never get 235 // deleted (if we set this in our constructor) or the popup will never get
143 // another OnFinalMessage() call (if not, as currently). So instead, we tell 236 // another OnFinalMessage() call (if not, as currently). So instead, we tell
144 // the popup to synchronously hide, and then asynchronously close and delete 237 // the popup to synchronously hide, and then asynchronously close and delete
145 // itself. 238 // itself.
146 popup_->Close(); 239 popup_->Close();
147 MessageLoop::current()->DeleteSoon(FROM_HERE, popup_); 240 MessageLoop::current()->DeleteSoon(FROM_HERE, popup_);
148 } 241 }
149 242
150 void FullscreenExitBubbleViews::LinkClicked( 243 void FullscreenExitBubbleViews::LinkClicked(
151 views::Link* source, int event_flags) { 244 views::Link* source, int event_flags) {
152 ToggleFullscreen(); 245 ToggleFullscreen();
153 } 246 }
154 247
248 void FullscreenExitBubbleViews::OnAcceptFullscreen() {
249 AcceptFullscreen(url_);
250 view_->HideButtons();
251 StartWatchingMouse();
252 }
253
254 void FullscreenExitBubbleViews::OnCancelFullscreen() {
255 CancelFullscreen();
256 }
257
155 void FullscreenExitBubbleViews::AnimationProgressed( 258 void FullscreenExitBubbleViews::AnimationProgressed(
156 const ui::Animation* animation) { 259 const ui::Animation* animation) {
157 gfx::Rect popup_rect(GetPopupRect(false)); 260 gfx::Rect popup_rect(GetPopupRect(false));
158 if (popup_rect.IsEmpty()) { 261 if (popup_rect.IsEmpty()) {
159 popup_->Hide(); 262 popup_->Hide();
160 } else { 263 } else {
161 popup_->SetBounds(popup_rect); 264 popup_->SetBounds(popup_rect);
265 view_->SetY(popup_rect.height() - view_->height());
162 popup_->Show(); 266 popup_->Show();
163 } 267 }
164 } 268 }
269
165 void FullscreenExitBubbleViews::AnimationEnded( 270 void FullscreenExitBubbleViews::AnimationEnded(
166 const ui::Animation* animation) { 271 const ui::Animation* animation) {
167 AnimationProgressed(animation); 272 AnimationProgressed(animation);
168 } 273 }
169 274
170 void FullscreenExitBubbleViews::Hide() { 275 void FullscreenExitBubbleViews::Hide() {
171 size_animation_->SetSlideDuration(kSlideOutDurationMs); 276 size_animation_->SetSlideDuration(kSlideOutDurationMs);
172 size_animation_->Hide(); 277 size_animation_->Hide();
173 } 278 }
174 279
(...skipping 30 matching lines...) Expand all
205 } 310 }
206 // NOTE: don't use the bounds of the root_view_. On linux changing window 311 // NOTE: don't use the bounds of the root_view_. On linux changing window
207 // size is async. Instead we use the size of the screen. 312 // size is async. Instead we use the size of the screen.
208 gfx::Rect screen_bounds = gfx::Screen::GetMonitorAreaNearestWindow( 313 gfx::Rect screen_bounds = gfx::Screen::GetMonitorAreaNearestWindow(
209 root_view_->GetWidget()->GetNativeView()); 314 root_view_->GetWidget()->GetNativeView());
210 gfx::Point origin(screen_bounds.x() + 315 gfx::Point origin(screen_bounds.x() +
211 (screen_bounds.width() - size.width()) / 2, 316 (screen_bounds.width() - size.width()) / 2,
212 screen_bounds.y()); 317 screen_bounds.y());
213 return gfx::Rect(origin, size); 318 return gfx::Rect(origin, size);
214 } 319 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698