Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit df964be

Browse files
committed
[web] Migrate Flutter Web DOM usage to JS static interop - 31.
1 parent b7ee0fc commit df964be

File tree

7 files changed

+98
-64
lines changed

7 files changed

+98
-64
lines changed

lib/web_ui/lib/src/engine/dom.dart

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ extension DomHTMLDocumentExtension on DomHTMLDocument {
9999
external DomHTMLHeadElement? get head;
100100
external DomHTMLBodyElement? get body;
101101
external set title(String? value);
102+
Iterable<DomElement> getElementsByTagName(String tag) =>
103+
createDomListWrapper<DomElement>(js_util
104+
.callMethod<_DomList>(this, 'getElementsByTagName', <Object>[tag]));
102105
}
103106

104107
@JS('document')
@@ -124,6 +127,8 @@ extension DomEventTargetExtension on DomEventTarget {
124127
<Object>[type, listener, if (useCapture != null) useCapture]);
125128
}
126129
}
130+
131+
external bool dispatchEvent(DomEvent event);
127132
}
128133

129134
typedef DomEventListener = void Function(DomEvent event);
@@ -951,11 +956,19 @@ class DomMouseEvent extends DomUIEvent {}
951956
extension DomMouseEventExtension on DomMouseEvent {
952957
external num get clientX;
953958
external num get clientY;
959+
external num get offsetX;
960+
external num get offsetY;
961+
DomPoint get client => DomPoint(clientX, clientY);
962+
DomPoint get offset => DomPoint(offsetX, offsetY);
954963
external int get button;
955964
external int? get buttons;
956965
external bool getModifierState(String keyArg);
957966
}
958967

968+
DomMouseEvent createDomMouseEvent(String type, [Map<dynamic, dynamic>? init]) =>
969+
js_util.callConstructor(domGetConstructor('MouseEvent')!,
970+
<Object>[type, if (init != null) js_util.jsify(init)]);
971+
959972
@JS()
960973
@staticInterop
961974
class DomPointerEvent extends DomMouseEvent {}
@@ -971,6 +984,11 @@ extension DomPointerEventExtension on DomPointerEvent {
971984
this, 'getCoalescedEvents', <Object>[]).cast<DomPointerEvent>();
972985
}
973986

987+
DomPointerEvent createDomPointerEvent(String type,
988+
[Map<dynamic, dynamic>? init]) =>
989+
js_util.callConstructor(domGetConstructor('PointerEvent')!,
990+
<Object>[type, if (init != null) js_util.jsify(init)]);
991+
974992
@JS()
975993
@staticInterop
976994
class DomWheelEvent extends DomMouseEvent {}
@@ -997,10 +1015,15 @@ class DomTouch {}
9971015

9981016
extension DomTouchExtension on DomTouch {
9991017
external int? get identifier;
1000-
external num? get clientX;
1001-
external num? get clientY;
1018+
external num get clientX;
1019+
external num get clientY;
1020+
DomPoint get client => DomPoint(clientX, clientY);
10021021
}
10031022

1023+
DomTouchEvent createDomTouchEvent(String type, [Map<dynamic, dynamic>? init]) =>
1024+
js_util.callConstructor(domGetConstructor('TouchEvent')!,
1025+
<Object>[type, if (init != null) js_util.jsify(init)]);
1026+
10041027
@JS()
10051028
@staticInterop
10061029
class DomHTMLInputElement extends DomHTMLElement {}
@@ -1018,6 +1041,13 @@ extension DomHTMLInputElementExtension on DomHTMLInputElement {
10181041
DomHTMLInputElement createDomHTMLInputElement() =>
10191042
domDocument.createElement('input') as DomHTMLInputElement;
10201043

1044+
class DomPoint {
1045+
final num x;
1046+
final num y;
1047+
1048+
DomPoint(this.x, this.y);
1049+
}
1050+
10211051
Object? domGetConstructor(String constructorName) =>
10221052
js_util.getProperty(domWindow, constructorName);
10231053

lib/web_ui/lib/src/engine/embedder.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ class FlutterViewEmbedder {
311311

312312
final html.Element _accessibilityPlaceholder = EngineSemanticsOwner
313313
.instance.semanticsHelper
314-
.prepareAccessibilityPlaceholder();
314+
.prepareAccessibilityPlaceholder() as html.Element;
315315

316316
glassPaneElementHostNode.nodes.addAll(<html.Node>[
317317
_accessibilityPlaceholder,

lib/web_ui/lib/src/engine/pointer_binding.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -867,8 +867,8 @@ class _TouchAdapter extends _BaseAdapter {
867867
kind: ui.PointerDeviceKind.touch,
868868
signalKind: ui.PointerSignalKind.none,
869869
device: touch.identifier!,
870-
physicalX: touch.clientX!.toDouble() * ui.window.devicePixelRatio,
871-
physicalY: touch.clientY!.toDouble() * ui.window.devicePixelRatio,
870+
physicalX: touch.clientX.toDouble() * ui.window.devicePixelRatio,
871+
physicalY: touch.clientY.toDouble() * ui.window.devicePixelRatio,
872872
buttons: pressed ? _kPrimaryMouseButton : 0,
873873
pressure: 1.0,
874874
pressureMin: 0.0,

lib/web_ui/lib/src/engine/semantics/semantics.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1675,7 +1675,7 @@ class EngineSemanticsOwner {
16751675
_temporarilyDisableBrowserGestureMode();
16761676
}
16771677

1678-
return semanticsHelper.shouldEnableSemantics(event as html.Event);
1678+
return semanticsHelper.shouldEnableSemantics(event);
16791679
}
16801680

16811681
/// Callbacks called when the [GestureMode] changes.

lib/web_ui/lib/src/engine/semantics/semantics_helper.dart

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
// found in the LICENSE file.
44

55
import 'dart:async';
6-
import 'dart:html' as html;
76

87
import 'package:meta/meta.dart';
98

109
import '../browser_detection.dart';
10+
import '../dom.dart';
11+
import '../safe_browser_api.dart';
1112
import 'semantics.dart';
1213

1314
/// The maximum [semanticsActivationAttempts] before we give up waiting for
@@ -50,11 +51,11 @@ class SemanticsHelper {
5051
_semanticsEnabler = semanticsEnabler;
5152
}
5253

53-
bool shouldEnableSemantics(html.Event event) {
54+
bool shouldEnableSemantics(DomEvent event) {
5455
return _semanticsEnabler.shouldEnableSemantics(event);
5556
}
5657

57-
html.Element prepareAccessibilityPlaceholder() {
58+
DomElement prepareAccessibilityPlaceholder() {
5859
return _semanticsEnabler.prepareAccessibilityPlaceholder();
5960
}
6061

@@ -75,9 +76,9 @@ abstract class SemanticsEnabler {
7576
/// Semantics should be enabled if the web engine is no longer waiting for
7677
/// extra signals from the user events. See [isWaitingToEnableSemantics].
7778
///
78-
/// Or if the received [html.Event] is suitable/enough for enabling the
79+
/// Or if the received [DomEvent] is suitable/enough for enabling the
7980
/// semantics. See [tryEnableSemantics].
80-
bool shouldEnableSemantics(html.Event event) {
81+
bool shouldEnableSemantics(DomEvent event) {
8182
if (!isWaitingToEnableSemantics) {
8283
// Forward to framework as normal.
8384
return true;
@@ -90,15 +91,15 @@ abstract class SemanticsEnabler {
9091
///
9192
/// Returns true if the `event` is not related to semantics activation and
9293
/// should be forwarded to the framework.
93-
bool tryEnableSemantics(html.Event event);
94+
bool tryEnableSemantics(DomEvent event);
9495

9596
/// Creates the placeholder for accessibility.
9697
///
9798
/// Puts it inside the glasspane.
9899
///
99100
/// On focus the element announces that accessibility can be enabled by
100101
/// tapping/clicking. (Announcement depends on the assistive technology)
101-
html.Element prepareAccessibilityPlaceholder();
102+
DomElement prepareAccessibilityPlaceholder();
102103

103104
/// Whether platform is still considering enabling semantics.
104105
///
@@ -123,14 +124,14 @@ abstract class SemanticsEnabler {
123124
@visibleForTesting
124125
class DesktopSemanticsEnabler extends SemanticsEnabler {
125126
/// A temporary placeholder used to capture a request to activate semantics.
126-
html.Element? _semanticsPlaceholder;
127+
DomElement? _semanticsPlaceholder;
127128

128129
/// Whether we are waiting for the user to enable semantics.
129130
@override
130131
bool get isWaitingToEnableSemantics => _semanticsPlaceholder != null;
131132

132133
@override
133-
bool tryEnableSemantics(html.Event event) {
134+
bool tryEnableSemantics(DomEvent event) {
134135
// Semantics may be enabled programmatically. If there's a race between that
135136
// and the DOM event, we may end up here while there's no longer a placeholder
136137
// to work with.
@@ -173,15 +174,15 @@ class DesktopSemanticsEnabler extends SemanticsEnabler {
173174
}
174175

175176
@override
176-
html.Element prepareAccessibilityPlaceholder() {
177-
final html.Element placeholder =
178-
_semanticsPlaceholder = html.Element.tag('flt-semantics-placeholder');
177+
DomElement prepareAccessibilityPlaceholder() {
178+
final DomElement placeholder =
179+
_semanticsPlaceholder = createDomElement('flt-semantics-placeholder');
179180

180181
// Only listen to "click" because other kinds of events are reported via
181182
// PointerBinding.
182-
placeholder.addEventListener('click', (html.Event event) {
183+
placeholder.addEventListener('click', allowInterop((DomEvent event) {
183184
tryEnableSemantics(event);
184-
}, true);
185+
}), true);
185186

186187
// Adding roles to semantics placeholder. 'aria-live' will make sure that
187188
// the content is announced to the assistive technology user as soon as the
@@ -226,7 +227,7 @@ class MobileSemanticsEnabler extends SemanticsEnabler {
226227
Timer? semanticsActivationTimer;
227228

228229
/// A temporary placeholder used to capture a request to activate semantics.
229-
html.Element? _semanticsPlaceholder;
230+
DomElement? _semanticsPlaceholder;
230231

231232
/// The number of events we processed that could potentially activate
232233
/// semantics.
@@ -247,7 +248,7 @@ class MobileSemanticsEnabler extends SemanticsEnabler {
247248
bool get isWaitingToEnableSemantics => _semanticsPlaceholder != null;
248249

249250
@override
250-
bool tryEnableSemantics(html.Event event) {
251+
bool tryEnableSemantics(DomEvent event) {
251252
// Semantics may be enabled programmatically. If there's a race between that
252253
// and the DOM event, we may end up here while there's no longer a placeholder
253254
// to work with.
@@ -320,29 +321,29 @@ class MobileSemanticsEnabler extends SemanticsEnabler {
320321
// semantics tree is designed to not interfere with Flutter's gesture
321322
// detection.
322323
bool enableConditionPassed = false;
323-
html.Point<num> activationPoint;
324+
late final DomPoint activationPoint;
324325

325326
switch (event.type) {
326327
case 'click':
327-
final html.MouseEvent click = event as html.MouseEvent;
328+
final DomMouseEvent click = event as DomMouseEvent;
328329
activationPoint = click.offset;
329330
break;
330331
case 'touchstart':
331332
case 'touchend':
332-
final html.TouchEvent touch = event as html.TouchEvent;
333-
activationPoint = touch.changedTouches!.first.client;
333+
final DomTouchEvent touchEvent = event as DomTouchEvent;
334+
activationPoint = touchEvent.changedTouches!.first.client;
334335
break;
335336
case 'pointerdown':
336337
case 'pointerup':
337-
final html.PointerEvent touch = event as html.PointerEvent;
338-
activationPoint = html.Point<num>(touch.client.x, touch.client.y);
338+
final DomPointerEvent touch = event as DomPointerEvent;
339+
activationPoint = touch.client;
339340
break;
340341
default:
341342
// The event is not relevant, forward to framework as normal.
342343
return true;
343344
}
344345

345-
final html.Rectangle<num> activatingElementRect =
346+
final DomRect activatingElementRect =
346347
_semanticsPlaceholder!.getBoundingClientRect();
347348
final double midX = (activatingElementRect.left +
348349
(activatingElementRect.right - activatingElementRect.left) / 2)
@@ -372,15 +373,15 @@ class MobileSemanticsEnabler extends SemanticsEnabler {
372373
}
373374

374375
@override
375-
html.Element prepareAccessibilityPlaceholder() {
376-
final html.Element placeholder =
377-
_semanticsPlaceholder = html.Element.tag('flt-semantics-placeholder');
376+
DomElement prepareAccessibilityPlaceholder() {
377+
final DomElement placeholder =
378+
_semanticsPlaceholder = createDomElement('flt-semantics-placeholder');
378379

379380
// Only listen to "click" because other kinds of events are reported via
380381
// PointerBinding.
381-
placeholder.addEventListener('click', (html.Event event) {
382+
placeholder.addEventListener('click', allowInterop((DomEvent event) {
382383
tryEnableSemantics(event);
383-
}, true);
384+
}), true);
384385

385386
placeholder
386387
..setAttribute('role', 'button')

0 commit comments

Comments
 (0)