WebKit2/Shared/win/WebEventFactory.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2010 Apple Inc. All rights reserved.
       
     3  * Copyright (C) 2006-2009 Google Inc. All rights reserved.
       
     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 "WebEventFactory.h"
       
    28 
       
    29 #include <windowsx.h>
       
    30 #include <wtf/ASCIICType.h>
       
    31 
       
    32 using namespace WebCore;
       
    33 
       
    34 namespace WebKit {
       
    35 
       
    36 static const unsigned short HIGH_BIT_MASK_SHORT = 0x8000;
       
    37 static const unsigned short SPI_GETWHEELSCROLLCHARS = 0x006C;
       
    38 
       
    39 static const unsigned WM_VISTA_MOUSEHWHEEL = 0x30E;
       
    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 positionForEvent(HWND hWnd, LPARAM lParam)
       
    50 {
       
    51     POINT point = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
       
    52     return point;
       
    53 }
       
    54 
       
    55 static inline POINT globalPositionForEvent(HWND hWnd, LPARAM lParam)
       
    56 {
       
    57     POINT point = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
       
    58     ::ClientToScreen(hWnd, &point);
       
    59     return point;
       
    60 }
       
    61 
       
    62 static int horizontalScrollChars()
       
    63 {
       
    64     static ULONG scrollChars;
       
    65     if (!scrollChars && !::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &scrollChars, 0))
       
    66         scrollChars = 1;
       
    67     return scrollChars;
       
    68 }
       
    69 
       
    70 static int verticalScrollLines()
       
    71 {
       
    72     static ULONG scrollLines;
       
    73     if (!scrollLines && !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scrollLines, 0))
       
    74         scrollLines = 3;
       
    75     return scrollLines;
       
    76 }
       
    77 
       
    78 static inline int clickCount(WebEvent::Type type, WebMouseEvent::Button button, int positionX, int positionY, double timeStampSeconds)
       
    79 {
       
    80     static int gLastClickCount;
       
    81     static double gLastClickTime;
       
    82     static int lastClickPositionX;
       
    83     static int lastClickPositionY;
       
    84     static WebMouseEvent::Button lastClickButton = WebMouseEvent::LeftButton;
       
    85 
       
    86     bool cancelPreviousClick = (abs(lastClickPositionX - positionX) > (::GetSystemMetrics(SM_CXDOUBLECLK) / 2))
       
    87                             || (abs(lastClickPositionY - positionY) > (::GetSystemMetrics(SM_CYDOUBLECLK) / 2))
       
    88                             || ((timeStampSeconds - gLastClickTime) * 1000.0 > ::GetDoubleClickTime());
       
    89 
       
    90     if (type == WebEvent::MouseDown) {
       
    91         if (!cancelPreviousClick && (button == lastClickButton))
       
    92             ++gLastClickCount;
       
    93         else {
       
    94             gLastClickCount = 1;
       
    95             lastClickPositionX = positionX;
       
    96             lastClickPositionY = positionY;
       
    97         }
       
    98         gLastClickTime = timeStampSeconds;
       
    99         lastClickButton = button;
       
   100     } else if (type == WebEvent::MouseMove) {
       
   101         if (cancelPreviousClick) {
       
   102             gLastClickCount = 0;
       
   103             lastClickPositionX = 0;
       
   104             lastClickPositionY = 0;
       
   105             gLastClickTime = 0;
       
   106         }
       
   107     }
       
   108 
       
   109     return gLastClickCount;
       
   110 }
       
   111 
       
   112 static inline WebEvent::Modifiers modifiersForEvent(WPARAM wparam)
       
   113 {
       
   114     unsigned modifiers = 0;
       
   115     if (wparam & MK_CONTROL)
       
   116         modifiers |= WebEvent::ControlKey;
       
   117     if (wparam & MK_SHIFT)
       
   118         modifiers |= WebEvent::ShiftKey;
       
   119     if (::GetKeyState(VK_MENU) & HIGH_BIT_MASK_SHORT)
       
   120         modifiers |= WebEvent::AltKey;
       
   121     return static_cast<WebEvent::Modifiers>(modifiers);
       
   122 }
       
   123 
       
   124 static inline WebEvent::Modifiers modifiersForCurrentKeyState()
       
   125 {
       
   126     unsigned modifiers = 0;
       
   127     if (::GetKeyState(VK_CONTROL) & HIGH_BIT_MASK_SHORT)
       
   128         modifiers |= WebEvent::ControlKey;
       
   129     if (::GetKeyState(VK_SHIFT) & HIGH_BIT_MASK_SHORT)
       
   130         modifiers |= WebEvent::ShiftKey;
       
   131     if (::GetKeyState(VK_MENU) & HIGH_BIT_MASK_SHORT)
       
   132         modifiers |= WebEvent::AltKey;
       
   133     return static_cast<WebEvent::Modifiers>(modifiers);
       
   134 }
       
   135 
       
   136 static inline WebEvent::Type keyboardEventTypeForEvent(UINT message)
       
   137 {
       
   138     switch (message) {
       
   139     case WM_SYSKEYDOWN:
       
   140     case WM_KEYDOWN:
       
   141         return WebEvent::RawKeyDown;
       
   142         break;
       
   143     case WM_SYSKEYUP:
       
   144     case WM_KEYUP:
       
   145         return WebEvent::KeyUp;
       
   146         break;
       
   147     case WM_IME_CHAR:
       
   148     case WM_SYSCHAR:
       
   149     case WM_CHAR:
       
   150         return WebEvent::Char;
       
   151         break;
       
   152     default:
       
   153         ASSERT_NOT_REACHED();
       
   154         return WebEvent::Char;
       
   155     }
       
   156 }
       
   157 
       
   158 static inline bool isSystemKeyEvent(UINT message)
       
   159 {
       
   160     switch (message) {
       
   161     case WM_SYSKEYDOWN:
       
   162     case WM_SYSKEYUP:
       
   163     case WM_SYSCHAR:
       
   164         return true;
       
   165     default:
       
   166         return false;
       
   167     }
       
   168 }
       
   169 
       
   170 static bool isKeypadEvent(WPARAM wParam, LPARAM lParam, WebEvent::Type type)
       
   171 {
       
   172     if (type != WebEvent::RawKeyDown && type != WebEvent::KeyUp)
       
   173         return false;
       
   174 
       
   175     switch (wParam) {
       
   176     case VK_NUMLOCK:
       
   177     case VK_NUMPAD0:
       
   178     case VK_NUMPAD1:
       
   179     case VK_NUMPAD2:
       
   180     case VK_NUMPAD3:
       
   181     case VK_NUMPAD4:
       
   182     case VK_NUMPAD5:
       
   183     case VK_NUMPAD6:
       
   184     case VK_NUMPAD7:
       
   185     case VK_NUMPAD8:
       
   186     case VK_NUMPAD9:
       
   187     case VK_MULTIPLY:
       
   188     case VK_ADD:
       
   189     case VK_SEPARATOR:
       
   190     case VK_SUBTRACT:
       
   191     case VK_DECIMAL:
       
   192     case VK_DIVIDE:
       
   193         return true;
       
   194     case VK_RETURN:
       
   195         return HIWORD(lParam) & KF_EXTENDED;
       
   196     case VK_INSERT:
       
   197     case VK_DELETE:
       
   198     case VK_PRIOR:
       
   199     case VK_NEXT:
       
   200     case VK_END:
       
   201     case VK_HOME:
       
   202     case VK_LEFT:
       
   203     case VK_UP:
       
   204     case VK_RIGHT:
       
   205     case VK_DOWN:
       
   206         return !(HIWORD(lParam) & KF_EXTENDED);
       
   207     default:
       
   208         return false;
       
   209     }
       
   210 }
       
   211 
       
   212 static String textFromEvent(WPARAM wparam, WebEvent::Type type)
       
   213 {
       
   214     if (type != WebEvent::Char)
       
   215         return String();
       
   216 
       
   217     UChar c = static_cast<UChar>(wparam);
       
   218     return String(&c, 1);
       
   219 }
       
   220 
       
   221 static String unmodifiedTextFromEvent(WPARAM wparam, WebEvent::Type type)
       
   222 {
       
   223     if (type != WebEvent::Char)
       
   224         return String();
       
   225 
       
   226     UChar c = static_cast<UChar>(wparam);
       
   227     return String(&c, 1);
       
   228 }
       
   229 
       
   230 static String keyIdentifierFromEvent(WPARAM wparam, WebEvent::Type type)
       
   231 {
       
   232     if (type == WebEvent::Char)
       
   233         return String();
       
   234     
       
   235     unsigned short keyCode = static_cast<unsigned short>(wparam);
       
   236     switch (keyCode) {
       
   237     case VK_MENU:
       
   238         return String("Alt");
       
   239     case VK_CONTROL:
       
   240         return String("Control");
       
   241     case VK_SHIFT:
       
   242         return String("Shift");
       
   243     case VK_CAPITAL:
       
   244         return String("CapsLock");
       
   245     case VK_LWIN:
       
   246     case VK_RWIN:
       
   247         return String("Win");
       
   248     case VK_CLEAR:
       
   249         return String("Clear");
       
   250     case VK_DOWN:
       
   251         return String("Down");
       
   252     case VK_END:
       
   253         return String("End");
       
   254     case VK_RETURN:
       
   255         return String("Enter");
       
   256     case VK_EXECUTE:
       
   257         return String("Execute");
       
   258     case VK_F1:
       
   259         return String("F1");
       
   260     case VK_F2:
       
   261         return String("F2");
       
   262     case VK_F3:
       
   263         return String("F3");
       
   264     case VK_F4:
       
   265         return String("F4");
       
   266     case VK_F5:
       
   267         return String("F5");
       
   268     case VK_F6:
       
   269         return String("F6");
       
   270     case VK_F7:
       
   271         return String("F7");
       
   272     case VK_F8:
       
   273         return String("F8");
       
   274     case VK_F9:
       
   275         return String("F9");
       
   276     case VK_F10:
       
   277         return String("F11");
       
   278     case VK_F12:
       
   279         return String("F12");
       
   280     case VK_F13:
       
   281         return String("F13");
       
   282     case VK_F14:
       
   283         return String("F14");
       
   284     case VK_F15:
       
   285         return String("F15");
       
   286     case VK_F16:
       
   287         return String("F16");
       
   288     case VK_F17:
       
   289         return String("F17");
       
   290     case VK_F18:
       
   291         return String("F18");
       
   292     case VK_F19:
       
   293         return String("F19");
       
   294     case VK_F20:
       
   295         return String("F20");
       
   296     case VK_F21:
       
   297         return String("F21");
       
   298     case VK_F22:
       
   299         return String("F22");
       
   300     case VK_F23:
       
   301         return String("F23");
       
   302     case VK_F24:
       
   303         return String("F24");
       
   304     case VK_HELP:
       
   305         return String("Help");
       
   306     case VK_HOME:
       
   307         return String("Home");
       
   308     case VK_INSERT:
       
   309         return String("Insert");
       
   310     case VK_LEFT:
       
   311         return String("Left");
       
   312     case VK_NEXT:
       
   313         return String("PageDown");
       
   314     case VK_PRIOR:
       
   315         return String("PageUp");
       
   316     case VK_PAUSE:
       
   317         return String("Pause");
       
   318     case VK_SNAPSHOT:
       
   319         return String("PrintScreen");
       
   320     case VK_RIGHT:
       
   321         return String("Right");
       
   322     case VK_SCROLL:
       
   323         return String("Scroll");
       
   324     case VK_SELECT:
       
   325         return String("Select");
       
   326     case VK_UP:
       
   327         return String("Up");
       
   328     case VK_DELETE:
       
   329         return String("U+007F"); // Standard says that DEL becomes U+007F.
       
   330     default:
       
   331         return String::format("U+%04X", toASCIIUpper(keyCode));
       
   332     }
       
   333 }
       
   334 
       
   335 WebMouseEvent WebEventFactory::createWebMouseEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
       
   336 {
       
   337     WebEvent::Type type;
       
   338     WebMouseEvent::Button button = WebMouseEvent::NoButton;
       
   339     switch (message) {
       
   340     case WM_MOUSEMOVE:
       
   341         type = WebEvent::MouseMove;
       
   342         if (wParam & MK_LBUTTON)
       
   343             button = WebMouseEvent::LeftButton;
       
   344         else if (wParam & MK_MBUTTON)
       
   345             button = WebMouseEvent::MiddleButton;
       
   346         else if (wParam & MK_RBUTTON)
       
   347             button = WebMouseEvent::RightButton;
       
   348         break;
       
   349     case WM_MOUSELEAVE:
       
   350         type = WebEvent::MouseMove;
       
   351         if (wParam & MK_LBUTTON)
       
   352             button = WebMouseEvent::LeftButton;
       
   353         else if (wParam & MK_MBUTTON)
       
   354             button = WebMouseEvent::MiddleButton;
       
   355         else if (wParam & MK_RBUTTON)
       
   356             button = WebMouseEvent::RightButton;
       
   357 
       
   358         // Set the current mouse position (relative to the client area of the
       
   359         // current window) since none is specified for this event.
       
   360         lParam = relativeCursorPosition(hWnd);
       
   361         break;
       
   362     case WM_LBUTTONDOWN:
       
   363     case WM_LBUTTONDBLCLK:
       
   364         type = WebEvent::MouseDown;
       
   365         button = WebMouseEvent::LeftButton;
       
   366         break;
       
   367     case WM_MBUTTONDOWN:
       
   368     case WM_MBUTTONDBLCLK:
       
   369         type = WebEvent::MouseDown;
       
   370         button = WebMouseEvent::MiddleButton;
       
   371         break;
       
   372     case WM_RBUTTONDOWN:
       
   373     case WM_RBUTTONDBLCLK:
       
   374         type = WebEvent::MouseDown;
       
   375         button = WebMouseEvent::RightButton;
       
   376         break;
       
   377     case WM_LBUTTONUP:
       
   378         type = WebEvent::MouseUp;
       
   379         button = WebMouseEvent::LeftButton;
       
   380         break;
       
   381     case WM_MBUTTONUP:
       
   382         type = WebEvent::MouseUp;
       
   383         button = WebMouseEvent::MiddleButton;
       
   384         break;
       
   385     case WM_RBUTTONUP:
       
   386         type = WebEvent::MouseUp;
       
   387         button = WebMouseEvent::RightButton;
       
   388         break;
       
   389     default:
       
   390         ASSERT_NOT_REACHED();
       
   391         type = WebEvent::KeyDown;
       
   392     }
       
   393 
       
   394     POINT position = positionForEvent(hWnd, lParam);
       
   395     POINT globalPosition = globalPositionForEvent(hWnd, lParam);
       
   396 
       
   397     int positionX = position.x;
       
   398     int positionY = position.y;
       
   399     int globalPositionX = globalPosition.x;
       
   400     int globalPositionY = globalPosition.y;
       
   401     double timestamp = ::GetTickCount() * 0.001; // ::GetTickCount returns milliseconds (Chrome uses GetMessageTime() / 1000.0)
       
   402 
       
   403     int clickCount = WebKit::clickCount(type, button, positionX, positionY, timestamp);
       
   404     WebEvent::Modifiers modifiers = modifiersForEvent(wParam);
       
   405 
       
   406     return WebMouseEvent(type, button, positionX, positionY, globalPositionX, globalPositionY, clickCount, modifiers, timestamp);
       
   407 }
       
   408 
       
   409 WebWheelEvent WebEventFactory::createWebWheelEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
       
   410 {
       
   411     // Taken from WebCore
       
   412     static const float cScrollbarPixelsPerLine = 100.0f / 3.0f;
       
   413 
       
   414     POINT position = positionForEvent(hWnd, lParam);
       
   415     POINT globalPosition = globalPositionForEvent(hWnd, lParam);
       
   416 
       
   417     int positionX = position.x;
       
   418     int positionY = position.y;
       
   419     int globalPositionX = globalPosition.x;
       
   420     int globalPositionY = globalPosition.y;
       
   421 
       
   422     WebWheelEvent::Granularity granularity  = WebWheelEvent::ScrollByPixelWheelEvent;
       
   423 
       
   424     WebEvent::Modifiers modifiers = modifiersForEvent(wParam);
       
   425     double timestamp = ::GetTickCount() * 0.001; // ::GetTickCount returns milliseconds (Chrome uses GetMessageTime() / 1000.0)
       
   426 
       
   427     int deltaX = 0;
       
   428     int deltaY = 0;
       
   429     int wheelTicksX = 0;
       
   430     int wheelTicksY = 0;
       
   431 
       
   432     float delta = GET_WHEEL_DELTA_WPARAM(wParam) / static_cast<float>(WHEEL_DELTA);
       
   433     bool isMouseHWheel = (message == WM_VISTA_MOUSEHWHEEL);
       
   434     if (isMouseHWheel) {
       
   435         wheelTicksX = delta;
       
   436         wheelTicksY = 0;
       
   437         delta = -delta;
       
   438     } else {
       
   439         wheelTicksX = 0;
       
   440         wheelTicksY = delta;
       
   441     }
       
   442     if (isMouseHWheel || (modifiers & WebEvent::ShiftKey)) {
       
   443         deltaX = delta * static_cast<float>(horizontalScrollChars()) * cScrollbarPixelsPerLine;
       
   444         deltaY = 0;
       
   445         granularity = WebWheelEvent::ScrollByPixelWheelEvent;
       
   446     } else {
       
   447         deltaX = 0;
       
   448         deltaY = delta;
       
   449         int verticalMultiplier = verticalScrollLines();
       
   450         if (verticalMultiplier == WHEEL_PAGESCROLL)
       
   451             granularity = WebWheelEvent::ScrollByPageWheelEvent;
       
   452         else {
       
   453             granularity = WebWheelEvent::ScrollByPixelWheelEvent;
       
   454             deltaY *= static_cast<float>(verticalMultiplier) * cScrollbarPixelsPerLine;
       
   455         }
       
   456     }
       
   457 
       
   458     return WebWheelEvent(WebEvent::Wheel, positionX, positionY, globalPositionX, globalPositionY, deltaX, deltaY, wheelTicksX, wheelTicksY, granularity, modifiers, timestamp);
       
   459 }
       
   460 
       
   461 WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
       
   462 {
       
   463     WebEvent::Type type             = keyboardEventTypeForEvent(message);
       
   464     String text                     = textFromEvent(wparam, type);
       
   465     String unmodifiedText           = unmodifiedTextFromEvent(wparam, type);
       
   466     String keyIdentifier            = keyIdentifierFromEvent(wparam, type);
       
   467     int windowsVirtualKeyCode       = static_cast<int>(wparam);
       
   468     int nativeVirtualKeyCode        = static_cast<int>(wparam);
       
   469     bool autoRepeat                 = HIWORD(lparam) & KF_REPEAT;
       
   470     bool isKeypad                   = isKeypadEvent(wparam, lparam, type);
       
   471     bool isSystemKey                = isSystemKeyEvent(message);
       
   472     WebEvent::Modifiers modifiers   = modifiersForCurrentKeyState();
       
   473     double timestamp                = ::GetTickCount() * 0.001; // ::GetTickCount returns milliseconds (Chrome uses GetMessageTime() / 1000.0)
       
   474 
       
   475     return WebKeyboardEvent(type, text, unmodifiedText, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, autoRepeat, isKeypad, isSystemKey, modifiers, timestamp);
       
   476 }
       
   477 
       
   478 } // namespace WebKit