rust-windowing / winit

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

MacOS: non-activating window #3894

Open MatthiasGrandl opened 2 weeks ago

MatthiasGrandl commented 2 weeks ago

Description

I am currently evaluating porting Loungy from GPUI to Iced and I noticed I can't replicate the window behavior I need in Winit. The important bit is this from GPUI codebase:

https://github.com/zed-industries/zed/blob/a850731b0ed61b0ef2a0173843b6daedf45327e8/crates/gpui/src/platform/mac/window.rs#L56

This basically prevents the Window from ever "activating", which is required to get a nicely behaving launcher window on MacOS. I realize this is very niche usecase, but it would be nice to have it supported on Winit.

Relevant platforms

MacOS

MatthiasGrandl commented 2 weeks ago

Disregard. I tried patching winit and it’s more complicated than that. this styleMask requires the use of NSPanel instead of NSWindow and then it’s still not quite behaving the way I want it to.

madsmtm commented 2 weeks ago

If all you end up needing is the ability to set a specific style mask, then I'd be fine with accepting a PR for that - if the solution is to use NSPanel, then I'm a bit more wary, but that could also be doable with a platform-specific window attribute.

MatthiasGrandl commented 2 weeks ago

I got it to work the way I expect it to work, but there are multiple changes necessary. The one that took me the longest to find, was the focus_window function in window_delegate. It basically overrides the NSWindowStyleMask::NonactivatingPanel behavior. And yes sadly the styleMask is only supported on a NSPanel.

I'll try to cleanup my changes and open a PR, but given how niche this is, I am not sure it has a good chance of getting merged :(

MatthiasGrandl commented 2 weeks ago

@madsmtm given the class based approach of WinitWindow being based on NSWindow, do you have any idea what the least intrusive way of conditionally flipping to NSPanel? In my MVP I just switched NSWindow to NSPanel altogether, but that obviously is not an acceptable solution.

madsmtm commented 2 weeks ago

Well, we don't really use WinitWindow for anything other than canBecomeMainWindow and canBecomeKeyWindow, and the use of those are IMO questionable anyhow.

So I think you could change occurrences of WinitWindow with NSWindow, and then inside new_window use Retained::into_super to convert Retained<WinitWindow> (or if the option has been specified to create NSPanel, Retained<NSPanel>) to Retained<NSWindow>.