diff options
author | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-24 01:34:35 +0000 |
---|---|---|
committer | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-24 01:34:35 +0000 |
commit | 9649be09ca7396037a689efc706ad4fafa29b04b (patch) | |
tree | ef1cce9c266571c0c85c3c156a67013791a76d36 | |
parent | f125a763fcd2ad2fb91a97032c6a4eb96d0d845c (diff) | |
download | chromium_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.cc | 59 | ||||
-rw-r--r-- | views/focus/focus_manager_win.cc | 5 | ||||
-rw-r--r-- | views/widget/widget_win.cc | 34 | ||||
-rw-r--r-- | views/widget/widget_win.h | 3 |
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; } |