21 #include "../../SDL_internal.h" 23 #if SDL_VIDEO_DRIVER_COCOA 27 #include "../../events/SDL_events_c.h" 28 #include "../../events/SDL_keyboard_c.h" 29 #include "../../events/scancodes_darwin.h" 31 #include <Carbon/Carbon.h> 32 #include <IOKit/hid/IOHIDLib.h> 35 #define DEBUG_IME(...) 37 @interface SDLTranslatorResponder : NSView <NSTextInputClient> {
38 NSString *_markedText;
40 NSRange _selectedRange;
43 - (
void)doCommandBySelector:(
SEL)myselector;
47 @implementation SDLTranslatorResponder
54 - (
void)insertText:(
id)aString replacementRange:(NSRange)replacementRange
60 DEBUG_IME(
@"insertText: %@", aString);
64 if ([aString isKindOfClass: [NSAttributedString
class]]) {
65 str = [[aString string] UTF8String];
67 str = [aString UTF8String];
73 - (
void)doCommandBySelector:(
SEL)myselector
83 return _markedText != nil;
86 - (NSRange)markedRange
91 - (NSRange)selectedRange
93 return _selectedRange;
96 - (
void)setMarkedText:(
id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
98 if ([aString isKindOfClass:[NSAttributedString
class]]) {
99 aString = [aString string];
102 if ([aString
length] == 0) {
107 if (_markedText != aString) {
108 [_markedText release];
109 _markedText = [aString retain];
112 _selectedRange = selectedRange;
113 _markedRange = NSMakeRange(0, [aString
length]);
116 (
int) selectedRange.location, (
int) selectedRange.length);
118 DEBUG_IME(
@"setMarkedText: %@, (%d, %d)", _markedText,
119 selRange.location, selRange.length);
124 [_markedText release];
130 - (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
132 NSWindow *
window = [
self window];
133 NSRect contentRect = [window contentRectForFrameRect:[window frame]];
134 float windowHeight = contentRect.size.height;
135 NSRect rect = NSMakeRect(_inputRect.x, windowHeight - _inputRect.y - _inputRect.h,
136 _inputRect.w, _inputRect.h);
139 *actualRange = aRange;
142 DEBUG_IME(
@"firstRectForCharacterRange: (%d, %d): windowHeight = %g, rect = %@",
143 aRange.location, aRange.length, windowHeight,
144 NSStringFromRect(rect));
146 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 147 if (![window respondsToSelector:
@selector(convertRectToScreen:)]) {
148 rect.origin = [window convertBaseToScreen:rect.origin];
152 rect = [window convertRectToScreen:rect];
158 - (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
160 DEBUG_IME(
@"attributedSubstringFromRange: (%d, %d)", aRange.location, aRange.length);
164 - (NSInteger)conversationIdentifier
166 return (NSInteger)
self;
172 - (NSUInteger)characterIndexForPoint:(NSPoint)thePoint
174 DEBUG_IME(
@"characterIndexForPoint: (%g, %g)", thePoint.x, thePoint.y);
183 - (NSArray *)validAttributesForMarkedText
185 return [NSArray array];
196 static IOHIDManagerRef s_hidManager =
NULL;
201 if (context != s_hidManager) {
206 IOHIDElementRef elem = IOHIDValueGetElement(value);
207 if (IOHIDElementGetUsagePage(elem) != kHIDPage_KeyboardOrKeypad
208 || IOHIDElementGetUsage(elem) != kHIDUsage_KeyboardCapsLock) {
211 CFIndex pressed = IOHIDValueGetIntegerValue(value);
215 static CFDictionaryRef
216 CreateHIDDeviceMatchingDictionary(UInt32 usagePage, UInt32
usage)
218 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault,
219 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
221 CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usagePage);
223 CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsagePageKey), number);
225 number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage);
227 CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsageKey), number);
247 IOHIDManagerUnscheduleFromRunLoop(s_hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
248 IOHIDManagerRegisterInputValueCallback(s_hidManager,
NULL,
NULL);
249 IOHIDManagerClose(s_hidManager, 0);
251 CFRelease(s_hidManager);
259 s_hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
263 CFDictionaryRef keyboard =
NULL, keypad =
NULL;
264 CFArrayRef matches =
NULL;
265 keyboard = CreateHIDDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard);
269 keypad = CreateHIDDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keypad);
273 CFDictionaryRef matchesList[] = { keyboard, keypad };
274 matches = CFArrayCreate(kCFAllocatorDefault, (
const void **)matchesList, 2,
NULL);
278 IOHIDManagerSetDeviceMatchingMultiple(s_hidManager, matches);
279 IOHIDManagerRegisterInputValueCallback(s_hidManager, HIDCallback, s_hidManager);
280 IOHIDManagerScheduleWithRunLoop(s_hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
281 if (IOHIDManagerOpen(s_hidManager, kIOHIDOptionsTypeNone) == kIOReturnSuccess) {
305 HandleNonDeviceModifier(
unsigned int device_independent_mask,
306 unsigned int oldMods,
307 unsigned int newMods,
310 unsigned int oldMask, newMask;
315 oldMask = oldMods & device_independent_mask;
316 newMask = newMods & device_independent_mask;
318 if (oldMask && oldMask != newMask) {
320 }
else if (newMask && oldMask != newMask) {
329 HandleModifierOneSide(
unsigned int oldMods,
unsigned int newMods,
331 unsigned int sided_device_dependent_mask)
333 unsigned int old_dep_mask, new_dep_mask;
338 old_dep_mask = oldMods & sided_device_dependent_mask;
339 new_dep_mask = newMods & sided_device_dependent_mask;
345 if (new_dep_mask && old_dep_mask != new_dep_mask) {
357 HandleModifierSide(
int device_independent_mask,
358 unsigned int oldMods,
unsigned int newMods,
361 unsigned int left_device_dependent_mask,
362 unsigned int right_device_dependent_mask)
364 unsigned int device_dependent_mask = (left_device_dependent_mask |
365 right_device_dependent_mask);
366 unsigned int diff_mod;
372 if ((device_dependent_mask & newMods) == 0) {
374 HandleNonDeviceModifier(device_independent_mask, oldMods, newMods, left_scancode);
379 diff_mod = (device_dependent_mask & oldMods) ^
380 (device_dependent_mask & newMods);
386 if (left_device_dependent_mask & diff_mod) {
387 HandleModifierOneSide(oldMods, newMods, left_scancode, left_device_dependent_mask);
389 if (right_device_dependent_mask & diff_mod) {
390 HandleModifierOneSide(oldMods, newMods, right_scancode, right_device_dependent_mask);
401 ReleaseModifierSide(
unsigned int device_independent_mask,
402 unsigned int oldMods,
unsigned int newMods,
405 unsigned int left_device_dependent_mask,
406 unsigned int right_device_dependent_mask)
408 unsigned int device_dependent_mask = (left_device_dependent_mask |
409 right_device_dependent_mask);
415 if ((device_dependent_mask & oldMods) == 0) {
429 if ( left_device_dependent_mask & oldMods ) {
432 if ( right_device_dependent_mask & oldMods ) {
441 DoSidedModifiers(
unsigned short scancode,
442 unsigned int oldMods,
unsigned int newMods)
460 const unsigned int left_device_mapping[] = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK };
461 const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK };
466 for (i = 0, bit = NSEventModifierFlagShift; bit <= NSEventModifierFlagCommand; bit <<= 1, ++i) {
467 unsigned int oldMask, newMask;
469 oldMask = oldMods & bit;
470 newMask = newMods & bit;
476 HandleModifierSide(bit, oldMods, newMods,
477 left_mapping[i], right_mapping[i],
478 left_device_mapping[i], right_device_mapping[i]);
483 else if (oldMask && oldMask != newMask) {
484 ReleaseModifierSide(bit, oldMods, newMods,
485 left_mapping[i], right_mapping[i],
486 left_device_mapping[i], right_device_mapping[i]);
492 HandleModifiers(
_THIS,
unsigned short scancode,
unsigned int modifierFlags)
500 DoSidedModifiers(scancode, data->
modifierFlags, modifierFlags);
507 TISInputSourceRef key_layout;
508 const void *chr_data;
514 key_layout = TISCopyCurrentKeyboardLayoutInputSource();
523 CFDataRef uchrDataRef = TISGetInputSourceProperty(key_layout, kTISPropertyUnicodeKeyLayoutData);
525 chr_data = CFDataGetBytePtr(uchrDataRef);
531 UInt32 keyboard_type = LMGetKbdType();
537 UInt32 dead_key_state;
547 err = UCKeyTranslate ((UCKeyboardLayout *) chr_data,
550 kUCKeyTranslateNoDeadKeysMask,
551 &dead_key_state, 8, &len, s);
556 if (len > 0 && s[0] != 0x10) {
557 keymap[scancode] = s[0];
568 CFRelease(key_layout);
598 NSWindow *nswindow = nil;
603 NSView *parentView = [nswindow contentView];
612 [[SDLTranslatorResponder alloc] initWithFrame: NSMakeRect(0.0, 0.0, 0.0, 0.0)];
615 if (![[data->
fieldEdit superview] isEqual:parentView]) {
617 [data->fieldEdit removeFromSuperview];
618 [parentView addSubview: data->fieldEdit];
619 [nswindow makeFirstResponder: data->fieldEdit];
630 [data->fieldEdit removeFromSuperview];
631 [data->fieldEdit release];
646 [data->fieldEdit setInputRect:rect];
657 unsigned short scancode = [event keyCode];
663 if ((scancode == 10 || scancode == 50) && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) {
665 scancode = 60 - scancode;
675 switch ([event
type]) {
676 case NSEventTypeKeyDown:
677 if (![event isARepeat]) {
685 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);
690 [data->fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]];
692 text = [[event characters] UTF8String];
695 [data->fieldEdit setString:@""];
700 case NSEventTypeKeyUp:
703 case NSEventTypeFlagsChanged:
705 HandleModifiers(
_this, scancode, [event modifierFlags]);
void SDL_GetDefaultKeymap(SDL_Keycode *keymap)
void Cocoa_SetTextInputRect(_THIS, SDL_Rect *rect)
void Cocoa_HandleKeyEvent(_THIS, NSEvent *event)
SDLTranslatorResponder * fieldEdit
static screen_context_t context
#define SDLK_SCANCODE_MASK
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
#define SDL_GetKeyboardFocus
#define SDL_InvalidParamError(param)
unsigned int modifierFlags
void Cocoa_StartTextInput(_THIS)
Sint32 SDL_Keycode
The SDL virtual key representation.
int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
void Cocoa_QuitKeyboard(_THIS)
static SDL_VideoDevice * _this
void SDL_SetKeymap(int start, SDL_Keycode *keys, int length)
static const SDL_Scancode darwin_scancode_table[]
GLsizeiptr const void GLenum usage
int SDL_SendKeyboardText(const char *text)
GLsizei const GLfloat * value
void SDL_SetScancodeName(SDL_Scancode scancode, const char *name)
static const NSUInteger NSEventModifierFlagCapsLock
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
void SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle)
static char text[MAX_TEXT_LENGTH]
int SDL_SendKeymapChangedEvent(void)
EGLSurface EGLNativeWindowType * window
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
The type used to identify a window.
void Cocoa_InitKeyboard(_THIS)
void Cocoa_StopTextInput(_THIS)
GLuint GLuint GLsizei GLenum type
#define SDL_arraysize(array)
GLuint GLsizei GLsizei * length
static void cleanup(void)
SDL_Scancode
The SDL keyboard scancode representation.
int SDL_SendEditingText(const char *text, int start, int length)
A rectangle, with the origin at the upper left.