Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 80 additions & 8 deletions windows/src/desktop/kmshell/main/UfrmBaseKeyboard.pas
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,36 @@ interface
TfrmBaseKeyboard = class(TfrmWebContainer)
procedure TntFormCreate(Sender: TObject);
private
FBaseKeyboardID: Integer;
procedure Footer_Cancel;
procedure Footer_OK(params: TStringList);
protected
procedure FireCommand(const command: WideString; params: TStringList); override;
end;

function ConfigureBaseKeyboard: Boolean;
function ConfigureBaseKeyboard(out BaseKeyboardID: Integer): Boolean;
function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolean;
function MCompileBaseKeyboard(const BaseKeyboardIDText: string): Boolean;
function CompileForBaseKeyboard(BaseKeyboardID: Integer): Boolean;

implementation

{$R *.dfm}

uses
BaseKeyboards,
kmint;
ErrorControlledRegistry,
RegistryKeys,
keymanapi_TLB,
kmint,
utilkmshell;

function ConfigureBaseKeyboard: Boolean;
begin
with TfrmBaseKeyboard.Create(nil) do
function ConfigureBaseKeyboard(out BaseKeyboardID: Integer): Boolean;
begin with TfrmBaseKeyboard.Create(nil) do

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
begin with TfrmBaseKeyboard.Create(nil) do
begin
with TfrmBaseKeyboard.Create(nil) do

try
Result := ShowModal = mrOk;
if Result then
kmcom.Apply;
BaseKeyboardID := FBaseKeyboardID;
finally
Free;
end;
Expand Down Expand Up @@ -65,9 +72,74 @@ procedure TfrmBaseKeyboard.Footer_OK(params: TStringList);
v: Integer;
begin
if not TryStrToInt('$'+params.Values['id'], v) then Exit;
kmcom.Options['koBaseLayout'].Value := v;
kmcom.Options.Apply;
FBaseKeyboardID := v;
ModalResult := mrOk;
end;

function MCompileBaseKeyboard(const BaseKeyboardIDText: string): Boolean;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should move this into its own unit

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has changed a fair bit since this comment is it still valid. However, looking at it these 3 functions could be in there own unit around "Setting Base Keyboard" and are not tightly coupled to a form.

function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolean;
function MCompileBaseKeyboard(const BaseKeyboardIDText: string): Boolean;
function CompileForBaseKeyboard(BaseKeyboardID: Integer): Boolean;

var
BaseKeyboardID: Integer;
begin
Result := False;
if not TryStrToInt('$' + BaseKeyboardIDText, BaseKeyboardID) or
not kmcom.SystemInfo.IsAdministrator then
Exit;
Result := CompileForBaseKeyboard(BaseKeyboardID);
end;

function BaseKeyboardNeedsMCompile(BaseKeyboardID: Integer): Boolean;
var
I: Integer;
Keyboard: IKeymanKeyboardInstalled;
BaseFileName: string;
BaseKeyboardIDHex: string;
begin
BaseKeyboardIDHex := IntToHex(BaseKeyboardID, 8);
for I := 0 to kmcom.Keyboards.Count - 1 do
begin
Keyboard := kmcom.Keyboards.Items[I];
BaseFileName := Keyboard.Filename;
if FileExists(BaseFileName) and
(not FileExists(ChangeFileExt(BaseFileName, '') + '-' + BaseKeyboardIDHex + '.kmx') or
not FileExists(ChangeFileExt(BaseFileName, '') + '-' + BaseKeyboardIDHex + '-d.kmx')) then
Exit(True);
end;
Result := False;
end;

function SetBaseKeyboard(WindowHandle: THandle; BaseKeyboardID: Integer): Boolean;
var
MCompileResult: Boolean;
begin
MCompileResult := True;
Result := False;
if BaseKeyboardNeedsMCompile(BaseKeyboardID) then
begin
if not kmcom.SystemInfo.IsAdministrator then
begin
MCompileResult := WaitForElevatedConfiguration(WindowHandle, '-mcompilekbds ' + IntToHex(BaseKeyboardID, 8)) = 0;
end
else
MCompileResult := CompileForBaseKeyboard(BaseKeyboardID);
end;
if not MCompileResult then
Exit;

kmcom.Options['koBaseLayout'].Value := BaseKeyboardID;
kmcom.Options.Apply;
Result := True;
end;

function CompileForBaseKeyboard(BaseKeyboardID: Integer): Boolean;
var
i: Integer;
kbd: IKeymanKeyboardInstalled;
begin
for i := 0 to kmcom.Keyboards.Count - 1 do
begin
kbd := kmcom.Keyboards[i];
(kbd as IKeymanKeyboardInstalled2).MCompileForBaseKeyboard(BaseKeyboardID);
end;
end;

end.
11 changes: 9 additions & 2 deletions windows/src/desktop/kmshell/main/UfrmMain.pas
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ implementation
Keyman.Configuration.UI.UfrmStartInstall,
RegistryKeys,
SupportXMLRenderer,
UfrmBaseKeyboard,
UfrmChangeHotkey,
UfrmHTML,
UfrmInstallKeyboardFromWeb,
Expand Down Expand Up @@ -661,9 +662,15 @@ procedure TfrmMain.cefBeforeBrowseSync(Sender: TObject; const Url: string;
------------------------------------------------------------------------------}

procedure TfrmMain.Options_BaseKeyboard; // I4169
var
BaseKeyboardID: Integer;
begin
WaitForElevatedConfiguration(Handle, '-basekeyboard');
// Refresh will be triggered by elevated process
if ConfigureBaseKeyboard(BaseKeyboardID) then
begin
SetBaseKeyboard(Handle, BaseKeyboardID);
DoRefresh;
end;

end;

procedure TfrmMain.Options_SettingsManager;
Expand Down
16 changes: 15 additions & 1 deletion windows/src/desktop/kmshell/main/initprog.pas
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ function Main(Owner: TComponent = nil): TModalResult;
fmKeyboardWelcome, // I2569
fmKeyboardPrint, // I2329
fmBaseKeyboard, // I4169
fmMCompileKbds,
fmUpgradeMnemonicLayout, // I4553
fmRepair,
fmKeepInTouch,
Expand Down Expand Up @@ -262,6 +263,13 @@ function Init(var FMode: TKMShellMode; KeyboardFileNames: TStrings; var FSilent,
else if s = '-bd' then FMode := fmBackgroundDownload
else if s = '-an' then FMode := fmApplyInstallNow
else if s = '-basekeyboard' then FMode := fmBaseKeyboard // I4169
else if s = '-mcompilekbds' then
begin
FMode := fmMCompileKbds;
Inc(i);
if i > ParamCount then Exit;
FQuery := ParamStr(i);
end
else if s = '-nowelcome' then FNoWelcome := True
else if s = '-kw' then FMode := fmKeyboardWelcome // I2569
else if s = '-kp' then FMode := fmKeyboardPrint // I2329
Expand Down Expand Up @@ -393,6 +401,7 @@ procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FF
kdl: IKeymanDefaultLanguage;
FIcon: string;
FMutex: TKeymanMutex; // I2720
BaseKeyboardID: Integer;
function FirstKeyboardFileName: WideString;
begin
if KeyboardFileNames.Count = 0
Expand Down Expand Up @@ -540,7 +549,12 @@ procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FF
end;

fmBaseKeyboard: // I4169
if ConfigureBaseKeyboard
if ConfigureBaseKeyboard(BaseKeyboardID) and SetBaseKeyboard(0, BaseKeyboardID)
then ExitCode := 0
else ExitCode := 1;

fmMCompileKbds:
if MCompileBaseKeyboard(FQuery)
then ExitCode := 0
else ExitCode := 1;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ TKeymanKeyboardInstalled = class;
TKeymanKeyboardInstalled = class( // I3581
TKeymanKeyboard,
IIntKeymanKeyboardInstalled,
IKeymanKeyboardInstalled)
IKeymanKeyboardInstalled,
IKeymanKeyboardInstalled2)
private
FRegKeyboard: TRegKeyboard;
FVisualKeyboard: IKeymanVisualKeyboard;
Expand Down Expand Up @@ -112,6 +113,9 @@ TKeymanKeyboardInstalled = class( // I3581
procedure UpdateBaseLayout; // I4169
procedure RefreshInstallation;

{ IKeymanKeyboardInstalled2 }
procedure MCompileForBaseKeyboard(KLID: Integer); safecall;

public
constructor Create(AContext: TKeymanContext; const Name: string);
destructor Destroy; override;
Expand Down Expand Up @@ -152,14 +156,19 @@ procedure TKeymanKeyboardInstalled.Uninstall;
end;

procedure TKeymanKeyboardInstalled.UpdateBaseLayout; // I4169

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could now be removed

var
BaseKeyboardID: Integer;
begin
if FRegKeyboard.MnemonicLayout and FileExists(FRegKeyboard.KeymanFile) then // I4615
begin
BaseKeyboardID := (Context.Options as IKeymanOptions).Items['koBaseLayout'].Value;
Comment thread
rc-swag marked this conversation as resolved.
with TKPRecompileMnemonicKeyboard.Create(Context) do
try
Execute(FRegKeyboard.KeymanFile, FRegKeyboard.PackageName);
Execute(FRegKeyboard.KeymanFile, FRegKeyboard.PackageName, BaseKeyboardID);
finally
Free;
end;
end;
end;

function TKeymanKeyboardInstalled.Get_Copyright: WideString;
Expand Down Expand Up @@ -471,5 +480,21 @@ function TKeymanKeyboardInstalled.RegKeyboard: TRegKeyboard;
Result := FRegKeyboard;
end;

{ IKeymanKeyboardInstalled2 }
procedure TKeymanKeyboardInstalled.MCompileForBaseKeyboard(KLID: Integer); safecall;
var
RecompileMnemonicKeyboard: TKPRecompileMnemonicKeyboard;
begin
if FRegKeyboard.MnemonicLayout and FileExists(FRegKeyboard.KeymanFile) then
begin
RecompileMnemonicKeyboard := TKPRecompileMnemonicKeyboard.Create(Context);
try
RecompileMnemonicKeyboard.Execute(FRegKeyboard.KeymanFile, FRegKeyboard.PackageName, KLID);
finally
RecompileMnemonicKeyboard.Free;
end;
end;
end;

end.

36 changes: 8 additions & 28 deletions windows/src/engine/kmcomapi/com/options/keymanoptions.pas
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
(*
Name: keymanoptions
Copyright: Copyright (C) SIL International.
Documentation:
Description:
Documentation:
Description:
Create Date: 20 Jun 2006

Modified Date: 6 Feb 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 AutoRefershKeyman call
12 Aug 2008 - mcdurdin - Avoid crash with missing options
Expand Down Expand Up @@ -67,6 +67,7 @@ implementation
ErrorControlledRegistry,
RegistryKeys,
Glossary,
isadmin,
Keyman.System.BaseKeyboard,
KeymanOptionNames,
keymanerrorcodes;
Expand Down Expand Up @@ -111,29 +112,8 @@ function TKeymanOptions.IndexOf(const ID: WideString): Integer;
end;

procedure TKeymanOptions.Apply;
var
I, FOldBaseLayout: Integer;
begin
with TRegistryErrorControlled.Create do // I3717
try
if OpenKey(SRegKey_KeymanEngine_CU, True) then
begin
if ValueExists(SRegValue_UnderlyingLayout)
then FOldBaseLayout := StrToIntDef('$'+ReadString(SRegValue_UnderlyingLayout),0) // I3759
else FOldBaseLayout := TBaseKeyboard.GetDefaultBaseLayoutID;
end
else
FOldBaseLayout := TBaseKeyboard.GetDefaultBaseLayoutID;
finally
Free;
end;

FInternalOptions.Save(Context);

if FOldBaseLayout <> Get_Items('koBaseLayout').Value then
for I := 0 to Context.Keyboards.Count - 1 do // I4169
(Context.Keyboards.Items[I] as IIntKeymanKeyboardInstalled).UpdateBaseLayout;

Context.Control.AutoApplyKeyman;
end;

Expand Down
10 changes: 10 additions & 0 deletions windows/src/engine/kmcomapi/keymanapi_TLB.pas

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions windows/src/engine/kmcomapi/kmcomapi.ridl
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ library keymanapi
interface IKeymanKeyboardLanguagesInstalled;
interface IKeymanKeyboardLanguagesFile;
interface IKeymanKeyboardsInstalled2;
interface IKeymanKeyboardInstalled2;
interface IKeymanPackagesInstalled2;
interface IKeymanKeyboardFile2;
interface IKeymanPackageFile2;
Expand Down Expand Up @@ -936,6 +937,19 @@ library keymanapi
HRESULT _stdcall RefreshInstalledKeyboards(void);
};

[
uuid(3086C85C-932A-4726-BF76-2D74DD133AC9),
version(19.0),
helpstring("https://help.keyman.com/developer/engine/windows/19.0/api/IKeymanKeyboardInstalled2"),
dual,
oleautomation
]
interface IKeymanKeyboardInstalled2: IKeymanKeyboardInstalled
{
[id(0x00000120)]
HRESULT _stdcall MCompileForBaseKeyboard(long KLID);
};

[
uuid(F23B9848-2AEF-4A2B-BC3A-292E3A00D691),
version(14.0),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ procedure TKPInstallKeyboard.Execute(const FileName, PackageID: string; FInstall
FExitCode: Integer;
FKVKName: WideString;
FCreatedIcon: Boolean;
BaseKeyboardID: Integer;
begin
KL.MethodEnter(Self, 'Execute', [FileName,PackageID,ikPartOfPackage in FInstallOptions ,Force]);
try
Expand Down Expand Up @@ -248,9 +249,11 @@ procedure TKPInstallKeyboard.Execute(const FileName, PackageID: string; FInstall
// Recompile a mnemonic layout to the user's selected base layout
if ki.MnemonicLayout then // I4169
begin
with Context as TKeymanContext do
BaseKeyboardID := (Options as IKeymanOptions).Items['koBaseLayout'].Value;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will this still get the admin value of base layout? do we need to be able to pass baselayout as a param to elevated kmshell?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm yes I think we do. I just realised I have it resolved this case where it is on the install of new keyboard. We need get the users baselayout

with TKPRecompileMnemonicKeyboard.Create(Context) do
try
Execute(FDestFileName, PackageID);
Execute(FDestFileName, PackageID, BaseKeyboardID);
finally
Free;
end;
Expand Down
Loading