summaryrefslogtreecommitdiffstats
path: root/ui/views
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-03 00:19:18 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-03 00:19:18 +0000
commitb281162d602ce55ad45d8ff0e6604b8afece3c89 (patch)
tree4d208049b39cb7e70a97527876313f7f7b3d56ad /ui/views
parentfa4467a7d995cd64c5c728816e69873e75ec708b (diff)
downloadchromium_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.cc18
-rw-r--r--ui/views/focus/focus_manager.h8
-rw-r--r--ui/views/view.cc11
-rw-r--r--ui/views/views.gyp3
-rw-r--r--ui/views/widget/native_widget.h4
-rw-r--r--ui/views/widget/native_widget_listener.h6
-rw-r--r--ui/views/widget/native_widget_win.cc22
-rw-r--r--ui/views/widget/native_widget_win.h12
-rw-r--r--ui/views/widget/native_widget_win_unittest.cc20
-rw-r--r--ui/views/widget/widget.cc27
-rw-r--r--ui/views/widget/widget.h21
-rw-r--r--ui/views/widget/widget_test_util.cc28
-rw-r--r--ui/views/widget/widget_test_util.h20
-rw-r--r--ui/views/widget/widget_unittest.cc16
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