Skip to content

Popup anchor system refinement - #4646

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

Popup anchor system refinement#4646
Murmele wants to merge 36 commits into
rust-windowing:masterfrom
Murmele:popup-anchor

Conversation

@Murmele

@Murmele Murmele commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Implement possibility to change the anchor properties of a popup on wayland and imitate the behaviour for other platforms which do not support such anchoring system

  • 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

Tested on:

  • Windows
  • Wayland
  • MacOs
  • X11 Does not support popups

@Murmele Murmele mentioned this pull request Jul 27, 2026
8 tasks
@Murmele
Murmele marked this pull request as ready for review July 28, 2026 05:51
Comment thread winit-appkit/src/window_delegate.rs Outdated
Comment thread winit-appkit/src/window_delegate.rs Outdated
Comment thread winit-appkit/src/window_delegate.rs Outdated
Comment thread winit-core/src/window/positioner.rs Outdated
Comment thread winit-core/src/window.rs Outdated

@ogoffart ogoffart 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.

I wonder if it wouldn't be better to have a single with_positioner on the WindowAttribute / Window instead of many setter.
And use the WindowPositioner stuct.

Comment thread winit-core/src/window.rs
use dpi::{
LogicalPosition, LogicalSize, PhysicalInsets, PhysicalPosition, PhysicalSize, Position, Size,
};
pub use positioner::{WindowAnchor, WindowConstraintAdjustment, WindowGravity, place_window};

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.

i don't think place_window should be public API

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.

This depends on the usage. If it should be possible to reuse it in other software like for the ChildWindow in Slint or if we wanna make a copy of the algorithm on the slint side

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.

But we can't re-use it for ChildWindow in Slint because slint-core don't depend on winit on purpose.

in fact, the implementation of that function might be better placed in winit-common

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.

winit-common is also not possible, because it depends on winit-core. It has to be public, because otherwise the winit-win32 and winit-appkit cannot use it

Comment thread winit-win32/src/window.rs

self.set_outer_position(Position::Logical(origin));
if size != current_size {
let _ = self.request_surface_size(Size::Logical(size));

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.

that's the inner size. but current_size use get_outer_size

There are other inconsistency like that.

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.

Thanks I changed

Comment thread winit-win32/src/event_loop.rs Outdated

let userdata = unsafe { util::get_window_long(hwnd, GWL_USERDATA) };
if userdata != 0 {
let userdata = unsafe { &*(userdata as *const WindowData) };

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.

seems dangerous to do if there are window that are not handled by winit, we need to filter that.

@Murmele Murmele Aug 12, 2026

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.

public_window_callback will be called only for windows we handle otherwise this function is never called. We must be not take ownership of the pointer because of that this pattern. Also used a few times already in the code

Comment thread winit-win32/src/window.rs Outdated
monitor_position.y - parent_origin.y,
)
.to_logical::<f64>(scale_factor);
let clip_size = monitor_size.to_logical::<f64>(scale_factor);

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.

is the monitor size the right thing, or should it be the availiable space?
Depends if the window or popup can be placed over, say, the taskbar

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.

Good point, I have to check also for multiwindow systems

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.

I used the work area instead of the display, otherwise it disappears behind the taskbar instead of flipping / sliding (if enabled)

@Murmele

Murmele commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

@ogoffart Thanks for the feedback. I will go through it

@Murmele

Murmele commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

I wonder if it wouldn't be better to have a single with_positioner on the WindowAttribute / Window instead of many setter. And use the WindowPositioner stuct.

Good idea, it looks much cleaner now with the positioner struct used directly

@ogoffart ogoffart 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.

maybe there should be an example?

Comment thread winit-core/src/window.rs
use dpi::{
LogicalPosition, LogicalSize, PhysicalInsets, PhysicalPosition, PhysicalSize, Position, Size,
};
pub use positioner::{WindowAnchor, WindowConstraintAdjustment, WindowGravity, place_window};

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.

But we can't re-use it for ChildWindow in Slint because slint-core don't depend on winit on purpose.

in fact, the implementation of that function might be better placed in winit-common

Comment thread winit-core/src/window/positioner.rs Outdated
Comment on lines +148 to +152
anchor: WindowAnchor,
gravity: WindowGravity,
constraint_adjustment: WindowConstraintAdjustment,
(anchor_position, anchor_size): (LogicalPosition<f64>, LogicalSize<f64>),
offset: LogicalPosition<f64>,

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.

Can we use a WindowPositioner here instead of many arguments?

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.

yep, I will change

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.

done

Comment thread winit-core/src/window.rs
/// platform-specific behavior, and [`WindowPositioner::default`] for the values used when
/// [`WindowAttributes::with_positioner`] is never called.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct WindowPositioner {

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.

form an API evolution point of view, i wonder if this should be #[non_exhaustive]

Or is the positioning protocol set in stone anyway and there will never be extra fields?

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.

The wayland protocol can envolve, so it is a good idea to make it non_exhaustive

Comment thread winit-appkit/src/window_delegate.rs Outdated
// An anchored window's position is parent-relative; it's applied in
// `WindowDelegate::new` (after the delegate exists) via the shared
// translation in `set_outer_position`.
_ if anchored => NSPoint::new(0.0, 0.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.

but if you don't specify a position and there is no parent, it should be in the center of the screen (i think that's the current behavior in master)

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.

thanks, changed

Previously every close request left the event_loop which is not correct when only a popup closes
Reason: otherwise the popup might disappear behind the task bar
@Murmele
Murmele requested a review from ogoffart August 12, 2026 14:47
@Murmele

Murmele commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

But we can't re-use it for ChildWindow in Slint because slint-core don't depend on winit on purpose. in fact, the implementation of that function might be better placed in winit-common

winit-common depends on winit-core so we cannot use this as well. It has to be public otherwise the winit-win32 crate and the macos crate are not able to access it

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants