Repository: flutter/flutter
File: engine/src/flutter/lib/web_ui/lib/src/engine/pointer_binding.dart (Dart)

Code before:
    // Determine if we should prevent default and/or scroll parent
    final bool isInIframe = _isEmbeddedInIframe();
    final bool isFullPage = _isFullPageApp();

    // Special handling only for full-page Flutter apps running inside an iframe.
    // Custom element apps (Flutter embedded as a component) should let the
    // browser handle normal scroll flow.
    if (isInIframe && isFullPage) {
      // Full-page app in an iframe: always preventDefault to block native
      // scroll chaining. Without this, both the iframe content AND the parent
      // window would scroll simultaneously when the user scrolls.
      event.preventDefault();

      // Scroll parent window only when Flutter scrollables can't use the event:
      // - _lastWheelEventAllowedDefault: at least one scrollable is at boundary
      // - !_lastWheelEventHandledByWidget: no scrollable consumed the event
      //
      // For nested scrollables, inner widgets set _lastWheelEventHandledByWidget
      // to true, preventing parent window scroll even if outer is at boundary.
      //
      // Fixes GitHub issue #156985
      final bool shouldScrollParent =
          _lastWheelEventAllowedDefault && !_lastWheelEventHandledByWidget;
      if (shouldScrollParent) {
        scrollParentWindow(wheelEvent.deltaX, wheelEvent.deltaY);
      }
    } else {
      // Original behavior for:
      // 1. Apps NOT in an iframe (normal page)
      // 2. Custom element apps in an iframe (Flutter as a component)
      //
      // Only preventDefault when a scrollable widget handles the event.
      // This preserves native scroll behavior when Flutter can't scroll.
      if (!_lastWheelEventAllowedDefault) {
        event.preventDefault();
      }
    }
  }

  /// For browsers that report delta line instead of pixels such as FireFox
  /// compute line height using the default font size.
  ///
  /// Use Firefox to test this code path.
  double _computeDefaultScrollLineHeight() {
    const kFallbackFontHeight = 16.0;
    final DomHTMLDivElement probe = createDomHTMLDivElement();
    probe.style
      ..fontSize = 'initial'
      ..display = 'none';
    domDocument.body!.append(probe);
    String fontSize = domWindow.getComputedStyle(probe).fontSize;

Review comment (suggestion):
One last thought here to try to avoid the `scrollParentWindow`:

Instead of doing `event.preventDefault()` and then manually scrolling the parent, we should try something like this:
```dart
if (isInIframe && isFullPage) {
  final bool shouldScrollParent =
      _lastWheelEventAllowedDefault && !_lastWheelEventHandledByWidget;
  if (!shouldScrollParent) {
    event.preventDefault();
  }
} else {
  // ...
}
```
I'm not sure if it would work or not, but if it works let's do it!

Code after:
        event.preventDefault();
      }
    } else {
      // Original behavior for:
      // 1. Apps NOT in an iframe (normal page)
      // 2. Multi-view mode inside an iframe
      //
      // Only preventDefault when a scrollable widget handles the event.
      // This preserves native scroll behavior when Flutter can't scroll.
      if (!_lastWheelEventAllowedDefault) {
        event.preventDefault();
      }
    }
  }

  /// For browsers that report delta line instead of pixels such as FireFox
  /// compute line height using the default font size.
  ///
  /// Use Firefox to test this code path.
  double _computeDefaultScrollLineHeight() {
    const kFallbackFontHeight = 16.0;
    final DomHTMLDivElement probe = createDomHTMLDivElement();
    probe.style
      ..fontSize = 'initial'
      ..display = 'none';
    domDocument.body!.append(probe);
    String fontSize = domWindow.getComputedStyle(probe).fontSize;
    double? res;
    if (fontSize.contains('px')) {
      fontSize = fontSize.replaceAll('px', '');
      res = double.tryParse(fontSize);
    }
    probe.remove();
    return res == null ? kFallbackFontHeight : res / 4.0;
  }
}

@immutable
class _SanitizedDetails {
  const _SanitizedDetails({required this.buttons, required this.change});

  final ui.PointerChange change;
  final int buttons;

  @override
  String toString() => '$runtimeType(change: $change, buttons: $buttons)';
}

class _ButtonSanitizer {
  int _pressedButtons = 0;