Unreviewed, rolling out r234489.
[WebKit-https.git] / Source / WebKit / Shared / win / WebEventFactory.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2018 Sony Interactive Entertainment Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "WebEventFactory.h"
29
30 #include <WebCore/PlatformKeyboardEvent.h>
31 #include <WebCore/PlatformWheelEvent.h>
32 #include <WebCore/Scrollbar.h>
33 #include <WebCore/WindowsKeyboardCodes.h>
34 #include <windowsx.h>
35 #include <wtf/ASCIICType.h>
36
37 using namespace WebCore;
38
39 namespace WebKit {
40
41 static inline LPARAM relativeCursorPosition(HWND hwnd)
42 {
43     POINT point = { -1, -1 };
44     ::GetCursorPos(&point);
45     ::ScreenToClient(hwnd, &point);
46     return MAKELPARAM(point.x, point.y);
47 }
48
49 static inline POINT point(LPARAM lParam)
50 {
51     POINT point = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
52     return point;
53 }
54
55 static int horizontalScrollChars()
56 {
57     static ULONG scrollChars;
58     if (!scrollChars && !::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &scrollChars, 0))
59         scrollChars = 1;
60     return scrollChars;
61 }
62
63 static int verticalScrollLines()
64 {
65     static ULONG scrollLines;
66     if (!scrollLines && !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scrollLines, 0))
67         scrollLines = 3;
68     return scrollLines;
69 }
70
71 static inline int clickCount(WebEvent::Type type, WebMouseEvent::Button button, const POINT& position, double timeStampSeconds)
72 {
73     static int gLastClickCount;
74     static double gLastClickTime;
75     static POINT lastClickPosition;
76     static WebMouseEvent::Button lastClickButton = WebMouseEvent::LeftButton;
77
78     bool cancelPreviousClick = (std::abs(lastClickPosition.x - position.x) > (::GetSystemMetrics(SM_CXDOUBLECLK) / 2))
79         || (std::abs(lastClickPosition.y - position.y) > (::GetSystemMetrics(SM_CYDOUBLECLK) / 2))
80         || ((timeStampSeconds - gLastClickTime) * 1000.0 > ::GetDoubleClickTime());
81
82     if (type == WebEvent::MouseDown) {
83         if (!cancelPreviousClick && (button == lastClickButton))
84             ++gLastClickCount;
85         else {
86             gLastClickCount = 1;
87             lastClickPosition = position;
88         }
89         gLastClickTime = timeStampSeconds;
90         lastClickButton = button;
91     } else if (type == WebEvent::MouseMove) {
92         if (cancelPreviousClick) {
93             gLastClickCount = 0;
94             lastClickPosition.x = 0;
95             lastClickPosition.y = 0;
96             gLastClickTime = 0;
97         }
98     }
99
100     return gLastClickCount;
101 }
102
103 static inline bool IsKeyInDownState(int vk)
104 {
105     return ::GetKeyState(vk) & 0x8000;
106 }
107
108 static inline WebEvent::Modifiers modifiersForEvent(WPARAM wparam)
109 {
110     unsigned modifiers = 0;
111     if (wparam & MK_CONTROL)
112         modifiers |= WebEvent::ControlKey;
113     if (wparam & MK_SHIFT)
114         modifiers |= WebEvent::ShiftKey;
115     if (IsKeyInDownState(VK_MENU))
116         modifiers |= WebEvent::AltKey;
117     return static_cast<WebEvent::Modifiers>(modifiers);
118 }
119
120 static inline WebEvent::Modifiers modifiersForCurrentKeyState()
121 {
122     unsigned modifiers = 0;
123     if (IsKeyInDownState(VK_CONTROL))
124         modifiers |= WebEvent::ControlKey;
125     if (IsKeyInDownState(VK_SHIFT))
126         modifiers |= WebEvent::ShiftKey;
127     if (IsKeyInDownState(VK_MENU))
128         modifiers |= WebEvent::AltKey;
129     return static_cast<WebEvent::Modifiers>(modifiers);
130 }
131
132 static inline WebEvent::Type keyboardEventTypeForEvent(UINT message)
133 {
134     switch (message) {
135     case WM_SYSKEYDOWN:
136     case WM_KEYDOWN:
137         return WebEvent::RawKeyDown;
138         break;
139     case WM_SYSKEYUP:
140     case WM_KEYUP:
141         return WebEvent::KeyUp;
142         break;
143     case WM_IME_CHAR:
144     case WM_SYSCHAR:
145     case WM_CHAR:
146         return WebEvent::Char;
147         break;
148     default:
149         ASSERT_NOT_REACHED();
150         return WebEvent::Char;
151     }
152 }
153
154 static inline bool isSystemKeyEvent(UINT message)
155 {
156     switch (message) {
157     case WM_SYSKEYDOWN:
158     case WM_SYSKEYUP:
159     case WM_SYSCHAR:
160         return true;
161     default:
162         return false;
163     }
164 }
165
166 static bool isKeypadEvent(WPARAM wParam, LPARAM lParam, WebEvent::Type type)
167 {
168     if (type != WebEvent::RawKeyDown && type != WebEvent::KeyUp)
169         return false;
170
171     switch (wParam) {
172     case VK_NUMLOCK:
173     case VK_NUMPAD0:
174     case VK_NUMPAD1:
175     case VK_NUMPAD2:
176     case VK_NUMPAD3:
177     case VK_NUMPAD4:
178     case VK_NUMPAD5:
179     case VK_NUMPAD6:
180     case VK_NUMPAD7:
181     case VK_NUMPAD8:
182     case VK_NUMPAD9:
183     case VK_MULTIPLY:
184     case VK_ADD:
185     case VK_SEPARATOR:
186     case VK_SUBTRACT:
187     case VK_DECIMAL:
188     case VK_DIVIDE:
189         return true;
190     case VK_RETURN:
191         return HIWORD(lParam) & KF_EXTENDED;
192     case VK_INSERT:
193     case VK_DELETE:
194     case VK_PRIOR:
195     case VK_NEXT:
196     case VK_END:
197     case VK_HOME:
198     case VK_LEFT:
199     case VK_UP:
200     case VK_RIGHT:
201     case VK_DOWN:
202         return !(HIWORD(lParam) & KF_EXTENDED);
203     default:
204         return false;
205     }
206 }
207
208 static String textFromEvent(WPARAM wparam, WebEvent::Type type)
209 {
210     if (type != WebEvent::Char)
211         return String();
212
213     UChar c = static_cast<UChar>(wparam);
214     return String(&c, 1);
215 }
216
217 static String unmodifiedTextFromEvent(WPARAM wparam, WebEvent::Type type)
218 {
219     if (type != WebEvent::Char)
220         return String();
221
222     UChar c = static_cast<UChar>(wparam);
223     return String(&c, 1);
224 }
225
226 static String keyIdentifierFromEvent(WPARAM wparam, WebEvent::Type type)
227 {
228     if (type == WebEvent::Char)
229         return String();
230
231     unsigned short keyCode = static_cast<unsigned short>(wparam);
232     switch (keyCode) {
233     case VK_MENU:
234         return String("Alt");
235     case VK_CONTROL:
236         return String("Control");
237     case VK_SHIFT:
238         return String("Shift");
239     case VK_CAPITAL:
240         return String("CapsLock");
241     case VK_LWIN:
242     case VK_RWIN:
243         return String("Win");
244     case VK_CLEAR:
245         return String("Clear");
246     case VK_DOWN:
247         return String("Down");
248     case VK_END:
249         return String("End");
250     case VK_RETURN:
251         return String("Enter");
252     case VK_EXECUTE:
253         return String("Execute");
254     case VK_F1:
255         return String("F1");
256     case VK_F2:
257         return String("F2");
258     case VK_F3:
259         return String("F3");
260     case VK_F4:
261         return String("F4");
262     case VK_F5:
263         return String("F5");
264     case VK_F6:
265         return String("F6");
266     case VK_F7:
267         return String("F7");
268     case VK_F8:
269         return String("F8");
270     case VK_F9:
271         return String("F9");
272     case VK_F10:
273         return String("F11");
274     case VK_F12:
275         return String("F12");
276     case VK_F13:
277         return String("F13");
278     case VK_F14:
279         return String("F14");
280     case VK_F15:
281         return String("F15");
282     case VK_F16:
283         return String("F16");
284     case VK_F17:
285         return String("F17");
286     case VK_F18:
287         return String("F18");
288     case VK_F19:
289         return String("F19");
290     case VK_F20:
291         return String("F20");
292     case VK_F21:
293         return String("F21");
294     case VK_F22:
295         return String("F22");
296     case VK_F23:
297         return String("F23");
298     case VK_F24:
299         return String("F24");
300     case VK_HELP:
301         return String("Help");
302     case VK_HOME:
303         return String("Home");
304     case VK_INSERT:
305         return String("Insert");
306     case VK_LEFT:
307         return String("Left");
308     case VK_NEXT:
309         return String("PageDown");
310     case VK_PRIOR:
311         return String("PageUp");
312     case VK_PAUSE:
313         return String("Pause");
314     case VK_SNAPSHOT:
315         return String("PrintScreen");
316     case VK_RIGHT:
317         return String("Right");
318     case VK_SCROLL:
319         return String("Scroll");
320     case VK_SELECT:
321         return String("Select");
322     case VK_UP:
323         return String("Up");
324     case VK_DELETE:
325         return String("U+007F"); // Standard says that DEL becomes U+007F.
326     default:
327         return String::format("U+%04X", toASCIIUpper(keyCode));
328     }
329 }
330
331 WebMouseEvent WebEventFactory::createWebMouseEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool didActivateWebView)
332 {
333     WebEvent::Type type;
334     WebMouseEvent::Button button = WebMouseEvent::NoButton;
335     switch (message) {
336     case WM_MOUSEMOVE:
337         type = WebEvent::MouseMove;
338         if (wParam & MK_LBUTTON)
339             button = WebMouseEvent::LeftButton;
340         else if (wParam & MK_MBUTTON)
341             button = WebMouseEvent::MiddleButton;
342         else if (wParam & MK_RBUTTON)
343             button = WebMouseEvent::RightButton;
344         break;
345     case WM_MOUSELEAVE:
346         type = WebEvent::MouseMove;
347         if (wParam & MK_LBUTTON)
348             button = WebMouseEvent::LeftButton;
349         else if (wParam & MK_MBUTTON)
350             button = WebMouseEvent::MiddleButton;
351         else if (wParam & MK_RBUTTON)
352             button = WebMouseEvent::RightButton;
353
354         // Set the current mouse position (relative to the client area of the
355         // current window) since none is specified for this event.
356         lParam = relativeCursorPosition(hWnd);
357         break;
358     case WM_LBUTTONDOWN:
359     case WM_LBUTTONDBLCLK:
360         type = WebEvent::MouseDown;
361         button = WebMouseEvent::LeftButton;
362         break;
363     case WM_MBUTTONDOWN:
364     case WM_MBUTTONDBLCLK:
365         type = WebEvent::MouseDown;
366         button = WebMouseEvent::MiddleButton;
367         break;
368     case WM_RBUTTONDOWN:
369     case WM_RBUTTONDBLCLK:
370         type = WebEvent::MouseDown;
371         button = WebMouseEvent::RightButton;
372         break;
373     case WM_LBUTTONUP:
374         type = WebEvent::MouseUp;
375         button = WebMouseEvent::LeftButton;
376         break;
377     case WM_MBUTTONUP:
378         type = WebEvent::MouseUp;
379         button = WebMouseEvent::MiddleButton;
380         break;
381     case WM_RBUTTONUP:
382         type = WebEvent::MouseUp;
383         button = WebMouseEvent::RightButton;
384         break;
385     default:
386         ASSERT_NOT_REACHED();
387         type = WebEvent::KeyDown;
388     }
389
390     POINT position = point(lParam);
391     POINT globalPosition = position;
392     ::ClientToScreen(hWnd, &globalPosition);
393
394     double timestamp = ::GetTickCount() * 0.001; // ::GetTickCount returns milliseconds (Chrome uses GetMessageTime() / 1000.0)
395
396     int clickCount = WebKit::clickCount(type, button, position, timestamp);
397     WebEvent::Modifiers modifiers = modifiersForEvent(wParam);
398
399     return WebMouseEvent(type, button, 0, position, globalPosition, 0, 0, 0, clickCount, modifiers, WallTime::now(), didActivateWebView);
400 }
401
402 WebWheelEvent WebEventFactory::createWebWheelEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
403 {
404     POINT globalPosition = point(lParam);
405     POINT position = globalPosition;
406     ::ScreenToClient(hWnd, &position);
407
408     WebWheelEvent::Granularity granularity = WebWheelEvent::ScrollByPixelWheelEvent;
409
410     WebEvent::Modifiers modifiers = modifiersForEvent(wParam);
411
412     int deltaX = 0;
413     int deltaY = 0;
414     int wheelTicksX = 0;
415     int wheelTicksY = 0;
416
417     float delta = GET_WHEEL_DELTA_WPARAM(wParam) / static_cast<float>(WHEEL_DELTA);
418     bool isMouseHWheel = (message == WM_MOUSEHWHEEL);
419     if (isMouseHWheel) {
420         wheelTicksX = delta;
421         wheelTicksY = 0;
422         delta = -delta;
423     } else {
424         wheelTicksX = 0;
425         wheelTicksY = delta;
426     }
427     if (isMouseHWheel || (modifiers & WebEvent::ShiftKey)) {
428         deltaX = delta * static_cast<float>(horizontalScrollChars()) * WebCore::cScrollbarPixelsPerLine;
429         deltaY = 0;
430         granularity = WebWheelEvent::ScrollByPixelWheelEvent;
431     } else {
432         deltaX = 0;
433         deltaY = delta;
434         int verticalMultiplier = verticalScrollLines();
435         if (verticalMultiplier == WHEEL_PAGESCROLL)
436             granularity = WebWheelEvent::ScrollByPageWheelEvent;
437         else {
438             granularity = WebWheelEvent::ScrollByPixelWheelEvent;
439             deltaY *= static_cast<float>(verticalMultiplier) * WebCore::cScrollbarPixelsPerLine;
440         }
441     }
442
443     return WebWheelEvent(WebEvent::Wheel, position, globalPosition, FloatSize(deltaX, deltaY), FloatSize(wheelTicksX, wheelTicksY), granularity, modifiers, WallTime::now());
444 }
445
446 WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
447 {
448     WebEvent::Type type = keyboardEventTypeForEvent(message);
449     String text = textFromEvent(wparam, type);
450     String unmodifiedText = unmodifiedTextFromEvent(wparam, type);
451     String keyIdentifier = keyIdentifierFromEvent(wparam, type);
452     int windowsVirtualKeyCode = static_cast<int>(wparam);
453     int nativeVirtualKeyCode = static_cast<int>(wparam);
454     int macCharCode = 0;
455     bool autoRepeat = HIWORD(lparam) & KF_REPEAT;
456     bool isKeypad = isKeypadEvent(wparam, lparam, type);
457     bool isSystemKey = isSystemKeyEvent(message);
458     WebEvent::Modifiers modifiers = modifiersForCurrentKeyState();
459
460     return WebKeyboardEvent(type, text, unmodifiedText, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, macCharCode, autoRepeat, isKeypad, isSystemKey, modifiers, WallTime::now());
461 }
462
463 #if ENABLE(TOUCH_EVENTS)
464 WebTouchEvent WebEventFactory::createWebTouchEvent(const GdkEvent* event, Vector<WebPlatformTouchPoint>&& touchPoints)
465 {
466     return WebTouchEvent();
467 }
468 #endif // ENABLE(TOUCH_EVENTS)
469
470 } // namespace WebKit