mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-11-03 09:01:42 -05:00 
			
		
		
		
	First attempt at selection support
This commit is contained in:
		
							parent
							
								
									4cca349349
								
							
						
					
					
						commit
						ae6c8a6d73
					
				
					 5 changed files with 242 additions and 6 deletions
				
			
		| 
						 | 
					@ -682,6 +682,10 @@ notify_button(struct wl_input_device *device,
 | 
				
			||||||
	if (state && device->grab == NULL) {
 | 
						if (state && device->grab == NULL) {
 | 
				
			||||||
		wlsc_surface_raise(surface);
 | 
							wlsc_surface_raise(surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (wd->selection)
 | 
				
			||||||
 | 
								wlsc_selection_set_focus(wd->selection,
 | 
				
			||||||
 | 
											 &surface->surface, time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		wl_input_device_start_grab(device,
 | 
							wl_input_device_start_grab(device,
 | 
				
			||||||
					   &device->motion_grab,
 | 
										   &device->motion_grab,
 | 
				
			||||||
					   button, time);
 | 
										   button, time);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,6 +69,7 @@ struct wlsc_input_device {
 | 
				
			||||||
	int32_t hotspot_x, hotspot_y;
 | 
						int32_t hotspot_x, hotspot_y;
 | 
				
			||||||
	struct wl_list link;
 | 
						struct wl_list link;
 | 
				
			||||||
	uint32_t modifier_state;
 | 
						uint32_t modifier_state;
 | 
				
			||||||
 | 
						struct wl_selection *selection;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlsc_drm {
 | 
					struct wlsc_drm {
 | 
				
			||||||
| 
						 | 
					@ -165,6 +166,10 @@ wlsc_input_device_set_pointer_image(struct wlsc_input_device *device,
 | 
				
			||||||
struct wlsc_surface *
 | 
					struct wlsc_surface *
 | 
				
			||||||
pick_surface(struct wl_input_device *device, int32_t *sx, int32_t *sy);
 | 
					pick_surface(struct wl_input_device *device, int32_t *sx, int32_t *sy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					wlsc_selection_set_focus(struct wl_selection *selection,
 | 
				
			||||||
 | 
								 struct wl_surface *surface, uint32_t time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint32_t
 | 
					uint32_t
 | 
				
			||||||
get_time(void);
 | 
					get_time(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -206,11 +206,6 @@ shell_resize(struct wl_client *client, struct wl_shell *shell,
 | 
				
			||||||
	wlsc_input_device_set_pointer_image(wd, pointer);
 | 
						wlsc_input_device_set_pointer_image(wd, pointer);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
wl_drag_set_pointer_focus(struct wl_drag *drag,
 | 
					 | 
				
			||||||
			  struct wl_surface *surface, uint32_t time,
 | 
					 | 
				
			||||||
			  int32_t x, int32_t y, int32_t sx, int32_t sy);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
destroy_drag(struct wl_resource *resource, struct wl_client *client)
 | 
					destroy_drag(struct wl_resource *resource, struct wl_client *client)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -458,10 +453,176 @@ shell_create_drag(struct wl_client *client,
 | 
				
			||||||
	wl_client_add_resource(client, &drag->resource);
 | 
						wl_client_add_resource(client, &drag->resource);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					wlsc_selection_set_focus(struct wl_selection *selection,
 | 
				
			||||||
 | 
								 struct wl_surface *surface, uint32_t time)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char **p, **end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (selection->selection_focus == surface)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (selection->selection_focus != NULL)
 | 
				
			||||||
 | 
							wl_client_post_event(selection->selection_focus->client,
 | 
				
			||||||
 | 
									     &selection->selection_offer.object,
 | 
				
			||||||
 | 
									     WL_SELECTION_OFFER_KEYBOARD_FOCUS,
 | 
				
			||||||
 | 
									     NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (surface) {
 | 
				
			||||||
 | 
							wl_client_post_global(surface->client,
 | 
				
			||||||
 | 
									      &selection->selection_offer.object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							end = selection->types.data + selection->types.size;
 | 
				
			||||||
 | 
							for (p = selection->types.data; p < end; p++)
 | 
				
			||||||
 | 
								wl_client_post_event(surface->client,
 | 
				
			||||||
 | 
										     &selection->selection_offer.object,
 | 
				
			||||||
 | 
										     WL_SELECTION_OFFER_OFFER, *p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							wl_list_remove(&selection->selection_focus_listener.link);
 | 
				
			||||||
 | 
							wl_list_insert(surface->destroy_listener_list.prev,
 | 
				
			||||||
 | 
								       &selection->selection_focus_listener.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							wl_client_post_event(surface->client,
 | 
				
			||||||
 | 
									     &selection->selection_offer.object,
 | 
				
			||||||
 | 
									     WL_SELECTION_OFFER_KEYBOARD_FOCUS,
 | 
				
			||||||
 | 
									     selection->input_device);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						selection->selection_focus = surface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_remove(&selection->selection_focus_listener.link);
 | 
				
			||||||
 | 
						if (surface)
 | 
				
			||||||
 | 
							wl_list_insert(surface->destroy_listener_list.prev,
 | 
				
			||||||
 | 
								       &selection->selection_focus_listener.link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					selection_offer_receive(struct wl_client *client,
 | 
				
			||||||
 | 
								struct wl_selection_offer *offer,
 | 
				
			||||||
 | 
								const char *mime_type, int fd)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct wl_selection *selection =
 | 
				
			||||||
 | 
							container_of(offer, struct wl_selection, selection_offer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_client_post_event(selection->client,
 | 
				
			||||||
 | 
								     &selection->resource.object,
 | 
				
			||||||
 | 
								     WL_SELECTION_SEND, mime_type, fd);
 | 
				
			||||||
 | 
						close(fd);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct wl_selection_offer_interface selection_offer_interface = {
 | 
				
			||||||
 | 
						selection_offer_receive
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					selection_offer(struct wl_client *client,
 | 
				
			||||||
 | 
							struct wl_selection *selection, const char *type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char **p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p = wl_array_add(&selection->types, sizeof *p);
 | 
				
			||||||
 | 
						if (p)
 | 
				
			||||||
 | 
							*p = strdup(type);
 | 
				
			||||||
 | 
						if (!p || !*p)
 | 
				
			||||||
 | 
							wl_client_post_no_memory(client);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					selection_activate(struct wl_client *client,
 | 
				
			||||||
 | 
							   struct wl_selection *selection,
 | 
				
			||||||
 | 
							   struct wl_input_device *device, uint32_t time)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
 | 
				
			||||||
 | 
						struct wl_display *display = wl_client_get_display (client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						selection->input_device = device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						selection->selection_offer.object.interface =
 | 
				
			||||||
 | 
							&wl_selection_offer_interface;
 | 
				
			||||||
 | 
						selection->selection_offer.object.implementation =
 | 
				
			||||||
 | 
							(void (**)(void)) &selection_offer_interface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_display_add_object(display, &selection->selection_offer.object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (wd->selection) {
 | 
				
			||||||
 | 
							wl_client_post_event(wd->selection->client,
 | 
				
			||||||
 | 
									     &wd->selection->resource.object,
 | 
				
			||||||
 | 
									     WL_SELECTION_CANCELLED);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wd->selection = selection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlsc_selection_set_focus(selection, device->keyboard_focus, time);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					selection_destroy(struct wl_client *client, struct wl_selection *selection)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						wl_resource_destroy(&selection->resource, client);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct wl_selection_interface selection_interface = {
 | 
				
			||||||
 | 
						selection_offer,
 | 
				
			||||||
 | 
						selection_activate,
 | 
				
			||||||
 | 
						selection_destroy
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					destroy_selection(struct wl_resource *resource, struct wl_client *client)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct wl_selection *selection =
 | 
				
			||||||
 | 
							container_of(resource, struct wl_selection, resource);
 | 
				
			||||||
 | 
						struct wlsc_input_device *wd =
 | 
				
			||||||
 | 
							(struct wlsc_input_device *) selection->input_device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (wd && wd->selection == selection) {
 | 
				
			||||||
 | 
							wd->selection = NULL;
 | 
				
			||||||
 | 
							wlsc_selection_set_focus(selection, NULL, get_time());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_remove(&selection->selection_focus_listener.link);
 | 
				
			||||||
 | 
						free(selection);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					selection_handle_surface_destroy(struct wl_listener *listener,
 | 
				
			||||||
 | 
									 struct wl_surface *surface, uint32_t time)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					shell_create_selection(struct wl_client *client,
 | 
				
			||||||
 | 
							       struct wl_shell *shell, uint32_t id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct wl_selection *selection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						selection = malloc(sizeof *selection);
 | 
				
			||||||
 | 
						if (selection == NULL) {
 | 
				
			||||||
 | 
							wl_client_post_no_memory(client);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(selection, 0, sizeof *selection);
 | 
				
			||||||
 | 
						selection->resource.object.id = id;
 | 
				
			||||||
 | 
						selection->resource.object.interface = &wl_selection_interface;
 | 
				
			||||||
 | 
						selection->resource.object.implementation =
 | 
				
			||||||
 | 
							(void (**)(void)) &selection_interface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						selection->client = client;
 | 
				
			||||||
 | 
						selection->resource.destroy = destroy_selection;
 | 
				
			||||||
 | 
						selection->selection_focus = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						selection->selection_focus_listener.func =
 | 
				
			||||||
 | 
							selection_handle_surface_destroy;
 | 
				
			||||||
 | 
						wl_list_init(&selection->selection_focus_listener.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_client_add_resource(client, &selection->resource);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const static struct wl_shell_interface shell_interface = {
 | 
					const static struct wl_shell_interface shell_interface = {
 | 
				
			||||||
	shell_move,
 | 
						shell_move,
 | 
				
			||||||
	shell_resize,
 | 
						shell_resize,
 | 
				
			||||||
	shell_create_drag
 | 
						shell_create_drag,
 | 
				
			||||||
 | 
						shell_create_selection
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -164,6 +164,10 @@
 | 
				
			||||||
      <arg name="id" type="new_id" interface="drag"/>
 | 
					      <arg name="id" type="new_id" interface="drag"/>
 | 
				
			||||||
    </request>
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="create_selection">
 | 
				
			||||||
 | 
					      <arg name="id" type="new_id" interface="selection"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <!-- The configure event asks the client to resize its surface.
 | 
					    <!-- The configure event asks the client to resize its surface.
 | 
				
			||||||
         The size is a hint, in the sense that the client is free to
 | 
					         The size is a hint, in the sense that the client is free to
 | 
				
			||||||
         ignore it if it doesn't resize, pick a smaller size (to
 | 
					         ignore it if it doesn't resize, pick a smaller size (to
 | 
				
			||||||
| 
						 | 
					@ -179,6 +183,53 @@
 | 
				
			||||||
    </event>
 | 
					    </event>
 | 
				
			||||||
  </interface>
 | 
					  </interface>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <interface name="selection" version="1">
 | 
				
			||||||
 | 
					    <!-- Add an offered mime type.  Can be called several times to
 | 
				
			||||||
 | 
					         offer multiple types, but must be called before 'activate'. -->
 | 
				
			||||||
 | 
					    <request name="offer">
 | 
				
			||||||
 | 
					      <arg name="type" type="string"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- Can the selection be activated for multiple devices? -->
 | 
				
			||||||
 | 
					    <request name="activate">
 | 
				
			||||||
 | 
					      <arg name="input_device" type="object" interface="input_device"/>
 | 
				
			||||||
 | 
					      <arg name="time" type="uint"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- Destroy the selection. -->
 | 
				
			||||||
 | 
					    <request name="destroy" type="destructor"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- Another client pasted the selection, send the mime-type over
 | 
				
			||||||
 | 
					         the passed fd. -->
 | 
				
			||||||
 | 
					    <event name="send">
 | 
				
			||||||
 | 
					      <arg name="mime_type" type="string"/>
 | 
				
			||||||
 | 
					      <arg name="fd" type="fd"/>
 | 
				
			||||||
 | 
					    </event>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- Another selection became active. -->
 | 
				
			||||||
 | 
					    <event name="cancelled"/>
 | 
				
			||||||
 | 
					  </interface>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <interface name="selection_offer" version="1">
 | 
				
			||||||
 | 
					    <!-- Called to receive the selection data as the specified type.
 | 
				
			||||||
 | 
					         Sends the pipe fd to the compositor, which forwards it to the
 | 
				
			||||||
 | 
					         source in the 'send' event -->
 | 
				
			||||||
 | 
					    <request name="receive">
 | 
				
			||||||
 | 
					      <arg name="mime_type" type="string"/>
 | 
				
			||||||
 | 
					      <arg name="fd" type="fd"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- Sent before the keyboard_focus event to announce the types
 | 
				
			||||||
 | 
					         offered.  One event per offered mime type.  A mime type of
 | 
				
			||||||
 | 
					         NULL means the selection offer is going away.  -->
 | 
				
			||||||
 | 
					    <event name="offer">
 | 
				
			||||||
 | 
					      <arg name="type" type="string"/>
 | 
				
			||||||
 | 
					    </event>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <event name="keyboard_focus">
 | 
				
			||||||
 | 
					      <arg name="input_device" type="object" interface="input_device"/>
 | 
				
			||||||
 | 
					    </event>
 | 
				
			||||||
 | 
					  </interface>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <interface name="drag" version="1">
 | 
					  <interface name="drag" version="1">
 | 
				
			||||||
    <!-- Add an offered mime type.  Can be called several times to
 | 
					    <!-- Add an offered mime type.  Can be called several times to
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -188,6 +188,21 @@ struct wl_drag {
 | 
				
			||||||
	struct wl_listener drag_focus_listener;
 | 
						struct wl_listener drag_focus_listener;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wl_selection_offer {
 | 
				
			||||||
 | 
						struct wl_object object;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wl_selection {
 | 
				
			||||||
 | 
						struct wl_resource resource;
 | 
				
			||||||
 | 
						struct wl_client *client;
 | 
				
			||||||
 | 
						struct wl_input_device *input_device;
 | 
				
			||||||
 | 
						struct wl_selection_offer selection_offer;
 | 
				
			||||||
 | 
						struct wl_surface *selection_focus;
 | 
				
			||||||
 | 
						struct wl_client *target;
 | 
				
			||||||
 | 
						struct wl_array types;
 | 
				
			||||||
 | 
						struct wl_listener selection_focus_listener;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
wl_client_post_event(struct wl_client *client,
 | 
					wl_client_post_event(struct wl_client *client,
 | 
				
			||||||
		      struct wl_object *sender,
 | 
							      struct wl_object *sender,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue