Wayland: suspend window after frame timeout or suspend state
This is a pretty popular approach that took a while for me to wrap my head around and which only recently got "official" support through an update (xdg_shell version 6), so I think that this is all-in-all a better option than the overkill 2000Hz ticking we have now :P Basically, we wait for a frame event and, if either too much time passes or we get the new `suspended` state, we consider the window as "hidden" and stop drawing, ticking by the low usage rate. This should work great for KDE and Mutter, which support the new state, but not yet for sway, which is still stuck at a very old xdg_shell version and thus falls back to the timeout approach. Be aware that if we rely on timing out the engine will have to stall for the whole timeout, which _could_ be problematic but doensn't seem like it. Further testing is needed. Special thanks go to the guys over at #wayland on OFTC, who very patiently explained me this approach way too many times.
This commit is contained in:
@ -867,11 +867,11 @@ bool DisplayServerWayland::window_is_focused(WindowID p_window_id) const {
|
||||
}
|
||||
|
||||
bool DisplayServerWayland::window_can_draw(DisplayServer::WindowID p_window_id) const {
|
||||
return frame;
|
||||
return !suspended;
|
||||
}
|
||||
|
||||
bool DisplayServerWayland::can_any_window_draw() const {
|
||||
return frame;
|
||||
return !suspended;
|
||||
}
|
||||
|
||||
void DisplayServerWayland::window_set_ime_active(const bool p_active, DisplayServer::WindowID p_window_id) {
|
||||
@ -1143,7 +1143,32 @@ void DisplayServerWayland::process_events() {
|
||||
|
||||
wayland_thread.keyboard_echo_keys();
|
||||
|
||||
frame = wayland_thread.get_reset_frame();
|
||||
if (!suspended) {
|
||||
if (emulate_vsync) {
|
||||
// Due to various reasons, we manually handle display synchronization by
|
||||
// waiting for a frame event (request to draw) or, if available, the actual
|
||||
// window's suspend status. When a window is suspended, we can avoid drawing
|
||||
// altogether, either because the compositor told us that we don't need to or
|
||||
// because the pace of the frame events became unreliable.
|
||||
bool frame = wayland_thread.wait_frame_suspend_ms(1000);
|
||||
if (!frame) {
|
||||
suspended = true;
|
||||
}
|
||||
} else {
|
||||
if (wayland_thread.is_suspended()) {
|
||||
suspended = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (suspended) {
|
||||
DEBUG_LOG_WAYLAND("Window suspended.");
|
||||
}
|
||||
} else {
|
||||
if (wayland_thread.get_reset_frame()) {
|
||||
// At last, a sign of life! We're no longer suspended.
|
||||
suspended = false;
|
||||
}
|
||||
}
|
||||
|
||||
wayland_thread.mutex.unlock();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user