Make all ScriptWrappable IsoHeap-ed
[WebKit-https.git] / Source / WebCore / dom / KeyboardEvent.cpp
index b6ab1b6..0f294fc 100644 (file)
@@ -1,8 +1,8 @@
-/**
+/*
  * Copyright (C) 2001 Peter Kelly (pmk@post.com)
  * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
  * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
- * Copyright (C) 2003, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2018 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 #include "config.h"
 #include "KeyboardEvent.h"
 
-#include "Document.h"
 #include "DOMWindow.h"
-#include "EventDispatcher.h"
-#include "EventNames.h"
+#include "Document.h"
+#include "Editor.h"
 #include "EventHandler.h"
+#include "EventNames.h"
 #include "Frame.h"
 #include "PlatformKeyboardEvent.h"
-#include "Settings.h"
+#include "WindowsKeyboardCodes.h"
+#include <wtf/IsoMallocInlines.h>
 
 namespace WebCore {
 
-static inline const AtomicString& eventTypeForKeyboardEventType(PlatformKeyboardEvent::Type type)
+WTF_MAKE_ISO_ALLOCATED_IMPL(KeyboardEvent);
+
+static inline const AtomString& eventTypeForKeyboardEventType(PlatformEvent::Type type)
 {
     switch (type) {
-        case PlatformKeyboardEvent::KeyUp:
+        case PlatformEvent::KeyUp:
             return eventNames().keyupEvent;
-        case PlatformKeyboardEvent::RawKeyDown:
+        case PlatformEvent::RawKeyDown:
             return eventNames().keydownEvent;
-        case PlatformKeyboardEvent::Char:
+        case PlatformEvent::Char:
             return eventNames().keypressEvent;
-        case PlatformKeyboardEvent::KeyDown:
+        case PlatformEvent::KeyDown:
             // The caller should disambiguate the combined event into RawKeyDown or Char events.
             break;
+        default:
+            break;
     }
     ASSERT_NOT_REACHED();
     return eventNames().keydownEvent;
 }
 
-KeyboardEvent::KeyboardEvent()
-    : m_keyLocation(DOM_KEY_LOCATION_STANDARD)
-    , m_altGraphKey(false)
+static inline int windowsVirtualKeyCodeWithoutLocation(int keycode)
+{
+    switch (keycode) {
+    case VK_LCONTROL:
+    case VK_RCONTROL:
+        return VK_CONTROL;
+    case VK_LSHIFT:
+    case VK_RSHIFT:
+        return VK_SHIFT;
+    case VK_LMENU:
+    case VK_RMENU:
+        return VK_MENU;
+    default:
+        return keycode;
+    }
+}
+
+static inline KeyboardEvent::KeyLocationCode keyLocationCode(const PlatformKeyboardEvent& key)
 {
+    if (key.isKeypad())
+        return KeyboardEvent::DOM_KEY_LOCATION_NUMPAD;
+
+    switch (key.windowsVirtualKeyCode()) {
+    case VK_LCONTROL:
+    case VK_LSHIFT:
+    case VK_LMENU:
+    case VK_LWIN:
+        return KeyboardEvent::DOM_KEY_LOCATION_LEFT;
+    case VK_RCONTROL:
+    case VK_RSHIFT:
+    case VK_RMENU:
+    case VK_RWIN:
+        return KeyboardEvent::DOM_KEY_LOCATION_RIGHT;
+    default:
+        return KeyboardEvent::DOM_KEY_LOCATION_STANDARD;
+    }
 }
 
-KeyboardEvent::KeyboardEvent(const PlatformKeyboardEvent& key, AbstractView* view)
-    : UIEventWithKeyState(eventTypeForKeyboardEventType(key.type()),
-                          true, true, view, 0, key.ctrlKey(), key.altKey(), key.shiftKey(), key.metaKey())
-    , m_keyEvent(adoptPtr(new PlatformKeyboardEvent(key)))
+inline KeyboardEvent::KeyboardEvent() = default;
+
+inline KeyboardEvent::KeyboardEvent(const PlatformKeyboardEvent& key, RefPtr<WindowProxy>&& view)
+    : UIEventWithKeyState(eventTypeForKeyboardEventType(key.type()), CanBubble::Yes, IsCancelable::Yes, IsComposed::Yes,
+        key.timestamp().approximateMonotonicTime(), view.copyRef(), 0, key.modifiers(), IsTrusted::Yes)
+    , m_underlyingPlatformEvent(makeUnique<PlatformKeyboardEvent>(key))
+#if ENABLE(KEYBOARD_KEY_ATTRIBUTE)
+    , m_key(key.key())
+#endif
+#if ENABLE(KEYBOARD_CODE_ATTRIBUTE)
+    , m_code(key.code())
+#endif
     , m_keyIdentifier(key.keyIdentifier())
-    , m_keyLocation(key.isKeypad() ? DOM_KEY_LOCATION_NUMPAD : DOM_KEY_LOCATION_STANDARD) // FIXME: differentiate right/left, too
-    , m_altGraphKey(false)
+    , m_location(keyLocationCode(key))
+    , m_repeat(key.isAutoRepeat())
+    , m_isComposing(view && is<DOMWindow>(view->window()) && downcast<DOMWindow>(*view->window()).frame() && downcast<DOMWindow>(*view->window()).frame()->editor().hasComposition())
+#if USE(APPKIT) || USE(UIKIT_KEYBOARD_ADDITIONS)
+    , m_handledByInputMethod(key.handledByInputMethod())
+#endif
+#if USE(APPKIT)
+    , m_keypressCommands(key.commands())
+#endif
+{
+}
+
+inline KeyboardEvent::KeyboardEvent(const AtomString& eventType, const Init& initializer)
+    : UIEventWithKeyState(eventType, initializer)
+#if ENABLE(KEYBOARD_KEY_ATTRIBUTE)
+    , m_key(initializer.key)
+#endif
+#if ENABLE(KEYBOARD_CODE_ATTRIBUTE)
+    , m_code(initializer.code)
+#endif
+    , m_keyIdentifier(initializer.keyIdentifier)
+    , m_location(initializer.keyLocation ? *initializer.keyLocation : initializer.location)
+    , m_repeat(initializer.repeat)
+    , m_isComposing(initializer.isComposing)
+    , m_charCode(initializer.charCode)
+    , m_keyCode(initializer.keyCode)
+    , m_which(initializer.which)
+{
+}
+
+KeyboardEvent::~KeyboardEvent() = default;
+
+Ref<KeyboardEvent> KeyboardEvent::create(const PlatformKeyboardEvent& platformEvent, RefPtr<WindowProxy>&& view)
 {
+    return adoptRef(*new KeyboardEvent(platformEvent, WTFMove(view)));
 }
 
-KeyboardEvent::KeyboardEvent(const AtomicString& eventType, bool canBubble, bool cancelable, AbstractView *view,
-                             const String &keyIdentifier,  unsigned keyLocation,
-                             bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool altGraphKey)
-    : UIEventWithKeyState(eventType, canBubble, cancelable, view, 0, ctrlKey, altKey, shiftKey, metaKey)
-    , m_keyIdentifier(keyIdentifier)
-    , m_keyLocation(keyLocation)
-    , m_altGraphKey(altGraphKey)
+Ref<KeyboardEvent> KeyboardEvent::createForBindings()
 {
+    return adoptRef(*new KeyboardEvent);
 }
 
-KeyboardEvent::~KeyboardEvent()
+Ref<KeyboardEvent> KeyboardEvent::create(const AtomString& type, const Init& initializer)
 {
+    return adoptRef(*new KeyboardEvent(type, initializer));
 }
 
-void KeyboardEvent::initKeyboardEvent(const AtomicString& type, bool canBubble, bool cancelable, AbstractView* view,
-                                      const String &keyIdentifier, unsigned keyLocation,
-                                      bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool altGraphKey)
+void KeyboardEvent::initKeyboardEvent(const AtomString& type, bool canBubble, bool cancelable, RefPtr<WindowProxy>&& view,
+    const String& keyIdentifier, unsigned location, bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool altGraphKey)
 {
-    if (dispatched())
+    if (isBeingDispatched())
         return;
 
-    initUIEvent(type, canBubble, cancelable, view, 0);
+    initUIEvent(type, canBubble, cancelable, WTFMove(view), 0);
 
     m_keyIdentifier = keyIdentifier;
-    m_keyLocation = keyLocation;
-    m_ctrlKey = ctrlKey;
-    m_shiftKey = shiftKey;
-    m_altKey = altKey;
-    m_metaKey = metaKey;
-    m_altGraphKey = altGraphKey;
-}
+    m_location = location;
 
-bool KeyboardEvent::getModifierState(const String& keyIdentifier) const
-{
-    if (keyIdentifier == "Control")
-        return ctrlKey();
-    if (keyIdentifier == "Shift")
-        return shiftKey();
-    if (keyIdentifier == "Alt")
-        return altKey();
-    if (keyIdentifier == "Meta")
-        return metaKey();
-    return false;
+    setModifierKeys(ctrlKey, altKey, shiftKey, metaKey, altGraphKey);
+
+    m_charCode = WTF::nullopt;
+    m_isComposing = false;
+    m_keyCode = WTF::nullopt;
+    m_repeat = false;
+    m_underlyingPlatformEvent = nullptr;
+    m_which = WTF::nullopt;
+
+#if ENABLE(KEYBOARD_CODE_ATTRIBUTE)
+    m_code = { };
+#endif
+
+#if ENABLE(KEYBOARD_KEY_ATTRIBUTE)
+    m_key = { };
+#endif
+
+#if PLATFORM(COCOA)
+    m_handledByInputMethod = false;
+    m_keypressCommands = { };
+#endif
 }
 
 int KeyboardEvent::keyCode() const
 {
+    if (m_keyCode)
+        return m_keyCode.value();
+
     // IE: virtual key code for keyup/keydown, character code for keypress
     // Firefox: virtual key code for keyup/keydown, zero for keypress
     // We match IE.
-    if (!m_keyEvent)
+    if (!m_underlyingPlatformEvent)
         return 0;
     if (type() == eventNames().keydownEvent || type() == eventNames().keyupEvent)
-        return m_keyEvent->windowsVirtualKeyCode();
+        return windowsVirtualKeyCodeWithoutLocation(m_underlyingPlatformEvent->windowsVirtualKeyCode());
+
     return charCode();
 }
 
 int KeyboardEvent::charCode() const
 {
+    if (m_charCode)
+        return m_charCode.value();
+
     // IE: not supported
     // Firefox: 0 for keydown/keyup events, character code for keypress
     // We match Firefox, unless in backward compatibility mode, where we always return the character code.
     bool backwardCompatibilityMode = false;
-    if (view() && view()->frame())
-        backwardCompatibilityMode = view()->frame()->eventHandler()->needsKeyboardEventDisambiguationQuirks();
+    auto* window = view() ? view()->window() : nullptr;
+    if (is<DOMWindow>(window) && downcast<DOMWindow>(*window).frame())
+        backwardCompatibilityMode = downcast<DOMWindow>(*window).frame()->eventHandler().needsKeyboardEventDisambiguationQuirks();
 
-    if (!m_keyEvent || (type() != eventNames().keypressEvent && !backwardCompatibilityMode))
+    if (!m_underlyingPlatformEvent || (type() != eventNames().keypressEvent && !backwardCompatibilityMode))
         return 0;
-    String text = m_keyEvent->text();
-    return static_cast<int>(text.characterStartingAt(0));
+    return m_underlyingPlatformEvent->text().characterStartingAt(0);
+}
+
+EventInterface KeyboardEvent::eventInterface() const
+{
+    return KeyboardEventInterfaceType;
 }
 
 bool KeyboardEvent::isKeyboardEvent() const
@@ -148,26 +236,9 @@ int KeyboardEvent::which() const
 {
     // Netscape's "which" returns a virtual key code for keydown and keyup, and a character code for keypress.
     // That's exactly what IE's "keyCode" returns. So they are the same for keyboard events.
+    if (m_which)
+        return m_which.value();
     return keyCode();
 }
 
-KeyboardEvent* findKeyboardEvent(Event* event)
-{
-    for (Event* e = event; e; e = e->underlyingEvent())
-        if (e->isKeyboardEvent())
-            return static_cast<KeyboardEvent*>(e);
-    return 0;
-}
-
-KeyboardEventDispatchMediator::KeyboardEventDispatchMediator(PassRefPtr<KeyboardEvent> event)
-    : EventDispatchMediator(event)
-{
-}
-
-bool KeyboardEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
-{
-    // Make sure not to return true if we already took default action while handling the event.
-    return EventDispatchMediator::dispatchEvent(dispatcher) && !event()->defaultHandled();
-}
-
 } // namespace WebCore