Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
0c265d1
Introduce FullScreenApplicationDom, and wire it to meta viewport, eve…
ditman Nov 11, 2022
87f1c91
Move internal stylesheet to HostNode from ViewEmbedder.
ditman Nov 16, 2022
9dd964b
Add setHostStyles and Attribute to ApplicationDom. Use it in the embe…
ditman Nov 16, 2022
48ddb1b
Move HotRestartCacheHandler to its own file.
ditman Nov 16, 2022
ca8db3e
Remove Safari hack for visualViewport.
ditman Nov 16, 2022
9b88880
No need to keep a ref to the viewport meta in full-screen.
ditman Nov 16, 2022
7cc8cf3
Add applicationDom.attachGlassPane and use it in the Embedder.
ditman Nov 16, 2022
10cf86e
Remove empty method bodies.
ditman Nov 16, 2022
58fb7d5
Add attachResourcesHost and use it from the embedder.
ditman Nov 17, 2022
769b4b6
Removed some unused code.
ditman Nov 17, 2022
eac7d73
Some more cleanup.
ditman Nov 17, 2022
b43417d
Add ResizeObserver JS interop API.
ditman Nov 18, 2022
140d7cf
Add the CustomElementApplicationDom and wire it to the ViewEmbedder.
ditman Nov 18, 2022
ddc9c9c
Add the DimensionsProvider classes.
ditman Nov 18, 2022
f798750
Reimplement engine.window using the DimensionsProvider.
ditman Nov 18, 2022
1064d64
Delegate window metrics to engine window in html scene object.
ditman Nov 18, 2022
8d618d7
Wire DimensionsProvider into engine.window.
ditman Nov 18, 2022
d40ecb4
Moved ApplicationDom into its own subdir.
ditman Nov 18, 2022
77cd76a
Make DimensionsProvider also an Observer. Expose onResize Stream.
ditman Nov 24, 2022
0c9d2c0
Delegate onResize and dpr from window to DimensionsObserver object.
ditman Nov 24, 2022
6fba209
Remove or make most ApplicationDom methods private. Expose single ini…
ditman Nov 24, 2022
86d1c74
Hook the new API.
ditman Nov 24, 2022
c30f13e
dart format
ditman Nov 24, 2022
6fbdbd3
ApplicationDom -> EmbeddingStrategy.
ditman Nov 29, 2022
19b5cf2
Attach pointer move events to glassPaneElement
ditman Nov 30, 2022
641bba7
Use offset positions for mouse events (relative to host element) rath…
ditman Nov 30, 2022
f773333
Update TouchAdapter to understand scrolling (simulate offsetX/Y)
ditman Nov 30, 2022
d3cf9d3
Remove locale change handling from the embedding strategy.
ditman Nov 30, 2022
5a180db
Move locale handling from the embedder to the platform dispatcher
ditman Nov 30, 2022
74f639f
Move some styles from host to glassPane so we are more friendly with …
ditman Nov 30, 2022
dee3f54
Make analyzer fixes
ditman Nov 30, 2022
1811c17
Ensure DimensionsProvider is available in tests.
ditman Nov 30, 2022
0d89e8e
Initialize the view DimensionsProvider next to where the EmbeddingStr…
ditman Dec 1, 2022
44725be
Bring back the logic to support Firefox 83.
ditman Dec 1, 2022
649116a
Fix pointer_binding test for new anchor point in the DOM.
ditman Dec 2, 2022
9d3c903
Fix pointer_binding_test in Firefox.
ditman Dec 6, 2022
3b69e0b
Add an iterable way of accessing 'rules'
ditman Dec 6, 2022
f217f9d
Merge latest changes to host_node stylesheet.
ditman Dec 6, 2022
5d469b1
Format test
ditman Dec 6, 2022
4cc8ce6
Try to use insertRule for -ms-reveal, and fallback in tests.
ditman Dec 6, 2022
264e3a4
Test hot_restart_cache_handler
ditman Dec 7, 2022
be99c2a
Test dimensions_provider.
ditman Dec 7, 2022
3eb9321
Test full_page_dimensions_provider
ditman Dec 8, 2022
9019df4
Test custom_element_dimensions_provider
ditman Dec 8, 2022
8834630
Test embedding_strategy. Make getDomCache util public.
ditman Dec 8, 2022
079d201
Fixes and tests for *_embedding_strategy.
ditman Dec 8, 2022
9a6702b
Move default text colors to our innermost style inside host_node (app…
ditman Dec 8, 2022
f4ff288
Safari expands shorthand properties in CSSOM.
ditman Dec 8, 2022
42e4298
Add computeEventOffsetToTarget function, and use it.
ditman Dec 14, 2022
a7447ac
Address PR comments.
ditman Dec 15, 2022
d1b93ba
Update licenses_flutter.
ditman Dec 15, 2022
5e48d3d
Remove DomCSSRuleList class and instead use Iterable of DomCSSRule
ditman Dec 17, 2022
53de810
Make the embeddingStrategy final instead of late
ditman Dec 17, 2022
0a817a6
Attach mouse/pointermove events to domWindow.
ditman Dec 17, 2022
b293d36
Rename DimensionsProvider.onHotRestart to .close, and slightly improv…
ditman Dec 17, 2022
76cec66
Fix compute physicalX/Y for TalkBack events.
ditman Dec 21, 2022
b48b397
Clarify what does (and does not) support 3D transforms in the event_p…
ditman Dec 22, 2022
57dc432
Update licenses file
ditman Dec 22, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -4413,6 +4413,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/platform_views/message_handler.
FILE: ../../../flutter/lib/web_ui/lib/src/engine/platform_views/slots.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/plugins.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/pointer_binding.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/pointer_binding/event_position_helper.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/pointer_converter.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/profiler.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/raw_keyboard.dart
Expand Down
1 change: 1 addition & 0 deletions lib/web_ui/lib/src/engine.dart
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ export 'engine/platform_views/message_handler.dart';
export 'engine/platform_views/slots.dart';
export 'engine/plugins.dart';
export 'engine/pointer_binding.dart';
export 'engine/pointer_binding/event_position_helper.dart';
export 'engine/pointer_converter.dart';
export 'engine/profiler.dart';
export 'engine/raw_keyboard.dart';
Expand Down
5 changes: 5 additions & 0 deletions lib/web_ui/lib/src/engine/dom.dart
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,9 @@ class DomHTMLElement extends DomElement {}

extension DomHTMLElementExtension on DomHTMLElement {
external double get offsetWidth;
external double get offsetLeft;
external double get offsetTop;
external DomHTMLElement? get offsetParent;
}

@JS()
Expand Down Expand Up @@ -1090,6 +1093,8 @@ extension DomMouseEventExtension on DomMouseEvent {
external double get clientY;
external double get offsetX;
external double get offsetY;
external double get pageX;
external double get pageY;
DomPoint get client => DomPoint(clientX, clientY);
DomPoint get offset => DomPoint(offsetX, offsetY);
external double get button;
Expand Down
28 changes: 4 additions & 24 deletions lib/web_ui/lib/src/engine/pointer_binding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import '../engine.dart' show registerHotRestartListener;
import 'browser_detection.dart';
import 'dom.dart';
import 'platform_dispatcher.dart';
import 'pointer_binding/event_position_helper.dart';
import 'pointer_converter.dart';
import 'safe_browser_api.dart';
import 'semantics.dart';
Expand Down Expand Up @@ -342,27 +343,6 @@ abstract class _BaseAdapter {
((milliseconds - ms) * Duration.microsecondsPerMillisecond).toInt();
return Duration(milliseconds: ms, microseconds: micro);
}

/// Returns an [ui.Offset] of the position of [event], relative to the position of [actualTarget].
///
/// The offset is *not* multiplied by DPR or anything else, it's the closest
/// to what the DOM would return if we had currentTarget readily available.
///
// TODO(dit): Make this understand 3D transforms in the platform view case, https://github.com/flutter/flutter/issues/117091
static ui.Offset computeEventOffsetToTarget(DomMouseEvent event, DomElement actualTarget) {
if (event.target != actualTarget) {
// We're on top of a platform view.
final DomElement target = event.target! as DomElement;
// We can't use currentTarget because it gets lost when the PointerEvents
// are coalesced!
final DomRect targetRect = target.getBoundingClientRect();
final DomRect actualTargetRect = actualTarget.getBoundingClientRect();
final double offsetTop = targetRect.y - actualTargetRect.y;
final double offsetLeft = targetRect.x - actualTargetRect.x;
return ui.Offset(event.offsetX + offsetLeft, event.offsetY + offsetTop);
}
return ui.Offset(event.offsetX, event.offsetY);
}
}

mixin _WheelEventListenerMixin on _BaseAdapter {
Expand Down Expand Up @@ -472,7 +452,7 @@ mixin _WheelEventListenerMixin on _BaseAdapter {
}

final List<ui.PointerData> data = <ui.PointerData>[];
final ui.Offset offset = _BaseAdapter.computeEventOffsetToTarget(event, glassPaneElement);
final ui.Offset offset = computeEventOffsetToTarget(event, glassPaneElement);
_pointerDataConverter.convert(
data,
change: ui.PointerChange.hover,
Expand Down Expand Up @@ -844,7 +824,7 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin {
final double tilt = _computeHighestTilt(event);
final Duration timeStamp = _BaseAdapter._eventTimeStampToDuration(event.timeStamp!);
final num? pressure = event.pressure;
final ui.Offset offset = _BaseAdapter.computeEventOffsetToTarget(event, glassPaneElement);
final ui.Offset offset = computeEventOffsetToTarget(event, glassPaneElement);
_pointerDataConverter.convert(
data,
change: details.change,
Expand Down Expand Up @@ -1170,7 +1150,7 @@ class _MouseAdapter extends _BaseAdapter with _WheelEventListenerMixin {
assert(data != null);
assert(event != null);
assert(details != null);
final ui.Offset offset = _BaseAdapter.computeEventOffsetToTarget(event, glassPaneElement);
final ui.Offset offset = computeEventOffsetToTarget(event, glassPaneElement);
_pointerDataConverter.convert(
data,
change: details.change,
Expand Down
113 changes: 113 additions & 0 deletions lib/web_ui/lib/src/engine/pointer_binding/event_position_helper.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do logics in this file work if the host page has a non-zero scroll offset? I think scroll offset doesn't affect clientX/Y, but it will affect the position of the cursor relative to the elements.

Copy link
Member Author

@ditman ditman Dec 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, methods that only use offsetX/Y are relative to the glassPane/platformView, so the scroll position does not matter there.

The one that requires scroll handling is the pageX/Y one, because that gives us positions from the top left position of the page (with all its scroll position added).

See the pageY docs: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/pageY

// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:ui/ui.dart' as ui show Offset;

import '../dom.dart';
import '../semantics.dart' show EngineSemanticsOwner;

/// Returns an [ui.Offset] of the position of [event], relative to the position of [actualTarget].
///
/// The offset is *not* multiplied by DPR or anything else, it's the closest
/// to what the DOM would return if we had currentTarget readily available.
///
/// This needs an `actualTarget`, because the `event.currentTarget` (which is what
/// this would really need to use) gets lost when the `event` comes from a "coalesced"
/// event.
///
/// It also takes into account semantics being enabled to fix the case where
/// offsetX, offsetY == 0 (TalkBack events).
//
// TODO(dit): Make this understand 3D transforms in the platform view case, https://github.com/flutter/flutter/issues/117091
ui.Offset computeEventOffsetToTarget(DomMouseEvent event, DomElement actualTarget) {
// On top of a platform view
if (event.target != actualTarget) {
return _computeOffsetOnPlatformView(event, actualTarget);
}
// On a TalkBack event
if (EngineSemanticsOwner.instance.semanticsEnabled && event.offsetX == 0 && event.offsetY == 0) {
return _computeOffsetForTalkbackEvent(event, actualTarget);
}
// Return the offsetX/Y in the normal case.
return ui.Offset(event.offsetX, event.offsetY);
}

/// Computes the event offset when hovering over a platformView.
///
/// This still uses offsetX/Y, but adds the offset from the top/left corner of the
/// platform view to the glass pane (`actualTarget`).
///
/// ×--FlutterView(actualTarget)--------------+
/// |\ |
/// | x1,y1 |
/// | |
/// | |
/// | ×-PlatformView(target)---------+ |
/// | |\ | |
/// | | x2,y2 | |
/// | | | |
/// | | × (event) | |
/// | | \ | |
/// | | offsetX, offsetY | |
/// | | (Relative to PlatformView) | |
/// | +------------------------------+ |
/// +-----------------------------------------+
///
/// Offset between PlatformView and FlutterView (xP, yP) = (x2 - x1, y2 - y1)
///
/// Event offset relative to FlutterView = (offsetX + xP, offsetY + yP)
ui.Offset _computeOffsetOnPlatformView(DomMouseEvent event, DomElement actualTarget) {
final DomElement target = event.target! as DomElement;
final DomRect targetRect = target.getBoundingClientRect();
final DomRect actualTargetRect = actualTarget.getBoundingClientRect();
final double offsetTop = targetRect.y - actualTargetRect.y;
final double offsetLeft = targetRect.x - actualTargetRect.x;
return ui.Offset(event.offsetX + offsetLeft, event.offsetY + offsetTop);
}

/// Computes the event offset when TalkBack is firing the event.
///
/// In this case, we need to use the clientX/Y position of the event (which are
/// relative to the absolute top-left corner of the page, including scroll), then
/// deduct the offsetLeft/Top from every offsetParent of the `actualTarget`.
///
/// ×-Page----║-------------------------------+
/// | ║ |
/// | ×-------║--------offsetParent(s)-----+ |
/// | |\ | |
/// | | offsetLeft, offsetTop | |
/// | | | |
/// | | | |
/// | | ×-----║-------------actualTarget-+ | |
/// | | | | | |
/// ═════ × ─ (scrollLeft, scrollTop)═ ═ ═
/// | | | | | |
/// | | | × | | |
/// | | | \ | | |
/// | | | clientX, clientY | | |
/// | | | (Relative to Page + Scroll) | | |
/// | | +-----║--------------------------+ | |
/// | +-------║----------------------------+ |
/// +---------║-------------------------------+
///
/// Computing the offset of the event relative to the actualTarget requires to
/// compute the clientX, clientY of the actualTarget. To do that, we iterate
/// up the offsetParent elements of actualTarget adding their offset and scroll
/// positions. Finally, we deduct that from clientX, clientY of the event.

ui.Offset _computeOffsetForTalkbackEvent(DomMouseEvent event, DomElement actualTarget) {
assert(EngineSemanticsOwner.instance.semanticsEnabled);
// Use clientX/clientY as the position of the event (this is relative to
// the top left of the page, including scroll)
double offsetX = event.clientX;
double offsetY = event.clientY;
// Compute the scroll offset of actualTarget
DomHTMLElement parent = actualTarget as DomHTMLElement;
while(parent.offsetParent != null){
offsetX -= parent.offsetLeft - parent.scrollLeft;
offsetY -= parent.offsetTop - parent.scrollTop;
parent = parent.offsetParent!;
}
return ui.Offset(offsetX, offsetY);
}