updateEditingValue method
Requests that this client update its editing state to the given value.
The new value
is treated as user input and thus may subject to input
formatting.
Implementation
@override
void updateEditingValue(TextEditingValue value) {
if (!shouldCreateInputConnection) {
return;
}
if (_sentRemoteValues.contains(value)) {
/// There is a race condition in Flutter text input plugin where sending
/// updates to native side too often results in broken behavior.
/// TextInputConnection.setEditingValue is an async call to native side.
/// For each such call native side _always_ sends an update which triggers
/// this method (updateEditingValue) with the same value we've sent it.
/// If multiple calls to setEditingValue happen too fast and we only
/// track the last sent value then there is no way for us to filter out
/// automatic callbacks from native side.
/// Therefore we have to keep track of all values we send to the native
/// side and when we see this same value appear here we skip it.
/// This is fragile but it's probably the only available option.
_sentRemoteValues.remove(value);
return;
}
if (_lastKnownRemoteTextEditingValue == value) {
// There is no difference between this value and the last known value.
return;
}
// Check if only composing range changed.
if (_lastKnownRemoteTextEditingValue!.text == value.text &&
_lastKnownRemoteTextEditingValue!.selection == value.selection) {
// This update only modifies composing range. Since we don't keep track
// of composing range in Zefyr we just need to update last known value
// here.
// This check fixes an issue on Android when it sends
// composing updates separately from regular changes for text and
// selection.
_lastKnownRemoteTextEditingValue = value;
return;
}
// Note Flutter (unintentionally?) silences errors occurred during
// text input update, so we have to report it ourselves.
// For more details see https://github.com/flutter/flutter/issues/19191
// TODO: remove try-catch when/if Flutter stops silencing these errors.
try {
final effectiveLastKnownValue = _lastKnownRemoteTextEditingValue!;
_lastKnownRemoteTextEditingValue = value;
final oldText = effectiveLastKnownValue.text;
final text = value.text;
final cursorPosition = value.selection.extentOffset;
final diff = fastDiff(oldText, text, cursorPosition);
_remoteValueChanged(
diff.start, diff.deleted, diff.inserted, value.selection);
} catch (e, trace) {
FlutterError.reportError(FlutterErrorDetails(
exception: e,
stack: trace,
library: 'Zefyr',
context: ErrorSummary('while updating editing value'),
));
rethrow;
}
}