using global::Android.Views; namespace DodoSSH.Client.Android.Platform; /// /// Hands native focus back to the terminal's WebView after Avalonia chrome took it. /// /// /// /// The sibling of , and it exists for the same reason that one does: the /// keyboard over a terminal belongs to the WebView's own native view, which Avalonia's focus manager does /// not own. The accessory row's keys are already Focusable=false — see TerminalScreen — so Avalonia's /// idea of focus never leaves the terminal when one is tapped. What still moves is Android's: the /// tap lands on Avalonia's own input view, which is focusable-in-touch-mode because Avalonia's text boxes /// need it to be, and the platform hands that view focus on the way to delivering the touch. The WebView's /// input connection dies with its focus, the keyboard swaps to the layout it shows an editor that takes no /// text, and the inset churn that follows can leave it sitting on top of the very row that was tapped. /// /// /// So each accessory key hands focus straight back once its byte is on the wire. The page inside the /// WebView never noticed anything — its own DOM focus never moved — so regaining native focus re-establishes /// the same input connection and the keyboard settles back to what it was. Skipped when the WebView is still /// focused, which makes the call free on any platform arrangement where the steal never happened. /// /// /// Found by walking the decor view rather than asked of the NativeWebView control, because the /// control does not expose its platform child and this application only ever has the one WebView — the /// walk's first match is necessarily the terminal. Every step is allowed to be absent, exactly as /// 's are: no activity while backgrounded, no WebView while the terminal /// surface has never been shown, and nothing to do in either case. /// /// internal static class TerminalFocus { public static void Return() { if (PhoneEnvironment.CurrentActivity?.Window?.DecorView is not ViewGroup decor) { return; } if (FindWebView(decor) is { IsFocused: false } webView) { webView.RequestFocus(); } } private static View? FindWebView(ViewGroup parent) { for (var i = 0; i < parent.ChildCount; i++) { switch (parent.GetChildAt(i)) { case global::Android.Webkit.WebView webView: return webView; case ViewGroup child when FindWebView(child) is { } found: return found; } } return null; } }