7a68c7f297de251daad333ba1e41a98b19ef68f6
[WebKit-https.git] / Tools / WebKitTestRunner / efl / EventSenderProxyEfl.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) 2011 ProFUSION Embedded Systems
7  * Copyright (C) 2012 Samsung Electronics
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
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  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "EventSenderProxy.h"
33
34 #include "NotImplemented.h"
35 #include "PlatformWebView.h"
36 #include "TestController.h"
37
38 #include <Ecore.h>
39 #include <Ecore_Evas.h>
40 #include <unistd.h>
41 #include <wtf/StdLibExtras.h>
42 #include <wtf/text/CString.h>
43 #include <wtf/text/WTFString.h>
44
45 namespace WTR {
46
47 static const char* modifierNames[] = { "Shift", "Control", "Alt", "Meta" };
48
49 enum WTREventType {
50     WTREventTypeNone = 0,
51     WTREventTypeMouseDown,
52     WTREventTypeMouseUp,
53     WTREventTypeMouseMove,
54     WTREventTypeMouseScrollBy,
55     WTREventTypeLeapForward
56 };
57
58 enum EvasMouseButton {
59     EvasMouseButtonNone = 0,
60     EvasMouseButtonLeft,
61     EvasMouseButtonMiddle,
62     EvasMouseButtonRight
63 };
64
65 // Key event location code defined in DOM Level 3.
66 enum KeyLocationCode {
67     DOMKeyLocationStandard      = 0x00,
68     DOMKeyLocationLeft          = 0x01,
69     DOMKeyLocationRight         = 0x02,
70     DOMKeyLocationNumpad        = 0x03
71 };
72
73 struct WTREvent {
74     WTREventType eventType;
75     unsigned delay;
76     WKEventModifiers modifiers;
77     int button;
78     int horizontal;
79     int vertical;
80
81     WTREvent()
82         : eventType(WTREventTypeNone)
83         , delay(0)
84         , modifiers(0)
85         , button(-1)
86         , horizontal(-1)
87         , vertical(-1)
88     {
89     }
90
91     WTREvent(WTREventType eventType, unsigned delay, WKEventModifiers modifiers, int button)
92         : eventType(eventType)
93         , delay(delay)
94         , modifiers(modifiers)
95         , button(button)
96         , horizontal(-1)
97         , vertical(-1)
98     {
99     }
100 };
101
102 struct KeyEventInfo : public RefCounted<KeyEventInfo> {
103     KeyEventInfo(const CString& keyName, const CString& keyString)
104         : keyName(keyName)
105         , keyString(keyString)
106     {
107     }
108
109     const CString keyName;
110     const CString keyString;
111 };
112
113 static unsigned evasMouseButton(unsigned button)
114 {
115     // The common case involves converting from a WKEventMouseButton (which
116     // starts at -1) to an EvasMouseButton (which a starts at 0). The special
117     // case for button 3 exists because of fast/events/mouse-click-events.html,
118     // which tests whether a 4th mouse button behaves as the middle one.
119     if (button <= kWKEventMouseButtonRightButton)
120         return button + 1;
121     if (button == kWKEventMouseButtonRightButton + 1)
122         return EvasMouseButtonMiddle;
123     return EvasMouseButtonNone;
124 }
125
126 static void setEvasModifiers(Evas* evas, WKEventModifiers wkModifiers)
127 {
128     for (unsigned modifier = 0; modifier < (sizeof(modifierNames) / sizeof(char*)); ++modifier) {
129         if (wkModifiers & (1 << modifier))
130             evas_key_modifier_on(evas, modifierNames[modifier]);
131         else
132             evas_key_modifier_off(evas, modifierNames[modifier]);
133     }
134 }
135
136 static void dispatchMouseDownEvent(Evas* evas, unsigned button, WKEventModifiers wkModifiers, int clickCount)
137 {
138     Evas_Button_Flags buttonFlags = EVAS_BUTTON_NONE;
139     if (clickCount == 3)
140         buttonFlags = EVAS_BUTTON_TRIPLE_CLICK;
141     else if (clickCount == 2)
142         buttonFlags = EVAS_BUTTON_DOUBLE_CLICK;
143
144     setEvasModifiers(evas, wkModifiers);
145     evas_event_feed_mouse_down(evas, button, buttonFlags, 0, 0);
146     setEvasModifiers(evas, 0);
147 }
148
149 static void dispatchMouseUpEvent(Evas* evas, unsigned button, WKEventModifiers wkModifiers)
150 {
151     setEvasModifiers(evas, wkModifiers);
152     evas_event_feed_mouse_up(evas, button, EVAS_BUTTON_NONE, 0, 0);
153     setEvasModifiers(evas, 0);
154 }
155
156 static void dispatchMouseMoveEvent(Evas* evas, int x, int y)
157 {
158     evas_event_feed_mouse_move(evas, x, y, 0, 0);
159 }
160
161 static void dispatchMouseScrollByEvent(Evas* evas, int horizontal, int vertical)
162 {
163     if (horizontal)
164         evas_event_feed_mouse_wheel(evas, 1, horizontal, 0, 0);
165
166     if (vertical)
167         evas_event_feed_mouse_wheel(evas, 0, vertical, 0, 0);
168 }
169
170 static const PassRefPtr<KeyEventInfo> keyPadName(WKStringRef keyRef)
171 {
172     if (WKStringIsEqualToUTF8CString(keyRef, "leftArrow"))
173         return adoptRef(new KeyEventInfo("KP_Left", ""));
174     if (WKStringIsEqualToUTF8CString(keyRef, "rightArrow"))
175         return adoptRef(new KeyEventInfo("KP_Right", ""));
176     if (WKStringIsEqualToUTF8CString(keyRef, "upArrow"))
177         return adoptRef(new KeyEventInfo("KP_Up", ""));
178     if (WKStringIsEqualToUTF8CString(keyRef, "downArrow"))
179         return adoptRef(new KeyEventInfo("KP_Down", ""));
180     if (WKStringIsEqualToUTF8CString(keyRef, "pageUp"))
181         return adoptRef(new KeyEventInfo("KP_Prior", ""));
182     if (WKStringIsEqualToUTF8CString(keyRef, "pageDown"))
183         return adoptRef(new KeyEventInfo("KP_Next", ""));
184     if (WKStringIsEqualToUTF8CString(keyRef, "home"))
185         return adoptRef(new KeyEventInfo("KP_Home", ""));
186     if (WKStringIsEqualToUTF8CString(keyRef, "end"))
187         return adoptRef(new KeyEventInfo("KP_End", ""));
188     if (WKStringIsEqualToUTF8CString(keyRef, "insert"))
189         return adoptRef(new KeyEventInfo("KP_Insert", ""));
190     if (WKStringIsEqualToUTF8CString(keyRef, "delete"))
191         return adoptRef(new KeyEventInfo("KP_Delete", ""));
192
193     size_t bufferSize = WKStringGetMaximumUTF8CStringSize(keyRef);
194     auto buffer = std::make_unique<char[]>(bufferSize);
195     WKStringGetUTF8CString(keyRef, buffer.get(), bufferSize);
196     return adoptRef(new KeyEventInfo(buffer.get(), buffer.get()));
197 }
198
199 static const PassRefPtr<KeyEventInfo> keyName(WKStringRef keyRef)
200 {
201     if (WKStringIsEqualToUTF8CString(keyRef, "leftArrow"))
202         return adoptRef(new KeyEventInfo("Left", ""));
203     if (WKStringIsEqualToUTF8CString(keyRef, "rightArrow"))
204         return adoptRef(new KeyEventInfo("Right", ""));
205     if (WKStringIsEqualToUTF8CString(keyRef, "upArrow"))
206         return adoptRef(new KeyEventInfo("Up", ""));
207     if (WKStringIsEqualToUTF8CString(keyRef, "downArrow"))
208         return adoptRef(new KeyEventInfo("Down", ""));
209     if (WKStringIsEqualToUTF8CString(keyRef, "pageUp"))
210         return adoptRef(new KeyEventInfo("Prior", ""));
211     if (WKStringIsEqualToUTF8CString(keyRef, "pageDown"))
212         return adoptRef(new KeyEventInfo("Next", ""));
213     if (WKStringIsEqualToUTF8CString(keyRef, "home"))
214         return adoptRef(new KeyEventInfo("Home", ""));
215     if (WKStringIsEqualToUTF8CString(keyRef, "end"))
216         return adoptRef(new KeyEventInfo("End", ""));
217     if (WKStringIsEqualToUTF8CString(keyRef, "insert"))
218         return adoptRef(new KeyEventInfo("Insert", ""));
219     if (WKStringIsEqualToUTF8CString(keyRef, "delete"))
220         return adoptRef(new KeyEventInfo("Delete", ""));
221     if (WKStringIsEqualToUTF8CString(keyRef, "printScreen"))
222         return adoptRef(new KeyEventInfo("Print", ""));
223     if (WKStringIsEqualToUTF8CString(keyRef, "menu"))
224         return adoptRef(new KeyEventInfo("Menu", ""));
225     if (WKStringIsEqualToUTF8CString(keyRef, "leftControl"))
226         return adoptRef(new KeyEventInfo("Control_L", ""));
227     if (WKStringIsEqualToUTF8CString(keyRef, "rightControl"))
228         return adoptRef(new KeyEventInfo("Control_R", ""));
229     if (WKStringIsEqualToUTF8CString(keyRef, "leftShift"))
230         return adoptRef(new KeyEventInfo("Shift_L", ""));
231     if (WKStringIsEqualToUTF8CString(keyRef, "rightShift"))
232         return adoptRef(new KeyEventInfo("Shift_R", ""));
233     if (WKStringIsEqualToUTF8CString(keyRef, "leftAlt"))
234         return adoptRef(new KeyEventInfo("Alt_L", ""));
235     if (WKStringIsEqualToUTF8CString(keyRef, "rightAlt"))
236         return adoptRef(new KeyEventInfo("Alt_R", ""));
237     if (WKStringIsEqualToUTF8CString(keyRef, "F1"))
238         return adoptRef(new KeyEventInfo("F1", ""));
239     if (WKStringIsEqualToUTF8CString(keyRef, "F2"))
240         return adoptRef(new KeyEventInfo("F2", ""));
241     if (WKStringIsEqualToUTF8CString(keyRef, "F3"))
242         return adoptRef(new KeyEventInfo("F3", ""));
243     if (WKStringIsEqualToUTF8CString(keyRef, "F4"))
244         return adoptRef(new KeyEventInfo("F4", ""));
245     if (WKStringIsEqualToUTF8CString(keyRef, "F5"))
246         return adoptRef(new KeyEventInfo("F5", ""));
247     if (WKStringIsEqualToUTF8CString(keyRef, "F6"))
248         return adoptRef(new KeyEventInfo("F6", ""));
249     if (WKStringIsEqualToUTF8CString(keyRef, "F7"))
250         return adoptRef(new KeyEventInfo("F7", ""));
251     if (WKStringIsEqualToUTF8CString(keyRef, "F8"))
252         return adoptRef(new KeyEventInfo("F8", ""));
253     if (WKStringIsEqualToUTF8CString(keyRef, "F9"))
254         return adoptRef(new KeyEventInfo("F9", ""));
255     if (WKStringIsEqualToUTF8CString(keyRef, "F10"))
256         return adoptRef(new KeyEventInfo("F10", ""));
257     if (WKStringIsEqualToUTF8CString(keyRef, "F11"))
258         return adoptRef(new KeyEventInfo("F11", ""));
259     if (WKStringIsEqualToUTF8CString(keyRef, "F12"))
260         return adoptRef(new KeyEventInfo("F12", ""));
261
262     size_t bufferSize = WKStringGetMaximumUTF8CStringSize(keyRef);
263     auto buffer = std::make_unique<char[]>(bufferSize);
264     WKStringGetUTF8CString(keyRef, buffer.get(), bufferSize);
265     char charCode = buffer.get()[0];
266
267     if (charCode == '\n' || charCode == '\r')
268         return adoptRef(new KeyEventInfo("Return", "\r"));
269     if (charCode == '\t')
270         return adoptRef(new KeyEventInfo("Tab", "\t"));
271     if (charCode == '\x8')
272         return adoptRef(new KeyEventInfo("BackSpace", "\x8"));
273     if (charCode == ' ')
274         return adoptRef(new KeyEventInfo("space", " "));
275
276     return adoptRef(new KeyEventInfo(buffer.get(), buffer.get()));
277 }
278
279 EventSenderProxy::EventSenderProxy(TestController* testController)
280     : m_testController(testController)
281     , m_time(0)
282     , m_leftMouseButtonDown(false)
283     , m_clickCount(0)
284     , m_clickTime(0)
285     , m_clickButton(kWKEventMouseButtonNoButton)
286     , m_mouseButton(kWKEventMouseButtonNoButton)
287 #if ENABLE(TOUCH_EVENTS)
288     , m_touchPoints(0)
289 #endif
290 {
291 }
292
293 EventSenderProxy::~EventSenderProxy()
294 {
295 #if ENABLE(TOUCH_EVENTS)
296     clearTouchPoints();
297 #endif
298 }
299
300 void EventSenderProxy::updateClickCountForButton(int button)
301 {
302     if (m_time - m_clickTime < 1 && m_position == m_clickPosition && button == m_clickButton) {
303         ++m_clickCount;
304         m_clickTime = m_time;
305         return;
306     }
307
308     m_clickCount = 1;
309     m_clickTime = m_time;
310     m_clickPosition = m_position;
311     m_clickButton = button;
312 }
313
314 void EventSenderProxy::dispatchEvent(const WTREvent& event)
315 {
316     Evas* evas = evas_object_evas_get(m_testController->mainWebView()->platformView());
317
318     if (event.eventType == WTREventTypeMouseDown)
319         dispatchMouseDownEvent(evas, event.button, event.modifiers, m_clickCount);
320     else if (event.eventType == WTREventTypeMouseUp)
321         dispatchMouseUpEvent(evas, event.button, event.modifiers);
322     else if (event.eventType == WTREventTypeMouseMove)
323         dispatchMouseMoveEvent(evas, static_cast<int>(m_position.x), static_cast<int>(m_position.y));
324     else if (event.eventType == WTREventTypeMouseScrollBy)
325         dispatchMouseScrollByEvent(evas, event.horizontal, event.vertical);
326 }
327
328 void EventSenderProxy::replaySavedEvents()
329 {
330     while (!m_eventQueue.isEmpty()) {
331         WTREvent event = m_eventQueue.takeFirst();
332         if (event.delay)
333             usleep(event.delay * 1000);
334
335         dispatchEvent(event);
336     }
337 }
338
339 void EventSenderProxy::sendOrQueueEvent(const WTREvent& event)
340 {
341     if (m_eventQueue.isEmpty() || !m_eventQueue.last().delay) {
342         dispatchEvent(event);
343         return;
344     }
345
346     m_eventQueue.append(event);
347     replaySavedEvents();
348 }
349
350 void EventSenderProxy::mouseDown(unsigned button, WKEventModifiers wkModifiers)
351 {
352     if (m_mouseButton == button)
353         return;
354
355     m_mouseButton = button;
356     updateClickCountForButton(button);
357
358     sendOrQueueEvent(WTREvent(WTREventTypeMouseDown, 0, wkModifiers, evasMouseButton(button)));
359 }
360
361 void EventSenderProxy::mouseUp(unsigned button, WKEventModifiers wkModifiers)
362 {
363     sendOrQueueEvent(WTREvent(WTREventTypeMouseUp, 0, wkModifiers, evasMouseButton(button)));
364
365     if (m_mouseButton == button)
366         m_mouseButton = kWKEventMouseButtonNoButton;
367
368     m_clickPosition = m_position;
369     m_clickTime = currentEventTime();
370 }
371
372 void EventSenderProxy::mouseMoveTo(double x, double y)
373 {
374     m_position.x = x;
375     m_position.y = y;
376
377     sendOrQueueEvent(WTREvent(WTREventTypeMouseMove, 0, 0, kWKEventMouseButtonNoButton));
378 }
379
380 void EventSenderProxy::mouseScrollBy(int horizontal, int vertical)
381 {
382     WTREvent event(WTREventTypeMouseScrollBy, 0, 0, kWKEventMouseButtonNoButton);
383     // We need to invert scrolling values since in EFL negative z value means that
384     // canvas is scrolling down
385     event.horizontal = -horizontal;
386     event.vertical = -vertical;
387     sendOrQueueEvent(event);
388 }
389
390 void EventSenderProxy::continuousMouseScrollBy(int horizontal, int vertical, bool paged)
391 {
392     notImplemented();
393 }
394
395 void EventSenderProxy::mouseScrollByWithWheelAndMomentumPhases(int x, int y, int /*phase*/, int /*momentum*/)
396 {
397     // EFL does not have the concept of wheel gesture phases or momentum. Just relay to
398     // the mouse wheel handler.
399     mouseScrollBy(x, y);
400 }
401
402 void EventSenderProxy::leapForward(int milliseconds)
403 {
404     if (m_eventQueue.isEmpty())
405         m_eventQueue.append(WTREvent(WTREventTypeLeapForward, milliseconds, 0, kWKEventMouseButtonNoButton));
406
407     m_time += milliseconds / 1000.0;
408 }
409
410 void EventSenderProxy::keyDown(WKStringRef keyRef, WKEventModifiers wkModifiers, unsigned location)
411 {
412     const RefPtr<KeyEventInfo> keyEventInfo = (location == DOMKeyLocationNumpad) ? keyPadName(keyRef) : keyName(keyRef);
413     if (!keyEventInfo)
414         return;
415
416     const char* keyName = keyEventInfo->keyName.data();
417     const char* keyString = keyEventInfo->keyString.data();
418
419     // Enforce 'Shift' modifier for caps.
420     if ((strlen(keyName) == 1) && (keyName[0] >= 'A' && keyName[0] <= 'Z'))
421         wkModifiers |= kWKEventModifiersShiftKey;
422
423     Evas* evas = evas_object_evas_get(m_testController->mainWebView()->platformView());
424
425     int eventIndex = 0;
426     // Mimic the emacs ctrl-o binding by inserting a paragraph
427     // separator and then putting the cursor back to its original
428     // position. Allows us to pass emacs-ctrl-o.html
429     if ((wkModifiers & kWKEventModifiersControlKey) && !strcmp(keyName, "o")) {
430         setEvasModifiers(evas, 0);
431         evas_event_feed_key_down(evas, "Return", "Return", "\r", 0, eventIndex++, 0);
432         evas_event_feed_key_up(evas, "Return", "Return", "\r", 0, eventIndex++, 0);
433         wkModifiers = 0;
434         keyName = "Left";
435         keyString = 0;
436     }
437
438     setEvasModifiers(evas, wkModifiers);
439     evas_event_feed_key_down(evas, keyName, keyName, keyString, 0, eventIndex++, 0);
440     evas_event_feed_key_up(evas, keyName, keyName, keyString, 0, eventIndex++, 0);
441     setEvasModifiers(evas, 0);
442 }
443
444 #if ENABLE(TOUCH_EVENTS)
445 void EventSenderProxy::sendTouchEvent(Ewk_Touch_Event_Type eventType)
446 {
447     ASSERT(m_touchPoints);
448
449     Evas_Object* ewkView = m_testController->mainWebView()->platformView();
450     ewk_view_feed_touch_event(ewkView, eventType, m_touchPoints, evas_key_modifier_get(evas_object_evas_get(ewkView)));
451
452     Eina_List* list;
453     Eina_List* listNext;
454     void* data;
455     EINA_LIST_FOREACH_SAFE(m_touchPoints, list, listNext, data) {
456          Ewk_Touch_Point* touchPoint = static_cast<Ewk_Touch_Point*>(data);
457          ASSERT(touchPoint);
458
459          if ((touchPoint->state == EVAS_TOUCH_POINT_UP) || (touchPoint->state == EVAS_TOUCH_POINT_CANCEL)) {
460              delete touchPoint;
461              m_touchPoints = eina_list_remove_list(m_touchPoints, list);
462          } else
463              touchPoint->state = EVAS_TOUCH_POINT_STILL;
464      }
465 }
466
467 void EventSenderProxy::addTouchPoint(int x, int y)
468 {
469     int id = 0;
470     if (m_touchPoints) {
471         Eina_List* last = eina_list_last(m_touchPoints);
472         Ewk_Touch_Point* touchPoint = static_cast<Ewk_Touch_Point*>(eina_list_data_get(last));
473         ASSERT(touchPoint);
474
475         id = touchPoint->id + 1;
476     }
477
478     Ewk_Touch_Point* touchPoint = new Ewk_Touch_Point;
479     touchPoint->id = id;
480     touchPoint->x = x;
481     touchPoint->y = y;
482     touchPoint->state = EVAS_TOUCH_POINT_DOWN;
483
484     m_touchPoints = eina_list_append(m_touchPoints, touchPoint);
485 }
486
487 void EventSenderProxy::updateTouchPoint(int index, int x, int y)
488 {
489     ASSERT(index >= 0 && index < eina_list_count(m_touchPoints));
490
491     Ewk_Touch_Point* touchPoint = static_cast<Ewk_Touch_Point*>(eina_list_nth(m_touchPoints, index));
492     ASSERT(touchPoint);
493
494     touchPoint->x = x;
495     touchPoint->y = y;
496     touchPoint->state = EVAS_TOUCH_POINT_MOVE;
497 }
498
499 void EventSenderProxy::setTouchModifier(WKEventModifiers modifier, bool enable)
500 {
501     Evas_Object* ewkView = m_testController->mainWebView()->platformView();
502
503     for (unsigned index = 0; index < (sizeof(modifierNames) / sizeof(char*)); ++index) {
504         if (modifier & (1 << index)) {
505             if (enable)
506                 evas_key_modifier_on(evas_object_evas_get(ewkView), modifierNames[index]);
507             else
508                 evas_key_modifier_off(evas_object_evas_get(ewkView), modifierNames[index]);
509         }
510     }
511 }
512
513 void EventSenderProxy::touchStart()
514 {
515     sendTouchEvent(EWK_TOUCH_START);
516 }
517
518 void EventSenderProxy::touchMove()
519 {
520     sendTouchEvent(EWK_TOUCH_MOVE);
521 }
522
523 void EventSenderProxy::touchEnd()
524 {
525     sendTouchEvent(EWK_TOUCH_END);
526 }
527
528 void EventSenderProxy::touchCancel()
529 {
530     sendTouchEvent(EWK_TOUCH_CANCEL);
531 }
532
533 void EventSenderProxy::clearTouchPoints()
534 {
535     void* data = 0;
536     EINA_LIST_FREE(m_touchPoints, data)
537         delete static_cast<Ewk_Touch_Point*>(data);
538 }
539
540 void EventSenderProxy::releaseTouchPoint(int index)
541 {
542     ASSERT(index >= 0 && index < eina_list_count(m_touchPoints));
543
544     Ewk_Touch_Point* touchPoint = static_cast<Ewk_Touch_Point*>(eina_list_nth(m_touchPoints, index));
545     ASSERT(touchPoint);
546
547     touchPoint->state = EVAS_TOUCH_POINT_UP;
548 }
549
550 void EventSenderProxy::cancelTouchPoint(int index)
551 {
552     ASSERT(index >= 0 && index < eina_list_count(m_touchPoints));
553
554     Ewk_Touch_Point* touchPoint = static_cast<Ewk_Touch_Point*>(eina_list_nth(m_touchPoints, index));
555     ASSERT(touchPoint);
556
557     touchPoint->state = EVAS_TOUCH_POINT_CANCEL;
558 }
559
560 void EventSenderProxy::setTouchPointRadius(int radiusX, int radiusY)
561 {
562     notImplemented();
563 }
564
565 #endif
566
567 }