Skip to content

Commit

Permalink
WaylandBackend: copying to clipboard
Browse files Browse the repository at this point in the history
This forwards the internal clipboard to the host, but does not handle
the primary selection nor accessing the host's clipboard internally.

The source is recreated for every new copy, rather than being reused
when it is still valid. This doesn't seem to be necessary, but doing it
differently leads to clipboard managers not becoming aware of the reused
copies (under Sway, `wl-paste --watch` doesn't notice them), which at
least suggests that not reusing is more common.
  • Loading branch information
MithicSpirit committed Dec 25, 2024
1 parent 1c9495c commit 3a073fc
Showing 1 changed file with 48 additions and 1 deletion.
49 changes: 48 additions & 1 deletion src/Backends/WaylandBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,10 @@ namespace gamescope
void Wayland_XXColorManager_SupportedPrimariesNamed( xx_color_manager_v3 *pXXColorManager, uint32_t uPrimaries );
static const xx_color_manager_v3_listener s_XXColorManagerListener;

void Wayland_DataSource_Send( struct wl_data_source *pSource, const char *pMime, int nFd );
void Wayland_DataSource_Cancelled( struct wl_data_source *pSource );
static const wl_data_source_listener s_DataSourceListener;

CWaylandInputThread m_InputThread;

CWaylandConnector m_Connector;
Expand All @@ -665,6 +669,10 @@ namespace gamescope
wp_fractional_scale_manager_v1 *m_pFractionalScaleManager = nullptr;
xdg_toplevel_icon_manager_v1 *m_pToplevelIconManager = nullptr;

wl_data_device_manager *m_pDataDeviceManager = nullptr;
wl_data_device *m_pDataDevice = nullptr;
std::shared_ptr<std::string> m_pClipboard = nullptr;

struct
{
std::vector<xx_color_manager_v3_primaries> ePrimaries;
Expand Down Expand Up @@ -692,6 +700,7 @@ namespace gamescope

uint32_t m_uPointerEnterSerial = 0;
bool m_bMouseEntered = false;
uint32_t m_uKeyboardEnterSerial = 0;
bool m_bKeyboardEntered = false;

std::shared_ptr<INestedHints::CursorInfo> m_pCursorInfo;
Expand Down Expand Up @@ -752,6 +761,11 @@ namespace gamescope
.supported_tf_named = WAYLAND_USERDATA_TO_THIS( CWaylandBackend, Wayland_XXColorManager_SupportedTFNamed ),
.supported_primaries_named = WAYLAND_USERDATA_TO_THIS( CWaylandBackend, Wayland_XXColorManager_SupportedPrimariesNamed ),
};
const wl_data_source_listener CWaylandBackend::s_DataSourceListener =
{
.send = WAYLAND_USERDATA_TO_THIS( CWaylandBackend, Wayland_DataSource_Send ),
.cancelled = WAYLAND_USERDATA_TO_THIS( CWaylandBackend, Wayland_DataSource_Cancelled ),
};

//////////////////
// CWaylandFb
Expand Down Expand Up @@ -2005,7 +2019,21 @@ namespace gamescope
}
void CWaylandBackend::SetSelection( std::shared_ptr<std::string> szContents, GamescopeSelection eSelection )
{
// Do nothing
if ( !m_pDataDevice )
m_pDataDevice = wl_data_device_manager_get_data_device( m_pDataDeviceManager, m_pSeat );

if ( eSelection == GAMESCOPE_SELECTION_CLIPBOARD && m_pDataDevice )
{
m_pClipboard = szContents;
wl_data_source *source = wl_data_device_manager_create_data_source( m_pDataDeviceManager );
wl_data_source_add_listener( source, &s_DataSourceListener, this );
wl_data_source_offer( source, "text/plain" );
wl_data_device_set_selection( m_pDataDevice, source, m_uKeyboardEnterSerial );
}
else if ( eSelection == GAMESCOPE_SELECTION_PRIMARY )
{
// Do nothing
}
}

std::shared_ptr<INestedHints::CursorInfo> CWaylandBackend::GetHostCursor()
Expand Down Expand Up @@ -2183,6 +2211,10 @@ namespace gamescope
{
m_pToplevelIconManager = (xdg_toplevel_icon_manager_v1 *)wl_registry_bind( pRegistry, uName, &xdg_toplevel_icon_manager_v1_interface, 1u );
}
else if ( !strcmp( pInterface, wl_data_device_manager_interface.name ) )
{
m_pDataDeviceManager = (wl_data_device_manager *)wl_registry_bind( pRegistry, uName, &wl_data_device_manager_interface, 3u );
}
}

void CWaylandBackend::Wayland_Modifier( zwp_linux_dmabuf_v1 *pDmabuf, uint32_t uFormat, uint32_t uModifierHi, uint32_t uModifierLo )
Expand Down Expand Up @@ -2288,6 +2320,7 @@ namespace gamescope
if ( !IsSurfacePlane( pSurface ) )
return;

m_uKeyboardEnterSerial = uSerial;
m_bKeyboardEntered = true;

UpdateCursor();
Expand Down Expand Up @@ -2321,6 +2354,20 @@ namespace gamescope
m_XXColorManagerFeatures.ePrimaries.push_back( static_cast<xx_color_manager_v3_primaries>( uPrimaries ) );
}

// Data Source

void CWaylandBackend::Wayland_DataSource_Send( struct wl_data_source *pSource, const char *pMime, int nFd )
{
ssize_t len = m_pClipboard->length();
if ( write( nFd, m_pClipboard->c_str(), len ) != len )
xdg_log.infof( "Failed to write all %zd bytes to clipboard", len );
close( nFd );
}
void CWaylandBackend::Wayland_DataSource_Cancelled( struct wl_data_source *pSource )
{
wl_data_source_destroy( pSource );
}

///////////////////////
// CWaylandInputThread
///////////////////////
Expand Down

0 comments on commit 3a073fc

Please sign in to comment.