modified PopupLayout

This commit is contained in:
2026-08-09 20:24:21 +05:00
parent 1fc9765a3d
commit 163b86d239
6 changed files with 193 additions and 69 deletions
+37 -7
View File
@@ -27,29 +27,54 @@ public sealed class KeyboardLayoutOptions
public sealed class KeyboardLayoutService : IKeyboardLayoutService, IDisposable
{
private readonly DispatcherTimer _pollTimer;
private readonly Func<IntPtr> _getForegroundWindow;
private readonly Func<int> _getActiveLocaleId;
private readonly Action _requestNextLayout;
private int _lastLocaleId = -1;
private IntPtr _lastForegroundWindow;
public KeyboardLayoutService(KeyboardLayoutOptions options)
: this(
options,
KeyboardLayoutNative.GetForegroundWindow,
KeyboardLayoutNative.GetActiveLocaleId,
KeyboardLayoutNative.RequestNextLayout)
{
}
/// <summary>
/// Takes the sources of system information explicitly: in tests the layout and the
/// active window are not provided by Windows.
/// </summary>
internal KeyboardLayoutService(
KeyboardLayoutOptions options,
Func<IntPtr> getForegroundWindow,
Func<int> getActiveLocaleId,
Action requestNextLayout)
{
_getForegroundWindow = getForegroundWindow;
_getActiveLocaleId = getActiveLocaleId;
_requestNextLayout = requestNextLayout;
_pollTimer = new DispatcherTimer { Interval = options.PollInterval };
_pollTimer.Tick += OnTick;
}
public event EventHandler<LayoutChangedEventArgs>? LayoutChanged;
public KeyboardLayout Current => KeyboardLayout.FromLocaleId(KeyboardLayoutNative.GetActiveLocaleId());
public KeyboardLayout Current => KeyboardLayout.FromLocaleId(_getActiveLocaleId());
public void Start()
{
_lastForegroundWindow = KeyboardLayoutNative.GetForegroundWindow();
_lastLocaleId = KeyboardLayoutNative.GetActiveLocaleId();
_lastForegroundWindow = _getForegroundWindow();
_lastLocaleId = _getActiveLocaleId();
_pollTimer.Start();
}
public void Stop() => _pollTimer.Stop();
public void SwitchToNext() => KeyboardLayoutNative.RequestNextLayout();
public void SwitchToNext() => _requestNextLayout();
public void Dispose()
{
@@ -57,9 +82,14 @@ public sealed class KeyboardLayoutService : IKeyboardLayoutService, IDisposable
_pollTimer.Tick -= OnTick;
}
private void OnTick(object? sender, EventArgs e)
private void OnTick(object? sender, EventArgs e) => Poll();
// A single poll step. Called by the timer, and in tests — directly:
// there is no point waiting for a tick to check how the reason for a layout
// change is decided
internal void Poll()
{
IntPtr foreground = KeyboardLayoutNative.GetForegroundWindow();
IntPtr foreground = _getForegroundWindow();
if (foreground == IntPtr.Zero)
{
return;
@@ -68,7 +98,7 @@ public sealed class KeyboardLayoutService : IKeyboardLayoutService, IDisposable
bool appSwitched = foreground != _lastForegroundWindow;
_lastForegroundWindow = foreground;
int localeId = KeyboardLayoutNative.GetActiveLocaleId();
int localeId = _getActiveLocaleId();
if (localeId == _lastLocaleId)
{
return;