mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-05 00:15:32 +00:00
Merge pull request #12355 from keymanapp/change/mac/12342-remove-always-show-osk
change(mac): remove 'Always show OSK' option
This commit is contained in:
commit
492baead2c
13 changed files with 419 additions and 199 deletions
|
|
@ -14,6 +14,7 @@
|
|||
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 */; };
|
||||
296105232C8E91C7007BF6B7 /* KMInputMethodLifecycle.m in Sources */ = {isa = PBXBuildFile; fileRef = 296105222C8E91C7007BF6B7 /* KMInputMethodLifecycle.m */; };
|
||||
296FE2FC275DD21600F46898 /* KMPackageReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 296FE2FB275DD21600F46898 /* KMPackageReader.m */; };
|
||||
297A501728DF4D360074EB1B /* PrivacyWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 297A501228DF4D360074EB1B /* PrivacyWindowController.m */; };
|
||||
297A501828DF4D360074EB1B /* PrivacyWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 297A501328DF4D360074EB1B /* PrivacyWindowController.xib */; };
|
||||
|
|
@ -158,6 +159,8 @@
|
|||
293EA3EF27140DFA00545EED /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/preferences.strings; sourceTree = "<group>"; };
|
||||
293EA3F02714158600545EED /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/MainMenu.strings; sourceTree = "<group>"; };
|
||||
293EA3F527181FDA00545EED /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
296105212C8E91C7007BF6B7 /* KMInputMethodLifecycle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KMInputMethodLifecycle.h; sourceTree = "<group>"; };
|
||||
296105222C8E91C7007BF6B7 /* KMInputMethodLifecycle.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KMInputMethodLifecycle.m; sourceTree = "<group>"; };
|
||||
296FE2FA275DD21600F46898 /* KMPackageReader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KMPackageReader.h; sourceTree = "<group>"; };
|
||||
296FE2FB275DD21600F46898 /* KMPackageReader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KMPackageReader.m; sourceTree = "<group>"; };
|
||||
29781101297FB262007C886D /* kn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kn; path = kn.lproj/KMAboutWindowController.strings; sourceTree = "<group>"; };
|
||||
|
|
@ -579,6 +582,8 @@
|
|||
98D6DA7D1A799FF400B09822 /* KMInputController.m */,
|
||||
98A778C21A8C53BF00CF809D /* KMInputMethodAppDelegate.h */,
|
||||
98A778C31A8C53BF00CF809D /* KMInputMethodAppDelegate.m */,
|
||||
296105212C8E91C7007BF6B7 /* KMInputMethodLifecycle.h */,
|
||||
296105222C8E91C7007BF6B7 /* KMInputMethodLifecycle.m */,
|
||||
E21799031FC5B74D00F2D66A /* KMInputMethodEventHandler.h */,
|
||||
E21799041FC5B7BC00F2D66A /* KMInputMethodEventHandler.m */,
|
||||
298D09F62A1F4533006B9DFE /* TextApiCompliance.h */,
|
||||
|
|
@ -993,6 +998,7 @@
|
|||
29B4A0D52BF7675A00682049 /* KMLogs.m in Sources */,
|
||||
98BF924F1BF02DC20002126A /* KMBarView.m in Sources */,
|
||||
E240F599202DED740000067D /* KMPackage.m in Sources */,
|
||||
296105232C8E91C7007BF6B7 /* KMInputMethodLifecycle.m in Sources */,
|
||||
D861B03F2C5747F70003675E /* KMSettingsRepository.m in Sources */,
|
||||
984B8F441AF1C3D900E096A8 /* OSKWindowController.m in Sources */,
|
||||
9836B3711AE5F11D00780482 /* mztools.c in Sources */,
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="18122" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="18122"/>
|
||||
<plugIn identifier="com.apple.WebKitIBPlugin" version="18122"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22689"/>
|
||||
<plugIn identifier="com.apple.WebKitIBPlugin" version="22689"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="KMConfigurationWindowController">
|
||||
<connections>
|
||||
<outlet property="alwaysShowOSKCheckBox" destination="k5c-KF-717" id="EYm-1F-c71"/>
|
||||
<outlet property="supportBack" destination="LX7-yF-rV2" id="ciN-Ia-7ei"/>
|
||||
<outlet property="supportForward" destination="OSG-wW-VHs" id="8dG-cd-ByI"/>
|
||||
<outlet property="supportHome" destination="RUX-eW-d6h" id="i5g-Lo-6zG"/>
|
||||
|
|
@ -79,7 +78,7 @@
|
|||
</textFieldCell>
|
||||
<prototypeCellViews>
|
||||
<tableCellView id="1fH-kz-di5" customClass="KMConfigColumn1CellView">
|
||||
<rect key="frame" x="11" y="1" width="62" height="25"/>
|
||||
<rect key="frame" x="1" y="1" width="62" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mcD-zc-0eI">
|
||||
|
|
@ -115,7 +114,7 @@
|
|||
</textFieldCell>
|
||||
<prototypeCellViews>
|
||||
<tableCellView id="BtP-6C-zYt">
|
||||
<rect key="frame" x="76" y="1" width="550" height="25"/>
|
||||
<rect key="frame" x="66" y="1" width="550" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="YfS-ug-Llz">
|
||||
|
|
@ -146,7 +145,7 @@
|
|||
</textFieldCell>
|
||||
<prototypeCellViews>
|
||||
<tableCellView id="CGV-al-7wj" customClass="KMConfigColumn3CellView">
|
||||
<rect key="frame" x="629" y="1" width="88" height="25"/>
|
||||
<rect key="frame" x="619" y="1" width="88" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mJA-up-QcJ">
|
||||
|
|
@ -211,18 +210,7 @@
|
|||
<rect key="frame" x="10" y="33" width="754" height="538"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="k5c-KF-717">
|
||||
<rect key="frame" x="15" y="509" width="234" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="Always show on-screen keyboard" bezelStyle="regularSquare" imagePosition="left" inset="2" id="4UX-80-0Vo">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="alwaysShowOSKCheckBoxAction:" target="-2" id="TbQ-5n-ODK"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button toolTip="Turn this on if you are having problems with a specific keyboard or with Keyman in general." verticalHuggingPriority="750" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="uWx-3J-U0D">
|
||||
<button toolTip="Turn this on if you are having problems with a specific keyboard or with Keyman in general." verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="uWx-3J-U0D">
|
||||
<rect key="frame" x="15" y="483" width="200" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="Use verbose Console logging" bezelStyle="regularSquare" imagePosition="left" inset="2" id="7J6-zy-R20">
|
||||
|
|
@ -233,7 +221,7 @@
|
|||
<action selector="useVerboseLoggingCheckBoxAction:" target="-2" id="DGX-fy-5qP"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField hidden="YES" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="PiJ-pY-UY7">
|
||||
<textField hidden="YES" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="PiJ-pY-UY7">
|
||||
<rect key="frame" x="34" y="414" width="705" height="63"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" id="MrI-GM-7d6">
|
||||
|
|
@ -254,7 +242,7 @@
|
|||
<webView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gTQ-rF-m9S">
|
||||
<rect key="frame" x="17" y="43" width="720" height="492"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<webPreferences key="preferences" defaultFontSize="12" defaultFixedFontSize="12">
|
||||
<webPreferences key="preferences" defaultFontSize="12" defaultFixedFontSize="12" javaEnabled="NO">
|
||||
<nil key="identifier"/>
|
||||
</webPreferences>
|
||||
</webView>
|
||||
|
|
@ -305,9 +293,9 @@
|
|||
</window>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="NSActionTemplate" width="15" height="15"/>
|
||||
<image name="NSActionTemplate" width="19" height="19"/>
|
||||
<image name="NSInfo" width="32" height="32"/>
|
||||
<image name="NSRemoveTemplate" width="14" height="4"/>
|
||||
<image name="NSRemoveTemplate" width="18" height="4"/>
|
||||
<image name="buttonCell:clx-vL-wIY:image" width="1" height="1">
|
||||
<mutableData key="keyedArchiveRepresentation">
|
||||
YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMSAAGGoF8QD05T
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
@interface KMConfigurationWindowController ()
|
||||
@property (nonatomic, weak) IBOutlet NSTableView *tableView;
|
||||
@property (nonatomic, weak) IBOutlet WebView *webView;
|
||||
@property (nonatomic, weak) IBOutlet NSButton *alwaysShowOSKCheckBox;
|
||||
@property (nonatomic, weak) IBOutlet NSButton *useVerboseLoggingCheckBox;
|
||||
@property (nonatomic, weak) IBOutlet NSTextField *verboseLoggingInfo;
|
||||
@property (nonatomic, weak) IBOutlet NSButton *supportBack;
|
||||
|
|
@ -70,7 +69,6 @@
|
|||
NSURL *homeUrl = [[NSBundle mainBundle] URLForResource:@"index" withExtension:@"html" subdirectory:@"Help"];
|
||||
[self.webView.mainFrame loadRequest:[NSURLRequest requestWithURL:homeUrl]];
|
||||
|
||||
[self.alwaysShowOSKCheckBox setState:(self.AppDelegate.alwaysShowOSK ? NSOnState : NSOffState)];
|
||||
[self.useVerboseLoggingCheckBox setState:(self.AppDelegate.useVerboseLogging ? NSOnState : NSOffState)];
|
||||
}
|
||||
|
||||
|
|
@ -439,11 +437,6 @@
|
|||
[self.AppDelegate.downloadKBWindow.window makeKeyAndOrderFront:nil];
|
||||
}
|
||||
|
||||
- (IBAction)alwaysShowOSKCheckBoxAction:(id)sender {
|
||||
NSButton *checkBox = (NSButton *)sender;
|
||||
[self.AppDelegate setAlwaysShowOSK:(checkBox.state == NSOnState)];
|
||||
}
|
||||
|
||||
- (IBAction)useVerboseLoggingCheckBoxAction:(id)sender {
|
||||
NSButton *checkBox = (NSButton *)sender;
|
||||
BOOL verboseLoggingOn = checkBox.state == NSOnState;
|
||||
|
|
|
|||
|
|
@ -1,39 +1,46 @@
|
|||
//
|
||||
// KMInputController.m
|
||||
// Keyman4MacIM
|
||||
//
|
||||
// Created by Serkan Kurt on 29/01/2015.
|
||||
// Copyright (c) 2017 SIL International. All rights reserved.
|
||||
//
|
||||
/*
|
||||
* Keyman is copyright (C) SIL International. MIT License.
|
||||
*
|
||||
* Created by Serkan Kurt on 2015-01-29.
|
||||
*
|
||||
*/
|
||||
|
||||
#import "KMInputController.h"
|
||||
#import "KMInputMethodEventHandler.h"
|
||||
#import "KMOSVersion.h"
|
||||
#include <Carbon/Carbon.h> /* For kVK_ constants. */
|
||||
#import "KMSettingsRepository.h"
|
||||
#import "KMLogs.h"
|
||||
#import "InputMethodKit/InputMethodKit.h"
|
||||
#import "KMInputMethodLifecycle.h"
|
||||
|
||||
|
||||
@implementation KMInputController
|
||||
|
||||
KMInputMethodEventHandler* _eventHandler;
|
||||
NSMutableArray *servers;
|
||||
|
||||
- (KMInputMethodAppDelegate *)AppDelegate {
|
||||
- (KMInputMethodAppDelegate *)appDelegate {
|
||||
return (KMInputMethodAppDelegate *)[NSApp delegate];
|
||||
}
|
||||
|
||||
- (id)initWithServer:(IMKServer *)server delegate:(id)delegate client:(id)inputClient
|
||||
{
|
||||
os_log_debug([KMLogs lifecycleLog], "Initializing Keyman Input Method for server with bundleID: %{public}@", server.bundle.bundleIdentifier);
|
||||
|
||||
os_log_debug([KMLogs lifecycleLog], "initWithServer, active app: '%{public}@'", [KMInputMethodLifecycle getClientApplicationId]);
|
||||
|
||||
self = [super initWithServer:server delegate:delegate client:inputClient];
|
||||
if (self) {
|
||||
servers = [[NSMutableArray alloc] initWithCapacity:2];
|
||||
self.AppDelegate.inputController = self;
|
||||
if (self.AppDelegate.kvk != nil && self.AppDelegate.alwaysShowOSK) {
|
||||
[self.AppDelegate showOSK];
|
||||
}
|
||||
self.appDelegate.inputController = self;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register to receive the Deactivated and ChangedClient notification generated from KMInputMethodLifecycle so
|
||||
* that the eventHandler can be changed. There is no need to receive the Activated notification because
|
||||
* the InputController does it all it needs to when it receives the ChangedClient.
|
||||
*/
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(inputMethodDeactivated:) name:kInputMethodDeactivatedNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(inputMethodChangedClient:) name:kInputMethodClientChangeNotification object:nil];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
|
@ -59,102 +66,44 @@ NSMutableArray *servers;
|
|||
}
|
||||
}
|
||||
|
||||
- (void)activateServer:(id)sender {
|
||||
@synchronized(servers) {
|
||||
[sender overrideKeyboardWithKeyboardNamed:@"com.apple.keylayout.US"];
|
||||
|
||||
[self.AppDelegate wakeUpWith:sender];
|
||||
[servers addObject:sender];
|
||||
|
||||
if (_eventHandler != nil) {
|
||||
[_eventHandler deactivate];
|
||||
}
|
||||
|
||||
NSRunningApplication *currApp = [[NSWorkspace sharedWorkspace] frontmostApplication];
|
||||
NSString *clientAppId = [currApp bundleIdentifier];
|
||||
os_log_debug([KMLogs lifecycleLog], "activateServer, new active app: '%{public}@'", clientAppId);
|
||||
|
||||
_eventHandler = [[KMInputMethodEventHandler alloc] initWithClient:clientAppId client:sender];
|
||||
|
||||
/**
|
||||
* The Keyman input method is deactivating because the user chose a different input method: notification from KMInputMethodLifecycle
|
||||
*/
|
||||
- (void)inputMethodDeactivated:(NSNotification *)notification {
|
||||
os_log_debug([KMLogs lifecycleLog], "***KMInputController inputMethodDeactivated, deactivating eventHandler");
|
||||
if (_eventHandler != nil) {
|
||||
[_eventHandler deactivate];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The user has switched to a different text input client: notification from KMInputMethodLifecycle
|
||||
*/
|
||||
- (void)inputMethodChangedClient:(NSNotification *)notification {
|
||||
os_log_debug([KMLogs lifecycleLog], "***KMInputController inputMethodChangedClient, deactivating old eventHandler and activating new one");
|
||||
if (_eventHandler != nil) {
|
||||
[_eventHandler deactivate];
|
||||
}
|
||||
_eventHandler = [[KMInputMethodEventHandler alloc] initWithClient:[KMInputMethodLifecycle getClientApplicationId] client:self.client];
|
||||
|
||||
}
|
||||
|
||||
- (void)activateServer:(id)sender {
|
||||
[sender overrideKeyboardWithKeyboardNamed:@"com.apple.keylayout.US"];
|
||||
[KMInputMethodLifecycle.shared activateClient:sender];
|
||||
}
|
||||
|
||||
- (void)deactivateServer:(id)sender {
|
||||
if ([self.AppDelegate debugMode]) {
|
||||
os_log_debug([KMLogs lifecycleLog], "deactivateServer, sender %{public}@", sender);
|
||||
}
|
||||
@synchronized(servers) {
|
||||
for (int i = 0; i < servers.count; i++) {
|
||||
if (servers[i] == sender) {
|
||||
[servers removeObjectAtIndex:i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (servers.count == 0) {
|
||||
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];
|
||||
}
|
||||
}
|
||||
[KMInputMethodLifecycle.shared deactivateClient:sender];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (void)timerAction:(id)lastServer {
|
||||
@synchronized(servers) {
|
||||
if (servers.count == 0) {
|
||||
if (_eventHandler != nil) {
|
||||
[_eventHandler deactivate];
|
||||
_eventHandler = nil;
|
||||
}
|
||||
[self.AppDelegate sleepFollowingDeactivationOfServer:lastServer];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
- (NSDictionary *)modes:(id)sender {
|
||||
if ([self.AppDelegate debugMode])
|
||||
os_log_debug([KMLogs lifecycleLog], "*** Modes ***");
|
||||
if (_kmModes == nil) {
|
||||
NSDictionary *amhMode = [[NSDictionary alloc] initWithObjectsAndKeys:@"keyman.png", kTSInputModeAlternateMenuIconFileKey,
|
||||
[NSNumber numberWithBool:YES], kTSInputModeDefaultStateKey,
|
||||
[NSNumber numberWithBool:YES], kTSInputModeIsVisibleKey,
|
||||
@"A", kTSInputModeKeyEquivalentKey,
|
||||
[NSNumber numberWithInteger:4608], kTSInputModeKeyEquivalentModifiersKey,
|
||||
[NSNumber numberWithBool:YES], kTSInputModeDefaultStateKey,
|
||||
@"keyman.png", kTSInputModeMenuIconFileKey,
|
||||
@"keyman.png", kTSInputModePaletteIconFileKey,
|
||||
[NSNumber numberWithBool:YES], kTSInputModePrimaryInScriptKey,
|
||||
@"smUnicodeScript", kTSInputModeScriptKey,
|
||||
@"amh", @"TISIntendedLanguage", nil];
|
||||
|
||||
NSDictionary *hinMode = [[NSDictionary alloc] initWithObjectsAndKeys:@"keyman.png", kTSInputModeAlternateMenuIconFileKey,
|
||||
[NSNumber numberWithBool:YES], kTSInputModeDefaultStateKey,
|
||||
[NSNumber numberWithBool:YES], kTSInputModeIsVisibleKey,
|
||||
@"H", kTSInputModeKeyEquivalentKey,
|
||||
[NSNumber numberWithInteger:4608], kTSInputModeKeyEquivalentModifiersKey,
|
||||
[NSNumber numberWithBool:YES], kTSInputModeDefaultStateKey,
|
||||
@"keyman.png", kTSInputModeMenuIconFileKey,
|
||||
@"keyman.png", kTSInputModePaletteIconFileKey,
|
||||
[NSNumber numberWithBool:YES], kTSInputModePrimaryInScriptKey,
|
||||
@"smUnicodeScript", kTSInputModeScriptKey,
|
||||
@"hin", @"TISIntendedLanguage", nil];
|
||||
|
||||
NSDictionary *modeList = [[NSDictionary alloc] initWithObjectsAndKeys:amhMode, @"com.apple.inputmethod.amh", hinMode, @"com.apple.inputmethod.hin", nil];
|
||||
NSArray *modeOrder = [[NSArray alloc] initWithObjects:@"com.apple.inputmethod.amh", @"com.apple.inputmethod.hin", nil];
|
||||
_kmModes = [[NSDictionary alloc] initWithObjectsAndKeys:modeList, kTSInputModeListKey,
|
||||
modeOrder, kTSVisibleInputModeOrderedArrayKey, nil];
|
||||
}
|
||||
|
||||
return _kmModes;
|
||||
}
|
||||
*/
|
||||
|
||||
- (NSMenu *)menu {
|
||||
return self.AppDelegate.menu;
|
||||
return self.appDelegate.menu;
|
||||
}
|
||||
|
||||
- (KMXFile *)kmx {
|
||||
return self.AppDelegate.kmx;
|
||||
return self.appDelegate.kmx;
|
||||
}
|
||||
|
||||
- (void)menuAction:(id)sender {
|
||||
|
|
@ -165,13 +114,15 @@ NSMutableArray *servers;
|
|||
[self showConfigurationWindow:sender];
|
||||
}
|
||||
else if (itag == OSK_MENUITEM_TAG) {
|
||||
[self.AppDelegate showOSK];
|
||||
[KMSettingsRepository.shared writeShowOskOnActivate:YES];
|
||||
os_log_debug([KMLogs oskLog], "menuAction OSK_MENUITEM_TAG, updating settings writeShowOsk to YES");
|
||||
[self.appDelegate showOSK];
|
||||
}
|
||||
else if (itag == ABOUT_MENUITEM_TAG) {
|
||||
[self.AppDelegate showAboutWindow];
|
||||
[self.appDelegate showAboutWindow];
|
||||
}
|
||||
else if (itag >= KEYMAN_FIRST_KEYBOARD_MENUITEM_TAG) {
|
||||
[self.AppDelegate selectKeyboardFromMenu:itag];
|
||||
[self.appDelegate selectKeyboardFromMenu:itag];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -183,7 +134,7 @@ NSMutableArray *servers;
|
|||
if ([KMOSVersion Version_10_13_1] <= systemVersion && systemVersion <= [KMOSVersion Version_10_13_3]) // between 10.13.1 and 10.13.3 inclusive
|
||||
{
|
||||
os_log_info([KMLogs uiLog], "Input Menu: calling workaround instead of showPreferences (sys ver %x)", systemVersion);
|
||||
[self.AppDelegate showConfigurationWindow]; // call our workaround
|
||||
[self.appDelegate showConfigurationWindow]; // call our workaround
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@ static const int KEYMAN_FIRST_KEYBOARD_MENUITEM_INDEX = 0;
|
|||
@property (nonatomic, assign) NSEventModifierFlags currentModifierFlags;
|
||||
@property (nonatomic, assign) CFMachPortRef lowLevelEventTap;
|
||||
@property (nonatomic, assign) CFRunLoopSourceRef runLoopEventSrc;
|
||||
@property (nonatomic, assign) BOOL sleeping;
|
||||
@property (nonatomic, assign) BOOL contextChangedByLowLevelEvent;
|
||||
@property (nonatomic, strong) OSKWindowController *oskWindow;
|
||||
@property (nonatomic, strong) NSString *keyboardName;
|
||||
|
|
@ -90,7 +89,6 @@ static const int KEYMAN_FIRST_KEYBOARD_MENUITEM_INDEX = 0;
|
|||
@property (nonatomic, strong) NSString *downloadFilename;
|
||||
@property (nonatomic, strong) NSMutableData *receivedData;
|
||||
@property (nonatomic, assign) NSUInteger expectedBytes;
|
||||
@property (nonatomic, assign) BOOL alwaysShowOSK;
|
||||
@property (nonatomic, assign) BOOL useVerboseLogging;
|
||||
@property (nonatomic, assign) BOOL useNullChar;
|
||||
@property (nonatomic, assign) BOOL debugMode;
|
||||
|
|
@ -102,8 +100,6 @@ static const int KEYMAN_FIRST_KEYBOARD_MENUITEM_INDEX = 0;
|
|||
- (void)showOSK;
|
||||
- (void)showConfigurationWindow;
|
||||
- (void)selectKeyboardFromMenu:(NSInteger)tag;
|
||||
- (void)sleepFollowingDeactivationOfServer:(id)lastServer;
|
||||
- (void)wakeUpWith:(id)newServer;
|
||||
- (void)handleKeyEvent:(NSEvent *)event;
|
||||
- (BOOL)unzipFile:(NSString *)filePath;
|
||||
- (NSWindowController *)downloadKBWindow_;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
//
|
||||
|
||||
#import "KMInputMethodAppDelegate.h"
|
||||
#import "KMInputMethodLifecycle.h"
|
||||
#import "KMSettingsRepository.h"
|
||||
#import "KMDataRepository.h"
|
||||
#import "KMConfigurationWindowController.h"
|
||||
|
|
@ -58,7 +59,6 @@ NSString *const kKeymanKeyboardDownloadCompletedNotification = @"kKeymanKeyboard
|
|||
@synthesize selectedKeyboard = _selectedKeyboard;
|
||||
@synthesize activeKeyboards = _activeKeyboards;
|
||||
@synthesize contextBuffer = _contextBuffer;
|
||||
@synthesize alwaysShowOSK = _alwaysShowOSK;
|
||||
|
||||
id _lastServerWithOSKShowing = nil;
|
||||
|
||||
|
|
@ -116,6 +116,45 @@ id _lastServerWithOSKShowing = nil;
|
|||
if (self.runLoopEventSrc && runLoop) {
|
||||
CFRunLoopAddSource(runLoop, self.runLoopEventSrc, kCFRunLoopDefaultMode);
|
||||
}
|
||||
|
||||
// register to receive notifications generated from KMInputMethodLifecycle
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(inputMethodActivated:) name:kInputMethodActivatedNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(inputMethodDeactivated:) name:kInputMethodDeactivatedNotification object:nil];
|
||||
|
||||
// start Input Method lifecycle
|
||||
[KMInputMethodLifecycle.shared startLifecycle];
|
||||
}
|
||||
|
||||
/**
|
||||
* When the input method is deactivated, hide the OSK and disable the low-level event tap
|
||||
*/
|
||||
- (void)inputMethodDeactivated:(NSNotification *)notification {
|
||||
if ([self.oskWindow.window isVisible]) {
|
||||
os_log_debug([KMLogs oskLog], "***KMInputMethodAppDelegate inputMethodDeactivated, hiding OSK");
|
||||
[self.oskWindow.window setIsVisible:NO];
|
||||
} else {
|
||||
os_log_debug([KMLogs oskLog], "***KMInputMethodAppDelegate inputMethodDeactivated, OSK already hidden");
|
||||
}
|
||||
|
||||
if (self.lowLevelEventTap) {
|
||||
os_log_debug([KMLogs lifecycleLog], "***inputMethodDeactivated, disabling event tap");
|
||||
CGEventTapEnable(self.lowLevelEventTap, NO);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When the input method is activated, show the OSK and enable the low-level event tap
|
||||
*/
|
||||
- (void)inputMethodActivated:(NSNotification *)notification {
|
||||
if (self.lowLevelEventTap && !CGEventTapIsEnabled(self.lowLevelEventTap)) {
|
||||
os_log_debug([KMLogs lifecycleLog], "***KMInputMethodAppDelegate inputMethodActivated, re-enabling event tap...");
|
||||
CGEventTapEnable(self.lowLevelEventTap, YES);
|
||||
}
|
||||
|
||||
if (_kvk != nil && ([KMInputMethodLifecycle.shared shouldShowOskOnActivate])) {
|
||||
os_log_debug([KMLogs oskLog], "***KMInputMethodAppDelegate inputMethodActivated, showing OSK");
|
||||
[self showOSK];
|
||||
}
|
||||
}
|
||||
|
||||
- (KeymanVersionInfo)versionInfo {
|
||||
|
|
@ -222,43 +261,12 @@ id _lastServerWithOSKShowing = nil;
|
|||
return (KMInputMethodAppDelegate *)[NSApp delegate];
|
||||
}
|
||||
|
||||
-(void) sleepFollowingDeactivationOfServer:(id)lastServer {
|
||||
os_log_debug([KMLogs lifecycleLog], "Keyman no longer active IM.");
|
||||
self.sleeping = YES;
|
||||
if ([self.oskWindow.window isVisible]) {
|
||||
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) {
|
||||
os_log_debug([KMLogs lifecycleLog], "sleepFollowingDeactivationOfServer, disabling event tap...");
|
||||
CGEventTapEnable(self.lowLevelEventTap, NO);
|
||||
}
|
||||
}
|
||||
|
||||
-(void) wakeUpWith:(id)newServer {
|
||||
self.sleeping = NO;
|
||||
if (self.lowLevelEventTap && !CGEventTapIsEnabled(self.lowLevelEventTap)) {
|
||||
os_log_debug([KMLogs lifecycleLog], "wakeUpWith, Keyman is now the active IM. Re-enabling event tap...");
|
||||
CGEventTapEnable(self.lowLevelEventTap, YES);
|
||||
}
|
||||
// See note in sleepFollowingDeactivationOfServer.
|
||||
if (_kvk != nil && (_alwaysShowOSK || _lastServerWithOSKShowing == newServer)) {
|
||||
[self showOSK];
|
||||
}
|
||||
|
||||
_lastServerWithOSKShowing = nil;
|
||||
}
|
||||
|
||||
CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
|
||||
KMInputMethodAppDelegate *appDelegate = [KMInputMethodAppDelegate AppDelegate];
|
||||
if (appDelegate != nil) {
|
||||
if (type == kCGEventTapDisabledByTimeout || type == kCGEventTapDisabledByUserInput) {
|
||||
// kCGEventTapDisabledByUserInput most likely means we're "sleeping", in which case we want it to stay
|
||||
// disabled until we get the wake-up call.
|
||||
if (!appDelegate.sleeping) {
|
||||
// kCGEventTapDisabledByUserInput most likely means we're "sleeping", in which case we want it to stay disabled until we get the wake-up call.
|
||||
if ([KMInputMethodLifecycle.shared shouldEnableEventTap]) {
|
||||
// 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.
|
||||
os_log([KMLogs eventsLog], "Event tap disabled by %{public}@! Attempting to restart...", (type == kCGEventTapDisabledByTimeout ? @"timeout" : @"user"));
|
||||
|
|
@ -433,11 +441,6 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
return [NSString stringWithFormat:@"%@ - Keyman", _keyboardName];
|
||||
}
|
||||
|
||||
- (void)setAlwaysShowOSK:(BOOL)alwaysShowOSK {
|
||||
_alwaysShowOSK = alwaysShowOSK;
|
||||
[[KMSettingsRepository shared] writeAlwaysShowOsk:alwaysShowOSK];
|
||||
}
|
||||
|
||||
- (void)setUseVerboseLogging:(BOOL)useVerboseLogging {
|
||||
os_log_debug([KMLogs configLog], "Turning verbose logging %{public}@", useVerboseLogging ? @"on." : @"off.");
|
||||
_debugMode = useVerboseLogging;
|
||||
|
|
@ -447,11 +450,6 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
[[KMSettingsRepository shared] writeUseVerboseLogging:useVerboseLogging];
|
||||
}
|
||||
|
||||
- (BOOL)alwaysShowOSK {
|
||||
_alwaysShowOSK = [[KMSettingsRepository shared] readAlwaysShowOsk];
|
||||
return _alwaysShowOSK;
|
||||
}
|
||||
|
||||
- (BOOL)useVerboseLogging {
|
||||
return [[KMSettingsRepository shared] readUseVerboseLogging];
|
||||
}
|
||||
|
|
@ -711,7 +709,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
[KMDataRepository.shared createDataDirectoryIfNecessary];
|
||||
|
||||
if ([KMSettingsRepository.shared dataMigrationNeeded]) {
|
||||
BOOL movedData = [KMDataRepository.shared migrateData];
|
||||
[KMDataRepository.shared migrateData];
|
||||
[KMSettingsRepository.shared convertSettingsForMigration];
|
||||
}
|
||||
|
||||
|
|
@ -887,8 +885,6 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
[self setContextBuffer:nil];
|
||||
[self setSelectedKeyboard:path];
|
||||
[self applyPersistedOptions];
|
||||
if (kvk != nil && self.alwaysShowOSK)
|
||||
[self showOSK];
|
||||
}
|
||||
|
||||
- (NSArray *)getKmxFilesInKeyboardsDirectory {
|
||||
|
|
|
|||
27
mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodLifecycle.h
Normal file
27
mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodLifecycle.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Keyman is copyright (C) SIL International. MIT License.
|
||||
*
|
||||
* Created by Shawn Schantz on 2024-09-09.
|
||||
*
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
extern NSString *const kInputMethodActivatedNotification;
|
||||
extern NSString *const kInputMethodDeactivatedNotification;
|
||||
extern NSString *const kInputMethodClientChangeNotification;
|
||||
|
||||
@interface KMInputMethodLifecycle : NSObject
|
||||
+ (KMInputMethodLifecycle *)shared;
|
||||
+ (NSString*)getClientApplicationId;
|
||||
- (void)startLifecycle;
|
||||
- (void)activateClient:(id)client;
|
||||
- (void)deactivateClient:(id)client;
|
||||
- (BOOL)shouldEnableEventTap;
|
||||
- (BOOL)shouldShowOskOnActivate;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
253
mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodLifecycle.m
Normal file
253
mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodLifecycle.m
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
/*
|
||||
* Keyman is copyright (C) SIL International. MIT License.
|
||||
*
|
||||
* Created by Shawn Schantz on 2024-09-09.
|
||||
*
|
||||
* This class is responsible for determining the state of the Keyman input method.
|
||||
* It is called from the KMInputController (a subclass of IMKInputController), and
|
||||
* shares changes in the state of the input method by synchronously posting
|
||||
* notifications to NSNotificationCenter.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class is needed because many activateServer and deactivateServer messages sent from macOS
|
||||
* to KMInputController, but they are not particularly reliable. Keyman receives some messages when it
|
||||
* is not active and should not become active. It also receives messages when it is active, but there is no
|
||||
* need to change state. For example, when a menu is clicked with Keyman active, macOS will send a
|
||||
* deactivateServer message followed by an activateServer message when the menu is released.
|
||||
* The messages may also arrive in an unexpected order.
|
||||
*
|
||||
* Instead of relying on the information conveyed in these messages, this class interprets them as a notification
|
||||
* that the input method state may have changed. For the actual state of the input method, it gets the current
|
||||
* input source using the Carbon APIs TISCopyCurrentKeyboardInputSource and TISGetInputSourceProperty.
|
||||
* If the result is equal to "keyman.inputmethod.Keyman", then Keyman is the active input method. If, for
|
||||
* example, the U.S. keyboard were selected, then the result would be "com.apple.keylayout.US".
|
||||
*
|
||||
* The state of the text input client is discovered using the NSRunningApplication frontmostApplication API.
|
||||
* Knowing the current input method and the current text input client enables us to determine whether the
|
||||
* state has actually changed and how to adjust to the new state.
|
||||
*
|
||||
* It is important for state to be known so that the On-screen keyboard can be appropriately shown or hidden
|
||||
* and the low-level event tap can be stopped or started.
|
||||
*/
|
||||
|
||||
#import "KMInputMethodLifecycle.h"
|
||||
#import "KMLogs.h"
|
||||
#import <AppKit/AppKit.h>
|
||||
#import "KMSettingsRepository.h"
|
||||
#import <Carbon/Carbon.h>
|
||||
|
||||
NSString *const kInputMethodActivatedNotification = @"kInputMethodActivatedNotification";
|
||||
NSString *const kInputMethodDeactivatedNotification = @"kInputMethodDeactivatedNotification";
|
||||
NSString *const kInputMethodClientChangeNotification = @"kInputMethodClientChangeNotification";
|
||||
NSString *const keymanInputMethodName = @"keyman.inputmethod.Keyman";
|
||||
const double transitionDelay = 0.25;
|
||||
|
||||
typedef enum {
|
||||
Started,
|
||||
Active,
|
||||
Inactive
|
||||
} LifecycleState;
|
||||
|
||||
typedef enum {
|
||||
None,
|
||||
Activate,
|
||||
Deactivate,
|
||||
ChangeClients,
|
||||
} TransitionType;
|
||||
|
||||
|
||||
@interface KMInputMethodLifecycle()
|
||||
|
||||
@property LifecycleState lifecycleState;
|
||||
@property NSString *inputSourceId;
|
||||
@property NSString *clientApplicationId;
|
||||
@end
|
||||
|
||||
@implementation KMInputMethodLifecycle
|
||||
|
||||
+ (KMInputMethodLifecycle *)shared {
|
||||
static KMInputMethodLifecycle *shared = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
shared = [[KMInputMethodLifecycle alloc] init];
|
||||
});
|
||||
|
||||
return shared;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_lifecycleState = Started;
|
||||
_inputSourceId = @"";
|
||||
_clientApplicationId = @"";
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* called from Application Delgate during init
|
||||
*/
|
||||
- (void)startLifecycle {
|
||||
_lifecycleState = Started;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use Carbon APIs to get the current input source or input method. Even though many Carbon APIs were deprecated and removed
|
||||
* from the OS years ago, these and other low-level APIs are still supported (but apparently completely undocumented).
|
||||
*/
|
||||
+ (NSString*)getCurrentInputSourceId {
|
||||
TISInputSourceRef inputSource = TISCopyCurrentKeyboardInputSource();
|
||||
NSString *inputSourceId = (__bridge NSString *)(TISGetInputSourceProperty(inputSource, kTISPropertyInputSourceID));
|
||||
return inputSourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bundle ID of the currently active text input client..
|
||||
*/
|
||||
+ (NSString*)getClientApplicationId {
|
||||
NSRunningApplication *currentApp = [[NSWorkspace sharedWorkspace] frontmostApplication];
|
||||
NSString *clientAppId = [currentApp bundleIdentifier];
|
||||
return clientAppId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on the current lifecycleState and the input method state from the OS, determine how the state must transition.
|
||||
*/
|
||||
- (TransitionType)determineTransition:(NSString*)newInputSourceId withAppId:(NSString*)newClientAppId {
|
||||
TransitionType transition = None;
|
||||
BOOL inputSourceIsKeyman = [newInputSourceId isEqualTo:keymanInputMethodName];
|
||||
BOOL clientHasChanged = [self.clientApplicationId isNotEqualTo:newClientAppId];
|
||||
os_log_debug([KMLogs lifecycleLog], "determineTransition, current InputSourceId: %{public}@, new InputSourceId: %{public}@, current ClientAppId: %{public}@, new ClientAppId: %{public}@, inputSourceIsKeyman: %d, clientHasChanged: %d", self.inputSourceId, newInputSourceId, self.clientApplicationId, newClientAppId, inputSourceIsKeyman, clientHasChanged);
|
||||
|
||||
switch (self.lifecycleState) {
|
||||
case Started:
|
||||
transition = Activate;
|
||||
break;
|
||||
case Active:
|
||||
if (inputSourceIsKeyman) {
|
||||
if (clientHasChanged) {
|
||||
transition = ChangeClients;
|
||||
}
|
||||
} else {
|
||||
transition = Deactivate;
|
||||
}
|
||||
break;
|
||||
case Inactive:
|
||||
if (inputSourceIsKeyman) {
|
||||
transition = Activate;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return transition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the input method state, consisting of the input source ID and the client application ID.
|
||||
*/
|
||||
- (void)saveNewInputMethodState:(NSString*)newInputSourceId withAppId:(NSString*)newClientAppId {
|
||||
self.inputSourceId = newInputSourceId;
|
||||
self.clientApplicationId = newClientAppId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when IMKInputController receives an activateServer or a deactivateServer message
|
||||
*/
|
||||
- (void)performTransition:(id)client {
|
||||
NSString *currentInputSource = [KMInputMethodLifecycle getCurrentInputSourceId];
|
||||
NSString *currentClientAppId = [KMInputMethodLifecycle getClientApplicationId];
|
||||
|
||||
TransitionType transition = [self determineTransition:currentInputSource withAppId:currentClientAppId];
|
||||
[self saveNewInputMethodState:currentInputSource withAppId:currentClientAppId];
|
||||
|
||||
switch(transition) {
|
||||
case None:
|
||||
os_log_info([KMLogs lifecycleLog], "performTransition: None, new InputSourceId: %{public}@, new application ID: %{public}@", currentInputSource, currentClientAppId);
|
||||
break;
|
||||
case Activate:
|
||||
os_log_info([KMLogs lifecycleLog], "performTransition: Activate, new InputSourceId: %{public}@, new application ID: %{public}@", currentInputSource, currentClientAppId);
|
||||
/**
|
||||
* Perform two actions when activating the input method.
|
||||
* Change the client first which prepares the event handler.
|
||||
* Then do the activate which starts the event loop and opens the OSK.
|
||||
*/
|
||||
[self changeClient];
|
||||
[self activateInputMethod];
|
||||
break;
|
||||
case Deactivate:
|
||||
os_log_info([KMLogs lifecycleLog], "performTransition: Deactivate, new InputSourceId: %{public}@, new application ID: %{public}@", currentInputSource, currentClientAppId);
|
||||
[self deactivateInputMethod];
|
||||
break;
|
||||
case ChangeClients:
|
||||
os_log_info([KMLogs lifecycleLog], "performTransition: ChangeClients, new InputSourceId: %{public}@, new application ID: %{public}@", currentInputSource, currentClientAppId);
|
||||
[self changeClient];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when IMKInputController receives an activateServer message
|
||||
*/
|
||||
- (void)activateClient:(id)client {
|
||||
os_log_debug([KMLogs lifecycleLog], "KMInputMethodLifecycle activateClient");
|
||||
|
||||
[self performSelector:@selector(performTransitionAfterDelay:) withObject:client afterDelay:transitionDelay];
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when IMKInputController receives an deactivateServer message
|
||||
*/
|
||||
- (void)deactivateClient:(id)client {
|
||||
os_log_debug([KMLogs lifecycleLog], "KMInputMethodLifecycle deactivateClient");
|
||||
|
||||
[self performSelector:@selector(performTransitionAfterDelay:) withObject:client afterDelay:transitionDelay];
|
||||
}
|
||||
|
||||
- (void)performTransitionAfterDelay:(id)client {
|
||||
os_log_debug([KMLogs lifecycleLog], "performTransitionAfterDelay: calling performTransition");
|
||||
[self performTransition:client];
|
||||
}
|
||||
|
||||
/**
|
||||
* Change lifecycleState to Active and send notification.
|
||||
*/
|
||||
- (void)activateInputMethod {
|
||||
os_log_debug([KMLogs lifecycleLog], "activateInputMethod");
|
||||
_lifecycleState = Active;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kInputMethodActivatedNotification object:self];
|
||||
}
|
||||
|
||||
/**
|
||||
* Change lifecycleState to Inactive and send notification.
|
||||
*/
|
||||
- (void)deactivateInputMethod {
|
||||
os_log_debug([KMLogs lifecycleLog], "deactivateInputMethod");
|
||||
_lifecycleState = Inactive;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kInputMethodDeactivatedNotification object:self];
|
||||
}
|
||||
|
||||
/**
|
||||
* Does not change lifecycleState, just fires notification so that InputController knows to change the event handler
|
||||
*/
|
||||
- (void)changeClient {
|
||||
os_log_debug([KMLogs lifecycleLog], "changeClient");
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kInputMethodClientChangeNotification object:self];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if Started or Active
|
||||
*/
|
||||
- (BOOL)shouldEnableEventTap {
|
||||
return ((self.lifecycleState == Started) || (self.lifecycleState == Active));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if lifecycleState is Active and the Settings require us to show the OSK
|
||||
*/
|
||||
- (BOOL)shouldShowOskOnActivate {
|
||||
return [KMSettingsRepository.shared readShowOskOnActivate]
|
||||
&& (self.lifecycleState == Active);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -24,8 +24,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
- (void)clearActiveKeyboards;
|
||||
- (NSDictionary *)readOptionsForSelectedKeyboard;
|
||||
- (void)writeOptionForSelectedKeyboard:(NSString *)key withValue:(NSString*)value;
|
||||
- (BOOL)readAlwaysShowOsk;
|
||||
- (void)writeAlwaysShowOsk:(BOOL)alwaysShowOsk;
|
||||
- (BOOL)readShowOskOnActivate;
|
||||
- (void)writeShowOskOnActivate:(BOOL)show;
|
||||
- (BOOL)readUseVerboseLogging;
|
||||
- (void)writeUseVerboseLogging:(BOOL)verboseLogging;
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
NSString *const kActiveKeyboardsKey = @"KMActiveKeyboardsKey";
|
||||
NSString *const kSelectedKeyboardKey = @"KMSelectedKeyboardKey";
|
||||
NSString *const kPersistedOptionsKey = @"KMPersistedOptionsKey";
|
||||
NSString *const kAlwaysShowOSKKey = @"KMAlwaysShowOSKKey";
|
||||
NSString *const kShowOskOnActivate = @"KMShowOskOnActivate";
|
||||
NSString *const kUseVerboseLogging = @"KMUseVerboseLogging";
|
||||
|
||||
/**
|
||||
|
|
@ -25,6 +25,11 @@ NSString *const kUseVerboseLogging = @"KMUseVerboseLogging";
|
|||
* represents what it is saving.
|
||||
*/
|
||||
NSString *const kKMDeprecatedPersistedOptionsKey = @"KMSavedStoresKey";
|
||||
/**
|
||||
* The following constant "KMAlwaysShowOSKKey" is left here for documentation
|
||||
* but the related UI has been removed according to issue #12342
|
||||
*/
|
||||
NSString *const kAlwaysShowOSKKey = @"KMAlwaysShowOSKKey";
|
||||
|
||||
NSString *const kObsoletePathComponent = @"/Documents/Keyman-Keyboards";
|
||||
NSString *const kNewPathComponent = @"/Library/Application Support/keyman.inputmethod.Keyman/";
|
||||
|
|
@ -306,14 +311,14 @@ NSInteger const kCurrentDataModelVersionNumber = kVersionStoreDataInLibraryDirec
|
|||
}
|
||||
}
|
||||
|
||||
- (BOOL)readAlwaysShowOsk {
|
||||
- (BOOL)readShowOskOnActivate {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
return [userData boolForKey:kAlwaysShowOSKKey];
|
||||
return [userData boolForKey:kShowOskOnActivate];
|
||||
}
|
||||
|
||||
- (void)writeAlwaysShowOsk:(BOOL)alwaysShowOsk {
|
||||
- (void)writeShowOskOnActivate:(BOOL)show {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
[userData setBool:alwaysShowOsk forKey:kAlwaysShowOSKKey];
|
||||
[userData setBool:show forKey:kShowOskOnActivate];
|
||||
}
|
||||
|
||||
- (BOOL)readUseVerboseLogging {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
#import <KeymanEngine4Mac/KeymanEngine4Mac.h>
|
||||
|
||||
@interface OSKWindowController : NSWindowController
|
||||
@interface OSKWindowController : NSWindowController <NSWindowDelegate>
|
||||
|
||||
@property (nonatomic, weak) IBOutlet OSKView *oskView;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#import "OSKWindowController.h"
|
||||
#import "KMInputMethodAppDelegate.h"
|
||||
#import "KMInputMethodLifecycle.h"
|
||||
#import "KMSettingsRepository.h"
|
||||
#import "KMLogs.h"
|
||||
|
||||
@interface OSKWindowController ()
|
||||
|
|
@ -25,7 +27,6 @@
|
|||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
[self stopTimer];
|
||||
}
|
||||
|
||||
|
|
@ -55,7 +56,6 @@
|
|||
- (void)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]];
|
||||
[self startTimerWithTimeInterval:0.1];
|
||||
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
|
||||
|
|
@ -66,6 +66,11 @@
|
|||
[self.oskView resizeOSKLayout];
|
||||
}
|
||||
|
||||
- (void)windowWillClose:(NSNotification *)notification {
|
||||
[KMSettingsRepository.shared writeShowOskOnActivate:NO];
|
||||
os_log_debug([KMLogs oskLog], "OSKWindowController windowWillClose, updating settings writeShowOsk to NO");
|
||||
}
|
||||
|
||||
- (void)helpAction:(id)sender {
|
||||
NSString *kvkPath = [self AppDelegate].kvk.filePath;
|
||||
if (!kvkPath)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22689"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22690"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="Keyman" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" animationBehavior="default" id="F0z-JX-Cv5">
|
||||
<window title="Keyman" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" frameAutosaveName="KeymanOsk" animationBehavior="default" id="F0z-JX-Cv5">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="196" y="240" width="614" height="212"/>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue