diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-03 00:19:18 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-03 00:19:18 +0000 |
commit | b281162d602ce55ad45d8ff0e6604b8afece3c89 (patch) | |
tree | 4d208049b39cb7e70a97527876313f7f7b3d56ad /ui/views | |
parent | fa4467a7d995cd64c5c728816e69873e75ec708b (diff) | |
download | chromium_src-b281162d602ce55ad45d8ff0e6604b8afece3c89.zip chromium_src-b281162d602ce55ad45d8ff0e6604b8afece3c89.tar.gz chromium_src-b281162d602ce55ad45d8ff0e6604b8afece3c89.tar.bz2 |
More FocusManager hookup.
- One focus manager per Widget hierarchy
- Create focus manager on widget initialization
- Allow focus manager to be obtained from NativeView.
- Adds a test to ensure focus manager is only created for the top level widget.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/6349057
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73551 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/views')
-rw-r--r-- | ui/views/focus/focus_manager.cc | 18 | ||||
-rw-r--r-- | ui/views/focus/focus_manager.h | 8 | ||||
-rw-r--r-- | ui/views/view.cc | 11 | ||||
-rw-r--r-- | ui/views/views.gyp | 3 | ||||
-rw-r--r-- | ui/views/widget/native_widget.h | 4 | ||||
-rw-r--r-- | ui/views/widget/native_widget_listener.h | 6 | ||||
-rw-r--r-- | ui/views/widget/native_widget_win.cc | 22 | ||||
-rw-r--r-- | ui/views/widget/native_widget_win.h | 12 | ||||
-rw-r--r-- | ui/views/widget/native_widget_win_unittest.cc | 20 | ||||
-rw-r--r-- | ui/views/widget/widget.cc | 27 | ||||
-rw-r--r-- | ui/views/widget/widget.h | 21 | ||||
-rw-r--r-- | ui/views/widget/widget_test_util.cc | 28 | ||||
-rw-r--r-- | ui/views/widget/widget_test_util.h | 20 | ||||
-rw-r--r-- | ui/views/widget/widget_unittest.cc | 16 |
14 files changed, 179 insertions, 37 deletions
diff --git a/ui/views/focus/focus_manager.cc b/ui/views/focus/focus_manager.cc index c2c7aa8..5039918 100644 --- a/ui/views/focus/focus_manager.cc +++ b/ui/views/focus/focus_manager.cc @@ -325,7 +325,7 @@ void FocusManager::SetFocusedViewWithReason( void FocusManager::ClearFocus() { SetFocusedView(NULL); - ClearNativeFocus(); + widget_->native_widget()->FocusNativeView(NULL); } void FocusManager::StoreFocusedView() { @@ -504,6 +504,22 @@ bool FocusManager::IsTabTraversalKeyEvent(const KeyEvent& key_event) { !key_event.IsControlDown(); } +// static +FocusManager* FocusManager::GetFocusManagerForNativeView( + gfx::NativeView native_view) { + NativeWidget* native_widget = + NativeWidget::GetNativeWidgetForNativeView(native_view); + return native_widget ? native_widget->GetWidget()->GetFocusManager() : NULL; +} + +// static +FocusManager* FocusManager::GetFocusManagerForNativeWindow( + gfx::NativeWindow native_window) { + NativeWidget* native_widget = + NativeWidget::GetNativeWidgetForNativeWindow(native_window); + return native_widget ? native_widget->GetWidget()->GetFocusManager() : NULL; +} + void FocusManager::ViewRemoved(View* parent, View* removed) { if (focused_view_ && focused_view_ == removed) ClearFocus(); diff --git a/ui/views/focus/focus_manager.h b/ui/views/focus/focus_manager.h index e94f307..8169d63 100644 --- a/ui/views/focus/focus_manager.h +++ b/ui/views/focus/focus_manager.h @@ -194,7 +194,7 @@ class FocusManager { void AdvanceFocus(bool reverse); // The FocusManager keeps track of the focused view within a RootView. - View* GetFocusedView() const { return focused_view_; } + View* focused_view() const { return focused_view_; } // Low-level methods to force the focus to change (and optionally provide // a reason). If the focus change should only happen if the view is @@ -273,12 +273,6 @@ class FocusManager { // pressed). static bool IsTabTraversalKeyEvent(const KeyEvent& key_event); - // Sets the focus to the specified native view. - virtual void FocusNativeView(gfx::NativeView native_view); - - // Clears the native view having the focus. - virtual void ClearNativeFocus(); - // Retrieves the FocusManager associated with the passed native view. static FocusManager* GetFocusManagerForNativeView( gfx::NativeView native_view); diff --git a/ui/views/view.cc b/ui/views/view.cc index 7937f5d..77bd585 100644 --- a/ui/views/view.cc +++ b/ui/views/view.cc @@ -336,7 +336,8 @@ void View::RemoveAllAccelerators() { // Focus ----------------------------------------------------------------------- FocusManager* View::GetFocusManager() const { - return NULL; + Widget* widget = GetWidget(); + return widget ? widget->GetFocusManager() : NULL; } FocusTraversable* View::GetFocusTraversable() const { @@ -352,14 +353,18 @@ View* View::GetPreviousFocusableView() const { } bool View::IsFocusable() const { - return false; + return focusable_ && enabled_ && visible_; } bool View::HasFocus() const { - return false; + FocusManager* focus_manager = GetFocusManager(); + return focus_manager ? focus_manager->focused_view() == this : false; } void View::RequestFocus() { + FocusManager* focus_manager = GetFocusManager(); + if (focus_manager && focus_manager->focused_view() != this) + focus_manager->SetFocusedView(this); } // Resources ------------------------------------------------------------------- diff --git a/ui/views/views.gyp b/ui/views/views.gyp index f6c5bc8..82be13a 100644 --- a/ui/views/views.gyp +++ b/ui/views/views.gyp @@ -128,11 +128,12 @@ 'v2', ], 'sources': [ - # 'focus/focus_manager_unittest.cc', 'rendering/border_unittest.cc', 'run_all_unittests.cc', 'view_unittest.cc', 'widget/native_widget_win_unittest.cc', + 'widget/widget_test_util.cc', + 'widget/widget_test_util.h', 'widget/widget_unittest.cc', ], 'include_dirs': [ diff --git a/ui/views/widget/native_widget.h b/ui/views/widget/native_widget.h index 6b9add7..87bd146 100644 --- a/ui/views/widget/native_widget.h +++ b/ui/views/widget/native_widget.h @@ -64,15 +64,15 @@ class NativeWidget { virtual void SetAlwaysOnTop(bool always_on_top) = 0; virtual bool IsVisible() const = 0; virtual bool IsActive() const = 0; - virtual void SetMouseCapture() = 0; virtual void ReleaseMouseCapture() = 0; virtual bool HasMouseCapture() const = 0; virtual bool ShouldReleaseCaptureOnMouseReleased() const = 0; - virtual void Invalidate() = 0; virtual void InvalidateRect(const gfx::Rect& invalid_rect) = 0; virtual void Paint() = 0; + virtual void FocusNativeView(gfx::NativeView native_view) = 0; + virtual Widget* GetWidget() const = 0; }; } // namespace ui diff --git a/ui/views/widget/native_widget_listener.h b/ui/views/widget/native_widget_listener.h index 959c14f..d761f40 100644 --- a/ui/views/widget/native_widget_listener.h +++ b/ui/views/widget/native_widget_listener.h @@ -44,7 +44,13 @@ class NativeWidgetListener { virtual void OnPaint(gfx::Canvas* canvas) = 0; virtual void OnSizeChanged(const gfx::Size& size) = 0; + + virtual void OnNativeFocus(gfx::NativeView focused_view) = 0; + virtual void OnNativeBlur(gfx::NativeView focused_view) = 0; + virtual void OnWorkAreaChanged() = 0; + + virtual Widget* GetWidget() const = 0; }; } // namespace internal diff --git a/ui/views/widget/native_widget_win.cc b/ui/views/widget/native_widget_win.cc index e435592..15e9aff 100644 --- a/ui/views/widget/native_widget_win.cc +++ b/ui/views/widget/native_widget_win.cc @@ -12,7 +12,6 @@ #include "ui/base/view_prop.h" #include "ui/base/win/hwnd_util.h" #include "ui/views/view.h" -#include "ui/views/widget/native_widget_listener.h" #include "ui/views/widget/widget.h" namespace ui { @@ -217,6 +216,22 @@ void NativeWidgetWin::Paint() { } } +void NativeWidgetWin::FocusNativeView(gfx::NativeView native_view) { + if (IsWindow(native_view)) { + if (GetFocus() != native_view) + SetFocus(native_view); + } else { + // NULL or invalid |native_view| passed, we consider this to be clearing + // focus. Keep the top level window focused so we continue to receive + // key events. + SetFocus(hwnd()); + } +} + +Widget* NativeWidgetWin::GetWidget() const { + return listener_->GetWidget(); +} + //////////////////////////////////////////////////////////////////////////////// // NativeWidetWin, MessageLoopForUI::Observer implementation @@ -267,6 +282,7 @@ void NativeWidgetWin::OnCommand(UINT notification_code, int command_id, LRESULT NativeWidgetWin::OnCreate(CREATESTRUCT* create_struct) { SetNativeWindowProperty(kNativeWidgetKey, this); + listener_->OnNativeWidgetCreated(); MessageLoopForUI::current()->AddObserver(this); return 0; } @@ -347,7 +363,7 @@ LRESULT NativeWidgetWin::OnKeyUp(UINT message, WPARAM w_param, LPARAM l_param) { } void NativeWidgetWin::OnKillFocus(HWND focused_window) { - // TODO(beng): focus + listener_->OnNativeBlur(focused_window); SetMsgHandled(FALSE); } @@ -474,7 +490,7 @@ LRESULT NativeWidgetWin::OnReflectedMessage(UINT message, WPARAM w_param, } void NativeWidgetWin::OnSetFocus(HWND focused_window) { - // TODO(beng): focus + listener_->OnNativeFocus(focused_window); SetMsgHandled(FALSE); } diff --git a/ui/views/widget/native_widget_win.h b/ui/views/widget/native_widget_win.h index 0434a97..f5c8eec 100644 --- a/ui/views/widget/native_widget_win.h +++ b/ui/views/widget/native_widget_win.h @@ -18,6 +18,8 @@ class CanvasSkia; namespace ui { class ViewProp; +class Widget; + namespace internal { // A Windows message reflected from other windows. This message is sent with the @@ -39,8 +41,6 @@ const int kReflectedMessage = WM_APP + 3; const int WM_NCUAHDRAWCAPTION = 0xAE; const int WM_NCUAHDRAWFRAME = 0xAF; -class NativeWidgetListener; - //////////////////////////////////////////////////////////////////////////////// // NativeWidgetWin class // @@ -74,15 +74,17 @@ class NativeWidgetWin : public NativeWidget, virtual void Close(); virtual void MoveAbove(NativeWidget* other); virtual void SetAlwaysOnTop(bool always_on_top); - virtual void Invalidate(); - virtual void InvalidateRect(const gfx::Rect& invalid_rect); - virtual void Paint(); virtual bool IsVisible() const; virtual bool IsActive() const; virtual void SetMouseCapture(); virtual void ReleaseMouseCapture(); virtual bool HasMouseCapture() const; virtual bool ShouldReleaseCaptureOnMouseReleased() const; + virtual void Invalidate(); + virtual void InvalidateRect(const gfx::Rect& invalid_rect); + virtual void Paint(); + virtual void FocusNativeView(gfx::NativeView native_view); + virtual Widget* GetWidget() const; // Overridden from MessageLoop::Observer: void WillProcessMessage(const MSG& msg); diff --git a/ui/views/widget/native_widget_win_unittest.cc b/ui/views/widget/native_widget_win_unittest.cc index b5cdf04..da7e6ae 100644 --- a/ui/views/widget/native_widget_win_unittest.cc +++ b/ui/views/widget/native_widget_win_unittest.cc @@ -7,6 +7,7 @@ #include "ui/views/view.h" #include "ui/views/widget/native_widget.h" #include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_test_util.h" namespace ui { @@ -15,13 +16,6 @@ class NativeWidgetTest : public testing::Test { NativeWidgetTest() {} virtual ~NativeWidgetTest() {} - Widget* CreateWidget() const { - Widget* widget = new Widget(new View); - widget->set_delete_on_destroy(false); - widget->InitWithNativeViewParent(NULL, gfx::Rect(10, 10, 200, 200)); - return widget; - } - private: DISALLOW_COPY_AND_ASSIGN(NativeWidgetTest); }; @@ -45,12 +39,12 @@ class TestWindowImpl : public WindowImpl { }; TEST_F(NativeWidgetTest, CreateNativeWidget) { - scoped_ptr<Widget> widget(CreateWidget()); + scoped_ptr<Widget> widget(internal::CreateWidget()); EXPECT_TRUE(widget->native_widget()->GetNativeView() != NULL); } TEST_F(NativeWidgetTest, GetNativeWidgetForNativeView) { - scoped_ptr<Widget> widget(CreateWidget()); + scoped_ptr<Widget> widget(internal::CreateWidget()); NativeWidget* a = widget->native_widget(); HWND nv = widget->native_widget()->GetNativeView(); NativeWidget* b = NativeWidget::GetNativeWidgetForNativeView(nv); @@ -59,7 +53,7 @@ TEST_F(NativeWidgetTest, GetNativeWidgetForNativeView) { // |widget| has the toplevel NativeWidget. TEST_F(NativeWidgetTest, GetTopLevelNativeWidget1) { - scoped_ptr<Widget> widget(CreateWidget()); + scoped_ptr<Widget> widget(internal::CreateWidget()); EXPECT_EQ(widget->native_widget(), NativeWidget::GetTopLevelNativeWidget( widget->native_widget()->GetNativeView())); @@ -67,8 +61,8 @@ TEST_F(NativeWidgetTest, GetTopLevelNativeWidget1) { // |toplevel_widget| has the toplevel NativeWidget. TEST_F(NativeWidgetTest, GetTopLevelNativeWidget2) { - scoped_ptr<Widget> child_widget(CreateWidget()); - scoped_ptr<Widget> toplevel_widget(CreateWidget()); + scoped_ptr<Widget> child_widget(internal::CreateWidget()); + scoped_ptr<Widget> toplevel_widget(internal::CreateWidget()); SetParent(child_widget->native_widget()->GetNativeView(), toplevel_widget->native_widget()->GetNativeView()); EXPECT_EQ(toplevel_widget->native_widget(), @@ -78,7 +72,7 @@ TEST_F(NativeWidgetTest, GetTopLevelNativeWidget2) { // |child_widget| has the toplevel NativeWidget. TEST_F(NativeWidgetTest, GetTopLevelNativeWidget3) { - scoped_ptr<Widget> child_widget(CreateWidget()); + scoped_ptr<Widget> child_widget(internal::CreateWidget()); TestWindowImpl toplevel; toplevel.Init(NULL, gfx::Rect(10, 10, 100, 100)); diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc index ba2daa6..1759c6b 100644 --- a/ui/views/widget/widget.cc +++ b/ui/views/widget/widget.cc @@ -6,6 +6,7 @@ #include "base/compiler_specific.h" #include "base/message_loop.h" +#include "ui/views/focus/focus_manager.h" #include "ui/views/view.h" #include "ui/views/widget/native_widget.h" #include "ui/views/widget/root_view.h" @@ -67,6 +68,12 @@ void Widget::InitWithViewParent(View* parent, const gfx::Rect& bounds) { native_widget_->InitWithViewParent(parent, bounds); } +Widget* Widget::GetTopLevelWidget() const { + NativeWidget* native_widget = + NativeWidget::GetTopLevelNativeWidget(native_widget_->GetNativeView()); + return native_widget->GetWidget(); +} + gfx::Rect Widget::GetWindowScreenBounds() const { return native_widget_->GetWindowScreenBounds(); } @@ -112,6 +119,10 @@ ThemeProvider* Widget::GetThemeProvider() const { return NULL; } +FocusManager* Widget::GetFocusManager() const { + return GetTopLevelWidget()->focus_manager_.get(); +} + //////////////////////////////////////////////////////////////////////////////// // Widget, NativeWidgetListener implementation: @@ -195,6 +206,8 @@ bool Widget::OnMouseWheelEvent(const MouseWheelEvent& event) { } void Widget::OnNativeWidgetCreated() { + if (GetTopLevelWidget() == this) + focus_manager_.reset(new FocusManager(this)); } void Widget::OnPaint(gfx::Canvas* canvas) { @@ -205,10 +218,24 @@ void Widget::OnSizeChanged(const gfx::Size& size) { root_view_->SetSize(size); } +void Widget::OnNativeFocus(gfx::NativeView focused_view) { + GetFocusManager()->GetWidgetFocusManager()->OnWidgetFocusEvent( + focused_view, native_widget_->GetNativeView()); +} + +void Widget::OnNativeBlur(gfx::NativeView focused_view) { + GetFocusManager()->GetWidgetFocusManager()->OnWidgetFocusEvent( + native_widget_->GetNativeView(), focused_view); +} + void Widget::OnWorkAreaChanged() { } +Widget* Widget::GetWidget() const { + return const_cast<Widget*>(this); +} + //////////////////////////////////////////////////////////////////////////////// // Widget, private: diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h index b97e7933..42c5c32 100644 --- a/ui/views/widget/widget.h +++ b/ui/views/widget/widget.h @@ -10,17 +10,24 @@ #include "base/task.h" #include "gfx/point.h" #include "ui/views/native_types.h" +#include "ui/views/focus/focus_manager.h" #include "ui/views/widget/native_widget_listener.h" namespace gfx { +class Canvas; class Path; class Rect; +class Size; } namespace ui { namespace internal { class RootView; } +class FocusManager; +class KeyEvent; +class MouseEvent; +class MouseWheelEvent; class NativeWidget; class ThemeProvider; class View; @@ -51,6 +58,9 @@ class Widget : public internal::NativeWidgetListener { void InitWithWidgetParent(Widget* parent, const gfx::Rect& bounds); void InitWithViewParent(View* parent, const gfx::Rect& bounds); + // Returns the topmost Widget in a hierarchy. + Widget* GetTopLevelWidget() const; + // Returns the bounding rect of the Widget in screen coordinates. gfx::Rect GetWindowScreenBounds() const; @@ -80,10 +90,14 @@ class Widget : public internal::NativeWidgetListener { // rendering Views associated with this Widget. ThemeProvider* GetThemeProvider() const; + // Returns the FocusManager for this Widget. Only top-level Widgets have + // FocusManagers. + FocusManager* GetFocusManager() const; + NativeWidget* native_widget() const { return native_widget_.get(); } private: - // NativeWidgetListener implementation: + // Overridden from internal::NativeWidgetListener: virtual void OnClose(); virtual void OnDestroy(); virtual void OnDisplayChanged(); @@ -94,7 +108,10 @@ class Widget : public internal::NativeWidgetListener { virtual void OnNativeWidgetCreated(); virtual void OnPaint(gfx::Canvas* canvas); virtual void OnSizeChanged(const gfx::Size& size); + virtual void OnNativeFocus(gfx::NativeView focused_view); + virtual void OnNativeBlur(gfx::NativeView focused_view); virtual void OnWorkAreaChanged(); + virtual Widget* GetWidget() const; // Causes the Widget to be destroyed immediately. void CloseNow(); @@ -122,6 +139,8 @@ class Widget : public internal::NativeWidgetListener { // True if the Widget should be automatically deleted when it is destroyed. bool delete_on_destroy_; + scoped_ptr<FocusManager> focus_manager_; + DISALLOW_COPY_AND_ASSIGN(Widget); }; diff --git a/ui/views/widget/widget_test_util.cc b/ui/views/widget/widget_test_util.cc new file mode 100644 index 0000000..8382ea8 --- /dev/null +++ b/ui/views/widget/widget_test_util.cc @@ -0,0 +1,28 @@ +// 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 "ui/views/widget/widget_test_util.h" + +#include "ui/views/view.h" +#include "ui/views/widget/widget.h" + +namespace ui { +namespace internal { + +Widget* CreateWidget() { + Widget* widget = new Widget(new View); + widget->set_delete_on_destroy(false); + widget->InitWithNativeViewParent(NULL, gfx::Rect(10, 10, 200, 200)); + return widget; +} + +Widget* CreateWidgetWithParent(Widget* parent) { + Widget* widget = new Widget(new View); + widget->set_delete_on_destroy(false); + widget->InitWithWidgetParent(parent, gfx::Rect(10, 10, 200, 200)); + return widget; +} + +} // namespace internal +} // namespace ui diff --git a/ui/views/widget/widget_test_util.h b/ui/views/widget/widget_test_util.h new file mode 100644 index 0000000..35df923 --- /dev/null +++ b/ui/views/widget/widget_test_util.h @@ -0,0 +1,20 @@ +// 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 UI_VIEWS_WIDGET_WIDGET_TEST_UTIL_H_ +#define UI_VIEWS_WIDGET_WIDGET_TEST_UTIL_H_ +#pragma once + +namespace ui { +class Widget; +namespace internal { + +// Create dummy Widgets for use in testing. +Widget* CreateWidget(); +Widget* CreateWidgetWithParent(Widget* parent); + +} // namespace internal +} // namespace ui + +#endif // UI_VIEWS_WIDGET_WIDGET_TEST_UTIL_H_ diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc index 2233e5d..d158e7d 100644 --- a/ui/views/widget/widget_unittest.cc +++ b/ui/views/widget/widget_unittest.cc @@ -3,7 +3,12 @@ // found in the LICENSE file. #include "base/logging.h" +#include "base/scoped_ptr.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/views/focus/focus_manager.h" +#include "ui/views/widget/native_widget.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_test_util.h" namespace ui { @@ -16,7 +21,16 @@ class WidgetTest : public testing::Test { DISALLOW_COPY_AND_ASSIGN(WidgetTest); }; -TEST_F(WidgetTest, Init) { +TEST_F(WidgetTest, FocusManagerInit_Basic) { + scoped_ptr<Widget> widget(internal::CreateWidget()); + EXPECT_TRUE(widget->GetFocusManager() != NULL); +} + +TEST_F(WidgetTest, FocusManagerInit_Nested) { + scoped_ptr<Widget> parent(internal::CreateWidget()); + scoped_ptr<Widget> child(internal::CreateWidgetWithParent(parent.get())); + + EXPECT_EQ(parent->GetFocusManager(), child->GetFocusManager()); } } // namespace ui |