Skip to content

Commit fc4a91e

Browse files
authored
[pointer_interceptor_web] Fix unresponsive input above PointerInterceptor on Safari and Firefox. (#9362)
Fixes flutter/flutter#157920 ### Description When the `TextField` is placed above the `HtmlElementView`, it becomes unresponsive on Safari and Firefox. After the investigation, I found that this happens because the underlying `input`/`textarea` loses focus, leading to not listening to the keyboard input. After some investigation, I found out that calling `preventDefault` on `mousedown` events on `PointerInterceptor` `div` element prevents the `input/textarea` from losing focus. The same was already done for `SelectionArea` in flutter/flutter#167275 | Before | After | | :---: | :---: | | https://input-above-interceptor-bug.web.app | https://input-above-interceptor-fix.web.app | | <video src="https://github.com/user-attachments/assets/3537d34d-9eb2-4a36-bbcf-4cb0de01133d" /> | <video src="https://github.com/user-attachments/assets/14458b51-bcf0-4761-9b57-7735a214125b" /> | <details> <summary>Application Source Code</summary> ```dart import 'package:flutter/material.dart'; import 'package:web/web.dart' as web; import 'package:pointer_interceptor/pointer_interceptor.dart'; void main() { runApp(const App()); } class App extends StatelessWidget { const App({super.key}); @OverRide Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: Stack( children: [ Positioned.fill( child: HtmlElementView.fromTagName( tagName: 'iframe', onElementCreated: (element) { (element as web.HTMLIFrameElement); element.src = 'https://flutter.dev'; element.style ..border = 'none' ..height = '100%' ..width = '100%'; }, ), ), Center( child: PointerInterceptor( debug: true, child: Container( width: 400, decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), color: Colors.grey.shade300, ), padding: const EdgeInsets.all(20), child: Column( mainAxisSize: MainAxisSize.min, children: [ OneLineTextField(), OneLineTextField(), OneLineTextField(), ], ), ), ), ), ], ), ), ); } } class OneLineTextField extends StatelessWidget { const OneLineTextField({super.key}); @OverRide Widget build(BuildContext context) { return TextField( decoration: InputDecoration( labelText: 'One-line', floatingLabelBehavior: FloatingLabelBehavior.always, ), ); } } ``` </details> ## Pre-Review Checklist [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
1 parent 1765c95 commit fc4a91e

File tree

4 files changed

+45
-5
lines changed

4 files changed

+45
-5
lines changed

packages/pointer_interceptor/pointer_interceptor_web/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
## NEXT
1+
## 0.10.3
22

33
* Updates minimum supported SDK version to Flutter 3.27/Dart 3.6.
4+
* Fixes `TextField` internal focus loss when wrapped with `PointerInterceptor`.
45

56
## 0.10.2+1
67

packages/pointer_interceptor/pointer_interceptor_web/example/integration_test/widget_test.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,29 @@ void main() {
6363

6464
expect(element.id, 'background-html-view');
6565
}, semanticsEnabled: false);
66+
67+
// Regression test for https://github.com/flutter/flutter/issues/157920
68+
testWidgets(
69+
'prevents default action of mousedown events',
70+
(WidgetTester tester) async {
71+
await _fullyRenderApp(tester);
72+
73+
final web.Element element =
74+
_getHtmlElementAtCenter(clickableButtonFinder, tester);
75+
expect(element.tagName.toLowerCase(), 'div');
76+
77+
for (int i = 0; i <= 4; i++) {
78+
final web.MouseEvent event = web.MouseEvent(
79+
'mousedown',
80+
web.MouseEventInit(button: i, cancelable: true),
81+
);
82+
element.dispatchEvent(event);
83+
expect(event.target, element);
84+
expect(event.defaultPrevented, isTrue);
85+
}
86+
},
87+
semanticsEnabled: false,
88+
);
6689
});
6790
}
6891

packages/pointer_interceptor/pointer_interceptor_web/lib/pointer_interceptor_web.dart

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import 'dart:js_interop';
6+
57
import 'package:flutter/widgets.dart';
68
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
79
import 'package:pointer_interceptor_platform_interface/pointer_interceptor_platform_interface.dart';
@@ -17,8 +19,8 @@ class PointerInterceptorWeb extends PointerInterceptorPlatform {
1719
}
1820

1921
// Slightly modify the created `element` (for `debug` mode).
20-
void _onElementCreated(Object element) {
21-
(element as web.HTMLElement)
22+
void _debugOnElementCreated(web.HTMLElement element) {
23+
element
2224
..style.width = '100%'
2325
..style.height = '100%'
2426
..style.backgroundColor = 'rgba(255, 0, 0, .5)';
@@ -41,7 +43,21 @@ class PointerInterceptorWeb extends PointerInterceptorPlatform {
4143
child: HtmlElementView.fromTagName(
4244
tagName: 'div',
4345
isVisible: false,
44-
onElementCreated: debug ? _onElementCreated : null,
46+
onElementCreated: (Object element) {
47+
element as web.HTMLElement;
48+
if (debug) {
49+
_debugOnElementCreated(element);
50+
}
51+
52+
// Prevent the default action of `mousedown` events to avoid
53+
// input focus loss.
54+
element.addEventListener(
55+
'mousedown',
56+
(web.Event event) {
57+
event.preventDefault();
58+
}.toJS,
59+
);
60+
},
4561
),
4662
),
4763
child,

packages/pointer_interceptor/pointer_interceptor_web/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: pointer_interceptor_web
22
description: Web implementation of the pointer_interceptor plugin.
33
repository: https://github.com/flutter/packages/tree/main/packages/pointer_interceptor/pointer_interceptor_web
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3Apointer_interceptor
5-
version: 0.10.2+1
5+
version: 0.10.3
66

77
environment:
88
sdk: ^3.6.0

0 commit comments

Comments
 (0)