mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 19:17:10 +00:00
perf(ioscompanion): paste long text for atomic landing
This commit is contained in:
1 parent
2e817e3167
commit
841497cc30
2 files changed
+34
-8
No files matched your search
@@ -217,9 +217,10 @@ func TestScreenshotRejectsNonPNG(t *testing.T) {
|
|||||||
func TestInputTextFastPathSkipsFieldResolution(t *testing.T) {
|
func TestInputTextFastPathSkipsFieldResolution(t *testing.T) {
|
||||||
companion := &fakeCompanion{accessibilityJSON: "[]"}
|
companion := &fakeCompanion{accessibilityJSON: "[]"}
|
||||||
d := newTestDriver(companion)
|
d := newTestDriver(companion)
|
||||||
// "hello" is fully mappable, so the fast keyboard path runs and never reads
|
// "abc" is fully mappable and under the paste threshold, so the fast
|
||||||
// the accessibility dump for a field target.
|
// keyboard path runs and never reads the accessibility dump for a field
|
||||||
if err := d.InputText(context.Background(), "hello"); err != nil {
|
// target.
|
||||||
|
if err := d.InputText(context.Background(), "abc"); err != nil {
|
||||||
t.Fatalf("InputText: %v", err)
|
t.Fatalf("InputText: %v", err)
|
||||||
}
|
}
|
||||||
if indexOf(companion.calls, "hid") < 0 {
|
if indexOf(companion.calls, "hid") < 0 {
|
||||||
|
|||||||
@@ -99,12 +99,28 @@ type fieldTarget struct {
|
|||||||
centerY float64
|
centerY float64
|
||||||
}
|
}
|
||||||
|
|
||||||
// inputText types text into the focused field. Mappable text goes through the
|
// pasteLengthThreshold is the rune count above which mappable text still goes
|
||||||
// hardware keyboard in one HID stream; anything else falls back to the
|
// through the pasteboard. Typed keys render progressively on the simulator
|
||||||
// pasteboard. The field target is only consulted on the pasteboard path.
|
// (roughly 75ms per character), so a long typed string keeps the screen
|
||||||
|
// churning well past the HID call and stretches the post-action settle; a
|
||||||
|
// paste lands the whole value in one frame.
|
||||||
|
const pasteLengthThreshold = 3
|
||||||
|
|
||||||
|
// usesPasteboard reports whether text takes the pasteboard path: any
|
||||||
|
// unmappable rune forces it, and longer mappable text uses it so the value
|
||||||
|
// lands atomically.
|
||||||
|
func usesPasteboard(text string) bool {
|
||||||
|
_, skipped := typeString(text)
|
||||||
|
return len(skipped) > 0 || len([]rune(text)) > pasteLengthThreshold
|
||||||
|
}
|
||||||
|
|
||||||
|
// inputText types text into the focused field. Short mappable text goes
|
||||||
|
// through the hardware keyboard in one HID stream; everything else goes
|
||||||
|
// through the pasteboard. The field target is only consulted on the
|
||||||
|
// pasteboard path.
|
||||||
func inputText(ctx context.Context, run runner, text string, field fieldTarget) error {
|
func inputText(ctx context.Context, run runner, text string, field fieldTarget) error {
|
||||||
presses, skipped := typeString(text)
|
if !usesPasteboard(text) {
|
||||||
if len(skipped) == 0 {
|
presses, _ := typeString(text)
|
||||||
return run.sendHID(ctx, keyPressEvents(presses)...)
|
return run.sendHID(ctx, keyPressEvents(presses)...)
|
||||||
}
|
}
|
||||||
return pasteText(ctx, run, text, field)
|
return pasteText(ctx, run, text, field)
|
||||||
@@ -121,6 +137,15 @@ func pasteText(ctx context.Context, run runner, text string, field fieldTarget)
|
|||||||
if err := run.sendHID(ctx, pasteChordEvents()...); err != nil {
|
if err := run.sendHID(ctx, pasteChordEvents()...); err != nil {
|
||||||
return fmt.Errorf("send paste chord: %w", err)
|
return fmt.Errorf("send paste chord: %w", err)
|
||||||
}
|
}
|
||||||
|
// A warm paste lands within a frame or two; check once before paying
|
||||||
|
// the settle sleep so the common case stays fast.
|
||||||
|
quick, err := run.describeAll(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("describe accessibility: %w", err)
|
||||||
|
}
|
||||||
|
if pasteLanded(quick, field.identifier, text) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if err := run.sleep(ctx, pasteSettle); err != nil {
|
if err := run.sleep(ctx, pasteSettle); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user