Skip to content

Commit cc5befa

Browse files
committed
fix: macOS에서의 한국어 ime
1 parent 1ca5de5 commit cc5befa

2 files changed

Lines changed: 96 additions & 36 deletions

File tree

indra/llwindow/llopenglview-objc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
- (unsigned long) getVramSize;
6969

7070
- (void) allowMarkedTextInput:(bool)allowed;
71+
- (BOOL) isCJKCharacter:(unichar)character;
7172
- (void) viewDidEndLiveResize;
7273

7374
@end

indra/llwindow/llopenglview-objc.mm

Lines changed: 95 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,12 @@ - (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOO
313313

314314
mOldResize = false;
315315

316+
// CJK 입력 관련 변수 초기화 (한국어, 일본어, 중국어)
317+
mHasMarkedText = FALSE;
318+
mMarkedTextLength = 0;
319+
mMarkedTextAllowed = true; // 기본값을 true로 설정하여 IME 지원
320+
mSimulatedRightClick = false;
321+
316322
return self;
317323
}
318324

@@ -517,6 +523,23 @@ - (void) keyDown:(NSEvent *)theEvent
517523
{
518524
ch = [str_no_modifiers characterAtIndex:0];
519525
}
526+
527+
// CJK 언어 조합 중인지 확인 (한국어, 일본어, 중국어)
528+
BOOL isComposingCJK = mHasMarkedText ||
529+
(!mMarkedTextAllowed &&
530+
!(mModifiers & (NSControlKeyMask | NSCommandKeyMask)) &&
531+
![(LLAppDelegate*)[NSApp delegate] romanScript] &&
532+
ch > ' ' &&
533+
ch != NSDeleteCharacter &&
534+
(ch < 0xF700 || ch > 0xF8FF));
535+
536+
// CJK 조합 중이면 키 이벤트를 처리하지 않고 IME에 맡김
537+
if (isComposingCJK && mHasMarkedText)
538+
{
539+
[[self inputContext] handleEvent:theEvent];
540+
return;
541+
}
542+
520543
bool acceptsText = mHasMarkedText ? false : callKeyDown(&eventData, keycode, mModifiers, ch);
521544

522545
if (acceptsText &&
@@ -667,8 +690,17 @@ - (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replaceme
667690
};
668691

669692
int string_length = [aString length];
693+
694+
// 빈 문자열이면 marked text 제거
695+
if (string_length == 0)
696+
{
697+
[self unmarkText];
698+
return;
699+
}
700+
670701
unichar text[string_length];
671702
attributedStringInfo segments;
703+
672704
// I used 'respondsToSelector:@selector(string)'
673705
// to judge aString is an attributed string or not.
674706
if ([aString respondsToSelector:@selector(string)])
@@ -684,18 +716,13 @@ - (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replaceme
684716
segments.seg_lengths.push_back(string_length);
685717
segments.seg_standouts.push_back(true);
686718
}
719+
687720
setMarkedText(text, selected, replacement, string_length, segments);
688-
if (string_length > 0)
689-
{
690-
mHasMarkedText = TRUE;
691-
mMarkedTextLength = string_length;
692-
}
693-
else
694-
{
695-
// we must clear the marked text when aString is null.
696-
[self unmarkText];
697-
}
698-
} else {
721+
mHasMarkedText = TRUE;
722+
mMarkedTextLength = string_length;
723+
}
724+
else
725+
{
699726
if (mHasMarkedText)
700727
{
701728
[self unmarkText];
@@ -743,10 +770,17 @@ - (void)insertText:(id)insertString
743770

744771
- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange
745772
{
746-
// SL-19801 Special workaround for system emoji picker
747-
if ([aString length] == 2)
748-
{
749-
@try
773+
@try
774+
{
775+
// marked text가 있는 경우 먼저 정리
776+
if (mHasMarkedText)
777+
{
778+
resetPreedit();
779+
mHasMarkedText = FALSE;
780+
}
781+
782+
// 이모지 처리 (기존 로직 유지)
783+
if ([aString length] == 2)
750784
{
751785
uint32_t b0 = [aString characterAtIndex:0];
752786
uint32_t b1 = [aString characterAtIndex:1];
@@ -757,32 +791,23 @@ - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange
757791
return;
758792
}
759793
}
760-
@catch(NSException * e)
761-
{
762-
// One of the characters is an attribute string?
763-
NSLog(@"Encountered an unsupported attributed character. Exception: %@ String: %@", e.name, aString);
764-
return;
765-
}
766-
}
767-
768-
@try
769-
{
770-
if (!mHasMarkedText)
794+
795+
// 각 문자를 순차적으로 처리
796+
for (NSInteger i = 0; i < [aString length]; i++)
771797
{
772-
for (NSInteger i = 0; i < [aString length]; i++)
798+
unichar character = [aString characterAtIndex:i];
799+
800+
// CJK 문자인지 확인 (한국어, 일본어, 중국어)
801+
if ([self isCJKCharacter:character])
773802
{
774-
callUnicodeCallback([aString characterAtIndex:i], mModifiers);
803+
// CJK 문자는 modifier 없이 전송
804+
callUnicodeCallback(character, 0);
775805
}
776-
} else {
777-
resetPreedit();
778-
// We may never get this point since unmarkText may be called before insertText ever gets called once we submit our text.
779-
// But just in case...
780-
781-
for (NSInteger i = 0; i < [aString length]; i++)
806+
else
782807
{
783-
handleUnicodeCharacter([aString characterAtIndex:i]);
808+
// 기타 문자들
809+
callUnicodeCallback(character, mModifiers);
784810
}
785-
mHasMarkedText = FALSE;
786811
}
787812
}
788813
@catch(NSException * e)
@@ -831,6 +856,40 @@ - (BOOL)drawsVerticallyForCharacterAtIndex:(NSUInteger)charIndex
831856
- (void) allowMarkedTextInput:(bool)allowed
832857
{
833858
mMarkedTextAllowed = allowed;
859+
860+
// CJK 입력 모드에서는 강제로 허용
861+
if (![(LLAppDelegate*)[NSApp delegate] romanScript])
862+
{
863+
mMarkedTextAllowed = true;
864+
}
865+
}
866+
867+
// CJK 문자 판별 헬퍼 메서드
868+
- (BOOL)isCJKCharacter:(unichar)character
869+
{
870+
// 한국어: 한글 (가-힐힣)
871+
if (character >= 0xAC00 && character <= 0xD7AF) return YES;
872+
873+
// 일본어: 히라가나
874+
if (character >= 0x3040 && character <= 0x309F) return YES;
875+
876+
// 일본어: 가타기나
877+
if (character >= 0x30A0 && character <= 0x30FF) return YES;
878+
879+
// 일본어: 반각 가타기나
880+
if (character >= 0xFF65 && character <= 0xFF9F) return YES;
881+
882+
// 중국어/일본어: CJK 통합 한자
883+
if (character >= 0x4E00 && character <= 0x9FFF) return YES;
884+
885+
// 중국어: CJK 확장 A
886+
if (character >= 0x3400 && character <= 0x4DBF) return YES;
887+
888+
// 한국어: 한글 자모 (호환용)
889+
if (character >= 0x1100 && character <= 0x11FF) return YES; // 한글 자모
890+
if (character >= 0x3130 && character <= 0x318F) return YES; // 한글 호환 자모
891+
892+
return NO;
834893
}
835894

836895
@end

0 commit comments

Comments
 (0)