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

Side by Side Diff: Tools/TestWebKitAPI/Tests/gtk/InputMethodFilter.cpp

Issue 13602008: Remove non-chromium code from TestWebKitAPI (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 8 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2012 Igalia S.L.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27
28 #include "GtkInputMethodFilter.h"
29 #include "WTFStringUtilities.h"
30 #include <gdk/gdkkeysyms.h>
31 #include <gtk/gtk.h>
32 #include <wtf/gobject/GOwnPtr.h>
33 #include <wtf/gobject/GRefPtr.h>
34 #include <wtf/text/CString.h>
35
36 using namespace WebCore;
37
38 namespace TestWebKitAPI {
39
40 class TestInputMethodFilter : public GtkInputMethodFilter {
41 public:
42 TestInputMethodFilter()
43 : m_testWindow(gtk_window_new(GTK_WINDOW_POPUP))
44 {
45 gtk_widget_show(m_testWindow.get());
46 setWidget(m_testWindow.get());
47
48 // Focus in is necessary to activate the default input method in the mul ticontext.
49 notifyFocusedIn();
50 }
51
52 Vector<String>& events() { return m_events; }
53
54 void sendKeyEventToFilter(unsigned int gdkKeyValue, GdkEventType type, unsig ned int modifiers = 0)
55 {
56 GdkEvent* event = gdk_event_new(type);
57 event->key.keyval = gdkKeyValue;
58 event->key.state = modifiers;
59 event->key.window = gtk_widget_get_window(m_testWindow.get());
60 event->key.time = GDK_CURRENT_TIME;
61 g_object_ref(event->key.window);
62
63 #ifndef GTK_API_VERSION_2
64 gdk_event_set_device(event, gdk_device_manager_get_client_pointer(gdk_di splay_get_device_manager(gdk_display_get_default())));
65 #endif
66
67 GOwnPtr<GdkKeymapKey> keys;
68 gint nKeys;
69 if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), gdkKeyVa lue, &keys.outPtr(), &nKeys))
70 event->key.hardware_keycode = keys.get()[0].keycode;
71
72 filterKeyEvent(&event->key);
73 gdk_event_free(event);
74 }
75
76 void sendPressAndReleaseKeyEventPairToFilter(unsigned int gdkKeyValue, unsig ned int modifiers = 0)
77 {
78 sendKeyEventToFilter(gdkKeyValue, GDK_KEY_PRESS, modifiers);
79 sendKeyEventToFilter(gdkKeyValue, GDK_KEY_RELEASE, modifiers);
80 }
81
82 protected:
83 virtual bool sendSimpleKeyEvent(GdkEventKey* event, WTF::String eventString, EventFakedForComposition faked)
84 {
85 const char* eventType = event->type == GDK_KEY_RELEASE ? "release" : "pr ess";
86 const char* fakedString = faked == EventFaked ? " (faked)" : "";
87 if (!eventString.isNull())
88 m_events.append(String::format("sendSimpleKeyEvent type=%s keycode=% x text='%s'%s", eventType, event->keyval, eventString.utf8().data(), fakedString ));
89 else
90 m_events.append(String::format("sendSimpleKeyEvent type=%s keycode=% x%s", eventType, event->keyval, fakedString));
91
92 return true;
93 }
94
95 virtual bool sendKeyEventWithCompositionResults(GdkEventKey* event, ResultsT oSend resultsToSend, EventFakedForComposition faked)
96 {
97 const char* eventType = event->type == GDK_KEY_RELEASE ? "release" : "pr ess";
98 const char* fakedString = faked == EventFaked ? " (faked)" : "";
99 m_events.append(String::format("sendKeyEventWithCompositionResults type= %s keycode=%u%s", eventType, event->keyval, fakedString));
100
101 if (resultsToSend & Composition && !m_confirmedComposition.isNull())
102 confirmCompositionText(m_confirmedComposition);
103 if (resultsToSend & Preedit && !m_preedit.isNull())
104 setPreedit(m_preedit, m_cursorOffset);
105
106 return true;
107 }
108
109 virtual bool canEdit()
110 {
111 return true;
112 }
113
114 virtual void confirmCompositionText(String text)
115 {
116 m_events.append(String::format("confirmComposition '%s'", text.utf8().da ta()));
117 }
118
119 virtual void confirmCurrentComposition()
120 {
121 m_events.append(String("confirmCurrentcomposition"));
122 }
123
124 virtual void cancelCurrentComposition()
125 {
126 m_events.append(String("cancelCurrentComposition"));
127 }
128
129 virtual void setPreedit(String preedit, int cursorOffset)
130 {
131 m_events.append(String::format("setPreedit text='%s' cursorOffset=%i", p reedit.utf8().data(), cursorOffset));
132 }
133
134 private:
135 GRefPtr<GtkWidget> m_testWindow;
136 Vector<String> m_events;
137 };
138
139 TEST(GTK, GtkInputMethodFilterSimple)
140 {
141 TestInputMethodFilter inputMethodFilter;
142 inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_g);
143 inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_t);
144 inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_k);
145
146 const Vector<String>& events = inputMethodFilter.events();
147
148 ASSERT_EQ(6, events.size());
149 ASSERT_EQ(String("sendSimpleKeyEvent type=press keycode=67 text='g'"), event s[0]);
150 ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=67"), events[1]);
151 ASSERT_EQ(String("sendSimpleKeyEvent type=press keycode=74 text='t'"), event s[2]);
152 ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=74"), events[3]);
153 ASSERT_EQ(String("sendSimpleKeyEvent type=press keycode=6b text='k'"), event s[4]);
154 ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=6b"), events[5]);
155 }
156
157 TEST(GTK, GtkInputMethodFilterUnicodeSequence)
158 {
159 TestInputMethodFilter inputMethodFilter;
160
161 // This is simple unicode hex entry of the characters, u, 0, 0, f, 4 pressed with
162 // the shift and controls keys held down. In reality, these values are not t ypical
163 // of an actual hex entry, because they'd be transformed by the shift modifi er according
164 // to the keyboard layout. For instance, on a US keyboard a 0 with the shift key pressed
165 // is a right parenthesis. Using these values prevents having to work out wh at the
166 // transformed characters are based on the current keyboard layout.
167 inputMethodFilter.sendKeyEventToFilter(GDK_KEY_Control_L, GDK_KEY_PRESS);
168 inputMethodFilter.sendKeyEventToFilter(GDK_KEY_Shift_L, GDK_KEY_PRESS, GDK_C ONTROL_MASK);
169
170 inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_U, GDK_SHI FT_MASK | GDK_CONTROL_MASK);
171 inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_0, GDK_SHI FT_MASK | GDK_CONTROL_MASK);
172 inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_0, GDK_SHI FT_MASK | GDK_CONTROL_MASK);
173 inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_F, GDK_SHI FT_MASK | GDK_CONTROL_MASK);
174 inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_4, GDK_SHI FT_MASK | GDK_CONTROL_MASK);
175
176 inputMethodFilter.sendKeyEventToFilter(GDK_KEY_Shift_L, GDK_KEY_RELEASE, GDK _CONTROL_MASK | GDK_SHIFT_MASK);
177 inputMethodFilter.sendKeyEventToFilter(GDK_KEY_Control_L, GDK_KEY_RELEASE, G DK_CONTROL_MASK);
178
179 const Vector<String>& events = inputMethodFilter.events();
180 ASSERT_EQ(21, events.size());
181 ASSERT_EQ(String("sendSimpleKeyEvent type=press keycode=ffe3"), events[0]);
182 ASSERT_EQ(String("sendSimpleKeyEvent type=press keycode=ffe1"), events[1]);
183 ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=85") , events[2]);
184 ASSERT_EQ(String("setPreedit text='u' cursorOffset=1"), events[3]);
185 ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=55"), events[4]);
186 ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=48") , events[5]);
187 ASSERT_EQ(String("setPreedit text='u0' cursorOffset=2"), events[6]);
188 ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=30"), events[7]);
189 ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=48") , events[8]);
190 ASSERT_EQ(String("setPreedit text='u00' cursorOffset=3"), events[9]);
191 ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=30"), events[10]);
192 ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=70") , events[11]);
193 ASSERT_EQ(String("setPreedit text='u00F' cursorOffset=4"), events[12]);
194 ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=46"), events[13]);
195 ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=52") , events[14]);
196 ASSERT_EQ(String("setPreedit text='u00F4' cursorOffset=5"), events[15]);
197 ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=34"), events[16]);
198 ASSERT_EQ(String("confirmComposition 'ô'"), events[17]);
199 ASSERT_EQ(String("setPreedit text='' cursorOffset=0"), events[18]);
200 ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=ffe1"), events[19] );
201 ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=ffe3"), events[20] );
202 }
203
204 TEST(GTK, GtkInputMethodFilterComposeKey)
205 {
206 TestInputMethodFilter inputMethodFilter;
207
208 inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_Multi_key) ;
209 inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_apostrophe );
210 inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_o);
211
212 const Vector<String>& events = inputMethodFilter.events();
213 ASSERT_EQ(5, events.size());
214 ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=39") , events[0]);
215 ASSERT_EQ(String("setPreedit text='' cursorOffset=0"), events[1]);
216 ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=27"), events[2]);
217 ASSERT_EQ(String("sendSimpleKeyEvent type=press keycode=6f text='ó'"), event s[3]);
218 ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=6f"), events[4]);
219 }
220
221 typedef void (*GetPreeditStringCallback) (GtkIMContext*, gchar**, PangoAttrList* *, int*);
222 static void temporaryGetPreeditStringOverride(GtkIMContext*, char** string, Pang oAttrList** attrs, int* cursorPosition)
223 {
224 *string = g_strdup("preedit of doom, bringer of cheese");
225 *cursorPosition = 3;
226 }
227
228 TEST(GTK, GtkInputMethodFilterContextEventsWithoutKeyEvents)
229 {
230 TestInputMethodFilter inputMethodFilter;
231
232 // This is a bit of a hack to avoid mocking out the entire InputMethodContex t, by
233 // simply replacing the get_preedit_string virtual method for the length of this test.
234 GtkIMContext* context = inputMethodFilter.context();
235 GtkIMContextClass* contextClass = GTK_IM_CONTEXT_GET_CLASS(context);
236 GetPreeditStringCallback previousCallback = contextClass->get_preedit_string ;
237 contextClass->get_preedit_string = temporaryGetPreeditStringOverride;
238
239 g_signal_emit_by_name(context, "preedit-changed");
240 g_signal_emit_by_name(context, "commit", "commit text");
241
242 contextClass->get_preedit_string = previousCallback;
243
244 const Vector<String>& events = inputMethodFilter.events();
245 ASSERT_EQ(6, events.size());
246 ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=1677 7215 (faked)"), events[0]);
247 ASSERT_EQ(String("setPreedit text='preedit of doom, bringer of cheese' curso rOffset=3"), events[1]);
248 ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=ffffff (faked)"), events[2]);
249 ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=1677 7215 (faked)"), events[3]);
250 ASSERT_EQ(String("confirmComposition 'commit text'"), events[4]);
251 ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=ffffff (faked)"), events[5]);
252 }
253
254 static bool gSawContextReset = false;
255 typedef void (*ResetCallback) (GtkIMContext*);
256 static void temporaryResetOverride(GtkIMContext*)
257 {
258 gSawContextReset = true;
259 }
260
261 static void verifyCanceledComposition(const Vector<String>& events)
262 {
263 ASSERT_EQ(3, events.size());
264 ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=39") , events[0]);
265 ASSERT_EQ(String("setPreedit text='' cursorOffset=0"), events[1]);
266 ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=27"), events[2]);
267 ASSERT(gSawContextReset);
268 }
269
270 TEST(GTK, GtkInputMethodFilterContextFocusOutDuringOngoingComposition)
271 {
272 TestInputMethodFilter inputMethodFilter;
273
274 // See comment above about this technique.
275 GtkIMContext* context = inputMethodFilter.context();
276 GtkIMContextClass* contextClass = GTK_IM_CONTEXT_GET_CLASS(context);
277 ResetCallback previousCallback = contextClass->reset;
278 contextClass->reset = temporaryResetOverride;
279
280 gSawContextReset = false;
281 inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_Multi_key) ;
282 inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_apostrophe );
283 inputMethodFilter.notifyFocusedOut();
284
285 verifyCanceledComposition(inputMethodFilter.events());
286
287 contextClass->reset = previousCallback;
288 }
289
290 TEST(GTK, GtkInputMethodFilterContextMouseClickDuringOngoingComposition)
291 {
292 TestInputMethodFilter inputMethodFilter;
293
294 // See comment above about this technique.
295 GtkIMContext* context = inputMethodFilter.context();
296 GtkIMContextClass* contextClass = GTK_IM_CONTEXT_GET_CLASS(context);
297 ResetCallback previousCallback = contextClass->reset;
298 contextClass->reset = temporaryResetOverride;
299
300 gSawContextReset = false;
301 inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_Multi_key) ;
302 inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_apostrophe );
303 inputMethodFilter.notifyMouseButtonPress();
304
305 verifyCanceledComposition(inputMethodFilter.events());
306
307 contextClass->reset = previousCallback;
308 }
309
310 } // namespace TestWebKitAPI
OLDNEW
« no previous file with comments | « Tools/TestWebKitAPI/Tests/WebKit2ObjC/WKBrowsingContextLoadDelegateTest.mm ('k') | Tools/TestWebKitAPI/Tests/mac/0.png » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698