OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/ui/gtk/fullscreen_exit_bubble_gtk.h" | |
6 | |
7 #include "base/strings/utf_string_conversions.h" | |
8 #include "chrome/browser/chrome_notification_types.h" | |
9 #include "chrome/browser/ui/browser.h" | |
10 #include "chrome/browser/ui/gtk/gtk_chrome_link_button.h" | |
11 #include "chrome/browser/ui/gtk/gtk_theme_service.h" | |
12 #include "chrome/browser/ui/gtk/gtk_util.h" | |
13 #include "chrome/browser/ui/gtk/rounded_window.h" | |
14 #include "content/public/browser/notification_source.h" | |
15 #include "content/public/browser/render_widget_host_view.h" | |
16 #include "grit/generated_resources.h" | |
17 #include "grit/ui_strings.h" | |
18 #include "ui/base/gtk/gtk_floating_container.h" | |
19 #include "ui/base/gtk/gtk_hig_constants.h" | |
20 #include "ui/base/l10n/l10n_util.h" | |
21 | |
22 namespace { | |
23 | |
24 const GdkColor kBackgroundColor = GDK_COLOR_RGB(0xff, 0xff, 0xff); | |
25 const GdkColor kFrameColor = GDK_COLOR_RGB(0x63, 0x63, 0x63); | |
26 | |
27 } // namespace | |
28 | |
29 FullscreenExitBubbleGtk::FullscreenExitBubbleGtk( | |
30 GtkFloatingContainer* container, | |
31 Browser* browser, | |
32 const GURL& url, | |
33 FullscreenExitBubbleType bubble_type) | |
34 : FullscreenExitBubble(browser, url, bubble_type), | |
35 theme_service_(NULL), | |
36 bubble_(NULL), | |
37 container_(container) { | |
38 InitWidgets(); | |
39 } | |
40 | |
41 FullscreenExitBubbleGtk::~FullscreenExitBubbleGtk() { | |
42 } | |
43 | |
44 void FullscreenExitBubbleGtk::UpdateContent( | |
45 const GURL& url, | |
46 FullscreenExitBubbleType bubble_type) { | |
47 if (bubble_type == FEB_TYPE_NONE) { | |
48 NOTREACHED(); | |
49 bubble_type = FEB_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION; | |
50 } | |
51 | |
52 url_ = url; | |
53 bubble_type_ = bubble_type; | |
54 | |
55 gtk_label_set_text(GTK_LABEL(message_label_), | |
56 base::UTF16ToUTF8(GetCurrentMessageText()).c_str()); | |
57 if (fullscreen_bubble::ShowButtonsForType(bubble_type)) { | |
58 gtk_widget_hide(link_); | |
59 gtk_widget_hide(instruction_label_); | |
60 gtk_widget_show(allow_button_); | |
61 gtk_button_set_label(GTK_BUTTON(deny_button_), | |
62 base::UTF16ToUTF8(GetCurrentDenyButtonText()).c_str()); | |
63 gtk_widget_show(deny_button_); | |
64 } else { | |
65 bool link_visible = true; | |
66 base::string16 accelerator; | |
67 if (bubble_type == FEB_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION || | |
68 bubble_type == | |
69 FEB_TYPE_BROWSER_EXTENSION_FULLSCREEN_EXIT_INSTRUCTION) { | |
70 accelerator = l10n_util::GetStringUTF16(IDS_APP_F11_KEY); | |
71 } else if (bubble_type == FEB_TYPE_FULLSCREEN_EXIT_INSTRUCTION) { | |
72 accelerator = l10n_util::GetStringUTF16(IDS_APP_ESC_KEY); | |
73 } else { | |
74 link_visible = false; | |
75 } | |
76 if (link_visible) { | |
77 std::string exit_link_text( | |
78 l10n_util::GetStringUTF8(IDS_EXIT_FULLSCREEN_MODE) + " " + | |
79 l10n_util::GetStringFUTF8(IDS_EXIT_FULLSCREEN_MODE_ACCELERATOR, | |
80 accelerator)); | |
81 gtk_chrome_link_button_set_label(GTK_CHROME_LINK_BUTTON(link_), | |
82 exit_link_text.c_str()); | |
83 gtk_widget_show(link_); | |
84 gtk_widget_hide(instruction_label_); | |
85 } else { | |
86 gtk_widget_hide(link_); | |
87 gtk_widget_show(instruction_label_); | |
88 } | |
89 gtk_widget_hide(allow_button_); | |
90 gtk_widget_hide(deny_button_); | |
91 } | |
92 | |
93 Show(); | |
94 StopWatchingMouse(); | |
95 StartWatchingMouseIfNecessary(); | |
96 } | |
97 | |
98 void FullscreenExitBubbleGtk::InitWidgets() { | |
99 theme_service_ = GtkThemeService::GetFrom(browser_->profile()); | |
100 | |
101 hbox_ = gtk_hbox_new(false, ui::kControlSpacing); | |
102 | |
103 message_label_ = theme_service_->BuildLabel(GetMessage(url_).c_str(), | |
104 ui::kGdkBlack); | |
105 gtk_box_pack_start(GTK_BOX(hbox_), message_label_, FALSE, FALSE, 0); | |
106 | |
107 allow_button_ = gtk_button_new_with_label( | |
108 l10n_util::GetStringUTF8(IDS_FULLSCREEN_ALLOW).c_str()); | |
109 gtk_widget_set_can_focus(allow_button_, FALSE); | |
110 gtk_widget_set_no_show_all(allow_button_, FALSE); | |
111 gtk_box_pack_start(GTK_BOX(hbox_), allow_button_, FALSE, FALSE, 0); | |
112 | |
113 deny_button_ = gtk_button_new_with_label( | |
114 l10n_util::GetStringUTF8(IDS_FULLSCREEN_DENY).c_str()); | |
115 gtk_widget_set_can_focus(deny_button_, FALSE); | |
116 gtk_widget_set_no_show_all(deny_button_, FALSE); | |
117 gtk_box_pack_start(GTK_BOX(hbox_), deny_button_, FALSE, FALSE, 0); | |
118 | |
119 link_ = gtk_chrome_link_button_new(""); | |
120 gtk_widget_set_can_focus(link_, FALSE); | |
121 gtk_widget_set_no_show_all(link_, FALSE); | |
122 gtk_chrome_link_button_set_use_gtk_theme(GTK_CHROME_LINK_BUTTON(link_), | |
123 FALSE); | |
124 gtk_box_pack_start(GTK_BOX(hbox_), link_, FALSE, FALSE, 0); | |
125 | |
126 instruction_label_ = | |
127 gtk_label_new(base::UTF16ToUTF8(GetInstructionText()).c_str()); | |
128 gtk_widget_set_no_show_all(instruction_label_, FALSE); | |
129 gtk_box_pack_start(GTK_BOX(hbox_), instruction_label_, FALSE, FALSE, 0); | |
130 | |
131 bubble_ = gtk_util::CreateGtkBorderBin( | |
132 hbox_, &ui::kGdkWhite, | |
133 kPaddingPx, kPaddingPx, kPaddingPx, kPaddingPx); | |
134 gtk_util::ActAsRoundedWindow(bubble_, kFrameColor, 3, | |
135 gtk_util::ROUNDED_ALL, gtk_util::BORDER_ALL); | |
136 GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); | |
137 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 5, 0, 0, 0); | |
138 gtk_container_add(GTK_CONTAINER(alignment), bubble_); | |
139 ui_container_.Own(alignment); | |
140 | |
141 slide_widget_.reset(new SlideAnimatorGtk(ui_container_.get(), | |
142 SlideAnimatorGtk::DOWN, kSlideOutDurationMs, false, false, NULL)); | |
143 gtk_widget_set_name(widget(), "exit-fullscreen-bubble"); | |
144 gtk_widget_show_all(ui_container_.get()); | |
145 gtk_widget_show(widget()); | |
146 slide_widget_->OpenWithoutAnimation(); | |
147 | |
148 gtk_floating_container_add_floating(GTK_FLOATING_CONTAINER(container_), | |
149 widget()); | |
150 | |
151 signals_.Connect(container_, "set-floating-position", | |
152 G_CALLBACK(OnSetFloatingPositionThunk), this); | |
153 signals_.Connect(link_, "clicked", G_CALLBACK(OnLinkClickedThunk), this); | |
154 signals_.Connect(allow_button_, "clicked", | |
155 G_CALLBACK(&OnAllowClickedThunk), this); | |
156 signals_.Connect(deny_button_, "clicked", | |
157 G_CALLBACK(&OnDenyClickedThunk), this); | |
158 | |
159 UpdateContent(url_, bubble_type_); | |
160 | |
161 theme_service_->InitThemesFor(this); | |
162 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, | |
163 content::Source<ThemeService>(theme_service_)); | |
164 } | |
165 | |
166 std::string FullscreenExitBubbleGtk::GetMessage(const GURL& url) { | |
167 if (url.is_empty()) | |
168 return l10n_util::GetStringUTF8(IDS_FULLSCREEN_USER_ENTERED_FULLSCREEN); | |
169 | |
170 if (url.SchemeIsFile()) | |
171 return l10n_util::GetStringUTF8(IDS_FULLSCREEN_ENTERED_FULLSCREEN); | |
172 return l10n_util::GetStringFUTF8(IDS_FULLSCREEN_SITE_ENTERED_FULLSCREEN, | |
173 base::UTF8ToUTF16(url.host())); | |
174 } | |
175 | |
176 gfx::Rect FullscreenExitBubbleGtk::GetPopupRect( | |
177 bool ignore_animation_state) const { | |
178 GtkRequisition bubble_size; | |
179 if (ignore_animation_state) { | |
180 gtk_widget_size_request(ui_container_.get(), &bubble_size); | |
181 } else { | |
182 gtk_widget_size_request(widget(), &bubble_size); | |
183 } | |
184 return gfx::Rect(bubble_size.width, bubble_size.height); | |
185 } | |
186 | |
187 gfx::Point FullscreenExitBubbleGtk::GetCursorScreenPoint() { | |
188 GdkDisplay* display = gtk_widget_get_display(widget()); | |
189 | |
190 // Get cursor position. | |
191 // TODO: this hits the X server, so we may want to consider decreasing | |
192 // kPositionCheckHz if we detect that we're running remotely. | |
193 int x, y; | |
194 gdk_display_get_pointer(display, NULL, &x, &y, NULL); | |
195 | |
196 return gfx::Point(x, y); | |
197 } | |
198 | |
199 bool FullscreenExitBubbleGtk::WindowContainsPoint(gfx::Point pos) { | |
200 GtkWindow* window = GTK_WINDOW( | |
201 gtk_widget_get_ancestor(widget(), GTK_TYPE_WINDOW)); | |
202 int width, height, x, y; | |
203 gtk_window_get_size(window, &width, &height); | |
204 gtk_window_get_position(window, &x, &y); | |
205 return gfx::Rect(x, y, width, height).Contains(pos); | |
206 } | |
207 | |
208 bool FullscreenExitBubbleGtk::IsWindowActive() { | |
209 if (!gtk_widget_get_parent(widget())) | |
210 return false; | |
211 GtkWindow* window = GTK_WINDOW( | |
212 gtk_widget_get_ancestor(widget(), GTK_TYPE_WINDOW)); | |
213 return gtk_window_is_active(window); | |
214 } | |
215 | |
216 void FullscreenExitBubbleGtk::Hide() { | |
217 slide_widget_->Close(); | |
218 } | |
219 | |
220 void FullscreenExitBubbleGtk::Show() { | |
221 slide_widget_->Open(); | |
222 } | |
223 | |
224 bool FullscreenExitBubbleGtk::IsAnimating() { | |
225 return slide_widget_->IsAnimating(); | |
226 } | |
227 | |
228 bool FullscreenExitBubbleGtk::CanMouseTriggerSlideIn() const { | |
229 return true; | |
230 } | |
231 | |
232 void FullscreenExitBubbleGtk::StartWatchingMouseIfNecessary() { | |
233 if (!fullscreen_bubble::ShowButtonsForType(bubble_type_)) | |
234 StartWatchingMouse(); | |
235 } | |
236 | |
237 void FullscreenExitBubbleGtk::OnSetFloatingPosition( | |
238 GtkWidget* floating_container, | |
239 GtkAllocation* allocation) { | |
240 GtkRequisition bubble_size; | |
241 gtk_widget_size_request(widget(), &bubble_size); | |
242 | |
243 // Position the bubble at the top center of the screen. | |
244 GValue value = { 0, }; | |
245 g_value_init(&value, G_TYPE_INT); | |
246 g_value_set_int(&value, (allocation->width - bubble_size.width) / 2); | |
247 gtk_container_child_set_property(GTK_CONTAINER(floating_container), | |
248 widget(), "x", &value); | |
249 | |
250 g_value_set_int(&value, 0); | |
251 gtk_container_child_set_property(GTK_CONTAINER(floating_container), | |
252 widget(), "y", &value); | |
253 g_value_unset(&value); | |
254 } | |
255 | |
256 void FullscreenExitBubbleGtk::OnLinkClicked(GtkWidget* link) { | |
257 ToggleFullscreen(); | |
258 } | |
259 | |
260 void FullscreenExitBubbleGtk::OnAllowClicked(GtkWidget* button) { | |
261 Accept(); | |
262 } | |
263 | |
264 void FullscreenExitBubbleGtk::OnDenyClicked(GtkWidget* button) { | |
265 Cancel(); | |
266 } | |
267 | |
268 void FullscreenExitBubbleGtk::Observe( | |
269 int type, | |
270 const content::NotificationSource& source, | |
271 const content::NotificationDetails& details) { | |
272 DCHECK_EQ(type, chrome::NOTIFICATION_BROWSER_THEME_CHANGED); | |
273 if (theme_service_->UsingNativeTheme()) | |
274 gtk_widget_modify_bg(bubble_, GTK_STATE_NORMAL, NULL); | |
275 else | |
276 gtk_widget_modify_bg(bubble_, GTK_STATE_NORMAL, &kBackgroundColor); | |
277 } | |
OLD | NEW |