summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-22 21:37:54 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-22 21:37:54 +0000
commit47dfc956f274408cb60666181d846f057c827ba9 (patch)
tree18bcbecece29723f310a21b14cc6dc5cc40a024e /ui
parentace7ca0c74a46611c404e399fc35cee45ba840e4 (diff)
downloadchromium_src-47dfc956f274408cb60666181d846f057c827ba9.zip
chromium_src-47dfc956f274408cb60666181d846f057c827ba9.tar.gz
chromium_src-47dfc956f274408cb60666181d846f057c827ba9.tar.bz2
Enable FocusManager tests for Aura.
- Now building the file! - Disable some tests that only work on Windows. - Remove some dead Gtk code. http://crbug.com/102572 TEST=unittests Review URL: http://codereview.chromium.org/8642002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111220 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/views/focus/focus_manager.cc4
-rw-r--r--ui/views/focus/focus_manager.h3
-rw-r--r--ui/views/focus/focus_manager_test.cc114
-rw-r--r--ui/views/focus/focus_manager_test.h83
-rw-r--r--ui/views/focus/focus_manager_unittest.cc1360
-rw-r--r--ui/views/focus/focus_manager_unittest_win.cc285
-rw-r--r--ui/views/focus/focus_traversal_unittest.cc812
-rw-r--r--ui/views/widget/native_widget_aura.cc3
8 files changed, 1326 insertions, 1338 deletions
diff --git a/ui/views/focus/focus_manager.cc b/ui/views/focus/focus_manager.cc
index 1c98a12..0a44877 100644
--- a/ui/views/focus/focus_manager.cc
+++ b/ui/views/focus/focus_manager.cc
@@ -384,10 +384,6 @@ ui::AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator(
return accelerator_manager_->GetCurrentTarget(accelerator);
}
-void FocusManager::FocusNativeView(gfx::NativeView native_view) {
- widget_->FocusNativeView(native_view);
-}
-
// static
bool FocusManager::IsTabTraversalKeyEvent(const KeyEvent& key_event) {
return key_event.key_code() == ui::VKEY_TAB && !key_event.IsControlDown();
diff --git a/ui/views/focus/focus_manager.h b/ui/views/focus/focus_manager.h
index 01899e1..b428399 100644
--- a/ui/views/focus/focus_manager.h
+++ b/ui/views/focus/focus_manager.h
@@ -230,9 +230,6 @@ class VIEWS_EXPORT FocusManager {
ui::AcceleratorTarget* GetCurrentTargetForAccelerator(
const ui::Accelerator& accelertor) const;
- // 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();
diff --git a/ui/views/focus/focus_manager_test.cc b/ui/views/focus/focus_manager_test.cc
new file mode 100644
index 0000000..da15b27
--- /dev/null
+++ b/ui/views/focus/focus_manager_test.cc
@@ -0,0 +1,114 @@
+// 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/focus/focus_manager_test.h"
+
+#include "ui/views/focus/focus_manager.h"
+#include "ui/views/widget/widget.h"
+
+namespace views {
+
+////////////////////////////////////////////////////////////////////////////////
+// FocusManagerTest, public:
+
+FocusManagerTest::FocusManagerTest()
+ : contents_view_(new View),
+ focus_change_listener_(NULL) {
+}
+
+FocusManagerTest::~FocusManagerTest() {
+}
+
+FocusManager* FocusManagerTest::GetFocusManager() {
+ return GetWidget()->GetFocusManager();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// FocusManagerTest, ViewTestBase overrides:
+
+void FocusManagerTest::SetUp() {
+ ViewsTestBase::SetUp();
+ Widget* widget =
+ Widget::CreateWindowWithBounds(this, gfx::Rect(0, 0, 1024, 768));
+ InitContentView();
+ widget->Show();
+}
+
+void FocusManagerTest::TearDown() {
+ if (focus_change_listener_)
+ GetFocusManager()->RemoveFocusChangeListener(focus_change_listener_);
+ GetWidget()->Close();
+
+ // Flush the message loop to make application verifiers happy.
+ RunPendingMessages();
+ ViewsTestBase::TearDown();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// FocusManagerTest, WidgetDelegate implementation:
+
+View* FocusManagerTest::GetContentsView() {
+ return contents_view_;
+}
+
+Widget* FocusManagerTest::GetWidget() {
+ return contents_view_->GetWidget();
+}
+
+const Widget* FocusManagerTest::GetWidget() const {
+ return contents_view_->GetWidget();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// FocusManagerTest, protected:
+
+void FocusManagerTest::InitContentView() {
+}
+
+void FocusManagerTest::AddFocusChangeListener(FocusChangeListener* listener) {
+ ASSERT_FALSE(focus_change_listener_);
+ focus_change_listener_ = listener;
+ GetFocusManager()->AddFocusChangeListener(listener);
+}
+
+#if defined(OS_WIN) && !defined(USE_AURA)
+void FocusManagerTest::SimulateActivateWindow() {
+ SendMessage(GetWidget()->GetNativeWindow(), WM_ACTIVATE, WA_ACTIVE, NULL);
+}
+
+void FocusManagerTest::SimulateDeactivateWindow() {
+ SendMessage(GetWidget()->GetNativeWindow(), WM_ACTIVATE, WA_INACTIVE, NULL);
+}
+
+void FocusManagerTest::PostKeyDown(ui::KeyboardCode key_code) {
+ PostMessage(GetWidget()->GetNativeView(), WM_KEYDOWN, key_code, 0);
+}
+
+void FocusManagerTest::PostKeyUp(ui::KeyboardCode key_code) {
+ PostMessage(GetWidget()->GetNativeView(), WM_KEYUP, key_code, 0);
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// TestFocusChangeListener
+
+TestFocusChangeListener::TestFocusChangeListener() {
+}
+
+TestFocusChangeListener::~TestFocusChangeListener() {
+}
+
+void TestFocusChangeListener::OnWillChangeFocus(View* focused_before,
+ View* focused_now) {
+ focus_changes_.push_back(ViewPair(focused_before, focused_now));
+}
+void TestFocusChangeListener::OnDidChangeFocus(View* focused_before,
+ View* focused_now) {
+}
+
+void TestFocusChangeListener::ClearFocusChanges() {
+ focus_changes_.clear();
+}
+
+} // namespace views
diff --git a/ui/views/focus/focus_manager_test.h b/ui/views/focus/focus_manager_test.h
new file mode 100644
index 0000000..188ad23
--- /dev/null
+++ b/ui/views/focus/focus_manager_test.h
@@ -0,0 +1,83 @@
+// 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_FOCUS_FOCUS_MANAGER_TEST_H_
+#define UI_VIEWS_FOCUS_FOCUS_MANAGER_TEST_H_
+
+#include "ui/views/focus/focus_manager.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/widget/widget_delegate.h"
+
+namespace views {
+
+class FocusChangeListener;
+
+class FocusManagerTest : public ViewsTestBase,
+ public WidgetDelegate {
+ public:
+ FocusManagerTest();
+ virtual ~FocusManagerTest();
+
+ // Convenience to obtain the focus manager for the test's hosting widget.
+ FocusManager* GetFocusManager();
+
+ // Overridden from ViewsTestBase:
+ virtual void SetUp() OVERRIDE;
+ virtual void TearDown() OVERRIDE;
+
+ // Overridden from WidgetDelegate:
+ virtual View* GetContentsView() OVERRIDE;
+ virtual Widget* GetWidget() OVERRIDE;
+ virtual const Widget* GetWidget() const OVERRIDE;
+
+ protected:
+ // Called after the Widget is initialized and the content view is added.
+ // Override to add controls to the layout.
+ virtual void InitContentView();
+
+ void AddFocusChangeListener(FocusChangeListener* listener);
+
+#if defined(OS_WIN) && !defined(USE_AURA)
+ // Mocks activating/deactivating the window.
+ void SimulateActivateWindow();
+ void SimulateDeactivateWindow();
+
+ void PostKeyDown(ui::KeyboardCode key_code);
+ void PostKeyUp(ui::KeyboardCode key_code);
+#endif
+
+ private:
+ View* contents_view_;
+ FocusChangeListener* focus_change_listener_;
+
+ DISALLOW_COPY_AND_ASSIGN(FocusManagerTest);
+};
+
+typedef std::pair<View*, View*> ViewPair;
+
+// Use to record focus change notifications.
+class TestFocusChangeListener : public FocusChangeListener {
+ public:
+ TestFocusChangeListener();
+ virtual ~TestFocusChangeListener();
+
+ const std::vector<ViewPair>& focus_changes() const { return focus_changes_; }
+ void ClearFocusChanges();
+
+ // Overridden from FocusChangeListener:
+ virtual void OnWillChangeFocus(View* focused_before,
+ View* focused_now) OVERRIDE;
+ virtual void OnDidChangeFocus(View* focused_before,
+ View* focused_now) OVERRIDE;
+
+ private:
+ // A vector of which views lost/gained focus.
+ std::vector<ViewPair> focus_changes_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestFocusChangeListener);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_FOCUS_FOCUS_MANAGER_TEST_H_
diff --git a/ui/views/focus/focus_manager_unittest.cc b/ui/views/focus/focus_manager_unittest.cc
index 46c629a..21a6d8f 100644
--- a/ui/views/focus/focus_manager_unittest.cc
+++ b/ui/views/focus/focus_manager_unittest.cc
@@ -2,755 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/logging.h"
-#include "base/string16.h"
-#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
-#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/keycodes/keyboard_codes.h"
#include "ui/base/models/accelerator.h"
-#include "ui/base/models/combobox_model.h"
-#include "ui/gfx/rect.h"
#include "ui/views/focus/accelerator_handler.h"
#include "ui/views/focus/focus_manager_factory.h"
-#include "ui/views/test/views_test_base.h"
-#include "ui/views/widget/root_view.h"
+#include "ui/views/focus/focus_manager_test.h"
#include "ui/views/widget/widget.h"
-#include "ui/views/widget/widget_delegate.h"
-#include "ui/views/window/non_client_view.h"
-#include "views/background.h"
-#include "views/border.h"
-#include "views/controls/button/checkbox.h"
-#include "views/controls/button/radio_button.h"
-#include "views/controls/combobox/combobox.h"
-#include "views/controls/combobox/native_combobox_wrapper.h"
-#include "views/controls/label.h"
-#include "views/controls/link.h"
-#include "views/controls/native/native_view_host.h"
-#include "views/controls/scroll_view.h"
-#include "views/controls/tabbed_pane/native_tabbed_pane_wrapper.h"
-#include "views/controls/tabbed_pane/tabbed_pane.h"
+#include "views/controls/button/text_button.h"
#include "views/controls/textfield/textfield.h"
+#if !defined(USE_AURA)
+#include "views/controls/tabbed_pane/tabbed_pane.h"
+#include "views/controls/tabbed_pane/native_tabbed_pane_wrapper.h"
+#endif
+
#if defined(OS_LINUX)
#include "ui/base/keycodes/keyboard_code_conversion_gtk.h"
#endif
-namespace {
-const int kWindowWidth = 600;
-const int kWindowHeight = 500;
-
-int count = 1;
-
-const int kTopCheckBoxID = count++; // 1
-const int kLeftContainerID = count++;
-const int kAppleLabelID = count++;
-const int kAppleTextfieldID = count++;
-const int kOrangeLabelID = count++; // 5
-const int kOrangeTextfieldID = count++;
-const int kBananaLabelID = count++;
-const int kBananaTextfieldID = count++;
-const int kKiwiLabelID = count++;
-const int kKiwiTextfieldID = count++; // 10
-const int kFruitButtonID = count++;
-const int kFruitCheckBoxID = count++;
-const int kComboboxID = count++;
-
-const int kRightContainerID = count++;
-const int kAsparagusButtonID = count++; // 15
-const int kBroccoliButtonID = count++;
-const int kCauliflowerButtonID = count++;
-
-const int kInnerContainerID = count++;
-const int kScrollViewID = count++;
-const int kRosettaLinkID = count++; // 20
-const int kStupeurEtTremblementLinkID = count++;
-const int kDinerGameLinkID = count++;
-const int kRidiculeLinkID = count++;
-const int kClosetLinkID = count++;
-const int kVisitingLinkID = count++; // 25
-const int kAmelieLinkID = count++;
-const int kJoyeuxNoelLinkID = count++;
-const int kCampingLinkID = count++;
-const int kBriceDeNiceLinkID = count++;
-const int kTaxiLinkID = count++; // 30
-const int kAsterixLinkID = count++;
-
-const int kOKButtonID = count++;
-const int kCancelButtonID = count++;
-const int kHelpButtonID = count++;
-
-const int kStyleContainerID = count++; // 35
-const int kBoldCheckBoxID = count++;
-const int kItalicCheckBoxID = count++;
-const int kUnderlinedCheckBoxID = count++;
-const int kStyleHelpLinkID = count++;
-const int kStyleTextEditID = count++; // 40
-
-const int kSearchContainerID = count++;
-const int kSearchTextfieldID = count++;
-const int kSearchButtonID = count++;
-const int kHelpLinkID = count++;
-
-const int kThumbnailContainerID = count++; // 45
-const int kThumbnailStarID = count++;
-const int kThumbnailSuperStarID = count++;
-
-} // namespace
-
namespace views {
-class FocusManagerTest : public ViewsTestBase, public WidgetDelegate {
- public:
- FocusManagerTest()
- : window_(NULL),
- content_view_(NULL),
- focus_change_listener_(NULL) {
- }
-
- ~FocusManagerTest() {
- }
-
- virtual void SetUp() OVERRIDE {
- ViewsTestBase::SetUp();
- window_ = Widget::CreateWindowWithBounds(this, bounds());
- InitContentView();
- window_->Show();
- }
-
- virtual void TearDown() OVERRIDE {
- if (focus_change_listener_)
- GetFocusManager()->RemoveFocusChangeListener(focus_change_listener_);
- window_->Close();
-
- // Flush the message loop to make application verifiers happy.
- RunPendingMessages();
- ViewsTestBase::TearDown();
- }
-
- FocusManager* GetFocusManager() {
- return window_->GetFocusManager();
- }
-
- void FocusNativeView(gfx::NativeView native_view) {
-#if defined(USE_AURA)
- NOTIMPLEMENTED();
-#elif defined(OS_WIN)
- ::SendMessage(native_view, WM_SETFOCUS, NULL, NULL);
-#else
- gint return_val;
- GdkEventFocus event;
- event.type = GDK_FOCUS_CHANGE;
- event.window =
- gtk_widget_get_root_window(GTK_WIDGET(window_->GetNativeWindow()));
- event.send_event = TRUE;
- event.in = TRUE;
- gtk_signal_emit_by_name(GTK_OBJECT(native_view), "focus-in-event",
- &event, &return_val);
-#endif
- }
-
- // WidgetDelegate Implementation.
- virtual View* GetContentsView() OVERRIDE {
- if (!content_view_)
- content_view_ = new View();
- return content_view_;
- }
- virtual Widget* GetWidget() OVERRIDE {
- return content_view_->GetWidget();
- }
- virtual const Widget* GetWidget() const OVERRIDE {
- return content_view_->GetWidget();
- }
-
- virtual void InitContentView() {
- }
-
- protected:
- virtual gfx::Rect bounds() {
- return gfx::Rect(0, 0, 500, 500);
- }
-
- // Mocks activating/deactivating the window.
- void SimulateActivateWindow() {
-#if defined(USE_AURA)
- NOTIMPLEMENTED();
-#elif defined(OS_WIN)
- ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_ACTIVE, NULL);
-#else
- gboolean result;
- g_signal_emit_by_name(G_OBJECT(window_->GetNativeWindow()),
- "focus_in_event", 0, &result);
-#endif
- }
- void SimulateDeactivateWindow() {
-#if defined(USE_AURA)
- NOTIMPLEMENTED();
-#elif defined(OS_WIN)
- ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_INACTIVE, NULL);
-#else
- gboolean result;
- g_signal_emit_by_name(G_OBJECT(window_->GetNativeWindow()),
- "focus_out_event", 0, & result);
-#endif
- }
-
- Widget* window_;
- View* content_view_;
-
- void AddFocusChangeListener(FocusChangeListener* listener) {
- ASSERT_FALSE(focus_change_listener_);
- focus_change_listener_ = listener;
- GetFocusManager()->AddFocusChangeListener(listener);
- }
-
-#if defined(USE_AURA)
- void PostKeyDown(ui::KeyboardCode key_code) {
- NOTIMPLEMENTED();
- }
-
- void PostKeyUp(ui::KeyboardCode key_code) {
- NOTIMPLEMENTED();
- }
-#elif defined(OS_WIN)
- void PostKeyDown(ui::KeyboardCode key_code) {
- ::PostMessage(window_->GetNativeWindow(), WM_KEYDOWN, key_code, 0);
- }
-
- void PostKeyUp(ui::KeyboardCode key_code) {
- ::PostMessage(window_->GetNativeWindow(), WM_KEYUP, key_code, 0);
- }
-#elif defined(OS_LINUX)
- void PostKeyDown(ui::KeyboardCode key_code) {
- PostKeyEvent(key_code, true);
- }
-
- void PostKeyUp(ui::KeyboardCode key_code) {
- PostKeyEvent(key_code, false);
- }
-
- void PostKeyEvent(ui::KeyboardCode key_code, bool pressed) {
- int keyval = GdkKeyCodeForWindowsKeyCode(key_code, false);
- GdkKeymapKey* keys;
- gint n_keys;
- gdk_keymap_get_entries_for_keyval(
- gdk_keymap_get_default(),
- keyval,
- &keys,
- &n_keys);
- GdkEvent* event = gdk_event_new(pressed ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
- GdkEventKey* key_event = reinterpret_cast<GdkEventKey*>(event);
- int modifier = 0;
- if (pressed)
- key_event->state = modifier | GDK_KEY_PRESS_MASK;
- else
- key_event->state = modifier | GDK_KEY_RELEASE_MASK;
-
- key_event->window = GTK_WIDGET(window_->GetNativeWindow())->window;
- DCHECK(key_event->window != NULL);
- g_object_ref(key_event->window);
- key_event->send_event = true;
- key_event->time = GDK_CURRENT_TIME;
- key_event->keyval = keyval;
- key_event->hardware_keycode = keys[0].keycode;
- key_event->group = keys[0].group;
-
- g_free(keys);
-
- gdk_event_put(event);
- gdk_event_free(event);
- }
-#endif
-
- private:
- FocusChangeListener* focus_change_listener_;
-
- DISALLOW_COPY_AND_ASSIGN(FocusManagerTest);
-};
-
-// BorderView is a view containing a native window with its own view hierarchy.
-// It is interesting to test focus traversal from a view hierarchy to an inner
-// view hierarchy.
-class BorderView : public NativeViewHost {
- public:
- explicit BorderView(View* child) : child_(child), widget_(NULL) {
- DCHECK(child);
- set_focusable(false);
- }
-
- virtual ~BorderView() {}
-
- virtual internal::RootView* GetContentsRootView() {
- return static_cast<internal::RootView*>(widget_->GetRootView());
- }
-
- virtual FocusTraversable* GetFocusTraversable() {
- return static_cast<internal::RootView*>(widget_->GetRootView());
- }
-
- virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child) {
- NativeViewHost::ViewHierarchyChanged(is_add, parent, child);
-
- if (child == this && is_add) {
- if (!widget_) {
- widget_ = new Widget;
- Widget::InitParams params(Widget::InitParams::TYPE_CONTROL);
-#if defined(OS_WIN)
- params.parent = parent->GetWidget()->GetNativeView();
-#elif defined(TOOLKIT_USES_GTK)
- params.parent = native_view();
-#else
- NOTREACHED();
-#endif
- widget_->Init(params);
- widget_->SetFocusTraversableParentView(this);
- widget_->SetContentsView(child_);
- }
-
- // We have been added to a view hierarchy, attach the native view.
- Attach(widget_->GetNativeView());
- // Also update the FocusTraversable parent so the focus traversal works.
- static_cast<internal::RootView*>(widget_->GetRootView())->
- SetFocusTraversableParent(GetWidget()->GetFocusTraversable());
- }
- }
-
- private:
- View* child_;
- Widget* widget_;
-
- DISALLOW_COPY_AND_ASSIGN(BorderView);
-};
-
-class DummyComboboxModel : public ui::ComboboxModel {
- public:
- virtual int GetItemCount() { return 10; }
-
- virtual string16 GetItemAt(int index) {
- return ASCIIToUTF16("Item ") + base::IntToString16(index);
- }
-};
-
-// A View that can act as a pane.
-class PaneView : public View, public FocusTraversable {
- public:
- PaneView() : focus_search_(NULL) {}
-
- // If this method is called, this view will use GetPaneFocusTraversable to
- // have this provided FocusSearch used instead of the default one, allowing
- // you to trap focus within the pane.
- void EnablePaneFocus(FocusSearch* focus_search) {
- focus_search_ = focus_search;
- }
-
- // Overridden from views::View:
- virtual FocusTraversable* GetPaneFocusTraversable() {
- if (focus_search_)
- return this;
- else
- return NULL;
- }
-
- // Overridden from views::FocusTraversable:
- virtual views::FocusSearch* GetFocusSearch() {
- return focus_search_;
- }
- virtual FocusTraversable* GetFocusTraversableParent() {
- return NULL;
- }
- virtual View* GetFocusTraversableParentView() {
- return NULL;
- }
-
- private:
- FocusSearch* focus_search_;
-};
-
-class FocusTraversalTest : public FocusManagerTest {
- public:
- ~FocusTraversalTest();
-
- virtual void InitContentView();
-
- protected:
- FocusTraversalTest();
-
- virtual gfx::Rect bounds() {
- return gfx::Rect(0, 0, 600, 460);
- }
-
- View* FindViewByID(int id) {
- View* view = GetContentsView()->GetViewByID(id);
- if (view)
- return view;
- if (style_tab_)
- view = style_tab_->GetSelectedTab()->GetViewByID(id);
- if (view)
- return view;
- view = search_border_view_->GetContentsRootView()->GetViewByID(id);
- if (view)
- return view;
- return NULL;
- }
-
- protected:
- TabbedPane* style_tab_;
- BorderView* search_border_view_;
- DummyComboboxModel combobox_model_;
- PaneView* left_container_;
- PaneView* right_container_;
-
- DISALLOW_COPY_AND_ASSIGN(FocusTraversalTest);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// FocusTraversalTest
-////////////////////////////////////////////////////////////////////////////////
-
-FocusTraversalTest::FocusTraversalTest()
- : style_tab_(NULL),
- search_border_view_(NULL) {
-}
-
-FocusTraversalTest::~FocusTraversalTest() {
-}
-
-void FocusTraversalTest::InitContentView() {
- // Create a complicated view hierarchy with lots of control types for
- // use by all of the focus traversal tests.
- //
- // Class name, ID, and asterisk next to focusable views:
- //
- // View
- // Checkbox * kTopCheckBoxID
- // PaneView kLeftContainerID
- // Label kAppleLabelID
- // Textfield * kAppleTextfieldID
- // Label kOrangeLabelID
- // Textfield * kOrangeTextfieldID
- // Label kBananaLabelID
- // Textfield * kBananaTextfieldID
- // Label kKiwiLabelID
- // Textfield * kKiwiTextfieldID
- // NativeButton * kFruitButtonID
- // Checkbox * kFruitCheckBoxID
- // Combobox * kComboboxID
- // PaneView kRightContainerID
- // RadioButton * kAsparagusButtonID
- // RadioButton * kBroccoliButtonID
- // RadioButton * kCauliflowerButtonID
- // View kInnerContainerID
- // ScrollView kScrollViewID
- // View
- // Link * kRosettaLinkID
- // Link * kStupeurEtTremblementLinkID
- // Link * kDinerGameLinkID
- // Link * kRidiculeLinkID
- // Link * kClosetLinkID
- // Link * kVisitingLinkID
- // Link * kAmelieLinkID
- // Link * kJoyeuxNoelLinkID
- // Link * kCampingLinkID
- // Link * kBriceDeNiceLinkID
- // Link * kTaxiLinkID
- // Link * kAsterixLinkID
- // NativeButton * kOKButtonID
- // NativeButton * kCancelButtonID
- // NativeButton * kHelpButtonID
- // TabbedPane * kStyleContainerID
- // View
- // Checkbox * kBoldCheckBoxID
- // Checkbox * kItalicCheckBoxID
- // Checkbox * kUnderlinedCheckBoxID
- // Link * kStyleHelpLinkID
- // Textfield * kStyleTextEditID
- // Other
- // BorderView kSearchContainerID
- // View
- // Textfield * kSearchTextfieldID
- // NativeButton * kSearchButtonID
- // Link * kHelpLinkID
- // View * kThumbnailContainerID
- // NativeButton * kThumbnailStarID
- // NativeButton * kThumbnailSuperStarID
-
- content_view_->set_background(
- Background::CreateSolidBackground(SK_ColorWHITE));
-
- Checkbox* cb = new Checkbox(ASCIIToUTF16("This is a checkbox"));
- content_view_->AddChildView(cb);
- // In this fast paced world, who really has time for non hard-coded layout?
- cb->SetBounds(10, 10, 200, 20);
- cb->set_id(kTopCheckBoxID);
-
- left_container_ = new PaneView();
- left_container_->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
- left_container_->set_background(
- Background::CreateSolidBackground(240, 240, 240));
- left_container_->set_id(kLeftContainerID);
- content_view_->AddChildView(left_container_);
- left_container_->SetBounds(10, 35, 250, 200);
-
- int label_x = 5;
- int label_width = 50;
- int label_height = 15;
- int text_field_width = 150;
- int y = 10;
- int gap_between_labels = 10;
-
- Label* label = new Label(ASCIIToUTF16("Apple:"));
- label->set_id(kAppleLabelID);
- left_container_->AddChildView(label);
- label->SetBounds(label_x, y, label_width, label_height);
-
- Textfield* text_field = new Textfield();
- text_field->set_id(kAppleTextfieldID);
- left_container_->AddChildView(text_field);
- text_field->SetBounds(label_x + label_width + 5, y,
- text_field_width, label_height);
-
- y += label_height + gap_between_labels;
-
- label = new Label(ASCIIToUTF16("Orange:"));
- label->set_id(kOrangeLabelID);
- left_container_->AddChildView(label);
- label->SetBounds(label_x, y, label_width, label_height);
-
- text_field = new Textfield();
- text_field->set_id(kOrangeTextfieldID);
- left_container_->AddChildView(text_field);
- text_field->SetBounds(label_x + label_width + 5, y,
- text_field_width, label_height);
-
- y += label_height + gap_between_labels;
-
- label = new Label(ASCIIToUTF16("Banana:"));
- label->set_id(kBananaLabelID);
- left_container_->AddChildView(label);
- label->SetBounds(label_x, y, label_width, label_height);
-
- text_field = new Textfield();
- text_field->set_id(kBananaTextfieldID);
- left_container_->AddChildView(text_field);
- text_field->SetBounds(label_x + label_width + 5, y,
- text_field_width, label_height);
-
- y += label_height + gap_between_labels;
-
- label = new Label(ASCIIToUTF16("Kiwi:"));
- label->set_id(kKiwiLabelID);
- left_container_->AddChildView(label);
- label->SetBounds(label_x, y, label_width, label_height);
-
- text_field = new Textfield();
- text_field->set_id(kKiwiTextfieldID);
- left_container_->AddChildView(text_field);
- text_field->SetBounds(label_x + label_width + 5, y,
- text_field_width, label_height);
-
- y += label_height + gap_between_labels;
-
- NativeTextButton* button = new NativeTextButton(NULL,
- ASCIIToUTF16("Click me"));
- button->SetBounds(label_x, y + 10, 80, 30);
- button->set_id(kFruitButtonID);
- left_container_->AddChildView(button);
- y += 40;
-
- cb = new Checkbox(ASCIIToUTF16("This is another check box"));
- cb->SetBounds(label_x + label_width + 5, y, 180, 20);
- cb->set_id(kFruitCheckBoxID);
- left_container_->AddChildView(cb);
- y += 20;
-
- Combobox* combobox = new Combobox(&combobox_model_);
- combobox->SetBounds(label_x + label_width + 5, y, 150, 30);
- combobox->set_id(kComboboxID);
- left_container_->AddChildView(combobox);
-
- right_container_ = new PaneView();
- right_container_->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
- right_container_->set_background(
- Background::CreateSolidBackground(240, 240, 240));
- right_container_->set_id(kRightContainerID);
- content_view_->AddChildView(right_container_);
- right_container_->SetBounds(270, 35, 300, 200);
-
- y = 10;
- int radio_button_height = 18;
- int gap_between_radio_buttons = 10;
- RadioButton* radio_button = new RadioButton(ASCIIToUTF16("Asparagus"), 1);
- radio_button->set_id(kAsparagusButtonID);
- right_container_->AddChildView(radio_button);
- radio_button->SetBounds(5, y, 70, radio_button_height);
- radio_button->SetGroup(1);
- y += radio_button_height + gap_between_radio_buttons;
- radio_button = new RadioButton(ASCIIToUTF16("Broccoli"), 1);
- radio_button->set_id(kBroccoliButtonID);
- right_container_->AddChildView(radio_button);
- radio_button->SetBounds(5, y, 70, radio_button_height);
- radio_button->SetGroup(1);
- RadioButton* radio_button_to_check = radio_button;
- y += radio_button_height + gap_between_radio_buttons;
- radio_button = new RadioButton(ASCIIToUTF16("Cauliflower"), 1);
- radio_button->set_id(kCauliflowerButtonID);
- right_container_->AddChildView(radio_button);
- radio_button->SetBounds(5, y, 70, radio_button_height);
- radio_button->SetGroup(1);
- y += radio_button_height + gap_between_radio_buttons;
-
- View* inner_container = new View();
- inner_container->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
- inner_container->set_background(
- Background::CreateSolidBackground(230, 230, 230));
- inner_container->set_id(kInnerContainerID);
- right_container_->AddChildView(inner_container);
- inner_container->SetBounds(100, 10, 150, 180);
-
- ScrollView* scroll_view = new ScrollView();
- scroll_view->set_id(kScrollViewID);
- inner_container->AddChildView(scroll_view);
- scroll_view->SetBounds(1, 1, 148, 178);
-
- View* scroll_content = new View();
- scroll_content->SetBounds(0, 0, 200, 200);
- scroll_content->set_background(
- Background::CreateSolidBackground(200, 200, 200));
- scroll_view->SetContents(scroll_content);
-
- static const char* const kTitles[] = {
- "Rosetta", "Stupeur et tremblement", "The diner game",
- "Ridicule", "Le placard", "Les Visiteurs", "Amelie",
- "Joyeux Noel", "Camping", "Brice de Nice",
- "Taxi", "Asterix"
- };
-
- static const int kIDs[] = {
- kRosettaLinkID, kStupeurEtTremblementLinkID, kDinerGameLinkID,
- kRidiculeLinkID, kClosetLinkID, kVisitingLinkID, kAmelieLinkID,
- kJoyeuxNoelLinkID, kCampingLinkID, kBriceDeNiceLinkID,
- kTaxiLinkID, kAsterixLinkID
- };
-
- DCHECK(arraysize(kTitles) == arraysize(kIDs));
-
- y = 5;
- for (size_t i = 0; i < arraysize(kTitles); ++i) {
- Link* link = new Link(ASCIIToUTF16(kTitles[i]));
- link->SetHorizontalAlignment(Label::ALIGN_LEFT);
- link->set_id(kIDs[i]);
- scroll_content->AddChildView(link);
- link->SetBounds(5, y, 300, 15);
- y += 15;
- }
-
- y = 250;
- int width = 60;
- button = new NativeTextButton(NULL, ASCIIToUTF16("OK"));
- button->set_id(kOKButtonID);
- button->SetIsDefault(true);
-
- content_view_->AddChildView(button);
- button->SetBounds(150, y, width, 30);
-
- button = new NativeTextButton(NULL, ASCIIToUTF16("Cancel"));
- button->set_id(kCancelButtonID);
- content_view_->AddChildView(button);
- button->SetBounds(220, y, width, 30);
-
- button = new NativeTextButton(NULL, ASCIIToUTF16("Help"));
- button->set_id(kHelpButtonID);
- content_view_->AddChildView(button);
- button->SetBounds(290, y, width, 30);
-
- y += 40;
-
- // Left bottom box with style checkboxes.
- View* contents = new View();
- contents->set_background(Background::CreateSolidBackground(SK_ColorWHITE));
- cb = new Checkbox(ASCIIToUTF16("Bold"));
- contents->AddChildView(cb);
- cb->SetBounds(10, 10, 50, 20);
- cb->set_id(kBoldCheckBoxID);
-
- cb = new Checkbox(ASCIIToUTF16("Italic"));
- contents->AddChildView(cb);
- cb->SetBounds(70, 10, 50, 20);
- cb->set_id(kItalicCheckBoxID);
-
- cb = new Checkbox(ASCIIToUTF16("Underlined"));
- contents->AddChildView(cb);
- cb->SetBounds(130, 10, 70, 20);
- cb->set_id(kUnderlinedCheckBoxID);
-
- Link* link = new Link(ASCIIToUTF16("Help"));
- contents->AddChildView(link);
- link->SetBounds(10, 35, 70, 10);
- link->set_id(kStyleHelpLinkID);
-
- text_field = new Textfield();
- contents->AddChildView(text_field);
- text_field->SetBounds(10, 50, 100, 20);
- text_field->set_id(kStyleTextEditID);
-
- style_tab_ = new TabbedPane();
- style_tab_->set_id(kStyleContainerID);
- content_view_->AddChildView(style_tab_);
- style_tab_->SetBounds(10, y, 210, 100);
- style_tab_->AddTab(ASCIIToUTF16("Style"), contents);
- style_tab_->AddTab(ASCIIToUTF16("Other"), new View());
-
- // Right bottom box with search.
- contents = new View();
- contents->set_background(Background::CreateSolidBackground(SK_ColorWHITE));
- text_field = new Textfield();
- contents->AddChildView(text_field);
- text_field->SetBounds(10, 10, 100, 20);
- text_field->set_id(kSearchTextfieldID);
-
- button = new NativeTextButton(NULL, ASCIIToUTF16("Search"));
- contents->AddChildView(button);
- button->SetBounds(112, 5, 60, 30);
- button->set_id(kSearchButtonID);
-
- link = new Link(ASCIIToUTF16("Help"));
- link->SetHorizontalAlignment(Label::ALIGN_LEFT);
- link->set_id(kHelpLinkID);
- contents->AddChildView(link);
- link->SetBounds(175, 10, 30, 20);
-
- search_border_view_ = new BorderView(contents);
- search_border_view_->set_id(kSearchContainerID);
-
- content_view_->AddChildView(search_border_view_);
- search_border_view_->SetBounds(300, y, 240, 50);
-
- y += 60;
-
- contents = new View();
- contents->set_focusable(true);
- contents->set_background(Background::CreateSolidBackground(SK_ColorBLUE));
- contents->set_id(kThumbnailContainerID);
- button = new NativeTextButton(NULL, ASCIIToUTF16("Star"));
- contents->AddChildView(button);
- button->SetBounds(5, 5, 50, 30);
- button->set_id(kThumbnailStarID);
- button = new NativeTextButton(NULL, ASCIIToUTF16("SuperStar"));
- contents->AddChildView(button);
- button->SetBounds(60, 5, 100, 30);
- button->set_id(kThumbnailSuperStarID);
-
- content_view_->AddChildView(contents);
- contents->SetBounds(250, y, 200, 50);
- // We can only call RadioButton::SetChecked() on the radio-button is part of
- // the view hierarchy.
- radio_button_to_check->SetChecked(true);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// The tests
-////////////////////////////////////////////////////////////////////////////////
-
enum FocusTestEventType {
ON_FOCUS = 0,
ON_BLUR
@@ -795,8 +67,8 @@ TEST_F(FocusManagerTest, ViewFocusCallbacks) {
SimpleTestView* view1 = new SimpleTestView(&event_list, kView1ID);
SimpleTestView* view2 = new SimpleTestView(&event_list, kView2ID);
- content_view_->AddChildView(view1);
- content_view_->AddChildView(view2);
+ GetContentsView()->AddChildView(view1);
+ GetContentsView()->AddChildView(view2);
view1->RequestFocus();
ASSERT_EQ(1, static_cast<int>(event_list.size()));
@@ -818,30 +90,13 @@ TEST_F(FocusManagerTest, ViewFocusCallbacks) {
EXPECT_EQ(kView2ID, event_list[0].view_id);
}
-typedef std::pair<View*, View*> ViewPair;
-class TestFocusChangeListener : public FocusChangeListener {
- public:
- virtual void OnWillChangeFocus(View* focused_before, View* focused_now) {
- focus_changes_.push_back(ViewPair(focused_before, focused_now));
- }
- virtual void OnDidChangeFocus(View* focused_before, View* focused_now) {
- }
-
- const std::vector<ViewPair>& focus_changes() const { return focus_changes_; }
- void ClearFocusChanges() { focus_changes_.clear(); }
-
- private:
- // A vector of which views lost/gained focus.
- std::vector<ViewPair> focus_changes_;
-};
-
TEST_F(FocusManagerTest, FocusChangeListener) {
View* view1 = new View();
view1->set_focusable(true);
View* view2 = new View();
view2->set_focusable(true);
- content_view_->AddChildView(view1);
- content_view_->AddChildView(view2);
+ GetContentsView()->AddChildView(view1);
+ GetContentsView()->AddChildView(view2);
TestFocusChangeListener listener;
AddFocusChangeListener(&listener);
@@ -870,179 +125,49 @@ TEST_F(FocusManagerTest, FocusChangeListener) {
EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view2, null_view));
}
-class TestNativeButton : public NativeTextButton {
- public:
- explicit TestNativeButton(const string16& text)
- : NativeTextButton(NULL, text) {
- };
- virtual gfx::NativeView TestGetNativeControlView() {
- return GetWidget()->GetNativeView();
- }
-};
-
-class TestCheckbox : public Checkbox {
- public:
- explicit TestCheckbox(const string16& text) : Checkbox(text) {
- };
- virtual gfx::NativeView TestGetNativeControlView() {
- return GetWidget()->GetNativeView();
- }
-};
-
-class TestRadioButton : public RadioButton {
- public:
- explicit TestRadioButton(const string16& text)
- : RadioButton(text, 1) {
- }
- virtual gfx::NativeView TestGetNativeControlView() {
- return GetWidget()->GetNativeView();
- }
-};
-
+#if !defined(USE_AURA)
class TestTextfield : public Textfield {
public:
- TestTextfield() { }
+ TestTextfield() {}
virtual gfx::NativeView TestGetNativeControlView() {
return native_wrapper_->GetTestingHandle();
}
};
-class TestCombobox : public Combobox, public ui::ComboboxModel {
- public:
- TestCombobox() : Combobox(this) { }
- virtual gfx::NativeView TestGetNativeControlView() {
- return native_wrapper_->GetTestingHandle();
- }
- virtual int GetItemCount() {
- return 10;
- }
- virtual string16 GetItemAt(int index) {
- return ASCIIToUTF16("Hello combo");
- }
-};
-
class TestTabbedPane : public TabbedPane {
public:
- TestTabbedPane() { }
+ TestTabbedPane() {}
virtual gfx::NativeView TestGetNativeControlView() {
return native_tabbed_pane_->GetTestingHandle();
}
};
-#if !defined(TOUCH_UI)
-// TODO(oshima): replace TOUCH_UI with PURE_VIEWS
-
-// Tests that NativeControls do set the focus View appropriately on the
+// Tests that NativeControls do set the focused View appropriately on the
// FocusManager.
TEST_F(FocusManagerTest, FAILS_FocusNativeControls) {
TestTextfield* textfield = new TestTextfield();
TestTabbedPane* tabbed_pane = new TestTabbedPane();
TestTextfield* textfield2 = new TestTextfield();
- content_view_->AddChildView(textfield);
- content_view_->AddChildView(tabbed_pane);
+ GetContentsView()->AddChildView(textfield);
+ GetContentsView()->AddChildView(tabbed_pane);
tabbed_pane->AddTab(ASCIIToUTF16("Awesome textfield"), textfield2);
// Simulate the native view getting the native focus (such as by user click).
- FocusNativeView(textfield->TestGetNativeControlView());
+ GetWidget()->FocusNativeView(textfield->TestGetNativeControlView());
EXPECT_EQ(textfield, GetFocusManager()->GetFocusedView());
- FocusNativeView(tabbed_pane->TestGetNativeControlView());
+ GetWidget()->FocusNativeView(tabbed_pane->TestGetNativeControlView());
EXPECT_EQ(tabbed_pane, GetFocusManager()->GetFocusedView());
- FocusNativeView(textfield2->TestGetNativeControlView());
+ GetWidget()->FocusNativeView(textfield2->TestGetNativeControlView());
EXPECT_EQ(textfield2, GetFocusManager()->GetFocusedView());
}
#endif
-// On linux, we don't store/restore focused view because gtk handles
-// this (and pure views will be the same).
-#if defined(OS_WIN)
-
-// Test that when activating/deactivating the top window, the focus is stored/
-// restored properly.
-TEST_F(FocusManagerTest, FocusStoreRestore) {
- // Simulate an activate, otherwise the deactivate isn't going to do anything.
- SimulateActivateWindow();
-
- NativeTextButton* button = new NativeTextButton(NULL,
- ASCIIToUTF16("Press me"));
- View* view = new View();
- view->set_focusable(true);
-
- content_view_->AddChildView(button);
- button->SetBounds(10, 10, 200, 30);
- content_view_->AddChildView(view);
- RunPendingMessages();
-
- TestFocusChangeListener listener;
- AddFocusChangeListener(&listener);
-
- view->RequestFocus();
- RunPendingMessages();
- // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
-
- // Visual Studio 2010 has problems converting NULL to the null pointer for
- // std::pair. See http://connect.microsoft.com/VisualStudio/feedback/details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair
- // It will work if we pass nullptr.
-#if defined(_MSC_VER) && _MSC_VER >= 1600
- views::View* null_view = nullptr;
-#else
- views::View* null_view = NULL;
-#endif
-
- // Deacivate the window, it should store its focus.
- SimulateDeactivateWindow();
- EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView());
- ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size()));
- EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view));
- EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(view, null_view));
- listener.ClearFocusChanges();
-
- // Reactivate, focus should come-back to the previously focused view.
- SimulateActivateWindow();
- EXPECT_EQ(view, GetFocusManager()->GetFocusedView());
- ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size()));
- EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view));
- listener.ClearFocusChanges();
-
- // Same test with a NativeControl.
- button->RequestFocus();
- SimulateDeactivateWindow();
- EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView());
- ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size()));
- EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view, button));
- EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(button, null_view));
- listener.ClearFocusChanges();
-
- SimulateActivateWindow();
- EXPECT_EQ(button, GetFocusManager()->GetFocusedView());
- ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size()));
- EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, button));
- listener.ClearFocusChanges();
-
- /*
- // Now test that while the window is inactive we can change the focused view
- // (we do that in several places).
- SimulateDeactivateWindow();
- // TODO: would have to mock the window being inactive (with a TestWidgetWin
- // that would return false on IsActive()).
- GetFocusManager()->SetFocusedView(view);
- ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_ACTIVE, NULL);
-
- EXPECT_EQ(view, GetFocusManager()->GetFocusedView());
- ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size()));
- EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(button, null_view));
- EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(null_view, view));
- */
-}
-#endif
-
-#if !defined(TOUCH_UI)
-// TODO(oshima): There is no tabbed pane in pure views. Replace it
-// with different implementation.
-
+// There is no tabbed pane in Aura.
+#if !defined(USE_AURA)
TEST_F(FocusManagerTest, ContainsView) {
View* view = new View();
scoped_ptr<View> detached_view(new View());
@@ -1051,8 +176,8 @@ TEST_F(FocusManagerTest, ContainsView) {
NativeTextButton* tab_button = new NativeTextButton(
NULL, ASCIIToUTF16("tab button"));
- content_view_->AddChildView(view);
- content_view_->AddChildView(tabbed_pane);
+ GetContentsView()->AddChildView(view);
+ GetContentsView()->AddChildView(tabbed_pane);
// Adding a View inside a TabbedPane to test the case of nested root view.
tabbed_pane->AddTab(ASCIIToUTF16("Awesome tab"), nested_tabbed_pane);
@@ -1066,231 +191,6 @@ TEST_F(FocusManagerTest, ContainsView) {
}
#endif
-TEST_F(FocusTraversalTest, NormalTraversal) {
- const int kTraversalIDs[] = { kTopCheckBoxID, kAppleTextfieldID,
- kOrangeTextfieldID, kBananaTextfieldID, kKiwiTextfieldID,
- kFruitButtonID, kFruitCheckBoxID, kComboboxID, kBroccoliButtonID,
- kRosettaLinkID, kStupeurEtTremblementLinkID,
- kDinerGameLinkID, kRidiculeLinkID, kClosetLinkID, kVisitingLinkID,
- kAmelieLinkID, kJoyeuxNoelLinkID, kCampingLinkID, kBriceDeNiceLinkID,
- kTaxiLinkID, kAsterixLinkID, kOKButtonID, kCancelButtonID, kHelpButtonID,
- kStyleContainerID, kBoldCheckBoxID, kItalicCheckBoxID,
- kUnderlinedCheckBoxID, kStyleHelpLinkID, kStyleTextEditID,
- kSearchTextfieldID, kSearchButtonID, kHelpLinkID,
- kThumbnailContainerID, kThumbnailStarID, kThumbnailSuperStarID };
-
- // Uncomment the following line if you want to test manually the UI of this
- // test.
- // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
-
- // Let's traverse the whole focus hierarchy (several times, to make sure it
- // loops OK).
- GetFocusManager()->ClearFocus();
- for (int i = 0; i < 3; ++i) {
- for (size_t j = 0; j < arraysize(kTraversalIDs); j++) {
- GetFocusManager()->AdvanceFocus(false);
- View* focused_view = GetFocusManager()->GetFocusedView();
- EXPECT_TRUE(focused_view != NULL);
- if (focused_view)
- EXPECT_EQ(kTraversalIDs[j], focused_view->id());
- }
- }
-
- // Let's traverse in reverse order.
- GetFocusManager()->ClearFocus();
- for (int i = 0; i < 3; ++i) {
- for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) {
- GetFocusManager()->AdvanceFocus(true);
- View* focused_view = GetFocusManager()->GetFocusedView();
- EXPECT_TRUE(focused_view != NULL);
- if (focused_view)
- EXPECT_EQ(kTraversalIDs[j], focused_view->id());
- }
- }
-}
-
-TEST_F(FocusTraversalTest, TraversalWithNonEnabledViews) {
- const int kDisabledIDs[] = {
- kBananaTextfieldID, kFruitCheckBoxID, kComboboxID, kAsparagusButtonID,
- kCauliflowerButtonID, kClosetLinkID, kVisitingLinkID, kBriceDeNiceLinkID,
- kTaxiLinkID, kAsterixLinkID, kHelpButtonID, kBoldCheckBoxID,
- kSearchTextfieldID, kHelpLinkID };
-
- const int kTraversalIDs[] = { kTopCheckBoxID, kAppleTextfieldID,
- kOrangeTextfieldID, kKiwiTextfieldID, kFruitButtonID, kBroccoliButtonID,
- kRosettaLinkID, kStupeurEtTremblementLinkID, kDinerGameLinkID,
- kRidiculeLinkID, kAmelieLinkID, kJoyeuxNoelLinkID, kCampingLinkID,
- kOKButtonID, kCancelButtonID, kStyleContainerID, kItalicCheckBoxID,
- kUnderlinedCheckBoxID, kStyleHelpLinkID, kStyleTextEditID,
- kSearchButtonID, kThumbnailContainerID, kThumbnailStarID,
- kThumbnailSuperStarID };
-
- // Let's disable some views.
- for (size_t i = 0; i < arraysize(kDisabledIDs); i++) {
- View* v = FindViewByID(kDisabledIDs[i]);
- ASSERT_TRUE(v != NULL);
- v->SetEnabled(false);
- }
-
- // Uncomment the following line if you want to test manually the UI of this
- // test.
- // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
-
- View* focused_view;
- // Let's do one traversal (several times, to make sure it loops ok).
- GetFocusManager()->ClearFocus();
- for (int i = 0; i < 3; ++i) {
- for (size_t j = 0; j < arraysize(kTraversalIDs); j++) {
- GetFocusManager()->AdvanceFocus(false);
- focused_view = GetFocusManager()->GetFocusedView();
- EXPECT_TRUE(focused_view != NULL);
- if (focused_view)
- EXPECT_EQ(kTraversalIDs[j], focused_view->id());
- }
- }
-
- // Same thing in reverse.
- GetFocusManager()->ClearFocus();
- for (int i = 0; i < 3; ++i) {
- for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) {
- GetFocusManager()->AdvanceFocus(true);
- focused_view = GetFocusManager()->GetFocusedView();
- EXPECT_TRUE(focused_view != NULL);
- if (focused_view)
- EXPECT_EQ(kTraversalIDs[j], focused_view->id());
- }
- }
-}
-
-TEST_F(FocusTraversalTest, TraversalWithInvisibleViews) {
- const int kInvisibleIDs[] = { kTopCheckBoxID, kOKButtonID,
- kThumbnailContainerID };
-
- const int kTraversalIDs[] = { kAppleTextfieldID, kOrangeTextfieldID,
- kBananaTextfieldID, kKiwiTextfieldID, kFruitButtonID, kFruitCheckBoxID,
- kComboboxID, kBroccoliButtonID, kRosettaLinkID,
- kStupeurEtTremblementLinkID, kDinerGameLinkID, kRidiculeLinkID,
- kClosetLinkID, kVisitingLinkID, kAmelieLinkID, kJoyeuxNoelLinkID,
- kCampingLinkID, kBriceDeNiceLinkID, kTaxiLinkID, kAsterixLinkID,
- kCancelButtonID, kHelpButtonID, kStyleContainerID, kBoldCheckBoxID,
- kItalicCheckBoxID, kUnderlinedCheckBoxID, kStyleHelpLinkID,
- kStyleTextEditID, kSearchTextfieldID, kSearchButtonID, kHelpLinkID };
-
-
- // Let's make some views invisible.
- for (size_t i = 0; i < arraysize(kInvisibleIDs); i++) {
- View* v = FindViewByID(kInvisibleIDs[i]);
- ASSERT_TRUE(v != NULL);
- v->SetVisible(false);
- }
-
- // Uncomment the following line if you want to test manually the UI of this
- // test.
- // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
-
- View* focused_view;
- // Let's do one traversal (several times, to make sure it loops ok).
- GetFocusManager()->ClearFocus();
- for (int i = 0; i < 3; ++i) {
- for (size_t j = 0; j < arraysize(kTraversalIDs); j++) {
- GetFocusManager()->AdvanceFocus(false);
- focused_view = GetFocusManager()->GetFocusedView();
- EXPECT_TRUE(focused_view != NULL);
- if (focused_view)
- EXPECT_EQ(kTraversalIDs[j], focused_view->id());
- }
- }
-
- // Same thing in reverse.
- GetFocusManager()->ClearFocus();
- for (int i = 0; i < 3; ++i) {
- for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) {
- GetFocusManager()->AdvanceFocus(true);
- focused_view = GetFocusManager()->GetFocusedView();
- EXPECT_TRUE(focused_view != NULL);
- if (focused_view)
- EXPECT_EQ(kTraversalIDs[j], focused_view->id());
- }
- }
-}
-
-TEST_F(FocusTraversalTest, PaneTraversal) {
- // Tests trapping the traversal within a pane - useful for full
- // keyboard accessibility for toolbars.
-
- // First test the left container.
- const int kLeftTraversalIDs[] = {
- kAppleTextfieldID,
- kOrangeTextfieldID, kBananaTextfieldID, kKiwiTextfieldID,
- kFruitButtonID, kFruitCheckBoxID, kComboboxID };
-
- FocusSearch focus_search_left(left_container_, true, false);
- left_container_->EnablePaneFocus(&focus_search_left);
- FindViewByID(kComboboxID)->RequestFocus();
-
- // Traverse the focus hierarchy within the pane several times.
- for (int i = 0; i < 3; ++i) {
- for (size_t j = 0; j < arraysize(kLeftTraversalIDs); j++) {
- GetFocusManager()->AdvanceFocus(false);
- View* focused_view = GetFocusManager()->GetFocusedView();
- EXPECT_TRUE(focused_view != NULL);
- if (focused_view)
- EXPECT_EQ(kLeftTraversalIDs[j], focused_view->id());
- }
- }
-
- // Traverse in reverse order.
- FindViewByID(kAppleTextfieldID)->RequestFocus();
- for (int i = 0; i < 3; ++i) {
- for (int j = arraysize(kLeftTraversalIDs) - 1; j >= 0; --j) {
- GetFocusManager()->AdvanceFocus(true);
- View* focused_view = GetFocusManager()->GetFocusedView();
- EXPECT_TRUE(focused_view != NULL);
- if (focused_view)
- EXPECT_EQ(kLeftTraversalIDs[j], focused_view->id());
- }
- }
-
- // Now test the right container, but this time with accessibility mode.
- // Make some links not focusable, but mark one of them as
- // "accessibility focusable", so it should show up in the traversal.
- const int kRightTraversalIDs[] = {
- kBroccoliButtonID, kDinerGameLinkID, kRidiculeLinkID,
- kClosetLinkID, kVisitingLinkID, kAmelieLinkID, kJoyeuxNoelLinkID,
- kCampingLinkID, kBriceDeNiceLinkID, kTaxiLinkID, kAsterixLinkID };
-
- FocusSearch focus_search_right(right_container_, true, true);
- right_container_->EnablePaneFocus(&focus_search_right);
- FindViewByID(kRosettaLinkID)->set_focusable(false);
- FindViewByID(kStupeurEtTremblementLinkID)->set_focusable(false);
- FindViewByID(kDinerGameLinkID)->set_accessibility_focusable(true);
- FindViewByID(kDinerGameLinkID)->set_focusable(false);
- FindViewByID(kAsterixLinkID)->RequestFocus();
-
- // Traverse the focus hierarchy within the pane several times.
- for (int i = 0; i < 3; ++i) {
- for (size_t j = 0; j < arraysize(kRightTraversalIDs); j++) {
- GetFocusManager()->AdvanceFocus(false);
- View* focused_view = GetFocusManager()->GetFocusedView();
- EXPECT_TRUE(focused_view != NULL);
- if (focused_view)
- EXPECT_EQ(kRightTraversalIDs[j], focused_view->id());
- }
- }
-
- // Traverse in reverse order.
- FindViewByID(kBroccoliButtonID)->RequestFocus();
- for (int i = 0; i < 3; ++i) {
- for (int j = arraysize(kRightTraversalIDs) - 1; j >= 0; --j) {
- GetFocusManager()->AdvanceFocus(true);
- View* focused_view = GetFocusManager()->GetFocusedView();
- EXPECT_TRUE(focused_view != NULL);
- if (focused_view)
- EXPECT_EQ(kRightTraversalIDs[j], focused_view->id());
- }
- }
-}
-
// Counts accelerator calls.
class TestAcceleratorTarget : public ui::AcceleratorTarget {
public:
@@ -1453,199 +353,6 @@ TEST_F(FocusManagerTest, CallsSelfDeletingAcceleratorTarget) {
EXPECT_EQ(target.accelerator_count(), 1);
}
-class MessageTrackingView : public View {
- public:
- MessageTrackingView() : accelerator_pressed_(false) {
- }
-
- virtual bool OnKeyPressed(const KeyEvent& e) {
- keys_pressed_.push_back(e.key_code());
- return true;
- }
-
- virtual bool OnKeyReleased(const KeyEvent& e) {
- keys_released_.push_back(e.key_code());
- return true;
- }
-
- virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) {
- accelerator_pressed_ = true;
- return true;
- }
-
- void Reset() {
- accelerator_pressed_ = false;
- keys_pressed_.clear();
- keys_released_.clear();
- }
-
- const std::vector<ui::KeyboardCode>& keys_pressed() const {
- return keys_pressed_;
- }
-
- const std::vector<ui::KeyboardCode>& keys_released() const {
- return keys_released_;
- }
-
- bool accelerator_pressed() const {
- return accelerator_pressed_;
- }
-
- private:
- bool accelerator_pressed_;
- std::vector<ui::KeyboardCode> keys_pressed_;
- std::vector<ui::KeyboardCode> keys_released_;
-
- DISALLOW_COPY_AND_ASSIGN(MessageTrackingView);
-};
-
-#if defined(OS_WIN)
-// This test is now Windows only. Linux Views port does not handle accelerator
-// keys in AcceleratorHandler anymore. The logic has been moved into
-// NativeWidgetGtk::OnKeyEvent().
-// Tests that the keyup messages are eaten for accelerators.
-TEST_F(FocusManagerTest, IgnoreKeyupForAccelerators) {
- FocusManager* focus_manager = GetFocusManager();
- MessageTrackingView* mtv = new MessageTrackingView();
- mtv->AddAccelerator(ui::Accelerator(ui::VKEY_0, false, false, false));
- mtv->AddAccelerator(ui::Accelerator(ui::VKEY_1, false, false, false));
- content_view_->AddChildView(mtv);
- focus_manager->SetFocusedView(mtv);
-
- // First send a non-accelerator key sequence.
- PostKeyDown(ui::VKEY_9);
- PostKeyUp(ui::VKEY_9);
- AcceleratorHandler accelerator_handler;
- MessageLoopForUI::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
- MessageLoopForUI::current()->RunWithDispatcher(&accelerator_handler);
- // Make sure we get a key-up and key-down.
- ASSERT_EQ(1U, mtv->keys_pressed().size());
- EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[0]);
- ASSERT_EQ(1U, mtv->keys_released().size());
- EXPECT_EQ(ui::VKEY_9, mtv->keys_released()[0]);
- EXPECT_FALSE(mtv->accelerator_pressed());
- mtv->Reset();
-
- // Same thing with repeat and more than one key at once.
- PostKeyDown(ui::VKEY_9);
- PostKeyDown(ui::VKEY_9);
- PostKeyDown(ui::VKEY_8);
- PostKeyDown(ui::VKEY_9);
- PostKeyDown(ui::VKEY_7);
- PostKeyUp(ui::VKEY_9);
- PostKeyUp(ui::VKEY_7);
- PostKeyUp(ui::VKEY_8);
- MessageLoopForUI::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
- MessageLoopForUI::current()->RunWithDispatcher(&accelerator_handler);
- // Make sure we get a key-up and key-down.
- ASSERT_EQ(5U, mtv->keys_pressed().size());
- EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[0]);
- EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[1]);
- EXPECT_EQ(ui::VKEY_8, mtv->keys_pressed()[2]);
- EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[3]);
- EXPECT_EQ(ui::VKEY_7, mtv->keys_pressed()[4]);
- ASSERT_EQ(3U, mtv->keys_released().size());
- EXPECT_EQ(ui::VKEY_9, mtv->keys_released()[0]);
- EXPECT_EQ(ui::VKEY_7, mtv->keys_released()[1]);
- EXPECT_EQ(ui::VKEY_8, mtv->keys_released()[2]);
- EXPECT_FALSE(mtv->accelerator_pressed());
- mtv->Reset();
-
- // Now send an accelerator key sequence.
- PostKeyDown(ui::VKEY_0);
- PostKeyUp(ui::VKEY_0);
- MessageLoopForUI::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
- MessageLoopForUI::current()->RunWithDispatcher(&accelerator_handler);
- EXPECT_TRUE(mtv->keys_pressed().empty());
- EXPECT_TRUE(mtv->keys_released().empty());
- EXPECT_TRUE(mtv->accelerator_pressed());
- mtv->Reset();
-
- // Same thing with repeat and more than one key at once.
- PostKeyDown(ui::VKEY_0);
- PostKeyDown(ui::VKEY_1);
- PostKeyDown(ui::VKEY_1);
- PostKeyDown(ui::VKEY_0);
- PostKeyDown(ui::VKEY_0);
- PostKeyUp(ui::VKEY_1);
- PostKeyUp(ui::VKEY_0);
- MessageLoopForUI::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
- MessageLoopForUI::current()->RunWithDispatcher(&accelerator_handler);
- EXPECT_TRUE(mtv->keys_pressed().empty());
- EXPECT_TRUE(mtv->keys_released().empty());
- EXPECT_TRUE(mtv->accelerator_pressed());
- mtv->Reset();
-}
-#endif
-
-#if defined(OS_WIN) && !defined(USE_AURA)
-// Test that the focus manager is created successfully for the first view
-// window parented to a native dialog.
-TEST_F(FocusManagerTest, CreationForNativeRoot) {
- // Create a window class.
- WNDCLASSEX class_ex;
- memset(&class_ex, 0, sizeof(class_ex));
- class_ex.cbSize = sizeof(WNDCLASSEX);
- class_ex.lpfnWndProc = &DefWindowProc;
- class_ex.lpszClassName = L"TestWindow";
- ATOM atom = RegisterClassEx(&class_ex);
- ASSERT_TRUE(atom);
-
- // Create a native dialog window.
- HWND hwnd = CreateWindowEx(0, class_ex.lpszClassName, NULL,
- WS_OVERLAPPEDWINDOW, 0, 0, 200, 200,
- NULL, NULL, NULL, NULL);
- ASSERT_TRUE(hwnd);
-
- // Create a view window parented to native dialog.
- scoped_ptr<Widget> widget1(new Widget);
- Widget::InitParams params(Widget::InitParams::TYPE_CONTROL);
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.parent = hwnd;
- params.bounds = gfx::Rect(0, 0, 100, 100);
- params.top_level = true; // This is top level in views hierarchy.
- widget1->Init(params);
-
- // Get the focus manager directly from the first window. Should exist
- // because the first window is the root widget.
- views::FocusManager* focus_manager1 = widget1->GetFocusManager();
- EXPECT_TRUE(focus_manager1);
-
- // Create another view window parented to the first view window.
- scoped_ptr<Widget> widget2(new Widget);
- params.parent = widget1->GetNativeView();
- params.top_level = false; // This is child widget.
- widget2->Init(params);
-
- // Access the shared focus manager directly from the second window.
- views::FocusManager* focus_manager2 = widget2->GetFocusManager();
- EXPECT_EQ(focus_manager2, focus_manager1);
-
- // Access the shared focus manager indirectly from the first window handle.
- gfx::NativeWindow native_window = widget1->GetNativeWindow();
- views::Widget* widget =
- views::Widget::GetWidgetForNativeWindow(native_window);
- EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
-
- // Access the shared focus manager indirectly from the second window handle.
- native_window = widget2->GetNativeWindow();
- widget = views::Widget::GetWidgetForNativeWindow(native_window);
- EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
-
- // Access the shared focus manager indirectly from the first view handle.
- gfx::NativeView native_view = widget1->GetNativeView();
- widget = views::Widget::GetTopLevelWidgetForNativeView(native_view);
- EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
-
- // Access the shared focus manager indirectly from the second view handle.
- native_view = widget2->GetNativeView();
- widget = views::Widget::GetTopLevelWidgetForNativeView(native_view);
- EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
-
- DestroyWindow(hwnd);
-}
-#endif
-
class FocusManagerDtorTest : public FocusManagerTest {
protected:
typedef std::vector<std::string> DtorTrackVector;
@@ -1713,22 +420,18 @@ class FocusManagerDtorTest : public FocusManagerTest {
ViewsTestBase::SetUp();
FocusManagerFactory::Install(new TestFocusManagerFactory(&dtor_tracker_));
// Create WindowDtorTracked that uses FocusManagerDtorTracked.
- window_ = new WindowDtorTracked(&dtor_tracker_);
+ Widget* widget = new WindowDtorTracked(&dtor_tracker_);
Widget::InitParams params;
params.delegate = this;
params.bounds = gfx::Rect(0, 0, 100, 100);
- window_->Init(params);
+ widget->Init(params);
tracked_focus_manager_ =
static_cast<FocusManagerDtorTracked*>(GetFocusManager());
- window_->Show();
+ widget->Show();
}
virtual void TearDown() {
- if (window_) {
- window_->Close();
- RunPendingMessages();
- }
FocusManagerFactory::Install(NULL);
ViewsTestBase::TearDown();
}
@@ -1737,17 +440,18 @@ class FocusManagerDtorTest : public FocusManagerTest {
DtorTrackVector dtor_tracker_;
};
+#if !defined(USE_AURA)
TEST_F(FocusManagerDtorTest, FocusManagerDestructedLast) {
// Setup views hierarchy.
TabbedPane* tabbed_pane = new TabbedPane();
- content_view_->AddChildView(tabbed_pane);
+ GetContentsView()->AddChildView(tabbed_pane);
NativeButtonDtorTracked* button = new NativeButtonDtorTracked(
ASCIIToUTF16("button"), &dtor_tracker_);
tabbed_pane->AddTab(ASCIIToUTF16("Awesome tab"), button);
// Close the window.
- window_->Close();
+ GetWidget()->Close();
RunPendingMessages();
// Test window, button and focus manager should all be destructed.
@@ -1755,9 +459,7 @@ TEST_F(FocusManagerDtorTest, FocusManagerDestructedLast) {
// Focus manager should be the last one to destruct.
ASSERT_STREQ("FocusManagerDtorTracked", dtor_tracker_[2].c_str());
-
- // Clear window_ so that we don't try to close it again.
- window_ = NULL;
}
+#endif
} // namespace views
diff --git a/ui/views/focus/focus_manager_unittest_win.cc b/ui/views/focus/focus_manager_unittest_win.cc
new file mode 100644
index 0000000..4744d8d
--- /dev/null
+++ b/ui/views/focus/focus_manager_unittest_win.cc
@@ -0,0 +1,285 @@
+// 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/focus/focus_manager.h"
+
+#include "base/utf_string_conversions.h"
+#include "ui/views/focus/accelerator_handler.h"
+#include "ui/views/focus/focus_manager_test.h"
+#include "ui/views/widget/widget.h"
+#include "views/controls/button/text_button.h"
+
+namespace views {
+
+namespace {
+
+class MessageTrackingView : public View {
+ public:
+ MessageTrackingView() : accelerator_pressed_(false) {
+ }
+
+ void Reset() {
+ accelerator_pressed_ = false;
+ keys_pressed_.clear();
+ keys_released_.clear();
+ }
+
+ const std::vector<ui::KeyboardCode>& keys_pressed() const {
+ return keys_pressed_;
+ }
+
+ const std::vector<ui::KeyboardCode>& keys_released() const {
+ return keys_released_;
+ }
+
+ bool accelerator_pressed() const {
+ return accelerator_pressed_;
+ }
+
+ // Overridden from View:
+ virtual bool OnKeyPressed(const KeyEvent& e) OVERRIDE {
+ keys_pressed_.push_back(e.key_code());
+ return true;
+ }
+ virtual bool OnKeyReleased(const KeyEvent& e) OVERRIDE {
+ keys_released_.push_back(e.key_code());
+ return true;
+ }
+ virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE {
+ accelerator_pressed_ = true;
+ return true;
+ }
+
+ private:
+ bool accelerator_pressed_;
+ std::vector<ui::KeyboardCode> keys_pressed_;
+ std::vector<ui::KeyboardCode> keys_released_;
+
+ DISALLOW_COPY_AND_ASSIGN(MessageTrackingView);
+};
+
+} // namespace
+
+// Test that when activating/deactivating the top window, the focus is stored/
+// restored properly.
+TEST_F(FocusManagerTest, FocusStoreRestore) {
+ // Simulate an activate, otherwise the deactivate isn't going to do anything.
+ SimulateActivateWindow();
+
+ NativeTextButton* button = new NativeTextButton(NULL,
+ ASCIIToUTF16("Press me"));
+ View* view = new View();
+ view->set_focusable(true);
+
+ GetContentsView()->AddChildView(button);
+ button->SetBounds(10, 10, 200, 30);
+ GetContentsView()->AddChildView(view);
+ RunPendingMessages();
+
+ TestFocusChangeListener listener;
+ AddFocusChangeListener(&listener);
+
+ view->RequestFocus();
+ RunPendingMessages();
+ // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
+
+ // Visual Studio 2010 has problems converting NULL to the null pointer for
+ // std::pair. See http://connect.microsoft.com/VisualStudio/feedback/details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair
+ // It will work if we pass nullptr.
+#if defined(_MSC_VER) && _MSC_VER >= 1600
+ views::View* null_view = nullptr;
+#else
+ views::View* null_view = NULL;
+#endif
+
+ // Deacivate the window, it should store its focus.
+ SimulateDeactivateWindow();
+ EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView());
+ ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size()));
+ EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view));
+ EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(view, null_view));
+ listener.ClearFocusChanges();
+
+ // Reactivate, focus should come-back to the previously focused view.
+ SimulateActivateWindow();
+ EXPECT_EQ(view, GetFocusManager()->GetFocusedView());
+ ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size()));
+ EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view));
+ listener.ClearFocusChanges();
+
+ // Same test with a NativeControl.
+ button->RequestFocus();
+ SimulateDeactivateWindow();
+ EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView());
+ ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size()));
+ EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view, button));
+ EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(button, null_view));
+ listener.ClearFocusChanges();
+
+ SimulateActivateWindow();
+ EXPECT_EQ(button, GetFocusManager()->GetFocusedView());
+ ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size()));
+ EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, button));
+ listener.ClearFocusChanges();
+
+ /*
+ // Now test that while the window is inactive we can change the focused view
+ // (we do that in several places).
+ SimulateDeactivateWindow();
+ // TODO: would have to mock the window being inactive (with a TestWidgetWin
+ // that would return false on IsActive()).
+ GetFocusManager()->SetFocusedView(view);
+ ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_ACTIVE, NULL);
+
+ EXPECT_EQ(view, GetFocusManager()->GetFocusedView());
+ ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size()));
+ EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(button, null_view));
+ EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(null_view, view));
+ */
+}
+
+// Test that the focus manager is created successfully for the first view
+// window parented to a native dialog.
+TEST_F(FocusManagerTest, CreationForNativeRoot) {
+ // Create a window class.
+ WNDCLASSEX class_ex;
+ memset(&class_ex, 0, sizeof(class_ex));
+ class_ex.cbSize = sizeof(WNDCLASSEX);
+ class_ex.lpfnWndProc = &DefWindowProc;
+ class_ex.lpszClassName = L"TestWindow";
+ ATOM atom = RegisterClassEx(&class_ex);
+ ASSERT_TRUE(atom);
+
+ // Create a native dialog window.
+ HWND hwnd = CreateWindowEx(0, class_ex.lpszClassName, NULL,
+ WS_OVERLAPPEDWINDOW, 0, 0, 200, 200,
+ NULL, NULL, NULL, NULL);
+ ASSERT_TRUE(hwnd);
+
+ // Create a view window parented to native dialog.
+ scoped_ptr<Widget> widget1(new Widget);
+ Widget::InitParams params(Widget::InitParams::TYPE_CONTROL);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.parent = hwnd;
+ params.bounds = gfx::Rect(0, 0, 100, 100);
+ params.top_level = true; // This is top level in views hierarchy.
+ widget1->Init(params);
+
+ // Get the focus manager directly from the first window. Should exist
+ // because the first window is the root widget.
+ views::FocusManager* focus_manager1 = widget1->GetFocusManager();
+ EXPECT_TRUE(focus_manager1);
+
+ // Create another view window parented to the first view window.
+ scoped_ptr<Widget> widget2(new Widget);
+ params.parent = widget1->GetNativeView();
+ params.top_level = false; // This is child widget.
+ widget2->Init(params);
+
+ // Access the shared focus manager directly from the second window.
+ views::FocusManager* focus_manager2 = widget2->GetFocusManager();
+ EXPECT_EQ(focus_manager2, focus_manager1);
+
+ // Access the shared focus manager indirectly from the first window handle.
+ gfx::NativeWindow native_window = widget1->GetNativeWindow();
+ views::Widget* widget =
+ views::Widget::GetWidgetForNativeWindow(native_window);
+ EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
+
+ // Access the shared focus manager indirectly from the second window handle.
+ native_window = widget2->GetNativeWindow();
+ widget = views::Widget::GetWidgetForNativeWindow(native_window);
+ EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
+
+ // Access the shared focus manager indirectly from the first view handle.
+ gfx::NativeView native_view = widget1->GetNativeView();
+ widget = views::Widget::GetTopLevelWidgetForNativeView(native_view);
+ EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
+
+ // Access the shared focus manager indirectly from the second view handle.
+ native_view = widget2->GetNativeView();
+ widget = views::Widget::GetTopLevelWidgetForNativeView(native_view);
+ EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
+
+ DestroyWindow(hwnd);
+}
+
+// Tests that the keyup messages are eaten for accelerators.
+// Windows-only, Windows is the only platform that handles accelerators in
+// AcceleratorHandler. NativeWidgetAura/NativeWidgetGtk::OnKeyEvent handles
+// them in other configurations.
+TEST_F(FocusManagerTest, IgnoreKeyupForAccelerators) {
+ FocusManager* focus_manager = GetFocusManager();
+ MessageTrackingView* mtv = new MessageTrackingView();
+ mtv->AddAccelerator(ui::Accelerator(ui::VKEY_0, false, false, false));
+ mtv->AddAccelerator(ui::Accelerator(ui::VKEY_1, false, false, false));
+ GetContentsView()->AddChildView(mtv);
+ focus_manager->SetFocusedView(mtv);
+
+ // First send a non-accelerator key sequence.
+ PostKeyDown(ui::VKEY_9);
+ PostKeyUp(ui::VKEY_9);
+ AcceleratorHandler accelerator_handler;
+ MessageLoopForUI::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ MessageLoopForUI::current()->RunWithDispatcher(&accelerator_handler);
+ // Make sure we get a key-up and key-down.
+ ASSERT_EQ(1U, mtv->keys_pressed().size());
+ EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[0]);
+ ASSERT_EQ(1U, mtv->keys_released().size());
+ EXPECT_EQ(ui::VKEY_9, mtv->keys_released()[0]);
+ EXPECT_FALSE(mtv->accelerator_pressed());
+ mtv->Reset();
+
+ // Same thing with repeat and more than one key at once.
+ PostKeyDown(ui::VKEY_9);
+ PostKeyDown(ui::VKEY_9);
+ PostKeyDown(ui::VKEY_8);
+ PostKeyDown(ui::VKEY_9);
+ PostKeyDown(ui::VKEY_7);
+ PostKeyUp(ui::VKEY_9);
+ PostKeyUp(ui::VKEY_7);
+ PostKeyUp(ui::VKEY_8);
+ MessageLoopForUI::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ MessageLoopForUI::current()->RunWithDispatcher(&accelerator_handler);
+ // Make sure we get a key-up and key-down.
+ ASSERT_EQ(5U, mtv->keys_pressed().size());
+ EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[0]);
+ EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[1]);
+ EXPECT_EQ(ui::VKEY_8, mtv->keys_pressed()[2]);
+ EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[3]);
+ EXPECT_EQ(ui::VKEY_7, mtv->keys_pressed()[4]);
+ ASSERT_EQ(3U, mtv->keys_released().size());
+ EXPECT_EQ(ui::VKEY_9, mtv->keys_released()[0]);
+ EXPECT_EQ(ui::VKEY_7, mtv->keys_released()[1]);
+ EXPECT_EQ(ui::VKEY_8, mtv->keys_released()[2]);
+ EXPECT_FALSE(mtv->accelerator_pressed());
+ mtv->Reset();
+
+ // Now send an accelerator key sequence.
+ PostKeyDown(ui::VKEY_0);
+ PostKeyUp(ui::VKEY_0);
+ MessageLoopForUI::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ MessageLoopForUI::current()->RunWithDispatcher(&accelerator_handler);
+ EXPECT_TRUE(mtv->keys_pressed().empty());
+ EXPECT_TRUE(mtv->keys_released().empty());
+ EXPECT_TRUE(mtv->accelerator_pressed());
+ mtv->Reset();
+
+ // Same thing with repeat and more than one key at once.
+ PostKeyDown(ui::VKEY_0);
+ PostKeyDown(ui::VKEY_1);
+ PostKeyDown(ui::VKEY_1);
+ PostKeyDown(ui::VKEY_0);
+ PostKeyDown(ui::VKEY_0);
+ PostKeyUp(ui::VKEY_1);
+ PostKeyUp(ui::VKEY_0);
+ MessageLoopForUI::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ MessageLoopForUI::current()->RunWithDispatcher(&accelerator_handler);
+ EXPECT_TRUE(mtv->keys_pressed().empty());
+ EXPECT_TRUE(mtv->keys_released().empty());
+ EXPECT_TRUE(mtv->accelerator_pressed());
+ mtv->Reset();
+}
+
+} // namespace views
diff --git a/ui/views/focus/focus_traversal_unittest.cc b/ui/views/focus/focus_traversal_unittest.cc
new file mode 100644
index 0000000..87bfc26
--- /dev/null
+++ b/ui/views/focus/focus_traversal_unittest.cc
@@ -0,0 +1,812 @@
+// 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/focus/focus_manager.h"
+
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "ui/base/models/combobox_model.h"
+#include "ui/views/focus/focus_manager_test.h"
+#include "ui/views/widget/root_view.h"
+#include "ui/views/widget/widget.h"
+#include "views/controls/button/checkbox.h"
+#include "views/controls/button/radio_button.h"
+#include "views/controls/button/text_button.h"
+#include "views/controls/combobox/combobox.h"
+#include "views/controls/label.h"
+#include "views/controls/link.h"
+#include "views/controls/native/native_view_host.h"
+#include "views/controls/scroll_view.h"
+#include "views/controls/textfield/textfield.h"
+
+#if !defined(USE_AURA)
+#include "views/controls/tabbed_pane/tabbed_pane.h"
+#endif
+
+namespace views {
+
+namespace {
+
+int count = 1;
+
+const int kTopCheckBoxID = count++; // 1
+const int kLeftContainerID = count++;
+const int kAppleLabelID = count++;
+const int kAppleTextfieldID = count++;
+const int kOrangeLabelID = count++; // 5
+const int kOrangeTextfieldID = count++;
+const int kBananaLabelID = count++;
+const int kBananaTextfieldID = count++;
+const int kKiwiLabelID = count++;
+const int kKiwiTextfieldID = count++; // 10
+const int kFruitButtonID = count++;
+const int kFruitCheckBoxID = count++;
+const int kComboboxID = count++;
+
+const int kRightContainerID = count++;
+const int kAsparagusButtonID = count++; // 15
+const int kBroccoliButtonID = count++;
+const int kCauliflowerButtonID = count++;
+
+const int kInnerContainerID = count++;
+const int kScrollViewID = count++;
+const int kRosettaLinkID = count++; // 20
+const int kStupeurEtTremblementLinkID = count++;
+const int kDinerGameLinkID = count++;
+const int kRidiculeLinkID = count++;
+const int kClosetLinkID = count++;
+const int kVisitingLinkID = count++; // 25
+const int kAmelieLinkID = count++;
+const int kJoyeuxNoelLinkID = count++;
+const int kCampingLinkID = count++;
+const int kBriceDeNiceLinkID = count++;
+const int kTaxiLinkID = count++; // 30
+const int kAsterixLinkID = count++;
+
+const int kOKButtonID = count++;
+const int kCancelButtonID = count++;
+const int kHelpButtonID = count++;
+
+#if !defined(USE_AURA)
+const int kStyleContainerID = count++; // 35
+const int kBoldCheckBoxID = count++;
+const int kItalicCheckBoxID = count++;
+const int kUnderlinedCheckBoxID = count++;
+const int kStyleHelpLinkID = count++;
+const int kStyleTextEditID = count++; // 40
+#endif
+
+const int kSearchContainerID = count++;
+const int kSearchTextfieldID = count++;
+const int kSearchButtonID = count++;
+const int kHelpLinkID = count++;
+
+const int kThumbnailContainerID = count++; // 45
+const int kThumbnailStarID = count++;
+const int kThumbnailSuperStarID = count++;
+
+class DummyComboboxModel : public ui::ComboboxModel {
+ public:
+ virtual int GetItemCount() { return 10; }
+
+ virtual string16 GetItemAt(int index) {
+ return ASCIIToUTF16("Item ") + base::IntToString16(index);
+ }
+};
+
+// A View that can act as a pane.
+class PaneView : public View, public FocusTraversable {
+ public:
+ PaneView() : focus_search_(NULL) {}
+
+ // If this method is called, this view will use GetPaneFocusTraversable to
+ // have this provided FocusSearch used instead of the default one, allowing
+ // you to trap focus within the pane.
+ void EnablePaneFocus(FocusSearch* focus_search) {
+ focus_search_ = focus_search;
+ }
+
+ // Overridden from views::View:
+ virtual FocusTraversable* GetPaneFocusTraversable() {
+ if (focus_search_)
+ return this;
+ else
+ return NULL;
+ }
+
+ // Overridden from views::FocusTraversable:
+ virtual views::FocusSearch* GetFocusSearch() {
+ return focus_search_;
+ }
+ virtual FocusTraversable* GetFocusTraversableParent() {
+ return NULL;
+ }
+ virtual View* GetFocusTraversableParentView() {
+ return NULL;
+ }
+
+ private:
+ FocusSearch* focus_search_;
+};
+
+// BorderView is a view containing a native window with its own view hierarchy.
+// It is interesting to test focus traversal from a view hierarchy to an inner
+// view hierarchy.
+class BorderView : public NativeViewHost {
+ public:
+ explicit BorderView(View* child) : child_(child), widget_(NULL) {
+ DCHECK(child);
+ set_focusable(false);
+ }
+
+ virtual ~BorderView() {}
+
+ virtual internal::RootView* GetContentsRootView() {
+ return static_cast<internal::RootView*>(widget_->GetRootView());
+ }
+
+ virtual FocusTraversable* GetFocusTraversable() {
+ return static_cast<internal::RootView*>(widget_->GetRootView());
+ }
+
+ virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child) {
+ NativeViewHost::ViewHierarchyChanged(is_add, parent, child);
+
+ if (child == this && is_add) {
+ if (!widget_) {
+ widget_ = new Widget;
+ Widget::InitParams params(Widget::InitParams::TYPE_CONTROL);
+#if defined(OS_WIN) || defined(USE_AURA)
+ params.parent = parent->GetWidget()->GetNativeView();
+#elif defined(TOOLKIT_USES_GTK)
+ params.parent = native_view();
+#else
+ NOTREACHED();
+#endif
+ widget_->Init(params);
+ widget_->SetFocusTraversableParentView(this);
+ widget_->SetContentsView(child_);
+ }
+
+ // We have been added to a view hierarchy, attach the native view.
+ Attach(widget_->GetNativeView());
+ // Also update the FocusTraversable parent so the focus traversal works.
+ static_cast<internal::RootView*>(widget_->GetRootView())->
+ SetFocusTraversableParent(GetWidget()->GetFocusTraversable());
+ }
+ }
+
+ private:
+ View* child_;
+ Widget* widget_;
+
+ DISALLOW_COPY_AND_ASSIGN(BorderView);
+};
+
+} // namespace
+
+class FocusTraversalTest : public FocusManagerTest {
+ public:
+ ~FocusTraversalTest();
+
+ virtual void InitContentView() OVERRIDE;
+
+ protected:
+ FocusTraversalTest();
+
+ View* FindViewByID(int id) {
+ View* view = GetContentsView()->GetViewByID(id);
+ if (view)
+ return view;
+#if !defined(USE_AURA)
+ if (style_tab_)
+ view = style_tab_->GetSelectedTab()->GetViewByID(id);
+#endif
+ if (view)
+ return view;
+ view = search_border_view_->GetContentsRootView()->GetViewByID(id);
+ if (view)
+ return view;
+ return NULL;
+ }
+
+ protected:
+#if !defined(USE_AURA)
+ TabbedPane* style_tab_;
+#endif
+ BorderView* search_border_view_;
+ DummyComboboxModel combobox_model_;
+ PaneView* left_container_;
+ PaneView* right_container_;
+
+ DISALLOW_COPY_AND_ASSIGN(FocusTraversalTest);
+};
+
+FocusTraversalTest::FocusTraversalTest()
+ :
+#if !defined(USE_AURA)
+ style_tab_(NULL),
+#endif
+ search_border_view_(NULL) {
+}
+
+FocusTraversalTest::~FocusTraversalTest() {
+}
+
+void FocusTraversalTest::InitContentView() {
+ // Create a complicated view hierarchy with lots of control types for
+ // use by all of the focus traversal tests.
+ //
+ // Class name, ID, and asterisk next to focusable views:
+ //
+ // View
+ // Checkbox * kTopCheckBoxID
+ // PaneView kLeftContainerID
+ // Label kAppleLabelID
+ // Textfield * kAppleTextfieldID
+ // Label kOrangeLabelID
+ // Textfield * kOrangeTextfieldID
+ // Label kBananaLabelID
+ // Textfield * kBananaTextfieldID
+ // Label kKiwiLabelID
+ // Textfield * kKiwiTextfieldID
+ // NativeButton * kFruitButtonID
+ // Checkbox * kFruitCheckBoxID
+ // Combobox * kComboboxID
+ // PaneView kRightContainerID
+ // RadioButton * kAsparagusButtonID
+ // RadioButton * kBroccoliButtonID
+ // RadioButton * kCauliflowerButtonID
+ // View kInnerContainerID
+ // ScrollView kScrollViewID
+ // View
+ // Link * kRosettaLinkID
+ // Link * kStupeurEtTremblementLinkID
+ // Link * kDinerGameLinkID
+ // Link * kRidiculeLinkID
+ // Link * kClosetLinkID
+ // Link * kVisitingLinkID
+ // Link * kAmelieLinkID
+ // Link * kJoyeuxNoelLinkID
+ // Link * kCampingLinkID
+ // Link * kBriceDeNiceLinkID
+ // Link * kTaxiLinkID
+ // Link * kAsterixLinkID
+ // NativeButton * kOKButtonID
+ // NativeButton * kCancelButtonID
+ // NativeButton * kHelpButtonID
+ // #if !defined(USE_AURA)
+ // TabbedPane * kStyleContainerID
+ // View
+ // Checkbox * kBoldCheckBoxID
+ // Checkbox * kItalicCheckBoxID
+ // Checkbox * kUnderlinedCheckBoxID
+ // Link * kStyleHelpLinkID
+ // Textfield * kStyleTextEditID
+ // Other
+ // #endif
+ // BorderView kSearchContainerID
+ // View
+ // Textfield * kSearchTextfieldID
+ // NativeButton * kSearchButtonID
+ // Link * kHelpLinkID
+ // View * kThumbnailContainerID
+ // NativeButton * kThumbnailStarID
+ // NativeButton * kThumbnailSuperStarID
+
+ GetContentsView()->set_background(
+ Background::CreateSolidBackground(SK_ColorWHITE));
+
+ Checkbox* cb = new Checkbox(ASCIIToUTF16("This is a checkbox"));
+ GetContentsView()->AddChildView(cb);
+ // In this fast paced world, who really has time for non hard-coded layout?
+ cb->SetBounds(10, 10, 200, 20);
+ cb->set_id(kTopCheckBoxID);
+
+ left_container_ = new PaneView();
+ left_container_->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
+ left_container_->set_background(
+ Background::CreateSolidBackground(240, 240, 240));
+ left_container_->set_id(kLeftContainerID);
+ GetContentsView()->AddChildView(left_container_);
+ left_container_->SetBounds(10, 35, 250, 200);
+
+ int label_x = 5;
+ int label_width = 50;
+ int label_height = 15;
+ int text_field_width = 150;
+ int y = 10;
+ int gap_between_labels = 10;
+
+ Label* label = new Label(ASCIIToUTF16("Apple:"));
+ label->set_id(kAppleLabelID);
+ left_container_->AddChildView(label);
+ label->SetBounds(label_x, y, label_width, label_height);
+
+ Textfield* text_field = new Textfield();
+ text_field->set_id(kAppleTextfieldID);
+ left_container_->AddChildView(text_field);
+ text_field->SetBounds(label_x + label_width + 5, y,
+ text_field_width, label_height);
+
+ y += label_height + gap_between_labels;
+
+ label = new Label(ASCIIToUTF16("Orange:"));
+ label->set_id(kOrangeLabelID);
+ left_container_->AddChildView(label);
+ label->SetBounds(label_x, y, label_width, label_height);
+
+ text_field = new Textfield();
+ text_field->set_id(kOrangeTextfieldID);
+ left_container_->AddChildView(text_field);
+ text_field->SetBounds(label_x + label_width + 5, y,
+ text_field_width, label_height);
+
+ y += label_height + gap_between_labels;
+
+ label = new Label(ASCIIToUTF16("Banana:"));
+ label->set_id(kBananaLabelID);
+ left_container_->AddChildView(label);
+ label->SetBounds(label_x, y, label_width, label_height);
+
+ text_field = new Textfield();
+ text_field->set_id(kBananaTextfieldID);
+ left_container_->AddChildView(text_field);
+ text_field->SetBounds(label_x + label_width + 5, y,
+ text_field_width, label_height);
+
+ y += label_height + gap_between_labels;
+
+ label = new Label(ASCIIToUTF16("Kiwi:"));
+ label->set_id(kKiwiLabelID);
+ left_container_->AddChildView(label);
+ label->SetBounds(label_x, y, label_width, label_height);
+
+ text_field = new Textfield();
+ text_field->set_id(kKiwiTextfieldID);
+ left_container_->AddChildView(text_field);
+ text_field->SetBounds(label_x + label_width + 5, y,
+ text_field_width, label_height);
+
+ y += label_height + gap_between_labels;
+
+ NativeTextButton* button = new NativeTextButton(NULL,
+ ASCIIToUTF16("Click me"));
+ button->SetBounds(label_x, y + 10, 80, 30);
+ button->set_id(kFruitButtonID);
+ left_container_->AddChildView(button);
+ y += 40;
+
+ cb = new Checkbox(ASCIIToUTF16("This is another check box"));
+ cb->SetBounds(label_x + label_width + 5, y, 180, 20);
+ cb->set_id(kFruitCheckBoxID);
+ left_container_->AddChildView(cb);
+ y += 20;
+
+ Combobox* combobox = new Combobox(&combobox_model_);
+ combobox->SetBounds(label_x + label_width + 5, y, 150, 30);
+ combobox->set_id(kComboboxID);
+ left_container_->AddChildView(combobox);
+
+ right_container_ = new PaneView();
+ right_container_->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
+ right_container_->set_background(
+ Background::CreateSolidBackground(240, 240, 240));
+ right_container_->set_id(kRightContainerID);
+ GetContentsView()->AddChildView(right_container_);
+ right_container_->SetBounds(270, 35, 300, 200);
+
+ y = 10;
+ int radio_button_height = 18;
+ int gap_between_radio_buttons = 10;
+ RadioButton* radio_button = new RadioButton(ASCIIToUTF16("Asparagus"), 1);
+ radio_button->set_id(kAsparagusButtonID);
+ right_container_->AddChildView(radio_button);
+ radio_button->SetBounds(5, y, 70, radio_button_height);
+ radio_button->SetGroup(1);
+ y += radio_button_height + gap_between_radio_buttons;
+ radio_button = new RadioButton(ASCIIToUTF16("Broccoli"), 1);
+ radio_button->set_id(kBroccoliButtonID);
+ right_container_->AddChildView(radio_button);
+ radio_button->SetBounds(5, y, 70, radio_button_height);
+ radio_button->SetGroup(1);
+ RadioButton* radio_button_to_check = radio_button;
+ y += radio_button_height + gap_between_radio_buttons;
+ radio_button = new RadioButton(ASCIIToUTF16("Cauliflower"), 1);
+ radio_button->set_id(kCauliflowerButtonID);
+ right_container_->AddChildView(radio_button);
+ radio_button->SetBounds(5, y, 70, radio_button_height);
+ radio_button->SetGroup(1);
+ y += radio_button_height + gap_between_radio_buttons;
+
+ View* inner_container = new View();
+ inner_container->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
+ inner_container->set_background(
+ Background::CreateSolidBackground(230, 230, 230));
+ inner_container->set_id(kInnerContainerID);
+ right_container_->AddChildView(inner_container);
+ inner_container->SetBounds(100, 10, 150, 180);
+
+ ScrollView* scroll_view = new ScrollView();
+ scroll_view->set_id(kScrollViewID);
+ inner_container->AddChildView(scroll_view);
+ scroll_view->SetBounds(1, 1, 148, 178);
+
+ View* scroll_content = new View();
+ scroll_content->SetBounds(0, 0, 200, 200);
+ scroll_content->set_background(
+ Background::CreateSolidBackground(200, 200, 200));
+ scroll_view->SetContents(scroll_content);
+
+ static const char* const kTitles[] = {
+ "Rosetta", "Stupeur et tremblement", "The diner game",
+ "Ridicule", "Le placard", "Les Visiteurs", "Amelie",
+ "Joyeux Noel", "Camping", "Brice de Nice",
+ "Taxi", "Asterix"
+ };
+
+ static const int kIDs[] = {
+ kRosettaLinkID, kStupeurEtTremblementLinkID, kDinerGameLinkID,
+ kRidiculeLinkID, kClosetLinkID, kVisitingLinkID, kAmelieLinkID,
+ kJoyeuxNoelLinkID, kCampingLinkID, kBriceDeNiceLinkID,
+ kTaxiLinkID, kAsterixLinkID
+ };
+
+ DCHECK(arraysize(kTitles) == arraysize(kIDs));
+
+ y = 5;
+ for (size_t i = 0; i < arraysize(kTitles); ++i) {
+ Link* link = new Link(ASCIIToUTF16(kTitles[i]));
+ link->SetHorizontalAlignment(Label::ALIGN_LEFT);
+ link->set_id(kIDs[i]);
+ scroll_content->AddChildView(link);
+ link->SetBounds(5, y, 300, 15);
+ y += 15;
+ }
+
+ y = 250;
+ int width = 60;
+ button = new NativeTextButton(NULL, ASCIIToUTF16("OK"));
+ button->set_id(kOKButtonID);
+ button->SetIsDefault(true);
+
+ GetContentsView()->AddChildView(button);
+ button->SetBounds(150, y, width, 30);
+
+ button = new NativeTextButton(NULL, ASCIIToUTF16("Cancel"));
+ button->set_id(kCancelButtonID);
+ GetContentsView()->AddChildView(button);
+ button->SetBounds(220, y, width, 30);
+
+ button = new NativeTextButton(NULL, ASCIIToUTF16("Help"));
+ button->set_id(kHelpButtonID);
+ GetContentsView()->AddChildView(button);
+ button->SetBounds(290, y, width, 30);
+
+ y += 40;
+
+ View* contents = NULL;
+ Link* link = NULL;
+
+#if !defined(USE_AURA)
+ // Left bottom box with style checkboxes.
+ contents = new View();
+ contents->set_background(Background::CreateSolidBackground(SK_ColorWHITE));
+ cb = new Checkbox(ASCIIToUTF16("Bold"));
+ contents->AddChildView(cb);
+ cb->SetBounds(10, 10, 50, 20);
+ cb->set_id(kBoldCheckBoxID);
+
+ cb = new Checkbox(ASCIIToUTF16("Italic"));
+ contents->AddChildView(cb);
+ cb->SetBounds(70, 10, 50, 20);
+ cb->set_id(kItalicCheckBoxID);
+
+ cb = new Checkbox(ASCIIToUTF16("Underlined"));
+ contents->AddChildView(cb);
+ cb->SetBounds(130, 10, 70, 20);
+ cb->set_id(kUnderlinedCheckBoxID);
+
+ link = new Link(ASCIIToUTF16("Help"));
+ contents->AddChildView(link);
+ link->SetBounds(10, 35, 70, 10);
+ link->set_id(kStyleHelpLinkID);
+
+ text_field = new Textfield();
+ contents->AddChildView(text_field);
+ text_field->SetBounds(10, 50, 100, 20);
+ text_field->set_id(kStyleTextEditID);
+
+ style_tab_ = new TabbedPane();
+ style_tab_->set_id(kStyleContainerID);
+ GetContentsView()->AddChildView(style_tab_);
+ style_tab_->SetBounds(10, y, 210, 100);
+ style_tab_->AddTab(ASCIIToUTF16("Style"), contents);
+ style_tab_->AddTab(ASCIIToUTF16("Other"), new View());
+#endif
+
+ // Right bottom box with search.
+ contents = new View();
+ contents->set_background(Background::CreateSolidBackground(SK_ColorWHITE));
+ text_field = new Textfield();
+ contents->AddChildView(text_field);
+ text_field->SetBounds(10, 10, 100, 20);
+ text_field->set_id(kSearchTextfieldID);
+
+ button = new NativeTextButton(NULL, ASCIIToUTF16("Search"));
+ contents->AddChildView(button);
+ button->SetBounds(112, 5, 60, 30);
+ button->set_id(kSearchButtonID);
+
+ link = new Link(ASCIIToUTF16("Help"));
+ link->SetHorizontalAlignment(Label::ALIGN_LEFT);
+ link->set_id(kHelpLinkID);
+ contents->AddChildView(link);
+ link->SetBounds(175, 10, 30, 20);
+
+ search_border_view_ = new BorderView(contents);
+ search_border_view_->set_id(kSearchContainerID);
+
+ GetContentsView()->AddChildView(search_border_view_);
+ search_border_view_->SetBounds(300, y, 240, 50);
+
+ y += 60;
+
+ contents = new View();
+ contents->set_focusable(true);
+ contents->set_background(Background::CreateSolidBackground(SK_ColorBLUE));
+ contents->set_id(kThumbnailContainerID);
+ button = new NativeTextButton(NULL, ASCIIToUTF16("Star"));
+ contents->AddChildView(button);
+ button->SetBounds(5, 5, 50, 30);
+ button->set_id(kThumbnailStarID);
+ button = new NativeTextButton(NULL, ASCIIToUTF16("SuperStar"));
+ contents->AddChildView(button);
+ button->SetBounds(60, 5, 100, 30);
+ button->set_id(kThumbnailSuperStarID);
+
+ GetContentsView()->AddChildView(contents);
+ contents->SetBounds(250, y, 200, 50);
+ // We can only call RadioButton::SetChecked() on the radio-button is part of
+ // the view hierarchy.
+ radio_button_to_check->SetChecked(true);
+}
+
+TEST_F(FocusTraversalTest, NormalTraversal) {
+ const int kTraversalIDs[] = { kTopCheckBoxID, kAppleTextfieldID,
+ kOrangeTextfieldID, kBananaTextfieldID, kKiwiTextfieldID,
+ kFruitButtonID, kFruitCheckBoxID, kComboboxID, kBroccoliButtonID,
+ kRosettaLinkID, kStupeurEtTremblementLinkID,
+ kDinerGameLinkID, kRidiculeLinkID, kClosetLinkID, kVisitingLinkID,
+ kAmelieLinkID, kJoyeuxNoelLinkID, kCampingLinkID, kBriceDeNiceLinkID,
+ kTaxiLinkID, kAsterixLinkID, kOKButtonID, kCancelButtonID, kHelpButtonID,
+#if !defined(USE_AURA)
+ kStyleContainerID, kBoldCheckBoxID, kItalicCheckBoxID,
+ kUnderlinedCheckBoxID, kStyleHelpLinkID, kStyleTextEditID,
+#endif
+ kSearchTextfieldID, kSearchButtonID, kHelpLinkID,
+ kThumbnailContainerID, kThumbnailStarID, kThumbnailSuperStarID };
+
+ // Uncomment the following line if you want to test manually the UI of this
+ // test.
+ // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
+
+ // Let's traverse the whole focus hierarchy (several times, to make sure it
+ // loops OK).
+ GetFocusManager()->ClearFocus();
+ for (int i = 0; i < 3; ++i) {
+ for (size_t j = 0; j < arraysize(kTraversalIDs); j++) {
+ GetFocusManager()->AdvanceFocus(false);
+ View* focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kTraversalIDs[j], focused_view->id());
+ }
+ }
+
+ // Let's traverse in reverse order.
+ GetFocusManager()->ClearFocus();
+ for (int i = 0; i < 3; ++i) {
+ for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) {
+ GetFocusManager()->AdvanceFocus(true);
+ View* focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kTraversalIDs[j], focused_view->id());
+ }
+ }
+}
+
+TEST_F(FocusTraversalTest, TraversalWithNonEnabledViews) {
+ const int kDisabledIDs[] = {
+ kBananaTextfieldID, kFruitCheckBoxID, kComboboxID, kAsparagusButtonID,
+ kCauliflowerButtonID, kClosetLinkID, kVisitingLinkID, kBriceDeNiceLinkID,
+ kTaxiLinkID, kAsterixLinkID, kHelpButtonID,
+#if !defined(USE_AURA)
+ kBoldCheckBoxID,
+#endif
+ kSearchTextfieldID, kHelpLinkID };
+
+ const int kTraversalIDs[] = { kTopCheckBoxID, kAppleTextfieldID,
+ kOrangeTextfieldID, kKiwiTextfieldID, kFruitButtonID, kBroccoliButtonID,
+ kRosettaLinkID, kStupeurEtTremblementLinkID, kDinerGameLinkID,
+ kRidiculeLinkID, kAmelieLinkID, kJoyeuxNoelLinkID, kCampingLinkID,
+ kOKButtonID, kCancelButtonID,
+#if !defined(USE_AURA)
+ kStyleContainerID, kItalicCheckBoxID, kUnderlinedCheckBoxID,
+ kStyleHelpLinkID, kStyleTextEditID,
+#endif
+ kSearchButtonID, kThumbnailContainerID, kThumbnailStarID,
+ kThumbnailSuperStarID };
+
+ // Let's disable some views.
+ for (size_t i = 0; i < arraysize(kDisabledIDs); i++) {
+ View* v = FindViewByID(kDisabledIDs[i]);
+ ASSERT_TRUE(v != NULL);
+ v->SetEnabled(false);
+ }
+
+ // Uncomment the following line if you want to test manually the UI of this
+ // test.
+ // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
+
+ View* focused_view;
+ // Let's do one traversal (several times, to make sure it loops ok).
+ GetFocusManager()->ClearFocus();
+ for (int i = 0; i < 3; ++i) {
+ for (size_t j = 0; j < arraysize(kTraversalIDs); j++) {
+ GetFocusManager()->AdvanceFocus(false);
+ focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kTraversalIDs[j], focused_view->id());
+ }
+ }
+
+ // Same thing in reverse.
+ GetFocusManager()->ClearFocus();
+ for (int i = 0; i < 3; ++i) {
+ for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) {
+ GetFocusManager()->AdvanceFocus(true);
+ focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kTraversalIDs[j], focused_view->id());
+ }
+ }
+}
+
+TEST_F(FocusTraversalTest, TraversalWithInvisibleViews) {
+ const int kInvisibleIDs[] = { kTopCheckBoxID, kOKButtonID,
+ kThumbnailContainerID };
+
+ const int kTraversalIDs[] = { kAppleTextfieldID, kOrangeTextfieldID,
+ kBananaTextfieldID, kKiwiTextfieldID, kFruitButtonID, kFruitCheckBoxID,
+ kComboboxID, kBroccoliButtonID, kRosettaLinkID,
+ kStupeurEtTremblementLinkID, kDinerGameLinkID, kRidiculeLinkID,
+ kClosetLinkID, kVisitingLinkID, kAmelieLinkID, kJoyeuxNoelLinkID,
+ kCampingLinkID, kBriceDeNiceLinkID, kTaxiLinkID, kAsterixLinkID,
+ kCancelButtonID, kHelpButtonID,
+#if !defined(USE_AURA)
+ kStyleContainerID, kBoldCheckBoxID, kItalicCheckBoxID,
+ kUnderlinedCheckBoxID, kStyleHelpLinkID, kStyleTextEditID,
+#endif
+ kSearchTextfieldID, kSearchButtonID, kHelpLinkID };
+
+
+ // Let's make some views invisible.
+ for (size_t i = 0; i < arraysize(kInvisibleIDs); i++) {
+ View* v = FindViewByID(kInvisibleIDs[i]);
+ ASSERT_TRUE(v != NULL);
+ v->SetVisible(false);
+ }
+
+ // Uncomment the following line if you want to test manually the UI of this
+ // test.
+ // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
+
+ View* focused_view;
+ // Let's do one traversal (several times, to make sure it loops ok).
+ GetFocusManager()->ClearFocus();
+ for (int i = 0; i < 3; ++i) {
+ for (size_t j = 0; j < arraysize(kTraversalIDs); j++) {
+ GetFocusManager()->AdvanceFocus(false);
+ focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kTraversalIDs[j], focused_view->id());
+ }
+ }
+
+ // Same thing in reverse.
+ GetFocusManager()->ClearFocus();
+ for (int i = 0; i < 3; ++i) {
+ for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) {
+ GetFocusManager()->AdvanceFocus(true);
+ focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kTraversalIDs[j], focused_view->id());
+ }
+ }
+}
+
+TEST_F(FocusTraversalTest, PaneTraversal) {
+ // Tests trapping the traversal within a pane - useful for full
+ // keyboard accessibility for toolbars.
+
+ // First test the left container.
+ const int kLeftTraversalIDs[] = {
+ kAppleTextfieldID,
+ kOrangeTextfieldID, kBananaTextfieldID, kKiwiTextfieldID,
+ kFruitButtonID, kFruitCheckBoxID, kComboboxID };
+
+ FocusSearch focus_search_left(left_container_, true, false);
+ left_container_->EnablePaneFocus(&focus_search_left);
+ FindViewByID(kComboboxID)->RequestFocus();
+
+ // Traverse the focus hierarchy within the pane several times.
+ for (int i = 0; i < 3; ++i) {
+ for (size_t j = 0; j < arraysize(kLeftTraversalIDs); j++) {
+ GetFocusManager()->AdvanceFocus(false);
+ View* focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kLeftTraversalIDs[j], focused_view->id());
+ }
+ }
+
+ // Traverse in reverse order.
+ FindViewByID(kAppleTextfieldID)->RequestFocus();
+ for (int i = 0; i < 3; ++i) {
+ for (int j = arraysize(kLeftTraversalIDs) - 1; j >= 0; --j) {
+ GetFocusManager()->AdvanceFocus(true);
+ View* focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kLeftTraversalIDs[j], focused_view->id());
+ }
+ }
+
+ // Now test the right container, but this time with accessibility mode.
+ // Make some links not focusable, but mark one of them as
+ // "accessibility focusable", so it should show up in the traversal.
+ const int kRightTraversalIDs[] = {
+ kBroccoliButtonID, kDinerGameLinkID, kRidiculeLinkID,
+ kClosetLinkID, kVisitingLinkID, kAmelieLinkID, kJoyeuxNoelLinkID,
+ kCampingLinkID, kBriceDeNiceLinkID, kTaxiLinkID, kAsterixLinkID };
+
+ FocusSearch focus_search_right(right_container_, true, true);
+ right_container_->EnablePaneFocus(&focus_search_right);
+ FindViewByID(kRosettaLinkID)->set_focusable(false);
+ FindViewByID(kStupeurEtTremblementLinkID)->set_focusable(false);
+ FindViewByID(kDinerGameLinkID)->set_accessibility_focusable(true);
+ FindViewByID(kDinerGameLinkID)->set_focusable(false);
+ FindViewByID(kAsterixLinkID)->RequestFocus();
+
+ // Traverse the focus hierarchy within the pane several times.
+ for (int i = 0; i < 3; ++i) {
+ for (size_t j = 0; j < arraysize(kRightTraversalIDs); j++) {
+ GetFocusManager()->AdvanceFocus(false);
+ View* focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kRightTraversalIDs[j], focused_view->id());
+ }
+ }
+
+ // Traverse in reverse order.
+ FindViewByID(kBroccoliButtonID)->RequestFocus();
+ for (int i = 0; i < 3; ++i) {
+ for (int j = arraysize(kRightTraversalIDs) - 1; j >= 0; --j) {
+ GetFocusManager()->AdvanceFocus(true);
+ View* focused_view = GetFocusManager()->GetFocusedView();
+ EXPECT_TRUE(focused_view != NULL);
+ if (focused_view)
+ EXPECT_EQ(kRightTraversalIDs[j], focused_view->id());
+ }
+ }
+}
+
+} // namespace views
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index d8859c0..a49416c 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -510,8 +510,7 @@ void NativeWidgetAura::ClearNativeFocus() {
}
void NativeWidgetAura::FocusNativeView(gfx::NativeView native_view) {
- // http://crbug.com/102572
- NOTIMPLEMENTED();
+ window_->GetFocusManager()->SetFocusedWindow(native_view);
}
gfx::Rect NativeWidgetAura::GetWorkAreaBoundsInScreen() const {