Use high resolution timestamp for event time
[WebKit-https.git] / Source / WebCore / platform / ios / PlatformEventFactoryIOS.mm
1 /*
2  * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010, 2011, 2014 Apple Inc. All rights reserved.
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 #import "config.h"
27 #import "PlatformEventFactoryIOS.h"
28
29 #import "IntPoint.h"
30 #import "KeyEventCocoa.h"
31 #import "Logging.h"
32 #import "WAKAppKitStubs.h"
33 #import "WebEvent.h"
34 #import "WindowsKeyboardCodes.h"
35 #import <wtf/WallTime.h>
36
37 namespace WebCore {
38
39 static OptionSet<PlatformEvent::Modifier> modifiersForEvent(WebEvent *event)
40 {
41     OptionSet<PlatformEvent::Modifier> modifiers;
42
43     if (event.modifierFlags & WebEventFlagMaskShift)
44         modifiers |= PlatformEvent::Modifier::ShiftKey;
45     if (event.modifierFlags & WebEventFlagMaskControl)
46         modifiers |= PlatformEvent::Modifier::CtrlKey;
47     if (event.modifierFlags & WebEventFlagMaskAlternate)
48         modifiers |= PlatformEvent::Modifier::AltKey;
49     if (event.modifierFlags & WebEventFlagMaskCommand)
50         modifiers |= PlatformEvent::Modifier::MetaKey;
51     if (event.modifierFlags & WebEventFlagMaskAlphaShift)
52         modifiers |= PlatformEvent::Modifier::CapsLockKey;
53
54     return modifiers;
55 }
56
57 static inline IntPoint pointForEvent(WebEvent *event)
58 {
59     return IntPoint(event.locationInWindow);
60 }
61
62 static inline IntPoint globalPointForEvent(WebEvent *event)
63 {
64     // iOS WebKit works as if it is full screen. Therefore Web coords are Global coords.
65     return pointForEvent(event);
66 }
67
68 static PlatformEvent::Type mouseEventType(WebEvent *event)
69 {
70     switch (event.type) {
71     case WebEventMouseDown:
72         return PlatformEvent::MousePressed;
73     case WebEventMouseUp:
74         return PlatformEvent::MouseReleased;
75     case WebEventMouseMoved:
76         return PlatformEvent::MouseMoved;
77     default:
78         ASSERT_NOT_REACHED();
79         return PlatformEvent::MousePressed;
80     }
81 }
82
83 class PlatformMouseEventBuilder : public PlatformMouseEvent {
84 public:
85     PlatformMouseEventBuilder(WebEvent *event)
86     {
87         m_type = mouseEventType(event);
88         m_timestamp = WallTime::now();
89
90         m_position = pointForEvent(event);
91         m_globalPosition = globalPointForEvent(event);
92         m_button = LeftButton; // This has always been the LeftButton on iOS.
93         m_clickCount = 1; // This has always been 1 on iOS.
94     }
95 };
96
97 PlatformMouseEvent PlatformEventFactory::createPlatformMouseEvent(WebEvent *event)
98 {
99     return PlatformMouseEventBuilder(event);
100 }
101
102 class PlatformWheelEventBuilder : public PlatformWheelEvent {
103 public:
104     PlatformWheelEventBuilder(WebEvent *event)
105     {
106         ASSERT(event.type == WebEventScrollWheel);
107
108         m_type = PlatformEvent::Wheel;
109         m_timestamp = WallTime::now();
110
111         m_position = pointForEvent(event);
112         m_globalPosition = globalPointForEvent(event);
113         m_deltaX = event.deltaX;
114         m_deltaY = event.deltaY;
115         m_granularity = ScrollByPixelWheelEvent; // iOS only supports continuous (pixel-mode) scrolling.
116     }
117 };
118
119 PlatformWheelEvent PlatformEventFactory::createPlatformWheelEvent(WebEvent *event)
120 {
121     return PlatformWheelEventBuilder(event);
122 }
123
124 String keyIdentifierForKeyEvent(WebEvent *event)
125 {
126     NSString *s = event.charactersIgnoringModifiers;
127     if ([s length] != 1) {
128         LOG(Events, "received an unexpected number of characters in key event: %u", [s length]);
129         return "Unidentified";
130     }
131
132     return keyIdentifierForCharCode(CFStringGetCharacterAtIndex((CFStringRef)s, 0));
133 }
134
135 String keyForKeyEvent(WebEvent *event)
136 {
137     NSString *characters = event.characters;
138     auto length = [characters length];
139
140     // characters return an empty string for dead keys.
141     // https://developer.apple.com/reference/appkit/nsevent/1534183-characters
142     // "Dead" is defined here https://w3c.github.io/uievents-key/#keys-composition.
143     if (!length)
144         return ASCIILiteral("Dead");
145
146     if (length > 1)
147         return characters;
148
149     return keyForCharCode([characters characterAtIndex:0]);
150 }
151
152 // https://w3c.github.io/uievents-code/
153 String codeForKeyEvent(WebEvent *event)
154 {
155     switch (event.keyCode) {
156     // Keys in the alphanumeric section.
157     case VK_OEM_3: return ASCIILiteral("Backquote");
158     case VK_OEM_5: return ASCIILiteral("Backslash");
159     case VK_BACK: return ASCIILiteral("Backspace");
160     case VK_OEM_4: return ASCIILiteral("BracketLeft");
161     case VK_OEM_6: return ASCIILiteral("BracketRight");
162     case VK_OEM_COMMA: return ASCIILiteral("Comma");
163     case VK_0: return ASCIILiteral("Digit0");
164     case VK_1: return ASCIILiteral("Digit1");
165     case VK_2: return ASCIILiteral("Digit2");
166     case VK_3: return ASCIILiteral("Digit3");
167     case VK_4: return ASCIILiteral("Digit4");
168     case VK_5: return ASCIILiteral("Digit5");
169     case VK_6: return ASCIILiteral("Digit6");
170     case VK_7: return ASCIILiteral("Digit7");
171     case VK_8: return ASCIILiteral("Digit8");
172     case VK_9: return ASCIILiteral("Digit9");
173     case VK_OEM_PLUS: return ASCIILiteral("Equal");
174     case VK_OEM_102: return ASCIILiteral("IntlBackslash");
175     // IntlRo.
176     // IntlYen.
177     case VK_A: return ASCIILiteral("KeyA");
178     case VK_B: return ASCIILiteral("KeyB");
179     case VK_C: return ASCIILiteral("KeyC");
180     case VK_D: return ASCIILiteral("KeyD");
181     case VK_E: return ASCIILiteral("KeyE");
182     case VK_F: return ASCIILiteral("KeyF");
183     case VK_G: return ASCIILiteral("KeyG");
184     case VK_H: return ASCIILiteral("KeyH");
185     case VK_I: return ASCIILiteral("KeyI");
186     case VK_J: return ASCIILiteral("KeyJ");
187     case VK_K: return ASCIILiteral("KeyK");
188     case VK_L: return ASCIILiteral("KeyL");
189     case VK_M: return ASCIILiteral("KeyM");
190     case VK_N: return ASCIILiteral("KeyN");
191     case VK_O: return ASCIILiteral("KeyO");
192     case VK_P: return ASCIILiteral("KeyP");
193     case VK_Q: return ASCIILiteral("KeyQ");
194     case VK_R: return ASCIILiteral("KeyR");
195     case VK_S: return ASCIILiteral("KeyS");
196     case VK_T: return ASCIILiteral("KeyT");
197     case VK_U: return ASCIILiteral("KeyU");
198     case VK_V: return ASCIILiteral("KeyV");
199     case VK_W: return ASCIILiteral("KeyW");
200     case VK_X: return ASCIILiteral("KeyX");
201     case VK_Y: return ASCIILiteral("KeyY");
202     case VK_Z: return ASCIILiteral("KeyZ");
203     case VK_OEM_MINUS: return ASCIILiteral("Minus");
204     case VK_OEM_PERIOD: return ASCIILiteral("Period");
205     case VK_OEM_7: return ASCIILiteral("Quote");
206     case VK_OEM_1: return ASCIILiteral("Semicolon");
207     case VK_OEM_2: return ASCIILiteral("Slash");
208
209     // Functional keys in alphanumeric section.
210     case VK_MENU: return ASCIILiteral("AltLeft");
211     // AltRight.
212     case VK_CAPITAL: return ASCIILiteral("CapsLock");
213     // ContextMenu.
214     case VK_LCONTROL: return ASCIILiteral("ControlLeft");
215     case VK_RCONTROL: return ASCIILiteral("ControlRight");
216     case VK_RETURN: return ASCIILiteral("Enter"); //  Labeled Return on Apple keyboards.
217     case VK_LWIN: return ASCIILiteral("MetaLeft");
218     case VK_RWIN: return ASCIILiteral("MetaRight");
219     case VK_LSHIFT: return ASCIILiteral("ShiftLeft");
220     case VK_RSHIFT: return ASCIILiteral("ShiftRight");
221     case VK_SPACE: return ASCIILiteral("Space");
222     case VK_TAB: return ASCIILiteral("Tab");
223
224     // Functional keys found on Japanese and Korean keyboards.
225     // Convert.
226     case VK_KANA: return ASCIILiteral("KanaMode");
227     // Lang1.
228     // Lang2.
229     // Lang3.
230     // Lang4.
231     // Lang5.
232     // NonConvert.
233
234     // Keys in the ControlPad section.
235     // Delete
236     case VK_END: return ASCIILiteral("End");
237     case VK_HELP: return ASCIILiteral("Help");
238     case VK_HOME: return ASCIILiteral("Home");
239     // Insert: Not present on Apple keyboards.
240     case VK_NEXT: return ASCIILiteral("PageDown");
241     case VK_PRIOR: return ASCIILiteral("PageUp");
242
243     // Keys in the ArrowPad section.
244     case VK_DOWN: return ASCIILiteral("ArrowDown");
245     case VK_LEFT: return ASCIILiteral("ArrowLeft");
246     case VK_RIGHT: return ASCIILiteral("ArrowRight");
247     case VK_UP: return ASCIILiteral("ArrowUp");
248
249     // Keys in the Numpad section.
250     case VK_NUMLOCK: return ASCIILiteral("NumLock");
251     case VK_NUMPAD0: return ASCIILiteral("Numpad0");
252     case VK_NUMPAD1: return ASCIILiteral("Numpad1");
253     case VK_NUMPAD2: return ASCIILiteral("Numpad2");
254     case VK_NUMPAD3: return ASCIILiteral("Numpad3");
255     case VK_NUMPAD4: return ASCIILiteral("Numpad4");
256     case VK_NUMPAD5: return ASCIILiteral("Numpad5");
257     case VK_NUMPAD6: return ASCIILiteral("Numpad6");
258     case VK_NUMPAD7: return ASCIILiteral("Numpad7");
259     case VK_NUMPAD8: return ASCIILiteral("Numpad8");
260     case VK_NUMPAD9: return ASCIILiteral("Numpad9");
261     case VK_ADD: return ASCIILiteral("NumpadAdd");
262     // NumpadBackspace.
263     // NumpadClear.
264     // NumpadClearEntry.
265     case VK_SEPARATOR: return ASCIILiteral("NumpadComma");
266     case VK_DECIMAL: return ASCIILiteral("NumpadDecimal");
267     case VK_DIVIDE: return ASCIILiteral("NumpadDivide");
268     // NumpadEnter.
269     case VK_CLEAR: return ASCIILiteral("NumpadEqual");
270     // NumpadHash.
271     // NumpadMemoryAdd.
272     // NumpadMemoryClear.
273     // NumpadMemoryRecall.
274     // NumpadMemoryStore.
275     // NumpadMemorySubtract.
276     case VK_MULTIPLY: return ASCIILiteral("NumpadMultiply");
277     // NumpadParenLeft.
278     // NumpadParenRight.
279     // NumpadStar: The specification says to use "NumpadMultiply" for the * key on numeric keypads.
280     case VK_SUBTRACT: return ASCIILiteral("NumpadSubtract");
281
282     // Keys in the Function section.
283     case VK_ESCAPE: return ASCIILiteral("Escape");
284     case VK_F1: return ASCIILiteral("F1");
285     case VK_F2: return ASCIILiteral("F2");
286     case VK_F3: return ASCIILiteral("F3");
287     case VK_F4: return ASCIILiteral("F4");
288     case VK_F5: return ASCIILiteral("F5");
289     case VK_F6: return ASCIILiteral("F6");
290     case VK_F7: return ASCIILiteral("F7");
291     case VK_F8: return ASCIILiteral("F8");
292     case VK_F9: return ASCIILiteral("F9");
293     case VK_F10: return ASCIILiteral("F10");
294     case VK_F11: return ASCIILiteral("F11");
295     case VK_F12: return ASCIILiteral("F12");
296     case VK_F13: return ASCIILiteral("F13");
297     case VK_F14: return ASCIILiteral("F14");
298     case VK_F15: return ASCIILiteral("F15");
299     case VK_F16: return ASCIILiteral("F16");
300     case VK_F17: return ASCIILiteral("F17");
301     case VK_F18: return ASCIILiteral("F18");
302     case VK_F19: return ASCIILiteral("F19");
303     case VK_F20: return ASCIILiteral("F20");
304     // Fn: This is typically a hardware key that does not generate a separate code.
305     // FnLock.
306     // PrintScreen.
307     // ScrollLock.
308     // Pause.
309
310     // Media keys.
311     // BrowserBack.
312     // BrowserFavorites.
313     // BrowserForward.
314     // BrowserHome.
315     // BrowserRefresh.
316     // BrowserSearch.
317     // BrowserStop.
318     // Eject.
319     // LaunchApp1.
320     // LaunchApp2.
321     // LaunchMail.
322     // MediaPlayPause.
323     // MediaSelect.
324     // MediaStop.
325     // MediaTrackNext.
326     // MediaTrackPrevious.
327     // Power.
328     // Sleep.
329     case VK_VOLUME_DOWN: return ASCIILiteral("AudioVolumeDown");
330     case VK_VOLUME_MUTE: return ASCIILiteral("AudioVolumeMute");
331     case VK_VOLUME_UP: return ASCIILiteral("AudioVolumeUp");
332     // WakeUp.
333
334     // Legacy modifier keys.
335     // Hyper.
336     // Super.
337     // Turbo.
338
339     // Legacy process control keys.
340     // Abort.
341     // Resume.
342     // Suspend.
343
344     // Legacy editing keys.
345     // Again.
346     // Copy.
347     // Cut.
348     // Find.
349     // Open.
350     // Paste.
351     // Props.
352     // Select.
353     // Undo.
354
355     // Keys found on international keyboards.
356     // Hiragana.
357     // Katakana.
358
359     default:
360         return ASCIILiteral("Unidentified");
361     }
362 }
363
364 class PlatformKeyboardEventBuilder : public PlatformKeyboardEvent {
365 public:
366     PlatformKeyboardEventBuilder(WebEvent *event)
367     {
368         ASSERT(event.type == WebEventKeyDown || event.type == WebEventKeyUp);
369
370         m_type = (event.type == WebEventKeyUp ? PlatformEvent::KeyUp : PlatformEvent::KeyDown);
371         m_modifiers = modifiersForEvent(event);
372         m_timestamp = WallTime::now();
373
374         m_text = event.characters;
375         m_unmodifiedText = event.charactersIgnoringModifiers;
376         m_key = keyForKeyEvent(event);
377         m_code = codeForKeyEvent(event);
378         m_keyIdentifier = keyIdentifierForKeyEvent(event);
379         m_windowsVirtualKeyCode = event.keyCode;
380         m_autoRepeat = event.isKeyRepeating;
381         m_isKeypad = false; // iOS does not distinguish the numpad. See <rdar://problem/7190835>.
382         m_isSystemKey = false;
383         m_Event = event;
384
385         // Always use 13 for Enter/Return -- we don't want to use AppKit's different character for Enter.
386         if (m_windowsVirtualKeyCode == '\r') {
387             m_text = "\r";
388             m_unmodifiedText = "\r";
389         }
390
391         // The adjustments below are only needed in backward compatibility mode, but we cannot tell what mode we are in from here.
392
393         // Turn 0x7F into 8, because backspace needs to always be 8.
394         if (m_text == "\x7F")
395             m_text = "\x8";
396         if (m_unmodifiedText == "\x7F")
397             m_unmodifiedText = "\x8";
398         // Always use 9 for tab -- we don't want to use AppKit's different character for shift-tab.
399         if (m_windowsVirtualKeyCode == 9) {
400             m_text = "\x9";
401             m_unmodifiedText = "\x9";
402         }
403     }
404 };
405
406 PlatformKeyboardEvent PlatformEventFactory::createPlatformKeyboardEvent(WebEvent *event)
407 {
408     return PlatformKeyboardEventBuilder(event);
409 }
410
411 #if ENABLE(TOUCH_EVENTS)
412 static PlatformTouchPoint::TouchPhaseType convertTouchPhase(NSNumber *touchPhaseNumber)
413 {
414     WebEventTouchPhaseType touchPhase = static_cast<WebEventTouchPhaseType>([touchPhaseNumber unsignedIntValue]);
415     switch (touchPhase) {
416     case WebEventTouchPhaseBegan:
417         return PlatformTouchPoint::TouchPhaseBegan;
418     case WebEventTouchPhaseMoved:
419         return PlatformTouchPoint::TouchPhaseMoved;
420     case WebEventTouchPhaseStationary:
421         return PlatformTouchPoint::TouchPhaseStationary;
422     case WebEventTouchPhaseEnded:
423         return PlatformTouchPoint::TouchPhaseEnded;
424     case WebEventTouchPhaseCancelled:
425         return PlatformTouchPoint::TouchPhaseCancelled;
426     default:
427         ASSERT_NOT_REACHED();
428     }
429     return PlatformTouchPoint::TouchPhaseBegan;
430 }
431
432 static PlatformEvent::Type touchEventType(WebEvent *event)
433 {
434     switch (event.type) {
435     case WebEventTouchBegin:
436         return PlatformEvent::TouchStart;
437     case WebEventTouchEnd:
438         return PlatformEvent::TouchEnd;
439     case WebEventTouchCancel:
440         return PlatformEvent::TouchCancel;
441     case WebEventTouchChange:
442         return PlatformEvent::TouchMove;
443     default:
444         ASSERT_NOT_REACHED();
445         return PlatformEvent::TouchCancel;
446     }
447 }
448     
449 static PlatformTouchPoint::TouchPhaseType touchPhaseFromPlatformEventType(PlatformEvent::Type type)
450 {
451     switch (type) {
452     case PlatformEvent::TouchStart:
453         return PlatformTouchPoint::TouchPhaseBegan;
454     case PlatformEvent::TouchMove:
455         return PlatformTouchPoint::TouchPhaseMoved;
456     case PlatformEvent::TouchEnd:
457         return PlatformTouchPoint::TouchPhaseEnded;
458     default:
459         ASSERT_NOT_REACHED();
460         return PlatformTouchPoint::TouchPhaseCancelled;
461     }
462 }
463
464 class PlatformTouchPointBuilder : public PlatformTouchPoint {
465 public:
466     PlatformTouchPointBuilder(unsigned identifier, const IntPoint& location, TouchPhaseType phase)
467         : PlatformTouchPoint(identifier, location, phase)
468     {
469     }
470 };
471
472 class PlatformTouchEventBuilder : public PlatformTouchEvent {
473 public:
474     PlatformTouchEventBuilder(WebEvent *event)
475     {
476         m_type = touchEventType(event);
477         m_modifiers = modifiersForEvent(event);
478         m_timestamp = WallTime::fromRawSeconds(event.timestamp);
479
480         m_gestureScale = event.gestureScale;
481         m_gestureRotation = event.gestureRotation;
482         m_isGesture = event.isGesture;
483         m_position = pointForEvent(event);
484         m_globalPosition = globalPointForEvent(event);
485
486         unsigned touchCount = event.touchCount;
487         m_touchPoints.reserveInitialCapacity(touchCount);
488         for (unsigned i = 0; i < touchCount; ++i) {
489             unsigned identifier = [(NSNumber *)[event.touchIdentifiers objectAtIndex:i] unsignedIntValue];
490             IntPoint location = IntPoint([(NSValue *)[event.touchLocations objectAtIndex:i] pointValue]);
491             PlatformTouchPoint::TouchPhaseType touchPhase = convertTouchPhase([event.touchPhases objectAtIndex:i]);
492             m_touchPoints.uncheckedAppend(PlatformTouchPointBuilder(identifier, location, touchPhase));
493         }
494     }
495     
496     PlatformTouchEventBuilder(PlatformEvent::Type type, IntPoint location)
497     {
498         m_type = type;
499         m_timestamp = WallTime::now();
500         
501         m_gestureScale = 1;
502         m_gestureRotation = 0;
503         m_isGesture = 0;
504         m_position = location;
505         m_globalPosition = location;
506         m_isPotentialTap = true;
507         
508         unsigned touchCount = 1;
509         m_touchPoints.reserveInitialCapacity(touchCount);
510         for (unsigned i = 0; i < touchCount; ++i)
511             m_touchPoints.uncheckedAppend(PlatformTouchPointBuilder(1, location, touchPhaseFromPlatformEventType(type)));
512     }
513 };
514
515 PlatformTouchEvent PlatformEventFactory::createPlatformTouchEvent(WebEvent *event)
516 {
517     return PlatformTouchEventBuilder(event);
518 }
519     
520 PlatformTouchEvent PlatformEventFactory::createPlatformSimulatedTouchEvent(PlatformEvent::Type type, IntPoint location)
521 {
522     return PlatformTouchEventBuilder(type, location);
523 }
524
525 #endif // ENABLE(TOUCH_EVENTS)
526
527 } // namespace WebCore