mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-05 07:07:41 +00:00
[Windows] More tidyup and robustness for metro app support - debug cleanup and serialization of input (not quite finished) [windows] Refactor serialized input code when used with key event thread model [windows] Add consistent precompiled headers for other projects [windows] Merge console window test into metro support [Windows] Tidy up work and identify additional TODOs for metro-style app support [Windows] Ensure error case falls through to default hook processing for console windows [Windows] Refactor shared memory into memory mapped file so we can cross 32-64 bit boundary [Windows] Tweaks to C++ security calls and parameters [Windows] Start refactor of SerialKeyEvent* classes [Windows] Rename to SerialKeyEventServer (refactoring) [Windows] Complete refactoring of SerialKeyEventClient class [Windows] Further encapsulation and cleanup with 'interfaces' to reduce header pollution [Windows] Complete serialization fix with move of modifier state management from client thread to server thread to guarantee consistency [Windows] Replace atom-based keyboard switching with memory mapped file indexed to avoid security constraints [Windows] Fixup Left Alt+Shift interaction with serializer [Windows] Use Windows 8.1 SDK for test
142 lines
3.3 KiB
ObjectPascal
142 lines
3.3 KiB
ObjectPascal
unit GlobalKeyboardChangeManager;
|
|
|
|
interface
|
|
|
|
uses
|
|
Winapi.Windows,
|
|
Winapi.Messages,
|
|
System.Classes,
|
|
System.SysUtils,
|
|
|
|
Keyman.System.SharedBuffers,
|
|
LangSwitchManager;
|
|
|
|
type
|
|
TGlobalKeyboardChangeManager = class(TThread)
|
|
private type
|
|
TLastKeyboard = record
|
|
TIP: TSelectKeyboardBuffer;
|
|
Keyboard: HKL;
|
|
end;
|
|
private var
|
|
FWindow: HWND;
|
|
FLastKeyboard: TLastKeyboard;
|
|
procedure WndProc(var Message: TMessage);
|
|
procedure ProcessChange(Mode: Integer; Param: NativeUInt);
|
|
protected
|
|
procedure Execute; override;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
|
|
procedure PostChange(Keyboard: TLangSwitchKeyboard);
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
Keyman.System.DebugLogClient,
|
|
UfrmKeyman7Main;
|
|
|
|
const
|
|
WM_USER_DESTROY = WM_USER + 1;
|
|
WM_USER_CHANGE = WM_USER + 2;
|
|
|
|
{ TGlobalKeyboardChangeManager }
|
|
|
|
constructor TGlobalKeyboardChangeManager.Create;
|
|
begin
|
|
inherited Create(False);
|
|
end;
|
|
|
|
destructor TGlobalKeyboardChangeManager.Destroy;
|
|
begin
|
|
if FWindow <> 0 then
|
|
PostMessage(FWindow, WM_USER_DESTROY, 0, 0);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TGlobalKeyboardChangeManager.Execute;
|
|
var
|
|
msg: TMsg;
|
|
begin
|
|
FWindow := AllocateHwnd(WndProc); // TODO: Not thread safe!
|
|
while GetMessage(msg, 0, 0, 0) do
|
|
begin
|
|
DispatchMessage(msg);
|
|
end;
|
|
DeallocateHwnd(FWindow);
|
|
end;
|
|
|
|
procedure TGlobalKeyboardChangeManager.PostChange(
|
|
Keyboard: TLangSwitchKeyboard);
|
|
var
|
|
TIP: TLangSwitchKeyboard_TIP;
|
|
WinKB: TLangSwitchKeyboard_WinKeyboard;
|
|
lk: TLastKeyboard;
|
|
FIdentity: DWORD;
|
|
begin
|
|
lk := FLastKeyboard;
|
|
|
|
if Keyboard is TLangSwitchKeyboard_TIP then
|
|
begin
|
|
TIP := Keyboard as TLangSwitchKeyboard_TIP;
|
|
|
|
lk.TIP.LangID := TIP.Profile.langid;
|
|
lk.TIP.CLSID := TIP.Profile.clsid;
|
|
lk.TIP.GUIDProfile := TIP.Profile.guidProfile;
|
|
TDebugLogClient.Instance.WriteMessage('TGlobalKeyboardChangeManager.PostChange TIP', []);
|
|
|
|
if not CompareMem(@lk, @FLastKeyboard, SizeOf(TLastKeyboard)) then
|
|
begin
|
|
FLastKeyboard := lk;
|
|
FIdentity := TSharedBufferManager.Identity.WriteSelectKeyboardBuffer(lk.TIP);
|
|
PostMessage(FWindow, WM_USER_CHANGE, KMCI_SELECTKEYBOARD_BACKGROUND_TSF, FIdentity);
|
|
end;
|
|
end
|
|
else if Keyboard is TLangSwitchKeyboard_WinKeyboard then
|
|
begin
|
|
WinKB := Keyboard as TLangSwitchKeyboard_WinKeyboard;
|
|
lk.Keyboard := WinKB.HKL;
|
|
|
|
TDebugLogClient.Instance.WriteMessage('TGlobalKeyboardChangeManager.PostChange HKL', []);
|
|
|
|
if not CompareMem(@lk, @FLastKeyboard, SizeOf(TLastKeyboard)) then
|
|
begin
|
|
FLastKeyboard := lk;
|
|
PostMessage(FWindow, WM_USER_CHANGE, KMCI_SELECTKEYBOARD_BACKGROUND, lk.Keyboard);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
Exit;
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TGlobalKeyboardChangeManager.ProcessChange(Mode: Integer; Param: NativeUInt);
|
|
begin
|
|
SendMessageTimeout(HWND_BROADCAST, wm_keyman_control_internal, Mode, Param, SMTO_ABORTIFHUNG, 250, nil);
|
|
end;
|
|
|
|
procedure TGlobalKeyboardChangeManager.WndProc(var Message: TMessage);
|
|
begin
|
|
with Message do
|
|
begin
|
|
case Message.Msg of
|
|
WM_USER_DESTROY:
|
|
DestroyWindow(FWindow);
|
|
WM_DESTROY:
|
|
begin
|
|
PostQuitMessage(0);
|
|
Result := 0;
|
|
end;
|
|
WM_USER_CHANGE:
|
|
ProcessChange(WParam, LParam);
|
|
else
|
|
Message.Result := DefWindowProc(FWindow, Msg, WParam, LParam);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
end.
|