Repository: flutter
Issue: [macOS] Using Japanese IME suggestion panel produces incorrect results
Labels: a: text input,platform-mac,a: internationalization,a: desktop,has reproducible steps,P2,team-text-input,triaged-text-input,found in release: 3.24

### Steps to reproduce

1. Run the sample app on macOS
2. Set the keyboard to Japanese - Kana
3. Type "krwkwr"
4. Press down arrow a three times to navigate between the suggestions (the suggestions panel will appear at the bottom of the screen)

### Expected results

The message "old text from delta doesn't match resulting text from previous delta" shouldn't be printed.

### Actual results

The message "old text from delta doesn't match resulting text from previous delta" is printed, because a delta is reported with an `oldText` that's different from the resulting text of the previously applied delta.

### Code sample

<details open><summary>Code sample</summary>

```dart
// ignore_for_file: avoid_print

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(
    const MaterialApp(
      home: Scaffold(
        body: TextInputExample(),
      ),
    ),
  );
}

class TextInputExample extends StatefulWidget {
  const TextInputExample({super.key});

  @override
  State<TextInputExample> createState() => _TextInputExampleState();
}

class _TextInputExampleState extends State<TextInputExample> implements DeltaTextInputClient {
  final FocusNode _focusNode = FocusNode();
  final GlobalKey _textKey = GlobalKey();

  TextInputConnection? _inputConnection;
  TextEditingValue _currentEditingValue = const TextEditingValue(
    text: '',
    selection: TextSelection.collapsed(offset: 0),
  );

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      _attach();
    });
  }

  @override
  void dispose() {
    _focusNode.dispose();
    super.dispose();
  }

  @override
  void updateEditingValueWithDeltas(List<TextEditingDelta> textEditingDeltas) {
    TextEditingValue newEditingValue = _currentEditingValue;

    print('received ${textEditingDeltas.length} delta(s)');
    for (final delta in textEditingDeltas) {
      print('apply delta: $delta');
      if (delta.oldText != newEditingValue.text) {
        print('old text from delta doesn\'t match resulting text from previous delta');
        print('old text from current delta: ${delta.oldText}');
        print('the previous text was: ${newEditingValue.text}');
      }
      newEditingValue = delta.apply(newEditingValue);

      print('new editing value: $newEditingValue');
    }

    setState(() {
      _currentEditingValue = newEditingValue;
    });
  }

  void _attach() {
    if (_inputConnection != null) {
      return;
    }
    _inputConnection = TextInput.attach(
      this,
      const TextInputConfiguration(
        enableDeltaModel: true,
        inputType: TextInputType.multiline,
        textCapitalization: TextCapitalization.sentences,
        inputAction: TextInputAction.newline,
        keyboardAppearance: Brightness.light,
      ),
    );
    _inputConnection!.show();
    _inputConnection!.setEditingState(_currentEditingValue);
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Focus(
        focusNode: _focusNode,
        autofocus: true,
        onKeyEvent: _onKeyEvent,
        child: DecoratedBox(
          decoration: BoxDecoration(border: Border.all()),
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: Text(
              key: _textKey,
              _currentEditingValue.text,
              textAlign: TextAlign.center,
            ),
          ),
        ),
      ),
    );
  }

  @override
  void connectionClosed() {}

  @override
  AutofillScope? get currentAutofillScope => null;

  @override
  TextEditingValue? get currentTextEditingValue => _currentEditingValue;

  @override
  void insertTextPlaceholder(Size size) {}

  @override
  void performPrivateCommand(String action, Map<String, dynamic> data) {}

  @override
  void removeTextPlaceholder() {}

  @override
  void showAutocorrectionPromptRect(int start, int end) {}

  @override
  void showToolbar() {}

  @override
  void updateEditingValue(TextEditingValue value) {}

  @override
  void updateFloatingCursor(RawFloatingCursorPoint point) {}

  @override
  void didChangeInputControl(TextInputControl? oldControl, TextInputControl? newControl) {}

  @override
  void insertContent(KeyboardInsertedContent content) {}

  @override
  void performSelector(String selectorName) {}

  @override
  void performAction(TextInputAction action) {}

  KeyEventResult _onKeyEvent(FocusNode node, KeyEvent event) {
    return KeyEventResult.skipRemainingHandlers;
  }
}

```

</details>


### Screenshots or Video

_No response_

### Logs

<details open><summary>Logs</summary>

```console
Launching lib/main.dart on macOS in debug mode...
--- xcodebuild: WARNING: Using the first of multiple matching destinations:
{ platform:macOS, arch:arm64, id:00006020-001161A802C3C01E, name:My Mac }
{ platform:macOS, arch:x86_64, id:00006020-001161A802C3C01E, name:My Mac }
✓ Built build/macos/Build/Products/Debug/text_input_demo.app
Connecting to VM Service at ws://127.0.0.1:65413/SX6QDGFc-DE=/ws
Connected to the VM Service.
flutter: received 1 delta(s)
flutter: apply delta: TextEditingDeltaInsertion#7b906(oldText, textInserted: の, insertionOffset: 0, selection: TextSelection.collapsed(offset: 1, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: 0, end: 1))
flutter: new editing value: TextEditingValue(text: ┤の├, selection: TextSelection.collapsed(offset: 1, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: 0, end: 1))
flutter: received 1 delta(s)
flutter: apply delta: TextEditingDeltaInsertion#5d95c(oldText: の, textInserted: す, insertionOffset: 1, selection: TextSelection.collapsed(offset: 2, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: 0, end: 2))
flutter: new editing value: TextEditingValue(text: ┤のす├, selection: TextSelection.collapsed(offset: 2, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: 0, end: 2))
flutter: received 1 delta(s)
flutter: apply delta: TextEditingDeltaReplacement#40c0c(oldText: のす, textReplaced: のす, replacementText: のステ, replacedRange: TextRange(start: 0, end: 2), selection: TextSelection.collapsed(offset: 3, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: 0, end: 3))
flutter: new editing value: TextEditingValue(text: ┤のステ├, selection: TextSelection.collapsed(offset: 3, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: 0, end: 3))
flutter: received 1 delta(s)
flutter: apply delta: TextEditingDeltaInsertion#76689(oldText: のステ, textInserted: の, insertionOffset: 3, selection: TextSelection.collapsed(offset: 4, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: 0, end: 4))
flutter: new editing value: TextEditingValue(text: ┤のステの├, selection: TextSelection.collapsed(offset: 4, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: 0, end: 4))
flutter: received 1 delta(s)
flutter: apply delta: TextEditingDeltaInsertion#f548c(oldText: のステの, textInserted: て, insertionOffset: 4, selection: TextSelection.collapsed(offset: 5, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: 0, end: 5))
flutter: new editing value: TextEditingValue(text: ┤のステのて├, selection: TextSelection.collapsed(offset: 5, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: 0, end: 5))
flutter: received 1 delta(s)
flutter: apply delta: TextEditingDeltaReplacement#f4ab0(oldText: のステのて, textReplaced: のステのて, replacementText: のステのテス, replacedRange: TextRange(start: 0, end: 5), selection: TextSelection.collapsed(offset: 6, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: 0, end: 6))
flutter: new editing value: TextEditingValue(text: ┤のステのテス├, selection: TextSelection.collapsed(offset: 6, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: 0, end: 6))
flutter: received 1 delta(s)
flutter: apply delta: TextEditingDeltaReplacement#8ae6c(oldText: のステのテス, textReplaced: のステのテス, replacementText: の棄てのテス, replacedRange: TextRange(start: 0, end: 6), selection: TextSelection(baseOffset: 1, extentOffset: 6, isDirectional: false), composing: TextRange(start: 0, end: 6))
flutter: new editing value: TextEditingValue(text: ┤の棄てのテス├, selection: TextSelection(baseOffset: 1, extentOffset: 6, isDirectional: false), composing: TextRange(start: 0, end: 6))
flutter: received 1 delta(s)
flutter: apply delta: TextEditingDeltaReplacement#3748a(oldText: の棄てのテス, textReplaced: 棄てのテス, replacementText: のすてのテス, replacedRange: TextRange(start: 1, end: 6), selection: TextSelection(baseOffset: 1, extentOffset: 6, isDirectional: false), composing: TextRange(start: 0, end: 6))
flutter: new editing value: TextEditingValue(text: ┤ののすてのテス├, selection: TextSelection(baseOffset: 1, extentOffset: 6, isDirectional: false), composing: TextRange(start: 0, end: 6))
flutter: received 1 delta(s)
flutter: apply delta: TextEditingDeltaReplacement#d1388(oldText: のすてのテス, textReplaced: すてのテス, replacementText: の須てのテス, replacedRange: TextRange(start: 1, end: 6), selection: TextSelection(baseOffset: 1, extentOffset: 6, isDirectional: false), composing: TextRange(start: 0, end: 6))
flutter: old text from delta doesn't match resulting text from previous delta
flutter: old text from current delta: のすてのテス
flutter: the previous text was: ののすてのテス
flutter: new editing value: TextEditingValue(text: ┤のの須てのテス├, selection: TextSelection(baseOffset: 1, extentOffset: 6, isDirectional: false), composing: TextRange(start: 0, end: 6))

```

</details>


### Flutter Doctor output

<details open><summary>Doctor output</summary>

```console
[✓] Flutter (Channel master, 3.24.0-1.0.pre.193, on macOS 14.5 23F79 darwin-arm64, locale en-BR)
    • Flutter version 3.24.0-1.0.pre.193 on channel master at /Users/angelosilvestre/dev/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 665d9e6e86 (3 weeks ago), 2024-07-19 08:23:05 +0900
    • Engine revision 766f7bed71
    • Dart version 3.6.0 (build 3.6.0-55.0.dev)
    • DevTools version 2.37.1

[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at /Users/angelosilvestre/Library/Android/sdk
    • Platform android-34, build-tools 34.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)
    • All Android licenses accepted.

[!] Xcode - develop for iOS and macOS (Xcode 15.4)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 15F31d
    ! CocoaPods 1.12.1 out of date (1.13.0 is recommended).
        CocoaPods is a package manager for iOS or macOS platform code.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/to/platform-plugins
      To update CocoaPods, see https://guides.cocoapods.org/using/getting-started.html#updating-cocoapods

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.3)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)

[✓] VS Code (version 1.92.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.94.0

[✓] Connected device (3 available)
    • macOS (desktop)                 • macos                 • darwin-arm64   • macOS 14.5 23F79 darwin-arm64
    • Mac Designed for iPad (desktop) • mac-designed-for-ipad • darwin         • macOS 14.5 23F79 darwin-arm64
    • Chrome (web)                    • chrome                • web-javascript • Google Chrome 127.0.6533.90

[✓] Network resources
    • All expected network resources are available.
```

</details>