Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(849)

Unified Diff: ui/views/controls/textfield/textfield_unittest.cc

Issue 809773006: MacViews: Intercept events for Menus (after AppKit has interpreted keystrokes) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@20141205-MacViews-AcceleratedWidget-PLUS-AddingLayers-fromcl-PLUS-bringup
Patch Set: A few more cleanups Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/views/controls/textfield/textfield_unittest.cc
diff --git a/ui/views/controls/textfield/textfield_unittest.cc b/ui/views/controls/textfield/textfield_unittest.cc
index ca3839c18ed1cef77ff5352ee137d501e7202b35..fd57ce127d6a46032640e19bfe7c69f3ac64412c 100644
--- a/ui/views/controls/textfield/textfield_unittest.cc
+++ b/ui/views/controls/textfield/textfield_unittest.cc
@@ -21,6 +21,7 @@
#include "ui/base/ui_base_switches_util.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/events/test/event_generator.h"
#include "ui/gfx/render_text.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/controls/textfield/textfield_controller.h"
@@ -56,6 +57,15 @@ namespace {
const base::char16 kHebrewLetterSamekh = 0x05E1;
+// The method used for dispatching key events. Either dispatch directly to the
+// MockInputMethod using the keycodes it expects internally, or dispatch to the
+// native window implementation using platform-specific keycodes, which should
+// be translated into the correct editing commands.
+enum EventDispatchMethod {
+ DISPATCH_TO_INPUT_METHOD,
+ DISPATCH_TO_WINDOW,
+};
+
// A Textfield wrapper to intercept OnKey[Pressed|Released]() ressults.
class TestTextfield : public views::Textfield {
public:
@@ -159,6 +169,12 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
copied_to_clipboard_(ui::CLIPBOARD_TYPE_LAST) {
}
+ // Provide an implementation of GetParam which parameterized subclasses can
+ // override using gtest's GetParam().
+ virtual EventDispatchMethod GetParamWithDefault() {
+ return DISPATCH_TO_INPUT_METHOD;
+ }
+
// ::testing::Test:
void TearDown() override {
if (widget_)
@@ -202,7 +218,12 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
textfield_ = new TestTextfield();
textfield_->set_controller(this);
widget_ = new Widget();
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+
+ // The widget type must be an activatable type, and we don't want to worry
+ // about the non-client view, which leaves just TYPE_WINDOW_FRAMELESS.
+ Widget::InitParams params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+
params.bounds = gfx::Rect(100, 100, 100, 100);
widget_->Init(params);
View* container = new View();
@@ -224,8 +245,11 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
input_method_ = new MockInputMethod();
widget_->ReplaceInputMethod(input_method_);
- // Activate the widget and focus the textfield for input handling.
- widget_->Activate();
+ // Since the window type is activatable, showing the widget will also
+ // activate it. Calling Activate directly is insufficient, since that does
+ // not also _focus_ an aura::Window (i.e. using the FocusClient). Both the
+ // widget and the textfield must have focus to properly handle input.
+ widget_->Show();
textfield_->RequestFocus();
// On Mac, activation is asynchronous since desktop widgets are used. We
@@ -233,6 +257,11 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
#if defined(OS_MACOSX) && !defined(USE_AURA)
fake_activation_ = test::WidgetTest::FakeWidgetIsActiveAlways();
#endif
+
+ if (GetParamWithDefault() == DISPATCH_TO_WINDOW) {
+ event_generator_.reset(new ui::test::EventGenerator(
+ GetContext(), widget_->GetNativeWindow()));
+ }
}
ui::MenuModel* GetContextMenuModel() {
@@ -240,22 +269,50 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
return test_api_->context_menu_contents();
}
+ // On Mac, true if testing a views::TextField in an NSWindow using native
+ // NSEvents. On other platforms, a helper function to avoid ifdef litter.
+ bool TestingNativeMac() {
+#if defined(OS_MACOSX)
+ return GetParamWithDefault() == DISPATCH_TO_WINDOW;
+#else
+ return false;
+#endif
+ }
+
protected:
void SendKeyEvent(ui::KeyboardCode key_code,
bool alt,
bool shift,
- bool control,
+ bool control_or_command,
bool caps_lock) {
- int flags = (alt ? ui::EF_ALT_DOWN : 0) |
- (shift ? ui::EF_SHIFT_DOWN : 0) |
+ bool control = control_or_command;
+ bool command = false;
+
+ // By default, swap control and command for native events on Mac. This
+ // handles most cases.
+ if (TestingNativeMac())
+ std::swap(control, command);
+
+ int flags = (alt ? ui::EF_ALT_DOWN : 0) | (shift ? ui::EF_SHIFT_DOWN : 0) |
(control ? ui::EF_CONTROL_DOWN : 0) |
+ (command ? ui::EF_COMMAND_DOWN : 0) |
(caps_lock ? ui::EF_CAPS_LOCK_DOWN : 0);
+
+ // If dispatching to the window, ask the event generator to generate
+ // events populated with native event information for each platform.
+ if (GetParamWithDefault() == DISPATCH_TO_WINDOW) {
+ event_generator_->PressKey(key_code, flags);
+ return;
+ }
+
ui::KeyEvent event(ui::ET_KEY_PRESSED, key_code, flags);
input_method_->DispatchKeyEvent(event);
}
- void SendKeyEvent(ui::KeyboardCode key_code, bool shift, bool control) {
- SendKeyEvent(key_code, false, shift, control, false);
+ void SendKeyEvent(ui::KeyboardCode key_code,
+ bool shift,
+ bool control_or_command) {
+ SendKeyEvent(key_code, false, shift, control_or_command, false);
}
void SendKeyEvent(ui::KeyboardCode key_code) {
@@ -269,6 +326,7 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
static_cast<ui::KeyboardCode>(ui::VKEY_A + ch - 'a');
SendKeyEvent(code);
} else {
+ // TODO(tapted): Support DISPATCH_TO_WINDOW here.
ui::KeyEvent event(ch, ui::VKEY_UNKNOWN, ui::EF_NONE);
input_method_->DispatchKeyEvent(event);
}
@@ -357,10 +415,57 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
private:
ui::ClipboardType copied_to_clipboard_;
scoped_ptr<test::WidgetTest::FakeActivation> fake_activation_;
+ scoped_ptr<ui::test::EventGenerator> event_generator_;
DISALLOW_COPY_AND_ASSIGN(TextfieldTest);
};
+// TextfieldTest that overrides GetParamWithDefault() to override the default
+// using GetParam() from the gtest interface.
+class TextfieldTestWithParam
+ : public TextfieldTest,
+ public ::testing::WithParamInterface<EventDispatchMethod> {
+ public:
+ TextfieldTestWithParam() {}
+
+ void SendHomeEvent(bool shift) {
+ if (TestingNativeMac()) {
+ // Use Cmd+Left on native Mac. An RTL-agnostic "end" doesn't have a
+ // default key-binding on Mac.
+ SendKeyEvent(ui::VKEY_LEFT, shift /* shift */, true /* command */);
+ return;
+ }
+ SendKeyEvent(ui::VKEY_HOME, shift /* shift */, false /* control */);
+ }
+
+ void SendEndEvent(bool shift) {
+ if (TestingNativeMac()) {
+ SendKeyEvent(ui::VKEY_RIGHT, shift, true); // Cmd+Right.
+ return;
+ }
+ SendKeyEvent(ui::VKEY_END, shift, false);
+ }
+
+ // Sends {delete, move, select} word {forward, backward}.
+ void SendWordEvent(ui::KeyboardCode key, bool shift) {
+ bool alt = false;
+ bool control = true;
+ bool caps = false;
+ if (TestingNativeMac()) {
+ // Use Alt+Left/Right/Backspace on native Mac.
+ alt = true;
+ control = false;
+ }
+ SendKeyEvent(key, alt, shift, control, caps);
+ }
+
+ // Overridden from TextfieldTest:
+ EventDispatchMethod GetParamWithDefault() override { return GetParam(); }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextfieldTestWithParam);
+};
+
TEST_F(TextfieldTest, ModelChangesTest) {
InitTextfield();
@@ -398,11 +503,11 @@ TEST_F(TextfieldTest, KeyTest) {
EXPECT_STR_EQ("TexT!1!1", textfield_->text());
}
-TEST_F(TextfieldTest, ControlAndSelectTest) {
+TEST_P(TextfieldTestWithParam, ControlAndSelectTest) {
// Insert a test string in a textfield.
InitTextfield();
textfield_->SetText(ASCIIToUTF16("one two three"));
- SendKeyEvent(ui::VKEY_HOME, false /* shift */, false /* control */);
+ SendHomeEvent(false);
SendKeyEvent(ui::VKEY_RIGHT, true, false);
SendKeyEvent(ui::VKEY_RIGHT, true, false);
SendKeyEvent(ui::VKEY_RIGHT, true, false);
@@ -410,13 +515,13 @@ TEST_F(TextfieldTest, ControlAndSelectTest) {
EXPECT_STR_EQ("one", textfield_->GetSelectedText());
// Test word select.
- SendKeyEvent(ui::VKEY_RIGHT, true, true);
+ SendWordEvent(ui::VKEY_RIGHT, true);
EXPECT_STR_EQ("one two", textfield_->GetSelectedText());
- SendKeyEvent(ui::VKEY_RIGHT, true, true);
+ SendWordEvent(ui::VKEY_RIGHT, true);
EXPECT_STR_EQ("one two three", textfield_->GetSelectedText());
- SendKeyEvent(ui::VKEY_LEFT, true, true);
+ SendWordEvent(ui::VKEY_LEFT, true);
EXPECT_STR_EQ("one two ", textfield_->GetSelectedText());
- SendKeyEvent(ui::VKEY_LEFT, true, true);
+ SendWordEvent(ui::VKEY_LEFT, true);
EXPECT_STR_EQ("one ", textfield_->GetSelectedText());
// Replace the selected text.
@@ -427,13 +532,13 @@ TEST_F(TextfieldTest, ControlAndSelectTest) {
SendKeyEvent(ui::VKEY_SPACE, false, false);
EXPECT_STR_EQ("ZERO two three", textfield_->text());
- SendKeyEvent(ui::VKEY_END, true, false);
+ SendEndEvent(true);
EXPECT_STR_EQ("two three", textfield_->GetSelectedText());
- SendKeyEvent(ui::VKEY_HOME, true, false);
+ SendHomeEvent(true);
EXPECT_STR_EQ("ZERO ", textfield_->GetSelectedText());
}
-TEST_F(TextfieldTest, InsertionDeletionTest) {
+TEST_P(TextfieldTestWithParam, InsertionDeletionTest) {
// Insert a test string in a textfield.
InitTextfield();
for (size_t i = 0; i < 10; i++)
@@ -455,14 +560,17 @@ TEST_F(TextfieldTest, InsertionDeletionTest) {
EXPECT_STR_EQ("k", textfield_->text());
// Delete the previous word from cursor.
+ bool shift = false;
textfield_->SetText(ASCIIToUTF16("one two three four"));
- SendKeyEvent(ui::VKEY_END);
- SendKeyEvent(ui::VKEY_BACK, false, false, true, false);
+ SendEndEvent(shift);
+ SendWordEvent(ui::VKEY_BACK, shift);
EXPECT_STR_EQ("one two three ", textfield_->text());
- // Delete to a line break on Linux and ChromeOS, to a word break on Windows.
- SendKeyEvent(ui::VKEY_LEFT, false, false, true, false);
- SendKeyEvent(ui::VKEY_BACK, false, true, true, false);
+ // Delete to a line break on Linux and ChromeOS, to a word break on Windows
+ // and Mac.
+ SendWordEvent(ui::VKEY_LEFT, shift);
+ shift = true;
+ SendWordEvent(ui::VKEY_BACK, shift);
#if defined(OS_LINUX)
EXPECT_STR_EQ("three ", textfield_->text());
#else
@@ -471,13 +579,16 @@ TEST_F(TextfieldTest, InsertionDeletionTest) {
// Delete the next word from cursor.
textfield_->SetText(ASCIIToUTF16("one two three four"));
- SendKeyEvent(ui::VKEY_HOME);
- SendKeyEvent(ui::VKEY_DELETE, false, false, true, false);
+ shift = false;
+ SendHomeEvent(shift);
+ SendWordEvent(ui::VKEY_DELETE, shift);
EXPECT_STR_EQ(" two three four", textfield_->text());
- // Delete to a line break on Linux and ChromeOS, to a word break on Windows.
- SendKeyEvent(ui::VKEY_RIGHT, false, false, true, false);
- SendKeyEvent(ui::VKEY_DELETE, false, true, true, false);
+ // Delete to a line break on Linux and ChromeOS, to a word break on Windows
+ // and Mac.
+ SendWordEvent(ui::VKEY_RIGHT, shift);
+ shift = true;
+ SendWordEvent(ui::VKEY_DELETE, shift);
#if defined(OS_LINUX)
EXPECT_STR_EQ(" two", textfield_->text());
#else
@@ -2115,4 +2226,12 @@ TEST_F(TextfieldTouchSelectionTest, TapOnSelection) {
EXPECT_EQ(tap_range, range);
}
+// Instantiate parameterized tests. These are just the ones above using "TEST_P"
+// rather than "TEST_F".
+INSTANTIATE_TEST_CASE_P(
+ TextfieldTestWithParamInstance,
+ TextfieldTestWithParam,
+ ::testing::Values<EventDispatchMethod>(DISPATCH_TO_INPUT_METHOD,
+ DISPATCH_TO_WINDOW));
+
} // namespace views
« no previous file with comments | « ui/views/controls/menu/menu_event_dispatcher_linux.cc ('k') | ui/views/test/event_generator_delegate_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698