Skip to content

Commit

Permalink
WaylandBackend: copying to primary selection
Browse files Browse the repository at this point in the history
This is an extension of the previous commit, also forwarding the primary
selection to the host. This does not add support for accessing the
host's primary selection internally.
  • Loading branch information
MithicSpirit committed Dec 25, 2024
1 parent 3a073fc commit 2dab0fc
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 3 deletions.
1 change: 1 addition & 0 deletions protocol/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ protocols = [
wl_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml',
wl_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
wl_protocol_dir / 'unstable/relative-pointer/relative-pointer-unstable-v1.xml',
wl_protocol_dir / 'unstable/primary-selection/primary-selection-unstable-v1.xml',
wl_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml',
wl_protocol_dir / 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml',

Expand Down
45 changes: 42 additions & 3 deletions src/Backends/WaylandBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <xx-color-management-v3-client-protocol.h>
#include <pointer-constraints-unstable-v1-client-protocol.h>
#include <relative-pointer-unstable-v1-client-protocol.h>
#include <primary-selection-unstable-v1-client-protocol.h>
#include <fractional-scale-v1-client-protocol.h>
#include <xdg-toplevel-icon-v1-client-protocol.h>
#include "wlr_end.hpp"
Expand Down Expand Up @@ -644,6 +645,10 @@ namespace gamescope
void Wayland_DataSource_Cancelled( struct wl_data_source *pSource );
static const wl_data_source_listener s_DataSourceListener;

void Wayland_PrimarySelectionSource_Send( struct zwp_primary_selection_source_v1 *pSource, const char *pMime, int nFd );
void Wayland_PrimarySelectionSource_Cancelled( struct zwp_primary_selection_source_v1 *pSource );
static const zwp_primary_selection_source_v1_listener s_PrimarySelectionSourceListener;

CWaylandInputThread m_InputThread;

CWaylandConnector m_Connector;
Expand Down Expand Up @@ -673,6 +678,10 @@ namespace gamescope
wl_data_device *m_pDataDevice = nullptr;
std::shared_ptr<std::string> m_pClipboard = nullptr;

zwp_primary_selection_device_manager_v1 *m_pPrimarySelectionDeviceManager = nullptr;
zwp_primary_selection_device_v1 *m_pPrimarySelectionDevice = nullptr;
std::shared_ptr<std::string> m_pPrimarySelection = nullptr;

struct
{
std::vector<xx_color_manager_v3_primaries> ePrimaries;
Expand Down Expand Up @@ -766,6 +775,11 @@ namespace gamescope
.send = WAYLAND_USERDATA_TO_THIS( CWaylandBackend, Wayland_DataSource_Send ),
.cancelled = WAYLAND_USERDATA_TO_THIS( CWaylandBackend, Wayland_DataSource_Cancelled ),
};
const zwp_primary_selection_source_v1_listener CWaylandBackend::s_PrimarySelectionSourceListener =
{
.send = WAYLAND_USERDATA_TO_THIS( CWaylandBackend, Wayland_PrimarySelectionSource_Send ),
.cancelled = WAYLAND_USERDATA_TO_THIS( CWaylandBackend, Wayland_PrimarySelectionSource_Cancelled ),
};

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

if ( m_pPrimarySelectionDeviceManager && !m_pPrimarySelectionDevice )
m_pPrimarySelectionDevice = zwp_primary_selection_device_manager_v1_get_device( m_pPrimarySelectionDeviceManager, m_pSeat );

if ( eSelection == GAMESCOPE_SELECTION_CLIPBOARD && m_pDataDevice )
{
m_pClipboard = szContents;
Expand All @@ -2030,9 +2047,13 @@ namespace gamescope
wl_data_source_offer( source, "text/plain" );
wl_data_device_set_selection( m_pDataDevice, source, m_uKeyboardEnterSerial );
}
else if ( eSelection == GAMESCOPE_SELECTION_PRIMARY )
else if ( eSelection == GAMESCOPE_SELECTION_PRIMARY && m_pPrimarySelectionDevice )
{
// Do nothing
m_pPrimarySelection = szContents;
struct zwp_primary_selection_source_v1 *source = zwp_primary_selection_device_manager_v1_create_source( m_pPrimarySelectionDeviceManager );
zwp_primary_selection_source_v1_add_listener( source, &s_PrimarySelectionSourceListener, this );
zwp_primary_selection_source_v1_offer( source, "text/plain" );
zwp_primary_selection_device_v1_set_selection( m_pPrimarySelectionDevice, source, m_uPointerEnterSerial );
}
}

Expand Down Expand Up @@ -2215,6 +2236,10 @@ namespace gamescope
{
m_pDataDeviceManager = (wl_data_device_manager *)wl_registry_bind( pRegistry, uName, &wl_data_device_manager_interface, 3u );
}
else if ( !strcmp( pInterface, zwp_primary_selection_device_manager_v1_interface.name ) )
{
m_pPrimarySelectionDeviceManager = (zwp_primary_selection_device_manager_v1 *)wl_registry_bind( pRegistry, uName, &zwp_primary_selection_device_manager_v1_interface, 1u );
}
}

void CWaylandBackend::Wayland_Modifier( zwp_linux_dmabuf_v1 *pDmabuf, uint32_t uFormat, uint32_t uModifierHi, uint32_t uModifierLo )
Expand Down Expand Up @@ -2368,6 +2393,20 @@ namespace gamescope
wl_data_source_destroy( pSource );
}

// Primary Selection Source

void CWaylandBackend::Wayland_PrimarySelectionSource_Send( struct zwp_primary_selection_source_v1 *pSource, const char *pMime, int nFd )
{
ssize_t len = m_pPrimarySelection->length();
if ( write( nFd, m_pPrimarySelection->c_str(), len ) != len )
xdg_log.infof( "Failed to write all %zd bytes to clipboard", len );
close( nFd );
}
void CWaylandBackend::Wayland_PrimarySelectionSource_Cancelled( struct zwp_primary_selection_source_v1 *pSource)
{
zwp_primary_selection_source_v1_destroy( pSource );
}

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

0 comments on commit 2dab0fc

Please sign in to comment.