diff --git a/mac/TestInput/TestInput.xcodeproj/project.pbxproj b/mac/TestInput/TestInput.xcodeproj/project.pbxproj index 64b0d47446..70992fe2ef 100644 --- a/mac/TestInput/TestInput.xcodeproj/project.pbxproj +++ b/mac/TestInput/TestInput.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ E22804F320ACC3BE00085FCB /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = E22804F220ACC3BE00085FCB /* MainMenu.xib */; }; + E22804F820ADBFC400085FCB /* TestInputMethodAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E22804F720ADBFC400085FCB /* TestInputMethodAppDelegate.m */; }; E237EE721F6982E000DFBADF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E237EE711F6982E000DFBADF /* main.m */; }; E237EE771F6982E000DFBADF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E237EE761F6982E000DFBADF /* Assets.xcassets */; }; E237EE831F69849A00DFBADF /* TestInputController.m in Sources */ = {isa = PBXBuildFile; fileRef = E237EE821F69849A00DFBADF /* TestInputController.m */; }; @@ -16,6 +17,8 @@ /* Begin PBXFileReference section */ E22804F220ACC3BE00085FCB /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; + E22804F620ADBFC400085FCB /* TestInputMethodAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestInputMethodAppDelegate.h; sourceTree = ""; }; + E22804F720ADBFC400085FCB /* TestInputMethodAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestInputMethodAppDelegate.m; sourceTree = ""; }; E237EE6A1F6982E000DFBADF /* TestInput.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestInput.app; sourceTree = BUILT_PRODUCTS_DIR; }; E237EE711F6982E000DFBADF /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; E237EE761F6982E000DFBADF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -55,6 +58,8 @@ E237EE6C1F6982E000DFBADF /* TestInput */ = { isa = PBXGroup; children = ( + E22804F620ADBFC400085FCB /* TestInputMethodAppDelegate.h */, + E22804F720ADBFC400085FCB /* TestInputMethodAppDelegate.m */, E237EE841F6A2AC600DFBADF /* test.tiff */, E237EE711F6982E000DFBADF /* main.m */, E237EE761F6982E000DFBADF /* Assets.xcassets */, @@ -141,6 +146,7 @@ files = ( E237EE831F69849A00DFBADF /* TestInputController.m in Sources */, E237EE721F6982E000DFBADF /* main.m in Sources */, + E22804F820ADBFC400085FCB /* TestInputMethodAppDelegate.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/mac/TestInput/TestInput/MainMenu.xib b/mac/TestInput/TestInput/MainMenu.xib index d841fef55b..15401d9ad4 100644 --- a/mac/TestInput/TestInput/MainMenu.xib +++ b/mac/TestInput/TestInput/MainMenu.xib @@ -5,12 +5,21 @@ - + + + + + + + + + + - + diff --git a/mac/TestInput/TestInput/TestInputController.h b/mac/TestInput/TestInput/TestInputController.h index dfbfe4bb73..a82f9fea21 100644 --- a/mac/TestInput/TestInput/TestInputController.h +++ b/mac/TestInput/TestInput/TestInputController.h @@ -52,8 +52,6 @@ @interface TestInputController : IMKInputController { - IBOutlet NSMenu* _menu; - //_composedBuffer contains text that the input method has converted NSMutableString* _composedBuffer; //_original buffer contains the text has it was received from user input. @@ -61,6 +59,9 @@ //used to remember where text is being inserted in the _composedBuffer NSInteger _originalIndex; NSUInteger _numberOfDeletesExpected; + } +- (void)menuAction:(id)sender; + @end diff --git a/mac/TestInput/TestInput/TestInputController.m b/mac/TestInput/TestInput/TestInputController.m index ec6409fd5b..ad1cef9605 100644 --- a/mac/TestInput/TestInput/TestInputController.m +++ b/mac/TestInput/TestInput/TestInputController.m @@ -10,6 +10,7 @@ */ #import "TestInputController.h" +#import "TestInputMethodAppDelegate.h" #include /* For kVK_ constants, and TIS functions. */ @implementation TestInputController @@ -78,14 +79,11 @@ // return NO; // } - id inputClient; - inputClient = [self client]; + id inputClient = [self client]; if (![inputClient supportsUnicode]) return NO; -// [self setComposedBuffer:@""]; - NSUInteger location = [self logContext:inputClient]; if ([[event characters] isEqual: @"1"]) @@ -164,6 +162,15 @@ return YES; } + if ([[event characters] isEqual: @"~"]) + { + NSLog(@"Attempting to insert characters 'tilde' using insertText with undefined (default) replacement range."); + + [inputClient insertText:@"tilde" replacementRange:NSMakeRange(NSNotFound, NSNotFound)]; + + return YES; + } + if ([[event characters] isEqual: @"$"]) { NSLog(@"Attempting to delete the previous character by replacing it and the prior character with just the prior one. location = %lu", location); @@ -176,8 +183,29 @@ // This works in TextEdit, but not in TextWrangler. In Chrome, it just tacks the prior character on // at the current insertion point. - NSString *preChar = [[inputClient attributedSubstringFromRange:NSMakeRange(location - 2, 1)] string]; - NSLog(@"Previous character retrieved = %@", preChar); + NSString *preChar = @"="; + if ([inputClient respondsToSelector:@selector(attributedSubstringFromRange:)]) { + preChar = [[inputClient attributedSubstringFromRange:NSMakeRange(location - 2, 1)] string]; + if (!preChar || [preChar isEqualToString:@""]) { + NSLog(@"attributedSubstringFromRange did not return a previous character. Trying attributedSubstringForProposedRange..."); + if ([inputClient respondsToSelector:@selector(attributedSubstringForProposedRange:actualRange:)]) { + NSRange returnedRange; + preChar = [[inputClient attributedSubstringForProposedRange:NSMakeRange(location - 2, 1) actualRange:&returnedRange] string]; + if (!preChar || [preChar isEqualToString:@""]) { + NSLog(@"Previous character could NOT be retrieved using attributedSubstringFromRange or attributedSubstringForProposedRange. Using '&' instead"); + preChar = @"&"; + } + } + else { + NSLog(@"Client does not respond to attributedSubstringForProposedRange:actualRange:. Using '#' instead"); + preChar = @"#"; + } + } + else + NSLog(@"Previous character retrieved = %@", preChar); + } + else + NSLog(@"Client does not respond to attributedSubstringFromRange:. Using '=' instead"); [inputClient insertText:preChar replacementRange:NSMakeRange(location - 2, 2)]; return YES; @@ -493,38 +521,6 @@ CGKeyCode keyCodeForChar(const char c) [buffer setString:string]; } -/*! - @method - @abstract Called when a user action was taken that ends an input session. Typically triggered by the user selecting a new input method or keyboard layout. - @discussion When this method is called your controller should send the current input buffer to the client via a call to insertText:replacementRange:. Additionally, this is the time to clean up if that is necessary. - */ - -//-(void)commitComposition:(id)sender -//{ -// NSString* text = [self composedBuffer]; -// -// if ( text != nil && [text length] == 0 ) { -// [sender insertText: text replacementRange:NSMakeRange(NSNotFound, NSNotFound)]; -// [self setComposedBuffer:@""]; -// } -//} - -//// Return the composed buffer. If it is NIL create it. -//-(NSMutableString*)composedBuffer; -//{ -// if ( _composedBuffer == nil ) { -// _composedBuffer = [[NSMutableString alloc] init]; -// } -// return _composedBuffer; -//} -// -//// Change the composed buffer. -//-(void)setComposedBuffer:(NSString*)string -//{ -// NSMutableString* buffer = [self composedBuffer]; -// [buffer setString:string]; -//} - // Get the original buffer. -(NSMutableString*)originalBuffer { @@ -595,47 +591,23 @@ CGKeyCode keyCodeForChar(const char c) return selRange.location; } -NSMenu* _menu = nil; - - (void)activateServer:(id)sender { NSLog(@"*** activateServer ***"); NSLog(@"sender: %@", sender); [sender overrideKeyboardWithKeyboardNamed:@"com.apple.keylayout.US"]; - if (!_menu) { - _menu = [[NSApplication sharedApplication] mainMenu]; - if (!_menu) - NSLog(@"No main menu!"); - NSMenuItem *staticMenuItem1 = [_menu itemWithTag:1]; - if (staticMenuItem1) - [staticMenuItem1 setAction:@selector(menuAction:)]; - - NSMenuItem* staticDropdownMenuItem = [_menu itemWithTag:2]; - if (staticDropdownMenuItem) { - NSMenu* dropDownMenu = [staticDropdownMenuItem submenu]; - if (dropDownMenu) { - NSMenuItem* staticSubMenu = [dropDownMenu itemWithTag:10]; - if ( staticSubMenu ) { - NSLog(@"Setting action for static submenu item"); - [staticSubMenu setAction:@selector(menuAction:)]; - } - } - } - - NSMenuItem* dynamicDropdownMenuItem = [_menu itemWithTag:3]; - if (dynamicDropdownMenuItem) { - NSMenu* dropDownMenu = [staticDropdownMenuItem submenu]; - if (dropDownMenu) { - NSMenuItem *dynamicSubMenuItem = [[NSMenuItem alloc] initWithTitle:@"Submenu One" action:@selector(menuAction:) keyEquivalent:@""]; - [dynamicSubMenuItem setTag:100]; - NSLog(@"Adding dynamic submenu item"); - [dropDownMenu addItem:dynamicSubMenuItem]; - } - } - } [self performSelector:@selector(logContext:) withObject:sender afterDelay:0.25]; } +- (TestInputMethodAppDelegate *)AppDelegate { + return (TestInputMethodAppDelegate *)[NSApp delegate]; +} + +-(NSMenu*)menu +{ + return [self.AppDelegate menu]; +} + - (void)menuAction:(id)sender { NSMenuItem *mItem = [sender objectForKey:kIMKCommandMenuItemName]; NSInteger itag = mItem.tag; diff --git a/mac/TestInput/TestInput/TestInputMethodAppDelegate.h b/mac/TestInput/TestInput/TestInputMethodAppDelegate.h new file mode 100644 index 0000000000..43779bd238 --- /dev/null +++ b/mac/TestInput/TestInput/TestInputMethodAppDelegate.h @@ -0,0 +1,22 @@ +// +// TestInputMethodAppDelegate.h +// +// Copyright (c) 2018 SIL International. All rights reserved. +// + +#ifndef TestInputMethodAppDelegate_h +#define TestInputMethodAppDelegate_h + +#import +#import +#import "TestInputController.h" + +@interface TestInputMethodAppDelegate : NSObject { + IBOutlet NSMenu *_menu; +} + +- (NSMenu *)menu; + +@end + +#endif /* TestInputMethodAppDelegate_h */ diff --git a/mac/TestInput/TestInput/TestInputMethodAppDelegate.m b/mac/TestInput/TestInput/TestInputMethodAppDelegate.m new file mode 100644 index 0000000000..17a55c794c --- /dev/null +++ b/mac/TestInput/TestInput/TestInputMethodAppDelegate.m @@ -0,0 +1,53 @@ +// +// TestInputMethodAppDelegate.m +// Copyright (c) 2018 SIL International. All rights reserved. +// + +#import "TestInputMethodAppDelegate.h" + +@implementation TestInputMethodAppDelegate + ++ (TestInputMethodAppDelegate *)AppDelegate { + return (TestInputMethodAppDelegate *)[NSApp delegate]; +} + +- (NSMenu *)menu { + return _menu; +} + +- (void)awakeFromNib { + if (!_menu) + NSLog(@"No main menu!"); + NSMenuItem *staticMenuItem1 = [_menu itemWithTag:1]; + if (staticMenuItem1) { + NSLog(@"Setting action for menu 1"); + [staticMenuItem1 setAction:@selector(menuAction:)]; + } + + NSMenuItem* staticDropdownMenuItem = [_menu itemWithTag:2]; + if (staticDropdownMenuItem) { + NSLog(@"Looking for dropdown menu on menu 2"); + NSMenu* dropDownMenu = [staticDropdownMenuItem submenu]; + if (dropDownMenu) { + NSLog(@"Looking for menu 10"); + NSMenuItem* staticSubMenu = [dropDownMenu itemWithTag:10]; + if ( staticSubMenu ) { + NSLog(@"Setting action for static submenu item"); + [staticSubMenu setAction:@selector(menuAction:)]; + } + } + } + + NSMenuItem* dynamicDropdownMenuItem = [_menu itemWithTag:3]; + if (dynamicDropdownMenuItem) { + NSLog(@"Looking for dropdown menu on menu 3"); + NSMenu* dropDownMenu = [dynamicDropdownMenuItem submenu]; + if (dropDownMenu) { + NSMenuItem *dynamicSubMenuItem = [[NSMenuItem alloc] initWithTitle:@"Submenu One" action:@selector(menuAction:) keyEquivalent:@""]; + [dynamicSubMenuItem setTag:100]; + NSLog(@"Adding dynamic submenu item 100"); + [dropDownMenu addItem:dynamicSubMenuItem]; + } + } +} +@end diff --git a/mac/TestInput/TestInput/main.m b/mac/TestInput/TestInput/main.m index da291c77dd..c0bbb40cbd 100644 --- a/mac/TestInput/TestInput/main.m +++ b/mac/TestInput/TestInput/main.m @@ -57,17 +57,38 @@ const NSString* kConnectionName = @"TestInput_2_Connection"; //let this be a global so our application controller delegate can access it easily IMKServer* server; -int main(int argc, char *argv[]) -{ - NSString* identifier; - - //find the bundle identifier and then initialize the input method server - identifier = [[NSBundle mainBundle] bundleIdentifier]; - server = [[IMKServer alloc] initWithName:(NSString*)kConnectionName bundleIdentifier:[[NSBundle mainBundle] bundleIdentifier]]; - [NSBundle loadNibNamed:@"MainMenu" owner:[NSApplication sharedApplication]]; - - //finally run everything - [[NSApplication sharedApplication] run]; - +int main(int argc, const char * argv[]) { + NSString *identifier; + @autoreleasepool { + identifier = [[NSBundle mainBundle] bundleIdentifier]; + server = [[IMKServer alloc] initWithName:(NSString *)kConnectionName bundleIdentifier:identifier]; + [NSBundle loadNibNamed:@"MainMenu" owner:[NSApplication sharedApplication]]; + [[NSApplication sharedApplication] run]; + } return 0; } + +//int main(int argc, char *argv[]) +//{ +// NSString* identifier; +// +// //find the bundle identifier and then initialize the input method server +// identifier = [[NSBundle mainBundle] bundleIdentifier]; +// server = [[IMKServer alloc] initWithName:(NSString*)kConnectionName bundleIdentifier:[[NSBundle mainBundle] bundleIdentifier]]; +// NSLog(@"About to load MainMenu..."); +// @try { +// [NSBundle loadNibNamed:@"MainMenu" owner:[NSApplication sharedApplication]]; +// if ([[NSApplication sharedApplication] mainMenu]) +// NSLog(@"Finished loading MainMenu!"); +// else +// NSLog(@"MainMenu not set!!!"); +// } +// @catch (NSException *e) { +// NSLog(@"Error loading MainMenu: %@", e.description); +// } +// +// //finally run everything +// [[NSApplication sharedApplication] run]; +// +// return 0; +//}