| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/views/toolbar_view.h" | 5 #include "chrome/browser/views/toolbar_view.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "app/drag_drop_types.h" | 9 #include "app/drag_drop_types.h" |
| 10 #include "app/gfx/canvas.h" | 10 #include "app/gfx/canvas.h" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 #include "chrome/common/pref_names.h" | 45 #include "chrome/common/pref_names.h" |
| 46 #include "chrome/common/pref_service.h" | 46 #include "chrome/common/pref_service.h" |
| 47 #include "grit/chromium_strings.h" | 47 #include "grit/chromium_strings.h" |
| 48 #include "grit/generated_resources.h" | 48 #include "grit/generated_resources.h" |
| 49 #include "grit/theme_resources.h" | 49 #include "grit/theme_resources.h" |
| 50 #include "net/base/net_util.h" | 50 #include "net/base/net_util.h" |
| 51 #include "views/background.h" | 51 #include "views/background.h" |
| 52 #include "views/controls/button/button_dropdown.h" | 52 #include "views/controls/button/button_dropdown.h" |
| 53 #include "views/controls/label.h" | 53 #include "views/controls/label.h" |
| 54 #include "views/drag_utils.h" | 54 #include "views/drag_utils.h" |
| 55 #include "views/focus/view_storage.h" | |
| 56 #include "views/widget/root_view.h" | |
| 57 #include "views/widget/tooltip_manager.h" | |
| 58 #include "views/window/non_client_view.h" | 55 #include "views/window/non_client_view.h" |
| 59 #include "views/window/window.h" | 56 #include "views/window/window.h" |
| 60 | 57 |
| 61 static const int kControlHorizOffset = 4; | 58 static const int kControlHorizOffset = 4; |
| 62 static const int kControlVertOffset = 6; | 59 static const int kControlVertOffset = 6; |
| 63 static const int kControlIndent = 3; | 60 static const int kControlIndent = 3; |
| 64 static const int kStatusBubbleWidth = 480; | 61 static const int kStatusBubbleWidth = 480; |
| 65 | 62 |
| 66 // Separation between the location bar and the menus. | 63 // Separation between the location bar and the menus. |
| 67 static const int kMenuButtonOffset = 3; | 64 static const int kMenuButtonOffset = 3; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 AddItemWithStringId(IDC_ZOOM_PLUS, IDS_ZOOM_PLUS); | 144 AddItemWithStringId(IDC_ZOOM_PLUS, IDS_ZOOM_PLUS); |
| 148 AddItemWithStringId(IDC_ZOOM_NORMAL, IDS_ZOOM_NORMAL); | 145 AddItemWithStringId(IDC_ZOOM_NORMAL, IDS_ZOOM_NORMAL); |
| 149 AddItemWithStringId(IDC_ZOOM_MINUS, IDS_ZOOM_MINUS); | 146 AddItemWithStringId(IDC_ZOOM_MINUS, IDS_ZOOM_MINUS); |
| 150 } | 147 } |
| 151 | 148 |
| 152 //////////////////////////////////////////////////////////////////////////////// | 149 //////////////////////////////////////////////////////////////////////////////// |
| 153 // ToolbarView, public: | 150 // ToolbarView, public: |
| 154 | 151 |
| 155 ToolbarView::ToolbarView(Browser* browser) | 152 ToolbarView::ToolbarView(Browser* browser) |
| 156 : model_(browser->toolbar_model()), | 153 : model_(browser->toolbar_model()), |
| 157 acc_focused_view_(NULL), | |
| 158 last_focused_view_storage_id_( | |
| 159 views::ViewStorage::GetSharedInstance()->CreateStorageID()), | |
| 160 back_(NULL), | 154 back_(NULL), |
| 161 forward_(NULL), | 155 forward_(NULL), |
| 162 reload_(NULL), | 156 reload_(NULL), |
| 163 home_(NULL), | 157 home_(NULL), |
| 164 star_(NULL), | 158 star_(NULL), |
| 165 location_bar_(NULL), | 159 location_bar_(NULL), |
| 166 go_(NULL), | 160 go_(NULL), |
| 167 browser_actions_(NULL), | 161 browser_actions_(NULL), |
| 168 page_menu_(NULL), | 162 page_menu_(NULL), |
| 169 app_menu_(NULL), | 163 app_menu_(NULL), |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 } | 212 } |
| 219 | 213 |
| 220 void ToolbarView::Update(TabContents* tab, bool should_restore_state) { | 214 void ToolbarView::Update(TabContents* tab, bool should_restore_state) { |
| 221 if (location_bar_) | 215 if (location_bar_) |
| 222 location_bar_->Update(should_restore_state ? tab : NULL); | 216 location_bar_->Update(should_restore_state ? tab : NULL); |
| 223 | 217 |
| 224 if (browser_actions_) | 218 if (browser_actions_) |
| 225 browser_actions_->RefreshBrowserActionViews(); | 219 browser_actions_->RefreshBrowserActionViews(); |
| 226 } | 220 } |
| 227 | 221 |
| 228 int ToolbarView::GetNextAccessibleViewIndex(int view_index, bool nav_left) { | 222 //////////////////////////////////////////////////////////////////////////////// |
| 229 int modifier = 1; | 223 // ToolbarView, AccessibleToolbarView overrides: |
| 230 | 224 |
| 231 if (nav_left) | 225 bool ToolbarView::IsAccessibleViewTraversable(views::View* view) { |
| 232 modifier = -1; | 226 return view != location_bar_; |
| 233 | |
| 234 int current_view_index = view_index + modifier; | |
| 235 | |
| 236 while ((current_view_index >= 0) && | |
| 237 (current_view_index < GetChildViewCount())) { | |
| 238 // Skip the location bar, as it has its own keyboard navigation. Also skip | |
| 239 // any views that cannot be interacted with. | |
| 240 if (current_view_index == GetChildIndex(location_bar_) || | |
| 241 !GetChildViewAt(current_view_index)->IsEnabled() || | |
| 242 !GetChildViewAt(current_view_index)->IsVisible()) { | |
| 243 current_view_index += modifier; | |
| 244 continue; | |
| 245 } | |
| 246 // Update view_index with the available button index found. | |
| 247 view_index = current_view_index; | |
| 248 break; | |
| 249 } | |
| 250 // Returns the next available button index, or if no button is available in | |
| 251 // the specified direction, remains where it was. | |
| 252 return view_index; | |
| 253 } | |
| 254 | |
| 255 void ToolbarView::InitializeTraversal() { | |
| 256 // If MSAA focus exists, we don't need to traverse, since its already active. | |
| 257 if (acc_focused_view_ != NULL) | |
| 258 return; | |
| 259 | |
| 260 // Save the last focused view so that when the user presses ESC, it will | |
| 261 // return back to the last focus. | |
| 262 views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance(); | |
| 263 view_storage->StoreView(last_focused_view_storage_id_, | |
| 264 GetRootView()->GetFocusedView()); | |
| 265 | |
| 266 // HACK: Do not use RequestFocus() here, as the toolbar is not marked as | |
| 267 // "focusable". Instead bypass the sanity check in RequestFocus() and just | |
| 268 // force it to focus, which will do the right thing. | |
| 269 GetRootView()->FocusView(this); | |
| 270 } | 227 } |
| 271 | 228 |
| 272 //////////////////////////////////////////////////////////////////////////////// | 229 //////////////////////////////////////////////////////////////////////////////// |
| 273 // ToolbarView, Menu::BaseControllerDelegate overrides: | 230 // ToolbarView, Menu::BaseControllerDelegate overrides: |
| 274 | 231 |
| 275 bool ToolbarView::GetAcceleratorInfo(int id, views::Accelerator* accel) { | 232 bool ToolbarView::GetAcceleratorInfo(int id, views::Accelerator* accel) { |
| 276 return GetWidget()->GetAccelerator(id, accel); | 233 return GetWidget()->GetAccelerator(id, accel); |
| 277 } | 234 } |
| 278 | 235 |
| 279 //////////////////////////////////////////////////////////////////////////////// | 236 //////////////////////////////////////////////////////////////////////////////// |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 623 if (GetWindow()->GetNonClientView()->UseNativeFrame()) | 580 if (GetWindow()->GetNonClientView()->UseNativeFrame()) |
| 624 canvas->FillRectInt(SK_ColorBLACK, 0, height() - 1, width(), 1); | 581 canvas->FillRectInt(SK_ColorBLACK, 0, height() - 1, width(), 1); |
| 625 } | 582 } |
| 626 | 583 |
| 627 void ToolbarView::ThemeChanged() { | 584 void ToolbarView::ThemeChanged() { |
| 628 LoadLeftSideControlsImages(); | 585 LoadLeftSideControlsImages(); |
| 629 LoadCenterStackImages(); | 586 LoadCenterStackImages(); |
| 630 LoadRightSideControlsImages(); | 587 LoadRightSideControlsImages(); |
| 631 } | 588 } |
| 632 | 589 |
| 633 void ToolbarView::ShowContextMenu(int x, int y, bool is_mouse_gesture) { | |
| 634 if (acc_focused_view_) | |
| 635 acc_focused_view_->ShowContextMenu(x, y, is_mouse_gesture); | |
| 636 } | |
| 637 | |
| 638 void ToolbarView::DidGainFocus() { | |
| 639 // Check to see if MSAA focus should be restored to previously focused button, | |
| 640 // and if button is an enabled, visibled child of toolbar. | |
| 641 if (!acc_focused_view_ || | |
| 642 (acc_focused_view_->GetParent()->GetID() != VIEW_ID_TOOLBAR) || | |
| 643 !acc_focused_view_->IsEnabled() || | |
| 644 !acc_focused_view_->IsVisible()) { | |
| 645 // Find first accessible child (-1 to start search at parent). | |
| 646 int first_acc_child = GetNextAccessibleViewIndex(-1, false); | |
| 647 | |
| 648 // No buttons enabled or visible. | |
| 649 if (first_acc_child == -1) | |
| 650 return; | |
| 651 | |
| 652 set_acc_focused_view(GetChildViewAt(first_acc_child)); | |
| 653 } | |
| 654 | |
| 655 // Default focus is on the toolbar. | |
| 656 int view_index = VIEW_ID_TOOLBAR; | |
| 657 | |
| 658 // Set hot-tracking for child, and update focused_view for MSAA focus event. | |
| 659 if (acc_focused_view_) { | |
| 660 acc_focused_view_->SetHotTracked(true); | |
| 661 | |
| 662 // Show the tooltip for the view that got the focus. | |
| 663 if (GetWidget()->GetTooltipManager()) | |
| 664 GetWidget()->GetTooltipManager()->ShowKeyboardTooltip(acc_focused_view_); | |
| 665 | |
| 666 // Update focused_view with MSAA-adjusted child id. | |
| 667 view_index = acc_focused_view_->GetID(); | |
| 668 } | |
| 669 | |
| 670 #if defined(OS_WIN) | |
| 671 gfx::NativeView wnd = GetWidget()->GetNativeView(); | |
| 672 | |
| 673 // Notify Access Technology that there was a change in keyboard focus. | |
| 674 ::NotifyWinEvent(EVENT_OBJECT_FOCUS, wnd, OBJID_CLIENT, | |
| 675 static_cast<LONG>(view_index)); | |
| 676 #else | |
| 677 // TODO(port): deal with toolbar a11y focus. | |
| 678 NOTIMPLEMENTED(); | |
| 679 #endif | |
| 680 } | |
| 681 | |
| 682 void ToolbarView::WillLoseFocus() { | |
| 683 // Any tooltips that are active should be hidden when toolbar loses focus. | |
| 684 if (GetWidget() && GetWidget()->GetTooltipManager()) | |
| 685 GetWidget()->GetTooltipManager()->HideKeyboardTooltip(); | |
| 686 | |
| 687 // Removes the Child MSAA view's focus and the view from the ViewStorage, | |
| 688 // when toolbar loses focus. | |
| 689 if (acc_focused_view_) { | |
| 690 acc_focused_view_->SetHotTracked(false); | |
| 691 acc_focused_view_ = NULL; | |
| 692 views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance(); | |
| 693 view_storage->RemoveView(last_focused_view_storage_id_); | |
| 694 } | |
| 695 } | |
| 696 | |
| 697 void ToolbarView::RequestFocus() { | |
| 698 // When the toolbar needs to request focus, the default implementation of | |
| 699 // View::RequestFocus requires the View to be focusable. Since ToolbarView is | |
| 700 // not technically focused, we need to temporarily set and remove focus so | |
| 701 // that it can focus back to its MSAA focused state. |acc_focused_view_| is | |
| 702 // not necessarily set since it can be null if this view has already lost | |
| 703 // focus, such as traversing through the context menu. | |
| 704 SetFocusable(true); | |
| 705 View::RequestFocus(); | |
| 706 SetFocusable(false); | |
| 707 } | |
| 708 | |
| 709 bool ToolbarView::OnKeyPressed(const views::KeyEvent& e) { | |
| 710 // Paranoia check, button should be initialized upon toolbar gaining focus. | |
| 711 if (!acc_focused_view_) | |
| 712 return false; | |
| 713 | |
| 714 int focused_view = GetChildIndex(acc_focused_view_); | |
| 715 int next_view = focused_view; | |
| 716 | |
| 717 switch (e.GetKeyCode()) { | |
| 718 case base::VKEY_LEFT: | |
| 719 next_view = GetNextAccessibleViewIndex(focused_view, true); | |
| 720 break; | |
| 721 case base::VKEY_RIGHT: | |
| 722 next_view = GetNextAccessibleViewIndex(focused_view, false); | |
| 723 break; | |
| 724 case base::VKEY_DOWN: | |
| 725 case base::VKEY_RETURN: | |
| 726 // VKEY_SPACE is already handled by the default case. | |
| 727 if (acc_focused_view_->GetID() == VIEW_ID_PAGE_MENU || | |
| 728 acc_focused_view_->GetID() == VIEW_ID_APP_MENU) { | |
| 729 // If a menu button in toolbar is activated and its menu is displayed, | |
| 730 // then active tooltip should be hidden. | |
| 731 if (GetWidget()->GetTooltipManager()) | |
| 732 GetWidget()->GetTooltipManager()->HideKeyboardTooltip(); | |
| 733 // Safe to cast, given to above view id check. | |
| 734 static_cast<views::MenuButton*>(acc_focused_view_)->Activate(); | |
| 735 if (!acc_focused_view_) { | |
| 736 // Activate triggered a focus change, don't try to change focus. | |
| 737 return true; | |
| 738 } | |
| 739 // Re-enable hot-tracking, as Activate() will disable it. | |
| 740 acc_focused_view_->SetHotTracked(true); | |
| 741 break; | |
| 742 } | |
| 743 default: | |
| 744 // If key is not handled explicitly, pass it on to view. | |
| 745 return acc_focused_view_->OnKeyPressed(e); | |
| 746 } | |
| 747 | |
| 748 // No buttons enabled or visible. | |
| 749 if (next_view == -1) | |
| 750 return false; | |
| 751 | |
| 752 // Only send an event if focus moved. | |
| 753 if (next_view != focused_view) { | |
| 754 // Remove hot-tracking from old focused button. | |
| 755 acc_focused_view_->SetHotTracked(false); | |
| 756 | |
| 757 // All is well, update the focused child member variable. | |
| 758 acc_focused_view_ = GetChildViewAt(next_view); | |
| 759 | |
| 760 // Hot-track new focused button. | |
| 761 acc_focused_view_->SetHotTracked(true); | |
| 762 | |
| 763 // Show the tooltip for the view that got the focus. | |
| 764 if (GetWidget()->GetTooltipManager()) { | |
| 765 GetWidget()->GetTooltipManager()-> | |
| 766 ShowKeyboardTooltip(GetChildViewAt(next_view)); | |
| 767 } | |
| 768 #if defined(OS_WIN) | |
| 769 // Retrieve information to generate an MSAA focus event. | |
| 770 gfx::NativeView wnd = GetWidget()->GetNativeView(); | |
| 771 int view_id = acc_focused_view_->GetID(); | |
| 772 // Notify Access Technology that there was a change in keyboard focus. | |
| 773 ::NotifyWinEvent(EVENT_OBJECT_FOCUS, wnd, OBJID_CLIENT, | |
| 774 static_cast<LONG>(view_id)); | |
| 775 #else | |
| 776 NOTIMPLEMENTED(); | |
| 777 #endif | |
| 778 return true; | |
| 779 } | |
| 780 return false; | |
| 781 } | |
| 782 | |
| 783 bool ToolbarView::OnKeyReleased(const views::KeyEvent& e) { | |
| 784 // Paranoia check, button should be initialized upon toolbar gaining focus. | |
| 785 if (!acc_focused_view_) | |
| 786 return false; | |
| 787 | |
| 788 // Have keys be handled by the views themselves. | |
| 789 return acc_focused_view_->OnKeyReleased(e); | |
| 790 } | |
| 791 | |
| 792 bool ToolbarView::SkipDefaultKeyEventProcessing(const views::KeyEvent& e) { | |
| 793 if (acc_focused_view_ && e.GetKeyCode() == base::VKEY_ESCAPE) { | |
| 794 // Retrieve the focused view from the storage so we can request focus back | |
| 795 // to it. If |focus_view| is null, we place focus on the location bar. | |
| 796 // |acc_focused_view_| doesn't need to be resetted here since it will be | |
| 797 // dealt within the WillLoseFocus method. | |
| 798 views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance(); | |
| 799 views::View* focused_view = | |
| 800 view_storage->RetrieveView(last_focused_view_storage_id_); | |
| 801 if (focused_view) { | |
| 802 view_storage->RemoveView(last_focused_view_storage_id_); | |
| 803 focused_view->RequestFocus(); | |
| 804 } else { | |
| 805 location_bar_->RequestFocus(); | |
| 806 } | |
| 807 return true; | |
| 808 } | |
| 809 return false; | |
| 810 } | |
| 811 | |
| 812 bool ToolbarView::GetAccessibleName(std::wstring* name) { | |
| 813 if (!accessible_name_.empty()) { | |
| 814 (*name).assign(accessible_name_); | |
| 815 return true; | |
| 816 } | |
| 817 return false; | |
| 818 } | |
| 819 | |
| 820 bool ToolbarView::GetAccessibleRole(AccessibilityTypes::Role* role) { | |
| 821 DCHECK(role); | |
| 822 | |
| 823 *role = AccessibilityTypes::ROLE_TOOLBAR; | |
| 824 return true; | |
| 825 } | |
| 826 | |
| 827 void ToolbarView::SetAccessibleName(const std::wstring& name) { | |
| 828 accessible_name_.assign(name); | |
| 829 } | |
| 830 | |
| 831 //////////////////////////////////////////////////////////////////////////////// | 590 //////////////////////////////////////////////////////////////////////////////// |
| 832 // ToolbarView, views::DragController implementation: | 591 // ToolbarView, views::DragController implementation: |
| 833 | 592 |
| 834 void ToolbarView::WriteDragData(views::View* sender, | 593 void ToolbarView::WriteDragData(views::View* sender, |
| 835 int press_x, | 594 int press_x, |
| 836 int press_y, | 595 int press_y, |
| 837 OSExchangeData* data) { | 596 OSExchangeData* data) { |
| 838 DCHECK( | 597 DCHECK( |
| 839 GetDragOperations(sender, press_x, press_y) != DragDropTypes::DRAG_NONE); | 598 GetDragOperations(sender, press_x, press_y) != DragDropTypes::DRAG_NONE); |
| 840 | 599 |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1203 IDS_ABOUT, | 962 IDS_ABOUT, |
| 1204 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))); | 963 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME))); |
| 1205 app_menu_contents_->AddItemWithStringId(IDC_HELP_PAGE, IDS_HELP_PAGE); | 964 app_menu_contents_->AddItemWithStringId(IDC_HELP_PAGE, IDS_HELP_PAGE); |
| 1206 if (browser_defaults::kShowExitMenuItem) { | 965 if (browser_defaults::kShowExitMenuItem) { |
| 1207 app_menu_contents_->AddSeparator(); | 966 app_menu_contents_->AddSeparator(); |
| 1208 app_menu_contents_->AddItemWithStringId(IDC_EXIT, IDS_EXIT); | 967 app_menu_contents_->AddItemWithStringId(IDC_EXIT, IDS_EXIT); |
| 1209 } | 968 } |
| 1210 | 969 |
| 1211 app_menu_menu_.reset(new views::Menu2(app_menu_contents_.get())); | 970 app_menu_menu_.reset(new views::Menu2(app_menu_contents_.get())); |
| 1212 } | 971 } |
| OLD | NEW |