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>
36@interface SDLTranslatorResponder : NSView <NSTextInputClient> {
37 NSString *_markedText;
39 NSRange _selectedRange;
42- (
void)doCommandBySelector:(
SEL)myselector;
46@implementation SDLTranslatorResponder
53- (
void)insertText:(
id)aString replacementRange:(NSRange)replacementRange
59 DEBUG_IME(
@"insertText: %@", aString);
63 if ([aString isKindOfClass: [NSAttributedString
class]]) {
64 str = [[aString string] UTF8String];
66 str = [aString UTF8String];
72- (
void)doCommandBySelector:(
SEL)myselector
82 return _markedText != nil;
90- (NSRange)selectedRange
92 return _selectedRange;
95- (
void)setMarkedText:(
id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
97 if ([aString isKindOfClass:[NSAttributedString
class]]) {
98 aString = [aString string];
101 if ([aString
length] == 0) {
106 if (_markedText != aString) {
107 [_markedText release];
108 _markedText = [aString retain];
111 _selectedRange = selectedRange;
112 _markedRange = NSMakeRange(0, [aString
length]);
115 (
int) selectedRange.location, (
int) selectedRange.length);
117 DEBUG_IME(
@"setMarkedText: %@, (%d, %d)", _markedText,
118 selRange.location, selRange.length);
123 [_markedText release];
129- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
131 NSWindow *
window = [
self window];
132 NSRect contentRect = [window contentRectForFrameRect:[window frame]];
133 float windowHeight = contentRect.size.height;
134 NSRect
rect = NSMakeRect(_inputRect.x, windowHeight - _inputRect.y - _inputRect.h,
135 _inputRect.w, _inputRect.h);
138 *actualRange = aRange;
141 DEBUG_IME(
@"firstRectForCharacterRange: (%d, %d): windowHeight = %g, rect = %@",
142 aRange.location, aRange.length, windowHeight,
143 NSStringFromRect(
rect));
145#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
146 if (![
window respondsToSelector:
@selector(convertRectToScreen:)]) {
147 rect.origin = [window convertBaseToScreen:rect.origin];
151 rect = [window convertRectToScreen:rect];
157- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
159 DEBUG_IME(
@"attributedSubstringFromRange: (%d, %d)", aRange.location, aRange.length);
163- (NSInteger)conversationIdentifier
165 return (NSInteger)
self;
171- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint
173 DEBUG_IME(
@"characterIndexForPoint: (%g, %g)", thePoint.x, thePoint.y);
182- (NSArray *)validAttributesForMarkedText
184 return [NSArray array];
195HandleNonDeviceModifier(
unsigned int device_independent_mask,
196 unsigned int oldMods,
197 unsigned int newMods,
200 unsigned int oldMask, newMask;
205 oldMask = oldMods & device_independent_mask;
206 newMask = newMods & device_independent_mask;
208 if (oldMask && oldMask != newMask) {
210 }
else if (newMask && oldMask != newMask) {
219HandleModifierOneSide(
unsigned int oldMods,
unsigned int newMods,
221 unsigned int sided_device_dependent_mask)
223 unsigned int old_dep_mask, new_dep_mask;
228 old_dep_mask = oldMods & sided_device_dependent_mask;
229 new_dep_mask = newMods & sided_device_dependent_mask;
235 if (new_dep_mask && old_dep_mask != new_dep_mask) {
247HandleModifierSide(
int device_independent_mask,
248 unsigned int oldMods,
unsigned int newMods,
251 unsigned int left_device_dependent_mask,
252 unsigned int right_device_dependent_mask)
254 unsigned int device_dependent_mask = (left_device_dependent_mask |
255 right_device_dependent_mask);
256 unsigned int diff_mod;
262 if ((device_dependent_mask & newMods) == 0) {
264 HandleNonDeviceModifier(device_independent_mask, oldMods, newMods, left_scancode);
269 diff_mod = (device_dependent_mask & oldMods) ^
270 (device_dependent_mask & newMods);
276 if (left_device_dependent_mask & diff_mod) {
277 HandleModifierOneSide(oldMods, newMods, left_scancode, left_device_dependent_mask);
279 if (right_device_dependent_mask & diff_mod) {
280 HandleModifierOneSide(oldMods, newMods, right_scancode, right_device_dependent_mask);
291ReleaseModifierSide(
unsigned int device_independent_mask,
292 unsigned int oldMods,
unsigned int newMods,
295 unsigned int left_device_dependent_mask,
296 unsigned int right_device_dependent_mask)
298 unsigned int device_dependent_mask = (left_device_dependent_mask |
299 right_device_dependent_mask);
305 if ((device_dependent_mask & oldMods) == 0) {
319 if ( left_device_dependent_mask & oldMods ) {
322 if ( right_device_dependent_mask & oldMods ) {
331DoSidedModifiers(
unsigned short scancode,
332 unsigned int oldMods,
unsigned int newMods)
350 const unsigned int left_device_mapping[] = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK };
351 const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK };
356 for (
i = 0, bit = NSEventModifierFlagShift; bit <= NSEventModifierFlagCommand; bit <<= 1, ++
i) {
357 unsigned int oldMask, newMask;
359 oldMask = oldMods & bit;
360 newMask = newMods & bit;
366 HandleModifierSide(bit, oldMods, newMods,
367 left_mapping[
i], right_mapping[
i],
368 left_device_mapping[
i], right_device_mapping[
i]);
373 else if (oldMask && oldMask != newMask) {
374 ReleaseModifierSide(bit, oldMods, newMods,
375 left_mapping[
i], right_mapping[
i],
376 left_device_mapping[
i], right_device_mapping[
i]);
382HandleModifiers(
_THIS,
unsigned short scancode,
unsigned int modifierFlags)
386 if (modifierFlags ==
data->modifierFlags) {
390 DoSidedModifiers(scancode,
data->modifierFlags, modifierFlags);
391 data->modifierFlags = modifierFlags;
397 TISInputSourceRef key_layout;
398 const void *chr_data;
404 key_layout = TISCopyCurrentKeyboardLayoutInputSource();
405 if (key_layout ==
data->key_layout) {
408 data->key_layout = key_layout;
413 CFDataRef uchrDataRef = TISGetInputSourceProperty(key_layout, kTISPropertyUnicodeKeyLayoutData);
415 chr_data = CFDataGetBytePtr(uchrDataRef);
421 UInt32 keyboard_type = LMGetKbdType();
427 UInt32 dead_key_state;
437 err = UCKeyTranslate ((UCKeyboardLayout *) chr_data,
440 kUCKeyTranslateNoDeadKeysMask,
441 &dead_key_state, 8, &
len,
s);
446 if (
len > 0 &&
s[0] != 0x10) {
447 keymap[scancode] =
s[0];
458 CFRelease(key_layout);
476 data->modifierFlags = [NSEvent modifierFlags];
486 NSWindow *nswindow = nil;
491 NSView *parentView = [nswindow contentView];
498 if (!
data->fieldEdit) {
500 [[SDLTranslatorResponder alloc] initWithFrame: NSMakeRect(0.0, 0.0, 0.0, 0.0)];
503 if (![[
data->fieldEdit superview] isEqual:parentView]) {
505 [data->fieldEdit removeFromSuperview];
506 [parentView addSubview: data->fieldEdit];
507 [nswindow makeFirstResponder: data->fieldEdit];
518 [data->fieldEdit removeFromSuperview];
519 [data->fieldEdit release];
520 data->fieldEdit = nil;
534 [data->fieldEdit setInputRect:rect];
545 unsigned short scancode = [event keyCode];
551 if ((scancode == 10 || scancode == 50) && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) {
553 scancode = 60 - scancode;
564 case NSEventTypeKeyDown:
565 if (![
event isARepeat]) {
573 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);
578 [data->fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]];
580 text = [[event characters] UTF8String];
583 [data->fieldEdit setString:@""];
588 case NSEventTypeKeyUp:
591 case NSEventTypeFlagsChanged:
593 HandleModifiers(
_this, scancode, [
event modifierFlags]);
void Cocoa_QuitKeyboard(_THIS)
void Cocoa_StartTextInput(_THIS)
void Cocoa_HandleKeyEvent(_THIS, NSEvent *event)
void Cocoa_InitKeyboard(_THIS)
void Cocoa_SetTextInputRect(_THIS, SDL_Rect *rect)
void Cocoa_StopTextInput(_THIS)
static const NSUInteger NSEventModifierFlagCapsLock
#define SDL_GetKeyboardFocus
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
#define SDL_InvalidParamError(param)
int SDL_SendKeymapChangedEvent(void)
void SDL_SetScancodeName(SDL_Scancode scancode, const char *name)
void SDL_GetDefaultKeymap(SDL_Keycode *keymap)
void SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle)
void SDL_SetKeymap(int start, SDL_Keycode *keys, int length)
int SDL_SendEditingText(const char *text, int start, int length)
int SDL_SendKeyboardText(const char *text)
int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
#define SDLK_SCANCODE_MASK
Sint32 SDL_Keycode
The SDL virtual key representation.
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLuint GLuint GLsizei GLenum type
GLuint GLsizei GLsizei * length
SDL_Scancode
The SDL keyboard scancode representation.
#define SDL_arraysize(array)
static SDL_VideoDevice * _this
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)
EGLSurface EGLNativeWindowType * window
static const SDL_Scancode darwin_scancode_table[]
A rectangle, with the origin at the upper left (integer).
The type used to identify a window.
static void cleanup(void)
static char text[MAX_TEXT_LENGTH]