From 30f41c02aec763d32e62351452da9ef582bc3472 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Fri, 6 Mar 2026 13:30:59 -0800 Subject: Move contrib libraries to contrib repo --- .../SDL-3.2.8/src/video/cocoa/SDL_cocoakeyboard.m | 604 --------------------- 1 file changed, 604 deletions(-) delete mode 100644 contrib/SDL-3.2.8/src/video/cocoa/SDL_cocoakeyboard.m (limited to 'contrib/SDL-3.2.8/src/video/cocoa/SDL_cocoakeyboard.m') diff --git a/contrib/SDL-3.2.8/src/video/cocoa/SDL_cocoakeyboard.m b/contrib/SDL-3.2.8/src/video/cocoa/SDL_cocoakeyboard.m deleted file mode 100644 index e458be9..0000000 --- a/contrib/SDL-3.2.8/src/video/cocoa/SDL_cocoakeyboard.m +++ /dev/null @@ -1,604 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ -#include "SDL_internal.h" - -#ifdef SDL_VIDEO_DRIVER_COCOA - -#include "SDL_cocoavideo.h" - -#include "../../events/SDL_events_c.h" -#include "../../events/SDL_keyboard_c.h" -#include "../../events/scancodes_darwin.h" - -#include - -#if 0 -#define DEBUG_IME NSLog -#else -#define DEBUG_IME(...) -#endif - -@interface SDL3TranslatorResponder : NSView -{ - NSString *_markedText; - NSRange _markedRange; - NSRange _selectedRange; - SDL_Rect _inputRect; - int _pendingRawCode; - SDL_Scancode _pendingScancode; - Uint64 _pendingTimestamp; -} -- (void)doCommandBySelector:(SEL)myselector; -- (void)setInputRect:(const SDL_Rect *)rect; -- (void)setPendingKey:(int)rawcode scancode:(SDL_Scancode)scancode timestamp:(Uint64)timestamp; -- (void)sendPendingKey; -- (void)clearPendingKey; -@end - -@implementation SDL3TranslatorResponder - -- (void)setInputRect:(const SDL_Rect *)rect -{ - SDL_copyp(&_inputRect, rect); -} - -- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange -{ - const char *str; - - DEBUG_IME(@"insertText: %@ replacementRange: (%d, %d)", aString, - (int)replacementRange.location, (int)replacementRange.length); - - /* Could be NSString or NSAttributedString, so we have - * to test and convert it before return as SDL event */ - if ([aString isKindOfClass:[NSAttributedString class]]) { - str = [[aString string] UTF8String]; - } else { - str = [aString UTF8String]; - } - - // We're likely sending the composed text, so we reset the IME status. - if ([self hasMarkedText]) { - [self unmarkText]; - } - - // Deliver the raw key event that generated this text - [self sendPendingKey]; - - if ((int)replacementRange.location != -1) { - // We're replacing the last character - SDL_SendKeyboardKey(0, SDL_GLOBAL_KEYBOARD_ID, 0, SDL_SCANCODE_BACKSPACE, true); - SDL_SendKeyboardKey(0, SDL_GLOBAL_KEYBOARD_ID, 0, SDL_SCANCODE_BACKSPACE, false); - } - - SDL_SendKeyboardText(str); -} - -- (void)doCommandBySelector:(SEL)myselector -{ - /* No need to do anything since we are not using Cocoa - selectors to handle special keys, instead we use SDL - key events to do the same job. - */ -} - -- (BOOL)hasMarkedText -{ - return _markedText != nil; -} - -- (NSRange)markedRange -{ - return _markedRange; -} - -- (NSRange)selectedRange -{ - return _selectedRange; -} - -- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange -{ - if ([aString isKindOfClass:[NSAttributedString class]]) { - aString = [aString string]; - } - - if ([aString length] == 0) { - [self unmarkText]; - return; - } - - if (_markedText != aString) { - _markedText = aString; - } - - _selectedRange = selectedRange; - _markedRange = NSMakeRange(0, [aString length]); - - // This key event was consumed by the IME - [self clearPendingKey]; - - NSUInteger utf32SelectedRangeLocation = [[aString substringToIndex:selectedRange.location] lengthOfBytesUsingEncoding:NSUTF32StringEncoding] / 4; - NSUInteger utf32SelectionRangeEnd = [[aString substringToIndex:(selectedRange.location + selectedRange.length)] lengthOfBytesUsingEncoding:NSUTF32StringEncoding] / 4; - NSUInteger utf32SelectionRangeLength = utf32SelectionRangeEnd - utf32SelectedRangeLocation; - - SDL_SendEditingText([aString UTF8String], - (int)utf32SelectedRangeLocation, (int)utf32SelectionRangeLength); - - DEBUG_IME(@"setMarkedText: %@, (%d, %d) replacement range (%d, %d)", _markedText, - (int)selectedRange.location, (int)selectedRange.length, - (int)replacementRange.location, (int)replacementRange.length); -} - -- (void)unmarkText -{ - _markedText = nil; - - // This key event was consumed by the IME - [self clearPendingKey]; - - SDL_SendEditingText("", 0, 0); -} - -- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange -{ - NSWindow *window = [self window]; - NSRect contentRect = [window contentRectForFrameRect:[window frame]]; - float windowHeight = contentRect.size.height; - NSRect rect = NSMakeRect(_inputRect.x, windowHeight - _inputRect.y - _inputRect.h, - _inputRect.w, _inputRect.h); - - if (actualRange) { - *actualRange = aRange; - } - - DEBUG_IME(@"firstRectForCharacterRange: (%d, %d): windowHeight = %g, rect = %@", - (int)aRange.location, (int)aRange.length, windowHeight, - NSStringFromRect(rect)); - - rect = [window convertRectToScreen:rect]; - - return rect; -} - -- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange -{ - DEBUG_IME(@"attributedSubstringFromRange: (%d, %d)", (int)aRange.location, (int)aRange.length); - return nil; -} - -- (NSInteger)conversationIdentifier -{ - return (NSInteger)self; -} - -/* This method returns the index for character that is - * nearest to thePoint. thPoint is in screen coordinate system. - */ -- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint -{ - DEBUG_IME(@"characterIndexForPoint: (%g, %g)", thePoint.x, thePoint.y); - return 0; -} - -/* This method is the key to attribute extension. - * We could add new attributes through this method. - * NSInputServer examines the return value of this - * method & constructs appropriate attributed string. - */ -- (NSArray *)validAttributesForMarkedText -{ - return [NSArray array]; -} - -- (void)setPendingKey:(int)rawcode scancode:(SDL_Scancode)scancode timestamp:(Uint64)timestamp -{ - _pendingRawCode = rawcode; - _pendingScancode = scancode; - _pendingTimestamp = timestamp; -} - -- (void)sendPendingKey -{ - if (_pendingRawCode < 0) { - return; - } - - SDL_SendKeyboardKey(_pendingTimestamp, SDL_DEFAULT_KEYBOARD_ID, _pendingRawCode, _pendingScancode, true); - [self clearPendingKey]; -} - -- (void)clearPendingKey -{ - _pendingRawCode = -1; -} - -@end - -static bool IsModifierKeyPressed(unsigned int flags, - unsigned int target_mask, - unsigned int other_mask, - unsigned int either_mask) -{ - bool target_pressed = (flags & target_mask) != 0; - bool other_pressed = (flags & other_mask) != 0; - bool either_pressed = (flags & either_mask) != 0; - - if (either_pressed != (target_pressed || other_pressed)) - return either_pressed; - - return target_pressed; -} - -static void HandleModifiers(SDL_VideoDevice *_this, SDL_Scancode code, unsigned int modifierFlags) -{ - bool pressed = false; - - if (code == SDL_SCANCODE_LSHIFT) { - pressed = IsModifierKeyPressed(modifierFlags, NX_DEVICELSHIFTKEYMASK, - NX_DEVICERSHIFTKEYMASK, NX_SHIFTMASK); - } else if (code == SDL_SCANCODE_LCTRL) { - pressed = IsModifierKeyPressed(modifierFlags, NX_DEVICELCTLKEYMASK, - NX_DEVICERCTLKEYMASK, NX_CONTROLMASK); - } else if (code == SDL_SCANCODE_LALT) { - pressed = IsModifierKeyPressed(modifierFlags, NX_DEVICELALTKEYMASK, - NX_DEVICERALTKEYMASK, NX_ALTERNATEMASK); - } else if (code == SDL_SCANCODE_LGUI) { - pressed = IsModifierKeyPressed(modifierFlags, NX_DEVICELCMDKEYMASK, - NX_DEVICERCMDKEYMASK, NX_COMMANDMASK); - } else if (code == SDL_SCANCODE_RSHIFT) { - pressed = IsModifierKeyPressed(modifierFlags, NX_DEVICERSHIFTKEYMASK, - NX_DEVICELSHIFTKEYMASK, NX_SHIFTMASK); - } else if (code == SDL_SCANCODE_RCTRL) { - pressed = IsModifierKeyPressed(modifierFlags, NX_DEVICERCTLKEYMASK, - NX_DEVICELCTLKEYMASK, NX_CONTROLMASK); - } else if (code == SDL_SCANCODE_RALT) { - pressed = IsModifierKeyPressed(modifierFlags, NX_DEVICERALTKEYMASK, - NX_DEVICELALTKEYMASK, NX_ALTERNATEMASK); - } else if (code == SDL_SCANCODE_RGUI) { - pressed = IsModifierKeyPressed(modifierFlags, NX_DEVICERCMDKEYMASK, - NX_DEVICELCMDKEYMASK, NX_COMMANDMASK); - } else { - return; - } - - if (pressed) { - SDL_SendKeyboardKey(0, SDL_DEFAULT_KEYBOARD_ID, 0, code, true); - } else { - SDL_SendKeyboardKey(0, SDL_DEFAULT_KEYBOARD_ID, 0, code, false); - } -} - -static void UpdateKeymap(SDL_CocoaVideoData *data, bool send_event) -{ - TISInputSourceRef key_layout; - UCKeyboardLayout *keyLayoutPtr = NULL; - CFDataRef uchrDataRef; - - // See if the keymap needs to be updated - key_layout = TISCopyCurrentKeyboardLayoutInputSource(); - if (key_layout == data.key_layout) { - return; - } - data.key_layout = key_layout; - - // Try Unicode data first - uchrDataRef = TISGetInputSourceProperty(key_layout, kTISPropertyUnicodeKeyLayoutData); - if (uchrDataRef) { - keyLayoutPtr = (UCKeyboardLayout *)CFDataGetBytePtr(uchrDataRef); - } - - if (!keyLayoutPtr) { - CFRelease(key_layout); - return; - } - - static struct { - int flags; - SDL_Keymod modstate; - } mods[] = { - { 0, SDL_KMOD_NONE }, - { shiftKey, SDL_KMOD_SHIFT }, - { alphaLock, SDL_KMOD_CAPS }, - { (shiftKey | alphaLock), (SDL_KMOD_SHIFT | SDL_KMOD_CAPS) }, - { optionKey, SDL_KMOD_ALT }, - { (optionKey | shiftKey), (SDL_KMOD_ALT | SDL_KMOD_SHIFT) }, - { (optionKey | alphaLock), (SDL_KMOD_ALT | SDL_KMOD_CAPS) }, - { (optionKey | shiftKey | alphaLock), (SDL_KMOD_ALT | SDL_KMOD_SHIFT | SDL_KMOD_CAPS) } - }; - - UInt32 keyboard_type = LMGetKbdType(); - - SDL_Keymap *keymap = SDL_CreateKeymap(); - for (int m = 0; m < SDL_arraysize(mods); ++m) { - for (int i = 0; i < SDL_arraysize(darwin_scancode_table); i++) { - OSStatus err; - UniChar s[8]; - UniCharCount len; - UInt32 dead_key_state; - - // Make sure this scancode is a valid character scancode - SDL_Scancode scancode = darwin_scancode_table[i]; - if (scancode == SDL_SCANCODE_UNKNOWN || - scancode == SDL_SCANCODE_DELETE || - (SDL_GetKeymapKeycode(NULL, scancode, SDL_KMOD_NONE) & SDLK_SCANCODE_MASK)) { - continue; - } - - /* - * Swap the scancode for these two wrongly translated keys - * UCKeyTranslate() function does not do its job properly for ISO layout keyboards, where the key '@', - * which is located in the top left corner of the keyboard right under the Escape key, and the additional - * key '<', which is on the right of the Shift key, are inverted - */ - if ((scancode == SDL_SCANCODE_NONUSBACKSLASH || scancode == SDL_SCANCODE_GRAVE) && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) { - // see comments in scancodes_darwin.h - scancode = (SDL_Scancode)((SDL_SCANCODE_NONUSBACKSLASH + SDL_SCANCODE_GRAVE) - scancode); - } - - dead_key_state = 0; - err = UCKeyTranslate(keyLayoutPtr, i, kUCKeyActionDown, - ((mods[m].flags >> 8) & 0xFF), keyboard_type, - kUCKeyTranslateNoDeadKeysMask, - &dead_key_state, 8, &len, s); - if (err != noErr) { - continue; - } - - if (len > 0 && s[0] != 0x10) { - SDL_SetKeymapEntry(keymap, scancode, mods[m].modstate, s[0]); - } else { - // The default keymap doesn't have any SDL_KMOD_ALT entries, so we don't need to override them - if (!(mods[m].modstate & SDL_KMOD_ALT)) { - SDL_SetKeymapEntry(keymap, scancode, mods[m].modstate, SDLK_UNKNOWN); - } - } - } - } - SDL_SetKeymap(keymap, send_event); -} - -static void SDLCALL SDL_MacOptionAsAltChanged(void *userdata, const char *name, const char *oldValue, const char *hint) -{ - SDL_VideoDevice *_this = (SDL_VideoDevice *)userdata; - SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->internal; - - if (hint && *hint) { - if (SDL_strcmp(hint, "none") == 0) { - data.option_as_alt = OptionAsAltNone; - } else if (SDL_strcmp(hint, "only_left") == 0) { - data.option_as_alt = OptionAsAltOnlyLeft; - } else if (SDL_strcmp(hint, "only_right") == 0) { - data.option_as_alt = OptionAsAltOnlyRight; - } else if (SDL_strcmp(hint, "both") == 0) { - data.option_as_alt = OptionAsAltBoth; - } - } else { - data.option_as_alt = OptionAsAltNone; - } -} - -void Cocoa_InitKeyboard(SDL_VideoDevice *_this) -{ - SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->internal; - - UpdateKeymap(data, false); - - // Set our own names for the platform-dependent but layout-independent keys - // This key is NumLock on the MacBook keyboard. :) - // SDL_SetScancodeName(SDL_SCANCODE_NUMLOCKCLEAR, "Clear"); - SDL_SetScancodeName(SDL_SCANCODE_LALT, "Left Option"); - SDL_SetScancodeName(SDL_SCANCODE_LGUI, "Left Command"); - SDL_SetScancodeName(SDL_SCANCODE_RALT, "Right Option"); - SDL_SetScancodeName(SDL_SCANCODE_RGUI, "Right Command"); - - data.modifierFlags = (unsigned int)[NSEvent modifierFlags]; - SDL_ToggleModState(SDL_KMOD_CAPS, (data.modifierFlags & NSEventModifierFlagCapsLock) ? true : false); - - SDL_AddHintCallback(SDL_HINT_MAC_OPTION_AS_ALT, SDL_MacOptionAsAltChanged, _this); -} - -bool Cocoa_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props) -{ - @autoreleasepool { - NSView *parentView; - SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->internal; - NSWindow *nswindow = ((__bridge SDL_CocoaWindowData *)window->internal).nswindow; - - parentView = [nswindow contentView]; - - /* We only keep one field editor per process, since only the front most - * window can receive text input events, so it make no sense to keep more - * than one copy. When we switched to another window and requesting for - * text input, simply remove the field editor from its superview then add - * it to the front most window's content view */ - if (!data.fieldEdit) { - data.fieldEdit = [[SDL3TranslatorResponder alloc] initWithFrame:NSMakeRect(0.0, 0.0, 0.0, 0.0)]; - } - - if (![[data.fieldEdit superview] isEqual:parentView]) { - // DEBUG_IME(@"add fieldEdit to window contentView"); - [data.fieldEdit removeFromSuperview]; - [parentView addSubview:data.fieldEdit]; - [nswindow makeFirstResponder:data.fieldEdit]; - } - } - return Cocoa_UpdateTextInputArea(_this, window); -} - -bool Cocoa_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window) -{ - @autoreleasepool { - SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->internal; - - if (data && data.fieldEdit) { - [data.fieldEdit removeFromSuperview]; - data.fieldEdit = nil; - } - } - return true; -} - -bool Cocoa_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->internal; - if (data.fieldEdit) { - [data.fieldEdit setInputRect:&window->text_input_rect]; - } - return true; -} - -static NSEvent *ReplaceEvent(NSEvent *event, OptionAsAlt option_as_alt) -{ - if (option_as_alt == OptionAsAltNone) { - return event; - } - - const unsigned int modflags = (unsigned int)[event modifierFlags]; - - bool ignore_alt_characters = false; - - bool lalt_pressed = IsModifierKeyPressed(modflags, NX_DEVICELALTKEYMASK, - NX_DEVICERALTKEYMASK, NX_ALTERNATEMASK); - bool ralt_pressed = IsModifierKeyPressed(modflags, NX_DEVICERALTKEYMASK, - NX_DEVICELALTKEYMASK, NX_ALTERNATEMASK); - - if (option_as_alt == OptionAsAltOnlyLeft && lalt_pressed) { - ignore_alt_characters = true; - } else if (option_as_alt == OptionAsAltOnlyRight && ralt_pressed) { - ignore_alt_characters = true; - } else if (option_as_alt == OptionAsAltBoth && (lalt_pressed || ralt_pressed)) { - ignore_alt_characters = true; - } - - bool cmd_pressed = modflags & NX_COMMANDMASK; - bool ctrl_pressed = modflags & NX_CONTROLMASK; - - ignore_alt_characters = ignore_alt_characters && !cmd_pressed && !ctrl_pressed; - - if (ignore_alt_characters) { - NSString *charactersIgnoringModifiers = [event charactersIgnoringModifiers]; - return [NSEvent keyEventWithType:[event type] - location:[event locationInWindow] - modifierFlags:modflags - timestamp:[event timestamp] - windowNumber:[event windowNumber] - context:nil - characters:charactersIgnoringModifiers - charactersIgnoringModifiers:charactersIgnoringModifiers - isARepeat:[event isARepeat] - keyCode:[event keyCode]]; - } - - return event; -} - -void Cocoa_HandleKeyEvent(SDL_VideoDevice *_this, NSEvent *event) -{ - unsigned short scancode; - SDL_Scancode code; - SDL_CocoaVideoData *data = _this ? ((__bridge SDL_CocoaVideoData *)_this->internal) : nil; - if (!data) { - return; // can happen when returning from fullscreen Space on shutdown - } - - if ([event type] == NSEventTypeKeyDown || [event type] == NSEventTypeKeyUp) { - event = ReplaceEvent(event, data.option_as_alt); - } - - scancode = [event keyCode]; - - if ((scancode == 10 || scancode == 50) && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) { - // see comments in scancodes_darwin.h - scancode = 60 - scancode; - } - - if (scancode < SDL_arraysize(darwin_scancode_table)) { - code = darwin_scancode_table[scancode]; - } else { - // Hmm, does this ever happen? If so, need to extend the keymap... - code = SDL_SCANCODE_UNKNOWN; - } - - switch ([event type]) { - case NSEventTypeKeyDown: - if (![event isARepeat]) { - // See if we need to rebuild the keyboard layout - UpdateKeymap(data, true); - } - -#ifdef DEBUG_SCANCODES - if (code == SDL_SCANCODE_UNKNOWN) { - SDL_Log("The key you just pressed is not recognized by SDL. To help get this fixed, report this to the SDL forums/mailing list or to Christian Walther . Mac virtual key code is %d.", scancode); - } -#endif - if (SDL_TextInputActive(SDL_GetKeyboardFocus())) { - [data.fieldEdit setPendingKey:scancode scancode:code timestamp:Cocoa_GetEventTimestamp([event timestamp])]; - [data.fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]]; - [data.fieldEdit sendPendingKey]; - } else if (SDL_GetKeyboardFocus()) { - SDL_SendKeyboardKey(Cocoa_GetEventTimestamp([event timestamp]), SDL_DEFAULT_KEYBOARD_ID, scancode, code, true); - } - break; - case NSEventTypeKeyUp: - SDL_SendKeyboardKey(Cocoa_GetEventTimestamp([event timestamp]), SDL_DEFAULT_KEYBOARD_ID, scancode, code, false); - break; - case NSEventTypeFlagsChanged: { - // see if the new modifierFlags mean any existing keys should be pressed/released... - const unsigned int modflags = (unsigned int)[event modifierFlags]; - HandleModifiers(_this, SDL_SCANCODE_LSHIFT, modflags); - HandleModifiers(_this, SDL_SCANCODE_LCTRL, modflags); - HandleModifiers(_this, SDL_SCANCODE_LALT, modflags); - HandleModifiers(_this, SDL_SCANCODE_LGUI, modflags); - HandleModifiers(_this, SDL_SCANCODE_RSHIFT, modflags); - HandleModifiers(_this, SDL_SCANCODE_RCTRL, modflags); - HandleModifiers(_this, SDL_SCANCODE_RALT, modflags); - HandleModifiers(_this, SDL_SCANCODE_RGUI, modflags); - break; - } - default: // just to avoid compiler warnings - break; - } -} - -void Cocoa_QuitKeyboard(SDL_VideoDevice *_this) -{ -} - -typedef int CGSConnection; -typedef enum -{ - CGSGlobalHotKeyEnable = 0, - CGSGlobalHotKeyDisable = 1, -} CGSGlobalHotKeyOperatingMode; - -extern CGSConnection _CGSDefaultConnection(void); -extern CGError CGSSetGlobalHotKeyOperatingMode(CGSConnection connection, CGSGlobalHotKeyOperatingMode mode); - -bool Cocoa_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, bool grabbed) -{ -#ifdef SDL_MAC_NO_SANDBOX - CGSSetGlobalHotKeyOperatingMode(_CGSDefaultConnection(), grabbed ? CGSGlobalHotKeyDisable : CGSGlobalHotKeyEnable); -#endif - return true; -} - -#endif // SDL_VIDEO_DRIVER_COCOA -- cgit v1.2.3