First attempt at selection support

dev
Kristian Høgsberg 14 years ago
parent 4cca349349
commit ae6c8a6d73
  1. 4
      compositor/compositor.c
  2. 5
      compositor/compositor.h
  3. 173
      compositor/shell.c
  4. 51
      protocol/wayland.xml
  5. 15
      wayland/wayland-server.h

@ -682,6 +682,10 @@ notify_button(struct wl_input_device *device,
if (state && device->grab == NULL) {
wlsc_surface_raise(surface);
if (wd->selection)
wlsc_selection_set_focus(wd->selection,
&surface->surface, time);
wl_input_device_start_grab(device,
&device->motion_grab,
button, time);

@ -69,6 +69,7 @@ struct wlsc_input_device {
int32_t hotspot_x, hotspot_y;
struct wl_list link;
uint32_t modifier_state;
struct wl_selection *selection;
};
struct wlsc_drm {
@ -165,6 +166,10 @@ wlsc_input_device_set_pointer_image(struct wlsc_input_device *device,
struct wlsc_surface *
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
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);
}
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
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);
}
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 = {
shell_move,
shell_resize,
shell_create_drag
shell_create_drag,
shell_create_selection
};
int

@ -164,6 +164,10 @@
<arg name="id" type="new_id" interface="drag"/>
</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 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
@ -179,6 +183,53 @@
</event>
</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">
<!-- 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_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
wl_client_post_event(struct wl_client *client,
struct wl_object *sender,

Loading…
Cancel
Save