[GTK][Wayland] Crash when gdk_keymap_get_entries_for_keyval returns TRUE but n_keys=0
[WebKit-https.git] / Tools / TestWebKitAPI / gtk / PlatformWebViewGtk.cpp
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 #include "PlatformWebView.h"
28
29 #include <WebCore/GUniquePtrGtk.h>
30 #include <WebKit/WKRetainPtr.h>
31 #include <WebKit/WKView.h>
32 #include <gtk/gtk.h>
33 #include <wtf/glib/GUniquePtr.h>
34
35 namespace TestWebKitAPI {
36
37 PlatformWebView::PlatformWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef)
38 {
39     WKRetainPtr<WKPageConfigurationRef> configuration = adoptWK(WKPageConfigurationCreate());
40     WKPageConfigurationSetContext(configuration.get(), contextRef);
41     WKPageConfigurationSetPageGroup(configuration.get(), pageGroupRef);
42
43     initialize(configuration.get());
44 }
45
46 PlatformWebView::PlatformWebView(WKPageConfigurationRef configuration)
47 {
48     initialize(configuration);
49 }
50
51 PlatformWebView::PlatformWebView(WKPageRef relatedPage)
52 {
53     WKRetainPtr<WKPageConfigurationRef> configuration = adoptWK(WKPageConfigurationCreate());
54     WKPageConfigurationSetContext(configuration.get(), WKPageGetContext(relatedPage));
55     WKPageConfigurationSetPageGroup(configuration.get(), WKPageGetPageGroup(relatedPage));
56     WKPageConfigurationSetRelatedPage(configuration.get(), relatedPage);
57
58     initialize(configuration.get());
59 }
60
61 PlatformWebView::~PlatformWebView()
62 {
63     gtk_widget_destroy(m_window);
64 }
65
66 void PlatformWebView::initialize(WKPageConfigurationRef configuration)
67 {
68     m_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
69     m_view = WKViewCreate(configuration);
70     gtk_container_add(GTK_CONTAINER(m_window), GTK_WIDGET(m_view));
71     gtk_widget_show(GTK_WIDGET(m_view));
72     gtk_widget_show(m_window);
73 }
74
75 WKPageRef PlatformWebView::page() const
76 {
77     return WKViewGetPage(m_view);
78 }
79
80 void PlatformWebView::resizeTo(unsigned width, unsigned height)
81 {
82     gtk_window_resize(GTK_WINDOW(m_window), width, height);
83 }
84
85 static void doKeyStroke(GtkWidget* viewWidget, unsigned int keyVal)
86 {
87     GUniquePtr<GdkEvent> event(gdk_event_new(GDK_KEY_PRESS));
88     event->key.keyval = keyVal;
89     event->key.time = GDK_CURRENT_TIME;
90     event->key.state = 0;
91     event->key.window = gtk_widget_get_window(viewWidget);
92     g_object_ref(event->key.window);
93     gdk_event_set_device(event.get(), gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gtk_widget_get_display(viewWidget))));
94
95     // When synthesizing an event, an invalid hardware_keycode value can cause it to be badly processed by GTK+.
96     GUniqueOutPtr<GdkKeymapKey> keys;
97     int keysCount;
98     if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), keyVal, &keys.outPtr(), &keysCount) && keysCount)
99         event->key.hardware_keycode = keys.get()[0].keycode;
100
101     gtk_main_do_event(event.get());
102     event->key.type = GDK_KEY_RELEASE;
103     gtk_main_do_event(event.get());
104 }
105
106 void PlatformWebView::simulateSpacebarKeyPress()
107 {
108     GtkWidget* viewWidget = GTK_WIDGET(m_view);
109     if (!gtk_widget_get_realized(viewWidget))
110         gtk_widget_show(m_window);
111     doKeyStroke(viewWidget, GDK_KEY_KP_Space);
112 }
113
114 void PlatformWebView::simulateAltKeyPress()
115 {
116     GtkWidget* viewWidget = GTK_WIDGET(m_view);
117     if (!gtk_widget_get_realized(viewWidget))
118         gtk_widget_show(m_window);
119     doKeyStroke(viewWidget, GDK_KEY_Alt_L);
120 }
121
122 static void doMouseButtonEvent(GtkWidget* viewWidget, GdkEventType eventType, int x, int y, unsigned int button)
123 {
124     GUniquePtr<GdkEvent> event(gdk_event_new(eventType));
125     event->button.x = x;
126     event->button.y = y;
127     event->button.button = button;
128     event->button.time = GDK_CURRENT_TIME;
129     event->button.axes = 0;
130     event->button.state = 0;
131     event->button.window = gtk_widget_get_window(viewWidget);
132     g_object_ref(event->button.window);
133     event->button.device = gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gtk_widget_get_display(viewWidget)));
134
135     int xRoot, yRoot;
136     gdk_window_get_root_coords(gtk_widget_get_window(viewWidget), x, y, &xRoot, &yRoot);
137     event->button.x_root = xRoot;
138     event->button.y_root = yRoot;
139     gtk_main_do_event(event.get());
140 }
141
142 void PlatformWebView::simulateRightClick(unsigned x, unsigned y)
143 {
144     GtkWidget* viewWidget = GTK_WIDGET(m_view);
145     if (!gtk_widget_get_realized(viewWidget))
146         gtk_widget_show(m_window);
147     doMouseButtonEvent(viewWidget, GDK_BUTTON_PRESS, x, y, 3);
148     doMouseButtonEvent(viewWidget, GDK_BUTTON_RELEASE, x, y, 3);
149 }
150
151 void PlatformWebView::simulateMouseMove(unsigned x, unsigned y, WKEventModifiers)
152 {
153     GUniquePtr<GdkEvent> event(gdk_event_new(GDK_MOTION_NOTIFY));
154     event->motion.x = x;
155     event->motion.y = y;
156     event->motion.time = GDK_CURRENT_TIME;
157     event->motion.state = 0;
158     event->motion.axes = 0;
159
160     GtkWidget* viewWidget = GTK_WIDGET(m_view);
161     if (!gtk_widget_get_realized(viewWidget))
162         gtk_widget_show(m_window);
163     event->motion.window = gtk_widget_get_window(viewWidget);
164     g_object_ref(event->motion.window);
165     event->motion.device = gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gtk_widget_get_display(viewWidget)));
166
167     int xRoot, yRoot;
168     gdk_window_get_root_coords(gtk_widget_get_window(viewWidget), x, y, &xRoot, &yRoot);
169     event->motion.x_root = xRoot;
170     event->motion.y_root = yRoot;
171     gtk_main_do_event(event.get());
172 }
173
174 } // namespace TestWebKitAPI