Skip to content

SelectionArea incorrectly retains mouse cursor on Web #174246

@dkwingsmt

Description

@dkwingsmt

Overview

When SelectionArea wraps another smaller region that specifies a mouse cursor, moving the mouse from the inner region to where there's only SelectionArea behaves incorrectly on Web, where it retains the inner mouse cursor instead returning to default.

Screen.Recording.2025-08-29.at.3.46.47.PM.mp4

Internal: b/437197529

Reproduction

Reproduction:

  • Run the following app
    • The widget consists of two rectangles. The outer one is a SelectionArea. The inner one is a MouseRegion with mouse cursor forbidden.
  • Hover mouse into the inner region. The mouse cursor should be .forbidden.
  • Now hover mouse into the outer region.

Expected behavior (observable on -d macos):
The cursor becomes default (the arrow).

Actual behavior (observable on -d chrome):
The cursor stays .forbidden.

Repro code
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('SelectionArea Sample')),
        body: Center(
          child: Container(
            decoration: BoxDecoration(
              border: Border.all(color: const Color(0xFF000000), width: 1),
            ),
            child: SelectionArea(
              child: Padding(
                padding: const EdgeInsetsGeometry.all(40),
                child: MouseRegion(
                  cursor: SystemMouseCursors.forbidden,
                  onHover: (_) {},
                  child: Container(
                    color: const Color(0xFFAA9933),
                    padding: const EdgeInsets.all(30),
                    width: 200,
                    height: 50,
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

Analysis

This is because how platform views implements mouse cursors. Platform views apply MouseCursor.uncontrolled onto their regions so that Flutter can transfer the control of mouse cursors to the view contents.

Since desktop platforms control mouse cursors imperitively, i.e. by sending messages to change them, MouseCursor.uncontrolled is implemented by having the cursor do nothing, so that desktop embeddings will send no messages that change the cursor.

However, since Web controls mouse cursors declaratively, implementing MouseCursor.uncontrolled in the same way will retain the cursor property.

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work listframeworkflutter/packages/flutter repository. See also f: labels.platform-webWeb applications specificallyteam-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework team

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions