Skip to content

Commit

Permalink
Merge pull request #404 from youknowone/swift-port
Browse files Browse the repository at this point in the history
CIMInputReceiver swift port
  • Loading branch information
youknowone committed Oct 21, 2018
2 parents b4133ce + b45b529 commit ebaed30
Show file tree
Hide file tree
Showing 5 changed files with 239 additions and 272 deletions.
25 changes: 1 addition & 24 deletions CommonInputMethod/CIMInputController.h
Expand Up @@ -28,30 +28,7 @@
NS_ASSUME_NONNULL_BEGIN

@class CIMComposer;

@interface CIMInputReceiver : NSObject<CIMInputTextDelegate> {
id _inputClient;
CIMComposer *_composer;
CIMInputController *_controller;
}

@property(nonatomic, readonly) id inputClient;
@property(nonatomic, readonly) CIMComposer *composer;

- (instancetype)initWithServer:(nullable IMKServer *)server delegate:(nullable id)delegate client:(nullable id)inputClient;

@end


@interface CIMInputReceiver(SwiftBridge)

- (BOOL)commitCompositionEvent:(id)sender controller:(CIMInputController *)controller;
- (NSInteger)recognizedEvents:(_Null_unspecified id)sender;
- (void)setValue:(_Null_unspecified id)value forTag:(NSInteger)tag client:(_Null_unspecified id)sender controller:(CIMInputController *)controller;

@end


@class CIMInputReceiver;
@class IOConnect;

typedef NS_ENUM(NSInteger, CIMInputControllerSpecialKeyCode) {
Expand Down
247 changes: 1 addition & 246 deletions CommonInputMethod/CIMInputController.m
Expand Up @@ -36,251 +36,6 @@
}


@interface CIMInputReceiver(IMKServerInput)

- (BOOL)commitComposition:(id)sender controller:(CIMInputController *)controller;
- (void)updateComposition:(CIMInputController *)controller;
- (void)cancelComposition:(CIMInputController *)controller;
- (BOOL)commitCompositionEvent:(id)sender controller:(CIMInputController *)controller;
- (void)updateCompositionEvent:(CIMInputController *)controller;
- (void)cancelCompositionEvent:(CIMInputController *)controller;
@property (NS_NONATOMIC_IOSONLY, readonly, copy) NSString *_internalComposedString;

@end


@interface CIMInputReceiver ()

@property(nonatomic,assign) BOOL hasSelectionRange;

@end


@implementation CIMInputReceiver
@synthesize composer=_composer, inputClient=_inputClient;

- (instancetype)initWithServer:(nullable IMKServer *)server delegate:(nullable id)delegate client:(nullable id)inputClient {
self = [super init];
if (self != nil) {
dlog(DEBUG_INPUTCONTROLLER, @"**** NEW INPUT CONTROLLER INIT **** WITH SERVER: %@ / DELEGATE: %@ / CLIENT: %@", server, delegate, inputClient);
self->_composer = [CIMAppDelegate composerWithServer:server client:inputClient];
self->_composer.manager = CIMSharedInputManager;
_inputClient = inputClient;
}
return self;
}

- (CIMComposer *)composer {
return self->_composer;
}

// IMKServerInput 프로토콜에 대한 공용 핸들러
- (CIMInputTextProcessResult)inputController:(CIMInputController *)controller inputText:(nullable NSString *)string key:(NSInteger)keyCode modifiers:(NSEventModifierFlags)flags client:(id)sender {
dlog(DEBUG_LOGGING, @"LOGGING::KEY::(%@)(%ld)(%lu)", [string stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"], keyCode, flags);

BOOL hadComposedString = self._internalComposedString.length > 0;
CIMInputTextProcessResult handled = [CIMSharedInputManager inputController:controller inputText:string key:keyCode modifiers:flags client:sender];

CIMSharedInputManager.inputting = YES;

switch (handled) {
case CIMInputTextProcessResultNotProcessed:
case CIMInputTextProcessResultProcessed:
break;
case CIMInputTextProcessResultNotProcessedAndNeedsCancel:
[self cancelComposition:controller];
break;
case CIMInputTextProcessResultNotProcessedAndNeedsCommit:
[self cancelComposition:controller];
[self commitComposition:sender controller:controller];
return handled;
default:
dlog(TRUE, @"WRONG RESULT: %d", handled);
dassert(NO);
break;
}

BOOL commited = [self commitComposition:sender controller:controller]; // 조합 된 문자 반영
BOOL hasComposedString = self._internalComposedString.length > 0;
NSRange selectionRange = controller.selectionRange;
self.hasSelectionRange = selectionRange.location != NSNotFound && selectionRange.length > 0;
if (commited || controller.selectionRange.length > 0 || hadComposedString || hasComposedString) {
[self updateComposition:controller]; // 조합 중인 문자 반영
}

CIMSharedInputManager.inputting = NO;

dlog(DEBUG_INPUTCONTROLLER, @"*** End of Input handling ***");
return handled;
}

@end

@implementation CIMInputReceiver (IMKServerInput)

// Committing a Composition
// 조합을 중단하고 현재까지 조합된 글자를 커밋한다.
- (BOOL)commitComposition:(id)sender controller:(CIMInputController *)controller {
dlog(DEBUG_LOGGING, @"LOGGING::EVENT::COMMIT-INTERNAL");
return [self commitCompositionEvent:sender controller:controller];
}

- (void)updateComposition:(CIMInputController *)controller {
dlog(DEBUG_LOGGING, @"LOGGING::EVENT::UPDATE-INTERNAL");
[controller updateComposition];
}

- (void)cancelComposition:(CIMInputController *)controller {
dlog(DEBUG_LOGGING, @"LOGGING::EVENT::CANCEL-INTERNAL");
[controller cancelComposition];
}

// Committing a Composition
// 조합을 중단하고 현재까지 조합된 글자를 커밋한다.
- (BOOL)commitCompositionEvent:(id)sender controller:(CIMInputController *)controller {
dlog(DEBUG_LOGGING, @"LOGGING::EVENT::COMMIT");
if (!CIMSharedInputManager.inputting) {
// 입력기 외부에서 들어오는 커밋 요청에 대해서는 편집 중인 글자도 커밋한다.
dlog(DEBUG_INPUTCONTROLLER, @"-- CANCEL composition because of external commit request from %@", sender);
dlog(DEBUG_LOGGING, @"LOGGING::EVENT::CANCEL-INTERNAL");
[self cancelCompositionEvent:controller];
}
// 왠지는 모르겠지만 프로그램마다 동작이 달라서 조합을 반드시 마쳐주어야 한다
// 터미널과 같이 조합중에 리턴키 먹는 프로그램은 조합 중인 문자가 없고 보통은 있다
NSString *commitString = [self.composer dequeueCommitString];

// 커밋할 문자가 없으면 중단
if (commitString.length > 0) {
dlog(DEBUG_INPUTCONTROLLER, @"** CIMInputController -commitComposition: with sender: %@ / strings: %@", sender, commitString);
NSRange range = controller.selectionRange;
dlog(DEBUG_LOGGING, @"LOGGING::COMMIT::%lu:%lu:%@", range.location, range.length, commitString);
if (range.length) {
[controller.client insertText:commitString replacementRange:range];
} else {
[controller.client insertText:commitString replacementRange:NSMakeRange(NSNotFound, NSNotFound)];
}
return YES;
}
return NO;
}

- (void)updateCompositionEvent:(CIMInputController *)controller {
dlog(DEBUG_LOGGING, @"LOGGING::EVENT::UPDATE");
dlog(DEBUG_INPUTCONTROLLER, @"** CIMInputController -updateComposition");
}

- (void)cancelCompositionEvent:(CIMInputController *)controller {
dlog(DEBUG_LOGGING, @"LOGGING::EVENT::CANCEL");
[self.composer cancelComposition];
}

- (NSString *)_internalComposedString {
NSString *string = self.composer.composedString;
return string;
}

// Getting Input Strings and Candidates
// 현재 입력 중인 글자를 반환한다. -updateComposition: 이 사용
- (id)composedString:(id)sender controller:(CIMInputController *)controller {
NSString *string = self._internalComposedString;
dlog(DEBUG_LOGGING, @"LOGGING::CHECK::COMPOSEDSTRING::(%@)", string);
dlog(DEBUG_INPUTCONTROLLER, @"** CIMInputController -composedString: with return: '%@'", string);
return string;
}

- (NSAttributedString *)originalString:(id)sender controller:(CIMInputController *)controller {
dlog(DEBUG_INPUTCONTROLLER, @"** CIMInputController -originalString:");
NSAttributedString *string = [[NSAttributedString alloc] initWithString:(self.composer).originalString];
dlog(DEBUG_LOGGING, @"LOGGING::CHECK::ORIGINALSTRING::%@", string.string);
return string;
}

- (NSArray *)candidates:(id)sender controller:(CIMInputController *)controller {
dlog(DEBUG_LOGGING, @"LOGGING::CHECK::CANDIDATES");
return self.composer.candidates;
}

- (void)candidateSelected:(NSAttributedString *)candidateString controller:(CIMInputController *)controller {
dlog(DEBUG_LOGGING, @"LOGGING::CHECK::CANDIDATESELECTED::%@", candidateString);
CIMSharedInputManager.inputting = YES;
[self.composer candidateSelected:candidateString];
[self commitComposition:self.inputClient controller:controller];
CIMSharedInputManager.inputting = NO;
}

- (void)candidateSelectionChanged:(NSAttributedString *)candidateString controller:(CIMInputController *)controller {
dlog(DEBUG_LOGGING, @"LOGGING::CHECK::CANDIDATESELECTIONCHANGED::%@", candidateString);
[self.composer candidateSelectionChanged:candidateString];
[self updateComposition:controller];
}

@end


@implementation CIMInputReceiver (IMKStateSetting)

//! @brief 마우스 이벤트를 잡을 수 있게 한다.
- (NSInteger)recognizedEvents:(_Null_unspecified id)sender {
dlog(DEBUG_LOGGING, @"LOGGING::CHECK::RECOGNIZEDEVENTS");
// NSFlagsChangeMask는 -handleEvent: 에서만 동작
return NSKeyDownMask | NSFlagsChangedMask | NSLeftMouseDownMask | NSRightMouseDownMask | NSLeftMouseDraggedMask | NSRightMouseDraggedMask;
}

//! @brief 자판 전환을 감지한다.
- (void)setValue:(_Null_unspecified id)value forTag:(long)tag client:(_Null_unspecified id)sender controller:(CIMInputController *)controller {
dlog(DEBUG_LOGGING, @"LOGGING::EVENT::CHANGE-%lu-%@", tag, value);
dlog(DEBUG_INPUTCONTROLLER, @"** CIMInputController -setValue:forTag:client: with value: %@ / tag: %lx / client: %@", value, tag, controller.client);
switch (tag) {
case kTextServiceInputModePropertyTag:
if (![value isEqualToString:self.composer.inputMode]) {
dassert(sender != nil);
[self commitComposition:sender controller:controller];
self.composer.inputMode = value;
}
break;
default:
dlog(DEBUG_INPUTCONTROLLER, @"**** UNKNOWN TAG %ld !!! ****", tag);
break;
}

dlog(1, @"==== source");
return;

// 미국자판으로 기본자판 잡는 것도 임시로 포기

TISInputSource *mainSource = _USSource();
NSString *mainSourceID = mainSource.identifier;
TISInputSource *currentSource = [TISInputSource currentSource];
dlog(1, @"current source: %@", currentSource);

[TISInputSource setInputMethodKeyboardLayoutOverride:mainSource];

TISInputSource *override = [TISInputSource inputMethodKeyboardLayoutOverride];
if (override == nil) {
dlog(1, @"override fail");
TISInputSource *currentASCIISource = [TISInputSource currentASCIICapableLayoutSource];
dlog(1, @"ascii: %@", currentASCIISource);
id ASCIISourceID = currentASCIISource.identifier;
if (![ASCIISourceID isEqualToString:mainSourceID]) {
dlog(1, @"id: %@ != %@", ASCIISourceID, mainSourceID);
BOOL mainSourceIsEnabled = mainSource.enabled;
//if (!mainSourceIsEnabled) {
// [mainSource enable];
//}
if (mainSourceIsEnabled) {
[mainSource select];
[currentSource select];
}
//if (!mainSourceIsEnabled) {
// [mainSource disable];
//}
}
} else {
dlog(1, @"overrided");
}
}

@end


@implementation CIMInputController
Expand All @@ -291,7 +46,7 @@ - (instancetype)initWithServer:(nullable IMKServer *)server delegate:(nullable i
self = [super initWithServer:server delegate:delegate client:inputClient];
if (self != nil) {
dlog(DEBUG_INPUTCONTROLLER, @"**** NEW INPUT CONTROLLER INIT **** WITH SERVER: %@ / DELEGATE: %@ / CLIENT: %@", server, delegate, inputClient);
self->_receiver = [[CIMInputReceiver alloc] initWithServer:server delegate:delegate client:inputClient];
self->_receiver = [[CIMInputReceiver alloc] initWithServer:server delegate:delegate client:inputClient controller:self];

IOService* service = [[IOService alloc] initWithName:@(kIOHIDSystemClass) error:NULL];
self->_ioConnect = [service openWithOwningTask:mach_task_self_ type:kIOHIDParamConnectType];
Expand Down
4 changes: 2 additions & 2 deletions CommonInputMethod/CIMInputController.swift
Expand Up @@ -19,11 +19,11 @@ extension CIMInputController {
}

@objcMembers class CIMMockInputController: CIMInputController {
@objc var _receiver: CIMInputReceiver
@objc var _receiver: CIMInputReceiver!

@objc override init(server: IMKServer, delegate: Any!, client: Any!) {
self._receiver = CIMInputReceiver(server: server, delegate: delegate, client: client)
super.init()
self._receiver = CIMInputReceiver(server: server, delegate: delegate, client: client, controller: self)
}

@objc func repoduceTextLog(_ text: String) throws {
Expand Down

0 comments on commit ebaed30

Please sign in to comment.