diff --git a/src/Backends/WaylandBackend.cpp b/src/Backends/WaylandBackend.cpp index 964132b2a4..22425f5072 100644 --- a/src/Backends/WaylandBackend.cpp +++ b/src/Backends/WaylandBackend.cpp @@ -556,6 +556,7 @@ namespace gamescope uint32_t m_uAxisSource = WL_POINTER_AXIS_SOURCE_WHEEL; wl_surface *m_pCurrentCursorSurface = nullptr; + wl_surface *m_pCurrentTouchSurface = nullptr; std::optional m_ofPendingCursorX; std::optional m_ofPendingCursorY; @@ -592,6 +593,15 @@ namespace gamescope 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; + + 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 ); + void Wayland_Touch_Shape( wl_touch *pTouch, int32_t nId, wl_fixed_t fMajor, wl_fixed_t fMinor ); + void Wayland_Touch_Orientation( wl_touch *pTouch, int32_t nId, wl_fixed_t fOrientation ); + static const wl_touch_listener s_TouchListener; }; const wl_registry_listener CWaylandInputThread::s_RegistryListener = { @@ -629,6 +639,16 @@ namespace gamescope { .relative_motion = WAYLAND_USERDATA_TO_THIS( CWaylandInputThread, Wayland_RelativePointer_RelativeMotion ), }; + 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_USERDATA_TO_THIS( CWaylandInputThread, Wayland_Touch_Shape ), + .orientation = WAYLAND_USERDATA_TO_THIS( CWaylandInputThread, Wayland_Touch_Orientation ), + }; class CWaylandBackend : public CBaseBackend { @@ -3024,6 +3044,20 @@ 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; + } + else + { + m_pTouch = wl_seat_get_touch( m_pSeat ); + wl_touch_add_listener( m_pTouch, &s_TouchListener, this ); + } + } } void CWaylandInputThread::Wayland_Seat_Name( wl_seat *pSeat, const char *pName ) @@ -3250,6 +3284,78 @@ namespace gamescope wlserver_unlock(); } + // Touch + + 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 ) + { + if ( !IsGamescopeToplevel( pSurface ) ) + return; + + m_pCurrentTouchSurface = pSurface; + + CWaylandPlane *pPlane = (CWaylandPlane *)wl_surface_get_user_data( m_pCurrentTouchSurface ); + if ( !pPlane ) + return; + + auto oState = pPlane->GetCurrentState(); + if ( !oState ) + return; + + uint32_t uScale = oState->uFractionalScale; + double flX = ( wl_fixed_to_double( fX ) * uScale / 120.0 + oState->nDestX ) / g_nOutputWidth; + double flY = ( wl_fixed_to_double( fY ) * uScale / 120.0 + oState->nDestY ) / g_nOutputHeight; + + wlserver_lock(); + wlserver_touchdown( flX, flY, nId, ++m_uFakeTimestamp ); + wlserver_unlock(); + } + void CWaylandInputThread::Wayland_Touch_Up( wl_touch *pTouch, uint32_t uSerial, uint32_t uTime, int32_t nId ) + { + wlserver_lock(); + wlserver_touchup( nId, ++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 ) + { + if ( !m_pCurrentTouchSurface ) + return; + + CWaylandPlane *pPlane = (CWaylandPlane *)wl_surface_get_user_data( m_pCurrentTouchSurface ); + if ( !pPlane ) + return; + + auto oState = pPlane->GetCurrentState(); + if ( !oState ) + return; + + uint32_t uScale = oState->uFractionalScale; + double flX = ( wl_fixed_to_double( fX ) * uScale / 120.0 + oState->nDestX ) / g_nOutputWidth; + double flY = ( wl_fixed_to_double( fY ) * uScale / 120.0 + oState->nDestY ) / g_nOutputHeight; + + wlserver_lock(); + wlserver_touchmotion( flX, flY, nId, ++m_uFakeTimestamp ); + wlserver_unlock(); + } + void CWaylandInputThread::Wayland_Touch_Frame( wl_touch *pTouch ) + { + } + void CWaylandInputThread::Wayland_Touch_Cancel( wl_touch *pTouch ) + { + wlserver_lock(); + std::set touchIds = wlserver.touch_down_ids; + for ( uint32_t nId : touchIds ) + wlserver_touchup( nId, ++m_uFakeTimestamp ); + wlserver_unlock(); + + m_pCurrentTouchSurface = nullptr; + } + void CWaylandInputThread::Wayland_Touch_Shape( wl_touch *pTouch, int32_t nId, wl_fixed_t fMajor, wl_fixed_t fMinor ) + { + } + void CWaylandInputThread::Wayland_Touch_Orientation( wl_touch *pTouch, int32_t nId, wl_fixed_t fOrientation ) + { + } + ///////////////////////// // Backend Instantiator /////////////////////////