mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 17:42:43 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			196 lines
		
	
	
	
		
			8.8 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			196 lines
		
	
	
	
		
			8.8 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #include <AK/Utf8View.h>
 | |
| 
 | |
| #import <System/Carbon.h>
 | |
| #import <UI/Event.h>
 | |
| #import <Utilities/Conversions.h>
 | |
| 
 | |
| namespace Ladybird {
 | |
| 
 | |
| static KeyModifier ns_modifiers_to_key_modifiers(NSEventModifierFlags modifier_flags, Optional<GUI::MouseButton&> button = {})
 | |
| {
 | |
|     unsigned modifiers = KeyModifier::Mod_None;
 | |
| 
 | |
|     if ((modifier_flags & NSEventModifierFlagShift) != 0) {
 | |
|         modifiers |= KeyModifier::Mod_Shift;
 | |
|     }
 | |
|     if ((modifier_flags & NSEventModifierFlagControl) != 0) {
 | |
|         if (button == GUI::MouseButton::Primary) {
 | |
|             *button = GUI::MouseButton::Secondary;
 | |
|         } else {
 | |
|             modifiers |= KeyModifier::Mod_Ctrl;
 | |
|         }
 | |
|     }
 | |
|     if ((modifier_flags & NSEventModifierFlagOption) != 0) {
 | |
|         modifiers |= KeyModifier::Mod_Alt;
 | |
|     }
 | |
|     if ((modifier_flags & NSEventModifierFlagCommand) != 0) {
 | |
|         modifiers |= KeyModifier::Mod_Super;
 | |
|     }
 | |
| 
 | |
|     return static_cast<KeyModifier>(modifiers);
 | |
| }
 | |
| 
 | |
| MouseEvent ns_event_to_mouse_event(NSEvent* event, NSView* view, GUI::MouseButton button)
 | |
| {
 | |
|     auto position = [view convertPoint:event.locationInWindow fromView:nil];
 | |
|     auto screen_position = [NSEvent mouseLocation];
 | |
|     auto modifiers = ns_modifiers_to_key_modifiers(event.modifierFlags, button);
 | |
| 
 | |
|     return { ns_point_to_gfx_point(position), ns_point_to_gfx_point(screen_position), button, modifiers };
 | |
| }
 | |
| 
 | |
| NSEvent* create_context_menu_mouse_event(NSView* view, Gfx::IntPoint position)
 | |
| {
 | |
|     return create_context_menu_mouse_event(view, gfx_point_to_ns_point(position));
 | |
| }
 | |
| 
 | |
| NSEvent* create_context_menu_mouse_event(NSView* view, NSPoint position)
 | |
| {
 | |
|     return [NSEvent mouseEventWithType:NSEventTypeRightMouseUp
 | |
|                               location:[view convertPoint:position fromView:nil]
 | |
|                          modifierFlags:0
 | |
|                              timestamp:0
 | |
|                           windowNumber:[[view window] windowNumber]
 | |
|                                context:nil
 | |
|                            eventNumber:1
 | |
|                             clickCount:1
 | |
|                               pressure:1.0];
 | |
| }
 | |
| 
 | |
| static KeyCode ns_key_code_to_key_code(unsigned short key_code, KeyModifier& modifiers)
 | |
| {
 | |
|     auto augment_modifiers_and_return = [&](auto key, auto modifier) {
 | |
|         modifiers = static_cast<KeyModifier>(static_cast<unsigned>(modifiers) | modifier);
 | |
|         return key;
 | |
|     };
 | |
| 
 | |
|     // clang-format off
 | |
|     switch (key_code) {
 | |
|     case kVK_ANSI_0: return KeyCode::Key_0;
 | |
|     case kVK_ANSI_1: return KeyCode::Key_1;
 | |
|     case kVK_ANSI_2: return KeyCode::Key_2;
 | |
|     case kVK_ANSI_3: return KeyCode::Key_3;
 | |
|     case kVK_ANSI_4: return KeyCode::Key_4;
 | |
|     case kVK_ANSI_5: return KeyCode::Key_5;
 | |
|     case kVK_ANSI_6: return KeyCode::Key_6;
 | |
|     case kVK_ANSI_7: return KeyCode::Key_7;
 | |
|     case kVK_ANSI_8: return KeyCode::Key_8;
 | |
|     case kVK_ANSI_9: return KeyCode::Key_9;
 | |
|     case kVK_ANSI_A: return KeyCode::Key_A;
 | |
|     case kVK_ANSI_B: return KeyCode::Key_B;
 | |
|     case kVK_ANSI_C: return KeyCode::Key_C;
 | |
|     case kVK_ANSI_D: return KeyCode::Key_D;
 | |
|     case kVK_ANSI_E: return KeyCode::Key_E;
 | |
|     case kVK_ANSI_F: return KeyCode::Key_F;
 | |
|     case kVK_ANSI_G: return KeyCode::Key_G;
 | |
|     case kVK_ANSI_H: return KeyCode::Key_H;
 | |
|     case kVK_ANSI_I: return KeyCode::Key_I;
 | |
|     case kVK_ANSI_J: return KeyCode::Key_J;
 | |
|     case kVK_ANSI_K: return KeyCode::Key_K;
 | |
|     case kVK_ANSI_L: return KeyCode::Key_L;
 | |
|     case kVK_ANSI_M: return KeyCode::Key_M;
 | |
|     case kVK_ANSI_N: return KeyCode::Key_N;
 | |
|     case kVK_ANSI_O: return KeyCode::Key_O;
 | |
|     case kVK_ANSI_P: return KeyCode::Key_P;
 | |
|     case kVK_ANSI_Q: return KeyCode::Key_Q;
 | |
|     case kVK_ANSI_R: return KeyCode::Key_R;
 | |
|     case kVK_ANSI_S: return KeyCode::Key_S;
 | |
|     case kVK_ANSI_T: return KeyCode::Key_T;
 | |
|     case kVK_ANSI_U: return KeyCode::Key_U;
 | |
|     case kVK_ANSI_V: return KeyCode::Key_V;
 | |
|     case kVK_ANSI_W: return KeyCode::Key_W;
 | |
|     case kVK_ANSI_X: return KeyCode::Key_X;
 | |
|     case kVK_ANSI_Y: return KeyCode::Key_Y;
 | |
|     case kVK_ANSI_Z: return KeyCode::Key_Z;
 | |
|     case kVK_ANSI_Backslash: return KeyCode::Key_Backslash;
 | |
|     case kVK_ANSI_Comma: return KeyCode::Key_Comma;
 | |
|     case kVK_ANSI_Equal: return KeyCode::Key_Equal;
 | |
|     case kVK_ANSI_Grave: return KeyCode::Key_Backtick;
 | |
|     case kVK_ANSI_Keypad0: return augment_modifiers_and_return(KeyCode::Key_0, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_Keypad1: return augment_modifiers_and_return(KeyCode::Key_1, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_Keypad2: return augment_modifiers_and_return(KeyCode::Key_2, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_Keypad3: return augment_modifiers_and_return(KeyCode::Key_3, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_Keypad4: return augment_modifiers_and_return(KeyCode::Key_4, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_Keypad5: return augment_modifiers_and_return(KeyCode::Key_5, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_Keypad6: return augment_modifiers_and_return(KeyCode::Key_6, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_Keypad7: return augment_modifiers_and_return(KeyCode::Key_7, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_Keypad8: return augment_modifiers_and_return(KeyCode::Key_8, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_Keypad9: return augment_modifiers_and_return(KeyCode::Key_9, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_KeypadClear: return augment_modifiers_and_return(KeyCode::Key_Delete, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_KeypadDecimal: return augment_modifiers_and_return(KeyCode::Key_Period, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_KeypadDivide: return augment_modifiers_and_return(KeyCode::Key_Slash, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_KeypadEnter: return augment_modifiers_and_return(KeyCode::Key_Return, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_KeypadEquals: return augment_modifiers_and_return(KeyCode::Key_Equal, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_KeypadMinus: return augment_modifiers_and_return(KeyCode::Key_Minus, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_KeypadMultiply: return augment_modifiers_and_return(KeyCode::Key_Asterisk, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_KeypadPlus: return augment_modifiers_and_return(KeyCode::Key_Plus, KeyModifier::Mod_Keypad);
 | |
|     case kVK_ANSI_LeftBracket: return KeyCode::Key_LeftBracket;
 | |
|     case kVK_ANSI_Minus: return KeyCode::Key_Minus;
 | |
|     case kVK_ANSI_Period: return KeyCode::Key_Period;
 | |
|     case kVK_ANSI_Quote: return KeyCode::Key_Apostrophe;
 | |
|     case kVK_ANSI_RightBracket: return KeyCode::Key_RightBracket;
 | |
|     case kVK_ANSI_Semicolon: return KeyCode::Key_Semicolon;
 | |
|     case kVK_ANSI_Slash: return KeyCode::Key_Slash;
 | |
|     case kVK_CapsLock: return KeyCode::Key_CapsLock;
 | |
|     case kVK_Command: return KeyCode::Key_Super;
 | |
|     case kVK_Control: return KeyCode::Key_Control;
 | |
|     case kVK_Delete: return KeyCode::Key_Backspace;
 | |
|     case kVK_DownArrow: return KeyCode::Key_Down;
 | |
|     case kVK_End: return KeyCode::Key_End;
 | |
|     case kVK_Escape: return KeyCode::Key_Escape;
 | |
|     case kVK_F1: return KeyCode::Key_F1;
 | |
|     case kVK_F2: return KeyCode::Key_F2;
 | |
|     case kVK_F3: return KeyCode::Key_F3;
 | |
|     case kVK_F4: return KeyCode::Key_F4;
 | |
|     case kVK_F5: return KeyCode::Key_F5;
 | |
|     case kVK_F6: return KeyCode::Key_F6;
 | |
|     case kVK_F7: return KeyCode::Key_F7;
 | |
|     case kVK_F8: return KeyCode::Key_F8;
 | |
|     case kVK_F9: return KeyCode::Key_F9;
 | |
|     case kVK_F10: return KeyCode::Key_F10;
 | |
|     case kVK_F11: return KeyCode::Key_F11;
 | |
|     case kVK_F12: return KeyCode::Key_F12;
 | |
|     case kVK_ForwardDelete: return KeyCode::Key_Delete;
 | |
|     case kVK_Home: return KeyCode::Key_Home;
 | |
|     case kVK_LeftArrow: return KeyCode::Key_Left;
 | |
|     case kVK_Option: return KeyCode::Key_Alt;
 | |
|     case kVK_PageDown: return KeyCode::Key_PageDown;
 | |
|     case kVK_PageUp: return KeyCode::Key_PageUp;
 | |
|     case kVK_Return: return KeyCode::Key_Return;
 | |
|     case kVK_RightArrow: return KeyCode::Key_Right;
 | |
|     case kVK_RightCommand: return KeyCode::Key_Super; // FIXME: We do not distinguish left-vs-right.
 | |
|     case kVK_RightControl: return KeyCode::Key_Control; // FIXME: We do not distinguish left-vs-right.
 | |
|     case kVK_RightOption: return KeyCode::Key_Alt; // FIXME: We do not distinguish left-vs-right.
 | |
|     case kVK_RightShift: return KeyCode::Key_RightShift;
 | |
|     case kVK_Shift: return KeyCode::Key_Shift;
 | |
|     case kVK_Space: return KeyCode::Key_Space;
 | |
|     case kVK_Tab: return KeyCode::Key_Tab;
 | |
|     case kVK_UpArrow: return KeyCode::Key_Up;
 | |
|     default: break;
 | |
|     }
 | |
|     // clang-format on
 | |
| 
 | |
|     return KeyCode::Key_Invalid;
 | |
| }
 | |
| 
 | |
| KeyEvent ns_event_to_key_event(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();
 | |
| 
 | |
|     return { key_code, modifiers, code_point };
 | |
| }
 | |
| 
 | |
| }
 | 
