diff options
author | ananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-02 06:11:22 +0000 |
---|---|---|
committer | ananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-02 06:11:22 +0000 |
commit | 3ef5d1b8cd0d307dda2b03b7d8bf9c8d7d97e870 (patch) | |
tree | 7725c4b1c02db26a7e09c30d325c2777109228d6 | |
parent | 99f5dfdbdf3b9d948750a4bbed07b0a2eef2337e (diff) | |
download | chromium_src-3ef5d1b8cd0d307dda2b03b7d8bf9c8d7d97e870.zip chromium_src-3ef5d1b8cd0d307dda2b03b7d8bf9c8d7d97e870.tar.gz chromium_src-3ef5d1b8cd0d307dda2b03b7d8bf9c8d7d97e870.tar.bz2 |
Reverting to fix builder redness. Please fix and reland.
Revert 76483 - Remove/replace RootView/Widget getters with new NativeWidget getters.
BUG=72040
TEST=existing unittests.
Review URL: http://codereview.chromium.org/6598069
TBR=ben@chromium.org
Review URL: http://codereview.chromium.org/6597099
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76508 0039d316-1c4b-4281-b951-d872f2087c98
29 files changed, 360 insertions, 475 deletions
diff --git a/chrome/browser/automation/testing_automation_provider_views.cc b/chrome/browser/automation/testing_automation_provider_views.cc index 01fedb8..99b4065 100644 --- a/chrome/browser/automation/testing_automation_provider_views.cc +++ b/chrome/browser/automation/testing_automation_provider_views.cc @@ -13,7 +13,6 @@ #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" @@ -122,10 +121,8 @@ void TestingAutomationProvider::WindowGetViewBounds(int handle, if (window_tracker_->ContainsHandle(handle)) { gfx::NativeWindow window = window_tracker_->GetResource(handle); - views::NativeWidget* native_widget = - views::NativeWidget::GetNativeWidgetForNativeWindow(window); - if (native_widget) { - views::View* root_view = native_widget->GetWidget()->GetRootView(); + views::RootView* root_view = views::Widget::FindRootView(window); + if (root_view) { 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 eb75b1b..80d2bf0 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/native_widget.h" +#include "views/widget/root_view.h" #include "views/widget/widget.h" #elif defined(TOOLKIT_GTK) #include "chrome/browser/ui/gtk/custom_drag.h" @@ -335,13 +335,10 @@ void DragBookmarks(Profile* profile, bool was_nested = MessageLoop::current()->IsNested(); MessageLoop::current()->SetNestableTasksAllowed(true); - 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); - } + views::Widget* widget = views::Widget::GetWidgetFromNativeView(view); + widget->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 6633ab8..55aec2e 100644 --- a/chrome/browser/chromeos/setting_level_bubble.cc +++ b/chrome/browser/chromeos/setting_level_bubble.cc @@ -45,10 +45,14 @@ static views::Widget* GetToplevelWidget() { if (!browser) return NULL; - views::NativeWidget* native_widget = - views::NativeWidget::GetNativeWidgetForNativeWindow( + views::RootView* root = + views::Widget::FindRootView( GTK_WINDOW(browser->window()->GetNativeHandle())); - return native_widget->GetWidget(); + DCHECK(root); + if (!root) + return NULL; + + return root->GetWidget(); } SettingLevelBubble::SettingLevelBubble(SkBitmap* increase_icon, diff --git a/chrome/browser/download/download_util.cc b/chrome/browser/download/download_util.cc index ae0f398..215997f 100644 --- a/chrome/browser/download/download_util.cc +++ b/chrome/browser/download/download_util.cc @@ -540,8 +540,7 @@ void DragDownload(const DownloadItem* download, GtkWidget* root = gtk_widget_get_toplevel(view); if (!root) return; - views::WidgetGtk* widget = static_cast<views::WidgetGtk*>( - views::NativeWidget::GetNativeWidgetForNativeView(root)); + views::WidgetGtk* widget = views::WidgetGtk::GetViewForNative(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 37f53bc..6abe5d5 100644 --- a/chrome/browser/speech/speech_input_bubble_views.cc +++ b/chrome/browser/speech/speech_input_bubble_views.cc @@ -281,11 +281,12 @@ void SpeechInputBubbleImpl::Show() { bubble_content_ = new ContentView(delegate_); UpdateLayout(); - views::NativeWidget* toplevel_widget = - views::NativeWidget::GetTopLevelNativeWidget( - tab_contents()->view()->GetNativeView()); - if (toplevel_widget) { - info_bubble_ = InfoBubble::Show(toplevel_widget->GetWidget(), + views::Widget* tab = views::Widget::GetWidgetFromNativeView( + tab_contents()->view()->GetNativeView()); + views::Widget* parent = tab ? tab->GetRootWidget() : NULL; + + if (parent) { + info_bubble_ = InfoBubble::Show(parent, 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 c0819df..bacb9d8 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()->GetTopLevelWidget()->GetBounds(&frame_rect, true); + host()->GetRootWidget()->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 162b1f6..9b6dff2 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/native_widget.h" +#include "views/widget/root_view.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::NativeWidget* native_widget = - views::NativeWidget::GetNativeWidgetForNativeView(native_view_); - if (native_widget && - native_widget->GetWidget()->ContainsNativeView(native_view)) { + 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)) 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 dbb8461..88feac7 100644 --- a/views/controls/native/native_view_host_win.cc +++ b/views/controls/native/native_view_host_win.cc @@ -8,7 +8,6 @@ #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" @@ -38,13 +37,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 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, + // 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, host_->GetWidget()->GetNativeView()); } } @@ -53,13 +52,13 @@ void NativeViewHostWin::NativeViewDetaching(bool destroyed) { if (!destroyed && installed_clip_) UninstallClip(); installed_clip_ = 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, + // 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, 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 50b62c6..02d5fe6 100644 --- a/views/controls/tabbed_pane/native_tabbed_pane_gtk.cc +++ b/views/controls/tabbed_pane/native_tabbed_pane_gtk.cc @@ -64,8 +64,7 @@ View* NativeTabbedPaneGtk::RemoveTabAtIndex(int index) { GtkWidget* page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(native_view()), index); - WidgetGtk* widget = - static_cast<WidgetGtk*>(NativeWidget::GetNativeWidgetForNativeView(page)); + WidgetGtk* widget = WidgetGtk::GetViewForNative(page); // detach the content view from widget so that we can delete widget // without destroying the content view. @@ -195,8 +194,7 @@ WidgetGtk* NativeTabbedPaneGtk::GetWidgetAt(int index) { DCHECK(index <= GetTabCount()); GtkWidget* page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(native_view()), index); - WidgetGtk* widget = - static_cast<WidgetGtk*>(NativeWidget::GetNativeWidgetForNativeView(page)); + WidgetGtk* widget = WidgetGtk::GetViewForNative(page); DCHECK(widget); return widget; } diff --git a/views/focus/accelerator_handler_touch.cc b/views/focus/accelerator_handler_touch.cc index 389fe7d..d4b072a 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); - NativeWidget* widget = NativeWidget::GetNativeWidgetForNativeView(gtk_widget); - if (!widget) { + if (!widget_gtk) { DLOG(WARNING) << "no WidgetGtk found for that GtkWidget"; return NULL; } - return widget->GetWidget()->GetRootView(); + return widget_gtk->GetRootView(); } #if defined(HAVE_XINPUT2) diff --git a/views/focus/focus_manager_gtk.cc b/views/focus/focus_manager_gtk.cc index 327c785..6e9dbcf 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; - NativeWidget* widget = NativeWidget::GetNativeWidgetForNativeView(root); + WidgetGtk* widget = WidgetGtk::GetViewForNative(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->GetWidget()->GetFocusManager(); + FocusManager* focus_manager = widget->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 d6f1e02..faf3815 100644 --- a/views/focus/focus_manager_win.cc +++ b/views/focus/focus_manager_win.cc @@ -23,10 +23,8 @@ void FocusManager::FocusNativeView(gfx::NativeView native_view) { // static FocusManager* FocusManager::GetFocusManagerForNativeView( gfx::NativeView native_view) { - // 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; + WidgetWin* widget = WidgetWin::GetRootWidget(native_view); + return widget ? widget->GetFocusManager() : NULL; } // static diff --git a/views/test/views_test_base.h b/views/test/views_test_base.h index d66a1d8..080eca5 100644 --- a/views/test/views_test_base.h +++ b/views/test/views_test_base.h @@ -10,10 +10,6 @@ #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 16109f7..8207c76b 100644 --- a/views/view_unittest.cc +++ b/views/view_unittest.cc @@ -1439,22 +1439,33 @@ class TestChangeNativeViewHierarchy { view_test_->RunPendingMessages(); } - void CheckEnumeratingNativeWidgets() { - if (!host_->GetWindow()) + 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 { return; - NativeWidget::NativeWidgets widgets; - NativeWidget::GetAllNativeWidgets(host_->GetNativeView(), &widgets); - EXPECT_EQ(TestNativeViewHierarchy::kTotalViews + 1, widgets.size()); + } +#endif + EXPECT_EQ(TestNativeViewHierarchy::kTotalViews + 1, + enumerated_root_views.size()); // Unfortunately there is no guarantee the sequence of views here so always // go through all of them. - for (NativeWidget::NativeWidgets::iterator i = widgets.begin(); - i != widgets.end(); ++i) { - RootView* root_view = (*i)->GetWidget()->GetRootView(); - if (host_->GetRootView() == root_view) + for (std::vector<RootView*>::iterator i = enumerated_root_views.begin(); + i != enumerated_root_views.end(); ++i) { + if (host_->GetRootView() == *i) continue; size_t j; for (j = 0; j < TestNativeViewHierarchy::kTotalViews; ++j) - if (root_views_[j] == root_view) + if (root_views_[j] == *i) break; // EXPECT_LT/GT/GE() fails to compile with class-defined constants // with gcc, with error @@ -1498,7 +1509,7 @@ TEST_F(ViewTest, ChangeNativeViewHierarchyFindRoots) { // TODO(georgey): Fix the test for Linux #if defined(OS_WIN) TestChangeNativeViewHierarchy test(this); - test.CheckEnumeratingNativeWidgets(); + test.CheckEnumeratingRootViews(); #endif } diff --git a/views/views.gyp b/views/views.gyp index a8c1fa3..f81e669 100644 --- a/views/views.gyp +++ b/views/views.gyp @@ -489,10 +489,6 @@ '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 dffbf93..2700f8c 100644 --- a/views/widget/native_widget.h +++ b/views/widget/native_widget.h @@ -6,11 +6,8 @@ #define VIEWS_WIDGET_NATIVE_WIDGET_H_ #pragma once -#include <set> - namespace views { - -class Widget; +namespace internal { //////////////////////////////////////////////////////////////////////////////// // NativeWidget interface @@ -21,30 +18,9 @@ class Widget; 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 deleted file mode 100644 index ac3e5b4..0000000 --- a/views/widget/native_widget_test_utils.h +++ /dev/null @@ -1,22 +0,0 @@ -// 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 deleted file mode 100644 index 43c0279..0000000 --- a/views/widget/native_widget_test_utils_gtk.cc +++ /dev/null @@ -1,33 +0,0 @@ -// 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 deleted file mode 100644 index 2d016e9..0000000 --- a/views/widget/native_widget_test_utils_win.cc +++ /dev/null @@ -1,33 +0,0 @@ -// 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 deleted file mode 100644 index 91c29a3..0000000 --- a/views/widget/native_widget_unittest.cc +++ /dev/null @@ -1,81 +0,0 @@ -// 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 c280206..0299c2d 100644 --- a/views/widget/widget.cc +++ b/views/widget/widget.cc @@ -7,7 +7,6 @@ #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 { @@ -29,17 +28,6 @@ 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_; } @@ -94,6 +82,10 @@ 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 b1860d1..89e9061 100644 --- a/views/widget/widget.h +++ b/views/widget/widget.h @@ -29,13 +29,16 @@ 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 // @@ -88,6 +91,21 @@ 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(); @@ -110,11 +128,6 @@ 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(); @@ -170,6 +183,9 @@ 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; @@ -264,7 +280,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(NativeWidget* native_widget) { + void set_native_widget(internal::NativeWidget* native_widget) { native_widget_ = native_widget; } @@ -274,7 +290,7 @@ class Widget : public internal::NativeWidgetDelegate, virtual View* GetFocusTraversableParentView(); private: - NativeWidget* native_widget_; + internal::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 cb9eddf..0eca3d7 100644 --- a/views/widget/widget_gtk.cc +++ b/views/widget/widget_gtk.cc @@ -44,12 +44,10 @@ using ui::OSExchangeData; using ui::OSExchangeDataProviderGtk; using ui::ActiveWindowWatcherX; -namespace views { - namespace { -// Links the GtkWidget to its NativeWidget. -const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__"; +// g_object data keys to associate a WidgetGtk object to a GtkWidget. +const char* kWidgetKey = "__VIEWS_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 @@ -136,26 +134,10 @@ class CompositePainter { DISALLOW_COPY_AND_ASSIGN(CompositePainter); }; -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); - } - - NativeWidget* native_widget = - NativeWidget::GetNativeWidgetForNativeView(child_widget); - if (native_widget) { - NativeWidget::NativeWidgets* widgets = - reinterpret_cast<NativeWidget::NativeWidgets*>(param); - widgets->insert(native_widget); - } -} - } // namespace +namespace views { + // 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. // To work around that we listen for DROP_START, then ignore the subsequent @@ -185,8 +167,7 @@ class WidgetGtk::DropObserver : public MessageLoopForUI::Observer { if (!gtk_widget) return NULL; - return static_cast<WidgetGtk*>( - NativeWidget::GetNativeWidgetForNativeView(gtk_widget)); + return WidgetGtk::GetViewForNative(gtk_widget); } DISALLOW_COPY_AND_ASSIGN(DropObserver); @@ -440,11 +421,22 @@ 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_) && @@ -525,6 +517,7 @@ 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); @@ -637,8 +630,7 @@ 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 = static_cast<WidgetGtk*>( - NativeWidget::GetNativeWidgetForNativeView(parent)); + WidgetGtk* parent_widget = GetViewForNative(parent); parent_widget->PositionChild(widget_, bounds.x(), bounds.y(), bounds.width(), bounds.height()); } else { @@ -743,6 +735,16 @@ 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_); } @@ -794,11 +796,11 @@ FocusManager* WidgetGtk::GetFocusManager() { if (focus_manager_) return focus_manager_; - NativeWidget* native_widget = GetTopLevelNativeWidget(GetNativeView()); - if (native_widget && native_widget != this) { - // WidgetGtk subclasses may override GetFocusManager(), for example for + Widget* root = GetRootWidget(); + if (root && root != this) { + // Widget subclasses may override GetFocusManager(), for example for // dealing with cases where the widget has been unparented. - return native_widget->GetWidget()->GetFocusManager(); + return root->GetFocusManager(); } return NULL; } @@ -934,13 +936,6 @@ void WidgetGtk::EnableDebugPaint() { } //////////////////////////////////////////////////////////////////////////////// -// WidgetGtk, NativeWidget implementation: - -Widget* WidgetGtk::GetWidget() { - return this; -} - -//////////////////////////////////////////////////////////////////////////////// // WidgetGtk, protected: void WidgetGtk::OnSizeRequest(GtkWidget* widget, GtkRequisition* requisition) { @@ -1378,11 +1373,15 @@ 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 = static_cast<WidgetGtk*>( - NativeWidget::GetNativeWidgetForNativeView(parent)); + WidgetGtk* widget_gtk = GetViewForNative(parent); if (widget_gtk && widget_gtk->is_window_) return static_cast<WindowGtk*>(widget_gtk); parent = gtk_widget_get_parent(parent); @@ -1479,7 +1478,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_), kNativeWidgetKey, + g_object_set_data(G_OBJECT(window_contents_), kWidgetKey, static_cast<Widget*>(this)); if (transparent_) @@ -1493,7 +1492,9 @@ void WidgetGtk::CreateGtkWidget(GtkWidget* parent, const gfx::Rect& bounds) { // function properly. gtk_widget_realize(widget_); } - SetNativeWindowProperty(kNativeWidgetKey, this); + // Setting the WidgetKey property to widget_, which is used by + // GetWidgetFromNativeWindow. + SetNativeWindowProperty(kWidgetKey, this); } void WidgetGtk::ConfigureWidgetForTransparentBackground(GtkWidget* parent) { @@ -1572,71 +1573,95 @@ Widget* Widget::CreatePopupWidget(TransparencyParam transparent, return popup; } -// static -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(); +// 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); + } } - g_list_free(window_list); -} - -//////////////////////////////////////////////////////////////////////////////// -// NativeWidget, public: - -// 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 -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)); +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); + } } // static -NativeWidget* NativeWidget::GetTopLevelNativeWidget( - gfx::NativeView native_view) { - if (!native_view) - return NULL; +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); - NativeWidget* widget = NULL; + std::set<RootView*> root_views_set; - 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); + // 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); +} - return widget; +// 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; } // static -void NativeWidget::GetAllNativeWidgets(gfx::NativeView native_view, - NativeWidgets* children) { - if (!native_view) - return; +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* native_widget = GetNativeWidgetForNativeView(native_view); - if (native_widget) - children->insert(native_widget); - gtk_container_foreach(GTK_CONTAINER(native_view), - EnumerateChildWidgetsForNativeWidgets, - reinterpret_cast<gpointer>(children)); +// 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); } } // namespace views diff --git a/views/widget/widget_gtk.h b/views/widget/widget_gtk.h index 91b8024..8c0cacd 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 NativeWidget, + public internal::NativeWidget, public ui::ActiveWindowWatcherX::Observer { public: // Type of widget. @@ -137,10 +137,16 @@ 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. @@ -163,6 +169,7 @@ 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; @@ -200,9 +207,6 @@ 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, @@ -302,6 +306,8 @@ 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 d63a00c..70b946d 100644 --- a/views/widget/widget_utils.cc +++ b/views/widget/widget_utils.cc @@ -11,7 +11,7 @@ namespace views { ThemeProvider* GetWidgetThemeProvider(const Widget* widget) { - const Widget* root_widget = widget->GetTopLevelWidget(); + Widget* root_widget = widget->GetRootWidget(); 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 817ca77..8cde70f 100644 --- a/views/widget/widget_win.cc +++ b/views/widget/widget_win.cc @@ -94,22 +94,32 @@ bool ProcessChildWindowMessage(UINT message, return false; } -// 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); +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. } + return TRUE; // Keep enumerating. +} - return TRUE; +// 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. } -// Links the HWND to its NativeWidget. -const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__"; +// 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__"; // A custom MSAA object id used to determine if a screen reader is actively // listening for MSAA events. @@ -120,6 +130,11 @@ 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: @@ -145,7 +160,41 @@ WidgetWin::WidgetWin() WidgetWin::~WidgetWin() { DestroyRootView(); - CloseNow(); +} + +// 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; } // static @@ -203,7 +252,8 @@ void WidgetWin::Init(gfx::NativeView parent, const gfx::Rect& bounds) { drop_target_ = new DropTargetWin(GetRootView()); if ((window_style() & WS_CHILD) == 0 || - (!GetTopLevelNativeWidget(parent) && parent != GetDesktopWindow())) { + (WidgetWin::GetRootWidget(parent) == NULL && + 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 @@ -211,6 +261,9 @@ 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 @@ -335,6 +388,10 @@ 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()); } @@ -396,11 +453,11 @@ FocusManager* WidgetWin::GetFocusManager() { if (focus_manager_.get()) return focus_manager_.get(); - NativeWidget* native_widget = GetTopLevelNativeWidget(hwnd()); - if (native_widget && native_widget != this) { + WidgetWin* widget = static_cast<WidgetWin*>(GetRootWidget()); + if (widget && widget != this) { // WidgetWin subclasses may override GetFocusManager(), for example for // dealing with cases where the widget has been unparented. - return native_widget->GetWidget()->GetFocusManager(); + return widget->GetFocusManager(); } return NULL; } @@ -491,13 +548,6 @@ void WidgetWin::SetCursor(gfx::NativeCursor cursor) { } //////////////////////////////////////////////////////////////////////////////// -// WidgetWin, NativeWidget implementation: - -Widget* WidgetWin::GetWidget() { - return this; -} - -//////////////////////////////////////////////////////////////////////////////// // WidgetWin, MessageLoop::Observer implementation: void WidgetWin::WillProcessMessage(const MSG& msg) { @@ -582,7 +632,9 @@ void WidgetWin::OnCommand(UINT notification_code, int command_id, HWND window) { } LRESULT WidgetWin::OnCreate(CREATESTRUCT* create_struct) { - SetNativeWindowProperty(kNativeWidgetKey, this); + // Widget::GetWidgetFromNativeView expects the contents of this property + // to be of type Widget, so the cast is necessary. + SetNativeWindowProperty(kWidgetKey, static_cast<Widget*>(this)); use_layered_buffer_ = !!(window_ex_style() & WS_EX_LAYERED); LayoutRootView(); return 0; @@ -1241,68 +1293,50 @@ Widget* Widget::CreatePopupWidget(TransparencyParam transparent, } // static -void Widget::NotifyLocaleChanged() { - NOTIMPLEMENTED(); -} +RootView* Widget::FindRootView(HWND hwnd) { + RootView* root_view = GetRootViewForHWND(hwnd); + if (root_view) + return root_view; -//////////////////////////////////////////////////////////////////////////////// -// NativeWidget, public: + // Enumerate all children and check if they have a RootView. + EnumChildWindows(hwnd, EnumChildProc, reinterpret_cast<LPARAM>(&root_view)); -// static -NativeWidget* NativeWidget::GetNativeWidgetForNativeView( - gfx::NativeView native_view) { - if (!ui::WindowImpl::IsWindowImpl(native_view)) - return NULL; - return reinterpret_cast<WidgetWin*>( - ViewProp::GetValue(native_view, kNativeWidgetKey)); + return root_view; } // static -NativeWidget* NativeWidget::GetNativeWidgetForNativeWindow( - gfx::NativeWindow native_window) { - return GetNativeWidgetForNativeView(native_window); +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); } // static -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; +Widget* Widget::GetWidgetFromNativeView(gfx::NativeView native_view) { + return IsWindow(native_view) ? + reinterpret_cast<Widget*>(ViewProp::GetValue(native_view, kWidgetKey)) : + NULL; } // static -void NativeWidget::GetAllNativeWidgets(gfx::NativeView native_view, - NativeWidgets* children) { - if (!native_view) - return; +Widget* Widget::GetWidgetFromNativeWindow(gfx::NativeWindow native_window) { + return Widget::GetWidgetFromNativeView(native_window); +} - NativeWidget* native_widget = GetNativeWidgetForNativeView(native_view); - if (native_widget) - children->insert(native_widget); - EnumChildWindows(native_view, EnumerateChildWindowsForNativeWidgets, - reinterpret_cast<LPARAM>(children)); +// static +void Widget::NotifyLocaleChanged() { + NOTIMPLEMENTED(); } } // namespace views diff --git a/views/widget/widget_win.h b/views/widget/widget_win.h index 1916055..6130ad1 100644 --- a/views/widget/widget_win.h +++ b/views/widget/widget_win.h @@ -44,6 +44,8 @@ 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 @@ -78,12 +80,18 @@ const int WM_NCUAHDRAWFRAME = 0xAF; /////////////////////////////////////////////////////////////////////////////// class WidgetWin : public ui::WindowImpl, public Widget, - public NativeWidget, + public internal::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(); @@ -126,6 +134,7 @@ 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; @@ -219,9 +228,6 @@ 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 a47bc32..09e1984 100644 --- a/views/window/window_gtk.cc +++ b/views/window/window_gtk.cc @@ -97,8 +97,7 @@ void Window::CloseAllSecondaryWindows() { for (GList* window = windows; window; window = g_list_next(window)) { Window::CloseSecondaryWidget( - NativeWidget::GetNativeWidgetForNativeView( - GTK_WIDGET(window->data))->GetWidget()); + WidgetGtk::GetViewForNative(GTK_WIDGET(window->data))); } g_list_free(windows); } diff --git a/views/window/window_win.cc b/views/window/window_win.cc index 0bff7c0..239226d 100644 --- a/views/window/window_win.cc +++ b/views/window/window_win.cc @@ -1531,11 +1531,15 @@ void WindowWin::InitClass() { } namespace { -BOOL CALLBACK WindowCallbackProc(HWND hwnd, LPARAM lParam) { - NativeWidget* native_widget = - NativeWidget::GetNativeWidgetForNativeView(hwnd); - if (native_widget) - Window::CloseSecondaryWidget(native_widget->GetWidget()); +// 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()); return TRUE; } } // namespace |