mirror of
				https://github.com/gnif/LookingGlass.git
				synced 2025-10-31 04:31:57 +00:00 
			
		
		
		
	[client] clipboard/wayland: implement VM-to-host image copy
Co-authored-by: Quantum <quantum2048@gmail.com>
This commit is contained in:
		 Tudor Brindus
					Tudor Brindus
				
			
				
					committed by
					
						 Geoffrey McRae
						Geoffrey McRae
					
				
			
			
				
	
			
			
			 Geoffrey McRae
						Geoffrey McRae
					
				
			
						parent
						
							c58f33f5ab
						
					
				
				
					commit
					2bfd066833
				
			| @@ -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; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user