UI/AppKit: Send keyboard events for modifier-only key presses/releases

If the user only presses the shift key, for example, we are required to
still send that event to WebContent and generate the corresponding JS
events. Unfortunately, NSApp does not inform us of these events via the
keyDown/keyUp methods. We have to implement the flagsChanged interface,
and track for ourselves what modifier keys were pressed or released.
This commit is contained in:
Timothy Flynn 2024-10-08 20:17:08 -04:00 committed by Andreas Kling
commit eabd5b0f22
Notes: github-actions[bot] 2024-10-09 17:11:13 +00:00
2 changed files with 45 additions and 4 deletions

View file

@ -298,11 +298,15 @@ Web::KeyEvent ns_event_to_key_event(Web::KeyEvent::Type type, NSEvent* event)
auto modifiers = ns_modifiers_to_key_modifiers(event.modifierFlags);
auto key_code = ns_key_code_to_key_code(event.keyCode, modifiers);
auto const* utf8 = [event.characters UTF8String];
Utf8View utf8_view { StringView { utf8, strlen(utf8) } };
// FIXME: WebContent should really support multi-code point key events.
auto code_point = utf8_view.is_empty() ? 0u : *utf8_view.begin();
u32 code_point = 0;
if (event.type == NSEventTypeKeyDown || event.type == NSEventTypeKeyUp) {
auto const* utf8 = [event.characters UTF8String];
Utf8View utf8_view { StringView { utf8, strlen(utf8) } };
code_point = utf8_view.is_empty() ? 0u : *utf8_view.begin();
}
// NSEvent assigns PUA code points to to functional keys, e.g. arrow keys. Do not propagate them.
if (code_point >= 0xE000 && code_point <= 0xF8FF)

View file

@ -58,6 +58,11 @@ struct HideCursor {
Optional<String> m_context_menu_search_text;
Optional<HideCursor> m_hidden_cursor;
// We have to send key events for modifer keys, but AppKit does not generate key down/up events when only a modifier
// key is pressed. Instead, we only receive an event that the modifier flags have changed, and we must determine for
// ourselves whether the modifier key was pressed or released.
NSEventModifierFlags m_modifier_flags;
}
@property (nonatomic, weak) id<LadybirdWebViewObserver> observer;
@ -135,6 +140,8 @@ struct HideCursor {
[self addTrackingArea:area];
[self registerForDraggedTypes:[NSArray arrayWithObjects:NSPasteboardTypeFileURL, nil]];
m_modifier_flags = 0;
}
return self;
@ -1676,6 +1683,36 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
m_web_view_bridge->enqueue_input_event(move(key_event));
}
- (void)flagsChanged:(NSEvent*)event
{
if (self.event_being_redispatched == event) {
return;
}
auto enqueue_event_if_needed = [&](auto flag) {
auto is_flag_set = [&](auto flags) { return (flags & flag) != 0; };
Web::KeyEvent::Type type;
if (is_flag_set(event.modifierFlags) && !is_flag_set(m_modifier_flags)) {
type = Web::KeyEvent::Type::KeyDown;
} else if (!is_flag_set(event.modifierFlags) && is_flag_set(m_modifier_flags)) {
type = Web::KeyEvent::Type::KeyUp;
} else {
return;
}
auto key_event = Ladybird::ns_event_to_key_event(type, event);
m_web_view_bridge->enqueue_input_event(move(key_event));
};
enqueue_event_if_needed(NSEventModifierFlagShift);
enqueue_event_if_needed(NSEventModifierFlagControl);
enqueue_event_if_needed(NSEventModifierFlagOption);
enqueue_event_if_needed(NSEventModifierFlagCommand);
m_modifier_flags = event.modifierFlags;
}
#pragma mark - NSDraggingDestination
- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)event