Conversation
|
Thanks. I read #3441, #3442 and ff73119. If I understand the concern: the configure that adds If so, I can rework this along the lines you proposed in #3442: the application tells winit it has stopped presenting (for example, a window method called after handling |
Hyprland doesn't implement transactional configure sequences. It cannot be used to test anything related to configure sequences since it doesn't operate under the same constraints as other compositors.
Most compositors use a short timeout, say 200 milliseconds. So this would show up as a stutter instead of permanently blocking subsequent configuration sequences. |
|
Thanks, both. I tested this on compositors with transactional configure sequences and on ones that send
To model the case you describe, I changed Jay to also wait on hidden windows (200 ms timeout). There the patch caused one timeout-long stall, about 200 ms, each time a window was hidden, and no permanent block. Stock winit avoids that stall only because the app keeps drawing once and then freezes on vsync for as long as the window is hidden. A single empty commit from winit on the configure that leaves the window suspended removed every stall in that setup. sctk already acks each configure, so the commit is the only missing piece. A commit from winit is only safe while the app isn't presenting, though, so I'd follow the shape from #3442: a window method the app calls after handling |
A compositor sends no frame callbacks to a surface it has suspended, so a client presenting with vsync blocks until the window is shown again. Winit stopped reporting this state as `WindowEvent::Occluded` in rust-windowing#3441: every configure also requested a redraw so the acknowledgement would be committed, and drawing on the configure that suspends the window blocked. Emit `Occluded` again when the `suspended` state is added or removed, and add `WindowExtWayland::notify_presentation_paused`, as proposed in rust-windowing#3442. An application calls it after it has stopped presenting on `Occluded(true)`. Winit then commits the surface itself for the pending configure (sctk has already acknowledged it) and for every later configure while the window stays suspended, instead of asking for a redraw. The configure that ends the suspension asks for a redraw as before, and the next `Occluded(true)` needs a new call. Winit leaves the commit to the application when the integer buffer scale changed since the call, because the new scale would apply to the old buffer, whose size need not be a multiple of it. An application that never calls the method behaves as before: every configure, including the suspending one, asks for a redraw. Refs rust-windowing#3442
9d2015f to
a68ac90
Compare
|
I pushed the shape from my last comment.
Testing used a small softbuffer probe that hides its window three times per run. On headless Jay, I kept hidden windows in transactions as before, with the stock 50 ms timeout:
On Hyprland 0.56.2 (headless output, window moved to a special workspace and back), the events and commits were as expected. The 0.30 backport (#4710) gave the same results. @mahkoh, a side note: Jay's headless backend never clears The name is open. I can also move it to the core |
Hyprland stops frame callbacks to a window covered by a fullscreen or maximized one without marking it suspended, so a vsync swap blocked the event loop until the compositor called ZapFast unresponsive (#190). Pin the shared forks: crmne/egui apps-0.36 presents without a blocking swap on Wayland, paces frames by frame callbacks, and runs only the app logic when a redraw is 250 ms overdue (emilk/egui#8631); crmne/winit apps-0.30 reports suspended as Occluded and commits on the app's behalf (rust-windowing/winit#4709). vsync.rs's compositor check goes: vsync is requested everywhere and eframe handles Wayland. Fixes #190
Hyprland sends no frame callbacks to a window covered by a fullscreen or maximized one, on a hidden workspace, or with the display off, so a vsync swap blocked the event loop the tray shares and the compositor called the app unresponsive. Pin the forks ZapFast, Spotifast, RekordFlash and TonePush share: crmne/egui apps-0.36 paces Wayland frames by frame callbacks (emilk/egui#8631) and crmne/winit apps-0.30 reports suspended as Occluded (rust-windowing/winit#4709). egui_kittest comes from the same revision so the tests share one egui.
| return false; | ||
| } | ||
|
|
||
| self.window.wl_surface().commit(); |
There was a problem hiding this comment.
winit should never commit on behalf of the user when there's a possibility of user rendering, which there's, so such approach doesn't work.
What works, perhaps, is once you get Suspended, do RequestRedraw and after that request submit Occluded, so the event is kind of delayed with the hope that user redrawn because they got asked to do so, so delivering Occluded would be once we know that user kind-of committed the occluded state.
Hyprland sends no frame callbacks to a window covered by a fullscreen or maximized one, on a hidden workspace, or with the display off, so a vsync swap blocked the event loop the tray shares and the compositor called the app unresponsive. Pin the forks ZapFast, Spotifast, RekordFlash and TonePush share: crmne/egui apps-0.36 paces Wayland frames by frame callbacks (emilk/egui#8631) and crmne/winit apps-0.30 reports suspended as Occluded (rust-windowing/winit#4709). egui_kittest comes from the same revision so the tests share one egui.
Hyprland sends no frame callbacks to a window covered by a fullscreen or maximized one, on a hidden workspace, or with the display off, so a vsync swap blocked the event loop the tray shares and the compositor called the app unresponsive. Pin the forks ZapFast, Spotifast, RekordFlash and TonePush share: crmne/egui apps-0.36 paces Wayland frames by frame callbacks (emilk/egui#8631) and crmne/winit apps-0.30 reports suspended as Occluded (rust-windowing/winit#4709). egui_kittest comes from the same revision so the tests share one egui.
|
Thanks, understood about not committing on the user's behalf. I tested the redraw-then- So the dialog is the app's job ( |
On Wayland, a compositor stops sending frame callbacks to a window it has suspended (xdg-shell v6
suspended, sent for example when the window is on a hidden workspace or the outputs are off). A client that presents with vsync then blocks until the window is shown again, which freezes its event loop.Winit used to report this state as
WindowEvent::Occluded, but #3441 removed it: every configure also requested a redraw so the acknowledgement would be committed, and drawing on the configure that suspends the window blocked. This follows the design in #3442:Occluded(true)andOccluded(false)are emitted when thesuspendedstate is added or removed.WindowExtWayland::notify_presentation_paused(). An app calls it after it has stopped presenting onOccluded(true). Winit then commits the surface itself for the pending configure (sctk has already acked it) and for every later configure while the window stays suspended, instead of asking for a redraw. The configure that ends the suspension asks for a redraw as before, and the nextOccluded(true)needs a new call.Occludeddocs now cover Wayland and this contract, including apps that keep presenting at a low rate while occluded (swap interval 0, nopre_present_notify).Testing: a softbuffer probe hid its window three times per run, on headless Jay (with hidden windows kept in transactions, stock 50 ms timeout) and on Hyprland 0.56.2 (headless output):
Hyprland showed the expected
Occludedevents and commits. Sway doesn't sendsuspended. Compositors older than xdg_wm_base v6 never send it either, so nothing changes there.changelogmodule if knowledge of this change could be valuable to users