Public Access
Post the terminal's focus return past the dispatch that steals it
The first fix handed Android's focus back from inside the keys' Click handlers — which fire inside the UP event's dispatch, and Avalonia's own view requests focus for itself after every handled touch dispatch returns (AvaloniaView.DispatchTouchEvent, decompiled from 12.1.1). So the platform's request ran after ours and undid it microseconds later, which is exactly what the phone showed: the terminal still lost focus. The return is now posted onto the main looper, landing one message after the dispatch that stole, and it is wired at the row for both halves of a press — DOWN steals too, and Click only exists for UP, so a keyboard detached at DOWN would otherwise stay detached for the whole length of the press. Check 11.10a now also says what a tolerable blink looks like against a failure that stays.
This commit is contained in:
1 parent
e936ab4646
commit
9bc9069425
3 files changed
+49
-32
No files matched your search
@@ -139,29 +139,27 @@ internal sealed partial class TerminalScreen : UserControl
|
||||
{
|
||||
var row = this.FindControl<StackPanel>("AccessoryKeys")!;
|
||||
|
||||
// Both halves of a press steal Android's own focus — the platform requests it for Avalonia's view
|
||||
// after dispatching every handled touch, DOWN and UP alike; TerminalFocus carries the decompiled
|
||||
// citation. Countered at the row rather than inside each key's Click, and for two reasons: Click
|
||||
// only exists for the UP half, so a keyboard detached at DOWN would stay detached for the whole
|
||||
// length of the press; and the Return is posted past the current dispatch, so its ordering against
|
||||
// the key's own handler does not matter — which is what lets one pair of handlers cover ten keys.
|
||||
row.AddHandler(PointerPressedEvent, (_, _) => TerminalFocus.Return(), RoutingStrategies.Tunnel);
|
||||
row.AddHandler(PointerReleasedEvent, (_, _) => TerminalFocus.Return(), RoutingStrategies.Tunnel);
|
||||
|
||||
foreach (var (label, bytes, latches) in Keys)
|
||||
{
|
||||
var key = CreateKey(label);
|
||||
|
||||
// TerminalFocus.Return in both, after the key has done its work: by Click time the touch has
|
||||
// already moved Android's own focus onto Avalonia's input view, and leaving it there is what
|
||||
// swaps the keyboard out from over the terminal. Returning it is free when nothing moved.
|
||||
if (latches)
|
||||
{
|
||||
controlKey = key;
|
||||
key.Click += (_, _) =>
|
||||
{
|
||||
ToggleControl();
|
||||
TerminalFocus.Return();
|
||||
};
|
||||
key.Click += (_, _) => ToggleControl();
|
||||
}
|
||||
else
|
||||
{
|
||||
key.Click += (_, _) =>
|
||||
{
|
||||
SendAsync(bytes);
|
||||
TerminalFocus.Return();
|
||||
};
|
||||
key.Click += (_, _) => SendAsync(bytes);
|
||||
}
|
||||
|
||||
row.Children.Add(key);
|
||||
@@ -213,8 +211,9 @@ internal sealed partial class TerminalScreen : UserControl
|
||||
// At the Avalonia layer, that is. Android keeps a focus of its own, and the touch that
|
||||
// presses one of these keys hands it to Avalonia's input view regardless of what Avalonia
|
||||
// decides about its element — taking the keyboard's input connection off the terminal and
|
||||
// swapping its layout mid-typing. The Click wiring in BuildAccessoryRow hands that half
|
||||
// back; see TerminalFocus for the whole story.
|
||||
// swapping its layout mid-typing. The row's own pointer handlers in BuildAccessoryRow hand
|
||||
// that half back; see TerminalFocus for the whole story, including why the handing back has
|
||||
// to be posted rather than done inline.
|
||||
Focusable = false,
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user