[PATCH wayland] data_device: use a regular surface for drag icons
Ander Conselvan de Oliveira
ander.conselvan.de.oliveira at intel.com
Fri Feb 10 08:31:34 PST 2012
Change the data_device.attach request to data_device.set_surface. This
request will create a surface that will follow the mouse cursor. Client
provide the surface contests with the regular surface_attach.
Since data_device is implemented in libwayland-server, add a server
hook for the compositor to set the drag icon surface. An alternate
surface implementation in libwayland-server is then used to multiplex
the requests of different clients to the single surface on the
compositor side.
---
protocol/wayland.xml | 18 +++++--
src/data-device.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++---
src/wayland-server.h | 5 ++
3 files changed, 152 insertions(+), 13 deletions(-)
diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index c445d3f..081b0f6 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -282,11 +282,19 @@
<arg name="time" type="uint"/>
</request>
- <request name="attach">
- <arg name="time" type="uint"/>
- <arg name="buffer" type="object" interface="wl_buffer"/>
- <arg name="x" type="int"/>
- <arg name="y" type="int"/>
+ <request name="set_surface">
+ <description summary="create a surface that follows the cursor">
+ Create a surface that will follow the cursor during a drag.
+ The distance between the top-left corner of this surface and
+ the cursor's hotspot is maintained on mouse movement. Initially
+ this distance is set by parameters x and y.
+
+ This surface should be destroyed with surface.destroy.
+ </description>
+
+ <arg name="id" type="new_id" interface="wl_surface" />
+ <arg name="x" type="int" />
+ <arg name="y" type="int" />
</request>
<request name="set_selection">
diff --git a/src/data-device.c b/src/data-device.c
index 95b1a9d..1248267 100644
--- a/src/data-device.c
+++ b/src/data-device.c
@@ -232,6 +232,9 @@ drag_grab_button(struct wl_grab *grab,
{
struct wl_input_device *device =
container_of(grab, struct wl_input_device, drag_grab);
+ struct wl_resource *surface_resource;
+ struct wl_surface_interface *interface;
+ struct wl_client *client;
if (device->drag_focus_resource &&
device->grab_button == button && state == 0)
@@ -239,8 +242,15 @@ drag_grab_button(struct wl_grab *grab,
WL_DATA_DEVICE_DROP);
if (device->button_count == 0 && state == 0) {
+ client = device->drag_data_source->resource.client;
+
wl_input_device_end_grab(device, time);
device->drag_data_source = NULL;
+
+ surface_resource = &device->drag_surface->resource;
+ interface = (struct wl_surface_interface *)
+ surface_resource->object.implementation;
+ interface->attach(client, surface_resource, NULL, 0, 0);
}
}
@@ -269,13 +279,6 @@ data_device_start_drag(struct wl_client *client, struct wl_resource *resource,
}
static void
-data_device_attach(struct wl_client *client, struct wl_resource *resource,
- uint32_t time,
- struct wl_resource *buffer, int32_t x, int32_t y)
-{
-}
-
-static void
destroy_selection_data_source(struct wl_listener *listener,
struct wl_resource *resource, uint32_t time)
{
@@ -333,6 +336,45 @@ wl_input_device_set_selection(struct wl_input_device *device,
&device->selection_data_source_listener.link);
}
+static const struct wl_surface_interface drag_surface_interface;
+
+struct data_device_drag_surface {
+ struct wl_surface surface;
+ struct wl_resource resource;
+ struct wl_input_device *device;
+};
+
+static void
+data_device_set_surface(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id, int32_t x, int32_t y)
+{
+ struct wl_input_device *device = resource->data;
+ struct data_device_drag_surface *surface;
+
+ surface = malloc(sizeof *surface);
+ if (!surface) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ surface->resource.object.id = id;
+ surface->resource.object.interface = &wl_surface_interface;
+ surface->resource.object.implementation = (void (**)(void))
+ &drag_surface_interface;
+
+ surface->resource.data = surface;
+ surface->resource.client = client;
+ surface->resource.destroy = NULL;
+
+ surface->device = device;
+
+ device->drag_icon_x = x;
+ device->drag_icon_y = y;
+
+ wl_client_add_resource(client, &surface->resource);
+}
+
static void
data_device_set_selection(struct wl_client *client,
struct wl_resource *resource,
@@ -347,11 +389,88 @@ data_device_set_selection(struct wl_client *client,
static const struct wl_data_device_interface data_device_interface = {
data_device_start_drag,
- data_device_attach,
+ data_device_set_surface,
data_device_set_selection,
};
static void
+drag_surface_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+ struct data_device_drag_surface *surface = resource->data;
+
+ wl_resource_destroy(resource, 0);
+ free(surface);
+}
+
+static void
+drag_surface_attach(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *buffer_resource, int32_t sx, int32_t sy)
+{
+ struct data_device_drag_surface *surface = resource->data;
+ struct wl_input_device *device = surface->device;
+ struct wl_resource *drag_surface_resource;
+ struct wl_surface_interface *surface_interface;
+
+ if (!device->drag_surface || !device->drag_data_source)
+ return;
+
+ drag_surface_resource = &device->drag_surface->resource;
+ surface_interface = (struct wl_surface_interface *)
+ drag_surface_resource->object.implementation;
+
+ surface_interface->attach(client, drag_surface_resource,
+ buffer_resource, sx, sy);
+}
+
+static void
+drag_surface_damage(struct wl_client *client,
+ struct wl_resource *resource,
+ int32_t x, int32_t y, int32_t width, int32_t height)
+{
+ struct data_device_drag_surface *surface = resource->data;
+ struct wl_input_device *device = surface->device;
+ struct wl_resource *drag_surface_resource;
+ struct wl_surface_interface *surface_interface;
+
+ if (!device->drag_surface || !device->drag_data_source)
+ return;
+
+ drag_surface_resource = &device->drag_surface->resource;
+ surface_interface = (struct wl_surface_interface *)
+ drag_surface_resource->object.implementation;
+
+ surface_interface->damage(client, drag_surface_resource,
+ x, y, width, height);
+}
+
+static void
+drag_surface_frame(struct wl_client *client,
+ struct wl_resource *resource, uint32_t callback)
+{
+ struct data_device_drag_surface *surface = resource->data;
+ struct wl_input_device *device = surface->device;
+ struct wl_resource *drag_surface_resource;
+ struct wl_surface_interface *surface_interface;
+
+ if (!device->drag_surface || !device->drag_data_source)
+ return;
+
+ drag_surface_resource = &device->drag_surface->resource;
+ surface_interface = (struct wl_surface_interface *)
+ drag_surface_resource->object.implementation;
+
+ surface_interface->frame(client, drag_surface_resource, callback);
+}
+
+static const struct wl_surface_interface drag_surface_interface = {
+ drag_surface_destroy,
+ drag_surface_attach,
+ drag_surface_damage,
+ drag_surface_frame
+};
+
+static void
destroy_data_source(struct wl_resource *resource)
{
struct wl_data_source *source =
@@ -452,6 +571,13 @@ wl_data_device_set_keyboard_focus(struct wl_input_device *device)
}
}
+WL_EXPORT void
+wl_data_device_set_drag_surface(struct wl_input_device *device,
+ struct wl_surface *surface)
+{
+ device->drag_surface = surface;
+}
+
WL_EXPORT int
wl_data_device_manager_init(struct wl_display *display)
{
diff --git a/src/wayland-server.h b/src/wayland-server.h
index 53f918c..e965b2f 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -212,6 +212,8 @@ struct wl_input_device {
struct wl_resource *drag_focus_resource;
struct wl_listener drag_focus_listener;
struct wl_grab drag_grab;
+ struct wl_surface *drag_surface;
+ int32_t drag_icon_x, drag_icon_y;
struct wl_data_source *selection_data_source;
struct wl_listener selection_data_source_listener;
@@ -277,6 +279,9 @@ wl_input_device_set_keyboard_focus(struct wl_input_device *device,
uint32_t time);
void
wl_data_device_set_keyboard_focus(struct wl_input_device *device);
+void
+wl_data_device_set_drag_surface(struct wl_input_device *device,
+ struct wl_surface *surface);
int
wl_data_device_manager_init(struct wl_display *display);
--
1.7.4.1
More information about the wayland-devel
mailing list