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
ff97e255
Unverified
Commit
ff97e255
authored
Dec 14, 2018
by
Jonah Williams
Committed by
GitHub
Dec 14, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
drop/restore focus when app becomes invisible/visible (#24744)
parent
ea7d086e
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
99 additions
and
3 deletions
+99
-3
app.dart
packages/flutter/lib/src/widgets/app.dart
+28
-1
focus_manager.dart
packages/flutter/lib/src/widgets/focus_manager.dart
+43
-2
focus_test.dart
packages/flutter/test/widgets/focus_test.dart
+28
-0
No files found.
packages/flutter/lib/src/widgets/app.dart
View file @
ff97e255
...
...
@@ -12,6 +12,7 @@ import 'package:flutter/rendering.dart';
import
'banner.dart'
;
import
'basic.dart'
;
import
'binding.dart'
;
import
'focus_manager.dart'
;
import
'framework.dart'
;
import
'localizations.dart'
;
import
'media_query.dart'
;
...
...
@@ -730,7 +731,33 @@ class _WidgetsAppState extends State<WidgetsApp> implements WidgetsBindingObserv
}
@override
void
didChangeAppLifecycleState
(
AppLifecycleState
state
)
{
}
void
didChangeAppLifecycleState
(
AppLifecycleState
state
)
{
switch
(
defaultTargetPlatform
)
{
case
TargetPlatform
.
iOS
:
return
;
case
TargetPlatform
.
android
:
case
TargetPlatform
.
fuchsia
:
// When the application moves to the background, any focus nodes
// need to lose focus. When the application is restored to the
// foreground state, any focused node should regain focus (including)
// restoring the keyboard. This is only important in cases where
// applications in the background are partially visible.
switch
(
state
)
{
case
AppLifecycleState
.
paused
:
case
AppLifecycleState
.
suspending
:
case
AppLifecycleState
.
inactive
:
{
final
FocusManager
focusManager
=
WidgetsBinding
.
instance
.
focusManager
;
focusManager
.
windowDidLoseFocus
();
break
;
}
case
AppLifecycleState
.
resumed
:
{
final
FocusManager
focusManager
=
WidgetsBinding
.
instance
.
focusManager
;
focusManager
.
windowDidGainFocus
();
break
;
}
}
}
}
@override
void
didHaveMemoryPressure
()
{
}
...
...
packages/flutter/lib/src/widgets/focus_manager.dart
View file @
ff97e255
...
...
@@ -417,6 +417,45 @@ class FocusManager {
final
FocusScopeNode
rootScope
=
FocusScopeNode
();
FocusNode
_currentFocus
;
bool
_windowHasFocus
=
true
;
FocusNode
_cachedFocus
;
FocusScopeNode
_cachedScope
;
/// Call when the window loses focus.
///
/// The currently focused node and containg scope is cached, then the current
/// focus is removed. For example, this ensures that cursors do not blink
/// while in the background.
///
/// This method is safe to call multiple times.
void
windowDidLoseFocus
()
{
if
(!
_windowHasFocus
)
{
return
;
}
_windowHasFocus
=
false
;
_cachedFocus
=
_currentFocus
;
_cachedScope
=
_cachedFocus
.
_parent
;
_currentFocus
?.
unfocus
();
}
/// Call when the window regains focus.
///
/// If there is a cached focus node from when the window lost focus, this
/// method will restore focus to that node. For example, this ensures that
/// a focused text node will re-request the keyboard.
///
/// This method is safe to call multiple times.
void
windowDidGainFocus
()
{
if
(
_windowHasFocus
)
{
return
;
}
_windowHasFocus
=
true
;
if
(
_cachedFocus
!=
null
)
{
_cachedScope
.
_setFocus
(
_cachedFocus
);
_cachedFocus
=
null
;
_cachedScope
=
null
;
}
}
void
_willDisposeFocusNode
(
FocusNode
node
)
{
assert
(
node
!=
null
);
...
...
@@ -434,16 +473,18 @@ class FocusManager {
FocusNode
_findNextFocus
()
{
FocusScopeNode
scope
=
rootScope
;
while
(
scope
.
_firstChild
!=
null
)
while
(
scope
.
_firstChild
!=
null
)
{
scope
=
scope
.
_firstChild
;
}
return
scope
.
_focus
;
}
void
_update
()
{
_haveScheduledUpdate
=
false
;
final
FocusNode
nextFocus
=
_findNextFocus
();
if
(
_currentFocus
==
nextFocus
)
if
(
_currentFocus
==
nextFocus
)
{
return
;
}
final
FocusNode
previousFocus
=
_currentFocus
;
_currentFocus
=
nextFocus
;
previousFocus
?.
_notify
();
...
...
packages/flutter/test/widgets/focus_test.dart
View file @
ff97e255
...
...
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'package:flutter/widgets.dart'
;
...
...
@@ -243,4 +246,29 @@ void main() {
parentFocusScope
.
detach
();
});
testWidgets
(
'Focus is lost/restored when window focus is lost/restored on Fuchsia'
,
(
WidgetTester
tester
)
async
{
debugDefaultTargetPlatformOverride
=
TargetPlatform
.
fuchsia
;
final
FocusNode
node
=
FocusNode
();
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Scaffold
(
body:
TextField
(
focusNode:
node
,
autofocus:
true
,
)
),
));
expect
(
node
.
hasFocus
,
true
);
ByteData
message
=
const
StringCodec
().
encodeMessage
(
'AppLifecycleState.inactive'
);
await
BinaryMessages
.
handlePlatformMessage
(
'flutter/lifecycle'
,
message
,
(
_
)
{});
await
tester
.
pump
();
// Focus is lost when app goes to background.
expect
(
node
.
hasFocus
,
false
);
message
=
const
StringCodec
().
encodeMessage
(
'AppLifecycleState.resumed'
);
await
BinaryMessages
.
handlePlatformMessage
(
'flutter/lifecycle'
,
message
,
(
_
)
{});
await
tester
.
pump
();
// Focus is restored.
expect
(
node
.
hasFocus
,
true
);
debugDefaultTargetPlatformOverride
=
null
;
});
}
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