mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-05 00:15:32 +00:00
Merge pull request #16250 from keymanapp/feat/mac/notify-input-method
Some checks failed
Keyman Build Summary / Summarize build status checks (push) Has been cancelled
Some checks failed
Keyman Build Summary / Summarize build status checks (push) Has been cancelled
feat(mac): update input method on keyboard configuration change 🍎
This commit is contained in:
commit
e733df16ea
4 changed files with 66 additions and 13 deletions
|
|
@ -63,37 +63,37 @@ public class InstallationCheck {
|
|||
print("InstallationCheck registerObservers")
|
||||
DistributedNotificationCenter.default().addObserver(
|
||||
self,
|
||||
selector: #selector(self.handlePermissionNotification(_:)),
|
||||
name: NSNotification.Name.accessCheck,
|
||||
selector: #selector(self.handleAccessibilityResponse(_:)),
|
||||
name: NSNotification.Name.accessibilityQueryResponse,
|
||||
object: nil // Observe notifications from any sender
|
||||
)
|
||||
// MAC-CONFIG_TODO: add timeout?
|
||||
}
|
||||
|
||||
/**
|
||||
* called when `NSNotification.Name.accessCheck` is received
|
||||
* called when `NSNotification.Name.accessibilityQueryResponse` is received
|
||||
*/
|
||||
@objc func handlePermissionNotification(_ notification: Notification) {
|
||||
print("handlePermissionNotification")
|
||||
@objc func handleAccessibilityResponse(_ notification: Notification) {
|
||||
print("handleAccessibilityResponse")
|
||||
// Extract message from the notification if available
|
||||
if let message = notification.object as? String {
|
||||
let permissionGranted = self.processInputMethodResponse(with: message)
|
||||
let permissionGranted = self.processAccessibilityResponse(with: message)
|
||||
self.completeValidation(accessibilityPermissionGranted: permissionGranted)
|
||||
} else {
|
||||
print("accessCheckResponse received but did not include message")
|
||||
print("accessibilityQueryResponse received but did not include message")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the distributed notification message that we received from the Keyman input method.
|
||||
*/
|
||||
func processInputMethodResponse(with message: String) -> Bool {
|
||||
func processAccessibilityResponse(with message: String) -> Bool {
|
||||
let timeStyle = Date.FormatStyle()
|
||||
.hour(.twoDigits(amPM: Date.FormatStyle.Symbol.Hour.AMPMStyle.abbreviated))
|
||||
.minute(.twoDigits)
|
||||
.second(.twoDigits)
|
||||
.secondFraction(.fractional(3))
|
||||
print("processAccessibilityCheckResponse received message: \(message), time: \(Date().formatted(timeStyle))")
|
||||
print("processAccessibilityResponse received message: \(message), time: \(Date().formatted(timeStyle))")
|
||||
|
||||
// if the message indicates that access was granted, then return true
|
||||
return !message.isEmpty && message == kAccessibilityPermissionGrantedMessage
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@ NSString *processorType = @"Intel";
|
|||
NSString *processorType = @"Unknown";
|
||||
#endif
|
||||
|
||||
// distributed notifications
|
||||
NSString *const kKeyboardsChanged = @"com.keyman.keyboards.changed";
|
||||
|
||||
// in-app notifications
|
||||
NSString *const kKeymanKeyboardDownloadCompletedNotification = @"kKeymanKeyboardDownloadCompletedNotification";
|
||||
|
||||
@implementation NSString (VersionNumbers)
|
||||
|
|
@ -125,10 +129,22 @@ id _lastServerWithOSKShowing = nil;
|
|||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(inputMethodDeactivated:) name:kInputMethodDeactivatedNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(inputMethodChangedClient:) name:kInputMethodClientChangeNotification object:nil];
|
||||
|
||||
// register to receive notifications generated from Keyman Configuration App
|
||||
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(handleKeyboardsChanged:) name:kKeyboardsChanged object:nil];
|
||||
|
||||
// start Input Method lifecycle
|
||||
[KMInputMethodLifecycle.shared startLifecycle];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* When packages have been installed, removed, enabled or disabled -- notification from the Keyman Configuration app
|
||||
*/
|
||||
- (void)handleKeyboardsChanged:(NSNotification *)notification {
|
||||
os_log_debug([KMLogs configLog], "***KMInputMethodAppDelegate handleKeyboardsChanged");
|
||||
[self reloadEnabledKeyboards];
|
||||
}
|
||||
|
||||
/**
|
||||
* When the input method is activated -- notification from KMInputMethodLifecycle
|
||||
*/
|
||||
|
|
@ -677,6 +693,24 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
return _enabledKeyboards;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the enabled keyboards have been changed by the Keyman Config app.
|
||||
* Reload the enabled keyboards from the UserDefaults
|
||||
* Then update the Keyman menu
|
||||
*/
|
||||
- (void)reloadEnabledKeyboards {
|
||||
os_log_debug([KMLogs configLog], "reloadEnabledKeyboards");
|
||||
|
||||
// read the enabled keyboards from UserDefaults
|
||||
_enabledKeyboards = [[KMSettingsRepository.shared readEnabledKeyboards] mutableCopy];
|
||||
|
||||
// set Sentry tag for how many keyboards are enabled
|
||||
[KMSentryHelper addEnabledKeyboardCountTag:_enabledKeyboards.count];
|
||||
|
||||
// update the keyboard menu to reflect the updated list of enabled keyboards
|
||||
[self updateKeyboardMenuItems];
|
||||
}
|
||||
|
||||
- (void)saveEnabledKeyboards {
|
||||
os_log_debug([KMLogs dataLog], "saveEnabledKeyboards");
|
||||
[KMSettingsRepository.shared writeEnabledKeyboards:_enabledKeyboards];
|
||||
|
|
|
|||
|
|
@ -25,13 +25,17 @@ import Foundation
|
|||
import Combine
|
||||
import ZIPFoundation
|
||||
|
||||
// distributed notifications
|
||||
public extension Notification.Name {
|
||||
static let accessibilityQueryResponse = Notification.Name("com.keyman.accessibility.state")
|
||||
static let keyboardsChanged = Notification.Name("com.keyman.keyboards.changed")
|
||||
}
|
||||
|
||||
// in-app notifications
|
||||
public extension Notification.Name {
|
||||
static let accessCheck = Notification.Name("com.keyman.accessibility.state")
|
||||
static let newPackageInstalled = Notification.Name("com.keyman.package.installed")
|
||||
static let packageReplaced = Notification.Name("com.keyman.package.replaced")
|
||||
static let packageDowngradeRequested = Notification.Name("com.keyman.package.downgrade.requested")
|
||||
static let packageLoadRequired = Notification.Name("com.keyman.package.load.required")
|
||||
static let packageUpdateRequired = Notification.Name("com.keyman.package.update.required")
|
||||
}
|
||||
|
||||
public enum SettingsError: Error {
|
||||
|
|
@ -43,6 +47,7 @@ public class SettingsContainer : ObservableObject {
|
|||
// installed packages are loaded from disk, each package may contain one or more keyboard
|
||||
fileprivate var installedPackages: [KeymanPackage] {
|
||||
didSet {
|
||||
// whenever this array is modified, update the arrays that are derived from it
|
||||
self.updatePackageArrays()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,6 +81,20 @@ public class DefaultsRepository: DefaultsRepo {
|
|||
*/
|
||||
public func writeEnabledKeyboards(enabledKeyboardsArray: [String]) {
|
||||
self.groupDefaults.set(enabledKeyboardsArray, forKey: kEnabledKeyboardsKey)
|
||||
self.sendKeyboardsChangedNotification()
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a distributed notification that the keyboards have changed.
|
||||
* The input method will receive this and reload the enabled keyboards.
|
||||
*/
|
||||
func sendKeyboardsChangedNotification() {
|
||||
DistributedNotificationCenter.default().postNotificationName (
|
||||
.keyboardsChanged,
|
||||
object: nil,
|
||||
userInfo: nil,
|
||||
deliverImmediately: true
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue