sway: Sway does not handle subsurfaces that extend beyond the parent's bounding box very well (common in gtk applications)
-
Sway Version: 1.2
-
Debug Log:
Relevant portion:
2020-01-18 02:15:28 - [sway/desktop/transaction.c:489] Transaction 0x558676e2c7f0 is ready
2020-01-18 02:15:28 - [sway/desktop/transaction.c:280] Applying transaction 0x558676e2c7f0
2020-01-18 02:15:32 - [types/seat/wlr_seat_pointer.c:362] button_count=1 grab_serial=0 serial=132
2020-01-18 02:15:32 - [sway/desktop/transaction.c:411] Transaction 0x558676e2c7f0 committing with 1 instructions
2020-01-18 02:15:32 - [sway/desktop/transaction.c:280] Applying transaction 0x558676e2c7f0
2020-01-18 02:15:32 - [types/seat/wlr_seat_pointer.c:362] button_count=0 grab_serial=132 serial=133
2020-01-18 02:15:38 - [sway/input/cursor.c:576] denying request to set cursor from unfocused client
2020-01-18 02:15:46 - [sway/ipc-server.c:334] Sending window::focus event
- Configuration File: Happens with default configuration
Steps to reproduce:
Run the popover example code found here: https://python-gtk-3-tutorial.readthedocs.io/en/latest/popover.html#menu-popover (reproduced here):
It is more obvious if you change the border width on line 46 (for the app window) to something smaller, like 10.
Once the window opens switch to floating mode (Mod+Shift+space in default config). Then click on the button to make the popover appear. Although the popover displays outside of the parent window, it doesn’t seem to receive mouse events, and if focus_follows_mouse is enabled, as soon as you move over the popover, the parent window (and the popover itself) loses focus. Clicking also seems to send the click event to the window underneath the popover.
Update
After more investigation I’ve determined this is because GTK uses subsurfaces, rather than popup surfaces or toplevel surfaces for menus and popovers. And sway seems to have some assumptions that subsurfaces fit inside the bounding box of the parent top-level surface. This results in the following undesirable behavior:
- If a subsurface extends beyond the bounding box it does not receive cursor events
- If a subsurface extends beyond the bounding box of a floating window, the border is drawn over the subsurface
- If a subsurface extends beyond the bounding box of a tiling window, it is cut off by the bounding box.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 4
- Comments: 35 (31 by maintainers)
Good news: I found the problem. Bad news: I’m not sure what the best way to fix it is (mostly because of my unfamiliarity with sway’s codebase).
So the issue is in the container_at function, and the functions it calls. So,
surface_is_popupreturns false for these subsurfaces. At first I thought that was wrong, but then I realized, that might not actually be what we want since I don’t know if these popovers should have higher priority than floating windows above them. So, the problem is actually in how it checks the location for normal containers.I think
floating_container_atis definitely broken. It should probably callsurface_at_viewinstead of just relying on the bounding box of the floating container itself. But what if the floating container isn’t a view, and has a subsurface that extends beyond the floating container’s bounding box?And then I’m not sure about tiling windows. If a tiling window has a subsurface that extend beyond it’s bounding box, should that receive events events only if the parent view is focused?
I’d be happy to implement a fix, but would like a little direction from a maintainer on what my approach should be.
I haven’t figured out why the border is drawn on top of the subsurface yet, maybe that should be a different issue?
No change planned.
If what you are trying to implement in Godot is a context menu or mouseover thing, then xdg_popup is the only interface that should be considered. Subsurfaces are unsuitable for such use even in compositors which allow overflowing the parent as they lack things like position constraints that are required to make a context menu or mouseovers usable.
The options at this point:
It seems like this issue is not priority for the Gtk team, as they’re understandably focused on Gtk4 (which already fixes this). Things also started off on the wrong foot, which does not help.
If the spec is not changed, and sway’s current interpretation remains correct/passable, then it is healthier for the Wayland community to leave it as is in order to create a more heterogenous compositor environment which helps applications and toolkits identify incorrect assumptions about protocol details.
Wayland applications and toolkits must never assume anything other than what is explicitly written in the protocol specifications, and a compositor should never concern itself with applications and frameworks but instead just implement the exact details of its supported protocols.