Skip to content

Add toplevel geometry tracker protocol. #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

outfoxxed
Copy link
Member

This protocol allows tracking toplevel geometry relative to a workspace or monitor.

The intended use cases are for workspace displays (workspace switchers, bar widgets, overlays, etc) and
apps that have UI related to window location such as screenshot window pickers.

This is usually done via compositor specific IPC.

@outfoxxed outfoxxed mentioned this pull request May 23, 2025
given sibling in Z-order.

This event is double-buffered and must be followed by a
'shell_foreign_toplevel_geometry_tracker_manager_v1.done' event.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't it be better to do a css-style z-index?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this might be easier to manage. Most actions that change z index move one window relative to others, e.g. activate, tile/untile, which should end up as a single event to a single toplevel. With indexes the compositor has to tell the client how to shuffle the list, which is more work for both parties.

@outfoxxed outfoxxed force-pushed the toplevel-geometry-tracker branch from 58e495d to 4ace463 Compare May 23, 2025 10:17
Comment on lines +80 to +87
<request name="get_workspace_tracker">
<description summary="create a geometry tracker for a given workspace">
Creates a geometry tracker which tracks toplevels on a given workspace.
</description>

<arg name="tracker" type="new_id" interface="shell_foreign_toplevel_geometry_tracker_v1"/>
<arg name="workspace" type="object" interface="ext_workspace_handle_v1"/>
</request>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vaxerski thoughts on splitting this apart similarly to the image capture protocol? I'm not sure what sources other than a workspace or output would make sense but it might make sense to at least make workspace support optional.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

meh, I don't see any other possible tracker, so I don't really care

Comment on lines +92 to +93
A geometry tracker tracks the relative geometry of toplevels
intersecting with an output or workspace.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is "intersecting", as in a window visible on two outputs shows up on both trackers? As opposed to only showing up on a single tracker for this window's "main" output (i.e. one that it receives scale or frame callbacks for). Would be good to clarify

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. The primary output and workspace can be determined via existing toplevel and workspace protocols if the compositor wishes to send only one, but any toplevel even partially on the workspace should be listed.

Comment on lines +114 to +115
<event name="area">
<description summary="reports the geometry of the tracked area">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rename this to size maybe, because "area" reads like it has x and y coordinates

Comment on lines +118 to +119
Reported width and height should match the dimensions of the
tracked area in logical pixels.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this mean? Isn't this the tracked area? Or this is some other area (which?) that matches the tracked area?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was a couple different things during editing. Must've forgotten to clean that up.

Comment on lines +127 to +128
<arg name="width" type="int"/>
<arg name="height" type="int"/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With fractional scale the logical size isn't necessarily an int. While there's currently no good way to request a fractional size for e.g. fullscreen windows or anchored layer-shell elements or the lock surface, at least in niri the area is tracked in fractional logical pixels for the purpose of toplevel placement and such. So might be good to have some forward compatibility here when fractional sizes become more widely representable?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was probably thinking in physical pixels when I wrote it, but logical pixels make more sense if the workspace is on a single monitor.

This does highlight the issue of a single workspace spanning multiple monitors with mismatched geometry though. I'll have to revise that.

To account for workspaces spanning multiple monitors with potentially different DPIs or scaling ratios, should the compositor just pick some number that makes the math work out for relative positioning or something else you think?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about others, niri layout uses fractional logical coords and sizes everywhere and it seems to work alright (though, niri also doesn't do workspaces spanning several monitors). I expect that others either do the same or round sizes to logical ints

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Niri and Hyprland don't care about this since workspaces cant be on more than one monitor at once, but its likely a concern for KDE and such.

Comment on lines +147 to +150
<arg name="left" type="int"/>
<arg name="top" type="int"/>
<arg name="right" type="int"/>
<arg name="bottom" type="int"/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, not necessarily ints, can be fractional logical.

</evnt>

<request name="track_toplevels">
<description summary="begins tracking toplevels">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: should this include toplevels currently being interactively dragged with the cursor? I suppose this should be up to compositor policy; in niri even if dragged floating windows should be included, I would probably still exclude dragged tiled windows.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most clients I can think of would prefer a stream of events as position changes, matching how the toplevels are visible to the user. E.g. animations switching window positions and mouse drags should be reported as they happen, not as a single reposition at the end.

Comment on lines +222 to +223
<arg name="x" type="int"/>
<arg name="y" type="int"/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These definitely shouldn't be ints, there's nothing in Wayland that restricts windows to integer logical placement

Comment on lines +224 to +225
<arg name="width" type="int"/>
<arg name="height" type="int"/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While window geometry can only be integer logical currently due to Wayland, if you include compositor decorations, then it easily goes into fractional logical size

Comment on lines +228 to +250
<event name="above">
<description summary="the toplevel is now above another">
This event reports that the toplevel is now directly above the
given sibling in Z-order.

This event is double-buffered and must be followed by a
'shell_foreign_toplevel_geometry_tracker_manager_v1.done' event.
</description>

<arg name="sibling" type="object" interface="shell_foreign_toplevel_geometry_tracker_member_v1"/>
</event>

<event name="below">
<description summary="the toplevel is now below another">
This event reports that the toplevel is now directly below the
given sibling in Z-order.

This event is double-buffered and must be followed by a
'shell_foreign_toplevel_geometry_tracker_manager_v1.done' event.
</description>

<arg name="sibling" type="object" interface="shell_foreign_toplevel_geometry_tracker_member_v1"/>
</event>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess there can't be cycles between these two? Also, if the compositor restacks windows, should it send all changed "above" and "below" for all tracked objects? I.e. if you click on a bottommost window and it goes all the way to the top, should it send a ton of "above" requests (one for each other visible window), plus a ton of "below" requests? Sounds a bit spammy

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only a single one. Placing a toplevel above the topmost current one would implicitly require it to be above all the others as well. As such no more than one above/below should be sent per reposition.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if the toplevel is placed in the middle, only a single "above" (for the window immediately below) or "below" (for the window immediately above) suffices?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, what about tiled windows, which also technically have an above/below ordering, but for most intents and purposes it doesn't matter (since the geometries don't overlap), so the compositor can reorder them very frequently (it's convenient in the code, and it technically does show up visually in some ways, but probably not important enough to spam the protocol)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if the toplevel is placed in the middle, only a single "above" (for the window immediately below) or "below" (for the window immediately above) suffices?

Yes. Which one is sent is up to the compositor.

Also, what about tiled windows, which also technically have an above/below ordering, but for most intents and purposes it doesn't matter (since the geometries don't overlap)

It shouldn't usually matter yeah. I think it makes sense to include it in case a client wants to make visual effects based on it though. Best to leave it open to that sort of thing.

so the compositor can reorder them very frequently (it's convenient in the code, and it technically does show up visually in some ways, but probably not important enough to spam the protocol)?

I'm personally not very concerned about protocol spam on events that are triggered by user input, especially relatively infrequent ones. Wayland effectively batches events so if you're sending one (geometry changed) you might as well send more (stacking order changed).

Comment on lines +195 to +197
The toplevel has left the tracked area. A toplevel must not be
considered to have left until the toplevel's geometry has no
intersection with the geometry tracker.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In niri, windows can scroll outside a workspace, but they for all intents and purposes remain on that workspace. How should it behave wrt. this entered and left event? Would be good to clarify

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking the entire workspace strip should be considered to be the workspace, including parts that are currently out of view.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about minimized (on a workspace) or otherwise hidden (in niri's case, unfocused in a tabbed column) windows?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minimized windows should not be included in the workspace.

Tabs I'm unsure of. We could either stack the windows directly on top of eachother in position events or not send them at all. I'm leaning towards stacking them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants