diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-02 01:13:38 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-02 01:13:38 +0000 |
commit | d8d70b1414befb63913ada0abfc135eafd97a8a1 (patch) | |
tree | 3d4a290b8121549acfd8aefbb01170624726ab78 | |
parent | b472d4f576eb17916ab3444218dcb4586f60a247 (diff) | |
download | chromium_src-d8d70b1414befb63913ada0abfc135eafd97a8a1.zip chromium_src-d8d70b1414befb63913ada0abfc135eafd97a8a1.tar.gz chromium_src-d8d70b1414befb63913ada0abfc135eafd97a8a1.tar.bz2 |
Remove/replace RootView/Widget getters with new NativeWidget getters.
BUG=72040
TEST=existing unittests.
Review URL: http://codereview.chromium.org/6598069
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76483 0039d316-1c4b-4281-b951-d872f2087c98
29 files changed, 475 insertions, 360 deletions
diff --git a/chrome/browser/automation/testing_automation_provider_views.cc b/chrome/browser/automation/testing_automation_provider_views.cc index 99b4065..01fedb8 100644 --- a/chrome/browser/automation/testing_automation_provider_views.cc +++ b/chrome/browser/automation/testing_automation_provider_views.cc @@ -13,6 +13,7 @@ #include "ui/gfx/point.h" #include "views/controls/menu/menu_wrapper.h" #include "views/view.h" +#include "views/widget/native_widget.h" #include "views/widget/root_view.h" #include "views/widget/widget.h" @@ -121,8 +122,10 @@ void TestingAutomationProvider::WindowGetViewBounds(int handle, if (window_tracker_->ContainsHandle(handle)) { gfx::NativeWindow window = window_tracker_->GetResource(handle); - views::RootView* root_view = views::Widget::FindRootView(window); - if (root_view) { + views::NativeWidget* native_widget = + views::NativeWidget::GetNativeWidgetForNativeWindow(window); + if (native_widget) { + views::View* root_view = native_widget->GetWidget()->GetRootView(); views::View* view = root_view->GetViewByID(view_id); if (view) { *success = true; diff --git a/chrome/browser/bookmarks/bookmark_utils.cc b/chrome/browser/bookmarks/bookmark_utils.cc index 80d2bf0..eb75b1b 100644 --- a/chrome/browser/bookmarks/bookmark_utils.cc +++ b/chrome/browser/bookmarks/bookmark_utils.cc @@ -40,7 +40,7 @@ #include "ui/base/dragdrop/os_exchange_data.h" #include "views/drag_utils.h" #include "views/events/event.h" -#include "views/widget/root_view.h" +#include "views/widget/native_widget.h" #include "views/widget/widget.h" #elif defined(TOOLKIT_GTK) #include "chrome/browser/ui/gtk/custom_drag.h" @@ -335,10 +335,13 @@ void DragBookmarks(Profile* profile, bool was_nested = MessageLoop::current()->IsNested(); MessageLoop::current()->SetNestableTasksAllowed(true); - views::Widget* widget = views::Widget::GetWidgetFromNativeView(view); - widget->StartDragForViewFromMouseEvent(NULL, data, - ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE | - ui::DragDropTypes::DRAG_LINK); + views::NativeWidget* native_widget = + views::NativeWidget::GetNativeWidgetForNativeView(view); + if (native_widget) { + native_widget->GetWidget()->StartDragForViewFromMouseEvent(NULL, data, + ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE | + ui::DragDropTypes::DRAG_LINK); + } MessageLoop::current()->SetNestableTasksAllowed(was_nested); #elif defined(OS_MACOSX) diff --git a/chrome/browser/chromeos/setting_level_bubble.cc b/chrome/browser/chromeos/setting_level_bubble.cc index 55aec2e..6633ab8 100644 --- a/chrome/browser/chromeos/setting_level_bubble.cc +++ b/chrome/browser/chromeos/setting_level_bubble.cc @@ -45,14 +45,10 @@ static views::Widget* GetToplevelWidget() { if (!browser) return NULL; - views::RootView* root = - views::Widget::FindRootView( + views::NativeWidget* native_widget = + views::NativeWidget::GetNativeWidgetForNativeWindow( GTK_WINDOW(browser->window()->GetNativeHandle())); - DCHECK(root); - if (!root) - return NULL; - - return root->GetWidget(); + return native_widget->GetWidget(); } SettingLevelBubble::SettingLevelBubble(SkBitmap* increase_icon, diff --git a/chrome/browser/download/download_util.cc b/chrome/browser/download/download_util.cc index 215997f..ae0f398 100644 --- a/chrome/browser/download/download_util.cc +++ b/chrome/browser/download/download_util.cc @@ -540,7 +540,8 @@ void DragDownload(const DownloadItem* download, GtkWidget* root = gtk_widget_get_toplevel(view); if (!root) return; - views::WidgetGtk* widget = views::WidgetGtk::GetViewForNative(root); + views::WidgetGtk* widget = static_cast<views::WidgetGtk*>( + views::NativeWidget::GetNativeWidgetForNativeView(root)); if (!widget) return; diff --git a/chrome/browser/speech/speech_input_bubble_views.cc b/chrome/browser/speech/speech_input_bubble_views.cc index 6abe5d5..37f53bc 100644 --- a/chrome/browser/speech/speech_input_bubble_views.cc +++ b/chrome/browser/speech/speech_input_bubble_views.cc @@ -281,12 +281,11 @@ void SpeechInputBubbleImpl::Show() { bubble_content_ = new ContentView(delegate_); UpdateLayout(); - views::Widget* tab = views::Widget::GetWidgetFromNativeView( - tab_contents()->view()->GetNativeView()); - views::Widget* parent = tab ? tab->GetRootWidget() : NULL; - - if (parent) { - info_bubble_ = InfoBubble::Show(parent, + views::NativeWidget* toplevel_widget = + views::NativeWidget::GetTopLevelNativeWidget( + tab_contents()->view()->GetNativeView()); + if (toplevel_widget) { + info_bubble_ = InfoBubble::Show(toplevel_widget->GetWidget(), GetInfoBubbleTarget(element_rect_), BubbleBorder::TOP_LEFT, bubble_content_, this); diff --git a/chrome/browser/ui/views/find_bar_host_gtk.cc b/chrome/browser/ui/views/find_bar_host_gtk.cc index bacb9d8..c0819df 100644 --- a/chrome/browser/ui/views/find_bar_host_gtk.cc +++ b/chrome/browser/ui/views/find_bar_host_gtk.cc @@ -18,7 +18,7 @@ void FindBarHost::AudibleAlert() { void FindBarHost::GetWidgetPositionNative(gfx::Rect* avoid_overlapping_rect) { gfx::Rect frame_rect, webcontents_rect; - host()->GetRootWidget()->GetBounds(&frame_rect, true); + host()->GetTopLevelWidget()->GetBounds(&frame_rect, true); TabContentsView* tab_view = find_bar_controller_->tab_contents()->view(); tab_view->GetViewBounds(&webcontents_rect); avoid_overlapping_rect->Offset(0, webcontents_rect.y() - frame_rect.y()); diff --git a/views/controls/native/native_view_host.cc b/views/controls/native/native_view_host.cc index 9b6dff2..162b1f6 100644 --- a/views/controls/native/native_view_host.cc +++ b/views/controls/native/native_view_host.cc @@ -8,7 +8,7 @@ #include "ui/gfx/canvas.h" #include "views/controls/native/native_view_host_wrapper.h" #include "views/controls/native/native_view_host_views.h" -#include "views/widget/root_view.h" +#include "views/widget/native_widget.h" #include "views/widget/widget.h" namespace views { @@ -188,12 +188,12 @@ bool NativeViewHost::ContainsNativeView(gfx::NativeView native_view) const { if (!native_view_) return false; - views::Widget* native_widget = - views::Widget::GetWidgetFromNativeView(native_view_); - views::RootView* root_view = - native_widget ? native_widget->GetRootView() : NULL; - if (root_view && root_view->ContainsNativeView(native_view)) + views::NativeWidget* native_widget = + views::NativeWidget::GetNativeWidgetForNativeView(native_view_); + if (native_widget && + native_widget->GetWidget()->ContainsNativeView(native_view)) { return true; + } return View::ContainsNativeView(native_view); } diff --git a/views/controls/native/native_view_host_win.cc b/views/controls/native/native_view_host_win.cc index 88feac7..dbb8461 100644 --- a/views/controls/native/native_view_host_win.cc +++ b/views/controls/native/native_view_host_win.cc @@ -8,6 +8,7 @@ #include "ui/gfx/canvas.h" #include "views/controls/native/native_view_host.h" #include "views/focus/focus_manager.h" +#include "views/widget/native_widget.h" #include "views/widget/root_view.h" #include "views/widget/widget.h" @@ -37,13 +38,13 @@ 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(); - // Notify children that parent changed, so they could adjust the focus - std::vector<RootView*> root_views; - Widget::FindAllRootViews(host_->native_view(), &root_views); - for (std::vector<RootView*>::iterator it = root_views.begin(); - it < root_views.end(); - ++it) { - (*it)->NotifyNativeViewHierarchyChanged(true, + // Notify children that parent changed, so they can adjust focus. + NativeWidget::NativeWidgets widgets; + NativeWidget::GetAllNativeWidgets(host_->native_view(), &widgets); + for (NativeWidget::NativeWidgets::iterator it = widgets.begin(); + it != widgets.end(); ++it) { + (*it)->GetWidget()->GetRootView()->NotifyNativeViewHierarchyChanged( + true, host_->GetWidget()->GetNativeView()); } } @@ -52,13 +53,13 @@ void NativeViewHostWin::NativeViewDetaching(bool destroyed) { if (!destroyed && installed_clip_) UninstallClip(); installed_clip_ = false; - // Notify children that parent is removed - std::vector<RootView*> root_views; - Widget::FindAllRootViews(host_->native_view(), &root_views); - for (std::vector<RootView*>::iterator it = root_views.begin(); - it < root_views.end(); - ++it) { - (*it)->NotifyNativeViewHierarchyChanged(false, + // Notify children that parent is removed. + NativeWidget::NativeWidgets widgets; + NativeWidget::GetAllNativeWidgets(host_->native_view(), &widgets); + for (NativeWidget::NativeWidgets::iterator it = widgets.begin(); + it != widgets.end(); ++it) { + (*it)->GetWidget()->GetRootView()->NotifyNativeViewHierarchyChanged( + false, host_->GetWidget()->GetNativeView()); } } diff --git a/views/controls/tabbed_pane/native_tabbed_pane_gtk.cc b/views/controls/tabbed_pane/native_tabbed_pane_gtk.cc index 02d5fe6..50b62c6 100644 --- a/views/controls/tabbed_pane/native_tabbed_pane_gtk.cc +++ b/views/controls/tabbed_pane/native_tabbed_pane_gtk.cc @@ -64,7 +64,8 @@ View* NativeTabbedPaneGtk::RemoveTabAtIndex(int index) { GtkWidget* page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(native_view()), index); - WidgetGtk* widget = WidgetGtk::GetViewForNative(page); + WidgetGtk* widget = + static_cast<WidgetGtk*>(NativeWidget::GetNativeWidgetForNativeView(page)); // detach the content view from widget so that we can delete widget // without destroying the content view. @@ -194,7 +195,8 @@ WidgetGtk* NativeTabbedPaneGtk::GetWidgetAt(int index) { DCHECK(index <= GetTabCount()); GtkWidget* page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(native_view()), index); - WidgetGtk* widget = WidgetGtk::GetViewForNative(page); + WidgetGtk* widget = + static_cast<WidgetGtk*>(NativeWidget::GetNativeWidgetForNativeView(page)); DCHECK(widget); return widget; } diff --git a/views/focus/accelerator_handler_touch.cc b/views/focus/accelerator_handler_touch.cc index d4b072a..389fe7d 100644 --- a/views/focus/accelerator_handler_touch.cc +++ b/views/focus/accelerator_handler_touch.cc @@ -31,13 +31,13 @@ RootView* FindRootViewForGdkWindow(GdkWindow* gdk_window) { DLOG(WARNING) << "no GtkWidget found for that GdkWindow"; return NULL; } - WidgetGtk* widget_gtk = WidgetGtk::GetViewForNative(gtk_widget); - if (!widget_gtk) { + NativeWidget* widget = NativeWidget::GetNativeWidgetForNativeView(gtk_widget); + if (!widget) { DLOG(WARNING) << "no WidgetGtk found for that GtkWidget"; return NULL; } - return widget_gtk->GetRootView(); + return widget->GetWidget()->GetRootView(); } #if defined(HAVE_XINPUT2) diff --git a/views/focus/focus_manager_gtk.cc b/views/focus/focus_manager_gtk.cc index 6e9dbcf..327c785 100644 --- a/views/focus/focus_manager_gtk.cc +++ b/views/focus/focus_manager_gtk.cc @@ -28,7 +28,7 @@ FocusManager* FocusManager::GetFocusManagerForNativeView( if (!root || !GTK_WIDGET_TOPLEVEL(root)) return NULL; - WidgetGtk* widget = WidgetGtk::GetViewForNative(root); + NativeWidget* widget = NativeWidget::GetNativeWidgetForNativeView(root); if (!widget) { // TODO(jcampan): http://crbug.com/21378 Reenable this NOTREACHED() when the // options page is only based on views. @@ -36,7 +36,7 @@ FocusManager* FocusManager::GetFocusManagerForNativeView( NOTIMPLEMENTED(); return NULL; } - FocusManager* focus_manager = widget->GetFocusManager(); + FocusManager* focus_manager = widget->GetWidget()->GetFocusManager(); DCHECK(focus_manager) << "no FocusManager for top level Widget"; return focus_manager; } diff --git a/views/focus/focus_manager_win.cc b/views/focus/focus_manager_win.cc index faf3815..d6f1e02 100644 --- a/views/focus/focus_manager_win.cc +++ b/views/focus/focus_manager_win.cc @@ -23,8 +23,10 @@ void FocusManager::FocusNativeView(gfx::NativeView native_view) { // static FocusManager* FocusManager::GetFocusManagerForNativeView( gfx::NativeView native_view) { - WidgetWin* widget = WidgetWin::GetRootWidget(native_view); - return widget ? widget->GetFocusManager() : NULL; + // TODO(beng): This method probably isn't necessary. + views::NativeWidget* native_widget = + views::NativeWidget::GetTopLevelNativeWidget(native_view); + return native_widget ? native_widget->GetWidget()->GetFocusManager() : NULL; } // static diff --git a/views/test/views_test_base.h b/views/test/views_test_base.h index 080eca5..d66a1d8 100644 --- a/views/test/views_test_base.h +++ b/views/test/views_test_base.h @@ -10,6 +10,10 @@ #include "base/message_loop.h" +#if defined(OS_WIN) +#include <ole2.h> +#endif + namespace views { // A base class for views unit test. It creates a message loop necessary diff --git a/views/view_unittest.cc b/views/view_unittest.cc index 8207c76b..16109f7 100644 --- a/views/view_unittest.cc +++ b/views/view_unittest.cc @@ -1439,33 +1439,22 @@ class TestChangeNativeViewHierarchy { view_test_->RunPendingMessages(); } - void CheckEnumeratingRootViews() { - std::vector<RootView*> enumerated_root_views; -#if defined(OS_WIN) - views::Widget::FindAllRootViews(host_->GetNativeView(), - &enumerated_root_views); -#else - // host_->GetNativeView() returns gfx::NativeView which is GtkWidget on - // systems other than Windows and views::Widget::FindAllRootViews() - // requires GtkWindow. - if (host_->GetWindow()) { - views::Widget::FindAllRootViews(host_->GetWindow()->GetNativeWindow(), - &enumerated_root_views); - } else { + void CheckEnumeratingNativeWidgets() { + if (!host_->GetWindow()) return; - } -#endif - EXPECT_EQ(TestNativeViewHierarchy::kTotalViews + 1, - enumerated_root_views.size()); + NativeWidget::NativeWidgets widgets; + NativeWidget::GetAllNativeWidgets(host_->GetNativeView(), &widgets); + EXPECT_EQ(TestNativeViewHierarchy::kTotalViews + 1, widgets.size()); // Unfortunately there is no guarantee the sequence of views here so always // go through all of them. - for (std::vector<RootView*>::iterator i = enumerated_root_views.begin(); - i != enumerated_root_views.end(); ++i) { - if (host_->GetRootView() == *i) + for (NativeWidget::NativeWidgets::iterator i = widgets.begin(); + i != widgets.end(); ++i) { + RootView* root_view = (*i)->GetWidget()->GetRootView(); + if (host_->GetRootView() == root_view) continue; size_t j; for (j = 0; j < TestNativeViewHierarchy::kTotalViews; ++j) - if (root_views_[j] == *i) + if (root_views_[j] == root_view) break; // EXPECT_LT/GT/GE() fails to compile with class-defined constants // with gcc, with error @@ -1509,7 +1498,7 @@ TEST_F(ViewTest, ChangeNativeViewHierarchyFindRoots) { // TODO(georgey): Fix the test for Linux #if defined(OS_WIN) TestChangeNativeViewHierarchy test(this); - test.CheckEnumeratingRootViews(); + test.CheckEnumeratingNativeWidgets(); #endif } diff --git a/views/views.gyp b/views/views.gyp index f81e669..a8c1fa3 100644 --- a/views/views.gyp +++ b/views/views.gyp @@ -489,6 +489,10 @@ 'run_all_unittests.cc', 'test/test_views_delegate.h', 'view_unittest.cc', + 'widget/native_widget_test_utils.h', + 'widget/native_widget_test_utils_gtk.cc', + 'widget/native_widget_test_utils_win.cc', + 'widget/native_widget_unittest.cc', 'widget/widget_win_unittest.cc', 'window/window_win_unittest.cc', diff --git a/views/widget/native_widget.h b/views/widget/native_widget.h index 2700f8c..dffbf93 100644 --- a/views/widget/native_widget.h +++ b/views/widget/native_widget.h @@ -6,8 +6,11 @@ #define VIEWS_WIDGET_NATIVE_WIDGET_H_ #pragma once +#include <set> + namespace views { -namespace internal { + +class Widget; //////////////////////////////////////////////////////////////////////////////// // NativeWidget interface @@ -18,9 +21,30 @@ namespace internal { class NativeWidget { public: virtual ~NativeWidget() {} + + // Retrieves the NativeWidget implementation associated with the given + // NativeView or Window, or NULL if the supplied handle has no associated + // NativeView. + static NativeWidget* GetNativeWidgetForNativeView( + gfx::NativeView native_view); + static NativeWidget* GetNativeWidgetForNativeWindow( + gfx::NativeWindow native_window); + + // Retrieves the top NativeWidget in the hierarchy containing the given + // NativeView, or NULL if there is no NativeWidget that contains it. + static NativeWidget* GetTopLevelNativeWidget(gfx::NativeView native_view); + + // Returns all NativeWidgets in |native_view|'s hierarchy, including itself if + // it is one. + typedef std::set<NativeWidget*> NativeWidgets; + static void GetAllNativeWidgets(gfx::NativeView native_view, + NativeWidgets* children); + + // Returns the Widget associated with this NativeWidget. This function is + // guaranteed to return non-NULL for the lifetime of the NativeWidget. + virtual Widget* GetWidget() = 0; }; -} // namespace internal } // namespace views #endif // VIEWS_WIDGET_NATIVE_WIDGET_H_ diff --git a/views/widget/native_widget_test_utils.h b/views/widget/native_widget_test_utils.h new file mode 100644 index 0000000..ac3e5b4 --- /dev/null +++ b/views/widget/native_widget_test_utils.h @@ -0,0 +1,22 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef VIEWS_WIDGET_NATIVE_WIDGET_TEST_UTILS_H_ +#define VIEWS_WIDGET_NATIVE_WIDGET_TEST_UTILS_H_ +#pragma once + +namespace views { +class View; +class NativeWidget; +namespace internal { + +// Create dummy Widgets for use in testing. +NativeWidget* CreateNativeWidget(); +NativeWidget* CreateNativeWidgetWithContents(View* contents_view); +NativeWidget* CreateNativeWidgetWithParent(NativeWidget* parent); + +} // namespace internal +} // namespace views + +#endif // VIEWS_WIDGET_NATIVE_WIDGET_TEST_UTILS_H_ diff --git a/views/widget/native_widget_test_utils_gtk.cc b/views/widget/native_widget_test_utils_gtk.cc new file mode 100644 index 0000000..43c0279 --- /dev/null +++ b/views/widget/native_widget_test_utils_gtk.cc @@ -0,0 +1,33 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "views/widget/native_widget_test_utils.h" + +#include "views/view.h" +#include "views/widget/widget_gtk.h" + +namespace views { +namespace internal { + +NativeWidget* CreateNativeWidget() { + return CreateNativeWidgetWithContents(new View); +} + +NativeWidget* CreateNativeWidgetWithContents(View* contents_view) { + WidgetGtk* widget = new WidgetGtk(WidgetGtk::TYPE_WINDOW); + widget->set_delete_on_destroy(false); + widget->Init(NULL, gfx::Rect(10, 10, 200, 200)); + return widget; +} + +NativeWidget* CreateNativeWidgetWithParent(NativeWidget* parent) { + WidgetGtk* widget = new WidgetGtk(WidgetGtk::TYPE_CHILD); + widget->set_delete_on_destroy(false); + widget->Init(parent ? parent->GetWidget()->GetNativeView() : NULL, + gfx::Rect(10, 10, 200, 200)); + return widget; +} + +} // namespace internal +} // namespace ui diff --git a/views/widget/native_widget_test_utils_win.cc b/views/widget/native_widget_test_utils_win.cc new file mode 100644 index 0000000..2d016e9 --- /dev/null +++ b/views/widget/native_widget_test_utils_win.cc @@ -0,0 +1,33 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "views/widget/native_widget_test_utils.h" + +#include "views/view.h" +#include "views/widget/widget_win.h" + +namespace views { +namespace internal { + +NativeWidget* CreateNativeWidget() { + return CreateNativeWidgetWithContents(new View); +} + +NativeWidget* CreateNativeWidgetWithContents(View* contents_view) { + WidgetWin* widget = new WidgetWin; + widget->set_delete_on_destroy(false); + widget->Init(NULL, gfx::Rect(10, 10, 200, 200)); + return widget; +} + +NativeWidget* CreateNativeWidgetWithParent(NativeWidget* parent) { + WidgetWin* widget = new WidgetWin; + widget->set_delete_on_destroy(false); + widget->Init(parent ? parent->GetWidget()->GetNativeView() : NULL, + gfx::Rect(10, 10, 200, 200)); + return widget; +} + +} // namespace internal +} // namespace ui diff --git a/views/widget/native_widget_unittest.cc b/views/widget/native_widget_unittest.cc new file mode 100644 index 0000000..91c29a3 --- /dev/null +++ b/views/widget/native_widget_unittest.cc @@ -0,0 +1,81 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "testing/gtest/include/gtest/gtest.h" +#include "views/test/views_test_base.h" +#include "views/view.h" +#include "views/controls/native/native_view_host.h" +#include "views/widget/native_widget.h" +#include "views/widget/widget.h" +#include "views/widget/native_widget_test_utils.h" + +#if defined(TOOLKIT_USES_GTK) +#include "views/widget/widget_gtk.h" +#endif + +namespace views { + +class ScopedTestWidget { + public: + ScopedTestWidget(NativeWidget* native_widget) + : native_widget_(native_widget) { + } + ~ScopedTestWidget() { + native_widget_->GetWidget()->CloseNow(); + } + + NativeWidget* operator->() const { + return native_widget_.get(); + } + NativeWidget* get() const { return native_widget_.get(); } + + private: + scoped_ptr<NativeWidget> native_widget_; + DISALLOW_COPY_AND_ASSIGN(ScopedTestWidget); +}; + +class NativeWidgetTest : public ViewsTestBase { + public: + NativeWidgetTest() {} + virtual ~NativeWidgetTest() {} + + private: + DISALLOW_COPY_AND_ASSIGN(NativeWidgetTest); +}; + +TEST_F(NativeWidgetTest, CreateNativeWidget) { + ScopedTestWidget widget(internal::CreateNativeWidget()); + EXPECT_TRUE(widget->GetWidget()->GetNativeView() != NULL); +} + +TEST_F(NativeWidgetTest, GetNativeWidgetForNativeView) { + ScopedTestWidget widget(internal::CreateNativeWidget()); + EXPECT_EQ(widget.get(), + NativeWidget::GetNativeWidgetForNativeView( + widget->GetWidget()->GetNativeView())); +} + +// |widget| has the toplevel NativeWidget. +TEST_F(NativeWidgetTest, GetTopLevelNativeWidget1) { + ScopedTestWidget widget(internal::CreateNativeWidget()); + EXPECT_EQ(widget.get(), + NativeWidget::GetTopLevelNativeWidget( + widget->GetWidget()->GetNativeView())); +} + +// |toplevel_widget| has the toplevel NativeWidget. +TEST_F(NativeWidgetTest, GetTopLevelNativeWidget2) { + ScopedTestWidget child_widget(internal::CreateNativeWidgetWithParent(NULL)); + ScopedTestWidget toplevel_widget(internal::CreateNativeWidget()); + + NativeViewHost* child_host = new NativeViewHost; + toplevel_widget->GetWidget()->SetContentsView(child_host); + child_host->Attach(child_widget->GetWidget()->GetNativeView()); + + EXPECT_EQ(toplevel_widget.get(), + NativeWidget::GetTopLevelNativeWidget( + child_widget->GetWidget()->GetNativeView())); +} + +} // namespace views diff --git a/views/widget/widget.cc b/views/widget/widget.cc index 0299c2d..c280206 100644 --- a/views/widget/widget.cc +++ b/views/widget/widget.cc @@ -7,6 +7,7 @@ #include "base/logging.h" #include "views/widget/default_theme_provider.h" #include "views/widget/root_view.h" +#include "views/widget/native_widget.h" namespace views { @@ -28,6 +29,17 @@ void Widget::Init(gfx::NativeView parent, const gfx::Rect& bounds) { void Widget::InitWithWidget(Widget* parent, const gfx::Rect& bounds) { } +Widget* Widget::GetTopLevelWidget() { + return const_cast<Widget*>( + const_cast<const Widget*>(this)->GetTopLevelWidget()); +} + +const Widget* Widget::GetTopLevelWidget() const { + NativeWidget* native_widget = + NativeWidget::GetTopLevelNativeWidget(GetNativeView()); + return native_widget ? native_widget->GetWidget() : NULL; +} + WidgetDelegate* Widget::GetWidgetDelegate() { return delegate_; } @@ -82,10 +94,6 @@ RootView* Widget::GetRootView() { return root_view_.get(); } -Widget* Widget::GetRootWidget() const { - return NULL; -} - bool Widget::IsVisible() const { return false; } diff --git a/views/widget/widget.h b/views/widget/widget.h index 89e9061..b1860d1 100644 --- a/views/widget/widget.h +++ b/views/widget/widget.h @@ -29,16 +29,13 @@ using ui::ThemeProvider; namespace views { class DefaultThemeProvider; +class NativeWidget; class RootView; class TooltipManager; class View; class WidgetDelegate; class Window; -namespace internal { -class NativeWidget; -} - //////////////////////////////////////////////////////////////////////////////// // Widget class // @@ -91,21 +88,6 @@ class Widget : public internal::NativeWidgetDelegate, DeleteParam delete_on_destroy, MirroringParam mirror_in_rtl); - // Returns the root view for |native_window|. If |native_window| does not have - // a rootview, this recurses through all of |native_window|'s children until - // one is found. If a root view isn't found, null is returned. - static RootView* FindRootView(gfx::NativeWindow native_window); - - // Returns list of all root views for the native window and its - // children. - static void FindAllRootViews(gfx::NativeWindow native_window, - std::vector<RootView*>* root_views); - - // Retrieve the Widget corresponding to the specified native_view, or NULL - // if there is no such Widget. - static Widget* GetWidgetFromNativeView(gfx::NativeView native_view); - static Widget* GetWidgetFromNativeWindow(gfx::NativeWindow native_window); - // Enumerates all windows pertaining to us and notifies their // view hierarchies that the locale has changed. static void NotifyLocaleChanged(); @@ -128,6 +110,11 @@ class Widget : public internal::NativeWidgetDelegate, // |parent| is same as invoking |Init(NULL, bounds)|. virtual void InitWithWidget(Widget* parent, const gfx::Rect& bounds); + // Returns the topmost Widget in a hierarchy. Will return NULL if called + // before the underlying Native Widget has been initialized. + Widget* GetTopLevelWidget(); + const Widget* GetTopLevelWidget() const; + // Returns the WidgetDelegate for delegating certain events. virtual WidgetDelegate* GetWidgetDelegate(); @@ -183,9 +170,6 @@ class Widget : public internal::NativeWidgetDelegate, // Returns the RootView contained by this Widget. virtual RootView* GetRootView(); - // Returns the Widget associated with the root ancestor. - virtual Widget* GetRootWidget() const; - // Returns whether the Widget is visible to the user. virtual bool IsVisible() const; @@ -280,7 +264,7 @@ class Widget : public internal::NativeWidgetDelegate, // TODO(beng): Temporarily provided as a way to associate the subclass' // implementation of NativeWidget with this. - void set_native_widget(internal::NativeWidget* native_widget) { + void set_native_widget(NativeWidget* native_widget) { native_widget_ = native_widget; } @@ -290,7 +274,7 @@ class Widget : public internal::NativeWidgetDelegate, virtual View* GetFocusTraversableParentView(); private: - internal::NativeWidget* native_widget_; + NativeWidget* native_widget_; // Non-owned pointer to the Widget's delegate. May be NULL if no delegate is // being used. diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc index 0eca3d7..cb9eddf 100644 --- a/views/widget/widget_gtk.cc +++ b/views/widget/widget_gtk.cc @@ -44,10 +44,12 @@ using ui::OSExchangeData; using ui::OSExchangeDataProviderGtk; using ui::ActiveWindowWatcherX; +namespace views { + namespace { -// g_object data keys to associate a WidgetGtk object to a GtkWidget. -const char* kWidgetKey = "__VIEWS_WIDGET__"; +// Links the GtkWidget to its NativeWidget. +const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__"; // A g_object data key to associate a CompositePainter object to a GtkWidget. const char* kCompositePainterKey = "__VIEWS_COMPOSITE_PAINTER__"; // A g_object data key to associate the flag whether or not the widget @@ -134,9 +136,25 @@ class CompositePainter { DISALLOW_COPY_AND_ASSIGN(CompositePainter); }; -} // namespace +void EnumerateChildWidgetsForNativeWidgets(GtkWidget* child_widget, + gpointer param) { + // Walk child widgets, if necessary. + if (GTK_IS_CONTAINER(child_widget)) { + gtk_container_foreach(GTK_CONTAINER(child_widget), + EnumerateChildWidgetsForNativeWidgets, + param); + } -namespace views { + NativeWidget* native_widget = + NativeWidget::GetNativeWidgetForNativeView(child_widget); + if (native_widget) { + NativeWidget::NativeWidgets* widgets = + reinterpret_cast<NativeWidget::NativeWidgets*>(param); + widgets->insert(native_widget); + } +} + +} // namespace // During drag and drop GTK sends a drag-leave during a drop. This means we // have no way to tell the difference between a normal drag leave and a drop. @@ -167,7 +185,8 @@ class WidgetGtk::DropObserver : public MessageLoopForUI::Observer { if (!gtk_widget) return NULL; - return WidgetGtk::GetViewForNative(gtk_widget); + return static_cast<WidgetGtk*>( + NativeWidget::GetNativeWidgetForNativeView(gtk_widget)); } DISALLOW_COPY_AND_ASSIGN(DropObserver); @@ -421,22 +440,11 @@ void WidgetGtk::IsActiveChanged() { GetWidgetDelegate()->IsActiveChanged(IsActive()); } -// static -WidgetGtk* WidgetGtk::GetViewForNative(GtkWidget* widget) { - return static_cast<WidgetGtk*>(GetWidgetFromNativeView(widget)); -} - void WidgetGtk::ResetDropTarget() { ignore_drag_leave_ = false; drop_target_.reset(NULL); } -// static -RootView* WidgetGtk::GetRootViewForWidget(GtkWidget* widget) { - gpointer user_data = g_object_get_data(G_OBJECT(widget), "root-view"); - return static_cast<RootView*>(user_data); -} - void WidgetGtk::GetRequestedSize(gfx::Size* out) const { int width, height; if (GTK_IS_VIEWS_FIXED(widget_) && @@ -517,7 +525,6 @@ void WidgetGtk::Init(GtkWidget* parent, GDK_POINTER_MOTION_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK); - SetRootViewForWidget(widget_, GetRootView()); g_signal_connect_after(G_OBJECT(window_contents_), "size_request", G_CALLBACK(&OnSizeRequestThunk), this); @@ -630,7 +637,8 @@ void WidgetGtk::SetBounds(const gfx::Rect& bounds) { if (type_ == TYPE_CHILD) { GtkWidget* parent = gtk_widget_get_parent(widget_); if (GTK_IS_VIEWS_FIXED(parent)) { - WidgetGtk* parent_widget = GetViewForNative(parent); + WidgetGtk* parent_widget = static_cast<WidgetGtk*>( + NativeWidget::GetNativeWidgetForNativeView(parent)); parent_widget->PositionChild(widget_, bounds.x(), bounds.y(), bounds.width(), bounds.height()); } else { @@ -735,16 +743,6 @@ void WidgetGtk::SetAlwaysOnTop(bool on_top) { gtk_window_set_keep_above(GTK_WINDOW(widget_), on_top); } -Widget* WidgetGtk::GetRootWidget() const { - GtkWidget* parent = widget_; - GtkWidget* last_parent = parent; - while (parent) { - last_parent = parent; - parent = gtk_widget_get_parent(parent); - } - return last_parent ? GetViewForNative(last_parent) : NULL; -} - bool WidgetGtk::IsVisible() const { return GTK_WIDGET_VISIBLE(widget_); } @@ -796,11 +794,11 @@ FocusManager* WidgetGtk::GetFocusManager() { if (focus_manager_) return focus_manager_; - Widget* root = GetRootWidget(); - if (root && root != this) { - // Widget subclasses may override GetFocusManager(), for example for + NativeWidget* native_widget = GetTopLevelNativeWidget(GetNativeView()); + if (native_widget && native_widget != this) { + // WidgetGtk subclasses may override GetFocusManager(), for example for // dealing with cases where the widget has been unparented. - return root->GetFocusManager(); + return native_widget->GetWidget()->GetFocusManager(); } return NULL; } @@ -936,6 +934,13 @@ void WidgetGtk::EnableDebugPaint() { } //////////////////////////////////////////////////////////////////////////////// +// WidgetGtk, NativeWidget implementation: + +Widget* WidgetGtk::GetWidget() { + return this; +} + +//////////////////////////////////////////////////////////////////////////////// // WidgetGtk, protected: void WidgetGtk::OnSizeRequest(GtkWidget* widget, GtkRequisition* requisition) { @@ -1373,15 +1378,11 @@ bool WidgetGtk::ProcessScroll(GdkEventScroll* event) { } // static -void WidgetGtk::SetRootViewForWidget(GtkWidget* widget, RootView* root_view) { - g_object_set_data(G_OBJECT(widget), "root-view", root_view); -} - -// static Window* WidgetGtk::GetWindowImpl(GtkWidget* widget) { GtkWidget* parent = widget; while (parent) { - WidgetGtk* widget_gtk = GetViewForNative(parent); + WidgetGtk* widget_gtk = static_cast<WidgetGtk*>( + NativeWidget::GetNativeWidgetForNativeView(parent)); if (widget_gtk && widget_gtk->is_window_) return static_cast<WindowGtk*>(widget_gtk); parent = gtk_widget_get_parent(parent); @@ -1478,7 +1479,7 @@ void WidgetGtk::CreateGtkWidget(GtkWidget* parent, const gfx::Rect& bounds) { gtk_fixed_set_has_window(GTK_FIXED(window_contents_), true); gtk_container_add(GTK_CONTAINER(widget_), window_contents_); gtk_widget_show(window_contents_); - g_object_set_data(G_OBJECT(window_contents_), kWidgetKey, + g_object_set_data(G_OBJECT(window_contents_), kNativeWidgetKey, static_cast<Widget*>(this)); if (transparent_) @@ -1492,9 +1493,7 @@ void WidgetGtk::CreateGtkWidget(GtkWidget* parent, const gfx::Rect& bounds) { // function properly. gtk_widget_realize(widget_); } - // Setting the WidgetKey property to widget_, which is used by - // GetWidgetFromNativeWindow. - SetNativeWindowProperty(kWidgetKey, this); + SetNativeWindowProperty(kNativeWidgetKey, this); } void WidgetGtk::ConfigureWidgetForTransparentBackground(GtkWidget* parent) { @@ -1573,95 +1572,71 @@ Widget* Widget::CreatePopupWidget(TransparencyParam transparent, return popup; } -// Callback from gtk_container_foreach. Locates the first root view of widget -// or one of it's descendants. -static void RootViewLocatorCallback(GtkWidget* widget, - gpointer root_view_p) { - RootView** root_view = static_cast<RootView**>(root_view_p); - if (!*root_view) { - *root_view = WidgetGtk::GetRootViewForWidget(widget); - if (!*root_view && GTK_IS_CONTAINER(widget)) { - // gtk_container_foreach only iterates over children, not all descendants, - // so we have to recurse here to get all descendants. - gtk_container_foreach(GTK_CONTAINER(widget), RootViewLocatorCallback, - root_view_p); - } - } -} - // static -RootView* Widget::FindRootView(GtkWindow* window) { - RootView* root_view = WidgetGtk::GetRootViewForWidget(GTK_WIDGET(window)); - if (root_view) - return root_view; - - // Enumerate all children and check if they have a RootView. - gtk_container_foreach(GTK_CONTAINER(window), RootViewLocatorCallback, - static_cast<gpointer>(&root_view)); - return root_view; -} - -static void AllRootViewsLocatorCallback(GtkWidget* widget, - gpointer root_view_p) { - std::set<RootView*>* root_views_set = - reinterpret_cast<std::set<RootView*>*>(root_view_p); - RootView *root_view = WidgetGtk::GetRootViewForWidget(widget); - if (!root_view && GTK_IS_CONTAINER(widget)) { - // gtk_container_foreach only iterates over children, not all descendants, - // so we have to recurse here to get all descendants. - gtk_container_foreach(GTK_CONTAINER(widget), AllRootViewsLocatorCallback, - root_view_p); - } else { - if (root_view) - root_views_set->insert(root_view); +void Widget::NotifyLocaleChanged() { + GList *window_list = gtk_window_list_toplevels(); + for (GList* element = window_list; element; element = g_list_next(element)) { + NativeWidget* widget = + NativeWidget::GetNativeWidgetForNativeWindow(GTK_WINDOW(element->data)); + if (widget) + widget->GetWidget()->LocaleChanged(); } + g_list_free(window_list); } -// static -void Widget::FindAllRootViews(GtkWindow* window, - std::vector<RootView*>* root_views) { - RootView* root_view = WidgetGtk::GetRootViewForWidget(GTK_WIDGET(window)); - if (root_view) - root_views->push_back(root_view); - - std::set<RootView*> root_views_set; +//////////////////////////////////////////////////////////////////////////////// +// NativeWidget, public: - // Enumerate all children and check if they have a RootView. - gtk_container_foreach(GTK_CONTAINER(window), AllRootViewsLocatorCallback, - reinterpret_cast<gpointer>(&root_views_set)); - root_views->clear(); - root_views->reserve(root_views_set.size()); - for (std::set<RootView*>::iterator it = root_views_set.begin(); - it != root_views_set.end(); - ++it) - root_views->push_back(*it); +// static +NativeWidget* NativeWidget::GetNativeWidgetForNativeView( + gfx::NativeView native_view) { + if (!native_view) + return NULL; + return reinterpret_cast<WidgetGtk*>( + g_object_get_data(G_OBJECT(native_view), kNativeWidgetKey)); } // static -Widget* Widget::GetWidgetFromNativeView(gfx::NativeView native_view) { - gpointer raw_widget = g_object_get_data(G_OBJECT(native_view), kWidgetKey); - if (raw_widget) - return reinterpret_cast<Widget*>(raw_widget); - return NULL; +NativeWidget* NativeWidget::GetNativeWidgetForNativeWindow( + gfx::NativeWindow native_window) { + if (!native_window) + return NULL; + return reinterpret_cast<WidgetGtk*>( + g_object_get_data(G_OBJECT(native_window), kNativeWidgetKey)); } // static -Widget* Widget::GetWidgetFromNativeWindow(gfx::NativeWindow native_window) { - gpointer raw_widget = g_object_get_data(G_OBJECT(native_window), kWidgetKey); - if (raw_widget) - return reinterpret_cast<Widget*>(raw_widget); - return NULL; +NativeWidget* NativeWidget::GetTopLevelNativeWidget( + gfx::NativeView native_view) { + if (!native_view) + return NULL; + + NativeWidget* widget = NULL; + + GtkWidget* parent_gtkwidget = native_view; + NativeWidget* parent_widget; + do { + parent_widget = GetNativeWidgetForNativeView(parent_gtkwidget); + if (parent_widget) + widget = parent_widget; + parent_gtkwidget = gtk_widget_get_parent(parent_gtkwidget); + } while (parent_gtkwidget); + + return widget; } // static -void Widget::NotifyLocaleChanged() { - GList *window_list = gtk_window_list_toplevels(); - for (GList* element = window_list; element; element = g_list_next(element)) { - Widget* widget = GetWidgetFromNativeWindow(GTK_WINDOW(element->data)); - if (widget) - widget->LocaleChanged(); - } - g_list_free(window_list); +void NativeWidget::GetAllNativeWidgets(gfx::NativeView native_view, + NativeWidgets* children) { + if (!native_view) + return; + + NativeWidget* native_widget = GetNativeWidgetForNativeView(native_view); + if (native_widget) + children->insert(native_widget); + gtk_container_foreach(GTK_CONTAINER(native_view), + EnumerateChildWidgetsForNativeWidgets, + reinterpret_cast<gpointer>(children)); } } // namespace views diff --git a/views/widget/widget_gtk.h b/views/widget/widget_gtk.h index 8c0cacd..91b8024 100644 --- a/views/widget/widget_gtk.h +++ b/views/widget/widget_gtk.h @@ -40,7 +40,7 @@ class NativeWidgetDelegate; // Widget implementation for GTK. class WidgetGtk : public Widget, - public internal::NativeWidget, + public NativeWidget, public ui::ActiveWindowWatcherX::Observer { public: // Type of widget. @@ -137,16 +137,10 @@ class WidgetGtk : public Widget, // gets created. This will not be called on a TYPE_CHILD widget. virtual void SetInitialFocus() {} - // Gets the WidgetGtk in the userdata section of the widget. - static WidgetGtk* GetViewForNative(GtkWidget* widget); - // Sets the drop target to NULL. This is invoked by DropTargetGTK when the // drop is done. void ResetDropTarget(); - // Returns the RootView for |widget|. - static RootView* GetRootViewForWidget(GtkWidget* widget); - // Gets the requested size of the widget. This can be the size // stored in properties for a GtkViewsFixed, or in the requisitioned // size of other kinds of widgets. @@ -169,7 +163,6 @@ class WidgetGtk : public Widget, virtual gfx::NativeView GetNativeView() const; virtual void SetOpacity(unsigned char opacity); virtual void SetAlwaysOnTop(bool on_top); - virtual Widget* GetRootWidget() const; virtual bool IsVisible() const; virtual bool IsActive() const; virtual bool IsAccessibleWidget() const; @@ -207,6 +200,9 @@ class WidgetGtk : public Widget, static void EnableDebugPaint(); protected: + // Overridden from NativeWidget: + virtual Widget* GetWidget(); + // If widget contains another widget, translates event coordinates to the // contained widget's coordinates, else returns original event coordinates. template<class Event> bool GetContainedWidgetEventCoordinates(Event* event, @@ -306,8 +302,6 @@ class WidgetGtk : public Widget, // Process scroll event. bool ProcessScroll(GdkEventScroll* event); - static void SetRootViewForWidget(GtkWidget* widget, RootView* root_view); - // Returns the first ancestor of |widget| that is a window. static Window* GetWindowImpl(GtkWidget* widget); diff --git a/views/widget/widget_utils.cc b/views/widget/widget_utils.cc index 70b946d..d63a00c 100644 --- a/views/widget/widget_utils.cc +++ b/views/widget/widget_utils.cc @@ -11,7 +11,7 @@ namespace views { ThemeProvider* GetWidgetThemeProvider(const Widget* widget) { - Widget* root_widget = widget->GetRootWidget(); + const Widget* root_widget = widget->GetTopLevelWidget(); if (root_widget && root_widget != widget) { // Attempt to get the theme provider, and fall back to the default theme // provider if not found. diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc index 8cde70f..817ca77 100644 --- a/views/widget/widget_win.cc +++ b/views/widget/widget_win.cc @@ -94,32 +94,22 @@ bool ProcessChildWindowMessage(UINT message, return false; } -BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM l_param) { - RootView* root_view = GetRootViewForHWND(hwnd); - if (root_view) { - *reinterpret_cast<RootView**>(l_param) = root_view; - return FALSE; // Stop enumerating. +// Enumeration callback for NativeWidget::GetAllNativeWidgets(). Called for each +// child HWND beneath the original HWND. +BOOL CALLBACK EnumerateChildWindowsForNativeWidgets(HWND hwnd, LPARAM l_param) { + NativeWidget* native_widget = + NativeWidget::GetNativeWidgetForNativeView(hwnd); + if (native_widget) { + NativeWidget::NativeWidgets* native_widgets = + reinterpret_cast<NativeWidget::NativeWidgets*>(l_param); + native_widgets->insert(native_widget); } - return TRUE; // Keep enumerating. -} -// Enumerate child windows as they could have RootView distinct from -// the HWND's root view. -BOOL CALLBACK EnumAllRootViewsChildProc(HWND hwnd, LPARAM l_param) { - RootView* root_view = GetRootViewForHWND(hwnd); - if (root_view) { - std::set<RootView*>* root_views_set = - reinterpret_cast<std::set<RootView*>*>(l_param); - root_views_set->insert(root_view); - } - return TRUE; // Keep enumerating. + return TRUE; } -// Property used to link the HWND to its RootView. -const char* const kRootViewWindowProperty = "__ROOT_VIEW__"; - -// Links the HWND to it's Widget (as a Widget, not a WidgetWin). -const char* const kWidgetKey = "__VIEWS_WIDGET__"; +// Links the HWND to its NativeWidget. +const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__"; // A custom MSAA object id used to determine if a screen reader is actively // listening for MSAA events. @@ -130,11 +120,6 @@ const int kCustomObjectID = 1; // static bool WidgetWin::screen_reader_active_ = false; -RootView* GetRootViewForHWND(HWND hwnd) { - return reinterpret_cast<RootView*>( - ViewProp::GetValue(hwnd, kRootViewWindowProperty)); -} - //////////////////////////////////////////////////////////////////////////////// // WidgetWin, public: @@ -160,41 +145,7 @@ WidgetWin::WidgetWin() WidgetWin::~WidgetWin() { DestroyRootView(); -} - -// static -WidgetWin* WidgetWin::GetWidget(HWND hwnd) { - // TODO(jcivelli): http://crbug.com/44499 We need a way to test that hwnd is - // associated with a WidgetWin (it might be a pure - // WindowImpl). - if (!WindowImpl::IsWindowImpl(hwnd)) - return NULL; - return reinterpret_cast<WidgetWin*>(ui::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; + CloseNow(); } // static @@ -252,8 +203,7 @@ void WidgetWin::Init(gfx::NativeView parent, const gfx::Rect& bounds) { drop_target_ = new DropTargetWin(GetRootView()); if ((window_style() & WS_CHILD) == 0 || - (WidgetWin::GetRootWidget(parent) == NULL && - parent != GetDesktopWindow())) { + (!GetTopLevelNativeWidget(parent) && parent != GetDesktopWindow())) { // Top-level widgets and child widgets who do not have a top-level widget // ancestor get a FocusManager. Child widgets parented to the desktop do not // get a FocusManager because parenting to the desktop is the technique used @@ -261,9 +211,6 @@ void WidgetWin::Init(gfx::NativeView parent, const gfx::Rect& bounds) { focus_manager_.reset(new FocusManager(this)); } - // Sets the RootView as a property, so the automation can introspect windows. - SetNativeWindowProperty(kRootViewWindowProperty, GetRootView()); - // We need to add ourselves as a message loop observer so that we can repaint // aggressively if the contents of our window become invalid. Unfortunately // WM_PAINT messages are starved and we get flickery redrawing when resizing @@ -388,10 +335,6 @@ void WidgetWin::SetAlwaysOnTop(bool on_top) { set_window_ex_style(window_ex_style() & ~WS_EX_TOPMOST); } -Widget* WidgetWin::GetRootWidget() const { - return GetRootWidget(hwnd()); -} - bool WidgetWin::IsVisible() const { return !!::IsWindowVisible(hwnd()); } @@ -453,11 +396,11 @@ FocusManager* WidgetWin::GetFocusManager() { if (focus_manager_.get()) return focus_manager_.get(); - WidgetWin* widget = static_cast<WidgetWin*>(GetRootWidget()); - if (widget && widget != this) { + NativeWidget* native_widget = GetTopLevelNativeWidget(hwnd()); + if (native_widget && native_widget != this) { // WidgetWin subclasses may override GetFocusManager(), for example for // dealing with cases where the widget has been unparented. - return widget->GetFocusManager(); + return native_widget->GetWidget()->GetFocusManager(); } return NULL; } @@ -548,6 +491,13 @@ void WidgetWin::SetCursor(gfx::NativeCursor cursor) { } //////////////////////////////////////////////////////////////////////////////// +// WidgetWin, NativeWidget implementation: + +Widget* WidgetWin::GetWidget() { + return this; +} + +//////////////////////////////////////////////////////////////////////////////// // WidgetWin, MessageLoop::Observer implementation: void WidgetWin::WillProcessMessage(const MSG& msg) { @@ -632,9 +582,7 @@ void WidgetWin::OnCommand(UINT notification_code, int command_id, HWND window) { } LRESULT WidgetWin::OnCreate(CREATESTRUCT* create_struct) { - // Widget::GetWidgetFromNativeView expects the contents of this property - // to be of type Widget, so the cast is necessary. - SetNativeWindowProperty(kWidgetKey, static_cast<Widget*>(this)); + SetNativeWindowProperty(kNativeWidgetKey, this); use_layered_buffer_ = !!(window_ex_style() & WS_EX_LAYERED); LayoutRootView(); return 0; @@ -1293,50 +1241,68 @@ Widget* Widget::CreatePopupWidget(TransparencyParam transparent, } // static -RootView* Widget::FindRootView(HWND hwnd) { - RootView* root_view = GetRootViewForHWND(hwnd); - if (root_view) - return root_view; - - // Enumerate all children and check if they have a RootView. - EnumChildWindows(hwnd, EnumChildProc, reinterpret_cast<LPARAM>(&root_view)); - - return root_view; +void Widget::NotifyLocaleChanged() { + NOTIMPLEMENTED(); } +//////////////////////////////////////////////////////////////////////////////// +// NativeWidget, public: + // static -void Widget::FindAllRootViews(HWND window, - std::vector<RootView*>* root_views) { - RootView* root_view = GetRootViewForHWND(window); - std::set<RootView*> root_views_set; - if (root_view) - root_views_set.insert(root_view); - // Enumerate all children and check if they have a RootView. - EnumChildWindows(window, EnumAllRootViewsChildProc, - reinterpret_cast<LPARAM>(&root_views_set)); - root_views->clear(); - root_views->reserve(root_views_set.size()); - for (std::set<RootView*>::iterator it = root_views_set.begin(); - it != root_views_set.end(); - ++it) - root_views->push_back(*it); +NativeWidget* NativeWidget::GetNativeWidgetForNativeView( + gfx::NativeView native_view) { + if (!ui::WindowImpl::IsWindowImpl(native_view)) + return NULL; + return reinterpret_cast<WidgetWin*>( + ViewProp::GetValue(native_view, kNativeWidgetKey)); } // static -Widget* Widget::GetWidgetFromNativeView(gfx::NativeView native_view) { - return IsWindow(native_view) ? - reinterpret_cast<Widget*>(ViewProp::GetValue(native_view, kWidgetKey)) : - NULL; +NativeWidget* NativeWidget::GetNativeWidgetForNativeWindow( + gfx::NativeWindow native_window) { + return GetNativeWidgetForNativeView(native_window); } // static -Widget* Widget::GetWidgetFromNativeWindow(gfx::NativeWindow native_window) { - return Widget::GetWidgetFromNativeView(native_window); +NativeWidget* NativeWidget::GetTopLevelNativeWidget( + gfx::NativeView native_view) { + if (!native_view) + return NULL; + + // First, check if the top-level window is a Widget. + HWND root = ::GetAncestor(native_view, GA_ROOT); + if (!root) + return NULL; + + NativeWidget* widget = GetNativeWidgetForNativeView(root); + if (widget) + return widget; + + // Second, try to locate the last Widget window in the parent hierarchy. + HWND parent_hwnd = native_view; + NativeWidget* parent_widget; + do { + parent_widget = GetNativeWidgetForNativeView(parent_hwnd); + if (parent_widget) { + widget = parent_widget; + parent_hwnd = ::GetAncestor(parent_hwnd, GA_PARENT); + } + } while (parent_hwnd != NULL && parent_widget != NULL); + + return widget; } // static -void Widget::NotifyLocaleChanged() { - NOTIMPLEMENTED(); +void NativeWidget::GetAllNativeWidgets(gfx::NativeView native_view, + NativeWidgets* children) { + if (!native_view) + return; + + NativeWidget* native_widget = GetNativeWidgetForNativeView(native_view); + if (native_widget) + children->insert(native_widget); + EnumChildWindows(native_view, EnumerateChildWindowsForNativeWidgets, + reinterpret_cast<LPARAM>(children)); } } // namespace views diff --git a/views/widget/widget_win.h b/views/widget/widget_win.h index 6130ad1..1916055 100644 --- a/views/widget/widget_win.h +++ b/views/widget/widget_win.h @@ -44,8 +44,6 @@ namespace internal { class NativeWidgetDelegate; } -RootView* GetRootViewForHWND(HWND hwnd); - // A Windows message reflected from other windows. This message is sent // with the following arguments: // hWnd - Target window @@ -80,18 +78,12 @@ const int WM_NCUAHDRAWFRAME = 0xAF; /////////////////////////////////////////////////////////////////////////////// class WidgetWin : public ui::WindowImpl, public Widget, - public internal::NativeWidget, + public NativeWidget, public MessageLoopForUI::Observer { public: WidgetWin(); virtual ~WidgetWin(); - // 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); - // Returns true if we are on Windows Vista or greater and composition is // enabled. static bool IsAeroGlassEnabled(); @@ -134,7 +126,6 @@ class WidgetWin : public ui::WindowImpl, virtual gfx::NativeView GetNativeView() const; virtual void SetOpacity(unsigned char opacity); virtual void SetAlwaysOnTop(bool on_top); - virtual Widget* GetRootWidget() const; virtual bool IsVisible() const; virtual bool IsActive() const; virtual bool IsAccessibleWidget() const; @@ -228,6 +219,9 @@ class WidgetWin : public ui::WindowImpl, } protected: + // Overridden from NativeWidget: + virtual Widget* GetWidget(); + // Overridden from MessageLoop::Observer: void WillProcessMessage(const MSG& msg); virtual void DidProcessMessage(const MSG& msg); diff --git a/views/window/window_gtk.cc b/views/window/window_gtk.cc index 09e1984..a47bc32 100644 --- a/views/window/window_gtk.cc +++ b/views/window/window_gtk.cc @@ -97,7 +97,8 @@ void Window::CloseAllSecondaryWindows() { for (GList* window = windows; window; window = g_list_next(window)) { Window::CloseSecondaryWidget( - WidgetGtk::GetViewForNative(GTK_WIDGET(window->data))); + NativeWidget::GetNativeWidgetForNativeView( + GTK_WIDGET(window->data))->GetWidget()); } g_list_free(windows); } diff --git a/views/window/window_win.cc b/views/window/window_win.cc index 239226d..0bff7c0 100644 --- a/views/window/window_win.cc +++ b/views/window/window_win.cc @@ -1531,15 +1531,11 @@ void WindowWin::InitClass() { } namespace { -// static -static BOOL CALLBACK WindowCallbackProc(HWND hwnd, LPARAM lParam) { - // This is safer than calling GetWindowUserData, since it looks specifically - // for the RootView window property which should be unique. - RootView* root_view = GetRootViewForHWND(hwnd); - if (!root_view) - return TRUE; - - Window::CloseSecondaryWidget(root_view->GetWidget()); +BOOL CALLBACK WindowCallbackProc(HWND hwnd, LPARAM lParam) { + NativeWidget* native_widget = + NativeWidget::GetNativeWidgetForNativeView(hwnd); + if (native_widget) + Window::CloseSecondaryWidget(native_widget->GetWidget()); return TRUE; } } // namespace |