Fixes#1953.
Makes it possible to specify additional apps that need 'legacy' handling
without requiring an updated build of Keyman for Mac. The list should be
stored in user defaults under the `KMLegacyApps` key. It can be viewed
with the command:
```
defaults read keyman.inputmethod.Keyman KMLegacyApps
```
And updated with
```
defaults write keyman.inputmethod.Keyman KMLegacyApps -array value1 value2 ...
defaults write keyman.inputmethod.Keyman KMLegacyApps -array-add value1 value2 ...
```
Each entry should be a regex that matches the client app id.
For example:
```
defaults write keyman.inputmethod.Keyman KMLegacyApps -array com.microsoft.Word '^com.github.atom$'
```
(Note for purity, the `.` should be escaped in the regex but it'll
actually be fine without...)
This commit also adds the `keymanDataPath` method on
`KMInputMethodAppDelegate`, so we can place additional configuration
data there in the future (as opposed to in the shared config which is
less easy for users to edit.)
Relates to #3935.
This switches Java apps into legacy mode. However, Java itself will need
patching to support Keyman, as it makes assumptions about input methods,
including matching specific input methods by name, before enabling its
complex text support.
I am in process of submitting a bug report and may try and submit a
patch (although the process seems a little convoluted). It requires a
change to a single file, AWTView.m, with the following diff (against
JDK 16.0):
diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m
index 3e80b5a6cf3..2ae1f4f3f12 100644
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m
+++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m
@@ -263,6 +263,16 @@ - (void) keyDown: (NSEvent *)event {
fProcessingKeystroke = YES;
fKeyEventsNeeded = YES;
+ if([(NSString *)kbdLayout containsString:@"keyman"]) {
+ // Keyman handles all key events; none should be
+ // passed through as default before Keyman processes them
+ fKeyEventsNeeded = NO;
+ }
// Allow TSM to look at the event and potentially send back NSTextInputClient messages.
[self interpretKeyEvents:[NSArray arrayWithObject:event]];
@@ -960,7 +989,9 @@ - (void) insertText:(id)aString replacementRange:(NSRange)replacementRange
if ((utf16Length > 2) ||
((utf8Length > 1) && [self isCodePointInUnicodeBlockNeedingIMEvent:codePoint]) ||
- ((codePoint == 0x5c) && ([(NSString *)kbdLayout containsString:@"Kotoeri"]))) {
+ ((codePoint == 0x5c) && ([(NSString *)kbdLayout containsString:@"Kotoeri"])) ||
+ ([(NSString *)kbdLayout containsString:@"keyman"])
+ ) {
aStringIsComplex = YES;
}
I wasn't going to do this, but realised that crash reporting was going
to be a problem on mac because it still used crashlytics/fabric. Turned
out to be a good exercise to get me back into macOS world, and fairly
straightforward to get right (helps that the other platforms broke the
ice for me).
The handleEvent function has somewhat convoluted logic around emitting
the final transform to the client application. This starts to refactor
that code to move all client interaction to a single point at the end
of the event sequence.
Next phase will be to update delete and insert events to turn them into
a single action where possible.
Fixes#2375.
For applications that do not provide context to Keyman, Keyman was losing
the context buffer whenever a modifier key was pressed or released. This
change modifies the cache reset to occur only when the Command modifier is
pressed.
1) Enable/disable event tap depending on whether Keyman is the active IM; 2) Made code dealing with keeping track of activating/deactivating servers thread-safe; 3) Improved clean-up when event tap cannot be re-enabled; 4) Improved and cleaned up some comments and code aesthetics.
When a special event comes in indicating the event tap has been disabled by timeout or by the user, we attempt to re-enable it. Otherwise, use fallback logic.
This commit does not include the project and plist changes necessary to build/work because they have the APIKey in them and we don't want to publish that. Also, I haven't completely worked out where the frameworks should go or how that plumbing should be hooked up to work well on the build machines and for other developers.
Replaced logic in updateContextBufferIfNeeded to be based on tapping of low-level mouse events instead of relying on list of clients that might have unexpected selection changes.
I had previously made a change to do this in the base class but overloooked that it was also a factor in this subclass, so I refactored a little to have a single method in the base class that handles this. (Note: the base class method also checks to be sure that the client responds to the attributedSubstringFromRange method before calling it. This used to be done only in the subclass, but it seems like a useful safeguard in case some other client fails to implement this.
Turns out that length is not really a supported method/property on IMKTextInput, and it returns unreliable information. (It appears that perhaps this was actually causing Word to work incorrectly.) The diagnostic call to markedRange was pointless since Keyman keyboards to not compose text in this way.
Major refactoring to break long methods up by factoring out into meaningful sub-methods. Also removed small amount of unused code left over from previous refactoring step.
Added logic to correct bug in Safari Google Docs introduced a few months back to clear selection after replacement. Refactored code and fixed bug to correctly handle Chrome's need to replace characters individually.