Skip to content

Wayland, Windows, MacOS: Popup Implementation#4543

Open
Murmele wants to merge 31 commits into
rust-windowing:masterfrom
Murmele:popup
Open

Wayland, Windows, MacOS: Popup Implementation#4543
Murmele wants to merge 31 commits into
rust-windowing:masterfrom
Murmele:popup

Conversation

@Murmele

@Murmele Murmele commented Mar 25, 2026

Copy link
Copy Markdown
Contributor

Implement proper decorationless popups by specifying the type of the child window with with_type()

With this PR different kind of child windows can be created

  • Popups: Special windows without any decoration which can be positioned relative to the parent
  • Window: Normal window with a parent or not

The type can be specified during creation of the Window using the window_attributes and the with_type() function. As default a normal Window is used. If Popup is choosen a parent must be specified, otherwise the Popup creation fails with an Error returned by the new() function.

Related issues: #403 and #4256

  • Tested on all platforms changed
  • Added an entry to the changelog module if knowledge of this change could be valuable to users
  • Updated documentation to reflect any user-facing changes, including notes of platform-specific behavior
  • Created or updated an example program if it would help users understand this functionality

Platforms

  • Wayland
    • Testing grabbing
      • Gnome (Mutter)
      • Kde Plasma
  • Windows
  • MacOs
  • X11

Wayland:

Bildschirmaufzeichnung.vom.2026-06-04.13-18-16.mp4

This work is sponsored by the NLnet foundation

@madsmtm madsmtm added DS - wayland Affects the Wayland backend, or generally free Unix platforms S - platform parity Unintended platform differences labels Mar 26, 2026
Comment thread winit-wayland/src/window/state.rs
Comment thread winit-wayland/src/window/state.rs Outdated
@Murmele Murmele marked this pull request as ready for review May 18, 2026 08:06
@Murmele Murmele requested a review from kchibisov as a code owner May 18, 2026 08:06
Comment thread winit-wayland/src/state.rs Outdated
Comment thread winit-wayland/src/state.rs Outdated
Comment thread winit-core/src/window.rs
Comment thread winit-core/src/window.rs Outdated
Comment thread winit-core/src/window.rs Outdated
Comment thread winit-wayland/src/popup.rs Outdated
Comment thread winit-wayland/src/popup.rs Outdated
Comment thread winit-wayland/src/state.rs Outdated
Comment thread winit-wayland/src/popup.rs Outdated
Comment thread winit-win32/src/window.rs
@Murmele Murmele requested a review from madsmtm as a code owner May 28, 2026 15:09
@Murmele Murmele force-pushed the popup branch 2 times, most recently from facdfde to 87f6327 Compare June 4, 2026 12:59
Murmele added 15 commits June 4, 2026 15:07
Reason: Because a normal window can have a parent window as well, like a Dialog
Reason: otherwise the child surface is anchored to the center
Reason: otherwise the height of the client side decoration is not considered and therefore the location is shifted
Reason: There are multiple pointers to the smithay popup. Once in state.windows and one time in the popup object it self. Just dropping the popup object releases only one pointer but we have to notify the state to release also the other
…he position

Reason: Much easier in the resize handle
Reason: we have to call resize to initialize the viewport to map to correct window size
@Murmele Murmele changed the title Wayland: Popup Implementation Wayland, Windows, MacOS: Popup Implementation Jun 4, 2026
@kchibisov

kchibisov commented Jun 12, 2026

Copy link
Copy Markdown
Member

I think the idea with those pop-ups were to have a separate type other than glue to window, because as you said, they are very restricted on some platforms and on some platform it's indeed just a Window.

so in top-level API I would have them, as a separate type with its own restrictions, and what not, I'm also not sure if those things can be owned by the user, really, I think popups should be more like something you create from e.g. Window so Window::create_popup type of API call, that may take an ActiveEventLoop or ActiveEventLoop. EventLoop having an api like ActiveEventLoop::create_pop(&dyn Window, PopupProperties) as generally better in my opinion.

Popups need to be closed in reverse order (children before parents), otherwise you get a protocol violation:

Exactly why I want to have them owned by Parent, whether it's window or some other thing.

Generally, I think the initial plan was to have some kind of trait Surface and then for event loop to have ActiveEventLoop::create_popup(&mut dyn Surface, so it adds popup for the Surface so API is a bit more future proof.

@tronical would like to hear your opinion here since you're representing ui toolkit side 😅

I just want to account for other special surfaces Wayland people can create which has their own popup type that is certainly not different than standard popup.

@tronical

Copy link
Copy Markdown
Contributor

I think the idea with those pop-ups were to have a separate type other than glue to window, because as you said, they are very restricted on some platforms and on some platform it's indeed just a Window.

so in top-level API I would have them, as a separate type with its own restrictions, and what not, I'm also not sure if those things can be owned by the user, really, I think popups should be more like something you create from e.g. Window so Window::create_popup type of API call, that may take an ActiveEventLoop or ActiveEventLoop. EventLoop having an api like ActiveEventLoop::create_pop(&dyn Window, PopupProperties) as generally better in my opinion.

Popups need to be closed in reverse order (children before parents), otherwise you get a protocol violation:

Exactly why I want to have them owned by Parent, whether it's window or some other thing.

That's indeed an interesting constraint (reverse order required).

Generally, I think the initial plan was to have some kind of trait Surface and then for event loop to have ActiveEventLoop::create_popup(&mut dyn Surface, so it adds popup for the Surface so API is a bit more future proof.

@tronical would like to hear your opinion here since you're representing ui toolkit side 😅

I just want to account for other special surfaces Wayland people can create which has their own popup type that is certainly not different than standard popup.

I see the discrepancy, but I also see that - wayland aside - popups have more in common with Window than not. Another surface abstraction is tempting indeed, but my feeling is that it may be worthwhile to go with this approach first and learn from it.

(disclaimer: I'm biased though as I'm Martin's colleague :)

@kchibisov

Copy link
Copy Markdown
Member

The problem with Wayland, is that if you randomly use it wrongly, it really likes killing applications with protocol errors, so my suggestion is mostly to try solve it on type system level, or at least make it less likely, so users won't have to debug Wayland when it breaks in their cross platform app.

I also remember that popups can be discarded/removed on user behalf and winit window is kind of persistent now.

@HigherOrderLogic

Copy link
Copy Markdown

For Wayland: shouldnt we also use the xdg-dialog-v1 protocol to mark it as dialog? This implementation doesnt seems to use that protocol atm.

@kchibisov

Copy link
Copy Markdown
Member

I think dialog protocol serves a different purpose, and also not widely available?

@HigherOrderLogic

Copy link
Copy Markdown

I think dialog protocol serves a different purpose

Ah right, I didnt read the PR description carefully, my bad. Originally thought it was popup dialog.

and also not widely available?

All 3 most popular compositors right now, KWin, Mutter and Hyprland, implement it so I dont think it's a problem.

@Murmele

Murmele commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

For Wayland: shouldnt we also use the xdg-dialog-v1 protocol to mark it as dialog? This implementation doesnt seems to use that protocol atm.

This will be implemented in a second step. There I will use this protocol

@Murmele

Murmele commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

@kchibisov @kchibisov Thanks for the feedback. And the patches. I will go through it next days and integrate them.

The problem with Wayland, is that if you randomly use it wrongly, it really likes killing applications with protocol errors, so my suggestion is mostly to try solve it on type system level, or at least make it less likely, so users won't have to debug Wayland when it breaks in their cross platform app.

I also remember that popups can be discarded/removed on user behalf and winit window is kind of persistent now.

I will have a look into it how to integrate the popup as child of another popup/window so the reverse order could be solved automatically.

Murmele added 2 commits June 17, 2026 14:57
Reason: On wayland popups don't get automatically keyboard grab. So request on creation
@Murmele Murmele force-pushed the popup branch 2 times, most recently from 71b5db5 to 5c8042b Compare June 18, 2026 12:56
Murmele added 2 commits June 18, 2026 14:57
Reason: Because wayland or the event loop could destroy the popup and therefore it is anymore available
@Murmele

Murmele commented Jun 18, 2026

Copy link
Copy Markdown
Contributor Author

@kchibisov @CryZe @tronical

In 90ebef0 I implemented the correct popup order destroyment. I had the problem that the Popup Item it self contained a window state and therefore it got not delegated to the compositor that the popup shall be deleted. This I fixed in ac4a329 by storing only a Weak pointer of the window state in the Popup struct (popup_state: Weak<Mutex<WindowState>>).
What do you think about instead of returning a Box<dyn Window> returning a Weak pointer. So the event loop basically stores the state popup and the user has only a weak pointer and if the popup was destroyed for some reason (Parent destroyed, ...) then the pointer is invalid and the user is aware that it does not exist anymore?

@kchibisov

Copy link
Copy Markdown
Member

What do you think about instead of returning a Box returning a Weak pointer. So the event loop basically stores the state popup and the user has only a weak pointer and if the popup was destroyed for some reason (Parent destroyed, ...) then the pointer is invalid and the user is aware that it does not exist anymore?

I like that you also came to a conclusion I had for the window storage, as in basically user has some handle but the Window itself is only owned by winit.

I'll think about it a bit since we want to plug it into the current design, but generally, I think that's how it should be, honestly, even though a lot of folks disagree with me on that matter...

@Murmele Murmele closed this Jun 19, 2026
@Murmele Murmele reopened this Jun 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DS - wayland Affects the Wayland backend, or generally free Unix platforms S - platform parity Unintended platform differences

Development

Successfully merging this pull request may close these issues.

7 participants