Skip to content

Commit

Permalink
Wayland: Implement clipboard copy
Browse files Browse the repository at this point in the history
  • Loading branch information
linkmauve committed Oct 24, 2018
1 parent 8b54e28 commit c08abff
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 3 deletions.
4 changes: 4 additions & 0 deletions src/wl_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -1263,6 +1263,8 @@ void _glfwPlatformTerminate(void)
zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager);
if (_glfw.wl.wmBase)
xdg_wm_base_destroy(_glfw.wl.wmBase);
if (_glfw.wl.dataSource)
wl_data_source_destroy(_glfw.wl.dataSource);
if (_glfw.wl.dataDevice)
wl_data_device_destroy(_glfw.wl.dataDevice);
if (_glfw.wl.dataOffer)
Expand Down Expand Up @@ -1296,6 +1298,8 @@ void _glfwPlatformTerminate(void)

if (_glfw.wl.clipboardString)
free(_glfw.wl.clipboardString);
if (_glfw.wl.clipboardSendString)
free(_glfw.wl.clipboardSendString);
}

const char* _glfwPlatformGetVersionString(void)
Expand Down
3 changes: 3 additions & 0 deletions src/wl_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ typedef struct _GLFWlibraryWayland
struct wl_data_device_manager* dataDeviceManager;
struct wl_data_device* dataDevice;
struct wl_data_offer* dataOffer;
struct wl_data_source* dataSource;
struct xdg_wm_base* wmBase;
struct zxdg_decoration_manager_v1* decorationManager;
struct wp_viewporter* viewporter;
Expand All @@ -258,6 +259,8 @@ typedef struct _GLFWlibraryWayland
int keyboardLastScancode;
char* clipboardString;
size_t clipboardSize;
char* clipboardSendString;
size_t clipboardSendSize;
int timerfd;
short int keycodes[256];
short int scancodes[GLFW_KEY_LAST + 1];
Expand Down
121 changes: 118 additions & 3 deletions src/wl_window.c
Original file line number Diff line number Diff line change
Expand Up @@ -1569,11 +1569,126 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
}
}

static void dataSourceHandleTarget(void* data,
struct wl_data_source* dataSource,
const char* mimeType)
{
if (_glfw.wl.dataSource != dataSource)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Unknown clipboard data source");
return;
}
}

static void dataSourceHandleSend(void* data,
struct wl_data_source* dataSource,
const char* mimeType,
int fd)
{
const char* string = _glfw.wl.clipboardSendString;
size_t len = _glfw.wl.clipboardSendSize;
int ret;

if (_glfw.wl.dataSource != dataSource)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Unknown clipboard data source");
return;
}

if (!string)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Copy requested from an invalid string");
return;
}

if (strcmp(mimeType, "text/plain;charset=utf-8") != 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Wrong MIME type asked from clipboard");
close(fd);
return;
}

while (len > 0)
{
ret = write(fd, string, len);
if (ret == -1 && errno == EINTR)
continue;
if (ret == -1)
{
// TODO: also report errno maybe.
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Error while writing the clipboard");
close(fd);
return;
}
len -= ret;
}
close(fd);
}

static void dataSourceHandleCancelled(void* data,
struct wl_data_source* dataSource)
{
wl_data_source_destroy(dataSource);

if (_glfw.wl.dataSource != dataSource)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Unknown clipboard data source");
return;
}

_glfw.wl.dataSource = NULL;
}

static const struct wl_data_source_listener dataSourceListener = {
dataSourceHandleTarget,
dataSourceHandleSend,
dataSourceHandleCancelled,
};

void _glfwPlatformSetClipboardString(const char* string)
{
// TODO
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Clipboard setting not implemented yet");
if (_glfw.wl.dataSource)
{
wl_data_source_destroy(_glfw.wl.dataSource);
_glfw.wl.dataSource = NULL;
}

if (_glfw.wl.clipboardSendString)
{
free(_glfw.wl.clipboardSendString);
_glfw.wl.clipboardSendString = NULL;
}

_glfw.wl.clipboardSendString = strdup(string);
if (!_glfw.wl.clipboardSendString)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Impossible to allocate clipboard string");
return;
}
_glfw.wl.clipboardSendSize = strlen(string);
_glfw.wl.dataSource =
wl_data_device_manager_create_data_source(_glfw.wl.dataDeviceManager);
if (!_glfw.wl.dataSource)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Impossible to create clipboard source");
free(_glfw.wl.clipboardSendString);
return;
}
wl_data_source_add_listener(_glfw.wl.dataSource,
&dataSourceListener,
NULL);
wl_data_source_offer(_glfw.wl.dataSource, "text/plain;charset=utf-8");
wl_data_device_set_selection(_glfw.wl.dataDevice,
_glfw.wl.dataSource,
_glfw.wl.serial);
}

static GLFWbool growClipboardString(void)
Expand Down

0 comments on commit c08abff

Please sign in to comment.