Skip to content

Allow windows to be moved and resized with the cursor#179964

Closed
robert-ancell wants to merge 9 commits into
flutter:masterfrom
robert-ancell:move-windows
Closed

Allow windows to be moved and resized with the cursor#179964
robert-ancell wants to merge 9 commits into
flutter:masterfrom
robert-ancell:move-windows

Conversation

@robert-ancell

Copy link
Copy Markdown
Contributor

Add new API to allow windows to be moved and resized while a button is held down. This will be useful when drawing window decorations using Flutter. This feature is implemented for Linux which has native APIs for this. Some plumbing is implemented for Windows and MacOS, however based on the GTK source these systems do not have native API and this will have to be implemented by intercepting the move events and moving the window to match them.

@flutter-dashboard

Copy link
Copy Markdown

It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging.

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group.

@robert-ancell robert-ancell marked this pull request as draft December 16, 2025 23:01
@github-actions github-actions Bot added framework flutter/packages/flutter repository. See also f: labels. engine flutter/engine related. See also e: labels. platform-windows Building on or for Windows specifically d: examples Sample code and demos a: desktop Running on desktop platform-macos labels Dec 16, 2025
@robert-ancell

Copy link
Copy Markdown
Contributor Author

See #179859 for related PR to disable window decorations.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new API to allow moving and resizing windows with the cursor, with a full implementation for Linux and plumbing for Windows and macOS. My review focuses on improving the example code's correctness, enhancing the documentation for the new API, removing code duplication in the Linux implementation, and ensuring consistency in the macOS implementation. Overall, the changes are a good step towards the new feature.

Widget build(BuildContext context) {
return Listener(
onPointerDown: (PointerDownEvent event) {
onStart(0);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The button parameter is hardcoded to 0. This is likely incorrect for some platforms like Linux (GTK), which expect a button index (e.g., 1 for the left button). The PointerDownEvent provides a buttons property (which is a bitmask) that could be used to determine the correct button. Using event.buttons would pass 1 for a primary mouse button click, which is what GTK expects for the left button.

Suggested change
onStart(0);
onStart(event.buttons);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It's not clear the best way to handle the button pressed - event.buttons contains a bitmask of the buttons that are down, we probably just want the one button. So this is hardcoded for now.

Comment thread examples/multiple_windows/lib/app/regular_window_content.dart Outdated
Comment on lines +382 to +390
/// Start moving this window.
/// FIXME
@internal
void beginMoveDrag(int button);

/// Start resizing this window.
/// FIXME
@internal
void beginResizeDrag(int button, WindowDragEdge edge);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The documentation for beginMoveDrag and beginResizeDrag is just "FIXME". According to the style guide, documentation should be useful and explain the "why" and "how". Please add proper documentation for these methods, explaining their purpose, parameters (especially what button represents, e.g., a bitmask or an index), and current implementation status across platforms.

References
  1. The style guide requires documentation to be useful, explaining the 'why' and the 'how' (line 55). It also states that all public members should have documentation (line 53), and that public-quality documentation should be used even for private members (line 62). (link)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Documentation to be added...

Comment on lines +636 to +644
/// Start moving this window.
/// FIXME
@internal
void beginMoveDrag(int button);

/// Start resizing this window.
/// FIXME
@internal
void beginResizeDrag(int button, WindowDragEdge edge);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The documentation for beginMoveDrag and beginResizeDrag is just "FIXME". According to the style guide, documentation should be useful and explain the "why" and "how". Please add proper documentation for these methods, explaining their purpose, parameters (especially what button represents, e.g., a bitmask or an index), and current implementation status across platforms.

References
  1. The style guide requires documentation to be useful, explaining the 'why' and the 'how' (line 55). It also states that all public members should have documentation (line 53), and that public-quality documentation should be used even for private members (line 62). (link)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Documentation to be added...

Comment thread packages/flutter/lib/src/widgets/_window_linux.dart
Comment thread packages/flutter/lib/src/widgets/_window_linux.dart Outdated
Comment thread packages/flutter/lib/src/widgets/_window_linux.dart Outdated
Comment thread packages/flutter/lib/src/widgets/_window_macos.dart Outdated
@knopp

knopp commented Jan 16, 2026

Copy link
Copy Markdown
Member

I don't think this abstraction will map well on macOS. We can implement the dragging part ([NSWindow performWindowDragWithEvent:]), but there is no method that will start resizing. To do that on macOS you generally use with resizable window without titlebar.

On windows you can somewhat emulate this with WM_NCHITTEST.

@knopp

knopp commented Jan 16, 2026

Copy link
Copy Markdown
Member

TBF, even NSWindow performWindowDragWithEvent: is not a silver bullet, because it needs to be triggered from mouse event, but in some cases, i.e. when window has a context menu opened, the mouse down event gets eaten by the context menu and the framework never sees it, but on regular titlebar this would still result in window movement.

@Piinks

Piinks commented Mar 23, 2026

Copy link
Copy Markdown
Contributor

Greetings from stale PR triage! 👋
Is this change still on your radar?

@knopp

knopp commented Mar 24, 2026

Copy link
Copy Markdown
Member

We can do synchronous hittest from native. This means we can have a "WindowDraggable" widget in hierarchy and do a hit test to determine if said part of window should be draggable. This allows for proper NC_HITTEST implementation on windows, but more importantly also have NSWindow isMovableByWindowBackground by altering the hittest area of FlutterView, which should solve the context menu issues with performWindowDragWithEvent.

@robert-ancell

Copy link
Copy Markdown
Contributor Author

Still on radar but will withdraw this as the method required will be different as noted by @knopp.

@stuartmorgan-g stuartmorgan-g added platform-macos Building on or for macOS specifically and removed platform-macos labels Apr 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: desktop Running on desktop d: examples Sample code and demos engine flutter/engine related. See also e: labels. framework flutter/packages/flutter repository. See also f: labels. platform-macos Building on or for macOS specifically platform-windows Building on or for Windows specifically

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants