Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/views/controls/textfield/textfield.h" | 5 #include "ui/views/controls/textfield/textfield.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <set> | 10 #include <set> |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 *result = NativeEventResult(); | 150 *result = NativeEventResult(); |
| 151 return false; | 151 return false; |
| 152 } | 152 } |
| 153 | 153 |
| 154 ui::EventDispatchDetails MockInputMethod::DispatchKeyEvent(ui::KeyEvent* key) { | 154 ui::EventDispatchDetails MockInputMethod::DispatchKeyEvent(ui::KeyEvent* key) { |
| 155 // On Mac, emulate InputMethodMac behavior for character events. Composition | 155 // On Mac, emulate InputMethodMac behavior for character events. Composition |
| 156 // still needs to be mocked, since it's not possible to generate test events | 156 // still needs to be mocked, since it's not possible to generate test events |
| 157 // which trigger the appropriate NSResponder action messages for composition. | 157 // which trigger the appropriate NSResponder action messages for composition. |
| 158 #if defined(OS_MACOSX) | 158 #if defined(OS_MACOSX) |
| 159 if (key->is_char()) | 159 if (key->is_char()) |
| 160 return DispatchKeyEventPostIME(key); | 160 return DispatchKeyEventPostIME(key); |
|
tapted
2017/07/04 08:13:15
Note Mac bails out of this function up here -- it
msw
2017/07/05 19:21:21
Acknowledged.
| |
| 161 #endif | 161 #endif |
| 162 | 162 |
| 163 // Checks whether the key event is from EventGenerator on Windows which will | 163 // Checks whether the key event is from EventGenerator on Windows which will |
| 164 // generate key event for WM_CHAR. | 164 // generate key event for WM_CHAR. |
| 165 // The MockInputMethod will insert char on WM_KEYDOWN so ignore WM_CHAR here. | 165 // The MockInputMethod will insert char on WM_KEYDOWN so ignore WM_CHAR here. |
| 166 if (key->is_char() && key->HasNativeEvent()) { | 166 if (key->is_char() && key->HasNativeEvent()) { |
| 167 key->SetHandled(); | 167 key->SetHandled(); |
| 168 return ui::EventDispatchDetails(); | 168 return ui::EventDispatchDetails(); |
| 169 } | 169 } |
| 170 | 170 |
| 171 ui::EventDispatchDetails dispatch_details; | 171 ui::EventDispatchDetails dispatch_details; |
| 172 | 172 |
| 173 bool handled = !IsTextInputTypeNone() && HasComposition(); | 173 bool handled = !IsTextInputTypeNone() && HasComposition(); |
| 174 ClearStates(); | 174 ClearStates(); |
| 175 if (handled) { | 175 if (handled) { |
| 176 DCHECK(!key->is_char()); | 176 DCHECK(!key->is_char()); |
| 177 ui::KeyEvent mock_key(ui::ET_KEY_PRESSED, | 177 ui::KeyEvent mock_key(ui::ET_KEY_PRESSED, |
| 178 ui::VKEY_PROCESSKEY, | 178 ui::VKEY_PROCESSKEY, |
| 179 key->flags()); | 179 key->flags()); |
| 180 dispatch_details = DispatchKeyEventPostIME(&mock_key); | 180 dispatch_details = DispatchKeyEventPostIME(&mock_key); |
| 181 } else { | 181 } else { |
| 182 dispatch_details = DispatchKeyEventPostIME(key); | 182 dispatch_details = DispatchKeyEventPostIME(key); |
| 183 } | 183 } |
| 184 | 184 |
| 185 if (dispatch_details.dispatcher_destroyed) | 185 if (key->handled() || dispatch_details.dispatcher_destroyed) |
| 186 return dispatch_details; | 186 return dispatch_details; |
| 187 | 187 |
| 188 ui::TextInputClient* client = GetTextInputClient(); | 188 ui::TextInputClient* client = GetTextInputClient(); |
| 189 if (client) { | 189 if (client) { |
| 190 if (handled) { | 190 if (handled) { |
| 191 if (result_text_.length()) | 191 if (result_text_.length()) |
| 192 client->InsertText(result_text_); | 192 client->InsertText(result_text_); |
| 193 if (composition_.text.length()) | 193 if (composition_.text.length()) |
| 194 client->SetCompositionText(composition_); | 194 client->SetCompositionText(composition_); |
| 195 else | 195 else |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 341 if (target_) | 341 if (target_) |
| 342 target_->OnBlur(); | 342 target_->OnBlur(); |
| 343 target_.reset(); | 343 target_.reset(); |
| 344 return false; | 344 return false; |
| 345 } | 345 } |
| 346 | 346 |
| 347 private: | 347 private: |
| 348 std::unique_ptr<views::Textfield> target_; | 348 std::unique_ptr<views::Textfield> target_; |
| 349 }; | 349 }; |
| 350 | 350 |
| 351 // Class that focuses a textfield when it sees a KeyDown event. | |
| 352 class TextfieldFocuser : public views::View { | |
| 353 public: | |
| 354 explicit TextfieldFocuser(views::Textfield* textfield) | |
| 355 : textfield_(textfield) { | |
| 356 SetFocusBehavior(FocusBehavior::ALWAYS); | |
| 357 } | |
| 358 | |
| 359 void PretendNotConsumed() { consume_ = false; } | |
|
msw
2017/07/05 19:21:21
nit: do a simple |void set_consume(bool consume) {
tapted
2017/07/06 05:58:07
Done.
| |
| 360 | |
| 361 // View: | |
| 362 bool OnKeyPressed(const ui::KeyEvent& event) override { | |
| 363 textfield_->RequestFocus(); | |
| 364 return consume_; | |
| 365 } | |
| 366 | |
| 367 private: | |
| 368 bool consume_ = true; | |
| 369 views::Textfield* textfield_; | |
| 370 | |
| 371 DISALLOW_COPY_AND_ASSIGN(TextfieldFocuser); | |
| 372 }; | |
| 373 | |
| 351 base::string16 GetClipboardText(ui::ClipboardType type) { | 374 base::string16 GetClipboardText(ui::ClipboardType type) { |
| 352 base::string16 text; | 375 base::string16 text; |
| 353 ui::Clipboard::GetForCurrentThread()->ReadText(type, &text); | 376 ui::Clipboard::GetForCurrentThread()->ReadText(type, &text); |
| 354 return text; | 377 return text; |
| 355 } | 378 } |
| 356 | 379 |
| 357 void SetClipboardText(ui::ClipboardType type, const std::string& text) { | 380 void SetClipboardText(ui::ClipboardType type, const std::string& text) { |
| 358 ui::ScopedClipboardWriter(type).WriteText(ASCIIToUTF16(text)); | 381 ui::ScopedClipboardWriter(type).WriteText(ASCIIToUTF16(text)); |
| 359 } | 382 } |
| 360 | 383 |
| (...skipping 2800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3161 TEST_F(TextfieldTest, CursorVisibility) { | 3184 TEST_F(TextfieldTest, CursorVisibility) { |
| 3162 InitTextfield(); | 3185 InitTextfield(); |
| 3163 | 3186 |
| 3164 textfield_->SetCursorEnabled(false); | 3187 textfield_->SetCursorEnabled(false); |
| 3165 EXPECT_FALSE(test_api_->IsCursorVisible()); | 3188 EXPECT_FALSE(test_api_->IsCursorVisible()); |
| 3166 | 3189 |
| 3167 textfield_->SetCursorEnabled(true); | 3190 textfield_->SetCursorEnabled(true); |
| 3168 EXPECT_TRUE(test_api_->IsCursorVisible()); | 3191 EXPECT_TRUE(test_api_->IsCursorVisible()); |
| 3169 } | 3192 } |
| 3170 | 3193 |
| 3194 // Verify that if a textfield gains focus during key dispatch that an edit | |
| 3195 // command only results when the event is not consumed. | |
| 3196 TEST_F(TextfieldTest, SwitchFocusInKeyDown) { | |
| 3197 InitTextfield(); | |
| 3198 TextfieldFocuser* focuser = new TextfieldFocuser(textfield_); | |
| 3199 widget_->GetContentsView()->AddChildView(focuser); | |
| 3200 | |
| 3201 focuser->RequestFocus(); | |
| 3202 EXPECT_EQ(focuser, GetFocusedView()); | |
| 3203 SendKeyPress(ui::VKEY_SPACE, 0); | |
| 3204 EXPECT_EQ(textfield_, GetFocusedView()); | |
| 3205 EXPECT_EQ(base::string16(), textfield_->text()); | |
| 3206 | |
| 3207 focuser->PretendNotConsumed(); | |
| 3208 focuser->RequestFocus(); | |
| 3209 EXPECT_EQ(focuser, GetFocusedView()); | |
| 3210 SendKeyPress(ui::VKEY_SPACE, 0); | |
| 3211 EXPECT_EQ(textfield_, GetFocusedView()); | |
| 3212 EXPECT_EQ(base::ASCIIToUTF16(" "), textfield_->text()); | |
| 3213 } | |
| 3214 | |
| 3171 } // namespace views | 3215 } // namespace views |
| OLD | NEW |