summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-24 01:34:35 +0000
committerjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-24 01:34:35 +0000
commit9649be09ca7396037a689efc706ad4fafa29b04b (patch)
treeef1cce9c266571c0c85c3c156a67013791a76d36
parentf125a763fcd2ad2fb91a97032c6a4eb96d0d845c (diff)
downloadchromium_src-9649be09ca7396037a689efc706ad4fafa29b04b.zip
chromium_src-9649be09ca7396037a689efc706ad4fafa29b04b.tar.gz
chromium_src-9649be09ca7396037a689efc706ad4fafa29b04b.tar.bz2
Landing Marshall Greenblatt change.
See review at: http://codereview.chromium.org/609010/show BUG=None TEST=None Review URL: http://codereview.chromium.org/657019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@39827 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--views/focus/focus_manager_unittest.cc59
-rw-r--r--views/focus/focus_manager_win.cc5
-rw-r--r--views/widget/widget_win.cc34
-rw-r--r--views/widget/widget_win.h3
4 files changed, 93 insertions, 8 deletions
diff --git a/views/focus/focus_manager_unittest.cc b/views/focus/focus_manager_unittest.cc
index 548989a..6a5dba3 100644
--- a/views/focus/focus_manager_unittest.cc
+++ b/views/focus/focus_manager_unittest.cc
@@ -1306,4 +1306,63 @@ TEST_F(FocusManagerTest, IgnoreKeyupForAccelerators) {
}
#endif
+#if defined(OS_WIN)
+// Test that the focus manager is created successfully for the first view
+// window parented to a native dialog.
+TEST_F(FocusManagerTest, CreationForNativeRoot) {
+ // Create a window class.
+ WNDCLASSEX class_ex;
+ memset(&class_ex, 0, sizeof(class_ex));
+ class_ex.cbSize = sizeof(WNDCLASSEX);
+ class_ex.lpfnWndProc = &DefWindowProc;
+ class_ex.lpszClassName = L"TestWindow";
+ ATOM atom = RegisterClassEx(&class_ex);
+ ASSERT_TRUE(atom);
+
+ // Create a native dialog window.
+ HWND hwnd = CreateWindowEx(0, class_ex.lpszClassName, NULL,
+ WS_OVERLAPPEDWINDOW, 0, 0, 200, 200,
+ NULL, NULL, NULL, NULL);
+ ASSERT_TRUE(hwnd);
+
+ // Create a view window parented to native dialog.
+ WidgetWin window1;
+ window1.set_delete_on_destroy(false);
+ window1.set_window_style(WS_CHILD);
+ window1.Init(hwnd, gfx::Rect(0, 0, 100, 100));
+
+ // Get the focus manager directly from the first window. Should exist
+ // because the first window is the root widget.
+ views::FocusManager* focus_manager_member1 = window1.GetFocusManager();
+ EXPECT_TRUE(focus_manager_member1);
+
+ // Create another view window parented to the first view window.
+ WidgetWin window2;
+ window2.set_delete_on_destroy(false);
+ window2.set_window_style(WS_CHILD);
+ window2.Init(window1.GetNativeView(), gfx::Rect(0, 0, 100, 100));
+
+ // Get the focus manager directly from the second window. Should return the
+ // first window's focus manager.
+ views::FocusManager* focus_manager_member2 = window2.GetFocusManager();
+ EXPECT_EQ(focus_manager_member2, focus_manager_member1);
+
+ // Get the focus manager indirectly using the first window handle. Should
+ // return the first window's focus manager.
+ views::FocusManager* focus_manager_indirect =
+ views::FocusManager::GetFocusManagerForNativeView(
+ window1.GetNativeView());
+ EXPECT_EQ(focus_manager_indirect, focus_manager_member1);
+
+ // Get the focus manager indirectly using the second window handle. Should
+ // return the first window's focus manager.
+ focus_manager_indirect =
+ views::FocusManager::GetFocusManagerForNativeView(
+ window2.GetNativeView());
+ EXPECT_EQ(focus_manager_indirect, focus_manager_member1);
+
+ DestroyWindow(hwnd);
+}
+#endif
+
} // namespace views
diff --git a/views/focus/focus_manager_win.cc b/views/focus/focus_manager_win.cc
index a073a4c..fbccf7b 100644
--- a/views/focus/focus_manager_win.cc
+++ b/views/focus/focus_manager_win.cc
@@ -23,10 +23,7 @@ void FocusManager::FocusNativeView(gfx::NativeView native_view) {
// static
FocusManager* FocusManager::GetFocusManagerForNativeView(
gfx::NativeView native_view) {
- HWND root = ::GetAncestor(native_view, GA_ROOT);
- if (!root)
- return NULL;
- WidgetWin* widget = WidgetWin::GetWidget(root);
+ WidgetWin* widget = WidgetWin::GetRootWidget(native_view);
return widget ? widget->GetFocusManager() : NULL;
}
diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc
index ea54036..8a97b34 100644
--- a/views/widget/widget_win.cc
+++ b/views/widget/widget_win.cc
@@ -67,6 +67,31 @@ WidgetWin* WidgetWin::GetWidget(HWND hwnd) {
return reinterpret_cast<WidgetWin*>(win_util::GetWindowUserData(hwnd));
}
+// static
+WidgetWin* WidgetWin::GetRootWidget(HWND hwnd) {
+ // First, check if the top-level window is a Widget.
+ HWND root = ::GetAncestor(hwnd, GA_ROOT);
+ if (!root)
+ return NULL;
+
+ WidgetWin* widget = WidgetWin::GetWidget(root);
+ if (widget)
+ return widget;
+
+ // Second, try to locate the last Widget window in the parent hierarchy.
+ HWND parent_hwnd = hwnd;
+ WidgetWin* parent_widget;
+ do {
+ parent_widget = WidgetWin::GetWidget(parent_hwnd);
+ if (parent_widget) {
+ widget = parent_widget;
+ parent_hwnd = ::GetAncestor(parent_hwnd, GA_PARENT);
+ }
+ } while (parent_hwnd != NULL && parent_widget != NULL);
+
+ return widget;
+}
+
void WidgetWin::SetUseLayeredBuffer(bool use_layered_buffer) {
if (use_layered_buffer_ == use_layered_buffer)
return;
@@ -103,8 +128,10 @@ void WidgetWin::Init(gfx::NativeView parent, const gfx::Rect& bounds) {
drop_target_ = new DropTargetWin(root_view_.get());
- if ((window_style() & WS_CHILD) == 0) {
- // Top-level widgets get a FocusManager.
+ if ((window_style() & WS_CHILD) == 0 ||
+ WidgetWin::GetRootWidget(parent) == NULL) {
+ // Top-level widgets and child widgets who do not have a top-level widget
+ // ancestor get a FocusManager.
focus_manager_.reset(new FocusManager(this));
}
@@ -296,8 +323,7 @@ RootView* WidgetWin::GetRootView() {
}
Widget* WidgetWin::GetRootWidget() const {
- return reinterpret_cast<WidgetWin*>(
- win_util::GetWindowUserData(GetAncestor(hwnd(), GA_ROOT)));
+ return GetRootWidget(hwnd());
}
bool WidgetWin::IsVisible() const {
diff --git a/views/widget/widget_win.h b/views/widget/widget_win.h
index ed233d4..b8246da 100644
--- a/views/widget/widget_win.h
+++ b/views/widget/widget_win.h
@@ -76,6 +76,9 @@ class WidgetWin : public app::WindowImpl,
// Returns the Widget associated with the specified HWND (if any).
static WidgetWin* GetWidget(HWND hwnd);
+ // Returns the root Widget associated with the specified HWND (if any).
+ static WidgetWin* GetRootWidget(HWND hwnd);
+
void set_delete_on_destroy(bool delete_on_destroy) {
delete_on_destroy_ = delete_on_destroy;
}