Atlas - SDL_cocoakeyboard.m

Home / ext / SDL2 / src / video / cocoa Lines: 2 | Size: 23229 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../../SDL_internal.h" 22 23#if SDL_VIDEO_DRIVER_COCOA 24 25#include "SDL_cocoavideo.h" 26 27#include "../../events/SDL_events_c.h" 28#include "../../events/SDL_keyboard_c.h" 29#include "../../events/scancodes_darwin.h" 30 31#include <Carbon/Carbon.h> 32#include <IOKit/hid/IOHIDLib.h> 33 34/*#define DEBUG_IME NSLog */ 35#define DEBUG_IME(...) 36 37@interface SDLTranslatorResponder : NSView <NSTextInputClient> { 38 NSString *_markedText; 39 NSRange _markedRange; 40 NSRange _selectedRange; 41 SDL_Rect _inputRect; 42} 43- (void)doCommandBySelector:(SEL)myselector; 44- (void)setInputRect:(SDL_Rect *)rect; 45@end 46 47@implementation SDLTranslatorResponder 48 49- (void)setInputRect:(SDL_Rect *)rect 50{ 51 _inputRect = *rect; 52} 53 54- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange 55{ 56 /* TODO: Make use of replacementRange? */ 57 58 const char *str; 59 60 DEBUG_IME(@"insertText: %@", aString); 61 62 /* Could be NSString or NSAttributedString, so we have 63 * to test and convert it before return as SDL event */ 64 if ([aString isKindOfClass: [NSAttributedString class]]) { 65 str = [[aString string] UTF8String]; 66 } else { 67 str = [aString UTF8String]; 68 } 69 70 SDL_SendKeyboardText(str); 71} 72 73- (void)doCommandBySelector:(SEL)myselector 74{ 75 /* No need to do anything since we are not using Cocoa 76 selectors to handle special keys, instead we use SDL 77 key events to do the same job. 78 */ 79} 80 81- (BOOL)hasMarkedText 82{ 83 return _markedText != nil; 84} 85 86- (NSRange)markedRange 87{ 88 return _markedRange; 89} 90 91- (NSRange)selectedRange 92{ 93 return _selectedRange; 94} 95 96- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange 97{ 98 if ([aString isKindOfClass:[NSAttributedString class]]) { 99 aString = [aString string]; 100 } 101 102 if ([aString length] == 0) { 103 [self unmarkText]; 104 return; 105 } 106 107 if (_markedText != aString) { 108 [_markedText release]; 109 _markedText = [aString retain]; 110 } 111 112 _selectedRange = selectedRange; 113 _markedRange = NSMakeRange(0, [aString length]); 114 115 SDL_SendEditingText([aString UTF8String], 116 (int) selectedRange.location, (int) selectedRange.length); 117 118 DEBUG_IME(@"setMarkedText: %@, (%d, %d)", _markedText, 119 selRange.location, selRange.length); 120} 121 122- (void)unmarkText 123{ 124 [_markedText release]; 125 _markedText = nil; 126 127 SDL_SendEditingText("", 0, 0); 128} 129 130- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange 131{ 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); 137 138 if (actualRange) { 139 *actualRange = aRange; 140 } 141 142 DEBUG_IME(@"firstRectForCharacterRange: (%d, %d): windowHeight = %g, rect = %@", 143 aRange.location, aRange.length, windowHeight, 144 NSStringFromRect(rect)); 145 146#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 147 if (![window respondsToSelector:@selector(convertRectToScreen:)]) { 148 rect.origin = [window convertBaseToScreen:rect.origin]; 149 } else 150#endif 151 { 152 rect = [window convertRectToScreen:rect]; 153 } 154 155 return rect; 156} 157 158- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange 159{ 160 DEBUG_IME(@"attributedSubstringFromRange: (%d, %d)", aRange.location, aRange.length); 161 return nil; 162} 163 164- (NSInteger)conversationIdentifier 165{ 166 return (NSInteger) self; 167} 168 169/* This method returns the index for character that is 170 * nearest to thePoint. thPoint is in screen coordinate system. 171 */ 172- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint 173{ 174 DEBUG_IME(@"characterIndexForPoint: (%g, %g)", thePoint.x, thePoint.y); 175 return 0; 176} 177 178/* This method is the key to attribute extension. 179 * We could add new attributes through this method. 180 * NSInputServer examines the return value of this 181 * method & constructs appropriate attributed string. 182 */ 183- (NSArray *)validAttributesForMarkedText 184{ 185 return [NSArray array]; 186} 187 188@end 189 190/*------------------------------------------------------------------------------ 191Set up a HID callback to properly detect Caps Lock up/down events. 192Derived from: 193http://stackoverflow.com/questions/7190852/using-iohidmanager-to-get-modifier-key-events 194*/ 195 196static IOHIDManagerRef s_hidManager = NULL; 197 198static void 199HIDCallback(void *context, IOReturn result, void *sender, IOHIDValueRef value) 200{ 201 if (context != s_hidManager) { 202 /* An old callback, ignore it (related to bug 2157 below) */ 203 return; 204 } 205 206 IOHIDElementRef elem = IOHIDValueGetElement(value); 207 if (IOHIDElementGetUsagePage(elem) != kHIDPage_KeyboardOrKeypad 208 || IOHIDElementGetUsage(elem) != kHIDUsage_KeyboardCapsLock) { 209 return; 210 } 211 CFIndex pressed = IOHIDValueGetIntegerValue(value); 212 SDL_SendKeyboardKey(pressed ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_CAPSLOCK); 213} 214 215static CFDictionaryRef 216CreateHIDDeviceMatchingDictionary(UInt32 usagePage, UInt32 usage) 217{ 218 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 219 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 220 if (dict) { 221 CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usagePage); 222 if (number) { 223 CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsagePageKey), number); 224 CFRelease(number); 225 number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage); 226 if (number) { 227 CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsageKey), number); 228 CFRelease(number); 229 return dict; 230 } 231 } 232 CFRelease(dict); 233 } 234 return NULL; 235} 236 237static void 238QuitHIDCallback() 239{ 240 if (!s_hidManager) { 241 return; 242 } 243 244#if 0 /* Releasing here causes a crash on Mac OS X 10.10 and earlier, 245 * so just leak it for now. See bug 2157 for details. 246 */ 247 IOHIDManagerUnscheduleFromRunLoop(s_hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); 248 IOHIDManagerRegisterInputValueCallback(s_hidManager, NULL, NULL); 249 IOHIDManagerClose(s_hidManager, 0); 250 251 CFRelease(s_hidManager); 252#endif 253 s_hidManager = NULL; 254} 255 256static void 257InitHIDCallback() 258{ 259 s_hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); 260 if (!s_hidManager) { 261 return; 262 } 263 CFDictionaryRef keyboard = NULL, keypad = NULL; 264 CFArrayRef matches = NULL; 265 keyboard = CreateHIDDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard); 266 if (!keyboard) { 267 goto fail; 268 } 269 keypad = CreateHIDDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keypad); 270 if (!keypad) { 271 goto fail; 272 } 273 CFDictionaryRef matchesList[] = { keyboard, keypad }; 274 matches = CFArrayCreate(kCFAllocatorDefault, (const void **)matchesList, 2, NULL); 275 if (!matches) { 276 goto fail; 277 } 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) { 282 goto cleanup; 283 } 284 285fail: 286 QuitHIDCallback(); 287 288cleanup: 289 if (matches) { 290 CFRelease(matches); 291 } 292 if (keypad) { 293 CFRelease(keypad); 294 } 295 if (keyboard) { 296 CFRelease(keyboard); 297 } 298} 299 300/* This is a helper function for HandleModifierSide. This 301 * function reverts back to behavior before the distinction between 302 * sides was made. 303 */ 304static void 305HandleNonDeviceModifier(unsigned int device_independent_mask, 306 unsigned int oldMods, 307 unsigned int newMods, 308 SDL_Scancode scancode) 309{ 310 unsigned int oldMask, newMask; 311 312 /* Isolate just the bits we care about in the depedent bits so we can 313 * figure out what changed 314 */ 315 oldMask = oldMods & device_independent_mask; 316 newMask = newMods & device_independent_mask; 317 318 if (oldMask && oldMask != newMask) { 319 SDL_SendKeyboardKey(SDL_RELEASED, scancode); 320 } else if (newMask && oldMask != newMask) { 321 SDL_SendKeyboardKey(SDL_PRESSED, scancode); 322 } 323} 324 325/* This is a helper function for HandleModifierSide. 326 * This function sets the actual SDL_PrivateKeyboard event. 327 */ 328static void 329HandleModifierOneSide(unsigned int oldMods, unsigned int newMods, 330 SDL_Scancode scancode, 331 unsigned int sided_device_dependent_mask) 332{ 333 unsigned int old_dep_mask, new_dep_mask; 334 335 /* Isolate just the bits we care about in the depedent bits so we can 336 * figure out what changed 337 */ 338 old_dep_mask = oldMods & sided_device_dependent_mask; 339 new_dep_mask = newMods & sided_device_dependent_mask; 340 341 /* We now know that this side bit flipped. But we don't know if 342 * it went pressed to released or released to pressed, so we must 343 * find out which it is. 344 */ 345 if (new_dep_mask && old_dep_mask != new_dep_mask) { 346 SDL_SendKeyboardKey(SDL_PRESSED, scancode); 347 } else { 348 SDL_SendKeyboardKey(SDL_RELEASED, scancode); 349 } 350} 351 352/* This is a helper function for DoSidedModifiers. 353 * This function will figure out if the modifier key is the left or right side, 354 * e.g. left-shift vs right-shift. 355 */ 356static void 357HandleModifierSide(int device_independent_mask, 358 unsigned int oldMods, unsigned int newMods, 359 SDL_Scancode left_scancode, 360 SDL_Scancode right_scancode, 361 unsigned int left_device_dependent_mask, 362 unsigned int right_device_dependent_mask) 363{ 364 unsigned int device_dependent_mask = (left_device_dependent_mask | 365 right_device_dependent_mask); 366 unsigned int diff_mod; 367 368 /* On the basis that the device independent mask is set, but there are 369 * no device dependent flags set, we'll assume that we can't detect this 370 * keyboard and revert to the unsided behavior. 371 */ 372 if ((device_dependent_mask & newMods) == 0) { 373 /* Revert to the old behavior */ 374 HandleNonDeviceModifier(device_independent_mask, oldMods, newMods, left_scancode); 375 return; 376 } 377 378 /* XOR the previous state against the new state to see if there's a change */ 379 diff_mod = (device_dependent_mask & oldMods) ^ 380 (device_dependent_mask & newMods); 381 if (diff_mod) { 382 /* A change in state was found. Isolate the left and right bits 383 * to handle them separately just in case the values can simulataneously 384 * change or if the bits don't both exist. 385 */ 386 if (left_device_dependent_mask & diff_mod) { 387 HandleModifierOneSide(oldMods, newMods, left_scancode, left_device_dependent_mask); 388 } 389 if (right_device_dependent_mask & diff_mod) { 390 HandleModifierOneSide(oldMods, newMods, right_scancode, right_device_dependent_mask); 391 } 392 } 393} 394 395/* This is a helper function for DoSidedModifiers. 396 * This function will release a key press in the case that 397 * it is clear that the modifier has been released (i.e. one side 398 * can't still be down). 399 */ 400static void 401ReleaseModifierSide(unsigned int device_independent_mask, 402 unsigned int oldMods, unsigned int newMods, 403 SDL_Scancode left_scancode, 404 SDL_Scancode right_scancode, 405 unsigned int left_device_dependent_mask, 406 unsigned int right_device_dependent_mask) 407{ 408 unsigned int device_dependent_mask = (left_device_dependent_mask | 409 right_device_dependent_mask); 410 411 /* On the basis that the device independent mask is set, but there are 412 * no device dependent flags set, we'll assume that we can't detect this 413 * keyboard and revert to the unsided behavior. 414 */ 415 if ((device_dependent_mask & oldMods) == 0) { 416 /* In this case, we can't detect the keyboard, so use the left side 417 * to represent both, and release it. 418 */ 419 SDL_SendKeyboardKey(SDL_RELEASED, left_scancode); 420 return; 421 } 422 423 /* 424 * This could have been done in an if-else case because at this point, 425 * we know that all keys have been released when calling this function. 426 * But I'm being paranoid so I want to handle each separately, 427 * so I hope this doesn't cause other problems. 428 */ 429 if ( left_device_dependent_mask & oldMods ) { 430 SDL_SendKeyboardKey(SDL_RELEASED, left_scancode); 431 } 432 if ( right_device_dependent_mask & oldMods ) { 433 SDL_SendKeyboardKey(SDL_RELEASED, right_scancode); 434 } 435} 436 437/* This function will handle the modifier keys and also determine the 438 * correct side of the key. 439 */ 440static void 441DoSidedModifiers(unsigned short scancode, 442 unsigned int oldMods, unsigned int newMods) 443{ 444 /* Set up arrays for the key syms for the left and right side. */ 445 const SDL_Scancode left_mapping[] = { 446 SDL_SCANCODE_LSHIFT, 447 SDL_SCANCODE_LCTRL, 448 SDL_SCANCODE_LALT, 449 SDL_SCANCODE_LGUI 450 }; 451 const SDL_Scancode right_mapping[] = { 452 SDL_SCANCODE_RSHIFT, 453 SDL_SCANCODE_RCTRL, 454 SDL_SCANCODE_RALT, 455 SDL_SCANCODE_RGUI 456 }; 457 /* Set up arrays for the device dependent masks with indices that 458 * correspond to the _mapping arrays 459 */ 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 }; 462 463 unsigned int i, bit; 464 465 /* Iterate through the bits, testing each against the old modifiers */ 466 for (i = 0, bit = NSEventModifierFlagShift; bit <= NSEventModifierFlagCommand; bit <<= 1, ++i) { 467 unsigned int oldMask, newMask; 468 469 oldMask = oldMods & bit; 470 newMask = newMods & bit; 471 472 /* If the bit is set, we must always examine it because the left 473 * and right side keys may alternate or both may be pressed. 474 */ 475 if (newMask) { 476 HandleModifierSide(bit, oldMods, newMods, 477 left_mapping[i], right_mapping[i], 478 left_device_mapping[i], right_device_mapping[i]); 479 } 480 /* If the state changed from pressed to unpressed, we must examine 481 * the device dependent bits to release the correct keys. 482 */ 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]); 487 } 488 } 489} 490 491static void 492HandleModifiers(_THIS, unsigned short scancode, unsigned int modifierFlags) 493{ 494 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; 495 496 if (modifierFlags == data->modifierFlags) { 497 return; 498 } 499 500 DoSidedModifiers(scancode, data->modifierFlags, modifierFlags); 501 data->modifierFlags = modifierFlags; 502} 503 504static void 505UpdateKeymap(SDL_VideoData *data, SDL_bool send_event) 506{ 507 TISInputSourceRef key_layout; 508 const void *chr_data; 509 int i; 510 SDL_Scancode scancode; 511 SDL_Keycode keymap[SDL_NUM_SCANCODES]; 512 513 /* See if the keymap needs to be updated */ 514 key_layout = TISCopyCurrentKeyboardLayoutInputSource(); 515 if (key_layout == data->key_layout) { 516 return; 517 } 518 data->key_layout = key_layout; 519 520 SDL_GetDefaultKeymap(keymap); 521 522 /* Try Unicode data first */ 523 CFDataRef uchrDataRef = TISGetInputSourceProperty(key_layout, kTISPropertyUnicodeKeyLayoutData); 524 if (uchrDataRef) { 525 chr_data = CFDataGetBytePtr(uchrDataRef); 526 } else { 527 goto cleanup; 528 } 529 530 if (chr_data) { 531 UInt32 keyboard_type = LMGetKbdType(); 532 OSStatus err; 533 534 for (i = 0; i < SDL_arraysize(darwin_scancode_table); i++) { 535 UniChar s[8]; 536 UniCharCount len; 537 UInt32 dead_key_state; 538 539 /* Make sure this scancode is a valid character scancode */ 540 scancode = darwin_scancode_table[i]; 541 if (scancode == SDL_SCANCODE_UNKNOWN || 542 (keymap[scancode] & SDLK_SCANCODE_MASK)) { 543 continue; 544 } 545 546 dead_key_state = 0; 547 err = UCKeyTranslate ((UCKeyboardLayout *) chr_data, 548 i, kUCKeyActionDown, 549 0, keyboard_type, 550 kUCKeyTranslateNoDeadKeysMask, 551 &dead_key_state, 8, &len, s); 552 if (err != noErr) { 553 continue; 554 } 555 556 if (len > 0 && s[0] != 0x10) { 557 keymap[scancode] = s[0]; 558 } 559 } 560 SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES); 561 if (send_event) { 562 SDL_SendKeymapChangedEvent(); 563 } 564 return; 565 } 566 567cleanup: 568 CFRelease(key_layout); 569} 570 571void 572Cocoa_InitKeyboard(_THIS) 573{ 574 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; 575 576 UpdateKeymap(data, SDL_FALSE); 577 578 /* Set our own names for the platform-dependent but layout-independent keys */ 579 /* This key is NumLock on the MacBook keyboard. :) */ 580 /*SDL_SetScancodeName(SDL_SCANCODE_NUMLOCKCLEAR, "Clear");*/ 581 SDL_SetScancodeName(SDL_SCANCODE_LALT, "Left Option"); 582 SDL_SetScancodeName(SDL_SCANCODE_LGUI, "Left Command"); 583 SDL_SetScancodeName(SDL_SCANCODE_RALT, "Right Option"); 584 SDL_SetScancodeName(SDL_SCANCODE_RGUI, "Right Command"); 585 586 data->modifierFlags = [NSEvent modifierFlags]; 587 SDL_ToggleModState(KMOD_CAPS, (data->modifierFlags & NSEventModifierFlagCapsLock) != 0); 588 589 InitHIDCallback(); 590} 591 592void 593Cocoa_StartTextInput(_THIS) 594{ @autoreleasepool 595{ 596 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; 597 SDL_Window *window = SDL_GetKeyboardFocus(); 598 NSWindow *nswindow = nil; 599 if (window) { 600 nswindow = ((SDL_WindowData*)window->driverdata)->nswindow; 601 } 602 603 NSView *parentView = [nswindow contentView]; 604 605 /* We only keep one field editor per process, since only the front most 606 * window can receive text input events, so it make no sense to keep more 607 * than one copy. When we switched to another window and requesting for 608 * text input, simply remove the field editor from its superview then add 609 * it to the front most window's content view */ 610 if (!data->fieldEdit) { 611 data->fieldEdit = 612 [[SDLTranslatorResponder alloc] initWithFrame: NSMakeRect(0.0, 0.0, 0.0, 0.0)]; 613 } 614 615 if (![[data->fieldEdit superview] isEqual:parentView]) { 616 /* DEBUG_IME(@"add fieldEdit to window contentView"); */ 617 [data->fieldEdit removeFromSuperview]; 618 [parentView addSubview: data->fieldEdit]; 619 [nswindow makeFirstResponder: data->fieldEdit]; 620 } 621}} 622 623void 624Cocoa_StopTextInput(_THIS) 625{ @autoreleasepool 626{ 627 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; 628 629 if (data && data->fieldEdit) { 630 [data->fieldEdit removeFromSuperview]; 631 [data->fieldEdit release]; 632 data->fieldEdit = nil; 633 } 634}} 635 636void 637Cocoa_SetTextInputRect(_THIS, SDL_Rect *rect) 638{ 639 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; 640 641 if (!rect) { 642 SDL_InvalidParamError("rect"); 643 return; 644 } 645 646 [data->fieldEdit setInputRect:rect]; 647} 648 649void 650Cocoa_HandleKeyEvent(_THIS, NSEvent *event) 651{ 652 SDL_VideoData *data = _this ? ((SDL_VideoData *) _this->driverdata) : NULL; 653 if (!data) { 654 return; /* can happen when returning from fullscreen Space on shutdown */ 655 } 656 657 unsigned short scancode = [event keyCode]; 658 SDL_Scancode code; 659#if 0 660 const char *text; 661#endif 662 663 if ((scancode == 10 || scancode == 50) && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) { 664 /* see comments in SDL_cocoakeys.h */ 665 scancode = 60 - scancode; 666 } 667 668 if (scancode < SDL_arraysize(darwin_scancode_table)) { 669 code = darwin_scancode_table[scancode]; 670 } else { 671 /* Hmm, does this ever happen? If so, need to extend the keymap... */ 672 code = SDL_SCANCODE_UNKNOWN; 673 } 674 675 switch ([event type]) { 676 case NSEventTypeKeyDown: 677 if (![event isARepeat]) { 678 /* See if we need to rebuild the keyboard layout */ 679 UpdateKeymap(data, SDL_TRUE); 680 } 681 682 SDL_SendKeyboardKey(SDL_PRESSED, code); 683#if 1 684 if (code == SDL_SCANCODE_UNKNOWN) { 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 <[email protected]>. Mac virtual key code is %d.\n", scancode); 686 } 687#endif 688 if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) { 689 /* 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. */ 690 [data->fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]]; 691#if 0 692 text = [[event characters] UTF8String]; 693 if(text && *text) { 694 SDL_SendKeyboardText(text); 695 [data->fieldEdit setString:@""]; 696 } 697#endif 698 } 699 break; 700 case NSEventTypeKeyUp: 701 SDL_SendKeyboardKey(SDL_RELEASED, code); 702 break; 703 case NSEventTypeFlagsChanged: 704 /* FIXME CW 2007-08-14: check if this whole mess that takes up half of this file is really necessary */ 705 HandleModifiers(_this, scancode, [event modifierFlags]); 706 break; 707 default: /* just to avoid compiler warnings */ 708 break; 709 } 710} 711 712void 713Cocoa_QuitKeyboard(_THIS) 714{ 715 QuitHIDCallback(); 716} 717 718#endif /* SDL_VIDEO_DRIVER_COCOA */ 719 720/* vi: set ts=4 sw=4 expandtab: */ 721
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.