Skip to content

Conversation

@Cmdv
Copy link

@Cmdv Cmdv commented Oct 5, 2025

Add screen-absolute mouse position to CursorMoved event

Problem:
When implementing custom window resize handles, window-relative mouse coordinates become unreliable as the window dimensions change. The position jumps around because it's relative to a moving target.

This is particularly problematic for audio plugins (using nih-plug + baseview) where you can't access native window resize controls and have to implement resize handles yourself.

Solution:
Add screen_position: Point to mouse::Event::CursorMoved alongside the existing window-relative position.

  CursorMoved {
      position: Point,           // window-relative
      screen_position: Point,    // screen-absolute
  }

The screen position stays constant during resize operations, making drag calculations straightforward.

Implementation:

  • Winit backend: calculates as window.outer_position() + cursor_position
  • Falls back to window-relative position if window position unavailable (Wayland limitations)
  • Updated conversion::window_event() to accept pre-extracted window_position parameter (consistent with existing scale_factor pattern)

Breaking Changes:

  • CursorMoved has new field - existing pattern matches need ..
  • conversion::window_event() signature changed

It closes #2773 (only issue I could find related to it)

Working Result:
2025-10-05 00 09 13

@edwloef
Copy link
Contributor

edwloef commented Oct 6, 2025

Could you make the screen position field optional? As-is right now I'm fairly sure this'll result in no mouse movement events being emitted on Wayland anymore, since outer_position is unsupported there.

@Cmdv
Copy link
Author

Cmdv commented Oct 6, 2025

Optional might be valid, here's my actual user case

Baseview → Conversion → Iced → Widget

Baseview provides MouseEvent::CursorMoved with both position (window coords) and screen_position (screen coords) natively from the OS

Conversion layer does simple type conversion: f64 → f32, creating iced::Event::Mouse(CursorMoved { position, screen_position })

Iced runtime dispatches the event to all widgets. Standard widgets use { position, .. } ignoring screen_position. My custom widget extracts both.

Widget ResizeHandle widget uses screen_position for delta calculations because window coordinates shift during resize, but screen coordinates stay stable.

Why I modified iced: Core iced didn't have screen_position in CursorMoved events. I added it so backends(winit/baseview) can provide screen-absolute coordinates alongside window-relative coordinates. This enables custom widgets to perform stable calculations during window geometry changes.

Baseview vs Winit: Baseview provides both coordinates natively (simple passthrough). Winit must calculate screen_position = window.outer_position() + position.

@edwloef
Copy link
Contributor

edwloef commented Oct 6, 2025

Yeah, I just misread the code at first. It might be better to have users explicitly handle the case where screenspace coordinates aren't available or might be incorrect, but this way works too. In the end that's a design decision hecrj will have to make though.

@Cmdv
Copy link
Author

Cmdv commented Oct 6, 2025

I was also trying to think of a way to make it an opt-in so it wouldn't be a breaking change but couldn't see a logical way of doing that unfortunately. It's a really useful feature for us audio plugin devs, but might be out of scope and too niche to have it in iced 🤷

edit: I'm happy to have a scenario where users explicitly handle the case you mentioned, it was more I had this code that made my resizing work perfectly, so though why not share it upstream just incase 😄

@hecrj
Copy link
Member

hecrj commented Nov 29, 2025

I am unconvinced this is a use case that must be solved at the widget level.

This seems like it should not leak further than the shell itself.

I am closing this until we can come up with a better design.

@hecrj hecrj closed this Nov 29, 2025
@hecrj hecrj added this to the 0.14 milestone Nov 29, 2025
@hecrj hecrj added feature New feature or request widget shell addition labels Nov 29, 2025
@Cmdv
Copy link
Author

Cmdv commented Nov 29, 2025

@hecrj could you expand a little on you're previous comment. I'm keen to help have this feature but if you think it lives elsewhere what would be a logical place?

I'm not quite understanding:

This seems like it should not leak further than the shell itself.

@hecrj
Copy link
Member

hecrj commented Nov 29, 2025

Why does the burden of implementation fall on iced here and not on baseview or nih-plug? Why can't you access native resize controls but iced can?

@edwloef
Copy link
Contributor

edwloef commented Nov 29, 2025

The plugin needs to implement resizing itself because in this case iced is embedded into a foreign window, where the plugin needs to request the host to resize the window instead of it just being handled by the native resize controls. Typically this is solved by adding a "resize handle" widget somewhere in the bottom right of the window, and using that instead of the native controls. For example, nih_plug_vizia implements a ResizeHandle widget for plugins using the Vizia toolkit.

That being said, I'm not sure I understand why this needs the cursor screen-coordinates vs just window-coordinates.

@Cmdv
Copy link
Author

Cmdv commented Nov 29, 2025

Why does the burden of implementation fall on iced here and not on baseview or nih-plug? Why can't you access native resize controls but iced can?

I thought it was because only iced has access to the window event. But not to worry I'll try something else, pretty sure I tried putting it into baseview but wasn't able to. Just wanted to ask incase it was something I could help with!!

EDIT:
hahaha my bad I totally forgot I actually did it in this PR RustAudio/baseview#211 !! and here is it's implementation as a widget!!

Sorry I should have deleted this PR once I'd done the other. I write code then just forget about it!!! 🤦

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

get absolute mouse position in screen space

3 participants