/*
 * Copyright (C) 2011-2017 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 "PlatformEventFactoryMac.h"

#if PLATFORM(MAC)

#import "KeyEventCocoa.h"
#import "Logging.h"
#import "PlatformScreen.h"
#import "Scrollbar.h"
#import "WindowsKeyboardCodes.h"
#import <Carbon/Carbon.h>
#import <mach/mach_time.h>
#import <pal/spi/mac/HIToolboxSPI.h>
#import <pal/spi/mac/NSEventSPI.h>
#import <pal/spi/mac/NSMenuSPI.h>
#import <wtf/ASCIICType.h>
#import <wtf/WallTime.h>

namespace WebCore {

NSPoint globalPoint(const NSPoint& windowPoint, NSWindow *window)
{
    ALLOW_DEPRECATED_DECLARATIONS_BEGIN
    return flipScreenPoint([window convertBaseToScreen:windowPoint], screen(window));
    ALLOW_DEPRECATED_DECLARATIONS_END
}

static NSPoint globalPointForEvent(NSEvent *event)
{
    switch ([event type]) {
    case NSEventTypePressure:
    case NSEventTypeLeftMouseDown:
    case NSEventTypeLeftMouseDragged:
    case NSEventTypeLeftMouseUp:
    case NSEventTypeMouseEntered:
    case NSEventTypeMouseExited:
    case NSEventTypeMouseMoved:
    case NSEventTypeOtherMouseDown:
    case NSEventTypeOtherMouseDragged:
    case NSEventTypeOtherMouseUp:
    case NSEventTypeRightMouseDown:
    case NSEventTypeRightMouseDragged:
    case NSEventTypeRightMouseUp:
    case NSEventTypeScrollWheel:
        return globalPoint([event locationInWindow], [event window]);
    default:
        return { 0, 0 };
    }
}

static IntPoint pointForEvent(NSEvent *event, NSView *windowView)
{
    switch ([event type]) {
    case NSEventTypePressure:
    case NSEventTypeLeftMouseDown:
    case NSEventTypeLeftMouseDragged:
    case NSEventTypeLeftMouseUp:
    case NSEventTypeMouseEntered:
    case NSEventTypeMouseExited:
    case NSEventTypeMouseMoved:
    case NSEventTypeOtherMouseDown:
    case NSEventTypeOtherMouseDragged:
    case NSEventTypeOtherMouseUp:
    case NSEventTypeRightMouseDown:
    case NSEventTypeRightMouseDragged:
    case NSEventTypeRightMouseUp:
    case NSEventTypeScrollWheel: {
        // Note: This will have its origin at the bottom left of the window unless windowView is flipped.
        // In those cases, the Y coordinate gets flipped by Widget::convertFromContainingWindow.
        NSPoint location = [event locationInWindow];
        if (windowView)
            location = [windowView convertPoint:location fromView:nil];
        return IntPoint(location);
    }
    default:
        return IntPoint();
    }
}

static MouseButton mouseButtonForEvent(NSEvent *event)
{
    switch ([event type]) {
    case NSEventTypePressure:
    case NSEventTypeLeftMouseDown:
    case NSEventTypeLeftMouseUp:
    case NSEventTypeLeftMouseDragged:
        return LeftButton;
    case NSEventTypeRightMouseDown:
    case NSEventTypeRightMouseUp:
    case NSEventTypeRightMouseDragged:
        return RightButton;
    case NSEventTypeOtherMouseDown:
    case NSEventTypeOtherMouseUp:
    case NSEventTypeOtherMouseDragged:
        return MiddleButton;
    default:
        return NoButton;
    }
}

static unsigned short currentlyPressedMouseButtons()
{
    return static_cast<unsigned short>([NSEvent pressedMouseButtons]);
}

static PlatformEvent::Type mouseEventTypeForEvent(NSEvent* event)
{
    switch ([event type]) {
    case NSEventTypeLeftMouseDragged:
    case NSEventTypeMouseEntered:
    case NSEventTypeMouseExited:
    case NSEventTypeMouseMoved:
    case NSEventTypeOtherMouseDragged:
    case NSEventTypeRightMouseDragged:
        return PlatformEvent::MouseMoved;
    case NSEventTypeLeftMouseDown:
    case NSEventTypeRightMouseDown:
    case NSEventTypeOtherMouseDown:
        return PlatformEvent::MousePressed;
    case NSEventTypeLeftMouseUp:
    case NSEventTypeRightMouseUp:
    case NSEventTypeOtherMouseUp:
        return PlatformEvent::MouseReleased;
    default:
        return PlatformEvent::MouseMoved;
    }
}

static int clickCountForEvent(NSEvent *event)
{
    switch ([event type]) {
    case NSEventTypeLeftMouseDown:
    case NSEventTypeLeftMouseUp:
    case NSEventTypeLeftMouseDragged:
    case NSEventTypeRightMouseDown:
    case NSEventTypeRightMouseUp:
    case NSEventTypeRightMouseDragged:
    case NSEventTypeOtherMouseDown:
    case NSEventTypeOtherMouseUp:
    case NSEventTypeOtherMouseDragged:
        return [event clickCount];
    default:
        return 0;
    }
}

static PlatformWheelEventPhase phaseFromNSEventPhase(NSEventPhase eventPhase)
{
    switch (eventPhase) {
    case NSEventPhaseNone:
        return PlatformWheelEventPhase::None;
    case NSEventPhaseBegan:
        return PlatformWheelEventPhase::Began;
    case NSEventPhaseStationary:
        return PlatformWheelEventPhase::Stationary;
    case NSEventPhaseChanged:
        return PlatformWheelEventPhase::Changed;
    case NSEventPhaseEnded:
        return PlatformWheelEventPhase::Ended;
    case NSEventPhaseCancelled:
        return PlatformWheelEventPhase::Cancelled;
    case NSEventPhaseMayBegin:
        return PlatformWheelEventPhase::MayBegin;
    }

    return PlatformWheelEventPhase::None;
}

static PlatformWheelEventPhase momentumPhaseForEvent(NSEvent *event)
{
    return phaseFromNSEventPhase([event momentumPhase]);
}

static PlatformWheelEventPhase phaseForEvent(NSEvent *event)
{
    return phaseFromNSEventPhase([event phase]);
}

static inline String textFromEvent(NSEvent* event)
{
    if ([event type] == NSEventTypeFlagsChanged)
        return emptyString();
    return String([event characters]);
}

static inline String unmodifiedTextFromEvent(NSEvent* event)
{
    if ([event type] == NSEventTypeFlagsChanged)
        return emptyString();
    return String([event charactersIgnoringModifiers]);
}

String keyForKeyEvent(NSEvent *event)
{
    switch ([event keyCode]) {
    case kVK_RightCommand:
    case kVK_Command:
        return "Meta"_s;
    case kVK_Shift:
    case kVK_RightShift:
        return "Shift"_s;
    case kVK_CapsLock:
        return "CapsLock"_s;
    case kVK_Option: // Left Alt.
    case kVK_RightOption: // Right Alt.
        return "Alt"_s;
    case kVK_Control:
    case kVK_RightControl:
        return "Control"_s;
    }

    // If the event is an NSEventTypeFlagsChanged events and we have not returned yet then this means we could not
    // identify the modifier key. We return now and report the key as "Unidentified".
    // Note that [event characters] below raises an exception if called on an NSEventTypeFlagsChanged event.
    if ([event type] == NSEventTypeFlagsChanged)
        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] & NSEventModifierFlagControl);
    NSString *s = isControlDown ? [event charactersIgnoringModifiers] : [event characters];
    auto length = [s length];
    // characters / charactersIgnoringModifiers return an empty string for dead keys.
    // https://developer.apple.com/reference/appkit/nsevent/1534183-characters
    if (!length)
        return "Dead"_s;
    // High unicode codepoints are coded with a character sequence in Mac OS X.
    if (length > 1)
        return s;
    return keyForCharCode([s characterAtIndex:0]);
}

// https://w3c.github.io/uievents-code/
String codeForKeyEvent(NSEvent *event)
{
    switch ([event keyCode]) {
    // Keys in the alphanumeric section.
    case kVK_ANSI_Grave: return "Backquote"_s;
    case kVK_ANSI_Backslash: return "Backslash"_s;
    case kVK_Delete: return "Backspace"_s;
    case kVK_ANSI_LeftBracket: return "BracketLeft"_s;
    case kVK_ANSI_RightBracket: return "BracketRight"_s;
    case kVK_ANSI_Comma: return "Comma"_s;
    case kVK_ANSI_0: return "Digit0"_s;
    case kVK_ANSI_1: return "Digit1"_s;
    case kVK_ANSI_2: return "Digit2"_s;
    case kVK_ANSI_3: return "Digit3"_s;
    case kVK_ANSI_4: return "Digit4"_s;
    case kVK_ANSI_5: return "Digit5"_s;
    case kVK_ANSI_6: return "Digit6"_s;
    case kVK_ANSI_7: return "Digit7"_s;
    case kVK_ANSI_8: return "Digit8"_s;
    case kVK_ANSI_9: return "Digit9"_s;
    case kVK_ANSI_Equal: return "Equal"_s;
    case kVK_ISO_Section: return "IntlBackslash"_s;
    case kVK_JIS_Underscore: return "IntlRo"_s;
    case kVK_JIS_Yen: return "IntlYen"_s;
    case kVK_ANSI_A: return "KeyA"_s;
    case kVK_ANSI_B: return "KeyB"_s;
    case kVK_ANSI_C: return "KeyC"_s;
    case kVK_ANSI_D: return "KeyD"_s;
    case kVK_ANSI_E: return "KeyE"_s;
    case kVK_ANSI_F: return "KeyF"_s;
    case kVK_ANSI_G: return "KeyG"_s;
    case kVK_ANSI_H: return "KeyH"_s;
    case kVK_ANSI_I: return "KeyI"_s;
    case kVK_ANSI_J: return "KeyJ"_s;
    case kVK_ANSI_K: return "KeyK"_s;
    case kVK_ANSI_L: return "KeyL"_s;
    case kVK_ANSI_M: return "KeyM"_s;
    case kVK_ANSI_N: return "KeyN"_s;
    case kVK_ANSI_O: return "KeyO"_s;
    case kVK_ANSI_P: return "KeyP"_s;
    case kVK_ANSI_Q: return "KeyQ"_s;
    case kVK_ANSI_R: return "KeyR"_s;
    case kVK_ANSI_S: return "KeyS"_s;
    case kVK_ANSI_T: return "KeyT"_s;
    case kVK_ANSI_U: return "KeyU"_s;
    case kVK_ANSI_V: return "KeyV"_s;
    case kVK_ANSI_W: return "KeyW"_s;
    case kVK_ANSI_X: return "KeyX"_s;
    case kVK_ANSI_Y: return "KeyY"_s;
    case kVK_ANSI_Z: return "KeyZ"_s;
    case kVK_ANSI_Minus: return "Minus"_s;
    case kVK_ANSI_Period: return "Period"_s;
    case kVK_ANSI_Quote: return "Quote"_s;
    case kVK_ANSI_Semicolon: return "Semicolon"_s;
    case kVK_ANSI_Slash: return "Slash"_s;

    // Functional keys in alphanumeric section.
    case kVK_Option: return "AltLeft"_s;
    case kVK_RightOption: return "AltRight"_s;
    case kVK_CapsLock: return "CapsLock"_s;
    // ContextMenu.
    case kVK_Control: return "ControlLeft"_s;
    case kVK_RightControl: return "ControlRight"_s;
    case kVK_Return: return "Enter"_s; //  Labeled Return on Apple keyboards.
    case kVK_Command: return "MetaLeft"_s;
    case kVK_RightCommand: return "MetaRight"_s;
    case kVK_Shift: return "ShiftLeft"_s;
    case kVK_RightShift: return "ShiftRight"_s;
    case kVK_Space: return "Space"_s;
    case kVK_Tab: return "Tab"_s;

    // Functional keys found on Japanese and Korean keyboards.
    // Convert.
    case kVK_JIS_Kana: return "KanaMode"_s;
    // Lang1.
    case kVK_JIS_Eisu: return "Lang2"_s; // Japanese (Mac keyboard): eisu.
    // Lang3.
    // Lang4.
    // Lang5.
    // NonConvert.

    // Keys in the ControlPad section.
    case kVK_ForwardDelete: return "Delete"_s;
    case kVK_End: return "End"_s;
    case kVK_Help: return "Help"_s;
    case kVK_Home: return "Home"_s;
    // Insert: Not present on Apple keyboards.
    case kVK_PageDown: return "PageDown"_s;
    case kVK_PageUp: return "PageUp"_s;

    // Keys in the ArrowPad section.
    case kVK_DownArrow: return "ArrowDown"_s;
    case kVK_LeftArrow: return "ArrowLeft"_s;
    case kVK_RightArrow: return "ArrowRight"_s;
    case kVK_UpArrow: return "ArrowUp"_s;

    // Keys in the Numpad section.
    case kVK_ANSI_KeypadClear: return "NumLock"_s; // The specification says to use "NumLock" on Mac for the numpad Clear key.
    case kVK_ANSI_Keypad0: return "Numpad0"_s;
    case kVK_ANSI_Keypad1: return "Numpad1"_s;
    case kVK_ANSI_Keypad2: return "Numpad2"_s;
    case kVK_ANSI_Keypad3: return "Numpad3"_s;
    case kVK_ANSI_Keypad4: return "Numpad4"_s;
    case kVK_ANSI_Keypad5: return "Numpad5"_s;
    case kVK_ANSI_Keypad6: return "Numpad6"_s;
    case kVK_ANSI_Keypad7: return "Numpad7"_s;
    case kVK_ANSI_Keypad8: return "Numpad8"_s;
    case kVK_ANSI_Keypad9: return "Numpad9"_s;
    case kVK_ANSI_KeypadPlus: return "NumpadAdd"_s;
    // NumpadBackspace.
    // NumpadClear: The specification says that the numpad Clear key should always be encoded as "NumLock" on Mac.
    // NumpadClearEntry.
    case kVK_JIS_KeypadComma: return "NumpadComma"_s;
    case kVK_ANSI_KeypadDecimal: return "NumpadDecimal"_s;
    case kVK_ANSI_KeypadDivide: return "NumpadDivide"_s;
    case kVK_ANSI_KeypadEnter: return "NumpadEnter"_s;
    case kVK_ANSI_KeypadEquals: return "NumpadEqual"_s;
    // NumpadHash.
    // NumpadMemoryAdd.
    // NumpadMemoryClear.
    // NumpadMemoryRecall.
    // NumpadMemoryStore.
    // NumpadMemorySubtract.
    case kVK_ANSI_KeypadMultiply: return "NumpadMultiply"_s;
    // NumpadParenLeft.
    // NumpadParenRight.
    // NumpadStar: The specification says to use "NumpadMultiply" for the * key on numeric keypads.
    case kVK_ANSI_KeypadMinus: return "NumpadSubtract"_s;

    // Keys in the Function section.
    case kVK_Escape: return "Escape"_s;
    case kVK_F1: return "F1"_s;
    case kVK_F2: return "F2"_s;
    case kVK_F3: return "F3"_s;
    case kVK_F4: return "F4"_s;
    case kVK_F5: return "F5"_s;
    case kVK_F6: return "F6"_s;
    case kVK_F7: return "F7"_s;
    case kVK_F8: return "F8"_s;
    case kVK_F9: return "F9"_s;
    case kVK_F10: return "F10"_s;
    case kVK_F11: return "F11"_s;
    case kVK_F12: return "F12"_s;
    case kVK_F13: return "F13"_s;
    case kVK_F14: return "F14"_s;
    case kVK_F15: return "F15"_s;
    case kVK_F16: return "F16"_s;
    case kVK_F17: return "F17"_s;
    case kVK_F18: return "F18"_s;
    case kVK_F19: return "F19"_s;
    case kVK_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 kVK_VolumeDown: return "AudioVolumeDown"_s;
    case kVK_Mute: return "AudioVolumeMute"_s;
    case kVK_VolumeUp: 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;
    }
}

String keyIdentifierForKeyEvent(NSEvent* event)
{
    if ([event type] == NSEventTypeFlagsChanged) {
        switch ([event keyCode]) {
        case 54: // Right Command
        case 55: // Left Command
            return "Meta"_str;

        case 57: // Capslock
            return "CapsLock"_str;

        case 56: // Left Shift
        case 60: // Right Shift
            return "Shift"_str;

        case 58: // Left Alt
        case 61: // Right Alt
            return "Alt"_str;

        case 59: // Left Ctrl
        case 62: // Right Ctrl
            return "Control"_str;

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

static bool isKeypadEvent(NSEvent* event)
{
    // Check that this is the type of event that has a keyCode.
    switch ([event type]) {
    case NSEventTypeKeyDown:
    case NSEventTypeKeyUp:
    case NSEventTypeFlagsChanged:
        break;
    default:
        return false;
    }

    if ([event modifierFlags] & NSEventModifierFlagNumericPad)
        return true;

    switch ([event keyCode]) {
    case 71: // Clear
    case 81: // =
    case 75: // /
    case 67: // *
    case 78: // -
    case 69: // +
    case 76: // Enter
    case 65: // .
    case 82: // 0
    case 83: // 1
    case 84: // 2
    case 85: // 3
    case 86: // 4
    case 87: // 5
    case 88: // 6
    case 89: // 7
    case 91: // 8
    case 92: // 9
        return true;
    }
     
     return false;
}

int windowsKeyCodeForKeyEvent(NSEvent* event)
{
    int code = 0;
    // 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 Mac 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] == NSEventTypeKeyDown || [event type] == NSEventTypeKeyUp)) {
        // Cmd switches Roman letters for Dvorak-QWERTY layout, so try modified characters first.
        NSString* s = [event characters];
        code = [s length] > 0 ? windowsKeyCodeForCharCode([s characterAtIndex:0]) : 0;
        if (code)
            return code;

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

    // Map Mac virtual key code directly to Windows one 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 windowsKeyCodeForKeyCode([event keyCode]);
}

static CFAbsoluteTime systemStartupTime;

static void updateSystemStartupTimeIntervalSince1970()
{
    // CFAbsoluteTimeGetCurrent() provides the absolute time in seconds since 2001.
    // mach_absolute_time() provides a relative system time since startup minus the time the computer was suspended.
    mach_timebase_info_data_t timebase_info;
    mach_timebase_info(&timebase_info);
    double elapsedTimeSinceStartup = static_cast<double>(mach_absolute_time()) * timebase_info.numer / timebase_info.denom / 1e9;
    systemStartupTime = kCFAbsoluteTimeIntervalSince1970 + CFAbsoluteTimeGetCurrent() - elapsedTimeSinceStartup;
}

static CFTimeInterval cachedStartupTimeIntervalSince1970()
{
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        void (^updateBlock)(NSNotification *) = Block_copy(^(NSNotification *){ updateSystemStartupTimeIntervalSince1970(); });
        [[[NSWorkspace sharedWorkspace] notificationCenter] addObserverForName:NSWorkspaceDidWakeNotification
                                                                        object:nil
                                                                         queue:nil
                                                                    usingBlock:updateBlock];
        [[NSNotificationCenter defaultCenter] addObserverForName:NSSystemClockDidChangeNotification
                                                          object:nil
                                                           queue:nil
                                                      usingBlock:updateBlock];
        Block_release(updateBlock);

        updateSystemStartupTimeIntervalSince1970();
    });
    return systemStartupTime;
}

WallTime eventTimeStampSince1970(NSEvent* event)
{
    return WallTime::fromRawSeconds(static_cast<double>(cachedStartupTimeIntervalSince1970() + [event timestamp]));
}

static inline bool isKeyUpEvent(NSEvent *event)
{
    if ([event type] != NSEventTypeFlagsChanged)
        return [event type] == NSEventTypeKeyUp;
    // FIXME: This logic fails if the user presses both Shift keys at once, for example:
    // we treat releasing one of them as keyDown.
    switch ([event keyCode]) {
    case 54: // Right Command
    case 55: // Left Command
        return !([event modifierFlags] & NSEventModifierFlagCommand);

    case 57: // Capslock
        return !([event modifierFlags] & NSEventModifierFlagCapsLock);

    case 56: // Left Shift
    case 60: // Right Shift
        return !([event modifierFlags] & NSEventModifierFlagShift);

    case 58: // Left Alt
    case 61: // Right Alt
        return !([event modifierFlags] & NSEventModifierFlagOption);

    case 59: // Left Ctrl
    case 62: // Right Ctrl
        return !([event modifierFlags] & NSEventModifierFlagControl);

    case 63: // Function
        return !([event modifierFlags] & NSEventModifierFlagFunction);
    }
    return false;
}

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

    if (event.modifierFlags & NSEventModifierFlagShift)
        modifiers.add(PlatformEvent::Modifier::ShiftKey);
    if (event.modifierFlags & NSEventModifierFlagControl)
        modifiers.add(PlatformEvent::Modifier::ControlKey);
    if (event.modifierFlags & NSEventModifierFlagOption)
        modifiers.add(PlatformEvent::Modifier::AltKey);
    if (event.modifierFlags & NSEventModifierFlagCommand)
        modifiers.add(PlatformEvent::Modifier::MetaKey);
    if (event.modifierFlags & NSEventModifierFlagCapsLock)
        modifiers.add(PlatformEvent::Modifier::CapsLockKey);

    return modifiers;
}

static int typeForEvent(NSEvent *event)
{
    return static_cast<int>([NSMenu menuTypeForEvent:event]);
}

void getWheelEventDeltas(NSEvent *event, float& deltaX, float& deltaY, BOOL& continuous)
{
    ASSERT(event);
    if (event.hasPreciseScrollingDeltas) {
        deltaX = event.scrollingDeltaX;
        deltaY = event.scrollingDeltaY;
        continuous = YES;
    } else {
        deltaX = event.deltaX;
        deltaY = event.deltaY;
        continuous = NO;
    }
}

UInt8 keyCharForEvent(NSEvent *event)
{
    EventRef eventRef = (EventRef)[event _eventRef];
    if (!eventRef)
        return 0;

    ByteCount keyCharCount = 0;
    if (GetEventParameter(eventRef, kEventParamKeyMacCharCodes, typeChar, 0, 0, &keyCharCount, 0) != noErr)
        return 0;
    if (keyCharCount != 1)
        return 0;

    UInt8 keyChar = 0;
    if (GetEventParameter(eventRef, kEventParamKeyMacCharCodes, typeChar, 0, sizeof(keyChar), &keyCharCount, &keyChar) != noErr)
        return 0;
    
    return keyChar;
}

class PlatformMouseEventBuilder : public PlatformMouseEvent {
public:
    PlatformMouseEventBuilder(NSEvent *event, NSEvent *correspondingPressureEvent, NSView *windowView)
    {
        // PlatformEvent
        m_type = mouseEventTypeForEvent(event);

        BOOL eventIsPressureEvent = [event type] == NSEventTypePressure;
        if (eventIsPressureEvent) {
            // Since AppKit doesn't send mouse events for force down or force up, we have to use the current pressure
            // event and correspondingPressureEvent to detect if this is MouseForceDown, MouseForceUp, or just MouseForceChanged.
            if (correspondingPressureEvent.stage == 1 && event.stage == 2)
                m_type = PlatformEvent::MouseForceDown;
            else if (correspondingPressureEvent.stage == 2 && event.stage == 1)
                m_type = PlatformEvent::MouseForceUp;
            else
                m_type = PlatformEvent::MouseForceChanged;
        }

        m_modifiers = modifiersForEvent(event);
        m_timestamp = eventTimeStampSince1970(event);

        // PlatformMouseEvent
        m_position = pointForEvent(event, windowView);
        m_globalPosition = IntPoint(globalPointForEvent(event));
        m_button = mouseButtonForEvent(event);
        m_buttons = currentlyPressedMouseButtons();
        m_clickCount = clickCountForEvent(event);
        m_movementDelta = IntPoint(event.deltaX, event.deltaY);

        m_force = 0;
        int stage = eventIsPressureEvent ? event.stage : correspondingPressureEvent.stage;
        double pressure = eventIsPressureEvent ? event.pressure : correspondingPressureEvent.pressure;
        m_force = pressure + stage;

        // Mac specific
        m_modifierFlags = [event modifierFlags];
        m_eventNumber = [event eventNumber];
        m_menuTypeForEvent = typeForEvent(event);
    }
};

PlatformMouseEvent PlatformEventFactory::createPlatformMouseEvent(NSEvent *event, NSEvent *correspondingPressureEvent, NSView *windowView)
{
    return PlatformMouseEventBuilder(event, correspondingPressureEvent, windowView);
}


class PlatformWheelEventBuilder : public PlatformWheelEvent {
public:
    PlatformWheelEventBuilder(NSEvent *event, NSView *windowView)
    {
        // PlatformEvent
        m_type = PlatformEvent::Wheel;
        m_modifiers = modifiersForEvent(event);
        m_timestamp = eventTimeStampSince1970(event);

        // PlatformWheelEvent
        m_position = pointForEvent(event, windowView);
        m_globalPosition = IntPoint(globalPointForEvent(event));
        m_granularity = ScrollByPixelWheelEvent;

        BOOL continuous;
        getWheelEventDeltas(event, m_deltaX, m_deltaY, continuous);
        if (continuous) {
            m_wheelTicksX = m_deltaX / static_cast<float>(Scrollbar::pixelsPerLineStep());
            m_wheelTicksY = m_deltaY / static_cast<float>(Scrollbar::pixelsPerLineStep());
        } else {
            m_wheelTicksX = m_deltaX;
            m_wheelTicksY = m_deltaY;
            m_deltaX *= static_cast<float>(Scrollbar::pixelsPerLineStep());
            m_deltaY *= static_cast<float>(Scrollbar::pixelsPerLineStep());
        }

        m_phase = phaseForEvent(event);
        m_momentumPhase = momentumPhaseForEvent(event);
        m_hasPreciseScrollingDeltas = continuous;
        m_directionInvertedFromDevice = [event isDirectionInvertedFromDevice];
    }
};

PlatformWheelEvent PlatformEventFactory::createPlatformWheelEvent(NSEvent *event, NSView *windowView)
{
    return PlatformWheelEventBuilder(event, windowView);
}


class PlatformKeyboardEventBuilder : public PlatformKeyboardEvent {
public:
    PlatformKeyboardEventBuilder(NSEvent *event)
    {
        // PlatformEvent
        m_type = isKeyUpEvent(event) ? PlatformEvent::KeyUp : PlatformEvent::KeyDown;
        m_modifiers = modifiersForEvent(event);
        m_timestamp = eventTimeStampSince1970(event);

        // PlatformKeyboardEvent
        m_text = textFromEvent(event);
        m_unmodifiedText = unmodifiedTextFromEvent(event);
        m_keyIdentifier = keyIdentifierForKeyEvent(event);
        m_key = keyForKeyEvent(event);
        m_code = codeForKeyEvent(event);
        m_windowsVirtualKeyCode = windowsKeyCodeForKeyEvent(event);
        m_autoRepeat = [event type] != NSEventTypeFlagsChanged && [event isARepeat];
        m_isKeypad = isKeypadEvent(event);
        m_isSystemKey = false; // SystemKey is always false on the Mac.

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

        // AppKit sets text to "\x7F" for backspace, but the correct KeyboardEvent character code is 8.
        if (m_windowsVirtualKeyCode == VK_BACK) {
            m_text = "\x8";
            m_unmodifiedText = "\x8";
        }

        // Always use 9 for Tab -- we don't want to use AppKit's different character for shift-tab.
        if (m_windowsVirtualKeyCode == VK_TAB) {
            m_text = "\x9";
            m_unmodifiedText = "\x9";
        }

        // Mac specific.
        m_macEvent = event;
    }
};

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

} // namespace WebCore

#endif // PLATFORM(MAC)
