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

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: fix license 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 namespace {
30 // Space between the site info label and the buttons / link.
31 const int kMiddlePaddingPx = 30;
32 } // namespace
33
34 class FullscreenExitBubbleViews::FullscreenExitView
35 : public views::View,
36 public views::ButtonListener {
27 public: 37 public:
28 FullscreenExitView(FullscreenExitBubbleViews* bubble, 38 FullscreenExitView(FullscreenExitBubbleViews* bubble,
29 const std::wstring& accelerator); 39 const string16& accelerator,
40 const GURL& url,
41 bool ask_permission);
30 virtual ~FullscreenExitView(); 42 virtual ~FullscreenExitView();
31 43
32 // views::View 44 // views::View
33 virtual gfx::Size GetPreferredSize(); 45 virtual gfx::Size GetPreferredSize();
34 46
47 // views::ButtonListener
48 virtual void ButtonPressed(views::Button* sender, const views::Event& event);
49
50 // Hide the accept and deny buttons, exposing the exit link.
51 void HideButtons();
52
35 private: 53 private:
54 string16 GetMessage(const GURL& url);
55
36 // views::View 56 // views::View
37 virtual void Layout(); 57 virtual void Layout();
38 virtual void OnPaint(gfx::Canvas* canvas); 58
59 FullscreenExitBubbleViews* bubble_;
39 60
40 // Clickable hint text to show in the bubble. 61 // Clickable hint text to show in the bubble.
41 views::Link link_; 62 views::Link link_;
63 views::Label message_label_;
64 views::NativeTextButton* accept_button_;
65 views::NativeTextButton* deny_button_;
66
67 bool show_buttons_;
42 }; 68 };
43 69
44 FullscreenExitBubbleViews::FullscreenExitView::FullscreenExitView( 70 FullscreenExitBubbleViews::FullscreenExitView::FullscreenExitView(
45 FullscreenExitBubbleViews* bubble, 71 FullscreenExitBubbleViews* bubble,
46 const std::wstring& accelerator) { 72 const string16& accelerator,
73 const GURL& url,
74 bool ask_permission)
75 : bubble_(bubble),
76 accept_button_(NULL),
77 deny_button_(NULL),
78 show_buttons_(ask_permission) {
79 views::BubbleBorder* bubble_border =
80 new views::BubbleBorder(views::BubbleBorder::NONE);
81 bubble_border->set_background_color(Bubble::kBackgroundColor);
82 set_background(new views::BubbleBackground(bubble_border));
83 set_border(bubble_border);
84 set_focusable(false);
85
86 message_label_.set_parent_owned(false);
87 message_label_.SetText(GetMessage(url));
88 message_label_.SetFont(ResourceBundle::GetSharedInstance().GetFont(
89 ResourceBundle::MediumFont));
90
47 link_.set_parent_owned(false); 91 link_.set_parent_owned(false);
92 link_.set_collapse_when_hidden(false);
93 link_.set_focusable(false);
48 #if !defined(OS_CHROMEOS) 94 #if !defined(OS_CHROMEOS)
49 link_.SetText( 95 link_.SetText(
50 l10n_util::GetStringFUTF16(IDS_EXIT_FULLSCREEN_MODE, 96 l10n_util::GetStringFUTF16(IDS_EXIT_FULLSCREEN_MODE,
51 WideToUTF16(accelerator))); 97 accelerator));
52 #else 98 #else
53 link_.SetText(l10n_util::GetStringUTF16(IDS_EXIT_FULLSCREEN_MODE)); 99 link_.SetText(l10n_util::GetStringUTF16(IDS_EXIT_FULLSCREEN_MODE));
54 #endif 100 #endif
55 link_.set_listener(bubble); 101 link_.set_listener(bubble);
56 link_.SetFont(ResourceBundle::GetSharedInstance().GetFont( 102 link_.SetFont(ResourceBundle::GetSharedInstance().GetFont(
57 ResourceBundle::LargeFont)); 103 ResourceBundle::MediumFont));
58 link_.SetBackgroundColor(SK_ColorBLACK); 104 link_.SetPressedColor(message_label_.enabled_color());
59 link_.SetEnabledColor(SK_ColorWHITE); 105 link_.SetEnabledColor(message_label_.enabled_color());
60 link_.SetPressedColor(SK_ColorWHITE); 106 link_.SetVisible(false);
107
108 link_.SetBackgroundColor(background()->get_color());
109 message_label_.SetBackgroundColor(background()->get_color());
110 AddChildView(&message_label_);
61 AddChildView(&link_); 111 AddChildView(&link_);
112
113 accept_button_ = new views::NativeTextButton(this,
114 UTF16ToWide(l10n_util::GetStringUTF16(IDS_FULLSCREEN_INFOBAR_ALLOW)));
115 accept_button_->set_focusable(false);
116 AddChildView(accept_button_);
117
118 deny_button_ = new views::NativeTextButton(this,
119 UTF16ToWide(l10n_util::GetStringUTF16(IDS_FULLSCREEN_INFOBAR_DENY)));
120 deny_button_->set_focusable(false);
121 AddChildView(deny_button_);
122
123 if (!show_buttons_)
124 HideButtons();
125 }
126
127 string16 FullscreenExitBubbleViews::FullscreenExitView::GetMessage(
128 const GURL& url) {
129 if (url.is_empty()) {
130 return l10n_util::GetStringUTF16(
131 IDS_FULLSCREEN_INFOBAR_USER_ENTERED_FULLSCREEN);
132 }
133 if (url.SchemeIsFile())
134 return l10n_util::GetStringUTF16(IDS_FULLSCREEN_INFOBAR_FILE_PAGE_NAME);
135 return l10n_util::GetStringFUTF16(IDS_FULLSCREEN_INFOBAR_REQUEST_PERMISSION,
136 UTF8ToUTF16(url.host()));
62 } 137 }
63 138
64 FullscreenExitBubbleViews::FullscreenExitView::~FullscreenExitView() { 139 FullscreenExitBubbleViews::FullscreenExitView::~FullscreenExitView() {
65 } 140 }
66 141
142 void FullscreenExitBubbleViews::FullscreenExitView::ButtonPressed(
143 views::Button* sender, const views::Event& event) {
144 if (sender == accept_button_)
145 bubble_->OnAcceptFullscreen();
146 else
147 bubble_->OnCancelFullscreen();
148 }
149
150 void FullscreenExitBubbleViews::FullscreenExitView::HideButtons() {
151 show_buttons_ = false;
152 accept_button_->SetVisible(false);
153 deny_button_->SetVisible(false);
154 link_.SetVisible(true);
155 }
156
67 gfx::Size FullscreenExitBubbleViews::FullscreenExitView::GetPreferredSize() { 157 gfx::Size FullscreenExitBubbleViews::FullscreenExitView::GetPreferredSize() {
68 gfx::Size preferred_size(link_.GetPreferredSize()); 158 gfx::Size link_size(link_.GetPreferredSize());
69 preferred_size.Enlarge(kPaddingPx * 2, kPaddingPx * 2); 159 gfx::Size message_label_size(message_label_.GetPreferredSize());
70 return preferred_size; 160 gfx::Size accept_size(accept_button_->GetPreferredSize());
161 gfx::Size deny_size(deny_button_->GetPreferredSize());
162 gfx::Insets insets(GetInsets());
163
164 int buttons_width = accept_size.width() + kPaddingPx +
165 deny_size.width();
166 int button_box_width = std::max(buttons_width, link_size.width());
167 int width = kPaddingPx + message_label_size.width() + kMiddlePaddingPx +
168 button_box_width + kPaddingPx;
169
170 gfx::Size result(width + insets.width(),
171 kPaddingPx * 2 + accept_size.height() + insets.height());
172 return result;
71 } 173 }
72 174
73 void FullscreenExitBubbleViews::FullscreenExitView::Layout() { 175 void FullscreenExitBubbleViews::FullscreenExitView::Layout() {
74 gfx::Size link_preferred_size(link_.GetPreferredSize()); 176 gfx::Size link_size(link_.GetPreferredSize());
75 link_.SetBounds(kPaddingPx, 177 gfx::Size message_label_size(message_label_.GetPreferredSize());
76 height() - kPaddingPx - link_preferred_size.height(), 178 gfx::Size accept_size(accept_button_->GetPreferredSize());
77 link_preferred_size.width(), link_preferred_size.height()); 179 gfx::Size deny_size(deny_button_->GetPreferredSize());
78 } 180 gfx::Insets insets(GetInsets());
79 181
80 void FullscreenExitBubbleViews::FullscreenExitView::OnPaint( 182 int inner_height = height() - insets.height();
81 gfx::Canvas* canvas) { 183 int button_box_x = insets.left() + kPaddingPx +
82 // Create a round-bottomed rect to fill the whole View. 184 message_label_size.width() + kMiddlePaddingPx;
83 SkRect rect; 185 int message_label_y = insets.top() +
84 SkScalar padding = SkIntToScalar(kPaddingPx); 186 (inner_height - message_label_size.height()) / 2;
85 // The "-padding" top coordinate ensures that the rect is always tall enough 187 int link_x = width() - insets.right() - kPaddingPx -
86 // to contain the complete rounded corner radius. If we set this to 0, as the 188 link_size.width();
87 // popup slides offscreen (in reality, squishes to 0 height), the corners will 189 int link_y = insets.top() + (inner_height - link_size.height()) / 2;
88 // flatten out as the height becomes less than the corner radius.
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 190
94 // Fill it black. 191 message_label_.SetPosition(gfx::Point(insets.left() + kPaddingPx,
95 SkPaint paint; 192 message_label_y));
96 paint.setStyle(SkPaint::kFill_Style); 193 link_.SetPosition(gfx::Point(link_x, link_y));
97 paint.setFlags(SkPaint::kAntiAlias_Flag); 194 if (show_buttons_) {
98 paint.setColor(SK_ColorBLACK); 195 accept_button_->SetPosition(gfx::Point(button_box_x,
99 canvas->GetSkCanvas()->drawPath(path, paint); 196 insets.top() + kPaddingPx));
197 deny_button_->SetPosition(gfx::Point(
198 button_box_x + accept_size.width() + kPaddingPx,
199 insets.top() + kPaddingPx));
200 }
100 } 201 }
101 202
102 // FullscreenExitBubbleViews --------------------------------------------------- 203 // FullscreenExitBubbleViews ---------------------------------------------------
103 204
104 FullscreenExitBubbleViews::FullscreenExitBubbleViews( 205 FullscreenExitBubbleViews::FullscreenExitBubbleViews(views::Widget* frame,
105 views::Widget* frame, 206 Browser* browser,
106 CommandUpdater::CommandUpdaterDelegate* delegate) 207 const GURL& url,
107 : FullscreenExitBubble(delegate), 208 bool ask_permission)
209 : FullscreenExitBubble(browser),
108 root_view_(frame->GetRootView()), 210 root_view_(frame->GetRootView()),
109 popup_(NULL), 211 popup_(NULL),
110 size_animation_(new ui::SlideAnimation(this)) { 212 size_animation_(new ui::SlideAnimation(this)),
213 url_(url) {
111 size_animation_->Reset(1); 214 size_animation_->Reset(1);
112 215
113 // Create the contents view. 216 // Create the contents view.
114 views::Accelerator accelerator(ui::VKEY_UNKNOWN, false, false, false); 217 views::Accelerator accelerator(ui::VKEY_UNKNOWN, false, false, false);
115 bool got_accelerator = frame->GetAccelerator(IDC_FULLSCREEN, &accelerator); 218 bool got_accelerator = frame->GetAccelerator(IDC_FULLSCREEN, &accelerator);
116 DCHECK(got_accelerator); 219 DCHECK(got_accelerator);
117 view_ = new FullscreenExitView( 220 view_ = new FullscreenExitView(this,
118 this, UTF16ToWideHack(accelerator.GetShortcutText())); 221 accelerator.GetShortcutText(), url, ask_permission);
119 222
120 // Initialize the popup. 223 // Initialize the popup.
121 popup_ = new views::Widget; 224 popup_ = new views::Widget;
122 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); 225 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
123 params.transparent = true; 226 params.transparent = true;
124 params.can_activate = false; 227 params.can_activate = false;
125 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 228 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
126 params.parent = frame->GetNativeView(); 229 params.parent = frame->GetNativeView();
127 params.bounds = GetPopupRect(false); 230 params.bounds = GetPopupRect(false);
128 popup_->Init(params); 231 popup_->Init(params);
232 gfx::Size size = GetPopupRect(true).size();
129 popup_->SetContentsView(view_); 233 popup_->SetContentsView(view_);
130 popup_->SetOpacity(static_cast<unsigned char>(0xff * kOpacity)); 234 // We set layout manager to NULL to prevent the widget from sizing its
235 // contents to the same size as itself. This prevents the widget contents from
236 // shrinking while we animate the height of the popup to give the impression
237 // that it is sliding off the top of the screen.
238 popup_->GetRootView()->SetLayoutManager(NULL);
239 view_->SetBounds(0, 0, size.width(), size.height());
131 popup_->Show(); // This does not activate the popup. 240 popup_->Show(); // This does not activate the popup.
132 241
133 StartWatchingMouse(); 242 if (!ask_permission)
243 StartWatchingMouse();
134 } 244 }
135 245
136 FullscreenExitBubbleViews::~FullscreenExitBubbleViews() { 246 FullscreenExitBubbleViews::~FullscreenExitBubbleViews() {
137 // This is tricky. We may be in an ATL message handler stack, in which case 247 // 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 248 // 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 249 // 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 250 // 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 251 // 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 252 // 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 253 // another OnFinalMessage() call (if not, as currently). So instead, we tell
144 // the popup to synchronously hide, and then asynchronously close and delete 254 // the popup to synchronously hide, and then asynchronously close and delete
145 // itself. 255 // itself.
146 popup_->Close(); 256 popup_->Close();
147 MessageLoop::current()->DeleteSoon(FROM_HERE, popup_); 257 MessageLoop::current()->DeleteSoon(FROM_HERE, popup_);
148 } 258 }
149 259
150 void FullscreenExitBubbleViews::LinkClicked( 260 void FullscreenExitBubbleViews::LinkClicked(
151 views::Link* source, int event_flags) { 261 views::Link* source, int event_flags) {
152 ToggleFullscreen(); 262 ToggleFullscreen();
153 } 263 }
154 264
265 void FullscreenExitBubbleViews::OnAcceptFullscreen() {
266 AcceptFullscreen(url_);
267 view_->HideButtons();
268 StartWatchingMouse();
269 }
270
271 void FullscreenExitBubbleViews::OnCancelFullscreen() {
272 CancelFullscreen();
273 }
274
155 void FullscreenExitBubbleViews::AnimationProgressed( 275 void FullscreenExitBubbleViews::AnimationProgressed(
156 const ui::Animation* animation) { 276 const ui::Animation* animation) {
157 gfx::Rect popup_rect(GetPopupRect(false)); 277 gfx::Rect popup_rect(GetPopupRect(false));
158 if (popup_rect.IsEmpty()) { 278 if (popup_rect.IsEmpty()) {
159 popup_->Hide(); 279 popup_->Hide();
160 } else { 280 } else {
161 popup_->SetBounds(popup_rect); 281 popup_->SetBounds(popup_rect);
282 view_->SetY(popup_rect.height() - view_->height());
162 popup_->Show(); 283 popup_->Show();
163 } 284 }
164 } 285 }
286
165 void FullscreenExitBubbleViews::AnimationEnded( 287 void FullscreenExitBubbleViews::AnimationEnded(
166 const ui::Animation* animation) { 288 const ui::Animation* animation) {
167 AnimationProgressed(animation); 289 AnimationProgressed(animation);
168 } 290 }
169 291
170 void FullscreenExitBubbleViews::Hide() { 292 void FullscreenExitBubbleViews::Hide() {
171 size_animation_->SetSlideDuration(kSlideOutDurationMs); 293 size_animation_->SetSlideDuration(kSlideOutDurationMs);
172 size_animation_->Hide(); 294 size_animation_->Hide();
173 } 295 }
174 296
(...skipping 17 matching lines...) Expand all
192 gfx::Point FullscreenExitBubbleViews::GetCursorScreenPoint() { 314 gfx::Point FullscreenExitBubbleViews::GetCursorScreenPoint() {
193 gfx::Point cursor_pos = gfx::Screen::GetCursorScreenPoint(); 315 gfx::Point cursor_pos = gfx::Screen::GetCursorScreenPoint();
194 gfx::Point transformed_pos(cursor_pos); 316 gfx::Point transformed_pos(cursor_pos);
195 views::View::ConvertPointToView(NULL, root_view_, &transformed_pos); 317 views::View::ConvertPointToView(NULL, root_view_, &transformed_pos);
196 return transformed_pos; 318 return transformed_pos;
197 } 319 }
198 320
199 gfx::Rect FullscreenExitBubbleViews::GetPopupRect( 321 gfx::Rect FullscreenExitBubbleViews::GetPopupRect(
200 bool ignore_animation_state) const { 322 bool ignore_animation_state) const {
201 gfx::Size size(view_->GetPreferredSize()); 323 gfx::Size size(view_->GetPreferredSize());
202 if (!ignore_animation_state) {
203 size.set_height(static_cast<int>(static_cast<double>(size.height()) *
204 size_animation_->GetCurrentValue()));
205 }
206 // NOTE: don't use the bounds of the root_view_. On linux changing window 324 // 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. 325 // size is async. Instead we use the size of the screen.
208 gfx::Rect screen_bounds = gfx::Screen::GetMonitorAreaNearestWindow( 326 gfx::Rect screen_bounds = gfx::Screen::GetMonitorAreaNearestWindow(
209 root_view_->GetWidget()->GetNativeView()); 327 root_view_->GetWidget()->GetNativeView());
210 gfx::Point origin(screen_bounds.x() + 328 gfx::Point origin(screen_bounds.x() +
211 (screen_bounds.width() - size.width()) / 2, 329 (screen_bounds.width() - size.width()) / 2,
212 screen_bounds.y()); 330 kPopupTopPx + screen_bounds.y());
331 if (!ignore_animation_state) {
332 int total_height = size.height() + kPopupTopPx;
333 int popup_bottom = size_animation_->CurrentValueBetween(
334 static_cast<double>(total_height), 0.0f);
335 int y_offset = std::min(popup_bottom, kPopupTopPx);
336 size.set_height(size.height() - popup_bottom + y_offset);
337 origin.set_y(origin.y() - y_offset);
338 }
213 return gfx::Rect(origin, size); 339 return gfx::Rect(origin, size);
214 } 340 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/fullscreen_exit_bubble_views.h ('k') | chrome/browser/ui/webui/options/content_settings_handler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698