Merge pull request #97480 from Riteo/why-is-suspension-so-hard

Wayland: Unsuspend only for the same reason as suspension
This commit is contained in:
Rémi Verschelde 2025-01-08 15:53:19 +01:00
commit abd188f099
2 changed files with 39 additions and 14 deletions

View file

@ -906,11 +906,11 @@ bool DisplayServerWayland::window_is_focused(WindowID p_window_id) const {
}
bool DisplayServerWayland::window_can_draw(DisplayServer::WindowID p_window_id) const {
return !suspended;
return suspend_state == SuspendState::NONE;
}
bool DisplayServerWayland::can_any_window_draw() const {
return !suspended;
return suspend_state == SuspendState::NONE;
}
void DisplayServerWayland::window_set_ime_active(const bool p_active, DisplayServer::WindowID p_window_id) {
@ -1132,16 +1132,21 @@ void DisplayServerWayland::try_suspend() {
if (emulate_vsync) {
bool frame = wayland_thread.wait_frame_suspend_ms(1000);
if (!frame) {
suspended = true;
}
} else {
if (wayland_thread.is_suspended()) {
suspended = true;
suspend_state = SuspendState::TIMEOUT;
}
}
if (suspended) {
DEBUG_LOG_WAYLAND("Window suspended.");
// If we suspended by capability, we'll know with this check. We must do this
// after `wait_frame_suspend_ms` as it progressively dispatches the event queue
// during the "timeout".
if (wayland_thread.is_suspended()) {
suspend_state = SuspendState::CAPABILITY;
}
if (suspend_state == SuspendState::TIMEOUT) {
DEBUG_LOG_WAYLAND("Suspending. Reason: timeout.");
} else if (suspend_state == SuspendState::CAPABILITY) {
DEBUG_LOG_WAYLAND("Suspending. Reason: capability.");
}
}
@ -1226,7 +1231,7 @@ void DisplayServerWayland::process_events() {
wayland_thread.keyboard_echo_keys();
if (!suspended) {
if (suspend_state == SuspendState::NONE) {
// Due to the way legacy suspension works, we have to treat low processor
// usage mode very differently than the regular one.
if (OS::get_singleton()->is_in_low_processor_usage_mode()) {
@ -1250,9 +1255,23 @@ void DisplayServerWayland::process_events() {
} else {
try_suspend();
}
} else if (!wayland_thread.is_suspended() || wayland_thread.get_reset_frame()) {
// At last, a sign of life! We're no longer suspended.
suspended = false;
} else {
if (suspend_state == SuspendState::CAPABILITY) {
// If we suspended by capability we can assume that it will be reset when
// the compositor wants us to repaint.
if (!wayland_thread.is_suspended()) {
suspend_state = SuspendState::NONE;
DEBUG_LOG_WAYLAND("Unsuspending from capability.");
}
} else if (suspend_state == SuspendState::TIMEOUT) {
// Certain compositors might not report the "suspended" wm_capability flag.
// Because of this we'll wake up at the next frame event, indicating the
// desire for the compositor to let us repaint.
if (wayland_thread.get_reset_frame()) {
suspend_state = SuspendState::NONE;
DEBUG_LOG_WAYLAND("Unsuspending from timeout.");
}
}
}
#ifdef DBUS_ENABLED

View file

@ -105,6 +105,12 @@ class DisplayServerWayland : public DisplayServer {
Point2i hotspot;
};
enum class SuspendState {
NONE, // Unsuspended.
TIMEOUT, // Legacy fallback.
CAPABILITY, // New "suspended" wm_capability flag.
};
CursorShape cursor_shape = CURSOR_ARROW;
DisplayServer::MouseMode mouse_mode = DisplayServer::MOUSE_MODE_VISIBLE;
@ -118,7 +124,7 @@ class DisplayServerWayland : public DisplayServer {
String ime_text;
Vector2i ime_selection;
bool suspended = false;
SuspendState suspend_state = SuspendState::NONE;
bool emulate_vsync = false;
String rendering_driver;