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/ui/views/tab_contents/native_tab_contents_container_gtk.h" 6 7 #include "chrome/browser/ui/view_ids.h" 8 #include "chrome/browser/ui/views/tab_contents/tab_contents_container.h" 9 #include "content/browser/renderer_host/render_widget_host_view.h" 10 #include "content/browser/tab_contents/interstitial_page.h" 11 #include "content/browser/tab_contents/tab_contents.h" 12 #include "ui/base/accessibility/accessible_view_state.h" 13 #include "views/focus/focus_manager.h" 14 15 //////////////////////////////////////////////////////////////////////////////// 16 // NativeTabContentsContainerGtk, public: 17 18 NativeTabContentsContainerGtk::NativeTabContentsContainerGtk( 19 TabContentsContainer* container) 20 : container_(container), 21 focus_callback_id_(0) { 22 SetID(VIEW_ID_TAB_CONTAINER_FOCUS_VIEW); 23 } 24 25 NativeTabContentsContainerGtk::~NativeTabContentsContainerGtk() { 26 } 27 28 //////////////////////////////////////////////////////////////////////////////// 29 // NativeTabContentsContainerGtk, NativeTabContentsContainer overrides: 30 31 void NativeTabContentsContainerGtk::AttachContents(TabContents* contents) { 32 Attach(contents->GetNativeView()); 33 } 34 35 void NativeTabContentsContainerGtk::DetachContents(TabContents* contents) { 36 gtk_widget_hide(contents->GetNativeView()); 37 38 // Now detach the TabContents. 39 Detach(); 40 } 41 42 void NativeTabContentsContainerGtk::SetFastResize(bool fast_resize) { 43 set_fast_resize(fast_resize); 44 } 45 46 void NativeTabContentsContainerGtk::RenderViewHostChanged( 47 RenderViewHost* old_host, 48 RenderViewHost* new_host) { 49 // If we are focused, we need to pass the focus to the new RenderViewHost. 50 views::FocusManager* focus_manager = GetFocusManager(); 51 if (focus_manager->GetFocusedView() == this) 52 OnFocus(); 53 } 54 55 views::View* NativeTabContentsContainerGtk::GetView() { 56 return this; 57 } 58 59 void NativeTabContentsContainerGtk::TabContentsFocused( 60 TabContents* tab_contents) { 61 #if !defined(TOUCH_UI) 62 // Called when the tab contents native view gets focused (typically through a 63 // user click). We make ourself the focused view, so the focus is restored 64 // properly when the browser window is deactivated/reactivated. 65 views::FocusManager* focus_manager = GetFocusManager(); 66 if (!focus_manager) { 67 NOTREACHED(); 68 return; 69 } 70 focus_manager->SetFocusedView(this); 71 #else 72 // no native views in TOUCH_UI, so don't steal the focus 73 #endif 74 } 75 76 //////////////////////////////////////////////////////////////////////////////// 77 // NativeTabContentsContainerGtk, views::View overrides: 78 79 bool NativeTabContentsContainerGtk::SkipDefaultKeyEventProcessing( 80 const views::KeyEvent& e) { 81 // Don't look-up accelerators or tab-traverse if we are showing a non-crashed 82 // TabContents. 83 // We'll first give the page a chance to process the key events. If it does 84 // not process them, they'll be returned to us and we'll treat them as 85 // accelerators then. 86 return container_->tab_contents() && 87 !container_->tab_contents()->is_crashed(); 88 } 89 90 views::FocusTraversable* NativeTabContentsContainerGtk::GetFocusTraversable() { 91 return NULL; 92 } 93 94 bool NativeTabContentsContainerGtk::IsFocusable() const { 95 // We need to be focusable when our contents is not a view hierarchy, as 96 // clicking on the contents needs to focus us. 97 return container_->tab_contents() != NULL; 98 } 99 100 void NativeTabContentsContainerGtk::OnFocus() { 101 if (container_->tab_contents()) 102 container_->tab_contents()->Focus(); 103 } 104 105 void NativeTabContentsContainerGtk::RequestFocus() { 106 // This is a hack to circumvent the fact that a view does not explicitly get 107 // a call to set the focus if it already has the focus. This causes a problem 108 // with tabs such as the TabContents that instruct the RenderView that it got 109 // focus when they actually get the focus. When switching from one TabContents 110 // tab that has focus to another TabContents tab that had focus, since the 111 // TabContentsContainerView already has focus, OnFocus() would not be called 112 // and the RenderView would not get notified it got focused. 113 // By clearing the focused view before-hand, we ensure OnFocus() will be 114 // called. 115 views::FocusManager* focus_manager = GetFocusManager(); 116 if (focus_manager) 117 focus_manager->SetFocusedView(NULL); 118 View::RequestFocus(); 119 } 120 121 void NativeTabContentsContainerGtk::AboutToRequestFocusFromTabTraversal( 122 bool reverse) { 123 if (!container_->tab_contents()) 124 return; 125 // Give an opportunity to the tab to reset its focus. 126 if (container_->tab_contents()->interstitial_page()) { 127 container_->tab_contents()->interstitial_page()->FocusThroughTabTraversal( 128 reverse); 129 return; 130 } 131 container_->tab_contents()->FocusThroughTabTraversal(reverse); 132 } 133 134 void NativeTabContentsContainerGtk::GetAccessibleState( 135 ui::AccessibleViewState* state) { 136 state->role = ui::AccessibilityTypes::ROLE_GROUPING; 137 } 138 139 //////////////////////////////////////////////////////////////////////////////// 140 // NativeTabContentsContainer, public: 141 142 // static 143 NativeTabContentsContainer* NativeTabContentsContainer::CreateNativeContainer( 144 TabContentsContainer* container) { 145 return new NativeTabContentsContainerGtk(container); 146 } 147