rust-windowing / winit

Window handling library in pure Rust
https://docs.rs/winit/
Apache License 2.0
4.84k stars 902 forks source link

Allow returning `HITMAXBUTTON` from `WM_NCHITTEST` for Windows snap layout support #3884

Open sphw opened 2 months ago

sphw commented 2 months ago

Description

In Windows 11, when you hover over the maximize button a window is displayed that shows various layouts you can "snap" the window to. When drawing a custom titlebar, these options don't work unless you return HTMAXBUTTON from the WM_NCHITTEST handler.

As far as I can tell this isn't possible in winit at the moment, and best I can figure there isn't a work around available.

Relevant platforms

Windows

notgull commented 2 months ago

When drawing a custom titlebar, these options don't work unless you return HTMAXBUTTON from the WM_NCHITTEST handler.

I don't think there is something similar for any other platform, so it's probably outside the scope of winit. In addition it should be achievable through the with_msg_hook function.

sphw commented 2 months ago

I don't think there is something similar for any other platform, so it's probably outside the scope of winit. In addition it should be achievable through the with_msg_hook function.

Fair enough on this being platform specific, but it is a very common issue for people trying to make fully featured desktop windows apps.

I might be missing something, but with_msg_hook seems to return bool that either lets winit handle the event or not. To correctly handle WM_NCHITTEST, you need to return a value from the lpfnWndProc callback. As far as I can tell you can't control the return value of lpfnWndProc

In my mind this would be similar to show_window_menu in that it allows developers to create a more native feeling experience. I would be happy for it to be an additional method on EventLoopBuilderExtWindows or something similar to drag_resize_window on Window

DataTriny commented 2 months ago

Your only option @sphw at the moment is to use window subclassing. We use it in AccessKit to return handles to COM interfaces in response to the WM_GETOBJECT message. You can see how we implement it here.

I hope that API changes to winit 0.31 will allow us to get rid of this hack though.

sphw commented 2 months ago

Thanks for the suggestion! I'll give it a try

notgull commented 2 months ago

Yeah subclassing may be the best option here, since this is effectively "add a new function to a window handle". I would definitely be open to making subclassing easier, either through winit or through another library dedicated to this kind of subclassing.