using System.Runtime.InteropServices;
using Avalonia.Controls;
namespace DodoSSH.Client.App.Views;
///
/// Moves the window's keyboard focus back out of the terminal's native child window.
///
///
///
/// The two directions across this boundary are not symmetric, and only one of them needs anything
/// like this. is Focusable by default and its OnGotFocus
/// calls the adapter's Focus(), which on Windows is
/// ICoreWebView2Controller::MoveFocus(PROGRAMMATIC) — so an ordinary Avalonia
/// Focus() call on the control really does hand Win32 focus to WebView2. Measured: focus
/// lands on the Chrome_WidgetWin_1 child and the page reports
/// document.hasFocus() == true. Nothing custom is needed to give the terminal the keyboard.
///
///
/// Coming back is where the package stops helping. OnLostFocus calls the adapter's
/// ResignFocus(), and on Windows that method is empty — so moving Avalonia's focus to
/// another control leaves Win32 focus on WebView2. Measured: after textBox.Focus() the
/// focused element is the TextBox while GetFocus() is still the WebView2 child and the
/// page still reports focus, which is a text box that shows a caret and silently receives nothing.
/// Window.Activate() and Window.Focus() were both measured and neither recovers it.
/// A real mouse click does, because Avalonia's window sets focus on pointer input — which is why the
/// symptom is invisible to anyone who clicks before typing.
///
///
/// So the hand-back has to be the Win32 call. This is safe to run at any time, including while the
/// application is in the background: both windows live on this thread's message queue, and
/// SetFocus confined to one queue changes which window receives keys without activating
/// anything or taking focus from another application.
///
///
internal static class NativeKeyboardFocus
{
///
/// Returns keyboard focus to 's own window, so that Avalonia's focused
/// element receives keystrokes again.
///
///
/// Focus an element afterwards. Collapsing the terminal leaves Avalonia with no focused element
/// at all, so handing the keyboard back without also choosing a target means keystrokes reach
/// the window and stop there.
///
internal static void ReturnTo(Window window)
{
// Only Windows hosts the WebView in a child window today. Elsewhere this is either
// unnecessary or wrong, and doing nothing is the honest option until a spike says otherwise
// — see docs/platform-flags.md on the unproven Linux backend.
if (!OperatingSystem.IsWindows())
{
return;
}
if (window.TryGetPlatformHandle()?.Handle is { } handle && handle != IntPtr.Zero)
{
SetFocus(handle);
}
}
///
/// DllImport rather than the source-generated LibraryImport, which requires
/// AllowUnsafeBlocks for the whole project. The signature is blittable, so there is no
/// marshalling stub for the generator to improve on, and turning unsafe code on across a client
/// that handles key material to save nothing would be a poor trade. Hence the SYSLIB1054
/// suppression rather than a fix.
///
#pragma warning disable SYSLIB1054
[DllImport("user32.dll")]
private static extern IntPtr SetFocus(IntPtr window);
#pragma warning restore SYSLIB1054
}