updateEditingValue method

  1. @override
void updateEditingValue(
  1. TextEditingValue value
)
inherited

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;
  }
}