summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp
blob: 071e26bb9bede5470e87067f4cc93032cba9b3c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * Copyright (c) 2021-2022, Andreas Kling <kling@serenityos.org>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#include <AK/CharacterTypes.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/UIEvents/KeyboardEvent.h>

namespace Web::UIEvents {

// 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;

    // 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_Shift:
        return 16;
    case KeyCode::Key_Control:
        return 17;
    case KeyCode::Key_Alt:
        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;
    }

    // Return the virtual key code from the operating system.
    return platform_key;
}

KeyboardEvent* KeyboardEvent::create_from_platform_event(JS::Realm& realm, FlyString const& event_name, KeyCode platform_key, unsigned modifiers, u32 code_point)
{
    // FIXME: Figure out what these should actually contain.
    String event_key = key_code_to_string(platform_key);
    String event_code = "FIXME";

    auto key_code = determine_key_code(platform_key, code_point);
    KeyboardEventInit event_init {};
    event_init.key = move(event_key);
    event_init.code = move(event_code);
    event_init.location = 0;
    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 = false;
    event_init.repeat = false;
    event_init.is_composing = false;
    event_init.key_code = key_code;
    event_init.char_code = code_point;
    event_init.bubbles = true;
    event_init.cancelable = true;
    event_init.composed = true;
    return KeyboardEvent::create(realm, event_name, event_init);
}

bool KeyboardEvent::get_modifier_state(String const& key_arg)
{
    if (key_arg == "Alt")
        return m_alt_key;
    if (key_arg == "Control")
        return m_ctrl_key;
    if (key_arg == "Shift")
        return m_shift_key;
    if (key_arg == "Meta")
        return m_meta_key;
    return false;
}

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);
}

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_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)
{
    set_prototype(&Bindings::cached_web_prototype(realm, "KeyboardEvent"));
}

KeyboardEvent::~KeyboardEvent() = default;

}