diff --git a/mac/Keyman4Mac/Keyman4Mac/AppDelegate.m b/mac/Keyman4Mac/Keyman4Mac/AppDelegate.m index 2af130ae928..44f7cfda587 100644 --- a/mac/Keyman4Mac/Keyman4Mac/AppDelegate.m +++ b/mac/Keyman4Mac/Keyman4Mac/AppDelegate.m @@ -8,7 +8,6 @@ #import "AppDelegate.h" #import -#import static BOOL debugMode = YES; @@ -68,8 +67,6 @@ - (void)awakeFromNib { } - (void)windowDidResize:(NSNotification *)notification { - os_log_t oskLog = os_log_create("org.sil.keyman", "osk"); - os_log_with_type(oskLog, OS_LOG_TYPE_DEBUG, "AppDelegate windowDidResize"); [self.oskView resizeOSKLayout]; } diff --git a/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj b/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj index a9fc9f5e859..35a362f2617 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj +++ b/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 290BC680274B9DB1005CD1C3 /* KMPackageInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 290BC67F274B9DB1005CD1C3 /* KMPackageInfo.m */; }; 290BC75E274F3FD7005CD1C3 /* KMKeyboardInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 290BC75D274F3FD7005CD1C3 /* KMKeyboardInfo.m */; }; + 2915DC512BFE35DB0051FC52 /* KMLogs.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B4A0D32BF7675A00682049 /* KMLogs.m */; }; 293EA3E627140D8100545EED /* KMAboutWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 293EA3E827140D8100545EED /* KMAboutWindowController.xib */; }; 293EA3EB27140DEC00545EED /* preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = 293EA3ED27140DEC00545EED /* preferences.xib */; }; 293EA3F427181FDA00545EED /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 293EA3F627181FDA00545EED /* Localizable.strings */; }; @@ -27,6 +28,7 @@ 299B5E2129126CA20070841D /* keyman-icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 299B5E1F29126CA20070841D /* keyman-icon.png */; }; 29B42A572728339900EDD5D3 /* KMInfoWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 29B42A592728339900EDD5D3 /* KMInfoWindowController.xib */; }; 29B42A602728343B00EDD5D3 /* KMKeyboardHelpWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 29B42A622728343B00EDD5D3 /* KMKeyboardHelpWindowController.xib */; }; + 29B4A0D52BF7675A00682049 /* KMLogs.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B4A0D32BF7675A00682049 /* KMLogs.m */; }; 29B6FB732BC39DD60074BF7F /* TextApiComplianceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B6FB722BC39DD60074BF7F /* TextApiComplianceTests.m */; }; 37A245C12565DFA6000BBF92 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 37A245C02565DFA6000BBF92 /* Assets.xcassets */; }; 37AE5C9D239A7B770086CC7C /* qrcode.min.js in Resources */ = {isa = PBXBuildFile; fileRef = 37AE5C9C239A7B770086CC7C /* qrcode.min.js */; }; @@ -216,6 +218,8 @@ 29B42A612728343B00EDD5D3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/KMKeyboardHelpWindowController.xib; sourceTree = ""; }; 29B42A642728343F00EDD5D3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/KMKeyboardHelpWindowController.strings; sourceTree = ""; }; 29B42A682728344600EDD5D3 /* km */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = km; path = km.lproj/KMKeyboardHelpWindowController.strings; sourceTree = ""; }; + 29B4A0D32BF7675A00682049 /* KMLogs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KMLogs.m; sourceTree = ""; }; + 29B4A0D42BF7675A00682049 /* KMLogs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KMLogs.h; sourceTree = ""; }; 29B5BC0328169A6300B86A17 /* ff */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ff; path = ff.lproj/KMAboutWindowController.strings; sourceTree = ""; }; 29B5BC0428169A6400B86A17 /* ff */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ff; path = ff.lproj/preferences.strings; sourceTree = ""; }; 29B5BC0528169A6400B86A17 /* ff */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ff; path = ff.lproj/KMInfoWindowController.strings; sourceTree = ""; }; @@ -540,8 +544,10 @@ 989C9C0A1A7876DE00A20425 /* Keyman4MacIM */ = { isa = PBXGroup; children = ( - 299ABD7029ECE75B00AA5948 /* KeySender.h */, + 29B4A0D42BF7675A00682049 /* KMLogs.h */, + 29B4A0D32BF7675A00682049 /* KMLogs.m */, 299ABD6F29ECE75B00AA5948 /* KeySender.m */, + 299ABD7029ECE75B00AA5948 /* KeySender.h */, 297A501128DF4D360074EB1B /* Privacy */, 98FE105B1B4DE86300525F54 /* Categories */, 98D6DA791A799EE700B09822 /* Frameworks */, @@ -965,6 +971,7 @@ 9A3D6C5D221531B0008785A3 /* KMOSVersion.m in Sources */, 989C9C111A7876DE00A20425 /* main.m in Sources */, 290BC680274B9DB1005CD1C3 /* KMPackageInfo.m in Sources */, + 29B4A0D52BF7675A00682049 /* KMLogs.m in Sources */, 98BF924F1BF02DC20002126A /* KMBarView.m in Sources */, E240F599202DED740000067D /* KMPackage.m in Sources */, 984B8F441AF1C3D900E096A8 /* OSKWindowController.m in Sources */, @@ -998,6 +1005,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2915DC512BFE35DB0051FC52 /* KMLogs.m in Sources */, 2992F4202A28482800E08929 /* PrivacyWindowController.m in Sources */, 2992F41F2A2847C900E08929 /* TextApiCompliance.m in Sources */, 2992F41E2A2847AF00E08929 /* PrivacyConsent.m in Sources */, diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMAboutWindow/KMAboutBGView.m b/mac/Keyman4MacIM/Keyman4MacIM/KMAboutWindow/KMAboutBGView.m index 030e1b4ed25..361967506ed 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMAboutWindow/KMAboutBGView.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMAboutWindow/KMAboutBGView.m @@ -7,6 +7,7 @@ // #import "KMAboutBGView.h" +#import "KMLogs.h" @implementation KMAboutBGView @@ -20,15 +21,15 @@ - (void)drawRect:(NSRect)rect { NSRect topFill, botFill; topFill = rect; botFill = rect; - // NSLog(@"rect origin x %f y %f size h %f w %f", rect.origin.x, rect.origin.y, rect.size.height, rect.size.width); + //os_log_debug([KMLogs uiLog], "rect origin x %f y %f size h %f w %f", rect.origin.x, rect.origin.y, rect.size.height, rect.size.width); NSView *topImgView = [self viewWithTag:1]; - // NSLog(@"topImgView origin x %f y %f size h %f w %f before", topImgView.frame.origin.x, topImgView.frame.origin.y, topImgView.frame.size.height, topImgView.frame.size.width); + //os_log_debug([KMLogs uiLog], "topImgView origin x %f y %f size h %f w %f before", topImgView.frame.origin.x, topImgView.frame.origin.y, topImgView.frame.size.height, topImgView.frame.size.width); NSInteger imgOriginHeightDelta = topImgView.frame.origin.y - rect.origin.y; topFill.origin.y += imgOriginHeightDelta; topFill.size.height -= imgOriginHeightDelta; botFill.size.height = imgOriginHeightDelta; - // NSLog(@"topFill origin x %f y %f size h %f w %f after raising to imgHeight %ld", topFill.origin.x, topFill.origin.y, topFill.size.height, topFill.size.width, imgOriginHeightDelta); - // NSLog(@"botFill origin x %f y %f size h %f w %f after reducing by imgHeight %ld", botFill.origin.x, botFill.origin.y, botFill.size.height, botFill.size.width, imgOriginHeightDelta); + //os_log_debug([KMLogs uiLog], "topFill origin x %f y %f size h %f w %f after raising to imgHeight %ld", topFill.origin.x, topFill.origin.y, topFill.size.height, topFill.size.width, imgOriginHeightDelta); + //os_log_debug([KMLogs uiLog], "botFill origin x %f y %f size h %f w %f after reducing by imgHeight %ld", botFill.origin.x, botFill.origin.y, botFill.size.height, botFill.size.width, imgOriginHeightDelta); [[NSColor whiteColor] setFill]; NSRectFillUsingOperation(topFill, NSCompositingOperationSourceOver); [[NSColor windowBackgroundColor] setFill]; diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMAboutWindow/KMAboutWindowController.m b/mac/Keyman4MacIM/Keyman4MacIM/KMAboutWindow/KMAboutWindowController.m index d8674184c06..08b4d1b1e66 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMAboutWindow/KMAboutWindowController.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMAboutWindow/KMAboutWindowController.m @@ -9,6 +9,7 @@ #import "KMAboutWindowController.h" #import "KMInputMethodAppDelegate.h" #import "KMOSVersion.h" +#import "KMLogs.h" @interface KMAboutWindowController () @property (nonatomic, weak) IBOutlet NSTextField *versionLabel; @@ -53,12 +54,12 @@ - (IBAction)configAction:(id)sender { u_int16_t systemVersion = [KMOSVersion SystemVersion]; if ([KMOSVersion Version_10_13_1] <= systemVersion && systemVersion <= [KMOSVersion Version_10_13_3]) // between 10.13.1 and 10.13.3 inclusive { - NSLog(@"About Box: calling workaround instead of showPreferences (sys ver %x)", systemVersion); + os_log([KMLogs uiLog], "About Box: calling workaround instead of showPreferences (sys ver %x)", systemVersion); [self.AppDelegate showConfigurationWindow]; // call our workaround } else { - NSLog(@"About Box: calling Apple's showPreferences (sys ver %x)", systemVersion); + os_log([KMLogs uiLog], "About Box: calling Apple's showPreferences (sys ver %x)", systemVersion); [self.AppDelegate.inputController showPreferences:sender]; // call Apple API } [self close]; diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMConfiguration/KMConfigurationWindowController.m b/mac/Keyman4MacIM/Keyman4MacIM/KMConfiguration/KMConfigurationWindowController.m index acb6a4140ff..3e2ffe24100 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMConfiguration/KMConfigurationWindowController.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMConfiguration/KMConfigurationWindowController.m @@ -8,6 +8,7 @@ #import "KMConfigurationWindowController.h" #import "KMDownloadKBWindowController.h" +#import "KMLogs.h" @interface KMConfigurationWindowController () @property (nonatomic, weak) IBOutlet NSTableView *tableView; @@ -79,8 +80,7 @@ - (void)webView:(WebView *)sender decidePolicyForNewWindowAction:(NSDictionary * - (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id)listener { NSString* url = [[request URL] absoluteString]; - if (self.AppDelegate.debugMode) - NSLog(@"decidePolicyForNavigationAction, navigating to %@", url); + os_log_debug([KMLogs uiLog], "decidePolicyForNavigationAction, navigating to %{public}@", url); if([url hasPrefix: @"file:"]) { [listener use]; @@ -358,14 +358,12 @@ - (void)checkBoxAction:(id)sender { NSButton *checkBox = (NSButton *)sender; NSString *kmxFilePath = [self kmxFilePathAtIndex:checkBox.tag]; if (checkBox.state == NSOnState) { - if ([self.AppDelegate debugMode]) - NSLog(@"Adding active keyboard: %@", kmxFilePath); + os_log_debug([KMLogs uiLog], "Adding active keyboard: %{public}@", kmxFilePath); [self.activeKeyboards addObject:kmxFilePath]; [self saveActiveKeyboards]; } else if (checkBox.state == NSOffState) { - if ([self.AppDelegate debugMode]) - NSLog(@"Disabling active keyboard: %@", kmxFilePath); + os_log_debug([KMLogs uiLog], "Disabling active keyboard: %{public}@", kmxFilePath); [self.activeKeyboards removeObject:kmxFilePath]; [self saveActiveKeyboards]; } @@ -443,10 +441,7 @@ - (void)handleRequestToInstallPackage:(KMPackage *) package { NSString *keyboardInfoString = NSLocalizedString(@"info-install-keyboard-filename", nil); [self.confirmKmpInstallAlertView setInformativeText:[NSString localizedStringWithFormat:keyboardInfoString, package.getOrigKmpFilename]]; - if ([self.AppDelegate debugMode]) { - NSLog(@"Asking user to confirm installation of %@...", package.getOrigKmpFilename); - NSLog(@"KMP - temp file name: %@", package.getTempKmpFilename); - } + os_log_debug([KMLogs uiLog], "Asking user to confirm installation of %{public}@, KMP - temp file name: %{public}@", package.getOrigKmpFilename, package.getTempKmpFilename); [self.confirmKmpInstallAlertView beginSheetModalForWindow:self.window modalDelegate:self @@ -457,9 +452,7 @@ - (void)handleRequestToInstallPackage:(KMPackage *) package { - (void)installPackageFile:(NSString *)kmpFile { // kmpFile could be a temp file (in fact, it always is!), so don't display the name. - if ([self.AppDelegate debugMode]) { - NSLog(@"KMP - Ready to unzip/install Package File: %@", kmpFile); - } + os_log_debug([KMLogs dataLog], "KMP - Ready to unzip/install Package File: %{public}@", kmpFile); BOOL didUnzip = [self.AppDelegate unzipFile:kmpFile]; @@ -477,8 +470,8 @@ - (void)installPackageFile:(NSString *)kmpFile { didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:nil]; } - else if ([self.AppDelegate debugMode]) { - NSLog(@"Completed installation of KMP file."); + else { + os_log_debug([KMLogs dataLog], "Completed installation of KMP file."); } } @@ -555,9 +548,7 @@ - (NSAlert *)confirmKmpInstallAlertView { } - (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo { - if ([self.AppDelegate debugMode]) { - NSLog(@"User responded to NSAlert"); - } + os_log_debug([KMLogs uiLog], "User responded to NSAlert"); if (alert == _deleteAlertView) { if (returnCode == NSAlertFirstButtonReturn) { // Delete [self deleteFileAtIndex:(__bridge NSNumber *)contextInfo]; @@ -567,9 +558,7 @@ - (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInf } else if (alert == _confirmKmpInstallAlertView) { KMPackage *package = (__bridge KMPackage *)contextInfo; - if ([self.AppDelegate debugMode]) { - NSLog(@"KMP - Temp file: %@", package.getTempKmpFilename); - } + os_log_debug([KMLogs uiLog], "KMP - Temp file: %{public}@", package.getTempKmpFilename); if (returnCode == NSAlertFirstButtonReturn) { // Install [self installPackageFile: package.getTempKmpFilename]; } diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMDownloadKeyboard/KMDownloadKBWindowController.m b/mac/Keyman4MacIM/Keyman4MacIM/KMDownloadKeyboard/KMDownloadKBWindowController.m index e7b42138f54..4b5ce44dea8 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMDownloadKeyboard/KMDownloadKBWindowController.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMDownloadKeyboard/KMDownloadKBWindowController.m @@ -8,6 +8,7 @@ #import "KMDownloadKBWindowController.h" #import "KMInputMethodAppDelegate.h" +#import "KMLogs.h" @interface KMDownloadKBWindowController () @property (nonatomic, weak) IBOutlet WebView *webView; @@ -29,8 +30,8 @@ - (void)windowDidLoad { NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]; KeymanVersionInfo keymanVersionInfo = [[self AppDelegate] versionInfo]; NSString *url = [NSString stringWithFormat:@"https://%@/go/macos/14.0/download-keyboards/?version=%@", keymanVersionInfo.keymanCom, version]; - if (self.AppDelegate.debugMode) - NSLog(@"KMDownloadKBWindowController opening url = %@, version = '%@'", url, version); + + os_log_debug([KMLogs uiLog], "KMDownloadKBWindowController opening url = %@, version = '%@'", url, version); [self.webView.mainFrame loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]]; } @@ -41,9 +42,8 @@ - (void)webView:(WebView *)sender decidePolicyForNewWindowAction:(NSDictionary * - (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id)listener { NSString* url = [[request URL] absoluteString]; - if (self.AppDelegate.debugMode) - NSLog(@"decidePolicyForNavigationAction, navigating to %@", url); - + os_log_debug([KMLogs uiLog], "decidePolicyForNavigationAction, navigating to %@", url); + // The pattern for matching links matches work in #3602 NSString* urlPathMatchKeyboardsInstall = @"^http(?:s)?://keyman(?:-staging)?\\.com(?:\\.local)?/keyboards/install/([^?/]+)(?:\\?(.+))?$"; // e.g. https://keyman.com/keyboards/install/foo @@ -61,8 +61,7 @@ - (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary NSArray* matchesInstall = [regexInstall matchesInString:url options:0 range:range]; if(matchesInstall.count > 0) { - if (self.AppDelegate.debugMode) - NSLog(@"Farming out download to app delegate."); + os_log_debug([KMLogs uiLog], "Delegating download to app delegate."); [listener ignore]; NSTextCheckingResult* match = (NSTextCheckingResult*) matchesInstall[0]; NSString* matchKeyboardId = [url substringWithRange:[match rangeAtIndex:1]]; @@ -74,22 +73,19 @@ - (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary [regexGo numberOfMatchesInString:url options:0 range:range] > 0) { // allow https://keyman.com/keyboards* to go through // allow https://keyman.com/go/macos/download-keyboards to go through - if (self.AppDelegate.debugMode) - NSLog(@"Accepting link in this browser."); + os_log_debug([KMLogs uiLog], "Accepting link in this browser."); [listener use]; } else if([url startsWith:@"keyman:"]) { if ([url startsWith:@"keyman:link?url="]) { - if (self.AppDelegate.debugMode) - NSLog(@"Opening keyman:link URL in default browser: %@", url); + os_log_debug([KMLogs uiLog], "Opening keyman:link URL in default browser: %@", url); [listener ignore]; url = [request.URL.absoluteString substringFromIndex:[@"keyman:link?url=" length]]; [[NSWorkspace sharedWorkspace] openURL: [[NSURL alloc] initWithString:url]]; } else { - if (self.AppDelegate.debugMode) - NSLog(@"Farming out download to app delegate."); + os_log_debug([KMLogs uiLog], "Delegating download to app delegate."); [listener ignore]; [self.AppDelegate processURL:url]; } @@ -97,8 +93,7 @@ - (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary else { // Open in external browser - if (self.AppDelegate.debugMode) - NSLog(@"Opening URL in default browser: %@", url); + os_log_debug([KMLogs uiLog], "Opening URL in default browser: %@", url); [listener ignore]; [[NSWorkspace sharedWorkspace] openURL: [[NSURL alloc] initWithString:url]]; } diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInfoWindow/KMInfoWindowController.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInfoWindow/KMInfoWindowController.m index a37d66148bd..6be446ddd28 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInfoWindow/KMInfoWindowController.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInfoWindow/KMInfoWindowController.m @@ -10,6 +10,7 @@ #import "KMInputMethodAppDelegate.h" #import "KMPackageInfo.h" #import "KMKeyboardInfo.h" +#import "KMLogs.h" #import @interface KMInfoWindowController () @@ -199,7 +200,7 @@ - (NSString *)detailsHtml { return htmlStr; } @catch (NSException *e) { - NSLog(@"Error = %@", e.description); + os_log_error([KMLogs uiLog], "Error = %@", e.description); return nil; } } diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputController.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputController.m index 7c65bd97490..f832abf27fd 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputController.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputController.m @@ -10,6 +10,7 @@ #import "KMInputMethodEventHandler.h" #import "KMOSVersion.h" #include /* For kVK_ constants. */ +#import "KMLogs.h" @implementation KMInputController @@ -22,9 +23,7 @@ - (KMInputMethodAppDelegate *)AppDelegate { - (id)initWithServer:(IMKServer *)server delegate:(id)delegate client:(id)inputClient { - if ([self.AppDelegate debugMode]) { - NSLog(@"Initializing Keyman Input Method with server: %@", server); - } + os_log_debug([KMLogs lifecycleLog], "Initializing Keyman Input Method for server with bundleID: %{public}@", server.bundle.bundleIdentifier); self = [super initWithServer:server delegate:delegate client:inputClient]; if (self) { @@ -43,12 +42,8 @@ - (NSUInteger)recognizedEvents:(id)sender { } - (BOOL)handleEvent:(NSEvent *)event client:(id)sender { - if ([self.AppDelegate debugMode]) - NSLog(@"handleEvent: event = %@", event); - if (event == nil || sender == nil || self.kmx == nil || _eventHandler == nil) { - if ([self.AppDelegate debugMode]) - NSLog(@"handleEvent: not handling event"); + os_log_error([KMLogs eventsLog], "IMInputController handleEvent: not prepared to handle event = %{public}@", event); return NO; // Not sure this can ever happen. } @@ -58,7 +53,7 @@ - (BOOL)handleEvent:(NSEvent *)event client:(id)sender { // Passthrough from the app delegate low level event hook // to the input method event handler for handleBackspace. - (void)handleBackspace:(NSEvent *)event { - [self.AppDelegate logDebugMessage:@"KMInputController handleBackspace, event = %@", event]; + os_log_debug([KMLogs keyLog], "KMInputController handleBackspace, event = %{public}@", event); if(_eventHandler != nil) { [_eventHandler handleBackspace:event]; } @@ -77,9 +72,7 @@ - (void)activateServer:(id)sender { NSRunningApplication *currApp = [[NSWorkspace sharedWorkspace] frontmostApplication]; NSString *clientAppId = [currApp bundleIdentifier]; - if ([self.AppDelegate debugMode]) { - NSLog(@"activateServer, new active app: '%@', sender %@", clientAppId, sender); - } + os_log_debug([KMLogs lifecycleLog], "activateServer, new active app: '%{public}@'", clientAppId); _eventHandler = [[KMInputMethodEventHandler alloc] initWithClient:clientAppId client:sender]; @@ -88,9 +81,7 @@ - (void)activateServer:(id)sender { - (void)deactivateServer:(id)sender { if ([self.AppDelegate debugMode]) { - NSLog(@"*** deactivateServer ***"); - NSLog(@"sender: %@", sender); - NSLog(@"***"); + os_log_debug([KMLogs lifecycleLog], "deactivateServer, sender %{public}@", sender); } @synchronized(servers) { for (int i = 0; i < servers.count; i++) { @@ -100,9 +91,7 @@ - (void)deactivateServer:(id)sender { } } if (servers.count == 0) { - if ([self.AppDelegate debugMode]) { - NSLog(@"No known active server for Keyman IM. Starting countdown to sleep..."); - } + os_log_debug([KMLogs lifecycleLog], "No known active server for Keyman IM. Starting countdown to sleep..."); [self performSelector:@selector(timerAction:) withObject:sender afterDelay:0.7]; } } @@ -124,7 +113,7 @@ - (void)timerAction:(id)lastServer { /* - (NSDictionary *)modes:(id)sender { if ([self.AppDelegate debugMode]) - NSLog(@"*** Modes ***"); + os_log_debug([KMLogs lifecycleLog], "*** Modes ***"); if (_kmModes == nil) { NSDictionary *amhMode = [[NSDictionary alloc] initWithObjectsAndKeys:@"keyman.png", kTSInputModeAlternateMenuIconFileKey, [NSNumber numberWithBool:YES], kTSInputModeDefaultStateKey, @@ -171,8 +160,7 @@ - (KMXFile *)kmx { - (void)menuAction:(id)sender { NSMenuItem *mItem = [sender objectForKey:kIMKCommandMenuItemName]; NSInteger itag = mItem.tag; - if ([self.AppDelegate debugMode]) - NSLog(@"Keyman menu clicked - tag: %lu", itag); + os_log_debug([KMLogs uiLog], "Keyman menu clicked - tag: %lu", itag); if (itag == CONFIG_MENUITEM_TAG) { [self showConfigurationWindow:sender]; } @@ -194,12 +182,12 @@ - (void)showConfigurationWindow:(id)sender { u_int16_t systemVersion = [KMOSVersion SystemVersion]; if ([KMOSVersion Version_10_13_1] <= systemVersion && systemVersion <= [KMOSVersion Version_10_13_3]) // between 10.13.1 and 10.13.3 inclusive { - NSLog(@"Input Menu: calling workaround instead of showPreferences (sys ver %x)", systemVersion); + os_log_info([KMLogs uiLog], "Input Menu: calling workaround instead of showPreferences (sys ver %x)", systemVersion); [self.AppDelegate showConfigurationWindow]; // call our workaround } else { - NSLog(@"Input Menu: calling Apple's showPreferences (sys ver %x)", systemVersion); + os_log_info([KMLogs uiLog], "Input Menu: calling Apple's showPreferences (sys ver %x)", systemVersion); [self showPreferences:sender]; // call Apple API } } diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.h b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.h index 346fbc3edd7..4bf463c177f 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.h +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.h @@ -97,7 +97,6 @@ static const int KEYMAN_FIRST_KEYBOARD_MENUITEM_INDEX = 0; @property (nonatomic, assign) BOOL useNullChar; @property (nonatomic, assign) BOOL debugMode; -- (void)logDebugMessage:(NSString *)format, ...; - (NSMenu *)menu; - (void)saveActiveKeyboards; - (void)readPersistedOptions; diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m index e5311f55053..0675a78adec 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m @@ -23,6 +23,7 @@ #import "KMPackageInfo.h" #import "KMKeyboardInfo.h" #import "PrivacyConsent.h" +#import "KMLogs.h" @import Sentry; /** NSUserDefaults keys */ @@ -107,7 +108,7 @@ - (id)init { } - (void)initCompletion { - NSLog(@"initCompletionHandler method invoked"); + os_log_info([KMLogs startupLog], "initCompletionHandler method invoked"); [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleURLEvent:withReplyEvent:) forEventClass:kInternetEventClass @@ -124,10 +125,10 @@ - (void)initCompletion { nil); if (!self.lowLevelEventTap) { - NSLog(@"Unable to create lowLevelEventTap!"); + os_log_error([KMLogs startupLog], "Unable to create lowLevelEventTap!"); } else { - NSLog(@"Successfully created lowLevelEventTap with CGEventTapCreate."); + os_log([KMLogs startupLog], "Successfully created lowLevelEventTap with CGEventTapCreate."); CFRelease(self.lowLevelEventTap); } @@ -140,15 +141,6 @@ - (void)initCompletion { } } --(void)logDebugMessage:(NSString *)format, ... { - if (self.debugMode) { - va_list args; - va_start(args, format); - NSLogv(format, args); - va_end(args); - } -} - - (KeymanVersionInfo)versionInfo { KeymanVersionInfo result; // Get version information from Info.plist, which is filled in @@ -178,6 +170,8 @@ -(void)applicationDidFinishLaunching:(NSNotification *)aNotification { KeymanVersionInfo keymanVersionInfo = [self versionInfo]; NSString *releaseName = [NSString stringWithFormat:@"%@", keymanVersionInfo.versionGitTag]; + [KMLogs reportLogStatus]; + [SentrySDK startWithConfigureOptions:^(SentryOptions *options) { options.dsn = @"https://960f8b8e574c46e3be385d60ce8e1fea@o1005580.ingest.sentry.io/5983522"; options.releaseName = releaseName; @@ -190,9 +184,9 @@ -(void)applicationDidFinishLaunching:(NSNotification *)aNotification { #ifdef USE_ALERT_SHOW_HELP_TO_FORCE_EASTER_EGG_CRASH_FROM_ENGINE - (BOOL)alertShowHelp:(NSAlert *)alert { - NSLog(@"Sentry - KME: Got call to force crash from engine"); + os_log_error([KMLogs startupLog], "Sentry - KME: Got call to force crash from engine"); [SentrySDK crash]; - NSLog(@"Sentry - KME: should not have gotten this far!"); + os_log_error([KMLogs startupLog], "Sentry - KME: should not have gotten this far!"); return NO; } #endif @@ -206,13 +200,11 @@ - (void)processURL:(NSString*)rawUrl { NSMutableString *urlStr = [NSMutableString stringWithString:rawUrl]; [urlStr replaceOccurrencesOfString:@"keyman:" withString:@"keyman/" options:0 range:NSMakeRange(0, 7)]; NSURL *url = [NSURL URLWithString:urlStr]; - if (self.debugMode) - NSLog(@"url = %@", url); + os_log_debug([KMLogs keyboardLog], "processURL, url = %{public}@", url); if ([url.lastPathComponent isEqualToString:@"download"]) { if (_connection != nil) { - if (self.debugMode) - NSLog(@"Already downloading a keyboard."); + os_log_debug([KMLogs keyboardLog], "Already downloading a keyboard."); return; } @@ -236,23 +228,17 @@ + (KMInputMethodAppDelegate *)AppDelegate { } -(void) sleepFollowingDeactivationOfServer:(id)lastServer { - if ([self debugMode]) { - NSLog(@"Keyman no longer active IM."); - } + os_log_debug([KMLogs lifecycleLog], "Keyman no longer active IM."); self.sleeping = YES; if ([self.oskWindow.window isVisible]) { - if ([self debugMode]) { - NSLog(@"Hiding OSK."); - } + os_log_debug([KMLogs oskLog], "sleepFollowingDeactivationOfServer, Hiding OSK."); // Storing this ensures that if the deactivation is temporary, resulting from dropping down a menu, // the OSK will re-display when that client application re-activates. _lastServerWithOSKShowing = lastServer; [self.oskWindow.window setIsVisible:NO]; } if (self.lowLevelEventTap) { - if ([self debugMode]) { - NSLog(@"Disabling event tap..."); - } + os_log_debug([KMLogs lifecycleLog], "sleepFollowingDeactivationOfServer, disabling event tap..."); CGEventTapEnable(self.lowLevelEventTap, NO); } } @@ -260,9 +246,7 @@ -(void) sleepFollowingDeactivationOfServer:(id)lastServer { -(void) wakeUpWith:(id)newServer { self.sleeping = NO; if (self.lowLevelEventTap && !CGEventTapIsEnabled(self.lowLevelEventTap)) { - if ([self debugMode]) { - NSLog(@"Keyman is now the active IM. Re-enabling event tap..."); - } + os_log_debug([KMLogs lifecycleLog], "wakeUpWith, Keyman is now the active IM. Re-enabling event tap..."); CGEventTapEnable(self.lowLevelEventTap, YES); } // See note in sleepFollowingDeactivationOfServer. @@ -282,7 +266,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef if (!appDelegate.sleeping) { // REVIEW: We might need to consider putting in some kind of counter/flag to ensure that the very next // event is not another disable so we don't end up in an endless cycle. - NSLog(@"Event tap disabled by %@! Attempting to restart...", (type == kCGEventTapDisabledByTimeout ? @"timeout" : @"user")); + os_log([KMLogs eventsLog], "Event tap disabled by %{public}@! Attempting to restart...", (type == kCGEventTapDisabledByTimeout ? @"timeout" : @"user")); CGEventTapEnable(appDelegate.lowLevelEventTap, YES); if (!CGEventTapIsEnabled(appDelegate.lowLevelEventTap)) { if (appDelegate.runLoopEventSrc) { // This should always be true @@ -301,13 +285,11 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef NSEvent* sysEvent = [NSEvent eventWithCGEvent:event]; // Too many of these to be useful for most debugging sessions, but we'll keep this around to be // un-commented when needed. - //if (appDelegate.debugMode) - // NSLog(@"System Event: %@", sysEvent); + // os_log_debug([KMLogs eventsLog], "System Event: %@", sysEvent); switch (type) { case kCGEventFlagsChanged: - if (appDelegate.debugMode) - NSLog(@"eventTapFunction: system event kCGEventFlagsChanged to: %x", (int) sysEvent.modifierFlags); + os_log_debug([KMLogs eventsLog], "eventTapFunction: system event kCGEventFlagsChanged to: %x", (int) sysEvent.modifierFlags); appDelegate.currentModifierFlags = sysEvent.modifierFlags; if (appDelegate.currentModifierFlags & NSEventModifierFlagCommand) { appDelegate.contextChangedByLowLevelEvent = YES; @@ -318,26 +300,26 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef case kCGEventLeftMouseDown: case kCGEventOtherMouseUp: case kCGEventOtherMouseDown: - NSLog(@"Event tap context invalidation flagged due to event: %@", event); + os_log_debug([KMLogs eventsLog], "Event tap context invalidation flagged due to event of type: %u", type); appDelegate.contextChangedByLowLevelEvent = YES; break; case kCGEventKeyDown: - NSLog(@"Event tap keydown event, keyCode: %hu, event: %@", sysEvent.keyCode, event); + os_log_debug([KMLogs eventsLog], "Event tap keydown event, keyCode: %hu", sysEvent.keyCode); // Pass back low-level backspace events to the input method event handler // because some non-compliant apps do not allow us to see backspace events // that we have generated (and we need to see them, for serialization // of events) if(sysEvent.keyCode == kVK_Delete && appDelegate.inputController != nil) { - NSLog(@"Event tap handling kVK_Delete."); + os_log_debug([KMLogs eventsLog], "Event tap handling kVK_Delete."); [appDelegate.inputController handleBackspace:sysEvent]; } else if(sysEvent.keyCode == kVK_Delete) { - NSLog(@"Event tap not handling kVK_Delete, appDelegate.inputController = %@", appDelegate.inputController); + os_log_debug([KMLogs eventsLog], "Event tap not handling kVK_Delete, appDelegate.inputController = %{public}@", appDelegate.inputController); } if(sysEvent.keyCode == 255) { - NSLog(@"*** kKeymanEventKeyCode = 0xFF"); + os_log_debug([KMLogs eventsLog], "*** kKeymanEventKeyCode = 0xFF"); } else { - NSLog(@"*** other: %d(%x)", (char) sysEvent.keyCode, sysEvent.keyCode); + os_log_debug([KMLogs eventsLog], "*** other: %d(%x)", (char) sysEvent.keyCode, sysEvent.keyCode); } switch(sysEvent.keyCode) { @@ -439,14 +421,14 @@ - (void)readPersistedOptions { } NSDictionary *persistedOptionsForSelectedKeyboard = [allPersistedOptions objectForKey:_selectedKeyboard]; if (!persistedOptionsForSelectedKeyboard) { - NSLog(@"no persisted options found in UserDefaults for keyboard %@ ", _selectedKeyboard); + os_log_info([KMLogs configLog], "no persisted options found in UserDefaults for keyboard %{public}@ ", _selectedKeyboard); return; } // TODO: pass array instead of making repeated calls for (NSString *key in persistedOptionsForSelectedKeyboard) { NSString *value = [persistedOptionsForSelectedKeyboard objectForKey:key]; - NSLog(@"persisted options found in UserDefaults for keyboard %@, key: %@, value: %@", _selectedKeyboard, key, value); + os_log_info([KMLogs configLog], "persisted options found in UserDefaults for keyboard %{public}@, key: %{public}@, value: %{public}@", _selectedKeyboard, key, value); [self.kme setCoreOptions:key withValue:value]; } } @@ -495,7 +477,7 @@ - (void)setAlwaysShowOSK:(BOOL)alwaysShowOSK { } - (void)setUseVerboseLogging:(BOOL)useVerboseLogging { - NSLog(@"Turning verbose logging %@", useVerboseLogging ? @"on." : @"off."); + os_log_debug([KMLogs configLog], "Turning verbose logging %{public}@", useVerboseLogging ? @"on." : @"off."); _debugMode = useVerboseLogging; if (_kme != nil) [_kme setUseVerboseLogging:useVerboseLogging]; @@ -674,8 +656,7 @@ - (NSArray *)keyboardNamesFromFolder:(NSString *)packageFolder { if (infoDict != nil) { NSString *name = [infoDict objectForKey:kKMKeyboardNameKey]; if (name != nil && [name length]) { - if (self.debugMode) - NSLog(@"Adding keyboard name: %@", name); + os_log_debug([KMLogs configLog], "Adding keyboard name: %{public}@", name); [kbNames addObject:name]; } } @@ -814,9 +795,7 @@ - (int)calculateNumberOfKeyboardMenuItems { - (void)removeDynamicKeyboardMenuItems { int numberToRemove = (int) self.menu.numberOfItems - DEFAULT_KEYMAN_MENU_ITEM_COUNT; - if (self.debugMode) { - NSLog(@"*** removeDynamicKeyboardMenuItems, self.menu.numberOfItems = %ld, number of items to remove = %d", (long)self.menu.numberOfItems, numberToRemove); - } + os_log_info([KMLogs keyboardLog], "*** removeDynamicKeyboardMenuItems, self.menu.numberOfItems = %ld, number of items to remove = %d", (long)self.menu.numberOfItems, numberToRemove); if (numberToRemove > 0) { for (int i = 0; i < numberToRemove; i++) { @@ -832,7 +811,7 @@ - (void)addDynamicKeyboardMenuItems { int menuItemIndex = KEYMAN_FIRST_KEYBOARD_MENUITEM_INDEX; if (self.debugMode) { - NSLog(@"*** populateKeyboardMenuItems, number of active keyboards=%lu", self.activeKeyboards.count); + os_log_info([KMLogs configLog], "*** populateKeyboardMenuItems, number of active keyboards=%lu", self.activeKeyboards.count); } // loop through the active keyboards list and add them to the menu @@ -908,7 +887,7 @@ - (void) addKeyboardPlaceholderMenuItem { - (void)selectKeyboardFromMenu:(NSInteger)tag { NSMenuItem *menuItem = [self.menu itemWithTag:tag]; NSString *title = menuItem.title; - NSLog(@"Input Menu, selected Keyboards menu, itag: %lu, title: %@", tag, title); + os_log_info([KMLogs keyboardLog], "Input Menu, selected Keyboards menu, itag: %lu, title: %{public}@", tag, title); for (NSMenuItem *item in self.menu.itemArray) { // set the state of the keyboard items in the Keyman menu based on the new selection if (item.tag >= KEYMAN_FIRST_KEYBOARD_MENUITEM_TAG) { @@ -934,8 +913,7 @@ - (void)selectKeyboardFromMenu:(NSInteger)tag { } [self setKvk:kvk]; NSString *keyboardName = [kmxInfo objectForKey:kKMKeyboardNameKey]; - if ([self debugMode]) - NSLog(@"Selected keyboard from menu: %@", keyboardName); + os_log_info([KMLogs keyboardLog], "Selected keyboard from menu: %{public}@", keyboardName); [self setKeyboardName:keyboardName]; [self setKeyboardIcon:[kmxInfo objectForKey:kKMKeyboardIconKey]]; [self setContextBuffer:nil]; @@ -996,8 +974,7 @@ - (NSWindowController *)oskWindow { } - (void)showConfigurationWindow { - if (self.debugMode) - NSLog(@"Showing config window..."); + os_log_debug([KMLogs uiLog], "Showing config window..."); [self.configWindow.window centerInParent]; [self.configWindow.window makeKeyAndOrderFront:nil]; [self.configWindow.window setLevel:NSFloatingWindowLevel]; @@ -1027,8 +1004,7 @@ - (void)showAboutWindow { - (NSWindowController *)configWindow { if (_configWindow.window == nil) { - if (self.debugMode) - NSLog(@"Creating config window..."); + os_log_debug([KMLogs uiLog], "Creating config window..."); _configWindow = [[KMConfigurationWindowController alloc] initWithWindowNibName:@"preferences"]; [self observeCloseFor:_configWindow.window]; } @@ -1289,7 +1265,7 @@ - (void)postKeyboardEventWithSource: (CGEventSourceRef)source code:(CGKeyCode) v CGEventRef ev = CGEventCreateKeyboardEvent (source, virtualKey, true); //down if (postEvent) { - NSLog(@"postKeyboardEventWithSource, keycode: %d", virtualKey); + os_log_info([KMLogs eventsLog], "postKeyboardEventWithSource, keycode: %d", virtualKey); postEvent(ev); } CFRelease(ev); @@ -1306,7 +1282,7 @@ - (void)postKeyboardEventWithSource: (CGEventSourceRef)source code:(CGKeyCode) v - (BOOL)verifyPackageVersionInTempFolder: (NSString *)tempDestFolder filePath:(NSString *)filePath { KMPackageInfo *packageInfo = [self loadPackageInfo:tempDestFolder]; if(packageInfo == nil) { - NSLog(@"Could not find kmp.json in %@", filePath); + os_log_info([KMLogs eventsLog], "Could not find kmp.json in %{public}@", filePath); } else { NSString* requiredVersion = [packageInfo.fileVersion minimalVersionNumberString]; KeymanVersionInfo keymanVersionInfo = [self versionInfo]; @@ -1314,7 +1290,7 @@ - (BOOL)verifyPackageVersionInTempFolder: (NSString *)tempDestFolder filePath:(N if ([requiredVersion compare:currentVersion options:NSNumericSearch] == NSOrderedDescending) { // currentVersion is lower than the requiredVersion - NSLog(@"Package %@ requires a newer version of Keyman: %@", filePath, requiredVersion); + os_log_error([KMLogs keyboardLog], "Package %{public}@ requires a newer version of Keyman: %{public}@", filePath, requiredVersion); } else { return YES; } @@ -1340,10 +1316,9 @@ - (BOOL)unzipFile:(NSString *)filePath { ZipArchive *za = [[ZipArchive alloc] init]; if ([za UnzipOpenFile:filePath]) { - if (self.debugMode) { - NSLog(@"Unzipping %@ to %@", filePath, tempDestFolder); - if ([[NSFileManager defaultManager] fileExistsAtPath:tempDestFolder]) - NSLog(@"The temp destination folder already exists. Overwriting..."); + os_log_debug([KMLogs keyboardLog], "Unzipping %{public}@ to %{public}@", filePath, tempDestFolder); + if ([[NSFileManager defaultManager] fileExistsAtPath:tempDestFolder]) { + os_log_debug([KMLogs keyboardLog], "The temp destination folder already exists. Overwriting..."); } didUnzip = [za UnzipFileTo:tempDestFolder overWrite:YES]; @@ -1351,25 +1326,22 @@ - (BOOL)unzipFile:(NSString *)filePath { } if (!didUnzip) { - NSLog(@"Failed to unzip file: %@", filePath); + os_log_error([KMLogs keyboardLog], "Failed to unzip file: %{public}@", filePath); return NO; } - if (self.debugMode) - NSLog(@"Unzipped file: %@", filePath); + os_log_debug([KMLogs keyboardLog], "Unzipped file: %{public}@", filePath); BOOL didInstall = [self verifyPackageVersionInTempFolder:tempDestFolder filePath:filePath]; NSString *destFolder = [self.keyboardsPath stringByAppendingPathComponent:folderName]; - + // Remove existing package if it exists if (didInstall && [[NSFileManager defaultManager] fileExistsAtPath:destFolder]) { - if(self.debugMode) { - NSLog(@"The destination folder already exists. Overwriting..."); - } + os_log_debug([KMLogs keyboardLog], "The destination folder already exists. Overwriting..."); [[NSFileManager defaultManager] removeItemAtPath:destFolder error:&error]; if (error != nil) { - NSLog(@"Unable to remove destination folder %@", destFolder); + os_log_error([KMLogs keyboardLog], "Unable to remove destination folder %{public}@", destFolder); didInstall = NO; } } @@ -1382,7 +1354,7 @@ - (BOOL)unzipFile:(NSString *)filePath { if(didInstall) { [[NSFileManager defaultManager] moveItemAtPath:tempDestFolder toPath:destFolder error:&error]; if (error != nil) { - NSLog(@"Unable to move temp folder %@ to dest folder %@", tempDestFolder, destFolder); + os_log_error([KMLogs keyboardLog], "Unable to move temp folder %{public}@ to dest folder %{public}@", tempDestFolder, destFolder); didInstall = NO; } } @@ -1390,7 +1362,7 @@ - (BOOL)unzipFile:(NSString *)filePath { if(!didInstall) { [[NSFileManager defaultManager] removeItemAtPath:tempDestFolder error:&error]; if (error != nil) { - NSLog(@"Unable to remove temp folder %@", tempDestFolder); + os_log_error([KMLogs keyboardLog], "Unable to remove temp folder %{public}@", tempDestFolder); } return NO; @@ -1401,8 +1373,7 @@ - (BOOL)unzipFile:(NSString *)filePath { NSString * keyboardFolderPath = [self.keyboardsPath stringByAppendingPathComponent:folderName]; [self installFontsAtPath:keyboardFolderPath]; for (NSString *kmxFile in [self KMXFilesAtPath:keyboardFolderPath]) { - if (self.debugMode) - NSLog(@"Adding keyboard to list of active keyboards: %@", kmxFile); + os_log_debug([KMLogs keyboardLog], "Adding keyboard to list of active keyboards: %{public}@", kmxFile); if (![self.activeKeyboards containsObject:kmxFile]) [self.activeKeyboards addObject:kmxFile]; } @@ -1442,7 +1413,7 @@ - (void)installFontsAtPath:(NSString *)path { [[NSFileManager defaultManager] copyItemAtPath:srcPath toPath:destPath error:&error]; if (error != nil) - NSLog(@"Error = %@", error); + os_log_error([KMLogs keyboardLog], "installFontsAtPath error = %{public}@", error); } } diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m index b7c4cb98954..fa912ca67d5 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m @@ -10,6 +10,7 @@ #import /* For kVK_ constants. */ #import "KeySender.h" #import "TextApiCompliance.h" +#import "KMLogs.h" @import Sentry; @interface KMInputMethodEventHandler () @@ -47,7 +48,7 @@ - (instancetype)initWithClient:(NSString *)clientAppId client:(id) sender { // the current keyboard and you type "Sentry force now", it will force a simulated crash to // test reporting to sentry.keyman.com if ([self.appDelegate debugMode] && [clientAppId isEqual: @"com.apple.dt.Xcode"]) { - NSLog(@"Sentry - Preparing to detect Easter egg."); + os_log_debug([KMLogs testLog], "Sentry - Preparing to detect Easter egg."); _easterEggForSentry = [[NSMutableString alloc] init]; } else @@ -61,10 +62,7 @@ - (void)deactivate { _keyCodeOfOriginalEvent != 0 || _sourceFromOriginalEvent != nil) { if ([self.appDelegate debugMode]) { - NSLog(@"ERROR: new app activated before previous app finished processing pending events!"); - NSLog(@" _generatedBackspaceCount = %lu", _generatedBackspaceCount); - NSLog(@" _queuedText = \"%@\"", _queuedText == nil ? @"(NIL)" : (NSString*)[self queuedText]); - NSLog(@" _keyCodeOfOriginalEvent = %hu", _keyCodeOfOriginalEvent); + os_log_error([KMLogs lifecycleLog], "ERROR: new app activated before previous app finished processing pending events! _generatedBackspaceCount: %lu, _queuedText: '%{public}@' _keyCodeOfOriginalEvent: %hu", _generatedBackspaceCount, _queuedText == nil ? @"(NIL)" : (NSString*)[self queuedText], _keyCodeOfOriginalEvent); } _keyCodeOfOriginalEvent = 0; _generatedBackspaceCount = 0; @@ -91,7 +89,7 @@ - (void)handleCommand:(NSEvent *)event { // the only downside to treating all commands as having the potential to change the selection // is that some non-compliant apps can't get their context at all. This can be overridden so that // non-compliant apps can mitigate this problem as appropriate. - [self.appDelegate logDebugMessage:@"KMInputMethodEventHandler handleCommand, event type=%@, must refresh context", event.type]; + os_log_debug([KMLogs keyLog], "KMInputMethodEventHandler handleCommand, event type=%lu, must refresh context", (unsigned long)event.type); self.contextChanged = YES; } @@ -104,7 +102,6 @@ - (KMEngine *)kme { } - (BOOL) handleEventWithKeymanEngine:(NSEvent *)event in:(id) sender { - [self.appDelegate logDebugMessage:@"handleEventWithKeymanEngine, event = %@", event]; CoreKeyOutput *output = nil; output = [self processEventWithKeymanEngine:event in:sender]; @@ -121,7 +118,7 @@ - (CoreKeyOutput*) processEventWithKeymanEngine:(NSEvent *)event in:(id) sender if (self.appDelegate.lowLevelEventTap != nil) { NSEvent *eventWithOriginalModifierFlags = [NSEvent keyEventWithType:event.type location:event.locationInWindow modifierFlags:self.appDelegate.currentModifierFlags timestamp:event.timestamp windowNumber:event.windowNumber context:[NSGraphicsContext currentContext] characters:event.characters charactersIgnoringModifiers:event.charactersIgnoringModifiers isARepeat:event.isARepeat keyCode:event.keyCode]; coreKeyOutput = [self.kme processEvent:eventWithOriginalModifierFlags]; - [self.appDelegate logDebugMessage:@"processEventWithKeymanEngine, using AppDelegate.currentModifierFlags %lu, instead of event.modifiers = %lu", (unsigned long)self.appDelegate.currentModifierFlags, (unsigned long)event.modifierFlags]; + os_log_debug([KMLogs eventsLog], "processEventWithKeymanEngine, using AppDelegate.currentModifierFlags: %lu / 0x%lX, instead of event.modifiers = %lu / 0x%lX", self.appDelegate.currentModifierFlags, self.appDelegate.currentModifierFlags, event.modifierFlags, event.modifierFlags); } else { // Depending on the client app and the keyboard, using the passed-in event as it is should work okay. @@ -129,28 +126,28 @@ - (CoreKeyOutput*) processEventWithKeymanEngine:(NSEvent *)event in:(id) sender // context might go undetected in some apps, resulting in errant behavior for subsequent typing. coreKeyOutput = [self.kme processEvent:event]; } - [self.appDelegate logDebugMessage:@"processEventWithKeymanEngine, coreKeyOutput = %@", coreKeyOutput]; + //os_log_debug([KMLogs eventsLog], "processEventWithKeymanEngine, coreKeyOutput = %{public}@", coreKeyOutput); return coreKeyOutput; } - (void)checkEventForSentryEasterEgg:(NSEvent *)event { if (_easterEggForSentry != nil) { NSString * kmxName = [[self.kme.kmx filePath] lastPathComponent]; - NSLog(@"Sentry - KMX name: %@", kmxName); + os_log_debug([KMLogs testLog], "Sentry - KMX name: %{public}@", kmxName); if ([kmxName isEqualToString:kEasterEggKmxName]) { NSUInteger len = [_easterEggForSentry length]; - NSLog(@"Sentry - Processing character(s): %@", [event characters]); + os_log_debug([KMLogs testLog], "Sentry - Processing character(s): %{public}@", [event characters]); if ([[event characters] characterAtIndex:0] == [kEasterEggText characterAtIndex:len]) { NSString *characterToAdd = [kEasterEggText substringWithRange:NSMakeRange(len, 1)]; - NSLog(@"Sentry - Adding character to Easter Egg code string: %@", characterToAdd); + os_log_debug([KMLogs testLog], "Sentry - Adding character to Easter Egg code string: %{public}@", characterToAdd); [_easterEggForSentry appendString:characterToAdd]; if ([_easterEggForSentry isEqualToString:kEasterEggText]) { - NSLog(@"Sentry - Forcing crash now"); + os_log_debug([KMLogs testLog], "Sentry - Forcing crash now"); [SentrySDK crash]; } } else if (len > 0) { - NSLog(@"Sentry - Clearing Easter Egg code string."); + os_log_debug([KMLogs testLog], "Sentry - Clearing Easter Egg code string."); [_easterEggForSentry setString:@""]; } } @@ -167,7 +164,7 @@ - (void)checkEventForSentryEasterEgg:(NSEvent *)event { Core for processing, as it is already the result of processing. */ - (void)handleBackspace:(NSEvent *)event { - [self.appDelegate logDebugMessage:@"KMInputMethodEventHandler handleBackspace, event = %@", event]; + os_log_debug([KMLogs eventsLog], "KMInputMethodEventHandler handleBackspace, event = %{public}@", event); if (self.generatedBackspaceCount > 0) { self.generatedBackspaceCount--; @@ -181,7 +178,7 @@ - (void)handleBackspace:(NSEvent *)event { } - (void)triggerInsertQueuedText:(NSEvent *)event { - [self.appDelegate logDebugMessage:@"KMInputMethodEventHandler triggerInsertQueuedText"]; + os_log_debug([KMLogs eventsLog], "KMInputMethodEventHandler triggerInsertQueuedText"); [self.keySender sendKeymanKeyCodeForEvent:event]; } @@ -196,7 +193,7 @@ - (void)checkTextApiCompliance:(id)client { (![self.apiCompliance.clientApplicationId isEqualTo:self.clientApplicationId]) || self.contextChanged) { self.apiCompliance = [[TextApiCompliance alloc]initWithClient:client applicationId:self.clientApplicationId]; - [self.appDelegate logDebugMessage:@"KMInputMethodHandler initWithClient checkTextApiCompliance: %@", _apiCompliance]; + os_log_debug([KMLogs complianceLog], "KMInputMethodHandler initWithClient checkTextApiCompliance: %{public}@", _apiCompliance); } else if (self.apiCompliance.isComplianceUncertain) { // We have a valid TextApiCompliance object, but compliance is uncertain, so test it [self.apiCompliance checkCompliance:client]; @@ -206,7 +203,7 @@ - (void)checkTextApiCompliance:(id)client { - (void) handleContextChangedByLowLevelEvent { if (self.appDelegate.contextChangedByLowLevelEvent) { if (!self.contextChanged) { - [self.appDelegate logDebugMessage:@"Low-level event has changed the context."]; + os_log_debug([KMLogs complianceLog], "Low-level event has changed the context."); self.contextChanged = YES; } self.appDelegate.contextChangedByLowLevelEvent = NO; @@ -216,8 +213,8 @@ - (void) handleContextChangedByLowLevelEvent { // handleEvent implementation for core event processing - (BOOL)handleEvent:(NSEvent *)event client:(id)sender { BOOL handled = NO; - [self.appDelegate logDebugMessage:@"handleEvent event = %@", event]; - + os_log_debug([KMLogs eventsLog], "handleEvent፡ event = %{public}@", event); + [self checkTextApiCompliance:sender]; // mouse movement requires that the context be invalidated @@ -227,7 +224,7 @@ - (BOOL)handleEvent:(NSEvent *)event client:(id)sender { // indicates that our generated backspace event(s) are consumed // and we can insert text that followed the backspace(s) if (event.keyCode == kKeymanEventKeyCode) { - [self.appDelegate logDebugMessage:@"handleEvent, handling kKeymanEventKeyCode"]; + os_log_debug([KMLogs eventsLog], "handleEvent, handling kKeymanEventKeyCode"); [self insertQueuedText: event client:sender]; return YES; } @@ -235,7 +232,7 @@ - (BOOL)handleEvent:(NSEvent *)event client:(id)sender { // for some apps, handleEvent will not be called for the generated backspace // but if it is, we need to let it pass through rather than process again in core if((event.keyCode == kVK_Delete) && (self.lowLevelBackspaceCount > 0)) { - [self.appDelegate logDebugMessage:@"handleEvent, allowing generated backspace to pass through"]; + os_log_debug([KMLogs eventsLog], "handleEvent, allowing generated backspace to pass through"); self.lowLevelBackspaceCount--; // return NO to pass through to client app @@ -258,7 +255,7 @@ - (BOOL)handleEvent:(NSEvent *)event client:(id)sender { handled = [self handleEventWithKeymanEngine:event in: sender]; } - [self.appDelegate logDebugMessage:@"event, keycode: %u, characters='%@' handled = %@", event.keyCode, event.characters, handled?@"yes":@"no"]; + os_log_debug([KMLogs eventsLog], "event, keycode: %u, characters='%{public}@' handled = %{public}@", event.keyCode, event.characters, handled?@"yes":@"no"); return handled; } @@ -293,11 +290,11 @@ -(void)reportContext:(NSEvent *)event forClient:(id) client { // we do this whether the context has changed or not if (self.apiCompliance.canReadText) { contextString = [self readContext:event forClient:client]; - [self.appDelegate logDebugMessage:@"reportContext, setting new context='%@' for compliant app (if needed)", contextString]; + os_log_debug([KMLogs eventsLog], "reportContext, setting new context='%{public}@' for compliant app (if needed)", contextString); [self.kme setCoreContextIfNeeded:contextString]; } else if (self.contextChanged) { // we cannot read the text but know the context has changed, so we must clear it - [self.appDelegate logDebugMessage:@"reportContext, clearing context for non-compliant app"]; + os_log_debug([KMLogs eventsLog], "reportContext, clearing context for non-compliant app"); [self.kme clearCoreContext]; } @@ -316,7 +313,7 @@ -(NSString*)readContext:(NSEvent *)event forClient:(id) client { NSUInteger contextStart = selectionRange.location - contextLength; if (contextLength > 0) { - [self.appDelegate logDebugMessage:@" *** InputMethodEventHandler readContext, %d characters", contextLength]; + os_log_debug([KMLogs eventsLog], " *** InputMethodEventHandler readContext, %lu characters", (unsigned long)contextLength); NSRange contextRange = NSMakeRange(contextStart, contextLength); attributedString = [client attributedSubstringFromRange:contextRange]; @@ -324,7 +321,7 @@ -(NSString*)readContext:(NSEvent *)event forClient:(id) client { // the API appears to always return a full code point, but this could vary by app if (attributedString.length > 0) { if (CFStringIsSurrogateLowCharacter([attributedString.string characterAtIndex:0])) { - [self.appDelegate logDebugMessage:@" *** InputMethodEventHandler readContext, first char is low surrogate, reducing context by one character"]; + os_log_debug([KMLogs eventsLog], " *** InputMethodEventHandler readContext, first char is low surrogate, reducing context by one character"); contextString = [attributedString.string substringFromIndex:1]; } else { contextString = attributedString.string; @@ -340,7 +337,7 @@ -(NSString*)readContext:(NSEvent *)event forClient:(id) client { * Returns NO if we have not applied an event to the client or if Keyman Core determines that we should emit the keystroke */ -(BOOL)applyKeymanCoreActions:(CoreKeyOutput*)output event: (NSEvent*)event client:(id) client { - [self.appDelegate logDebugMessage:@" *** InputMethodEventHandler applyKeymanCoreActions: output = %@ ", output]; + //os_log_debug([KMLogs eventsLog], "InputMethodEventHandler applyKeymanCoreActions: output = %{public}@ ", output); BOOL handledEvent = [self applyKeyOutputToTextInputClient:output keyDownEvent:event client:client]; [self applyNonTextualOutput:output]; @@ -348,7 +345,7 @@ -(BOOL)applyKeymanCoreActions:(CoreKeyOutput*)output event: (NSEvent*)event clie // if output from Keyman Core indicates to emit the keystroke, // then return NO, so that the OS still handles the event if (handledEvent && output.emitKeystroke) { - [self.appDelegate logDebugMessage:@" *** InputMethodEventHandler applyKeymanCoreActions: emit keystroke true, returning false for handledEvent"]; + os_log_debug([KMLogs eventsLog], " *** emitKeystroke, not handling event"); handledEvent = NO; } @@ -359,15 +356,15 @@ -(BOOL)applyKeyOutputToTextInputClient:(CoreKeyOutput*)output keyDownEvent:(nonn BOOL handledEvent = YES; if (output.isInsertOnlyScenario) { - [self.appDelegate logDebugMessage:@"KXMInputMethodHandler applyOutputToTextInputClient, insert only scenario"]; + os_log_debug([KMLogs keyLog], "applyOutputToTextInputClient, insert only scenario"); [self insertAndReplaceTextForOutput:output client:client]; } else if (output.isDeleteOnlyScenario) { if ((event.keyCode == kVK_Delete) && output.codePointsToDeleteBeforeInsert == 1) { // let the delete pass through in the original event rather than sending a new delete - [self.appDelegate logDebugMessage:@"KXMInputMethodHandler applyOutputToTextInputClient, delete only scenario with passthrough"]; + os_log_debug([KMLogs keyLog], "applyOutputToTextInputClient, delete only scenario with passthrough"); handledEvent = NO; } else { - [self.appDelegate logDebugMessage:@"KXMInputMethodHandler applyOutputToTextInputClient, delete only scenario"]; + os_log_debug([KMLogs keyLog], "applyOutputToTextInputClient, delete only scenario"); [self sendEvents:event forOutput:output]; } } else if (output.isDeleteAndInsertScenario) { @@ -377,7 +374,7 @@ -(BOOL)applyKeyOutputToTextInputClient:(CoreKeyOutput*)output keyDownEvent:(nonn // assume that all non-compliant apps which require backspaces apply an extra backspace if the original event is a backspace if ((self.apiCompliance.mustBackspaceUsingEvents) && (event.keyCode == kVK_Delete)) { output.codePointsToDeleteBeforeInsert--; - os_log_with_type(keymanLog, OS_LOG_TYPE_INFO, "isDeleteAndInsertScenario, after delete pressed subtracting one backspace to reach %d and insert text '%{public}@'", output.codePointsToDeleteBeforeInsert, output.textToInsert); + os_log_info(keymanLog, "isDeleteAndInsertScenario, after delete pressed subtracting one backspace to reach %d and insert text '%{public}@'", output.codePointsToDeleteBeforeInsert, output.textToInsert); if (output.codePointsToDeleteBeforeInsert == 0) { // no backspace events needed [self insertAndReplaceTextForOutput:output client:client]; @@ -389,10 +386,10 @@ -(BOOL)applyKeyOutputToTextInputClient:(CoreKeyOutput*)output keyDownEvent:(nonn */ if (self.apiCompliance.mustBackspaceUsingEvents) { - [self.appDelegate logDebugMessage:@"KXMInputMethodHandler applyOutputToTextInputClient, delete and insert scenario with events"]; + os_log_debug([KMLogs keyLog], "applyOutputToTextInputClient, delete and insert scenario with events"); [self sendEvents:event forOutput:output]; } else { - [self.appDelegate logDebugMessage:@"KXMInputMethodHandler applyOutputToTextInputClient, delete and insert scenario with insert API"]; + os_log_debug([KMLogs keyLog], "applyOutputToTextInputClient, delete and insert scenario with insert API"); // directly insert text and handle backspaces by using replace [self insertAndReplaceTextForOutput:output client:client]; } @@ -415,11 +412,11 @@ -(void) persistOptions:(NSDictionary*)options{ for(NSString *key in options) { NSString *value = [options objectForKey:key]; if(key && value) { - [self.appDelegate logDebugMessage:@"applyNonTextualOutput calling writePersistedOptions, key: %@, value: %@", key, value]; + os_log_debug([KMLogs keyLog], "applyNonTextualOutput calling writePersistedOptions, key: %{public}@, value: %{public}@", key, value); [self.appDelegate writePersistedOptions:key withValue:value]; } else { - [self.appDelegate logDebugMessage:@"applyNonTextualOutput, invalid values in optionsToPersist, not writing to UserDefaults, key: %@, value: %@", key, value]; + os_log_debug([KMLogs keyLog], "applyNonTextualOutput, invalid values in optionsToPersist, not writing to UserDefaults, key: %{public}@, value: %{public}@", key, value); } } } @@ -448,7 +445,7 @@ -(void)insertAndReplaceTextForOutput:(CoreKeyOutput*)output client:(id) client { * this method can only be used if approved by TextApiCompliance */ -(void)insertAndReplaceText:(NSString *)text deleteCount:(int) replacementCount toReplace:(NSString*)textToDelete client:(id) client { - [self.appDelegate logDebugMessage:@"KXMInputMethodHandler insertAndReplaceText: %@ replacementCount: %d", text, replacementCount]; + os_log_debug([KMLogs keyLog], "insertAndReplaceText, insert: %{public}@, delete: %{public}@, replacementCount: %d", text, textToDelete, replacementCount); NSRange selectionRange = [client selectedRange]; NSRange replacementRange = [self calculateInsertRangeForDeletedText:textToDelete selectionRange:selectionRange]; @@ -481,8 +478,8 @@ -(NSRange) calculateInsertRangeForDeletedText:(NSString*)textToDelete selectionR } -(void)sendEvents:(NSEvent *)event forOutput:(CoreKeyOutput*)output { - [self.appDelegate logDebugMessage:@"sendEvents called, output = %@", output]; - + os_log_debug([KMLogs keyLog], "sendEvents called, output = %{public}@", output); + _sourceForGeneratedEvent = CGEventCreateSourceFromEvent([event CGEvent]); self.generatedBackspaceCount = output.codePointsToDeleteBeforeInsert; @@ -490,13 +487,13 @@ -(void)sendEvents:(NSEvent *)event forOutput:(CoreKeyOutput*)output { if (output.hasCodePointsToDelete) { for (int i = 0; i < output.codePointsToDeleteBeforeInsert; i++) { - [self.appDelegate logDebugMessage:@"sendEvents sending backspace key event"]; + os_log_debug([KMLogs keyLog], "sendEvents sending backspace key event"); [self.keySender sendBackspaceforEventSource:_sourceForGeneratedEvent]; } } if (output.hasTextToInsert) { - [self.appDelegate logDebugMessage:@"sendEvents, queueing text to insert: %@", output.textToInsert]; + os_log_debug([KMLogs keyLog], "sendEvents, queueing text to insert: %{public}@", output.textToInsert); self.queuedText = output.textToInsert; } @@ -504,11 +501,11 @@ -(void)sendEvents:(NSEvent *)event forOutput:(CoreKeyOutput*)output { -(void)insertQueuedText: (NSEvent *)event client:(id) client { if (self.queuedText.length> 0) { - [self.appDelegate logDebugMessage:@"insertQueuedText, inserting %@", self.queuedText]; + os_log_debug([KMLogs keyLog], "insertQueuedText, inserting %{public}@", self.queuedText); [self insertAndReplaceText:self.queuedText deleteCount:0 toReplace:nil client:client]; self.queuedText = nil; } else { - [self.appDelegate logDebugMessage:@"insertQueuedText called but no text to insert"]; + os_log_debug([KMLogs keyLog], "insertQueuedText called but no text to insert"); } } diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMKeyboardHelpWindow/KMKeyboardHelpWindowController.m b/mac/Keyman4MacIM/Keyman4MacIM/KMKeyboardHelpWindow/KMKeyboardHelpWindowController.m index 359ddaa8803..21a015951a0 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMKeyboardHelpWindow/KMKeyboardHelpWindowController.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMKeyboardHelpWindow/KMKeyboardHelpWindowController.m @@ -10,6 +10,7 @@ #import "KMInputMethodAppDelegate.h" #import "KMPackageInfo.h" #import +#import "KMLogs.h" @interface KMKeyboardHelpWindowController () @property (nonatomic, weak) IBOutlet WebView *welcomeView; @@ -39,7 +40,7 @@ - (void)setPackagePath:(NSString *)packagePath { [self.window setTitle:title]; } @catch (NSException *e) { - NSLog(@"Error = %@", e.description); + os_log_error([KMLogs dataLog], "Error = %{public}@", e.description); } NSString *welcomeFile = [packagePath stringByAppendingPathComponent:@"welcome.htm"]; diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMLogs.h b/mac/Keyman4MacIM/Keyman4MacIM/KMLogs.h new file mode 100644 index 00000000000..002bc5023c1 --- /dev/null +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMLogs.h @@ -0,0 +1,35 @@ +/** + * Keyman is copyright (C) SIL International. MIT License. + * + * KMLogs.h + * Keyman + * + * Created by Shawn Schantz on 2024-05-16. + * + * Contains methods to get singleton logger objects and constants for subsystem and category names. + */ + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KMLogs : NSObject + ++ (void)reportLogStatus; ++ (os_log_t)startupLog; ++ (os_log_t)privacyLog; ++ (os_log_t)complianceLog; ++ (os_log_t)lifecycleLog; ++ (os_log_t)configLog; ++ (os_log_t)dataLog; ++ (os_log_t)uiLog; ++ (os_log_t)eventsLog; ++ (os_log_t)keyboardLog; ++ (os_log_t)keyLog; ++ (os_log_t)oskLog; ++ (os_log_t)testLog; + +@end + +NS_ASSUME_NONNULL_END diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMLogs.m b/mac/Keyman4MacIM/Keyman4MacIM/KMLogs.m new file mode 100644 index 00000000000..f2d4dc4d534 --- /dev/null +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMLogs.m @@ -0,0 +1,95 @@ +/** + * Keyman is copyright (C) SIL International. MIT License. + * + * KMLogs.m + * Keyman + * + * Created by Shawn Schantz on 2024-05-16. + * + * Contains methods to get singleton logger objects and constants for subsystem and category names. + */ + +/** + * + * The loggers do not appear to be singletons, but the API which creates them manages + * them as singletons within macOS so that any subsequent call to create a log object + * using the same subsystem and category will return the existing instance. + * + * For any new log categories used anywhere in the Keyman Input method, the name should be defined here. + * Keyman Engine may define and use the same category name but will use a different subsystem name. + */ + +#import "KMLogs.h" + +@implementation KMLogs + +char *const keymanSubsystem = "com.keyman.app"; +char *const startupCategory = "startup"; +char *const privacyCategory = "privacy"; +char *const complianceCategory = "compliance"; +char *const lifecycleCategory = "lifecycle"; +char *const configCategory = "config"; +char *const dataCategory = "data"; +char *const uiCategory = "ui"; +char *const eventsCategory = "events"; +char *const keyboardCategory = "keyboard"; +char *const keyCategory = "key"; +char *const oskCategory = "osk"; +char *const testCategory = "test"; + ++ (void)reportLogStatus { + bool debugLogEnabled = os_log_type_enabled([KMLogs startupLog], OS_LOG_TYPE_DEBUG); + os_log([KMLogs startupLog], "startupLog has debug messages enabled: %@", debugLogEnabled?@"YES":@"NO"); + bool infoLogEnabled = os_log_type_enabled([KMLogs startupLog], OS_LOG_TYPE_INFO); + os_log([KMLogs startupLog], "startupLog has info messages enabled: %@", infoLogEnabled?@"YES":@"NO"); +} + ++ (os_log_t)startupLog { + return os_log_create(keymanSubsystem, startupCategory); +} + ++ (os_log_t)privacyLog { + return os_log_create(keymanSubsystem, privacyCategory); +} + ++ (os_log_t)complianceLog { + return os_log_create(keymanSubsystem, complianceCategory); +} + ++ (os_log_t)lifecycleLog { + return os_log_create(keymanSubsystem, lifecycleCategory); +} + ++ (os_log_t)configLog { + return os_log_create(keymanSubsystem, configCategory); +} + ++ (os_log_t)dataLog{ + return os_log_create(keymanSubsystem, dataCategory); +} + ++ (os_log_t)uiLog { + return os_log_create(keymanSubsystem, uiCategory); +} + ++ (os_log_t)eventsLog { + return os_log_create(keymanSubsystem, eventsCategory); +} + ++ (os_log_t)keyboardLog { + return os_log_create(keymanSubsystem, keyboardCategory); +} + ++ (os_log_t)keyLog { + return os_log_create(keymanSubsystem, keyCategory); +} + ++ (os_log_t)oskLog { + return os_log_create(keymanSubsystem, oskCategory); +} + ++ (os_log_t)testLog { + return os_log_create(keymanSubsystem, testCategory); +} + +@end diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMOSVersion.m b/mac/Keyman4MacIM/Keyman4MacIM/KMOSVersion.m index 8668e881dde..44a4b126172 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMOSVersion.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMOSVersion.m @@ -7,6 +7,7 @@ // #import "KMOSVersion.h" +#import "KMLogs.h" static CFStringRef sSystemVersionPath = CFSTR("/System/Library/CoreServices/SystemVersion.plist"); @@ -16,19 +17,19 @@ +(u_int16_t)SystemVersion NSDictionary *systemVersionDict = [NSDictionary dictionaryWithContentsOfFile:(__bridge NSString*)sSystemVersionPath]; if (NULL ==systemVersionDict) { - NSLog(@"could not read system version dictionary file: %@", sSystemVersionPath); + os_log_info([KMLogs configLog], "Could not read system version dictionary file: %{public}@", sSystemVersionPath); return 0; } NSString *systemVersionString = [systemVersionDict objectForKey:@"ProductVersion"]; if (NULL ==systemVersionString) { - NSLog(@"could not retrieve system version from dictionary at %@ with %d keys", sSystemVersionPath, (int)systemVersionDict.count); + os_log_info([KMLogs configLog], "Could not retrieve system version from dictionary at %{public}@ with %d keys", sSystemVersionPath, (int)systemVersionDict.count); return 0; } NSArray *systemVersionStringParts = [systemVersionString componentsSeparatedByString:@"."]; if (systemVersionStringParts.count < 2) { - NSLog(@"Too few parts to the system version (probably): %@", systemVersionString); + os_log_info([KMLogs configLog], "Too few parts to the system version (probably): %{public}@", systemVersionString); return [systemVersionString intValue]; // hopefully this will at least be the major OS version, e.g., 10 (all versions so far!) } @@ -43,7 +44,7 @@ +(u_int16_t)SystemVersion } if (systemVersionStringParts.count > 3) { - NSLog(@"Portions of System Version string after third part unused: %@", systemVersionString); + os_log_info([KMLogs configLog], "Portions of System Version string after third part unused: %{public}@", systemVersionString); } return systemVersion; } diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMPackage.m b/mac/Keyman4MacIM/Keyman4MacIM/KMPackage.m index 4a54e445c02..8f204706bd7 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMPackage.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMPackage.m @@ -9,6 +9,7 @@ #import #import "KMPackage.h" #import "KMConfigurationWindowController.h" +#import "KMLogs.h" @implementation KMPackage @@ -33,9 +34,8 @@ + (BOOL)autosavesInPlace { // they decide to install it or cancel the installation. It also gets called one time up-front // when Keyman first loads. - (void)makeWindowControllers { - if ([self.AppDelegate debugMode]) - NSLog(@"KMP - in KMPackage.makeWindowControllers"); - + os_log_debug([KMLogs dataLog], "KMP - in KMPackage.makeWindowControllers"); + if (filename != nil) { // Should be true every time except maybe the very first time (when loading). filename = nil; [self closeIfFilesAreReleased]; @@ -47,8 +47,8 @@ -(void) closeIfFilesAreReleased { // we need to close this document so the controller doesn't hold onto it. Otherwise, if the user // double-clicks the same KMP file a second time it will just assume we want to open the window // to display the already open document, rather than attempting to read it again. - if ([self.AppDelegate debugMode]) - NSLog(@"Closing document to release presenter..."); + + os_log_debug([KMLogs dataLog], "Closing document to release presenter..."); if (filename == nil && filenameTempKMP == nil) [self close]; } @@ -61,9 +61,8 @@ -(BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeN filename = [fileWrapper filename]; - if ([self.AppDelegate debugMode]) - NSLog(@"readFromFileWrapper called with file: %@", filename); - + os_log_debug([KMLogs dataLog], "readFromFileWrapper called with file: %{public}@", filename); + if (![typeName isEqualToString: @"Keyman Package"]) { if (outError != NULL) { NSString *description = [@"Unexpected file association for type " stringByAppendingString:typeName]; diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMPackageReader.m b/mac/Keyman4MacIM/Keyman4MacIM/KMPackageReader.m index dc882276720..7406488a8a0 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMPackageReader.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMPackageReader.m @@ -12,6 +12,7 @@ */ #import "KMPackageReader.h" +#import "KMLogs.h" static NSString *const kPackageJsonFile = @"kmp.json"; static NSString *const kPackageInfFile = @"kmp.inf"; @@ -84,20 +85,19 @@ - (NSString *)packageNameFromPackageInfo:(NSString *)path { - (KMPackageInfo *) loadPackageInfoFromJsonFile:(NSString *)path { KMPackageInfo * packageInfo = nil; - if (self.debugMode) - NSLog(@"Loading JSON package info from path: %@", path); + os_log([KMLogs dataLog], "Loading JSON package info from path: %{public}@", path); NSError *readError = nil; NSData *data = [NSData dataWithContentsOfFile:path options:kNilOptions error:&readError]; NSDictionary *parsedData = nil; if (data == nil) { - NSLog(@"Error reading JSON file at path : %@, error: %@ ", path, readError); + os_log_error([KMLogs dataLog], "Error reading JSON file at path : %{public}@, error: %{public}@ ", path, readError); } else { NSError *parseError = nil; parsedData = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&parseError]; if (parsedData == nil) { - NSLog(@"Error parsing JSON file at path : %@, error: %@ ", path, parseError); + os_log_error([KMLogs dataLog], "Error parsing JSON file at path : %{public}@, error: %{public}@ ", path, parseError); } else { packageInfo = [self createPackageInfoFromJsonData:parsedData]; } @@ -192,9 +192,8 @@ - (KMPackageInfo *) createPackageInfoFromJsonData:(NSDictionary *) jsonData { * @return the corresponding PackageInfo value object or nil if the file cannot be found or parsed */ - (KMPackageInfo *) loadPackageInfoFromInfFile:(NSString *)path { - if (self.debugMode) - NSLog(@"Loading inf package info from path: %@", path); - + os_log_debug([KMLogs dataLog], "Loading inf package info from path: %{public}@", path); + NSMutableArray *files = [NSMutableArray arrayWithCapacity:0]; NSMutableArray *keyboardInfoArray = [NSMutableArray arrayWithCapacity:0]; NSMutableArray *fontArray = [NSMutableArray arrayWithCapacity:0]; @@ -324,7 +323,7 @@ - (KMPackageInfo *) loadPackageInfoFromInfFile:(NSString *)path { } } @catch (NSException *e) { - NSLog(@"Error = %@", e.description); + os_log_error([KMLogs dataLog], "Error = %{public}@", e.description); return nil; } diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KeySender.h b/mac/Keyman4MacIM/Keyman4MacIM/KeySender.h index fdd332794d6..d47fa479f1a 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KeySender.h +++ b/mac/Keyman4MacIM/Keyman4MacIM/KeySender.h @@ -15,7 +15,6 @@ extern const CGKeyCode kKeymanEventKeyCode; @interface KeySender : NSObject - (instancetype)init; -- (void)sendKeyDown:(NSUInteger)keyCode forSourceEvent:(NSEvent *)event includeKeyUp:(BOOL)includeKeyUpEvent; - (void)sendBackspaceforEventSource:(CGEventSourceRef)eventSource; - (void)sendKeymanKeyCodeForEvent:(NSEvent *)event; diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KeySender.m b/mac/Keyman4MacIM/Keyman4MacIM/KeySender.m index 8bc1954d150..417475c777d 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KeySender.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KeySender.m @@ -12,6 +12,7 @@ #import #import "KeySender.h" #import "KMInputMethodAppDelegate.h" +#import "KMLogs.h" const CGKeyCode kKeymanEventKeyCode = 0xFF; @@ -30,8 +31,8 @@ -(instancetype)init { } - (void)sendBackspaceforEventSource:(CGEventSourceRef)eventSource { - [self.appDelegate logDebugMessage:@"KeySender sendBackspaceforEventSource"]; - + os_log_debug([KMLogs keyLog], "KeySender sendBackspaceforEventSource"); + [self postKeyboardEventWithSource:eventSource code:kVK_Delete postCallback:^(CGEventRef eventToPost) { CGEventPost(kCGHIDEventTap, eventToPost); }]; @@ -40,11 +41,11 @@ - (void)sendBackspaceforEventSource:(CGEventSourceRef)eventSource { - (void)postKeyboardEventWithSource: (CGEventSourceRef)source code:(CGKeyCode) virtualKey postCallback:(PostEventCallback)postEvent{ if (!postEvent) { - [self.appDelegate logDebugMessage:@"KeySender postKeyboardEventWithSource callback not specified", virtualKey]; + os_log_debug([KMLogs keyLog], "KeySender postKeyboardEventWithSource callback not specified for virtualKey: %u", virtualKey); return; } - [self.appDelegate logDebugMessage:@"KeySender postKeyboardEventWithSource for virtualKey: @%", virtualKey]; + os_log_debug([KMLogs keyLog], "KeySender postKeyboardEventWithSource for virtualKey: %u", virtualKey); CGEventRef ev = CGEventCreateKeyboardEvent (source, virtualKey, true); //down postEvent(ev); @@ -61,8 +62,8 @@ - (void)postKeyboardEventWithSource: (CGEventSourceRef)source code:(CGKeyCode) v */ - (void)sendKeymanKeyCodeForEvent:(NSEvent *)event { - [self.appDelegate logDebugMessage:@"KeySender sendKeymanKeyCodeForEvent"]; - + os_log_debug([KMLogs keyLog], "KeySender sendKeymanKeyCodeForEvent"); + ProcessSerialNumber psn; // Returns the frontmost app, which is the app that receives key events. @@ -70,7 +71,7 @@ - (void)sendKeymanKeyCodeForEvent:(NSEvent *)event { pid_t processId = app.processIdentifier; NSString *bundleId = app.bundleIdentifier; - [self.appDelegate logDebugMessage:@"sendKeymanKeyCodeForEvent keyCode %lu to app %@ with pid %d", (unsigned long)kKeymanEventKeyCode, bundleId, processId]; + os_log_debug([KMLogs keyLog], "sendKeymanKeyCodeForEvent keyCode %lu to app %{public}@ with pid %d", (unsigned long)kKeymanEventKeyCode, bundleId, processId); // use nil as source, as this generated event is not directly tied to the originating event CGEventRef keyDownEvent = CGEventCreateKeyboardEvent(nil, kKeymanEventKeyCode, true); diff --git a/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m b/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m index b8c699583de..30d30004c45 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m @@ -8,7 +8,7 @@ #import "OSKWindowController.h" #import "KMInputMethodAppDelegate.h" -#import +#import "KMLogs.h" @interface OSKWindowController () @property (nonatomic, strong) NSButton *helpButton; @@ -30,8 +30,7 @@ - (void)dealloc { } - (void)awakeFromNib { - os_log_t oskLog = os_log_create("org.sil.keyman", "osk"); - os_log_with_type(oskLog, OS_LOG_TYPE_DEBUG, "OSKWC awakeFromNib"); + os_log_debug([KMLogs oskLog], "OSKWindowController awakeFromNib"); // Keep the aspect ratio constant at its current value [self.window setAspectRatio:self.window.frame.size]; NSSize size = self.window.frame.size; @@ -54,8 +53,7 @@ - (void)awakeFromNib { } - (void)windowDidLoad { - os_log_t oskLog = os_log_create("org.sil.keyman", "osk"); - os_log_with_type(oskLog, OS_LOG_TYPE_DEBUG, "OSKWC windowDidLoad"); + os_log_debug([KMLogs oskLog], "OSKWindowController windowDidLoad"); [super windowDidLoad]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:self.window]; [self.oskView setKvk:[self.AppDelegate kvk]]; @@ -64,8 +62,7 @@ - (void)windowDidLoad { } - (void)windowDidResize:(NSNotification *)notification { - os_log_t oskLog = os_log_create("org.sil.keyman", "osk"); - os_log_with_type(oskLog, OS_LOG_TYPE_DEBUG, "OSKWC windowDidResize"); + os_log_debug([KMLogs oskLog], "OSKWindowController windowDidResize"); [self.oskView resizeOSKLayout]; } @@ -87,8 +84,7 @@ - (void)helpAction:(id)sender { } - (void)resetOSK { - os_log_t oskLog = os_log_create("org.sil.keyman", "osk"); - os_log_with_type(oskLog, OS_LOG_TYPE_DEBUG, "OSKWC windowDidLoad"); + os_log_debug([KMLogs oskLog], "OSKWindowController windowDidLoad"); [self.oskView setKvk:[self.AppDelegate kvk]]; [self.oskView resetOSK]; if (_helpButton) { diff --git a/mac/Keyman4MacIM/Keyman4MacIM/Privacy/PrivacyConsent.m b/mac/Keyman4MacIM/Keyman4MacIM/Privacy/PrivacyConsent.m index 18047dccf3f..057f401cbe4 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/Privacy/PrivacyConsent.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/Privacy/PrivacyConsent.m @@ -28,6 +28,7 @@ */ #import "PrivacyConsent.h" +#import "KMLogs.h" @implementation PrivacyConsent @@ -49,7 +50,7 @@ - (BOOL)checkAccessibility BOOL hasAccessibility = NO; hasAccessibility = AXIsProcessTrusted(); - NSLog(@" hasAccessibility: %@",hasAccessibility ? @"YES" : @"NO"); + os_log([KMLogs privacyLog], " hasAccessibility: %@",hasAccessibility ? @"YES" : @"NO" ); return hasAccessibility; } @@ -72,13 +73,13 @@ - (void)requestPrivacyAccess:(void (^)(void))withCompletionHandler } if (hasAccessibility) { - NSLog(@"already have Accessibility: no need to make request."); + os_log([KMLogs privacyLog], "already has Accessibility: no need to make request."); // call completionHandler immediately -> privacyDialog will not be presented withCompletionHandler(); } else { // set completionHandler to be called after privacyDialog is dismissed _completionHandler = withCompletionHandler; - NSLog(@"do not have Accessibility, present Privacy Dialog"); + os_log([KMLogs privacyLog], "does not have Accessibility, present Privacy Dialog"); [self showPrivacyDialog]; } } @@ -90,7 +91,7 @@ - (void)requestAccessibility { NSDictionary *options = @{(id)CFBridgingRelease(kAXTrustedCheckOptionPrompt): @YES}; BOOL hasAccessibility = AXIsProcessTrustedWithOptions((CFDictionaryRef)options); - NSLog(@" hasAccessibility: %@",hasAccessibility ? @"YES" : @"NO, requesting..."); + os_log([KMLogs privacyLog], "hasAccessibility: %@",hasAccessibility ? @"YES" : @"NO, requesting..."); } /** @@ -100,7 +101,7 @@ - (void)requestAccessibility - (NSWindowController *)privacyDialog { if (!_privacyDialog) { _privacyDialog = [[PrivacyWindowController alloc] initWithWindowNibName:@"PrivacyWindowController"]; - NSLog(@"privacyDialog created"); + os_log([KMLogs privacyLog], "privacyDialog created"); [self configureDialogForOsVersion]; } @@ -171,9 +172,9 @@ - (BOOL)checkListenEventAccess // below checks for ListenEvent access if (@available(macOS 10.15, *)) { hasAccess = CGPreflightListenEventAccess(); - NSLog(@"CGPreflightListenEventAccess() returned %@", hasAccess ? @"YES" : @"NO"); + os_log([KMLogs privacyLog], "CGPreflightListenEventAccess() returned %@", hasAccess ? @"YES" : @"NO"); } else { - NSLog(@"CGPreflightListenEventAccess not available before macOS version 10.15"); + os_log([KMLogs privacyLog], "CGPreflightListenEventAccess not available before macOS version 10.15"); } return hasAccess; } @@ -192,9 +193,9 @@ - (BOOL)checkPostEventAccess if (@available(macOS 10.15, *)) { hasAccess = CGPreflightPostEventAccess(); - NSLog(@"CGPreflightPostEventAccess() returned %@", hasAccess ? @"YES" : @"NO"); + os_log([KMLogs privacyLog], "CGPreflightPostEventAccess() returned %@", hasAccess ? @"YES" : @"NO"); } else { - NSLog(@"CGPreflightPostEventAccess not available before macOS version 10.15"); + os_log([KMLogs privacyLog], "CGPreflightPostEventAccess not available before macOS version 10.15"); } return hasAccess; } @@ -209,9 +210,9 @@ - (BOOL)requestListenEventAccess if (@available(macOS 10.15, *)) { granted = CGRequestListenEventAccess(); - NSLog(@"CGRequestListenEventAccess() returned %@", granted ? @"YES" : @"NO"); + os_log([KMLogs privacyLog], "CGRequestListenEventAccess() returned %@", granted ? @"YES" : @"NO"); } else { - NSLog(@"CGRequestListenEventAccess not available before macOS version 10.15"); + os_log([KMLogs privacyLog], "CGRequestListenEventAccess not available before macOS version 10.15"); } return granted; } @@ -226,9 +227,9 @@ - (BOOL)requestPostEventAccess if (@available(macOS 10.15, *)) { granted = CGRequestPostEventAccess(); - NSLog(@"CGRequestPostEventAccess() returned %@", granted ? @"YES" : @"NO"); + os_log([KMLogs privacyLog], "CGRequestPostEventAccess() returned %@", granted ? @"YES" : @"NO"); } else { - NSLog(@"CGRequestPostEventAccess not available before macOS version 10.15"); + os_log([KMLogs privacyLog], "CGRequestPostEventAccess not available before macOS version 10.15"); } return granted; } diff --git a/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.m b/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.m index 6150efae563..0f62fa61a8a 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/TextApiCompliance.m @@ -35,6 +35,7 @@ #import "TextApiCompliance.h" #import #import "KMInputMethodAppDelegate.h" +#import "KMLogs.h" // this is the user managed list of non-compliant apps persisted in User Defaults NSString *const kKMLegacyApps = @"KMLegacyApps"; @@ -86,10 +87,10 @@ -(void) checkCompliance:(id) client { else { // if API exists, call it and see if it works as expected self.initialSelection = [client selectedRange]; - [self.appDelegate logDebugMessage:@"TextApiCompliance checkCompliance, location = %lu, length = %lu", self.initialSelection.location, self.initialSelection.length]; + os_log_debug([KMLogs complianceLog], "checkCompliance, location = %lu, length = %lu", self.initialSelection.location, self.initialSelection.length); [self checkComplianceUsingInitialSelection]; } - [self.appDelegate logDebugMessage:@"TextApiCompliance checkCompliance workingSelectionApi for app %@: set to %@", self.clientApplicationId, self.complianceUncertain?@"YES":@"NO"]; + os_log_debug([KMLogs complianceLog], "checkCompliance workingSelectionApi for app %{public}@: set to %{public}@", self.clientApplicationId, self.complianceUncertain?@"YES":@"NO"); } -(void) checkComplianceUsingInitialSelection { @@ -100,7 +101,7 @@ -(void) checkComplianceUsingInitialSelection { */ self.hasCompliantSelectionApi = NO; self.complianceUncertain = YES; - [self.appDelegate logDebugMessage:@"TextApiCompliance checkComplianceUsingInitialSelection not compliant but uncertain, range is NSNotFound"]; + os_log_debug([KMLogs complianceLog], "checkComplianceUsingInitialSelection not compliant but uncertain, range is NSNotFound"); } else if (self.initialSelection.location >= 0) { /** * location greater than or equal to zero may just mean that the client @@ -109,7 +110,7 @@ -(void) checkComplianceUsingInitialSelection { */ self.hasCompliantSelectionApi = YES; self.complianceUncertain = YES; - [self.appDelegate logDebugMessage:@"TextApiCompliance checkComplianceUsingInitialSelection compliant but uncertain, location >= 0"]; + os_log_debug([KMLogs complianceLog], "checkComplianceUsingInitialSelection compliant but uncertain, location >= 0"); } } @@ -122,7 +123,7 @@ -(void) checkComplianceAfterInsert:(id) client delete:(NSString *)textToDelete i // return if compliance is already certain if(!self.complianceUncertain) { - [self.appDelegate logDebugMessage:@"TextApiCompliance checkComplianceAfterInsert, compliance is already known"]; + os_log_debug([KMLogs complianceLog], "checkComplianceAfterInsert, compliance is already known"); return; } @@ -133,7 +134,7 @@ -(void) checkComplianceAfterInsert:(id) client delete:(NSString *)textToDelete i [self validateLocationChange:changeExpected hasLocationChanged:locationChanged]; } - [self.appDelegate logDebugMessage:@"TextApiCompliance checkComplianceAfterInsert, self.hasWorkingSelectionApi = %@ for app %@", self.hasCompliantSelectionApi?@"YES":@"NO", self.clientApplicationId]; + os_log_info([KMLogs complianceLog], "checkComplianceAfterInsert, self.hasWorkingSelectionApi = %{public}@ for app %{public}@", self.hasCompliantSelectionApi?@"YES":@"NO", self.clientApplicationId); } - (BOOL)validateNewLocation:(NSUInteger)location delete:(NSString *)textToDelete { @@ -143,16 +144,16 @@ - (BOOL)validateNewLocation:(NSUInteger)location delete:(NSString *)textToDelete // invalid location: insertText means we have focus, NSNotFound means selection API not functioning self.hasCompliantSelectionApi = NO; self.complianceUncertain = NO; - [self.appDelegate logDebugMessage:@"TextApiCompliance validateNewLocation = NO, location is NSNotFound"]; + os_log_debug([KMLogs complianceLog], "validateNewLocation = NO, location is NSNotFound"); } else if ((location == 0) && (textToDelete.length > 0)) { // invalid location: cannot have text to delete at location zero self.hasCompliantSelectionApi = NO; self.complianceUncertain = NO; - [self.appDelegate logDebugMessage:@"TextApiCompliance validateNewLocation = NO, location is zero with textToDelete.length > 0"]; + os_log_debug([KMLogs complianceLog], "validateNewLocation = NO, location is zero with textToDelete.length > 0"); } else { // location is valid, but do not know if it is compliant yet validLocation = YES; - [self.appDelegate logDebugMessage:@"TextApiCompliance validateNewLocation = YES, newLocation = %d, oldLocation = %d", location, self.initialSelection.location]; + os_log_debug([KMLogs complianceLog], "validateNewLocation = YES, newLocation = %lu, oldLocation = %lu", (unsigned long)location, (unsigned long)self.initialSelection.location); } return validLocation; } @@ -163,18 +164,18 @@ - (void) validateLocationChange:(BOOL) changeExpected hasLocationChanged:(BOOL) // YES for certain, the location is where we expect it self.hasCompliantSelectionApi = YES; self.complianceUncertain = NO; - [self.appDelegate logDebugMessage:@"TextApiCompliance validateLocationChange compliant, locationChanged = %@, changeExpected = %@", locationChanged?@"YES":@"NO", changeExpected?@"YES":@"NO"]; + os_log_debug([KMLogs complianceLog], "validateLocationChange compliant, locationChanged = %{public}@, changeExpected = %{public}@", locationChanged?@"YES":@"NO", changeExpected?@"YES":@"NO"); } else if (changeExpected != locationChanged) { // NO for certain, when the selection is unchanged after an insert self.hasCompliantSelectionApi = NO; self.complianceUncertain = NO; - [self.appDelegate logDebugMessage:@"TextApiCompliance validateLocationChange non-compliant, locationChanged = %@, changeExpected = %@", locationChanged?@"YES":@"NO", changeExpected?@"YES":@"NO"]; + os_log_debug([KMLogs complianceLog], "validateLocationChange non-compliant, locationChanged = %{public}@, changeExpected = %{public}@", locationChanged?@"YES":@"NO", changeExpected?@"YES":@"NO"); } } - (BOOL)isLocationChangeExpectedOnInsert:(NSString *)textToDelete insert:(NSString *)textToInsert { BOOL changeExpected = textToInsert.length != textToDelete.length; - [self.appDelegate logDebugMessage:@"TextApiCompliance isLocationChangeExpected, changeExpected = %@", changeExpected?@"YES":@"NO"]; + os_log_debug([KMLogs complianceLog], "isLocationChangeExpected, changeExpected = %{public}@", changeExpected?@"YES":@"NO"); return changeExpected; } @@ -183,8 +184,7 @@ - (BOOL)hasLocationChanged:(NSRange)newSelection { NSUInteger newLocation = newSelection.location; NSUInteger oldLocation = self.initialSelection.location; BOOL locationChanged = newLocation != oldLocation; - [self.appDelegate logDebugMessage:@"TextApiCompliance hasLocationChanged, currentSelection = %lu, length = %lu", newSelection.location, newSelection.length]; - + os_log_debug([KMLogs complianceLog], "hasLocationChanged: %{public}@, new location: %lu, selection length: %lu", locationChanged?@"YES":@"NO", newSelection.location, newSelection.length); return locationChanged; } @@ -198,7 +198,7 @@ - (BOOL)applyNoncompliantAppLists:(NSString *)clientAppId { isAppNonCompliant = [self containedInUserManagedNoncompliantAppList:clientAppId]; } - [self.appDelegate logDebugMessage:@"applyNoncompliantAppLists: for app %@: %@", clientAppId, isAppNonCompliant?@"YES":@"NO"]; + os_log_info([KMLogs complianceLog], "applyNoncompliantAppLists: for app %{public}@: %{public}@", clientAppId, isAppNonCompliant?@"YES":@"NO"); if (isAppNonCompliant) { self.complianceUncertain = NO; @@ -238,7 +238,7 @@ - (BOOL)containedInHardCodedNoncompliantAppList:(NSString *)clientAppId { /*||[clientAppId isEqual: @"ro.sync.exml.Oxygen"] - Oxygen has worse problems */ ); - [self.appDelegate logDebugMessage:@"containedInHardCodedNoncompliantAppList: for app %@: %@", clientAppId, isAppNonCompliant?@"yes":@"no"]; + os_log_debug([KMLogs complianceLog], "containedInHardCodedNoncompliantAppList: for app %{public}@: %{public}@", clientAppId, isAppNonCompliant?@"yes":@"no"); return isAppNonCompliant; } @@ -260,7 +260,7 @@ - (BOOL)containedInUserManagedNoncompliantAppList:(NSString *)clientAppId { if(legacyAppsUserDefaults != nil) { isAppNonCompliant = [self arrayContainsApplicationId:clientAppId fromArray:legacyAppsUserDefaults]; } - [self.appDelegate logDebugMessage:@"containedInUserManagedNoncompliantAppList: for app %@: %@", clientAppId, isAppNonCompliant?@"yes":@"no"]; + os_log_debug([KMLogs complianceLog], "containedInUserManagedNoncompliantAppList: for app %{public}@: %{public}@", clientAppId, isAppNonCompliant?@"yes":@"no"); return isAppNonCompliant; } @@ -271,7 +271,7 @@ - (BOOL)arrayContainsApplicationId:(NSString *)applicationId fromArray:(NSArray for(id appId in applicationArray) { if(![appId isKindOfClass:[NSString class]]) { // always log this: bad data in UserDefaults - NSLog(@"arrayContainsApplicationId:fromArray: LegacyApps user defaults array should contain only strings"); + os_log_error([KMLogs complianceLog], "arrayContainsApplicationId:fromArray: LegacyApps user defaults array should contain only strings"); } else { NSError *error = nil; NSRange range = NSMakeRange(0, applicationId.length); @@ -279,7 +279,7 @@ - (BOOL)arrayContainsApplicationId:(NSString *)applicationId fromArray:(NSArray NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern: (NSString *) appId options: 0 error: &error]; NSArray *matchesArray = [regex matchesInString:applicationId options:0 range:range]; if(matchesArray.count>0) { - [self.appDelegate logDebugMessage:@"arrayContainsApplicationId: found match for application ID %@: ", applicationId]; + os_log_debug([KMLogs complianceLog], "arrayContainsApplicationId: found match for application ID %{public}@: ", applicationId); return YES; } } diff --git a/mac/Keyman4MacIM/Keyman4MacIM/main.m b/mac/Keyman4MacIM/Keyman4MacIM/main.m index 04388ae1aaa..3c8eb752e69 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/main.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/main.m @@ -8,14 +8,13 @@ #import #import -#import +#import "KMLogs.h" const NSString *kConnectionName = @"Keyman_Input_Connection"; IMKServer *server; int main(int argc, const char * argv[]) { NSString *identifier; - os_log_t configLog = os_log_create("org.sil.keyman", "startup"); @autoreleasepool { identifier = [[NSBundle mainBundle] bundleIdentifier]; @@ -23,7 +22,7 @@ int main(int argc, const char * argv[]) { BOOL didLoadNib = [[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:[NSApplication sharedApplication] topLevelObjects: nil]; - os_log_with_type(configLog, OS_LOG_TYPE_DEBUG, "main Did load MainMenu nib: %@", didLoadNib?@"YES":@"NO"); + os_log_info([KMLogs startupLog], "main Did load MainMenu nib: %@", didLoadNib?@"YES":@"NO"); [[NSApplication sharedApplication] run]; } diff --git a/mac/Keyman4MacIM/KeymanTests/TextApiComplianceTests.m b/mac/Keyman4MacIM/KeymanTests/TextApiComplianceTests.m index 2b3cce1a4d4..e0e513af1cd 100644 --- a/mac/Keyman4MacIM/KeymanTests/TextApiComplianceTests.m +++ b/mac/Keyman4MacIM/KeymanTests/TextApiComplianceTests.m @@ -12,6 +12,7 @@ #import #import "TextApiCompliance.h" #import "AppleCompliantTestClient.h" +#import "KMLogs.h" @interface TextApiComplianceTests : XCTestCase @end @@ -153,7 +154,7 @@ - (void)testIsClientAppLegacy_unlistedClientAppId_returnsNo { NSArray *legacyAppsArray = [NSArray arrayWithObjects:@"com.microsoft.VSCode",@"com.adobe.Photoshop",nil]; BOOL isLegacy = [apiCompliance arrayContainsApplicationId:clientAppId fromArray:legacyAppsArray]; - NSLog(@"isLegacy = %@", isLegacy?@"yes":@"no"); + os_log_debug([KMLogs testLog], "isLegacy = %@", isLegacy?@"yes":@"no"); XCTAssertFalse(isLegacy, @"App not expected to be in legacy list"); } diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac.xcodeproj/project.pbxproj b/mac/KeymanEngine4Mac/KeymanEngine4Mac.xcodeproj/project.pbxproj index d5c330e1f4d..658891c0c6f 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac.xcodeproj/project.pbxproj +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac.xcodeproj/project.pbxproj @@ -23,6 +23,8 @@ 29A1971E2AF091E600512A37 /* CoreKeyOutput.h in Headers */ = {isa = PBXBuildFile; fileRef = 29A1971C2AF091E600512A37 /* CoreKeyOutput.h */; settings = {ATTRIBUTES = (Public, ); }; }; 29A1971F2AF091E600512A37 /* CoreKeyOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = 29A1971D2AF091E600512A37 /* CoreKeyOutput.m */; }; 29A658C82AF394560038DCFE /* armenian_mnemonic.kmx in Resources */ = {isa = PBXBuildFile; fileRef = 29A658C72AF394560038DCFE /* armenian_mnemonic.kmx */; }; + 29B4A0D82BFAE8A400682049 /* KMELogs.h in Headers */ = {isa = PBXBuildFile; fileRef = 29B4A0D62BFAE8A400682049 /* KMELogs.h */; }; + 29B4A0D92BFAE8A400682049 /* KMELogs.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B4A0D72BFAE8A400682049 /* KMELogs.m */; }; 378568D122FCCF0A00B481B5 /* sil_ipa.kmx in Resources */ = {isa = PBXBuildFile; fileRef = 378568D022FCCF0A00B481B5 /* sil_ipa.kmx */; }; 378568D322FCD93300B481B5 /* indexoffset1892.kmx in Resources */ = {isa = PBXBuildFile; fileRef = 378568D222FCD93300B481B5 /* indexoffset1892.kmx */; }; 980053351B37C9B50088DDDD /* NFont.h in Headers */ = {isa = PBXBuildFile; fileRef = 980053311B37C9B50088DDDD /* NFont.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -97,6 +99,8 @@ 29A205D82AC2E446000750C0 /* libsicuuc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsicuuc.a; path = "../../core/build/mac-arm64/release/subprojects/icu/source/common/libsicuuc.a"; sourceTree = ""; }; 29A205DA2AC2E46A000750C0 /* libsicui18n.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsicui18n.a; path = "../../core/build/mac-arm64/release/subprojects/icu/source/i18n/libsicui18n.a"; sourceTree = ""; }; 29A658C72AF394560038DCFE /* armenian_mnemonic.kmx */ = {isa = PBXFileReference; lastKnownFileType = file; path = armenian_mnemonic.kmx; sourceTree = ""; }; + 29B4A0D62BFAE8A400682049 /* KMELogs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KMELogs.h; sourceTree = ""; }; + 29B4A0D72BFAE8A400682049 /* KMELogs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KMELogs.m; sourceTree = ""; }; 378568D022FCCF0A00B481B5 /* sil_ipa.kmx */ = {isa = PBXFileReference; lastKnownFileType = file; path = sil_ipa.kmx; sourceTree = ""; }; 378568D222FCD93300B481B5 /* indexoffset1892.kmx */ = {isa = PBXFileReference; lastKnownFileType = file; path = indexoffset1892.kmx; sourceTree = ""; }; 980053311B37C9B50088DDDD /* NFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NFont.h; sourceTree = ""; }; @@ -286,6 +290,8 @@ 984C2AEE1A79CA4F0023F89D /* KME */ = { isa = PBXGroup; children = ( + 29B4A0D62BFAE8A400682049 /* KMELogs.h */, + 29B4A0D72BFAE8A400682049 /* KMELogs.m */, 981880641BC1EA5800A1FBA5 /* OnScreenKeyboard */, 984C2AEF1A79CA4F0023F89D /* Categories */, 984C2AF51A79CA4F0023F89D /* KMBinaryFileFormat.h */, @@ -351,6 +357,7 @@ 2993C33229B1D92E00FB5E95 /* CoreWrapper.h in Headers */, 9818806F1BC1EA5800A1FBA5 /* KeyLabel.h in Headers */, 981880751BC1EA5800A1FBA5 /* OSKKey.h in Headers */, + 29B4A0D82BFAE8A400682049 /* KMELogs.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -501,6 +508,7 @@ 980053381B37C9B50088DDDD /* NKey.m in Sources */, 981880701BC1EA5800A1FBA5 /* KeyLabel.m in Sources */, 981880721BC1EA5800A1FBA5 /* KeyLabelCell.m in Sources */, + 29B4A0D92BFAE8A400682049 /* KMELogs.m in Sources */, 981880781BC1EA5800A1FBA5 /* OSKView.m in Sources */, 2993C32E29B1D92E00FB5E95 /* CoreWrapper.m in Sources */, 984C2B0F1A79CA4F0023F89D /* KMCompKey.m in Sources */, diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/CoreWrapper/CoreHelper.h b/mac/KeymanEngine4Mac/KeymanEngine4Mac/CoreWrapper/CoreHelper.h index 7f89ecd0094..0345ea6f31e 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/CoreWrapper/CoreHelper.h +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/CoreWrapper/CoreHelper.h @@ -23,7 +23,6 @@ extern UInt32 VirtualKeyMap[0x80]; -(unsigned long long) unicharStringLength:(unichar const *)string; -(instancetype)initWithDebugMode:(BOOL)debugMode; --(void)logDebugMessage:(NSString *)format, ...; -(unsigned short) macVirtualKeyToWindowsVirtualKey:(unsigned short) keyCode; -(UTF32Char)macToKeymanModifier:(NSEventModifierFlags)modifiers; -(NSString*)utf32ValueToString:(UTF32Char)scalarValue; diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/CoreWrapper/CoreHelper.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/CoreWrapper/CoreHelper.m index 8aa02433766..46ddbdeeb14 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/CoreWrapper/CoreHelper.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/CoreWrapper/CoreHelper.m @@ -19,6 +19,7 @@ #import "keyman_core_api.h" #import "MacVKCodes.h" #import "WindowsVKCodes.h" +#import "KMELogs.h" const int VIRTUAL_KEY_ARRAY_SIZE = 0x80; UInt32 VirtualKeyMap[VIRTUAL_KEY_ARRAY_SIZE]; @@ -32,7 +33,7 @@ @implementation CoreHelper -(unichar const *) createUnicharStringFromNSString:(NSString *)string { NSString *nullTerminatedString = [string stringByAppendingString:@"\0"]; if (![nullTerminatedString canBeConvertedToEncoding:NSUTF16LittleEndianStringEncoding]) { - [self logDebugMessage:@"createUnicharStringFromNSString, canBeConvertedToEncoding false for NSUTF16LittleEndianStringEncoding"]; + os_log_debug([KMELogs coreLog], "createUnicharStringFromNSString, canBeConvertedToEncoding false for NSUTF16LittleEndianStringEncoding"); return nil; } @@ -77,15 +78,6 @@ -(instancetype)initWithDebugMode:(BOOL)debugMode { return self; } --(void)logDebugMessage:(NSString *)format, ... { - if (self.debugMode) { - va_list args; - va_start(args, format); - NSLogv(format, args); - va_end(args); - } -} - -(unsigned short) macVirtualKeyToWindowsVirtualKey:(unsigned short) keyCode { if ((keyCode<0) || (keyCode>=VIRTUAL_KEY_ARRAY_SIZE)) { return 0; @@ -125,7 +117,7 @@ -(UTF32Char)macToKeymanModifier:(NSEventModifierFlags)modifiers { keymanModifiers |= KM_CORE_MODIFIER_NOCAPS; }*/ - [self logDebugMessage:@"macToKeymanModifier result = %u", (unsigned int)keymanModifiers]; + os_log_debug([KMELogs coreLog], "macToKeymanModifier, macModifiers: %lu / ox%lX keymanModifiers: %d / 0x%X", (unsigned long)modifiers, modifiers, keymanModifiers, keymanModifiers); return keymanModifiers; } @@ -169,7 +161,7 @@ -(NSString*)utf32ValueToString:(UTF32Char)scalarValue { NSData * characterData = [[NSData alloc] initWithBytes:&scalarValue length:sizeof(scalarValue)]; NSString *characterString=[[NSString alloc] initWithBytes:[characterData bytes] length:[characterData length] encoding:NSUTF32LittleEndianStringEncoding]; - [self logDebugMessage:@"utf32ValueToString data: '%@', string: %@", characterData, characterString]; + os_log_debug([KMELogs coreLog], "utf32ValueToString data: '%@', string: %@", characterData, characterString); return characterString; } diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/CoreWrapper/CoreKeyOutput.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/CoreWrapper/CoreKeyOutput.m index 7ab8fdfd6b2..61da1f736d2 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/CoreWrapper/CoreKeyOutput.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/CoreWrapper/CoreKeyOutput.m @@ -32,9 +32,10 @@ -(instancetype)init:(NSUInteger)codePointsToDelete textToDelete:(NSString*)delet -(NSString *)description { - NSData* data = [self.textToInsert dataUsingEncoding:NSUTF16LittleEndianStringEncoding]; - - return [[NSString alloc] initWithFormat: @"codePointsToDeleteBeforeInsert: %li, textToInsert: '%@', optionsToPersist: %@, alert: %d, emitKeystroke: %d, capsLockState: %d ", self.codePointsToDeleteBeforeInsert, data, self.optionsToPersist, self.alert, self.emitKeystroke, self.capsLockState]; + NSData* deleteData = [self.textToDelete dataUsingEncoding:NSUTF16LittleEndianStringEncoding]; + NSData* insertData = [self.textToInsert dataUsingEncoding:NSUTF16LittleEndianStringEncoding]; + + return [[NSString alloc] initWithFormat: @"codePointsToDeleteBeforeInsert: %li, textToDelete: '%@' [data: '%@'], textToInsert: '%@' [data: '%@], optionsToPersist: %@, alert: %d, emitKeystroke: %d, capsLockState: %d ", self.codePointsToDeleteBeforeInsert, self.textToDelete, deleteData, self.textToInsert, insertData, self.optionsToPersist, self.alert, self.emitKeystroke, self.capsLockState]; } -(BOOL)hasCodePointsToDelete { diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/CoreWrapper/CoreWrapper.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/CoreWrapper/CoreWrapper.m index 4c8b2884141..44c82e5b7b8 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/CoreWrapper/CoreWrapper.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/CoreWrapper/CoreWrapper.m @@ -15,6 +15,7 @@ #import "CoreWrapper.h" #import "keyman_core_api.h" #import "keyman_core_api_consts.h" +#import "KMELogs.h" @interface CoreWrapper() @@ -73,7 +74,7 @@ -(void) dealloc{ if (self.coreKeyboard) { km_core_keyboard_dispose(self.coreKeyboard); } - [self.coreHelper logDebugMessage:@"CoreWrapper dealloc called."]; + os_log_debug([KMELogs coreLog], "dealloc called."); } -(void)loadKeyboardUsingCore:(NSString*) path { @@ -94,9 +95,9 @@ -(void)readKeyboardAttributesUsingCore { if (result==KM_CORE_STATUS_OK) { _keyboardVersion = [self.coreHelper createNSStringFromUnicharString:keyboardAttributes->version_string]; _keyboardId = [self.coreHelper createNSStringFromUnicharString:keyboardAttributes->id]; - [self.coreHelper logDebugMessage:@"keyboardVersion = %@\n, keyboardId = %@\n", _keyboardVersion, _keyboardId]; + os_log_debug([KMELogs coreLog], "readKeyboardAttributesUsingCore, keyboardVersion: %{public}@\n, keyboardId: %{public}@\n", _keyboardVersion, _keyboardId); } else { - NSLog(@"km_core_keyboard_get_attrs() failed with result = %u\n", result ); + os_log_error([KMELogs coreLog], "km_core_keyboard_get_attrs() failed with result = %u\n", result); } } } @@ -117,7 +118,7 @@ -(void)createKeyboardStateUsingCore { [NSException raise:@"CreateKeyboardStateException" format:@"%@", message]; } } else { - NSLog(@"CoreWrapper, Unable to set environment options for keyboard" ); + os_log_error([KMELogs coreLog], "CoreWrapper, Unable to set environment options for keyboard"); } } @@ -149,6 +150,7 @@ -(CoreKeyOutput*)processMacVirtualKey:(unsigned short)macKeyCode withModifier:modifierState withKeyDown:keyDown]) { output = [self loadOutputForLastKeyProcessed]; + os_log_debug([KMELogs coreLog], "processMacVirtualKey for macKeyCode: %d / 0x%X, core output: %{public}@", macKeyCode, macKeyCode, output); } return output; } @@ -160,7 +162,7 @@ -(BOOL)processVirtualKey:(uint16_t)keyCode km_core_status result = km_core_process_event(self.coreState, keyCode, modifierState, isKeyDown, KM_CORE_EVENT_FLAG_DEFAULT); if (result!=KM_CORE_STATUS_OK) { - [self.coreHelper logDebugMessage:@"km_core_process_event() result = %u\n", result]; + os_log_error([KMELogs coreLog], "km_core_process_event() result = %u\n", result); } return (result==KM_CORE_STATUS_OK); @@ -171,7 +173,6 @@ -(CoreKeyOutput*)loadOutputForLastKeyProcessed { } -(CoreKeyOutput*)loadActionStructUsingCore { - [self.coreHelper logDebugMessage:@"CoreWrapper loadActionStructUsingCore"]; km_core_actions * actions = km_core_state_get_actions(self.coreState); CoreKeyOutput *output = [self createCoreKeyOutputForActionsStruct:actions]; return output; @@ -184,7 +185,7 @@ -(CoreKeyOutput*) createCoreKeyOutputForActionsStruct:(km_core_actions*)actions NSString* deletedText = [self.coreHelper utf32CStringToString:actions->deleted_context]; CoreKeyOutput* coreKeyOutput = [[CoreKeyOutput alloc] init: actions->code_points_to_delete textToDelete:deletedText textToInsert:text optionsToPersist:options alert:actions->do_alert emitKeystroke:actions->emit_keystroke capsLockState:capsLock]; - + return coreKeyOutput; } @@ -225,13 +226,13 @@ -(CapsLockState)convertCapsLockState:(km_core_caps_state)capsState { -(void)clearContextUsingCore { km_core_state_context_clear(self.coreState); - [self.coreHelper logDebugMessage:@"km_core_state_context_clear called"]; + os_log_debug([KMELogs coreLog], "km_core_state_context_clear called"); } -(void)setContextIfNeeded:(NSString*)context { unichar const * unicharContext = [self.coreHelper createUnicharStringFromNSString:context]; km_core_status result = km_core_state_context_set_if_needed(self.coreState, unicharContext); - [self.coreHelper logDebugMessage:@"CoreWrapper setContextIfNeeded, context=%@, km_core_state_context_set_if_needed result=%i", context, result]; + os_log_debug([KMELogs coreLog], "setContextIfNeeded, context=%{public}@, km_core_state_context_set_if_needed result=%d", context, result); } -(NSString*)contextDebug { @@ -239,7 +240,7 @@ -(NSString*)contextDebug { NSString *debugString = [self.coreHelper createNSStringFromUnicharString:context]; km_core_cu_dispose(context); - [self.coreHelper logDebugMessage:@"CoreWrapper contextDebug = %@", debugString]; + os_log_debug([KMELogs coreLog], "contextDebug = %{public}@", debugString); return debugString; } @@ -271,8 +272,8 @@ +(BOOL)setupCoreEnvironment:(km_core_option_item *) coreOptionArray { } -(BOOL)setOptionsForCore: (NSString *) key value:(NSString *) value { - [self.coreHelper logDebugMessage:@"setOptionsForCore, key = %@, value = %@", key, value]; - + os_log_debug([KMELogs coreLog], "setOptionsForCore, key = %@, value = %@", key, value); + // array of length 2, second item is terminating null struct km_core_option_item option[2] = {0}; option[0].key = [self.coreHelper createUnicharStringFromNSString: key]; @@ -280,8 +281,8 @@ -(BOOL)setOptionsForCore: (NSString *) key value:(NSString *) value { option[0].scope = KM_CORE_OPT_KEYBOARD; km_core_status result = km_core_state_options_update(self.coreState, &option[0]); - [self.coreHelper logDebugMessage:@"setOptionsForCore, km_core_state_options_update result = %d", result]; - + os_log_debug([KMELogs coreLog], "setOptionsForCore, km_core_state_options_update result = %d", result); + return (result==KM_CORE_STATUS_OK); } @@ -294,15 +295,15 @@ -(void)readCoreOptions: (km_core_cu const *) key { &valueFromCore); if (result == KM_CORE_STATUS_OK) { if (valueFromCore) { - [self.coreHelper logDebugMessage:@"km_core_state_option_lookup successful, current value set in core= %@", [self.coreHelper createNSStringFromUnicharString:valueFromCore]]; + os_log_debug([KMELogs coreLog], "km_core_state_option_lookup successful, current value set in core= %@", [self.coreHelper createNSStringFromUnicharString:valueFromCore]); } else { - [self.coreHelper logDebugMessage:@"km_core_state_option_lookup returned nil"]; + os_log_debug([KMELogs coreLog], "km_core_state_option_lookup returned nil"); } } else { if (valueFromCore) { - [self.coreHelper logDebugMessage:@"km_core_state_option_lookup failed, result = %d", result]; + os_log_debug([KMELogs coreLog], "km_core_state_option_lookup failed, result = %d", result); } else { - [self.coreHelper logDebugMessage:@"km_core_state_option_lookup returned nil, result = %d", result]; + os_log_debug([KMELogs coreLog], "km_core_state_option_lookup returned nil, result = %d", result); } } diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMELogs.h b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMELogs.h new file mode 100644 index 00000000000..45d60de7f4c --- /dev/null +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMELogs.h @@ -0,0 +1,29 @@ +/** + * Keyman is copyright (C) SIL International. MIT License. + * + * KMELogs.h + * KeymanEngine4Mac + * + * Created by Shawn Schantz on 2024-05-16. + * + * Contains methods to get singleton logger objects and constants for subsystem and category names. + */ + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KMELogs : NSObject + ++ (os_log_t)startupLog; ++ (os_log_t)configLog; ++ (os_log_t)keyLog; ++ (os_log_t)coreLog; ++ (os_log_t)oskLog; ++ (os_log_t)uiLog; ++ (os_log_t)testLog; + +@end + +NS_ASSUME_NONNULL_END diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMELogs.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMELogs.m new file mode 100644 index 00000000000..80f3012636e --- /dev/null +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMELogs.m @@ -0,0 +1,63 @@ +/** + * Keyman is copyright (C) SIL International. MIT License. + * + * KMELogs.m + * KeymanEngine4Mac + * + * Created by Shawn Schantz on 2024-05-16. + * + * Contains methods to get singleton logger objects and constants for subsystem and category names. + */ + +/** + * The loggers do not appear to be singletons, but the API which creates them manages + * them as singletons within macOS so that any subsequent call to create a log object + * using the same subsystem and category will return the existing instance. + * + * For any new log categories used anywhere in the Keyman Engine for Mac, the name should be defined here. + * The Keyman Input Method may define and use the same category name but will use a different subsystem name. + */ + +#import "KMELogs.h" +#import + +@implementation KMELogs + +char *const keymanEngineSubsystem = "com.keyman.engine"; +char *const startupCategory = "startup"; +char *const configCategory = "config"; +char *const keyCategory = "key"; +char *const coreCategory = "core"; +char *const oskCategory = "osk"; +char *const uiCategory = "ui"; +char *const testCategory = "test"; + ++ (os_log_t)startupLog { + return os_log_create(keymanEngineSubsystem, startupCategory); +} + ++ (os_log_t)configLog { + return os_log_create(keymanEngineSubsystem, configCategory); +} + ++ (os_log_t)keyLog { + return os_log_create(keymanEngineSubsystem, keyCategory); +} + ++ (os_log_t)coreLog { + return os_log_create(keymanEngineSubsystem, coreCategory); +} + ++ (os_log_t)oskLog { + return os_log_create(keymanEngineSubsystem, oskCategory); +} + ++ (os_log_t)uiLog { + return os_log_create(keymanEngineSubsystem, uiCategory); +} + ++ (os_log_t)testLog { + return os_log_create(keymanEngineSubsystem, testCategory); +} + +@end diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m index 71a59411778..dd2b3247ede 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m @@ -15,10 +15,9 @@ #import "WindowsVKCodes.h" #import "MacVKCodes.h" #import "CoreWrapper.h" +#import "KMELogs.h" @import Carbon; -//DWORD VKMap[0x80]; - @interface KMEngine () @property (readonly) CoreHelper *coreHelper; @property (nonatomic, retain) CoreWrapper * coreWrapper; @@ -49,10 +48,9 @@ - (id)initWithKMX:(KMXFile *)kmx context:(NSString *)contextString verboseLoggin -(void)loadCoreWrapperFromKmxFile:(NSString *)kmxFilePath { @try { _coreWrapper = [[CoreWrapper alloc] initWithHelper:_coreHelper kmxFilePath:kmxFilePath]; - [self.coreHelper logDebugMessage:@"loadCoreWrapperFromKmxFile, keyboardId = %@", [self.coreWrapper keyboardId]]; } @catch (NSException *exception) { - NSLog(@"loadCoreWrapperFromKmxFile, failed to create keyboard for path '%@' with exception: %@", kmxFilePath, exception.description); + os_log_error([KMELogs coreLog], "loadCoreWrapperFromKmxFile, failed to create keyboard for path '%{public}@' with exception: %{public}@", kmxFilePath, exception.description); } } @@ -73,20 +71,21 @@ - (void)setUseVerboseLogging:(BOOL)useVerboseLogging { } if (useVerboseLogging) { - NSLog(@"KMEngine - Turning verbose logging on"); + os_log_debug([KMELogs testLog], "KMEngine - Turning verbose logging on"); // In Keyman Engine if "debugMode" is turned on (explicitly) with "English plus Spanish" as the current keyboard and you type "Sentrycrash#KME", // it will force a simulated crash to test reporting to sentry.keyman.com. NSString * kmxName = [[_kmx filePath] lastPathComponent]; - NSLog(@"Sentry - KME: _kmx name = %@", kmxName); + os_log_debug([KMELogs testLog], "Sentry - KME: _kmx name = %{public}@", kmxName); if ([kEasterEggKmxName isEqualToString:kmxName]) { - NSLog(@"Sentry - KME: Preparing to detect Easter egg."); + os_log_debug([KMELogs testLog], "Sentry - KME: Preparing to detect Easter egg."); _easterEggForSentry = [[NSMutableString alloc] init]; } else _easterEggForSentry = nil; } - else - NSLog(@"KMEngine - Turning verbose logging off"); + else { + os_log_debug([KMELogs testLog], "KMEngine - Turning verbose logging off"); + } } - (NSString *)getCoreContextDebug { @@ -103,7 +102,7 @@ - (void)setCoreContextIfNeeded:(NSString *)context { - (void)setCoreOptions:(NSString *)key withValue:(NSString *)value { BOOL success = [self.coreWrapper setOptionsForCore:key value:value]; - [self.coreHelper logDebugMessage:@"setCoreOptions for key: %@, value: %@ succeeded = %@", key, value, success ? @"YES" : @"NO"]; + os_log_debug([KMELogs coreLog], "setCoreOptions for key: %{public}@, value: %{public}@ succeeded = %{public}@", key, value, success ? @"YES" : @"NO"); } /* @@ -118,13 +117,13 @@ - (CoreKeyOutput *)processEvent:(NSEvent *)event { - (void) processPossibleEasterEggCharacterFrom:(NSString *)characters { NSUInteger len = [_easterEggForSentry length]; - NSLog(@"Sentry - KME: Processing character(s): %@", characters); + os_log_debug([KMELogs keyLog], "Sentry - KME: Processing character(s): %{public}@", characters); if ([characters length] == 1 && [characters characterAtIndex:0] == [kEasterEggText characterAtIndex:len]) { NSString *characterToAdd = [kEasterEggText substringWithRange:NSMakeRange(len, 1)]; - NSLog(@"Sentry - KME: Adding character to Easter Egg code string: %@", characterToAdd); + os_log_debug([KMELogs keyLog], "Sentry - KME: Adding character to Easter Egg code string: %{public}@", characterToAdd); [_easterEggForSentry appendString:characterToAdd]; if ([kEasterEggText isEqualToString:_easterEggForSentry]) { - NSLog(@"Sentry - KME: Forcing crash now!"); + os_log_debug([KMELogs keyLog], "Sentry - KME: Forcing crash now!"); // Both of the following approaches do throw an exception that causes control to exit this method, // but at least in my debug builds locally, neither one seems to get picked up by Sentry in a // way that results in a new report on sentry.keyman.com @@ -145,12 +144,10 @@ - (void) processPossibleEasterEggCharacterFrom:(NSString *)characters { // purpose of enabling the engine to force a crash. [(NSObject *)[NSApp delegate] alertShowHelp:[NSAlert alertWithMessageText:@"Forcing an error" defaultButton:nil alternateButton:nil otherButton:nil informativeTextWithFormat:@"Forcing an Easter egg error from KME!"]]; #endif - - NSLog(@"Sentry - KME: You should not be seeing this line!"); } } else if (len > 0) { - NSLog(@"Sentry - KME: Clearing Easter Egg code string."); + os_log_debug([KMELogs keyLog], "Sentry - KME: Clearing Easter Egg code string."); [_easterEggForSentry setString:@""]; } } diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMXFile.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMXFile.m index 6fa222c2b02..2ce2fbfa89d 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMXFile.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMXFile.m @@ -11,6 +11,7 @@ #import "KMCompGroup.h" #import "KMCompKey.h" #import "NSString+XString.h" +#import "KMELogs.h" NSString *const kKMKeyboardNameKey = @"KMKeyboardNameKey"; NSString *const kKMKeyboardVersionKey = @"KMKeyboardVersionKey"; @@ -31,7 +32,7 @@ - (id)initWithFilePath:(NSString *)path { NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path]; if (file == nil) { - //NSLog(@"Failed to open kmx file"); + os_log_error([KMELogs configLog], "Failed to open kmx file"); _filePath = nil; return nil; } @@ -162,7 +163,7 @@ + (NSDictionary *)keyboardInfoFromKmxFile:(NSString *)path { NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path]; if (file == nil) { - //NSLog(@"Failed to open file"); + os_log_error([KMELogs configLog], "Failed to open file"); return nil; } diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KVKFile.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KVKFile.m index 202426d853d..bc9e9f1b058 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KVKFile.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KVKFile.m @@ -8,6 +8,7 @@ #import "KVKFile.h" #import "NKey.h" +#import "KMELogs.h" @implementation KVKFile @@ -21,7 +22,7 @@ - (id)initWithFilePath:(NSString *)path { NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path]; if (file == nil) { - //NSLog(@"Failed to open kvk file"); + os_log_error([KMELogs configLog], "Failed to open kvk file"); _filePath = nil; return nil; } diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/KeyView.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/KeyView.m index fc8029812e4..c1dfa75a87a 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/KeyView.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/KeyView.m @@ -10,7 +10,7 @@ #import "KeyLabel.h" #import "MacVKCodes.h" #import "TimerTarget.h" -#import +#import "KMELogs.h" CGFloat lw = 1.0; CGFloat r = 7.0; @@ -39,10 +39,9 @@ @implementation KeyView @synthesize bgColorRegularKey, bgColorSpecialKey; - (id)initWithFrame:(NSRect)frame { - os_log_t oskKeyLog = os_log_create("org.sil.keyman", "osk-key"); self = [super initWithFrame:frame]; if (self) { - os_log_with_type(oskKeyLog, OS_LOG_TYPE_DEBUG, "KeyView initWithFrame: %{public}@, bounds: %{public}@, default clipsToBounds %{public}@", NSStringFromRect(frame), NSStringFromRect(self.bounds), self.clipsToBounds?@"YES":@"NO"); + os_log_debug([KMELogs oskLog], "KeyView initWithFrame: %{public}@, bounds: %{public}@, default clipsToBounds %{public}@", NSStringFromRect(frame), NSStringFromRect(self.bounds), self.clipsToBounds?@"YES":@"NO"); self.clipsToBounds = true; CGSize size = frame.size; CGFloat x = size.width*0.05; @@ -71,8 +70,7 @@ - (id)initWithFrame:(NSRect)frame { } - (void)drawRect:(NSRect)rect { - os_log_t oskKeyLog = os_log_create("org.sil.keyman", "osk-key"); - os_log_with_type(oskKeyLog, OS_LOG_TYPE_DEBUG, "KeyView drawRect: %{public}@, bounds: %{public}@, keyCode: 0x%lx, caption: %{public}@, label: %{public}@", NSStringFromRect(rect), NSStringFromRect(self.bounds), self.keyCode, self.caption.stringValue, self.label.stringValue); + os_log_debug([KMELogs uiLog], "KeyView drawRect: %{public}@, bounds: %{public}@, keyCode: 0x%lx, caption: %{public}@, label: %{public}@", NSStringFromRect(rect), NSStringFromRect(self.bounds), self.keyCode, self.caption.stringValue, self.label.stringValue); [[self getOpaqueColorWithRed:241 green:242 blue:242] setFill]; NSRectFillUsingOperation(rect, NSCompositingOperationSourceOver); @@ -306,7 +304,7 @@ - (void)startTimerWithTimeInterval:(NSTimeInterval)interval { - (void)stopTimer { @synchronized(self.target) { - //NSLog(@"KeyView TIMER - stopping"); + //os_log_debug([KMELogs uiLog], "KeyView TIMER - stopping"); if (_keyEventTimer != nil) { [_keyEventTimer invalidate]; _keyEventTimer = nil; @@ -316,7 +314,7 @@ - (void)stopTimer { - (void)timerAction:(NSTimer *)timer { @synchronized(self.target) { - //NSLog(@"KeyView TIMER - Fired for key %lu", [self keyCode]); + //os_log_debug([KMELogs uiLog], "KeyView TIMER - Fired for key %lu", [self keyCode]); [self processKeyClick]; if ([timer timeInterval] == delayBeforeRepeating) { diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKKey.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKKey.m index a8840eb4118..d81097d3e2f 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKKey.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKKey.m @@ -7,15 +7,14 @@ // #import "OSKKey.h" -#import +#import "KMELogs.h" @implementation OSKKey - (id)initWithKeyCode:(NSUInteger)keyCode caption:(NSString *)caption scale:(CGFloat)scale { self = [super init]; if (self) { - os_log_t oskKeyLog = os_log_create("org.sil.keyman", "osk-key"); - os_log_with_type(oskKeyLog, OS_LOG_TYPE_DEBUG, "OSKKey initWithKeyCode: 0x%lx, caption: %{public}@, scale: %f", keyCode, caption, scale); + os_log_debug([KMELogs oskLog], "OSKKey initWithKeyCode: 0x%lx, caption: %{public}@, scale: %f", keyCode, caption, scale); _keyCode = keyCode; if (caption == nil) diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m index 2dda9283587..f5154fa76da 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m @@ -12,11 +12,10 @@ #import "MacVKCodes.h" #import "WindowsVKCodes.h" #import "NKey.h" -//#import "KMEngine.h" #import "CoreHelper.h" #include -#import +#import "KMELogs.h" @interface OSKView() @property (nonatomic, strong) NSArray *oskLayout; @@ -33,8 +32,7 @@ @implementation OSKView @synthesize tag; - (id)initWithFrame:(NSRect)frame { - os_log_t oskLog = os_log_create("org.sil.keyman", "osk"); - os_log_with_type(oskLog, OS_LOG_TYPE_DEBUG, "OSKView initWithFrame: %{public}@", NSStringFromRect(frame)); + os_log_debug([KMELogs oskLog], "OSKView initWithFrame: %{public}@", NSStringFromRect(frame)); self = [super initWithFrame:frame]; if (self) { // Custom initialization @@ -45,8 +43,7 @@ - (id)initWithFrame:(NSRect)frame { } - (void)drawRect:(NSRect)rect { - os_log_t oskLog = os_log_create("org.sil.keyman", "osk"); - os_log_with_type(oskLog, OS_LOG_TYPE_DEBUG, "OSKView drawRect: %{public}@", NSStringFromRect(rect)); + os_log_debug([KMELogs uiLog], "OSKView drawRect: %{public}@", NSStringFromRect(rect)); CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] CGContext]; CGContextSetLineJoin(context, kCGLineJoinRound); @@ -104,8 +101,7 @@ - (BOOL)use102ndKey { } - (void)setKvk:(KVKFile *)kvk { - os_log_t oskLog = os_log_create("org.sil.keyman", "osk"); - os_log_with_type(oskLog, OS_LOG_TYPE_DEBUG, "OSKView setKvk, forces keyboard to re-layout"); + os_log_debug([KMELogs oskLog], "OSKView setKvk, forces keyboard to re-layout"); _kvk = kvk; // Force the keyboard to re-layout @@ -116,8 +112,7 @@ - (void)setKvk:(KVKFile *)kvk { } - (void)initOSKKeys { - os_log_t oskLog = os_log_create("org.sil.keyman", "osk"); - os_log_with_type(oskLog, OS_LOG_TYPE_DEBUG, "OSKView initOSKKeys"); + os_log_debug([KMELogs oskLog], "OSKView initOSKKeys"); CGFloat viewWidth = self.frame.size.width; CGFloat viewHeight = self.frame.size.height; CGFloat margin = 2.0; @@ -152,8 +147,7 @@ - (void)initOSKKeys { - (NSArray *)oskLayout { if (_oskLayout == nil) { - os_log_t oskLog = os_log_create("org.sil.keyman", "osk"); - os_log_with_type(oskLog, OS_LOG_TYPE_DEBUG, "oskLayout -> creating new arrays of OSKKey objects"); + os_log_debug([KMELogs oskLog], "oskLayout -> creating new arrays of OSKKey objects"); NSArray *row1 = [NSArray arrayWithObjects: [[OSKKey alloc] initWithKeyCode:MVK_GRAVE caption:@"`" scale:1.0], [[OSKKey alloc] initWithKeyCode:MVK_1 caption:@"1" scale:1.0], @@ -238,8 +232,7 @@ - (NSArray *)oskLayout { - (NSArray *)oskDefaultNKeys { if (_oskDefaultNKeys == nil) { - os_log_t oskLog = os_log_create("org.sil.keyman", "osk"); - os_log_with_type(oskLog, OS_LOG_TYPE_DEBUG, "oskDefaultNKeys -> creating new arrays of default number OSKKey objects"); + os_log_debug([KMELogs oskLog], "oskDefaultNKeys -> creating new arrays of default number OSKKey objects"); NSMutableArray *defNKeys = [[NSMutableArray alloc] initWithCapacity:0]; // row 1 @@ -410,8 +403,7 @@ - (void)resetOSK { } - (void)resizeOSKLayout { - os_log_t oskLog = os_log_create("org.sil.keyman", "osk"); - os_log_with_type(oskLog, OS_LOG_TYPE_DEBUG, "OSKView resizeOSKLayout, removing all superviews"); + os_log_debug([KMELogs oskLog], "OSKView resizeOSKLayout, removing all superviews"); [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; [self initOSKKeys]; } @@ -419,8 +411,7 @@ - (void)resizeOSKLayout { - (void)keyAction:(id)sender { KeyView *keyView = (KeyView *)sender; NSUInteger keyCode = [keyView.key keyCode]; - os_log_t oskLog = os_log_create("org.sil.keyman", "osk"); - os_log_with_type(oskLog, OS_LOG_TYPE_DEBUG, "OSKView keyAction keyCode: 0x%lx", keyCode); + os_log_debug([KMELogs oskLog], "OSKView keyAction keyCode: 0x%lx", keyCode); if (keyCode < 0x100) { NSRunningApplication *app = NSWorkspace.sharedWorkspace.frontmostApplication; pid_t processId = app.processIdentifier; @@ -459,8 +450,7 @@ - (void)keyAction:(id)sender { } - (void)handleKeyEvent:(NSEvent *)event { - os_log_t oskLog = os_log_create("org.sil.keyman", "osk"); - os_log_with_type(oskLog, OS_LOG_TYPE_DEBUG, "OSKView handleKeyEvent event.type: %lu", event.type); + os_log_debug([KMELogs oskLog], "OSKView handleKeyEvent event.type: %lu", event.type); NSView *view = [self viewWithTag:event.keyCode|0x1000]; if (view == nil || ![view isKindOfClass:[KeyView class]]) return; diff --git a/mac/KeymanEngine4Mac/KeymanEngine4MacTests/CoreWrapperTests.m b/mac/KeymanEngine4Mac/KeymanEngine4MacTests/CoreWrapperTests.m index 6b6beb3f69d..aa0463c7cf2 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4MacTests/CoreWrapperTests.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4MacTests/CoreWrapperTests.m @@ -15,6 +15,7 @@ #import "CoreTestStaticHelperMethods.h" #import "CoreAction.h" #import "MacVKCodes.h" +#import "KMELogs.h" @interface CoreWrapperTests : XCTestCase @@ -28,8 +29,8 @@ @implementation CoreWrapperTests + (void)setUp { NSString *khmerKeyboardPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"khmer_angkor.kmx"]; - NSLog(@"mockKmxFilePath = %@\n", mockKmxFilePath); - + os_log_debug([KMELogs testLog], "mockKmxFilePath = %@\n", mockKmxFilePath); + mockWrapper = [[CoreWrapper alloc] initWithHelper: [CoreTestStaticHelperMethods helper] kmxFilePath:mockKmxFilePath]; } diff --git a/mac/KeymanEngine4Mac/KeymanEngine4MacTests/KMEngineTests.m b/mac/KeymanEngine4Mac/KeymanEngine4MacTests/KMEngineTests.m index 275b73911dd..290f30f302b 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4MacTests/KMEngineTests.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4MacTests/KMEngineTests.m @@ -11,6 +11,7 @@ #import "KeymanEngineTestsStaticHelperMethods.h" #import "KMEngine.h" #import "CoreAction.h" +#import "KMELogs.h" @interface KMEngineTests : XCTestCase @end @@ -106,7 +107,7 @@ - (void)testprocessEvent_eventForLowercaseA_ReturnsCharacterActionWithExpectedCh KMEngine *engine = [[KMEngine alloc] initWithKMX:kmxFile context:@"" verboseLogging:YES]; NSEvent *event = [NSEvent keyEventWithType:NSEventTypeKeyDown location:NSMakePoint(0, 0) modifierFlags:0 timestamp:0 windowNumber:0 context:nil characters:@"a" charactersIgnoringModifiers:@"a" isARepeat:NO keyCode:kVK_ANSI_A]; CoreKeyOutput *output = [engine processEvent:event]; - NSLog(@"output = %@", output); + os_log_debug([KMELogs testLog], "output = %{public}@", output); XCTAssert(output.hasTextToInsert, @"output has text to insert"); XCTAssert([output.textToInsert isEqualToString:@"\u00C7"], @"Expected capital C cedille (U+00C7)"); } @@ -171,7 +172,7 @@ - (void)testprocessEvent_eventForUnshiftedNumeralWithCipherMusicKmx_ReturnsChara NSString * numeral = [NSString stringWithFormat:@"%d", i]; NSEvent *event = [NSEvent keyEventWithType:NSEventTypeKeyDown location:NSMakePoint(0, 0) modifierFlags:0 timestamp:0 windowNumber:0 context:nil characters:numeral charactersIgnoringModifiers:numeral isARepeat:NO keyCode:ansiCode]; NSArray *actions = [engine processEvent:event]; - NSLog(@"testprocessEvent, actions[0]: %@, expected numeral: %@", actions[0], numeral); + os_log_debug([KMELogs testLog], "testprocessEvent, actions[0]: %{public}@, expected numeral: %{public}@", actions[0], numeral); XCTAssert(actions.count == 1, @"Expected 1 action"); CoreAction *action = actions[0]; XCTAssert([action isCharacter], @"Expected CharacterAction"); @@ -287,14 +288,14 @@ - (void)testprocessEvent_eventForAWithModifiers_ReturnsCharacterActionWithExpect if (modifiers[i] & (LEFT_ALT_FLAG | RIGHT_ALT_FLAG)) characters = [characters stringByAppendingString:@"\u030A"]; - NSLog(@"Test case: %lu", (NSUInteger)modifiers[i]); + os_log_debug([KMELogs testLog], "Test case: %lu", (NSUInteger)modifiers[i]); // NOTE: 'a' happens to be keyCode 0 (see initVirtualKeyMapping in CoreHelper) NSEvent *event = [NSEvent keyEventWithType:NSEventTypeKeyDown location:NSMakePoint(0, 0) modifierFlags:modifiers[i] timestamp:0 windowNumber:0 context:nil characters:characters charactersIgnoringModifiers:charactersIgnoringModifiers isARepeat:NO keyCode:0]; NSString * keyCombination = [names[i] stringByAppendingFormat:@" %@", charactersIgnoringModifiers]; CoreKeyOutput *coreKeyOutput = [engine processEvent:event]; XCTAssert(coreKeyOutput.hasTextToInsert, @"hasTextToInsert for %@", keyCombination); NSString *output = coreKeyOutput.textToInsert; - NSLog(@"output = %@", output); + os_log_debug([KMELogs testLog], "output = %{public}@", output); switch (modifiers[i]) { case LEFT_SHIFT_FLAG: case RIGHT_SHIFT_FLAG: @@ -358,13 +359,13 @@ - (void)testprocessEvent_eventForSWithModifiers_ReturnsCharacterActionWithExpect characters = @"ß"; } - NSLog(@"Test case: %lu", (NSUInteger)modifiers[i]); + os_log_debug([KMELogs testLog], "Test case: %lu", (NSUInteger)modifiers[i]); // NOTE: 's' happens to be keyCode 1 (see initVirtualKeyMapping in CoreHelper) NSEvent *event = [NSEvent keyEventWithType:NSEventTypeKeyDown location:NSMakePoint(0, 0) modifierFlags:modifiers[i] timestamp:0 windowNumber:0 context:nil characters:characters charactersIgnoringModifiers:charactersIgnoringModifiers isARepeat:NO keyCode:1]; NSString * keyCombination = [names[i] stringByAppendingFormat:@" %@", charactersIgnoringModifiers]; CoreKeyOutput *coreKeyOutput = [engine processEvent:event]; NSString *output = coreKeyOutput.textToInsert; - NSLog(@"output = %@", output); + os_log_debug([KMELogs testLog], "output = %@", output); switch (modifiers[i]) { case LEFT_SHIFT_FLAG: case RIGHT_SHIFT_FLAG: @@ -548,7 +549,7 @@ - (void)testCoreProcessEvent_backspaceElNuerEmptyContext_PassesThrough { KMEngine *engine = [[KMEngine alloc] initWithKMX:kmxFile context:@"" verboseLogging:YES]; NSEvent *event = [NSEvent keyEventWithType:NSEventTypeKeyDown location:NSMakePoint(0, 0) modifierFlags:0 timestamp:0 windowNumber:0 context:nil characters:@"\b" charactersIgnoringModifiers:@"\b" isARepeat:NO keyCode:kVK_Delete]; CoreKeyOutput *output = [engine processEvent:event]; - NSLog(@"output: %@", output); + os_log_debug([KMELogs testLog], "output = %{public}@", output); XCTAssert(!output.hasTextToInsert, @"expected to insert nothing"); XCTAssert(!output.hasCodePointsToDelete, @"expected to delete nothing"); XCTAssert(output.emitKeystroke, @"expected to emit key"); @@ -559,7 +560,7 @@ - (void)testCoreProcessEvent_backspaceElNuerWithContext_EmptiesContextReturnsDel KMEngine *engine = [[KMEngine alloc] initWithKMX:kmxFile context:@"ɣ" verboseLogging:YES]; NSEvent *event = [NSEvent keyEventWithType:NSEventTypeKeyDown location:NSMakePoint(0, 0) modifierFlags:0 timestamp:0 windowNumber:0 context:nil characters:@"\b" charactersIgnoringModifiers:@"\b" isARepeat:NO keyCode:kVK_Delete]; CoreKeyOutput *output = [engine processEvent:event]; - NSLog(@"output: %@", output); + os_log_debug([KMELogs testLog], "output = %{public}@", output); XCTAssert(output.codePointsToDeleteBeforeInsert == 1, @"Expected output to delete one code point"); XCTAssert(!output.hasTextToInsert, @"expected to insert nothing"); NSString *context = engine.getCoreContextDebug;