From b9ef6d7bb5d483d03a9600132f9d33286f0600c7 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 27 Feb 2024 17:41:07 +0100 Subject: [PATCH 01/13] fix(linux): Replace deprecated `pkg_resources` module with `packaging.version` Fixes #10850. --- linux/debian/control | 1 + linux/keyman-config/keyman_config/install_kmp.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/linux/debian/control b/linux/debian/control index 5e4ca9870c..910db9caf5 100644 --- a/linux/debian/control +++ b/linux/debian/control @@ -30,6 +30,7 @@ Build-Depends: python3-lxml, python3-magic, python3-numpy, + python3-packaging, python3-pil, python3-pip, python3-qrcode, diff --git a/linux/keyman-config/keyman_config/install_kmp.py b/linux/keyman-config/keyman_config/install_kmp.py index 06399c5304..d44a84cb97 100755 --- a/linux/keyman-config/keyman_config/install_kmp.py +++ b/linux/keyman-config/keyman_config/install_kmp.py @@ -3,8 +3,8 @@ import json import logging import os +import packaging.version import zipfile -from pkg_resources import parse_version from enum import Enum from shutil import rmtree @@ -149,7 +149,7 @@ class InstallKmp(): fileVersion = secure_lookup(system, 'fileVersion') if not fileVersion: fileVersion = '7.0' - if parse_version(fileVersion) > parse_version(__version__): + if packaging.version.parse(fileVersion) > packaging.version.parse(__version__): logging.error("install_kmp.py: error: %s requires a newer version of Keyman (%s)", inputfile, fileVersion) rmtree(self.packageDir) From 10b60006bd1fae713cc93b2e6249d601f0aa4785 Mon Sep 17 00:00:00 2001 From: sgschantz Date: Thu, 8 Feb 2024 14:12:27 +0700 Subject: [PATCH 02/13] added lowLevelBackspaceCount, eliminated redundant keymanCode 0xFF event --- .../Keyman4MacIM/KMInputMethodAppDelegate.m | 11 +++- .../Keyman4MacIM/KMInputMethodEventHandler.m | 58 +++++++++++++------ mac/Keyman4MacIM/Keyman4MacIM/KeySender.m | 44 +++----------- 3 files changed, 54 insertions(+), 59 deletions(-) diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m index 301164db1a..b17034116f 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m @@ -335,9 +335,14 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef // of events) if(sysEvent.keyCode == kVK_Delete && appDelegate.inputController != nil) { NSLog(@"Event tap handling kVK_Delete."); - [appDelegate.inputController handleBackspace:sysEvent]; + [appDelegate.inputController handleBackspace:sysEvent]; + } else if(sysEvent.keyCode == kVK_Delete) { + NSLog(@"Event tap not handling kVK_Delete, appDelegate.inputController = %@", appDelegate.inputController); + } + if(sysEvent.keyCode == 255) { + NSLog(@"*** kKeymanEventKeyCode = 0xFF"); } else { - NSLog(@"Event tap not handling kVK_Delete, appDelegate.inputController = %@", appDelegate.inputController); + NSLog(@"*** other: %d(%x)", (char) sysEvent.keyCode, sysEvent.keyCode); } switch(sysEvent.keyCode) { @@ -443,7 +448,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef return; } - // TODO pass array instead of making repeated calls + // 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); diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m index d5d82ab6e0..d108713a81 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m @@ -11,14 +11,13 @@ #import /* For kVK_ constants. */ #import "KeySender.h" #import "TextApiCompliance.h" - @import Sentry; @interface KMInputMethodEventHandler () @property (nonatomic, retain) KeySender* keySender; @property (nonatomic, retain) TextApiCompliance* apiCompliance; @property NSUInteger generatedBackspaceCount; -@property BOOL backspaceHandledLowLevel; +@property NSUInteger lowLevelBackspaceCount; @property (nonatomic, retain) NSString* clientApplicationId; @property NSString *queuedText; @property BOOL contextChanged; @@ -63,7 +62,9 @@ NSRange _previousSelRange; _keySender = [[KeySender alloc] init]; _clientApplicationId = clientAppId; _generatedBackspaceCount = 0; - + _lowLevelBackspaceCount = 0; + _queuedText = nil; + //BOOL legacy = [self isClientAppLegacy:clientAppId]; // In Xcode, if Keyman is the active IM and is in "debugMode" and "English plus Spanish" is @@ -76,10 +77,13 @@ NSRange _previousSelRange; else _easterEggForSentry = nil; + /* // For the Atom editor, this isn't really true (the context CAN change unexpectedly), but we can't get // the context, so we pretend/hope it won't. BOOL selectionCanChangeUnexpectedly = (![clientAppId isEqual: @"com.github.atom"]); return [self initWithLegacyMode:self.apiCompliance.mustBackspaceUsingEvents clientSelectionCanChangeUnexpectedly:selectionCanChangeUnexpectedly]; + */ + return [self initWithLegacyMode:NO clientSelectionCanChangeUnexpectedly:NO]; } - (void)switchToLegacyMode { @@ -265,7 +269,7 @@ NSRange _previousSelRange; } /** - handleBackspace: handles generated for a subset of non-compliant apps (such as Adobe apps) that do + handleBackspace: handles generated backspaces for a subset of non-compliant apps (such as Adobe apps) that do not support replacing text with the insertText API but also intercept events so that we do not see them in handleEvent. Other apps, such as Word, show the event both in the low level EventTap and in the normal IM handleEvent. Thus, we set a flag after @@ -275,16 +279,14 @@ NSRange _previousSelRange; */ - (void)handleBackspace:(NSEvent *)event { [self.appDelegate logDebugMessage:@"KMInputMethodEventHandler handleBackspace, event = %@", event]; - NSLog(@" backspaceHandledLowLevel: %d, generatedBackspaceCount: %lu", _backspaceHandledLowLevel, (unsigned long)_generatedBackspaceCount); - self.backspaceHandledLowLevel = NO; - + if (self.generatedBackspaceCount > 0) { self.generatedBackspaceCount--; - self.backspaceHandledLowLevel = YES; + self.lowLevelBackspaceCount++; // if we just encountered the last backspace, then send event to insert queued text - if (self.generatedBackspaceCount == 0) { - [self performSelector:@selector(triggerInsertQueuedText:) withObject:event afterDelay:kQueuedTextEventDelayInSeconds]; + if ((self.generatedBackspaceCount == 0) && (self.queuedText.length > 0)) { + [self performSelector:@selector(triggerInsertQueuedText:) withObject:event afterDelay:kQueuedTextEventDelayInSeconds]; } } } @@ -358,16 +360,17 @@ NSRange _previousSelRange; // 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"]; + [self.appDelegate logDebugMessage:@"handleEvent, handling kKeymanEventKeyCode"]; [self insertQueuedText: event client:sender]; return YES; } - + // 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.backspaceHandledLowLevel)) { + if((event.keyCode == kVK_Delete) && (self.lowLevelBackspaceCount > 0)) { [self.appDelegate logDebugMessage:@"handleEvent, allowing generated backspace to pass through"]; - self.backspaceHandledLowLevel = NO; + self.lowLevelBackspaceCount--; + // return NO to pass through to client app return NO; } @@ -482,18 +485,34 @@ NSRange _previousSelRange; } 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"]; + [self.appDelegate logDebugMessage:@"KXMInputMethodHandler applyOutputToTextInputClient, delete only scenario with passthrough"]; handledEvent = NO; } else { [self.appDelegate logDebugMessage:@"KXMInputMethodHandler applyOutputToTextInputClient, delete only scenario"]; [self sendEvents:event forOutput:output]; } } else if (output.isDeleteAndInsertScenario) { + /* + // needs further testing to fix backspace bug in google docs (without breaking other apps) + // 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); + if (output.codePointsToDeleteBeforeInsert == 0) { + // no backspace events needed + [self insertAndReplaceTextForOutput:output client:client]; + } else { + // still need at least one backspace event + [self sendEvents:event forOutput:output]; + } + } + */ + if (self.apiCompliance.mustBackspaceUsingEvents) { [self.appDelegate logDebugMessage:@"KXMInputMethodHandler 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"]; + [self.appDelegate logDebugMessage:@"KXMInputMethodHandler applyOutputToTextInputClient, delete and insert scenario with insert API"]; // directly insert text and handle backspaces by using replace [self insertAndReplaceTextForOutput:output client:client]; } @@ -585,15 +604,16 @@ NSRange _previousSelRange; } -(void)sendEvents:(NSEvent *)event forOutput:(CoreKeyOutput*)output { - [self.appDelegate logDebugMessage:@"sendEvents called"]; - + [self.appDelegate logDebugMessage:@"sendEvents called, output = %@", output]; + _sourceForGeneratedEvent = CGEventCreateSourceFromEvent([event CGEvent]); self.generatedBackspaceCount = output.codePointsToDeleteBeforeInsert; + if (output.hasCodePointsToDelete) { for (int i = 0; i < output.codePointsToDeleteBeforeInsert; i++) { - [self.appDelegate logDebugMessage:@"sendEvents queueing backspace"]; + [self.appDelegate logDebugMessage:@"sendEvents sending backspace key event"]; [self.keySender sendBackspaceforEventSource:_sourceForGeneratedEvent]; } } diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KeySender.m b/mac/Keyman4MacIM/Keyman4MacIM/KeySender.m index 9c1bcead13..74092ea26f 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KeySender.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KeySender.m @@ -29,33 +29,6 @@ const CGKeyCode kKeymanEventKeyCode = 0xFF; return self; } -- (void)sendKeyDown:(NSUInteger)keyCode forSourceEvent:(NSEvent *)event includeKeyUp:(BOOL)includeKeyUpEvent { - // Returns the frontmost app, which is the app that receives key events. - NSRunningApplication *app = NSWorkspace.sharedWorkspace.frontmostApplication; - pid_t processId = app.processIdentifier; - NSString *bundleId = app.bundleIdentifier; - - [self.appDelegate logDebugMessage:@"sendKeyDown keyCode %lu to app %@ with pid %d", (unsigned long)keyCode, bundleId, processId]; - - if (keyCode < 0x100) { - CGEventRef cgevent = [event CGEvent]; - - // use source from event to generate new event - CGEventSourceRef source = CGEventCreateSourceFromEvent(cgevent); - CGEventRef keyDownEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode)keyCode, true); - - // TODO: add version check - CGEventPostToPid(processId, keyDownEvent); - CFRelease(keyDownEvent); - - if (includeKeyUpEvent) { - CGEventRef keyUpEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode)keyCode, false); - CGEventPostToPid(processId, keyUpEvent); - CFRelease(keyUpEvent); - } - } -} - - (void)sendBackspaceforEventSource:(CGEventSourceRef)eventSource { [self.appDelegate logDebugMessage:@"KeySender sendBackspaceforEventSource"]; @@ -90,23 +63,20 @@ const CGKeyCode kKeymanEventKeyCode = 0xFF; - (void)sendKeymanKeyCodeForEvent:(NSEvent *)event { [self.appDelegate logDebugMessage:@"KeySender sendKeymanKeyCodeForEvent"]; - [self sendKeyDown:kKeymanEventKeyCode forSourceEvent:event includeKeyUp:NO]; - + ProcessSerialNumber psn; + // Returns the frontmost app, which is the app that receives key events. NSRunningApplication *app = NSWorkspace.sharedWorkspace.frontmostApplication; pid_t processId = app.processIdentifier; NSString *bundleId = app.bundleIdentifier; + GetProcessForPID(processId, &psn); [self.appDelegate logDebugMessage:@"sendKeymanKeyCodeForEvent keyCode %lu to app %@ with pid %d", (unsigned long)kKeymanEventKeyCode, bundleId, processId]; - CGEventRef cgevent = [event CGEvent]; - - // use source from event to generate new event - CGEventSourceRef source = CGEventCreateSourceFromEvent(cgevent); - CGEventRef keyDownEvent = CGEventCreateKeyboardEvent(source, kKeymanEventKeyCode, true); - - // TODO: add version check - CGEventPostToPid(processId, keyDownEvent); + // use nil as source, as this generated event is not directly tied to the originating event + CGEventRef keyDownEvent = CGEventCreateKeyboardEvent(nil, kKeymanEventKeyCode, true); + + CGEventPostToPSN(&psn, keyDownEvent); CFRelease(keyDownEvent); // this is not a real keycode, so we do not need a key up event From 07bf055edb64f06e98af92a508bb19f3f7e68529 Mon Sep 17 00:00:00 2001 From: sgschantz Date: Wed, 28 Feb 2024 13:25:03 +0700 Subject: [PATCH 03/13] mostly deletions of obsolete pre-core code --- .../Keyman4MacIM.xcodeproj/project.pbxproj | 24 +-- .../Keyman4MacIM/KMInputController.m | 18 --- .../KMInputMethodBrowserClientEventHandler.h | 20 --- .../KMInputMethodBrowserClientEventHandler.m | 108 -------------- ...MethodBrowserClientEventHandlerProtected.h | 18 --- .../Keyman4MacIM/KMInputMethodEventHandler.m | 140 +----------------- .../KMInputMethodEventHandlerProtected.h | 38 ----- .../KMInputMethodSafariClientEventHandler.h | 17 --- .../KMInputMethodSafariClientEventHandler.m | 86 ----------- ...nputMethodBrowserClientEventHandlerTests.m | 58 -------- 10 files changed, 6 insertions(+), 521 deletions(-) delete mode 100644 mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodBrowserClientEventHandler.h delete mode 100644 mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodBrowserClientEventHandler.m delete mode 100644 mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodBrowserClientEventHandlerProtected.h delete mode 100644 mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodSafariClientEventHandler.h delete mode 100644 mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodSafariClientEventHandler.m delete mode 100644 mac/Keyman4MacIM/KeymanTests/KMInputMethodBrowserClientEventHandlerTests.m diff --git a/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj b/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj index 8574f5c6da..45704f455e 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj +++ b/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj @@ -75,18 +75,14 @@ E213601E2142D7C000A043B7 /* keyman-88.png in Resources */ = {isa = PBXBuildFile; fileRef = E213601D2142D7BF00A043B7 /* keyman-88.png */; }; E21799051FC5B7BC00F2D66A /* KMInputMethodEventHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = E21799041FC5B7BC00F2D66A /* KMInputMethodEventHandler.m */; }; E21E645820C04EA8000D6274 /* logo.png in Resources */ = {isa = PBXBuildFile; fileRef = E21E645720C04EA7000D6274 /* logo.png */; }; - E22020F6200506F300B74FAC /* KMInputMethodSafariClientEventHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = E22020F5200506F300B74FAC /* KMInputMethodSafariClientEventHandler.m */; }; E23380FB21407AA100B90591 /* SILInBlue76.png in Resources */ = {isa = PBXBuildFile; fileRef = E23380FA21407AA100B90591 /* SILInBlue76.png */; }; E240F599202DED740000067D /* KMPackage.m in Sources */ = {isa = PBXBuildFile; fileRef = E240F598202DED740000067D /* KMPackage.m */; }; - E24C79EA1FFFCC7500D8E46F /* KMInputMethodBrowserClientEventHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = E24C79E91FFFCC7500D8E46F /* KMInputMethodBrowserClientEventHandler.m */; }; E2585A7F20DD6C3C00CBB994 /* KMMethodEventHandlerTests.kmx in Resources */ = {isa = PBXBuildFile; fileRef = E2585A7E20DD6C3C00CBB994 /* KMMethodEventHandlerTests.kmx */; }; E2585A8120DD7CF100CBB994 /* TestAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E2585A8020DD7CF100CBB994 /* TestAppDelegate.m */; }; E27BA9D32020D8BF00D273E7 /* SimpleTest.kmx in Resources */ = {isa = PBXBuildFile; fileRef = E27BA9D22020D8BF00D273E7 /* SimpleTest.kmx */; }; E28914D32024D1B80048E71E /* KeymanEngine4Mac.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 984C2B211A79DF1B0023F89D /* KeymanEngine4Mac.framework */; }; - E28914D52024E3DF0048E71E /* KMInputMethodBrowserClientEventHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = E24C79E91FFFCC7500D8E46F /* KMInputMethodBrowserClientEventHandler.m */; }; E28914D62024E4010048E71E /* KMInputMethodEventHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = E21799041FC5B7BC00F2D66A /* KMInputMethodEventHandler.m */; }; E28914D72024E6220048E71E /* KeymanEngine4Mac.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 984C2B211A79DF1B0023F89D /* KeymanEngine4Mac.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - E29F22F4201A59B1005EA234 /* KMInputMethodBrowserClientEventHandlerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E29F22F3201A59B1005EA234 /* KMInputMethodBrowserClientEventHandlerTests.m */; }; E2D5529D20DD8E0200D77CFB /* LegacyTestClient.m in Sources */ = {isa = PBXBuildFile; fileRef = E2D5529C20DD8E0200D77CFB /* LegacyTestClient.m */; }; F9B9814A51575496B5DA2948 /* Pods_KeymanTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A71FD8BA8404531DFBD861B6 /* Pods_KeymanTests.framework */; }; /* End PBXBuildFile section */ @@ -357,14 +353,9 @@ E21799031FC5B74D00F2D66A /* KMInputMethodEventHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KMInputMethodEventHandler.h; sourceTree = ""; }; E21799041FC5B7BC00F2D66A /* KMInputMethodEventHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KMInputMethodEventHandler.m; sourceTree = ""; }; E21E645720C04EA7000D6274 /* logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = logo.png; path = Keyman4MacIM/KMConfiguration/logo.png; sourceTree = SOURCE_ROOT; }; - E22020F3200505EF00B74FAC /* KMInputMethodSafariClientEventHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KMInputMethodSafariClientEventHandler.h; sourceTree = ""; }; - E22020F5200506F300B74FAC /* KMInputMethodSafariClientEventHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KMInputMethodSafariClientEventHandler.m; sourceTree = ""; }; - E22020F920050D6300B74FAC /* KMInputMethodBrowserClientEventHandlerProtected.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KMInputMethodBrowserClientEventHandlerProtected.h; sourceTree = ""; }; E23380FA21407AA100B90591 /* SILInBlue76.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SILInBlue76.png; path = Keyman4MacIM/Images/SILInBlue76.png; sourceTree = SOURCE_ROOT; }; E240F597202DED300000067D /* KMPackage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KMPackage.h; sourceTree = ""; }; E240F598202DED740000067D /* KMPackage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KMPackage.m; sourceTree = ""; }; - E24C79E91FFFCC7500D8E46F /* KMInputMethodBrowserClientEventHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KMInputMethodBrowserClientEventHandler.m; sourceTree = ""; }; - E24C79EB1FFFCE3000D8E46F /* KMInputMethodBrowserClientEventHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KMInputMethodBrowserClientEventHandler.h; sourceTree = ""; }; E24C79EC1FFFEA6B00D8E46F /* KMInputMethodEventHandlerProtected.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KMInputMethodEventHandlerProtected.h; sourceTree = ""; }; E2585A7E20DD6C3C00CBB994 /* KMMethodEventHandlerTests.kmx */ = {isa = PBXFileReference; lastKnownFileType = file; path = KMMethodEventHandlerTests.kmx; sourceTree = ""; }; E2585A8020DD7CF100CBB994 /* TestAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestAppDelegate.m; sourceTree = ""; }; @@ -372,7 +363,6 @@ E27BA9CD2020322000D273E7 /* OCMock.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OCMock.framework; path = ../Carthage/Build/Mac/OCMock.framework; sourceTree = ""; }; E27BA9D22020D8BF00D273E7 /* SimpleTest.kmx */ = {isa = PBXFileReference; lastKnownFileType = file; path = SimpleTest.kmx; sourceTree = ""; }; E29F22F1201A59B1005EA234 /* KeymanTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KeymanTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - E29F22F3201A59B1005EA234 /* KMInputMethodBrowserClientEventHandlerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KMInputMethodBrowserClientEventHandlerTests.m; sourceTree = ""; }; E29F22F5201A59B2005EA234 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E2C92D4720B46CEA00742A7D /* KeymanEngine4Mac.framework.dSYM */ = {isa = PBXFileReference; lastKnownFileType = wrapper.dsym; name = KeymanEngine4Mac.framework.dSYM; path = Keyman4MacIM/Frameworks/KeymanEngine4Mac.framework.dSYM; sourceTree = ""; }; E2D5529B20DD8D6100D77CFB /* LegacyTestClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LegacyTestClient.h; sourceTree = ""; }; @@ -569,11 +559,6 @@ 298D09F62A1F4533006B9DFE /* TextApiCompliance.h */, 298D09F52A1F4533006B9DFE /* TextApiCompliance.m */, E24C79EC1FFFEA6B00D8E46F /* KMInputMethodEventHandlerProtected.h */, - E22020F920050D6300B74FAC /* KMInputMethodBrowserClientEventHandlerProtected.h */, - E24C79EB1FFFCE3000D8E46F /* KMInputMethodBrowserClientEventHandler.h */, - E22020F3200505EF00B74FAC /* KMInputMethodSafariClientEventHandler.h */, - E24C79E91FFFCC7500D8E46F /* KMInputMethodBrowserClientEventHandler.m */, - E22020F5200506F300B74FAC /* KMInputMethodSafariClientEventHandler.m */, 98E672961B532DE000DBDE2F /* KMKeyboardHelpWindow */, 989C9C141A7876DE00A20425 /* MainMenu.xib */, 984B8F3E1AF1C2F400E096A8 /* OnScreenKeyboard */, @@ -689,7 +674,6 @@ children = ( E2585A7E20DD6C3C00CBB994 /* KMMethodEventHandlerTests.kmx */, E27BA9D22020D8BF00D273E7 /* SimpleTest.kmx */, - E29F22F3201A59B1005EA234 /* KMInputMethodBrowserClientEventHandlerTests.m */, E29F22F5201A59B2005EA234 /* Info.plist */, E2585A8220DD7D3F00CBB994 /* TestAppDelegate.h */, E2585A8020DD7CF100CBB994 /* TestAppDelegate.m */, @@ -997,8 +981,6 @@ 9836B3721AE5F11D00780482 /* unzip.c in Sources */, 296FE2FC275DD21600F46898 /* KMPackageReader.m in Sources */, 9832472E1A9EABC70010B90C /* KMConfigColumn1CellView.m in Sources */, - E22020F6200506F300B74FAC /* KMInputMethodSafariClientEventHandler.m in Sources */, - E24C79EA1FFFCC7500D8E46F /* KMInputMethodBrowserClientEventHandler.m in Sources */, 297A501928DF4D360074EB1B /* PrivacyConsent.m in Sources */, 98FE105E1B4DE8F400525F54 /* NSWindow+SuppMethods.m in Sources */, 9836B3741AE5F11D00780482 /* ZipArchive.mm in Sources */, @@ -1022,8 +1004,6 @@ 2999C69929D3E4CE006366F5 /* InputMethodTests.m in Sources */, E211769D20E182DD00F8065D /* NoContextTestClient.m in Sources */, E2D5529D20DD8E0200D77CFB /* LegacyTestClient.m in Sources */, - E29F22F4201A59B1005EA234 /* KMInputMethodBrowserClientEventHandlerTests.m in Sources */, - E28914D52024E3DF0048E71E /* KMInputMethodBrowserClientEventHandler.m in Sources */, E21176A020E18C5200F8065D /* AppleCompliantTestClient.m in Sources */, E2585A8120DD7CF100CBB994 /* TestAppDelegate.m in Sources */, E28914D62024E4010048E71E /* KMInputMethodEventHandler.m in Sources */, @@ -1424,7 +1404,7 @@ "@loader_path/../Frameworks", "@loader_path/Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.7; + MACOSX_DEPLOYMENT_TARGET = 10.10; PRODUCT_BUNDLE_IDENTIFIER = org.sil.consoleTestbed.KeymanTests; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1458,7 +1438,7 @@ "@executable_path/../Frameworks", "@loader_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.7; + MACOSX_DEPLOYMENT_TARGET = 10.10; PRODUCT_BUNDLE_IDENTIFIER = org.sil.consoleTestbed.KeymanTests; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputController.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputController.m index 9b6ee2f5b2..8ba6966dab 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputController.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputController.m @@ -8,8 +8,6 @@ #import "KMInputController.h" #import "KMInputMethodEventHandler.h" -#import "KMInputMethodBrowserClientEventHandler.h" -#import "KMInputMethodSafariClientEventHandler.h" #import "KMOSVersion.h" #include /* For kVK_ constants. */ @@ -83,22 +81,6 @@ NSMutableArray *servers; NSLog(@"activateServer, new active app: '%@', sender %@", clientAppId, sender); } - // TODO: uncomment? commented the browser cases to see how they work with core code - /* - // Most things in Safari work well using the normal way, but Google Docs doesn't. - if ([clientAppId isEqual: @"com.apple.Safari"]) { - _eventHandler = [[KMInputMethodSafariClientEventHandler alloc] init]; - } - else if ([clientAppId isEqual: @"org.mozilla.firefox"] || - [clientAppId isEqual: @"com.google.Chrome"]) { - _eventHandler = [[KMInputMethodBrowserClientEventHandler alloc] init]; - } - else { - // We cache the client for use with events sourced from the low level tap - // where we don't necessarily have any access to the current client. - _eventHandler = [[KMInputMethodEventHandler alloc] initWithClient:clientAppId client:sender]; - } -*/ _eventHandler = [[KMInputMethodEventHandler alloc] initWithClient:clientAppId client:sender]; } diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodBrowserClientEventHandler.h b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodBrowserClientEventHandler.h deleted file mode 100644 index f04233322b..0000000000 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodBrowserClientEventHandler.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// KMInputMethodBrowserClientEventHandler.h -// Keyman4MacIM -// This class is used for browser clients because certain javascript-based websites, such as Google Docs) do -// not properly deal with calls to insertText calls that replace a range of characters. So for these "legacy" -// apps, we post one or more deletes (i.e., backspace), followed by a special code that tells us we're now -// ready to insert the composed text. -// -// Created by tom on 1/5/18. -// Copyright © 2018 SIL International. All rights reserved. -// - -#ifndef KMInputMethodBrowserClientEventHandler_h -#define KMInputMethodBrowserClientEventHandler_h -#import "KMInputMethodEventHandler.h" - -@interface KMInputMethodBrowserClientEventHandler : KMInputMethodEventHandler -@end - -#endif /* KMInputMethodBrowserClientEventHandler_h */ diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodBrowserClientEventHandler.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodBrowserClientEventHandler.m deleted file mode 100644 index efef3e4aef..0000000000 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodBrowserClientEventHandler.m +++ /dev/null @@ -1,108 +0,0 @@ -// -// KMInputMethodBrowserClientEventHandler.m -// Keyman -// -// Created by tom on 1/5/18. -// Copyright © 2018 SIL International. All rights reserved. -// - -#import "KMInputMethodBrowserClientEventHandler.h" -#import "KMInputMethodEventHandlerProtected.h" -#import "KMInputMethodBrowserClientEventHandlerProtected.h" - -@implementation KMInputMethodBrowserClientEventHandler - -// Because Google Docs can't report its context in any of the browsers (Safari, Chrome, Firefox) and Word sometimes -// has trouble doing this in Chrome, we want to try to detect it so each browser can respond appropriately. -NSUInteger _failuresToRetrieveExpectedContext; - -- (instancetype)init { - return [self initWithLegacyMode:YES clientSelectionCanChangeUnexpectedly:YES]; -} - -- (instancetype)initWithLegacyMode:(BOOL)legacy clientSelectionCanChangeUnexpectedly:(BOOL) flagClientSelectionCanChangeUnexpectedly { - self = [super initWithLegacyMode:legacy clientSelectionCanChangeUnexpectedly: flagClientSelectionCanChangeUnexpectedly]; - if (self) { - _failuresToRetrieveExpectedContext = 0; - } - return self; -} - -- (void)checkContextIn:(id) client { - if (!self.willDeleteNullChar && !self.contextOutOfDate && _failuresToRetrieveExpectedContext < 3) { - if (self.appDelegate.debugMode) { - NSLog(@"Checking to see if we're in Google Docs (or some other site that can't give context)."); - } - NSUInteger bufferLength = self.contextBuffer.length; - if (bufferLength) { - NSUInteger location = [client selectedRange].location; - - if (location != NSNotFound && location > 0) { - if ([self appDelegate].debugMode) - NSLog(@"Trying to get context up to location %lu", location); - NSString* clientContext = [self getLimitedContextFrom:client at:location]; - if (clientContext == nil) - { - // Client is failing to provide useful response to attributedSubstringFromRange. - // Word (in MS Live) occasionally does this. - [self setInSiteThatDoesNotGiveContext]; - } - else if (!clientContext.length) { - if ([self appDelegate].debugMode) { - NSLog(@"Expected context = '%@'", self.contextBuffer); - NSLog(@"Actual clientContext was empty"); - } - _failuresToRetrieveExpectedContext++; - } - else - { - unichar lastCodepointExpected = [self.contextBuffer characterAtIndex:bufferLength - 1]; - unichar lastCodepointInClient = [clientContext characterAtIndex:clientContext.length - 1]; - if (lastCodepointExpected != lastCodepointInClient) { - if ([self appDelegate].debugMode) { - NSLog(@"Expected context = '%@'", self.contextBuffer); - NSLog(@"Actual clientContext = '%@'", (clientContext == nil ? @"{nil}" : clientContext)); - NSLog(@"Last character expected (in contextBuffer) = '%lu'", (unsigned long)lastCodepointExpected); - NSLog(@"Last character in clientContext = '%lu'", (unsigned long)lastCodepointInClient); - } - // MS Word converts/reports plain spaces (32) as non-breaking spaces (160). If we - // get this kind of mismatch, we don't want to count this as a definite match, but - // we also don't want to count it as a failure to match. So just wait for a more - // reliable character to test. - if (lastCodepointInClient != 160 || lastCodepointExpected != 32) { - _failuresToRetrieveExpectedContext++; - } - } - else { - if ([self appDelegate].debugMode) { - NSLog(@"We got what we were expecting from the client. We can stop checking."); - } - _failuresToRetrieveExpectedContext = NSUIntegerMax; - } - } - } - else { - if ([self appDelegate].debugMode) { - NSLog(@"bufferLength is %lu, but location was %lu.", bufferLength, location); - } - _failuresToRetrieveExpectedContext++; - } - - if (_failuresToRetrieveExpectedContext == 3) - [self setInSiteThatDoesNotGiveContext]; - } - } -} - -- (void)setInSiteThatDoesNotGiveContext { - if ([self appDelegate].debugMode) { - NSLog(@"Detected some editor (e.g., Google Docs) that can't provide context."); - } - _failuresToRetrieveExpectedContext = NSUIntegerMax; - - if (self.clientSelectionCanChangeUnexpectedly) { - self.clientCanProvideSelectionInfo = Unreliable; - self.clientSelectionCanChangeUnexpectedly = NO; // This isn't true (it can change unexpectedly), but we can't get the context, so we pretend/hope it won't. - } -} -@end diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodBrowserClientEventHandlerProtected.h b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodBrowserClientEventHandlerProtected.h deleted file mode 100644 index faaf606546..0000000000 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodBrowserClientEventHandlerProtected.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// KMInputMethodBrowserClientEventHandlerProtected.h -// Keyman4MacIM -// -// Created by tom on 1/9/18. -// Copyright © 2018 SIL International. All rights reserved. -// - -#ifndef KMInputMethodEventBrowserClientHandlerProtected_h -#define KMInputMethodEventBrowserClientHandlerProtected_h - -@interface KMInputMethodBrowserClientEventHandler () - -- (void)setInSiteThatDoesNotGiveContext; - -@end - -#endif /* KMInputMethodEventBrowserClientHandlerProtected_h */ diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m index d108713a81..3da0bdd237 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m @@ -29,8 +29,6 @@ const CGKeyCode kProcessPendingBuffer = 0xFF; const NSUInteger kMaxContext = 80; const NSTimeInterval kQueuedTextEventDelayInSeconds = 0.1; -//_pendingBuffer contains text that is ready to be sent to the client when all delete-backs are finished. -NSMutableString* _pendingBuffer; CGKeyCode _keyCodeOfOriginalEvent; CGEventSourceRef _sourceFromOriginalEvent = nil; CGEventSourceRef _sourceForGeneratedEvent = nil; @@ -38,35 +36,14 @@ NSMutableString* _easterEggForSentry = nil; NSString* const kEasterEggText = @"Sentry force now"; NSString* const kEasterEggKmxName = @"EnglishSpanish.kmx"; -NSRange _previousSelRange; - -// Protected initializer for use by subclasses -- (instancetype)initWithLegacyMode:(BOOL)legacy clientSelectionCanChangeUnexpectedly:(BOOL) flagClientSelectionCanChangeUnexpectedly { - self = [super init]; - if (self) { - _previousSelRange = NSMakeRange(NSNotFound, NSNotFound); - _clientSelectionCanChangeUnexpectedly = flagClientSelectionCanChangeUnexpectedly; - _clientCanProvideSelectionInfo = Unknown; - _legacyMode = NO; - _contextOutOfDate = YES; - if (legacy) { - [self switchToLegacyMode]; - } - } - return self; -} - // This is the public initializer. - (instancetype)initWithClient:(NSString *)clientAppId client:(id) sender { - self.senderForDeleteBack = sender; _keySender = [[KeySender alloc] init]; _clientApplicationId = clientAppId; _generatedBackspaceCount = 0; _lowLevelBackspaceCount = 0; _queuedText = nil; - //BOOL legacy = [self isClientAppLegacy:clientAppId]; - // In Xcode, if Keyman is the active IM and is in "debugMode" and "English plus Spanish" is // the current keyboard and you type "Sentry force now", it will force a simulated crash to // test reporting to sentry.keyman.com @@ -77,19 +54,7 @@ NSRange _previousSelRange; else _easterEggForSentry = nil; - /* - // For the Atom editor, this isn't really true (the context CAN change unexpectedly), but we can't get - // the context, so we pretend/hope it won't. - BOOL selectionCanChangeUnexpectedly = (![clientAppId isEqual: @"com.github.atom"]); - return [self initWithLegacyMode:self.apiCompliance.mustBackspaceUsingEvents clientSelectionCanChangeUnexpectedly:selectionCanChangeUnexpectedly]; - */ - return [self initWithLegacyMode:NO clientSelectionCanChangeUnexpectedly:NO]; -} - -- (void)switchToLegacyMode { - _legacyMode = YES; - if ([self.appDelegate debugMode]) - NSLog(@"Using legacy mode for this app."); + return self; } - (void)deactivate { @@ -125,39 +90,12 @@ NSRange _previousSelRange; // situation where a user could reasonably hope that any dead-keys typed before using a // command shortcut would be remembered, so other than an insignificant performance penalty, // the only downside to treating all commands as having the potential to change the selection - // is that some "legacy" apps can't get their context at all. This can be overridden so that - // legacy apps can mitigate this problem as appropriate. + // 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]; self.contextChanged = YES; } -- (void)checkContextIn:(id)client { - // Base implementation is no-op -} - -- (void)replaceExistingSelectionIn:(id)client with:(NSString *) text { - [client insertText:text replacementRange:NSMakeRange(NSNotFound, NSNotFound)]; - _previousSelRange.location += text.length; - _previousSelRange.length = 0; -} - -- (void)insertPendingBufferTextIn:(id)client { - NSUInteger length = [self pendingBuffer].length; - if (!length) { - [self.appDelegate logDebugMessage:@"Error - expected text in pending buffer!"]; - return; - } - NSString* text = [self pendingBuffer]; - - [self.appDelegate logDebugMessage:@"Inserting text from pending buffer: \"%@\"", text]; - - [client insertText:text replacementRange:NSMakeRange(NSNotFound, NSNotFound)]; - _previousSelRange.location += text.length; - _previousSelRange.length = 0; - - [self setPendingBuffer:@""]; -} - - (KMInputMethodAppDelegate *)appDelegate { return (KMInputMethodAppDelegate *)[NSApp delegate]; } @@ -166,54 +104,6 @@ NSRange _previousSelRange; return self.appDelegate.kme; } -- (NSMutableString *)contextBuffer { - if (_contextOutOfDate) { - NSException* exception = [NSException - exceptionWithName:@"InvalidOperationException" - reason:@"Attempt to access out-of-date context." - userInfo:nil]; - @throw exception; - } - return self.appDelegate.contextBuffer; -} - --(NSString *)getLimitedContextFrom:(id)sender at:(NSUInteger) len { - if (![sender respondsToSelector:@selector(attributedSubstringFromRange:)]) - return nil; - - NSUInteger start = 0; - if (len > kMaxContext) { - [self.appDelegate logDebugMessage:@"Limiting context to %lu characters", kMaxContext]; - start = len - kMaxContext; - len = kMaxContext; - } - - NSString *preBuffer = [[sender attributedSubstringFromRange:NSMakeRange(start, len)] string]; - [self.appDelegate logDebugMessage:@"preBuffer = \"%@\"", preBuffer ? preBuffer : @"nil"]; - if (preBuffer.length) - [self.appDelegate logDebugMessage:@"First character: '%x'", [preBuffer characterAtIndex:0]]; - else - [self.appDelegate logDebugMessage:@"preBuffer has a length of 0"]; - - return preBuffer; -} - -// Return the pending buffer. If it is NIL create it. --(NSMutableString*)pendingBuffer; -{ - if ( _pendingBuffer == nil ) { - _pendingBuffer = [[NSMutableString alloc] init]; - } - return _pendingBuffer; -} - -// Change the pending buffer. --(void)setPendingBuffer:(NSString*)string -{ - NSMutableString* buffer = [self pendingBuffer]; - [buffer setString:string]; -} - - (BOOL) handleEventWithKeymanEngine:(NSEvent *)event in:(id) sender { [self.appDelegate logDebugMessage:@"handleEventWithKeymanEngine, event = %@", event]; CoreKeyOutput *output = nil; @@ -296,28 +186,6 @@ NSRange _previousSelRange; [self.keySender sendKeymanKeyCodeForEvent:event]; } -- (void)initiatePendingBufferProcessing:(id)sender { - [self postKeyPressToFrontProcess:kProcessPendingBuffer from:NULL]; -} - -- (void)postKeyPressToFrontProcess:(CGKeyCode)code from:(CGEventSourceRef) source { - ProcessSerialNumber psn; - GetFrontProcess(&psn); - - if ([self.appDelegate debugMode]) { - if (code == kProcessPendingBuffer) { - NSLog(@"Posting code to tell Keyman to process characters in pending buffer."); - } - else { - NSLog(@"Posting a keypress (down/up) to the 'front process' for the %hu key.", code); - } - } - - [self.appDelegate postKeyboardEventWithSource:source code:code postCallback:^(CGEventRef eventToPost) { - CGEventPostToPSN((ProcessSerialNumberPtr)&psn, eventToPost); - }]; -} - //MARK: Core-related key processing - (void)checkTextApiCompliance:(id)client { @@ -631,7 +499,7 @@ NSRange _previousSelRange; [self insertAndReplaceText:self.queuedText deleteCount:0 client:client]; self.queuedText = nil; } else { - [self.appDelegate logDebugMessage:@"handleQueuedText called but no text to insert"]; + [self.appDelegate logDebugMessage:@"insertQueuedText called but no text to insert"]; } } diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandlerProtected.h b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandlerProtected.h index b224f7bf50..0645f1ce08 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandlerProtected.h +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandlerProtected.h @@ -9,48 +9,10 @@ #ifndef KMInputMethodEventHandlerProtected_h #define KMInputMethodEventHandlerProtected_h -typedef NS_ENUM(NSInteger, ClientCapability) { - Unknown, - Yes, - No, - Unreliable -}; - @interface KMInputMethodEventHandler () -//@property (nonatomic) NSMutableDictionary *kbData; -//@property (nonatomic) NSDictionary *kmModes; -@property (assign) BOOL willDeleteNullChar; -@property (assign) BOOL contextOutOfDate; -// This flag indicates which mode is being used for replacing already typed text when composing characters -// (i.e., when not using deadkeys). Some apps (and some javascript-based websites, such as Google Docs) do -// not properly deal with calls to insertText calls that replace a range of characters. So for these "legacy" -// apps, we post one or more deletes (i.e., backspace), followed by a special code that tells us we're now -// ready to insert the composed text. -@property BOOL legacyMode; -// Some clients (e.g. Chrome) handle the mouse down events before we get a crack at them. For such apps that -// are able to report their current selection location (LibreOffice can't even do that!), we can do some -// checking at the start of the event processing to see if we're probably still in the same place where we -// left off previously. -@property (assign) BOOL clientSelectionCanChangeUnexpectedly; // REVIEW: Maybe we can get notification from these clients by handling mouseDownOnCharacterIndex. -@property (assign) ClientCapability clientCanProvideSelectionInfo; -@property id senderForDeleteBack; -@property BOOL ignoreNextDeleteBackHighLevel; - -- (instancetype)initWithLegacyMode:(BOOL)legacy clientSelectionCanChangeUnexpectedly:(BOOL) flagClientSelectionCanChangeUnexpectedly; - (void)handleCommand:(NSEvent *)event; -// This just sets the legacyMode property to true and spits out a debug message to that effect. -- (void)switchToLegacyMode; -- (void)checkContextIn:(id)client; -- (void)replaceExistingSelectionIn:(id)client with:(NSString *) text; -- (void)insertPendingBufferTextIn:(id)client; - (KMInputMethodAppDelegate *)appDelegate; -- (NSMutableString *)contextBuffer; -- (NSString *)getLimitedContextFrom:(id)sender at:(NSUInteger) len; -// Return the pending buffer. If it is NIL create it. --(NSMutableString*)pendingBuffer; --(void)setPendingBuffer:(NSString*)string; -- (void)initiatePendingBufferProcessing:(id)sender; @end #endif /* KMInputMethodEventHandlerProtected_h */ diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodSafariClientEventHandler.h b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodSafariClientEventHandler.h deleted file mode 100644 index b65236ec83..0000000000 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodSafariClientEventHandler.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// KMInputMethodSafariClientEventHandler.h -// Keyman4MacIM -// This class is used for the Safari browser to get specific behavior needed to improve behavior for some sites. -// -// Created by tom on 1/9/18. -// Copyright © 2018 SIL International. All rights reserved. -// - -#ifndef KMInputMethodSafariClientEventHandler_h -#define KMInputMethodSafariClientEventHandler_h -#import "KMInputMethodBrowserClientEventHandler.h" - -@interface KMInputMethodSafariClientEventHandler : KMInputMethodBrowserClientEventHandler -@end - -#endif /* KMInputMethodSafariClientEventHandler_h */ diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodSafariClientEventHandler.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodSafariClientEventHandler.m deleted file mode 100644 index 838913b9a7..0000000000 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodSafariClientEventHandler.m +++ /dev/null @@ -1,86 +0,0 @@ -// -// KMInputMethodSafariClientEventHandler.m -// Keyman -// -// Created by tom on 1/9/18. -// Copyright © 2018 SIL International. All rights reserved. -// - -#import "KMInputMethodSafariClientEventHandler.h" -#import "KMInputMethodEventHandlerProtected.h" -#import "KMInputMethodBrowserClientEventHandlerProtected.h" - -@implementation KMInputMethodSafariClientEventHandler - -// Because Google Docs can't report its context, if we detect that we are in Google Docs, we change to legacy mode. -//BOOL _explicitlyDeleteExistingSelectionBeforeInserting = NO; -BOOL _preserveContextForNextCmdA; - -- (instancetype)init { - self = [super initWithLegacyMode:NO clientSelectionCanChangeUnexpectedly:NO]; - if (self) { - _preserveContextForNextCmdA = NO; - //_explicitlyDeleteExistingSelectionBeforeInserting = YES; - } - return self; -} - -- (void)handleCommand:(NSEvent *)event { - // If Safari issued a Cmd-A to remove the selection, we know what the - // context should be, so keep it. - if ([event.characters isEqualTo:@"a"] && _preserveContextForNextCmdA) - _preserveContextForNextCmdA = NO; - else - [super handleCommand:event]; -} - -- (void)setInSiteThatDoesNotGiveContext { - [self switchToLegacyMode]; -} - -- (void)replaceExistingSelectionIn:(id)client with:(NSString *) text { - // The following commented out code is the code that would make it possible to type over an - // existing selection in Word in Safari, but I don't know of a way to distinguish that case - // from other contexts in Safari (wherein this code inserts an extra leading space). - // if (_explicitlyDeleteExistingSelectionBeforeInserting) { - // NSUInteger selLength = [sender selectedRange].length; - // if (selLength > 0 && selLength != NSNotFound) { - // if ([self.AppDelegate debugMode]) { - // NSLog(@"Attempting to delete existing selection of length = %lu by replacing it with a space (which should not actually appear in the text).", selLength); - // } - // - // [sender insertText:@" " replacementRange:NSMakeRange(NSNotFound, NSNotFound)]; - // - // if ([self.AppDelegate debugMode]) - // NSLog(@"Re-posting original (unhandled) code: %d", (int)_keyCodeOfOriginalEvent); - // - // CGEventSourceRef sourceFromEvent = CGEventCreateSourceFromEvent([event CGEvent]); - // [self postKeyPressToFrontProcess:event.keyCode from:sourceFromEvent]; - // CFRelease(sourceFromEvent); - // return YES; - // } - // } - [super replaceExistingSelectionIn:client with:text]; - - // In Google Docs (i.e., "legacy mode" when there is an existing selection, the inserted characters - // stay selected. The following clears the selection. - if (self.legacyMode) { - if ([self.appDelegate debugMode]) - NSLog(@"Sending Command-Shift-A to clear selection in Google Docs"); - _preserveContextForNextCmdA = YES; - ProcessSerialNumber psn; - GetFrontProcess(&psn); - - CGEventRef event = CGEventCreateKeyboardEvent(NULL, kVK_ANSI_A, true); - //set shift and command keys down for above event - CGEventSetFlags(event, kCGEventFlagMaskShift | kCGEventFlagMaskCommand); - CGEventPostToPSN(&psn, event); - CFRelease(event); - - event = CGEventCreateKeyboardEvent(NULL, kVK_ANSI_A, false); - CGEventSetFlags(event, kCGEventFlagMaskShift | kCGEventFlagMaskCommand); - CGEventPostToPSN(&psn, event); - CFRelease(event); - } -} -@end diff --git a/mac/Keyman4MacIM/KeymanTests/KMInputMethodBrowserClientEventHandlerTests.m b/mac/Keyman4MacIM/KeymanTests/KMInputMethodBrowserClientEventHandlerTests.m deleted file mode 100644 index cb03bb71ae..0000000000 --- a/mac/Keyman4MacIM/KeymanTests/KMInputMethodBrowserClientEventHandlerTests.m +++ /dev/null @@ -1,58 +0,0 @@ -// -// KMInputMethodBrowserClientEventHandlerTests.m -// KeymanTests -// -// Created by tom on 1/25/18. -// Copyright © 2018 SIL International. All rights reserved. -// - -#import -#import "TestAppDelegate.h" -#import "KMInputMethodBrowserClientEventHandler.h" -#import "KMInputMethodEventHandlerProtected.h" -#import - -@interface KeymanTests : XCTestCase -@property (nonatomic, strong) TestAppDelegate * delegate; -@end - -@implementation KeymanTests -KMInputMethodBrowserClientEventHandler * _im; - -- (void)setUp { - [super setUp]; - _delegate = [[TestAppDelegate alloc] init]; - [[NSApplication sharedApplication] setDelegate:_delegate]; - // Put setup code here. This method is called before the invocation of each test method in the class. - NSString *path = [[NSBundle bundleForClass:[KeymanTests class]] pathForResource:@"SimpleTest.kmx" ofType:nil]; - KMXFile *kmxFile = [[KMXFile alloc] initWithFilePath:path]; - [_delegate setKmx:kmxFile]; - _im = [[KMInputMethodBrowserClientEventHandler alloc] init]; -} - -- (void)tearDown { - // Put teardown code here. This method is called after the invocation of each test method in the class. - [super tearDown]; -} - -- (void)skip_TestcheckContextIn_EmptyContextExpected_NoChangeToclientSelectionCanChangeUnexpectedly { - // If the expected context is empty, no attempt should be made to check for matching context from - // client, so even though the client would also return an empty string, calling checkContextIn - // repeatedly has no effect (i.e., it does not set clientSelectionCanChangeUnexpectedly to false). - // Therefore a subsequent key down event *should* result in a call to the client to inquire about - // the current selection. - id client = OCMStrictProtocolMock(@protocol(IMKTextInput)); - OCMStub([client selectedRange]).andReturn(NSMakeRange(0, 0)); - NSAttributedString *attrSubstring = [[NSAttributedString alloc] init]; - OCMStub([client attributedSubstringFromRange:(NSMakeRange(0, 0))]).andReturn(attrSubstring); - OCMExpect([client insertText:@"a" replacementRange:NSMakeRange(NSNotFound, NSNotFound)]); - for (int i = 0; i < 8; i++) - { - [_im checkContextIn:client]; - } - NSEvent *event = [_delegate keyStrokeEventForCharacter: @"a" keyCode:kVK_ANSI_A]; - [_im handleEvent:event client:client]; - [client verify]; -} - -@end From f899627129f1d0be14d587fc0aa5bad145a6549a Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 29 Feb 2024 17:55:02 +0100 Subject: [PATCH 04/13] fix(linux): Add `packaging` Python dependency It isn't enough to have the package as build dependency, we also have to list is in the binary package or in the `install_requires` list in `setup.py`. This change also adds other missing python modules to `install_requires` so that things work correctly if building/installing from source. --- linux/debian/control | 3 ++- linux/keyman-config/setup.py | 13 +++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/linux/debian/control b/linux/debian/control index 910db9caf5..e124ce7214 100644 --- a/linux/debian/control +++ b/linux/debian/control @@ -84,13 +84,14 @@ Package: python3-keyman-config Section: python Architecture: all Depends: + dbus-x11, dconf-cli, gir1.2-webkit2-4.1 | gir1.2-webkit2-4.0, keyman-engine, python3-bs4, python3-gi, + python3-packaging, python3-sentry-sdk (>= 1.1), - dbus-x11, ${misc:Depends}, ${python3:Depends}, Description: Keyman for Linux configuration diff --git a/linux/keyman-config/setup.py b/linux/keyman-config/setup.py index 8931241ff2..58fdbbaaca 100644 --- a/linux/keyman-config/setup.py +++ b/linux/keyman-config/setup.py @@ -17,8 +17,17 @@ setup( zip_safe=False, # don't install a zip install_requires=[ - 'lxml', 'numpy', 'Pillow', 'requests', 'requests-cache', - 'python-magic', 'qrcode', 'sentry-sdk' + 'dbus-python', + 'lxml', + 'numpy', + 'packaging', + 'pillow', + 'PyGObject', + 'python-magic', + 'qrcode', + 'requests-cache', + 'requests', + 'sentry-sdk', ], # metadata to display on PyPI From 4b11a5d319d31ac5160bf45e1f678d7af7306ef6 Mon Sep 17 00:00:00 2001 From: jahorton Date: Wed, 6 Mar 2024 15:16:24 +0700 Subject: [PATCH 05/13] fix(ios): selection range sync for long contexts --- web/src/app/webview/src/contextManager.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/web/src/app/webview/src/contextManager.ts b/web/src/app/webview/src/contextManager.ts index 2f6cfd6ae7..d9ef2c6e52 100644 --- a/web/src/app/webview/src/contextManager.ts +++ b/web/src/app/webview/src/contextManager.ts @@ -60,18 +60,24 @@ export class ContextHost extends Mock { updateContext(text: string, selStart: number, selEnd: number): boolean { let shouldResetContext = false; + let tempMock = new Mock(text, selStart ?? text._kmwLength(), selEnd ?? text._kmwLength()); + let newLeft = tempMock.getTextBeforeCaret(); + let oldLeft = this.getTextBeforeCaret(); + if(text != this.text) { - let tempMock = new Mock(text, selStart ?? text._kmwLength(), selEnd ?? text._kmwLength()); - - let newLeft = tempMock.getTextBeforeCaret(); - let oldLeft = this.getTextBeforeCaret(); - let unexpectedBeforeCharCount = findCommonSubstringEndIndex(newLeft, oldLeft, true) + 1; shouldResetContext = !!unexpectedBeforeCharCount; } if(shouldResetContext) { this.text = text; + this.selStart = selStart; + this.selEnd = selEnd; + } else { + // Transform selection coordinates to their location within the longform context window. + let delta = oldLeft._kmwLength() - newLeft._kmwLength(); + this.selStart = selStart - delta; + this.selEnd = selEnd - delta; } if(selStart === undefined || selEnd === undefined) { From ca32ceb54271656a594933f94d67202d6e7a4844 Mon Sep 17 00:00:00 2001 From: sgschantz Date: Thu, 7 Mar 2024 12:15:45 +0700 Subject: [PATCH 06/13] removed obsolete input method event handler class --- .../Keyman4MacIM.xcodeproj/project.pbxproj | 2 -- .../Keyman4MacIM/KMInputMethodEventHandler.m | 1 - .../KMInputMethodEventHandlerProtected.h | 18 ------------------ .../KeymanTests/InputMethodTests.m | 1 - 4 files changed, 22 deletions(-) delete mode 100644 mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandlerProtected.h diff --git a/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj b/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj index 45704f455e..cf83375ba8 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj +++ b/mac/Keyman4MacIM/Keyman4MacIM.xcodeproj/project.pbxproj @@ -356,7 +356,6 @@ E23380FA21407AA100B90591 /* SILInBlue76.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SILInBlue76.png; path = Keyman4MacIM/Images/SILInBlue76.png; sourceTree = SOURCE_ROOT; }; E240F597202DED300000067D /* KMPackage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KMPackage.h; sourceTree = ""; }; E240F598202DED740000067D /* KMPackage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KMPackage.m; sourceTree = ""; }; - E24C79EC1FFFEA6B00D8E46F /* KMInputMethodEventHandlerProtected.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KMInputMethodEventHandlerProtected.h; sourceTree = ""; }; E2585A7E20DD6C3C00CBB994 /* KMMethodEventHandlerTests.kmx */ = {isa = PBXFileReference; lastKnownFileType = file; path = KMMethodEventHandlerTests.kmx; sourceTree = ""; }; E2585A8020DD7CF100CBB994 /* TestAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestAppDelegate.m; sourceTree = ""; }; E2585A8220DD7D3F00CBB994 /* TestAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestAppDelegate.h; sourceTree = ""; }; @@ -558,7 +557,6 @@ E21799041FC5B7BC00F2D66A /* KMInputMethodEventHandler.m */, 298D09F62A1F4533006B9DFE /* TextApiCompliance.h */, 298D09F52A1F4533006B9DFE /* TextApiCompliance.m */, - E24C79EC1FFFEA6B00D8E46F /* KMInputMethodEventHandlerProtected.h */, 98E672961B532DE000DBDE2F /* KMKeyboardHelpWindow */, 989C9C141A7876DE00A20425 /* MainMenu.xib */, 984B8F3E1AF1C2F400E096A8 /* OnScreenKeyboard */, diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m index 3da0bdd237..00fe764132 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m @@ -6,7 +6,6 @@ // Copyright © 2017-2018 SIL International. All rights reserved. // #import "KMInputMethodEventHandler.h" -#import "KMInputMethodEventHandlerProtected.h" #import #import /* For kVK_ constants. */ #import "KeySender.h" diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandlerProtected.h b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandlerProtected.h deleted file mode 100644 index 0645f1ce08..0000000000 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandlerProtected.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// KMInputMethodEventHandlerProtected.h -// Keyman4MacIM -// -// Created by tom on 1/5/18. -// Copyright © 2018 SIL International. All rights reserved. -// - -#ifndef KMInputMethodEventHandlerProtected_h -#define KMInputMethodEventHandlerProtected_h - -@interface KMInputMethodEventHandler () - -- (void)handleCommand:(NSEvent *)event; -- (KMInputMethodAppDelegate *)appDelegate; -@end - -#endif /* KMInputMethodEventHandlerProtected_h */ diff --git a/mac/Keyman4MacIM/KeymanTests/InputMethodTests.m b/mac/Keyman4MacIM/KeymanTests/InputMethodTests.m index 2cefe45fcb..1acd05384d 100644 --- a/mac/Keyman4MacIM/KeymanTests/InputMethodTests.m +++ b/mac/Keyman4MacIM/KeymanTests/InputMethodTests.m @@ -11,7 +11,6 @@ #import #import "KMInputMethodEventHandler.h" -#import "KMInputMethodEventHandlerProtected.h" #import "LegacyTestClient.h" #import "AppleCompliantTestClient.h" #import "TextApiCompliance.h" From 92899752c693b0c5203729eab47279d787e59d7a Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 11 Mar 2024 05:44:45 -0500 Subject: [PATCH 07/13] fix(common): add unit test for --debug flag for builder Fixes #10957. The builder --debug flag appears to be passed correctly, according to this test. This is a good test to keep, so won't remove it, but there is something else going on in the base test. --- .../build/test/debug-deps/child/build.sh | 28 +++++++++++++++++++ .../build/test/debug-deps/child/dep/build.sh | 27 ++++++++++++++++++ resources/build/test/debug-deps/dep/build.sh | 27 ++++++++++++++++++ resources/build/test/debug-deps/test.sh | 22 +++++++++++++++ resources/build/test/test.sh | 1 + 5 files changed, 105 insertions(+) create mode 100755 resources/build/test/debug-deps/child/build.sh create mode 100755 resources/build/test/debug-deps/child/dep/build.sh create mode 100755 resources/build/test/debug-deps/dep/build.sh create mode 100755 resources/build/test/debug-deps/test.sh diff --git a/resources/build/test/debug-deps/child/build.sh b/resources/build/test/debug-deps/child/build.sh new file mode 100755 index 0000000000..49fe938ffa --- /dev/null +++ b/resources/build/test/debug-deps/child/build.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" +. "${THIS_SCRIPT%/*}/../../../../../resources/build/build-utils.sh" +# END STANDARD BUILD SCRIPT INCLUDE + +builder_describe \ + "Tests child builds debug flag" \ + @dep build + +function do_build() { + # Test the debug flag + builder_is_debug_build || builder_die "FAIL: child: expecting builder_is_debug_build to be true" + echo "PASS: child: builder_is_debug_build is true" + + builder_has_option --debug || builder_die "FAIL: child: expecting builder_has_option --debug to be true" + echo "PASS: child: builder_has_option --debug is true" +} + +builder_parse "$@" + +# Sanity Check: verify that we are running as a child (and not a dep) build +! builder_is_dep_build || builder_die "FAIL: child: builder_is_dep_build should be false" +builder_is_child_build || builder_die "FAIL: child: builder_is_child_build should be true" + +builder_run_action build do_build + diff --git a/resources/build/test/debug-deps/child/dep/build.sh b/resources/build/test/debug-deps/child/dep/build.sh new file mode 100755 index 0000000000..09087786e7 --- /dev/null +++ b/resources/build/test/debug-deps/child/dep/build.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" +. "${THIS_SCRIPT%/*}/../../../../../../resources/build/build-utils.sh" +# END STANDARD BUILD SCRIPT INCLUDE + +builder_describe \ + "Tests child/dependency builds debug flag" \ + configure build + +function do_build() { + # Test the debug flag + builder_is_debug_build || builder_die "FAIL: child/dep: expecting builder_is_debug_build to be true" + echo "PASS: child/dep: builder_is_debug_build is true" + + builder_has_option --debug || builder_die "FAIL: child/dep: expecting builder_has_option --debug to be true" + echo "PASS: child/dep: builder_has_option --debug is true" +} + +builder_parse "$@" + +# Sanity Check: verify that we are running as a dep (and not a child) build +builder_is_dep_build || builder_die "FAIL: child/dep: builder_is_dep_build should be true" +! builder_is_child_build || builder_die "FAIL: child/dep: builder_is_child_build should be false" + +builder_run_action build do_build diff --git a/resources/build/test/debug-deps/dep/build.sh b/resources/build/test/debug-deps/dep/build.sh new file mode 100755 index 0000000000..5fcd3d4c3d --- /dev/null +++ b/resources/build/test/debug-deps/dep/build.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" +. "${THIS_SCRIPT%/*}/../../../../../resources/build/build-utils.sh" +# END STANDARD BUILD SCRIPT INCLUDE + +builder_describe \ + "Tests dependency builds debug flag" \ + configure build + +function do_build() { + # Test the debug flag + builder_is_debug_build || builder_die "FAIL: dep: expecting builder_is_debug_build to be true" + echo "PASS: dep: builder_is_debug_build is true" + + builder_has_option --debug || builder_die "FAIL: dep: expecting builder_has_option --debug to be true" + echo "PASS: dep: builder_has_option --debug is true" +} + +builder_parse "$@" + +# Sanity Check: verify that we are running as a dep (and not a child) build +builder_is_dep_build || builder_die "FAIL: dep: builder_is_dep_build should be true" +! builder_is_child_build || builder_die "FAIL: dep: builder_is_child_build should be false" + +builder_run_action build do_build diff --git a/resources/build/test/debug-deps/test.sh b/resources/build/test/debug-deps/test.sh new file mode 100755 index 0000000000..d3ad4f2d63 --- /dev/null +++ b/resources/build/test/debug-deps/test.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" +. "${THIS_SCRIPT%/*}/../../../../resources/build/build-utils.sh" +# END STANDARD BUILD SCRIPT INCLUDE + +builder_describe \ + "Tests child and dependency builds --debug flag" \ + @dep :child build + +function do_build() { + builder_is_debug_build || builder_die "FAIL: parent: expecting builder_is_debug_build to be true" + echo "PASS: parent: builder_is_debug_build is true" + + builder_has_option --debug || builder_die "FAIL: parent: expecting builder_has_option --debug to be true" + echo "PASS: parent: builder_has_option --debug is true" +} + +builder_parse build:child -d +builder_run_action build do_build +builder_run_child_actions build diff --git a/resources/build/test/test.sh b/resources/build/test/test.sh index 4cb78ab2c2..584be82446 100755 --- a/resources/build/test/test.sh +++ b/resources/build/test/test.sh @@ -174,6 +174,7 @@ echo -e "${COLOR_BLUE}## Running dependency tests${COLOR_RESET}" "$THIS_SCRIPT_PATH/builder-deps.test.sh" "$THIS_SCRIPT_PATH/dependencies/test.sh" "$THIS_SCRIPT_PATH/trees/test.sh" +"$THIS_SCRIPT_PATH/debug-deps/test.sh" echo -e "${COLOR_BLUE}## End external tests${COLOR_RESET}" echo From 9a8ea596bef8213c2fbc311dfdaec6755bd994ff Mon Sep 17 00:00:00 2001 From: sgschantz Date: Mon, 11 Mar 2024 14:29:42 -0500 Subject: [PATCH 08/13] added issue # in comment --- mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m | 1 + 1 file changed, 1 insertion(+) diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m index 00fe764132..2ebda0470a 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m @@ -359,6 +359,7 @@ NSString* const kEasterEggKmxName = @"EnglishSpanish.kmx"; [self sendEvents:event forOutput:output]; } } else if (output.isDeleteAndInsertScenario) { + // TODO: fix issue #10246 /* // needs further testing to fix backspace bug in google docs (without breaking other apps) // assume that all non-compliant apps which require backspaces apply an extra backspace if the original event is a backspace From 3240ee72c0e7ba48fb0797ba34d0368a7f1e1013 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Tue, 12 Mar 2024 23:37:45 +0700 Subject: [PATCH 09/13] fix(ios): hard context resets --- .../Keyman.bundle/Contents/Resources/ios-host.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ios/engine/KMEI/KeymanEngine/resources/Keyman.bundle/Contents/Resources/ios-host.js b/ios/engine/KMEI/KeymanEngine/resources/Keyman.bundle/Contents/Resources/ios-host.js index 621e643bb9..d5eb798b67 100644 --- a/ios/engine/KMEI/KeymanEngine/resources/Keyman.bundle/Contents/Resources/ios-host.js +++ b/ios/engine/KMEI/KeymanEngine/resources/Keyman.bundle/Contents/Resources/ios-host.js @@ -287,9 +287,16 @@ function setKeymanContext(text, doSync, selStart, selLength) { let selEnd = selStart + selLength; selEnd = isNaN(selEnd) ? undefined : selEnd; - const shouldReset = keyman.context.updateContext(text, selStart, selEnd); - if(!doSync || shouldReset) { + if(doSync) { + const shouldReset = keyman.context.updateContext(text, selStart, selEnd); + if(shouldReset) { keyman.resetContext(); + } + } else { + // if not in "sync" mode, we have a hard context reset; just full-reset it. + keyman.context.setText(text); + keyman.context.setSelection(selStart, selStart+selLength); + keyman.resetContext(); } } From 48e81bbe6fdae01e7cc90f25f84f42dcf811cfdd Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Sat, 16 Mar 2024 14:03:54 -0400 Subject: [PATCH 10/13] auto: increment beta version to 17.0.290 --- HISTORY.md | 4 ++++ VERSION.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index fe669d5609..0875e9b716 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,9 @@ # Keyman Version History +## 17.0.289 beta 2024-03-16 + +* fix(common): add unit test for --debug flag for builder (#10974) + ## 17.0.288 beta 2024-03-13 * test(developer): kmc keyboard info compiler messages unit tests (#10848) diff --git a/VERSION.md b/VERSION.md index 065d23ebd9..ae99cf2827 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -17.0.289 \ No newline at end of file +17.0.290 \ No newline at end of file From 3315df26a477234761ceb07d67cfcda1d671fe8c Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Tue, 19 Mar 2024 14:03:34 -0400 Subject: [PATCH 11/13] auto: increment beta version to 17.0.291 --- HISTORY.md | 4 ++++ VERSION.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 0875e9b716..54814daa0f 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,9 @@ # Keyman Version History +## 17.0.290 beta 2024-03-19 + +* (#10956) + ## 17.0.289 beta 2024-03-16 * fix(common): add unit test for --debug flag for builder (#10974) diff --git a/VERSION.md b/VERSION.md index ae99cf2827..126fc2004c 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -17.0.290 \ No newline at end of file +17.0.291 \ No newline at end of file From b9d116adad98082b95606b03317b8e4095f50ccd Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Wed, 20 Mar 2024 11:43:44 +0100 Subject: [PATCH 12/13] fix(linux): Replace deprecated `pkg_resources` module in remaining places Previous commit missed a few places where `pkg_resources` module was used. --- linux/keyman-config/keyman_config/install_window.py | 10 +++++----- .../keyman-config/keyman_config/list_installed_kmp.py | 4 ++-- linux/keyman-config/km-package-install | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/linux/keyman-config/keyman_config/install_window.py b/linux/keyman-config/keyman_config/install_window.py index 686e24eac9..dda242c7e1 100755 --- a/linux/keyman-config/keyman_config/install_window.py +++ b/linux/keyman-config/keyman_config/install_window.py @@ -10,6 +10,7 @@ import subprocess import sys import tempfile import webbrowser +import packaging.version import gi @@ -20,8 +21,6 @@ except ValueError: # TODO: Remove once we drop support for Ubuntu 20.04 Focal gi.require_version('WebKit2', '4.0') -from pkg_resources import parse_version - from gi.repository import Gtk, WebKit2 from keyman_config import _, secure_lookup @@ -134,11 +133,12 @@ class InstallKmpWindow(Gtk.Dialog): self.checkcontinue = False def _uninstall_prev_version_if_necessary(self, keyboardid, viewkmp, installed_kmp_ver, info): - if not installed_kmp_ver or not secure_lookup(info, 'version', 'description'): + new_kmp_version = secure_lookup(info, 'version', 'description') + if not installed_kmp_ver or not new_kmp_version: return True - logging.info("package version %s", secure_lookup(info, 'version', 'description')) + logging.info("package version %s", new_kmp_version) logging.info("installed kmp version %s", installed_kmp_ver) - if parse_version(secure_lookup(info, 'version', 'description')) >= parse_version(installed_kmp_ver): + if packaging.version.parse(new_kmp_version) >= packaging.version.parse(installed_kmp_ver): return True response = self._show_version_message_dlg( viewkmp, diff --git a/linux/keyman-config/keyman_config/list_installed_kmp.py b/linux/keyman-config/keyman_config/list_installed_kmp.py index 2b6a32acc4..2bac9c8d4e 100755 --- a/linux/keyman-config/keyman_config/list_installed_kmp.py +++ b/linux/keyman-config/keyman_config/list_installed_kmp.py @@ -3,7 +3,7 @@ import json import logging import os -from pkg_resources import parse_version +import packaging.version from keyman_config import secure_lookup from keyman_config.deprecated_decorator import deprecated @@ -133,7 +133,7 @@ def _get_kmp_version_internal(packageId, location, previousVersion): kmp = get_installed_kmp(location) if packageId in kmp: version = kmp[packageId]['kmpversion'] - if not previousVersion or parse_version(previousVersion) < parse_version(version): + if not previousVersion or packaging.version.parse(previousVersion) < packaging.version.parse(version): previousVersion = version return previousVersion diff --git a/linux/keyman-config/km-package-install b/linux/keyman-config/km-package-install index 613e00368d..675439ee72 100755 --- a/linux/keyman-config/km-package-install +++ b/linux/keyman-config/km-package-install @@ -4,12 +4,12 @@ import argparse import datetime import logging import os -import requests -import requests_cache import sys import time -from pkg_resources import parse_version from zipfile import is_zipfile +import packaging.version +import requests +import requests_cache from keyman_config import KeymanApiUrl, add_standard_arguments, initialize_logging, initialize_sentry, secure_lookup from keyman_config.get_kmp import get_keyboard_data, get_kmp, keyman_cache_dir @@ -175,7 +175,7 @@ def main(): sys.exit(3) pkg_version = secure_lookup(pkgdata, 'version') if installed_kmp_ver and pkg_version: - if parse_version(installed_kmp_ver) > parse_version(pkg_version): + if packaging.version.parse(installed_kmp_ver) > packaging.version.parse(pkg_version): if args.force: logging.warning(f'km-package-install: warning: The {args.package} keyboard ' + f'is already installed with a newer version {installed_kmp_ver}. ' + From e9ac7c6dc891e9a0c57349f3833945b6e9e280e2 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Wed, 20 Mar 2024 14:04:41 -0400 Subject: [PATCH 13/13] auto: increment beta version to 17.0.292 --- HISTORY.md | 5 +++++ VERSION.md | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 54814daa0f..ef43dd0bc8 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,10 @@ # Keyman Version History +## 17.0.291 beta 2024-03-20 + +* chore(mac): clean up code obsoleted by core (#10877) +* fix(linux): Replace deprecated `pkg_resources` module with `packaging.version` (#10860) + ## 17.0.290 beta 2024-03-19 * (#10956) diff --git a/VERSION.md b/VERSION.md index 126fc2004c..8f31495ca0 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -17.0.291 \ No newline at end of file +17.0.292 \ No newline at end of file