chrome_web_contents_view_delegate_views.cc revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
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 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.h" 6 7#include "chrome/browser/browser_shutdown.h" 8#include "chrome/browser/ui/sad_tab_helper.h" 9#include "chrome/browser/ui/tab_contents/chrome_web_contents_view_delegate.h" 10#include "chrome/browser/ui/views/sad_tab_view.h" 11#include "chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h" 12#include "chrome/browser/ui/web_contents_modal_dialog_manager.h" 13#include "chrome/common/chrome_switches.h" 14#include "content/public/browser/render_process_host.h" 15#include "content/public/browser/render_view_host.h" 16#include "content/public/browser/render_widget_host_view.h" 17#include "content/public/browser/web_contents.h" 18#include "content/public/browser/web_contents_delegate.h" 19#include "content/public/browser/web_contents_view.h" 20#include "ui/views/focus/focus_manager.h" 21#include "ui/views/focus/view_storage.h" 22#include "ui/views/widget/widget.h" 23 24#if defined(USE_AURA) 25#include "chrome/browser/ui/aura/tab_contents/web_drag_bookmark_handler_aura.h" 26#include "ui/aura/client/screen_position_client.h" 27#include "ui/aura/root_window.h" 28#include "ui/aura/window.h" 29#else 30#include "chrome/browser/ui/views/tab_contents/web_drag_bookmark_handler_win.h" 31#endif 32 33ChromeWebContentsViewDelegateViews::ChromeWebContentsViewDelegateViews( 34 content::WebContents* web_contents) 35 : web_contents_(web_contents) { 36 last_focused_view_storage_id_ = 37 views::ViewStorage::GetInstance()->CreateStorageID(); 38} 39 40ChromeWebContentsViewDelegateViews::~ChromeWebContentsViewDelegateViews() { 41 // Makes sure to remove any stored view we may still have in the ViewStorage. 42 // 43 // It is possible the view went away before us, so we only do this if the 44 // view is registered. 45 views::ViewStorage* view_storage = views::ViewStorage::GetInstance(); 46 if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL) 47 view_storage->RemoveView(last_focused_view_storage_id_); 48} 49 50content::WebDragDestDelegate* 51 ChromeWebContentsViewDelegateViews::GetDragDestDelegate() { 52 // We install a chrome specific handler to intercept bookmark drags for the 53 // bookmark manager/extension API. 54#if defined(USE_AURA) 55 bookmark_handler_.reset(new WebDragBookmarkHandlerAura); 56#else 57 bookmark_handler_.reset(new WebDragBookmarkHandlerWin); 58#endif 59 return bookmark_handler_.get(); 60} 61 62bool ChromeWebContentsViewDelegateViews::Focus() { 63 SadTabHelper* sad_tab_helper = SadTabHelper::FromWebContents(web_contents_); 64 if (sad_tab_helper) { 65 SadTabView* sad_tab = static_cast<SadTabView*>(sad_tab_helper->sad_tab()); 66 if (sad_tab) { 67 sad_tab->RequestFocus(); 68 return true; 69 } 70 } 71 72 WebContentsModalDialogManager* web_contents_modal_dialog_manager = 73 WebContentsModalDialogManager::FromWebContents(web_contents_); 74 if (web_contents_modal_dialog_manager) { 75 // TODO(erg): WebContents used to own web contents modal dialogs, which is 76 // why this is here. Eventually this should be ported to a containing view 77 // specializing in web contents modal dialog management. 78 if (web_contents_modal_dialog_manager->IsShowingDialog()) { 79 web_contents_modal_dialog_manager->FocusTopmostDialog(); 80 return true; 81 } 82 } 83 84 return false; 85} 86 87void ChromeWebContentsViewDelegateViews::TakeFocus(bool reverse) { 88 GetFocusManager()->AdvanceFocus(reverse); 89} 90 91void ChromeWebContentsViewDelegateViews::StoreFocus() { 92 views::ViewStorage* view_storage = views::ViewStorage::GetInstance(); 93 94 if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL) 95 view_storage->RemoveView(last_focused_view_storage_id_); 96 97 if (!GetFocusManager()) 98 return; 99 views::View* focused_view = GetFocusManager()->GetFocusedView(); 100 if (focused_view) 101 view_storage->StoreView(last_focused_view_storage_id_, focused_view); 102} 103 104void ChromeWebContentsViewDelegateViews::RestoreFocus() { 105 views::ViewStorage* view_storage = views::ViewStorage::GetInstance(); 106 views::View* last_focused_view = 107 view_storage->RetrieveView(last_focused_view_storage_id_); 108 109 if (!last_focused_view) { 110 SetInitialFocus(); 111 } else { 112 if (last_focused_view->IsFocusable() && 113 GetFocusManager()->ContainsView(last_focused_view)) { 114 last_focused_view->RequestFocus(); 115 } else { 116 // The focused view may not belong to the same window hierarchy (e.g. 117 // if the location bar was focused and the tab is dragged out), or it may 118 // no longer be focusable (e.g. if the location bar was focused and then 119 // we switched to fullscreen mode). In that case we default to the 120 // default focus. 121 SetInitialFocus(); 122 } 123 view_storage->RemoveView(last_focused_view_storage_id_); 124 } 125} 126 127void ChromeWebContentsViewDelegateViews::ShowContextMenu( 128 const content::ContextMenuParams& params, 129 content::ContextMenuSourceType type) { 130 // Menus need a Widget to work. If we're not the active tab we won't 131 // necessarily be in a widget. 132 views::Widget* top_level_widget = GetTopLevelWidget(); 133 if (!top_level_widget) 134 return; 135 136 context_menu_.reset( 137 RenderViewContextMenuViews::Create(web_contents_, params)); 138 context_menu_->Init(); 139 140 // Don't show empty menus. 141 if (context_menu_->menu_model().GetItemCount() == 0) 142 return; 143 144 gfx::Point screen_point(params.x, params.y); 145 146#if defined(USE_AURA) 147 // Convert from content coordinates to window coordinates. 148 aura::Window* web_contents_window = 149 web_contents_->GetView()->GetNativeView(); 150 aura::RootWindow* root_window = web_contents_window->GetRootWindow(); 151 aura::client::ScreenPositionClient* screen_position_client = 152 aura::client::GetScreenPositionClient(root_window); 153 if (screen_position_client) { 154 screen_position_client->ConvertPointToScreen(web_contents_window, 155 &screen_point); 156 } 157#else 158 POINT temp = screen_point.ToPOINT(); 159 ClientToScreen(web_contents_->GetView()->GetNativeView(), &temp); 160 screen_point = temp; 161#endif 162 163 // Enable recursive tasks on the message loop so we can get updates while 164 // the context menu is being displayed. 165 base::MessageLoop::ScopedNestableTaskAllower allow( 166 base::MessageLoop::current()); 167 context_menu_->RunMenuAt(top_level_widget, screen_point, type); 168} 169 170void ChromeWebContentsViewDelegateViews::SizeChanged(const gfx::Size& size) { 171 SadTabHelper* sad_tab_helper = SadTabHelper::FromWebContents(web_contents_); 172 if (!sad_tab_helper) 173 return; 174 SadTabView* sad_tab = static_cast<SadTabView*>(sad_tab_helper->sad_tab()); 175 if (sad_tab) 176 sad_tab->GetWidget()->SetBounds(gfx::Rect(size)); 177} 178 179views::Widget* ChromeWebContentsViewDelegateViews::GetTopLevelWidget() { 180 gfx::NativeWindow top_level_window = 181 web_contents_->GetView()->GetTopLevelNativeWindow(); 182 if (!top_level_window) 183 return NULL; 184 return views::Widget::GetWidgetForNativeWindow(top_level_window); 185} 186 187views::FocusManager* 188 ChromeWebContentsViewDelegateViews::GetFocusManager() { 189 views::Widget* toplevel_widget = GetTopLevelWidget(); 190 return toplevel_widget ? toplevel_widget->GetFocusManager() : NULL; 191} 192 193void ChromeWebContentsViewDelegateViews::SetInitialFocus() { 194 if (web_contents_->FocusLocationBarByDefault()) { 195 if (web_contents_->GetDelegate()) 196 web_contents_->GetDelegate()->SetFocusToLocationBar(false); 197 } else { 198 web_contents_->GetView()->Focus(); 199 } 200} 201 202namespace chrome { 203 204content::WebContentsViewDelegate* CreateWebContentsViewDelegate( 205 content::WebContents* web_contents) { 206 return new ChromeWebContentsViewDelegateViews(web_contents); 207} 208 209} // namespace chrome 210