comparison src/video/cocoa/SDL_cocoakeyboard.m @ 3280:00cace2d9080

Merged a cleaned up version of Jiang's code changes from Google Summer of Code 2009
author Sam Lantinga <slouken@libsdl.org>
date Sat, 19 Sep 2009 13:29:40 +0000
parents 2dcfb4e07a57
children d390778b59c1
comparison
equal deleted inserted replaced
3279:fd207dce9f94 3280:00cace2d9080
26 #include "../../events/SDL_keyboard_c.h" 26 #include "../../events/SDL_keyboard_c.h"
27 #include "../../events/scancodes_darwin.h" 27 #include "../../events/scancodes_darwin.h"
28 28
29 #include <Carbon/Carbon.h> 29 #include <Carbon/Carbon.h>
30 30
31 //#define DEBUG_IME NSLog
32 #define DEBUG_IME
31 33
32 #ifndef NX_DEVICERCTLKEYMASK 34 #ifndef NX_DEVICERCTLKEYMASK
33 #define NX_DEVICELCTLKEYMASK 0x00000001 35 #define NX_DEVICELCTLKEYMASK 0x00000001
34 #endif 36 #endif
35 #ifndef NX_DEVICELSHIFTKEYMASK 37 #ifndef NX_DEVICELSHIFTKEYMASK
52 #endif 54 #endif
53 #ifndef NX_DEVICERCTLKEYMASK 55 #ifndef NX_DEVICERCTLKEYMASK
54 #define NX_DEVICERCTLKEYMASK 0x00002000 56 #define NX_DEVICERCTLKEYMASK 0x00002000
55 #endif 57 #endif
56 58
57 @interface SDLTranslatorResponder : NSTextView 59 @interface SDLTranslatorResponder : NSView <NSTextInput>
58 { 60 {
61 NSString *_markedText;
62 NSRange _markedRange;
63 NSRange _selectedRange;
64 SDL_Rect _inputRect;
65 int _keyboard;
59 } 66 }
60 - (void) doCommandBySelector:(SEL)myselector; 67 - (void) doCommandBySelector:(SEL)myselector;
68 - (void) setInputRect:(SDL_Rect *) rect;
69 - (void) setKeyboard:(int) keyboard;
61 @end 70 @end
62 71
63 @implementation SDLTranslatorResponder 72 @implementation SDLTranslatorResponder
64 - (void) doCommandBySelector:(SEL) myselector {} 73
74 - (void) setKeyboard:(int) keyboard
75 {
76 _keyboard = keyboard;
77 }
78
79 - (void) setInputRect:(SDL_Rect *) rect
80 {
81 _inputRect = *rect;
82 }
83
84 - (void) insertText:(id) aString
85 {
86 const char *str;
87
88 DEBUG_IME(@"insertText: %@", aString);
89
90 /* Could be NSString or NSAttributedString, so we have
91 * to test and convert it before return as SDL event */
92 if ([aString isKindOfClass: [NSAttributedString class]])
93 str = [[aString string] UTF8String];
94 else
95 str = [aString UTF8String];
96
97 SDL_SendKeyboardText(_keyboard, str);
98 }
99
100 - (void) doCommandBySelector:(SEL) myselector
101 {
102 [super doCommandBySelector: myselector];
103 }
104
105 - (BOOL) hasMarkedText
106 {
107 return _markedText != nil;
108 }
109
110 - (NSRange) markedRange
111 {
112 return _markedRange;
113 }
114
115 - (NSRange) selectedRange
116 {
117 return _selectedRange;
118 }
119
120 - (void) setMarkedText:(id) aString
121 selectedRange:(NSRange) selRange
122 {
123 if ([aString isKindOfClass: [NSAttributedString class]])
124 aString = [aString string];
125
126 if ([aString length] == 0)
127 {
128 [self unmarkText];
129 return;
130 }
131
132 if (_markedText != aString)
133 {
134 [_markedText release];
135 _markedText = [aString retain];
136 }
137
138 _selectedRange = selRange;
139 _markedRange = NSMakeRange(0, [aString length]);
140
141 SDL_SendEditingText([aString UTF8String], selRange.location, selRange.length);
142
143 DEBUG_IME(@"setMarkedText: %@, (%d, %d)", _markedText,
144 selRange.location, selRange.length);
145 }
146
147 - (void) unmarkText
148 {
149 [_markedText release];
150 _markedText = nil;
151 }
152
153 - (NSRect) firstRectForCharacterRange: (NSRange) theRange
154 {
155 float windowHeight = [[self window] frame].size.height;
156 NSRect rect = NSMakeRect(_inputRect.x, windowHeight - _inputRect.y - _inputRect.h,
157 _inputRect.w, _inputRect.h);
158
159 DEBUG_IME(@"firstRectForCharacterRange: (%d, %d): windowHeight = %g, rect = %@",
160 theRange.location, theRange.length, windowHeight,
161 NSStringFromRect(rect));
162 rect.origin = [[self window] convertBaseToScreen: rect.origin];
163
164 return rect;
165 }
166
167 - (NSAttributedString *) attributedSubstringFromRange: (NSRange) theRange
168 {
169 DEBUG_IME(@"attributedSubstringFromRange: (%d, %d)", theRange.location, theRange.length);
170 return nil;
171 }
172
173 - (NSInteger) conversationIdentifier
174 {
175 return (NSInteger) self;
176 }
177
178 // This method returns the index for character that is
179 // nearest to thePoint. thPoint is in screen coordinate system.
180 - (NSUInteger) characterIndexForPoint:(NSPoint) thePoint
181 {
182 DEBUG_IME(@"characterIndexForPoint: (%g, %g)", thePoint.x, thePoint.y);
183 return 0;
184 }
185
186 // This method is the key to attribute extension.
187 // We could add new attributes through this method.
188 // NSInputServer examines the return value of this
189 // method & constructs appropriate attributed string.
190 - (NSArray *) validAttributesForMarkedText
191 {
192 return [NSArray array];
193 }
194
65 @end 195 @end
66 196
67 /* This is the original behavior, before support was added for 197 /* This is the original behavior, before support was added for
68 * differentiating between left and right versions of the keys. 198 * differentiating between left and right versions of the keys.
69 */ 199 */
476 void 606 void
477 Cocoa_InitKeyboard(_THIS) 607 Cocoa_InitKeyboard(_THIS)
478 { 608 {
479 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; 609 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
480 SDL_Keyboard keyboard; 610 SDL_Keyboard keyboard;
481 NSAutoreleasePool *pool; 611
482
483 pool = [[NSAutoreleasePool alloc] init];
484 data->fieldEdit = [[SDLTranslatorResponder alloc] initWithFrame:NSMakeRect(0.0, 0.0, 0.0, 0.0)];
485 [pool release];
486
487 SDL_zero(keyboard); 612 SDL_zero(keyboard);
488 data->keyboard = SDL_AddKeyboard(&keyboard, -1); 613 data->keyboard = SDL_AddKeyboard(&keyboard, -1);
489 UpdateKeymap(data); 614 UpdateKeymap(data);
490 615
491 /* Set our own names for the platform-dependent but layout-independent keys */ 616 /* Set our own names for the platform-dependent but layout-independent keys */
496 SDL_SetScancodeName(SDL_SCANCODE_RALT, "Right Option"); 621 SDL_SetScancodeName(SDL_SCANCODE_RALT, "Right Option");
497 SDL_SetScancodeName(SDL_SCANCODE_RGUI, "Right Command"); 622 SDL_SetScancodeName(SDL_SCANCODE_RGUI, "Right Command");
498 } 623 }
499 624
500 void 625 void
626 Cocoa_StartTextInput(_THIS)
627 {
628 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
629 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
630 NSView *parentView = [[NSApp keyWindow] contentView];
631
632 data->fieldEdit = [[SDLTranslatorResponder alloc] initWithFrame:NSMakeRect(0.0, 0.0, 0.0, 0.0)];
633 [data->fieldEdit setKeyboard: data->keyboard];
634
635 if (! [[data->fieldEdit superview] isEqual: parentView])
636 {
637 // DEBUG_IME(@"add fieldEdit to window contentView");
638 [data->fieldEdit removeFromSuperview];
639 [parentView addSubview: data->fieldEdit];
640 [[NSApp keyWindow] makeFirstResponder: data->fieldEdit];
641 }
642
643 [pool release];
644 }
645
646 void
647 Cocoa_StopTextInput(_THIS)
648 {
649 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
650
651 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
652 [data->fieldEdit removeFromSuperview];
653 [data->fieldEdit release];
654 data->fieldEdit = nil;
655 [pool release];
656 }
657
658 void
659 Cocoa_SetTextInputRect(_THIS, SDL_Rect *rect)
660 {
661 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
662
663 [data->fieldEdit setInputRect: rect];
664 }
665
666 void
501 Cocoa_HandleKeyEvent(_THIS, NSEvent *event) 667 Cocoa_HandleKeyEvent(_THIS, NSEvent *event)
502 { 668 {
503 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; 669 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
504 unsigned short scancode = [event keyCode]; 670 unsigned short scancode = [event keyCode];
505 SDL_scancode code; 671 SDL_scancode code;
531 #endif 697 #endif
532 } 698 }
533 if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) { 699 if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
534 /* 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. */ 700 /* 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. */
535 [data->fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]]; 701 [data->fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]];
702 #if 0
536 text = [[event characters] UTF8String]; 703 text = [[event characters] UTF8String];
537 if(text && *text) { 704 if(text && *text) {
538 SDL_SendKeyboardText(data->keyboard, text); 705 SDL_SendKeyboardText(data->keyboard, text);
539 [data->fieldEdit setString:@""]; 706 [data->fieldEdit setString:@""];
540 } 707 }
708 #endif
541 } 709 }
542 break; 710 break;
543 case NSKeyUp: 711 case NSKeyUp:
544 SDL_SendKeyboardKey(data->keyboard, SDL_RELEASED, code); 712 SDL_SendKeyboardKey(data->keyboard, SDL_RELEASED, code);
545 break; 713 break;
557 { 725 {
558 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; 726 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
559 NSAutoreleasePool *pool; 727 NSAutoreleasePool *pool;
560 728
561 SDL_DelKeyboard(data->keyboard); 729 SDL_DelKeyboard(data->keyboard);
562
563 pool = [[NSAutoreleasePool alloc] init];
564 [data->fieldEdit release];
565 [pool release];
566 } 730 }
567 731
568 /* vi: set ts=4 sw=4 expandtab: */ 732 /* vi: set ts=4 sw=4 expandtab: */