Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
61299b16
Unverified
Commit
61299b16
authored
Jan 20, 2021
by
LongCatIsLooong
Committed by
GitHub
Jan 20, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "[text_input] prepare for custom text input sources (#72803)" (#74349)
parent
def31b42
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
185 additions
and
354 deletions
+185
-354
text_input.dart
packages/flutter/lib/src/services/text_input.dart
+183
-293
editable_text.dart
packages/flutter/lib/src/widgets/editable_text.dart
+2
-1
text_input_test.dart
packages/flutter/test/services/text_input_test.dart
+0
-60
No files found.
packages/flutter/lib/src/services/text_input.dart
View file @
61299b16
...
...
@@ -860,22 +860,21 @@ abstract class TextInputClient {
/// An interface for interacting with a text input control.
///
/// [TextInputConnection] communicates with the platform text input plugin
/// over the [SystemChannels.textInput] method channel. See [SystemChannels.textInput]
/// for more details about the method channel messages.
///
/// See also:
///
/// * [TextInput.attach], a method used to establish a [TextInputConnection]
/// between the system's text input and a [TextInputClient].
/// * [EditableText], a [TextInputClient] that connects to and interacts with
/// the system's text input using a [TextInputConnection].
abstract
class
TextInputConnection
{
/// Creates a connection for a [TextInputClient].
TextInputConnection
(
this
.
_client
)
class
TextInputConnection
{
TextInputConnection
.
_
(
this
.
_client
)
:
assert
(
_client
!=
null
),
_id
=
_nextId
++;
Size
?
_cachedSize
;
Matrix4
?
_cachedTransform
;
Rect
?
_cachedRect
;
static
int
_nextId
=
1
;
final
int
_id
;
...
...
@@ -898,18 +897,10 @@ abstract class TextInputConnection {
bool
get
attached
=>
TextInput
.
_instance
.
_currentConnection
==
this
;
/// Requests that the text input control become visible.
void
show
();
/// Requests that the text input control is hidden.
///
/// This method is called by the framework when the text input control should
/// hide.
///
/// See also:
///
/// * [TextInput.detach], a method to stop interacting with the text
/// input control.
void
hide
();
void
show
()
{
assert
(
attached
);
TextInput
.
_instance
.
_show
();
}
/// Requests the system autofill UI to appear.
///
...
...
@@ -919,23 +910,24 @@ abstract class TextInputConnection {
/// See also:
///
/// * [EditableText], a [TextInputClient] that calls this method when focused.
void
requestAutofill
();
/// This method actually notifies the embedding of the client. It is utilized
/// by [TextInput.attach] and for the `TextInputClient.requestExistingInputState`
/// method.
void
setClient
(
TextInputConfiguration
configuration
);
/// Clears the embedding of the client.
void
clearClient
();
void
requestAutofill
()
{
assert
(
attached
);
TextInput
.
_instance
.
_requestAutofill
();
}
/// Requests that the text input control update itself according to the new
/// [TextInputConfiguration].
void
updateConfig
(
TextInputConfiguration
configuration
);
void
updateConfig
(
TextInputConfiguration
configuration
)
{
assert
(
attached
);
TextInput
.
_instance
.
_updateConfig
(
configuration
);
}
/// Requests that the text input control change its internal state to match
/// the given state.
void
setEditingState
(
TextEditingValue
value
);
void
setEditingState
(
TextEditingValue
value
)
{
assert
(
attached
);
TextInput
.
_instance
.
_setEditingState
(
value
);
}
/// Send the size and transform of the editable text to engine.
///
...
...
@@ -946,126 +938,11 @@ abstract class TextInputConnection {
///
/// 2. [transform]: a matrix that maps the local paint coordinate system
/// to the [PipelineOwner.rootNode].
void
setEditableSizeAndTransform
(
Size
editableBoxSize
,
Matrix4
transform
);
/// Send the smallest rect that covers the text in the client that's currently
/// being composed.
///
/// The given `rect` can not be null. If any of the 4 coordinates of the given
/// [Rect] is not finite, a [Rect] of size (-1, -1) will be sent instead.
///
/// The information is currently only used on iOS, for positioning the IME bar.
void
setComposingRect
(
Rect
rect
);
/// 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
,
});
/// Stop interacting with the text input control.
///
/// After calling this method, the text input control might disappear if no
/// other client attaches to it within this animation frame.
@Deprecated
(
'Use TextInput.detach instead. '
'This feature was deprecated after v1.26.0-1.0.pre.'
)
void
close
()
{
TextInput
.
detach
(
_client
);
assert
(!
attached
);
}
/// Platform sent a notification informing the connection is closed.
///
/// [TextInputConnection] should clean current client connection.
@Deprecated
(
'Use TextInput.reset instead. '
'This feature was deprecated after v1.26.0-1.0.pre.'
)
void
connectionClosedReceived
()
{
TextInput
.
reset
();
assert
(!
attached
);
}
}
// A MethodChannel-based TextInputConnection implementation.
class
_TextInputChannelConnection
extends
TextInputConnection
{
_TextInputChannelConnection
(
TextInputClient
client
,
this
.
_channel
)
:
super
(
client
);
Size
?
_cachedSize
;
Matrix4
?
_cachedTransform
;
Rect
?
_cachedRect
;
final
MethodChannel
_channel
;
@override
void
show
()
{
assert
(
attached
);
_channel
.
invokeMethod
<
void
>(
'TextInput.show'
);
}
@override
void
hide
()
{
_channel
.
invokeMethod
<
void
>(
'TextInput.hide'
);
}
@override
void
requestAutofill
()
{
assert
(
attached
);
_channel
.
invokeMethod
<
void
>(
'TextInput.requestAutofill'
);
}
@override
void
setClient
(
TextInputConfiguration
configuration
)
{
assert
(
_client
!=
null
);
assert
(
configuration
!=
null
);
_channel
.
invokeMethod
<
void
>(
'TextInput.setClient'
,
<
dynamic
>[
_id
,
configuration
.
toJson
()],
);
}
@override
void
clearClient
()
{
_channel
.
invokeMethod
<
void
>(
'TextInput.clearClient'
);
}
@override
void
updateConfig
(
TextInputConfiguration
configuration
)
{
assert
(
attached
);
assert
(
configuration
!=
null
);
_channel
.
invokeMethod
<
void
>(
'TextInput.updateConfig'
,
configuration
.
toJson
(),
);
}
@override
void
setEditingState
(
TextEditingValue
value
)
{
assert
(
attached
);
assert
(
value
!=
null
);
_channel
.
invokeMethod
<
void
>(
'TextInput.setEditingState'
,
value
.
toJSON
(),
);
}
@override
void
setEditableSizeAndTransform
(
Size
editableBoxSize
,
Matrix4
transform
)
{
if
(
editableBoxSize
!=
_cachedSize
||
transform
!=
_cachedTransform
)
{
_cachedSize
=
editableBoxSize
;
_cachedTransform
=
transform
;
_channel
.
invokeMethod
<
void
>(
'TextInput.setEditableSizeAndTransform'
,
TextInput
.
_instance
.
_setEditableSizeAndTransform
(
<
String
,
dynamic
>{
'width'
:
editableBoxSize
.
width
,
'height'
:
editableBoxSize
.
height
,
...
...
@@ -1075,15 +952,20 @@ class _TextInputChannelConnection extends TextInputConnection {
}
}
@override
/// Send the smallest rect that covers the text in the client that's currently
/// being composed.
///
/// The given `rect` can not be null. If any of the 4 coordinates of the given
/// [Rect] is not finite, a [Rect] of size (-1, -1) will be sent instead.
///
/// The information is currently only used on iOS, for positioning the IME bar.
void
setComposingRect
(
Rect
rect
)
{
assert
(
rect
!=
null
);
if
(
rect
==
_cachedRect
)
return
;
_cachedRect
=
rect
;
final
Rect
validRect
=
rect
.
isFinite
?
rect
:
Offset
.
zero
&
const
Size
(-
1
,
-
1
);
_channel
.
invokeMethod
<
void
>(
'TextInput.setMarkedTextRect'
,
TextInput
.
_instance
.
_setComposingTextRect
(
<
String
,
dynamic
>{
'width'
:
validRect
.
width
,
'height'
:
validRect
.
height
,
...
...
@@ -1093,7 +975,11 @@ class _TextInputChannelConnection extends TextInputConnection {
);
}
@override
/// 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
,
...
...
@@ -1102,8 +988,8 @@ class _TextInputChannelConnection extends TextInputConnection {
required
TextAlign
textAlign
,
})
{
assert
(
attached
);
_channel
.
invokeMethod
<
void
>(
'TextInput.setStyle'
,
TextInput
.
_instance
.
_setStyle
(
<
String
,
dynamic
>{
'fontFamily'
:
fontFamily
,
'fontSize'
:
fontSize
,
...
...
@@ -1114,68 +1000,23 @@ class _TextInputChannelConnection extends TextInputConnection {
);
}
Future
<
dynamic
>
_handleTextInputInvocation
(
MethodCall
methodCall
)
async
{
final
String
method
=
methodCall
.
method
;
// The requestExistingInputState request needs to be handled regardless of
// the client ID, as long as we have a _currentConnection.
if
(
method
==
'TextInputClient.requestExistingInputState'
)
{
assert
(
_client
!=
null
);
setClient
(
TextInput
.
_instance
.
_currentConfiguration
);
final
TextEditingValue
?
editingValue
=
_client
.
currentTextEditingValue
;
if
(
editingValue
!=
null
)
{
setEditingState
(
editingValue
);
}
return
;
}
final
List
<
dynamic
>
args
=
methodCall
.
arguments
as
List
<
dynamic
>;
if
(
method
==
'TextInputClient.updateEditingStateWithTag'
)
{
assert
(
_client
!=
null
);
final
AutofillScope
?
scope
=
_client
.
currentAutofillScope
;
final
Map
<
String
,
dynamic
>
editingValue
=
args
[
1
]
as
Map
<
String
,
dynamic
>;
for
(
final
String
tag
in
editingValue
.
keys
)
{
final
TextEditingValue
textEditingValue
=
TextEditingValue
.
fromJSON
(
editingValue
[
tag
]
as
Map
<
String
,
dynamic
>,
);
scope
?.
getAutofillClient
(
tag
)?.
updateEditingValue
(
textEditingValue
);
}
return
;
/// Stop interacting with the text input control.
///
/// After calling this method, the text input control might disappear if no
/// other client attaches to it within this animation frame.
void
close
()
{
if
(
attached
)
{
TextInput
.
_instance
.
_clearClient
();
}
assert
(!
attached
);
}
final
int
clientId
=
args
[
0
]
as
int
;
// The incoming message was for a different client.
if
(
clientId
!=
_id
)
return
;
switch
(
method
)
{
case
'TextInputClient.updateEditingState'
:
_client
.
updateEditingValue
(
TextEditingValue
.
fromJSON
(
args
[
1
]
as
Map
<
String
,
dynamic
>));
break
;
case
'TextInputClient.performAction'
:
_client
.
performAction
(
_toTextInputAction
(
args
[
1
]
as
String
));
break
;
case
'TextInputClient.performPrivateCommand'
:
_client
.
performPrivateCommand
(
args
[
1
][
'action'
]
as
String
,
args
[
1
][
'data'
]
as
Map
<
String
,
dynamic
>);
break
;
case
'TextInputClient.updateFloatingCursor'
:
_client
.
updateFloatingCursor
(
_toTextPoint
(
_toTextCursorAction
(
args
[
1
]
as
String
),
args
[
2
]
as
Map
<
String
,
dynamic
>,
));
break
;
case
'TextInputClient.onConnectionClosed'
:
_client
.
connectionClosed
();
TextInput
.
reset
();
break
;
case
'TextInputClient.showAutocorrectionPromptRect'
:
_client
.
showAutocorrectionPromptRect
(
args
[
1
]
as
int
,
args
[
2
]
as
int
);
break
;
default
:
throw
MissingPluginException
();
}
/// Platform sent a notification informing the connection is closed.
///
/// [TextInputConnection] should clean current client connection.
void
connectionClosedReceived
()
{
TextInput
.
_instance
.
_currentConnection
=
null
;
assert
(!
attached
);
}
}
...
...
@@ -1288,7 +1129,8 @@ RawFloatingCursorPoint _toTextPoint(FloatingCursorDragState state, Map<String, d
/// wants to take user input from the keyboard.
class
TextInput
{
TextInput
.
_
()
{
_currentSource
.
init
();
_channel
=
SystemChannels
.
textInput
;
_channel
.
setMethodCallHandler
(
_handleTextInputInvocation
);
}
/// Set the [MethodChannel] used to communicate with the system's text input
...
...
@@ -1300,7 +1142,7 @@ class TextInput {
@visibleForTesting
static
void
setChannel
(
MethodChannel
newChannel
)
{
assert
(()
{
_
TextInputSource
.
setChannel
(
newChannel
);
_
instance
.
_channel
=
newChannel
..
setMethodCallHandler
(
_instance
.
_handleTextInputInvocation
);
return
true
;
}());
}
...
...
@@ -1341,23 +1183,28 @@ class TextInput {
/// the text input control.
///
/// A client that no longer wishes to interact with the text input control
/// should call [TextInput.detach].
/// should call [TextInputConnection.close] on the returned
/// [TextInputConnection].
static
TextInputConnection
attach
(
TextInputClient
client
,
TextInputConfiguration
configuration
)
{
assert
(
client
!=
null
);
assert
(
configuration
!=
null
);
_instance
.
_detach
();
final
TextInputConnection
connection
=
_instance
.
_currentSource
.
attach
(
client
);
final
TextInputConnection
connection
=
TextInputConnection
.
_
(
client
);
_instance
.
_attach
(
connection
,
configuration
);
return
connection
;
}
// This method actually notifies the embedding of the client.
/// This method actually notifies the embedding of the client. It is utilized
/// by [attach] and by [_handleTextInputInvocation] for the
/// `TextInputClient.requestExistingInputState` method.
void
_attach
(
TextInputConnection
connection
,
TextInputConfiguration
configuration
)
{
assert
(
connection
!=
null
);
assert
(
connection
.
_client
!=
null
);
assert
(
configuration
!=
null
);
assert
(
_debugEnsureInputActionWorksOnPlatform
(
configuration
.
inputAction
));
connection
.
setClient
(
configuration
);
_channel
.
invokeMethod
<
void
>(
'TextInput.setClient'
,
<
dynamic
>[
connection
.
_id
,
configuration
.
toJson
()
],
);
_currentConnection
=
connection
;
_currentConfiguration
=
configuration
;
}
...
...
@@ -1384,13 +1231,80 @@ class TextInput {
return
true
;
}
final
_TextInputSource
_currentSource
=
_TextInputSource
();
late
MethodChannel
_channel
;
TextInputConnection
?
_currentConnection
;
late
TextInputConfiguration
_currentConfiguration
;
Future
<
dynamic
>
_handleTextInputInvocation
(
MethodCall
methodCall
)
async
{
if
(
_currentConnection
==
null
)
return
;
final
String
method
=
methodCall
.
method
;
// The requestExistingInputState request needs to be handled regardless of
// the client ID, as long as we have a _currentConnection.
if
(
method
==
'TextInputClient.requestExistingInputState'
)
{
assert
(
_currentConnection
!.
_client
!=
null
);
_attach
(
_currentConnection
!,
_currentConfiguration
);
final
TextEditingValue
?
editingValue
=
_currentConnection
!.
_client
.
currentTextEditingValue
;
if
(
editingValue
!=
null
)
{
_setEditingState
(
editingValue
);
}
return
;
}
final
List
<
dynamic
>
args
=
methodCall
.
arguments
as
List
<
dynamic
>;
if
(
method
==
'TextInputClient.updateEditingStateWithTag'
)
{
final
TextInputClient
client
=
_currentConnection
!.
_client
;
assert
(
client
!=
null
);
final
AutofillScope
?
scope
=
client
.
currentAutofillScope
;
final
Map
<
String
,
dynamic
>
editingValue
=
args
[
1
]
as
Map
<
String
,
dynamic
>;
for
(
final
String
tag
in
editingValue
.
keys
)
{
final
TextEditingValue
textEditingValue
=
TextEditingValue
.
fromJSON
(
editingValue
[
tag
]
as
Map
<
String
,
dynamic
>,
);
scope
?.
getAutofillClient
(
tag
)?.
updateEditingValue
(
textEditingValue
);
}
return
;
}
final
int
client
=
args
[
0
]
as
int
;
// The incoming message was for a different client.
if
(
client
!=
_currentConnection
!.
_id
)
return
;
switch
(
method
)
{
case
'TextInputClient.updateEditingState'
:
_currentConnection
!.
_client
.
updateEditingValue
(
TextEditingValue
.
fromJSON
(
args
[
1
]
as
Map
<
String
,
dynamic
>));
break
;
case
'TextInputClient.performAction'
:
_currentConnection
!.
_client
.
performAction
(
_toTextInputAction
(
args
[
1
]
as
String
));
break
;
case
'TextInputClient.performPrivateCommand'
:
_currentConnection
!.
_client
.
performPrivateCommand
(
args
[
1
][
'action'
]
as
String
,
args
[
1
][
'data'
]
as
Map
<
String
,
dynamic
>);
break
;
case
'TextInputClient.updateFloatingCursor'
:
_currentConnection
!.
_client
.
updateFloatingCursor
(
_toTextPoint
(
_toTextCursorAction
(
args
[
1
]
as
String
),
args
[
2
]
as
Map
<
String
,
dynamic
>,
));
break
;
case
'TextInputClient.onConnectionClosed'
:
_currentConnection
!.
_client
.
connectionClosed
();
break
;
case
'TextInputClient.showAutocorrectionPromptRect'
:
_currentConnection
!.
_client
.
showAutocorrectionPromptRect
(
args
[
1
]
as
int
,
args
[
2
]
as
int
);
break
;
default
:
throw
MissingPluginException
();
}
}
bool
_hidePending
=
false
;
void
_scheduleHide
(
TextInputConnection
connection
)
{
void
_scheduleHide
()
{
if
(
_hidePending
)
return
;
_hidePending
=
true
;
...
...
@@ -1401,50 +1315,59 @@ class TextInput {
scheduleMicrotask
(()
{
_hidePending
=
false
;
if
(
_currentConnection
==
null
)
connection
.
hide
(
);
_channel
.
invokeMethod
<
void
>(
'TextInput.hide'
);
});
}
/// Stop interacting with the text input control.
///
/// A client that no longer wishes to interact with the text input control
/// should call this method.
///
/// After calling this method, the text input control might be requested to
/// hide if no other client attaches to it within this animation frame.
///
/// See also:
///
/// * [TextInputConnection.hide], a method called when the text input control
/// actually should hide.
static
void
detach
(
TextInputClient
client
)
{
assert
(
client
!=
null
);
if
(
client
!=
_instance
.
_currentConnection
?.
_client
)
return
;
_instance
.
_detach
();
void
_clearClient
()
{
_channel
.
invokeMethod
<
void
>(
'TextInput.clearClient'
);
_currentConnection
=
null
;
_scheduleHide
();
}
void
_detach
()
{
if
(
_currentConnection
==
null
)
return
;
_currentConnection
!.
clearClient
();
_scheduleHide
(
_currentConnection
!);
_currentSource
.
detach
(
_currentConnection
!.
_client
);
_currentConnection
=
null
;
void
_updateConfig
(
TextInputConfiguration
configuration
)
{
assert
(
configuration
!=
null
);
_channel
.
invokeMethod
<
void
>(
'TextInput.updateConfig'
,
configuration
.
toJson
(),
);
}
/// Resets the current text input connection.
///
/// This function should be called to reset the current text input connection
/// in case the platform sent a notification informing the connection is
/// closed.
///
/// See also:
///
/// * [TextInputClient.connectionClosed], a method called to notify the
/// current text input client when the connection is closed.
static
void
reset
()
{
_instance
.
_currentConnection
=
null
;
void
_setEditingState
(
TextEditingValue
value
)
{
assert
(
value
!=
null
);
_channel
.
invokeMethod
<
void
>(
'TextInput.setEditingState'
,
value
.
toJSON
(),
);
}
void
_show
()
{
_channel
.
invokeMethod
<
void
>(
'TextInput.show'
);
}
void
_requestAutofill
()
{
_channel
.
invokeMethod
<
void
>(
'TextInput.requestAutofill'
);
}
void
_setEditableSizeAndTransform
(
Map
<
String
,
dynamic
>
args
)
{
_channel
.
invokeMethod
<
void
>(
'TextInput.setEditableSizeAndTransform'
,
args
,
);
}
void
_setComposingTextRect
(
Map
<
String
,
dynamic
>
args
)
{
_channel
.
invokeMethod
<
void
>(
'TextInput.setMarkedTextRect'
,
args
,
);
}
void
_setStyle
(
Map
<
String
,
dynamic
>
args
)
{
_channel
.
invokeMethod
<
void
>(
'TextInput.setStyle'
,
args
,
);
}
/// Finishes the current autofill context, and potentially saves the user
...
...
@@ -1497,42 +1420,9 @@ class TextInput {
/// topmost [AutofillGroup] is getting disposed.
static
void
finishAutofillContext
({
bool
shouldSave
=
true
})
{
assert
(
shouldSave
!=
null
);
_instance
.
_currentSource
.
finishAutofillContext
(
shouldSave:
shouldSave
);
}
}
class
_TextInputSource
{
static
MethodChannel
?
_channel
;
static
void
setChannel
(
MethodChannel
newChannel
)
{
_channel
=
newChannel
..
setMethodCallHandler
(
_handleTextInputInvocation
);
}
void
init
()
{
_channel
??=
SystemChannels
.
textInput
;
_channel
!.
setMethodCallHandler
(
_handleTextInputInvocation
);
}
void
cleanup
()
{
_channel
!.
setMethodCallHandler
((
MethodCall
methodCall
)
async
{});
}
TextInputConnection
attach
(
TextInputClient
client
)
{
return
_TextInputChannelConnection
(
client
,
_channel
!);
}
void
detach
(
TextInputClient
client
)
{}
void
finishAutofillContext
({
bool
shouldSave
=
true
})
{
_channel
!.
invokeMethod
<
void
>(
TextInput
.
_instance
.
_channel
.
invokeMethod
<
void
>(
'TextInput.finishAutofillContext'
,
shouldSave
,
shouldSave
,
);
}
static
Future
<
dynamic
>
_handleTextInputInvocation
(
MethodCall
methodCall
)
async
{
final
TextInputConnection
?
connection
=
TextInput
.
_instance
.
_currentConnection
;
if
(
connection
is
_TextInputChannelConnection
)
return
connection
.
_handleTextInputInvocation
(
methodCall
);
}
}
packages/flutter/lib/src/widgets/editable_text.dart
View file @
61299b16
...
...
@@ -2038,7 +2038,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
void
_closeInputConnectionIfNeeded
()
{
if
(
_hasInputConnection
)
{
TextInput
.
detach
(
this
);
_textInputConnection
!.
close
(
);
_textInputConnection
=
null
;
_lastKnownRemoteTextEditingValue
=
null
;
}
...
...
@@ -2056,6 +2056,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
@override
void
connectionClosed
()
{
if
(
_hasInputConnection
)
{
_textInputConnection
!.
connectionClosedReceived
();
_textInputConnection
=
null
;
_lastKnownRemoteTextEditingValue
=
null
;
_finalizeEditing
(
TextInputAction
.
done
,
shouldUnfocus:
true
);
...
...
packages/flutter/test/services/text_input_test.dart
View file @
61299b16
...
...
@@ -22,7 +22,6 @@ void main() {
});
tearDown
(()
{
TextInput
.
reset
();
TextInputConnection
.
debugResetId
();
TextInput
.
setChannel
(
SystemChannels
.
textInput
);
});
...
...
@@ -75,65 +74,6 @@ void main() {
}),
]);
});
test
(
'text input client is requested to hide on detach'
,
()
async
{
final
FakeTextInputClient
client
=
FakeTextInputClient
(
TextEditingValue
.
empty
);
TextInput
.
attach
(
client
,
client
.
configuration
);
fakeTextChannel
.
validateOutgoingMethodCalls
(<
MethodCall
>[
MethodCall
(
'TextInput.setClient'
,
<
dynamic
>[
1
,
client
.
configuration
.
toJson
()]),
]);
TextInput
.
detach
(
client
);
fakeTextChannel
.
validateOutgoingMethodCalls
(<
MethodCall
>[
// From original attach
MethodCall
(
'TextInput.setClient'
,
<
dynamic
>[
1
,
client
.
configuration
.
toJson
()]),
// From detach
const
MethodCall
(
'TextInput.clearClient'
),
]);
final
TestWidgetsFlutterBinding
binding
=
TestWidgetsFlutterBinding
.
ensureInitialized
()
as
TestWidgetsFlutterBinding
;
await
binding
.
runAsync
(()
async
{});
await
expectLater
(
fakeTextChannel
.
outgoingCalls
.
length
,
3
);
fakeTextChannel
.
validateOutgoingMethodCalls
(<
MethodCall
>[
// From original attach
MethodCall
(
'TextInput.setClient'
,
<
dynamic
>[
1
,
client
.
configuration
.
toJson
()]),
// From detach
const
MethodCall
(
'TextInput.clearClient'
),
// From hide
const
MethodCall
(
'TextInput.hide'
),
]);
});
test
(
'old client is detached when a new client is attached'
,()
{
final
FakeTextInputClient
client1
=
FakeTextInputClient
(
const
TextEditingValue
(
text:
'1'
));
final
TextInputConnection
connection1
=
TextInput
.
attach
(
client1
,
client1
.
configuration
);
expect
(
connection1
.
attached
,
isTrue
);
fakeTextChannel
.
validateOutgoingMethodCalls
(<
MethodCall
>[
MethodCall
(
'TextInput.setClient'
,
<
dynamic
>[
1
,
client1
.
configuration
.
toJson
()]),
]);
final
FakeTextInputClient
client2
=
FakeTextInputClient
(
const
TextEditingValue
(
text:
'1'
));
final
TextInputConnection
connection2
=
TextInput
.
attach
(
client2
,
client2
.
configuration
);
expect
(
connection2
.
attached
,
isTrue
);
expect
(
connection1
.
attached
,
isFalse
);
fakeTextChannel
.
validateOutgoingMethodCalls
(<
MethodCall
>[
// From original attach
MethodCall
(
'TextInput.setClient'
,
<
dynamic
>[
1
,
client1
.
configuration
.
toJson
()]),
// From internal detach
const
MethodCall
(
'TextInput.clearClient'
),
// From second attach
MethodCall
(
'TextInput.setClient'
,
<
dynamic
>[
2
,
client1
.
configuration
.
toJson
()]),
]);
});
test
(
'text input connection is reset'
,
()
async
{
final
FakeTextInputClient
client
=
FakeTextInputClient
(
TextEditingValue
.
empty
);
final
TextInputConnection
connection
=
TextInput
.
attach
(
client
,
client
.
configuration
);
expect
(
connection
.
attached
,
isTrue
);
TextInput
.
reset
();
expect
(
connection
.
attached
,
isFalse
);
});
});
group
(
'TextInputConfiguration'
,
()
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment