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 ([window respondsToSelector:
@selector(convertRectToScreen:)]) {
147 rect = [window convertRectToScreen:rect];
149 rect.origin = [window convertBaseToScreen:rect.origin];
155 - (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange;
157 DEBUG_IME(
@"attributedSubstringFromRange: (%d, %d)", aRange.location, aRange.length);
161 - (NSInteger)conversationIdentifier
163 return (NSInteger)
self;
169 - (NSUInteger)characterIndexForPoint:(NSPoint)thePoint
171 DEBUG_IME(
@"characterIndexForPoint: (%g, %g)", thePoint.x, thePoint.y);
180 - (NSArray *)validAttributesForMarkedText
182 return [NSArray array];
193 static IOHIDManagerRef s_hidManager =
NULL;
196 HIDCallback(
void *context, IOReturn
result,
void *sender, IOHIDValueRef
value)
198 if (context != s_hidManager) {
203 IOHIDElementRef elem = IOHIDValueGetElement(value);
204 if (IOHIDElementGetUsagePage(elem) != kHIDPage_KeyboardOrKeypad
205 || IOHIDElementGetUsage(elem) != kHIDUsage_KeyboardCapsLock) {
208 CFIndex pressed = IOHIDValueGetIntegerValue(value);
212 static CFDictionaryRef
213 CreateHIDDeviceMatchingDictionary(UInt32 usagePage, UInt32
usage)
215 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault,
216 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
218 CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usagePage);
220 CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsagePageKey), number);
222 number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage);
224 CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsageKey), number);
244 IOHIDManagerUnscheduleFromRunLoop(s_hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
245 IOHIDManagerRegisterInputValueCallback(s_hidManager,
NULL,
NULL);
246 IOHIDManagerClose(s_hidManager, 0);
248 CFRelease(s_hidManager);
256 s_hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
260 CFDictionaryRef keyboard =
NULL, keypad =
NULL;
261 CFArrayRef matches =
NULL;
262 keyboard = CreateHIDDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard);
266 keypad = CreateHIDDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keypad);
270 CFDictionaryRef matchesList[] = { keyboard, keypad };
271 matches = CFArrayCreate(kCFAllocatorDefault, (
const void **)matchesList, 2,
NULL);
275 IOHIDManagerSetDeviceMatchingMultiple(s_hidManager, matches);
276 IOHIDManagerRegisterInputValueCallback(s_hidManager, HIDCallback, s_hidManager);
277 IOHIDManagerScheduleWithRunLoop(s_hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
278 if (IOHIDManagerOpen(s_hidManager, kIOHIDOptionsTypeNone) == kIOReturnSuccess) {
302 HandleNonDeviceModifier(
unsigned int device_independent_mask,
303 unsigned int oldMods,
304 unsigned int newMods,
307 unsigned int oldMask, newMask;
312 oldMask = oldMods & device_independent_mask;
313 newMask = newMods & device_independent_mask;
315 if (oldMask && oldMask != newMask) {
317 }
else if (newMask && oldMask != newMask) {
326 HandleModifierOneSide(
unsigned int oldMods,
unsigned int newMods,
328 unsigned int sided_device_dependent_mask)
330 unsigned int old_dep_mask, new_dep_mask;
335 old_dep_mask = oldMods & sided_device_dependent_mask;
336 new_dep_mask = newMods & sided_device_dependent_mask;
342 if (new_dep_mask && old_dep_mask != new_dep_mask) {
354 HandleModifierSide(
int device_independent_mask,
355 unsigned int oldMods,
unsigned int newMods,
358 unsigned int left_device_dependent_mask,
359 unsigned int right_device_dependent_mask)
361 unsigned int device_dependent_mask = (left_device_dependent_mask |
362 right_device_dependent_mask);
363 unsigned int diff_mod;
369 if ((device_dependent_mask & newMods) == 0) {
371 HandleNonDeviceModifier(device_independent_mask, oldMods, newMods, left_scancode);
376 diff_mod = (device_dependent_mask & oldMods) ^
377 (device_dependent_mask & newMods);
383 if (left_device_dependent_mask & diff_mod) {
384 HandleModifierOneSide(oldMods, newMods, left_scancode, left_device_dependent_mask);
386 if (right_device_dependent_mask & diff_mod) {
387 HandleModifierOneSide(oldMods, newMods, right_scancode, right_device_dependent_mask);
398 ReleaseModifierSide(
unsigned int device_independent_mask,
399 unsigned int oldMods,
unsigned int newMods,
402 unsigned int left_device_dependent_mask,
403 unsigned int right_device_dependent_mask)
405 unsigned int device_dependent_mask = (left_device_dependent_mask |
406 right_device_dependent_mask);
412 if ((device_dependent_mask & oldMods) == 0) {
426 if ( left_device_dependent_mask & oldMods ) {
429 if ( right_device_dependent_mask & oldMods ) {
438 DoSidedModifiers(
unsigned short scancode,
439 unsigned int oldMods,
unsigned int newMods)
457 const unsigned int left_device_mapping[] = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK };
458 const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK };
463 for (i = 0, bit = NSShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
464 unsigned int oldMask, newMask;
466 oldMask = oldMods & bit;
467 newMask = newMods & bit;
473 HandleModifierSide(bit, oldMods, newMods,
474 left_mapping[i], right_mapping[i],
475 left_device_mapping[i], right_device_mapping[i]);
480 else if (oldMask && oldMask != newMask) {
481 ReleaseModifierSide(bit, oldMods, newMods,
482 left_mapping[i], right_mapping[i],
483 left_device_mapping[i], right_device_mapping[i]);
489 HandleModifiers(
_THIS,
unsigned short scancode,
unsigned int modifierFlags)
497 DoSidedModifiers(scancode, data->
modifierFlags, modifierFlags);
504 TISInputSourceRef key_layout;
505 const void *chr_data;
511 key_layout = TISCopyCurrentKeyboardLayoutInputSource();
520 CFDataRef uchrDataRef = TISGetInputSourceProperty(key_layout, kTISPropertyUnicodeKeyLayoutData);
522 chr_data = CFDataGetBytePtr(uchrDataRef);
528 UInt32 keyboard_type = LMGetKbdType();
534 UInt32 dead_key_state;
544 err = UCKeyTranslate ((UCKeyboardLayout *) chr_data,
547 kUCKeyTranslateNoDeadKeysMask,
548 &dead_key_state, 8, &len, s);
553 if (len > 0 && s[0] != 0x10) {
554 keymap[scancode] = s[0];
565 CFRelease(key_layout);
595 NSWindow *nswindow = nil;
600 NSView *parentView = [nswindow contentView];
609 [[SDLTranslatorResponder alloc] initWithFrame: NSMakeRect(0.0, 0.0, 0.0, 0.0)];
612 if (![[data->
fieldEdit superview] isEqual:parentView]) {
614 [data->fieldEdit removeFromSuperview];
615 [parentView addSubview: data->fieldEdit];
616 [nswindow makeFirstResponder: data->fieldEdit];
627 [data->fieldEdit removeFromSuperview];
628 [data->fieldEdit release];
643 [data->fieldEdit setInputRect:rect];
654 unsigned short scancode = [event keyCode];
660 if ((scancode == 10 || scancode == 50) && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) {
662 scancode = 60 - scancode;
672 switch ([event
type]) {
674 if (![event isARepeat]) {
682 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);
687 [data->fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]];
689 text = [[event characters] UTF8String];
692 [data->fieldEdit setString:@""];
702 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 SDL_Window * window
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
#define SDLK_SCANCODE_MASK
#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[]
GLuint GLuint GLsizei GLenum type
GLsizeiptr const void GLenum usage
GLsizei const GLfloat * value
int SDL_SendKeyboardText(const char *text)
void SDL_SetScancodeName(SDL_Scancode scancode, const char *name)
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]
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
int SDL_SendKeymapChangedEvent(void)
The type used to identify a window.
void Cocoa_InitKeyboard(_THIS)
void Cocoa_StopTextInput(_THIS)
#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.