mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-12-23 22:31:46 +00:00
[client] clipboard/wayland: implement VM-to-host image copy
Co-authored-by: Quantum <quantum2048@gmail.com>
This commit is contained in:
parent
c58f33f5ab
commit
2bfd066833
1 changed files with 64 additions and 19 deletions
|
@ -28,6 +28,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
struct transfer {
|
struct transfer {
|
||||||
void * data;
|
void * data;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
const char ** mimetypes;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct state
|
struct state
|
||||||
|
@ -58,8 +59,56 @@ static const char * text_mimetypes[] =
|
||||||
"TEXT",
|
"TEXT",
|
||||||
"STRING",
|
"STRING",
|
||||||
"UTF8_STRING",
|
"UTF8_STRING",
|
||||||
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char * png_mimetypes[] =
|
||||||
|
{
|
||||||
|
"image/png",
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * bmp_mimetypes[] =
|
||||||
|
{
|
||||||
|
"image/bmp",
|
||||||
|
"image/x-bmp",
|
||||||
|
"image/x-MS-bmp",
|
||||||
|
"image/x-win-bitmap",
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * tiff_mimetypes[] =
|
||||||
|
{
|
||||||
|
"image/tiff",
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * jpeg_mimetypes[] =
|
||||||
|
{
|
||||||
|
"image/jpeg",
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char ** cb_type_to_mimetypes(enum LG_ClipboardData type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case LG_CLIPBOARD_DATA_TEXT:
|
||||||
|
return text_mimetypes;
|
||||||
|
case LG_CLIPBOARD_DATA_PNG:
|
||||||
|
return png_mimetypes;
|
||||||
|
case LG_CLIPBOARD_DATA_BMP:
|
||||||
|
return bmp_mimetypes;
|
||||||
|
case LG_CLIPBOARD_DATA_TIFF:
|
||||||
|
return tiff_mimetypes;
|
||||||
|
case LG_CLIPBOARD_DATA_JPEG:
|
||||||
|
return jpeg_mimetypes;
|
||||||
|
default:
|
||||||
|
DEBUG_ERROR("invalid clipboard type");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const char * wayland_cb_getName()
|
static const char * wayland_cb_getName()
|
||||||
{
|
{
|
||||||
return "Wayland";
|
return "Wayland";
|
||||||
|
@ -208,19 +257,20 @@ static void wayland_cb_wmevent(SDL_SysWMmsg * msg)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_text_mimetype(const char * mime_type)
|
static bool is_valid_mimetype(struct transfer * transfer,
|
||||||
|
const char * needle)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < sizeof(text_mimetypes)/sizeof(char *); i++)
|
for (const char ** mimetype = transfer->mimetypes; *mimetype; mimetype++)
|
||||||
if (!strcmp(mime_type, text_mimetypes[i]))
|
if (!strcmp(needle, *mimetype))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void data_source_handle_send(void * data, struct wl_data_source * source,
|
static void data_source_handle_send(void * data, struct wl_data_source * source,
|
||||||
const char * mime_type, int fd) {
|
const char * mimetype, int fd) {
|
||||||
struct transfer *transfer = (struct transfer *) data;
|
struct transfer *transfer = (struct transfer *) data;
|
||||||
if (is_text_mimetype(mime_type))
|
if (is_valid_mimetype(transfer, mimetype))
|
||||||
{
|
{
|
||||||
// Consider making this do non-blocking sends to not stall the Wayland
|
// Consider making this do non-blocking sends to not stall the Wayland
|
||||||
// event loop if it becomes a problem. This is "fine" in the sense that
|
// event loop if it becomes a problem. This is "fine" in the sense that
|
||||||
|
@ -263,16 +313,17 @@ static void wayland_cb_reply_fn(void * opaque, LG_ClipboardData type, uint8_t *
|
||||||
struct transfer * transfer = malloc(sizeof(struct transfer));
|
struct transfer * transfer = malloc(sizeof(struct transfer));
|
||||||
void * data_copy = malloc(size);
|
void * data_copy = malloc(size);
|
||||||
memcpy(data_copy, data, size);
|
memcpy(data_copy, data, size);
|
||||||
transfer->data = data_copy;
|
*transfer = (struct transfer) {
|
||||||
transfer->size = size;
|
.data = data_copy,
|
||||||
|
.size = size,
|
||||||
|
.mimetypes = cb_type_to_mimetypes(type),
|
||||||
|
};
|
||||||
|
|
||||||
struct wl_data_source * source =
|
struct wl_data_source * source =
|
||||||
wl_data_device_manager_create_data_source(this->data_device_manager);
|
wl_data_device_manager_create_data_source(this->data_device_manager);
|
||||||
wl_data_source_add_listener(source, &data_source_listener, transfer);
|
wl_data_source_add_listener(source, &data_source_listener, transfer);
|
||||||
for (int i = 0; i < sizeof(text_mimetypes)/sizeof(*text_mimetypes); i++)
|
for (const char ** mimetype = transfer->mimetypes; *mimetype; mimetype++)
|
||||||
{
|
wl_data_source_offer(source, *mimetype);
|
||||||
wl_data_source_offer(source, text_mimetypes[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_data_device_set_selection(this->data_device, source,
|
wl_data_device_set_selection(this->data_device, source,
|
||||||
this->keyboard_enter_serial);
|
this->keyboard_enter_serial);
|
||||||
|
@ -280,12 +331,6 @@ static void wayland_cb_reply_fn(void * opaque, LG_ClipboardData type, uint8_t *
|
||||||
|
|
||||||
static void wayland_cb_notice(LG_ClipboardRequestFn requestFn, LG_ClipboardData type)
|
static void wayland_cb_notice(LG_ClipboardRequestFn requestFn, LG_ClipboardData type)
|
||||||
{
|
{
|
||||||
if (type != LG_CLIPBOARD_DATA_TEXT)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Only text selection currently supported");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->requestFn = requestFn;
|
this->requestFn = requestFn;
|
||||||
this->type = type;
|
this->type = type;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue