fix: ios keyboard, composing input (#8471)

* fix: ios keyboard, composing input

Signed-off-by: fufesou <linlong1266@gmail.com>

* Incorrect changes

Signed-off-by: fufesou <linlong1266@gmail.com>

---------

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou 2024-06-26 00:24:57 +08:00 committed by GitHub
parent f0dcc91907
commit 11bdd3cfcd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -55,6 +55,9 @@ class _RemotePageState extends State<RemotePage> {
InputModel get inputModel => gFFI.inputModel; InputModel get inputModel => gFFI.inputModel;
SessionID get sessionId => gFFI.sessionId; SessionID get sessionId => gFFI.sessionId;
final TextEditingController _textController =
TextEditingController(text: initText);
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -145,37 +148,59 @@ class _RemotePageState extends State<RemotePage> {
setState(() {}); setState(() {});
} }
// handle mobile virtual keyboard void _handleIOSSoftKeyboardInput(String newValue) {
void handleSoftKeyboardInput(String newValue) {
var oldValue = _value; var oldValue = _value;
_value = newValue; _value = newValue;
if (isIOS) { var i = newValue.length - 1;
var i = newValue.length - 1; for (; i >= 0 && newValue[i] != '\1'; --i) {}
for (; i >= 0 && newValue[i] != '\1'; --i) {} var j = oldValue.length - 1;
var j = oldValue.length - 1; for (; j >= 0 && oldValue[j] != '\1'; --j) {}
for (; j >= 0 && oldValue[j] != '\1'; --j) {} if (i < j) j = i;
if (i < j) j = i; var subNewValue = newValue.substring(j + 1);
newValue = newValue.substring(j + 1); var subOldValue = oldValue.substring(j + 1);
oldValue = oldValue.substring(j + 1);
var common = 0; // get common prefix of subNewValue and subOldValue
for (; var common = 0;
common < oldValue.length && for (;
common < newValue.length && common < subOldValue.length &&
newValue[common] == oldValue[common]; common < subNewValue.length &&
++common) {} subNewValue[common] == subOldValue[common];
for (i = 0; i < oldValue.length - common; ++i) { ++common) {}
inputModel.inputKey('VK_BACK');
} // get newStr from subNewValue
if (newValue.length > common) { var newStr = "";
var s = newValue.substring(common); if (subNewValue.length > common) {
if (s.length > 1) { newStr = subNewValue.substring(common);
bind.sessionInputString(sessionId: sessionId, value: s);
} else {
inputChar(s);
}
}
return;
} }
// Set the value to the old value and early return if is still composing. (1 && 2)
// 1. The composing range is valid
// 2. The new string is shorter than the composing range.
if (_textController.value.isComposingRangeValid) {
final composingLength = _textController.value.composing.end -
_textController.value.composing.start;
if (composingLength > newStr.length) {
_value = oldValue;
return;
}
}
// Delete the different part in the old value.
for (i = 0; i < subOldValue.length - common; ++i) {
inputModel.inputKey('VK_BACK');
}
// Input the new string.
if (newStr.length > 1) {
bind.sessionInputString(sessionId: sessionId, value: newStr);
} else {
inputChar(newStr);
}
}
void _handleNonIOSSoftKeyboardInput(String newValue) {
var oldValue = _value;
_value = newValue;
if (oldValue.isNotEmpty && if (oldValue.isNotEmpty &&
newValue.isNotEmpty && newValue.isNotEmpty &&
oldValue[0] == '\1' && oldValue[0] == '\1' &&
@ -214,6 +239,15 @@ class _RemotePageState extends State<RemotePage> {
} }
} }
// handle mobile virtual keyboard
void handleSoftKeyboardInput(String newValue) {
if (isIOS) {
_handleIOSSoftKeyboardInput(newValue);
} else {
_handleNonIOSSoftKeyboardInput(newValue);
}
}
void inputChar(String char) { void inputChar(String char) {
if (char == '\n') { if (char == '\n') {
char = 'VK_RETURN'; char = 'VK_RETURN';
@ -227,6 +261,7 @@ class _RemotePageState extends State<RemotePage> {
gFFI.invokeMethod("enable_soft_keyboard", true); gFFI.invokeMethod("enable_soft_keyboard", true);
// destroy first, so that our _value trick can work // destroy first, so that our _value trick can work
_value = initText; _value = initText;
_textController.text = _value;
setState(() => _showEdit = false); setState(() => _showEdit = false);
_timer?.cancel(); _timer?.cancel();
_timer = Timer(kMobileDelaySoftKeyboard, () { _timer = Timer(kMobileDelaySoftKeyboard, () {
@ -491,7 +526,7 @@ class _RemotePageState extends State<RemotePage> {
autofocus: true, autofocus: true,
focusNode: _mobileFocusNode, focusNode: _mobileFocusNode,
maxLines: null, maxLines: null,
initialValue: _value, controller: _textController,
// trick way to make backspace work always // trick way to make backspace work always
keyboardType: TextInputType.multiline, keyboardType: TextInputType.multiline,
onChanged: handleSoftKeyboardInput, onChanged: handleSoftKeyboardInput,