summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-12 19:14:54 +0000
committerjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-12 19:14:54 +0000
commit7e38369f764596be0a38c0a1a7339c5ed43b67de (patch)
tree5d1c9f4bfc0e51f30cab13fbcfce40ea975a3782
parent9fc286c694089736ee8e7b740302dc4dd080a6aa (diff)
downloadchromium_src-7e38369f764596be0a38c0a1a7339c5ed43b67de.zip
chromium_src-7e38369f764596be0a38c0a1a7339c5ed43b67de.tar.gz
chromium_src-7e38369f764596be0a38c0a1a7339c5ed43b67de.tar.bz2
Changing the focus manager to not subclass HWNDs (but for the top-windows).Components that have HWND now need to specifically let the FocusManager know when they get the native focus.This is the reason for the new GotFocus() notification on the RenderWidgetHostViewWin class.BUG=NoneTEST=Run the interactive tests, the unit-tests. Test that the focus is remembered correctly when switching windows, switching tabs. Test that focus traversal in the browser and in the option dialog works as expected.
Review URL: http://codereview.chromium.org/122002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18301 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view_win.cc10
-rw-r--r--chrome/browser/browser.cc4
-rw-r--r--chrome/browser/browser.h1
-rw-r--r--chrome/browser/browser_focus_uitest.cc46
-rw-r--r--chrome/browser/browser_window.h8
-rw-r--r--chrome/browser/cocoa/browser_window_cocoa.h1
-rw-r--r--chrome/browser/cocoa/browser_window_cocoa.mm4
-rw-r--r--chrome/browser/extensions/extension_host.cc3
-rw-r--r--chrome/browser/extensions/extension_host.h1
-rw-r--r--chrome/browser/gtk/browser_window_gtk.cc4
-rw-r--r--chrome/browser/gtk/browser_window_gtk.h1
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc8
-rw-r--r--chrome/browser/renderer_host/render_view_host.h1
-rw-r--r--chrome/browser/renderer_host/render_view_host_delegate.h3
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc4
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h5
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.cc2
-rw-r--r--chrome/browser/tab_contents/interstitial_page.cc11
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc5
-rw-r--r--chrome/browser/tab_contents/tab_contents_delegate.h3
-rw-r--r--chrome/browser/tab_contents/tab_contents_view_gtk.cc4
-rw-r--r--chrome/browser/tab_contents/tab_contents_view_gtk.h1
-rw-r--r--chrome/browser/tab_contents/tab_contents_view_mac.h1
-rw-r--r--chrome/browser/tab_contents/tab_contents_view_mac.mm4
-rw-r--r--chrome/browser/tab_contents/tab_contents_view_win.cc48
-rw-r--r--chrome/browser/tab_contents/tab_contents_view_win.h2
-rw-r--r--chrome/browser/views/frame/browser_view.cc8
-rw-r--r--chrome/browser/views/frame/browser_view.h8
-rw-r--r--chrome/browser/views/tab_contents/native_tab_contents_container.h3
-rw-r--r--chrome/browser/views/tab_contents/native_tab_contents_container_gtk.cc12
-rw-r--r--chrome/browser/views/tab_contents/native_tab_contents_container_gtk.h1
-rw-r--r--chrome/browser/views/tab_contents/native_tab_contents_container_win.cc84
-rw-r--r--chrome/browser/views/tab_contents/native_tab_contents_container_win.h2
-rw-r--r--chrome/browser/views/tab_contents/tab_contents_container.cc5
-rw-r--r--chrome/browser/views/tab_contents/tab_contents_container.h11
-rw-r--r--chrome/test/test_browser_window.h2
-rw-r--r--views/controls/native/native_view_host_gtk.cc2
-rw-r--r--views/controls/native/native_view_host_win.cc7
-rw-r--r--views/controls/native_control.cc11
-rw-r--r--views/controls/native_control_win.cc10
-rw-r--r--views/controls/textfield/native_textfield_win.cc13
-rw-r--r--views/controls/textfield/native_textfield_win.h2
-rw-r--r--views/focus/focus_manager.cc19
-rw-r--r--views/focus/focus_manager.h20
-rw-r--r--views/focus/focus_manager_unittest.cc29
-rw-r--r--views/widget/widget_win.cc4
46 files changed, 275 insertions, 163 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc
index 2a58b66..7aac332 100644
--- a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc
@@ -1621,6 +1621,16 @@ void AutocompleteEditViewWin::OnPaste() {
}
void AutocompleteEditViewWin::OnSetFocus(HWND focus_wnd) {
+ views::FocusManager* focus_manager =
+ views::FocusManager::GetFocusManager(m_hWnd);
+ if (focus_manager) {
+ // Notify the FocusManager that the focused view is now the location bar
+ // (our parent view).
+ focus_manager->SetFocusedView(parent_view_);
+ } else {
+ NOTREACHED();
+ }
+
model_->OnSetFocus(GetKeyState(VK_CONTROL) < 0);
// Notify controller if it needs to show hint UI of some kind.
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index fe267cb..b1007c0 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -1851,6 +1851,10 @@ void Browser::ContentsZoomChange(bool zoom_in) {
ExecuteCommand(zoom_in ? IDC_ZOOM_PLUS : IDC_ZOOM_MINUS);
}
+void Browser::TabContentsFocused(TabContents* tab_content) {
+ window_->TabContentsFocused(tab_content);
+}
+
bool Browser::IsApplication() const {
return (type_ & TYPE_APP) != 0;
}
diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h
index 501fdb8..16af168f 100644
--- a/chrome/browser/browser.h
+++ b/chrome/browser/browser.h
@@ -478,6 +478,7 @@ class Browser : public TabStripModelDelegate,
virtual void UpdateTargetURL(TabContents* source, const GURL& url);
virtual void ContentsZoomChange(bool zoom_in);
+ virtual void TabContentsFocused(TabContents* tab_content);
virtual bool IsApplication() const;
virtual void ConvertContentsToApplication(TabContents* source);
virtual bool ShouldDisplayURLField();
diff --git a/chrome/browser/browser_focus_uitest.cc b/chrome/browser/browser_focus_uitest.cc
index 712f955..3681c1b 100644
--- a/chrome/browser/browser_focus_uitest.cc
+++ b/chrome/browser/browser_focus_uitest.cc
@@ -96,7 +96,7 @@ class TestInterstitialPage : public InterstitialPage {
};
} // namespace
-IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_BrowsersRememberFocus) {
+IN_PROC_BROWSER_TEST_F(BrowserFocusTest, BrowsersRememberFocus) {
HTTPTestServer* server = StartHTTPServer();
// First we navigate to our test page.
@@ -111,7 +111,7 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_BrowsersRememberFocus) {
views::FocusManager::GetFocusManager(hwnd);
ASSERT_TRUE(focus_manager);
- EXPECT_EQ(browser_view->contents_container()->GetFocusView(),
+ EXPECT_EQ(browser_view->GetTabContentsContainerView(),
focus_manager->GetFocusedView());
// Now hide the window, show it again, the focus should not have changed.
@@ -119,7 +119,7 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_BrowsersRememberFocus) {
// using Windows API.
::ShowWindow(hwnd, SW_HIDE);
::ShowWindow(hwnd, SW_SHOW);
- EXPECT_EQ(browser_view->contents_container()->GetFocusView(),
+ EXPECT_EQ(browser_view->GetTabContentsContainerView(),
focus_manager->GetFocusedView());
// Click on the location bar.
@@ -151,7 +151,7 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_BrowsersRememberFocus) {
views::FocusManager* focus_manager2 =
views::FocusManager::GetFocusManager(hwnd2);
ASSERT_TRUE(focus_manager2);
- EXPECT_EQ(browser_view2->contents_container()->GetFocusView(),
+ EXPECT_EQ(browser_view2->GetTabContentsContainerView(),
focus_manager2->GetFocusedView());
// Switch to the 1st browser window, focus should still be on the location
@@ -163,7 +163,7 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_BrowsersRememberFocus) {
// Switch back to the second browser, focus should still be on the page.
browser2->window()->Activate();
EXPECT_EQ(NULL, focus_manager->GetFocusedView());
- EXPECT_EQ(browser_view->contents_container()->GetFocusView(),
+ EXPECT_EQ(browser_view2->GetTabContentsContainerView(),
focus_manager2->GetFocusedView());
// Close the 2nd browser to avoid a DCHECK().
@@ -205,9 +205,12 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, TabsRememberFocus) {
browser()->SelectTabContentsAt(j, true);
// Activate the location bar or the page.
- views::View* view_to_focus = kFocusPage[i][j] ?
- browser_view->contents_container()->GetFocusView() :
- browser_view->GetLocationBarView();
+ views::View* view_to_focus;
+ if (kFocusPage[i][j]) {
+ view_to_focus = browser_view->GetTabContentsContainerView();
+ } else {
+ view_to_focus = browser_view->GetLocationBarView();
+ }
ui_controls::MoveMouseToCenterAndPress(view_to_focus,
ui_controls::LEFT,
@@ -223,9 +226,12 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, TabsRememberFocus) {
browser()->SelectTabContentsAt(j, true);
// Activate the location bar or the page.
- views::View* view = kFocusPage[i][j] ?
- browser_view->contents_container()->GetFocusView() :
- browser_view->GetLocationBarView();
+ views::View* view;
+ if (kFocusPage[i][j]) {
+ view = browser_view->GetTabContentsContainerView();
+ } else {
+ view = browser_view->GetLocationBarView();
+ }
EXPECT_EQ(view, focus_manager->GetFocusedView());
}
}
@@ -398,7 +404,7 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FocusTraversalOnInterstitial) {
views::FocusManager::GetFocusManager(hwnd);
// Focus should be on the page.
- EXPECT_EQ(browser_view->contents_container()->GetFocusView(),
+ EXPECT_EQ(browser_view->GetTabContentsContainerView(),
focus_manager->GetFocusedView());
// Let's show an interstitial.
@@ -493,12 +499,12 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, InterstitialFocus) {
views::FocusManager::GetFocusManager(hwnd);
// Page should have focus.
- EXPECT_EQ(browser_view->contents_container()->GetFocusView(),
+ EXPECT_EQ(browser_view->GetTabContentsContainerView(),
focus_manager->GetFocusedView());
EXPECT_TRUE(browser()->GetSelectedTabContents()->render_view_host()->view()->
HasFocus());
- // Let's show an interstitial.
+ // Let's show an interstitial.erstitial
TestInterstitialPage* interstitial_page =
new TestInterstitialPage(browser()->GetSelectedTabContents(),
true, GURL("http://interstitial.com"));
@@ -510,7 +516,7 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, InterstitialFocus) {
ui_test_utils::RunMessageLoop();
// The interstitial should have focus now.
- EXPECT_EQ(browser_view->contents_container()->GetFocusView(),
+ EXPECT_EQ(browser_view->GetTabContentsContainerView(),
focus_manager->GetFocusedView());
EXPECT_TRUE(interstitial_page->HasFocus());
@@ -518,7 +524,7 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, InterstitialFocus) {
interstitial_page->DontProceed();
// Focus should be back on the original page.
- EXPECT_EQ(browser_view->contents_container()->GetFocusView(),
+ EXPECT_EQ(browser_view->GetTabContentsContainerView(),
focus_manager->GetFocusedView());
EXPECT_TRUE(browser()->GetSelectedTabContents()->render_view_host()->view()->
HasFocus());
@@ -577,12 +583,12 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FindFocusTest) {
// Set focus to the page.
ui_controls::MoveMouseToCenterAndPress(
- browser_view->contents_container()->GetFocusView(),
+ browser_view->GetTabContentsContainerView(),
ui_controls::LEFT,
ui_controls::DOWN | ui_controls::UP,
new MessageLoop::QuitTask());
ui_test_utils::RunMessageLoop();
- EXPECT_EQ(browser_view->contents_container()->GetFocusView(),
+ EXPECT_EQ(browser_view->GetTabContentsContainerView(),
focus_manager->GetFocusedView());
// Now press Ctrl+F again and focus should move to the Find box.
@@ -612,7 +618,7 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, TabInitialFocus) {
// Open the history tab, focus should be on the tab contents.
browser()->ShowHistoryTab();
- EXPECT_EQ(browser_view->contents_container()->GetFocusView(),
+ EXPECT_EQ(browser_view->GetTabContentsContainerView(),
focus_manager->GetFocusedView());
// Open the new tab, focus should be on the location bar.
@@ -622,6 +628,6 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, TabInitialFocus) {
// Open the download tab, focus should be on the tab contents.
browser()->ShowDownloadsTab();
- EXPECT_EQ(browser_view->contents_container()->GetFocusView(),
+ EXPECT_EQ(browser_view->GetTabContentsContainerView(),
focus_manager->GetFocusedView());
}
diff --git a/chrome/browser/browser_window.h b/chrome/browser/browser_window.h
index 011cab1..2b3ed63 100644
--- a/chrome/browser/browser_window.h
+++ b/chrome/browser/browser_window.h
@@ -16,6 +16,7 @@ class LocationBar;
class HtmlDialogUIDelegate;
class StatusBubble;
class TabContents;
+class TabContentsContainer;
namespace gfx {
class Rect;
@@ -190,6 +191,10 @@ class BrowserWindow {
// during infobar animations).
virtual int GetExtraRenderViewHeight() const = 0;
+ // Notification that |tab_contents| got the focus through user action (click
+ // on the page).
+ virtual void TabContentsFocused(TabContents* tab_contents) = 0;
+
// Construct a BrowserWindow implementation for the specified |browser|.
static BrowserWindow* CreateBrowserWindow(Browser* browser);
@@ -217,6 +222,9 @@ class BrowserWindowTesting {
// Returns the LocationBarView.
virtual LocationBarView* GetLocationBarView() const = 0;
+
+ // Returns the TabContentsContainer.
+ virtual views::View* GetTabContentsContainerView() const = 0;
#endif
};
diff --git a/chrome/browser/cocoa/browser_window_cocoa.h b/chrome/browser/cocoa/browser_window_cocoa.h
index 69b9715..9dc9e72 100644
--- a/chrome/browser/cocoa/browser_window_cocoa.h
+++ b/chrome/browser/cocoa/browser_window_cocoa.h
@@ -71,6 +71,7 @@ class BrowserWindowCocoa : public BrowserWindow,
gfx::NativeWindow parent_window);
virtual void UserChangedTheme();
virtual int GetExtraRenderViewHeight() const;
+ virtual void TabContentsFocused(TabContents* tab_contents);
// Overridden from NotificationObserver
virtual void Observe(NotificationType type,
diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm
index d052f61..f295167 100644
--- a/chrome/browser/cocoa/browser_window_cocoa.mm
+++ b/chrome/browser/cocoa/browser_window_cocoa.mm
@@ -249,6 +249,10 @@ int BrowserWindowCocoa::GetExtraRenderViewHeight() const {
return 0;
}
+void BrowserWindowCocoa::TabContentsFocused(TabContents* tab_contents) {
+ NOTIMPLEMENTED();
+}
+
void BrowserWindowCocoa::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index d78d8bc..aebf7cf 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -183,6 +183,9 @@ void ExtensionHost::StartDragging(const WebDropData& drop_data) {
void ExtensionHost::UpdateDragCursor(bool is_drop_target) {
}
+void ExtensionHost::GotFocus() {
+}
+
void ExtensionHost::TakeFocus(bool reverse) {
}
diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h
index 04ee8f3..4634723 100644
--- a/chrome/browser/extensions/extension_host.h
+++ b/chrome/browser/extensions/extension_host.h
@@ -83,6 +83,7 @@ class ExtensionHost : public RenderViewHostDelegate,
virtual void ShowContextMenu(const ContextMenuParams& params);
virtual void StartDragging(const WebDropData& drop_data);
virtual void UpdateDragCursor(bool is_drop_target);
+ virtual void GotFocus();
virtual void TakeFocus(bool reverse);
virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
virtual void HandleMouseEvent();
diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc
index bbc2497..91eaf3e 100644
--- a/chrome/browser/gtk/browser_window_gtk.cc
+++ b/chrome/browser/gtk/browser_window_gtk.cc
@@ -686,6 +686,10 @@ int BrowserWindowGtk::GetExtraRenderViewHeight() const {
return sum;
}
+void BrowserWindowGtk::TabContentsFocused(TabContents* tab_contents) {
+ NOTIMPLEMENTED();
+}
+
void BrowserWindowGtk::ConfirmBrowserCloseWithPendingDownloads() {
NOTIMPLEMENTED();
browser_->InProgressDownloadResponse(false);
diff --git a/chrome/browser/gtk/browser_window_gtk.h b/chrome/browser/gtk/browser_window_gtk.h
index c253832..ee43808 100644
--- a/chrome/browser/gtk/browser_window_gtk.h
+++ b/chrome/browser/gtk/browser_window_gtk.h
@@ -88,6 +88,7 @@ class BrowserWindowGtk : public BrowserWindow,
gfx::NativeWindow parent_window);
virtual void UserChangedTheme();
virtual int GetExtraRenderViewHeight() const;
+ virtual void TabContentsFocused(TabContents* tab_contents);
// Overridden from NotificationObserver:
virtual void Observe(NotificationType type,
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 5e4fd06..d7d787e 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -664,6 +664,14 @@ void RenderViewHost::MakeNavigateParams(const NavigationEntry& entry,
params->request_time = base::Time::Now();
}
+void RenderViewHost::GotFocus() {
+ RenderWidgetHost::GotFocus(); // Notifies the renderer it got focus.
+
+ RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
+ if (view)
+ view->GotFocus();
+}
+
bool RenderViewHost::CanBlur() const {
return delegate_->CanBlur();
}
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index efe3b39..0407e1b 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -418,6 +418,7 @@ class RenderViewHost : public RenderWidgetHost {
virtual void Shutdown();
virtual bool IsRenderView() { return true; }
virtual void OnMessageReceived(const IPC::Message& msg);
+ virtual void GotFocus();
virtual bool CanBlur() const;
virtual void ForwardMouseEvent(const WebKit::WebMouseEvent& mouse_event);
virtual gfx::Rect GetRootWindowResizerRect() const;
diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h
index 8c8ffe1..b91b69b 100644
--- a/chrome/browser/renderer_host/render_view_host_delegate.h
+++ b/chrome/browser/renderer_host/render_view_host_delegate.h
@@ -110,6 +110,9 @@ class RenderViewHostDelegate {
// |is_drop_target| is true if the mouse is over a valid drop target.
virtual void UpdateDragCursor(bool is_drop_target) = 0;
+ // Notification that view for this delegate got the focus.
+ virtual void GotFocus() = 0;
+
// Callback to inform the browser it should take back focus. If reverse is
// true, it means the focus was retrieved by doing a Shift-Tab.
virtual void TakeFocus(bool reverse) = 0;
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index fb6303b..fccd45d 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -188,6 +188,10 @@ void RenderWidgetHost::WasResized() {
resize_ack_pending_ = false;
}
+void RenderWidgetHost::GotFocus() {
+ Focus();
+}
+
void RenderWidgetHost::Focus() {
Send(new ViewMsg_SetFocus(routing_id_, true));
}
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index 8ac2376..0645496 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -165,6 +165,11 @@ class RenderWidgetHost : public IPC::Channel::Listener {
// Called to notify the RenderWidget that it has been resized.
void WasResized();
+ // Called to notify the RenderWidget that its associated native window got
+ // focused.
+ virtual void GotFocus();
+
+ // Tells the renderer it got/lost focus.
void Focus();
void Blur();
void LostCapture();
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc
index c786e70..9c33865 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc
@@ -791,7 +791,7 @@ LRESULT RenderWidgetHostViewWin::OnSetCursor(HWND window, UINT hittest_code,
}
void RenderWidgetHostViewWin::OnSetFocus(HWND window) {
- render_widget_host_->Focus();
+ render_widget_host_->GotFocus();
}
void RenderWidgetHostViewWin::OnKillFocus(HWND window) {
diff --git a/chrome/browser/tab_contents/interstitial_page.cc b/chrome/browser/tab_contents/interstitial_page.cc
index a461414..15959be 100644
--- a/chrome/browser/tab_contents/interstitial_page.cc
+++ b/chrome/browser/tab_contents/interstitial_page.cc
@@ -83,6 +83,7 @@ class InterstitialPage::InterstitialPageRVHViewDelegate
virtual void ShowContextMenu(const ContextMenuParams& params);
virtual void StartDragging(const WebDropData& drop_data);
virtual void UpdateDragCursor(bool is_drop_target);
+ virtual void GotFocus();
virtual void TakeFocus(bool reverse);
virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
virtual void HandleMouseEvent();
@@ -210,6 +211,13 @@ void InterstitialPage::Hide() {
old_view->Show();
}
+ // If the focus was on the interstitial, let's keep it to the page.
+ // (Note that in unit-tests the RVH may not have a view).
+ if (render_view_host_->view() && render_view_host_->view()->HasFocus() &&
+ tab_->render_view_host()->view()) {
+ tab_->render_view_host()->view()->Focus();
+ }
+
render_view_host_->Shutdown();
render_view_host_ = NULL;
if (tab_->interstitial_page())
@@ -519,6 +527,9 @@ void InterstitialPage::InterstitialPageRVHViewDelegate::UpdateDragCursor(
NOTREACHED() << "InterstitialPage does not support dragging yet.";
}
+void InterstitialPage::InterstitialPageRVHViewDelegate::GotFocus() {
+}
+
void InterstitialPage::InterstitialPageRVHViewDelegate::UpdatePreferredWidth(
int pref_width) {
}
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index 6b45c3e..77e29af 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -34,6 +34,7 @@
#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/browser/renderer_host/web_cache_manager.h"
#include "chrome/browser/tab_contents/infobar_delegate.h"
+#include "chrome/browser/tab_contents/interstitial_page.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/tab_contents_delegate.h"
#include "chrome/browser/tab_contents/tab_contents_view.h"
@@ -822,6 +823,10 @@ void TabContents::Focus() {
}
void TabContents::FocusThroughTabTraversal(bool reverse) {
+ if (showing_interstitial_page()) {
+ render_manager_.interstitial_page()->FocusThroughTabTraversal(reverse);
+ return;
+ }
render_view_host()->SetInitialFocus(reverse);
}
diff --git a/chrome/browser/tab_contents/tab_contents_delegate.h b/chrome/browser/tab_contents/tab_contents_delegate.h
index d7820e2..2fdaa7a 100644
--- a/chrome/browser/tab_contents/tab_contents_delegate.h
+++ b/chrome/browser/tab_contents/tab_contents_delegate.h
@@ -171,6 +171,9 @@ class TabContentsDelegate {
return false;
}
+ // Notification that |tab_contents| has gained focus.
+ virtual void TabContentsFocused(TabContents* tab_content) { }
+
// Return much extra vertical space should be allotted to the
// render view widget during various animations (e.g. infobar closing).
// This is used to make painting look smoother.
diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.cc b/chrome/browser/tab_contents/tab_contents_view_gtk.cc
index 8496b03..3443b84 100644
--- a/chrome/browser/tab_contents/tab_contents_view_gtk.cc
+++ b/chrome/browser/tab_contents/tab_contents_view_gtk.cc
@@ -264,6 +264,10 @@ void TabContentsViewGtk::UpdateDragCursor(bool is_drop_target) {
NOTIMPLEMENTED();
}
+void TabContentsViewGtk::GotFocus() {
+ NOTIMPLEMENTED();
+}
+
// This is called when we the renderer asks us to take focus back (i.e., it has
// iterated past the last focusable element on the page).
void TabContentsViewGtk::TakeFocus(bool reverse) {
diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.h b/chrome/browser/tab_contents/tab_contents_view_gtk.h
index 7056ee9..8c85421 100644
--- a/chrome/browser/tab_contents/tab_contents_view_gtk.h
+++ b/chrome/browser/tab_contents/tab_contents_view_gtk.h
@@ -56,6 +56,7 @@ class TabContentsViewGtk : public TabContentsView,
virtual void ShowContextMenu(const ContextMenuParams& params);
virtual void StartDragging(const WebDropData& drop_data);
virtual void UpdateDragCursor(bool is_drop_target);
+ virtual void GotFocus();
virtual void TakeFocus(bool reverse);
virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
diff --git a/chrome/browser/tab_contents/tab_contents_view_mac.h b/chrome/browser/tab_contents/tab_contents_view_mac.h
index 91af1a6..5b464b9 100644
--- a/chrome/browser/tab_contents/tab_contents_view_mac.h
+++ b/chrome/browser/tab_contents/tab_contents_view_mac.h
@@ -63,6 +63,7 @@ class TabContentsViewMac : public TabContentsView,
virtual void ShowContextMenu(const ContextMenuParams& params);
virtual void StartDragging(const WebDropData& drop_data);
virtual void UpdateDragCursor(bool is_drop_target);
+ virtual void GotFocus();
virtual void TakeFocus(bool reverse);
virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
diff --git a/chrome/browser/tab_contents/tab_contents_view_mac.mm b/chrome/browser/tab_contents/tab_contents_view_mac.mm
index 9bf8e1e..1d2d59a 100644
--- a/chrome/browser/tab_contents/tab_contents_view_mac.mm
+++ b/chrome/browser/tab_contents/tab_contents_view_mac.mm
@@ -161,6 +161,10 @@ void TabContentsViewMac::UpdateDragCursor(bool is_drop_target) {
NOTIMPLEMENTED();
}
+void TabContentsViewMac::GotFocus() {
+ NOTIMPLEMENTED();
+}
+
// This is called when we the renderer asks us to take focus back (i.e., it has
// iterated past the last focusable element on the page).
void TabContentsViewMac::TakeFocus(bool reverse) {
diff --git a/chrome/browser/tab_contents/tab_contents_view_win.cc b/chrome/browser/tab_contents/tab_contents_view_win.cc
index 966c41e..341eb50 100644
--- a/chrome/browser/tab_contents/tab_contents_view_win.cc
+++ b/chrome/browser/tab_contents/tab_contents_view_win.cc
@@ -232,25 +232,34 @@ void TabContentsViewWin::SizeContents(const gfx::Size& size) {
}
void TabContentsViewWin::Focus() {
- HWND container_hwnd = GetNativeView();
- if (!container_hwnd)
+ views::FocusManager* focus_manager =
+ views::FocusManager::GetFocusManager(GetNativeView());
+
+ if (tab_contents()->interstitial_page()) {
+ tab_contents()->interstitial_page()->Focus();
+ return;
+ }
+
+ if (sad_tab_.get()) {
+ sad_tab_->RequestFocus();
return;
+ }
- views::FocusManager* focus_manager =
- views::FocusManager::GetFocusManager(container_hwnd);
- if (!focus_manager)
- return; // During testing we have no focus manager.
- views::View* v = focus_manager->GetViewForWindow(container_hwnd, true);
- DCHECK(v);
- if (v)
- v->RequestFocus();
+ RenderWidgetHostView* rwhv = tab_contents()->render_widget_host_view();
+ if (rwhv) {
+ ::SetFocus(rwhv->GetNativeView());
+ return;
+ }
+
+ // Default to focusing our HWND.
+ ::SetFocus(GetNativeView());
}
void TabContentsViewWin::SetInitialFocus() {
if (tab_contents()->FocusLocationBarByDefault())
tab_contents()->delegate()->SetFocusToLocationBar();
else
- ::SetFocus(GetNativeView());
+ Focus();
}
void TabContentsViewWin::StoreFocus() {
@@ -316,6 +325,10 @@ void TabContentsViewWin::UpdateDragCursor(bool is_drop_target) {
drop_target_->set_is_drop_target(is_drop_target);
}
+void TabContentsViewWin::GotFocus() {
+ tab_contents()->delegate()->TabContentsFocused(tab_contents());
+}
+
void TabContentsViewWin::TakeFocus(bool reverse) {
if (!tab_contents()->delegate()->TakeFocus(reverse)) {
views::FocusManager* focus_manager =
@@ -485,19 +498,6 @@ LRESULT TabContentsViewWin::OnReflectedMessage(UINT msg, WPARAM w_param,
return 0;
}
-void TabContentsViewWin::OnSetFocus(HWND window) {
- // TODO(jcampan): figure out why removing this prevents tabs opened in the
- // background from properly taking focus.
- // We NULL-check the render_view_host_ here because Windows can send us
- // messages during the destruction process after it has been destroyed.
- if (tab_contents()->render_widget_host_view()) {
- HWND inner_hwnd =
- tab_contents()->render_widget_host_view()->GetNativeView();
- if (::IsWindow(inner_hwnd))
- ::SetFocus(inner_hwnd);
- }
-}
-
void TabContentsViewWin::OnVScroll(int scroll_type, short position,
HWND scrollbar) {
ScrollCommon(WM_VSCROLL, scroll_type, position, scrollbar);
diff --git a/chrome/browser/tab_contents/tab_contents_view_win.h b/chrome/browser/tab_contents/tab_contents_view_win.h
index b4d360b..07bd545 100644
--- a/chrome/browser/tab_contents/tab_contents_view_win.h
+++ b/chrome/browser/tab_contents/tab_contents_view_win.h
@@ -48,6 +48,7 @@ class TabContentsViewWin : public TabContentsView,
virtual void ShowContextMenu(const ContextMenuParams& params);
virtual void StartDragging(const WebDropData& drop_data);
virtual void UpdateDragCursor(bool is_drop_target);
+ virtual void GotFocus();
virtual void TakeFocus(bool reverse);
virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
@@ -61,7 +62,6 @@ class TabContentsViewWin : public TabContentsView,
virtual LRESULT OnMouseRange(UINT msg, WPARAM w_param, LPARAM l_param);
virtual void OnPaint(HDC junk_dc);
virtual LRESULT OnReflectedMessage(UINT msg, WPARAM w_param, LPARAM l_param);
- virtual void OnSetFocus(HWND window);
virtual void OnVScroll(int scroll_type, short position, HWND scrollbar);
virtual void OnWindowPosChanged(WINDOWPOS* window_pos);
virtual void OnSize(UINT param, const WTL::CSize& size);
diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc
index 1b1f6f9..1b3e42b 100644
--- a/chrome/browser/views/frame/browser_view.cc
+++ b/chrome/browser/views/frame/browser_view.cc
@@ -895,6 +895,10 @@ int BrowserView::GetExtraRenderViewHeight() const {
return 0;
}
+void BrowserView::TabContentsFocused(TabContents* tab_contents) {
+ contents_container_->TabContentsFocused(tab_contents);
+}
+
///////////////////////////////////////////////////////////////////////////////
// BrowserView, BrowserWindowTesting implementation:
@@ -906,6 +910,10 @@ LocationBarView* BrowserView::GetLocationBarView() const {
return toolbar_->location_bar();
}
+views::View* BrowserView::GetTabContentsContainerView() const {
+ return contents_container_->GetFocusView();
+}
+
///////////////////////////////////////////////////////////////////////////////
// BrowserView, NotificationObserver implementation:
diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h
index a6c134b..b6d8dcc 100644
--- a/chrome/browser/views/frame/browser_view.h
+++ b/chrome/browser/views/frame/browser_view.h
@@ -185,12 +185,6 @@ class BrowserView : public BrowserWindow,
void AttachBrowserBubble(BrowserBubble *bubble);
void DetachBrowserBubble(BrowserBubble *bubble);
-#ifdef UNIT_TEST
- TabContentsContainer* contents_container() const {
- return contents_container_;
- }
-#endif
-
// Overridden from BrowserWindow:
virtual void Show();
virtual void SetBounds(const gfx::Rect& bounds);
@@ -237,10 +231,12 @@ class BrowserView : public BrowserWindow,
gfx::NativeWindow parent_window);
virtual void UserChangedTheme();
virtual int GetExtraRenderViewHeight() const;
+ virtual void TabContentsFocused(TabContents* source);
// Overridden from BrowserWindowTesting:
virtual BookmarkBarView* GetBookmarkBarView() const;
virtual LocationBarView* GetLocationBarView() const;
+ virtual views::View* GetTabContentsContainerView() const;
// Overridden from NotificationObserver:
virtual void Observe(NotificationType type,
diff --git a/chrome/browser/views/tab_contents/native_tab_contents_container.h b/chrome/browser/views/tab_contents/native_tab_contents_container.h
index 4d17002..9c540b9 100644
--- a/chrome/browser/views/tab_contents/native_tab_contents_container.h
+++ b/chrome/browser/views/tab_contents/native_tab_contents_container.h
@@ -35,6 +35,9 @@ class NativeTabContentsContainer {
virtual void RenderViewHostChanged(RenderViewHost* old_host,
RenderViewHost* new_host) = 0;
+ // Tells the container that |tab_contents| got the focus.
+ virtual void TabContentsFocused(TabContents* tab_contents) = 0;
+
// Retrieves the views::View that hosts the TabContents.
virtual views::View* GetView() = 0;
};
diff --git a/chrome/browser/views/tab_contents/native_tab_contents_container_gtk.cc b/chrome/browser/views/tab_contents/native_tab_contents_container_gtk.cc
index 08495fc..56fd42a 100644
--- a/chrome/browser/views/tab_contents/native_tab_contents_container_gtk.cc
+++ b/chrome/browser/views/tab_contents/native_tab_contents_container_gtk.cc
@@ -112,6 +112,18 @@ views::View* NativeTabContentsContainerGtk::GetView() {
return this;
}
+void NativeTabContentsContainerGtk::TabContentsFocused(
+ TabContents* tab_contents) {
+#if defined(OS_WIN)
+ views::FocusManager* focus_manager = GetFocusManager();
+ if (!focus_manager) {
+ NOTREACHED();
+ return;
+ }
+ focus_manager->SetFocusedView(this);
+#endif
+}
+
////////////////////////////////////////////////////////////////////////////////
// NativeTabContentsContainerGtk, views::View overrides:
diff --git a/chrome/browser/views/tab_contents/native_tab_contents_container_gtk.h b/chrome/browser/views/tab_contents/native_tab_contents_container_gtk.h
index 855faa2..0d4ed05 100644
--- a/chrome/browser/views/tab_contents/native_tab_contents_container_gtk.h
+++ b/chrome/browser/views/tab_contents/native_tab_contents_container_gtk.h
@@ -20,6 +20,7 @@ class NativeTabContentsContainerGtk : public NativeTabContentsContainer,
virtual void SetFastResize(bool fast_resize);
virtual void RenderViewHostChanged(RenderViewHost* old_host,
RenderViewHost* new_host);
+ virtual void TabContentsFocused(TabContents* tab_contents);
virtual views::View* GetView();
// Overridden from views::View:
diff --git a/chrome/browser/views/tab_contents/native_tab_contents_container_win.cc b/chrome/browser/views/tab_contents/native_tab_contents_container_win.cc
index 800bb54..1e4933f 100644
--- a/chrome/browser/views/tab_contents/native_tab_contents_container_win.cc
+++ b/chrome/browser/views/tab_contents/native_tab_contents_container_win.cc
@@ -9,8 +9,6 @@
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/views/tab_contents/tab_contents_container.h"
#include "views/focus/focus_manager.h"
-#include "views/widget/root_view.h"
-#include "views/widget/widget.h"
////////////////////////////////////////////////////////////////////////////////
// NativeTabContentsContainerWin, public:
@@ -33,13 +31,11 @@ void NativeTabContentsContainerWin::AttachContents(TabContents* contents) {
set_focus_view(this);
Attach(contents->GetNativeView());
- HWND contents_hwnd = contents->GetContentNativeView();
- if (contents_hwnd)
- views::FocusManager::InstallFocusSubclass(contents_hwnd, this);
}
void NativeTabContentsContainerWin::DetachContents(TabContents* contents) {
- // TODO(brettw) should this move to NativeViewHost::Detach which is called below?
+ // TODO(brettw) should this move to NativeViewHost::Detach which is called
+ // below?
// It needs cleanup regardless.
HWND container_hwnd = contents->GetNativeView();
if (container_hwnd) {
@@ -49,16 +45,6 @@ void NativeTabContentsContainerWin::DetachContents(TabContents* contents) {
// Reset the parent to NULL to ensure hidden tabs don't receive messages.
::SetParent(container_hwnd, NULL);
-
- // Unregister the tab contents window from the FocusManager.
- views::FocusManager::UninstallFocusSubclass(container_hwnd);
- }
-
- HWND hwnd = contents->GetContentNativeView();
- if (hwnd) {
- // We may not have an HWND anymore, if the renderer crashed and we are
- // displaying the sad tab for example.
- views::FocusManager::UninstallFocusSubclass(hwnd);
}
// Now detach the TabContents.
@@ -72,20 +58,8 @@ void NativeTabContentsContainerWin::SetFastResize(bool fast_resize) {
void NativeTabContentsContainerWin::RenderViewHostChanged(
RenderViewHost* old_host,
RenderViewHost* new_host) {
- if (old_host && old_host->view()) {
- views::FocusManager::UninstallFocusSubclass(
- old_host->view()->GetNativeView());
- }
-
- if (new_host && new_host->view()) {
- views::FocusManager::InstallFocusSubclass(
- new_host->view()->GetNativeView(), this);
- }
-
// If we are focused, we need to pass the focus to the new RenderViewHost.
- views::FocusManager* focus_manager = views::FocusManager::GetFocusManager(
- GetRootView()->GetWidget()->GetNativeView());
- if (focus_manager->GetFocusedView() == this)
+ if (GetFocusManager()->GetFocusedView() == this)
Focus();
}
@@ -93,12 +67,22 @@ views::View* NativeTabContentsContainerWin::GetView() {
return this;
}
+void NativeTabContentsContainerWin::TabContentsFocused(
+ TabContents* tab_contents) {
+ views::FocusManager* focus_manager = GetFocusManager();
+ if (!focus_manager) {
+ NOTREACHED();
+ return;
+ }
+ focus_manager->SetFocusedView(this);
+}
+
////////////////////////////////////////////////////////////////////////////////
// NativeTabContentsContainerWin, views::View overrides:
bool NativeTabContentsContainerWin::SkipDefaultKeyEventProcessing(
const views::KeyEvent& e) {
- // Don't look-up accelerators or tab-traverse if we are showing a non-crashed
+ // Don't look-up accelerators or tab-traversal if we are showing a non-crashed
// TabContents.
// We'll first give the page a chance to process the key events. If it does
// not process them, they'll be returned to us and we'll treat them as
@@ -107,10 +91,6 @@ bool NativeTabContentsContainerWin::SkipDefaultKeyEventProcessing(
!container_->tab_contents()->is_crashed();
}
-views::FocusTraversable* NativeTabContentsContainerWin::GetFocusTraversable() {
- return NULL;
-}
-
bool NativeTabContentsContainerWin::IsFocusable() const {
// We need to be focusable when our contents is not a view hierarchy, as
// clicking on the contents needs to focus us.
@@ -118,40 +98,24 @@ bool NativeTabContentsContainerWin::IsFocusable() const {
}
void NativeTabContentsContainerWin::Focus() {
- if (container_->tab_contents()) {
- // Set the native focus on the actual content of the tab, that is the
- // interstitial if one is showing.
- if (container_->tab_contents()->interstitial_page()) {
- container_->tab_contents()->interstitial_page()->Focus();
- return;
- }
- SetFocus(container_->tab_contents()->GetContentNativeView());
- }
+ if (container_->tab_contents())
+ container_->tab_contents()->Focus();
}
void NativeTabContentsContainerWin::RequestFocus() {
- // This is a hack to circumvent the fact that a view does not explicitly get
- // a call to set the focus if it already has the focus. This causes a problem
- // with tabs such as the TabContents that instruct the RenderView that it got
- // focus when they actually get the focus. When switching from one TabContents
- // tab that has focus to another TabContents tab that had focus, since the
- // TabContentsContainerView already has focus, Focus() would not be called and
- // the RenderView would not get notified it got focused.
- // By clearing the focused view before-hand, we ensure Focus() will be called.
- GetRootView()->FocusView(NULL);
+ // This is a hack to circumvent the fact that a the Focus() method is not
+ // invoked when RequestFocus() is called on an already focused view.
+ // The TabContentsContainer is the view focused when the TabContents has
+ // focus. When switching between from one tab that has focus to another tab
+ // that should also have focus, RequestFocus() is invoked one the
+ // TabContentsContainer. In order to make sure Focus() is invoked we need to
+ // clear the focus before hands.
+ GetFocusManager()->ClearFocus();
View::RequestFocus();
}
void NativeTabContentsContainerWin::AboutToRequestFocusFromTabTraversal(
bool reverse) {
- if (!container_->tab_contents())
- return;
- // Give an opportunity to the tab to reset its focus.
- if (container_->tab_contents()->interstitial_page()) {
- container_->tab_contents()->interstitial_page()->
- FocusThroughTabTraversal(reverse);
- return;
- }
container_->tab_contents()->FocusThroughTabTraversal(reverse);
}
diff --git a/chrome/browser/views/tab_contents/native_tab_contents_container_win.h b/chrome/browser/views/tab_contents/native_tab_contents_container_win.h
index 301c26b..5fb5700 100644
--- a/chrome/browser/views/tab_contents/native_tab_contents_container_win.h
+++ b/chrome/browser/views/tab_contents/native_tab_contents_container_win.h
@@ -20,11 +20,11 @@ class NativeTabContentsContainerWin : public NativeTabContentsContainer,
virtual void SetFastResize(bool fast_resize);
virtual void RenderViewHostChanged(RenderViewHost* old_host,
RenderViewHost* new_host);
+ virtual void TabContentsFocused(TabContents* tab_contents);
virtual views::View* GetView();
// Overridden from views::View:
virtual bool SkipDefaultKeyEventProcessing(const views::KeyEvent& e);
- virtual views::FocusTraversable* GetFocusTraversable();
virtual bool IsFocusable() const;
virtual void Focus();
virtual void RequestFocus();
diff --git a/chrome/browser/views/tab_contents/tab_contents_container.cc b/chrome/browser/views/tab_contents/tab_contents_container.cc
index 8ffe870..5e1d2b0 100644
--- a/chrome/browser/views/tab_contents/tab_contents_container.cc
+++ b/chrome/browser/views/tab_contents/tab_contents_container.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/views/tab_contents/tab_contents_container.h"
+#include "chrome/browser/tab_contents/interstitial_page.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/view_ids.h"
#include "chrome/browser/views/tab_contents/native_tab_contents_container.h"
@@ -38,6 +39,10 @@ void TabContentsContainer::ChangeTabContents(TabContents* contents) {
}
}
+void TabContentsContainer::TabContentsFocused(TabContents* tab_contents) {
+ native_container_->TabContentsFocused(tab_contents);
+}
+
void TabContentsContainer::SetFastResize(bool fast_resize) {
native_container_->SetFastResize(fast_resize);
}
diff --git a/chrome/browser/views/tab_contents/tab_contents_container.h b/chrome/browser/views/tab_contents/tab_contents_container.h
index aba2565..d7a8afe 100644
--- a/chrome/browser/views/tab_contents/tab_contents_container.h
+++ b/chrome/browser/views/tab_contents/tab_contents_container.h
@@ -5,9 +5,7 @@
#ifndef CHROME_BROWSER_VIEWS_TAB_CONTENTS_TAB_CONTENTS_CONTAINER_H_
#define CHROME_BROWSER_VIEWS_TAB_CONTENTS_TAB_CONTENTS_CONTAINER_H_
-#ifdef UNIT_TEST
#include "chrome/browser/views/tab_contents/native_tab_contents_container.h"
-#endif
#include "chrome/common/notification_registrar.h"
#include "views/view.h"
@@ -24,12 +22,13 @@ class TabContentsContainer : public views::View,
// Changes the TabContents associated with this view.
void ChangeTabContents(TabContents* contents);
+ View* GetFocusView() { return native_container_->GetView(); }
+
// Accessor for |tab_contents_|.
TabContents* tab_contents() const { return tab_contents_; }
-#ifdef UNIT_TEST
- View* GetFocusView() { return native_container_->GetView(); }
-#endif
+ // Called by the BrowserView to notify that |tab_contents| got the focus.
+ void TabContentsFocused(TabContents* tab_contents);
// Tells the container to update less frequently during resizing operations
// so performance is better.
@@ -42,8 +41,8 @@ class TabContentsContainer : public views::View,
// Overridden from views::View:
virtual void Layout();
- protected:
+ protected:
// Overridden from views::View:
virtual void ViewHierarchyChanged(bool is_add, views::View* parent,
views::View* child);
diff --git a/chrome/test/test_browser_window.h b/chrome/test/test_browser_window.h
index ccafcd6a..0e25938 100644
--- a/chrome/test/test_browser_window.h
+++ b/chrome/test/test_browser_window.h
@@ -66,6 +66,8 @@ class TestBrowserWindow : public BrowserWindow {
gfx::NativeWindow parent_window) {}
virtual void UserChangedTheme() {}
virtual int GetExtraRenderViewHeight() const { return 0; }
+ virtual void TabContentsFocused(TabContents* tab_contents) { }
+
protected:
virtual void DestroyBrowser() {}
diff --git a/views/controls/native/native_view_host_gtk.cc b/views/controls/native/native_view_host_gtk.cc
index 4b88067c..7f59144 100644
--- a/views/controls/native/native_view_host_gtk.cc
+++ b/views/controls/native/native_view_host_gtk.cc
@@ -71,8 +71,6 @@ void NativeViewHostGtk::NativeViewAttached() {
host_->Layout();
// TODO(port): figure out focus.
- // FocusManager::InstallFocusSubclass(
- // hwnd, associated_focus_view()_ ? associated_focus_view() : this);
}
void NativeViewHostGtk::NativeViewDetaching() {
diff --git a/views/controls/native/native_view_host_win.cc b/views/controls/native/native_view_host_win.cc
index 04c9edc..d1a5217 100644
--- a/views/controls/native/native_view_host_win.cc
+++ b/views/controls/native/native_view_host_win.cc
@@ -37,16 +37,9 @@ void NativeViewHostWin::NativeViewAttached() {
// Need to set the HWND's parent before changing its size to avoid flashing.
SetParent(host_->native_view(), host_->GetWidget()->GetNativeView());
host_->Layout();
-
- // Register with the focus manager so the associated view is focused when the
- // native control gets the focus.
- View* focus_view = host_->focus_view() ? host_->focus_view() : host_;
- FocusManager::InstallFocusSubclass(host_->native_view(), focus_view);
}
void NativeViewHostWin::NativeViewDetaching() {
- DCHECK(host_->native_view());
- FocusManager::UninstallFocusSubclass(host_->native_view());
installed_clip_ = false;
}
diff --git a/views/controls/native_control.cc b/views/controls/native_control.cc
index cbb375a..2df961e 100644
--- a/views/controls/native_control.cc
+++ b/views/controls/native_control.cc
@@ -81,8 +81,6 @@ class NativeControlContainer : public CWindowImpl<NativeControlContainer,
LRESULT OnCreate(LPCREATESTRUCT create_struct) {
control_ = parent_->CreateNativeControl(m_hWnd);
- FocusManager::InstallFocusSubclass(control_, parent_);
-
// We subclass the control hwnd so we get the WM_KEYDOWN messages.
WNDPROC original_handler =
win_util::SetWindowProc(control_,
@@ -367,6 +365,15 @@ LRESULT CALLBACK NativeControl::NativeControlWndProc(HWND window, UINT message,
if (message == WM_KEYDOWN && native_control->NotifyOnKeyDown()) {
if (native_control->OnKeyDown(static_cast<int>(w_param)))
return 0;
+ } else if (message == WM_SETFOCUS) {
+ // Let the focus manager know that the focus changed.
+ FocusManager* focus_manager =
+ FocusManager::GetFocusManager(native_control->GetNativeControlHWND());
+ if (focus_manager) {
+ focus_manager->SetFocusedView(native_control);
+ } else {
+ NOTREACHED();
+ }
} else if (message == WM_DESTROY) {
win_util::SetWindowProc(window,
reinterpret_cast<WNDPROC>(original_handler));
diff --git a/views/controls/native_control_win.cc b/views/controls/native_control_win.cc
index 2d53f28..b6111fd 100644
--- a/views/controls/native_control_win.cc
+++ b/views/controls/native_control_win.cc
@@ -7,6 +7,7 @@
#include "app/l10n_util_win.h"
#include "base/logging.h"
#include "base/win_util.h"
+#include "views/focus/focus_manager.h"
namespace views {
@@ -193,6 +194,15 @@ LRESULT NativeControlWin::NativeControlWndProc(HWND window,
if (message == WM_KEYDOWN && native_control->NotifyOnKeyDown()) {
if (native_control->OnKeyDown(static_cast<int>(w_param)))
return 0;
+ } else if (message == WM_SETFOCUS) {
+ // Let the focus manager know that the focus changed.
+ FocusManager* focus_manager =
+ FocusManager::GetFocusManager(native_control->native_view());
+ if (focus_manager) {
+ focus_manager->SetFocusedView(native_control->focus_view());
+ } else {
+ NOTREACHED();
+ }
} else if (message == WM_DESTROY) {
win_util::SetWindowProc(window, native_control->original_wndproc_);
}
diff --git a/views/controls/textfield/native_textfield_win.cc b/views/controls/textfield/native_textfield_win.cc
index ff20496..d2044a5 100644
--- a/views/controls/textfield/native_textfield_win.cc
+++ b/views/controls/textfield/native_textfield_win.cc
@@ -16,6 +16,7 @@
#include "views/controls/native/native_view_host.h"
#include "views/controls/textfield/native_textfield_win.h"
#include "views/controls/textfield/textfield.h"
+#include "views/focus/focus_manager.h"
#include "views/focus/focus_util_win.h"
#include "views/views_delegate.h"
#include "views/widget/widget.h"
@@ -667,6 +668,18 @@ void NativeTextfieldWin::OnPaste() {
}
}
+void NativeTextfieldWin::OnSetFocus(HWND hwnd) {
+ SetMsgHandled(FALSE); // We still want the default processing of the message.
+
+ views::FocusManager* focus_manager =
+ views::FocusManager::GetFocusManager(m_hWnd);
+ if (!focus_manager) {
+ NOTREACHED();
+ return;
+ }
+ focus_manager->SetFocusedView(textfield_);
+}
+
void NativeTextfieldWin::OnSysChar(TCHAR ch, UINT repeat_count, UINT flags) {
// Nearly all alt-<xxx> combos result in beeping rather than doing something
// useful, so we discard most. Exceptions:
diff --git a/views/controls/textfield/native_textfield_win.h b/views/controls/textfield/native_textfield_win.h
index 194614a..58034c0 100644
--- a/views/controls/textfield/native_textfield_win.h
+++ b/views/controls/textfield/native_textfield_win.h
@@ -74,6 +74,7 @@ class NativeTextfieldWin
MSG_WM_NCPAINT(OnNCPaint)
MSG_WM_RBUTTONDOWN(OnNonLButtonDown)
MSG_WM_PASTE(OnPaste)
+ MSG_WM_SETFOCUS(OnSetFocus)
MSG_WM_SYSCHAR(OnSysChar) // WM_SYSxxx == WM_xxx with ALT down
MSG_WM_SYSKEYDOWN(OnKeyDown)
END_MSG_MAP()
@@ -122,6 +123,7 @@ class NativeTextfieldWin
void OnNCPaint(HRGN region);
void OnNonLButtonDown(UINT keys, const CPoint& point);
void OnPaste();
+ void OnSetFocus(HWND hwnd);
void OnSysChar(TCHAR ch, UINT repeat_count, UINT flags);
// Helper function for OnChar() and OnKeyDown() that handles keystrokes that
diff --git a/views/focus/focus_manager.cc b/views/focus/focus_manager.cc
index 046d6ea..ab67301 100644
--- a/views/focus/focus_manager.cc
+++ b/views/focus/focus_manager.cc
@@ -71,10 +71,6 @@ static LRESULT CALLBACK FocusWindowCallback(HWND window, UINT message,
// but that window may not have an associated FocusManager.
if (focus_manager) {
switch (message) {
- case WM_SETFOCUS:
- if (!focus_manager->OnSetFocus(window))
- return 0;
- break;
case WM_NCDESTROY:
if (!focus_manager->OnNCDestroy(window))
return 0;
@@ -189,21 +185,6 @@ FocusManager::~FocusManager() {
#if defined(OS_WIN)
// Message handlers.
-bool FocusManager::OnSetFocus(HWND window) {
- if (ignore_set_focus_msg_)
- return true;
-
- // Focus the view associated with that window.
- View* v = static_cast<View*>(GetProp(window, kViewKey));
- if (v && v->IsFocusable()) {
- v->GetRootView()->FocusView(v);
- } else {
- SetFocusedView(NULL);
- }
-
- return true;
-}
-
bool FocusManager::OnNCDestroy(HWND window) {
// Window is being destroyed, undo the subclassing.
FocusManager::UninstallFocusSubclass(window);
diff --git a/views/focus/focus_manager.h b/views/focus/focus_manager.h
index 4c7f6ce..c5e2be9a 100644
--- a/views/focus/focus_manager.h
+++ b/views/focus/focus_manager.h
@@ -160,16 +160,6 @@ class FocusManager {
// The RootView specified should be the top RootView of the window.
// This also invokes InstallFocusSubclass.
static FocusManager* CreateFocusManager(HWND window, RootView* root_view);
-
- // Subclasses the specified window. The subclassed window procedure listens
- // for WM_SETFOCUS notification and keeps the FocusManager's focus owner
- // property in sync.
- // It's not necessary to explicitly invoke Uninstall, it's automatically done
- // when the window is destroyed and Uninstall wasn't invoked.
- static void InstallFocusSubclass(HWND window, View* view);
-
- // Uninstalls the window subclass installed by InstallFocusSubclass.
- static void UninstallFocusSubclass(HWND window);
#endif
static FocusManager* GetFocusManager(gfx::NativeView window);
@@ -294,6 +284,16 @@ class FocusManager {
private:
#if defined(OS_WIN)
explicit FocusManager(HWND root, RootView* root_view);
+
+ // Subclasses the specified window. The subclassed window procedure listens
+ // for WM_SETFOCUS notification and keeps the FocusManager's focus owner
+ // property in sync.
+ // It's not necessary to explicitly invoke Uninstall, it's automatically done
+ // when the window is destroyed and Uninstall wasn't invoked.
+ static void InstallFocusSubclass(HWND window, View* view);
+
+ // Uninstalls the window subclass installed by InstallFocusSubclass.
+ static void UninstallFocusSubclass(HWND window);
#endif
~FocusManager();
diff --git a/views/focus/focus_manager_unittest.cc b/views/focus/focus_manager_unittest.cc
index 95257ec..f4142db 100644
--- a/views/focus/focus_manager_unittest.cc
+++ b/views/focus/focus_manager_unittest.cc
@@ -699,6 +699,24 @@ class TestNativeButton : public NativeButton {
}
};
+class TestCheckbox : public Checkbox {
+ public:
+ explicit TestCheckbox(const std::wstring& text) : Checkbox(text) {
+ };
+ virtual HWND TestGetNativeControlHWND() {
+ return native_wrapper_->GetTestingHandle();
+ }
+};
+
+class TestRadioButton : public RadioButton {
+ public:
+ explicit TestRadioButton(const std::wstring& text) : RadioButton(text, 1) {
+ };
+ virtual HWND TestGetNativeControlHWND() {
+ return native_wrapper_->GetTestingHandle();
+ }
+};
+
class TestTextfield : public Textfield {
public:
TestTextfield() { }
@@ -719,11 +737,15 @@ class TestTabbedPane : public TabbedPane {
// FocusManager.
TEST_F(FocusManagerTest, FocusNativeControls) {
TestNativeButton* button = new TestNativeButton(L"Press me");
+ TestCheckbox* checkbox = new TestCheckbox(L"Checkbox");
+ TestRadioButton* radio_button = new TestRadioButton(L"RadioButton");
TestTextfield* textfield = new TestTextfield();
TestTabbedPane* tabbed_pane = new TestTabbedPane();
TestNativeButton* tab_button = new TestNativeButton(L"tab button");
content_view_->AddChildView(button);
+ content_view_->AddChildView(checkbox);
+ content_view_->AddChildView(radio_button);
content_view_->AddChildView(textfield);
content_view_->AddChildView(tabbed_pane);
tabbed_pane->AddTab(L"Awesome tab", tab_button);
@@ -732,6 +754,13 @@ TEST_F(FocusManagerTest, FocusNativeControls) {
::SendMessage(button->TestGetNativeControlHWND(), WM_SETFOCUS, NULL, NULL);
EXPECT_EQ(button, GetFocusManager()->GetFocusedView());
+ ::SendMessage(checkbox->TestGetNativeControlHWND(), WM_SETFOCUS, NULL, NULL);
+ EXPECT_EQ(checkbox, GetFocusManager()->GetFocusedView());
+
+ ::SendMessage(radio_button->TestGetNativeControlHWND(), WM_SETFOCUS,
+ NULL, NULL);
+ EXPECT_EQ(radio_button, GetFocusManager()->GetFocusedView());
+
::SendMessage(textfield->TestGetNativeComponent(), WM_SETFOCUS, NULL, NULL);
EXPECT_EQ(textfield, GetFocusManager()->GetFocusedView());
diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc
index 41c7309..7d8aced 100644
--- a/views/widget/widget_win.cc
+++ b/views/widget/widget_win.cc
@@ -189,10 +189,6 @@ void WidgetWin::Init(HWND parent, const gfx::Rect& bounds,
if (has_own_focus_manager) {
FocusManager::CreateFocusManager(hwnd_, GetRootView());
- } else {
- // Subclass the window so we get the tab key messages when a view with no
- // associated native window is focused.
- FocusManager::InstallFocusSubclass(hwnd_, NULL);
}
// Sets the RootView as a property, so the automation can introspect windows.