mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-09 18:35:32 +00:00
fix(windows): ensure mitigation works with new registration strategy
The keyboard profile and registration strategy was not taking into account the mitigation for Win10 1803 (#1285) and this meant that the Amharic, Tigrigna and Sinhala keyboards would not install correctly.
This commit is contained in:
parent
cbc1c8a22b
commit
e83061ef80
5 changed files with 141 additions and 89 deletions
|
|
@ -145,7 +145,7 @@ function TKeymanKeyboardLanguageInstalled.FindInstallationLangID(
|
|||
out RegistrationRequired: WordBool; Flags: tagKeymanInstallFlags): WordBool;
|
||||
var
|
||||
kp: TKPInstallKeyboardLanguage;
|
||||
s: string;
|
||||
BCP47Code, s: string;
|
||||
KPFlags: TKPInstallKeyboardLanguageFlags;
|
||||
begin
|
||||
LangID := Self.Get_LangID;
|
||||
|
|
@ -160,7 +160,8 @@ begin
|
|||
KPFlags := [];
|
||||
if (Flags and kifInstallTransientLanguage) <> 0 then
|
||||
Include(KPFlags, ilkInstallTransientLanguage);
|
||||
Result := kp.FindInstallationLangID(Self.Get_BCP47Code, LangID, s, KPFlags);
|
||||
BCP47Code := Self.Get_BCP47Code;
|
||||
Result := kp.FindInstallationLangID(BCP47Code, LangID, s, KPFlags);
|
||||
|
||||
// We only need to register a TIP for user custom installations of languages:
|
||||
// languages that are suggested already have a TIP registered, and the
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ uses
|
|||
|
||||
Keyman.System.CanonicalLanguageCodeUtils,
|
||||
Keyman.System.LanguageCodeUtils,
|
||||
Keyman.System.MitigateWin10_1803LanguageInstall,
|
||||
Keyman.System.Process.KPInstallKeyboardLanguage,
|
||||
BCP47Tag,
|
||||
keymankeyboardlanguageinstalled,
|
||||
|
|
@ -85,15 +86,22 @@ var
|
|||
FKeyboardLanguage: TKeymanKeyboardLanguageInstalled;
|
||||
FCanonicalBCP47Tag: string;
|
||||
i: Integer;
|
||||
ml: TMitigateWin10_1803.TMitigatedLanguage;
|
||||
begin
|
||||
// This adds an in-memory item to the array so that it can be installed
|
||||
FCanonicalBCP47Tag := TCanonicalLanguageCodeUtils.FindBestTag(BCP47Tag, True);
|
||||
if FCanonicalBCP47Tag = '' then
|
||||
Exit(nil);
|
||||
|
||||
if TMitigateWin10_1803.IsMitigationRequired(FCanonicalBCP47Tag, ml) then
|
||||
begin
|
||||
FCanonicalBCP47Tag := ml.NewLanguage.BCP47;
|
||||
(Context as TKeymanContext).Errors.AddFmt(KMN_W_ProfileInstall_Win10_1803_MitigationApplied, VarArrayOf([ml.OriginalLanguage.Name, ml.NewLanguage.Name]), kesWarning);
|
||||
end;
|
||||
|
||||
for i := 0 to FLanguages.Count - 1 do
|
||||
if SameText((FLanguages[i] as IKeymanKeyboardLanguageInstalled).BCP47Code, FCanonicalBCP47Tag) then
|
||||
Exit(nil);
|
||||
Exit(FLanguages[i] as IKeymanKeyboardLanguageInstalled);
|
||||
|
||||
FKeyboardLanguage := TKeymanKeyboardLanguageInstalled.Create(Context, FOwner, FCanonicalBCP47Tag, 0, GUID_NULL, '');
|
||||
FLanguages.Add(FKeyboardLanguage);
|
||||
|
|
|
|||
|
|
@ -24,17 +24,20 @@ type
|
|||
NewLanguage: TLanguageReference;
|
||||
end;
|
||||
|
||||
class function IsMitigationRequired(Code: LANGID; var lang: TMitigateWin10_1803.TMitigatedLanguage): Boolean;
|
||||
class function IsMitigationRequired(Code: LANGID; var lang: TMitigateWin10_1803.TMitigatedLanguage): Boolean; overload;
|
||||
class function IsMitigationRequired(BCP47Tag: string; var lang: TMitigateWin10_1803.TMitigatedLanguage): Boolean; overload;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
System.SysUtils;
|
||||
|
||||
const
|
||||
MitigatedLanguages: array[0..2] of TMitigateWin10_1803.TMitigatedLanguage = (
|
||||
(OriginalLanguage: (Code: $005E; Name: 'Amharic'); NewLanguage: (BCP47: 'gez-Ethi-ET'; Name: 'Geez')),
|
||||
(OriginalLanguage: (Code: $0073; Name: 'Tigrinya'); NewLanguage: (BCP47: 'gez-Ethi-ET'; Name: 'Geez')),
|
||||
(OriginalLanguage: (Code: $005B; Name: 'Sinhala'); NewLanguage: (Code: $0409; Name: 'English (US)'))
|
||||
(OriginalLanguage: (Code: $005E; BCP47: 'am'; Name: 'Amharic'); NewLanguage: (BCP47: 'gez-Ethi-ET'; Name: 'Geez')),
|
||||
(OriginalLanguage: (Code: $0073; BCP47: 'ti'; Name: 'Tigrinya'); NewLanguage: (BCP47: 'gez-Ethi-ET'; Name: 'Geez')),
|
||||
(OriginalLanguage: (Code: $005B; BCP47: 'si'; Name: 'Sinhala'); NewLanguage: (Code: $0409; Name: 'English (US)'))
|
||||
);
|
||||
|
||||
{ TMitigateWin10_1803 }
|
||||
|
|
@ -86,4 +89,29 @@ begin
|
|||
Result := False;
|
||||
end;
|
||||
|
||||
class function TMitigateWin10_1803.IsMitigationRequired(BCP47Tag: string;
|
||||
var lang: TMitigateWin10_1803.TMitigatedLanguage): Boolean;
|
||||
var
|
||||
I: Integer;
|
||||
begin
|
||||
if not IsWindows10_1803_OrGreater then
|
||||
Exit(False);
|
||||
|
||||
// We only want to look at the primary language tag for comparison
|
||||
// And we assume that the tag has been canonicalized from ISO639-3 first
|
||||
BCP47Tag := LowerCase(BCP47Tag);
|
||||
I := Pos('-', BCP47Tag);
|
||||
if I > 0 then
|
||||
BCP47Tag := Copy(BCP47Tag, 1, I-1);
|
||||
|
||||
for I := Low(MitigatedLanguages) to High(MitigatedLanguages) do
|
||||
if MitigatedLanguages[I].OriginalLanguage.BCP47 = BCP47Tag then
|
||||
begin
|
||||
lang := MitigatedLanguages[I];
|
||||
Exit(True);
|
||||
end;
|
||||
// lang value undefined.
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ type
|
|||
/// a temporary keyboard if necessary to establish a transient LangID.
|
||||
/// Current User.</summary>
|
||||
/// <returns>True if a language ID can be found</return>
|
||||
/// <param name="BCP47Tag">A canonical BCP47 tag to install</param>
|
||||
/// <param name="BCP47Tag">A canonical BCP47 tag to install. May be updated
|
||||
/// for compatibility reasons; see #1285.</param>
|
||||
/// <param name="LangID">LangID found that corresponds to BCP47Tag</param>
|
||||
/// <param name="TemporaryLayoutString">If a transient LangID is installed, then
|
||||
/// Windows will have added a default keyboard for the language which should be
|
||||
|
|
@ -30,7 +31,8 @@ type
|
|||
/// <param name="Flags">If ilkInstallTransientLanguage is included in flags,
|
||||
/// will not install a transient language and will return False if no standard
|
||||
/// Windows LangID can be found that corresponds to the BCP47 tag.</param>
|
||||
function FindInstallationLangID(const BCP47Tag: string;
|
||||
function FindInstallationLangID(
|
||||
var BCP47Tag: string;
|
||||
var LangID: Integer;
|
||||
var TemporaryLayoutString: string;
|
||||
Flags: TKPInstallKeyboardLanguageFlags): Boolean;
|
||||
|
|
@ -163,92 +165,92 @@ begin
|
|||
end;
|
||||
|
||||
// TODO: change LangID to Winapi.Windows.LANGID
|
||||
function TKPInstallKeyboardLanguage.FindInstallationLangID(const BCP47Tag: string; var LangID: Integer; var TemporaryLayoutString: string; Flags: TKPInstallKeyboardLanguageFlags): Boolean;
|
||||
function TKPInstallKeyboardLanguage.FindInstallationLangID(var BCP47Tag: string; var LangID: Integer; var TemporaryLayoutString: string; Flags: TKPInstallKeyboardLanguageFlags): Boolean;
|
||||
var
|
||||
ml: TMitigateWin10_1803.TMitigatedLanguage;
|
||||
Win8Lang: TWindows8Language;
|
||||
tag: string;
|
||||
begin
|
||||
if BCP47Tag = '' then
|
||||
ErrorFmt(KMN_E_ProfileInstall_InvalidBCP47Tag, VarArrayOf([BCP47Tag]));
|
||||
|
||||
tag := BCP47Tag;
|
||||
TemporaryLayoutString := '';
|
||||
|
||||
if ConvertBCP47TagToLangID(tag, LangID) then
|
||||
if ConvertBCP47TagToLangID(BCP47Tag, LangID) then
|
||||
begin
|
||||
if TMitigateWin10_1803.IsMitigationRequired(LangID, ml) then
|
||||
begin
|
||||
LangID := ml.NewLanguage.Code;
|
||||
BCP47Tag := ml.NewLanguage.BCP47;
|
||||
WarnFmt(KMN_W_ProfileInstall_Win10_1803_MitigationApplied, VarArrayOf([ml.OriginalLanguage.Name, ml.NewLanguage.Name]));
|
||||
end;
|
||||
|
||||
if LangID <> 0 then
|
||||
Exit(True);
|
||||
end;
|
||||
|
||||
if not (ilkInstallTransientLanguage in Flags) then
|
||||
begin
|
||||
// No warning, because this is to be expected
|
||||
Exit(False);
|
||||
end;
|
||||
|
||||
//
|
||||
// Installing a custom language only supported with Win8 and later
|
||||
//
|
||||
|
||||
if not FWin8Languages.IsSupported then
|
||||
begin
|
||||
Warn(KMN_W_ProfileInstall_CustomLocalesNotSupported);
|
||||
Exit(False);
|
||||
end;
|
||||
|
||||
//
|
||||
// Windows only appears to support 4 transient languages: 0x2000, 0x2400,
|
||||
// 0x2800, 0x2C00. While Powershell will add extra languages above those,
|
||||
// it will not install TIPs for any additional languages (e.g. 0x3000+),
|
||||
// so we should stop after 4
|
||||
//
|
||||
|
||||
if AreMaximumTransientLanguagesInstalled then
|
||||
begin
|
||||
Warn(KMN_W_ProfileInstall_CustomLocalesNotSupported); // TODO new code
|
||||
Exit(False);
|
||||
end;
|
||||
|
||||
//
|
||||
// Install user language with Powershell if it isn't present
|
||||
//
|
||||
|
||||
LangID := 0;
|
||||
|
||||
if (BCP47Tag = '') or not InstallBCP47Language(BCP47Tag) then
|
||||
begin
|
||||
WarnFmt(KMN_W_ProfileInstall_FailedToInstallLanguage, VarArrayOf([BCP47Tag]));
|
||||
Exit(False);
|
||||
end;
|
||||
|
||||
//
|
||||
// Find the new language ID
|
||||
//
|
||||
|
||||
FWin8Languages.Refresh;
|
||||
Win8Lang := FWin8Languages.FindClosestByBCP47Tag(BCP47Tag);
|
||||
if not Assigned(Win8Lang) then
|
||||
begin
|
||||
WarnFmt(KMN_W_ProfileInstall_LanguageInstalledButNotFound, VarArrayOf([BCP47Tag]));
|
||||
Exit(False);
|
||||
end;
|
||||
|
||||
LangID := Win8Lang.LangID;
|
||||
|
||||
if Win8Lang.InputMethods.Count = 1 then
|
||||
begin
|
||||
TemporaryLayoutString := Win8Lang.InputMethods[0];
|
||||
end
|
||||
else
|
||||
begin
|
||||
if not (ilkInstallTransientLanguage in Flags) then
|
||||
begin
|
||||
// No warning, because this is to be expected
|
||||
Exit(False);
|
||||
end;
|
||||
|
||||
//
|
||||
// Installing a custom language only supported with Win8 and later
|
||||
//
|
||||
|
||||
if not FWin8Languages.IsSupported then
|
||||
begin
|
||||
Warn(KMN_W_ProfileInstall_CustomLocalesNotSupported);
|
||||
Exit(False);
|
||||
end;
|
||||
|
||||
//
|
||||
// Windows only appears to support 4 transient languages: 0x2000, 0x2400,
|
||||
// 0x2800, 0x2C00. While Powershell will add extra languages above those,
|
||||
// it will not install TIPs for any additional languages (e.g. 0x3000+),
|
||||
// so we should stop after 4
|
||||
//
|
||||
|
||||
if AreMaximumTransientLanguagesInstalled then
|
||||
begin
|
||||
Warn(KMN_W_ProfileInstall_CustomLocalesNotSupported); // TODO new code
|
||||
Exit(False);
|
||||
end;
|
||||
|
||||
//
|
||||
// Install user language with Powershell if it isn't present
|
||||
//
|
||||
|
||||
LangID := 0;
|
||||
|
||||
if (tag = '') or not InstallBCP47Language(tag) then
|
||||
begin
|
||||
WarnFmt(KMN_W_ProfileInstall_FailedToInstallLanguage, VarArrayOf([tag]));
|
||||
Exit(False);
|
||||
end;
|
||||
|
||||
//
|
||||
// Find the new language ID
|
||||
//
|
||||
|
||||
FWin8Languages.Refresh;
|
||||
Win8Lang := FWin8Languages.FindClosestByBCP47Tag(tag);
|
||||
if not Assigned(Win8Lang) then
|
||||
begin
|
||||
WarnFmt(KMN_W_ProfileInstall_LanguageInstalledButNotFound, VarArrayOf([tag]));
|
||||
Exit(False);
|
||||
end;
|
||||
|
||||
LangID := Win8Lang.LangID;
|
||||
|
||||
if Win8Lang.InputMethods.Count = 1 then
|
||||
begin
|
||||
TemporaryLayoutString := Win8Lang.InputMethods[0];
|
||||
end
|
||||
else
|
||||
// We'll continue on, but this is unexpected, so we won't try and uninstall the temporary input method. The user
|
||||
// will have more than one input method installed.
|
||||
WarnFmt(KMN_W_ProfileInstall_MoreThanOneInputMethodInstalled, VarArrayOf([Win8Lang.InputMethods.Text]));
|
||||
end;
|
||||
// We'll continue on, but this is unexpected, so we won't try and uninstall the temporary input method. The user
|
||||
// will have more than one input method installed.
|
||||
WarnFmt(KMN_W_ProfileInstall_MoreThanOneInputMethodInstalled, VarArrayOf([Win8Lang.InputMethods.Text]));
|
||||
|
||||
Result := True;
|
||||
end;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
(*
|
||||
Name: kpinstallkeyboard
|
||||
Copyright: Copyright (C) SIL International.
|
||||
Documentation:
|
||||
Description:
|
||||
Documentation:
|
||||
Description:
|
||||
Create Date: 20 Jun 2006
|
||||
|
||||
Modified Date: 30 Apr 2015
|
||||
Authors: mcdurdin
|
||||
Related Files:
|
||||
Dependencies:
|
||||
Related Files:
|
||||
Dependencies:
|
||||
|
||||
Bugs:
|
||||
Todo:
|
||||
Notes:
|
||||
Bugs:
|
||||
Todo:
|
||||
Notes:
|
||||
History: 20 Jun 2006 - mcdurdin - Initial version
|
||||
01 Aug 2006 - mcdurdin - Add AutoApplyKeyman call
|
||||
04 Dec 2006 - mcdurdin - Check product licence on install
|
||||
|
|
@ -82,6 +82,7 @@ uses
|
|||
Vcl.Graphics,
|
||||
|
||||
Keyman.System.LanguageCodeUtils,
|
||||
Keyman.System.MitigateWin10_1803LanguageInstall,
|
||||
Keyman.System.CanonicalLanguageCodeUtils,
|
||||
|
||||
bcp47tag,
|
||||
|
|
@ -290,17 +291,18 @@ end;
|
|||
function TKPInstallKeyboard.LegacyRegisterAndInstallLanguageProfile(const BCP47Tag, KeyboardID, KeyboardName, IconFileName, LanguageName: string): Boolean; // I3581 // I3619 // I3707 // I3768 // I4607
|
||||
var
|
||||
kpil: TKPInstallKeyboardLanguage;
|
||||
TemporaryKeyboardID: string;
|
||||
tag, TemporaryKeyboardID: string;
|
||||
LangID: Integer;
|
||||
guid: TGUID;
|
||||
begin
|
||||
Result := False;
|
||||
kpil := TKPInstallKeyboardLanguage.Create(Context);
|
||||
try
|
||||
if kpil.FindInstallationLangID(BCP47Tag, LangID, TemporaryKeyboardID, []) then
|
||||
tag := BCP47Tag;
|
||||
if kpil.FindInstallationLangID(tag, LangID, TemporaryKeyboardID, []) then
|
||||
begin
|
||||
kpil.RegisterTip(KeyboardID, BCP47Tag, KeyboardID, LangID, IconFileName, '');
|
||||
kpil.InstallTip(KeyboardID, BCP47Tag, LangID, guid);
|
||||
kpil.RegisterTip(KeyboardID, tag, KeyboardID, LangID, IconFileName, '');
|
||||
kpil.InstallTip(KeyboardID, tag, LangID, guid);
|
||||
Result := True;
|
||||
end;
|
||||
finally
|
||||
|
|
@ -326,6 +328,7 @@ var
|
|||
BCP47Tag: string;
|
||||
i: Integer;
|
||||
kpil: TKPInstallKeyboardLanguage;
|
||||
ml: TMitigateWin10_1803.TMitigatedLanguage;
|
||||
|
||||
type
|
||||
TWSLCallback = reference to procedure(r: TRegistryErrorControlled);
|
||||
|
|
@ -400,6 +403,11 @@ begin
|
|||
BCP47Tag := TCanonicalLanguageCodeUtils.FindBestTag(PackageLanguageMetadata[i].ID, True);
|
||||
if BCP47Tag <> '' then
|
||||
begin
|
||||
if TMitigateWin10_1803.IsMitigationRequired(BCP47Tag, ml) then
|
||||
begin
|
||||
BCP47Tag := ml.NewLanguage.BCP47;
|
||||
end;
|
||||
|
||||
// Note: this may return a repeated tag, but FindInstallationLangID
|
||||
// and RegisterTIP are idempotent, so it doesn't matter.
|
||||
|
||||
|
|
@ -494,6 +502,11 @@ begin
|
|||
BCP47Tag := TLanguageCodeUtils.TranslateWindowsLanguagesToBCP47(FLanguages[i]);
|
||||
if BCP47Tag <> '' then
|
||||
begin
|
||||
if TMitigateWin10_1803.IsMitigationRequired(BCP47Tag, ml) then
|
||||
begin
|
||||
BCP47Tag := ml.NewLanguage.BCP47;
|
||||
end;
|
||||
|
||||
kpil := TKPInstallKeyboardLanguage.Create(Context);
|
||||
try
|
||||
kpil.RegisterTip(kbdname, BCP47Tag, ki.KeyboardName, FLanguages[i], FIconFileName, ''); //TODO: language name
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue