// 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 <utility>
#include <vector>
+#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
+#include "ui/aura/client/focus_client.h"
+#include "ui/aura/window.h"
#include "ui/base/accelerators/accelerator.h"
+#include "ui/base/ime/dummy_text_input_client.h"
+#include "ui/base/ime/text_input_focus_manager.h"
+#include "ui/base/ui_base_switches.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/views/accessible_pane_view.h"
#include "ui/views/controls/button/label_button.h"
-#include "ui/views/controls/textfield/textfield.h"
-#include "ui/views/focus/accelerator_handler.h"
#include "ui/views/focus/focus_manager_factory.h"
-#include "ui/views/focus/focus_manager_test.h"
#include "ui/views/focus/widget_focus_manager.h"
+#include "ui/views/test/focus_manager_test.h"
#include "ui/views/widget/widget.h"
-#if defined(USE_AURA)
-#include "ui/aura/client/focus_client.h"
-#include "ui/aura/window.h"
-#endif
-
namespace views {
-void FocusNativeView(gfx::NativeView view) {
-#if defined(USE_AURA)
- aura::client::GetFocusClient(view)->FocusWindow(view);
-#elif defined(OS_WIN)
- SetFocus(view);
-#else
-#error
-#endif
-}
-
enum FocusTestEventType {
ON_FOCUS = 0,
ON_BLUR
public:
SimpleTestView(std::vector<FocusTestEvent>* event_list, int view_id)
: event_list_(event_list) {
- set_focusable(true);
+ SetFocusable(true);
set_id(view_id);
}
private:
std::vector<FocusTestEvent>* event_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(SimpleTestView);
};
// Tests that the appropriate Focus related methods are called when a View
TEST_F(FocusManagerTest, FocusChangeListener) {
View* view1 = new View();
- view1->set_focusable(true);
+ view1->SetFocusable(true);
View* view2 = new View();
- view2->set_focusable(true);
+ view2->SetFocusable(true);
GetContentsView()->AddChildView(view1);
GetContentsView()->AddChildView(view2);
widget_listener.ClearFocusChanges();
gfx::NativeView native_view1 = widget1->GetNativeView();
- FocusNativeView(native_view1);
+ aura::client::GetFocusClient(native_view1)->FocusWindow(native_view1);
ASSERT_EQ(2, static_cast<int>(widget_listener.focus_changes().size()));
EXPECT_EQ(native_view1, widget_listener.focus_changes()[0].second);
EXPECT_EQ(native_view1, widget_listener.focus_changes()[1].second);
widget_listener.ClearFocusChanges();
gfx::NativeView native_view2 = widget2->GetNativeView();
- FocusNativeView(native_view2);
+ aura::client::GetFocusClient(native_view2)->FocusWindow(native_view2);
ASSERT_EQ(2, static_cast<int>(widget_listener.focus_changes().size()));
EXPECT_EQ(NativeViewPair(native_view1, native_view2),
widget_listener.focus_changes()[0]);
widget_listener.focus_changes()[1]);
}
-#if !defined(USE_AURA)
-class TestTextfield : public Textfield {
- public:
- TestTextfield() {}
- virtual gfx::NativeView TestGetNativeControlView() {
- return native_wrapper_->GetTestingHandle();
- }
-};
-
-// Tests that NativeControls do set the focused View appropriately on the
-// FocusManager.
-TEST_F(FocusManagerTest, DISABLED_FocusNativeControls) {
- TestTextfield* textfield = new TestTextfield();
- GetContentsView()->AddChildView(textfield);
- // Simulate the native view getting the native focus (such as by user click).
- FocusNativeView(textfield->TestGetNativeControlView());
- EXPECT_EQ(textfield, GetFocusManager()->GetFocusedView());
-}
-#endif
-
// Counts accelerator calls.
class TestAcceleratorTarget : public ui::AcceleratorTarget {
public:
class LabelButtonDtorTracked : public LabelButton {
public:
- LabelButtonDtorTracked(const string16& text, DtorTrackVector* dtor_tracker)
+ LabelButtonDtorTracked(const base::string16& text,
+ DtorTrackVector* dtor_tracker)
: LabelButton(NULL, text),
dtor_tracker_(dtor_tracker) {
- SetStyle(STYLE_NATIVE_TEXTBUTTON);
+ SetStyle(STYLE_BUTTON);
};
virtual ~LabelButtonDtorTracked() {
dtor_tracker_->push_back("LabelButtonDtorTracked");
DtorTrackVector dtor_tracker_;
};
-#if !defined(USE_AURA)
-TEST_F(FocusManagerDtorTest, FocusManagerDestructedLast) {
- // Setup views hierarchy.
- GetContentsView()->AddChildView(new TestTextfield());
- GetContentsView()->AddChildView(new LabelButtonDtorTracked(
- ASCIIToUTF16("button"), &dtor_tracker_));
-
- // Close the window.
- GetWidget()->Close();
- RunPendingMessages();
-
- // Test window, button and focus manager should all be destructed.
- ASSERT_EQ(3, static_cast<int>(dtor_tracker_.size()));
-
- // Focus manager should be the last one to destruct.
- ASSERT_STREQ("FocusManagerDtorTracked", dtor_tracker_[2].c_str());
-}
-#endif
-
namespace {
class FocusInAboutToRequestFocusFromTabTraversalView : public View {
// Create 3 views focuses the 3 and advances to the second. The 2nd views
// implementation of AboutToRequestFocusFromTabTraversal() focuses the first.
views::View* v1 = new View;
- v1->set_focusable(true);
+ v1->SetFocusable(true);
GetContentsView()->AddChildView(v1);
FocusInAboutToRequestFocusFromTabTraversalView* v2 =
new FocusInAboutToRequestFocusFromTabTraversalView;
- v2->set_focusable(true);
+ v2->SetFocusable(true);
v2->set_view_to_focus(v1);
GetContentsView()->AddChildView(v2);
views::View* v3 = new View;
- v3->set_focusable(true);
+ v3->SetFocusable(true);
GetContentsView()->AddChildView(v3);
v3->RequestFocus();
GetContentsView()->AddChildView(pane1);
views::View* v1 = new View;
- v1->set_focusable(true);
+ v1->SetFocusable(true);
pane1->AddChildView(v1);
views::View* v2 = new View;
- v2->set_focusable(true);
+ v2->SetFocusable(true);
pane1->AddChildView(v2);
views::AccessiblePaneView* pane2 = new AccessiblePaneView();
GetContentsView()->AddChildView(pane2);
views::View* v3 = new View;
- v3->set_focusable(true);
+ v3->SetFocusable(true);
pane2->AddChildView(v3);
views::View* v4 = new View;
- v4->set_focusable(true);
+ v4->SetFocusable(true);
pane2->AddChildView(v4);
std::vector<views::View*> panes;
// Verifies the stored focus view tracks the focused view.
TEST_F(FocusManagerTest, ImplicitlyStoresFocus) {
views::View* v1 = new View;
- v1->set_focusable(true);
+ v1->SetFocusable(true);
GetContentsView()->AddChildView(v1);
views::View* v2 = new View;
- v2->set_focusable(true);
+ v2->SetFocusable(true);
GetContentsView()->AddChildView(v2);
// Verify a focus request on |v1| implicitly updates the stored focus view.
TEST_F(FocusManagerArrowKeyTraversalTest, ArrowKeyTraversal) {
FocusManager* focus_manager = GetFocusManager();
- const ui::KeyEvent left_key(
- ui::ET_KEY_PRESSED, ui::VKEY_LEFT, ui::EF_NONE, false);
- const ui::KeyEvent right_key(
- ui::ET_KEY_PRESSED, ui::VKEY_RIGHT, ui::EF_NONE, false);
- const ui::KeyEvent up_key(
- ui::ET_KEY_PRESSED, ui::VKEY_UP, ui::EF_NONE, false);
- const ui::KeyEvent down_key(
- ui::ET_KEY_PRESSED, ui::VKEY_DOWN, ui::EF_NONE, false);
+ const ui::KeyEvent left_key(ui::ET_KEY_PRESSED, ui::VKEY_LEFT, ui::EF_NONE);
+ const ui::KeyEvent right_key(ui::ET_KEY_PRESSED, ui::VKEY_RIGHT, ui::EF_NONE);
+ const ui::KeyEvent up_key(ui::ET_KEY_PRESSED, ui::VKEY_UP, ui::EF_NONE);
+ const ui::KeyEvent down_key(ui::ET_KEY_PRESSED, ui::VKEY_DOWN, ui::EF_NONE);
std::vector<views::View*> v;
for (size_t i = 0; i < 2; ++i) {
views::View* view = new View;
- view->set_focusable(true);
+ view->SetFocusable(true);
GetContentsView()->AddChildView(view);
v.push_back(view);
}
View view;
GetFocusManager()->SetFocusedView(&view);
GetFocusManager()->StoreFocusedView(false);
+ EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView());
EXPECT_TRUE(GetFocusManager()->RestoreFocusedView());
EXPECT_EQ(&view, GetFocusManager()->GetStoredFocusView());
// Repeat with |true|.
GetFocusManager()->SetFocusedView(&view);
GetFocusManager()->StoreFocusedView(true);
+ EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView());
EXPECT_TRUE(GetFocusManager()->RestoreFocusedView());
EXPECT_EQ(&view, GetFocusManager()->GetStoredFocusView());
}
+class TextInputTestView : public View {
+ public:
+ TextInputTestView() {}
+
+ virtual ui::TextInputClient* GetTextInputClient() OVERRIDE {
+ return &text_input_client_;
+ }
+
+ private:
+ ui::DummyTextInputClient text_input_client_;
+
+ DISALLOW_COPY_AND_ASSIGN(TextInputTestView);
+};
+
+TEST_F(FocusManagerTest, TextInputClient) {
+ base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+ cmd_line->AppendSwitch(switches::kEnableTextInputFocusManager);
+
+ View* view = new TextInputTestView;
+ ui::TextInputClient* text_input_client = view->GetTextInputClient();
+ view->SetFocusable(true);
+ GetContentsView()->AddChildView(view);
+ ui::TextInputFocusManager* text_input_focus_manager =
+ ui::TextInputFocusManager::GetInstance();
+
+ GetFocusManager()->SetFocusedView(view);
+ EXPECT_EQ(view, GetFocusManager()->GetFocusedView());
+ EXPECT_EQ(text_input_client,
+ text_input_focus_manager->GetFocusedTextInputClient());
+ GetFocusManager()->StoreFocusedView(false);
+ EXPECT_TRUE(GetFocusManager()->RestoreFocusedView());
+ EXPECT_EQ(text_input_client,
+ text_input_focus_manager->GetFocusedTextInputClient());
+
+ // Repeat with |true|.
+ GetFocusManager()->SetFocusedView(view);
+ EXPECT_EQ(view, GetFocusManager()->GetFocusedView());
+ EXPECT_EQ(text_input_client,
+ text_input_focus_manager->GetFocusedTextInputClient());
+ GetFocusManager()->StoreFocusedView(true);
+ EXPECT_TRUE(GetFocusManager()->RestoreFocusedView());
+ EXPECT_EQ(text_input_client,
+ text_input_focus_manager->GetFocusedTextInputClient());
+
+ // Focus the view twice in a row.
+ GetFocusManager()->SetFocusedView(view);
+ EXPECT_EQ(text_input_client,
+ text_input_focus_manager->GetFocusedTextInputClient());
+ ui::TextInputFocusManager::GetInstance()->FocusTextInputClient(NULL);
+ GetFocusManager()->SetFocusedView(view);
+ EXPECT_EQ(text_input_client,
+ text_input_focus_manager->GetFocusedTextInputClient());
+}
+
namespace {
// Trivial WidgetDelegate implementation that allows setting return value of
TEST_F(FocusManagerTest, AdvanceFocusStaysInWidget) {
// Add |widget_view| as a child of the Widget.
View* widget_view = new View;
- widget_view->set_focusable(true);
+ widget_view->SetFocusable(true);
widget_view->SetBounds(20, 0, 20, 20);
GetContentsView()->AddChildView(widget_view);
params.delegate = delegate.get();
child_widget.Init(params);
View* view1 = new View;
- view1->set_focusable(true);
+ view1->SetFocusable(true);
view1->SetBounds(0, 0, 20, 20);
View* view2 = new View;
- view2->set_focusable(true);
+ view2->SetFocusable(true);
view2->SetBounds(20, 0, 20, 20);
child_widget.client_view()->AddChildView(view1);
child_widget.client_view()->AddChildView(view2);