/*
 * Copyright (C) 2004, 2006-2011, 2014, 2019 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#import "config.h"
#import "PlatformEventFactoryIOS.h"

#if PLATFORM(IOS_FAMILY)

#import "IntPoint.h"
#import "KeyEventCocoa.h"
#import "KeyEventCodesIOS.h"
#import "Logging.h"
#import "WAKAppKitStubs.h"
#import "WebEvent.h"
#import "WindowsKeyboardCodes.h"
#import <wtf/WallTime.h>

namespace WebCore {

static OptionSet<PlatformEvent::Modifier> modifiersForEvent(WebEvent *event)
{
    OptionSet<PlatformEvent::Modifier> modifiers;

    if (event.modifierFlags & WebEventFlagMaskShiftKey)
        modifiers.add(PlatformEvent::Modifier::ShiftKey);
    if (event.modifierFlags & WebEventFlagMaskControlKey)
        modifiers.add(PlatformEvent::Modifier::ControlKey);
    if (event.modifierFlags & WebEventFlagMaskOptionKey)
        modifiers.add(PlatformEvent::Modifier::AltKey);
    if (event.modifierFlags & WebEventFlagMaskCommandKey)
        modifiers.add(PlatformEvent::Modifier::MetaKey);
    if (event.modifierFlags & WebEventFlagMaskLeftCapsLockKey)
        modifiers.add(PlatformEvent::Modifier::CapsLockKey);

    return modifiers;
}

static inline IntPoint pointForEvent(WebEvent *event)
{
    return IntPoint(event.locationInWindow);
}

static inline IntPoint globalPointForEvent(WebEvent *event)
{
    // iOS WebKit works as if it is full screen. Therefore Web coords are Global coords.
    return pointForEvent(event);
}

static PlatformEvent::Type mouseEventType(WebEvent *event)
{
    switch (event.type) {
    case WebEventMouseDown:
        return PlatformEvent::MousePressed;
    case WebEventMouseUp:
        return PlatformEvent::MouseReleased;
    case WebEventMouseMoved:
        return PlatformEvent::MouseMoved;
    default:
        ASSERT_NOT_REACHED();
        return PlatformEvent::MousePressed;
    }
}

class PlatformMouseEventBuilder : public PlatformMouseEvent {
public:
    PlatformMouseEventBuilder(WebEvent *event)
    {
        m_type = mouseEventType(event);
        m_timestamp = WallTime::now();

        m_position = pointForEvent(event);
        m_globalPosition = globalPointForEvent(event);
        m_button = LeftButton; // This has always been the LeftButton on iOS.
        m_clickCount = 1; // This has always been 1 on iOS.
        m_modifiers = modifiersForEvent(event);
    }
};

PlatformMouseEvent PlatformEventFactory::createPlatformMouseEvent(WebEvent *event)
{
    return PlatformMouseEventBuilder(event);
}

class PlatformWheelEventBuilder : public PlatformWheelEvent {
public:
    PlatformWheelEventBuilder(WebEvent *event)
    {
        ASSERT(event.type == WebEventScrollWheel);

        m_type = PlatformEvent::Wheel;
        m_timestamp = WallTime::now();

        m_position = pointForEvent(event);
        m_globalPosition = globalPointForEvent(event);
        m_deltaX = event.deltaX;
        m_deltaY = event.deltaY;
        m_granularity = ScrollByPixelWheelEvent; // iOS only supports continuous (pixel-mode) scrolling.
    }
};

PlatformWheelEvent PlatformEventFactory::createPlatformWheelEvent(WebEvent *event)
{
    return PlatformWheelEventBuilder(event);
}

String keyIdentifierForKeyEvent(WebEvent *event)
{
    if (event.keyboardFlags & WebEventKeyboardInputModifierFlagsChanged) {
        switch (event.keyCode) {
        case VK_LWIN: // Left Command
        case VK_APPS: // Right Command
            return "Meta"_s;

        case VK_CAPITAL: // Caps Lock
            return "CapsLock"_s;

        case VK_LSHIFT: // Left Shift
        case VK_RSHIFT: // Right Shift
            return "Shift"_s;

        case VK_LMENU: // Left Alt
        case VK_RMENU: // Right Alt
            return "Alt"_s;

        case VK_LCONTROL: // Left Ctrl
        case VK_RCONTROL: // Right Ctrl
            return "Control"_s;

        default:
            ASSERT_NOT_REACHED();
            return emptyString();
        }
    }
    NSString *characters = event.charactersIgnoringModifiers;
    if ([characters length] != 1) {
        LOG(Events, "received an unexpected number of characters in key event: %u", [characters length]);
        return "Unidentified"_s;
    }
    return keyIdentifierForCharCode([characters characterAtIndex:0]);
}

String keyForKeyEvent(WebEvent *event)
{
    if (event.keyboardFlags & WebEventKeyboardInputModifierFlagsChanged) {
        switch (event.keyCode) {
        case VK_LWIN: // Left Command
        case VK_APPS: // Right Command
            return "Meta"_s;

        case VK_CAPITAL: // Caps Lock
            return "CapsLock"_s;

        case VK_LSHIFT: // Left Shift
        case VK_RSHIFT: // Right Shift
            return "Shift"_s;

        case VK_LMENU: // Left Alt
        case VK_RMENU: // Right Alt
            return "Alt"_s;

        case VK_LCONTROL: // Left Ctrl
        case VK_RCONTROL: // Right Ctrl
            return "Control"_s;

        default:
            ASSERT_NOT_REACHED();
            return "Unidentified"_s;
        }
    }

    // If more than one key is being pressed and the key combination includes one or more modifier keys
    // that result in the key no longer producing a printable character (e.g., Control + a), then the
    // key value should be the printable key value that would have been produced if the key had been
    // typed with the default keyboard layout with no modifier keys except for Shift and AltGr applied.
    // See <https://www.w3.org/TR/2015/WD-uievents-20151215/#keys-guidelines>.
    bool isControlDown = event.modifierFlags & WebEventFlagMaskControlKey;
    NSString *characters = isControlDown ? event.charactersIgnoringModifiers : event.characters;
    auto length = [characters length];
    // characters return an empty string for dead keys.
    // https://developer.apple.com/reference/appkit/nsevent/1534183-characters
    // "Dead" is defined here https://w3c.github.io/uievents-key/#keys-composition.
    if (!length)
        return "Dead"_s;
    if (length > 1)
        return characters;
    return keyForCharCode([characters characterAtIndex:0]);
}

// https://w3c.github.io/uievents-code/
String codeForKeyEvent(WebEvent *event)
{
    switch (event.keyCode) {
    // Keys in the alphanumeric section.
    case VK_OEM_3: return "Backquote"_s;
    case VK_OEM_5: return "Backslash"_s;
    case VK_BACK: return "Backspace"_s;
    case VK_OEM_4: return "BracketLeft"_s;
    case VK_OEM_6: return "BracketRight"_s;
    case VK_OEM_COMMA: return "Comma"_s;
    case VK_0: return "Digit0"_s;
    case VK_1: return "Digit1"_s;
    case VK_2: return "Digit2"_s;
    case VK_3: return "Digit3"_s;
    case VK_4: return "Digit4"_s;
    case VK_5: return "Digit5"_s;
    case VK_6: return "Digit6"_s;
    case VK_7: return "Digit7"_s;
    case VK_8: return "Digit8"_s;
    case VK_9: return "Digit9"_s;
    case VK_OEM_PLUS: return "Equal"_s;
    case VK_OEM_102: return "IntlBackslash"_s;
    // IntlRo.
    // IntlYen.
    case VK_A: return "KeyA"_s;
    case VK_B: return "KeyB"_s;
    case VK_C: return "KeyC"_s;
    case VK_D: return "KeyD"_s;
    case VK_E: return "KeyE"_s;
    case VK_F: return "KeyF"_s;
    case VK_G: return "KeyG"_s;
    case VK_H: return "KeyH"_s;
    case VK_I: return "KeyI"_s;
    case VK_J: return "KeyJ"_s;
    case VK_K: return "KeyK"_s;
    case VK_L: return "KeyL"_s;
    case VK_M: return "KeyM"_s;
    case VK_N: return "KeyN"_s;
    case VK_O: return "KeyO"_s;
    case VK_P: return "KeyP"_s;
    case VK_Q: return "KeyQ"_s;
    case VK_R: return "KeyR"_s;
    case VK_S: return "KeyS"_s;
    case VK_T: return "KeyT"_s;
    case VK_U: return "KeyU"_s;
    case VK_V: return "KeyV"_s;
    case VK_W: return "KeyW"_s;
    case VK_X: return "KeyX"_s;
    case VK_Y: return "KeyY"_s;
    case VK_Z: return "KeyZ"_s;
    case VK_OEM_MINUS: return "Minus"_s;
    case VK_OEM_PERIOD: return "Period"_s;
    case VK_OEM_7: return "Quote"_s;
    case VK_OEM_1: return "Semicolon"_s;
    case VK_OEM_2: return "Slash"_s;

    // Functional keys in alphanumeric section.
    case VK_LMENU: return "AltLeft"_s;
    case VK_RMENU: return "AltRight"_s;
    case VK_CAPITAL: return "CapsLock"_s;
    // ContextMenu.
    case VK_LCONTROL: return "ControlLeft"_s;
    case VK_RCONTROL: return "ControlRight"_s;
    case VK_RETURN: return "Enter"_s; //  Labeled Return on Apple keyboards.
    case VK_LWIN: return "MetaLeft"_s;
    case VK_APPS: return "MetaRight"_s;
    case VK_LSHIFT: return "ShiftLeft"_s;
    case VK_RSHIFT: return "ShiftRight"_s;
    case VK_SPACE: return "Space"_s;
    case VK_TAB: return "Tab"_s;

    // Functional keys found on Japanese and Korean keyboards.
    // Convert.
    case VK_KANA: return "KanaMode"_s;
    // Lang1.
    // Lang2.
    // Lang3.
    // Lang4.
    // Lang5.
    // NonConvert.

    // Keys in the ControlPad section.
    // Delete
    case VK_END: return "End"_s;
    case VK_HELP: return "Help"_s;
    case VK_HOME: return "Home"_s;
    // Insert: Not present on Apple keyboards.
    case VK_NEXT: return "PageDown"_s;
    case VK_PRIOR: return "PageUp"_s;

    // Keys in the ArrowPad section.
    case VK_DOWN: return "ArrowDown"_s;
    case VK_LEFT: return "ArrowLeft"_s;
    case VK_RIGHT: return "ArrowRight"_s;
    case VK_UP: return "ArrowUp"_s;

    // Keys in the Numpad section.
    case VK_NUMLOCK: return "NumLock"_s;
    case VK_NUMPAD0: return "Numpad0"_s;
    case VK_NUMPAD1: return "Numpad1"_s;
    case VK_NUMPAD2: return "Numpad2"_s;
    case VK_NUMPAD3: return "Numpad3"_s;
    case VK_NUMPAD4: return "Numpad4"_s;
    case VK_NUMPAD5: return "Numpad5"_s;
    case VK_NUMPAD6: return "Numpad6"_s;
    case VK_NUMPAD7: return "Numpad7"_s;
    case VK_NUMPAD8: return "Numpad8"_s;
    case VK_NUMPAD9: return "Numpad9"_s;
    case VK_ADD: return "NumpadAdd"_s;
    // NumpadBackspace.
    // NumpadClear.
    // NumpadClearEntry.
    case VK_SEPARATOR: return "NumpadComma"_s; // On JIS keyboard
    case VK_DECIMAL: return "NumpadDecimal"_s;
    case VK_DIVIDE: return "NumpadDivide"_s;
    // NumpadEnter.
    case VK_CLEAR: return "NumpadEqual"_s;
    // NumpadHash.
    // NumpadMemoryAdd.
    // NumpadMemoryClear.
    // NumpadMemoryRecall.
    // NumpadMemoryStore.
    // NumpadMemorySubtract.
    case VK_MULTIPLY: return "NumpadMultiply"_s;
    // NumpadParenLeft.
    // NumpadParenRight.
    // NumpadStar: The specification says to use "NumpadMultiply" for the * key on numeric keypads.
    case VK_SUBTRACT: return "NumpadSubtract"_s;

    // Keys in the Function section.
    case VK_ESCAPE: return "Escape"_s;
    case VK_F1: return "F1"_s;
    case VK_F2: return "F2"_s;
    case VK_F3: return "F3"_s;
    case VK_F4: return "F4"_s;
    case VK_F5: return "F5"_s;
    case VK_F6: return "F6"_s;
    case VK_F7: return "F7"_s;
    case VK_F8: return "F8"_s;
    case VK_F9: return "F9"_s;
    case VK_F10: return "F10"_s;
    case VK_F11: return "F11"_s;
    case VK_F12: return "F12"_s;
    case VK_F13: return "F13"_s;
    case VK_F14: return "F14"_s;
    case VK_F15: return "F15"_s;
    case VK_F16: return "F16"_s;
    case VK_F17: return "F17"_s;
    case VK_F18: return "F18"_s;
    case VK_F19: return "F19"_s;
    case VK_F20: return "F20"_s;
    // Fn: This is typically a hardware key that does not generate a separate code.
    // FnLock.
    // PrintScreen.
    // ScrollLock.
    // Pause.

    // Media keys.
    // BrowserBack.
    // BrowserFavorites.
    // BrowserForward.
    // BrowserHome.
    // BrowserRefresh.
    // BrowserSearch.
    // BrowserStop.
    // Eject.
    // LaunchApp1.
    // LaunchApp2.
    // LaunchMail.
    // MediaPlayPause.
    // MediaSelect.
    // MediaStop.
    // MediaTrackNext.
    // MediaTrackPrevious.
    // Power.
    // Sleep.
    case VK_VOLUME_DOWN: return "AudioVolumeDown"_s;
    case VK_VOLUME_MUTE: return "AudioVolumeMute"_s;
    case VK_VOLUME_UP: return "AudioVolumeUp"_s;
    // WakeUp.

    // Legacy modifier keys.
    // Hyper.
    // Super.
    // Turbo.

    // Legacy process control keys.
    // Abort.
    // Resume.
    // Suspend.

    // Legacy editing keys.
    // Again.
    // Copy.
    // Cut.
    // Find.
    // Open.
    // Paste.
    // Props.
    // Select.
    // Undo.

    // Keys found on international keyboards.
    // Hiragana.
    // Katakana.

    default:
        return "Unidentified"_s;
    }
}

static bool isKeypadEvent(WebEvent* event)
{
    // Check that this is the type of event that has a keyCode.
    if (event.type != WebEventKeyDown && event.type != WebEventKeyUp)
        return false;

    switch (event.keyCode) {
    case VK_CLEAR: // Num Pad Clear
    case VK_OEM_PLUS: // Num Pad =
    case VK_DIVIDE:
    case VK_MULTIPLY:
    case VK_SUBTRACT:
    case VK_ADD:
    case VK_RETURN: // Num Pad Enter
    case VK_DECIMAL: // Num Pad .
    case VK_SEPARATOR: // Num Pad , (on JIS keyboard)
    case VK_NUMPAD0:
    case VK_NUMPAD1:
    case VK_NUMPAD2:
    case VK_NUMPAD3:
    case VK_NUMPAD4:
    case VK_NUMPAD5:
    case VK_NUMPAD6:
    case VK_NUMPAD7:
    case VK_NUMPAD8:
    case VK_NUMPAD9:
        return true;
    }
    return false;
}

int windowsKeyCodeForKeyEvent(WebEvent* event)
{
    if (event.keyboardFlags & WebEventKeyboardInputModifierFlagsChanged)
        return event.keyCode;

    // There are several kinds of characters for which we produce key code from char code:
    // 1. Roman letters. Windows keyboard layouts affect both virtual key codes and character codes for these,
    //    so e.g. 'A' gets the same keyCode on QWERTY, AZERTY or Dvorak layouts.
    // 2. Keys for which there is no known iOS virtual key codes, like PrintScreen.
    // 3. Certain punctuation keys. On Windows, these are also remapped depending on current keyboard layout,
    //    but see comment in windowsKeyCodeForCharCode().
    if (!isKeypadEvent(event) && (event.type == WebEventKeyDown || event.type == WebEventKeyUp)) {
        // Cmd switches Roman letters for Dvorak-QWERTY layout, so try modified characters first.
        NSString *string = event.characters;
        int code = string.length > 0 ? windowsKeyCodeForCharCode([string characterAtIndex:0]) : 0;
        if (code)
            return code;

        // Ctrl+A on an AZERTY keyboard would get VK_Q keyCode if we relied on -[WebEvent keyCode] below.
        string = event.charactersIgnoringModifiers;
        code = string.length > 0 ? windowsKeyCodeForCharCode([string characterAtIndex:0]) : 0;
        if (code)
            return code;
    }

    // Use iOS virtual key code directly for any keys not handled above.
    // E.g. the key next to Caps Lock has the same Event.keyCode on U.S. keyboard ('A') and on
    // Russian keyboard (CYRILLIC LETTER EF).
    return event.keyCode;
}

class PlatformKeyboardEventBuilder : public PlatformKeyboardEvent {
public:
    PlatformKeyboardEventBuilder(WebEvent *event)
    {
        ASSERT(event.type == WebEventKeyDown || event.type == WebEventKeyUp);

        m_type = (event.type == WebEventKeyUp ? PlatformEvent::KeyUp : PlatformEvent::KeyDown);
        m_modifiers = modifiersForEvent(event);
        m_timestamp = WallTime::now();

        if (event.keyboardFlags & WebEventKeyboardInputModifierFlagsChanged) {
            m_text = emptyString();
            m_unmodifiedText = emptyString();
            m_autoRepeat = false;
        } else {
            m_text = event.characters;
            m_unmodifiedText = event.charactersIgnoringModifiers;
            m_autoRepeat = event.isKeyRepeating;
        }
        m_key = keyForKeyEvent(event);
        m_code = codeForKeyEvent(event);
        m_keyIdentifier = keyIdentifierForKeyEvent(event);
        m_windowsVirtualKeyCode = windowsKeyCodeForKeyEvent(event);
        m_isKeypad = false; // iOS does not distinguish the numpad. See <rdar://problem/7190835>.
        m_isSystemKey = false;
        m_Event = event;

        // Always use 13 for Enter/Return -- we don't want to use AppKit's different character for Enter.
        if (m_windowsVirtualKeyCode == '\r') {
            m_text = "\r";
            m_unmodifiedText = "\r";
        }

        // The adjustments below are only needed in backward compatibility mode, but we cannot tell what mode we are in from here.

        // Turn 0x7F into 8, because backspace needs to always be 8.
        if (m_text == "\x7F")
            m_text = "\x8";
        if (m_unmodifiedText == "\x7F")
            m_unmodifiedText = "\x8";
        // Always use 9 for tab -- we don't want to use AppKit's different character for shift-tab.
        if (m_windowsVirtualKeyCode == 9) {
            m_text = "\x9";
            m_unmodifiedText = "\x9";
        }
    }
};

PlatformKeyboardEvent PlatformEventFactory::createPlatformKeyboardEvent(WebEvent *event)
{
    return PlatformKeyboardEventBuilder(event);
}

#if ENABLE(TOUCH_EVENTS)
static PlatformTouchPoint::TouchPhaseType convertTouchPhase(NSNumber *touchPhaseNumber)
{
    WebEventTouchPhaseType touchPhase = static_cast<WebEventTouchPhaseType>([touchPhaseNumber unsignedIntValue]);
    switch (touchPhase) {
    case WebEventTouchPhaseBegan:
        return PlatformTouchPoint::TouchPhaseBegan;
    case WebEventTouchPhaseMoved:
        return PlatformTouchPoint::TouchPhaseMoved;
    case WebEventTouchPhaseStationary:
        return PlatformTouchPoint::TouchPhaseStationary;
    case WebEventTouchPhaseEnded:
        return PlatformTouchPoint::TouchPhaseEnded;
    case WebEventTouchPhaseCancelled:
        return PlatformTouchPoint::TouchPhaseCancelled;
    default:
        ASSERT_NOT_REACHED();
    }
    return PlatformTouchPoint::TouchPhaseBegan;
}

static PlatformEvent::Type touchEventType(WebEvent *event)
{
    switch (event.type) {
    case WebEventTouchBegin:
        return PlatformEvent::TouchStart;
    case WebEventTouchEnd:
        return PlatformEvent::TouchEnd;
    case WebEventTouchCancel:
        return PlatformEvent::TouchCancel;
    case WebEventTouchChange:
        return PlatformEvent::TouchMove;
    default:
        ASSERT_NOT_REACHED();
        return PlatformEvent::TouchCancel;
    }
}
    
static PlatformTouchPoint::TouchPhaseType touchPhaseFromPlatformEventType(PlatformEvent::Type type)
{
    switch (type) {
    case PlatformEvent::TouchStart:
        return PlatformTouchPoint::TouchPhaseBegan;
    case PlatformEvent::TouchMove:
        return PlatformTouchPoint::TouchPhaseMoved;
    case PlatformEvent::TouchEnd:
        return PlatformTouchPoint::TouchPhaseEnded;
    default:
        ASSERT_NOT_REACHED();
        return PlatformTouchPoint::TouchPhaseCancelled;
    }
}

class PlatformTouchPointBuilder : public PlatformTouchPoint {
public:
    PlatformTouchPointBuilder(unsigned identifier, const IntPoint& location, TouchPhaseType phase)
        : PlatformTouchPoint(identifier, location, phase)
    {
    }
};

class PlatformTouchEventBuilder : public PlatformTouchEvent {
public:
    PlatformTouchEventBuilder(WebEvent *event)
    {
        m_type = touchEventType(event);
        m_modifiers = modifiersForEvent(event);
        m_timestamp = WallTime::fromRawSeconds(event.timestamp);

        m_gestureScale = event.gestureScale;
        m_gestureRotation = event.gestureRotation;
        m_isGesture = event.isGesture;
        m_position = pointForEvent(event);
        m_globalPosition = globalPointForEvent(event);

        unsigned touchCount = event.touchCount;
        m_touchPoints.reserveInitialCapacity(touchCount);
        for (unsigned i = 0; i < touchCount; ++i) {
            unsigned identifier = [(NSNumber *)[event.touchIdentifiers objectAtIndex:i] unsignedIntValue];
            IntPoint location = IntPoint([(NSValue *)[event.touchLocations objectAtIndex:i] pointValue]);
            PlatformTouchPoint::TouchPhaseType touchPhase = convertTouchPhase([event.touchPhases objectAtIndex:i]);
            m_touchPoints.uncheckedAppend(PlatformTouchPointBuilder(identifier, location, touchPhase));
        }
    }
    
    PlatformTouchEventBuilder(PlatformEvent::Type type, IntPoint location)
    {
        m_type = type;
        m_timestamp = WallTime::now();
        
        m_gestureScale = 1;
        m_gestureRotation = 0;
        m_isGesture = 0;
        m_position = location;
        m_globalPosition = location;
        m_isPotentialTap = true;
        
        unsigned touchCount = 1;
        m_touchPoints.reserveInitialCapacity(touchCount);
        for (unsigned i = 0; i < touchCount; ++i)
            m_touchPoints.uncheckedAppend(PlatformTouchPointBuilder(1, location, touchPhaseFromPlatformEventType(type)));
    }
};

PlatformTouchEvent PlatformEventFactory::createPlatformTouchEvent(WebEvent *event)
{
    return PlatformTouchEventBuilder(event);
}
    
PlatformTouchEvent PlatformEventFactory::createPlatformSimulatedTouchEvent(PlatformEvent::Type type, IntPoint location)
{
    return PlatformTouchEventBuilder(type, location);
}

#endif // ENABLE(TOUCH_EVENTS)

} // namespace WebCore

#endif // PLATFORM(IOS_FAMILY)
