summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-12 00:21:28 +0000
committerjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-12 00:21:28 +0000
commit401513c474b3520fe784c03e068a15fc6655d6e1 (patch)
tree9d5368feb8f3a668ec4523e90bc9694bcfc3a9d3 /chrome
parenta8e9b16e3e3f944d0eaf7f91e5cc96a7b2c914d3 (diff)
downloadchromium_src-401513c474b3520fe784c03e068a15fc6655d6e1.zip
chromium_src-401513c474b3520fe784c03e068a15fc6655d6e1.tar.gz
chromium_src-401513c474b3520fe784c03e068a15fc6655d6e1.tar.bz2
Moving the storing/restoring of the focus from TabContents to WebContentsView. This makes TabContents less dependent on views.
This requires few contortions with DOMUIs (NTP, history and downloads tab) as they still need to set the initial focus specifically. BUG=None TEST=Run the interactive tests. Review URL: http://codereview.chromium.org/39269 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@11501 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/browser.cc6
-rw-r--r--chrome/browser/browser_focus_uitest.cc24
-rw-r--r--chrome/browser/browser_init.cc7
-rw-r--r--chrome/browser/browser_process_impl.cc7
-rw-r--r--chrome/browser/dom_ui/dom_ui_contents.cc3
-rw-r--r--chrome/browser/dom_ui/dom_ui_contents.h6
-rw-r--r--chrome/browser/sessions/session_restore.cc7
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc88
-rw-r--r--chrome/browser/tab_contents/tab_contents.h20
-rw-r--r--chrome/browser/tab_contents/web_contents_view.h11
-rw-r--r--chrome/browser/tab_contents/web_contents_view_gtk.cc12
-rw-r--r--chrome/browser/tab_contents/web_contents_view_gtk.h3
-rw-r--r--chrome/browser/tab_contents/web_contents_view_mac.h3
-rw-r--r--chrome/browser/tab_contents/web_contents_view_mac.mm12
-rw-r--r--chrome/browser/tab_contents/web_contents_view_win.cc78
-rw-r--r--chrome/browser/tab_contents/web_contents_view_win.h6
-rw-r--r--chrome/browser/views/frame/browser_view.cc14
-rw-r--r--chrome/views/view_storage.cc19
-rw-r--r--chrome/views/view_storage.h9
19 files changed, 186 insertions, 149 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index dea7ae1..cbbe84d 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -31,6 +31,7 @@
#include "chrome/browser/tab_contents/site_instance.h"
#include "chrome/browser/tab_contents/tab_contents_type.h"
#include "chrome/browser/tab_contents/web_contents.h"
+#include "chrome/browser/tab_contents/web_contents_view.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/l10n_util.h"
@@ -318,7 +319,7 @@ void Browser::OpenApplicationWindow(Profile* profile, const GURL& url) {
browser->window()->Show();
// TODO(jcampan): http://crbug.com/8123 we should not need to set the initial
// focus explicitly.
- browser->GetSelectedTabContents()->SetInitialFocus();
+ browser->GetSelectedTabContents()->AsWebContents()->view()->SetInitialFocus();
}
///////////////////////////////////////////////////////////////////////////////
@@ -657,8 +658,7 @@ void Browser::NewTab() {
// The call to AddBlankTab above did not set the focus to the tab as its
// window was not active, so we have to do it explicitly.
// See http://crbug.com/6380.
- TabContents* tab = b->GetSelectedTabContents();
- tab->RestoreFocus();
+ b->GetSelectedTabContents()->AsWebContents()->view()->RestoreFocus();
}
}
diff --git a/chrome/browser/browser_focus_uitest.cc b/chrome/browser/browser_focus_uitest.cc
index d920a012..81edcc2 100644
--- a/chrome/browser/browser_focus_uitest.cc
+++ b/chrome/browser/browser_focus_uitest.cc
@@ -442,3 +442,27 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FindFocusTest) {
ASSERT_TRUE(focused_view != NULL);
EXPECT_EQ(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD, focused_view->GetID());
}
+
+// Makes sure the focus is in the right location when opening the different
+// types of tabs.
+IN_PROC_BROWSER_TEST_F(BrowserFocusTest, TabInitialFocus) {
+ HWND hwnd = reinterpret_cast<HWND>(browser()->window()->GetNativeHandle());
+ BrowserView* browser_view = BrowserView::GetBrowserViewForHWND(hwnd);
+ ASSERT_TRUE(browser_view);
+ views::FocusManager* focus_manager =
+ views::FocusManager::GetFocusManager(hwnd);
+ ASSERT_TRUE(focus_manager);
+
+ // Open the history tab, focus should be on the tab contents.
+ browser()->ShowHistoryTab();
+ EXPECT_EQ(browser_view->GetContentsView(), focus_manager->GetFocusedView());
+
+ // Open the new tab, focus should be on the location bar.
+ browser()->NewTab();
+ EXPECT_EQ(browser_view->GetLocationBarView(),
+ focus_manager->GetFocusedView());
+
+ // Open the download tab, focus should be on the tab contents.
+ browser()->ShowDownloadsTab();
+ EXPECT_EQ(browser_view->GetContentsView(), focus_manager->GetFocusedView());
+}
diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc
index 328507cb..0e8ac37 100644
--- a/chrome/browser/browser_init.cc
+++ b/chrome/browser/browser_init.cc
@@ -25,6 +25,8 @@
#include "chrome/browser/sessions/session_restore.h"
#include "chrome/browser/tab_contents/infobar_delegate.h"
#include "chrome/browser/tab_contents/navigation_controller.h"
+#include "chrome/browser/tab_contents/web_contents.h"
+#include "chrome/browser/tab_contents/web_contents_view.h"
#include "chrome/browser/net/url_fixer_upper.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
@@ -341,7 +343,10 @@ Browser* BrowserInit::LaunchWithProfile::OpenURLsInBrowser(
browser->window()->Show();
// TODO(jcampan): http://crbug.com/8123 we should not need to set the initial
// focus explicitly.
- browser->GetSelectedTabContents()->SetInitialFocus();
+ if (browser->GetSelectedTabContents()->AsWebContents()) {
+ browser->GetSelectedTabContents()->AsWebContents()->view()->
+ SetInitialFocus();
+ }
return browser;
}
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 2563d2d4..4730c93 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -196,13 +196,6 @@ BrowserProcessImpl::~BrowserProcessImpl() {
print_job_manager_->OnQuit();
print_job_manager_.reset();
- // TODO(port): remove this completely from BrowserProcessImpl, it has no
- // business being here.
-#if defined(OS_WIN)
- // The ViewStorage needs to go before the NotificationService.
- views::ViewStorage::DeleteSharedInstance();
-#endif
-
// Now OK to destroy NotificationService.
main_notification_service_.reset();
diff --git a/chrome/browser/dom_ui/dom_ui_contents.cc b/chrome/browser/dom_ui/dom_ui_contents.cc
index 9d80db3..f27d441 100644
--- a/chrome/browser/dom_ui/dom_ui_contents.cc
+++ b/chrome/browser/dom_ui/dom_ui_contents.cc
@@ -13,6 +13,7 @@
#include "chrome/browser/extensions/extensions_ui.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
+#include "chrome/browser/tab_contents/web_contents_view.h"
#include "chrome/common/l10n_util.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/common/url_constants.h"
@@ -194,7 +195,7 @@ void DOMUIContents::SetInitialFocus() {
if (InitCurrentUI(false))
current_ui_->SetInitialFocus();
else
- TabContents::SetInitialFocus();
+ current_ui_->get_contents()->view()->SetInitialFocus();
}
const string16& DOMUIContents::GetTitle() const {
diff --git a/chrome/browser/dom_ui/dom_ui_contents.h b/chrome/browser/dom_ui/dom_ui_contents.h
index 3c8e985..f1796f2 100644
--- a/chrome/browser/dom_ui/dom_ui_contents.h
+++ b/chrome/browser/dom_ui/dom_ui_contents.h
@@ -105,8 +105,6 @@ class DOMUIContents : public WebContents {
virtual bool ShouldDisplayFavIcon();
// The bookmark bar is always visible on the new tab.
virtual bool IsBookmarkBarAlwaysVisible();
- // When NTP gets the initial focus, focus the URL bar.
- virtual void SetInitialFocus();
// Whether we want to display the page's URL.
virtual bool ShouldDisplayURL();
// Get the title for this page.
@@ -114,6 +112,7 @@ class DOMUIContents : public WebContents {
// We may wish to control what happens when a URL is opened.
virtual void RequestOpenURL(const GURL& url, const GURL& referrer,
WindowOpenDisposition disposition);
+ virtual DOMUIContents* AsDOMUIContents() { return this; }
virtual void RenderViewCreated(RenderViewHost* render_view_host);
@@ -124,6 +123,9 @@ class DOMUIContents : public WebContents {
const ViewHostMsg_FrameNavigate_Params& params) { }
virtual bool NavigateToPendingEntry(bool reload);
+ // Gives the DOMUI an opportunity to chose where the focus should go.
+ void SetInitialFocus();
+
// Return the scheme used. We currently use chrome-ui:
static const std::string GetScheme();
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc
index 51c5403..9563204 100644
--- a/chrome/browser/sessions/session_restore.cc
+++ b/chrome/browser/sessions/session_restore.cc
@@ -14,6 +14,8 @@
#include "chrome/browser/sessions/session_service.h"
#include "chrome/browser/sessions/session_types.h"
#include "chrome/browser/tab_contents/navigation_controller.h"
+#include "chrome/browser/tab_contents/web_contents.h"
+#include "chrome/browser/tab_contents/web_contents_view.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
@@ -363,7 +365,10 @@ class SessionRestoreImpl : public NotificationObserver {
browser->window()->Show();
// TODO(jcampan): http://crbug.com/8123 we should not need to set the
// initial focus explicitly.
- browser->GetSelectedTabContents()->SetInitialFocus();
+ if (browser->GetSelectedTabContents()->AsWebContents()) {
+ browser->GetSelectedTabContents()->AsWebContents()->view()->
+ SetInitialFocus();
+ }
}
void AppendURLsToBrowser(Browser* browser, const std::vector<GURL>& urls) {
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index 4da0609..0e8f6e4 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -22,10 +22,6 @@
#include "chrome/browser/views/download_started_animation.h"
#include "chrome/browser/views/blocked_popup_container.h"
#include "chrome/views/native_scroll_bar.h"
-#include "chrome/views/root_view.h"
-#include "chrome/views/view.h"
-#include "chrome/views/view_storage.h"
-#include "chrome/views/widget.h"
#endif
#if defined(OS_WIN)
@@ -54,22 +50,9 @@ TabContents::TabContents(TabContentsType type)
capturing_contents_(false),
blocked_popups_(NULL),
is_being_destroyed_(false) {
-#if defined(OS_WIN)
- last_focused_view_storage_id_ =
- views::ViewStorage::GetSharedInstance()->CreateStorageID();
-#endif
}
TabContents::~TabContents() {
-#if defined(OS_WIN)
- // Makes sure to remove any stored view we may still have in the ViewStorage.
- //
- // It is possible the view went away before us, so we only do this if the
- // view is registered.
- views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
- if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
- view_storage->RemoveView(last_focused_view_storage_id_);
-#endif
}
// static
@@ -366,77 +349,6 @@ void TabContents::Focus() {
#endif
}
-void TabContents::StoreFocus() {
-#if defined(OS_WIN)
- views::ViewStorage* view_storage =
- views::ViewStorage::GetSharedInstance();
-
- if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
- view_storage->RemoveView(last_focused_view_storage_id_);
-
- views::FocusManager* focus_manager =
- views::FocusManager::GetFocusManager(GetNativeView());
- if (focus_manager) {
- // |focus_manager| can be NULL if the tab has been detached but still
- // exists.
- views::View* focused_view = focus_manager->GetFocusedView();
- if (focused_view)
- view_storage->StoreView(last_focused_view_storage_id_, focused_view);
-
- // If the focus was on the page, explicitly clear the focus so that we
- // don't end up with the focused HWND not part of the window hierarchy.
- // TODO(brettw) this should move to the view somehow.
- HWND container_hwnd = GetNativeView();
- if (container_hwnd) {
- views::View* focused_view = focus_manager->GetFocusedView();
- if (focused_view) {
- HWND hwnd = focused_view->GetRootView()->GetWidget()->GetHWND();
- if (container_hwnd == hwnd || ::IsChild(container_hwnd, hwnd))
- focus_manager->ClearFocus();
- }
- }
- }
-#endif
-}
-
-void TabContents::RestoreFocus() {
-#if defined(OS_WIN)
- views::ViewStorage* view_storage =
- views::ViewStorage::GetSharedInstance();
- views::View* last_focused_view =
- view_storage->RetrieveView(last_focused_view_storage_id_);
-
- if (!last_focused_view) {
- SetInitialFocus();
- } else {
- views::FocusManager* focus_manager =
- views::FocusManager::GetFocusManager(GetNativeView());
-
- // If you hit this DCHECK, please report it to Jay (jcampan).
- DCHECK(focus_manager != NULL) << "No focus manager when restoring focus.";
-
- if (last_focused_view->IsFocusable() && focus_manager &&
- focus_manager->ContainsView(last_focused_view)) {
- last_focused_view->RequestFocus();
- } else {
- // The focused view may not belong to the same window hierarchy (e.g.
- // if the location bar was focused and the tab is dragged out), or it may
- // no longer be focusable (e.g. if the location bar was focused and then
- // we switched to fullscreen mode). In that case we default to the
- // default focus.
- SetInitialFocus();
- }
- view_storage->RemoveView(last_focused_view_storage_id_);
- }
-#endif
-}
-
-void TabContents::SetInitialFocus() {
-#if defined(OS_WIN)
- ::SetFocus(GetNativeView());
-#endif
-}
-
void TabContents::AddInfoBar(InfoBarDelegate* delegate) {
// Look through the existing InfoBarDelegates we have for a match. If we've
// already got one that matches, then we don't add the new one.
diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h
index 7d0e562..d28e068 100644
--- a/chrome/browser/tab_contents/tab_contents.h
+++ b/chrome/browser/tab_contents/tab_contents.h
@@ -37,6 +37,7 @@ class WindowDelegate;
}
class BlockedPopupContainer;
+class DOMUIContents;
class DOMUIHost;
class DownloadItem;
class DownloadShelf;
@@ -141,6 +142,9 @@ class TabContents : public PageNavigator,
// Returns this object as a DOMUIHost if it is one, and NULL otherwise.
virtual DOMUIHost* AsDOMUIHost() { return NULL; }
+ // Returns this object as a DOMUIContents if it is one, and NULL otherwise.
+ virtual DOMUIContents* AsDOMUIContents() { return NULL; }
+
TabContentsDelegate* delegate() const { return delegate_; }
void set_delegate(TabContentsDelegate* d) { delegate_ = d; }
@@ -373,13 +377,6 @@ class TabContents : public PageNavigator,
// Make the tab the focused window.
virtual void Focus();
- // Stores the currently focused view.
- virtual void StoreFocus();
-
- // Restores focus to the last focus view. If StoreFocus has not yet been
- // invoked, SetInitialFocus is invoked.
- virtual void RestoreFocus();
-
// Invoked the first time this tab is getting the focus through TAB traversal.
// By default this does nothing, but is overridden to set the focus for the
// first element in the page.
@@ -450,12 +447,6 @@ class TabContents : public PageNavigator,
// Called when a ConstrainedWindow we own is moved or resized.
void DidMoveOrResize(ConstrainedWindow* window);
- // Sets focus to the tab contents window, but doesn't actually set focus to
- // a particular element in it (see also SetInitialFocus(bool) which does
- // that in different circumstances).
- // FIXME(brettw) having two SetInitialFocus that do different things is silly.
- virtual void SetInitialFocus();
-
protected:
// NotificationObserver implementation:
virtual void Observe(NotificationType type,
@@ -548,9 +539,6 @@ class TabContents : public PageNavigator,
// each SiteInstance.
int32 max_page_id_;
- // The id used in the ViewStorage to store the last focused view.
- int last_focused_view_storage_id_;
-
// See capturing_contents() above.
bool capturing_contents_;
diff --git a/chrome/browser/tab_contents/web_contents_view.h b/chrome/browser/tab_contents/web_contents_view.h
index f9d7075..52fceba 100644
--- a/chrome/browser/tab_contents/web_contents_view.h
+++ b/chrome/browser/tab_contents/web_contents_view.h
@@ -115,6 +115,17 @@ class WebContentsView : public RenderViewHostDelegate::View {
// page.
virtual void ForwardMessageToDevToolsClient(const IPC::Message& message) = 0;
+ // Sets focus to the appropriate element when the tab contents is shown the
+ // first time.
+ virtual void SetInitialFocus() = 0;
+
+ // Stores the currently focused view.
+ virtual void StoreFocus() = 0;
+
+ // Restores focus to the last focus view. If StoreFocus has not yet been
+ // invoked, SetInitialFocus is invoked.
+ virtual void RestoreFocus() = 0;
+
protected:
WebContentsView() {} // Abstract interface.
diff --git a/chrome/browser/tab_contents/web_contents_view_gtk.cc b/chrome/browser/tab_contents/web_contents_view_gtk.cc
index a8a8522..6c90ae1 100644
--- a/chrome/browser/tab_contents/web_contents_view_gtk.cc
+++ b/chrome/browser/tab_contents/web_contents_view_gtk.cc
@@ -141,6 +141,18 @@ bool WebContentsViewGtk::GetFindBarWindowInfo(gfx::Point* position,
return false;
}
+void WebContentsViewGtk::SetInitialFocus() {
+ // TODO(port)
+}
+
+void WebContentsViewGtk::StoreFocus() {
+ // TODO(port)
+}
+
+void WebContentsViewGtk::RestoreFocus() {
+ // TODO(port)
+}
+
void WebContentsViewGtk::UpdateDragCursor(bool is_drop_target) {
NOTIMPLEMENTED();
}
diff --git a/chrome/browser/tab_contents/web_contents_view_gtk.h b/chrome/browser/tab_contents/web_contents_view_gtk.h
index 2edd353..ec71c49 100644
--- a/chrome/browser/tab_contents/web_contents_view_gtk.h
+++ b/chrome/browser/tab_contents/web_contents_view_gtk.h
@@ -41,6 +41,9 @@ class WebContentsViewGtk : public WebContentsView {
virtual void ReparentFindWindow(Browser* new_browser) const;
virtual bool GetFindBarWindowInfo(gfx::Point* position,
bool* fully_visible) const;
+ virtual void SetInitialFocus();
+ virtual void StoreFocus();
+ virtual void RestoreFocus();
// Backend implementation of RenderViewHostDelegate::View.
virtual WebContents* CreateNewWindowInternal(
diff --git a/chrome/browser/tab_contents/web_contents_view_mac.h b/chrome/browser/tab_contents/web_contents_view_mac.h
index 9f562c0..59eb422 100644
--- a/chrome/browser/tab_contents/web_contents_view_mac.h
+++ b/chrome/browser/tab_contents/web_contents_view_mac.h
@@ -56,6 +56,9 @@ class WebContentsViewMac : public WebContentsView,
virtual void HideFindBar(bool end_session);
virtual bool GetFindBarWindowInfo(gfx::Point* position,
bool* fully_visible) const;
+ virtual void SetInitialFocus();
+ virtual void StoreFocus();
+ virtual void RestoreFocus();
// Backend implementation of RenderViewHostDelegate::View.
virtual WebContents* CreateNewWindowInternal(
diff --git a/chrome/browser/tab_contents/web_contents_view_mac.mm b/chrome/browser/tab_contents/web_contents_view_mac.mm
index deb452c..b607697 100644
--- a/chrome/browser/tab_contents/web_contents_view_mac.mm
+++ b/chrome/browser/tab_contents/web_contents_view_mac.mm
@@ -152,6 +152,18 @@ bool WebContentsViewMac::GetFindBarWindowInfo(gfx::Point* position,
return true;
}
+void WebContentsViewMac::SetInitialFocus() {
+ // TODO(port)
+}
+
+void WebContentsViewMac::StoreFocus() {
+ // TODO(port)
+}
+
+void WebContentsViewMac::RestoreFocus() {
+ // TODO(port)
+}
+
void WebContentsViewMac::UpdateDragCursor(bool is_drop_target) {
NOTIMPLEMENTED();
}
diff --git a/chrome/browser/tab_contents/web_contents_view_win.cc b/chrome/browser/tab_contents/web_contents_view_win.cc
index 48b7466..51a9ffb 100644
--- a/chrome/browser/tab_contents/web_contents_view_win.cc
+++ b/chrome/browser/tab_contents/web_contents_view_win.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/browser.h" // TODO(beng): this dependency is awful.
#include "chrome/browser/browser_process.h"
#include "chrome/browser/debugger/dev_tools_window.h"
+#include "chrome/browser/dom_ui/dom_ui_host.h"
#include "chrome/browser/download/download_request_manager.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_view_host.h"
@@ -24,6 +25,8 @@
#include "chrome/common/gfx/chrome_canvas.h"
#include "chrome/common/os_exchange_data.h"
#include "chrome/common/url_constants.h"
+#include "chrome/views/root_view.h"
+#include "chrome/views/view_storage.h"
#include "net/base/net_util.h"
#include "webkit/glue/plugins/webplugin_delegate_impl.h"
#include "webkit/glue/webdropdata.h"
@@ -51,9 +54,18 @@ WebContentsView* WebContentsView::Create(WebContents* web_contents) {
WebContentsViewWin::WebContentsViewWin(WebContents* web_contents)
: web_contents_(web_contents),
ignore_next_char_event_(false) {
+ last_focused_view_storage_id_ =
+ views::ViewStorage::GetSharedInstance()->CreateStorageID();
}
WebContentsViewWin::~WebContentsViewWin() {
+ // Makes sure to remove any stored view we may still have in the ViewStorage.
+ //
+ // It is possible the view went away before us, so we only do this if the
+ // view is registered.
+ views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
+ if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
+ view_storage->RemoveView(last_focused_view_storage_id_);
}
WebContents* WebContentsViewWin::GetWebContents() {
@@ -232,6 +244,72 @@ void WebContentsViewWin::ForwardMessageToDevToolsClient(
dev_tools_window_->SendDevToolsClientMessage(message);
}
+void WebContentsViewWin::SetInitialFocus() {
+ if (web_contents_->AsDOMUIContents())
+ web_contents_->AsDOMUIContents()->SetInitialFocus();
+ else
+ ::SetFocus(GetNativeView());
+}
+
+void WebContentsViewWin::StoreFocus() {
+ views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
+
+ if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
+ view_storage->RemoveView(last_focused_view_storage_id_);
+
+ views::FocusManager* focus_manager =
+ views::FocusManager::GetFocusManager(GetNativeView());
+ if (focus_manager) {
+ // |focus_manager| can be NULL if the tab has been detached but still
+ // exists.
+ views::View* focused_view = focus_manager->GetFocusedView();
+ if (focused_view)
+ view_storage->StoreView(last_focused_view_storage_id_, focused_view);
+
+ // If the focus was on the page, explicitly clear the focus so that we
+ // don't end up with the focused HWND not part of the window hierarchy.
+ // TODO(brettw) this should move to the view somehow.
+ HWND container_hwnd = GetNativeView();
+ if (container_hwnd) {
+ views::View* focused_view = focus_manager->GetFocusedView();
+ if (focused_view) {
+ HWND hwnd = focused_view->GetRootView()->GetWidget()->GetHWND();
+ if (container_hwnd == hwnd || ::IsChild(container_hwnd, hwnd))
+ focus_manager->ClearFocus();
+ }
+ }
+ }
+}
+
+void WebContentsViewWin::RestoreFocus() {
+ views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
+ views::View* last_focused_view =
+ view_storage->RetrieveView(last_focused_view_storage_id_);
+
+ if (!last_focused_view) {
+ SetInitialFocus();
+ } else {
+ views::FocusManager* focus_manager =
+ views::FocusManager::GetFocusManager(GetNativeView());
+
+ // If you hit this DCHECK, please report it to Jay (jcampan).
+ DCHECK(focus_manager != NULL) << "No focus manager when restoring focus.";
+
+ if (last_focused_view->IsFocusable() && focus_manager &&
+ focus_manager->ContainsView(last_focused_view)) {
+ last_focused_view->RequestFocus();
+ } else {
+ // The focused view may not belong to the same window hierarchy (e.g.
+ // if the location bar was focused and the tab is dragged out), or it may
+ // no longer be focusable (e.g. if the location bar was focused and then
+ // we switched to fullscreen mode). In that case we default to the
+ // default focus.
+ SetInitialFocus();
+ }
+ view_storage->RemoveView(last_focused_view_storage_id_);
+ }
+}
+
void WebContentsViewWin::UpdateDragCursor(bool is_drop_target) {
drop_target_->set_is_drop_target(is_drop_target);
}
diff --git a/chrome/browser/tab_contents/web_contents_view_win.h b/chrome/browser/tab_contents/web_contents_view_win.h
index 15fd3f5..cd26bb7 100644
--- a/chrome/browser/tab_contents/web_contents_view_win.h
+++ b/chrome/browser/tab_contents/web_contents_view_win.h
@@ -43,6 +43,9 @@ class WebContentsViewWin : public WebContentsView,
virtual void SizeContents(const gfx::Size& size);
virtual void OpenDeveloperTools();
virtual void ForwardMessageToDevToolsClient(const IPC::Message& message);
+ virtual void SetInitialFocus();
+ virtual void StoreFocus();
+ virtual void RestoreFocus();
// Backend implementation of RenderViewHostDelegate::View.
virtual WebContents* CreateNewWindowInternal(
@@ -113,6 +116,9 @@ class WebContentsViewWin : public WebContentsView,
// Whether to ignore the next CHAR keyboard event.
bool ignore_next_char_event_;
+ // The id used in the ViewStorage to store the last focused view.
+ int last_focused_view_storage_id_;
+
DISALLOW_COPY_AND_ASSIGN(WebContentsViewWin);
};
diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc
index 5836e55..e8c2a54 100644
--- a/chrome/browser/views/frame/browser_view.cc
+++ b/chrome/browser/views/frame/browser_view.cc
@@ -500,8 +500,8 @@ void BrowserView::Show() {
// If we do find there are cases where we need to restore the focus on show,
// that should be added and this should be removed.
TabContents* selected_tab_contents = GetSelectedTabContents();
- if (selected_tab_contents)
- selected_tab_contents->RestoreFocus();
+ if (selected_tab_contents && selected_tab_contents->AsWebContents())
+ selected_tab_contents->AsWebContents()->view()->RestoreFocus();
frame_->Show();
}
@@ -923,8 +923,9 @@ void BrowserView::TabSelectedAt(TabContents* old_contents,
// We do not store the focus when closing the tab to work-around bug 4633.
// Some reports seem to show that the focus manager and/or focused view can
// be garbage at that point, it is not clear why.
- if (old_contents && !old_contents->is_being_destroyed())
- old_contents->StoreFocus();
+ if (old_contents && !old_contents->is_being_destroyed() &&
+ old_contents->AsWebContents())
+ old_contents->AsWebContents()->view()->StoreFocus();
// Update various elements that are interested in knowing the current
// TabContents.
@@ -936,8 +937,9 @@ void BrowserView::TabSelectedAt(TabContents* old_contents,
// etc not result in sad tab.
new_contents->DidBecomeSelected();
if (BrowserList::GetLastActive() == browser_ &&
- !browser_->tabstrip_model()->closing_all()) {
- new_contents->RestoreFocus();
+ !browser_->tabstrip_model()->closing_all() &&
+ new_contents->AsWebContents()) {
+ new_contents->AsWebContents()->view()->RestoreFocus();
}
// Update all the UI bits.
diff --git a/chrome/views/view_storage.cc b/chrome/views/view_storage.cc
index bc5849c..42396b8 100644
--- a/chrome/views/view_storage.cc
+++ b/chrome/views/view_storage.cc
@@ -11,8 +11,6 @@
namespace views {
-ViewStorage* ViewStorage::shared_instance_ = NULL;
-
// This struct contains the information to locate a specific view.
// Locating a view is not always straight-forward as a view can be a floating
// view, or the child of a floating view. Floating views are frequently deleted
@@ -36,19 +34,7 @@ struct ViewLocationInfo {
// static
ViewStorage* ViewStorage::GetSharedInstance() {
- if (shared_instance_)
- return shared_instance_;
-
- shared_instance_ = new ViewStorage();
- return shared_instance_;
-}
-
-// static
-void ViewStorage::DeleteSharedInstance() {
- if (!shared_instance_)
- return;
- delete shared_instance_;
- shared_instance_ = NULL;
+ return Singleton<ViewStorage>::get();
}
ViewStorage::ViewStorage() : view_storage_next_id_(0) {
@@ -57,9 +43,6 @@ ViewStorage::ViewStorage() : view_storage_next_id_(0) {
}
ViewStorage::~ViewStorage() {
- NotificationService::current()->RemoveObserver(
- this, NotificationType::VIEW_REMOVED, NotificationService::AllSources());
-
STLDeleteContainerPairSecondPointers(id_to_view_location_.begin(),
id_to_view_location_.end());
diff --git a/chrome/views/view_storage.h b/chrome/views/view_storage.h
index a965158..8b17474 100644
--- a/chrome/views/view_storage.h
+++ b/chrome/views/view_storage.h
@@ -5,6 +5,7 @@
#ifndef CHROME_VIEWS_VIEW_STORAGE_H_
#define CHROME_VIEWS_VIEW_STORAGE_H_
+#include "base/singleton.h"
#include "chrome/common/notification_observer.h"
#include "chrome/views/view.h"
@@ -31,9 +32,6 @@ class ViewStorage : public NotificationObserver {
// It is guaranted to be non NULL.
static ViewStorage* GetSharedInstance();
- // Deletes the global instance of the ViewStorage.
- static void DeleteSharedInstance();
-
// Returns a unique storage id that can be used to store/retrieve views.
int CreateStorageID();
@@ -47,6 +45,8 @@ class ViewStorage : public NotificationObserver {
void RemoveView(int storage_id);
private:
+ friend struct DefaultSingletonTraits<ViewStorage>;
+
ViewStorage();
~ViewStorage();
@@ -69,9 +69,6 @@ class ViewStorage : public NotificationObserver {
// Association View to id, used to speed up view notification removal.
std::map<View*, std::vector<int>*> view_to_ids_;
- // The singleton instance.
- static ViewStorage* shared_instance_;
-
DISALLOW_COPY_AND_ASSIGN(ViewStorage);
};