diff --git a/packages/flutter/lib/src/rendering/editable.dart b/packages/flutter/lib/src/rendering/editable.dart index 0b4abc8742..34fb0ec7cd 100644 --- a/packages/flutter/lib/src/rendering/editable.dart +++ b/packages/flutter/lib/src/rendering/editable.dart @@ -257,10 +257,10 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin { _obscureText = obscureText, _readOnly = readOnly, _forceLine = forceLine, - _clipBehavior = clipBehavior { + _clipBehavior = clipBehavior, + _hasFocus = hasFocus ?? false { assert(_showCursor != null); assert(!_showCursor.value || cursorColor != null); - this.hasFocus = hasFocus ?? false; _selectionPainter.highlightColor = selectionColor; _selectionPainter.highlightedRange = selection; @@ -2016,6 +2016,13 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin { if (_hasFocus == value) return; _hasFocus = value; + markNeedsSemanticsUpdate(); + + if (!attached) { + assert(!_listenerAttached); + return; + } + if (_hasFocus) { assert(!_listenerAttached); // TODO(justinmc): This listener should be ported to Actions and removed. @@ -2029,7 +2036,6 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin { RawKeyboard.instance.removeListener(_handleKeyEvent); _listenerAttached = false; } - markNeedsSemanticsUpdate(); } /// Whether this rendering object will take a full line regardless the text width. @@ -2614,8 +2620,11 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin { _offset.addListener(markNeedsPaint); _showHideCursor(); _showCursor.addListener(_showHideCursor); - if (_listenerAttached) + assert(!_listenerAttached); + if (_hasFocus) { RawKeyboard.instance.addListener(_handleKeyEvent); + _listenerAttached = true; + } } @override @@ -2626,8 +2635,10 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin { _showCursor.removeListener(_showHideCursor); // TODO(justinmc): This listener should be ported to Actions and removed. // https://github.com/flutter/flutter/issues/75004 - if (_listenerAttached) + if (_listenerAttached) { RawKeyboard.instance.removeListener(_handleKeyEvent); + _listenerAttached = false; + } super.detach(); _foregroundRenderObject?.detach(); _backgroundRenderObject?.detach(); diff --git a/packages/flutter/test/rendering/editable_test.dart b/packages/flutter/test/rendering/editable_test.dart index afc0c8d254..3ea2f2c108 100644 --- a/packages/flutter/test/rendering/editable_test.dart +++ b/packages/flutter/test/rendering/editable_test.dart @@ -1175,6 +1175,45 @@ void main() { expect(delegate.textEditingValue.text, 'W Sczebrzeszynie chrzÄ…szcz brzmi w trzcinie'); }, skip: isBrowser); // https://github.com/flutter/flutter/issues/61021 + test('RenderEditable registers and unregisters raw keyboard listener correctly', () async { + final TextSelectionDelegate delegate = FakeEditableTextState() + ..textEditingValue = const TextEditingValue( + text: 'how are you', + selection: TextSelection.collapsed(offset: 0), + ); + final ViewportOffset viewportOffset = ViewportOffset.zero(); + final RenderEditable editable = RenderEditable( + backgroundCursorColor: Colors.grey, + selectionColor: Colors.black, + textDirection: TextDirection.ltr, + cursorColor: Colors.red, + offset: viewportOffset, + hasFocus: true, + textSelectionDelegate: delegate, + onSelectionChanged: (TextSelection selection, RenderEditable renderObject, SelectionChangedCause cause) { + renderObject.selection = selection; + }, + startHandleLayerLink: LayerLink(), + endHandleLayerLink: LayerLink(), + text: const TextSpan( + text: 'how are you', + style: TextStyle( + height: 1.0, fontSize: 10.0, fontFamily: 'Ahem', + ), + ), + selection: const TextSelection.collapsed( + offset: 0, + ), + ); + + final PipelineOwner pipelineOwner = PipelineOwner(); + editable.attach(pipelineOwner); + + await simulateKeyDownEvent(LogicalKeyboardKey.delete, platform: 'android'); + await simulateKeyUpEvent(LogicalKeyboardKey.delete, platform: 'android'); + expect(delegate.textEditingValue.text, 'ow are you'); + }, skip: isBrowser); // https://github.com/flutter/flutter/issues/61021 + test('arrow keys with selection text', () async { const String text = '012345'; final TextSelectionDelegate delegate = FakeEditableTextState()