65 lines
2.7 KiB
Diff
65 lines
2.7 KiB
Diff
From: PT Linux Launcher maintainers
|
|
Subject: Keep client-side decoration clicks out of nested applications
|
|
Bug: https://github.com/ValveSoftware/gamescope/issues/2299
|
|
Forwarded: https://github.com/ValveSoftware/gamescope/issues/2299
|
|
|
|
On compositors without xdg-decoration support, libdecor creates client-side
|
|
surfaces owned by the Gamescope Wayland connection. Pointer button callbacks
|
|
for those titlebar and resize surfaces consequently also reach Gamescope's
|
|
input thread. Forwarding a decoration press to the nested application can
|
|
leave its button permanently held because libdecor consumes the matching
|
|
release while performing a move, resize, or maximize operation.
|
|
|
|
Only begin nested button sequences while the pointer is over Gamescope's
|
|
actual toplevel surface. Track those presses so their releases are delivered
|
|
even if the pointer or keyboard focus changes during a game-originated drag.
|
|
|
|
--- a/src/Backends/WaylandBackend.cpp
|
|
+++ b/src/Backends/WaylandBackend.cpp
|
|
@@ -562,6 +562,7 @@
|
|
|
|
std::atomic<std::shared_ptr<zwp_relative_pointer_v1>> m_pRelativePointer = nullptr;
|
|
std::unordered_set<uint32_t> m_uScancodesHeld;
|
|
+ std::unordered_set<uint32_t> m_uMouseButtonsHeld;
|
|
|
|
void Wayland_Registry_Global( wl_registry *pRegistry, uint32_t uName, const char *pInterface, uint32_t uVersion );
|
|
static const wl_registry_listener s_RegistryListener;
|
|
@@ -3091,13 +3092,33 @@
|
|
}
|
|
void CWaylandInputThread::Wayland_Pointer_Button( wl_pointer *pPointer, uint32_t uSerial, uint32_t uTime, uint32_t uButton, uint32_t uState )
|
|
{
|
|
- // Don't do any motion/movement stuff if we don't have kb focus
|
|
- if ( !cv_wayland_mouse_warp_without_keyboard_focus && !m_bKeyboardEntered )
|
|
- return;
|
|
+ const bool bPressed = uState == WL_POINTER_BUTTON_STATE_PRESSED;
|
|
+ const bool bWasPressed = m_uMouseButtonsHeld.contains( uButton );
|
|
+
|
|
+ if ( bPressed )
|
|
+ {
|
|
+ // libdecor's client-side decorations share our Wayland seat, but
|
|
+ // their button events must not be sent to the nested application.
|
|
+ if ( !m_bMouseEntered || bWasPressed )
|
|
+ return;
|
|
+
|
|
+ // Don't start an application click without keyboard focus.
|
|
+ if ( !cv_wayland_mouse_warp_without_keyboard_focus && !m_bKeyboardEntered )
|
|
+ return;
|
|
+ }
|
|
+ else if ( !bWasPressed )
|
|
+ {
|
|
+ return;
|
|
+ }
|
|
|
|
wlserver_lock();
|
|
- wlserver_mousebutton( uButton, uState == WL_POINTER_BUTTON_STATE_PRESSED, ++m_uFakeTimestamp );
|
|
+ wlserver_mousebutton( uButton, bPressed, ++m_uFakeTimestamp );
|
|
wlserver_unlock();
|
|
+
|
|
+ if ( bPressed )
|
|
+ m_uMouseButtonsHeld.emplace( uButton );
|
|
+ else
|
|
+ m_uMouseButtonsHeld.erase( uButton );
|
|
}
|
|
void CWaylandInputThread::Wayland_Pointer_Axis( wl_pointer *pPointer, uint32_t uTime, uint32_t uAxis, wl_fixed_t fValue )
|
|
{
|