/src/serenity/Userland/Libraries/LibWeb/UIEvents/MouseEvent.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2020, the SerenityOS developers. |
3 | | * Copyright (c) 2022, Andreas Kling <kling@serenityos.org> |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #include <LibWeb/Bindings/Intrinsics.h> |
9 | | #include <LibWeb/Bindings/MouseEventPrototype.h> |
10 | | #include <LibWeb/HTML/EventNames.h> |
11 | | #include <LibWeb/UIEvents/EventNames.h> |
12 | | #include <LibWeb/UIEvents/KeyCode.h> |
13 | | #include <LibWeb/UIEvents/MouseButton.h> |
14 | | #include <LibWeb/UIEvents/MouseEvent.h> |
15 | | |
16 | | namespace Web::UIEvents { |
17 | | |
18 | | JS_DEFINE_ALLOCATOR(MouseEvent); |
19 | | |
20 | | 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) |
21 | 0 | : UIEvent(realm, event_name, event_init) |
22 | 0 | , m_screen_x(event_init.screen_x) |
23 | 0 | , m_screen_y(event_init.screen_y) |
24 | 0 | , m_page_x(page_x) |
25 | 0 | , m_page_y(page_y) |
26 | 0 | , m_client_x(event_init.client_x) |
27 | 0 | , m_client_y(event_init.client_y) |
28 | 0 | , m_offset_x(offset_x) |
29 | 0 | , m_offset_y(offset_y) |
30 | 0 | , m_ctrl_key(event_init.ctrl_key) |
31 | 0 | , m_shift_key(event_init.shift_key) |
32 | 0 | , m_alt_key(event_init.alt_key) |
33 | 0 | , m_meta_key(event_init.meta_key) |
34 | 0 | , m_modifier_alt_graph(event_init.modifier_alt_graph) |
35 | 0 | , m_modifier_caps_lock(event_init.modifier_caps_lock) |
36 | 0 | , m_modifier_fn(event_init.modifier_fn) |
37 | 0 | , m_modifier_fn_lock(event_init.modifier_fn_lock) |
38 | 0 | , m_modifier_hyper(event_init.modifier_hyper) |
39 | 0 | , m_modifier_num_lock(event_init.modifier_num_lock) |
40 | 0 | , m_modifier_scroll_lock(event_init.modifier_scroll_lock) |
41 | 0 | , m_modifier_super(event_init.modifier_super) |
42 | 0 | , m_modifier_symbol(event_init.modifier_symbol) |
43 | 0 | , m_modifier_symbol_lock(event_init.modifier_symbol_lock) |
44 | 0 | , m_movement_x(event_init.movement_x) |
45 | 0 | , m_movement_y(event_init.movement_y) |
46 | 0 | , m_button(event_init.button) |
47 | 0 | , m_buttons(event_init.buttons) |
48 | 0 | , m_related_target(event_init.related_target) |
49 | 0 | { |
50 | 0 | } |
51 | | |
52 | 0 | MouseEvent::~MouseEvent() = default; |
53 | | |
54 | | void MouseEvent::initialize(JS::Realm& realm) |
55 | 0 | { |
56 | 0 | Base::initialize(realm); |
57 | 0 | WEB_SET_PROTOTYPE_FOR_INTERFACE(MouseEvent); |
58 | 0 | } |
59 | | |
60 | | void MouseEvent::visit_edges(Cell::Visitor& visitor) |
61 | 0 | { |
62 | 0 | Base::visit_edges(visitor); |
63 | 0 | visitor.visit(m_related_target); |
64 | 0 | } |
65 | | |
66 | | bool MouseEvent::get_modifier_state(String const& key_arg) const |
67 | 0 | { |
68 | 0 | if (key_arg == "Control") |
69 | 0 | return m_ctrl_key; |
70 | 0 | if (key_arg == "Shift") |
71 | 0 | return m_shift_key; |
72 | 0 | if (key_arg == "Alt") |
73 | 0 | return m_alt_key; |
74 | 0 | if (key_arg == "Meta") |
75 | 0 | return m_meta_key; |
76 | 0 | if (key_arg == "AltGraph") |
77 | 0 | return m_modifier_alt_graph; |
78 | 0 | if (key_arg == "CapsLock") |
79 | 0 | return m_modifier_caps_lock; |
80 | 0 | if (key_arg == "Fn") |
81 | 0 | return m_modifier_fn; |
82 | 0 | if (key_arg == "FnLock") |
83 | 0 | return m_modifier_fn_lock; |
84 | 0 | if (key_arg == "Hyper") |
85 | 0 | return m_modifier_hyper; |
86 | 0 | if (key_arg == "NumLock") |
87 | 0 | return m_modifier_num_lock; |
88 | 0 | if (key_arg == "ScrollLock") |
89 | 0 | return m_modifier_scroll_lock; |
90 | 0 | if (key_arg == "Super") |
91 | 0 | return m_modifier_super; |
92 | 0 | if (key_arg == "Symbol") |
93 | 0 | return m_modifier_symbol; |
94 | 0 | if (key_arg == "SymbolLock") |
95 | 0 | return m_modifier_symbol_lock; |
96 | 0 | return false; |
97 | 0 | } |
98 | | |
99 | | // https://w3c.github.io/uievents/#dom-mouseevent-initmouseevent |
100 | | 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) |
101 | 0 | { |
102 | | // Initializes attributes of a MouseEvent object. This method has the same behavior as UIEvent.initUIEvent(). |
103 | | |
104 | | // 1. If this’s dispatch flag is set, then return. |
105 | 0 | if (dispatched()) |
106 | 0 | return; |
107 | | |
108 | | // 2. Initialize this with type, bubbles, and cancelable. |
109 | 0 | initialize_event(type, bubbles, cancelable); |
110 | | |
111 | | // Implementation Defined: Initialise other values. |
112 | 0 | m_view = view; |
113 | 0 | m_detail = detail; |
114 | 0 | m_screen_x = screen_x; |
115 | 0 | m_screen_y = screen_y; |
116 | 0 | m_client_x = client_x; |
117 | 0 | m_client_y = client_y; |
118 | 0 | m_ctrl_key = ctrl_key; |
119 | 0 | m_shift_key = shift_key; |
120 | 0 | m_alt_key = alt_key; |
121 | 0 | m_meta_key = meta_key; |
122 | 0 | m_button = button; |
123 | 0 | m_related_target = related_target; |
124 | 0 | } |
125 | | |
126 | | 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) |
127 | 0 | { |
128 | 0 | return realm.heap().allocate<MouseEvent>(realm, realm, event_name, event_init, page_x, page_y, offset_x, offset_y); |
129 | 0 | } |
130 | | |
131 | | WebIDL::ExceptionOr<JS::NonnullGCPtr<MouseEvent>> MouseEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, MouseEventInit const& event_init) |
132 | 0 | { |
133 | 0 | return create(realm, event_name, event_init); |
134 | 0 | } |
135 | | |
136 | | 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) |
137 | 0 | { |
138 | 0 | MouseEventInit event_init {}; |
139 | 0 | event_init.ctrl_key = modifiers & Mod_Ctrl; |
140 | 0 | event_init.shift_key = modifiers & Mod_Shift; |
141 | 0 | event_init.alt_key = modifiers & Mod_Alt; |
142 | 0 | event_init.meta_key = modifiers & Mod_Super; |
143 | 0 | event_init.screen_x = screen.x().to_double(); |
144 | 0 | event_init.screen_y = screen.y().to_double(); |
145 | 0 | event_init.client_x = client.x().to_double(); |
146 | 0 | event_init.client_y = client.y().to_double(); |
147 | 0 | if (movement.has_value()) { |
148 | 0 | event_init.movement_x = movement.value().x().to_double(); |
149 | 0 | event_init.movement_y = movement.value().y().to_double(); |
150 | 0 | } |
151 | 0 | event_init.button = mouse_button_to_button_code(static_cast<MouseButton>(button)); |
152 | 0 | event_init.buttons = buttons; |
153 | 0 | 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()); |
154 | 0 | event->set_is_trusted(true); |
155 | 0 | event->set_bubbles(true); |
156 | 0 | event->set_cancelable(true); |
157 | 0 | event->set_composed(true); |
158 | 0 | return event; |
159 | 0 | } |
160 | | |
161 | | } |