Fix iOS TextInputResponder (#19310)

* Fix iOS TextInputResponder

* Add null validations to TextInputResponder

* Revert
This commit is contained in:
kerams
2026-01-06 15:04:12 +01:00
committed by GitHub
parent f1703dd784
commit 66af66e609
+104 -71
View File
@@ -216,41 +216,46 @@ partial class AvaloniaView
string IUITextInput.TextInRange(UITextRange range) string IUITextInput.TextInRange(UITextRange range)
{ {
var r = (AvaloniaTextRange)range; if (range is AvaloniaTextRange r)
var surroundingText = _client.SurroundingText;
Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "IUIKeyInput.TextInRange {start} {end}", r.StartIndex, r.EndIndex);
string result = "";
if (string.IsNullOrEmpty(_markedText))
{ {
if (surroundingText != null && r.EndIndex <= surroundingText.Length) var surroundingText = _client.SurroundingText;
Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "IUIKeyInput.TextInRange {start} {end}", r.StartIndex, r.EndIndex);
string result = "";
if (string.IsNullOrEmpty(_markedText))
{ {
result = surroundingText[r.StartIndex..r.EndIndex]; if (surroundingText != null && r.EndIndex <= surroundingText.Length)
{
result = surroundingText[r.StartIndex..r.EndIndex];
}
} }
} else
else {
{ var currentSelection = _client.Selection;
var currentSelection = _client.Selection; var span = new CombinedSpan3<char>(surroundingText.AsSpan(0, currentSelection.Start),
var span = new CombinedSpan3<char>(surroundingText.AsSpan(0, currentSelection.Start), _markedText,
_markedText, surroundingText.AsSpan(currentSelection.Start, currentSelection.End - currentSelection.Start));
surroundingText.AsSpan(currentSelection.Start, currentSelection.End - currentSelection.Start)); var buf = new char[r.EndIndex - r.StartIndex];
var buf = new char[r.EndIndex - r.StartIndex]; span.CopyTo(buf, r.StartIndex);
span.CopyTo(buf, r.StartIndex); result = new string(buf);
result = new string(buf); }
} Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "result: {res}", result);
Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "result: {res}", result);
return result; return result;
}
return null!;
} }
void IUITextInput.ReplaceText(UITextRange range, string text) void IUITextInput.ReplaceText(UITextRange range, string text)
{ {
var r = (AvaloniaTextRange)range; if (range is AvaloniaTextRange r)
Logger.TryGet(LogEventLevel.Debug, ImeLog)? {
.Log(null, "IUIKeyInput.ReplaceText {start} {end} {text}", r.StartIndex, r.EndIndex, text); Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "IUIKeyInput.ReplaceText {start} {end} {text}", r.StartIndex, r.EndIndex, text);
_client.Selection = new TextSelection(r.StartIndex, r.EndIndex); _client.Selection = new TextSelection(r.StartIndex, r.EndIndex);
TextInput(text); TextInput(text);
}
} }
void IUITextInput.SetMarkedText(string markedText, NSRange selectedRange) void IUITextInput.SetMarkedText(string markedText, NSRange selectedRange)
@@ -278,23 +283,33 @@ partial class AvaloniaView
public UITextRange GetTextRange(UITextPosition fromPosition, UITextPosition toPosition) public UITextRange GetTextRange(UITextPosition fromPosition, UITextPosition toPosition)
{ {
var f = (AvaloniaTextPosition)fromPosition; if (fromPosition is AvaloniaTextPosition f && toPosition is AvaloniaTextPosition t)
var t = (AvaloniaTextPosition)toPosition; {
Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "IUIKeyInput.GetTextRange {start} {end}", f.Index, t.Index); Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "IUIKeyInput.GetTextRange {start} {end}", f.Index, t.Index);
return new AvaloniaTextRange(f.Index, t.Index);
}
return new AvaloniaTextRange(f.Index, t.Index); return null!;
} }
UITextPosition IUITextInput.GetPosition(UITextPosition fromPosition, nint offset) UITextPosition IUITextInput.GetPosition(UITextPosition fromPosition, nint offset)
{ {
var pos = (AvaloniaTextPosition)fromPosition; if (fromPosition is AvaloniaTextPosition pos)
Logger.TryGet(LogEventLevel.Debug, ImeLog) {
?.Log(null, "IUIKeyInput.GetPosition {start} {offset}", pos.Index, (int)offset); Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "IUIKeyInput.GetPosition {start} {offset}", pos.Index, (int)offset);
var res = GetPositionCore(pos, offset); var res = GetPositionCore(pos, offset);
Logger.TryGet(LogEventLevel.Debug, ImeLog)
?.Log(null, $"res: " + (res == null ? "null" : (int)res.Index)); if (res is not null)
return res!; {
Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "res: {position}", res.Index);
return res;
}
return null!;
}
return null!;
} }
private AvaloniaTextPosition? GetPositionCore(AvaloniaTextPosition pos, nint offset) private AvaloniaTextPosition? GetPositionCore(AvaloniaTextPosition pos, nint offset)
@@ -308,24 +323,29 @@ partial class AvaloniaView
return new AvaloniaTextPosition(end); return new AvaloniaTextPosition(end);
} }
UITextPosition IUITextInput.GetPosition(UITextPosition fromPosition, UITextLayoutDirection inDirection, UITextPosition IUITextInput.GetPosition(UITextPosition fromPosition, UITextLayoutDirection inDirection, nint offset)
nint offset)
{ {
var pos = (AvaloniaTextPosition)fromPosition; if (fromPosition is AvaloniaTextPosition pos)
Logger.TryGet(LogEventLevel.Debug, ImeLog) {
?.Log(null, "IUIKeyInput.GetPosition {start} {direction} {offset}", pos.Index, inDirection, (int)offset); Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "IUIKeyInput.GetPosition {start} {direction} {offset}", pos.Index, inDirection, (int)offset);
var res = GetPositionCore(pos, inDirection, offset); var res = GetPositionCore(pos, inDirection, offset);
Logger.TryGet(LogEventLevel.Debug, ImeLog)
?.Log(null, $"res: " + (res == null ? "null" : (int)res.Index)); if (res is not null)
return res!; {
Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "res: {position}", res.Index);
return res;
}
return null!;
}
return null!;
} }
private AvaloniaTextPosition? GetPositionCore(AvaloniaTextPosition fromPosition, UITextLayoutDirection inDirection, private AvaloniaTextPosition? GetPositionCore(AvaloniaTextPosition fromPosition, UITextLayoutDirection inDirection, nint offset)
nint offset)
{ {
var f = (AvaloniaTextPosition)fromPosition; var newPosition = fromPosition.Index;
var newPosition = f.Index;
switch (inDirection) switch (inDirection)
{ {
@@ -339,50 +359,63 @@ partial class AvaloniaView
} }
if (newPosition < 0) if (newPosition < 0)
return null!; return null;
if (newPosition > DocumentLength) if (newPosition > DocumentLength)
return null!; return null;
return new AvaloniaTextPosition(newPosition); return new AvaloniaTextPosition(newPosition);
} }
NSComparisonResult IUITextInput.ComparePosition(UITextPosition first, UITextPosition second) NSComparisonResult IUITextInput.ComparePosition(UITextPosition first, UITextPosition second)
{ {
var f = (AvaloniaTextPosition)first; if (first is AvaloniaTextPosition f && second is AvaloniaTextPosition s)
var s = (AvaloniaTextPosition)second; {
if (f.Index < s.Index) if (f.Index < s.Index)
return NSComparisonResult.Ascending; return NSComparisonResult.Ascending;
if (f.Index > s.Index) if (f.Index > s.Index)
return NSComparisonResult.Descending; return NSComparisonResult.Descending;
return NSComparisonResult.Same; return NSComparisonResult.Same;
}
return default;
} }
nint IUITextInput.GetOffsetFromPosition(UITextPosition fromPosition, UITextPosition toPosition) nint IUITextInput.GetOffsetFromPosition(UITextPosition fromPosition, UITextPosition toPosition)
{ {
var f = (AvaloniaTextPosition)fromPosition; if (fromPosition is AvaloniaTextPosition f && toPosition is AvaloniaTextPosition t)
var t = (AvaloniaTextPosition)toPosition; {
return t.Index - f.Index; return t.Index - f.Index;
}
return default;
} }
UITextPosition IUITextInput.GetPositionWithinRange(UITextRange range, UITextLayoutDirection direction) UITextPosition IUITextInput.GetPositionWithinRange(UITextRange range, UITextLayoutDirection direction)
{ {
var r = (AvaloniaTextRange)range; if (range is AvaloniaTextRange r)
{
if (direction is UITextLayoutDirection.Right or UITextLayoutDirection.Down)
return r.End;
return r.Start;
}
if (direction is UITextLayoutDirection.Right or UITextLayoutDirection.Down) return null!;
return r.End;
return r.Start;
} }
UITextRange IUITextInput.GetCharacterRange(UITextPosition byExtendingPosition, UITextLayoutDirection direction) UITextRange IUITextInput.GetCharacterRange(UITextPosition byExtendingPosition, UITextLayoutDirection direction)
{ {
var p = (AvaloniaTextPosition)byExtendingPosition; if (byExtendingPosition is AvaloniaTextPosition p)
if (direction is UITextLayoutDirection.Left or UITextLayoutDirection.Up) {
return new AvaloniaTextRange(0, p.Index); if (direction is UITextLayoutDirection.Left or UITextLayoutDirection.Up)
return new AvaloniaTextRange(0, p.Index);
return new AvaloniaTextRange(p.Index, DocumentLength); return new AvaloniaTextRange(p.Index, DocumentLength);
}
return null!;
} }
NSWritingDirection IUITextInput.GetBaseWritingDirection(UITextPosition forPosition, NSWritingDirection IUITextInput.GetBaseWritingDirection(UITextPosition forPosition,