-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Open
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work lista: desktopRunning on desktopRunning on desktopa: text inputEntering text in a text field or keyboard related problemsEntering text in a text field or keyboard related problemsa: typographyText rendering, possibly libtxtText rendering, possibly libtxtengineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.found in release: 2.3Found to occur in 2.3Found to occur in 2.3has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onplatform-macBuilding on or for macOS specificallyBuilding on or for macOS specificallyteam-macosOwned by the macOS platform teamOwned by the macOS platform teamtriaged-macosTriaged by the macOS platform teamTriaged by the macOS platform team
Description
When creating a custom TextInputClient, macOS does not update the editingValue for the following keystrokes:
- all arrows
- shift + an arrow
- delete
- cmd+a
- cmd+c
- cmd+x
- cmd+v
The last three were not tested since I'm unable to make a selection with either shift + arrows or cmd+a.
Steps to Reproduce
using the code sample provided below, run the following sequence:
- type the sequence
abcde - press delete (nothing happen on macOS)
- type the sequence
efg - press left arrow key till baseOffset = 0 (nothing happen on macOS)
- press
cmd + a(nothing happen on macOS) - press
cmd + c(nothing happen on macOS) - press delete (nothing happen on macOS)
Expected results:
I expected the following result which was produced with the same steps on the web platform.
value => TextEditingValue(text: ┤├, selection: TextSelection(baseOffset: 0, extentOffset: 0, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤a├, selection: TextSelection(baseOffset: 1, extentOffset: 1, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤ab├, selection: TextSelection(baseOffset: 2, extentOffset: 2, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤abc├, selection: TextSelection(baseOffset: 3, extentOffset: 3, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤abcd├, selection: TextSelection(baseOffset: 4, extentOffset: 4, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤abcde├, selection: TextSelection(baseOffset: 5, extentOffset: 5, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤abcd├, selection: TextSelection(baseOffset: 4, extentOffset: 4, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤abcde├, selection: TextSelection(baseOffset: 5, extentOffset: 5, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤abcdef├, selection: TextSelection(baseOffset: 6, extentOffset: 6, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤abcdefg├, selection: TextSelection(baseOffset: 7, extentOffset: 7, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤abcdefg├, selection: TextSelection(baseOffset: 6, extentOffset: 6, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤abcdefg├, selection: TextSelection(baseOffset: 5, extentOffset: 5, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤abcdefg├, selection: TextSelection(baseOffset: 4, extentOffset: 4, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤abcdefg├, selection: TextSelection(baseOffset: 3, extentOffset: 3, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤abcdefg├, selection: TextSelection(baseOffset: 2, extentOffset: 2, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤abcdefg├, selection: TextSelection(baseOffset: 1, extentOffset: 1, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤abcdefg├, selection: TextSelection(baseOffset: 0, extentOffset: 0, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤abcdefg├, selection: TextSelection(baseOffset: 0, extentOffset: 7, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
value => TextEditingValue(text: ┤├, selection: TextSelection(baseOffset: 0, extentOffset: 0, affinity: TextAffinity.downstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
Actual results:
flutter: value => TextEditingValue(text: ┤a├, selection: TextSelection(baseOffset: 1, extentOffset: 1, affinity: TextAffinity.upstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
flutter: value => TextEditingValue(text: ┤ab├, selection: TextSelection(baseOffset: 2, extentOffset: 2, affinity: TextAffinity.upstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
flutter: value => TextEditingValue(text: ┤abc├, selection: TextSelection(baseOffset: 3, extentOffset: 3, affinity: TextAffinity.upstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
flutter: value => TextEditingValue(text: ┤abcd├, selection: TextSelection(baseOffset: 4, extentOffset: 4, affinity: TextAffinity.upstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
flutter: value => TextEditingValue(text: ┤abcde├, selection: TextSelection(baseOffset: 5, extentOffset: 5, affinity: TextAffinity.upstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
flutter: value => TextEditingValue(text: ┤abcdee├, selection: TextSelection(baseOffset: 6, extentOffset: 6, affinity: TextAffinity.upstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
flutter: value => TextEditingValue(text: ┤abcdeef├, selection: TextSelection(baseOffset: 7, extentOffset: 7, affinity: TextAffinity.upstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
flutter: value => TextEditingValue(text: ┤abcdeefg├, selection: TextSelection(baseOffset: 8, extentOffset: 8, affinity: TextAffinity.upstream, isDirectional: false), composing: TextRange(start: -1, end: -1))
Minimal Code Sample
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
FocusNode focusNode;
TextInputConnection textInputConnection;
@override
void initState() {
super.initState();
textInputConnection = TextInput.attach(
CustomTextInputClient(),
TextInputConfiguration(
inputType: TextInputType.text,
inputAction: TextInputAction.newline,
),
);
textInputConnection.show();
}
@override
void dispose() {
textInputConnection.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(),
);
}
}
class CustomTextInputClient extends TextInputClient {
@override
void connectionClosed() {
// TODO: implement connectionClosed
}
@override
// TODO: implement currentAutofillScope
AutofillScope get currentAutofillScope {
throw UnimplementedError();
}
@override
// TODO: implement currentTextEditingValue
TextEditingValue get currentTextEditingValue {
throw UnimplementedError();
}
@override
void performAction(TextInputAction action) {
// TODO: implement performAction
}
@override
void performPrivateCommand(String action, Map<String, dynamic> data) {
// TODO: implement performPrivateCommand
}
@override
void showAutocorrectionPromptRect(int start, int end) {
// TODO: implement showAutocorrectionPromptRect
}
@override
void updateEditingValue(TextEditingValue value) {
// TODO: implement updateEditingValue
print('value => $value');
}
@override
void updateFloatingCursor(RawFloatingCursorPoint point) {
// TODO: implement updateFloatingCursor
}
}
flutter doctor -v
[✓] Flutter (Channel stable, 2.0.6, on macOS 11.2.3 20D91 darwin-x64, locale en)
• Flutter version 2.0.6 at /Users/osaxma/fvm/versions/stable
• Framework revision 1d9032c7e1 (9 days ago), 2021-04-29 17:37:58 -0700
• Engine revision 05e680e202
• Dart version 2.12.3
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
• Android SDK at /Users/osaxma/Library/Android/sdk
• Platform android-30, build-tools 29.0.2
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 12.4, Build version 12D4e
• CocoaPods version 1.10.1
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 4.1)
• 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 1.8.0_242-release-1644-b3-6915495)
[✓] VS Code (version 1.56.0)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.22.0
[✓] Connected device (2 available)
• macOS (desktop) • macos • darwin-x64 • macOS 11.2.3 20D91 darwin-x64
• Chrome (web) • chrome • web-javascript • Google Chrome 90.0.4430.93
• No issues found!
side note:
I'm not sure if I'm missing something out since TextField works fine. I tried to look at the EditableText implementation to see if there's anything unique about macOS or desktop but I couldn't find such indication. Nevertheless, given that the same provided sample code works for web, I was expecting the same behavior on macOS. Please advise.
Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work lista: desktopRunning on desktopRunning on desktopa: text inputEntering text in a text field or keyboard related problemsEntering text in a text field or keyboard related problemsa: typographyText rendering, possibly libtxtText rendering, possibly libtxtengineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.found in release: 2.3Found to occur in 2.3Found to occur in 2.3has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onplatform-macBuilding on or for macOS specificallyBuilding on or for macOS specificallyteam-macosOwned by the macOS platform teamOwned by the macOS platform teamtriaged-macosTriaged by the macOS platform teamTriaged by the macOS platform team