2
0
Эх сурвалжийг харах

Wayland: Fix stuck pointer buttons on window leave

This issue came from the frame-based refactoring done in the multiwin
PR.

It looks like some (all?) compositors group certain events alongside
`wl_pointer::leave`, which I absolutely did not expect. The docs don't
seem to mention it either from what I can tell.

We now fall-back on the old pointed window if and only if the current
window is invalid and the old one isn't. Each state fetch is guarded
with an `ERR_FAIL_NULL` so this should still catch any potentially
corrupted window with missing data but a valid ID.

I also added the usual big comment so that this "quirk" does not get
lost to time.
Riteo 5 сар өмнө
parent
commit
a3913b045d

+ 16 - 4
platform/linuxbsd/wayland/wayland_thread.cpp

@@ -1692,16 +1692,28 @@ void WaylandThread::_wl_pointer_on_frame(void *data, struct wl_pointer *wl_point
 		}
 		}
 	}
 	}
 
 
-	if (pd.pointed_id == DisplayServer::INVALID_WINDOW_ID) {
+	WindowState *ws = nullptr;
+
+	// NOTE: At least on sway, with wl_pointer version 5 or greater,
+	// wl_pointer::leave might be emitted with other events (like
+	// wl_pointer::button) within the same wl_pointer::frame. Because of this, we
+	// need to account for when the currently pointed window might be invalid
+	// (third-party or even none) and fall back to the old one.
+	if (pd.pointed_id != DisplayServer::INVALID_WINDOW_ID) {
+		ws = ss->wayland_thread->window_get_state(pd.pointed_id);
+		ERR_FAIL_NULL(ws);
+	} else if (old_pd.pointed_id != DisplayServer::INVALID_WINDOW_ID) {
+		ws = ss->wayland_thread->window_get_state(old_pd.pointed_id);
+		ERR_FAIL_NULL(ws);
+	}
+
+	if (ws == nullptr) {
 		// We're probably on a decoration or some other third-party thing. Let's
 		// We're probably on a decoration or some other third-party thing. Let's
 		// "commit" the data and call it a day.
 		// "commit" the data and call it a day.
 		old_pd = pd;
 		old_pd = pd;
 		return;
 		return;
 	}
 	}
 
 
-	WindowState *ws = ss->wayland_thread->window_get_state(pd.pointed_id);
-	ERR_FAIL_NULL(ws);
-
 	double scale = window_state_get_scale_factor(ws);
 	double scale = window_state_get_scale_factor(ws);
 
 
 	wayland_thread->_set_current_seat(ss->wl_seat);
 	wayland_thread->_set_current_seat(ss->wl_seat);