mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-27 02:37:42 +00:00
Merge branch 'master' into feat/developer/kmc-generate
This commit is contained in:
commit
64c8bce011
31 changed files with 288 additions and 165 deletions
33
HISTORY.md
33
HISTORY.md
|
|
@ -1,5 +1,28 @@
|
|||
# Keyman Version History
|
||||
|
||||
## 18.0.106 alpha 2024-09-06
|
||||
|
||||
* feat(windows): add right modifier included in hotkey optional functionality (#12259)
|
||||
* fix(android): Skip language counts for lexical-model packages (#12361)
|
||||
* docs(web): fix link to documentation page (#12369)
|
||||
|
||||
## 18.0.105 alpha 2024-09-05
|
||||
|
||||
* chore(common): Fix missing entries in HISTORY.md (#12352)
|
||||
* docs(android): Add in-app help for adjusting longpress delay (#12359)
|
||||
* fix(mac): avoid crash on startup with macOS 10.15 (Catalina) (#12354)
|
||||
* chore(oem/fv): Update to fv_all 13.0 (#12362)
|
||||
* feat(windows): Add two new strings for SIL Global name instead of SIL International (#12327)
|
||||
|
||||
## 18.0.104 alpha 2024-09-03
|
||||
|
||||
* fix(mac): display package info after keyboard installation (#12326)
|
||||
|
||||
## 18.0.103 alpha 2024-09-02
|
||||
|
||||
* feat(windows): Remove hotkey related feature flags (#12252)
|
||||
* feat(windows): update SIL logo for Windows UI (#12250)
|
||||
|
||||
## 18.0.102 alpha 2024-08-30
|
||||
|
||||
* docs(web): add documentation comments for touch layout interfaces (#12314)
|
||||
|
|
@ -20,7 +43,7 @@
|
|||
* fix(android): Prioritize certain actions over multi-line for ENTER key (#12315)
|
||||
* fix(linux): add `keymanFacename` to .ldml file (#12277)
|
||||
* chore(common): Update crowdin strings for Czech (#12316)
|
||||
* (#12313)
|
||||
* fix(web): prevent unintuitive space-output blocking for mid-context suggestions (#12313)
|
||||
|
||||
## 18.0.100 alpha 2024-08-28
|
||||
|
||||
|
|
@ -30,8 +53,8 @@
|
|||
|
||||
* feat(web): import the generator for the pred-text wordbreaker's Unicode-property data-table (#10690)
|
||||
* feat(web): optimize the wordbreaker data table for filesize and ease of first-load parsing (#10692)
|
||||
* (#12297)
|
||||
* (#12115)
|
||||
* fix(web): fixes wordbreaker test import path (#12297)
|
||||
* feat(web): enable utf8 charset encoding for the build artifacts (#12115)
|
||||
|
||||
## 18.0.98 alpha 2024-08-26
|
||||
|
||||
|
|
@ -76,11 +99,11 @@
|
|||
|
||||
## 18.0.93 alpha 2024-08-20
|
||||
|
||||
* (#12188)
|
||||
* refactor(web): remove engine/interfaces dependency on engine/js-processor (#12188)
|
||||
* fix(web): fix malformed reversion display strings (#12201)
|
||||
* feat(android): Add menu to specify long-press delay (#12170)
|
||||
* feat(android): Pass longpress delay to KeymanWeb (#12185)
|
||||
* (#12223)
|
||||
* fix(core): set mac build version for meson cli build to 10.13 (#12223)
|
||||
|
||||
## 18.0.92 alpha 2024-08-19
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
18.0.103
|
||||
18.0.107
|
||||
|
|
@ -112,7 +112,8 @@ public class PackageActivity extends AppCompatActivity implements
|
|||
|
||||
// Number of languages associated with the first keyboard in a keyboard package.
|
||||
// lexical-model packages will be 0
|
||||
final int languageCount = kmpProcessor.getLanguageCount(pkgInfo, PackageProcessor.PP_KEYBOARDS_KEY, 0);
|
||||
final int languageCount = (keyboardCount > 0) ?
|
||||
kmpProcessor.getLanguageCount(pkgInfo, PackageProcessor.PP_KEYBOARDS_KEY, 0) : 0;
|
||||
|
||||
// Sanity check for keyboard packages
|
||||
if (pkgTarget.equals(PackageProcessor.PP_TARGET_KEYBOARDS)) {
|
||||
|
|
|
|||
BIN
android/help/android_images/ic_timelapse.png
Normal file
BIN
android/help/android_images/ic_timelapse.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
BIN
android/help/android_images/longpress-slider.png
Normal file
BIN
android/help/android_images/longpress-slider.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 37 KiB |
13
android/help/basic/config/adjust-longpress-delay.md
Normal file
13
android/help/basic/config/adjust-longpress-delay.md
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
title: Adjust Longpress Delay - Keyman for Android Help
|
||||
---
|
||||
|
||||
## Adjust Longpress Delay
|
||||
|
||||
This menu is used to adjust the duration for triggering a longpress gesture.
|
||||
|
||||
Drag the slider to set the delay between 0.3 seconds to 1.5 seconds.
|
||||
|
||||
The default value is 0.5 seconds.
|
||||
|
||||

|
||||
|
|
@ -44,6 +44,11 @@ Click on this to bring up the Android system configuration for setting Keyman as
|
|||
|
||||
Click on this to [adjust the keyboard height](adjust-keyboard-height).
|
||||
|
||||
## Adjust longpress delay
|
||||

|
||||
|
||||
Click on this to adjust the delay time for a longpress gesture.
|
||||
|
||||
## Spacebar Caption
|
||||
Click on this to [change the displayed keyboard name](spacebar-caption) on the spacebar.
|
||||
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@
|
|||
#define REGSZ_KeyboardHotkeysAreToggle "hotkeys are toggles"
|
||||
#define REGSZ_DeadkeyConversionMode "deadkey conversion mode" // CU // I4552
|
||||
#define REGSZ_ZapVirtualKeyCode "zap virtual key code" // LM, defaults to 0x0E (_VK_PREFIX_DEFAULT)
|
||||
/* Non-chiral use of hotkeys instead of left-only hotkeys */
|
||||
/* Default is to only use left modifier in hotkeys trigger */
|
||||
#define REGSZ_AllowRightModifierHotKey "allow right modifier for hotkey"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -113,10 +113,11 @@ const
|
|||
SRegValue_ShowWelcome = 'show welcome'; // CU
|
||||
SRegValue_UseAdvancedInstall = 'use advanced install'; // CU
|
||||
|
||||
SRegValue_AltGrCtrlAlt = 'simulate altgr'; // CU
|
||||
SRegValue_KeyboardHotKeysAreToggle = 'hotkeys are toggles'; // CU
|
||||
SRegValue_AltGrCtrlAlt = 'simulate altgr'; // CU
|
||||
SRegValue_KeyboardHotKeysAreToggle = 'hotkeys are toggles'; // CU
|
||||
SRegValue_AllowRightModifierHotKey = 'allow right modifier for hotkey'; // CU
|
||||
SRegValue_ReleaseShiftKeysAfterKeyPress = 'release shift keys after key press'; // CU
|
||||
SRegValue_TestKeymanFunctioning = 'test keyman functioning'; // CU, default true
|
||||
SRegValue_TestKeymanFunctioning = 'test keyman functioning'; // CU, default true
|
||||
|
||||
SRegValue_CreateStartMenuAsSubfolders = 'create start menu as subfolders'; // CU
|
||||
SRegValue_CreateUninstallEntries = 'create uninstall entries'; // CU
|
||||
|
|
|
|||
|
|
@ -409,8 +409,8 @@
|
|||
}
|
||||
|
||||
- (void)removeAction:(id)sender {
|
||||
NSButton *removeButton = (NSButton *)sender;
|
||||
NSDictionary *info = [self.tableContents objectAtIndex:removeButton.tag];
|
||||
NSButton *deleteButton = (NSButton *)sender;
|
||||
NSDictionary *info = [self.tableContents objectAtIndex:deleteButton.tag];
|
||||
NSString *deleteKeyboardMessage = NSLocalizedString(@"message-confirm-delete-keyboard", nil);
|
||||
|
||||
if ([info objectForKey:@"HeaderTitle"] != nil)
|
||||
|
|
@ -418,10 +418,13 @@
|
|||
else
|
||||
[self.deleteAlertView setMessageText:[NSString localizedStringWithFormat:deleteKeyboardMessage, [info objectForKey:kKMKeyboardNameKey]]];
|
||||
|
||||
[self.deleteAlertView beginSheetModalForWindow:self.window
|
||||
modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
|
||||
contextInfo:(__bridge void *)([NSNumber numberWithInteger:removeButton.tag])];
|
||||
[self.deleteAlertView beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) {
|
||||
if (returnCode == NSAlertFirstButtonReturn) {
|
||||
os_log_debug([KMLogs uiLog], "confirm delete keyboard alert dismissed");
|
||||
[self deleteFileAtIndex:[NSNumber numberWithInteger:deleteButton.tag]];
|
||||
}
|
||||
self.deleteAlertView = nil;
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)downloadAction:(id)sender {
|
||||
|
|
@ -449,25 +452,30 @@
|
|||
}
|
||||
|
||||
- (void)handleRequestToInstallPackage:(KMPackage *) package {
|
||||
os_log_debug([KMLogs dataLog], "handleRequestToInstallPackage");
|
||||
NSString *keyboardInfoString = NSLocalizedString(@"info-install-keyboard-filename", nil);
|
||||
[self.confirmKmpInstallAlertView setInformativeText:[NSString localizedStringWithFormat:keyboardInfoString, package.getOrigKmpFilename]];
|
||||
|
||||
os_log_debug([KMLogs uiLog], "Asking user to confirm installation of %{public}@, KMP - temp file name: %{public}@", package.getOrigKmpFilename, package.getTempKmpFilename);
|
||||
|
||||
[self.confirmKmpInstallAlertView beginSheetModalForWindow:self.window
|
||||
modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
|
||||
contextInfo:(__bridge void *)(package)];
|
||||
[self.confirmKmpInstallAlertView beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) {
|
||||
os_log_debug([KMLogs uiLog], "confirm keyboard installation alert dismissed");
|
||||
if (returnCode == NSAlertFirstButtonReturn) {
|
||||
[self installPackageFile: package.getTempKmpFilename];
|
||||
}
|
||||
[package releaseTempKMPFile];
|
||||
self.confirmKmpInstallAlertView = nil;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)installPackageFile:(NSString *)kmpFile {
|
||||
// kmpFile could be a temp file (in fact, it always is!), so don't display the name.
|
||||
|
||||
os_log_debug([KMLogs dataLog], "KMP - Ready to unzip/install Package File: %{public}@", kmpFile);
|
||||
os_log_debug([KMLogs dataLog], "kmpFile - ready to unzip/install Package File: %{public}@", kmpFile);
|
||||
|
||||
BOOL didUnzip = [self.AppDelegate unzipFile:kmpFile];
|
||||
|
||||
if (!didUnzip) {
|
||||
os_log_debug([KMLogs dataLog], "kmpFile, unzipFile failed");
|
||||
NSAlert *failure = [[NSAlert alloc] init];
|
||||
[failure addButtonWithTitle:NSLocalizedString(@"button-keyboard-file-unreadable", @"Alert button")];
|
||||
|
||||
|
|
@ -476,13 +484,12 @@
|
|||
|
||||
[failure setIcon:[[NSBundle mainBundle] imageForResource:@"logo.png"]];
|
||||
[failure setAlertStyle:NSAlertStyleWarning];
|
||||
[failure beginSheetModalForWindow:self.window
|
||||
modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
|
||||
contextInfo:nil];
|
||||
[failure beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) {
|
||||
os_log_debug([KMLogs uiLog], "kmpFile, keyboard file unreadable alert dismissed with returnCode: %ld", (long)returnCode);
|
||||
}];
|
||||
}
|
||||
else {
|
||||
os_log_debug([KMLogs dataLog], "Completed installation of KMP file.");
|
||||
os_log_debug([KMLogs dataLog], "kmpFile, completed installation of KMP file");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -558,28 +565,6 @@
|
|||
return _confirmKmpInstallAlertView;
|
||||
}
|
||||
|
||||
- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
|
||||
os_log_debug([KMLogs uiLog], "User responded to NSAlert");
|
||||
if (alert == _deleteAlertView) {
|
||||
if (returnCode == NSAlertFirstButtonReturn) { // Delete
|
||||
[self deleteFileAtIndex:(__bridge NSNumber *)contextInfo];
|
||||
}
|
||||
|
||||
_deleteAlertView = nil;
|
||||
}
|
||||
else if (alert == _confirmKmpInstallAlertView) {
|
||||
KMPackage *package = (__bridge KMPackage *)contextInfo;
|
||||
os_log_debug([KMLogs uiLog], "KMP - Temp file: %{public}@", package.getTempKmpFilename);
|
||||
if (returnCode == NSAlertFirstButtonReturn) { // Install
|
||||
[self installPackageFile: package.getTempKmpFilename];
|
||||
}
|
||||
|
||||
[package releaseTempKMPFile];
|
||||
_confirmKmpInstallAlertView = nil;
|
||||
}
|
||||
// else, just a message - nothing to do.
|
||||
}
|
||||
|
||||
- (void)deleteFileAtIndex:(NSNumber *) n {
|
||||
NSInteger index = [n integerValue];
|
||||
NSString *path2Remove = nil;
|
||||
|
|
|
|||
|
|
@ -85,8 +85,6 @@
|
|||
// TODO: refactor: any reason for this to be HTML? hard to read stringWithFormat applied to template with 16 arguments
|
||||
- (NSString *)detailsHtml {
|
||||
|
||||
NSString *errorString = NSLocalizedString(@"message-keyboard-file-unreadable", nil);
|
||||
|
||||
@try {
|
||||
NSString *htmlFormat =
|
||||
@"<html>"
|
||||
|
|
|
|||
|
|
@ -983,6 +983,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
return _configWindow;
|
||||
}
|
||||
|
||||
// TODO: rewrite confusing pattern, multiple methods differing only by underscore
|
||||
- (NSWindowController *)aboutWindow_ {
|
||||
return _aboutWindow;
|
||||
}
|
||||
|
|
@ -1065,14 +1066,19 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
* TODO: this should really be refactored
|
||||
*/
|
||||
|
||||
- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
|
||||
NSButton *button = (NSButton *)[alert.buttons objectAtIndex:0];
|
||||
if (button.tag == -1) {
|
||||
- (void)downloadComplete:(NSModalResponse) returnCode {
|
||||
os_log_debug([KMLogs uiLog], "downloadComplete, NSModalResponse returnCode: %ld", (long)returnCode);
|
||||
if (returnCode == NSModalResponseCancel) {
|
||||
os_log_debug([KMLogs uiLog], "downloadComplete, returnCode == NSModalResponseCancel");
|
||||
[_connection cancel];
|
||||
}
|
||||
else if (button.tag == 1) {
|
||||
else if (returnCode == NSModalResponseOK) {
|
||||
os_log_debug([KMLogs uiLog], "downloadComplete, returnCode == NSModalResponseOK");
|
||||
|
||||
[_downloadKBWindow close];
|
||||
|
||||
if (self.configWindow.window != nil) {
|
||||
os_log_debug([KMLogs uiLog], "downloadComplete, self.configWindow.window != nil");
|
||||
[self.configWindow.window makeKeyAndOrderFront:nil];
|
||||
if (![[self.configWindow.window childWindows] containsObject:self.infoWindow.window]) {
|
||||
[self.configWindow.window addChildWindow:self.infoWindow.window ordered:NSWindowAbove];
|
||||
|
|
@ -1081,6 +1087,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
[self.infoWindow.window makeKeyAndOrderFront:nil];
|
||||
}
|
||||
else {
|
||||
os_log_debug([KMLogs uiLog], "downloadComplete, self.configWindow.window == nil");
|
||||
[self.infoWindow.window centerInParent];
|
||||
[self.infoWindow.window makeKeyAndOrderFront:nil];
|
||||
[self.infoWindow.window setLevel:NSFloatingWindowLevel];
|
||||
|
|
@ -1098,6 +1105,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
}
|
||||
|
||||
- (NSAlert *)downloadInfoView {
|
||||
os_log_debug([KMLogs uiLog], "downloadInfoView");
|
||||
if (_downloadInfoView == nil) {
|
||||
_downloadInfoView = [[NSAlert alloc] init];
|
||||
[_downloadInfoView setMessageText:NSLocalizedString(@"message-keyboard-downloading", nil)];
|
||||
|
|
@ -1111,6 +1119,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
}
|
||||
|
||||
- (NSProgressIndicator *)progressIndicator {
|
||||
os_log_debug([KMLogs uiLog], "progressIndicator");
|
||||
if (_progressIndicator == nil) {
|
||||
_progressIndicator = [[NSProgressIndicator alloc] initWithFrame:NSMakeRect(0, 0, 300, 20)];
|
||||
[_progressIndicator setIndeterminate:NO];
|
||||
|
|
@ -1130,38 +1139,51 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
[self downloadKeyboardFromURL:url];
|
||||
}
|
||||
|
||||
|
||||
- (void)downloadKeyboardFromURL:(NSURL *)url {
|
||||
NSURL* downloadUrl = url;
|
||||
|
||||
os_log_debug([KMLogs uiLog], "downloadKeyboardFromURL, url.path: %{public}@", url.path);
|
||||
|
||||
if (downloadUrl && _downloadFilename) {
|
||||
if (_infoWindow.window != nil)
|
||||
[_infoWindow close];
|
||||
|
||||
[self.downloadInfoView setInformativeText:self.downloadFilename];
|
||||
|
||||
if (self.configWindow.window != nil) {
|
||||
os_log_debug([KMLogs uiLog], "downloadKeyboardFromURL, self.configWindow.window != nil");
|
||||
[self.configWindow.window makeKeyAndOrderFront:nil];
|
||||
if (![[self.configWindow.window childWindows] containsObject:self.downloadKBWindow.window]) {
|
||||
[self.configWindow.window addChildWindow:self.downloadKBWindow.window ordered:NSWindowAbove];
|
||||
}
|
||||
[self.downloadKBWindow.window centerInParent];
|
||||
[self.downloadKBWindow.window makeKeyAndOrderFront:nil];
|
||||
[self.downloadInfoView beginSheetModalForWindow:self.downloadKBWindow.window
|
||||
modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
|
||||
contextInfo:nil];
|
||||
|
||||
/*
|
||||
Open sheet off of config window, not the download window.
|
||||
This is because, if the download is successful,
|
||||
the download window will be closed by the sheet.
|
||||
*/
|
||||
[self.downloadInfoView beginSheetModalForWindow:self.configWindow.window completionHandler:^(NSModalResponse returnCode) {
|
||||
[self downloadComplete:returnCode];
|
||||
}];
|
||||
}
|
||||
else {
|
||||
os_log_debug([KMLogs uiLog], "downloadKeyboardFromURL, self.configWindow.window == nil");
|
||||
[self.downloadKBWindow.window centerInParent];
|
||||
[self.downloadKBWindow.window makeKeyAndOrderFront:nil];
|
||||
[self.downloadKBWindow.window setLevel:NSFloatingWindowLevel];
|
||||
[self.downloadInfoView beginSheetModalForWindow:self.downloadKBWindow.window
|
||||
modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
|
||||
contextInfo:nil];
|
||||
/*
|
||||
Open sheet off of config window, same as above.
|
||||
*/
|
||||
[self.downloadInfoView beginSheetModalForWindow:self.configWindow.window completionHandler:^(NSModalResponse returnCode) {
|
||||
[self downloadComplete:returnCode];
|
||||
}];
|
||||
}
|
||||
|
||||
if (_connection == nil) {
|
||||
[_downloadInfoView setMessageText:NSLocalizedString(@"message-keyboard-downloading", nil)];
|
||||
os_log_debug([KMLogs uiLog], "downloadKeyboardFromURL, _connection == nil, set button title cancel downloading, tag = -1");
|
||||
[_downloadInfoView setMessageText:NSLocalizedString(@"message-keyboard-downloading", nil)];
|
||||
NSButton *button = (NSButton *)[_downloadInfoView.buttons objectAtIndex:0];
|
||||
[button setTitle:NSLocalizedString(@"button-cancel-downloading", nil)];
|
||||
[button setTag:-1];
|
||||
|
|
@ -1170,7 +1192,6 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
_receivedData = [[NSMutableData alloc] initWithLength:0];
|
||||
_connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1203,6 +1224,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
}
|
||||
|
||||
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
|
||||
os_log_debug([KMLogs uiLog], "connectionDidFinishLoading");
|
||||
NSString *filePath = [self.keyboardsPath stringByAppendingPathComponent:self.downloadFilename];
|
||||
[self.receivedData writeToFile:filePath atomically:YES];
|
||||
[self unzipFile:filePath];
|
||||
|
|
@ -1210,6 +1232,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
|
||||
[_downloadInfoView setMessageText:NSLocalizedString(@"message-keyboard-download-complete", nil)];
|
||||
NSButton *button = (NSButton *)[_downloadInfoView.buttons objectAtIndex:0];
|
||||
os_log_debug([KMLogs uiLog], "connectionDidFinishLoading, set button title download complete, tag = 1");
|
||||
[button setTitle:NSLocalizedString(@"button-download-complete", nil)];
|
||||
[button setTag:1];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kKeymanKeyboardDownloadCompletedNotification
|
||||
|
|
@ -1276,6 +1299,7 @@ extern const CGKeyCode kProcessPendingBuffer;
|
|||
NSError *error = nil;
|
||||
NSString *fileName = filePath.lastPathComponent;
|
||||
NSString *folderName = [fileName stringByDeletingPathExtension];
|
||||
|
||||
os_log_debug([KMLogs keyboardLog], "unzipFile, folderName: %{public}@, fileName: %{public}@", folderName, fileName);
|
||||
|
||||
// First we unzip into a temp folder, and check kmp.json for the fileVersion
|
||||
|
|
|
|||
|
|
@ -239,14 +239,12 @@ typedef enum {
|
|||
NSString *s = [line substringFromIndex:kName.length+1];
|
||||
NSArray *vs = [s componentsSeparatedByString:@"\","];
|
||||
NSString *v1 = [[vs objectAtIndex:0] stringByReplacingOccurrencesOfString:@"\"" withString:@""];
|
||||
NSString *v2 = [[vs objectAtIndex:1] stringByReplacingOccurrencesOfString:@"\"" withString:@""];
|
||||
builder.packageName = v1;
|
||||
}
|
||||
else if ([[line lowercaseString] hasPrefix:[kVersion lowercaseString]]) {
|
||||
NSString *s = [line substringFromIndex:kVersion.length+1];
|
||||
NSArray *vs = [s componentsSeparatedByString:@"\","];
|
||||
NSString *v1 = [[vs objectAtIndex:0] stringByReplacingOccurrencesOfString:@"\"" withString:@""];
|
||||
NSString *v2 = [[vs objectAtIndex:1] stringByReplacingOccurrencesOfString:@"\"" withString:@""];
|
||||
builder.packageVersion = v1;
|
||||
}
|
||||
else if ([[line lowercaseString] hasPrefix:[kAuthor lowercaseString]]) {
|
||||
|
|
@ -261,14 +259,12 @@ typedef enum {
|
|||
NSString *s = [line substringFromIndex:kCopyright.length+1];
|
||||
NSArray *vs = [s componentsSeparatedByString:@"\","];
|
||||
NSString *v1 = [[vs objectAtIndex:0] stringByReplacingOccurrencesOfString:@"\"" withString:@""];
|
||||
NSString *v2 = [[vs objectAtIndex:1] stringByReplacingOccurrencesOfString:@"\"" withString:@""];
|
||||
builder.copyright = v1;
|
||||
}
|
||||
else if ([[line lowercaseString] hasPrefix:[kWebSite lowercaseString]]) {
|
||||
NSString *s = [line substringFromIndex:kWebSite.length+1];
|
||||
NSArray *vs = [s componentsSeparatedByString:@"\","];
|
||||
NSString *v1 = [[vs objectAtIndex:0] stringByReplacingOccurrencesOfString:@"\"" withString:@""];
|
||||
NSString *v2 = [[vs objectAtIndex:1] stringByReplacingOccurrencesOfString:@"\"" withString:@""];
|
||||
builder.website = v1;
|
||||
}
|
||||
|
||||
|
|
@ -282,20 +278,17 @@ typedef enum {
|
|||
NSString *s = [line substringFromIndex:x+2];
|
||||
if ([[s lowercaseString] hasPrefix:[kFile lowercaseString]]) {
|
||||
NSArray *vs = [s componentsSeparatedByString:@"\","];
|
||||
NSString *v1 = [[[vs objectAtIndex:0] substringFromIndex:kFile.length+1] stringByReplacingOccurrencesOfString:@"\"" withString:@""];
|
||||
NSString *fileName = [[vs objectAtIndex:1] stringByReplacingOccurrencesOfString:@"\"" withString:@""];
|
||||
[files addObject:fileName];
|
||||
}
|
||||
else if ([[s lowercaseString] hasPrefix:[kFont lowercaseString]]) {
|
||||
NSArray *vs = [s componentsSeparatedByString:@"\","];
|
||||
NSString *fontName = [[[vs objectAtIndex:0] substringFromIndex:kFont.length+1] stringByReplacingOccurrencesOfString:@"\"" withString:@""];
|
||||
NSString *fontFileName = [[vs objectAtIndex:1] stringByReplacingOccurrencesOfString:@"\"" withString:@""];
|
||||
[fontArray addObject:fontName];
|
||||
}
|
||||
else if ([[s lowercaseString] hasPrefix:[kKeyboard lowercaseString]]) {
|
||||
NSArray *vs = [s componentsSeparatedByString:@"\","];
|
||||
NSString *keyboardName = [[[vs objectAtIndex:0] substringFromIndex:kKeyboard.length+1] stringByReplacingOccurrencesOfString:@"\"" withString:@""];
|
||||
NSString *keyboardFileName = [[vs objectAtIndex:1] stringByReplacingOccurrencesOfString:@"\"" withString:@""];
|
||||
|
||||
KMKeyboardInfoBuilder *builder = [[KMKeyboardInfoBuilder alloc] init];
|
||||
builder.name = keyboardName;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/*
|
||||
* Keyman is copyright (C) SIL International. MIT License.
|
||||
*
|
||||
* KMSettingsRepository.h
|
||||
|
|
|
|||
|
|
@ -251,7 +251,6 @@ NSInteger const kCurrentDataModelVersionNumber = kVersionStoreDataInLibraryDirec
|
|||
}
|
||||
|
||||
- (void)convertActiveKeyboardArrayForMigration {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
NSMutableArray *keyboards = [self activeKeyboards];
|
||||
NSMutableArray *convertedActiveKeyboards = [[NSMutableArray alloc] initWithCapacity:0];
|
||||
BOOL didConvert = NO;
|
||||
|
|
@ -269,9 +268,9 @@ NSInteger const kCurrentDataModelVersionNumber = kVersionStoreDataInLibraryDirec
|
|||
}
|
||||
}
|
||||
|
||||
// only update array in UserDefaults if we actually converted something
|
||||
// only write array to UserDefaults if we actually converted something
|
||||
if (didConvert) {
|
||||
[[NSUserDefaults standardUserDefaults] setObject:convertedActiveKeyboards forKey:kActiveKeyboardsKey];
|
||||
[self writeActiveKeyboards:convertedActiveKeyboards];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
/**
|
||||
* Keyman is copyright (C) SIL International. MIT License.
|
||||
*
|
||||
* KeySender.m
|
||||
* Keyman
|
||||
*
|
||||
* Created by Shawn Schantz on 2023-04-17.
|
||||
*
|
||||
* Sends keydown events for the provided keycode to the frontmost application.
|
||||
|
|
@ -56,15 +53,13 @@ const CGKeyCode kKeymanEventKeyCode = 0xFF;
|
|||
}
|
||||
|
||||
/**
|
||||
sendKeymanKeyCodeForEvent sends the kKeymanEventKeyCode to the
|
||||
frontmost application to indicate that all the backspaces have been processed
|
||||
and we can insert the queuedText to the client
|
||||
* sendKeymanKeyCodeForEvent sends the kKeymanEventKeyCode to the
|
||||
* frontmost application to indicate that all the backspaces have been processed
|
||||
* and we can insert the queuedText to the client
|
||||
*/
|
||||
|
||||
- (void)sendKeymanKeyCodeForEvent:(NSEvent *)event {
|
||||
os_log_debug([KMLogs keyLog], "KeySender sendKeymanKeyCodeForEvent");
|
||||
|
||||
ProcessSerialNumber psn;
|
||||
|
||||
// Returns the frontmost app, which is the app that receives key events.
|
||||
NSRunningApplication *app = NSWorkspace.sharedWorkspace.frontmostApplication;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/*
|
||||
* Keyman is copyright (C) SIL International. MIT License.
|
||||
*
|
||||
* PrivacyConsent.m
|
||||
|
|
@ -7,8 +7,8 @@
|
|||
* Created by Shawn Schantz on 2022-09-22.
|
||||
*
|
||||
* Used to determine if the user has provided consent to the services it needs
|
||||
* and, if not, to request that consent. For versions of macOS prior to 10.15,
|
||||
* Keyman requires Accessibility access. For 10.15 and later, Keyman requires
|
||||
* and, if not, to request that consent. For versions of macOS prior to 11.0,
|
||||
* Keyman requires Accessibility access. For 11.0 and later, Keyman requires
|
||||
* PostEvent access. Both are presented to the user as a need for Accessibility
|
||||
* when prompted by the system and are listed under Accessibility in the Privacy
|
||||
* tab in System Preferences, Security & Privacy. Both Accessibility and
|
||||
|
|
@ -16,7 +16,11 @@
|
|||
* that access is not explicitly needed as long as one of the others is provided
|
||||
* first.
|
||||
*
|
||||
* Access this functionality through the shared instance. Call
|
||||
* Note that Apple's documentation states that the PostEvent access APIs are
|
||||
* available with macOS 10.15 (Catalina) but testing showed that it was only
|
||||
* available with macOS 11.0 (Big Sur). This is documented with issue #12295.
|
||||
*
|
||||
* To access this functionality, used the shared instance. Call
|
||||
* requestPrivacyAccess which will check whether access has been granted. If
|
||||
* not, then a dialog will be presented to the user to inform them that
|
||||
* Accessibility is required. Dismissing this dialog will trigger the API call
|
||||
|
|
@ -24,7 +28,7 @@
|
|||
* only happen once. If the user was prompted earlier and did not grant access,
|
||||
* they can still go to System Preferences and enable it there. So it is useful
|
||||
* to prompt with a dialog from Keyman at startup. Without Accessibility, the
|
||||
* shift layer and the OSK do not work -- so Keyman is basically useless.
|
||||
* shift layer and the OSK do not work.
|
||||
*/
|
||||
|
||||
#import "PrivacyConsent.h"
|
||||
|
|
@ -43,7 +47,7 @@
|
|||
}
|
||||
|
||||
/**
|
||||
* For macOS earlier than 10.15: check for Accessibility access.
|
||||
* For macOS earlier than 11.0: check for Accessibility access.
|
||||
*/
|
||||
- (BOOL)checkAccessibility
|
||||
{
|
||||
|
|
@ -66,7 +70,7 @@
|
|||
BOOL hasAccessibility = NO;
|
||||
|
||||
// check if we already have accessibility
|
||||
if (@available(macOS 10.15, *)) {
|
||||
if (@available(macOS 11.0, *)) {
|
||||
hasAccessibility = [self checkPostEventAccess];
|
||||
} else {
|
||||
hasAccessibility = [self checkAccessibility];
|
||||
|
|
@ -85,7 +89,7 @@
|
|||
}
|
||||
|
||||
/**
|
||||
* For macOS earlier than 10.15: request Accessibility access.
|
||||
* For macOS earlier than 11.0: request Accessibility access.
|
||||
*/
|
||||
- (void)requestAccessibility
|
||||
{
|
||||
|
|
@ -113,18 +117,18 @@
|
|||
*/
|
||||
- (void)configureDialogForOsVersion {
|
||||
|
||||
if (@available(macOS 10.15, *)) {
|
||||
[self configureDialogForCatalinaAndLater];
|
||||
if (@available(macOS 11.0, *)) {
|
||||
[self configureDialogForBigSurAndLater];
|
||||
} else {
|
||||
[self configureDialogForPreCatalina];
|
||||
[self configureDialogForPreBigSur];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize privacy dialog for macOS versions prior to Catalina (10.15).
|
||||
* Initialize privacy dialog for macOS versions prior to Big Sur (11.0).
|
||||
* In this case, request Accessibility access, not PostEvent.
|
||||
*/
|
||||
- (void)configureDialogForPreCatalina {
|
||||
- (void)configureDialogForPreBigSur {
|
||||
void (^consentPrompt)(void) = ^(void) {
|
||||
[self requestAccessibility];
|
||||
|
||||
|
|
@ -136,10 +140,10 @@
|
|||
}
|
||||
|
||||
/**
|
||||
* Initialize privacy dialog for macOS versions of Catalina (10.15) or later.
|
||||
* Initialize privacy dialog for macOS versions of Big Sur (11.0) or later.
|
||||
* In this case, request PostEvent access, not Accessibility.
|
||||
*/
|
||||
- (void)configureDialogForCatalinaAndLater {
|
||||
- (void)configureDialogForBigSurAndLater {
|
||||
void (^consentPrompt)(void) = ^(void) {
|
||||
[self requestPostEventAccess];
|
||||
|
||||
|
|
@ -160,7 +164,7 @@
|
|||
|
||||
/**
|
||||
* Check whether the user has allowed ListenEvent access.
|
||||
* Only available with macOS Catalina (10.15) or later.
|
||||
* Only available with macOS Big Sur (11.0) or later.
|
||||
*
|
||||
* If user has granted Accessibility or PostEvent access, then
|
||||
* ListenEvent access is also granted.
|
||||
|
|
@ -170,18 +174,18 @@
|
|||
BOOL hasAccess = NO;
|
||||
|
||||
// below checks for ListenEvent access
|
||||
if (@available(macOS 10.15, *)) {
|
||||
if (@available(macOS 11.0, *)) {
|
||||
hasAccess = CGPreflightListenEventAccess();
|
||||
os_log([KMLogs privacyLog], "CGPreflightListenEventAccess() returned %@", hasAccess ? @"YES" : @"NO");
|
||||
} else {
|
||||
os_log([KMLogs privacyLog], "CGPreflightListenEventAccess not available before macOS version 10.15");
|
||||
os_log([KMLogs privacyLog], "CGPreflightListenEventAccess not available before macOS version 11.0");
|
||||
}
|
||||
return hasAccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the user has allowed PostEvent access.
|
||||
* Only available with macOS Catalina (10.15) or later.
|
||||
* Only available with macOS Big Sur (11.0) or later.
|
||||
*
|
||||
* If user has granted Accessibility, then PostEvent access is also granted.
|
||||
*/
|
||||
|
|
@ -190,46 +194,46 @@
|
|||
BOOL hasAccess = NO;
|
||||
|
||||
// below checks for PostEvent access
|
||||
if (@available(macOS 10.15, *)) {
|
||||
if (@available(macOS 11.0, *)) {
|
||||
hasAccess = CGPreflightPostEventAccess();
|
||||
|
||||
os_log([KMLogs privacyLog], "CGPreflightPostEventAccess() returned %@", hasAccess ? @"YES" : @"NO");
|
||||
} else {
|
||||
os_log([KMLogs privacyLog], "CGPreflightPostEventAccess not available before macOS version 10.15");
|
||||
os_log([KMLogs privacyLog], "CGPreflightPostEventAccess not available before macOS version 11.0");
|
||||
}
|
||||
return hasAccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request ListenEvent access.
|
||||
* Only available with macOS Catalina (10.15) or later.
|
||||
* Only available with macOS Big Sur (11.0) or later.
|
||||
*/
|
||||
- (BOOL)requestListenEventAccess
|
||||
{
|
||||
BOOL granted = NO;
|
||||
|
||||
if (@available(macOS 10.15, *)) {
|
||||
if (@available(macOS 11.0, *)) {
|
||||
granted = CGRequestListenEventAccess();
|
||||
os_log([KMLogs privacyLog], "CGRequestListenEventAccess() returned %@", granted ? @"YES" : @"NO");
|
||||
} else {
|
||||
os_log([KMLogs privacyLog], "CGRequestListenEventAccess not available before macOS version 10.15");
|
||||
os_log([KMLogs privacyLog], "CGRequestListenEventAccess not available before macOS version 11.0");
|
||||
}
|
||||
return granted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request PostEvent access.
|
||||
* Only available with macOS Catalina (10.15) or later.
|
||||
* Only available with macOS Big Sur (11.0) or later.
|
||||
*/
|
||||
- (BOOL)requestPostEventAccess
|
||||
{
|
||||
BOOL granted = NO;
|
||||
|
||||
if (@available(macOS 10.15, *)) {
|
||||
if (@available(macOS 11.0, *)) {
|
||||
granted = CGRequestPostEventAccess();
|
||||
os_log([KMLogs privacyLog], "CGRequestPostEventAccess() returned %@", granted ? @"YES" : @"NO");
|
||||
} else {
|
||||
os_log([KMLogs privacyLog], "CGRequestPostEventAccess not available before macOS version 10.15");
|
||||
os_log([KMLogs privacyLog], "CGRequestPostEventAccess not available before macOS version 11.0");
|
||||
}
|
||||
return granted;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,10 @@ static CGFloat const kRelativeModifierLabelHeight = 0.30f;
|
|||
- (id)initWithFrame:(NSRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
os_log_debug([KMELogs oskLog], "KeyView initWithFrame: %{public}@, bounds: %{public}@, default clipsToBounds %{public}@", NSStringFromRect(frame), NSStringFromRect(self.bounds), self.clipsToBounds?@"YES":@"NO");
|
||||
/*
|
||||
// usually too much logging, uncomment for debugging
|
||||
os_log_debug([KMELogs oskLog], "KeyView initWithFrame: %{public}@, bounds: %{public}@, default clipsToBounds %{public}@", NSStringFromRect(frame), NSStringFromRect(self.bounds), self.clipsToBounds?@"YES":@"NO");
|
||||
*/
|
||||
self.clipsToBounds = true;
|
||||
CGSize size = frame.size;
|
||||
CGFloat x = size.width*0.05;
|
||||
|
|
@ -70,7 +73,10 @@ static CGFloat const kRelativeModifierLabelHeight = 0.30f;
|
|||
}
|
||||
|
||||
- (void)drawRect:(NSRect)rect {
|
||||
/*
|
||||
// usually too much logging, uncomment for debugging
|
||||
os_log_debug([KMELogs uiLog], "KeyView drawRect: %{public}@, bounds: %{public}@, keyCode: 0x%lx, caption: %{public}@, label: %{public}@", NSStringFromRect(rect), NSStringFromRect(self.bounds), self.keyCode, self.caption.stringValue, self.label.stringValue);
|
||||
*/
|
||||
|
||||
[[self getOpaqueColorWithRed:241 green:242 blue:242] setFill];
|
||||
NSRectFillUsingOperation(rect, NSCompositingOperationSourceOver);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,10 @@
|
|||
- (id)initWithKeyCode:(NSUInteger)keyCode caption:(NSString *)caption scale:(CGFloat)scale {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
os_log_debug([KMELogs oskLog], "OSKKey initWithKeyCode: 0x%lx, caption: %{public}@, scale: %f", keyCode, caption, scale);
|
||||
/*
|
||||
// usually too much logging, uncomment for debugging
|
||||
os_log_debug([KMELogs oskLog], "OSKKey initWithKeyCode: 0x%lx, caption: %{public}@, scale: %f", keyCode, caption, scale);
|
||||
*/
|
||||
_keyCode = keyCode;
|
||||
|
||||
if (caption == nil)
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
}
|
||||
|
||||
- (void)drawRect:(NSRect)rect {
|
||||
os_log_debug([KMELogs uiLog], "OSKView drawRect: %{public}@", NSStringFromRect(rect));
|
||||
os_log_debug([KMELogs oskLog], "OSKView drawRect: %{public}@", NSStringFromRect(rect));
|
||||
|
||||
CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] CGContext];
|
||||
CGContextSetLineJoin(context, kCGLineJoinRound);
|
||||
|
|
|
|||
|
|
@ -12,40 +12,40 @@ fv,fv_dexwlesucid,Dəxʷləšucid,BC Coast,fv_dexwlesucid_kmw-9.0.js,9.2.1,lut-L
|
|||
fv,fv_diitiidatx,Diidiitidq,BC Coast,fv_diitiidatx_kmw-9.0.js,9.2.1,nuk-Latn,Nuu-chah-nulth (Latin)
|
||||
fv,fv_gitsenimx,Gitsenimx̱,BC Coast,fv_gitsenimx_kmw-9.0.js,10.1.2,git,Gitxsan (Latin)
|
||||
fv,fv_hailzaqvla,Haiɫzaqvla,BC Coast,fv_hailzaqvla_kmw-9.0.js,9.5.2,hei,Heiltsuk (Latin)
|
||||
fv,fv_haisla,Haisla,BC Coast,fv_haisla.js,2.1.2,has-Latn,Haisla (Latin)
|
||||
fv,fv_halqemeylem,Halq'eméylem,BC Coast,fv_halqemeylem_kmw-9.0.js,9.2,hur-Latn,Halkomelem (Latin)
|
||||
fv,fv_henqeminem,Hǝn̓q̓ǝmin̓ǝm,BC Coast,fv_henqeminem_kmw-9.0.js,10.1,hur-Latn,Halkomelem (Latin)
|
||||
fv,fv_klahoose,Homalco-Klahoose-Sliammon,BC Coast,fv_klahoose_kmw-9.0.js,10.1,coo,Comox
|
||||
fv,fv_hulquminum,Hul’q’umi’num’,BC Coast,fv_hulquminum_kmw-9.0.js,9.1,hur-Latn,Halkomelem (Latin)
|
||||
fv,fv_haisla,Haisla,BC Coast,fv_haisla.js,2.1.3,has-Latn,Haisla (Latin)
|
||||
fv,fv_halqemeylem,Halq'eméylem,BC Coast,fv_halqemeylem_kmw-9.0.js,9.2.1,hur-Latn,Halkomelem (Latin)
|
||||
fv,fv_henqeminem,Hǝn̓q̓ǝmin̓ǝm,BC Coast,fv_henqeminem_kmw-9.0.js,10.2.1,hur-Latn,Halkomelem (Latin)
|
||||
fv,fv_klahoose,Homalco-Klahoose-Sliammon,BC Coast,fv_klahoose_kmw-9.0.js,10.2,coo,Comox
|
||||
fv,fv_hulquminum,Hul’q’umi’num’,BC Coast,fv_hulquminum_kmw-9.0.js,9.1,hur,Halkomelem
|
||||
fv,fv_hulquminum_combine,Hul̓q̓umin̓um̓,BC Coast,fv_hulquminum_combine_kmw-9.0.js,2.0.1,hur-Latn,Halkomelem (Latin)
|
||||
fv,fv_kwakwala_liqwala,Kʷak̓ʷala,BC Coast,fv_kwakwala_liqwala_kmw-9.0.js,9.3,kwk-Latn,Kwakiutl (Latin)
|
||||
fv,fv_kwakwala,Kwak̕wala,BC Coast,fv_kwakwala_kmw-9.0.js,9.2,kwk-Latn,Kwakiutl (Latin)
|
||||
fv,fv_lekwungen,Lək̓ʷəŋən,BC Coast,fv_lekwungen-9.0.js,1.0,str,Lekwungen
|
||||
fv,fv_nexwslayemucen,Nəxʷsƛ̓ay̓əmúcən,BC Coast,fv_nexwslayemucen_kmw-9.0.js,10.0,clm-Latn,Clallam (Latin)
|
||||
fv,fv_nisgaa,Nisg̱a'a,BC Coast,fv_nisgaa_kmw-9.0.js,9.2,ncg-Latn,Nisga'a (Latin)
|
||||
fv,fv_lekwungen,Lekwungen (Lək̓ʷəŋən),BC Coast,fv_lekwungen_kmw-9.0.js,1.0.1,str,Straits Salish
|
||||
fv,fv_nexwslayemucen,Nəxʷsƛ̓ay̓əmúcən,BC Coast,fv_nexwslayemucen_kmw-9.0.js,11.0,clm,Clallam
|
||||
fv,fv_nisgaa,Nisg̱a'a,BC Coast,fv_nisgaa_kmw-9.0.js,9.2.1,ncg-Latn,Nisga'a (Latin)
|
||||
fv,fv_nuucaanul,Nuučaan̓uł,BC Coast,fv_nuucaanul_kmw-9.0.js,9.2,nuk-Latn,Nuu-chah-nulth (Latin)
|
||||
fv,fv_nuxalk,Nuxalk,BC Coast,fv_nuxalk_kmw-9.0.js,10.0.1,blc-Latn,Bella Coola (Latin)
|
||||
fv,fv_sencoten,SENĆOŦEN,BC Coast,fv_sencoten_kmw-9.0.js,9.2.2,str,Straits Salish
|
||||
fv,fv_sencoten,SENĆOŦEN,BC Coast,fv_sencoten_kmw-9.0.js,9.2.3,str,Straits Salish
|
||||
fv,fv_sguuxs,Sgüüx̱s,BC Coast,fv_sguuxs.js,1.1,tsi,Tsimshian
|
||||
fv,fv_shashishalhem,Shashishalhem,BC Coast,fv_shashishalhem_kmw-9.0.js,9.2,sec-Latn,Sechelt (Latin)
|
||||
fv,fv_shashishalhem,Shashishalhem,BC Coast,fv_shashishalhem_kmw-9.0.js,9.2.1,sec-Latn,Sechelt (Latin)
|
||||
fv,fv_skwxwumesh_snichim,Sḵwx̱wúmesh sníchim,BC Coast,fv_skwxwumesh_snichim_kmw-9.0.js,10.0,squ-Latn,Squamish (Latin)
|
||||
fv,fv_smalgyax,Sm'algya̱x,BC Coast,fv_smalgyax_kmw-9.0.js,9.2,tsi-Latn,Tsimshian (Latin)
|
||||
fv,fv_smalgyax,Sm'algya̱x,BC Coast,fv_smalgyax_kmw-9.0.js,9.3,tsi-Latn,Tsimshian (Latin)
|
||||
fv,fv_xaislakala,X̄a'ʼislak̓ala,BC Coast,fv_xaislakala_kmw-9.0.js,10.0,has-Latn,Haisla (Latin)
|
||||
fv,fv_hlgaagilda_xaayda_kil,X̱aayda-X̱aad Kil,BC Coast,fv_hlgaagilda_xaayda_kil_kmw-9.0.js,9.4,hax,Southern Haida
|
||||
fv,fv_dakelh,Dakelh,BC Interior,fv_dakelh_kmw-9.0.js,9.2.1,caf-Latn,Southern Carrier (Latin)
|
||||
fv,fv_ktunaxa,Ktunaxa,BC Interior,fv_ktunaxa_kmw-9.0.js,10.0,kut-Latn,Kutenai (Latin)
|
||||
fv,fv_kwadacha_tsekene,Kwadacha Tsek’ene,BC Interior,fv_kwadacha_tsekene_kmw-9.0.js,1.1,sek-Latn,Sekani
|
||||
fv,fv_natwits,Nedut’en-Witsuwit'en,BC Interior,fv_natwits_kmw-9.0.js,9.1.3,caf-Latn,Southern Carrier (Latin)
|
||||
fv,fv_natwits,Nedut’en-Witsuwit'en,BC Interior,fv_natwits_kmw-9.0.js,9.2,caf-Latn,Southern Carrier (Latin)
|
||||
fv,fv_nlekepmxcin,Nłeʔkepmxcin,BC Interior,fv_nlekepmxcin_kmw-9.0.js,9.5.1,thp-Latn,Thompson (Latin)
|
||||
fv,fv_nlha7kapmxtsin,Nlha7kapmxtsin,BC Interior,fv_nlha7kapmxtsin_kmw-9.0.js,10.1.1,thp-Latn,Thompson (Latin)
|
||||
fv,fv_nlha7kapmxtsin,Nlha7kapmxtsin,BC Interior,fv_nlha7kapmxtsin_kmw-9.0.js,10.1.2,thp,Thompson
|
||||
fv,fv_nlakapamuxcheen,Nlakapamuxcheen,BC Interior,fv_nlakapamuxcheen_kmw-9.0.js,1.1,thp,Thompson
|
||||
fv,fv_nsilxcen,Nsilxcən,BC Interior,fv_nsilxcen_kmw-9.0.js,10.0,oka,Okanagan
|
||||
fv,fv_secwepemctsin,Secwepemctsín,BC Interior,fv_secwepemctsin_kmw-9.0.js,9.2,shs-Latn,Shuswap (Latin)
|
||||
fv,fv_stlatlimxec,Sƛ̓aƛ̓imxəc,BC Interior,fv_stlatlimxec_kmw-9.0.js,9.3,lil-Latn,Lillooet (Latin)
|
||||
fv,fv_nsilxcen,Nsilxcən,BC Interior,fv_nsilxcen_kmw-9.0.js,10.0.1,oka,Okanagan
|
||||
fv,fv_secwepemctsin,Secwepemctsín,BC Interior,fv_secwepemctsin_kmw-9.0.js,9.3,shs,Shuswap
|
||||
fv,fv_stlatlimxec,Sƛ̓aƛ̓imxəc,BC Interior,fv_stlatlimxec_kmw-9.0.js,9.4,lil-Latn,Lillooet (Latin)
|
||||
fv,fv_statimcets,St̓át̓imcets,BC Interior,fv_statimcets_kmw-9.0.js,9.2,lil-Latn,Lillooet (Latin)
|
||||
fv,fv_taltan,Tāłtān,BC Interior,fv_taltan_kmw-9.0.js,9.2,tht-Latn,Tahltan (Latin)
|
||||
fv,fv_tsekehne,Tsek'ehne,BC Interior,fv_tsekehne_kmw-9.0.js,9.2,sek-Latn,Sekani (Latin)
|
||||
fv,fv_tsilhqotin,Tŝilhqot'in,BC Interior,fv_tsilhqotin_kmw-9.0.js,9.2,clc-Latn,Chilcotin (Latin)
|
||||
fv,fv_tsilhqotin,Tŝilhqot'in,BC Interior,fv_tsilhqotin_kmw-9.0.js,9.3,clc-Latn,Chilcotin (Latin)
|
||||
fv,fv_southern_carrier,ᑐᑊᘁᗕᑋᗸ (Southern Carrier),BC Interior,fv_southern_carrier_kmw-9.0.js,10.1,caf-Cans,Southern Carrier (Unified Canadian Aboriginal Syllabics)
|
||||
fv,fv_anicinapemi8in,Anicinapemi8in/Anishinàbemiwin,Eastern Subarctic,fv_anicinapemi8in_kmw-9.0.js,9.1.1,alq-Latn,Algonquin (Latin)
|
||||
fv,fv_atikamekw,Atikamekw,Eastern Subarctic,fv_atikamekw_kmw-9.0.js,9.1.1,atj-Latn,Atikamekw (Latin)
|
||||
|
|
@ -53,16 +53,16 @@ fv,fv_ilnu_innu_aimun,Ilnu-Innu Aimun,Eastern Subarctic,fv_ilnu_innu_aimun_kmw-9
|
|||
fv,fv_swampy_cree,ᐃᓂᓂᒧᐎᐣ (Swampy Cree),Eastern Subarctic,fv_swampy_cree_kmw-9.0.js,9.2.1,csw-Cans,Swampy Cree (Unified Canadian Aboriginal Syllabics)
|
||||
fv,fv_moose_cree,ᐃᓕᓖᒧᐎᓐ (Moose Cree),Eastern Subarctic,fv_moose_cree_kmw-9.0.js,9.2.1,crm-Cans,Moose Cree (Unified Canadian Aboriginal Syllabics)
|
||||
fv,fv_northern_east_cree,ᐄᔨᔫ-ᐄᓅ ᐊᔨᒨᓐ (Northern East Cree),Eastern Subarctic,fv_northern_east_cree_kmw-9.0.js,9.2.1,crl-Cans,Northern East Cree (Unified Canadian Aboriginal Syllabics)
|
||||
fv,fv_severn_ojibwa,ᐊᓂᔑᓂᓂᒧᐎᐣ (Severn Ojibwa),Eastern Subarctic,fv_severn_ojibwa_kmw-9.0.js,10.1,ojs-Cans,Severn Ojibwa (Unified Canadian Aboriginal Syllabics)
|
||||
fv,fv_severn_ojibwa_rdot,ᐊᓂᔑᓂᓂᒧᐏᐣ (Severn Ojibwa right w-dot),Eastern Subarctic,fv_severn_ojibwa_kmw-9.0.js,1.1,ojs,Oji-Cree
|
||||
fv,fv_severn_ojibwa,ᐊᓂᔑᓂᓂᒧᐎᐣ (Severn Ojibwa),Eastern Subarctic,fv_severn_ojibwa_kmw-9.0.js,10.1.1,ojs-Cans,Severn Ojibwa (Unified Canadian Aboriginal Syllabics)
|
||||
fv,fv_severn_ojibwa_rdot,ᐊᓂᔑᓂᓂᒧᐏᐣ (Severn Ojibwa right w-dot),Eastern Subarctic,fv_severn_ojibwa_kmw-9.0.js,1.1.1,ojs,Oji-Cree
|
||||
fv,fv_ojibwa,ᐊᓂᔑᓇᐯᒧᐎᓐ (a-finals),Eastern Subarctic,fv_ojibwa_kmw-9.0.js,10.1,ojb-Cans,Northwestern Ojibwa (Unified Canadian Aboriginal Syllabics)
|
||||
fv,fv_ojibwa_rdot,ᐁᓂᔑᓇᐯᒧᐏᓐ (a-finals right w-dot),Eastern Subarctic,fv_ojibwa_rdot_kmw-9.0.js,1.0.2,oj,Ojibwa
|
||||
fv,fv_ojibwa_ifinal,ᐊᓂᔑᓇᐯᒧᐎᣙ (i-finals),Eastern Subarctic,fv_ojibwa_ifinal_kmw-9.0.js,1.0.1,oj,Ojibwa
|
||||
fv,fv_ojibwa_ifinal_rdot,ᐊᓂᔑᓇᐯᒧᐏᣙ (i-finals right w-dot),Eastern Subarctic,fv_ojibwa_ifinal_rdot_kmw-9.0.js,1.0.1,oj,Ojibwa
|
||||
fv,fv_ojibwa_rdot,ᐁᓂᔑᓇᐯᒧᐏᓐ (a-finals right w-dot),Eastern Subarctic,fv_ojibwa_rdot_kmw-9.0.js,1.0.3,oj,Ojibwa
|
||||
fv,fv_ojibwa_ifinal,ᐊᓂᔑᓇᐯᒧᐎᣙ (i-finals),Eastern Subarctic,fv_ojibwa_ifinal_kmw-9.0.js,1.0.2,oj,Ojibwa
|
||||
fv,fv_ojibwa_ifinal_rdot,ᐊᓂᔑᓇᐯᒧᐏᣙ (i-finals right w-dot),Eastern Subarctic,fv_ojibwa_ifinal_rdot_kmw-9.0.js,1.0.2,oj,Ojibwa
|
||||
fv,fv_naskapi,ᓇᔅᑲᐱ (Naskapi),Eastern Subarctic,fv_naskapi_kmw-9.0.js,9.3.1,nsk-Cans,Naskapi (Unified Canadian Aboriginal Syllabics)
|
||||
sil,sil_euro_latin,English,European,european2-1.6.js,3.0.2,en,English
|
||||
basic,basic_kbdcan,Français,European,canadian_french-1.0.js,1.1.1,fr-CA,French (Canada)
|
||||
fv,fv_anishinaabemowin,Anishinaabemowin,Great Lakes - St. Lawrence,fv_anishinaabemowin_kmw-9.0.js,10.1,oj,Ojibwa
|
||||
fv,fv_anishinaabemowin,Anishinaabemowin,Great Lakes - St. Lawrence,fv_anishinaabemowin_kmw-9.0.js,10.2,oj,Ojibwa
|
||||
fv,fv_bodewadminwen,Bodéwadminwen-Nishnabémwen,Great Lakes - St. Lawrence,fv_bodewadminwen_kmw-9.0.js,9.1.1,pot-Latn,Potawatomi (Latin)
|
||||
fv,fv_goyogohono,Goyogo̱hó:nǫ',Great Lakes - St. Lawrence,fv_goyogohono_kmw-9.0.js,9.2.1,cay-Latn,Cayuga (Latin)
|
||||
fv,fv_kanienkeha_e,Kanien'kéha-Kanyen'kéha,Great Lakes - St. Lawrence,fv_kanienkeha_e_kmw-9.0.js,9.1.3,moh-Latn,Mohawk (Latin)
|
||||
|
|
@ -85,7 +85,7 @@ fv,fv_nakoda,Nakoda,Prairies,fv_nakoda_kmw-9.0.js,9.1.1,asb-Latn,Assiniboine (La
|
|||
fv,fv_tsuutina,Tsúùt'ínà,Prairies,fv_tsuutina_kmw-9.0.js,9.1.1,srs-Latn,Sarsi (Latin)
|
||||
fv,fv_plains_cree,ᓀᐦᐃᔭᐍᐏᐣ (Plains Cree),Prairies,fv_plains_cree_kmw-9.0.js,11.1,crk-Cans,ᓀᐦᐃᔭᐍᐏᐣ (Cree syllabics)
|
||||
fv,fv_dine_bizaad,Diné Bizaad,South West,fv_dine_bizaad_kmw-9.0.js,9.1.1,nv-Latn,Navajo (Latin)
|
||||
fv,fv_dane_zaa_zaage,Dane-Z̲aa Z̲áágéʔ,Western Subarctic,fv_dane_zaa_zaage_kmw-9.0.js,9.4,bea,Beaver
|
||||
fv,fv_dane_zaa_zaage,Dane-Z̲aa Z̲áágéʔ,Western Subarctic,fv_dane_zaa_zaage_kmw-9.0.js,9.4.1,bea,Beaver
|
||||
fv,fv_dene_dzage,Dene Dzage,Western Subarctic,fv_dene_dzage_kmw-9.0.js,11.0.1,kkz-Latn,Kaska (Latin)
|
||||
fv,fv_dene_zhatie,Dene Zhatié,Western Subarctic,fv_dene_zhatie_kmw-9.0.js,10.2.1,den,Dene Zhatıé
|
||||
fv,fv_denesuline_epsilon,Dënesųłıné,Western Subarctic,fv_denesuline_epsilon_kmw-9.0.js,10.0.1,chp,Chipewyan
|
||||
|
|
@ -100,7 +100,7 @@ fv,fv_northern_tutchone,Northern Tutchone,Western Subarctic,fv_northern_tutchone
|
|||
fv,fv_sahugotine_yati,Sahtúgot'ı̨nę́ Yatı̨́,Western Subarctic,fv_sahugotine_yati_kmw-9.0.js,9.1.1,scs-Latn,North Slavey (Latin)
|
||||
fv,fv_shihgotine_yati,Shıhgot'ı̨nę́ Yatı̨́,Western Subarctic,fv_shihgotine_yati_kmw-9.0.js,9.1.1,scs-Latn,North Slavey (Latin)
|
||||
fv,fv_southern_tutchone,Southern Tutchone,Western Subarctic,fv_southern_tutchone_kmw-9.0.js,9.3,tce-Latn,Southern Tutchone (Latin)
|
||||
fv,fv_tagizi_dene,Tāgizi Dene,Western Subarctic,fv_tagizi_dene_kmw-9.0.js,9.3,tgx-Latn,Tagish (Latin)
|
||||
fv,fv_tagizi_dene,Tāgizi Dene,Western Subarctic,fv_tagizi_dene_kmw-9.0.js,9.4,tgx-Latn,Tagish (Latin)
|
||||
fv,fv_tlicho_yatii,Tłı̨chǫ Yatıı̀,Western Subarctic,fv_tlicho_yatii_kmw-9.0.js,9.1.1,dgr-Latn,Dogrib (Latin)
|
||||
fv,fv_dene_mb,ᑌᓀ ᔭᕠᐁ (Dene MB),Western Subarctic,fv_dene_mb_kmw-9.0.js,9.2.1,chp-Cans,Chipewyan (Unified Canadian Aboriginal Syllabics)
|
||||
fv,fv_dene_nt,ᑌᓀ ᔭᕱᐁ (Dene NT),Western Subarctic,fv_dene_nt_kmw-9.0.js,9.2.1,chp-Cans,Chipewyan (Unified Canadian Aboriginal Syllabics)
|
||||
|
|
|
|||
|
|
|
@ -32,11 +32,19 @@
|
|||
</div>
|
||||
|
||||
<div class="support_sil">
|
||||
<xsl:value-of select="$locale/string[@name='S_Support_CreatedBySIL']"/>
|
||||
<xsl:variable name="originalText" select="$locale/string[@name='S_Support_CreatedBySILGlobal']"/>
|
||||
<xsl:variable name="replacement" select="'SIL Global'"/>
|
||||
<xsl:variable name="beforePlaceholder" select="substring-before($originalText, '%0:s')"/>
|
||||
<xsl:variable name="afterPlaceholder" select="substring-after($originalText, '%0:s')"/>
|
||||
<xsl:value-of select="concat($beforePlaceholder, $replacement, $afterPlaceholder)"/>
|
||||
</div>
|
||||
|
||||
<div class="support_copyright">
|
||||
<xsl:value-of select="$locale/string[@name='S_Support_Copyright']"/>
|
||||
<xsl:variable name="originalText" select="$locale/string[@name='S_Support_CopyrightSILGlobal']"/>
|
||||
<xsl:variable name="replacement" select="'SIL Global'"/>
|
||||
<xsl:variable name="beforePlaceholder" select="substring-before($originalText, '%0:s')"/>
|
||||
<xsl:variable name="afterPlaceholder" select="substring-after($originalText, '%0:s')"/>
|
||||
<xsl:value-of select="concat($beforePlaceholder, $replacement, $afterPlaceholder)"/>
|
||||
</div>
|
||||
|
||||
<div class="support_links">
|
||||
|
|
|
|||
|
|
@ -512,6 +512,16 @@
|
|||
<!-- Introduced: 7.0.230.0 -->
|
||||
<string name="S_Support_Copyright" comment="Support - Product Copyright">Copyright © SIL International. All Rights Reserved.</string>
|
||||
|
||||
<!-- Context: Configuration Dialog - Support tab -->
|
||||
<!-- String Type: PlainText -->
|
||||
<!-- Introduced: 18.0.94.0 -->
|
||||
<string name="S_Support_CreatedBySILGlobal" comment="Created by {SIL Global} ">Created by %1$s</string>
|
||||
|
||||
<!-- Context: Configuration Dialog - Support tab -->
|
||||
<!-- String Type: PlainText -->
|
||||
<!-- Introduced: 18.0.94.0 -->
|
||||
<string name="S_Support_CopyrightSILGlobal" comment="Copyright © {SIL Global}. All Rights Reserved.">Copyright © %1$s. All Rights Reserved.</string>
|
||||
|
||||
<!-- Context: Configuration Dialog - Support tab -->
|
||||
<!-- String Type: PlainText -->
|
||||
<!-- Introduced: 7.0.230.0 -->
|
||||
|
|
|
|||
|
|
@ -660,7 +660,7 @@ export default class KeymanEngine extends KeymanEngineBase<BrowserConfiguration,
|
|||
* @param {(string)=} argLayerId name or index of layer to show, defaulting to 'default'
|
||||
* @return {Object} DIV object with filled keyboard layer content
|
||||
*
|
||||
* See https://help.keyman.com/developer/engine/web/current-version/reference/osk/BuildVisualKeyboard
|
||||
* See https://help.keyman.com/developer/engine/web/current-version/reference/core/BuildVisualKeyboard
|
||||
*/
|
||||
public BuildVisualKeyboard(
|
||||
PInternalName: string,
|
||||
|
|
|
|||
|
|
@ -29,11 +29,19 @@
|
|||
</div>
|
||||
|
||||
<div class="support_sil">
|
||||
<xsl:value-of select="$locale/string[@name='S_Support_CreatedBySIL']"/>
|
||||
<xsl:variable name="originalText" select="$locale/string[@name='S_Support_CreatedBySILGlobal']"/>
|
||||
<xsl:variable name="replacement" select="'SIL Global'"/>
|
||||
<xsl:variable name="beforePlaceholder" select="substring-before($originalText, '%0:s')"/>
|
||||
<xsl:variable name="afterPlaceholder" select="substring-after($originalText, '%0:s')"/>
|
||||
<xsl:value-of select="concat($beforePlaceholder, $replacement, $afterPlaceholder)"/>
|
||||
</div>
|
||||
|
||||
<div class="support_copyright">
|
||||
<xsl:value-of select="$locale/string[@name='S_Support_Copyright']"/>
|
||||
<xsl:variable name="originalText" select="$locale/string[@name='S_Support_CopyrightSILGlobal']"/>
|
||||
<xsl:variable name="replacement" select="'SIL Global'"/>
|
||||
<xsl:variable name="beforePlaceholder" select="substring-before($originalText, '%0:s')"/>
|
||||
<xsl:variable name="afterPlaceholder" select="substring-after($originalText, '%0:s')"/>
|
||||
<xsl:value-of select="concat($beforePlaceholder, $replacement, $afterPlaceholder)"/>
|
||||
</div>
|
||||
|
||||
<div class="support_links">
|
||||
|
|
|
|||
|
|
@ -377,6 +377,11 @@
|
|||
<!-- Introduced: 7.0.230.0 -->
|
||||
<string name="koAltGrCtrlAlt" comment="General options - Ctrl+Alt simulates AltGr on computers without AltGr">Simulate AltGr with Ctrl+Alt</string>
|
||||
|
||||
<!-- Context: Configuration Dialog - Options tab -->
|
||||
<!-- String Type: FormatString -->
|
||||
<!-- Introduced: 18.0.95 -->
|
||||
<string name="koRightModifierHK" comment="General options - Right Ctrl Alt and Shift trigger hotkey">Allow right modifier for hotkeys</string>
|
||||
|
||||
<!-- Context: Configuration Dialog - Options tab -->
|
||||
<!-- String Type: FormatString -->
|
||||
<!-- Introduced: 9.0.480.0 -->
|
||||
|
|
@ -536,6 +541,16 @@
|
|||
<!-- Introduced: 7.0.230.0 -->
|
||||
<string name="S_Support_Copyright" comment="Support - Product Copyright">Copyright © SIL International. All Rights Reserved.</string>
|
||||
|
||||
<!-- Context: Configuration Dialog - Support tab -->
|
||||
<!-- String Type: PlainText -->
|
||||
<!-- Introduced: 18.0.94.0 -->
|
||||
<string name="S_Support_CreatedBySILGlobal" comment="Created by {SIL Global} ">Created by %1$s</string>
|
||||
|
||||
<!-- Context: Configuration Dialog - Support tab -->
|
||||
<!-- String Type: PlainText -->
|
||||
<!-- Introduced: 18.0.94.0 -->
|
||||
<string name="S_Support_CopyrightSILGlobal" comment="Copyright © {SIL Global}. All Rights Reserved.">Copyright © %1$s. All Rights Reserved.</string>
|
||||
|
||||
<!-- Context: Configuration Dialog - Support tab -->
|
||||
<!-- String Type: PlainText -->
|
||||
<!-- Introduced: 7.0.230.0 -->
|
||||
|
|
|
|||
|
|
@ -139,8 +139,6 @@ Hotkey *Hotkeys::GetHotkey(DWORD hotkey)
|
|||
{
|
||||
for (int i = 0; i < m_nHotkeys; i++) {
|
||||
if (m_hotkeys[i].HotkeyValue == hotkey) {
|
||||
SendDebugMessageFormat(
|
||||
"LanguageHotkey[%d] = {HotkeyValue: %x, hkl: %x} passed in: %x", i, m_hotkeys[i].HotkeyValue, m_hotkeys[i].hkl, hotkey);
|
||||
return &m_hotkeys[i];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,6 +129,25 @@ BOOL IsTouchPanelVisible() {
|
|||
return touchPanelVisible;
|
||||
}
|
||||
|
||||
/*
|
||||
Cache AllowRightModifierHotKey for this session
|
||||
*/
|
||||
BOOL AllowRightModifierHotKey() {
|
||||
static BOOL flag_AllowRightModifierHotKey = FALSE;
|
||||
static BOOL loaded = FALSE;
|
||||
|
||||
if (!loaded) {
|
||||
RegistryReadOnly reg(HKEY_CURRENT_USER);
|
||||
if (reg.OpenKeyReadOnly(REGSZ_KeymanCU)) {
|
||||
if (reg.ValueExists(REGSZ_AllowRightModifierHotKey)) {
|
||||
flag_AllowRightModifierHotKey = !!reg.ReadInteger(REGSZ_AllowRightModifierHotKey);
|
||||
}
|
||||
}
|
||||
loaded = TRUE; // Set loaded to TRUE whether or not the key exists
|
||||
}
|
||||
return flag_AllowRightModifierHotKey;
|
||||
}
|
||||
|
||||
LRESULT _kmnLowLevelKeyboardProc(
|
||||
_In_ int nCode,
|
||||
_In_ WPARAM wParam,
|
||||
|
|
@ -150,16 +169,33 @@ LRESULT _kmnLowLevelKeyboardProc(
|
|||
|
||||
// #5190: Don't cache modifier state because sometimes we won't receive
|
||||
// modifier change events (e.g. on lock screen)
|
||||
FHotkeyShiftState = 0;
|
||||
if (GetKeyState(VK_LCONTROL) < 0) FHotkeyShiftState |= HK_CTRL;
|
||||
if (GetKeyState(VK_RCONTROL) < 0) FHotkeyShiftState |= HK_RCTRL_INVALID;
|
||||
if (GetKeyState(VK_LMENU) < 0) FHotkeyShiftState |= HK_ALT;
|
||||
if (GetKeyState(VK_RMENU) < 0) FHotkeyShiftState |= HK_RALT_INVALID;
|
||||
if (GetKeyState(VK_LSHIFT) < 0) FHotkeyShiftState |= HK_SHIFT;
|
||||
if (GetKeyState(VK_RSHIFT) < 0) FHotkeyShiftState |= HK_RSHIFT_INVALID;
|
||||
//TODO: #8064. Can remove debug message once issue #8064 is resolved
|
||||
SendDebugMessageFormat("!UseCachedHotkeyModifierState [FHotkeyShiftState:%x]", FHotkeyShiftState);
|
||||
FHotkeyShiftState = 0;
|
||||
|
||||
if (GetKeyState(VK_LCONTROL) < 0) {
|
||||
FHotkeyShiftState |= HK_CTRL;
|
||||
}
|
||||
|
||||
if (GetKeyState(VK_RCONTROL) < 0) {
|
||||
FHotkeyShiftState |= AllowRightModifierHotKey() ? HK_CTRL : HK_RCTRL_INVALID;
|
||||
}
|
||||
|
||||
if (GetKeyState(VK_LMENU) < 0) {
|
||||
FHotkeyShiftState |= HK_ALT;
|
||||
}
|
||||
|
||||
if (GetKeyState(VK_RMENU) < 0) {
|
||||
FHotkeyShiftState |= AllowRightModifierHotKey() ? HK_ALT : HK_RALT_INVALID;
|
||||
}
|
||||
|
||||
if (GetKeyState(VK_LSHIFT) < 0) {
|
||||
FHotkeyShiftState |= HK_SHIFT;
|
||||
}
|
||||
if (GetKeyState(VK_RSHIFT) < 0) {
|
||||
FHotkeyShiftState |= AllowRightModifierHotKey() ? HK_SHIFT : HK_RSHIFT_INVALID;
|
||||
}
|
||||
|
||||
//TODO: #8064. Can remove debug message once issue #8064 is resolved
|
||||
SendDebugMessageFormat("[FHotkeyShiftState:%x]", FHotkeyShiftState);
|
||||
|
||||
// #7337 Post the modifier state ensuring the serialized queue is in sync
|
||||
// Note that the modifier key may be posted again with WM_KEYMAN_KEY_EVENT,
|
||||
|
|
@ -243,30 +279,24 @@ BOOL ProcessHotkey(UINT vkCode, BOOL isUp, DWORD ShiftState) {
|
|||
|
||||
Hotkeys *hotkeys = Hotkeys::Instance(); // I4641
|
||||
if (!hotkeys) {
|
||||
SendDebugMessageFormat("Failed to get Instance");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Hotkey *hotkey = hotkeys->GetHotkey(ShiftState | vkCode); // I4641
|
||||
if (!hotkey) {
|
||||
SendDebugMessageFormat("GetHotkey Null");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (isUp) {
|
||||
SendDebugMessageFormat("Is Up");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (hotkey->HotkeyType == hktInterface) {
|
||||
SendDebugMessageFormat("PostMasterController");
|
||||
Globals::PostMasterController(wm_keyman_control, MAKELONG(KMC_INTERFACEHOTKEY, hotkey->Target), 0);
|
||||
}
|
||||
else {
|
||||
SendDebugMessageFormat("ReportKeyboardChanged");
|
||||
ReportKeyboardChanged(PC_HOTKEYCHANGE, hotkey->hkl == 0 ? TF_PROFILETYPE_INPUTPROCESSOR : TF_PROFILETYPE_KEYBOARDLAYOUT, 0, hotkey->hkl, GUID_NULL, hotkey->profileGUID);
|
||||
}
|
||||
SendDebugMessageFormat("PostDummyKeyEvent");
|
||||
/* Generate a dummy keystroke to block menu activations, etc but let the shift key through */
|
||||
PostDummyKeyEvent(); // I3301 - this is imperfect because we don't deal with HC_NOREMOVE. But good enough? // I3534 // I4844
|
||||
|
||||
|
|
|
|||
|
|
@ -121,12 +121,13 @@ type
|
|||
GroupName: string;
|
||||
end;
|
||||
|
||||
const KeymanOptionInfo: array[0..15] of TKeymanOptionInfo = ( // I3331 // I3620 // I4552
|
||||
const KeymanOptionInfo: array[0..16] of TKeymanOptionInfo = ( // I3331 // I3620 // I4552
|
||||
// Global options
|
||||
|
||||
(opt: koKeyboardHotkeysAreToggle; RegistryName: SRegValue_KeyboardHotkeysAreToggle; OptionType: kotBool; BoolValue: False; GroupName: 'kogGeneral'),
|
||||
(opt: koSwitchLanguageForAllApplications; RegistryName: SRegValue_SwitchLanguageForAllApplications; OptionType: kotBool; BoolValue: True; GroupName: 'kogGeneral'), // I2277 // I4393
|
||||
(opt: koAltGrCtrlAlt; RegistryName: SRegValue_AltGrCtrlAlt; OptionType: kotBool; BoolValue: False; GroupName: 'kogGeneral'),
|
||||
(opt: koRightModifierHK; RegistryName: SRegValue_AllowRightModifierHotKey; OptionType: kotBool; BoolValue: False; GroupName: 'kogGeneral'),
|
||||
(opt: koShowHints; RegistryName: SRegValue_EnableHints; OptionType: kotBool; BoolValue: True; GroupName: 'kogGeneral'),
|
||||
(opt: koBaseLayout; RegistryName: SRegValue_UnderlyingLayout; OptionType: kotLong; IntValue: 0; GroupName: 'kogGeneral'),
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ interface
|
|||
type
|
||||
TUtilKeymanOption = (
|
||||
// General options
|
||||
koKeyboardHotkeysAreToggle, koAltGrCtrlAlt, koReleaseShiftKeysAfterKeyPress,
|
||||
koKeyboardHotkeysAreToggle,
|
||||
koAltGrCtrlAlt,
|
||||
koRightModifierHK,
|
||||
koReleaseShiftKeysAfterKeyPress,
|
||||
koShowHints, // I1256
|
||||
// Startup options
|
||||
koTestKeymanFunctioning,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue