summaryrefslogtreecommitdiff
path: root/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoakeyboard.m
diff options
context:
space:
mode:
Diffstat (limited to 'source/3rd-party/SDL2/src/video/cocoa/SDL_cocoakeyboard.m')
-rw-r--r--source/3rd-party/SDL2/src/video/cocoa/SDL_cocoakeyboard.m720
1 files changed, 720 insertions, 0 deletions
diff --git a/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoakeyboard.m b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoakeyboard.m
new file mode 100644
index 0000000..8436047
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/cocoa/SDL_cocoakeyboard.m
@@ -0,0 +1,720 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ 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"
+
+#if 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 <Carbon/Carbon.h>
+#include <IOKit/hid/IOHIDLib.h>
+
+/*#define DEBUG_IME NSLog */
+#define DEBUG_IME(...)
+
+@interface SDLTranslatorResponder : NSView <NSTextInputClient> {
+ NSString *_markedText;
+ NSRange _markedRange;
+ NSRange _selectedRange;
+ SDL_Rect _inputRect;
+}
+- (void)doCommandBySelector:(SEL)myselector;
+- (void)setInputRect:(SDL_Rect *)rect;
+@end
+
+@implementation SDLTranslatorResponder
+
+- (void)setInputRect:(SDL_Rect *)rect
+{
+ _inputRect = *rect;
+}
+
+- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange
+{
+ /* TODO: Make use of replacementRange? */
+
+ const char *str;
+
+ DEBUG_IME(@"insertText: %@", aString);
+
+ /* 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];
+ }
+
+ 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 release];
+ _markedText = [aString retain];
+ }
+
+ _selectedRange = selectedRange;
+ _markedRange = NSMakeRange(0, [aString length]);
+
+ SDL_SendEditingText([aString UTF8String],
+ (int) selectedRange.location, (int) selectedRange.length);
+
+ DEBUG_IME(@"setMarkedText: %@, (%d, %d)", _markedText,
+ selRange.location, selRange.length);
+}
+
+- (void)unmarkText
+{
+ [_markedText release];
+ _markedText = nil;
+
+ 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 = %@",
+ aRange.location, aRange.length, windowHeight,
+ NSStringFromRect(rect));
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
+ if (![window respondsToSelector:@selector(convertRectToScreen:)]) {
+ rect.origin = [window convertBaseToScreen:rect.origin];
+ } else
+#endif
+ {
+ rect = [window convertRectToScreen:rect];
+ }
+
+ return rect;
+}
+
+- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
+{
+ DEBUG_IME(@"attributedSubstringFromRange: (%d, %d)", aRange.location, 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];
+}
+
+@end
+
+/*------------------------------------------------------------------------------
+Set up a HID callback to properly detect Caps Lock up/down events.
+Derived from:
+http://stackoverflow.com/questions/7190852/using-iohidmanager-to-get-modifier-key-events
+*/
+
+static IOHIDManagerRef s_hidManager = NULL;
+
+static void
+HIDCallback(void *context, IOReturn result, void *sender, IOHIDValueRef value)
+{
+ if (context != s_hidManager) {
+ /* An old callback, ignore it (related to bug 2157 below) */
+ return;
+ }
+
+ IOHIDElementRef elem = IOHIDValueGetElement(value);
+ if (IOHIDElementGetUsagePage(elem) != kHIDPage_KeyboardOrKeypad
+ || IOHIDElementGetUsage(elem) != kHIDUsage_KeyboardCapsLock) {
+ return;
+ }
+ CFIndex pressed = IOHIDValueGetIntegerValue(value);
+ SDL_SendKeyboardKey(pressed ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_CAPSLOCK);
+}
+
+static CFDictionaryRef
+CreateHIDDeviceMatchingDictionary(UInt32 usagePage, UInt32 usage)
+{
+ CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault,
+ 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (dict) {
+ CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usagePage);
+ if (number) {
+ CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsagePageKey), number);
+ CFRelease(number);
+ number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage);
+ if (number) {
+ CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsageKey), number);
+ CFRelease(number);
+ return dict;
+ }
+ }
+ CFRelease(dict);
+ }
+ return NULL;
+}
+
+static void
+QuitHIDCallback()
+{
+ if (!s_hidManager) {
+ return;
+ }
+
+#if 0 /* Releasing here causes a crash on Mac OS X 10.10 and earlier,
+ * so just leak it for now. See bug 2157 for details.
+ */
+ IOHIDManagerUnscheduleFromRunLoop(s_hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
+ IOHIDManagerRegisterInputValueCallback(s_hidManager, NULL, NULL);
+ IOHIDManagerClose(s_hidManager, 0);
+
+ CFRelease(s_hidManager);
+#endif
+ s_hidManager = NULL;
+}
+
+static void
+InitHIDCallback()
+{
+ s_hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
+ if (!s_hidManager) {
+ return;
+ }
+ CFDictionaryRef keyboard = NULL, keypad = NULL;
+ CFArrayRef matches = NULL;
+ keyboard = CreateHIDDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard);
+ if (!keyboard) {
+ goto fail;
+ }
+ keypad = CreateHIDDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keypad);
+ if (!keypad) {
+ goto fail;
+ }
+ CFDictionaryRef matchesList[] = { keyboard, keypad };
+ matches = CFArrayCreate(kCFAllocatorDefault, (const void **)matchesList, 2, NULL);
+ if (!matches) {
+ goto fail;
+ }
+ IOHIDManagerSetDeviceMatchingMultiple(s_hidManager, matches);
+ IOHIDManagerRegisterInputValueCallback(s_hidManager, HIDCallback, s_hidManager);
+ IOHIDManagerScheduleWithRunLoop(s_hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
+ if (IOHIDManagerOpen(s_hidManager, kIOHIDOptionsTypeNone) == kIOReturnSuccess) {
+ goto cleanup;
+ }
+
+fail:
+ QuitHIDCallback();
+
+cleanup:
+ if (matches) {
+ CFRelease(matches);
+ }
+ if (keypad) {
+ CFRelease(keypad);
+ }
+ if (keyboard) {
+ CFRelease(keyboard);
+ }
+}
+
+/* This is a helper function for HandleModifierSide. This
+ * function reverts back to behavior before the distinction between
+ * sides was made.
+ */
+static void
+HandleNonDeviceModifier(unsigned int device_independent_mask,
+ unsigned int oldMods,
+ unsigned int newMods,
+ SDL_Scancode scancode)
+{
+ unsigned int oldMask, newMask;
+
+ /* Isolate just the bits we care about in the depedent bits so we can
+ * figure out what changed
+ */
+ oldMask = oldMods & device_independent_mask;
+ newMask = newMods & device_independent_mask;
+
+ if (oldMask && oldMask != newMask) {
+ SDL_SendKeyboardKey(SDL_RELEASED, scancode);
+ } else if (newMask && oldMask != newMask) {
+ SDL_SendKeyboardKey(SDL_PRESSED, scancode);
+ }
+}
+
+/* This is a helper function for HandleModifierSide.
+ * This function sets the actual SDL_PrivateKeyboard event.
+ */
+static void
+HandleModifierOneSide(unsigned int oldMods, unsigned int newMods,
+ SDL_Scancode scancode,
+ unsigned int sided_device_dependent_mask)
+{
+ unsigned int old_dep_mask, new_dep_mask;
+
+ /* Isolate just the bits we care about in the depedent bits so we can
+ * figure out what changed
+ */
+ old_dep_mask = oldMods & sided_device_dependent_mask;
+ new_dep_mask = newMods & sided_device_dependent_mask;
+
+ /* We now know that this side bit flipped. But we don't know if
+ * it went pressed to released or released to pressed, so we must
+ * find out which it is.
+ */
+ if (new_dep_mask && old_dep_mask != new_dep_mask) {
+ SDL_SendKeyboardKey(SDL_PRESSED, scancode);
+ } else {
+ SDL_SendKeyboardKey(SDL_RELEASED, scancode);
+ }
+}
+
+/* This is a helper function for DoSidedModifiers.
+ * This function will figure out if the modifier key is the left or right side,
+ * e.g. left-shift vs right-shift.
+ */
+static void
+HandleModifierSide(int device_independent_mask,
+ unsigned int oldMods, unsigned int newMods,
+ SDL_Scancode left_scancode,
+ SDL_Scancode right_scancode,
+ unsigned int left_device_dependent_mask,
+ unsigned int right_device_dependent_mask)
+{
+ unsigned int device_dependent_mask = (left_device_dependent_mask |
+ right_device_dependent_mask);
+ unsigned int diff_mod;
+
+ /* On the basis that the device independent mask is set, but there are
+ * no device dependent flags set, we'll assume that we can't detect this
+ * keyboard and revert to the unsided behavior.
+ */
+ if ((device_dependent_mask & newMods) == 0) {
+ /* Revert to the old behavior */
+ HandleNonDeviceModifier(device_independent_mask, oldMods, newMods, left_scancode);
+ return;
+ }
+
+ /* XOR the previous state against the new state to see if there's a change */
+ diff_mod = (device_dependent_mask & oldMods) ^
+ (device_dependent_mask & newMods);
+ if (diff_mod) {
+ /* A change in state was found. Isolate the left and right bits
+ * to handle them separately just in case the values can simulataneously
+ * change or if the bits don't both exist.
+ */
+ if (left_device_dependent_mask & diff_mod) {
+ HandleModifierOneSide(oldMods, newMods, left_scancode, left_device_dependent_mask);
+ }
+ if (right_device_dependent_mask & diff_mod) {
+ HandleModifierOneSide(oldMods, newMods, right_scancode, right_device_dependent_mask);
+ }
+ }
+}
+
+/* This is a helper function for DoSidedModifiers.
+ * This function will release a key press in the case that
+ * it is clear that the modifier has been released (i.e. one side
+ * can't still be down).
+ */
+static void
+ReleaseModifierSide(unsigned int device_independent_mask,
+ unsigned int oldMods, unsigned int newMods,
+ SDL_Scancode left_scancode,
+ SDL_Scancode right_scancode,
+ unsigned int left_device_dependent_mask,
+ unsigned int right_device_dependent_mask)
+{
+ unsigned int device_dependent_mask = (left_device_dependent_mask |
+ right_device_dependent_mask);
+
+ /* On the basis that the device independent mask is set, but there are
+ * no device dependent flags set, we'll assume that we can't detect this
+ * keyboard and revert to the unsided behavior.
+ */
+ if ((device_dependent_mask & oldMods) == 0) {
+ /* In this case, we can't detect the keyboard, so use the left side
+ * to represent both, and release it.
+ */
+ SDL_SendKeyboardKey(SDL_RELEASED, left_scancode);
+ return;
+ }
+
+ /*
+ * This could have been done in an if-else case because at this point,
+ * we know that all keys have been released when calling this function.
+ * But I'm being paranoid so I want to handle each separately,
+ * so I hope this doesn't cause other problems.
+ */
+ if ( left_device_dependent_mask & oldMods ) {
+ SDL_SendKeyboardKey(SDL_RELEASED, left_scancode);
+ }
+ if ( right_device_dependent_mask & oldMods ) {
+ SDL_SendKeyboardKey(SDL_RELEASED, right_scancode);
+ }
+}
+
+/* This function will handle the modifier keys and also determine the
+ * correct side of the key.
+ */
+static void
+DoSidedModifiers(unsigned short scancode,
+ unsigned int oldMods, unsigned int newMods)
+{
+ /* Set up arrays for the key syms for the left and right side. */
+ const SDL_Scancode left_mapping[] = {
+ SDL_SCANCODE_LSHIFT,
+ SDL_SCANCODE_LCTRL,
+ SDL_SCANCODE_LALT,
+ SDL_SCANCODE_LGUI
+ };
+ const SDL_Scancode right_mapping[] = {
+ SDL_SCANCODE_RSHIFT,
+ SDL_SCANCODE_RCTRL,
+ SDL_SCANCODE_RALT,
+ SDL_SCANCODE_RGUI
+ };
+ /* Set up arrays for the device dependent masks with indices that
+ * correspond to the _mapping arrays
+ */
+ const unsigned int left_device_mapping[] = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK };
+ const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK };
+
+ unsigned int i, bit;
+
+ /* Iterate through the bits, testing each against the old modifiers */
+ for (i = 0, bit = NSEventModifierFlagShift; bit <= NSEventModifierFlagCommand; bit <<= 1, ++i) {
+ unsigned int oldMask, newMask;
+
+ oldMask = oldMods & bit;
+ newMask = newMods & bit;
+
+ /* If the bit is set, we must always examine it because the left
+ * and right side keys may alternate or both may be pressed.
+ */
+ if (newMask) {
+ HandleModifierSide(bit, oldMods, newMods,
+ left_mapping[i], right_mapping[i],
+ left_device_mapping[i], right_device_mapping[i]);
+ }
+ /* If the state changed from pressed to unpressed, we must examine
+ * the device dependent bits to release the correct keys.
+ */
+ else if (oldMask && oldMask != newMask) {
+ ReleaseModifierSide(bit, oldMods, newMods,
+ left_mapping[i], right_mapping[i],
+ left_device_mapping[i], right_device_mapping[i]);
+ }
+ }
+}
+
+static void
+HandleModifiers(_THIS, unsigned short scancode, unsigned int modifierFlags)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+ if (modifierFlags == data->modifierFlags) {
+ return;
+ }
+
+ DoSidedModifiers(scancode, data->modifierFlags, modifierFlags);
+ data->modifierFlags = modifierFlags;
+}
+
+static void
+UpdateKeymap(SDL_VideoData *data, SDL_bool send_event)
+{
+ TISInputSourceRef key_layout;
+ const void *chr_data;
+ int i;
+ SDL_Scancode scancode;
+ SDL_Keycode keymap[SDL_NUM_SCANCODES];
+
+ /* See if the keymap needs to be updated */
+ key_layout = TISCopyCurrentKeyboardLayoutInputSource();
+ if (key_layout == data->key_layout) {
+ return;
+ }
+ data->key_layout = key_layout;
+
+ SDL_GetDefaultKeymap(keymap);
+
+ /* Try Unicode data first */
+ CFDataRef uchrDataRef = TISGetInputSourceProperty(key_layout, kTISPropertyUnicodeKeyLayoutData);
+ if (uchrDataRef) {
+ chr_data = CFDataGetBytePtr(uchrDataRef);
+ } else {
+ goto cleanup;
+ }
+
+ if (chr_data) {
+ UInt32 keyboard_type = LMGetKbdType();
+ OSStatus err;
+
+ for (i = 0; i < SDL_arraysize(darwin_scancode_table); i++) {
+ UniChar s[8];
+ UniCharCount len;
+ UInt32 dead_key_state;
+
+ /* Make sure this scancode is a valid character scancode */
+ scancode = darwin_scancode_table[i];
+ if (scancode == SDL_SCANCODE_UNKNOWN ||
+ (keymap[scancode] & SDLK_SCANCODE_MASK)) {
+ continue;
+ }
+
+ dead_key_state = 0;
+ err = UCKeyTranslate ((UCKeyboardLayout *) chr_data,
+ i, kUCKeyActionDown,
+ 0, keyboard_type,
+ kUCKeyTranslateNoDeadKeysMask,
+ &dead_key_state, 8, &len, s);
+ if (err != noErr) {
+ continue;
+ }
+
+ if (len > 0 && s[0] != 0x10) {
+ keymap[scancode] = s[0];
+ }
+ }
+ SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES);
+ if (send_event) {
+ SDL_SendKeymapChangedEvent();
+ }
+ return;
+ }
+
+cleanup:
+ CFRelease(key_layout);
+}
+
+void
+Cocoa_InitKeyboard(_THIS)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+ UpdateKeymap(data, SDL_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 = [NSEvent modifierFlags];
+ SDL_ToggleModState(KMOD_CAPS, (data->modifierFlags & NSEventModifierFlagCapsLock) != 0);
+
+ InitHIDCallback();
+}
+
+void
+Cocoa_StartTextInput(_THIS)
+{ @autoreleasepool
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ SDL_Window *window = SDL_GetKeyboardFocus();
+ NSWindow *nswindow = nil;
+ if (window) {
+ nswindow = ((SDL_WindowData*)window->driverdata)->nswindow;
+ }
+
+ NSView *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 =
+ [[SDLTranslatorResponder 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];
+ }
+}}
+
+void
+Cocoa_StopTextInput(_THIS)
+{ @autoreleasepool
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+ if (data && data->fieldEdit) {
+ [data->fieldEdit removeFromSuperview];
+ [data->fieldEdit release];
+ data->fieldEdit = nil;
+ }
+}}
+
+void
+Cocoa_SetTextInputRect(_THIS, SDL_Rect *rect)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+ if (!rect) {
+ SDL_InvalidParamError("rect");
+ return;
+ }
+
+ [data->fieldEdit setInputRect:rect];
+}
+
+void
+Cocoa_HandleKeyEvent(_THIS, NSEvent *event)
+{
+ SDL_VideoData *data = _this ? ((SDL_VideoData *) _this->driverdata) : NULL;
+ if (!data) {
+ return; /* can happen when returning from fullscreen Space on shutdown */
+ }
+
+ unsigned short scancode = [event keyCode];
+ SDL_Scancode code;
+#if 0
+ const char *text;
+#endif
+
+ if ((scancode == 10 || scancode == 50) && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) {
+ /* see comments in SDL_cocoakeys.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, SDL_TRUE);
+ }
+
+ SDL_SendKeyboardKey(SDL_PRESSED, code);
+#if 1
+ if (code == SDL_SCANCODE_UNKNOWN) {
+ fprintf(stderr, "The key you just pressed is not recognized by SDL. To help get this fixed, report this to the SDL forums/mailing list <https://discourse.libsdl.org/> or to Christian Walther <cwalther@gmx.ch>. Mac virtual key code is %d.\n", scancode);
+ }
+#endif
+ if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
+ /* FIXME CW 2007-08-16: only send those events to the field editor for which we actually want text events, not e.g. esc or function keys. Arrow keys in particular seem to produce crashes sometimes. */
+ [data->fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]];
+#if 0
+ text = [[event characters] UTF8String];
+ if(text && *text) {
+ SDL_SendKeyboardText(text);
+ [data->fieldEdit setString:@""];
+ }
+#endif
+ }
+ break;
+ case NSEventTypeKeyUp:
+ SDL_SendKeyboardKey(SDL_RELEASED, code);
+ break;
+ case NSEventTypeFlagsChanged:
+ /* FIXME CW 2007-08-14: check if this whole mess that takes up half of this file is really necessary */
+ HandleModifiers(_this, scancode, [event modifierFlags]);
+ break;
+ default: /* just to avoid compiler warnings */
+ break;
+ }
+}
+
+void
+Cocoa_QuitKeyboard(_THIS)
+{
+ QuitHIDCallback();
+}
+
+#endif /* SDL_VIDEO_DRIVER_COCOA */
+
+/* vi: set ts=4 sw=4 expandtab: */