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 |