Unverified Commit a2957c57 authored by Mouad Debbar's avatar Mouad Debbar Committed by GitHub

Upstream changes necessary for text editing in flutter web (#39344)

parent bb1d139c
......@@ -4,9 +4,17 @@
import 'dart:async';
import 'dart:io' show Platform;
import 'dart:ui' show TextAffinity, hashValues, Offset;
import 'dart:ui' show
FontWeight,
Offset,
Size,
TextAffinity,
TextAlign,
TextDirection,
hashValues;
import 'package:flutter/foundation.dart';
import 'package:vector_math/vector_math_64.dart' show Matrix4;
import 'message_codec.dart';
import 'system_channels.dart';
......@@ -660,6 +668,52 @@ class TextInputConnection {
);
}
/// Send the size and transform of the editable text to engine.
///
/// The values are sent as platform messages so they can be used on web for
/// example to correctly position and size the html input field.
///
/// 1. [editableBoxSize]: size of the render editable box.
///
/// 2. [transform]: a matrix that maps the local paint coordinate system
/// to the [PipelineOwner.rootNode].
void setEditableSizeAndTransform(Size editableBoxSize, Matrix4 transform) {
SystemChannels.textInput.invokeMethod<void>(
'TextInput.setEditableSizeAndTransform',
<String, dynamic>{
'width': editableBoxSize.width,
'height': editableBoxSize.height,
'transform': transform.storage,
},
);
}
/// Send text styling information.
///
/// This information is used by the Flutter Web Engine to change the style
/// of the hidden native input's content. Hence, the content size will match
/// to the size of the editable widget's content.
void setStyle({
@required String fontFamily,
@required double fontSize,
@required FontWeight fontWeight,
@required TextDirection textDirection,
@required TextAlign textAlign,
}) {
assert(attached);
SystemChannels.textInput.invokeMethod<void>(
'TextInput.setStyle',
<String, dynamic>{
'fontFamily': fontFamily,
'fontSize': fontSize,
'fontWeightIndex': fontWeight?.index,
'textAlignIndex': textAlign.index,
'textDirectionIndex': textDirection.index,
},
);
}
/// Stop interacting with the text input control.
///
/// After calling this method, the text input control might disappear if no
......
......@@ -4,7 +4,7 @@
import 'dart:async';
import 'dart:math' as math;
import 'dart:ui' as ui;
import 'dart:ui' as ui hide TextStyle;
import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart';
......@@ -1095,6 +1095,16 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
if (oldWidget.readOnly && _hasFocus)
_openInputConnection();
}
if (widget.style != oldWidget.style) {
final TextStyle style = widget.style;
_textInputConnection?.setStyle(
fontFamily: style.fontFamily,
fontSize: style.fontSize,
fontWeight: style.fontWeight,
textDirection: _textDirection,
textAlign: widget.textAlign,
);
}
}
@override
......@@ -1335,7 +1345,19 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
textCapitalization: widget.textCapitalization,
keyboardAppearance: widget.keyboardAppearance,
),
)..setEditingState(localValue);
);
_updateSizeAndTransform();
final TextStyle style = widget.style;
_textInputConnection
..setStyle(
fontFamily: style.fontFamily,
fontSize: style.fontSize,
fontWeight: style.fontWeight,
textDirection: _textDirection,
textAlign: widget.textAlign,
)
..setEditingState(localValue);
}
_textInputConnection.show();
}
......@@ -1626,6 +1648,23 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
updateKeepAlive();
}
Size _lastSize;
Matrix4 _lastTransform;
void _updateSizeAndTransform() {
if (_hasInputConnection) {
final Size size = renderEditable.size;
final Matrix4 transform = renderEditable.getTransformTo(null);
if (size != _lastSize || transform != _lastTransform) {
_lastSize = size;
_lastTransform = transform;
_textInputConnection.setEditableSizeAndTransform(size, transform);
}
SchedulerBinding.instance
.addPostFrameCallback((Duration _) => _updateSizeAndTransform());
}
}
TextDirection get _textDirection {
final TextDirection result = widget.textDirection ?? Directionality.of(context);
assert(result != null, '$runtimeType created without a textDirection and with no ambient Directionality.');
......@@ -1659,6 +1698,14 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
/// Returns `false` if a toolbar couldn't be shown, such as when the toolbar
/// is already shown, or when no text selection currently exists.
bool showToolbar() {
// Web is using native dom elements to enable clipboard functionality of the
// toolbar: copy, paste, select, cut. It might also provide additional
// functionality depending on the browser (such as translate). Due to this
// we should not show a Flutter toolbar for the editable text elements.
if (kIsWeb) {
return false;
}
if (_selectionOverlay == null || _selectionOverlay.toolbarIsVisible) {
return false;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment