mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-11 19:11:08 +00:00
gamescope: take the host's touch in the nested Wayland backend
3.16.29's Wayland backend bound only wl_pointer and wl_keyboard; touch from DroidDeck's compositor was never read, so Steam could not be touched. 0110 binds wl_touch in the input thread and feeds each finger to wlserver_touchdown/touchmotion/touchup, the Steam Deck touchscreen's path, so Big Picture's Passthrough touch mode gets real touches.
This commit is contained in:
1 parent
e8aaae1343
commit
ed1f8dd2b6
2 files changed
+127
No files matched your search
@@ -16,6 +16,12 @@ library list, before anything is published.
|
||||
3.16.29: realtime-priority Vulkan queues on request (`GAMESCOPE_FORCE_VULKAN_REALTIME=1`)
|
||||
without CAP_SYS_NICE, which proot can never have; and the gamepad-driven cursor sprite following
|
||||
the X pointer that XTest moves (it sat frozen).
|
||||
- `0110-wayland-backend-touch.patch` - this app: the nested Wayland backend bound only the host's
|
||||
pointer and keyboard, so a finger on the phone's screen never reached Steam. It now binds
|
||||
`wl_touch` too and hands each finger to wlserver's touch path (`wlserver_touchdown` / `motion` /
|
||||
`up`) - the one a Steam Deck's touchscreen drives - so what a touch does follows the client's
|
||||
touch mode (Steam's Big Picture sets Passthrough: a real touch, rows scroll under a finger).
|
||||
Finger ids are offset by one, since the nested pointer already moves wlserver's touch 0.
|
||||
|
||||
Sixteen more of Armada's patches are DRM/lease/HDR-on-KMS work for a native display, which this
|
||||
app's Wayland-hosted gamescope never reaches, or need a newer gamescope than the runtime has.
|
||||
@@ -0,0 +1,121 @@
|
||||
diff --git a/src/Backends/WaylandBackend.cpp b/src/Backends/WaylandBackend.cpp
|
||||
index d74268b..bf72267 100644
|
||||
--- a/src/Backends/WaylandBackend.cpp
|
||||
+++ b/src/Backends/WaylandBackend.cpp
|
||||
@@ -601,6 +601,17 @@ namespace gamescope
|
||||
void Wayland_Keyboard_RepeatInfo( wl_keyboard *pKeyboard, int32_t nRate, int32_t nDelay );
|
||||
static const wl_keyboard_listener s_KeyboardListener;
|
||||
|
||||
+ // Touch from the host compositor (DroidDeck): each finger goes to wlserver's touch path,
|
||||
+ // the one a Steam Deck's touchscreen drives, instead of being dropped.
|
||||
+ void Wayland_Touch_Down( wl_touch *pTouch, uint32_t uSerial, uint32_t uTime, wl_surface *pSurface, int32_t nId, wl_fixed_t fX, wl_fixed_t fY );
|
||||
+ void Wayland_Touch_Up( wl_touch *pTouch, uint32_t uSerial, uint32_t uTime, int32_t nId );
|
||||
+ void Wayland_Touch_Motion( wl_touch *pTouch, uint32_t uTime, int32_t nId, wl_fixed_t fX, wl_fixed_t fY );
|
||||
+ void Wayland_Touch_Frame( wl_touch *pTouch );
|
||||
+ void Wayland_Touch_Cancel( wl_touch *pTouch );
|
||||
+ static const wl_touch_listener s_TouchListener;
|
||||
+ bool TouchToOutput( wl_surface *pSurface, wl_fixed_t fX, wl_fixed_t fY, double *pflX, double *pflY );
|
||||
+ std::unordered_map<int32_t, wl_surface *> m_TouchSurfaces;
|
||||
+
|
||||
void Wayland_RelativePointer_RelativeMotion( zwp_relative_pointer_v1 *pRelativePointer, uint32_t uTimeHi, uint32_t uTimeLo, wl_fixed_t fDx, wl_fixed_t fDy, wl_fixed_t fDxUnaccel, wl_fixed_t fDyUnaccel );
|
||||
static const zwp_relative_pointer_v1_listener s_RelativePointerListener;
|
||||
};
|
||||
@@ -636,6 +647,16 @@ namespace gamescope
|
||||
.modifiers = WAYLAND_USERDATA_TO_THIS( CWaylandInputThread, Wayland_Keyboard_Modifiers ),
|
||||
.repeat_info = WAYLAND_USERDATA_TO_THIS( CWaylandInputThread, Wayland_Keyboard_RepeatInfo ),
|
||||
};
|
||||
+ const wl_touch_listener CWaylandInputThread::s_TouchListener =
|
||||
+ {
|
||||
+ .down = WAYLAND_USERDATA_TO_THIS( CWaylandInputThread, Wayland_Touch_Down ),
|
||||
+ .up = WAYLAND_USERDATA_TO_THIS( CWaylandInputThread, Wayland_Touch_Up ),
|
||||
+ .motion = WAYLAND_USERDATA_TO_THIS( CWaylandInputThread, Wayland_Touch_Motion ),
|
||||
+ .frame = WAYLAND_USERDATA_TO_THIS( CWaylandInputThread, Wayland_Touch_Frame ),
|
||||
+ .cancel = WAYLAND_USERDATA_TO_THIS( CWaylandInputThread, Wayland_Touch_Cancel ),
|
||||
+ .shape = WAYLAND_NULL(),
|
||||
+ .orientation = WAYLAND_NULL(),
|
||||
+ };
|
||||
const zwp_relative_pointer_v1_listener CWaylandInputThread::s_RelativePointerListener =
|
||||
{
|
||||
.relative_motion = WAYLAND_USERDATA_TO_THIS( CWaylandInputThread, Wayland_RelativePointer_RelativeMotion ),
|
||||
@@ -3067,6 +3088,81 @@ namespace gamescope
|
||||
wl_keyboard_add_listener( m_pKeyboard, &s_KeyboardListener, this );
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if ( !!( uCapabilities & WL_SEAT_CAPABILITY_TOUCH ) != !!m_pTouch )
|
||||
+ {
|
||||
+ if ( m_pTouch )
|
||||
+ {
|
||||
+ wl_touch_release( m_pTouch );
|
||||
+ m_pTouch = nullptr;
|
||||
+ m_TouchSurfaces.clear();
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ m_pTouch = wl_seat_get_touch( m_pSeat );
|
||||
+ wl_touch_add_listener( m_pTouch, &s_TouchListener, this );
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Touch
|
||||
+
|
||||
+ bool CWaylandInputThread::TouchToOutput( wl_surface *pSurface, wl_fixed_t fX, wl_fixed_t fY, double *pflX, double *pflY )
|
||||
+ {
|
||||
+ if ( !pSurface || !IsGamescopeToplevel( pSurface ) )
|
||||
+ return false;
|
||||
+ CWaylandPlane *pPlane = (CWaylandPlane *)wl_surface_get_user_data( pSurface );
|
||||
+ if ( !pPlane )
|
||||
+ return false;
|
||||
+ auto oState = pPlane->GetCurrentState();
|
||||
+ if ( !oState || !g_nOutputWidth || !g_nOutputHeight )
|
||||
+ return false;
|
||||
+ uint32_t uScale = oState->uFractionalScale;
|
||||
+ *pflX = ( wl_fixed_to_double( fX ) * uScale / 120.0 + oState->nDestX ) / g_nOutputWidth;
|
||||
+ *pflY = ( wl_fixed_to_double( fY ) * uScale / 120.0 + oState->nDestY ) / g_nOutputHeight;
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Touch ids are offset by one: the nested pointer already moves wlserver's touch 0.
|
||||
+ void CWaylandInputThread::Wayland_Touch_Down( wl_touch *pTouch, uint32_t uSerial, uint32_t uTime, wl_surface *pSurface, int32_t nId, wl_fixed_t fX, wl_fixed_t fY )
|
||||
+ {
|
||||
+ double flX, flY;
|
||||
+ if ( !TouchToOutput( pSurface, fX, fY, &flX, &flY ) )
|
||||
+ return;
|
||||
+ m_TouchSurfaces[ nId ] = pSurface;
|
||||
+ wlserver_lock();
|
||||
+ wlserver_touchdown( flX, flY, nId + 1, ++m_uFakeTimestamp );
|
||||
+ wlserver_unlock();
|
||||
+ }
|
||||
+ void CWaylandInputThread::Wayland_Touch_Up( wl_touch *pTouch, uint32_t uSerial, uint32_t uTime, int32_t nId )
|
||||
+ {
|
||||
+ if ( m_TouchSurfaces.erase( nId ) == 0 )
|
||||
+ return;
|
||||
+ wlserver_lock();
|
||||
+ wlserver_touchup( nId + 1, ++m_uFakeTimestamp );
|
||||
+ wlserver_unlock();
|
||||
+ }
|
||||
+ void CWaylandInputThread::Wayland_Touch_Motion( wl_touch *pTouch, uint32_t uTime, int32_t nId, wl_fixed_t fX, wl_fixed_t fY )
|
||||
+ {
|
||||
+ auto it = m_TouchSurfaces.find( nId );
|
||||
+ if ( it == m_TouchSurfaces.end() )
|
||||
+ return;
|
||||
+ double flX, flY;
|
||||
+ if ( !TouchToOutput( it->second, fX, fY, &flX, &flY ) )
|
||||
+ return;
|
||||
+ wlserver_lock();
|
||||
+ wlserver_touchmotion( flX, flY, nId + 1, ++m_uFakeTimestamp );
|
||||
+ wlserver_unlock();
|
||||
+ }
|
||||
+ void CWaylandInputThread::Wayland_Touch_Frame( wl_touch *pTouch )
|
||||
+ {
|
||||
+ }
|
||||
+ void CWaylandInputThread::Wayland_Touch_Cancel( wl_touch *pTouch )
|
||||
+ {
|
||||
+ wlserver_lock();
|
||||
+ for ( auto &[ nId, pSurface ] : m_TouchSurfaces )
|
||||
+ wlserver_touchup( nId + 1, ++m_uFakeTimestamp );
|
||||
+ wlserver_unlock();
|
||||
+ m_TouchSurfaces.clear();
|
||||
}
|
||||
|
||||
void CWaylandInputThread::Wayland_Seat_Name( wl_seat *pSeat, const char *pName )
|
||||
Reference in new issue
Block a user