Content-Length: 483829 | pFad | http://github.com/flutter/flutter/pull/171935/files

26 [Web] Implement disabling interactive selection by loic-sharma · Pull Request #171935 · flutter/flutter · GitHub
Skip to content

[Web] Implement disabling interactive selection #171935

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1027,6 +1027,7 @@ class InputConfiguration {
this.autofill,
this.autofillGroup,
this.enableDeltaModel = false,
this.enableInteractiveSelection = true,
});

InputConfiguration.fromFrameworkMessage(Map<String, dynamic> flutterInputConfiguration)
Expand All @@ -1052,7 +1053,9 @@ class InputConfiguration {
flutterInputConfiguration.tryJson('autofill'),
flutterInputConfiguration.tryList('fields'),
),
enableDeltaModel = flutterInputConfiguration.tryBool('enableDeltaModel') ?? false;
enableDeltaModel = flutterInputConfiguration.tryBool('enableDeltaModel') ?? false,
enableInteractiveSelection =
flutterInputConfiguration.tryBool('enableInteractiveSelection') ?? true;

//github.com/ The ID of the view that contains the text field.
final int viewId;
Expand Down Expand Up @@ -1087,6 +1090,13 @@ class InputConfiguration {
final EngineAutofillForm? autofillGroup;

final TextCapitalizationConfig textCapitalization;

//github.com/ Whether the user can change the text selection.
//github.com/
//github.com/ When this is false, the text selection cannot be adjusted by
//github.com/ the user, text cannot be copied, and the user cannot paste into
//github.com/ the text field from the clipboard.
final bool enableInteractiveSelection;
}

typedef OnChangeCallback =
Expand Down Expand Up @@ -1401,6 +1411,14 @@ abstract class DefaultTextEditingStrategy
);
}

subscriptions.add(
DomSubscription(activeDomElement, 'copy', createDomEventListener(handleClipboardEvent)),
);

subscriptions.add(
DomSubscription(activeDomElement, 'paste', createDomEventListener(handleClipboardEvent)),
);

addCompositionEventHandlers(activeDomElement);

preventDefaultForMouseEvents();
Expand Down Expand Up @@ -1482,6 +1500,7 @@ abstract class DefaultTextEditingStrategy
assert(isEnabled);

EditingState newEditingState = EditingState.fromDomElement(activeDomElement);
newEditingState = suppressInteractiveSelectionIfNeeded(newEditingState);
newEditingState = determineCompositionState(newEditingState);

TextEditingDeltaState? newTextEditingDeltaState;
Expand All @@ -1504,6 +1523,24 @@ abstract class DefaultTextEditingStrategy
_editingDeltaState = null;
}

EditingState suppressInteractiveSelectionIfNeeded(EditingState editingState) {
if (inputConfiguration.enableInteractiveSelection) {
return editingState;
}

if (editingState.baseOffset == editingState.extentOffset) {
return editingState;
}

// If interactive selection is disabled, collapse the selection to the end.
final newEditingState = editingState.copyWith(
baseOffset: editingState.extentOffset,
extentOffset: editingState.extentOffset,
);
newEditingState.applyToDomElement(activeDomElement);
return newEditingState;
}

void handleBeforeInput(DomEvent event) {
// In some cases the beforeinput event is not fired such as when the selection
// of a text field is updated. In this case only the oninput event is fired.
Expand Down Expand Up @@ -1571,6 +1608,13 @@ abstract class DefaultTextEditingStrategy
}
}

void handleClipboardEvent(DomEvent event) {
// Prevent clipboard copy/paste if interactive selection is disabled.
if (!inputConfiguration.enableInteractiveSelection) {
event.preventDefault();
}
}

void maybeSendAction(DomEvent e) {
if (e.isA<DomKeyboardEvent>()) {
final DomKeyboardEvent event = e as DomKeyboardEvent;
Expand Down Expand Up @@ -1754,6 +1798,14 @@ class IOSTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
DomSubscription(activeDomElement, 'blur', createDomEventListener(handleBlur)),
);

subscriptions.add(
DomSubscription(activeDomElement, 'copy', createDomEventListener(handleClipboardEvent)),
);

subscriptions.add(
DomSubscription(activeDomElement, 'paste', createDomEventListener(handleClipboardEvent)),
);

addCompositionEventHandlers(activeDomElement);

// Position the DOM element after it is focused.
Expand Down Expand Up @@ -1892,6 +1944,14 @@ class AndroidTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
DomSubscription(activeDomElement, 'blur', createDomEventListener(handleBlur)),
);

subscriptions.add(
DomSubscription(activeDomElement, 'copy', createDomEventListener(handleClipboardEvent)),
);

subscriptions.add(
DomSubscription(activeDomElement, 'paste', createDomEventListener(handleClipboardEvent)),
);

addCompositionEventHandlers(activeDomElement);

preventDefaultForMouseEvents();
Expand Down Expand Up @@ -1978,6 +2038,14 @@ class FirefoxTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
DomSubscription(activeDomElement, 'blur', createDomEventListener(handleBlur)),
);

subscriptions.add(
DomSubscription(activeDomElement, 'copy', createDomEventListener(handleClipboardEvent)),
);

subscriptions.add(
DomSubscription(activeDomElement, 'paste', createDomEventListener(handleClipboardEvent)),
);

preventDefaultForMouseEvents();
}

Expand Down
75 changes: 75 additions & 0 deletions engine/src/flutter/lib/web_ui/test/engine/text_editing_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,7 @@ Future<void> testMain() async {
bool decimal = false,
bool isMultiline = false,
bool autofillEnabled = true,
bool enableInteractiveSelection = true,
}) {
final MethodCall setClient = MethodCall('TextInput.setClient', <dynamic>[
++clientId,
Expand All @@ -736,6 +737,7 @@ Future<void> testMain() async {
decimal: decimal,
isMultiline: isMultiline,
autofillEnabled: autofillEnabled,
enableInteractiveSelection: enableInteractiveSelection,
),
]);
sendFrameworkMessage(codec.encodeMethodCall(setClient));
Expand Down Expand Up @@ -2947,6 +2949,77 @@ Future<void> testMain() async {
// https://github.com/flutter/flutter/issues/145101
}, skip: true);

test('Collapses selections if interactive selection disabled', () {
final int clientId = showKeyboard(inputType: 'text', enableInteractiveSelection: false);

// The Safari strategy doesn't insert the input element into the DOM until
// it has received the geometry information.
final List<double> transform = Matrix4.identity().storage.toList();
final MethodCall setSizeAndTransform = configureSetSizeAndTransformMethodCall(
10,
10,
transform,
);
sendFrameworkMessage(codec.encodeMethodCall(setSizeAndTransform));

final DomHTMLInputElement input = textEditing!.strategy.domElement! as DomHTMLInputElement;

input.value = 'something';
input.dispatchEvent(createDomEvent('Event', 'input'));

spy.messages.clear();

// Forward selection collapses at the end.
input.setSelectionRange(2, 5, 'forward');
if (ui_web.browser.browserEngine == ui_web.BrowserEngine.firefox) {
final DomEvent keyup = createDomEvent('Event', 'keyup');
textEditing!.strategy.domElement!.dispatchEvent(keyup);
} else {
domDocument.dispatchEvent(createDomEvent('Event', 'selectionchange'));
}

expect(spy.messages, hasLength(1));
expect(spy.messages[0].channel, 'flutter/textinput');
expect(spy.messages[0].methodName, 'TextInputClient.updateEditingState');
expect(spy.messages[0].methodArguments, <dynamic>[
clientId,
<String, dynamic>{
'text': 'something',
'selectionBase': 5,
'selectionExtent': 5,
'composingBase': -1,
'composingExtent': -1,
},
]);
spy.messages.clear();

// Backward selection collapses at the start.
input.setSelectionRange(2, 5, 'backward');
if (ui_web.browser.browserEngine == ui_web.BrowserEngine.firefox) {
final DomEvent keyup = createDomEvent('Event', 'keyup');
textEditing!.strategy.domElement!.dispatchEvent(keyup);
} else {
domDocument.dispatchEvent(createDomEvent('Event', 'selectionchange'));
}

expect(spy.messages, hasLength(1));
expect(spy.messages[0].channel, 'flutter/textinput');
expect(spy.messages[0].methodName, 'TextInputClient.updateEditingState');
expect(spy.messages[0].methodArguments, <dynamic>[
clientId,
<String, dynamic>{
'text': 'something',
'selectionBase': 2,
'selectionExtent': 2,
'composingBase': -1,
'composingExtent': -1,
},
]);
spy.messages.clear();

hideKeyboard();
});

tearDown(() {
clearForms();
});
Expand Down Expand Up @@ -3981,6 +4054,7 @@ Map<String, dynamic> createFlutterConfig(
bool decimal = false,
bool enableDeltaModel = false,
bool isMultiline = false,
bool enableInteractiveSelection = true,
}) {
return <String, dynamic>{
'inputType': <String, dynamic>{
Expand All @@ -4003,6 +4077,7 @@ Map<String, dynamic> createFlutterConfig(
if (autofillEnabled && autofillHintsForFields != null)
'fields': createFieldValues(autofillHintsForFields, autofillHintsForFields),
'enableDeltaModel': enableDeltaModel,
'enableInteractiveSelection': enableInteractiveSelection,
};
}

Expand Down








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/flutter/flutter/pull/171935/files

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy