7# import <Carbon/Carbon.h>
25 GHOST_ImeStateFlagCocoa state_flag;
26 NSRect candidate_window_position;
30 std::string combined_result;
40 frame:(NSRect)frameRect;
57 frame:(NSRect)frameRect
62 system_cocoa_ = sysCocoa;
63 window_cocoa_ = winCocoa;
70 ime.candidate_window_position = NSZeroRect;
71 ime.event.cursor_position = -1;
72 ime.event.target_start = -1;
73 ime.event.target_end = -1;
80 selector:@selector(ImeDidChangeCallback:)
81 name:NSTextInputContextKeyboardSelectionDidChangeNotification
90- (BOOL)acceptsFirstResponder
95- (BOOL)acceptsFirstMouse:(NSEvent *)event
101- (void)keyDown:(NSEvent *)event
104 [
self checkKeyCodeIsControlChar:event];
105 const bool ime_process = [
self isProcessedByIme];
107 const bool ime_process =
false;
111 system_cocoa_->handleKeyEvent(event);
115 if ([[event characters]
length] == 0 || [[event charactersIgnoringModifiers]
length] == 0 ||
116 composing || ime_process)
122 [
self interpretKeyEvents:[NSArray arrayWithObject:event]];
127 const int controlCharForKorean = (GHOST_IME_COMPOSITION_EVENT | GHOST_IME_RESULT_EVENT |
128 GHOST_IME_KEY_CONTROL_CHAR);
129 if (((ime.state_flag & controlCharForKorean) == controlCharForKorean)) {
130 system_cocoa_->handleKeyEvent(event);
133 ime.state_flag &= ~(GHOST_IME_COMPOSITION_EVENT | GHOST_IME_RESULT_EVENT);
135 ime.combined_result.clear();
142#define HANDLE_KEY_EVENT(eventType) \
143 -(void)eventType : (NSEvent *)event \
145 system_cocoa_->handleKeyEvent(event); \
148#define HANDLE_MOUSE_EVENT(eventType) \
149 -(void)eventType : (NSEvent *)event \
151 system_cocoa_->handleMouseEvent(event); \
154#define HANDLE_TABLET_EVENT(eventType) \
155 -(void)eventType : (NSEvent *)event \
157 system_cocoa_->handleMouseEvent(event); \
186- (void)drawRect:(NSRect)rect
188 if ([
self inLiveResize]) {
192 [
super drawRect:rect];
197 if (window_cocoa_->getImmediateDraw()) {
198 system_cocoa_->dispatchEvents();
205- (void)composing_free
209 if (composing_text) {
210 [composing_text release];
216- (void)insertText:(
id)chars replacementRange:(NSRange)replacementRange
218 [
self composing_free];
221 if (ime.state_flag & GHOST_IME_ENABLED) {
222 if (!(ime.state_flag & GHOST_IME_COMPOSING)) {
223 [
self processImeEvent:GHOST_kEventImeCompositionStart];
227 if (ime.state_flag & GHOST_IME_RESULT_EVENT) {
228 ime.combined_result += [
self convertNSString:chars];
231 ime.combined_result = [
self convertNSString:chars];
234 [
self setImeResult:ime.combined_result];
238 if (![
self ime_did_composition]) {
239 [
self processImeEvent:GHOST_kEventImeComposition];
241 ime.state_flag |= GHOST_IME_RESULT_EVENT;
243 [
self processImeEvent:GHOST_kEventImeCompositionEnd];
244 ime.state_flag &= ~GHOST_IME_COMPOSING;
250- (void)setMarkedText:(
id)chars
251 selectedRange:(NSRange)range
252 replacementRange:(NSRange)replacementRange
254 [
self composing_free];
256 if ([chars
length] == 0) {
259 if (ime.state_flag & GHOST_IME_COMPOSING) {
260 [
self setImeResult:std::string()];
261 [
self processImeEvent:GHOST_kEventImeComposition];
262 [
self processImeEvent:GHOST_kEventImeCompositionEnd];
263 ime.state_flag &= ~GHOST_IME_COMPOSING;
275 if ([chars isKindOfClass:[NSAttributedString
class]]) {
280 if ([composing_text
length] == 0) {
281 [
self composing_free];
285 if (ime.state_flag & GHOST_IME_ENABLED) {
286 if (!(ime.state_flag & GHOST_IME_COMPOSING)) {
287 ime.state_flag |= GHOST_IME_COMPOSING;
288 [
self processImeEvent:GHOST_kEventImeCompositionStart];
291 [
self setImeComposition:composing_text selectedRange:range];
294 if (![
self ime_did_composition]) {
295 ime.state_flag |= GHOST_IME_COMPOSITION_EVENT;
296 [
self processImeEvent:GHOST_kEventImeComposition];
304 [
self composing_free];
309 return (composing) ? YES : NO;
312- (void)doCommandBySelector:(
SEL)selector
321- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)range
322 actualRange:(NSRangePointer)actualRange
324 return [[[NSAttributedString alloc] init] autorelease];
327- (NSRange)markedRange
332 return NSMakeRange(0,
length);
335 return NSMakeRange(NSNotFound, 0);
338- (NSRange)selectedRange
341 return NSMakeRange(0,
length);
345- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actualRange
348 if (ime.state_flag & GHOST_IME_ENABLED) {
349 return ime.candidate_window_position;
355- (NSUInteger)characterIndexForPoint:(NSPoint)point
360- (NSArray *)validAttributesForMarkedText
362 return [NSArray array];
366- (void)checkImeEnabled
368 ime.state_flag &= ~GHOST_IME_ENABLED;
370 if (ime.state_flag & GHOST_IME_INPUT_FOCUSED) {
373 TISInputSourceRef currentKeyboardInputSource = TISCopyCurrentKeyboardInputSource();
374 bool ime_enabled = !CFBooleanGetValue((CFBooleanRef)TISGetInputSourceProperty(
375 currentKeyboardInputSource, kTISPropertyInputSourceIsASCIICapable));
376 CFRelease(currentKeyboardInputSource);
379 ime.state_flag |= GHOST_IME_ENABLED;
386- (void)ImeDidChangeCallback:(NSNotification *)notification
388 [
self checkImeEnabled];
394 window_cocoa_->clientToScreen(
x,
y, outX, outY);
395 ime.candidate_window_position = NSMakeRect((CGFloat)outX, (CGFloat)outY, (CGFloat)
w, (CGFloat)h);
400 ime.state_flag |= GHOST_IME_INPUT_FOCUSED;
401 [
self checkImeEnabled];
402 [
self setImeCandidateWinPos:x y:y w:w h:h];
408 ime.event.result.clear();
409 ime.event.composite.clear();
413 [[NSTextInputContext currentInputContext] discardMarkedText];
419 GHOST_Event *
event =
new GHOST_EventIME(
420 system_cocoa_->getMilliSeconds(), imeEventType, window_cocoa_, &ime.event);
421 system_cocoa_->pushEvent(event);
424- (std::string)convertNSString:(NSString *)inString
427 std::string
str(inString.UTF8String);
432- (void)setImeComposition:(NSString *)inString selectedRange:(NSRange)range
434 ime.event.composite = [
self convertNSString:inString];
438 if (!(ime.state_flag & GHOST_IME_RESULT_EVENT)) {
439 ime.event.result.clear();
445 char *front_string = (
char *)[[inString substringWithRange:NSMakeRange(0, range.location)]
447 char *selected_string = (
char *)[[inString substringWithRange:range] UTF8String];
448 ime.event.cursor_position = strlen(front_string);
449 ime.event.target_start = ime.event.cursor_position;
450 ime.event.target_end = ime.event.target_start + strlen(selected_string);
454- (void)setImeResult:(std::
string)result
456 ime.event.result =
result;
457 ime.event.composite.clear();
458 ime.event.cursor_position = -1;
459 ime.event.target_start = -1;
460 ime.event.target_end = -1;
463- (void)checkKeyCodeIsControlChar:(NSEvent *)event
465 ime.state_flag &= ~GHOST_IME_KEY_CONTROL_CHAR;
468 if (event.modifierFlags & (NSEventModifierFlagCommand | NSEventModifierFlagControl)) {
469 ime.state_flag |= GHOST_IME_KEY_CONTROL_CHAR;
474 switch (event.keyCode) {
475 case kVK_ANSI_KeypadEnter:
476 case kVK_ANSI_KeypadClear:
503 case kVK_ForwardDelete:
513 ime.state_flag |= GHOST_IME_KEY_CONTROL_CHAR;
518- (bool)ime_did_composition
520 return (ime.state_flag & GHOST_IME_COMPOSITION_EVENT) ||
521 (ime.state_flag & GHOST_IME_RESULT_EVENT);
526- (bool)isProcessedByIme
529 (ime.state_flag & GHOST_IME_ENABLED) &&
530 ((ime.state_flag & GHOST_IME_COMPOSING) || !(ime.state_flag & GHOST_IME_KEY_CONTROL_CHAR)));
@ GHOST_kEventWindowUpdate
#define COCOA_VIEW_BASE_CLASS
#define HANDLE_KEY_EVENT(eventType)
#define HANDLE_TABLET_EVENT(eventType)
#define HANDLE_MOUSE_EVENT(eventType)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
GHOST_SystemCocoa * systemCocoa
NSString * composing_text
GHOST_WindowCocoa * windowCocoa