mirror of https://github.com/encounter/SDL.git
608 lines
19 KiB
Mathematica
608 lines
19 KiB
Mathematica
|
/*
|
||
|
Simple DirectMedia Layer
|
||
|
Copyright (C) 1997-2015 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_keyboard_c.h"
|
||
|
#include "../../events/scancodes_darwin.h"
|
||
|
|
||
|
#include <Carbon/Carbon.h>
|
||
|
|
||
|
/*#define DEBUG_IME NSLog */
|
||
|
#define DEBUG_IME(...)
|
||
|
|
||
|
@interface SDLTranslatorResponder : NSView <NSTextInput> {
|
||
|
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
|
||
|
{
|
||
|
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) selRange
|
||
|
{
|
||
|
if ([aString isKindOfClass: [NSAttributedString class]]) {
|
||
|
aString = [aString string];
|
||
|
}
|
||
|
|
||
|
if ([aString length] == 0) {
|
||
|
[self unmarkText];
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (_markedText != aString) {
|
||
|
[_markedText release];
|
||
|
_markedText = [aString retain];
|
||
|
}
|
||
|
|
||
|
_selectedRange = selRange;
|
||
|
_markedRange = NSMakeRange(0, [aString length]);
|
||
|
|
||
|
SDL_SendEditingText([aString UTF8String],
|
||
|
selRange.location, selRange.length);
|
||
|
|
||
|
DEBUG_IME(@"setMarkedText: %@, (%d, %d)", _markedText,
|
||
|
selRange.location, selRange.length);
|
||
|
}
|
||
|
|
||
|
- (void) unmarkText
|
||
|
{
|
||
|
[_markedText release];
|
||
|
_markedText = nil;
|
||
|
|
||
|
SDL_SendEditingText("", 0, 0);
|
||
|
}
|
||
|
|
||
|
- (NSRect) firstRectForCharacterRange: (NSRange) theRange
|
||
|
{
|
||
|
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);
|
||
|
|
||
|
DEBUG_IME(@"firstRectForCharacterRange: (%d, %d): windowHeight = %g, rect = %@",
|
||
|
theRange.location, theRange.length, windowHeight,
|
||
|
NSStringFromRect(rect));
|
||
|
rect.origin = [[self window] convertBaseToScreen: rect.origin];
|
||
|
|
||
|
return rect;
|
||
|
}
|
||
|
|
||
|
- (NSAttributedString *) attributedSubstringFromRange: (NSRange) theRange
|
||
|
{
|
||
|
DEBUG_IME(@"attributedSubstringFromRange: (%d, %d)", theRange.location, theRange.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
|
||
|
|
||
|
/* 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 is a helper function for DoSidedModifiers.
|
||
|
* This function handles the CapsLock case.
|
||
|
*/
|
||
|
static void
|
||
|
HandleCapsLock(unsigned short scancode,
|
||
|
unsigned int oldMods, unsigned int newMods)
|
||
|
{
|
||
|
unsigned int oldMask, newMask;
|
||
|
|
||
|
oldMask = oldMods & NSAlphaShiftKeyMask;
|
||
|
newMask = newMods & NSAlphaShiftKeyMask;
|
||
|
|
||
|
if (oldMask != newMask) {
|
||
|
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_CAPSLOCK);
|
||
|
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_CAPSLOCK);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* 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;
|
||
|
|
||
|
/* Handle CAPSLOCK separately because it doesn't have a left/right side */
|
||
|
HandleCapsLock(scancode, oldMods, newMods);
|
||
|
|
||
|
/* Iterate through the bits, testing each against the old modifiers */
|
||
|
for (i = 0, bit = NSShiftKeyMask; bit <= NSCommandKeyMask; 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)
|
||
|
{
|
||
|
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);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
cleanup:
|
||
|
CFRelease(key_layout);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
Cocoa_InitKeyboard(_THIS)
|
||
|
{
|
||
|
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
||
|
|
||
|
UpdateKeymap(data);
|
||
|
|
||
|
/* 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");
|
||
|
}
|
||
|
|
||
|
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 = (SDL_VideoData *) _this->driverdata;
|
||
|
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 NSKeyDown:
|
||
|
if (![event isARepeat]) {
|
||
|
/* See if we need to rebuild the keyboard layout */
|
||
|
UpdateKeymap(data);
|
||
|
}
|
||
|
|
||
|
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 mailing list <sdl@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 NSKeyUp:
|
||
|
SDL_SendKeyboardKey(SDL_RELEASED, code);
|
||
|
break;
|
||
|
case NSFlagsChanged:
|
||
|
/* 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)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
||
|
|
||
|
/* vi: set ts=4 sw=4 expandtab: */
|