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 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 <WebCore/GtkUtilities.h>
39#include <WebCore/NotImplemented.h>
40#include <gdk/gdkkeysyms.h>
41#include <gtk/gtk.h>
42#include <wtf/StdLibExtras.h>
43#include <wtf/glib/GUniquePtr.h>
44#include <wtf/text/WTFString.h>
45
46namespace WTR {
47
48// WebCore and layout tests assume this value
49static const float pixelsPerScrollTick = 40;
50
51// Key event location code defined in DOM Level 3.
52enum KeyLocationCode {
53 DOMKeyLocationStandard = 0x00,
54 DOMKeyLocationLeft = 0x01,
55 DOMKeyLocationRight = 0x02,
56 DOMKeyLocationNumpad = 0x03
57};
58
59
60struct WTREventQueueItem {
61 GdkEvent* event;
62 gulong delay;
63
64 WTREventQueueItem()
65 : event(0)
66 , delay(0)
67 {
68 }
69 WTREventQueueItem(GdkEvent* event, gulong delay)
70 : event(event)
71 , delay(delay)
72 {
73 }
74};
75
76EventSenderProxy::EventSenderProxy(TestController* testController)
77 : m_testController(testController)
78 , m_time(0)
79 , m_leftMouseButtonDown(false)
80 , m_clickCount(0)
81 , m_clickTime(0)
82 , m_clickButton(kWKEventMouseButtonNoButton)
83{
84}
85
86EventSenderProxy::~EventSenderProxy()
87{
88}
89
90static unsigned eventSenderButtonToGDKButton(unsigned button)
91{
92 int mouseButton = 3;
93 if (button <= 2)
94 mouseButton = button + 1;
95 // fast/events/mouse-click-events expects the 4th button to be treated as the middle button.
96 else if (button == 3)
97 mouseButton = 2;
98
99 return mouseButton;
100}
101
102static guint webkitModifiersToGDKModifiers(WKEventModifiers wkModifiers)
103{
104 guint modifiers = 0;
105
106 if (wkModifiers & kWKEventModifiersControlKey)
107 modifiers |= GDK_CONTROL_MASK;
108 if (wkModifiers & kWKEventModifiersShiftKey)
109 modifiers |= GDK_SHIFT_MASK;
110 if (wkModifiers & kWKEventModifiersAltKey)
111 modifiers |= GDK_MOD1_MASK;
112 if (wkModifiers & kWKEventModifiersMetaKey)
113 modifiers |= GDK_META_MASK;
114 if (wkModifiers & kWKEventModifiersCapsLockKey)
115 modifiers |= GDK_LOCK_MASK;
116
117 return modifiers;
118}
119
120GdkEvent* EventSenderProxy::createMouseButtonEvent(GdkEventType eventType, unsigned button, WKEventModifiers modifiers)
121{
122 GdkEvent* mouseEvent = gdk_event_new(eventType);
123
124 mouseEvent->button.button = button;
125 mouseEvent->button.x = m_position.x;
126 mouseEvent->button.y = m_position.y;
127 mouseEvent->button.window = gtk_widget_get_window(GTK_WIDGET(m_testController->mainWebView()->platformView()));
128 g_object_ref(mouseEvent->button.window);
129 gdk_event_set_device(mouseEvent, gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gdk_window_get_display(mouseEvent->button.window))));
130 mouseEvent->button.state = webkitModifiersToGDKModifiers(modifiers) | m_mouseButtonsCurrentlyDown;
131 mouseEvent->button.time = GDK_CURRENT_TIME;
132 mouseEvent->button.axes = 0;
133
134 int xRoot, yRoot;
135 gdk_window_get_root_coords(mouseEvent->button.window, m_position.x, m_position.y, &xRoot, &yRoot);
136 mouseEvent->button.x_root = xRoot;
137 mouseEvent->button.y_root = yRoot;
138
139 return mouseEvent;
140}
141
142void EventSenderProxy::updateClickCountForButton(int button)
143{
144 if (m_time - m_clickTime < 1 && m_position == m_clickPosition && button == m_clickButton) {
145 ++m_clickCount;
146 m_clickTime = m_time;
147 return;
148 }
149
150 m_clickCount = 1;
151 m_clickTime = m_time;
152 m_clickPosition = m_position;
153 m_clickButton = button;
154}
155
156void EventSenderProxy::dispatchEvent(GdkEvent* event)
157{
158 ASSERT(m_testController->mainWebView());
159 gtk_main_do_event(event);
160 gdk_event_free(event);
161}
162
163void EventSenderProxy::replaySavedEvents()
164{
165 while (!m_eventQueue.isEmpty()) {
166 WTREventQueueItem item = m_eventQueue.takeFirst();
167 if (item.delay)
168 g_usleep(item.delay * 1000);
169
170 dispatchEvent(item.event);
171 }
172}
173
174void EventSenderProxy::sendOrQueueEvent(GdkEvent* event)
175{
176 if (m_eventQueue.isEmpty() || !m_eventQueue.last().delay) {
177 dispatchEvent(event);
178 return;
179 }
180
181 m_eventQueue.last().event = event;
182 replaySavedEvents();
183}
184
185int getGDKKeySymForKeyRef(WKStringRef keyRef, unsigned location, guint* modifiers)
186{
187 if (location == DOMKeyLocationNumpad) {
188 if (WKStringIsEqualToUTF8CString(keyRef, "leftArrow"))
189 return GDK_KEY_KP_Left;
190 if (WKStringIsEqualToUTF8CString(keyRef, "rightArror"))
191 return GDK_KEY_KP_Right;
192 if (WKStringIsEqualToUTF8CString(keyRef, "upArrow"))
193 return GDK_KEY_KP_Up;
194 if (WKStringIsEqualToUTF8CString(keyRef, "downArrow"))
195 return GDK_KEY_KP_Down;
196 if (WKStringIsEqualToUTF8CString(keyRef, "pageUp"))
197 return GDK_KEY_KP_Page_Up;
198 if (WKStringIsEqualToUTF8CString(keyRef, "pageDown"))
199 return GDK_KEY_KP_Page_Down;
200 if (WKStringIsEqualToUTF8CString(keyRef, "home"))
201 return GDK_KEY_KP_Home;
202 if (WKStringIsEqualToUTF8CString(keyRef, "end"))
203 return GDK_KEY_KP_End;
204 if (WKStringIsEqualToUTF8CString(keyRef, "insert"))
205 return GDK_KEY_KP_Insert;
206 if (WKStringIsEqualToUTF8CString(keyRef, "delete"))
207 return GDK_KEY_KP_Delete;
208
209 return GDK_KEY_VoidSymbol;
210 }
211
212 if (WKStringIsEqualToUTF8CString(keyRef, "leftControl"))
213 return GDK_KEY_Control_L;
214 if (WKStringIsEqualToUTF8CString(keyRef, "rightControl"))
215 return GDK_KEY_Control_R;
216 if (WKStringIsEqualToUTF8CString(keyRef, "leftShift"))
217 return GDK_KEY_Shift_L;
218 if (WKStringIsEqualToUTF8CString(keyRef, "rightShift"))
219 return GDK_KEY_Shift_R;
220 if (WKStringIsEqualToUTF8CString(keyRef, "leftAlt"))
221 return GDK_KEY_Alt_L;
222 if (WKStringIsEqualToUTF8CString(keyRef, "rightAlt"))
223 return GDK_KEY_Alt_R;
224 if (WKStringIsEqualToUTF8CString(keyRef, "leftArrow"))
225 return GDK_KEY_Left;
226 if (WKStringIsEqualToUTF8CString(keyRef, "rightArrow"))
227 return GDK_KEY_Right;
228 if (WKStringIsEqualToUTF8CString(keyRef, "upArrow"))
229 return GDK_KEY_Up;
230 if (WKStringIsEqualToUTF8CString(keyRef, "downArrow"))
231 return GDK_KEY_Down;
232 if (WKStringIsEqualToUTF8CString(keyRef, "pageUp"))
233 return GDK_KEY_Page_Up;
234 if (WKStringIsEqualToUTF8CString(keyRef, "pageDown"))
235 return GDK_KEY_Page_Down;
236 if (WKStringIsEqualToUTF8CString(keyRef, "home"))
237 return GDK_KEY_Home;
238 if (WKStringIsEqualToUTF8CString(keyRef, "end"))
239 return GDK_KEY_End;
240 if (WKStringIsEqualToUTF8CString(keyRef, "insert"))
241 return GDK_KEY_Insert;
242 if (WKStringIsEqualToUTF8CString(keyRef, "delete"))
243 return GDK_KEY_Delete;
244 if (WKStringIsEqualToUTF8CString(keyRef, "printScreen"))
245 return GDK_KEY_Print;
246 if (WKStringIsEqualToUTF8CString(keyRef, "menu"))
247 return GDK_KEY_Menu;
248 if (WKStringIsEqualToUTF8CString(keyRef, "F1"))
249 return GDK_KEY_F1;
250 if (WKStringIsEqualToUTF8CString(keyRef, "F2"))
251 return GDK_KEY_F2;
252 if (WKStringIsEqualToUTF8CString(keyRef, "F3"))
253 return GDK_KEY_F3;
254 if (WKStringIsEqualToUTF8CString(keyRef, "F4"))
255 return GDK_KEY_F4;
256 if (WKStringIsEqualToUTF8CString(keyRef, "F5"))
257 return GDK_KEY_F5;
258 if (WKStringIsEqualToUTF8CString(keyRef, "F6"))
259 return GDK_KEY_F6;
260 if (WKStringIsEqualToUTF8CString(keyRef, "F7"))
261 return GDK_KEY_F7;
262 if (WKStringIsEqualToUTF8CString(keyRef, "F8"))
263 return GDK_KEY_F8;
264 if (WKStringIsEqualToUTF8CString(keyRef, "F9"))
265 return GDK_KEY_F9;
266 if (WKStringIsEqualToUTF8CString(keyRef, "F10"))
267 return GDK_KEY_F10;
268 if (WKStringIsEqualToUTF8CString(keyRef, "F11"))
269 return GDK_KEY_F11;
270 if (WKStringIsEqualToUTF8CString(keyRef, "F12"))
271 return GDK_KEY_F12;
272
273 size_t bufferSize = WKStringGetMaximumUTF8CStringSize(keyRef);
274 auto buffer = std::make_unique<char[]>(bufferSize);
275 WKStringGetUTF8CString(keyRef, buffer.get(), bufferSize);
276 char charCode = buffer.get()[0];
277
278 if (charCode == '\n' || charCode == '\r')
279 return GDK_KEY_Return;
280 if (charCode == '\t')
281 return GDK_KEY_Tab;
282 if (charCode == '\x8')
283 return GDK_KEY_BackSpace;
284 if (charCode == 0x001B)
285 return GDK_KEY_Escape;
286
287 if (WTF::isASCIIUpper(charCode))
288 *modifiers |= GDK_SHIFT_MASK;
289
290 return gdk_unicode_to_keyval(static_cast<guint32>(buffer.get()[0]));
291}
292
293void EventSenderProxy::keyDown(WKStringRef keyRef, WKEventModifiers wkModifiers, unsigned location)
294{
295 guint modifiers = webkitModifiersToGDKModifiers(wkModifiers);
296 int gdkKeySym = getGDKKeySymForKeyRef(keyRef, location, &modifiers);
297
298 GdkEvent* pressEvent = gdk_event_new(GDK_KEY_PRESS);
299 pressEvent->key.keyval = gdkKeySym;
300 pressEvent->key.state = modifiers;
301 pressEvent->key.window = gtk_widget_get_window(GTK_WIDGET(m_testController->mainWebView()->platformWindow()));
302 g_object_ref(pressEvent->key.window);
303 gdk_event_set_device(pressEvent, gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gdk_window_get_display(pressEvent->key.window))));
304
305 GUniqueOutPtr<GdkKeymapKey> keys;
306 gint nKeys;
307 if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), gdkKeySym, &keys.outPtr(), &nKeys) && nKeys)
308 pressEvent->key.hardware_keycode = keys.get()[0].keycode;
309
310 GdkEvent* releaseEvent = gdk_event_copy(pressEvent);
311 dispatchEvent(pressEvent);
312 releaseEvent->key.type = GDK_KEY_RELEASE;
313 dispatchEvent(releaseEvent);
314}
315
316void EventSenderProxy::mouseDown(unsigned button, WKEventModifiers wkModifiers)
317{
318 unsigned gdkButton = eventSenderButtonToGDKButton(button);
319 auto modifier = WebCore::stateModifierForGdkButton(gdkButton);
320
321 // If the same mouse button is already in the down position don't
322 // send another event as it may confuse Xvfb.
323 if (m_mouseButtonsCurrentlyDown & modifier)
324 return;
325
326 // Normally GDK will send both GDK_BUTTON_PRESS and GDK_2BUTTON_PRESS for
327 // the second button press during double-clicks. WebKit GTK+ selectively
328 // ignores the first GDK_BUTTON_PRESS of that pair using gdk_event_peek.
329 // Since our events aren't ever going onto the GDK event queue, WebKit won't
330 // be able to filter out the first GDK_BUTTON_PRESS, so we just don't send
331 // it here. Eventually this code should probably figure out a way to get all
332 // appropriate events onto the event queue and this work-around should be
333 // removed.
334 updateClickCountForButton(button);
335
336 GdkEventType eventType;
337 if (m_clickCount == 2)
338 eventType = GDK_2BUTTON_PRESS;
339 else if (m_clickCount == 3)
340 eventType = GDK_3BUTTON_PRESS;
341 else
342 eventType = GDK_BUTTON_PRESS;
343
344 GdkEvent* event = createMouseButtonEvent(eventType, gdkButton, wkModifiers);
345 m_mouseButtonsCurrentlyDown |= modifier;
346 sendOrQueueEvent(event);
347}
348
349void EventSenderProxy::mouseUp(unsigned button, WKEventModifiers wkModifiers)
350{
351 m_clickButton = kWKEventMouseButtonNoButton;
352 unsigned gdkButton = eventSenderButtonToGDKButton(button);
353 GdkEvent* event = createMouseButtonEvent(GDK_BUTTON_RELEASE, gdkButton, wkModifiers);
354 auto modifier = WebCore::stateModifierForGdkButton(gdkButton);
355 m_mouseButtonsCurrentlyDown &= ~modifier;
356 sendOrQueueEvent(event);
357
358 m_clickPosition = m_position;
359 m_clickTime = GDK_CURRENT_TIME;
360}
361
362void EventSenderProxy::mouseMoveTo(double x, double y)
363{
364 m_position.x = x;
365 m_position.y = y;
366
367 GdkEvent* event = gdk_event_new(GDK_MOTION_NOTIFY);
368 event->motion.x = m_position.x;
369 event->motion.y = m_position.y;
370
371 event->motion.time = GDK_CURRENT_TIME;
372 event->motion.window = gtk_widget_get_window(GTK_WIDGET(m_testController->mainWebView()->platformView()));
373 g_object_ref(event->motion.window);
374 gdk_event_set_device(event, gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gdk_window_get_display(event->motion.window))));
375 event->motion.state = m_mouseButtonsCurrentlyDown;
376 event->motion.axes = 0;
377
378 int xRoot, yRoot;
379 gdk_window_get_root_coords(gtk_widget_get_window(GTK_WIDGET(m_testController->mainWebView()->platformView())), m_position.x, m_position.y , &xRoot, &yRoot);
380 event->motion.x_root = xRoot;
381 event->motion.y_root = yRoot;
382
383 sendOrQueueEvent(event);
384}
385
386void EventSenderProxy::mouseScrollBy(int horizontal, int vertical)
387{
388 // Copy behaviour of Qt and EFL - just return in case of (0,0) mouse scroll
389 if (!horizontal && !vertical)
390 return;
391
392 GdkEvent* event = gdk_event_new(GDK_SCROLL);
393 event->scroll.x = m_position.x;
394 event->scroll.y = m_position.y;
395 event->scroll.time = GDK_CURRENT_TIME;
396 event->scroll.window = gtk_widget_get_window(GTK_WIDGET(m_testController->mainWebView()->platformView()));
397 g_object_ref(event->scroll.window);
398 gdk_event_set_device(event, gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gdk_window_get_display(event->scroll.window))));
399
400 // For more than one tick in a scroll, we need smooth scroll event
401 if ((horizontal && vertical) || horizontal > 1 || horizontal < -1 || vertical > 1 || vertical < -1) {
402 event->scroll.direction = GDK_SCROLL_SMOOTH;
403 event->scroll.delta_x = -horizontal;
404 event->scroll.delta_y = -vertical;
405
406 sendOrQueueEvent(event);
407 return;
408 }
409
410 if (horizontal < 0)
411 event->scroll.direction = GDK_SCROLL_RIGHT;
412 else if (horizontal > 0)
413 event->scroll.direction = GDK_SCROLL_LEFT;
414 else if (vertical < 0)
415 event->scroll.direction = GDK_SCROLL_DOWN;
416 else if (vertical > 0)
417 event->scroll.direction = GDK_SCROLL_UP;
418 else
419 g_assert_not_reached();
420
421 sendOrQueueEvent(event);
422}
423
424void EventSenderProxy::continuousMouseScrollBy(int horizontal, int vertical, bool paged)
425{
426 // Gtk+ does not support paged scroll events.
427 if (paged) {
428 WTFLogAlways("EventSenderProxy::continuousMouseScrollBy not implemented for paged scroll events");
429 return;
430 }
431
432 GdkEvent* event = gdk_event_new(GDK_SCROLL);
433 event->scroll.x = m_position.x;
434 event->scroll.y = m_position.y;
435 event->scroll.time = GDK_CURRENT_TIME;
436 event->scroll.window = gtk_widget_get_window(GTK_WIDGET(m_testController->mainWebView()->platformView()));
437 g_object_ref(event->scroll.window);
438 gdk_event_set_device(event, gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gdk_window_get_display(event->scroll.window))));
439
440 event->scroll.direction = GDK_SCROLL_SMOOTH;
441 event->scroll.delta_x = -horizontal / pixelsPerScrollTick;
442 event->scroll.delta_y = -vertical / pixelsPerScrollTick;
443
444 sendOrQueueEvent(event);
445}
446
447void EventSenderProxy::mouseScrollByWithWheelAndMomentumPhases(int x, int y, int /*phase*/, int /*momentum*/)
448{
449 // Gtk+ does not have the concept of wheel gesture phases or momentum. Just relay to
450 // the mouse wheel handler.
451 mouseScrollBy(x, y);
452}
453
454void EventSenderProxy::leapForward(int milliseconds)
455{
456 if (m_eventQueue.isEmpty())
457 m_eventQueue.append(WTREventQueueItem());
458
459 m_eventQueue.last().delay = milliseconds;
460 m_time += milliseconds / 1000.0;
461}
462
463void updateEventCoordinates(GdkEvent* touchEvent, int x, int y)
464{
465 touchEvent->touch.x = x;
466 touchEvent->touch.y = y;
467
468 int xRoot, yRoot;
469 gdk_window_get_root_coords(touchEvent->touch.window, x, y, &xRoot, &yRoot);
470 touchEvent->touch.x_root = xRoot;
471 touchEvent->touch.y_root = yRoot;
472}
473
474GUniquePtr<GdkEvent> EventSenderProxy::createTouchEvent(GdkEventType eventType, int id)
475{
476 GUniquePtr<GdkEvent> touchEvent(gdk_event_new(eventType));
477
478 touchEvent->touch.sequence = static_cast<GdkEventSequence*>(GINT_TO_POINTER(id));
479 touchEvent->touch.window = gtk_widget_get_window(GTK_WIDGET(m_testController->mainWebView()->platformView()));
480 g_object_ref(touchEvent->touch.window);
481 gdk_event_set_device(touchEvent.get(), gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gdk_window_get_display(touchEvent->button.window))));
482 touchEvent->touch.time = GDK_CURRENT_TIME;
483
484 return touchEvent;
485}
486
487#if ENABLE(TOUCH_EVENTS)
488void EventSenderProxy::addTouchPoint(int x, int y)
489{
490 // Touch ID is array index plus one, so 0 is skipped.
491 GUniquePtr<GdkEvent> event = createTouchEvent(static_cast<GdkEventType>(GDK_TOUCH_BEGIN), m_touchEvents.size() + 1);
492 updateEventCoordinates(event.get(), x, y);
493 m_updatedTouchEvents.add(GPOINTER_TO_INT(event->touch.sequence));
494 m_touchEvents.append(std::move(event));
495}
496
497void EventSenderProxy::updateTouchPoint(int index, int x, int y)
498{
499 ASSERT(index >= 0 && static_cast<size_t>(index) < m_touchEvents.size());
500
501 const auto& event = m_touchEvents[index];
502 ASSERT(event);
503
504 event->type = GDK_TOUCH_UPDATE;
505 updateEventCoordinates(event.get(), x, y);
506 m_updatedTouchEvents.add(GPOINTER_TO_INT(event->touch.sequence));
507}
508
509void EventSenderProxy::sendUpdatedTouchEvents()
510{
511 for (auto id : m_updatedTouchEvents)
512 sendOrQueueEvent(gdk_event_copy(m_touchEvents[id - 1].get()));
513
514 m_updatedTouchEvents.clear();
515}
516
517void EventSenderProxy::touchStart()
518{
519 sendUpdatedTouchEvents();
520}
521
522void EventSenderProxy::touchMove()
523{
524 sendUpdatedTouchEvents();
525}
526
527void EventSenderProxy::touchEnd()
528{
529 sendUpdatedTouchEvents();
530}
531
532void EventSenderProxy::touchCancel()
533{
534 notImplemented();
535}
536
537void EventSenderProxy::clearTouchPoints()
538{
539 m_updatedTouchEvents.clear();
540 m_touchEvents.clear();
541}
542
543void EventSenderProxy::releaseTouchPoint(int index)
544{
545 ASSERT(index >= 0 && static_cast<size_t>(index) < m_touchEvents.size());
546
547 const auto& event = m_touchEvents[index];
548 event->type = GDK_TOUCH_END;
549 m_updatedTouchEvents.add(GPOINTER_TO_INT(event->touch.sequence));
550}
551
552void EventSenderProxy::cancelTouchPoint(int index)
553{
554 notImplemented();
555}
556
557void EventSenderProxy::setTouchPointRadius(int radiusX, int radiusY)
558{
559 notImplemented();
560}
561
562void EventSenderProxy::setTouchModifier(WKEventModifiers modifier, bool enable)
563{
564 guint state = webkitModifiersToGDKModifiers(modifier);
565
566 for (const auto& event : m_touchEvents) {
567 if (event->type == GDK_TOUCH_END)
568 continue;
569
570 if (enable)
571 event->touch.state |= state;
572 else
573 event->touch.state &= ~(state);
574
575 m_updatedTouchEvents.add(GPOINTER_TO_INT(event->touch.sequence));
576 }
577}
578#endif // ENABLE(TOUCH_EVENTS)
579
580} // namespace WTR
581