From aff5f7b0a56ca2b3c102922cd5f3c581c9d852e0 Mon Sep 17 00:00:00 2001 From: Renzo Olivares Date: Mon, 4 Apr 2022 13:11:19 -0700 Subject: [PATCH 1/4] Fix special character input on a selection --- .../darwin/macos/framework/Source/FlutterTextInputPlugin.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.mm index 44349528339a3..bf62d91e95891 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.mm @@ -629,6 +629,7 @@ - (void)setMarkedText:(id)string _activeModel->BeginComposing(); } flutter::TextRange composingBeforeChange = _activeModel->composing_range(); + flutter::TextRange selectionBeforeChange = _activeModel->selection(); // Input string may be NSString or NSAttributedString. BOOL isAttributedString = [string isKindOfClass:[NSAttributedString class]]; @@ -646,7 +647,7 @@ - (void)setMarkedText:(id)string if (_enableDeltaModel) { [self updateEditStateWithDelta:flutter::TextEditingDelta(textBeforeChange, - composingBeforeChange, marked_text)]; + selectionBeforeChange.collapsed() ? composingBeforeChange : selectionBeforeChange, marked_text)]; } else { [self updateEditState]; } From 506d8062c3f733f8ab66da0c3fe7e03a5a92497a Mon Sep 17 00:00:00 2001 From: Renzo Olivares Date: Mon, 4 Apr 2022 13:13:58 -0700 Subject: [PATCH 2/4] Formatting --- .../darwin/macos/framework/Source/FlutterTextInputPlugin.mm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.mm index bf62d91e95891..621f2431c957c 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.mm @@ -647,7 +647,10 @@ - (void)setMarkedText:(id)string if (_enableDeltaModel) { [self updateEditStateWithDelta:flutter::TextEditingDelta(textBeforeChange, - selectionBeforeChange.collapsed() ? composingBeforeChange : selectionBeforeChange, marked_text)]; + selectionBeforeChange.collapsed() + ? composingBeforeChange + : selectionBeforeChange, + marked_text)]; } else { [self updateEditState]; } From efc221db039191cf761df16140a59ddea7e5f98f Mon Sep 17 00:00:00 2001 From: Renzo Olivares Date: Mon, 4 Apr 2022 14:02:46 -0700 Subject: [PATCH 3/4] Add test for composing when selection is active --- .../Source/FlutterTextInputPluginTest.mm | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/shell/platform/darwin/macos/framework/Source/FlutterTextInputPluginTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterTextInputPluginTest.mm index 17c50b26c5987..be7960e0f915c 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterTextInputPluginTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterTextInputPluginTest.mm @@ -845,6 +845,78 @@ - (bool)testComposingWithDelta { return true; } +- (bool)testComposingWithDeltasWhenSelectionIsActive { + id engineMock = OCMClassMock([FlutterEngine class]); + id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger)); + OCMStub( // NOLINT(google-objc-avoid-throwing-exception) + [engineMock binaryMessenger]) + .andReturn(binaryMessengerMock); + + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock + nibName:@"" + bundle:nil]; + + FlutterTextInputPlugin* plugin = + [[FlutterTextInputPlugin alloc] initWithViewController:viewController]; + + [plugin handleMethodCall:[FlutterMethodCall + methodCallWithMethodName:@"TextInput.setClient" + arguments:@[ + @(1), @{ + @"inputAction" : @"action", + @"enableDeltaModel" : @"true", + @"inputType" : @{@"name" : @"inputName"}, + } + ]] + result:^(id){ + }]; + + FlutterMethodCall* call = [FlutterMethodCall methodCallWithMethodName:@"TextInput.setEditingState" + arguments:@{ + @"text" : @"Text", + @"selectionBase" : @(0), + @"selectionExtent" : @(4), + @"composingBase" : @(-1), + @"composingExtent" : @(-1), + }]; + [plugin handleMethodCall:call + result:^(id){ + }]; + + [plugin setMarkedText:@"~" + selectedRange:NSMakeRange(1, 0) + replacementRange:NSMakeRange(NSNotFound, 0)]; + + NSDictionary* deltaToFramework = @{ + @"oldText" : @"Text", + @"deltaText" : @"~", + @"deltaStart" : @(0), + @"deltaEnd" : @(4), + @"selectionBase" : @(1), + @"selectionExtent" : @(1), + @"selectionAffinity" : @"TextAffinity.upstream", + @"selectionIsDirectional" : @(false), + @"composingBase" : @(0), + @"composingExtent" : @(1), + }; + NSDictionary* expectedState = @{ + @"deltas" : @[ deltaToFramework ], + }; + + NSData* updateCall = [[FlutterJSONMethodCodec sharedInstance] + encodeMethodCall:[FlutterMethodCall + methodCallWithMethodName:@"TextInputClient.updateEditingStateWithDeltas" + arguments:@[ @(1), expectedState ]]]; + + @try { + OCMVerify( // NOLINT(google-objc-avoid-throwing-exception) + [binaryMessengerMock sendOnChannel:@"flutter/textinput" message:updateCall]); + } @catch (...) { + return false; + } + return true; +} + - (bool)testLocalTextAndSelectionUpdateAfterDelta { id engineMock = OCMClassMock([FlutterEngine class]); id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger)); @@ -957,6 +1029,10 @@ - (bool)testLocalTextAndSelectionUpdateAfterDelta { ASSERT_TRUE([[FlutterInputPluginTestObjc alloc] testComposingWithDelta]); } +TEST(FlutterTextInputPluginTest, testComposingWithDeltasWhenSelectionIsActive) { + ASSERT_TRUE([[FlutterInputPluginTestObjc alloc] testComposingWithDeltasWhenSelectionIsActive]); +} + TEST(FlutterTextInputPluginTest, TestLocalTextAndSelectionUpdateAfterDelta) { ASSERT_TRUE([[FlutterInputPluginTestObjc alloc] testLocalTextAndSelectionUpdateAfterDelta]); } From 60421fa9911474912fdf3f9f820f65bde02b7204 Mon Sep 17 00:00:00 2001 From: Renzo Olivares Date: Mon, 4 Apr 2022 14:04:00 -0700 Subject: [PATCH 4/4] Fix formatting --- .../macos/framework/Source/FlutterTextInputPluginTest.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/platform/darwin/macos/framework/Source/FlutterTextInputPluginTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterTextInputPluginTest.mm index be7960e0f915c..a724b112b7239 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterTextInputPluginTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterTextInputPluginTest.mm @@ -886,7 +886,7 @@ - (bool)testComposingWithDeltasWhenSelectionIsActive { [plugin setMarkedText:@"~" selectedRange:NSMakeRange(1, 0) replacementRange:NSMakeRange(NSNotFound, 0)]; - + NSDictionary* deltaToFramework = @{ @"oldText" : @"Text", @"deltaText" : @"~", @@ -902,7 +902,7 @@ - (bool)testComposingWithDeltasWhenSelectionIsActive { NSDictionary* expectedState = @{ @"deltas" : @[ deltaToFramework ], }; - + NSData* updateCall = [[FlutterJSONMethodCodec sharedInstance] encodeMethodCall:[FlutterMethodCall methodCallWithMethodName:@"TextInputClient.updateEditingStateWithDeltas"