mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-03 22:59:33 +00:00
Everywhere: Hoist the Libraries folder to the top-level
This commit is contained in:
parent
950e819ee7
commit
93712b24bf
Notes:
github-actions[bot]
2024-11-10 11:51:52 +00:00
Author: https://github.com/trflynn89
Commit: 93712b24bf
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2256
Reviewed-by: https://github.com/sideshowbarker
4547 changed files with 104 additions and 113 deletions
57
Libraries/LibWeb/UIEvents/CompositionEvent.cpp
Normal file
57
Libraries/LibWeb/UIEvents/CompositionEvent.cpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/CompositionEventPrototype.h>
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/UIEvents/CompositionEvent.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
JS_DEFINE_ALLOCATOR(CompositionEvent);
|
||||
|
||||
JS::NonnullGCPtr<CompositionEvent> CompositionEvent::create(JS::Realm& realm, FlyString const& event_name, CompositionEventInit const& event_init)
|
||||
{
|
||||
return realm.heap().allocate<CompositionEvent>(realm, realm, event_name, event_init);
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<CompositionEvent>> CompositionEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, CompositionEventInit const& event_init)
|
||||
{
|
||||
return realm.heap().allocate<CompositionEvent>(realm, realm, event_name, event_init);
|
||||
}
|
||||
|
||||
CompositionEvent::CompositionEvent(JS::Realm& realm, FlyString const& event_name, CompositionEventInit const& event_init)
|
||||
: UIEvent(realm, event_name, event_init)
|
||||
, m_data(event_init.data)
|
||||
{
|
||||
}
|
||||
|
||||
CompositionEvent::~CompositionEvent() = default;
|
||||
|
||||
void CompositionEvent::initialize(JS::Realm& realm)
|
||||
{
|
||||
Base::initialize(realm);
|
||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(CompositionEvent);
|
||||
}
|
||||
|
||||
// https://w3c.github.io/uievents/#dom-compositionevent-initcompositionevent
|
||||
void CompositionEvent::init_composition_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, String const& data)
|
||||
{
|
||||
// Initializes attributes of a CompositionEvent object. This method has the same behavior as UIEvent.initUIEvent().
|
||||
// The value of detail remains undefined.
|
||||
|
||||
// 1. If this’s dispatch flag is set, then return.
|
||||
if (dispatched())
|
||||
return;
|
||||
|
||||
// 2. Initialize this with type, bubbles, and cancelable.
|
||||
initialize_event(type, bubbles, cancelable);
|
||||
|
||||
// Implementation Defined: Initialise other values.
|
||||
m_view = view;
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
}
|
40
Libraries/LibWeb/UIEvents/CompositionEvent.h
Normal file
40
Libraries/LibWeb/UIEvents/CompositionEvent.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/UIEvents/UIEvent.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
struct CompositionEventInit : public UIEventInit {
|
||||
String data;
|
||||
};
|
||||
|
||||
class CompositionEvent final : public UIEvent {
|
||||
WEB_PLATFORM_OBJECT(CompositionEvent, UIEvent);
|
||||
JS_DECLARE_ALLOCATOR(CompositionEvent);
|
||||
|
||||
public:
|
||||
[[nodiscard]] static JS::NonnullGCPtr<CompositionEvent> create(JS::Realm&, FlyString const& event_name, CompositionEventInit const& = {});
|
||||
static WebIDL::ExceptionOr<JS::NonnullGCPtr<CompositionEvent>> construct_impl(JS::Realm&, FlyString const& event_name, CompositionEventInit const& event_init);
|
||||
|
||||
virtual ~CompositionEvent() override;
|
||||
|
||||
// https://w3c.github.io/uievents/#dom-compositionevent-data
|
||||
String data() const { return m_data; }
|
||||
|
||||
void init_composition_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, String const& data);
|
||||
|
||||
private:
|
||||
CompositionEvent(JS::Realm&, FlyString const& event_name, CompositionEventInit const&);
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
|
||||
String m_data;
|
||||
};
|
||||
|
||||
}
|
17
Libraries/LibWeb/UIEvents/CompositionEvent.idl
Normal file
17
Libraries/LibWeb/UIEvents/CompositionEvent.idl
Normal file
|
@ -0,0 +1,17 @@
|
|||
#import <UIEvents/UIEvent.idl>
|
||||
|
||||
// https://w3c.github.io/uievents/#compositionevent
|
||||
[Exposed=Window]
|
||||
interface CompositionEvent : UIEvent {
|
||||
constructor(DOMString type, optional CompositionEventInit eventInitDict = {});
|
||||
readonly attribute USVString data;
|
||||
|
||||
// https://w3c.github.io/uievents/#dom-compositionevent-initcompositionevent
|
||||
// FIXME: The spec uses WindowProxy rather than Window (see https://github.com/w3c/uievents/pull/379).
|
||||
undefined initCompositionEvent(DOMString typeArg, optional boolean bubblesArg = false, optional boolean cancelableArg = false, optional Window? viewArg = null, optional DOMString dataArg = "");
|
||||
};
|
||||
|
||||
// https://w3c.github.io/uievents/#dictdef-compositioneventinit
|
||||
dictionary CompositionEventInit : UIEventInit {
|
||||
DOMString data = "";
|
||||
};
|
32
Libraries/LibWeb/UIEvents/EventModifier.h
Normal file
32
Libraries/LibWeb/UIEvents/EventModifier.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/UIEvents/UIEvent.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
// https://w3c.github.io/uievents/#event-modifier-initializers
|
||||
struct EventModifierInit : public UIEventInit {
|
||||
bool ctrl_key { false };
|
||||
bool shift_key { false };
|
||||
bool alt_key { false };
|
||||
bool meta_key { false };
|
||||
|
||||
bool modifier_alt_graph { false };
|
||||
bool modifier_caps_lock { false };
|
||||
bool modifier_fn { false };
|
||||
bool modifier_fn_lock { false };
|
||||
bool modifier_hyper { false };
|
||||
bool modifier_num_lock { false };
|
||||
bool modifier_scroll_lock { false };
|
||||
bool modifier_super { false };
|
||||
bool modifier_symbol { false };
|
||||
bool modifier_symbol_lock { false };
|
||||
};
|
||||
|
||||
}
|
19
Libraries/LibWeb/UIEvents/EventModifier.idl
Normal file
19
Libraries/LibWeb/UIEvents/EventModifier.idl
Normal file
|
@ -0,0 +1,19 @@
|
|||
#import <UIEvents/UIEvent.idl>
|
||||
|
||||
dictionary EventModifierInit : UIEventInit {
|
||||
boolean ctrlKey = false;
|
||||
boolean shiftKey = false;
|
||||
boolean altKey = false;
|
||||
boolean metaKey = false;
|
||||
|
||||
boolean modifierAltGraph = false;
|
||||
boolean modifierCapsLock = false;
|
||||
boolean modifierFn = false;
|
||||
boolean modifierFnLock = false;
|
||||
boolean modifierHyper = false;
|
||||
boolean modifierNumLock = false;
|
||||
boolean modifierScrollLock = false;
|
||||
boolean modifierSuper = false;
|
||||
boolean modifierSymbol = false;
|
||||
boolean modifierSymbolLock = false;
|
||||
};
|
28
Libraries/LibWeb/UIEvents/EventNames.cpp
Normal file
28
Libraries/LibWeb/UIEvents/EventNames.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2020, the SerenityOS developers.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/UIEvents/EventNames.h>
|
||||
|
||||
namespace Web::UIEvents::EventNames {
|
||||
|
||||
#define __ENUMERATE_UI_EVENT(name) FlyString name;
|
||||
ENUMERATE_UI_EVENTS
|
||||
#undef __ENUMERATE_UI_EVENT
|
||||
|
||||
void initialize_strings()
|
||||
{
|
||||
static bool s_initialized = false;
|
||||
VERIFY(!s_initialized);
|
||||
|
||||
#define __ENUMERATE_UI_EVENT(name) \
|
||||
name = #name##_fly_string;
|
||||
ENUMERATE_UI_EVENTS
|
||||
#undef __ENUMERATE_UI_EVENT
|
||||
|
||||
s_initialized = true;
|
||||
}
|
||||
|
||||
}
|
43
Libraries/LibWeb/UIEvents/EventNames.h
Normal file
43
Libraries/LibWeb/UIEvents/EventNames.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2020, the SerenityOS developers.
|
||||
* Copyright (c) 2021, Andreas Kling <andreas@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Error.h>
|
||||
#include <AK/FlyString.h>
|
||||
|
||||
namespace Web::UIEvents::EventNames {
|
||||
|
||||
// FIXME: This is not all of the events
|
||||
|
||||
#define ENUMERATE_UI_EVENTS \
|
||||
__ENUMERATE_UI_EVENT(auxclick) \
|
||||
__ENUMERATE_UI_EVENT(beforeinput) \
|
||||
__ENUMERATE_UI_EVENT(click) \
|
||||
__ENUMERATE_UI_EVENT(contextmenu) \
|
||||
__ENUMERATE_UI_EVENT(dblclick) \
|
||||
__ENUMERATE_UI_EVENT(input) \
|
||||
__ENUMERATE_UI_EVENT(keydown) \
|
||||
__ENUMERATE_UI_EVENT(keypress) \
|
||||
__ENUMERATE_UI_EVENT(keyup) \
|
||||
__ENUMERATE_UI_EVENT(mousedown) \
|
||||
__ENUMERATE_UI_EVENT(mouseenter) \
|
||||
__ENUMERATE_UI_EVENT(mouseleave) \
|
||||
__ENUMERATE_UI_EVENT(mousemove) \
|
||||
__ENUMERATE_UI_EVENT(mouseout) \
|
||||
__ENUMERATE_UI_EVENT(mouseover) \
|
||||
__ENUMERATE_UI_EVENT(mouseup) \
|
||||
__ENUMERATE_UI_EVENT(resize) \
|
||||
__ENUMERATE_UI_EVENT(wheel)
|
||||
|
||||
#define __ENUMERATE_UI_EVENT(name) extern FlyString name;
|
||||
ENUMERATE_UI_EVENTS
|
||||
#undef __ENUMERATE_UI_EVENT
|
||||
|
||||
void initialize_strings();
|
||||
|
||||
}
|
39
Libraries/LibWeb/UIEvents/FocusEvent.cpp
Normal file
39
Libraries/LibWeb/UIEvents/FocusEvent.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <andreas@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/FocusEventPrototype.h>
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/UIEvents/FocusEvent.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
JS_DEFINE_ALLOCATOR(FocusEvent);
|
||||
|
||||
JS::NonnullGCPtr<FocusEvent> FocusEvent::create(JS::Realm& realm, FlyString const& event_name, FocusEventInit const& event_init)
|
||||
{
|
||||
return realm.heap().allocate<FocusEvent>(realm, realm, event_name, event_init);
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<FocusEvent>> FocusEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, FocusEventInit const& event_init)
|
||||
{
|
||||
return create(realm, event_name, event_init);
|
||||
}
|
||||
|
||||
FocusEvent::FocusEvent(JS::Realm& realm, FlyString const& event_name, FocusEventInit const& event_init)
|
||||
: UIEvent(realm, event_name, event_init)
|
||||
{
|
||||
set_related_target(const_cast<DOM::EventTarget*>(event_init.related_target.ptr()));
|
||||
}
|
||||
|
||||
FocusEvent::~FocusEvent() = default;
|
||||
|
||||
void FocusEvent::initialize(JS::Realm& realm)
|
||||
{
|
||||
Base::initialize(realm);
|
||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(FocusEvent);
|
||||
}
|
||||
|
||||
}
|
34
Libraries/LibWeb/UIEvents/FocusEvent.h
Normal file
34
Libraries/LibWeb/UIEvents/FocusEvent.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <andreas@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/FlyString.h>
|
||||
#include <LibWeb/UIEvents/UIEvent.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
struct FocusEventInit : public UIEventInit {
|
||||
JS::GCPtr<DOM::EventTarget> related_target;
|
||||
};
|
||||
|
||||
class FocusEvent final : public UIEvent {
|
||||
WEB_PLATFORM_OBJECT(FocusEvent, UIEvent);
|
||||
JS_DECLARE_ALLOCATOR(FocusEvent);
|
||||
|
||||
public:
|
||||
[[nodiscard]] static JS::NonnullGCPtr<FocusEvent> create(JS::Realm&, FlyString const& event_name, FocusEventInit const& = {});
|
||||
static WebIDL::ExceptionOr<JS::NonnullGCPtr<FocusEvent>> construct_impl(JS::Realm&, FlyString const& event_name, FocusEventInit const& event_init);
|
||||
|
||||
virtual ~FocusEvent() override;
|
||||
|
||||
private:
|
||||
FocusEvent(JS::Realm&, FlyString const& event_name, FocusEventInit const&);
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
};
|
||||
|
||||
}
|
17
Libraries/LibWeb/UIEvents/FocusEvent.idl
Normal file
17
Libraries/LibWeb/UIEvents/FocusEvent.idl
Normal file
|
@ -0,0 +1,17 @@
|
|||
#import <UIEvents/UIEvent.idl>
|
||||
|
||||
// https://www.w3.org/TR/uievents/#idl-focusevent
|
||||
[Exposed=Window]
|
||||
interface FocusEvent : UIEvent {
|
||||
|
||||
constructor(DOMString type, optional FocusEventInit eventInitDict = {});
|
||||
readonly attribute EventTarget? relatedTarget;
|
||||
|
||||
};
|
||||
|
||||
// https://www.w3.org/TR/uievents/#idl-focuseventinit
|
||||
dictionary FocusEventInit : UIEventInit {
|
||||
|
||||
EventTarget? relatedTarget = null;
|
||||
|
||||
};
|
52
Libraries/LibWeb/UIEvents/InputEvent.cpp
Normal file
52
Libraries/LibWeb/UIEvents/InputEvent.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/InputEventPrototype.h>
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/UIEvents/InputEvent.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
JS_DEFINE_ALLOCATOR(InputEvent);
|
||||
|
||||
JS::NonnullGCPtr<InputEvent> InputEvent::create_from_platform_event(JS::Realm& realm, FlyString const& event_name, InputEventInit const& event_init)
|
||||
{
|
||||
auto event = realm.heap().allocate<InputEvent>(realm, realm, event_name, event_init);
|
||||
event->set_bubbles(true);
|
||||
if (event_name == "beforeinput"_fly_string) {
|
||||
event->set_cancelable(true);
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<InputEvent>> InputEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, InputEventInit const& event_init)
|
||||
{
|
||||
return realm.heap().allocate<InputEvent>(realm, realm, event_name, event_init);
|
||||
}
|
||||
|
||||
InputEvent::InputEvent(JS::Realm& realm, FlyString const& event_name, InputEventInit const& event_init)
|
||||
: UIEvent(realm, event_name, event_init)
|
||||
, m_data(event_init.data)
|
||||
, m_is_composing(event_init.is_composing)
|
||||
, m_input_type(event_init.input_type)
|
||||
{
|
||||
}
|
||||
|
||||
InputEvent::~InputEvent() = default;
|
||||
|
||||
void InputEvent::initialize(JS::Realm& realm)
|
||||
{
|
||||
Base::initialize(realm);
|
||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(InputEvent);
|
||||
}
|
||||
|
||||
Vector<DOM::StaticRange> InputEvent::get_target_ranges() const
|
||||
{
|
||||
dbgln("FIXME: Implement InputEvent::get_target_ranges()");
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
51
Libraries/LibWeb/UIEvents/InputEvent.h
Normal file
51
Libraries/LibWeb/UIEvents/InputEvent.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/DOM/StaticRange.h>
|
||||
#include <LibWeb/UIEvents/UIEvent.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
struct InputEventInit : public UIEventInit {
|
||||
Optional<String> data;
|
||||
bool is_composing { false };
|
||||
FlyString input_type {};
|
||||
};
|
||||
|
||||
class InputEvent final : public UIEvent {
|
||||
WEB_PLATFORM_OBJECT(InputEvent, UIEvent);
|
||||
JS_DECLARE_ALLOCATOR(InputEvent);
|
||||
|
||||
public:
|
||||
[[nodiscard]] static JS::NonnullGCPtr<InputEvent> create_from_platform_event(JS::Realm&, FlyString const& type, InputEventInit const& event_init);
|
||||
static WebIDL::ExceptionOr<JS::NonnullGCPtr<InputEvent>> construct_impl(JS::Realm&, FlyString const& event_name, InputEventInit const& event_init);
|
||||
|
||||
virtual ~InputEvent() override;
|
||||
|
||||
// https://w3c.github.io/uievents/#dom-inputevent-data
|
||||
Optional<String> data() const { return m_data; }
|
||||
|
||||
// https://w3c.github.io/uievents/#dom-inputevent-iscomposing
|
||||
bool is_composing() const { return m_is_composing; }
|
||||
|
||||
// https://w3c.github.io/uievents/#dom-inputevent-inputtype
|
||||
FlyString input_type() const { return m_input_type; }
|
||||
|
||||
Vector<DOM::StaticRange> get_target_ranges() const;
|
||||
|
||||
private:
|
||||
InputEvent(JS::Realm&, FlyString const& event_name, InputEventInit const&);
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
|
||||
Optional<String> m_data;
|
||||
bool m_is_composing;
|
||||
FlyString m_input_type;
|
||||
};
|
||||
|
||||
}
|
20
Libraries/LibWeb/UIEvents/InputEvent.idl
Normal file
20
Libraries/LibWeb/UIEvents/InputEvent.idl
Normal file
|
@ -0,0 +1,20 @@
|
|||
#import <UIEvents/UIEvent.idl>
|
||||
#import <DOM/StaticRange.idl>
|
||||
|
||||
// https://w3c.github.io/uievents/#inputevent
|
||||
[Exposed=Window]
|
||||
interface InputEvent : UIEvent {
|
||||
constructor(DOMString type, optional InputEventInit eventInitDict = {});
|
||||
readonly attribute USVString? data;
|
||||
readonly attribute boolean isComposing;
|
||||
readonly attribute DOMString inputType;
|
||||
|
||||
sequence<StaticRange> getTargetRanges();
|
||||
};
|
||||
|
||||
// https://w3c.github.io/uievents/#dictdef-inputeventinit
|
||||
dictionary InputEventInit : UIEventInit {
|
||||
DOMString? data = null;
|
||||
boolean isComposing = false;
|
||||
DOMString inputType = "";
|
||||
};
|
28
Libraries/LibWeb/UIEvents/InputTypes.cpp
Normal file
28
Libraries/LibWeb/UIEvents/InputTypes.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/UIEvents/InputTypes.h>
|
||||
|
||||
namespace Web::UIEvents::InputTypes {
|
||||
|
||||
#define __ENUMERATE_INPUT_TYPE(name) FlyString name;
|
||||
ENUMERATE_INPUT_TYPES
|
||||
#undef __ENUMERATE_INPUT_TYPE
|
||||
|
||||
void initialize_strings()
|
||||
{
|
||||
static bool s_initialized = false;
|
||||
VERIFY(!s_initialized);
|
||||
|
||||
#define __ENUMERATE_INPUT_TYPE(name) \
|
||||
name = #name##_fly_string;
|
||||
ENUMERATE_INPUT_TYPES
|
||||
#undef __ENUMERATE_INPUT_TYPE
|
||||
|
||||
s_initialized = true;
|
||||
}
|
||||
|
||||
}
|
28
Libraries/LibWeb/UIEvents/InputTypes.h
Normal file
28
Libraries/LibWeb/UIEvents/InputTypes.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Error.h>
|
||||
#include <AK/FlyString.h>
|
||||
|
||||
namespace Web::UIEvents::InputTypes {
|
||||
|
||||
// https://w3c.github.io/input-events/#interface-InputEvent-Attributes
|
||||
|
||||
#define ENUMERATE_INPUT_TYPES \
|
||||
__ENUMERATE_INPUT_TYPE(insertText) \
|
||||
__ENUMERATE_INPUT_TYPE(insertParagraph) \
|
||||
__ENUMERATE_INPUT_TYPE(deleteContentBackward) \
|
||||
__ENUMERATE_INPUT_TYPE(deleteContentForward)
|
||||
|
||||
#define __ENUMERATE_INPUT_TYPE(name) extern FlyString name;
|
||||
ENUMERATE_INPUT_TYPES
|
||||
#undef __ENUMERATE_INPUT_TYPE
|
||||
|
||||
void initialize_strings();
|
||||
|
||||
}
|
284
Libraries/LibWeb/UIEvents/KeyCode.h
Normal file
284
Libraries/LibWeb/UIEvents/KeyCode.h
Normal file
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <andreas@ladybird.org>
|
||||
* Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/EnumBits.h>
|
||||
#include <AK/Platform.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <AK/Types.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
#define ENUMERATE_KEY_CODES \
|
||||
__ENUMERATE_KEY_CODE(Invalid, "Invalid", 0x00) \
|
||||
__ENUMERATE_KEY_CODE(Backspace, "Backspace", 0x08) \
|
||||
__ENUMERATE_KEY_CODE(Tab, "Tab", 0x09) \
|
||||
__ENUMERATE_KEY_CODE(Return, "Return", 0x0D) \
|
||||
__ENUMERATE_KEY_CODE(LeftShift, "LeftShift", 0x10) \
|
||||
__ENUMERATE_KEY_CODE(RightShift, "RightShift", 0xB0) \
|
||||
__ENUMERATE_KEY_CODE(LeftControl, "LeftControl", 0x11) \
|
||||
__ENUMERATE_KEY_CODE(RightControl, "RightControl", 0xB1) \
|
||||
__ENUMERATE_KEY_CODE(LeftAlt, "LeftAlt", 0x12) \
|
||||
__ENUMERATE_KEY_CODE(RightAlt, "RightAlt", 0xB2) \
|
||||
__ENUMERATE_KEY_CODE(AltGr, "AltGr", 0xE1) \
|
||||
__ENUMERATE_KEY_CODE(PauseBreak, "PauseBreak", 0x13) \
|
||||
__ENUMERATE_KEY_CODE(CapsLock, "CapsLock", 0x14) \
|
||||
__ENUMERATE_KEY_CODE(Escape, "Escape", 0x1B) \
|
||||
__ENUMERATE_KEY_CODE(Space, "Space", 0x20) \
|
||||
__ENUMERATE_KEY_CODE(PageUp, "PageUp", 0x21) \
|
||||
__ENUMERATE_KEY_CODE(PageDown, "PageDown", 0x22) \
|
||||
__ENUMERATE_KEY_CODE(End, "End", 0x23) \
|
||||
__ENUMERATE_KEY_CODE(Home, "Home", 0x24) \
|
||||
__ENUMERATE_KEY_CODE(Left, "Left", 0x25) \
|
||||
__ENUMERATE_KEY_CODE(Up, "Up", 0x26) \
|
||||
__ENUMERATE_KEY_CODE(Right, "Right", 0x27) \
|
||||
__ENUMERATE_KEY_CODE(Down, "Down", 0x28) \
|
||||
__ENUMERATE_KEY_CODE(PrintScreen, "PrintScreen", 0x2A) \
|
||||
__ENUMERATE_KEY_CODE(SysRq, "SysRq", 0x2C) \
|
||||
__ENUMERATE_KEY_CODE(Delete, "Delete", 0x2E) \
|
||||
__ENUMERATE_KEY_CODE(0, "0", 0x30) \
|
||||
__ENUMERATE_KEY_CODE(1, "1", 0x31) \
|
||||
__ENUMERATE_KEY_CODE(2, "2", 0x32) \
|
||||
__ENUMERATE_KEY_CODE(3, "3", 0x33) \
|
||||
__ENUMERATE_KEY_CODE(4, "4", 0x34) \
|
||||
__ENUMERATE_KEY_CODE(5, "5", 0x35) \
|
||||
__ENUMERATE_KEY_CODE(6, "6", 0x36) \
|
||||
__ENUMERATE_KEY_CODE(7, "7", 0x37) \
|
||||
__ENUMERATE_KEY_CODE(8, "8", 0x38) \
|
||||
__ENUMERATE_KEY_CODE(9, "9", 0x39) \
|
||||
__ENUMERATE_KEY_CODE(A, "A", 0x41) \
|
||||
__ENUMERATE_KEY_CODE(B, "B", 0x42) \
|
||||
__ENUMERATE_KEY_CODE(C, "C", 0x43) \
|
||||
__ENUMERATE_KEY_CODE(D, "D", 0x44) \
|
||||
__ENUMERATE_KEY_CODE(E, "E", 0x45) \
|
||||
__ENUMERATE_KEY_CODE(F, "F", 0x46) \
|
||||
__ENUMERATE_KEY_CODE(G, "G", 0x47) \
|
||||
__ENUMERATE_KEY_CODE(H, "H", 0x48) \
|
||||
__ENUMERATE_KEY_CODE(I, "I", 0x49) \
|
||||
__ENUMERATE_KEY_CODE(J, "J", 0x4A) \
|
||||
__ENUMERATE_KEY_CODE(K, "K", 0x4B) \
|
||||
__ENUMERATE_KEY_CODE(L, "L", 0x4C) \
|
||||
__ENUMERATE_KEY_CODE(M, "M", 0x4D) \
|
||||
__ENUMERATE_KEY_CODE(N, "N", 0x4E) \
|
||||
__ENUMERATE_KEY_CODE(O, "O", 0x4F) \
|
||||
__ENUMERATE_KEY_CODE(P, "P", 0x50) \
|
||||
__ENUMERATE_KEY_CODE(Q, "Q", 0x51) \
|
||||
__ENUMERATE_KEY_CODE(R, "R", 0x52) \
|
||||
__ENUMERATE_KEY_CODE(S, "S", 0x53) \
|
||||
__ENUMERATE_KEY_CODE(T, "T", 0x54) \
|
||||
__ENUMERATE_KEY_CODE(U, "U", 0x55) \
|
||||
__ENUMERATE_KEY_CODE(V, "V", 0x56) \
|
||||
__ENUMERATE_KEY_CODE(W, "W", 0x57) \
|
||||
__ENUMERATE_KEY_CODE(X, "X", 0x58) \
|
||||
__ENUMERATE_KEY_CODE(Y, "Y", 0x59) \
|
||||
__ENUMERATE_KEY_CODE(Z, "Z", 0x5A) \
|
||||
__ENUMERATE_KEY_CODE(RightParen, ")", 0x60) \
|
||||
__ENUMERATE_KEY_CODE(ExclamationPoint, "!", 0x61) \
|
||||
__ENUMERATE_KEY_CODE(AtSign, "@", 0x62) \
|
||||
__ENUMERATE_KEY_CODE(Hashtag, "#", 0x63) \
|
||||
__ENUMERATE_KEY_CODE(Dollar, "$", 0x64) \
|
||||
__ENUMERATE_KEY_CODE(Percent, "%", 0x65) \
|
||||
__ENUMERATE_KEY_CODE(Circumflex, "^", 0x66) \
|
||||
__ENUMERATE_KEY_CODE(Ampersand, "&", 0x67) \
|
||||
__ENUMERATE_KEY_CODE(Asterisk, "*", 0x68) \
|
||||
__ENUMERATE_KEY_CODE(LeftParen, "(", 0x69) \
|
||||
__ENUMERATE_KEY_CODE(Plus, "+", 0x6A) \
|
||||
__ENUMERATE_KEY_CODE(Minus, "-", 0x6B) \
|
||||
__ENUMERATE_KEY_CODE(Slash, "/", 0x6C) \
|
||||
__ENUMERATE_KEY_CODE(Comma, ",", 0x6D) \
|
||||
__ENUMERATE_KEY_CODE(Period, ".", 0x6E) \
|
||||
__ENUMERATE_KEY_CODE(Colon, ":", 0x6F) \
|
||||
__ENUMERATE_KEY_CODE(F1, "F1", 0x70) \
|
||||
__ENUMERATE_KEY_CODE(F2, "F2", 0x71) \
|
||||
__ENUMERATE_KEY_CODE(F3, "F3", 0x72) \
|
||||
__ENUMERATE_KEY_CODE(F4, "F4", 0x73) \
|
||||
__ENUMERATE_KEY_CODE(F5, "F5", 0x74) \
|
||||
__ENUMERATE_KEY_CODE(F6, "F6", 0x75) \
|
||||
__ENUMERATE_KEY_CODE(F7, "F7", 0x76) \
|
||||
__ENUMERATE_KEY_CODE(F8, "F8", 0x77) \
|
||||
__ENUMERATE_KEY_CODE(F9, "F9", 0x78) \
|
||||
__ENUMERATE_KEY_CODE(F10, "F10", 0x79) \
|
||||
__ENUMERATE_KEY_CODE(F11, "F11", 0x7A) \
|
||||
__ENUMERATE_KEY_CODE(F12, "F12", 0x7B) \
|
||||
__ENUMERATE_KEY_CODE(DoubleQuote, "\"", 0x7C) \
|
||||
__ENUMERATE_KEY_CODE(Apostrophe, "'", 0x7D) \
|
||||
__ENUMERATE_KEY_CODE(Insert, "Insert", 0x7E) \
|
||||
__ENUMERATE_KEY_CODE(Semicolon, ";", 0x7F) \
|
||||
__ENUMERATE_KEY_CODE(LessThan, "<", 0x80) \
|
||||
__ENUMERATE_KEY_CODE(Equal, "=", 0x81) \
|
||||
__ENUMERATE_KEY_CODE(GreaterThan, ">", 0x82) \
|
||||
__ENUMERATE_KEY_CODE(QuestionMark, "?", 0x83) \
|
||||
__ENUMERATE_KEY_CODE(LeftBracket, "[", 0x84) \
|
||||
__ENUMERATE_KEY_CODE(RightBracket, "]", 0x85) \
|
||||
__ENUMERATE_KEY_CODE(Backslash, "\\", 0x86) \
|
||||
__ENUMERATE_KEY_CODE(Underscore, "_", 0x87) \
|
||||
__ENUMERATE_KEY_CODE(LeftBrace, "{", 0x88) \
|
||||
__ENUMERATE_KEY_CODE(RightBrace, "}", 0x89) \
|
||||
__ENUMERATE_KEY_CODE(Pipe, "|", 0x8A) \
|
||||
__ENUMERATE_KEY_CODE(Tilde, "~", 0x8B) \
|
||||
__ENUMERATE_KEY_CODE(Backtick, "`", 0x8C) \
|
||||
__ENUMERATE_KEY_CODE(NumLock, "NumLock", 0x90) \
|
||||
__ENUMERATE_KEY_CODE(ScrollLock, "ScrollLock", 0x91) \
|
||||
__ENUMERATE_KEY_CODE(LeftSuper, "LeftSuper", 0x92) \
|
||||
__ENUMERATE_KEY_CODE(RightSuper, "RightSuper", 0xAC) \
|
||||
__ENUMERATE_KEY_CODE(BrowserSearch, "BrowserSearch", 0x93) \
|
||||
__ENUMERATE_KEY_CODE(BrowserFavorites, "BrowserFavorites", 0x94) \
|
||||
__ENUMERATE_KEY_CODE(BrowserHome, "BrowserHome", 0x95) \
|
||||
__ENUMERATE_KEY_CODE(PreviousTrack, "PreviousTrack", 0x96) \
|
||||
__ENUMERATE_KEY_CODE(BrowserBack, "BrowserBack", 0x97) \
|
||||
__ENUMERATE_KEY_CODE(BrowserForward, "BrowserForward", 0x98) \
|
||||
__ENUMERATE_KEY_CODE(BrowserRefresh, "BrowserRefresh", 0x99) \
|
||||
__ENUMERATE_KEY_CODE(BrowserStop, "BrowserStop", 0x9A) \
|
||||
__ENUMERATE_KEY_CODE(VolumeDown, "VolumeDown", 0x9B) \
|
||||
__ENUMERATE_KEY_CODE(VolumeUp, "VolumeUp", 0x9C) \
|
||||
__ENUMERATE_KEY_CODE(Wake, "Wake", 0x9D) \
|
||||
__ENUMERATE_KEY_CODE(Sleep, "Sleep", 0x9E) \
|
||||
__ENUMERATE_KEY_CODE(NextTrack, "NextTrack", 0x9F) \
|
||||
__ENUMERATE_KEY_CODE(MediaSelect, "MediaSelect", 0xA0) \
|
||||
__ENUMERATE_KEY_CODE(Email, "Email", 0xA1) \
|
||||
__ENUMERATE_KEY_CODE(MyComputer, "MyComputer", 0xA2) \
|
||||
__ENUMERATE_KEY_CODE(Power, "Power", 0xA3) \
|
||||
__ENUMERATE_KEY_CODE(Stop, "Stop", 0xA4) \
|
||||
__ENUMERATE_KEY_CODE(LeftGUI, "LeftGUI", 0xA5) \
|
||||
__ENUMERATE_KEY_CODE(Mute, "Mute", 0xA6) \
|
||||
__ENUMERATE_KEY_CODE(RightGUI, "RightGUI", 0xA7) \
|
||||
__ENUMERATE_KEY_CODE(Calculator, "Calculator", 0xA8) \
|
||||
__ENUMERATE_KEY_CODE(Apps, "Apps", 0xA9) \
|
||||
__ENUMERATE_KEY_CODE(PlayPause, "PlayPause", 0xAA) \
|
||||
__ENUMERATE_KEY_CODE(Menu, "Menu", 0xAB)
|
||||
|
||||
enum KeyCode : u8 {
|
||||
#define __ENUMERATE_KEY_CODE(name, ui_name, code) Key_##name = code,
|
||||
ENUMERATE_KEY_CODES
|
||||
#undef __ENUMERATE_KEY_CODE
|
||||
};
|
||||
|
||||
constexpr KeyCode key_code_from_string(StringView key_name)
|
||||
{
|
||||
#define __ENUMERATE_KEY_CODE(name, ui_name, code) \
|
||||
if (key_name == ui_name##sv) \
|
||||
return KeyCode::Key_##name;
|
||||
ENUMERATE_KEY_CODES
|
||||
#undef __ENUMERATE_KEY_CODE
|
||||
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
enum KeyModifier {
|
||||
Mod_None = 0x00,
|
||||
Mod_Alt = (1 << 0),
|
||||
Mod_Ctrl = (1 << 1),
|
||||
Mod_Shift = (1 << 2),
|
||||
Mod_Super = (1 << 3),
|
||||
Mod_Keypad = (1 << 4),
|
||||
Mod_Mask = Mod_Alt | Mod_Ctrl | Mod_Shift | Mod_Super | Mod_Keypad,
|
||||
|
||||
Is_Press = 0x80,
|
||||
|
||||
#if defined(AK_OS_MACOS)
|
||||
Mod_PlatformCtrl = Mod_Super,
|
||||
Mod_PlatformWordJump = Mod_Alt,
|
||||
#else
|
||||
Mod_PlatformCtrl = Mod_Ctrl,
|
||||
Mod_PlatformWordJump = Mod_Ctrl,
|
||||
#endif
|
||||
};
|
||||
|
||||
AK_ENUM_BITWISE_OPERATORS(KeyModifier);
|
||||
|
||||
inline KeyCode code_point_to_key_code(u32 code_point)
|
||||
{
|
||||
switch (code_point) {
|
||||
#define MATCH_ALPHA(letter) \
|
||||
case #letter[0]: \
|
||||
case #letter[0] + 32: \
|
||||
return KeyCode::Key_##letter;
|
||||
MATCH_ALPHA(A)
|
||||
MATCH_ALPHA(B)
|
||||
MATCH_ALPHA(C)
|
||||
MATCH_ALPHA(D)
|
||||
MATCH_ALPHA(E)
|
||||
MATCH_ALPHA(F)
|
||||
MATCH_ALPHA(G)
|
||||
MATCH_ALPHA(H)
|
||||
MATCH_ALPHA(I)
|
||||
MATCH_ALPHA(J)
|
||||
MATCH_ALPHA(K)
|
||||
MATCH_ALPHA(L)
|
||||
MATCH_ALPHA(M)
|
||||
MATCH_ALPHA(N)
|
||||
MATCH_ALPHA(O)
|
||||
MATCH_ALPHA(P)
|
||||
MATCH_ALPHA(Q)
|
||||
MATCH_ALPHA(R)
|
||||
MATCH_ALPHA(S)
|
||||
MATCH_ALPHA(T)
|
||||
MATCH_ALPHA(U)
|
||||
MATCH_ALPHA(V)
|
||||
MATCH_ALPHA(W)
|
||||
MATCH_ALPHA(X)
|
||||
MATCH_ALPHA(Y)
|
||||
MATCH_ALPHA(Z)
|
||||
#undef MATCH_ALPHA
|
||||
|
||||
#define MATCH_KEY(name, character) \
|
||||
case character: \
|
||||
return KeyCode::Key_##name;
|
||||
MATCH_KEY(ExclamationPoint, '!')
|
||||
MATCH_KEY(DoubleQuote, '"')
|
||||
MATCH_KEY(Hashtag, '#')
|
||||
MATCH_KEY(Dollar, '$')
|
||||
MATCH_KEY(Percent, '%')
|
||||
MATCH_KEY(Ampersand, '&')
|
||||
MATCH_KEY(Apostrophe, '\'')
|
||||
MATCH_KEY(LeftParen, '(')
|
||||
MATCH_KEY(RightParen, ')')
|
||||
MATCH_KEY(Asterisk, '*')
|
||||
MATCH_KEY(Plus, '+')
|
||||
MATCH_KEY(Comma, ',')
|
||||
MATCH_KEY(Minus, '-')
|
||||
MATCH_KEY(Period, '.')
|
||||
MATCH_KEY(Slash, '/')
|
||||
MATCH_KEY(0, '0')
|
||||
MATCH_KEY(1, '1')
|
||||
MATCH_KEY(2, '2')
|
||||
MATCH_KEY(3, '3')
|
||||
MATCH_KEY(4, '4')
|
||||
MATCH_KEY(5, '5')
|
||||
MATCH_KEY(6, '6')
|
||||
MATCH_KEY(7, '7')
|
||||
MATCH_KEY(8, '8')
|
||||
MATCH_KEY(9, '9')
|
||||
MATCH_KEY(Colon, ':')
|
||||
MATCH_KEY(Semicolon, ';')
|
||||
MATCH_KEY(LessThan, '<')
|
||||
MATCH_KEY(Equal, '=')
|
||||
MATCH_KEY(GreaterThan, '>')
|
||||
MATCH_KEY(QuestionMark, '?')
|
||||
MATCH_KEY(AtSign, '@')
|
||||
MATCH_KEY(LeftBracket, '[')
|
||||
MATCH_KEY(RightBracket, ']')
|
||||
MATCH_KEY(Backslash, '\\')
|
||||
MATCH_KEY(Circumflex, '^')
|
||||
MATCH_KEY(Underscore, '_')
|
||||
MATCH_KEY(LeftBrace, '{')
|
||||
MATCH_KEY(RightBrace, '}')
|
||||
MATCH_KEY(Pipe, '|')
|
||||
MATCH_KEY(Tilde, '~')
|
||||
MATCH_KEY(Backtick, '`')
|
||||
MATCH_KEY(Space, ' ')
|
||||
MATCH_KEY(Tab, '\t')
|
||||
MATCH_KEY(Backspace, '\b')
|
||||
#undef MATCH_KEY
|
||||
|
||||
default:
|
||||
return KeyCode::Key_Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
799
Libraries/LibWeb/UIEvents/KeyboardEvent.cpp
Normal file
799
Libraries/LibWeb/UIEvents/KeyboardEvent.cpp
Normal file
|
@ -0,0 +1,799 @@
|
|||
/*
|
||||
* Copyright (c) 2021-2022, Andreas Kling <andreas@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/CharacterTypes.h>
|
||||
#include <LibUnicode/CharacterTypes.h>
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/Bindings/KeyboardEventPrototype.h>
|
||||
#include <LibWeb/UIEvents/EventNames.h>
|
||||
#include <LibWeb/UIEvents/KeyboardEvent.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
JS_DEFINE_ALLOCATOR(KeyboardEvent);
|
||||
|
||||
// https://www.w3.org/TR/uievents/#determine-keydown-keyup-keyCode
|
||||
static unsigned long determine_key_code(KeyCode platform_key, u32 code_point)
|
||||
{
|
||||
// If input key when pressed without modifiers would insert a numerical character (0-9), return the ASCII code of that numerical character.
|
||||
if (is_ascii_digit(code_point))
|
||||
return code_point;
|
||||
|
||||
switch (platform_key) {
|
||||
case KeyCode::Key_ExclamationPoint:
|
||||
return static_cast<unsigned long>('1');
|
||||
case KeyCode::Key_AtSign:
|
||||
return static_cast<unsigned long>('2');
|
||||
case KeyCode::Key_Hashtag:
|
||||
return static_cast<unsigned long>('3');
|
||||
case KeyCode::Key_Dollar:
|
||||
return static_cast<unsigned long>('4');
|
||||
case KeyCode::Key_Percent:
|
||||
return static_cast<unsigned long>('5');
|
||||
case KeyCode::Key_Circumflex:
|
||||
return static_cast<unsigned long>('6');
|
||||
case KeyCode::Key_Ampersand:
|
||||
return static_cast<unsigned long>('7');
|
||||
case KeyCode::Key_Asterisk:
|
||||
return static_cast<unsigned long>('8');
|
||||
case KeyCode::Key_LeftParen:
|
||||
return static_cast<unsigned long>('9');
|
||||
case KeyCode::Key_RightParen:
|
||||
return static_cast<unsigned long>('0');
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// If input key when pressed without modifiers would insert a lower case character in the a-z alphabetical range, return the ASCII code of the upper case equivalent.
|
||||
if (is_ascii_lower_alpha(code_point))
|
||||
return to_ascii_uppercase(code_point);
|
||||
|
||||
// If the key’s function, as determined in an implementation-specific way, corresponds to one of the keys in the §8.3.3 Fixed virtual key codes table, return the corresponding key code.
|
||||
// https://www.w3.org/TR/uievents/#fixed-virtual-key-codes
|
||||
switch (platform_key) {
|
||||
case KeyCode::Key_Backspace:
|
||||
return 8;
|
||||
case KeyCode::Key_Tab:
|
||||
return 9;
|
||||
case KeyCode::Key_Return:
|
||||
return 13;
|
||||
case KeyCode::Key_LeftShift:
|
||||
case KeyCode::Key_RightShift:
|
||||
return 16;
|
||||
case KeyCode::Key_LeftControl:
|
||||
case KeyCode::Key_RightControl:
|
||||
return 17;
|
||||
case KeyCode::Key_LeftAlt:
|
||||
case KeyCode::Key_RightAlt:
|
||||
return 18;
|
||||
case KeyCode::Key_CapsLock:
|
||||
return 20;
|
||||
case KeyCode::Key_Escape:
|
||||
return 27;
|
||||
case KeyCode::Key_Space:
|
||||
return 32;
|
||||
case KeyCode::Key_PageUp:
|
||||
return 33;
|
||||
case KeyCode::Key_PageDown:
|
||||
return 34;
|
||||
case KeyCode::Key_End:
|
||||
return 35;
|
||||
case KeyCode::Key_Home:
|
||||
return 36;
|
||||
case KeyCode::Key_Left:
|
||||
return 37;
|
||||
case KeyCode::Key_Up:
|
||||
return 38;
|
||||
case KeyCode::Key_Right:
|
||||
return 39;
|
||||
case KeyCode::Key_Down:
|
||||
return 40;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// https://www.w3.org/TR/uievents/#optionally-fixed-virtual-key-codes
|
||||
switch (platform_key) {
|
||||
case KeyCode::Key_Semicolon:
|
||||
case KeyCode::Key_Colon:
|
||||
return 186;
|
||||
case KeyCode::Key_Equal:
|
||||
case KeyCode::Key_Plus:
|
||||
return 187;
|
||||
case KeyCode::Key_Comma:
|
||||
case KeyCode::Key_LessThan:
|
||||
return 188;
|
||||
case KeyCode::Key_Minus:
|
||||
case KeyCode::Key_Underscore:
|
||||
return 189;
|
||||
case KeyCode::Key_Period:
|
||||
case KeyCode::Key_GreaterThan:
|
||||
return 190;
|
||||
case KeyCode::Key_Slash:
|
||||
case KeyCode::Key_QuestionMark:
|
||||
return 191;
|
||||
case KeyCode::Key_Backtick:
|
||||
case KeyCode::Key_Tilde:
|
||||
return 192;
|
||||
case KeyCode::Key_LeftBracket:
|
||||
case KeyCode::Key_LeftBrace:
|
||||
return 219;
|
||||
case KeyCode::Key_Backslash:
|
||||
case KeyCode::Key_Pipe:
|
||||
return 220;
|
||||
case KeyCode::Key_RightBracket:
|
||||
case KeyCode::Key_RightBrace:
|
||||
return 221;
|
||||
case KeyCode::Key_Apostrophe:
|
||||
case KeyCode::Key_DoubleQuote:
|
||||
return 222;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Return the virtual key code from the operating system.
|
||||
return platform_key;
|
||||
}
|
||||
|
||||
// https://www.w3.org/TR/uievents/#dom-keyboardevent-charcode
|
||||
static u32 determine_char_code(FlyString const& event_name, u32 code_point)
|
||||
{
|
||||
// charCode holds a character value, for keypress events which generate character input. The value is the Unicode
|
||||
// reference number (code point) of that character (e.g. event.charCode = event.key.charCodeAt(0) for printable
|
||||
// characters). For keydown or keyup events, the value of charCode is 0.
|
||||
if (event_name == UIEvents::EventNames::keypress) {
|
||||
if (Unicode::code_point_is_printable(code_point))
|
||||
return code_point;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 3. Named key Attribute Values, https://www.w3.org/TR/uievents-key/#named-key-attribute-values
|
||||
static ErrorOr<Optional<String>> get_event_named_key(KeyCode platform_key)
|
||||
{
|
||||
switch (platform_key) {
|
||||
// 3.1. Special Keys, https://www.w3.org/TR/uievents-key/#keys-special
|
||||
case KeyCode::Key_Invalid:
|
||||
return "Unidentified"_string;
|
||||
|
||||
// 3.2. Modifier Keys, https://www.w3.org/TR/uievents-key/#keys-modifier
|
||||
case KeyCode::Key_LeftAlt:
|
||||
case KeyCode::Key_RightAlt:
|
||||
return "Alt"_string;
|
||||
case KeyCode::Key_AltGr:
|
||||
return "AltGraph"_string;
|
||||
case KeyCode::Key_CapsLock:
|
||||
return "CapsLock"_string;
|
||||
case KeyCode::Key_LeftControl:
|
||||
case KeyCode::Key_RightControl:
|
||||
return "Control"_string;
|
||||
// FIXME: Fn
|
||||
// FIXME: FnLock
|
||||
case KeyCode::Key_LeftSuper:
|
||||
case KeyCode::Key_RightSuper:
|
||||
return "Meta"_string;
|
||||
case KeyCode::Key_NumLock:
|
||||
return "NumLock"_string;
|
||||
case KeyCode::Key_ScrollLock:
|
||||
return "ScrollLock"_string;
|
||||
case KeyCode::Key_LeftShift:
|
||||
case KeyCode::Key_RightShift:
|
||||
return "Shift"_string;
|
||||
|
||||
// 3.3. Whitespace Keys, https://www.w3.org/TR/uievents-key/#keys-whitespace
|
||||
case KeyCode::Key_Return:
|
||||
return "Enter"_string;
|
||||
case KeyCode::Key_Tab:
|
||||
return "Tab"_string;
|
||||
case KeyCode::Key_Space:
|
||||
return " "_string;
|
||||
|
||||
// 3.4. Navigation Keys, https://www.w3.org/TR/uievents-key/#keys-navigation
|
||||
case KeyCode::Key_Down:
|
||||
return "ArrowDown"_string;
|
||||
case KeyCode::Key_Left:
|
||||
return "ArrowLeft"_string;
|
||||
case KeyCode::Key_Right:
|
||||
return "ArrowRight"_string;
|
||||
case KeyCode::Key_Up:
|
||||
return "ArrowUp"_string;
|
||||
case KeyCode::Key_End:
|
||||
return "End"_string;
|
||||
case KeyCode::Key_Home:
|
||||
return "Home"_string;
|
||||
case KeyCode::Key_PageDown:
|
||||
return "PageDown"_string;
|
||||
case KeyCode::Key_PageUp:
|
||||
return "PageUp"_string;
|
||||
|
||||
// 3.5. Editing Keys, https://www.w3.org/TR/uievents-key/#keys-editing
|
||||
case KeyCode::Key_Backspace:
|
||||
return "Backspace"_string;
|
||||
case KeyCode::Key_Delete:
|
||||
return "Delete"_string;
|
||||
case KeyCode::Key_Insert:
|
||||
return "Insert"_string;
|
||||
|
||||
// 3.6. UI Keys, https://www.w3.org/TR/uievents-key/#keys-ui
|
||||
case KeyCode::Key_Menu:
|
||||
return "ContextMenu"_string;
|
||||
case KeyCode::Key_Escape:
|
||||
return "Escape"_string;
|
||||
// FIXME: Help
|
||||
// FIXME: Pause
|
||||
|
||||
// 3.7. Device Keys, https://www.w3.org/TR/uievents-key/#keys-device
|
||||
case KeyCode::Key_PrintScreen:
|
||||
return "PrintScreen"_string;
|
||||
|
||||
// 3.9. General-Purpose Function Keys, https://www.w3.org/TR/uievents-key/#keys-function
|
||||
case KeyCode::Key_F1:
|
||||
return "F1"_string;
|
||||
case KeyCode::Key_F2:
|
||||
return "F2"_string;
|
||||
case KeyCode::Key_F3:
|
||||
return "F3"_string;
|
||||
case KeyCode::Key_F4:
|
||||
return "F4"_string;
|
||||
case KeyCode::Key_F5:
|
||||
return "F5"_string;
|
||||
case KeyCode::Key_F6:
|
||||
return "F6"_string;
|
||||
case KeyCode::Key_F7:
|
||||
return "F7"_string;
|
||||
case KeyCode::Key_F8:
|
||||
return "F8"_string;
|
||||
case KeyCode::Key_F9:
|
||||
return "F9"_string;
|
||||
case KeyCode::Key_F10:
|
||||
return "F10"_string;
|
||||
case KeyCode::Key_F11:
|
||||
return "F11"_string;
|
||||
case KeyCode::Key_F12:
|
||||
return "F12"_string;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return OptionalNone {};
|
||||
}
|
||||
|
||||
// 2.1. Unicode Values, https://www.w3.org/TR/uievents-key/#keys-unicode
|
||||
static ErrorOr<Optional<String>> get_event_key_string(u32 code_point)
|
||||
{
|
||||
auto is_non_control_character = [&]() {
|
||||
// A non-control character is any valid Unicode character except those that are part of the "Other, Control"
|
||||
// ("Cc") General Category.
|
||||
return !Unicode::code_point_has_control_general_category(code_point);
|
||||
};
|
||||
|
||||
// A key string is a string containing a 0 or 1 non-control characters ("base" characters) followed by 0 or more
|
||||
// combining characters. The string MUST be in Normalized Form C (NFC) as described in [UAX15].
|
||||
// FIXME: Our key events are currently set up to provide one code point at a time. We will need to handle multi-
|
||||
// code point events and NFC normalize that string.
|
||||
if (is_non_control_character())
|
||||
return String::from_code_point(code_point);
|
||||
|
||||
return OptionalNone {};
|
||||
}
|
||||
|
||||
// 2.2. Selecting key Attribute Values, https://www.w3.org/TR/uievents-key/#selecting-key-attribute-values
|
||||
static ErrorOr<String> get_event_key(KeyCode platform_key, u32 code_point)
|
||||
{
|
||||
// 1. Let key be a DOMString initially set to "Unidentified".
|
||||
// NOTE: We return "Unidentified" at the end to avoid needlessly allocating it here.
|
||||
|
||||
// 2. If there exists an appropriate named key attribute value for this key event, then
|
||||
// AD-HOC: Key_Invalid would be interpreted as "Unidentified" here. But we also use Key_Invalid for key presses that
|
||||
// are not on a standard US keyboard. If such a key would generate a valid key string below, let's allow that
|
||||
// to happen; otherwise, we will still return "Unidentified" at the end.
|
||||
if (platform_key != KeyCode::Key_Invalid) {
|
||||
if (auto named_key = TRY(get_event_named_key(platform_key)); named_key.has_value()) {
|
||||
// 1. Set key to that named key attribute value.
|
||||
return named_key.release_value();
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Else, if the key event generates a valid key string, then
|
||||
if (auto key_string = TRY(get_event_key_string(code_point)); key_string.has_value()) {
|
||||
// 1. Set key to that key string value.
|
||||
return key_string.release_value();
|
||||
}
|
||||
|
||||
// FIXME: 4. Else, if the key event has any modifier keys other than glyph modifier keys, then
|
||||
// FIXME: 1. Set key to the key string that would have been generated by this event if it had been typed with all
|
||||
// modifer keys removed except for glyph modifier keys.
|
||||
|
||||
// 5. Return key as the key attribute value for this key event.
|
||||
return "Unidentified"_string;
|
||||
}
|
||||
|
||||
// 3. Keyboard Event code Value Tables, https://www.w3.org/TR/uievents-code/#code-value-tables
|
||||
static ErrorOr<String> get_event_code(KeyCode platform_key, unsigned modifiers)
|
||||
{
|
||||
// 3.4. Numpad Section, https://www.w3.org/TR/uievents-code/#key-numpad-section
|
||||
if ((modifiers & Mod_Keypad) != 0) {
|
||||
switch (platform_key) {
|
||||
case KeyCode::Key_0:
|
||||
return "Numpad0"_string;
|
||||
case KeyCode::Key_1:
|
||||
return "Numpad1"_string;
|
||||
case KeyCode::Key_2:
|
||||
return "Numpad2"_string;
|
||||
case KeyCode::Key_3:
|
||||
return "Numpad3"_string;
|
||||
case KeyCode::Key_4:
|
||||
return "Numpad4"_string;
|
||||
case KeyCode::Key_5:
|
||||
return "Numpad5"_string;
|
||||
case KeyCode::Key_6:
|
||||
return "Numpad6"_string;
|
||||
case KeyCode::Key_7:
|
||||
return "Numpad7"_string;
|
||||
case KeyCode::Key_8:
|
||||
return "Numpad8"_string;
|
||||
case KeyCode::Key_9:
|
||||
return "Numpad9"_string;
|
||||
case KeyCode::Key_Plus:
|
||||
return "NumpadAdd"_string;
|
||||
case KeyCode::Key_Comma:
|
||||
return "NumpadComma"_string;
|
||||
case KeyCode::Key_Period:
|
||||
case KeyCode::Key_Delete:
|
||||
return "NumpadDecimal"_string;
|
||||
case KeyCode::Key_Slash:
|
||||
return "NumpadDivide"_string;
|
||||
case KeyCode::Key_Return:
|
||||
return "NumpadEnter"_string;
|
||||
case KeyCode::Key_Asterisk:
|
||||
return "NumpadMultiply"_string;
|
||||
case KeyCode::Key_Minus:
|
||||
return "NumpadSubtract"_string;
|
||||
case KeyCode::Key_Equal:
|
||||
return "NumpadEqual"_string;
|
||||
case KeyCode::Key_Hashtag:
|
||||
return "NumpadHash"_string;
|
||||
case KeyCode::Key_LeftParen:
|
||||
return "NumpadParenLeft"_string;
|
||||
case KeyCode::Key_RightParen:
|
||||
return "NumpadParenRight"_string;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (platform_key) {
|
||||
// 3.1.1. Writing System Keys, https://www.w3.org/TR/uievents-code/#key-alphanumeric-writing-system
|
||||
case KeyCode::Key_Backtick:
|
||||
case KeyCode::Key_Tilde:
|
||||
return "Backquote"_string;
|
||||
case KeyCode::Key_Backslash:
|
||||
case KeyCode::Key_Pipe:
|
||||
return "Backslash"_string;
|
||||
case KeyCode::Key_LeftBrace:
|
||||
case KeyCode::Key_LeftBracket:
|
||||
return "BracketLeft"_string;
|
||||
case KeyCode::Key_RightBrace:
|
||||
case KeyCode::Key_RightBracket:
|
||||
return "BracketRight"_string;
|
||||
case KeyCode::Key_Comma:
|
||||
case KeyCode::Key_LessThan:
|
||||
return "Comma"_string;
|
||||
case KeyCode::Key_0:
|
||||
case KeyCode::Key_RightParen:
|
||||
return "Digit0"_string;
|
||||
case KeyCode::Key_1:
|
||||
case KeyCode::Key_ExclamationPoint:
|
||||
return "Digit1"_string;
|
||||
case KeyCode::Key_2:
|
||||
case KeyCode::Key_AtSign:
|
||||
return "Digit2"_string;
|
||||
case KeyCode::Key_3:
|
||||
case KeyCode::Key_Hashtag:
|
||||
return "Digit3"_string;
|
||||
case KeyCode::Key_4:
|
||||
case KeyCode::Key_Dollar:
|
||||
return "Digit4"_string;
|
||||
case KeyCode::Key_5:
|
||||
case KeyCode::Key_Percent:
|
||||
return "Digit5"_string;
|
||||
case KeyCode::Key_6:
|
||||
case KeyCode::Key_Circumflex:
|
||||
return "Digit6"_string;
|
||||
case KeyCode::Key_7:
|
||||
case KeyCode::Key_Ampersand:
|
||||
return "Digit7"_string;
|
||||
case KeyCode::Key_8:
|
||||
case KeyCode::Key_Asterisk:
|
||||
return "Digit8"_string;
|
||||
case KeyCode::Key_9:
|
||||
case KeyCode::Key_LeftParen:
|
||||
return "Digit9"_string;
|
||||
case KeyCode::Key_Equal:
|
||||
case KeyCode::Key_Plus:
|
||||
return "Equal"_string;
|
||||
// FIXME: IntlBackslash
|
||||
// FIXME: IntlRo
|
||||
// FIXME: IntlYen
|
||||
case KeyCode::Key_A:
|
||||
return "KeyA"_string;
|
||||
case KeyCode::Key_B:
|
||||
return "KeyB"_string;
|
||||
case KeyCode::Key_C:
|
||||
return "KeyC"_string;
|
||||
case KeyCode::Key_D:
|
||||
return "KeyD"_string;
|
||||
case KeyCode::Key_E:
|
||||
return "KeyE"_string;
|
||||
case KeyCode::Key_F:
|
||||
return "KeyF"_string;
|
||||
case KeyCode::Key_G:
|
||||
return "KeyG"_string;
|
||||
case KeyCode::Key_H:
|
||||
return "KeyH"_string;
|
||||
case KeyCode::Key_I:
|
||||
return "KeyI"_string;
|
||||
case KeyCode::Key_J:
|
||||
return "KeyJ"_string;
|
||||
case KeyCode::Key_K:
|
||||
return "KeyK"_string;
|
||||
case KeyCode::Key_L:
|
||||
return "KeyL"_string;
|
||||
case KeyCode::Key_M:
|
||||
return "KeyM"_string;
|
||||
case KeyCode::Key_N:
|
||||
return "KeyN"_string;
|
||||
case KeyCode::Key_O:
|
||||
return "KeyO"_string;
|
||||
case KeyCode::Key_P:
|
||||
return "KeyP"_string;
|
||||
case KeyCode::Key_Q:
|
||||
return "KeyQ"_string;
|
||||
case KeyCode::Key_R:
|
||||
return "KeyR"_string;
|
||||
case KeyCode::Key_S:
|
||||
return "KeyS"_string;
|
||||
case KeyCode::Key_T:
|
||||
return "KeyT"_string;
|
||||
case KeyCode::Key_U:
|
||||
return "KeyU"_string;
|
||||
case KeyCode::Key_V:
|
||||
return "KeyV"_string;
|
||||
case KeyCode::Key_W:
|
||||
return "KeyW"_string;
|
||||
case KeyCode::Key_X:
|
||||
return "KeyX"_string;
|
||||
case KeyCode::Key_Y:
|
||||
return "KeyY"_string;
|
||||
case KeyCode::Key_Z:
|
||||
return "KeyZ"_string;
|
||||
case KeyCode::Key_Minus:
|
||||
case KeyCode::Key_Underscore:
|
||||
return "Minus"_string;
|
||||
case KeyCode::Key_Period:
|
||||
case KeyCode::Key_GreaterThan:
|
||||
return "Period"_string;
|
||||
case KeyCode::Key_Apostrophe:
|
||||
case KeyCode::Key_DoubleQuote:
|
||||
return "Quote"_string;
|
||||
case KeyCode::Key_Semicolon:
|
||||
case KeyCode::Key_Colon:
|
||||
return "Semicolon"_string;
|
||||
case KeyCode::Key_Slash:
|
||||
case KeyCode::Key_QuestionMark:
|
||||
return "Slash"_string;
|
||||
|
||||
// 3.1.2. Functional Keys, https://www.w3.org/TR/uievents-code/#key-alphanumeric-functional
|
||||
case KeyCode::Key_LeftAlt:
|
||||
return "AltLeft"_string;
|
||||
case KeyCode::Key_RightAlt:
|
||||
return "AltRight"_string;
|
||||
case KeyCode::Key_AltGr:
|
||||
return "AltGraph"_string;
|
||||
case KeyCode::Key_Backspace:
|
||||
return "Backspace"_string;
|
||||
case KeyCode::Key_CapsLock:
|
||||
return "CapsLock"_string;
|
||||
case KeyCode::Key_Menu:
|
||||
return "ContextMenu"_string;
|
||||
case KeyCode::Key_LeftControl:
|
||||
return "ControlLeft"_string;
|
||||
case KeyCode::Key_RightControl:
|
||||
return "ControlRight"_string;
|
||||
case KeyCode::Key_Return:
|
||||
return "Enter"_string;
|
||||
case KeyCode::Key_LeftSuper:
|
||||
return "MetaLeft"_string;
|
||||
case KeyCode::Key_RightSuper:
|
||||
return "MetaRight"_string;
|
||||
case KeyCode::Key_LeftShift:
|
||||
return "ShiftLeft"_string;
|
||||
case KeyCode::Key_RightShift:
|
||||
return "ShiftRight"_string;
|
||||
case KeyCode::Key_Space:
|
||||
return "Space"_string;
|
||||
case KeyCode::Key_Tab:
|
||||
return "Tab"_string;
|
||||
|
||||
// 3.2. Control Pad Section, https://www.w3.org/TR/uievents-code/#key-controlpad-section
|
||||
case KeyCode::Key_Delete:
|
||||
return "Delete"_string;
|
||||
case KeyCode::Key_End:
|
||||
return "End"_string;
|
||||
// FIXME: Help
|
||||
case KeyCode::Key_Home:
|
||||
return "Home"_string;
|
||||
case KeyCode::Key_Insert:
|
||||
return "Insert"_string;
|
||||
case KeyCode::Key_PageDown:
|
||||
return "PageDown"_string;
|
||||
case KeyCode::Key_PageUp:
|
||||
return "PageUp"_string;
|
||||
|
||||
// 3.3. Arrow Pad Section, https://www.w3.org/TR/uievents-code/#key-arrowpad-section
|
||||
case KeyCode::Key_Down:
|
||||
return "ArrowDown"_string;
|
||||
case KeyCode::Key_Left:
|
||||
return "ArrowLeft"_string;
|
||||
case KeyCode::Key_Right:
|
||||
return "ArrowRight"_string;
|
||||
case KeyCode::Key_Up:
|
||||
return "ArrowUp"_string;
|
||||
|
||||
// 3.4. Numpad Section, https://www.w3.org/TR/uievents-code/#key-numpad-section
|
||||
case KeyCode::Key_NumLock:
|
||||
return "NumLock"_string;
|
||||
|
||||
// 3.5. Function Section, https://www.w3.org/TR/uievents-code/#key-function-section
|
||||
case KeyCode::Key_Escape:
|
||||
return "Escape"_string;
|
||||
case KeyCode::Key_F1:
|
||||
return "F1"_string;
|
||||
case KeyCode::Key_F2:
|
||||
return "F2"_string;
|
||||
case KeyCode::Key_F3:
|
||||
return "F3"_string;
|
||||
case KeyCode::Key_F4:
|
||||
return "F4"_string;
|
||||
case KeyCode::Key_F5:
|
||||
return "F5"_string;
|
||||
case KeyCode::Key_F6:
|
||||
return "F6"_string;
|
||||
case KeyCode::Key_F7:
|
||||
return "F7"_string;
|
||||
case KeyCode::Key_F8:
|
||||
return "F8"_string;
|
||||
case KeyCode::Key_F9:
|
||||
return "F9"_string;
|
||||
case KeyCode::Key_F10:
|
||||
return "F10"_string;
|
||||
case KeyCode::Key_F11:
|
||||
return "F11"_string;
|
||||
case KeyCode::Key_F12:
|
||||
return "F12"_string;
|
||||
case KeyCode::Key_PrintScreen:
|
||||
case KeyCode::Key_SysRq:
|
||||
return "PrintScreen"_string;
|
||||
case KeyCode::Key_ScrollLock:
|
||||
return "ScrollLock"_string;
|
||||
case KeyCode::Key_PauseBreak:
|
||||
return "Pause"_string;
|
||||
|
||||
// 3.6. Media Section, https://www.w3.org/TR/uievents-code/#media-keys
|
||||
case KeyCode::Key_BrowserSearch:
|
||||
return "BrowserSearch"_string;
|
||||
case KeyCode::Key_BrowserFavorites:
|
||||
return "BrowserFavorites"_string;
|
||||
case KeyCode::Key_BrowserHome:
|
||||
return "BrowserHome"_string;
|
||||
case KeyCode::Key_PreviousTrack:
|
||||
return "PreviousTrack"_string;
|
||||
case KeyCode::Key_BrowserBack:
|
||||
return "BrowserBack"_string;
|
||||
case KeyCode::Key_BrowserForward:
|
||||
return "BrowserForward"_string;
|
||||
case KeyCode::Key_BrowserRefresh:
|
||||
return "BrowserRefresh"_string;
|
||||
case KeyCode::Key_BrowserStop:
|
||||
return "BrowserStop"_string;
|
||||
case KeyCode::Key_VolumeDown:
|
||||
return "AudioVolumeDown"_string;
|
||||
case KeyCode::Key_VolumeUp:
|
||||
return "AudioVolumeUp"_string;
|
||||
case KeyCode::Key_Wake:
|
||||
return "WakeUp"_string;
|
||||
case KeyCode::Key_Sleep:
|
||||
return "Sleep"_string;
|
||||
case KeyCode::Key_NextTrack:
|
||||
return "NextTrack"_string;
|
||||
case KeyCode::Key_MediaSelect:
|
||||
return "MediaSelect"_string;
|
||||
case KeyCode::Key_Email:
|
||||
return "LaunchMail"_string;
|
||||
|
||||
case KeyCode::Key_Power:
|
||||
return "Power"_string;
|
||||
case KeyCode::Key_Stop:
|
||||
return "MediaStop"_string;
|
||||
case KeyCode::Key_PlayPause:
|
||||
return "MediaPlayPause"_string;
|
||||
case KeyCode::Key_Mute:
|
||||
return "AudioVolumeMute"_string;
|
||||
case KeyCode::Key_Calculator:
|
||||
return "LaunchApp2"_string;
|
||||
case KeyCode::Key_MyComputer:
|
||||
return "LaunchApp1"_string;
|
||||
|
||||
// FIXME: Are these correct?
|
||||
case KeyCode::Key_LeftGUI:
|
||||
return "LaunchApp2"_string;
|
||||
case KeyCode::Key_RightGUI:
|
||||
case KeyCode::Key_Apps:
|
||||
return "LaunchApp1"_string;
|
||||
|
||||
// 3.7. Legacy, Non-Standard and Special Keys, https://www.w3.org/TR/uievents-code/#key-legacy
|
||||
case KeyCode::Key_Invalid:
|
||||
return "Unidentified"_string;
|
||||
}
|
||||
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
// 5.6.2. Keyboard Event Key Location, https://www.w3.org/TR/uievents/#events-keyboard-key-location
|
||||
static DOMKeyLocation get_event_location(KeyCode platform_key, unsigned modifiers)
|
||||
{
|
||||
if ((modifiers & Mod_Keypad) != 0)
|
||||
return DOMKeyLocation::Numpad;
|
||||
|
||||
switch (platform_key) {
|
||||
case KeyCode::Key_LeftAlt:
|
||||
case KeyCode::Key_LeftControl:
|
||||
case KeyCode::Key_LeftShift:
|
||||
case KeyCode::Key_LeftSuper:
|
||||
return DOMKeyLocation::Left;
|
||||
case KeyCode::Key_RightAlt:
|
||||
case KeyCode::Key_RightControl:
|
||||
case KeyCode::Key_RightShift:
|
||||
case KeyCode::Key_RightSuper:
|
||||
return DOMKeyLocation::Right;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DOMKeyLocation::Standard;
|
||||
}
|
||||
|
||||
JS::NonnullGCPtr<KeyboardEvent> KeyboardEvent::create_from_platform_event(JS::Realm& realm, FlyString const& event_name, KeyCode platform_key, unsigned modifiers, u32 code_point, bool repeat)
|
||||
{
|
||||
auto event_key = MUST(get_event_key(platform_key, code_point));
|
||||
auto event_code = MUST(get_event_code(platform_key, modifiers));
|
||||
auto key_code = determine_key_code(platform_key, code_point);
|
||||
auto char_code = determine_char_code(event_name, code_point);
|
||||
|
||||
KeyboardEventInit event_init {};
|
||||
event_init.key = move(event_key);
|
||||
event_init.code = move(event_code);
|
||||
event_init.location = to_underlying(get_event_location(platform_key, modifiers));
|
||||
event_init.ctrl_key = modifiers & Mod_Ctrl;
|
||||
event_init.shift_key = modifiers & Mod_Shift;
|
||||
event_init.alt_key = modifiers & Mod_Alt;
|
||||
event_init.meta_key = modifiers & Mod_Super;
|
||||
event_init.repeat = repeat;
|
||||
event_init.is_composing = false;
|
||||
event_init.key_code = key_code;
|
||||
event_init.char_code = char_code;
|
||||
event_init.bubbles = true;
|
||||
event_init.cancelable = true;
|
||||
event_init.composed = true;
|
||||
|
||||
auto event = KeyboardEvent::create(realm, event_name, event_init);
|
||||
event->set_is_trusted(true);
|
||||
return event;
|
||||
}
|
||||
|
||||
bool KeyboardEvent::get_modifier_state(String const& key_arg) const
|
||||
{
|
||||
if (key_arg == "Control")
|
||||
return m_ctrl_key;
|
||||
if (key_arg == "Shift")
|
||||
return m_shift_key;
|
||||
if (key_arg == "Alt")
|
||||
return m_alt_key;
|
||||
if (key_arg == "Meta")
|
||||
return m_meta_key;
|
||||
if (key_arg == "AltGraph")
|
||||
return m_modifier_alt_graph;
|
||||
if (key_arg == "CapsLock")
|
||||
return m_modifier_caps_lock;
|
||||
if (key_arg == "Fn")
|
||||
return m_modifier_fn;
|
||||
if (key_arg == "FnLock")
|
||||
return m_modifier_fn_lock;
|
||||
if (key_arg == "Hyper")
|
||||
return m_modifier_hyper;
|
||||
if (key_arg == "NumLock")
|
||||
return m_modifier_num_lock;
|
||||
if (key_arg == "ScrollLock")
|
||||
return m_modifier_scroll_lock;
|
||||
if (key_arg == "Super")
|
||||
return m_modifier_super;
|
||||
if (key_arg == "Symbol")
|
||||
return m_modifier_symbol;
|
||||
if (key_arg == "SymbolLock")
|
||||
return m_modifier_symbol_lock;
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/uievents/#dom-keyboardevent-initkeyboardevent
|
||||
void KeyboardEvent::init_keyboard_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, String const& key, WebIDL::UnsignedLong location, bool ctrl_key, bool alt_key, bool shift_key, bool meta_key)
|
||||
{
|
||||
// Initializes attributes of a KeyboardEvent object. This method has the same behavior as UIEvent.initUIEvent().
|
||||
// The value of detail remains undefined.
|
||||
|
||||
// 1. If this’s dispatch flag is set, then return.
|
||||
if (dispatched())
|
||||
return;
|
||||
|
||||
// 2. Initialize this with type, bubbles, and cancelable.
|
||||
initialize_event(type, bubbles, cancelable);
|
||||
|
||||
// Implementation Defined: Initialise other values.
|
||||
m_view = view;
|
||||
m_key = key;
|
||||
m_location = location;
|
||||
m_ctrl_key = ctrl_key;
|
||||
m_alt_key = alt_key;
|
||||
m_shift_key = shift_key;
|
||||
m_meta_key = meta_key;
|
||||
}
|
||||
|
||||
JS::NonnullGCPtr<KeyboardEvent> KeyboardEvent::create(JS::Realm& realm, FlyString const& event_name, KeyboardEventInit const& event_init)
|
||||
{
|
||||
return realm.heap().allocate<KeyboardEvent>(realm, realm, event_name, event_init);
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<KeyboardEvent>> KeyboardEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, KeyboardEventInit const& event_init)
|
||||
{
|
||||
return create(realm, event_name, event_init);
|
||||
}
|
||||
|
||||
KeyboardEvent::KeyboardEvent(JS::Realm& realm, FlyString const& event_name, KeyboardEventInit const& event_init)
|
||||
: UIEvent(realm, event_name, event_init)
|
||||
, m_key(event_init.key)
|
||||
, m_code(event_init.code)
|
||||
, m_location(event_init.location)
|
||||
, m_ctrl_key(event_init.ctrl_key)
|
||||
, m_shift_key(event_init.shift_key)
|
||||
, m_alt_key(event_init.alt_key)
|
||||
, m_meta_key(event_init.meta_key)
|
||||
, m_modifier_alt_graph(event_init.modifier_alt_graph)
|
||||
, m_modifier_caps_lock(event_init.modifier_caps_lock)
|
||||
, m_modifier_fn(event_init.modifier_fn)
|
||||
, m_modifier_fn_lock(event_init.modifier_fn_lock)
|
||||
, m_modifier_hyper(event_init.modifier_hyper)
|
||||
, m_modifier_num_lock(event_init.modifier_num_lock)
|
||||
, m_modifier_scroll_lock(event_init.modifier_scroll_lock)
|
||||
, m_modifier_super(event_init.modifier_super)
|
||||
, m_modifier_symbol(event_init.modifier_symbol)
|
||||
, m_modifier_symbol_lock(event_init.modifier_symbol_lock)
|
||||
, m_repeat(event_init.repeat)
|
||||
, m_is_composing(event_init.is_composing)
|
||||
, m_key_code(event_init.key_code)
|
||||
, m_char_code(event_init.char_code)
|
||||
{
|
||||
}
|
||||
|
||||
KeyboardEvent::~KeyboardEvent() = default;
|
||||
|
||||
void KeyboardEvent::initialize(JS::Realm& realm)
|
||||
{
|
||||
Base::initialize(realm);
|
||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(KeyboardEvent);
|
||||
}
|
||||
|
||||
}
|
95
Libraries/LibWeb/UIEvents/KeyboardEvent.h
Normal file
95
Libraries/LibWeb/UIEvents/KeyboardEvent.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 2021-2022, Andreas Kling <andreas@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/FlyString.h>
|
||||
#include <AK/TypeCasts.h>
|
||||
#include <LibWeb/UIEvents/EventModifier.h>
|
||||
#include <LibWeb/UIEvents/KeyCode.h>
|
||||
#include <LibWeb/UIEvents/UIEvent.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
struct KeyboardEventInit : public EventModifierInit {
|
||||
String key;
|
||||
String code;
|
||||
u32 location { 0 };
|
||||
bool repeat { false };
|
||||
bool is_composing { false };
|
||||
u32 key_code { 0 };
|
||||
u32 char_code { 0 };
|
||||
};
|
||||
|
||||
enum class DOMKeyLocation {
|
||||
Standard = 0,
|
||||
Left = 1,
|
||||
Right = 2,
|
||||
Numpad = 3,
|
||||
};
|
||||
|
||||
// https://www.w3.org/TR/uievents/#interface-keyboardevent
|
||||
class KeyboardEvent final : public UIEvent {
|
||||
WEB_PLATFORM_OBJECT(KeyboardEvent, UIEvent);
|
||||
JS_DECLARE_ALLOCATOR(KeyboardEvent);
|
||||
|
||||
public:
|
||||
[[nodiscard]] static JS::NonnullGCPtr<KeyboardEvent> create(JS::Realm&, FlyString const& event_name, KeyboardEventInit const& = {});
|
||||
[[nodiscard]] static JS::NonnullGCPtr<KeyboardEvent> create_from_platform_event(JS::Realm&, FlyString const& event_name, KeyCode, unsigned modifiers, u32 code_point, bool repeat);
|
||||
static WebIDL::ExceptionOr<JS::NonnullGCPtr<KeyboardEvent>> construct_impl(JS::Realm&, FlyString const& event_name, KeyboardEventInit const&);
|
||||
|
||||
virtual ~KeyboardEvent() override;
|
||||
|
||||
u32 key_code() const { return m_key_code; }
|
||||
u32 char_code() const { return m_char_code; }
|
||||
|
||||
String key() const { return m_key; }
|
||||
String code() const { return m_code; }
|
||||
u32 location() const { return m_location; }
|
||||
|
||||
bool ctrl_key() const { return m_ctrl_key; }
|
||||
bool shift_key() const { return m_shift_key; }
|
||||
bool alt_key() const { return m_alt_key; }
|
||||
bool meta_key() const { return m_meta_key; }
|
||||
|
||||
bool repeat() const { return m_repeat; }
|
||||
bool is_composing() const { return m_is_composing; }
|
||||
|
||||
bool get_modifier_state(String const& key_arg) const;
|
||||
|
||||
virtual u32 which() const override { return m_key_code; }
|
||||
|
||||
void init_keyboard_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, String const& key, WebIDL::UnsignedLong location, bool ctrl_key, bool alt_key, bool shift_key, bool meta_key);
|
||||
|
||||
private:
|
||||
KeyboardEvent(JS::Realm&, FlyString const& event_name, KeyboardEventInit const& event_init);
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
|
||||
String m_key;
|
||||
String m_code;
|
||||
u32 m_location { 0 };
|
||||
bool m_ctrl_key { false };
|
||||
bool m_shift_key { false };
|
||||
bool m_alt_key { false };
|
||||
bool m_meta_key { false };
|
||||
bool m_modifier_alt_graph { false };
|
||||
bool m_modifier_caps_lock { false };
|
||||
bool m_modifier_fn { false };
|
||||
bool m_modifier_fn_lock { false };
|
||||
bool m_modifier_hyper { false };
|
||||
bool m_modifier_num_lock { false };
|
||||
bool m_modifier_scroll_lock { false };
|
||||
bool m_modifier_super { false };
|
||||
bool m_modifier_symbol { false };
|
||||
bool m_modifier_symbol_lock { false };
|
||||
bool m_repeat { false };
|
||||
bool m_is_composing { false };
|
||||
u32 m_key_code { 0 };
|
||||
u32 m_char_code { 0 };
|
||||
};
|
||||
|
||||
}
|
46
Libraries/LibWeb/UIEvents/KeyboardEvent.idl
Normal file
46
Libraries/LibWeb/UIEvents/KeyboardEvent.idl
Normal file
|
@ -0,0 +1,46 @@
|
|||
#import <UIEvents/EventModifier.idl>
|
||||
|
||||
// https://www.w3.org/TR/uievents/#idl-keyboardevent
|
||||
[Exposed=Window]
|
||||
interface KeyboardEvent : UIEvent {
|
||||
|
||||
constructor(DOMString type, optional KeyboardEventInit eventInitDict = {});
|
||||
|
||||
// KeyLocationCode
|
||||
const unsigned long DOM_KEY_LOCATION_STANDARD = 0x00;
|
||||
const unsigned long DOM_KEY_LOCATION_LEFT = 0x01;
|
||||
const unsigned long DOM_KEY_LOCATION_RIGHT = 0x02;
|
||||
const unsigned long DOM_KEY_LOCATION_NUMPAD = 0x03;
|
||||
|
||||
readonly attribute DOMString key;
|
||||
readonly attribute DOMString code;
|
||||
readonly attribute unsigned long location;
|
||||
|
||||
readonly attribute boolean ctrlKey;
|
||||
readonly attribute boolean shiftKey;
|
||||
readonly attribute boolean altKey;
|
||||
readonly attribute boolean metaKey;
|
||||
|
||||
readonly attribute boolean repeat;
|
||||
readonly attribute boolean isComposing;
|
||||
|
||||
readonly attribute unsigned long charCode;
|
||||
readonly attribute unsigned long keyCode;
|
||||
|
||||
boolean getModifierState(DOMString keyArg);
|
||||
|
||||
// https://w3c.github.io/uievents/#dom-keyboardevent-initkeyboardevent
|
||||
undefined initKeyboardEvent(DOMString typeArg, optional boolean bubblesArg = false, optional boolean cancelableArg = false, optional Window? viewArg = null, optional DOMString keyArg = "", optional unsigned long locationArg = 0, optional boolean ctrlKey = false, optional boolean altKey = false, optional boolean shiftKey = false, optional boolean metaKey = false);
|
||||
|
||||
};
|
||||
|
||||
// https://www.w3.org/TR/uievents/#dictdef-keyboardeventinit
|
||||
dictionary KeyboardEventInit : EventModifierInit {
|
||||
DOMString key = "";
|
||||
DOMString code = "";
|
||||
unsigned long location = 0;
|
||||
boolean repeat = false;
|
||||
boolean isComposing = false;
|
||||
unsigned long charCode = 0;
|
||||
unsigned long keyCode = 0;
|
||||
};
|
61
Libraries/LibWeb/UIEvents/MouseButton.h
Normal file
61
Libraries/LibWeb/UIEvents/MouseButton.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Andreas Kling <andreas@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Assertions.h>
|
||||
#include <AK/EnumBits.h>
|
||||
#include <AK/Types.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
enum MouseButton : u8 {
|
||||
None = 0,
|
||||
Primary = 1,
|
||||
Secondary = 2,
|
||||
Middle = 4,
|
||||
Backward = 8,
|
||||
Forward = 16,
|
||||
};
|
||||
|
||||
AK_ENUM_BITWISE_OPERATORS(MouseButton);
|
||||
|
||||
// https://www.w3.org/TR/uievents/#dom-mouseevent-button
|
||||
constexpr i16 mouse_button_to_button_code(MouseButton button)
|
||||
{
|
||||
switch (button) {
|
||||
case MouseButton::Primary:
|
||||
return 0;
|
||||
case MouseButton::Middle:
|
||||
return 1;
|
||||
case MouseButton::Secondary:
|
||||
return 2;
|
||||
case MouseButton::Backward:
|
||||
return 3;
|
||||
case MouseButton::Forward:
|
||||
return 4;
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
// https://www.w3.org/TR/uievents/#dom-mouseevent-button
|
||||
constexpr MouseButton button_code_to_mouse_button(i16 button)
|
||||
{
|
||||
if (button == 0)
|
||||
return MouseButton::Primary;
|
||||
if (button == 1)
|
||||
return MouseButton::Middle;
|
||||
if (button == 2)
|
||||
return MouseButton::Secondary;
|
||||
if (button == 3)
|
||||
return MouseButton::Backward;
|
||||
if (button == 4)
|
||||
return MouseButton::Forward;
|
||||
return MouseButton::None;
|
||||
}
|
||||
|
||||
}
|
161
Libraries/LibWeb/UIEvents/MouseEvent.cpp
Normal file
161
Libraries/LibWeb/UIEvents/MouseEvent.cpp
Normal file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright (c) 2020, the SerenityOS developers.
|
||||
* Copyright (c) 2022, Andreas Kling <andreas@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/Bindings/MouseEventPrototype.h>
|
||||
#include <LibWeb/HTML/EventNames.h>
|
||||
#include <LibWeb/UIEvents/EventNames.h>
|
||||
#include <LibWeb/UIEvents/KeyCode.h>
|
||||
#include <LibWeb/UIEvents/MouseButton.h>
|
||||
#include <LibWeb/UIEvents/MouseEvent.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
JS_DEFINE_ALLOCATOR(MouseEvent);
|
||||
|
||||
MouseEvent::MouseEvent(JS::Realm& realm, FlyString const& event_name, MouseEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y)
|
||||
: UIEvent(realm, event_name, event_init)
|
||||
, m_screen_x(event_init.screen_x)
|
||||
, m_screen_y(event_init.screen_y)
|
||||
, m_page_x(page_x)
|
||||
, m_page_y(page_y)
|
||||
, m_client_x(event_init.client_x)
|
||||
, m_client_y(event_init.client_y)
|
||||
, m_offset_x(offset_x)
|
||||
, m_offset_y(offset_y)
|
||||
, m_ctrl_key(event_init.ctrl_key)
|
||||
, m_shift_key(event_init.shift_key)
|
||||
, m_alt_key(event_init.alt_key)
|
||||
, m_meta_key(event_init.meta_key)
|
||||
, m_modifier_alt_graph(event_init.modifier_alt_graph)
|
||||
, m_modifier_caps_lock(event_init.modifier_caps_lock)
|
||||
, m_modifier_fn(event_init.modifier_fn)
|
||||
, m_modifier_fn_lock(event_init.modifier_fn_lock)
|
||||
, m_modifier_hyper(event_init.modifier_hyper)
|
||||
, m_modifier_num_lock(event_init.modifier_num_lock)
|
||||
, m_modifier_scroll_lock(event_init.modifier_scroll_lock)
|
||||
, m_modifier_super(event_init.modifier_super)
|
||||
, m_modifier_symbol(event_init.modifier_symbol)
|
||||
, m_modifier_symbol_lock(event_init.modifier_symbol_lock)
|
||||
, m_movement_x(event_init.movement_x)
|
||||
, m_movement_y(event_init.movement_y)
|
||||
, m_button(event_init.button)
|
||||
, m_buttons(event_init.buttons)
|
||||
, m_related_target(event_init.related_target)
|
||||
{
|
||||
}
|
||||
|
||||
MouseEvent::~MouseEvent() = default;
|
||||
|
||||
void MouseEvent::initialize(JS::Realm& realm)
|
||||
{
|
||||
Base::initialize(realm);
|
||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(MouseEvent);
|
||||
}
|
||||
|
||||
void MouseEvent::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_related_target);
|
||||
}
|
||||
|
||||
bool MouseEvent::get_modifier_state(String const& key_arg) const
|
||||
{
|
||||
if (key_arg == "Control")
|
||||
return m_ctrl_key;
|
||||
if (key_arg == "Shift")
|
||||
return m_shift_key;
|
||||
if (key_arg == "Alt")
|
||||
return m_alt_key;
|
||||
if (key_arg == "Meta")
|
||||
return m_meta_key;
|
||||
if (key_arg == "AltGraph")
|
||||
return m_modifier_alt_graph;
|
||||
if (key_arg == "CapsLock")
|
||||
return m_modifier_caps_lock;
|
||||
if (key_arg == "Fn")
|
||||
return m_modifier_fn;
|
||||
if (key_arg == "FnLock")
|
||||
return m_modifier_fn_lock;
|
||||
if (key_arg == "Hyper")
|
||||
return m_modifier_hyper;
|
||||
if (key_arg == "NumLock")
|
||||
return m_modifier_num_lock;
|
||||
if (key_arg == "ScrollLock")
|
||||
return m_modifier_scroll_lock;
|
||||
if (key_arg == "Super")
|
||||
return m_modifier_super;
|
||||
if (key_arg == "Symbol")
|
||||
return m_modifier_symbol;
|
||||
if (key_arg == "SymbolLock")
|
||||
return m_modifier_symbol_lock;
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/uievents/#dom-mouseevent-initmouseevent
|
||||
void MouseEvent::init_mouse_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, WebIDL::Long detail, WebIDL::Long screen_x, WebIDL::Long screen_y, WebIDL::Long client_x, WebIDL::Long client_y, bool ctrl_key, bool alt_key, bool shift_key, bool meta_key, WebIDL::Short button, DOM::EventTarget* related_target)
|
||||
{
|
||||
// Initializes attributes of a MouseEvent object. This method has the same behavior as UIEvent.initUIEvent().
|
||||
|
||||
// 1. If this’s dispatch flag is set, then return.
|
||||
if (dispatched())
|
||||
return;
|
||||
|
||||
// 2. Initialize this with type, bubbles, and cancelable.
|
||||
initialize_event(type, bubbles, cancelable);
|
||||
|
||||
// Implementation Defined: Initialise other values.
|
||||
m_view = view;
|
||||
m_detail = detail;
|
||||
m_screen_x = screen_x;
|
||||
m_screen_y = screen_y;
|
||||
m_client_x = client_x;
|
||||
m_client_y = client_y;
|
||||
m_ctrl_key = ctrl_key;
|
||||
m_shift_key = shift_key;
|
||||
m_alt_key = alt_key;
|
||||
m_meta_key = meta_key;
|
||||
m_button = button;
|
||||
m_related_target = related_target;
|
||||
}
|
||||
|
||||
JS::NonnullGCPtr<MouseEvent> MouseEvent::create(JS::Realm& realm, FlyString const& event_name, MouseEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y)
|
||||
{
|
||||
return realm.heap().allocate<MouseEvent>(realm, realm, event_name, event_init, page_x, page_y, offset_x, offset_y);
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<MouseEvent>> MouseEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, MouseEventInit const& event_init)
|
||||
{
|
||||
return create(realm, event_name, event_init);
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<MouseEvent>> MouseEvent::create_from_platform_event(JS::Realm& realm, FlyString const& event_name, CSSPixelPoint screen, CSSPixelPoint page, CSSPixelPoint client, CSSPixelPoint offset, Optional<CSSPixelPoint> movement, unsigned button, unsigned buttons, unsigned modifiers)
|
||||
{
|
||||
MouseEventInit event_init {};
|
||||
event_init.ctrl_key = modifiers & Mod_Ctrl;
|
||||
event_init.shift_key = modifiers & Mod_Shift;
|
||||
event_init.alt_key = modifiers & Mod_Alt;
|
||||
event_init.meta_key = modifiers & Mod_Super;
|
||||
event_init.screen_x = screen.x().to_double();
|
||||
event_init.screen_y = screen.y().to_double();
|
||||
event_init.client_x = client.x().to_double();
|
||||
event_init.client_y = client.y().to_double();
|
||||
if (movement.has_value()) {
|
||||
event_init.movement_x = movement.value().x().to_double();
|
||||
event_init.movement_y = movement.value().y().to_double();
|
||||
}
|
||||
event_init.button = mouse_button_to_button_code(static_cast<MouseButton>(button));
|
||||
event_init.buttons = buttons;
|
||||
auto event = MouseEvent::create(realm, event_name, event_init, page.x().to_double(), page.y().to_double(), offset.x().to_double(), offset.y().to_double());
|
||||
event->set_is_trusted(true);
|
||||
event->set_bubbles(true);
|
||||
event->set_cancelable(true);
|
||||
event->set_composed(true);
|
||||
return event;
|
||||
}
|
||||
|
||||
}
|
127
Libraries/LibWeb/UIEvents/MouseEvent.h
Normal file
127
Libraries/LibWeb/UIEvents/MouseEvent.h
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Andreas Kling <andreas@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/TypeCasts.h>
|
||||
#include <LibWeb/PixelUnits.h>
|
||||
#include <LibWeb/UIEvents/EventModifier.h>
|
||||
#include <LibWeb/UIEvents/UIEvent.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
struct MouseEventInit : public EventModifierInit {
|
||||
double screen_x = 0;
|
||||
double screen_y = 0;
|
||||
double client_x = 0;
|
||||
double client_y = 0;
|
||||
double movement_x = 0;
|
||||
double movement_y = 0;
|
||||
i16 button = 0;
|
||||
u16 buttons = 0;
|
||||
JS::GCPtr<DOM::EventTarget> related_target = nullptr;
|
||||
};
|
||||
|
||||
class MouseEvent : public UIEvent {
|
||||
WEB_PLATFORM_OBJECT(MouseEvent, UIEvent);
|
||||
JS_DECLARE_ALLOCATOR(MouseEvent);
|
||||
|
||||
public:
|
||||
[[nodiscard]] static JS::NonnullGCPtr<MouseEvent> create(JS::Realm&, FlyString const& event_name, MouseEventInit const& = {}, double page_x = 0, double page_y = 0, double offset_x = 0, double offset_y = 0);
|
||||
static WebIDL::ExceptionOr<JS::NonnullGCPtr<MouseEvent>> create_from_platform_event(JS::Realm&, FlyString const& event_name, CSSPixelPoint screen, CSSPixelPoint page, CSSPixelPoint client, CSSPixelPoint offset, Optional<CSSPixelPoint> movement, unsigned button, unsigned buttons, unsigned modifiers);
|
||||
static WebIDL::ExceptionOr<JS::NonnullGCPtr<MouseEvent>> construct_impl(JS::Realm&, FlyString const& event_name, MouseEventInit const&);
|
||||
|
||||
virtual ~MouseEvent() override;
|
||||
|
||||
double screen_x() const { return m_screen_x; }
|
||||
double screen_y() const { return m_screen_y; }
|
||||
|
||||
double page_x() const { return m_page_x; }
|
||||
double page_y() const { return m_page_y; }
|
||||
|
||||
double client_x() const { return m_client_x; }
|
||||
double client_y() const { return m_client_y; }
|
||||
|
||||
double x() const { return client_x(); }
|
||||
double y() const { return client_y(); }
|
||||
|
||||
double offset_x() const { return m_offset_x; }
|
||||
double offset_y() const { return m_offset_y; }
|
||||
|
||||
bool ctrl_key() const { return m_ctrl_key; }
|
||||
bool shift_key() const { return m_shift_key; }
|
||||
bool alt_key() const { return m_alt_key; }
|
||||
bool meta_key() const { return m_meta_key; }
|
||||
|
||||
bool platform_ctrl_key() const
|
||||
{
|
||||
#if defined(AK_OS_MACOS)
|
||||
return meta_key();
|
||||
#else
|
||||
return ctrl_key();
|
||||
#endif
|
||||
}
|
||||
|
||||
double movement_x() const { return m_movement_x; }
|
||||
double movement_y() const { return m_movement_y; }
|
||||
|
||||
i16 button() const { return m_button; }
|
||||
u16 buttons() const { return m_buttons; }
|
||||
|
||||
JS::GCPtr<DOM::EventTarget> related_target() const { return m_related_target; }
|
||||
|
||||
bool get_modifier_state(String const& key_arg) const;
|
||||
|
||||
virtual u32 which() const override { return m_button + 1; }
|
||||
|
||||
void init_mouse_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, WebIDL::Long detail, WebIDL::Long screen_x, WebIDL::Long screen_y, WebIDL::Long client_x, WebIDL::Long client_y, bool ctrl_key, bool alt_key, bool shift_key, bool meta_key, WebIDL::Short button, DOM::EventTarget* related_target);
|
||||
|
||||
protected:
|
||||
MouseEvent(JS::Realm&, FlyString const& event_name, MouseEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y);
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
private:
|
||||
virtual bool is_mouse_event() const override { return true; }
|
||||
|
||||
double m_screen_x { 0 };
|
||||
double m_screen_y { 0 };
|
||||
double m_page_x { 0 };
|
||||
double m_page_y { 0 };
|
||||
double m_client_x { 0 };
|
||||
double m_client_y { 0 };
|
||||
double m_offset_x { 0 };
|
||||
double m_offset_y { 0 };
|
||||
bool m_ctrl_key { false };
|
||||
bool m_shift_key { false };
|
||||
bool m_alt_key { false };
|
||||
bool m_meta_key { false };
|
||||
bool m_modifier_alt_graph { false };
|
||||
bool m_modifier_caps_lock { false };
|
||||
bool m_modifier_fn { false };
|
||||
bool m_modifier_fn_lock { false };
|
||||
bool m_modifier_hyper { false };
|
||||
bool m_modifier_num_lock { false };
|
||||
bool m_modifier_scroll_lock { false };
|
||||
bool m_modifier_super { false };
|
||||
bool m_modifier_symbol { false };
|
||||
bool m_modifier_symbol_lock { false };
|
||||
double m_movement_x { 0 };
|
||||
double m_movement_y { 0 };
|
||||
i16 m_button { 0 };
|
||||
u16 m_buttons { 0 };
|
||||
JS::GCPtr<DOM::EventTarget> m_related_target { nullptr };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Web::DOM {
|
||||
|
||||
template<>
|
||||
inline bool Event::fast_is<UIEvents::MouseEvent>() const { return is_mouse_event(); }
|
||||
|
||||
}
|
55
Libraries/LibWeb/UIEvents/MouseEvent.idl
Normal file
55
Libraries/LibWeb/UIEvents/MouseEvent.idl
Normal file
|
@ -0,0 +1,55 @@
|
|||
#import <UIEvents/EventModifier.idl>
|
||||
|
||||
// https://w3c.github.io/uievents/#mouseevent
|
||||
[Exposed=Window]
|
||||
interface MouseEvent : UIEvent {
|
||||
constructor(DOMString type, optional MouseEventInit eventInitDict = {});
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#extensions-to-the-mouseevent-interface
|
||||
readonly attribute double screenX;
|
||||
readonly attribute double screenY;
|
||||
readonly attribute double pageX;
|
||||
readonly attribute double pageY;
|
||||
readonly attribute double clientX;
|
||||
readonly attribute double clientY;
|
||||
readonly attribute double x;
|
||||
readonly attribute double y;
|
||||
readonly attribute double offsetX;
|
||||
readonly attribute double offsetY;
|
||||
|
||||
readonly attribute boolean ctrlKey;
|
||||
readonly attribute boolean shiftKey;
|
||||
readonly attribute boolean altKey;
|
||||
readonly attribute boolean metaKey;
|
||||
|
||||
// https://w3c.github.io/pointerlock/#extensions-to-the-mouseevent-interface
|
||||
readonly attribute double movementX;
|
||||
readonly attribute double movementY;
|
||||
|
||||
readonly attribute short button;
|
||||
readonly attribute unsigned short buttons;
|
||||
|
||||
readonly attribute EventTarget? relatedTarget;
|
||||
|
||||
boolean getModifierState(DOMString keyArg);
|
||||
|
||||
// https://w3c.github.io/uievents/#dom-mouseevent-initmouseevent
|
||||
undefined initMouseEvent(DOMString typeArg, optional boolean bubblesArg = false, optional boolean cancelableArg = false, optional Window? viewArg = null, optional long detailArg = 0, optional long screenXArg = 0, optional long screenYArg = 0, optional long clientXArg = 0, optional long clientYArg = 0, optional boolean ctrlKeyArg = false, optional boolean altKeyArg = false, optional boolean shiftKeyArg = false, optional boolean metaKeyArg = false, optional short buttonArg = 0, optional EventTarget? relatedTargetArg = null);
|
||||
};
|
||||
|
||||
// https://w3c.github.io/uievents/#idl-mouseeventinit
|
||||
dictionary MouseEventInit : EventModifierInit {
|
||||
// https://drafts.csswg.org/cssom-view/#extensions-to-the-mouseevent-interface
|
||||
double screenX = 0;
|
||||
double screenY = 0;
|
||||
double clientX = 0;
|
||||
double clientY = 0;
|
||||
|
||||
// https://w3c.github.io/pointerlock/#extensions-to-the-mouseeventinit-dictionary
|
||||
double movementX = 0;
|
||||
double movementY = 0;
|
||||
|
||||
short button = 0;
|
||||
unsigned short buttons = 0;
|
||||
EventTarget? relatedTarget = null;
|
||||
};
|
64
Libraries/LibWeb/UIEvents/PointerEvent.cpp
Normal file
64
Libraries/LibWeb/UIEvents/PointerEvent.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Shannon Booth <shannon@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/PointerEventPrototype.h>
|
||||
#include <LibWeb/UIEvents/PointerEvent.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
JS_DEFINE_ALLOCATOR(PointerEvent);
|
||||
|
||||
PointerEvent::PointerEvent(JS::Realm& realm, FlyString const& type, PointerEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y)
|
||||
: MouseEvent(realm, type, event_init, page_x, page_y, offset_x, offset_y)
|
||||
, m_pointer_id(event_init.pointer_id)
|
||||
, m_width(event_init.width)
|
||||
, m_height(event_init.height)
|
||||
, m_pressure(event_init.pressure)
|
||||
, m_tangential_pressure(event_init.tangential_pressure)
|
||||
, m_tilt_x(event_init.tilt_x.value_or(0))
|
||||
, m_tilt_y(event_init.tilt_y.value_or(0))
|
||||
, m_twist(event_init.twist)
|
||||
, m_altitude_angle(event_init.altitude_angle.value_or(DEFAULT_ALTITUDE_ANGLE))
|
||||
, m_azimuth_angle(event_init.azimuth_angle.value_or(0))
|
||||
, m_pointer_type(event_init.pointer_type)
|
||||
, m_is_primary(event_init.is_primary)
|
||||
, m_persistent_device_id(event_init.persistent_device_id)
|
||||
{
|
||||
m_coalesced_events.ensure_capacity(event_init.coalesced_events.size());
|
||||
for (auto const& coalesced_event : event_init.coalesced_events)
|
||||
m_coalesced_events.unchecked_append(*coalesced_event);
|
||||
|
||||
m_predicted_events.ensure_capacity(event_init.predicted_events.size());
|
||||
for (auto const& predicted_event : event_init.predicted_events)
|
||||
m_predicted_events.unchecked_append(*predicted_event);
|
||||
}
|
||||
|
||||
PointerEvent::~PointerEvent() = default;
|
||||
|
||||
void PointerEvent::initialize(JS::Realm& realm)
|
||||
{
|
||||
Base::initialize(realm);
|
||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(PointerEvent);
|
||||
}
|
||||
|
||||
void PointerEvent::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_coalesced_events);
|
||||
visitor.visit(m_predicted_events);
|
||||
}
|
||||
|
||||
JS::NonnullGCPtr<PointerEvent> PointerEvent::create(JS::Realm& realm, FlyString const& type, PointerEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y)
|
||||
{
|
||||
return realm.heap().allocate<PointerEvent>(realm, realm, type, event_init, page_x, page_y, offset_x, offset_y);
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<PointerEvent>> PointerEvent::construct_impl(JS::Realm& realm, FlyString const& type, PointerEventInit const& event_init)
|
||||
{
|
||||
return create(realm, type, event_init);
|
||||
}
|
||||
|
||||
}
|
148
Libraries/LibWeb/UIEvents/PointerEvent.h
Normal file
148
Libraries/LibWeb/UIEvents/PointerEvent.h
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Shannon Booth <shannon@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/UIEvents/MouseEvent.h>
|
||||
#include <LibWeb/WebIDL/Types.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
struct PointerEventInit : public MouseEventInit {
|
||||
WebIDL::Long pointer_id { 0 };
|
||||
double width { 1 };
|
||||
double height { 1 };
|
||||
float pressure { 0 };
|
||||
float tangential_pressure { 0 };
|
||||
Optional<WebIDL::Long> tilt_x;
|
||||
Optional<WebIDL::Long> tilt_y;
|
||||
WebIDL::Long twist { 0 };
|
||||
Optional<double> altitude_angle;
|
||||
Optional<double> azimuth_angle;
|
||||
String pointer_type;
|
||||
bool is_primary { false };
|
||||
WebIDL::Long persistent_device_id { 0 };
|
||||
AK::Vector<JS::Handle<PointerEvent>> coalesced_events;
|
||||
AK::Vector<JS::Handle<PointerEvent>> predicted_events;
|
||||
};
|
||||
|
||||
// https://w3c.github.io/pointerevents/#pointerevent-interface
|
||||
class PointerEvent : public MouseEvent {
|
||||
WEB_PLATFORM_OBJECT(PointerEvent, MouseEvent);
|
||||
JS_DECLARE_ALLOCATOR(PointerEvent);
|
||||
|
||||
public:
|
||||
[[nodiscard]] static JS::NonnullGCPtr<PointerEvent> create(JS::Realm&, FlyString const& type, PointerEventInit const& = {}, double page_x = 0, double page_y = 0, double offset_x = 0, double offset_y = 0);
|
||||
static WebIDL::ExceptionOr<JS::NonnullGCPtr<PointerEvent>> construct_impl(JS::Realm&, FlyString const& type, PointerEventInit const&);
|
||||
|
||||
virtual ~PointerEvent() override;
|
||||
|
||||
WebIDL::Long pointer_id() const { return m_pointer_id; }
|
||||
double width() const { return m_width; }
|
||||
double height() const { return m_height; }
|
||||
float pressure() const { return m_pressure; }
|
||||
float tangential_pressure() const { return m_tangential_pressure; }
|
||||
WebIDL::Long tilt_x() const { return m_tilt_x; }
|
||||
WebIDL::Long tilt_y() const { return m_tilt_y; }
|
||||
WebIDL::Long twist() const { return m_twist; }
|
||||
double altitude_angle() const { return m_altitude_angle; }
|
||||
double azimuth_angle() const { return m_azimuth_angle; }
|
||||
String const& pointer_type() const { return m_pointer_type; }
|
||||
bool is_primary() const { return m_is_primary; }
|
||||
WebIDL::Long persistent_device_id() const { return m_persistent_device_id; }
|
||||
AK::ReadonlySpan<JS::NonnullGCPtr<PointerEvent>> get_coalesced_events() const { return m_coalesced_events; }
|
||||
AK::ReadonlySpan<JS::NonnullGCPtr<PointerEvent>> get_predicted_events() const { return m_predicted_events; }
|
||||
|
||||
// https://w3c.github.io/pointerevents/#dom-pointerevent-pressure
|
||||
// For hardware and platforms that do not support pressure, the value MUST be 0.5 when in the active buttons state and 0 otherwise.
|
||||
static constexpr float ACTIVE_PRESSURE_DEFAULT_IN_ACTIVE_BUTTON_STATE { 0.5 };
|
||||
|
||||
protected:
|
||||
PointerEvent(JS::Realm&, FlyString const& type, PointerEventInit const&, double page_x, double page_y, double offset_x, double offset_y);
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
private:
|
||||
virtual bool is_pointer_event() const final { return true; }
|
||||
|
||||
// A unique identifier for the pointer causing the event.
|
||||
// https://w3c.github.io/pointerevents/#dom-pointerevent-pointerid
|
||||
WebIDL::Long m_pointer_id { 0 };
|
||||
|
||||
// The width (magnitude on the X axis), in CSS pixels (see [CSS21]), of the contact geometry of the pointer
|
||||
// https://w3c.github.io/pointerevents/#dom-pointerevent-width
|
||||
double m_width { 1 };
|
||||
|
||||
// The height (magnitude on the Y axis), in CSS pixels (see [CSS21]), of the contact geometry of the pointer.
|
||||
// https://w3c.github.io/pointerevents/#dom-pointerevent-width
|
||||
double m_height { 1 };
|
||||
|
||||
// The normalized pressure of the pointer input in the range of [0,1], where 0 and 1 represent the minimum and
|
||||
// maximum pressure the hardware is capable of detecting, respectively
|
||||
// https://w3c.github.io/pointerevents/#dom-pointerevent-pressure
|
||||
float m_pressure { 0 };
|
||||
|
||||
// The normalized tangential pressure (also known as barrel pressure), typically set by an additional control
|
||||
// (e.g. a finger wheel on an airbrush stylus), of the pointer input in the range of [-1,1], where 0 is the
|
||||
// neutral position of the control
|
||||
// https://w3c.github.io/pointerevents/#dom-pointerevent-tangentialpressure
|
||||
float m_tangential_pressure { 0 };
|
||||
|
||||
// The plane angle (in degrees, in the range of [-90,90]) between the Y-Z plane and the plane containing both the
|
||||
// transducer (e.g. pen/stylus) axis and the Y axis
|
||||
// https://w3c.github.io/pointerevents/#dom-pointerevent-tiltx
|
||||
WebIDL::Long m_tilt_x { 0 };
|
||||
|
||||
// The plane angle (in degrees, in the range of [-90,90]) between the X-Z plane and the plane containing both the
|
||||
// transducer (e.g. pen/stylus) axis and the X axis
|
||||
// https://w3c.github.io/pointerevents/#dom-pointerevent-tilty
|
||||
WebIDL::Long m_tilt_y { 0 };
|
||||
|
||||
// The clockwise rotation (in degrees, in the range of [0,359]) of a transducer (e.g. pen/stylus) around its own major axis
|
||||
// https://w3c.github.io/pointerevents/#dom-pointerevent-twist
|
||||
WebIDL::Long m_twist { 0 };
|
||||
|
||||
// The altitude (in radians) of the transducer (e.g. pen/stylus), in the range [0,π/2] — where 0 is parallel to the surface
|
||||
// (X-Y plane), and π/2 is perpendicular to the surface
|
||||
// For hardware and platforms that do not report tilt or angle, the value MUST be π/2.
|
||||
// https://w3c.github.io/pointerevents/#dom-pointerevent-altitudeangle
|
||||
static constexpr double DEFAULT_ALTITUDE_ANGLE { AK::Pi<double> / 2 };
|
||||
double m_altitude_angle { DEFAULT_ALTITUDE_ANGLE };
|
||||
|
||||
// The azimuth angle (in radians) of the transducer (e.g. pen/stylus), in the range [0, 2π] — where 0 represents a transducer
|
||||
// whose cap is pointing in the direction of increasing X values (point to "3 o'clock" if looking straight down) on the X-Y
|
||||
// plane, and the values progressively increase when going clockwise (π/2 at "6 o'clock", π at "9 o'clock", 3π/2 at "12 o'clock").
|
||||
// https://w3c.github.io/pointerevents/#dom-pointerevent-azimuthangle
|
||||
double m_azimuth_angle { 0 };
|
||||
|
||||
// Indicates the device type that caused the event (mouse, pen, touch, etc.)
|
||||
// https://w3c.github.io/pointerevents/#dom-pointerevent-pointertype
|
||||
String m_pointer_type;
|
||||
|
||||
// Indicates if the pointer represents the primary pointer of this pointer type
|
||||
// https://w3c.github.io/pointerevents/#dom-pointerevent-isprimary
|
||||
bool m_is_primary { false };
|
||||
|
||||
// A unique identifier for the pointing device.
|
||||
// https://w3c.github.io/pointerevents/#dom-pointerevent-persistentdeviceid
|
||||
WebIDL::Long m_persistent_device_id { 0 };
|
||||
|
||||
// https://w3c.github.io/pointerevents/#dom-pointerevent-getcoalescedevents
|
||||
AK::Vector<JS::NonnullGCPtr<PointerEvent>> m_coalesced_events;
|
||||
|
||||
// https://w3c.github.io/pointerevents/#dom-pointerevent-getpredictedevents
|
||||
AK::Vector<JS::NonnullGCPtr<PointerEvent>> m_predicted_events;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Web::DOM {
|
||||
|
||||
template<>
|
||||
inline bool Event::fast_is<UIEvents::PointerEvent>() const { return is_pointer_event(); }
|
||||
|
||||
}
|
41
Libraries/LibWeb/UIEvents/PointerEvent.idl
Normal file
41
Libraries/LibWeb/UIEvents/PointerEvent.idl
Normal file
|
@ -0,0 +1,41 @@
|
|||
#import <UIEvents/MouseEvent.idl>
|
||||
|
||||
// https://w3c.github.io/pointerevents/#ref-for-dom-pointereventinit-1
|
||||
dictionary PointerEventInit : MouseEventInit {
|
||||
long pointerId = 0;
|
||||
double width = 1;
|
||||
double height = 1;
|
||||
float pressure = 0;
|
||||
float tangentialPressure = 0;
|
||||
long tiltX;
|
||||
long tiltY;
|
||||
long twist = 0;
|
||||
double altitudeAngle;
|
||||
double azimuthAngle;
|
||||
DOMString pointerType = "";
|
||||
boolean isPrimary = false;
|
||||
long persistentDeviceId = 0;
|
||||
sequence<PointerEvent> coalescedEvents = [];
|
||||
sequence<PointerEvent> predictedEvents = [];
|
||||
};
|
||||
|
||||
// https://w3c.github.io/pointerevents/#pointerevent-interface
|
||||
[Exposed=Window]
|
||||
interface PointerEvent : MouseEvent {
|
||||
constructor(DOMString type, optional PointerEventInit eventInitDict = {});
|
||||
readonly attribute long pointerId;
|
||||
readonly attribute double width;
|
||||
readonly attribute double height;
|
||||
readonly attribute float pressure;
|
||||
readonly attribute float tangentialPressure;
|
||||
readonly attribute long tiltX;
|
||||
readonly attribute long tiltY;
|
||||
readonly attribute long twist;
|
||||
readonly attribute double altitudeAngle;
|
||||
readonly attribute double azimuthAngle;
|
||||
readonly attribute DOMString pointerType;
|
||||
readonly attribute boolean isPrimary;
|
||||
readonly attribute long persistentDeviceId;
|
||||
[SecureContext] sequence<PointerEvent> getCoalescedEvents();
|
||||
sequence<PointerEvent> getPredictedEvents();
|
||||
};
|
51
Libraries/LibWeb/UIEvents/TextEvent.cpp
Normal file
51
Libraries/LibWeb/UIEvents/TextEvent.cpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/Bindings/TextEventPrototype.h>
|
||||
#include <LibWeb/UIEvents/TextEvent.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
JS_DEFINE_ALLOCATOR(TextEvent);
|
||||
|
||||
JS::NonnullGCPtr<TextEvent> TextEvent::create(JS::Realm& realm, FlyString const& event_name)
|
||||
{
|
||||
return realm.heap().allocate<TextEvent>(realm, realm, event_name);
|
||||
}
|
||||
|
||||
TextEvent::TextEvent(JS::Realm& realm, FlyString const& event_name)
|
||||
: UIEvent(realm, event_name)
|
||||
{
|
||||
}
|
||||
|
||||
TextEvent::~TextEvent() = default;
|
||||
|
||||
void TextEvent::initialize(JS::Realm& realm)
|
||||
{
|
||||
Base::initialize(realm);
|
||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(TextEvent);
|
||||
}
|
||||
|
||||
// https://w3c.github.io/uievents/#dom-textevent-inittextevent
|
||||
void TextEvent::init_text_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, String const& data)
|
||||
{
|
||||
// Initializes attributes of a TextEvent object. This method has the same behavior as UIEvent.initUIEvent().
|
||||
// The value of detail remains undefined.
|
||||
|
||||
// 1. If this’s dispatch flag is set, then return.
|
||||
if (dispatched())
|
||||
return;
|
||||
|
||||
// 2. Initialize this with type, bubbles, and cancelable.
|
||||
initialize_event(type, bubbles, cancelable);
|
||||
|
||||
// Implementation Defined: Initialise other values.
|
||||
m_view = view;
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
}
|
35
Libraries/LibWeb/UIEvents/TextEvent.h
Normal file
35
Libraries/LibWeb/UIEvents/TextEvent.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Jamie Mansfield <jmansfield@cadixdev.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/UIEvents/UIEvent.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
class TextEvent final : public UIEvent {
|
||||
WEB_PLATFORM_OBJECT(TextEvent, UIEvent);
|
||||
JS_DECLARE_ALLOCATOR(TextEvent);
|
||||
|
||||
public:
|
||||
[[nodiscard]] static JS::NonnullGCPtr<TextEvent> create(JS::Realm&, FlyString const& event_name);
|
||||
|
||||
virtual ~TextEvent() override;
|
||||
|
||||
// https://w3c.github.io/uievents/#dom-textevent-data
|
||||
String data() const { return m_data; }
|
||||
|
||||
void init_text_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, String const& data);
|
||||
|
||||
private:
|
||||
TextEvent(JS::Realm&, FlyString const& event_name);
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
|
||||
String m_data;
|
||||
};
|
||||
|
||||
}
|
8
Libraries/LibWeb/UIEvents/TextEvent.idl
Normal file
8
Libraries/LibWeb/UIEvents/TextEvent.idl
Normal file
|
@ -0,0 +1,8 @@
|
|||
#import <UIEvents/UIEvent.idl>
|
||||
|
||||
// https://w3c.github.io/uievents/#textevent
|
||||
[Exposed=Window]
|
||||
interface TextEvent : UIEvent {
|
||||
readonly attribute DOMString data;
|
||||
undefined initTextEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false, optional Window? view = null, optional DOMString data = "undefined");
|
||||
};
|
51
Libraries/LibWeb/UIEvents/UIEvent.cpp
Normal file
51
Libraries/LibWeb/UIEvents/UIEvent.cpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <andreas@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/Bindings/UIEventPrototype.h>
|
||||
#include <LibWeb/UIEvents/UIEvent.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
JS_DEFINE_ALLOCATOR(UIEvent);
|
||||
|
||||
JS::NonnullGCPtr<UIEvent> UIEvent::create(JS::Realm& realm, FlyString const& event_name)
|
||||
{
|
||||
return realm.heap().allocate<UIEvent>(realm, realm, event_name);
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<UIEvent>> UIEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, UIEventInit const& event_init)
|
||||
{
|
||||
return realm.heap().allocate<UIEvent>(realm, realm, event_name, event_init);
|
||||
}
|
||||
|
||||
UIEvent::UIEvent(JS::Realm& realm, FlyString const& event_name)
|
||||
: Event(realm, event_name)
|
||||
{
|
||||
}
|
||||
|
||||
UIEvent::UIEvent(JS::Realm& realm, FlyString const& event_name, UIEventInit const& event_init)
|
||||
: Event(realm, event_name, event_init)
|
||||
, m_view(event_init.view)
|
||||
, m_detail(event_init.detail)
|
||||
{
|
||||
}
|
||||
|
||||
UIEvent::~UIEvent() = default;
|
||||
|
||||
void UIEvent::initialize(JS::Realm& realm)
|
||||
{
|
||||
Base::initialize(realm);
|
||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(UIEvent);
|
||||
}
|
||||
|
||||
void UIEvent::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_view);
|
||||
}
|
||||
|
||||
}
|
61
Libraries/LibWeb/UIEvents/UIEvent.h
Normal file
61
Libraries/LibWeb/UIEvents/UIEvent.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2022, Andreas Kling <andreas@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/RefPtr.h>
|
||||
#include <LibWeb/DOM/Event.h>
|
||||
#include <LibWeb/HTML/Window.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
struct UIEventInit : public DOM::EventInit {
|
||||
JS::GCPtr<HTML::Window> view;
|
||||
int detail { 0 };
|
||||
};
|
||||
|
||||
class UIEvent : public DOM::Event {
|
||||
WEB_PLATFORM_OBJECT(UIEvent, DOM::Event);
|
||||
JS_DECLARE_ALLOCATOR(UIEvent);
|
||||
|
||||
public:
|
||||
[[nodiscard]] static JS::NonnullGCPtr<UIEvent> create(JS::Realm&, FlyString const& type);
|
||||
static WebIDL::ExceptionOr<JS::NonnullGCPtr<UIEvent>> construct_impl(JS::Realm&, FlyString const& event_name, UIEventInit const& event_init);
|
||||
|
||||
virtual ~UIEvent() override;
|
||||
|
||||
HTML::Window const* view() const { return m_view.ptr(); }
|
||||
int detail() const { return m_detail; }
|
||||
virtual u32 which() const { return 0; }
|
||||
|
||||
void init_ui_event(String const& type, bool bubbles, bool cancelable, HTML::Window* view, int detail)
|
||||
{
|
||||
// Initializes attributes of an UIEvent object. This method has the same behavior as initEvent().
|
||||
|
||||
// 1. If this’s dispatch flag is set, then return.
|
||||
if (dispatched())
|
||||
return;
|
||||
|
||||
// 2. Initialize this with type, bubbles, and cancelable.
|
||||
initialize_event(type, bubbles, cancelable);
|
||||
|
||||
// Implementation Defined: Initialise other values.
|
||||
m_view = view;
|
||||
m_detail = detail;
|
||||
}
|
||||
|
||||
protected:
|
||||
UIEvent(JS::Realm&, FlyString const& event_name);
|
||||
UIEvent(JS::Realm&, FlyString const& event_name, UIEventInit const& event_init);
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
JS::GCPtr<HTML::Window> m_view;
|
||||
int m_detail { 0 };
|
||||
};
|
||||
|
||||
}
|
20
Libraries/LibWeb/UIEvents/UIEvent.idl
Normal file
20
Libraries/LibWeb/UIEvents/UIEvent.idl
Normal file
|
@ -0,0 +1,20 @@
|
|||
#import <DOM/Event.idl>
|
||||
#import <HTML/Window.idl>
|
||||
|
||||
// https://w3c.github.io/uievents/#uievent
|
||||
[Exposed=Window]
|
||||
interface UIEvent : Event {
|
||||
constructor(DOMString type, optional UIEventInit eventInitDict = {});
|
||||
readonly attribute Window? view;
|
||||
readonly attribute long detail;
|
||||
|
||||
// Obsolete
|
||||
[ImplementedAs=init_ui_event] undefined initUIEvent(DOMString typeArg, optional boolean bubblesArg = false, optional boolean cancelableArg = false, optional Window? viewArg = null, optional long detailArg = 0);
|
||||
readonly attribute unsigned long which;
|
||||
};
|
||||
|
||||
// https://w3c.github.io/uievents/#idl-uieventinit
|
||||
dictionary UIEventInit : EventInit {
|
||||
Window? view = null;
|
||||
long detail = 0;
|
||||
};
|
70
Libraries/LibWeb/UIEvents/WheelEvent.cpp
Normal file
70
Libraries/LibWeb/UIEvents/WheelEvent.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/Bindings/WheelEventPrototype.h>
|
||||
#include <LibWeb/HTML/EventNames.h>
|
||||
#include <LibWeb/UIEvents/EventNames.h>
|
||||
#include <LibWeb/UIEvents/KeyCode.h>
|
||||
#include <LibWeb/UIEvents/WheelEvent.h>
|
||||
#include <LibWeb/WebIDL/ExceptionOr.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
JS_DEFINE_ALLOCATOR(WheelEvent);
|
||||
|
||||
WheelEvent::WheelEvent(JS::Realm& realm, FlyString const& event_name, WheelEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y)
|
||||
: MouseEvent(realm, event_name, event_init, page_x, page_y, offset_x, offset_y)
|
||||
, m_delta_x(event_init.delta_x)
|
||||
, m_delta_y(event_init.delta_y)
|
||||
, m_delta_z(event_init.delta_z)
|
||||
, m_delta_mode(event_init.delta_mode)
|
||||
{
|
||||
}
|
||||
|
||||
WheelEvent::~WheelEvent() = default;
|
||||
|
||||
void WheelEvent::initialize(JS::Realm& realm)
|
||||
{
|
||||
Base::initialize(realm);
|
||||
WEB_SET_PROTOTYPE_FOR_INTERFACE(WheelEvent);
|
||||
}
|
||||
|
||||
JS::NonnullGCPtr<WheelEvent> WheelEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, WheelEventInit const& wheel_event_init)
|
||||
{
|
||||
return create(realm, event_name, wheel_event_init);
|
||||
}
|
||||
|
||||
JS::NonnullGCPtr<WheelEvent> WheelEvent::create(JS::Realm& realm, FlyString const& event_name, WheelEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y)
|
||||
{
|
||||
return realm.heap().allocate<WheelEvent>(realm, realm, event_name, event_init, page_x, page_y, offset_x, offset_y);
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<WheelEvent>> WheelEvent::create_from_platform_event(JS::Realm& realm, FlyString const& event_name, CSSPixelPoint screen, CSSPixelPoint page, CSSPixelPoint client, CSSPixelPoint offset, double delta_x, double delta_y, unsigned button, unsigned buttons, unsigned modifiers)
|
||||
{
|
||||
WheelEventInit event_init {};
|
||||
event_init.ctrl_key = modifiers & Mod_Ctrl;
|
||||
event_init.shift_key = modifiers & Mod_Shift;
|
||||
event_init.alt_key = modifiers & Mod_Alt;
|
||||
event_init.meta_key = modifiers & Mod_Super;
|
||||
event_init.screen_x = screen.x().to_double();
|
||||
event_init.screen_y = screen.y().to_double();
|
||||
event_init.client_x = client.x().to_double();
|
||||
event_init.client_y = client.y().to_double();
|
||||
event_init.button = button;
|
||||
event_init.buttons = buttons;
|
||||
event_init.delta_x = delta_x;
|
||||
event_init.delta_y = delta_y;
|
||||
event_init.delta_mode = WheelDeltaMode::DOM_DELTA_PIXEL;
|
||||
auto event = WheelEvent::create(realm, event_name, event_init, page.x().to_double(), page.y().to_double(), offset.x().to_double(), offset.y().to_double());
|
||||
event->set_is_trusted(true);
|
||||
event->set_bubbles(true);
|
||||
event->set_cancelable(true);
|
||||
event->set_composed(true);
|
||||
return event;
|
||||
}
|
||||
|
||||
}
|
57
Libraries/LibWeb/UIEvents/WheelEvent.h
Normal file
57
Libraries/LibWeb/UIEvents/WheelEvent.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/UIEvents/MouseEvent.h>
|
||||
#include <LibWeb/UIEvents/UIEvent.h>
|
||||
#include <LibWeb/WebIDL/Types.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
enum WheelDeltaMode : WebIDL::UnsignedLong {
|
||||
DOM_DELTA_PIXEL = 0,
|
||||
DOM_DELTA_LINE = 1,
|
||||
DOM_DELTA_PAGE = 2,
|
||||
};
|
||||
|
||||
struct WheelEventInit : public MouseEventInit {
|
||||
double delta_x = 0;
|
||||
double delta_y = 0;
|
||||
double delta_z = 0;
|
||||
|
||||
WebIDL::UnsignedLong delta_mode = WheelDeltaMode::DOM_DELTA_PIXEL;
|
||||
};
|
||||
|
||||
class WheelEvent final : public MouseEvent {
|
||||
WEB_PLATFORM_OBJECT(WheelEvent, MouseEvent);
|
||||
JS_DECLARE_ALLOCATOR(WheelEvent);
|
||||
|
||||
public:
|
||||
[[nodiscard]] static JS::NonnullGCPtr<WheelEvent> create(JS::Realm&, FlyString const& event_name, WheelEventInit const& = {}, double page_x = 0, double page_y = 0, double offset_x = 0, double offset_y = 0);
|
||||
[[nodiscard]] static JS::NonnullGCPtr<WheelEvent> construct_impl(JS::Realm&, FlyString const& event_name, WheelEventInit const& = {});
|
||||
|
||||
static WebIDL::ExceptionOr<JS::NonnullGCPtr<WheelEvent>> create_from_platform_event(JS::Realm&, FlyString const& event_name, CSSPixelPoint screen, CSSPixelPoint page, CSSPixelPoint client, CSSPixelPoint offset, double delta_x, double delta_y, unsigned button, unsigned buttons, unsigned modifiers);
|
||||
|
||||
virtual ~WheelEvent() override;
|
||||
|
||||
double delta_x() const { return m_delta_x; }
|
||||
double delta_y() const { return m_delta_y; }
|
||||
double delta_z() const { return m_delta_z; }
|
||||
WebIDL::UnsignedLong delta_mode() const { return m_delta_mode; }
|
||||
|
||||
private:
|
||||
WheelEvent(JS::Realm&, FlyString const& event_name, WheelEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y);
|
||||
|
||||
virtual void initialize(JS::Realm&) override;
|
||||
|
||||
double m_delta_x { 0 };
|
||||
double m_delta_y { 0 };
|
||||
double m_delta_z { 0 };
|
||||
WebIDL::UnsignedLong m_delta_mode { WheelDeltaMode::DOM_DELTA_PIXEL };
|
||||
};
|
||||
|
||||
}
|
25
Libraries/LibWeb/UIEvents/WheelEvent.idl
Normal file
25
Libraries/LibWeb/UIEvents/WheelEvent.idl
Normal file
|
@ -0,0 +1,25 @@
|
|||
#import <UIEvents/MouseEvent.idl>
|
||||
|
||||
// https://www.w3.org/TR/uievents/#idl-wheelevent
|
||||
[Exposed=Window]
|
||||
interface WheelEvent : MouseEvent {
|
||||
constructor(DOMString type, optional WheelEventInit eventInitDict = {});
|
||||
|
||||
// DeltaModeCode
|
||||
const unsigned long DOM_DELTA_PIXEL = 0x00;
|
||||
const unsigned long DOM_DELTA_LINE = 0x01;
|
||||
const unsigned long DOM_DELTA_PAGE = 0x02;
|
||||
|
||||
readonly attribute double deltaX;
|
||||
readonly attribute double deltaY;
|
||||
readonly attribute double deltaZ;
|
||||
readonly attribute unsigned long deltaMode;
|
||||
};
|
||||
|
||||
// https://www.w3.org/TR/uievents/#idl-wheeleventinit
|
||||
dictionary WheelEventInit : MouseEventInit {
|
||||
double deltaX = 0;
|
||||
double deltaY = 0;
|
||||
double deltaZ = 0;
|
||||
unsigned long deltaMode = 0;
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue