[GTK] Implement KeyDown function for WebKit2 EventSender.
[WebKit-https.git] / Tools / WebKitTestRunner / gtk / EventSenderProxyGtk.cpp
1 /*
2  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3  * Copyright (C) 2009 Zan Dobersek <zandobersek@gmail.com>
4  * Copyright (C) 2009 Holger Hans Peter Freyther
5  * Copyright (C) 2010 Igalia S.L.
6  * Copyright (c) 2010 Motorola Mobility, Inc.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1.  Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  * 2.  Redistributions in binary form must reproduce the above copyright
15  *     notice, this list of conditions and the following disclaimer in the
16  *     documentation and/or other materials provided with the distribution.
17  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
18  *     its contributors may be used to endorse or promote products derived
19  *     from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
22  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
25  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "config.h"
34 #include "EventSenderProxy.h"
35
36 #include "PlatformWebView.h"
37 #include "TestController.h"
38 #include <GOwnPtrGtk.h>
39 #include <GtkVersioning.h>
40 #include <gdk/gdk.h>
41 #include <gdk/gdkkeysyms.h>
42 #include <gtk/gtk.h>
43 #include <wtf/text/WTFString.h>
44
45 namespace WTR {
46 // Key event location code defined in DOM Level 3.
47 enum KeyLocationCode {
48     DOMKeyLocationStandard      = 0x00,
49     DOMKeyLocationLeft          = 0x01,
50     DOMKeyLocationRight         = 0x02,
51     DOMKeyLocationNumpad        = 0x03
52 };
53
54 EventSenderProxy::EventSenderProxy(TestController* testController)
55     : m_testController(testController)
56 {
57 }
58
59 static void dispatchEvent(GdkEvent* event)
60 {
61     gtk_main_do_event(event);
62     gdk_event_free(event);
63 }
64
65
66 static guint getModifiers(WKEventModifiers modifiersRef)
67 {
68     guint modifiers = 0;
69
70     if (modifiersRef & kWKEventModifiersControlKey)
71         modifiers |= kWKEventModifiersControlKey;
72     if (modifiersRef & kWKEventModifiersShiftKey)
73         modifiers |= kWKEventModifiersShiftKey;
74     if (modifiersRef & kWKEventModifiersAltKey)
75         modifiers |= kWKEventModifiersAltKey;
76     if (modifiersRef & kWKEventModifiersMetaKey)
77         modifiers |= kWKEventModifiersMetaKey;
78
79     return modifiers;
80 }
81
82 int getGDKKeySymForKeyRef(WKStringRef keyRef, unsigned location, guint* modifiers)
83 {
84     if (location == DOMKeyLocationNumpad) {
85         if (WKStringIsEqualToUTF8CString(keyRef, "leftArrow"))
86             return GDK_KEY_KP_Left;
87         if (WKStringIsEqualToUTF8CString(keyRef, "rightArror"))
88             return GDK_KEY_KP_Right;
89         if (WKStringIsEqualToUTF8CString(keyRef, "upArrow"))
90             return GDK_KEY_KP_Up;
91         if (WKStringIsEqualToUTF8CString(keyRef, "downArrow"))
92             return GDK_KEY_KP_Down;
93         if (WKStringIsEqualToUTF8CString(keyRef, "pageUp"))
94             return GDK_KEY_KP_Page_Up;
95         if (WKStringIsEqualToUTF8CString(keyRef, "pageDown"))
96             return GDK_KEY_KP_Page_Down;
97         if (WKStringIsEqualToUTF8CString(keyRef, "home"))
98             return GDK_KEY_KP_Home;
99         if (WKStringIsEqualToUTF8CString(keyRef, "end"))
100             return GDK_KEY_KP_End;
101         if (WKStringIsEqualToUTF8CString(keyRef, "insert"))
102             return GDK_KEY_KP_Insert;
103         if (WKStringIsEqualToUTF8CString(keyRef, "delete"))
104             return GDK_KEY_KP_Delete;
105
106         return GDK_KEY_VoidSymbol;
107     }
108
109     if (WKStringIsEqualToUTF8CString(keyRef, "leftArrow"))
110         return GDK_KEY_Left;
111     if (WKStringIsEqualToUTF8CString(keyRef, "rightArror"))
112         return GDK_KEY_Right;
113     if (WKStringIsEqualToUTF8CString(keyRef, "upArrow"))
114         return GDK_KEY_Up;
115     if (WKStringIsEqualToUTF8CString(keyRef, "downArrow"))
116         return GDK_KEY_Down;
117     if (WKStringIsEqualToUTF8CString(keyRef, "pageUp"))
118         return GDK_KEY_Page_Up;
119     if (WKStringIsEqualToUTF8CString(keyRef, "pageDown"))
120         return GDK_KEY_Page_Down;
121     if (WKStringIsEqualToUTF8CString(keyRef, "home"))
122         return GDK_KEY_Home;
123     if (WKStringIsEqualToUTF8CString(keyRef, "end"))
124         return GDK_KEY_End;
125     if (WKStringIsEqualToUTF8CString(keyRef, "insert"))
126         return GDK_KEY_Insert;
127     if (WKStringIsEqualToUTF8CString(keyRef, "delete"))
128         return GDK_KEY_Delete;
129     if (WKStringIsEqualToUTF8CString(keyRef, "printScreen"))
130         return GDK_KEY_Print;
131     if (WKStringIsEqualToUTF8CString(keyRef, "menu"))
132         return GDK_KEY_Menu;
133     if (WKStringIsEqualToUTF8CString(keyRef, "F1"))
134         return GDK_KEY_F1;
135     if (WKStringIsEqualToUTF8CString(keyRef, "F2"))
136         return GDK_KEY_F2;
137     if (WKStringIsEqualToUTF8CString(keyRef, "F3"))
138         return GDK_KEY_F3;
139     if (WKStringIsEqualToUTF8CString(keyRef, "F4"))
140         return GDK_KEY_F4;
141     if (WKStringIsEqualToUTF8CString(keyRef, "F5"))
142         return GDK_KEY_F5;
143     if (WKStringIsEqualToUTF8CString(keyRef, "F6"))
144         return GDK_KEY_F6;
145     if (WKStringIsEqualToUTF8CString(keyRef, "F7"))
146         return GDK_KEY_F7;
147     if (WKStringIsEqualToUTF8CString(keyRef, "F8"))
148         return GDK_KEY_F8;
149     if (WKStringIsEqualToUTF8CString(keyRef, "F9"))
150         return GDK_KEY_F9;
151     if (WKStringIsEqualToUTF8CString(keyRef, "F10"))
152         return GDK_KEY_F10;
153     if (WKStringIsEqualToUTF8CString(keyRef, "F11"))
154         return GDK_KEY_F11;
155     if (WKStringIsEqualToUTF8CString(keyRef, "F12"))
156         return GDK_KEY_F12;
157
158     size_t stringSize = WKStringGetLength(keyRef);
159     char* buffer = new char[stringSize];
160     WKStringGetUTF8CString(keyRef, buffer, stringSize);
161     int charCode = buffer[0];
162
163     if (charCode == '\n' || charCode == '\r')
164         return GDK_KEY_Return;
165     if (charCode == '\t')
166         return GDK_KEY_Tab;
167     if (charCode == '\x8')
168         return GDK_KEY_BackSpace;
169
170     if (WTF::isASCIIUpper(charCode))
171         *modifiers |= GDK_SHIFT_MASK;
172
173     return gdk_unicode_to_keyval(charCode);
174 }
175
176 void EventSenderProxy::keyDown(WKStringRef keyRef, WKEventModifiers modifiersRef, unsigned location)
177 {
178     guint modifiers = getModifiers(modifiersRef);
179     int gdkKeySym = getGDKKeySymForKeyRef(keyRef, location, &modifiers);
180
181     GdkEvent* pressEvent = gdk_event_new(GDK_KEY_PRESS);
182     pressEvent->key.keyval = gdkKeySym;
183     pressEvent->key.state = modifiers;
184     pressEvent->key.window = gtk_widget_get_window(GTK_WIDGET(m_testController->mainWebView()->platformView()));
185     g_object_ref(pressEvent->key.window);
186     gdk_event_set_device(pressEvent, getDefaultGDKPointerDevice(pressEvent->key.window));
187
188     GOwnPtr<GdkKeymapKey> keys;
189     gint nKeys;
190     if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), gdkKeySym, &keys.outPtr(), &nKeys))
191         pressEvent->key.hardware_keycode = keys.outPtr()[0].keycode;
192
193     GdkEvent* releaseEvent = gdk_event_copy(pressEvent);
194     dispatchEvent(pressEvent);
195     releaseEvent->key.type = GDK_KEY_RELEASE;
196     dispatchEvent(releaseEvent);
197 }
198
199 } // namespace WTR