Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/gtk/browser_titlebar.h" | 5 #include "chrome/browser/ui/gtk/browser_titlebar.h" |
| 6 | 6 |
| 7 #include <gdk/gdkkeysyms.h> | 7 #include <gdk/gdkkeysyms.h> |
| 8 #include <gtk/gtk.h> | 8 #include <gtk/gtk.h> |
| 9 | 9 |
| 10 #include <string> | 10 #include <string> |
| (...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 427 StringTokenizer tokenizer(button_string, ":,"); | 427 StringTokenizer tokenizer(button_string, ":,"); |
| 428 tokenizer.set_options(StringTokenizer::RETURN_DELIMS); | 428 tokenizer.set_options(StringTokenizer::RETURN_DELIMS); |
| 429 int left_count = 0; | 429 int left_count = 0; |
| 430 int right_count = 0; | 430 int right_count = 0; |
| 431 while (tokenizer.GetNext()) { | 431 while (tokenizer.GetNext()) { |
| 432 if (tokenizer.token_is_delim()) { | 432 if (tokenizer.token_is_delim()) { |
| 433 if (*tokenizer.token_begin() == ':') | 433 if (*tokenizer.token_begin() == ':') |
| 434 left_side = false; | 434 left_side = false; |
| 435 } else { | 435 } else { |
| 436 base::StringPiece token = tokenizer.token_piece(); | 436 base::StringPiece token = tokenizer.token_piece(); |
| 437 if (token == "minimize" && !IsTypePanel()) { | 437 if (BuildButton(token.as_string(), left_side)) |
| 438 (left_side ? left_count : right_count)++; | 438 (left_side ? left_count : right_count)++; |
| 439 GtkWidget* parent_box = GetButtonHBox(left_side); | |
| 440 minimize_button_.reset( | |
| 441 BuildTitlebarButton(IDR_MINIMIZE, IDR_MINIMIZE_P, | |
| 442 IDR_MINIMIZE_H, parent_box, true, | |
| 443 IDS_XPFRAME_MINIMIZE_TOOLTIP)); | |
| 444 | |
| 445 gtk_widget_size_request(minimize_button_->widget(), | |
| 446 &minimize_button_req_); | |
| 447 } else if (token == "maximize" && !IsTypePanel()) { | |
| 448 (left_side ? left_count : right_count)++; | |
| 449 GtkWidget* parent_box = GetButtonHBox(left_side); | |
| 450 restore_button_.reset( | |
| 451 BuildTitlebarButton(IDR_RESTORE, IDR_RESTORE_P, | |
| 452 IDR_RESTORE_H, parent_box, true, | |
| 453 IDS_XPFRAME_RESTORE_TOOLTIP)); | |
| 454 maximize_button_.reset( | |
| 455 BuildTitlebarButton(IDR_MAXIMIZE, IDR_MAXIMIZE_P, | |
| 456 IDR_MAXIMIZE_H, parent_box, true, | |
| 457 IDS_XPFRAME_MAXIMIZE_TOOLTIP)); | |
| 458 | |
| 459 gtk_util::SetButtonClickableByMouseButtons(maximize_button_->widget(), | |
| 460 true, true, true); | |
| 461 gtk_widget_size_request(restore_button_->widget(), | |
| 462 &restore_button_req_); | |
| 463 } else if (token == "close") { | |
| 464 (left_side ? left_count : right_count)++; | |
| 465 GtkWidget* parent_box = GetButtonHBox(left_side); | |
| 466 close_button_.reset( | |
| 467 BuildTitlebarButton(IDR_CLOSE, IDR_CLOSE_P, | |
| 468 IDR_CLOSE_H, parent_box, true, | |
| 469 IDS_XPFRAME_CLOSE_TOOLTIP)); | |
| 470 close_button_->set_flipped(left_side); | |
| 471 | |
| 472 gtk_widget_size_request(close_button_->widget(), &close_button_req_); | |
| 473 } | |
| 474 // Ignore any other values like "pin" since we don't have images for | |
| 475 // those. | |
| 476 } | 439 } |
| 477 } | 440 } |
| 478 | 441 |
| 479 // If we are in incognito mode, add the spy guy to either the end of the left | 442 // If we are in incognito mode, add the spy guy to either the end of the left |
| 480 // or the beginning of the right depending on which side has fewer buttons. | 443 // or the beginning of the right depending on which side has fewer buttons. |
| 481 display_avatar_on_left_ = right_count > left_count; | 444 display_avatar_on_left_ = right_count > left_count; |
| 482 | 445 |
| 483 // Now show the correct widgets in the two hierarchies. | 446 // Now show the correct widgets in the two hierarchies. |
| 484 if (using_custom_frame_) { | 447 if (using_custom_frame_) { |
| 485 gtk_widget_show_all(titlebar_left_buttons_vbox_); | 448 gtk_widget_show_all(titlebar_left_buttons_vbox_); |
| 486 gtk_widget_show_all(titlebar_right_buttons_vbox_); | 449 gtk_widget_show_all(titlebar_right_buttons_vbox_); |
| 487 } | 450 } |
| 488 UpdateMaximizeRestoreVisibility(); | 451 UpdateMaximizeRestoreVisibility(); |
| 489 } | 452 } |
| 490 | 453 |
| 454 bool BrowserTitlebar::BuildButton(const std::string& button_token, | |
| 455 bool left_side) { | |
| 456 if (button_token == "minimize") { | |
| 457 GtkWidget* parent_box = GetButtonHBox(left_side); | |
| 458 minimize_button_.reset( | |
| 459 CreateTitlebarButton(IDR_MINIMIZE, IDR_MINIMIZE_P, | |
| 460 IDR_MINIMIZE_H, parent_box, | |
| 461 IDS_XPFRAME_MINIMIZE_TOOLTIP)); | |
| 462 | |
| 463 gtk_widget_size_request(minimize_button_->widget(), | |
| 464 &minimize_button_req_); | |
| 465 return true; | |
| 466 } else if (button_token == "maximize") { | |
|
jennb
2012/04/20 22:26:32
Should we add a "restore" token and separate the b
jianli
2012/04/20 23:00:29
We can't do that because the passing string to Bui
jennb
2012/04/21 01:04:49
You could modify the passed in string, kDefaultBut
| |
| 467 GtkWidget* parent_box = GetButtonHBox(left_side); | |
| 468 restore_button_.reset( | |
| 469 CreateTitlebarButton(IDR_RESTORE, IDR_RESTORE_P, | |
| 470 IDR_RESTORE_H, parent_box, | |
| 471 IDS_XPFRAME_RESTORE_TOOLTIP)); | |
| 472 maximize_button_.reset( | |
| 473 CreateTitlebarButton(IDR_MAXIMIZE, IDR_MAXIMIZE_P, | |
| 474 IDR_MAXIMIZE_H, parent_box, | |
| 475 IDS_XPFRAME_MAXIMIZE_TOOLTIP)); | |
| 476 | |
| 477 gtk_util::SetButtonClickableByMouseButtons(maximize_button_->widget(), | |
| 478 true, true, true); | |
| 479 gtk_widget_size_request(restore_button_->widget(), | |
| 480 &restore_button_req_); | |
| 481 return true; | |
| 482 } else if (button_token == "close") { | |
| 483 GtkWidget* parent_box = GetButtonHBox(left_side); | |
| 484 close_button_.reset( | |
| 485 CreateTitlebarButton(IDR_CLOSE, IDR_CLOSE_P, | |
| 486 IDR_CLOSE_H, parent_box, | |
| 487 IDS_XPFRAME_CLOSE_TOOLTIP)); | |
| 488 close_button_->set_flipped(left_side); | |
| 489 | |
| 490 gtk_widget_size_request(close_button_->widget(), &close_button_req_); | |
| 491 return true; | |
| 492 } | |
| 493 // Ignore any other values like "pin" since we don't have images for | |
| 494 // those. | |
| 495 return false; | |
| 496 } | |
| 497 | |
| 491 GtkWidget* BrowserTitlebar::GetButtonHBox(bool left_side) { | 498 GtkWidget* BrowserTitlebar::GetButtonHBox(bool left_side) { |
| 492 if (left_side && titlebar_left_buttons_hbox_) | 499 if (left_side && titlebar_left_buttons_hbox_) |
| 493 return titlebar_left_buttons_hbox_; | 500 return titlebar_left_buttons_hbox_; |
| 494 else if (!left_side && titlebar_right_buttons_hbox_) | 501 else if (!left_side && titlebar_right_buttons_hbox_) |
| 495 return titlebar_right_buttons_hbox_; | 502 return titlebar_right_buttons_hbox_; |
| 496 | 503 |
| 497 // We put the min/max/restore/close buttons in a vbox so they are top aligned | 504 // We put the min/max/restore/close buttons in a vbox so they are top aligned |
| 498 // (up to padding) and don't vertically stretch. | 505 // (up to padding) and don't vertically stretch. |
| 499 GtkWidget* vbox = left_side ? titlebar_left_buttons_vbox_ : | 506 GtkWidget* vbox = left_side ? titlebar_left_buttons_vbox_ : |
| 500 titlebar_right_buttons_vbox_; | 507 titlebar_right_buttons_vbox_; |
| 501 | 508 |
| 502 GtkWidget* top_padding = gtk_fixed_new(); | 509 GtkWidget* top_padding = gtk_fixed_new(); |
| 503 gtk_widget_set_size_request(top_padding, -1, kButtonOuterPadding); | 510 gtk_widget_set_size_request(top_padding, -1, kButtonOuterPadding); |
| 504 gtk_box_pack_start(GTK_BOX(vbox), top_padding, FALSE, FALSE, 0); | 511 gtk_box_pack_start(GTK_BOX(vbox), top_padding, FALSE, FALSE, 0); |
| 505 | 512 |
| 506 GtkWidget* buttons_hbox = gtk_hbox_new(FALSE, kButtonSpacing); | 513 GtkWidget* buttons_hbox = gtk_hbox_new(FALSE, kButtonSpacing); |
| 507 gtk_box_pack_start(GTK_BOX(vbox), buttons_hbox, FALSE, FALSE, 0); | 514 gtk_box_pack_start(GTK_BOX(vbox), buttons_hbox, FALSE, FALSE, 0); |
| 508 | 515 |
| 509 if (left_side) { | 516 if (left_side) { |
| 510 titlebar_left_buttons_hbox_ = buttons_hbox; | 517 titlebar_left_buttons_hbox_ = buttons_hbox; |
| 511 top_padding_left_ = top_padding; | 518 top_padding_left_ = top_padding; |
| 512 } else { | 519 } else { |
| 513 titlebar_right_buttons_hbox_ = buttons_hbox; | 520 titlebar_right_buttons_hbox_ = buttons_hbox; |
| 514 top_padding_right_ = top_padding; | 521 top_padding_right_ = top_padding; |
| 515 } | 522 } |
| 516 | 523 |
| 517 return buttons_hbox; | 524 return buttons_hbox; |
| 518 } | 525 } |
| 519 | 526 |
| 520 CustomDrawButton* BrowserTitlebar::BuildTitlebarButton(int image, | 527 CustomDrawButton* BrowserTitlebar::CreateTitlebarButton(int image, |
| 521 int image_pressed, int image_hot, GtkWidget* box, bool start, | 528 int image_pressed, int image_hot, GtkWidget* box, int tooltip) { |
| 522 int tooltip) { | |
| 523 CustomDrawButton* button = new CustomDrawButton(image, image_pressed, | 529 CustomDrawButton* button = new CustomDrawButton(image, image_pressed, |
| 524 image_hot, 0); | 530 image_hot, 0); |
| 525 gtk_widget_add_events(GTK_WIDGET(button->widget()), GDK_POINTER_MOTION_MASK); | 531 gtk_widget_add_events(GTK_WIDGET(button->widget()), GDK_POINTER_MOTION_MASK); |
| 526 g_signal_connect(button->widget(), "clicked", | 532 g_signal_connect(button->widget(), "clicked", |
| 527 G_CALLBACK(OnButtonClickedThunk), this); | 533 G_CALLBACK(OnButtonClickedThunk), this); |
| 528 g_signal_connect(button->widget(), "motion-notify-event", | 534 g_signal_connect(button->widget(), "motion-notify-event", |
| 529 G_CALLBACK(OnMouseMoveEvent), browser_window_); | 535 G_CALLBACK(OnMouseMoveEvent), browser_window_); |
| 530 std::string localized_tooltip = l10n_util::GetStringUTF8(tooltip); | 536 std::string localized_tooltip = l10n_util::GetStringUTF8(tooltip); |
| 531 gtk_widget_set_tooltip_text(button->widget(), | 537 gtk_widget_set_tooltip_text(button->widget(), |
| 532 localized_tooltip.c_str()); | 538 localized_tooltip.c_str()); |
| 533 if (start) | 539 gtk_box_pack_start(GTK_BOX(box), button->widget(), FALSE, FALSE, 0); |
| 534 gtk_box_pack_start(GTK_BOX(box), button->widget(), FALSE, FALSE, 0); | |
| 535 else | |
| 536 gtk_box_pack_end(GTK_BOX(box), button->widget(), FALSE, FALSE, 0); | |
| 537 return button; | 540 return button; |
| 538 } | 541 } |
| 539 | 542 |
| 540 void BrowserTitlebar::UpdateButtonBackground(CustomDrawButton* button) { | 543 void BrowserTitlebar::UpdateButtonBackground(CustomDrawButton* button) { |
| 541 SkColor color = theme_service_->GetColor( | 544 SkColor color = theme_service_->GetColor( |
| 542 ThemeService::COLOR_BUTTON_BACKGROUND); | 545 ThemeService::COLOR_BUTTON_BACKGROUND); |
| 543 SkBitmap* background = | 546 SkBitmap* background = |
| 544 theme_service_->GetBitmapNamed(IDR_THEME_WINDOW_CONTROL_BACKGROUND); | 547 theme_service_->GetBitmapNamed(IDR_THEME_WINDOW_CONTROL_BACKGROUND); |
| 545 | 548 |
| 546 // TODO(erg): For now, we just use a completely black mask and we can get | 549 // TODO(erg): For now, we just use a completely black mask and we can get |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 622 void BrowserTitlebar::UpdateThrobber(WebContents* web_contents) { | 625 void BrowserTitlebar::UpdateThrobber(WebContents* web_contents) { |
| 623 DCHECK(app_mode_favicon_); | 626 DCHECK(app_mode_favicon_); |
| 624 | 627 |
| 625 if (web_contents && web_contents->IsLoading()) { | 628 if (web_contents && web_contents->IsLoading()) { |
| 626 GdkPixbuf* icon_pixbuf = | 629 GdkPixbuf* icon_pixbuf = |
| 627 throbber_.GetNextFrame(web_contents->IsWaitingForResponse()); | 630 throbber_.GetNextFrame(web_contents->IsWaitingForResponse()); |
| 628 gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_), icon_pixbuf); | 631 gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_), icon_pixbuf); |
| 629 } else { | 632 } else { |
| 630 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 633 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 631 | 634 |
| 632 // Note: we want to exclude the application popup window. | 635 // Note: we want to exclude the application popup/panel window. |
| 633 if ((browser_window_->browser()->is_app() && | 636 if ((browser_window_->browser()->is_app() && |
| 634 browser_window_->browser()->is_type_popup()) || | 637 !browser_window_->browser()->is_type_tabbed())) { |
| 635 IsTypePanel()) { | |
| 636 SkBitmap icon = browser_window_->browser()->GetCurrentPageIcon(); | 638 SkBitmap icon = browser_window_->browser()->GetCurrentPageIcon(); |
| 637 if (icon.empty()) { | 639 if (icon.empty()) { |
| 638 // Fallback to the Chromium icon if the page has no icon. | 640 // Fallback to the Chromium icon if the page has no icon. |
| 639 gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_), | 641 gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_), |
| 640 rb.GetNativeImageNamed(IDR_PRODUCT_LOGO_16).ToGdkPixbuf()); | 642 rb.GetNativeImageNamed(IDR_PRODUCT_LOGO_16).ToGdkPixbuf()); |
| 641 } else { | 643 } else { |
| 642 GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(&icon); | 644 GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(&icon); |
| 643 gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_), icon_pixbuf); | 645 gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_), icon_pixbuf); |
| 644 g_object_unref(icon_pixbuf); | 646 g_object_unref(icon_pixbuf); |
| 645 } | 647 } |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 897 browser_window_->UnMaximize(); | 899 browser_window_->UnMaximize(); |
| 898 } else if (maximize_button_.get() && maximize_button_->widget() == button) { | 900 } else if (maximize_button_.get() && maximize_button_->widget() == button) { |
| 899 MaximizeButtonClicked(); | 901 MaximizeButtonClicked(); |
| 900 } else if (minimize_button_.get() && minimize_button_->widget() == button) { | 902 } else if (minimize_button_.get() && minimize_button_->widget() == button) { |
| 901 gtk_window_iconify(window_); | 903 gtk_window_iconify(window_); |
| 902 } | 904 } |
| 903 } | 905 } |
| 904 | 906 |
| 905 gboolean BrowserTitlebar::OnFaviconMenuButtonPressed(GtkWidget* widget, | 907 gboolean BrowserTitlebar::OnFaviconMenuButtonPressed(GtkWidget* widget, |
| 906 GdkEventButton* event) { | 908 GdkEventButton* event) { |
| 907 if (event->button != 1 || IsTypePanel()) | 909 if (event->button != 1) |
| 908 return FALSE; | 910 return FALSE; |
| 909 | 911 |
| 910 ShowFaviconMenu(event); | 912 ShowFaviconMenu(event); |
| 911 return TRUE; | 913 return TRUE; |
| 912 } | 914 } |
| 913 | 915 |
| 914 void BrowserTitlebar::ShowContextMenu(GdkEventButton* event) { | 916 void BrowserTitlebar::ShowContextMenu(GdkEventButton* event) { |
| 915 if (!context_menu_.get()) { | 917 if (!context_menu_.get()) { |
| 916 context_menu_model_.reset(new ContextMenuModel(this)); | 918 context_menu_model_.reset(new ContextMenuModel(this)); |
| 917 context_menu_.reset(new MenuGtk(NULL, context_menu_model_.get())); | 919 context_menu_.reset(new MenuGtk(NULL, context_menu_model_.get())); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1048 // Can be called during shutdown; BrowserWindowGtk will set our |window_| | 1050 // Can be called during shutdown; BrowserWindowGtk will set our |window_| |
| 1049 // to NULL during that time. | 1051 // to NULL during that time. |
| 1050 if (!window_) | 1052 if (!window_) |
| 1051 return; | 1053 return; |
| 1052 | 1054 |
| 1053 window_has_focus_ = | 1055 window_has_focus_ = |
| 1054 gtk_widget_get_window(GTK_WIDGET(window_)) == active_window; | 1056 gtk_widget_get_window(GTK_WIDGET(window_)) == active_window; |
| 1055 UpdateTextColor(); | 1057 UpdateTextColor(); |
| 1056 } | 1058 } |
| 1057 | 1059 |
| 1058 bool BrowserTitlebar::IsTypePanel() { | |
| 1059 return browser_window_->browser()->is_type_panel(); | |
| 1060 } | |
| 1061 | |
| 1062 bool BrowserTitlebar::ShouldDisplayAvatar() { | 1060 bool BrowserTitlebar::ShouldDisplayAvatar() { |
| 1063 return (IsOffTheRecord() || HasMultipleProfiles()) && | 1061 return (IsOffTheRecord() || HasMultipleProfiles()) && |
| 1064 browser_window_->browser()->is_type_tabbed(); | 1062 browser_window_->browser()->is_type_tabbed(); |
| 1065 } | 1063 } |
| 1066 | 1064 |
| 1067 bool BrowserTitlebar::IsOffTheRecord() { | 1065 bool BrowserTitlebar::IsOffTheRecord() { |
| 1068 return browser_window_->browser()->profile()->IsOffTheRecord(); | 1066 return browser_window_->browser()->profile()->IsOffTheRecord(); |
| 1069 } | 1067 } |
| 1070 | 1068 |
| 1071 /////////////////////////////////////////////////////////////////////////////// | 1069 /////////////////////////////////////////////////////////////////////////////// |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1128 ui::SimpleMenuModel::Delegate* delegate) | 1126 ui::SimpleMenuModel::Delegate* delegate) |
| 1129 : SimpleMenuModel(delegate) { | 1127 : SimpleMenuModel(delegate) { |
| 1130 AddItemWithStringId(IDC_NEW_TAB, IDS_TAB_CXMENU_NEWTAB); | 1128 AddItemWithStringId(IDC_NEW_TAB, IDS_TAB_CXMENU_NEWTAB); |
| 1131 AddItemWithStringId(IDC_RESTORE_TAB, IDS_RESTORE_TAB); | 1129 AddItemWithStringId(IDC_RESTORE_TAB, IDS_RESTORE_TAB); |
| 1132 AddSeparator(); | 1130 AddSeparator(); |
| 1133 AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER); | 1131 AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER); |
| 1134 AddSeparator(); | 1132 AddSeparator(); |
| 1135 AddCheckItemWithStringId(kShowWindowDecorationsCommand, | 1133 AddCheckItemWithStringId(kShowWindowDecorationsCommand, |
| 1136 IDS_SHOW_WINDOW_DECORATIONS_MENU); | 1134 IDS_SHOW_WINDOW_DECORATIONS_MENU); |
| 1137 } | 1135 } |
| OLD | NEW |