Open hawkkiller opened 6 months ago
At first glance, this doesn't look like a SuperEditor
issue - it looks like a focus management issue.
The focused widget receives key events and IME input, so Super Editor can't keep the keyboard open if focus moves to a different widget. My guess is that tapping on the toggle button is changing focus to that button.
SuperEditor
lets you specify a focusNode
. It also lets you specify a tagRegionGroupId
. Can you please try to use the available focus-related properties on SuperEditor
to get the result that you want?
@angelosilvestre do you have any other thoughts on this?
It is not necessarily a button. Tapping on any surface in Mobile Web closes the keyboard (material TextField as well). Another problem is that the SuperEditor stays focused (or at least paints the cursor).
https://github.com/superlistapp/super_editor/assets/62852417/064ebb76-2666-4bf7-9c91-0023843c18e6
Tapping on any surface in Mobile Web closes the keyboard (material TextField as well)
Right. I didn't say it was about the button. I said it was about the focus node that's probably inside the button, which is probably receiving focus when you tap on it.
Another problem is that the SuperEditor stays focused (or at least paints the cursor).
This may or may not be a bug. Depends on the exact situation.
By default, SuperEditor
will close the IME connection when it loses focus. This will cause the keyboard to close.
If you want to keep the keyboard visible, you need to either:
SuperEditorImePolicies
).@hawkkiller please let us know if Angelo's message resolved your issues.
Hi @matthew-carroll @angelosilvestre
I've just verified that neither setting tap regions, focus nodes, or configuring the policy doesn't work (at least for the code provided).
Do you have any suggestions to check?
Widget build(BuildContext context) => MaterialApp(
home: Builder(builder: (context) {
return Scaffold(
body: Padding(
padding: MediaQuery.of(context).padding,
child: Focus(
focusNode: _focusNode,
child: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Center(
child: TapRegion(
groupId: 'super_editor',
child: ToggleButtons(
onPressed: (index) {},
isSelected: const [false, false, false],
children: const [
Icon(Icons.ac_unit),
Icon(Icons.call),
Icon(Icons.cake),
],
),
),
),
),
SliverToBoxAdapter(
child: SuperEditor(
imePolicies: const SuperEditorImePolicies(
closeKeyboardOnSelectionLost: false,
closeImeOnNonPrimaryFocusLost: false,
closeKeyboardOnLosePrimaryFocus: false,
),
tapRegionGroupId: 'super_editor',
focusNode: _focusNode,
editor: editor,
document: document,
composer: composer,
),
),
],
),
),
),
);
}),
);
@hawkkiller Please try to do something like this:
Widget build(BuildContext context) => MaterialApp(
home: Builder(builder: (context) {
return Scaffold(
body: Padding(
padding: MediaQuery.of(context).padding,
child: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Center(
child: Focus(
focusNode: _buttonsFocusNode,
parentNode: _editorFocusNode,
child: ToggleButtons(
onPressed: (index) {},
isSelected: const [false, false, false],
children: const [
Icon(Icons.ac_unit),
Icon(Icons.call),
Icon(Icons.cake),
],
),
),
),
),
SliverToBoxAdapter(
child: SuperEditor(
focusNode: _editorFocusNode,
editor: editor,
document: document,
composer: composer,
),
),
],
),
),
);
}),
);
@angelosilvestre Keyboard still closes and this happens only on the Mobile Web (where clicking anywhere closes the keyboard by default for some reason, which is not typical for other platforms).
For example, this issue doesn't occur on mobile (if launched not via Web).
If you need assistance with debugging, testing, or experimenting with potential fixes for this problem, I'm happy to help you.
@hawkkiller Did you try to use my sample code and also provide the IME policies?
@angelosilvestre Yes!
@matthew-carroll @hawkkiller I'm afraid we might not be able to work around this. I took a look and this seems related to the events the browser send us.
When we tap outside of the currently focused input ( the invisible input that Flutter places to handle the input), the browser sends us a blur event.
The Flutter engine listens for blur events and closes the input connection when that happens:
// Record start time of blur subscription.
final Stopwatch blurWatch = Stopwatch()..start();
// On iOS, blur is trigerred in the following cases:
//
// 1. The browser app is sent to the background (or the tab is changed). In
// this case, the window loses focus (see [windowHasFocus]),
// so we close the input connection with the framework.
// 2. The user taps on another focusable element. In this case, we refocus
// the input field and wait for the framework to manage the focus change.
// 3. The virtual keyboard is closed by tapping "done". We can't detect this
// programmatically, so we end up refocusing the input field. This is
// okay because the virtual keyboard will hide, and as soon as the user
// taps the text field again, the virtual keyboard will come up.
// 4. Safari sometimes sends a blur event immediately after activating the
// input field. In this case, we want to keep the focus on the input field.
// In order to detect this, we measure how much time has passed since the
// input field was activated. If the time is too short, we re-focus the
// input element.
subscriptions.add(DomSubscription(activeDomElement, 'blur',
(_) {
final bool isFastCallback = blurWatch.elapsed < _blurFastCallbackInterval;
if (windowHasFocus && isFastCallback) {
activeDomElement.focus();
} else {
owner.sendTextConnectionClosedToFrameworkIfAny(); <----- Here
}
}));
}
Maybe this comment is outdated, or I'm not looking at the correct place, but I'm not seeing how the following case is being handled:
// 2. The user taps on another focusable element. In this case, we refocus
// the input field and wait for the framework to manage the focus change.
@justinmc @Renzo-Olivares - Do either of you have insights or info about this situation with Flutter on web when tapping outside the currently focused widget?
I'm not entirely sure what the issue is here but it looks like the frameworks TextField
is exhibiting the same behavior. I opened an issue to track this https://github.com/flutter/flutter/issues/149685.
Package Version Github, main
To Reproduce Steps to reproduce the behavior:
Minimal Reproduction Code
Minimal, Runnable Code Sample
```dart import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:super_editor/super_editor.dart'; void main() { runApp(const MainApp()); } class MainApp extends StatefulWidget { const MainApp({super.key}); @override StateActual behavior Keyboard closes.
Expected behavior The keyboard is not closed.
Platform iOS Web.
Additional context In flutter docs, there is a TextFieldTapRegion that seems to work with text fields (though with some problems).
I have tried wrapping toggle buttons in TapRegion and providing the same group id to SuperEditor, but it doesn't seem to work.
cc: @matthew-carroll @angelosilvestre