Chromium Code Reviews

Side by Side Diff: chrome/browser/gtk/browser_toolbar_gtk.cc

Issue 6251001: Move chrome/browser/gtk/ to chrome/browser/ui/gtk/... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/gtk/browser_toolbar_gtk.h"
6
7 #include <X11/XF86keysym.h>
8 #include <gdk/gdkkeysyms.h>
9 #include <gtk/gtk.h>
10
11 #include "app/gtk_dnd_util.h"
12 #include "app/l10n_util.h"
13 #include "app/menus/accelerator_gtk.h"
14 #include "base/base_paths.h"
15 #include "base/command_line.h"
16 #include "base/i18n/rtl.h"
17 #include "base/logging.h"
18 #include "base/path_service.h"
19 #include "base/singleton.h"
20 #include "chrome/app/chrome_command_ids.h"
21 #include "chrome/browser/background_page_tracker.h"
22 #include "chrome/browser/gtk/accelerators_gtk.h"
23 #include "chrome/browser/gtk/back_forward_button_gtk.h"
24 #include "chrome/browser/gtk/browser_actions_toolbar_gtk.h"
25 #include "chrome/browser/gtk/browser_window_gtk.h"
26 #include "chrome/browser/gtk/cairo_cached_surface.h"
27 #include "chrome/browser/gtk/custom_button.h"
28 #include "chrome/browser/gtk/gtk_chrome_button.h"
29 #include "chrome/browser/gtk/gtk_theme_provider.h"
30 #include "chrome/browser/gtk/gtk_util.h"
31 #include "chrome/browser/gtk/location_bar_view_gtk.h"
32 #include "chrome/browser/gtk/reload_button_gtk.h"
33 #include "chrome/browser/gtk/rounded_window.h"
34 #include "chrome/browser/gtk/tabs/tab_strip_gtk.h"
35 #include "chrome/browser/gtk/view_id_util.h"
36 #include "chrome/browser/metrics/user_metrics.h"
37 #include "chrome/browser/net/url_fixer_upper.h"
38 #include "chrome/browser/prefs/pref_service.h"
39 #include "chrome/browser/profiles/profile.h"
40 #include "chrome/browser/tab_contents/tab_contents.h"
41 #include "chrome/browser/themes/browser_theme_provider.h"
42 #include "chrome/browser/ui/browser.h"
43 #include "chrome/browser/ui/toolbar/encoding_menu_controller.h"
44 #include "chrome/browser/upgrade_detector.h"
45 #include "chrome/common/notification_details.h"
46 #include "chrome/common/notification_service.h"
47 #include "chrome/common/notification_type.h"
48 #include "chrome/common/pref_names.h"
49 #include "chrome/common/url_constants.h"
50 #include "gfx/canvas_skia_paint.h"
51 #include "gfx/gtk_util.h"
52 #include "gfx/skbitmap_operations.h"
53 #include "grit/chromium_strings.h"
54 #include "grit/generated_resources.h"
55 #include "grit/theme_resources.h"
56
57 namespace {
58
59 // Padding on left and right of the left toolbar buttons (back, forward, reload,
60 // etc.).
61 const int kToolbarLeftAreaPadding = 4;
62
63 // Height of the toolbar in pixels (not counting padding).
64 const int kToolbarHeight = 29;
65
66 // Padding within the toolbar above the buttons and location bar.
67 const int kTopBottomPadding = 3;
68
69 // Height of the toolbar in pixels when we only show the location bar.
70 const int kToolbarHeightLocationBarOnly = kToolbarHeight - 2;
71
72 // Interior spacing between toolbar widgets.
73 const int kToolbarWidgetSpacing = 1;
74
75 // Amount of rounding on top corners of toolbar. Only used in Gtk theme mode.
76 const int kToolbarCornerSize = 3;
77
78 void SetWidgetHeightRequest(GtkWidget* widget, gpointer user_data) {
79 gtk_widget_set_size_request(widget, -1, GPOINTER_TO_INT(user_data));
80 }
81
82 } // namespace
83
84 // BrowserToolbarGtk, public ---------------------------------------------------
85
86 BrowserToolbarGtk::BrowserToolbarGtk(Browser* browser, BrowserWindowGtk* window)
87 : toolbar_(NULL),
88 location_bar_(new LocationBarViewGtk(browser)),
89 model_(browser->toolbar_model()),
90 wrench_menu_model_(this, browser),
91 browser_(browser),
92 window_(window),
93 profile_(NULL) {
94 browser_->command_updater()->AddCommandObserver(IDC_BACK, this);
95 browser_->command_updater()->AddCommandObserver(IDC_FORWARD, this);
96 browser_->command_updater()->AddCommandObserver(IDC_HOME, this);
97 browser_->command_updater()->AddCommandObserver(IDC_BOOKMARK_PAGE, this);
98
99 registrar_.Add(this,
100 NotificationType::BROWSER_THEME_CHANGED,
101 NotificationService::AllSources());
102 registrar_.Add(this,
103 NotificationType::UPGRADE_RECOMMENDED,
104 NotificationService::AllSources());
105 registrar_.Add(this,
106 NotificationType::BACKGROUND_PAGE_TRACKER_CHANGED,
107 NotificationService::AllSources());
108 }
109
110 BrowserToolbarGtk::~BrowserToolbarGtk() {
111 browser_->command_updater()->RemoveCommandObserver(IDC_BACK, this);
112 browser_->command_updater()->RemoveCommandObserver(IDC_FORWARD, this);
113 browser_->command_updater()->RemoveCommandObserver(IDC_HOME, this);
114 browser_->command_updater()->RemoveCommandObserver(IDC_BOOKMARK_PAGE, this);
115
116 offscreen_entry_.Destroy();
117
118 wrench_menu_.reset();
119 }
120
121 void BrowserToolbarGtk::Init(Profile* profile,
122 GtkWindow* top_level_window) {
123 // Make sure to tell the location bar the profile before calling its Init.
124 SetProfile(profile);
125
126 theme_provider_ = GtkThemeProvider::GetFrom(profile);
127 offscreen_entry_.Own(gtk_entry_new());
128
129 show_home_button_.Init(prefs::kShowHomeButton, profile->GetPrefs(), this);
130 home_page_.Init(prefs::kHomePage, profile->GetPrefs(), this);
131 home_page_is_new_tab_page_.Init(prefs::kHomePageIsNewTabPage,
132 profile->GetPrefs(), this);
133
134 event_box_ = gtk_event_box_new();
135 // Make the event box transparent so themes can use transparent toolbar
136 // backgrounds.
137 if (!theme_provider_->UseGtkTheme())
138 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_), FALSE);
139
140 toolbar_ = gtk_hbox_new(FALSE, 0);
141 alignment_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
142 UpdateForBookmarkBarVisibility(false);
143 g_signal_connect(alignment_, "expose-event",
144 G_CALLBACK(&OnAlignmentExposeThunk), this);
145 gtk_container_add(GTK_CONTAINER(event_box_), alignment_);
146 gtk_container_add(GTK_CONTAINER(alignment_), toolbar_);
147
148 toolbar_left_ = gtk_hbox_new(FALSE, kToolbarWidgetSpacing);
149
150 back_.reset(new BackForwardButtonGtk(browser_, false));
151 g_signal_connect(back_->widget(), "clicked",
152 G_CALLBACK(OnButtonClickThunk), this);
153 gtk_box_pack_start(GTK_BOX(toolbar_left_), back_->widget(), FALSE,
154 FALSE, 0);
155
156 forward_.reset(new BackForwardButtonGtk(browser_, true));
157 g_signal_connect(forward_->widget(), "clicked",
158 G_CALLBACK(OnButtonClickThunk), this);
159 gtk_box_pack_start(GTK_BOX(toolbar_left_), forward_->widget(), FALSE,
160 FALSE, 0);
161
162 reload_.reset(new ReloadButtonGtk(location_bar_.get(), browser_));
163 gtk_box_pack_start(GTK_BOX(toolbar_left_), reload_->widget(), FALSE, FALSE,
164 0);
165
166 home_.reset(new CustomDrawButton(GtkThemeProvider::GetFrom(profile_),
167 IDR_HOME, IDR_HOME_P, IDR_HOME_H, 0, GTK_STOCK_HOME,
168 GTK_ICON_SIZE_SMALL_TOOLBAR));
169 gtk_widget_set_tooltip_text(home_->widget(),
170 l10n_util::GetStringUTF8(IDS_TOOLTIP_HOME).c_str());
171 g_signal_connect(home_->widget(), "clicked",
172 G_CALLBACK(OnButtonClickThunk), this);
173 gtk_box_pack_start(GTK_BOX(toolbar_left_), home_->widget(), FALSE, FALSE,
174 kToolbarWidgetSpacing);
175 gtk_util::SetButtonTriggersNavigation(home_->widget());
176
177 gtk_box_pack_start(GTK_BOX(toolbar_), toolbar_left_, FALSE, FALSE,
178 kToolbarLeftAreaPadding);
179
180 location_hbox_ = gtk_hbox_new(FALSE, 0);
181 location_bar_->Init(ShouldOnlyShowLocation());
182 gtk_box_pack_start(GTK_BOX(location_hbox_), location_bar_->widget(), TRUE,
183 TRUE, 0);
184
185 g_signal_connect(location_hbox_, "expose-event",
186 G_CALLBACK(OnLocationHboxExposeThunk), this);
187 gtk_box_pack_start(GTK_BOX(toolbar_), location_hbox_, TRUE, TRUE,
188 ShouldOnlyShowLocation() ? 1 : 0);
189
190 if (!ShouldOnlyShowLocation()) {
191 actions_toolbar_.reset(new BrowserActionsToolbarGtk(browser_));
192 gtk_box_pack_start(GTK_BOX(toolbar_), actions_toolbar_->widget(),
193 FALSE, FALSE, 0);
194 }
195
196 wrench_menu_image_ = gtk_image_new_from_pixbuf(
197 theme_provider_->GetRTLEnabledPixbufNamed(IDR_TOOLS));
198 wrench_menu_button_.reset(new CustomDrawButton(
199 GtkThemeProvider::GetFrom(profile_),
200 IDR_TOOLS, IDR_TOOLS_P, IDR_TOOLS_H, 0,
201 wrench_menu_image_));
202 GtkWidget* wrench_button = wrench_menu_button_->widget();
203
204 gtk_widget_set_tooltip_text(
205 wrench_button,
206 l10n_util::GetStringFUTF8(IDS_APPMENU_TOOLTIP,
207 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)).c_str());
208 g_signal_connect(wrench_button, "button-press-event",
209 G_CALLBACK(OnMenuButtonPressEventThunk), this);
210 GTK_WIDGET_UNSET_FLAGS(wrench_button, GTK_CAN_FOCUS);
211
212 // Put the wrench button in a box so that we can paint the update notification
213 // over it.
214 GtkWidget* wrench_box = gtk_alignment_new(0, 0, 1, 1);
215 g_signal_connect_after(wrench_box, "expose-event",
216 G_CALLBACK(OnWrenchMenuButtonExposeThunk), this);
217 gtk_container_add(GTK_CONTAINER(wrench_box), wrench_button);
218 gtk_box_pack_start(GTK_BOX(toolbar_), wrench_box, FALSE, FALSE, 4);
219
220 wrench_menu_.reset(new MenuGtk(this, &wrench_menu_model_));
221 registrar_.Add(this, NotificationType::ZOOM_LEVEL_CHANGED,
222 Source<Profile>(browser_->profile()));
223
224 if (ShouldOnlyShowLocation()) {
225 gtk_widget_show(event_box_);
226 gtk_widget_show(alignment_);
227 gtk_widget_show(toolbar_);
228 gtk_widget_show_all(location_hbox_);
229 gtk_widget_hide(reload_->widget());
230 } else {
231 gtk_widget_show_all(event_box_);
232 if (actions_toolbar_->button_count() == 0)
233 gtk_widget_hide(actions_toolbar_->widget());
234 }
235 // Initialize pref-dependent UI state.
236 NotifyPrefChanged(NULL);
237
238 // Because the above does a recursive show all on all widgets we need to
239 // update the icon visibility to hide them.
240 location_bar_->UpdateContentSettingsIcons();
241
242 SetViewIDs();
243 theme_provider_->InitThemesFor(this);
244 }
245
246 void BrowserToolbarGtk::SetViewIDs() {
247 ViewIDUtil::SetID(widget(), VIEW_ID_TOOLBAR);
248 ViewIDUtil::SetID(back_->widget(), VIEW_ID_BACK_BUTTON);
249 ViewIDUtil::SetID(forward_->widget(), VIEW_ID_FORWARD_BUTTON);
250 ViewIDUtil::SetID(reload_->widget(), VIEW_ID_RELOAD_BUTTON);
251 ViewIDUtil::SetID(home_->widget(), VIEW_ID_HOME_BUTTON);
252 ViewIDUtil::SetID(location_bar_->widget(), VIEW_ID_LOCATION_BAR);
253 ViewIDUtil::SetID(wrench_menu_button_->widget(), VIEW_ID_APP_MENU);
254 }
255
256 void BrowserToolbarGtk::Show() {
257 gtk_widget_show(toolbar_);
258 }
259
260 void BrowserToolbarGtk::Hide() {
261 gtk_widget_hide(toolbar_);
262 }
263
264 LocationBar* BrowserToolbarGtk::GetLocationBar() const {
265 return location_bar_.get();
266 }
267
268 void BrowserToolbarGtk::UpdateForBookmarkBarVisibility(
269 bool show_bottom_padding) {
270 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment_),
271 ShouldOnlyShowLocation() ? 0 : kTopBottomPadding,
272 !show_bottom_padding || ShouldOnlyShowLocation() ? 0 : kTopBottomPadding,
273 0, 0);
274 }
275
276 void BrowserToolbarGtk::ShowAppMenu() {
277 wrench_menu_->Cancel();
278 wrench_menu_button_->SetPaintOverride(GTK_STATE_ACTIVE);
279 UserMetrics::RecordAction(UserMetricsAction("ShowAppMenu"));
280 wrench_menu_->PopupAsFromKeyEvent(wrench_menu_button_->widget());
281 }
282
283 // CommandUpdater::CommandObserver ---------------------------------------------
284
285 void BrowserToolbarGtk::EnabledStateChangedForCommand(int id, bool enabled) {
286 GtkWidget* widget = NULL;
287 switch (id) {
288 case IDC_BACK:
289 widget = back_->widget();
290 break;
291 case IDC_FORWARD:
292 widget = forward_->widget();
293 break;
294 case IDC_HOME:
295 if (home_.get())
296 widget = home_->widget();
297 break;
298 }
299 if (widget) {
300 if (!enabled && GTK_WIDGET_STATE(widget) == GTK_STATE_PRELIGHT) {
301 // If we're disabling a widget, GTK will helpfully restore it to its
302 // previous state when we re-enable it, even if that previous state
303 // is the prelight. This looks bad. See the bug for a simple repro.
304 // http://code.google.com/p/chromium/issues/detail?id=13729
305 gtk_widget_set_state(widget, GTK_STATE_NORMAL);
306 }
307 gtk_widget_set_sensitive(widget, enabled);
308 }
309 }
310
311 // MenuGtk::Delegate -----------------------------------------------------------
312
313 void BrowserToolbarGtk::StoppedShowing() {
314 // Without these calls, the hover state can get stuck since the leave-notify
315 // event is not sent when clicking a button brings up the menu.
316 gtk_chrome_button_set_hover_state(
317 GTK_CHROME_BUTTON(wrench_menu_button_->widget()), 0.0);
318 wrench_menu_button_->UnsetPaintOverride();
319
320 // Stop showing the BG page badge when we close the wrench menu.
321 BackgroundPageTracker::GetInstance()->AcknowledgeBackgroundPages();
322 }
323
324 GtkIconSet* BrowserToolbarGtk::GetIconSetForId(int idr) {
325 return theme_provider_->GetIconSetForId(idr);
326 }
327
328 // Always show images because we desire that some icons always show
329 // regardless of the system setting.
330 bool BrowserToolbarGtk::AlwaysShowIconForCmd(int command_id) const {
331 return command_id == IDC_UPGRADE_DIALOG ||
332 command_id == IDC_VIEW_BACKGROUND_PAGES;
333 }
334
335 // menus::AcceleratorProvider
336
337 bool BrowserToolbarGtk::GetAcceleratorForCommandId(
338 int id,
339 menus::Accelerator* accelerator) {
340 const menus::AcceleratorGtk* accelerator_gtk =
341 AcceleratorsGtk::GetInstance()->GetPrimaryAcceleratorForCommand(id);
342 if (accelerator_gtk)
343 *accelerator = *accelerator_gtk;
344 return !!accelerator_gtk;
345 }
346
347 // NotificationObserver --------------------------------------------------------
348
349 void BrowserToolbarGtk::Observe(NotificationType type,
350 const NotificationSource& source,
351 const NotificationDetails& details) {
352 if (type == NotificationType::PREF_CHANGED) {
353 NotifyPrefChanged(Details<std::string>(details).ptr());
354 } else if (type == NotificationType::BROWSER_THEME_CHANGED) {
355 // Update the spacing around the menu buttons
356 bool use_gtk = theme_provider_->UseGtkTheme();
357 int border = use_gtk ? 0 : 2;
358 gtk_container_set_border_width(
359 GTK_CONTAINER(wrench_menu_button_->widget()), border);
360
361 // Force the height of the toolbar so we get the right amount of padding
362 // above and below the location bar. We always force the size of the widgets
363 // to either side of the location box, but we only force the location box
364 // size in chrome-theme mode because that's the only time we try to control
365 // the font size.
366 int toolbar_height = ShouldOnlyShowLocation() ?
367 kToolbarHeightLocationBarOnly : kToolbarHeight;
368 gtk_container_foreach(GTK_CONTAINER(toolbar_), SetWidgetHeightRequest,
369 GINT_TO_POINTER(toolbar_height));
370 gtk_widget_set_size_request(location_hbox_, -1,
371 use_gtk ? -1 : toolbar_height);
372
373 // When using the GTK+ theme, we need to have the event box be visible so
374 // buttons don't get a halo color from the background. When using Chromium
375 // themes, we want to let the background show through the toolbar.
376 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_), use_gtk);
377
378 if (use_gtk) {
379 // We need to manually update the icon if we are in GTK mode. (Note that
380 // we set the initial value in Init()).
381 gtk_image_set_from_pixbuf(
382 GTK_IMAGE(wrench_menu_image_),
383 theme_provider_->GetRTLEnabledPixbufNamed(IDR_TOOLS));
384 }
385
386 UpdateRoundedness();
387 } else if (type == NotificationType::UPGRADE_RECOMMENDED ||
388 type == NotificationType::BACKGROUND_PAGE_TRACKER_CHANGED) {
389 // Redraw the wrench menu to update the badge.
390 gtk_widget_queue_draw(wrench_menu_button_->widget());
391 } else if (type == NotificationType::ZOOM_LEVEL_CHANGED) {
392 // If our zoom level changed, we need to tell the menu to update its state,
393 // since the menu could still be open.
394 wrench_menu_->UpdateMenu();
395 } else {
396 NOTREACHED();
397 }
398 }
399
400 // BrowserToolbarGtk, public ---------------------------------------------------
401
402 void BrowserToolbarGtk::SetProfile(Profile* profile) {
403 if (profile == profile_)
404 return;
405
406 profile_ = profile;
407 location_bar_->SetProfile(profile);
408 }
409
410 void BrowserToolbarGtk::UpdateTabContents(TabContents* contents,
411 bool should_restore_state) {
412 location_bar_->Update(should_restore_state ? contents : NULL);
413
414 if (actions_toolbar_.get())
415 actions_toolbar_->Update();
416 }
417
418 // BrowserToolbarGtk, private --------------------------------------------------
419
420 void BrowserToolbarGtk::SetUpDragForHomeButton(bool enable) {
421 if (enable) {
422 gtk_drag_dest_set(home_->widget(), GTK_DEST_DEFAULT_ALL,
423 NULL, 0, GDK_ACTION_COPY);
424 static const int targets[] = { gtk_dnd_util::TEXT_PLAIN,
425 gtk_dnd_util::TEXT_URI_LIST, -1 };
426 gtk_dnd_util::SetDestTargetList(home_->widget(), targets);
427
428 drop_handler_.reset(new GtkSignalRegistrar());
429 drop_handler_->Connect(home_->widget(), "drag-data-received",
430 G_CALLBACK(OnDragDataReceivedThunk), this);
431 } else {
432 gtk_drag_dest_unset(home_->widget());
433 drop_handler_.reset(NULL);
434 }
435 }
436
437 bool BrowserToolbarGtk::UpdateRoundedness() {
438 // We still round the corners if we are in chrome theme mode, but we do it by
439 // drawing theme resources rather than changing the physical shape of the
440 // widget.
441 bool should_be_rounded = theme_provider_->UseGtkTheme() &&
442 window_->ShouldDrawContentDropShadow();
443
444 if (should_be_rounded == gtk_util::IsActingAsRoundedWindow(alignment_))
445 return false;
446
447 if (should_be_rounded) {
448 gtk_util::ActAsRoundedWindow(alignment_, GdkColor(), kToolbarCornerSize,
449 gtk_util::ROUNDED_TOP,
450 gtk_util::BORDER_NONE);
451 } else {
452 gtk_util::StopActingAsRoundedWindow(alignment_);
453 }
454
455 return true;
456 }
457
458 gboolean BrowserToolbarGtk::OnAlignmentExpose(GtkWidget* widget,
459 GdkEventExpose* e) {
460 // We may need to update the roundedness of the toolbar's top corners. In
461 // this case, don't draw; we'll be called again soon enough.
462 if (UpdateRoundedness())
463 return TRUE;
464
465 // We don't need to render the toolbar image in GTK mode.
466 if (theme_provider_->UseGtkTheme())
467 return FALSE;
468
469 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
470 gdk_cairo_rectangle(cr, &e->area);
471 cairo_clip(cr);
472
473 gfx::Point tabstrip_origin =
474 window_->tabstrip()->GetTabStripOriginForWidget(widget);
475 // Fill the entire region with the toolbar color.
476 GdkColor color = theme_provider_->GetGdkColor(
477 BrowserThemeProvider::COLOR_TOOLBAR);
478 gdk_cairo_set_source_color(cr, &color);
479 cairo_fill(cr);
480
481 // The horizontal size of the top left and right corner images.
482 const int kCornerWidth = 4;
483 // The thickness of the shadow outside the toolbar's bounds; the offset
484 // between the edge of the toolbar and where we anchor the corner images.
485 const int kShadowThickness = 2;
486
487 gfx::Rect area(e->area);
488 gfx::Rect right(widget->allocation.x + widget->allocation.width -
489 kCornerWidth,
490 widget->allocation.y - kShadowThickness,
491 kCornerWidth,
492 widget->allocation.height + kShadowThickness);
493 gfx::Rect left(widget->allocation.x - kShadowThickness,
494 widget->allocation.y - kShadowThickness,
495 kCornerWidth,
496 widget->allocation.height + kShadowThickness);
497
498 if (window_->ShouldDrawContentDropShadow()) {
499 // Leave room to draw rounded corners.
500 area = area.Subtract(right).Subtract(left);
501 }
502
503 CairoCachedSurface* background = theme_provider_->GetSurfaceNamed(
504 IDR_THEME_TOOLBAR, widget);
505 background->SetSource(cr, tabstrip_origin.x(), tabstrip_origin.y());
506 cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
507 cairo_rectangle(cr, area.x(), area.y(), area.width(), area.height());
508 cairo_fill(cr);
509
510 if (!window_->ShouldDrawContentDropShadow()) {
511 // The rest of this function is for rounded corners. Our work is done here.
512 cairo_destroy(cr);
513 return FALSE;
514 }
515
516 bool draw_left_corner = left.Intersects(gfx::Rect(e->area));
517 bool draw_right_corner = right.Intersects(gfx::Rect(e->area));
518
519 if (draw_left_corner || draw_right_corner) {
520 // Create a mask which is composed of the left and/or right corners.
521 cairo_surface_t* target = cairo_surface_create_similar(
522 cairo_get_target(cr),
523 CAIRO_CONTENT_COLOR_ALPHA,
524 widget->allocation.x + widget->allocation.width,
525 widget->allocation.y + widget->allocation.height);
526 cairo_t* copy_cr = cairo_create(target);
527
528 cairo_set_operator(copy_cr, CAIRO_OPERATOR_SOURCE);
529 if (draw_left_corner) {
530 CairoCachedSurface* left_corner = theme_provider_->GetSurfaceNamed(
531 IDR_CONTENT_TOP_LEFT_CORNER_MASK, widget);
532 left_corner->SetSource(copy_cr, left.x(), left.y());
533 cairo_paint(copy_cr);
534 }
535 if (draw_right_corner) {
536 CairoCachedSurface* right_corner = theme_provider_->GetSurfaceNamed(
537 IDR_CONTENT_TOP_RIGHT_CORNER_MASK, widget);
538 right_corner->SetSource(copy_cr, right.x(), right.y());
539 // We fill a path rather than just painting because we don't want to
540 // overwrite the left corner.
541 cairo_rectangle(copy_cr, right.x(), right.y(),
542 right.width(), right.height());
543 cairo_fill(copy_cr);
544 }
545
546 // Draw the background. CAIRO_OPERATOR_IN uses the existing pixel data as
547 // an alpha mask.
548 background->SetSource(copy_cr, tabstrip_origin.x(), tabstrip_origin.y());
549 cairo_set_operator(copy_cr, CAIRO_OPERATOR_IN);
550 cairo_pattern_set_extend(cairo_get_source(copy_cr), CAIRO_EXTEND_REPEAT);
551 cairo_paint(copy_cr);
552 cairo_destroy(copy_cr);
553
554 // Copy the temporary surface to the screen.
555 cairo_set_source_surface(cr, target, 0, 0);
556 cairo_paint(cr);
557 cairo_surface_destroy(target);
558 }
559
560 cairo_destroy(cr);
561
562 return FALSE; // Allow subwidgets to paint.
563 }
564
565 gboolean BrowserToolbarGtk::OnLocationHboxExpose(GtkWidget* location_hbox,
566 GdkEventExpose* e) {
567 if (theme_provider_->UseGtkTheme()) {
568 gtk_util::DrawTextEntryBackground(offscreen_entry_.get(),
569 location_hbox, &e->area,
570 &location_hbox->allocation);
571 }
572
573 return FALSE;
574 }
575
576 void BrowserToolbarGtk::OnButtonClick(GtkWidget* button) {
577 if ((button == back_->widget()) || (button == forward_->widget())) {
578 if (gtk_util::DispositionForCurrentButtonPressEvent() == CURRENT_TAB)
579 location_bar_->Revert();
580 return;
581 }
582
583 DCHECK(home_.get() && button == home_->widget()) <<
584 "Unexpected button click callback";
585 browser_->Home(gtk_util::DispositionForCurrentButtonPressEvent());
586 }
587
588 gboolean BrowserToolbarGtk::OnMenuButtonPressEvent(GtkWidget* button,
589 GdkEventButton* event) {
590 if (event->button != 1)
591 return FALSE;
592
593 wrench_menu_button_->SetPaintOverride(GTK_STATE_ACTIVE);
594 wrench_menu_->Popup(button, reinterpret_cast<GdkEvent*>(event));
595
596 return TRUE;
597 }
598
599 void BrowserToolbarGtk::OnDragDataReceived(GtkWidget* widget,
600 GdkDragContext* drag_context, gint x, gint y,
601 GtkSelectionData* data, guint info, guint time) {
602 if (info != gtk_dnd_util::TEXT_PLAIN) {
603 NOTIMPLEMENTED() << "Only support plain text drops for now, sorry!";
604 return;
605 }
606
607 GURL url(reinterpret_cast<char*>(data->data));
608 if (!url.is_valid())
609 return;
610
611 bool url_is_newtab = url.spec() == chrome::kChromeUINewTabURL;
612 home_page_is_new_tab_page_.SetValue(url_is_newtab);
613 if (!url_is_newtab)
614 home_page_.SetValue(url.spec());
615 }
616
617 void BrowserToolbarGtk::NotifyPrefChanged(const std::string* pref) {
618 if (!pref || *pref == prefs::kShowHomeButton) {
619 if (show_home_button_.GetValue() && !ShouldOnlyShowLocation()) {
620 gtk_widget_show(home_->widget());
621 } else {
622 gtk_widget_hide(home_->widget());
623 }
624 }
625
626 if (!pref ||
627 *pref == prefs::kHomePage ||
628 *pref == prefs::kHomePageIsNewTabPage)
629 SetUpDragForHomeButton(!home_page_.IsManaged() &&
630 !home_page_is_new_tab_page_.IsManaged());
631 }
632
633 bool BrowserToolbarGtk::ShouldOnlyShowLocation() const {
634 // If we're a popup window, only show the location bar (omnibox).
635 return browser_->type() != Browser::TYPE_NORMAL;
636 }
637
638 gboolean BrowserToolbarGtk::OnWrenchMenuButtonExpose(GtkWidget* sender,
639 GdkEventExpose* expose) {
640 const SkBitmap* badge = NULL;
641 if (UpgradeDetector::GetInstance()->notify_upgrade()) {
642 badge = theme_provider_->GetBitmapNamed(IDR_UPDATE_BADGE);
643 } else if (BackgroundPageTracker::GetInstance()->
644 GetUnacknowledgedBackgroundPageCount()) {
645 badge = theme_provider_->GetBitmapNamed(IDR_BACKGROUND_BADGE);
646 } else {
647 return FALSE;
648 }
649
650 // Draw the chrome app menu icon onto the canvas.
651 gfx::CanvasSkiaPaint canvas(expose, false);
652 int x_offset = base::i18n::IsRTL() ? 0 :
653 sender->allocation.width - badge->width();
654 int y_offset = 0;
655 canvas.DrawBitmapInt(
656 *badge,
657 sender->allocation.x + x_offset,
658 sender->allocation.y + y_offset);
659
660 return FALSE;
661 }
OLDNEW
« no previous file with comments | « chrome/browser/gtk/browser_toolbar_gtk.h ('k') | chrome/browser/gtk/browser_window_factory_gtk.cc » ('j') | no next file with comments »

Powered by Google App Engine