2
* Copyright (C) 2017 Igalia S.L.
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2,1 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Library General Public License for more details.
14
* You should have received a copy of the GNU Library General Public License
15
* along with this library; see the file COPYING.LIB. If not, write to
16
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
* Boston, MA 02110-1301, USA.
23
#include "WebViewTest.h"
24
#include <wtf/glib/GUniquePtr.h>
27
using PlatformEventKey = GdkEventKey;
28
#define KEY(x) GDK_KEY_##x
29
#define CONTROL_MASK GDK_CONTROL_MASK
30
#define SHIFT_MASK GDK_SHIFT_MASK
32
using PlatformEventKey = struct wpe_input_keyboard_event;
33
#define KEY(x) WPE_KEY_##x
34
#define CONTROL_MASK wpe_input_keyboard_modifier_control
35
#define SHIFT_MASK wpe_input_keyboard_modifier_shift
38
typedef struct _WebKitInputMethodContextMock {
39
WebKitInputMethodContext parent;
43
bool commitNextCharacter;
44
char* surroundingText;
45
unsigned surroundingCursorIndex;
46
unsigned surroundingSelectionIndex;
47
} WebKitInputMethodContextMock;
49
typedef struct _WebKitInputMethodContextMockClass {
50
WebKitInputMethodContextClass parent;
51
} WebKitInputMethodContextMockClass;
53
G_DEFINE_TYPE(WebKitInputMethodContextMock, webkit_input_method_context_mock, WEBKIT_TYPE_INPUT_METHOD_CONTEXT)
55
static const char* testHTML = "<html><body><textarea id='editable' rows='3', cols='50' onkeydown='logKeyDown()' onkeyup='logKeyUp()' onkeypress='logKeyPress()'></textarea><script>"
56
"var input = document.getElementById('editable');"
57
"input.addEventListener('compositionstart', logCompositionEvent);"
58
"input.addEventListener('compositionupdate', logCompositionEvent);"
59
"input.addEventListener('compositionend', logCompositionEvent);"
60
"function logCompositionEvent(event) { window.webkit.messageHandlers.imEvent.postMessage({ 'type' : event.type, 'data' : event.data }) }"
61
"function logKeyDown() { window.webkit.messageHandlers.imEvent.postMessage({ 'type' : 'keyDown', 'keyCode' : event.keyCode, 'key' : event.key, 'isComposing' : event.isComposing }) }"
62
"function logKeyUp() { window.webkit.messageHandlers.imEvent.postMessage({ 'type' : 'keyUp', 'keyCode' : event.keyCode, 'key' : event.key, 'isComposing' : event.isComposing }) }"
63
"function logKeyPress() { window.webkit.messageHandlers.imEvent.postMessage({ 'type' : 'keyPress', 'keyCode' : event.keyCode }) }"
64
"</script></body></html>";
66
static void webkitInputMethodContextMockFinalize(GObject* object)
68
auto* mock = reinterpret_cast<WebKitInputMethodContextMock*>(object);
70
g_string_free(mock->preedit, TRUE);
71
mock->preedit = nullptr;
73
g_clear_pointer(&mock->surroundingText, g_free);
74
G_OBJECT_CLASS(webkit_input_method_context_mock_parent_class)->finalize(object);
77
static void webkitInputMethodContextMockGetPreedit(WebKitInputMethodContext* context, char** text, GList** underlines, guint* cursorOffset)
79
auto* mock = reinterpret_cast<WebKitInputMethodContextMock*>(context);
81
*text = mock->preedit ? g_strdup(mock->preedit->str) : g_strdup("");
83
*underlines = mock->preedit ? g_list_prepend(*underlines, webkit_input_method_underline_new(0, mock->preedit->len)) : nullptr;
85
*cursorOffset = mock->preedit ? mock->preedit->len : 0;
88
static gboolean webkitInputMethodContextMockFilterKeyEvent(WebKitInputMethodContext* context, PlatformEventKey* keyEvent)
90
auto* mock = reinterpret_cast<WebKitInputMethodContextMock*>(context);
95
GdkModifierType state;
97
if (!gdk_event_get_state(reinterpret_cast<GdkEvent*>(keyEvent), &state) || !gdk_event_get_keyval(reinterpret_cast<GdkEvent*>(keyEvent), &keyval))
99
bool isKeyPress = gdk_event_get_event_type(reinterpret_cast<GdkEvent*>(keyEvent)) == GDK_KEY_PRESS;
100
gunichar character = gdk_keyval_to_unicode(keyval);
102
uint32_t state = keyEvent->modifiers;
103
uint32_t keyval = keyEvent->key_code;
104
bool isKeyPress = keyEvent->pressed;
105
gunichar character = wpe_key_code_to_unicode(keyval);
107
bool isControl = state & CONTROL_MASK;
108
bool isShift = state & SHIFT_MASK;
109
bool isComposeEnd = (keyval == KEY(space) || keyval == KEY(Return) || keyval == KEY(ISO_Enter));
111
if (isKeyPress && mock->commitNextCharacter) {
113
auto length = g_unichar_to_utf8(character, buffer);
114
buffer[length] = '\0';
115
g_signal_emit_by_name(context, "committed", buffer, nullptr);
116
mock->commitNextCharacter = false;
121
if (!mock->preedit) {
122
if (isKeyPress && isControl && isShift && keyval == KEY(w)) {
123
mock->preedit = g_string_new("w");
124
g_signal_emit_by_name(context, "preedit-started", nullptr);
125
g_signal_emit_by_name(context, "preedit-changed", nullptr);
133
if (keyval == KEY(Escape)) {
134
g_string_free(mock->preedit, TRUE);
135
mock->preedit = nullptr;
136
g_signal_emit_by_name(context, "preedit-changed", nullptr);
137
g_signal_emit_by_name(context, "preedit-finished", nullptr);
143
if (!g_strcmp0(mock->preedit->str, "wgtk"))
144
g_signal_emit_by_name(context, "committed", "WebKitGTK", nullptr);
145
else if (!g_strcmp0(mock->preedit->str, "wwpe"))
146
g_signal_emit_by_name(context, "committed", "WPEWebKit", nullptr);
148
g_signal_emit_by_name(context, "committed", mock->preedit->str + 1, nullptr);
150
g_string_free(mock->preedit, TRUE);
151
mock->preedit = nullptr;
152
g_signal_emit_by_name(context, "preedit-changed", nullptr);
153
g_signal_emit_by_name(context, "preedit-finished", nullptr);
159
g_string_append_unichar(mock->preedit, character);
160
g_signal_emit_by_name(context, "preedit-changed", nullptr);
168
static void webkitInputMethodContextMockNotifyFocusIn(WebKitInputMethodContext* context)
170
reinterpret_cast<WebKitInputMethodContextMock*>(context)->enabled = true;
173
static void webkitInputMethodContextMockNotifyFocusOut(WebKitInputMethodContext* context)
175
reinterpret_cast<WebKitInputMethodContextMock*>(context)->enabled = false;
178
static void webkitInputMethodContextMockNotifySurrounding(WebKitInputMethodContext* context, const gchar *text, unsigned length, unsigned cursorIndex, unsigned selectionIndex)
180
auto* mock = reinterpret_cast<WebKitInputMethodContextMock*>(context);
181
g_clear_pointer(&mock->surroundingText, g_free);
183
if (!mock->preedit && cursorIndex >= 3 && text[cursorIndex - 3] == ':' && text[cursorIndex - 2] == '-' && text[cursorIndex - 1] == ')') {
184
g_signal_emit_by_name(context, "delete-surrounding", -3, 3, nullptr);
185
g_signal_emit_by_name(context, "committed", "😀️", nullptr);
187
mock->surroundingText = g_strndup(text, length);
188
mock->surroundingCursorIndex = cursorIndex;
189
mock->surroundingSelectionIndex = selectionIndex;
192
static void webkitInputMethodContextMockReset(WebKitInputMethodContext* context)
194
auto* mock = reinterpret_cast<WebKitInputMethodContextMock*>(context);
198
g_string_free(mock->preedit, TRUE);
199
mock->preedit = nullptr;
200
g_clear_pointer(&mock->surroundingText, g_free);
201
mock->surroundingCursorIndex = 0;
202
mock->surroundingSelectionIndex = 0;
204
g_signal_emit_by_name(context, "preedit-changed", nullptr);
205
g_signal_emit_by_name(context, "preedit-finished", nullptr);
208
static void webkit_input_method_context_mock_class_init(WebKitInputMethodContextMockClass* klass)
210
GObjectClass* objectClass = G_OBJECT_CLASS(klass);
211
objectClass->finalize = webkitInputMethodContextMockFinalize;
213
auto* imClass = WEBKIT_INPUT_METHOD_CONTEXT_CLASS(klass);
214
imClass->get_preedit = webkitInputMethodContextMockGetPreedit;
215
imClass->filter_key_event = webkitInputMethodContextMockFilterKeyEvent;
216
imClass->notify_focus_in = webkitInputMethodContextMockNotifyFocusIn;
217
imClass->notify_focus_out = webkitInputMethodContextMockNotifyFocusOut;
218
imClass->notify_surrounding = webkitInputMethodContextMockNotifySurrounding;
219
imClass->reset = webkitInputMethodContextMockReset;
222
static void webkit_input_method_context_mock_init(WebKitInputMethodContextMock*)
226
class InputMethodTest: public WebViewTest {
228
MAKE_GLIB_TEST_FIXTURE(InputMethodTest);
231
enum class Type { KeyDown, KeyPress, KeyUp, CompositionStart, CompositionUpdate, CompositionEnd };
233
explicit Event(Type type)
245
static void imEventCallback(WebKitUserContentManager*, WebKitJavascriptResult* javascriptResult, InputMethodTest* test)
247
test->imEvent(javascriptResult);
251
: m_context(adoptGRef(static_cast<WebKitInputMethodContextMock*>(g_object_new(webkit_input_method_context_mock_get_type(), nullptr))))
254
WebViewTest::showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL);
255
auto* defaultContext = webkit_web_view_get_input_method_context(m_webView);
256
g_assert_true(WEBKIT_IS_INPUT_METHOD_CONTEXT(defaultContext));
257
assertObjectIsDeletedWhenTestFinishes(G_OBJECT(defaultContext));
259
WebViewTest::showInWindow();
260
g_assert_null(webkit_web_view_get_input_method_context(m_webView));
262
assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_context.get()));
263
webkit_web_view_set_input_method_context(m_webView, WEBKIT_INPUT_METHOD_CONTEXT(m_context.get()));
264
g_assert_true(webkit_web_view_get_input_method_context(m_webView) == WEBKIT_INPUT_METHOD_CONTEXT(m_context.get()));
266
webkit_user_content_manager_register_script_message_handler(m_userContentManager.get(), "imEvent");
267
g_signal_connect(m_userContentManager.get(), "script-message-received::imEvent", G_CALLBACK(imEventCallback), this);
272
webkit_user_content_manager_unregister_script_message_handler(m_userContentManager.get(), "imEvent");
273
g_signal_handlers_disconnect_by_data(m_userContentManager.get(), this);
276
void imEvent(WebKitJavascriptResult* result)
278
auto* jsEvent = webkit_javascript_result_get_js_value(result);
279
g_assert_true(jsc_value_is_object(jsEvent));
281
GRefPtr<JSCValue> value = adoptGRef(jsc_value_object_get_property(jsEvent, "type"));
282
g_assert_true(jsc_value_is_string(value.get()));
283
GUniquePtr<char> strValue(jsc_value_to_string(value.get()));
284
if (!g_strcmp0(strValue.get(), "keyDown")) {
285
InputMethodTest::Event event(InputMethodTest::Event::Type::KeyDown);
286
value = adoptGRef(jsc_value_object_get_property(jsEvent, "keyCode"));
287
g_assert_true(jsc_value_is_number(value.get()));
288
event.keyCode = jsc_value_to_int32(value.get());
289
value = adoptGRef(jsc_value_object_get_property(jsEvent, "key"));
290
g_assert_true(jsc_value_is_string(value.get()));
291
strValue.reset(jsc_value_to_string(value.get()));
292
event.key = strValue.get();
293
value = adoptGRef(jsc_value_object_get_property(jsEvent, "isComposing"));
294
g_assert_true(jsc_value_is_boolean(value.get()));
295
event.isComposing = jsc_value_to_boolean(value.get());
296
m_events.append(WTFMove(event));
297
} else if (!g_strcmp0(strValue.get(), "keyPress")) {
298
InputMethodTest::Event event(InputMethodTest::Event::Type::KeyPress);
299
value = adoptGRef(jsc_value_object_get_property(jsEvent, "keyCode"));
300
g_assert_true(jsc_value_is_number(value.get()));
301
event.keyCode = jsc_value_to_int32(value.get());
302
m_events.append(WTFMove(event));
303
} else if (!g_strcmp0(strValue.get(), "keyUp")) {
304
InputMethodTest::Event event(InputMethodTest::Event::Type::KeyUp);
305
value = adoptGRef(jsc_value_object_get_property(jsEvent, "keyCode"));
306
g_assert_true(jsc_value_is_number(value.get()));
307
event.keyCode = jsc_value_to_int32(value.get());
308
value = adoptGRef(jsc_value_object_get_property(jsEvent, "key"));
309
g_assert_true(jsc_value_is_string(value.get()));
310
strValue.reset(jsc_value_to_string(value.get()));
311
event.key = strValue.get();
312
value = adoptGRef(jsc_value_object_get_property(jsEvent, "isComposing"));
313
g_assert_true(jsc_value_is_boolean(value.get()));
314
event.isComposing = jsc_value_to_boolean(value.get());
315
m_events.append(WTFMove(event));
316
} else if (!g_strcmp0(strValue.get(), "compositionstart")) {
317
InputMethodTest::Event event(InputMethodTest::Event::Type::CompositionStart);
318
value = adoptGRef(jsc_value_object_get_property(jsEvent, "data"));
319
g_assert_true(jsc_value_is_string(value.get()));
320
strValue.reset(jsc_value_to_string(value.get()));
321
event.data = strValue.get();
322
m_events.append(WTFMove(event));
323
} else if (!g_strcmp0(strValue.get(), "compositionupdate")) {
324
InputMethodTest::Event event(InputMethodTest::Event::Type::CompositionUpdate);
325
value = adoptGRef(jsc_value_object_get_property(jsEvent, "data"));
326
g_assert_true(jsc_value_is_string(value.get()));
327
strValue.reset(jsc_value_to_string(value.get()));
328
event.data = strValue.get();
329
m_events.append(WTFMove(event));
330
} else if (!g_strcmp0(strValue.get(), "compositionend")) {
331
InputMethodTest::Event event(InputMethodTest::Event::Type::CompositionEnd);
332
value = adoptGRef(jsc_value_object_get_property(jsEvent, "data"));
333
g_assert_true(jsc_value_is_string(value.get()));
334
strValue.reset(jsc_value_to_string(value.get()));
335
event.data = strValue.get();
336
m_events.append(WTFMove(event));
339
if (m_events.size() == m_eventsExpected)
340
g_main_loop_quit(m_mainLoop);
343
void focusEditableAndWaitUntilInputMethodEnabled()
345
g_assert_false(m_context->enabled);
346
runJavaScriptAndWaitUntilFinished("document.getElementById('editable').focus()", nullptr);
347
if (m_context->enabled)
350
g_idle_add([](gpointer userData) -> gboolean {
351
auto* test = static_cast<InputMethodTest*>(userData);
352
if (test->m_context->enabled) {
353
test->quitMainLoop();
359
g_main_loop_run(m_mainLoop);
360
g_assert_true(m_context->enabled);
363
void unfocusEditableAndWaitUntilInputMethodDisabled()
365
g_assert_true(m_context->enabled);
366
runJavaScriptAndWaitUntilFinished("document.getElementById('editable').blur()", nullptr);
367
if (!m_context->enabled)
370
g_idle_add([](gpointer userData) -> gboolean {
371
auto* test = static_cast<InputMethodTest*>(userData);
372
if (!test->m_context->enabled) {
373
test->quitMainLoop();
379
g_main_loop_run(m_mainLoop);
380
g_assert_false(m_context->enabled);
385
runJavaScriptAndWaitUntilFinished("document.getElementById('editable').value = ''", nullptr);
389
GUniquePtr<char> editableValue()
391
auto* jsResult = runJavaScriptAndWaitUntilFinished("document.getElementById('editable').value", nullptr);
392
return GUniquePtr<char>(WebViewTest::javascriptResultToCString(jsResult));
395
void keyStrokeAndWaitForEvents(unsigned keyval, unsigned eventsCount, unsigned modifiers = 0)
397
m_eventsExpected = eventsCount;
398
keyStroke(keyval, modifiers);
399
g_main_loop_run(m_mainLoop);
400
m_eventsExpected = 0;
403
void keyStrokeHandledByInputMethodAndWaitForEvents(unsigned keyval, unsigned eventsCount)
405
m_context->commitNextCharacter = true;
406
keyStrokeAndWaitForEvents(keyval, eventsCount);
407
m_context->commitNextCharacter = false;
410
void clickAndWaitForEvents(unsigned eventsCount)
412
m_eventsExpected = eventsCount;
413
clickMouseButton(0, 0, 1);
414
g_main_loop_run(m_mainLoop);
415
m_eventsExpected = 0;
418
WebKitInputPurpose purpose() const
420
return webkit_input_method_context_get_input_purpose(WEBKIT_INPUT_METHOD_CONTEXT(m_context.get()));
423
WebKitInputHints hints() const
425
return webkit_input_method_context_get_input_hints(WEBKIT_INPUT_METHOD_CONTEXT(m_context.get()));
428
const char* surroundingText() const
430
return m_context->surroundingText;
433
unsigned surroundingCursorIndex() const
435
return m_context->surroundingCursorIndex;
438
unsigned surroundingSelectionIndex() const
440
return m_context->surroundingSelectionIndex;
443
void waitForSurroundingText(const char* text)
445
m_expectedSurroundingText = text;
446
g_idle_add([](gpointer userData) -> gboolean {
447
auto* test = static_cast<InputMethodTest*>(userData);
448
if (!g_strcmp0(test->m_context->surroundingText, test->m_expectedSurroundingText.data())) {
449
test->quitMainLoop();
455
g_main_loop_run(m_mainLoop);
456
m_expectedSurroundingText = { };
459
GRefPtr<WebKitInputMethodContextMock> m_context;
460
Vector<Event> m_events;
461
unsigned m_eventsExpected { 0 };
462
CString m_expectedSurroundingText;
465
static void testWebKitInputMethodContextSimple(InputMethodTest* test, gconstpointer)
467
test->loadHtml(testHTML, nullptr);
468
test->waitUntilLoadFinished();
470
test->focusEditableAndWaitUntilInputMethodEnabled();
472
// Send a normal character not handled by IM.
473
test->keyStrokeAndWaitForEvents(KEY(a), 3);
474
g_assert_cmpuint(test->m_events.size(), ==, 3);
475
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
476
g_assert_cmpuint(test->m_events[0].keyCode, ==, 65);
477
g_assert_cmpstr(test->m_events[0].key.data(), ==, "a");
478
g_assert_false(test->m_events[0].isComposing);
479
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::KeyPress);
480
g_assert_cmpuint(test->m_events[1].keyCode, ==, 97);
481
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::KeyUp);
482
g_assert_cmpuint(test->m_events[2].keyCode, ==, 65);
483
g_assert_cmpstr(test->m_events[2].key.data(), ==, "a");
484
g_assert_false(test->m_events[2].isComposing);
486
auto editableValue = test->editableValue();
487
g_assert_cmpstr(editableValue.get(), ==, "a");
489
test->resetEditable();
491
// Send a normal character handled by IM.
492
test->keyStrokeHandledByInputMethodAndWaitForEvents(KEY(a), 3);
493
g_assert_cmpuint(test->m_events.size(), ==, 3);
494
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
495
g_assert_cmpuint(test->m_events[0].keyCode, ==, 65);
496
g_assert_cmpstr(test->m_events[0].key.data(), ==, "a");
497
g_assert_false(test->m_events[0].isComposing);
498
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::KeyPress);
499
g_assert_cmpuint(test->m_events[1].keyCode, ==, 97);
500
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::KeyUp);
501
g_assert_cmpuint(test->m_events[2].keyCode, ==, 65);
502
g_assert_cmpstr(test->m_events[2].key.data(), ==, "a");
503
g_assert_false(test->m_events[2].isComposing);
505
auto editableValue = test->editableValue();
506
g_assert_cmpstr(editableValue.get(), ==, "a");
508
test->resetEditable();
511
static void testWebKitInputMethodContextSequence(InputMethodTest* test, gconstpointer)
513
test->loadHtml(testHTML, nullptr);
514
test->waitUntilLoadFinished();
516
test->focusEditableAndWaitUntilInputMethodEnabled();
518
// Compose w + gtk + Enter.
519
test->keyStrokeAndWaitForEvents(KEY(w), 4, CONTROL_MASK | SHIFT_MASK);
520
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
521
g_assert_cmpuint(test->m_events[0].keyCode, ==, 229);
522
g_assert_cmpstr(test->m_events[0].key.data(), ==, "Unidentified");
523
g_assert_false(test->m_events[0].isComposing);
524
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::CompositionStart);
525
g_assert_cmpstr(test->m_events[1].data.data(), ==, "");
526
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::CompositionUpdate);
527
g_assert_cmpstr(test->m_events[2].data.data(), ==, "w");
528
g_assert_true(test->m_events[3].type == InputMethodTest::Event::Type::KeyUp);
529
g_assert_cmpuint(test->m_events[3].keyCode, ==, 87);
530
g_assert_cmpstr(test->m_events[3].key.data(), ==, "w");
531
g_assert_true(test->m_events[3].isComposing);
532
test->m_events.clear();
533
test->keyStrokeAndWaitForEvents(KEY(g), 3);
534
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
535
g_assert_cmpuint(test->m_events[0].keyCode, ==, 229);
536
g_assert_cmpstr(test->m_events[0].key.data(), ==, "Unidentified");
537
g_assert_true(test->m_events[0].isComposing);
538
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::CompositionUpdate);
539
g_assert_cmpstr(test->m_events[1].data.data(), ==, "wg");
540
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::KeyUp);
541
g_assert_cmpuint(test->m_events[2].keyCode, ==, 71);
542
g_assert_cmpstr(test->m_events[2].key.data(), ==, "g");
543
g_assert_true(test->m_events[2].isComposing);
544
test->m_events.clear();
545
test->keyStrokeAndWaitForEvents(KEY(t), 3);
546
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
547
g_assert_cmpuint(test->m_events[0].keyCode, ==, 229);
548
g_assert_cmpstr(test->m_events[0].key.data(), ==, "Unidentified");
549
g_assert_true(test->m_events[0].isComposing);
550
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::CompositionUpdate);
551
g_assert_cmpstr(test->m_events[1].data.data(), ==, "wgt");
552
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::KeyUp);
553
g_assert_cmpuint(test->m_events[2].keyCode, ==, 84);
554
g_assert_cmpstr(test->m_events[2].key.data(), ==, "t");
555
g_assert_true(test->m_events[2].isComposing);
556
test->m_events.clear();
557
test->keyStrokeAndWaitForEvents(KEY(k), 3);
558
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
559
g_assert_cmpuint(test->m_events[0].keyCode, ==, 229);
560
g_assert_cmpstr(test->m_events[0].key.data(), ==, "Unidentified");
561
g_assert_true(test->m_events[0].isComposing);
562
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::CompositionUpdate);
563
g_assert_cmpstr(test->m_events[1].data.data(), ==, "wgtk");
564
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::KeyUp);
565
g_assert_cmpuint(test->m_events[2].keyCode, ==, 75);
566
g_assert_cmpstr(test->m_events[2].key.data(), ==, "k");
567
g_assert_true(test->m_events[2].isComposing);
568
test->m_events.clear();
569
test->keyStrokeAndWaitForEvents(KEY(ISO_Enter), 3);
570
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
571
g_assert_cmpuint(test->m_events[0].keyCode, ==, 229);
572
g_assert_cmpstr(test->m_events[0].key.data(), ==, "Unidentified");
573
g_assert_true(test->m_events[0].isComposing);
574
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::CompositionEnd);
575
g_assert_cmpstr(test->m_events[1].data.data(), ==, "WebKitGTK");
576
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::KeyUp);
577
g_assert_cmpuint(test->m_events[2].keyCode, ==, 13);
578
g_assert_cmpstr(test->m_events[2].key.data(), ==, "Enter");
579
g_assert_false(test->m_events[2].isComposing);
581
auto editableValue = test->editableValue();
582
g_assert_cmpstr(editableValue.get(), ==, "WebKitGTK");
584
test->resetEditable();
586
// Compose w + wpe + Space.
587
test->keyStrokeAndWaitForEvents(KEY(w), 4, CONTROL_MASK | SHIFT_MASK);
588
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
589
g_assert_cmpuint(test->m_events[0].keyCode, ==, 229);
590
g_assert_cmpstr(test->m_events[0].key.data(), ==, "Unidentified");
591
g_assert_false(test->m_events[0].isComposing);
592
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::CompositionStart);
593
g_assert_cmpstr(test->m_events[1].data.data(), ==, "");
594
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::CompositionUpdate);
595
g_assert_cmpstr(test->m_events[2].data.data(), ==, "w");
596
g_assert_true(test->m_events[3].type == InputMethodTest::Event::Type::KeyUp);
597
g_assert_cmpuint(test->m_events[3].keyCode, ==, 87);
598
g_assert_cmpstr(test->m_events[3].key.data(), ==, "w");
599
g_assert_true(test->m_events[3].isComposing);
600
test->m_events.clear();
601
test->keyStrokeAndWaitForEvents(KEY(w), 3);
602
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
603
g_assert_cmpuint(test->m_events[0].keyCode, ==, 229);
604
g_assert_cmpstr(test->m_events[0].key.data(), ==, "Unidentified");
605
g_assert_true(test->m_events[0].isComposing);
606
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::CompositionUpdate);
607
g_assert_cmpstr(test->m_events[1].data.data(), ==, "ww");
608
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::KeyUp);
609
g_assert_cmpuint(test->m_events[2].keyCode, ==, 87);
610
g_assert_cmpstr(test->m_events[2].key.data(), ==, "w");
611
g_assert_true(test->m_events[2].isComposing);
612
test->m_events.clear();
613
test->keyStrokeAndWaitForEvents(KEY(p), 3);
614
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
615
g_assert_cmpuint(test->m_events[0].keyCode, ==, 229);
616
g_assert_cmpstr(test->m_events[0].key.data(), ==, "Unidentified");
617
g_assert_true(test->m_events[0].isComposing);
618
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::CompositionUpdate);
619
g_assert_cmpstr(test->m_events[1].data.data(), ==, "wwp");
620
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::KeyUp);
621
g_assert_cmpuint(test->m_events[2].keyCode, ==, 80);
622
g_assert_cmpstr(test->m_events[2].key.data(), ==, "p");
623
g_assert_true(test->m_events[2].isComposing);
624
test->m_events.clear();
625
test->keyStrokeAndWaitForEvents(KEY(e), 3);
626
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
627
g_assert_cmpuint(test->m_events[0].keyCode, ==, 229);
628
g_assert_cmpstr(test->m_events[0].key.data(), ==, "Unidentified");
629
g_assert_true(test->m_events[0].isComposing);
630
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::CompositionUpdate);
631
g_assert_cmpstr(test->m_events[1].data.data(), ==, "wwpe");
632
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::KeyUp);
633
g_assert_cmpuint(test->m_events[2].keyCode, ==, 69);
634
g_assert_cmpstr(test->m_events[2].key.data(), ==, "e");
635
g_assert_true(test->m_events[2].isComposing);
636
test->m_events.clear();
637
test->keyStrokeAndWaitForEvents(KEY(space), 3);
638
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
639
g_assert_cmpuint(test->m_events[0].keyCode, ==, 229);
640
g_assert_cmpstr(test->m_events[0].key.data(), ==, "Unidentified");
641
g_assert_true(test->m_events[0].isComposing);
642
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::CompositionEnd);
643
g_assert_cmpstr(test->m_events[1].data.data(), ==, "WPEWebKit");
644
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::KeyUp);
645
g_assert_cmpuint(test->m_events[2].keyCode, ==, 32);
646
g_assert_cmpstr(test->m_events[2].key.data(), ==, " ");
647
g_assert_false(test->m_events[2].isComposing);
649
auto editableValue = test->editableValue();
650
g_assert_cmpstr(editableValue.get(), ==, "WPEWebKit");
652
test->resetEditable();
655
static void testWebKitInputMethodContextInvalidSequence(InputMethodTest* test, gconstpointer)
657
test->loadHtml(testHTML, nullptr);
658
test->waitUntilLoadFinished();
660
test->focusEditableAndWaitUntilInputMethodEnabled();
662
// Compose w + w + Space -> invalid sequence.
663
test->keyStrokeAndWaitForEvents(KEY(w), 4, CONTROL_MASK | SHIFT_MASK);
664
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
665
g_assert_cmpuint(test->m_events[0].keyCode, ==, 229);
666
g_assert_cmpstr(test->m_events[0].key.data(), ==, "Unidentified");
667
g_assert_false(test->m_events[0].isComposing);
668
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::CompositionStart);
669
g_assert_cmpstr(test->m_events[1].data.data(), ==, "");
670
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::CompositionUpdate);
671
g_assert_cmpstr(test->m_events[2].data.data(), ==, "w");
672
g_assert_true(test->m_events[3].type == InputMethodTest::Event::Type::KeyUp);
673
g_assert_cmpuint(test->m_events[3].keyCode, ==, 87);
674
g_assert_cmpstr(test->m_events[3].key.data(), ==, "w");
675
g_assert_true(test->m_events[3].isComposing);
676
test->m_events.clear();
677
test->keyStrokeAndWaitForEvents(KEY(w), 3);
678
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
679
g_assert_cmpuint(test->m_events[0].keyCode, ==, 229);
680
g_assert_cmpstr(test->m_events[0].key.data(), ==, "Unidentified");
681
g_assert_true(test->m_events[0].isComposing);
682
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::CompositionUpdate);
683
g_assert_cmpstr(test->m_events[1].data.data(), ==, "ww");
684
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::KeyUp);
685
g_assert_cmpuint(test->m_events[2].keyCode, ==, 87);
686
g_assert_cmpstr(test->m_events[2].key.data(), ==, "w");
687
g_assert_true(test->m_events[2].isComposing);
688
test->m_events.clear();
689
test->keyStrokeAndWaitForEvents(KEY(space), 3);
690
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
691
g_assert_cmpuint(test->m_events[0].keyCode, ==, 229);
692
g_assert_cmpstr(test->m_events[0].key.data(), ==, "Unidentified");
693
g_assert_true(test->m_events[0].isComposing);
694
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::CompositionEnd);
695
g_assert_cmpstr(test->m_events[1].data.data(), ==, "w");
696
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::KeyUp);
697
g_assert_cmpuint(test->m_events[2].keyCode, ==, 32);
698
g_assert_cmpstr(test->m_events[2].key.data(), ==, " ");
699
g_assert_false(test->m_events[2].isComposing);
701
auto editableValue = test->editableValue();
702
g_assert_cmpstr(editableValue.get(), ==, "w");
704
test->resetEditable();
707
static void testWebKitInputMethodContextCancelSequence(InputMethodTest* test, gconstpointer)
709
test->loadHtml(testHTML, nullptr);
710
test->waitUntilLoadFinished();
712
test->focusEditableAndWaitUntilInputMethodEnabled();
714
// Compose w + w + Escape -> cancel sequence.
715
test->keyStrokeAndWaitForEvents(KEY(w), 4, CONTROL_MASK | SHIFT_MASK);
716
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
717
g_assert_cmpuint(test->m_events[0].keyCode, ==, 229);
718
g_assert_cmpstr(test->m_events[0].key.data(), ==, "Unidentified");
719
g_assert_false(test->m_events[0].isComposing);
720
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::CompositionStart);
721
g_assert_cmpstr(test->m_events[1].data.data(), ==, "");
722
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::CompositionUpdate);
723
g_assert_cmpstr(test->m_events[2].data.data(), ==, "w");
724
g_assert_true(test->m_events[3].type == InputMethodTest::Event::Type::KeyUp);
725
g_assert_cmpuint(test->m_events[3].keyCode, ==, 87);
726
g_assert_cmpstr(test->m_events[3].key.data(), ==, "w");
727
g_assert_true(test->m_events[3].isComposing);
728
test->m_events.clear();
729
test->keyStrokeAndWaitForEvents(KEY(Escape), 3);
730
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
731
g_assert_cmpuint(test->m_events[0].keyCode, ==, 229);
732
g_assert_cmpstr(test->m_events[0].key.data(), ==, "Unidentified");
733
g_assert_true(test->m_events[0].isComposing);
734
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::CompositionEnd);
735
g_assert_cmpstr(test->m_events[1].data.data(), ==, "");
736
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::KeyUp);
737
g_assert_cmpuint(test->m_events[2].keyCode, ==, 27);
738
g_assert_cmpstr(test->m_events[2].key.data(), ==, "Escape");
739
g_assert_false(test->m_events[2].isComposing);
741
auto editableValue = test->editableValue();
742
g_assert_cmpstr(editableValue.get(), ==, "");
744
test->resetEditable();
747
static void testWebKitInputMethodContextSurrounding(InputMethodTest* test, gconstpointer)
749
test->loadHtml(testHTML, nullptr);
750
test->waitUntilLoadFinished();
752
test->focusEditableAndWaitUntilInputMethodEnabled();
754
g_assert_null(test->surroundingText());
755
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 0);
756
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, test->surroundingCursorIndex());
758
test->keyStrokeAndWaitForEvents(KEY(a), 3);
759
test->keyStrokeAndWaitForEvents(KEY(b), 6);
760
test->keyStrokeAndWaitForEvents(KEY(c), 9);
761
g_assert_cmpstr(test->surroundingText(), ==, "abc");
762
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 3);
763
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, test->surroundingCursorIndex());
764
test->m_events.clear();
766
// Check preedit string is not included in surrounding.
767
// 1. Preedit string at the beginning of context.
768
test->keyStrokeAndWaitForEvents(KEY(Left), 2);
769
test->keyStrokeAndWaitForEvents(KEY(Left), 4);
770
test->keyStrokeAndWaitForEvents(KEY(Left), 6);
771
g_assert_cmpstr(test->surroundingText(), ==, "abc");
772
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 0);
773
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, test->surroundingCursorIndex());
774
test->m_events.clear();
775
test->keyStrokeAndWaitForEvents(KEY(w), 4, CONTROL_MASK | SHIFT_MASK);
776
g_assert_cmpstr(test->surroundingText(), ==, "abc");
777
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 0);
778
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, test->surroundingCursorIndex());
779
test->keyStrokeAndWaitForEvents(KEY(g), 7);
780
test->keyStrokeAndWaitForEvents(KEY(t), 10);
781
test->keyStrokeAndWaitForEvents(KEY(k), 13);
782
g_assert_cmpstr(test->surroundingText(), ==, "abc");
783
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 0);
784
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, test->surroundingCursorIndex());
785
test->keyStrokeAndWaitForEvents(KEY(ISO_Enter), 16);
786
g_assert_cmpstr(test->surroundingText(), ==, "WebKitGTKabc");
787
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 9);
788
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, test->surroundingCursorIndex());
789
test->m_events.clear();
790
// 2. Preedit string in the middle of context.
791
test->keyStrokeAndWaitForEvents(KEY(w), 4, CONTROL_MASK | SHIFT_MASK);
792
g_assert_cmpstr(test->surroundingText(), ==, "WebKitGTKabc");
793
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 9);
794
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, test->surroundingCursorIndex());
795
test->keyStrokeAndWaitForEvents(KEY(w), 7);
796
test->keyStrokeAndWaitForEvents(KEY(p), 10);
797
test->keyStrokeAndWaitForEvents(KEY(e), 13);
798
g_assert_cmpstr(test->surroundingText(), ==, "WebKitGTKabc");
799
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 9);
800
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, test->surroundingCursorIndex());
801
test->keyStrokeAndWaitForEvents(KEY(space), 16);
802
g_assert_cmpstr(test->surroundingText(), ==, "WebKitGTKWPEWebKitabc");
803
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 18);
804
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, test->surroundingCursorIndex());
805
test->m_events.clear();
806
// 3. Preedit string at the end of context.
807
test->keyStrokeAndWaitForEvents(KEY(Right), 2);
808
test->keyStrokeAndWaitForEvents(KEY(Right), 4);
809
test->keyStrokeAndWaitForEvents(KEY(Right), 6);
810
g_assert_cmpstr(test->surroundingText(), ==, "WebKitGTKWPEWebKitabc");
811
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 21);
812
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, test->surroundingCursorIndex());
813
test->m_events.clear();
814
test->keyStrokeAndWaitForEvents(KEY(w), 4, CONTROL_MASK | SHIFT_MASK);
815
g_assert_cmpstr(test->surroundingText(), ==, "WebKitGTKWPEWebKitabc");
816
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 21);
817
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, test->surroundingCursorIndex());
818
test->keyStrokeAndWaitForEvents(KEY(g), 7);
819
test->keyStrokeAndWaitForEvents(KEY(t), 10);
820
test->keyStrokeAndWaitForEvents(KEY(k), 13);
821
g_assert_cmpstr(test->surroundingText(), ==, "WebKitGTKWPEWebKitabc");
822
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 21);
823
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, test->surroundingCursorIndex());
824
test->keyStrokeAndWaitForEvents(KEY(ISO_Enter), 16);
825
g_assert_cmpstr(test->surroundingText(), ==, "WebKitGTKWPEWebKitabcWebKitGTK");
826
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 30);
827
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, test->surroundingCursorIndex());
828
test->m_events.clear();
830
// Check selection cursor.
831
test->keyStrokeAndWaitForEvents(KEY(Left), 2, SHIFT_MASK);
832
g_assert_cmpstr(test->surroundingText(), ==, "WebKitGTKWPEWebKitabcWebKitGTK");
833
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 29);
834
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, 30);
835
test->keyStrokeAndWaitForEvents(KEY(Home), 4, SHIFT_MASK);
836
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 0);
837
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, 30);
838
test->keyStrokeAndWaitForEvents(KEY(Left), 6);
839
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 0);
840
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, test->surroundingCursorIndex());
841
test->m_events.clear();
842
test->keyStrokeAndWaitForEvents(KEY(Right), 2, SHIFT_MASK);
843
g_assert_cmpstr(test->surroundingText(), ==, "WebKitGTKWPEWebKitabcWebKitGTK");
844
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 0);
845
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, 1);
846
test->keyStrokeAndWaitForEvents(KEY(End), 4, SHIFT_MASK);
847
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 0);
848
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, 30);
849
test->keyStrokeAndWaitForEvents(KEY(Right), 6);
850
g_assert_cmpstr(test->surroundingText(), ==, "WebKitGTKWPEWebKitabcWebKitGTK");
851
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 30);
852
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, test->surroundingCursorIndex());
853
test->m_events.clear();
855
// Check text replacements (get surrounding + delete surrounding).
856
test->keyStrokeAndWaitForEvents(KEY(colon), 3);
857
test->keyStrokeAndWaitForEvents(KEY(minus), 6);
858
test->keyStrokeAndWaitForEvents(KEY(parenright), 9);
859
test->waitForSurroundingText("WebKitGTKWPEWebKitabcWebKitGTK😀️");
860
g_assert_cmpstr(test->surroundingText(), ==, "WebKitGTKWPEWebKitabcWebKitGTK😀️");
861
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 37);
862
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, test->surroundingCursorIndex());
863
test->m_events.clear();
865
// Check multiline context.
866
test->keyStrokeAndWaitForEvents(KEY(Return), 3);
867
test->keyStrokeAndWaitForEvents(KEY(a), 6);
868
test->waitForSurroundingText("WebKitGTKWPEWebKitabcWebKitGTK😀️\na");
869
g_assert_cmpstr(test->surroundingText(), ==, "WebKitGTKWPEWebKitabcWebKitGTK😀️\na");
870
g_assert_cmpuint(test->surroundingCursorIndex(), ==, 39);
871
g_assert_cmpuint(test->surroundingSelectionIndex(), ==, test->surroundingCursorIndex());
872
test->m_events.clear();
875
static void testWebKitInputMethodContextReset(InputMethodTest* test, gconstpointer)
877
test->loadHtml(testHTML, nullptr);
878
test->waitUntilLoadFinished();
880
test->focusEditableAndWaitUntilInputMethodEnabled();
882
// Compose w + w + click -> reset sequence.
883
test->keyStrokeAndWaitForEvents(KEY(w), 4, CONTROL_MASK | SHIFT_MASK);
884
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::KeyDown);
885
g_assert_cmpuint(test->m_events[0].keyCode, ==, 229);
886
g_assert_cmpstr(test->m_events[0].key.data(), ==, "Unidentified");
887
g_assert_false(test->m_events[0].isComposing);
888
g_assert_true(test->m_events[1].type == InputMethodTest::Event::Type::CompositionStart);
889
g_assert_cmpstr(test->m_events[1].data.data(), ==, "");
890
g_assert_true(test->m_events[2].type == InputMethodTest::Event::Type::CompositionUpdate);
891
g_assert_cmpstr(test->m_events[2].data.data(), ==, "w");
892
g_assert_true(test->m_events[3].type == InputMethodTest::Event::Type::KeyUp);
893
g_assert_cmpuint(test->m_events[3].keyCode, ==, 87);
894
g_assert_cmpstr(test->m_events[3].key.data(), ==, "w");
895
g_assert_true(test->m_events[3].isComposing);
896
test->m_events.clear();
897
test->clickAndWaitForEvents(1);
898
g_assert_true(test->m_events[0].type == InputMethodTest::Event::Type::CompositionEnd);
899
g_assert_cmpstr(test->m_events[0].data.data(), ==, "w");
901
auto editableValue = test->editableValue();
902
g_assert_cmpstr(editableValue.get(), ==, "w");
904
test->resetEditable();
907
static void testWebKitInputMethodContextContentType(InputMethodTest* test, gconstpointer)
909
test->loadHtml("<input id='editable' spellcheck='false'></input>", nullptr);
910
test->waitUntilLoadFinished();
911
test->focusEditableAndWaitUntilInputMethodEnabled();
912
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_FREE_FORM);
913
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_NONE);
914
test->unfocusEditableAndWaitUntilInputMethodDisabled();
916
test->loadHtml("<input id='editable' type='number' spellcheck='false'>", nullptr);
917
test->waitUntilLoadFinished();
918
test->focusEditableAndWaitUntilInputMethodEnabled();
919
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_NUMBER);
920
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_NONE);
921
test->unfocusEditableAndWaitUntilInputMethodDisabled();
923
test->loadHtml("<input id='editable' type='number' spellcheck='false' pattern='[0-9]*'>", nullptr);
924
test->waitUntilLoadFinished();
925
test->focusEditableAndWaitUntilInputMethodEnabled();
926
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_DIGITS);
927
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_NONE);
928
test->unfocusEditableAndWaitUntilInputMethodDisabled();
930
test->loadHtml("<input id='editable' type='text' spellcheck='false' pattern='\\d*'>", nullptr);
931
test->waitUntilLoadFinished();
932
test->focusEditableAndWaitUntilInputMethodEnabled();
933
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_DIGITS);
934
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_NONE);
935
test->unfocusEditableAndWaitUntilInputMethodDisabled();
937
test->loadHtml("<input id='editable' type='tel' spellcheck='false'>", nullptr);
938
test->waitUntilLoadFinished();
939
test->focusEditableAndWaitUntilInputMethodEnabled();
940
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_PHONE);
941
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_NONE);
942
test->unfocusEditableAndWaitUntilInputMethodDisabled();
944
test->loadHtml("<input id='editable' type='url' spellcheck='false'>", nullptr);
945
test->waitUntilLoadFinished();
946
test->focusEditableAndWaitUntilInputMethodEnabled();
947
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_URL);
948
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_NONE);
949
test->unfocusEditableAndWaitUntilInputMethodDisabled();
951
test->loadHtml("<input id='editable' type='email' spellcheck='false'>", nullptr);
952
test->waitUntilLoadFinished();
953
test->focusEditableAndWaitUntilInputMethodEnabled();
954
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_EMAIL);
955
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_NONE);
956
test->unfocusEditableAndWaitUntilInputMethodDisabled();
958
test->loadHtml("<input id='editable' type='password' spellcheck='false'>", nullptr);
959
test->waitUntilLoadFinished();
960
test->focusEditableAndWaitUntilInputMethodEnabled();
961
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_PASSWORD);
962
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_NONE);
963
test->unfocusEditableAndWaitUntilInputMethodDisabled();
965
test->loadHtml("<div contenteditable id='editable' inputmode='text' spellcheck='false'></div>", nullptr);
966
test->waitUntilLoadFinished();
967
test->focusEditableAndWaitUntilInputMethodEnabled();
968
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_FREE_FORM);
969
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_NONE);
970
test->unfocusEditableAndWaitUntilInputMethodDisabled();
972
test->loadHtml("<div contenteditable id='editable' inputmode='decimal' spellcheck='false'></div>", nullptr);
973
test->waitUntilLoadFinished();
974
test->focusEditableAndWaitUntilInputMethodEnabled();
975
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_NUMBER);
976
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_NONE);
977
test->unfocusEditableAndWaitUntilInputMethodDisabled();
979
test->loadHtml("<div contenteditable id='editable' inputmode='numeric' spellcheck='false'></div>", nullptr);
980
test->waitUntilLoadFinished();
981
test->focusEditableAndWaitUntilInputMethodEnabled();
982
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_DIGITS);
983
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_NONE);
984
test->unfocusEditableAndWaitUntilInputMethodDisabled();
986
test->loadHtml("<div contenteditable id='editable' inputmode='tel' spellcheck='false'></div>", nullptr);
987
test->waitUntilLoadFinished();
988
test->focusEditableAndWaitUntilInputMethodEnabled();
989
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_PHONE);
990
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_NONE);
991
test->unfocusEditableAndWaitUntilInputMethodDisabled();
993
test->loadHtml("<div contenteditable id='editable' inputmode='email' spellcheck='false'></div>", nullptr);
994
test->waitUntilLoadFinished();
995
test->focusEditableAndWaitUntilInputMethodEnabled();
996
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_EMAIL);
997
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_NONE);
998
test->unfocusEditableAndWaitUntilInputMethodDisabled();
1000
test->loadHtml("<div contenteditable id='editable' inputmode='url' spellcheck='false'></div>", nullptr);
1001
test->waitUntilLoadFinished();
1002
test->focusEditableAndWaitUntilInputMethodEnabled();
1003
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_URL);
1004
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_NONE);
1005
test->unfocusEditableAndWaitUntilInputMethodDisabled();
1007
test->loadHtml("<div contenteditable id='editable' inputmode='search' spellcheck='false'></div>", nullptr);
1008
test->waitUntilLoadFinished();
1009
test->focusEditableAndWaitUntilInputMethodEnabled();
1010
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_FREE_FORM);
1011
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_NONE);
1012
test->unfocusEditableAndWaitUntilInputMethodDisabled();
1014
test->loadHtml("<div contenteditable id='editable' inputmode='none' spellcheck='false'></div>", nullptr);
1015
test->waitUntilLoadFinished();
1016
test->focusEditableAndWaitUntilInputMethodEnabled();
1017
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_FREE_FORM);
1018
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_INHIBIT_OSK);
1019
test->unfocusEditableAndWaitUntilInputMethodDisabled();
1021
test->loadHtml("<textarea id='editable'></textarea>", nullptr);
1022
test->waitUntilLoadFinished();
1023
test->focusEditableAndWaitUntilInputMethodEnabled();
1024
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_FREE_FORM);
1025
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_SPELLCHECK);
1026
test->unfocusEditableAndWaitUntilInputMethodDisabled();
1028
test->loadHtml("<textarea id='editable' autocapitalize='none'></textarea>", nullptr);
1029
test->waitUntilLoadFinished();
1030
test->focusEditableAndWaitUntilInputMethodEnabled();
1031
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_FREE_FORM);
1032
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_SPELLCHECK | WEBKIT_INPUT_HINT_LOWERCASE);
1033
test->unfocusEditableAndWaitUntilInputMethodDisabled();
1035
test->loadHtml("<textarea id='editable' autocapitalize='sentences'></textarea>", nullptr);
1036
test->waitUntilLoadFinished();
1037
test->focusEditableAndWaitUntilInputMethodEnabled();
1038
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_FREE_FORM);
1039
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_SPELLCHECK | WEBKIT_INPUT_HINT_UPPERCASE_SENTENCES);
1040
test->unfocusEditableAndWaitUntilInputMethodDisabled();
1042
test->loadHtml("<textarea id='editable' autocapitalize='words'></textarea>", nullptr);
1043
test->waitUntilLoadFinished();
1044
test->focusEditableAndWaitUntilInputMethodEnabled();
1045
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_FREE_FORM);
1046
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_SPELLCHECK | WEBKIT_INPUT_HINT_UPPERCASE_WORDS);
1047
test->unfocusEditableAndWaitUntilInputMethodDisabled();
1049
test->loadHtml("<textarea id='editable' autocapitalize='characters'></textarea>", nullptr);
1050
test->waitUntilLoadFinished();
1051
test->focusEditableAndWaitUntilInputMethodEnabled();
1052
g_assert_cmpuint(test->purpose(), ==, WEBKIT_INPUT_PURPOSE_FREE_FORM);
1053
g_assert_cmpuint(test->hints(), ==, WEBKIT_INPUT_HINT_SPELLCHECK | WEBKIT_INPUT_HINT_UPPERCASE_CHARS);
1054
test->unfocusEditableAndWaitUntilInputMethodDisabled();
1059
InputMethodTest::add("WebKitInputMethodContext", "simple", testWebKitInputMethodContextSimple);
1060
InputMethodTest::add("WebKitInputMethodContext", "sequence", testWebKitInputMethodContextSequence);
1061
InputMethodTest::add("WebKitInputMethodContext", "invalid-sequence", testWebKitInputMethodContextInvalidSequence);
1062
InputMethodTest::add("WebKitInputMethodContext", "cancel-sequence", testWebKitInputMethodContextCancelSequence);
1063
InputMethodTest::add("WebKitInputMethodContext", "surrounding", testWebKitInputMethodContextSurrounding);
1064
InputMethodTest::add("WebKitInputMethodContext", "reset", testWebKitInputMethodContextReset);
1065
InputMethodTest::add("WebKitInputMethodContext", "content-type", testWebKitInputMethodContextContentType);