First step towards drag and drop protocol
diff --git a/TODO b/TODO
index 820288a..5cb6ab4 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,7 @@
 Core wayland protocol
 
- - generate pointer_focus on raise/lower, move windows, all kinds of
-   changes in surface stacking.
+ - generate pointer_focus (and drag focus) on raise/lower, move
+   windows, all kinds of changes in surface stacking.
 
  - glyph cache
 
@@ -9,10 +9,53 @@
    pass an fd through the compositor to the other client and let them
    sort it out?
 
+ - DnD issues:
+
+   How to roboustly handle failing drag, ie the case where an
+   application gets a button event, tries to activate a drag, but when
+   the server gets the drag request, the button has already been
+   released and the grab is no longer active.  What's the concern:
+
+    - Application may set a drag cursor that doesn't revert back,
+      since a failed drag doesn't result in a pointer_focus event to
+      give focus back to the surface.  We could just do that: if the
+      pointer_focus is the same surface as we tried to start a grab
+      for, just remove and give back pointer_focus.
+
+      Alternatively, set drag cursors only in response to drag events,
+      like drag focus.  But drag_focus and drag_motion are sent to the
+      drag target, so the source surface won't always get those.  We
+      may also end up setting the cursor after the drag ends, but in
+      this case the drag started and ended and we'll get a
+      pointer_focus event, which will make the application reset the
+      pointer image.  Could introduce a drag start event that
+      indicates that the drag active.
+
+   How to handle drop decline (accept with type=NULL)
+
+    - Targets must send a NULL type in accept if they don't accept a
+      drop at the drag_focus/drag_motion position.  Root window will
+      send a NULL type or x-wayland/root-something type if the source
+      offers that.
+
+   Races between pointer motion, ending the drag, the target sending
+   accept request and the source receiving the target event.
+
+    - We've sent a drag focus or motion event to the source, but
+      haven't received an accept request corresponding to that event
+      and now the button is release.  The compositor could wait for
+      the source to reply to outstanding focus/motion events before
+      sending the finish event to the source.  Or we could send the
+      finish event through the source so that it needs to reply to the
+      finish event too.  Either way, the state of the drag blocks on
+      the client.  What if we drag to a client that doesn't doo dnd?
+
  - copy-n-paste, store data in server (only one mime-type available)
    or do X style (content mime-type negotiation, but data goes away
    when client quits).
 
+ - Optional pointer images.
+
  - Discard buffer, as in "wayland discarded your buffer, it's no
    longer visible, you can stop updating it now.", reattach, as in "oh
    hey, I'm about to show your buffer that I threw away, what was it
diff --git a/compositor.c b/compositor.c
index 5a2bada..93aad96 100644
--- a/compositor.c
+++ b/compositor.c
@@ -239,15 +239,17 @@
 	image_attribs[1] = width;
 	image_attribs[3] = height;
 	count = ARRAY_LENGTH(pointer_images);
-	ec->pointer_images = malloc(count * sizeof *ec->pointer_images);
+	ec->pointer_buffers = malloc(count * sizeof *ec->pointer_buffers);
 	for (i = 0; i < count; i++) {
-		ec->pointer_images[i] =
+		ec->pointer_buffers[i].image =
 			eglCreateDRMImageMESA(ec->display, image_attribs);
 		glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
-					     ec->pointer_images[i]);
+					     ec->pointer_buffers[i].image);
 		texture_from_png(pointer_images[i].filename, width, height);
+		ec->pointer_buffers[i].visual = &ec->argb_visual;
+		ec->pointer_buffers[i].width = width;
+		ec->pointer_buffers[i].height = height;
 	}
-
 }
 
 static struct wlsc_surface *
@@ -457,29 +459,43 @@
 };
 
 static void
-wlsc_input_device_set_pointer_image(struct wlsc_input_device *device,
-				    enum wlsc_pointer_type type)
+wlsc_input_device_attach(struct wlsc_input_device *device,
+			 struct wlsc_buffer *buffer, int x, int y)
 {
 	struct wlsc_compositor *ec = device->ec;
 
 	glBindTexture(GL_TEXTURE_2D, device->sprite->texture);
-	glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, ec->pointer_images[type]);
-	device->sprite->visual = &ec->argb_visual;
-	device->hotspot_x = pointer_images[type].hotspot_x;
-	device->hotspot_y = pointer_images[type].hotspot_y;
+	glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, buffer->image);
+	device->sprite->visual = buffer->visual;
+	device->hotspot_x = x;
+	device->hotspot_y = y;
 
 	device->sprite->x = device->x - device->hotspot_x;
 	device->sprite->y = device->y - device->hotspot_y;
+	device->sprite->width = buffer->width;
+	device->sprite->height = buffer->height;
 	wlsc_surface_update_matrix(device->sprite);
 
 	wlsc_compositor_schedule_repaint(ec);
 }
 
+
+static void
+wlsc_input_device_set_pointer_image(struct wlsc_input_device *device,
+				    enum wlsc_pointer_type type)
+{
+	struct wlsc_compositor *compositor = device->ec;
+
+	wlsc_input_device_attach(device,
+				 &compositor->pointer_buffers[type],
+				 pointer_images[type].hotspot_x,
+				 pointer_images[type].hotspot_y);
+}
+
 static void
 wlsc_input_device_start_grab(struct wlsc_input_device *device,
 			     uint32_t time,
-			     enum wlsc_grab_type grab,
-			     enum wlsc_pointer_type pointer)
+			     enum wlsc_grab_type grab)
 {
 	device->grab = grab;
 	device->grab_surface = device->pointer_focus;
@@ -491,8 +507,6 @@
 	wlsc_input_device_set_pointer_focus(device,
 					    (struct wlsc_surface *) &wl_grab_surface,
 					    time, 0, 0, 0, 0);
-
-	wlsc_input_device_set_pointer_image(device, pointer);
 }
 
 static void
@@ -507,9 +521,8 @@
 	    &wd->pointer_focus->base != surface)
 		return;
 
-	wlsc_input_device_start_grab(wd, time,
-				     WLSC_DEVICE_GRAB_MOVE,
-				     WLSC_POINTER_DRAGGING);
+	wlsc_input_device_start_grab(wd, time, WLSC_DEVICE_GRAB_MOVE);
+	wlsc_input_device_set_pointer_image(wd, WLSC_POINTER_DRAGGING);
 }
 
 static void
@@ -556,7 +569,8 @@
 		break;
 	}
 
-	wlsc_input_device_start_grab(wd, time, edges, pointer);
+	wlsc_input_device_start_grab(wd, time, edges);
+	wlsc_input_device_set_pointer_image(wd, pointer);
 }
 
 const static struct wl_shell_interface shell_interface = {
@@ -681,6 +695,13 @@
 	return NULL;
 }
 
+static void
+wl_drag_reset(struct wl_drag *drag);
+static void
+wl_drag_set_pointer_focus(struct wl_drag *drag,
+			  struct wlsc_surface *surface, uint32_t time,
+			  int32_t x, int32_t y, int32_t sx, int32_t sy);
+
 void
 notify_motion(struct wlsc_input_device *device, uint32_t time, int x, int y)
 {
@@ -773,6 +794,17 @@
 				      WL_SHELL_CONFIGURE, time, device->grab,
 				      &es->base, sx, sy, width, height);
 		break;
+
+	case WLSC_DEVICE_GRAB_DRAG:
+		es = pick_surface(device, &sx, &sy);
+		wl_drag_set_pointer_focus(&device->drag,
+					  es, time, x, y, sx, sy);
+		if (es)
+			wl_surface_post_event(&es->base, &device->drag.base,
+					      WL_DRAG_MOTION,
+					      time, x, y, sx, sy);
+		break;
+
 	}
 
 	device->sprite->x = device->x - device->hotspot_x;
@@ -785,9 +817,21 @@
 static void
 wlsc_input_device_end_grab(struct wlsc_input_device *device, uint32_t time)
 {
+	struct wl_drag *drag = &device->drag;
 	struct wlsc_surface *es;
 	int32_t sx, sy;
 
+	switch (device->grab) {
+	case WLSC_DEVICE_GRAB_DRAG:
+		wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0);
+		wl_surface_post_event(drag->source, &drag->base,
+				      WL_DRAG_FINISH);
+		wl_drag_reset(drag);
+		break;
+	default:
+		break;
+	}
+
 	device->grab = WLSC_DEVICE_GRAB_NONE;
 	es = pick_surface(device, &sx, &sy);
 	wlsc_input_device_set_pointer_focus(device, es, time,
@@ -836,7 +880,6 @@
 		if (!state &&
 		    device->grab != WLSC_DEVICE_GRAB_NONE &&
 		    device->grab_button == button) {
-			device->grab = WLSC_DEVICE_GRAB_NONE;
 			wlsc_input_device_end_grab(device, time);
 		}
 
@@ -919,17 +962,7 @@
 		return;
 	}
 
-	glBindTexture(GL_TEXTURE_2D, device->sprite->texture);
-	glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, buffer->image);
-	device->sprite->visual = buffer->visual;
-	device->hotspot_x = x;
-	device->hotspot_y = y;
-
-	device->sprite->x = device->x - device->hotspot_x;
-	device->sprite->y = device->y - device->hotspot_y;
-	wlsc_surface_update_matrix(device->sprite);
-
-	wlsc_compositor_schedule_repaint(device->ec);
+	wlsc_input_device_attach(device, buffer, x, y);
 }
 
 const static struct wl_input_device_interface input_device_interface = {
@@ -962,6 +995,194 @@
 		wlsc_input_device_end_grab(device, time);
 }
 
+static void
+wl_drag_set_pointer_focus(struct wl_drag *drag,
+			  struct wlsc_surface *surface, uint32_t time,
+			  int32_t x, int32_t y, int32_t sx, int32_t sy)
+{
+	if (drag->pointer_focus == &surface->base)
+		return;
+
+	if (drag->pointer_focus &&
+	    (!surface || drag->pointer_focus->client != surface->base.client))
+		wl_surface_post_event(drag->pointer_focus,
+				      &drag->base,
+				      WL_DRAG_POINTER_FOCUS,
+				      time, NULL, 0, 0, 0, 0);
+	if (surface)
+		wl_surface_post_event(&surface->base,
+				      &drag->base,
+				      WL_DRAG_POINTER_FOCUS,
+				      time, &surface->base,
+				      x, y, sx, sy);
+
+	drag->pointer_focus = &surface->base;
+}
+
+static void
+wl_drag_reset(struct wl_drag *drag)
+{
+	char **p, **end;
+
+	end = drag->types.data + drag->types.size;
+	for (p = drag->types.data; p < end; p++)
+		free(*p);
+	wl_array_release(&drag->types);
+	wl_array_init(&drag->types);
+
+	drag->source = NULL;
+	drag->target = NULL;
+	drag->time = 0;
+	drag->pointer_focus = NULL;
+}
+
+static void
+drag_prepare(struct wl_client *client,
+	     struct wl_drag *drag, struct wl_surface *surface, uint32_t time,
+	     struct wl_buffer *buffer, int32_t hotspot_x, int32_t hotspot_y)
+{
+	struct wlsc_input_device *device =
+		(struct wlsc_input_device *) drag->input_device;
+
+	if (&device->pointer_focus->base != surface ||
+	    device->grab_time != time)
+		return;
+
+	wl_drag_reset(drag);
+	drag->source = surface;
+	drag->time = time;
+	drag->buffer = buffer;
+	drag->hotspot_x = hotspot_x;
+	drag->hotspot_y = hotspot_y;
+}
+
+static void
+drag_offer(struct wl_client *client, struct wl_drag *drag, const char *type)
+{
+	struct wl_display *display = wl_client_get_display (client);
+	struct wlsc_input_device *device =
+		(struct wlsc_input_device *) drag->input_device;
+	char **p;
+
+	if (drag->source == NULL ||
+	    drag->source->client != client ||
+	    device->grab != WLSC_DEVICE_GRAB_MOTION ||
+	    &device->pointer_focus->base != drag->source ||
+	    device->grab_time != drag->time)
+		return;
+
+	p = wl_array_add(&drag->types, sizeof *p);
+	if (p)
+		*p = strdup(type);
+	if (!p || !*p)
+		wl_client_post_event(client,
+				     (struct wl_object *) display,
+				     WL_DISPLAY_NO_MEMORY);
+}
+
+static void
+drag_activate(struct wl_client *client,
+	      struct wl_drag *drag)
+{
+	struct wlsc_input_device *device =
+		(struct wlsc_input_device *) drag->input_device;
+	struct wlsc_surface *surface;
+	int32_t sx, sy;
+
+	if (drag->source == NULL ||
+	    drag->source->client != client ||
+	    device->grab != WLSC_DEVICE_GRAB_MOTION ||
+	    &device->pointer_focus->base != drag->source ||
+	    device->grab_time != drag->time)
+		return;
+
+	wlsc_input_device_start_grab(device, drag->time,
+				     WLSC_DEVICE_GRAB_DRAG);
+	wlsc_input_device_attach(device, (struct wlsc_buffer *) drag->buffer,
+				 drag->hotspot_x, drag->hotspot_y);
+
+	surface = pick_surface(device, &sx, &sy);
+	wl_drag_set_pointer_focus(&device->drag, surface, drag->time,
+				  device->x, device->y, sx, sy);
+}
+
+static void
+drag_cancel(struct wl_client *client, struct wl_drag *drag)
+{
+	struct wlsc_input_device *device =
+		(struct wlsc_input_device *) drag->input_device;
+
+	if (drag->source == NULL ||
+	    drag->source->client != client ||
+	    device->grab != WLSC_DEVICE_GRAB_DRAG)
+		return;
+
+	wlsc_input_device_end_grab(device, get_time());
+}
+
+static void
+drag_send(struct wl_client *client,
+	  struct wl_drag *drag, struct wl_array *contents)
+{
+	wl_client_post_event(client, &drag->base, WL_DRAG_DROP, contents);
+}
+
+static void
+drag_accept(struct wl_client *client,
+	    struct wl_drag *drag, const char *type)
+{
+	char **p, **end;
+
+	if (drag->pointer_focus->client != client)
+		return;
+
+	/* FIXME: We need a serial number here to correlate the accept
+	 * request with a pointer_focus/motion event. */
+	drag->target = client;
+
+	end = drag->types.data + drag->types.size;
+	for (p = drag->types.data; p < end; p++)
+		if (strcmp(*p, type) == 0)
+		    drag->type = *p;
+
+	wl_surface_post_event(drag->source, &drag->base,
+			      WL_DRAG_TARGET, drag->type);
+}
+
+static const struct wl_drag_interface drag_interface = {
+	drag_prepare,
+	drag_offer,
+	drag_activate,
+	drag_cancel,
+	drag_send,
+	drag_accept
+};
+
+static void
+wl_drag_post_device(struct wl_client *client, struct wl_object *global)
+{
+	struct wl_drag *drag = container_of(global, struct wl_drag, base);
+
+	wl_client_post_event(client, global,
+			     WL_DRAG_DEVICE, drag->input_device);
+}
+
+static void
+wl_drag_init(struct wl_drag *drag,
+	     struct wl_display *display, struct wl_input_device *input_device)
+{
+	drag->base.interface = &wl_drag_interface;
+	drag->base.implementation = (void (**)(void))
+		&drag_interface;
+
+	wl_display_add_object(display, &drag->base);
+	wl_display_add_global(display, &drag->base, wl_drag_post_device);
+
+	drag->source = NULL;
+	wl_array_init(&drag->types);
+	drag->input_device = input_device;
+}
+
 void
 wlsc_input_device_init(struct wlsc_input_device *device,
 		       struct wlsc_compositor *ec)
@@ -972,6 +1193,8 @@
 	wl_display_add_object(ec->wl_display, &device->base.base);
 	wl_display_add_global(ec->wl_display, &device->base.base, NULL);
 
+	wl_drag_init(&device->drag, ec->wl_display, &device->base);
+
 	device->x = 100;
 	device->y = 100;
 	device->ec = ec;
diff --git a/compositor.h b/compositor.h
index 315cb36..44fc1a8 100644
--- a/compositor.h
+++ b/compositor.h
@@ -69,7 +69,8 @@
 	WLSC_DEVICE_GRAB_RESIZE_BOTTOM_RIGHT = 10,
 	WLSC_DEVICE_GRAB_RESIZE_MASK = 15,
 	WLSC_DEVICE_GRAB_MOVE = 16,
-	WLSC_DEVICE_GRAB_MOTION = 17
+	WLSC_DEVICE_GRAB_MOTION = 17,
+	WLSC_DEVICE_GRAB_DRAG = 18
 };
 
 enum wlsc_pointer_type {
@@ -106,6 +107,7 @@
 	int32_t grab_width, grab_height;
 	int32_t grab_dx, grab_dy;
 	uint32_t grab_button;
+	struct wl_drag drag;
 
 	struct wlsc_listener listener;
 };
@@ -118,6 +120,7 @@
 
 struct wlsc_buffer {
 	struct wl_buffer base;
+	int32_t width, height;
 	EGLImageKHR image;
 	struct wl_visual *visual;
 };
@@ -131,7 +134,7 @@
 	EGLContext context;
 	GLuint fbo, vbo;
 	GLuint proj_uniform, tex_uniform;
-	EGLImageKHR *pointer_images;
+	struct wlsc_buffer *pointer_buffers;
 	struct wl_display *wl_display;
 
 	/* We implement the shell interface. */
diff --git a/data/Makefile b/data/Makefile
index 3a44a1b..bc57d23 100644
--- a/data/Makefile
+++ b/data/Makefile
@@ -11,8 +11,8 @@
 	top_left_corner.png			\
 	top_right_corner.png			\
 	top_side.png				\
-	xterm.png
-
+	xterm.png				\
+	hand1.png
 
 all :
 
diff --git a/data/hand1.png b/data/hand1.png
new file mode 100644
index 0000000..c13aa36
--- /dev/null
+++ b/data/hand1.png
Binary files differ
diff --git a/protocol.xml b/protocol.xml
index d8c644c..9abeffa 100644
--- a/protocol.xml
+++ b/protocol.xml
@@ -96,6 +96,94 @@
     </event>
   </interface>
 
+  <interface name="drag" version="1">
+    <request name="prepare">
+      <!-- Start a drag action from given surface and device for the
+	   grab started by the button click at time -->
+      <arg name="surface" type="object" interface="surface"/>
+      <arg name="time" type="uint"/>
+      <arg name="buffer" type="object" interface="buffer"/>
+      <arg name="hotspot_x" type="int"/>
+      <arg name="hotspot_y" type="int"/>
+    </request>
+
+    <!-- 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>
+
+    <request name="activate"/>
+
+    <!-- Cancel the drag. -->
+    <request name="cancel"/>
+
+    <!-- Send the data to the target that accepted the offer -->
+    <request name="send">
+      <arg name="contents" type="array"/>
+    </request>
+
+    <!-- Called by the drag target to accept the offer of the given
+         type -->
+    <request name="accept">
+      <arg name="type" type="string"/>
+    </request>
+
+    <!-- Sent at connect time to announce the association -->
+    <event name="device">
+      <arg name="device" type="object" interface="input_device"/>
+    </event>
+
+    <!-- Similar to device::pointer_focus.  Sent to potential
+	 target surfaces to offer drag data.  If the device
+	 leaves the window, the drag stops or the originator cancels
+	 the drag, this event is sent with the NULL surface. -->
+    <event name="pointer_focus">
+      <arg name="time" type="uint"/>
+      <arg name="surface" type="object" interface="surface"/>
+      <arg name="x" type="int"/>
+      <arg name="y" type="int"/>
+      <arg name="surface_x" type="int"/>
+      <arg name="surface_y" type="int"/>
+    </event>
+
+    <!-- Sent after the pointer_focus event to announce the types
+	 offered.  One event per offered mime type. -->
+    <event name="offer">
+      <arg name="type" type="string"/>
+    </event>
+
+    <!-- Similar to device::motion.  Sent to potential target surfaces
+	 as the drag pointer moves around in the surface. -->
+    <event name="motion">
+      <arg name="time" type="uint"/>
+      <arg name="x" type="int"/>
+      <arg name="y" type="int"/>
+      <arg name="surface_x" type="int"/>
+      <arg name="surface_y" type="int"/>
+    </event>
+
+    <!-- Sent to drag originator in response to pointer_focus and
+         motion events.  If a target does not accept any of the
+         offered types, type is NULL -->
+    <event name="target">
+      <arg name="mime_type" type="string"/>
+    </event>
+
+    <!-- Sent to drag originator when the drag is finished.  It's also
+	 sent in case an originator tries to activate a drag after the
+	 grab was released.  If the originator didn't receive a
+	 'target' event before receiving the 'finish' event, no drag
+	 target was found and the originator should not send data. -->
+    <event name="finish"/>
+
+    <!-- Sent to target, contains dragged data.  Ends transaction on
+	 the target side. -->
+    <event name="drop">
+      <arg name="contents" type="array"/>
+    </event>
+  </interface>
+
   <interface name="surface" version="1">
     <request name="destroy"/>
 
diff --git a/scanner.c b/scanner.c
index 2ce88af..0fa5079 100644
--- a/scanner.c
+++ b/scanner.c
@@ -273,6 +273,22 @@
 		       interface->name,
 		       interface->name);
 
+	printf("static inline void\n"
+	       "wl_%s_set_user_data(struct wl_%s *%s, void *user_data)\n"
+	       "{\n"
+	       "\twl_proxy_set_user_data((struct wl_proxy *) %s, user_data);\n"
+	       "}\n\n",
+	       interface->name, interface->name, interface->name,
+	       interface->name);
+
+	printf("static inline void *\n"
+	       "wl_%s_get_user_data(struct wl_%s *%s)\n"
+	       "{\n"
+	       "\treturn wl_proxy_get_user_data((struct wl_proxy *) %s);\n"
+	       "}\n\n",
+	       interface->name, interface->name, interface->name,
+	       interface->name);
+
 	if (wl_list_empty(message_list))
 		return;
 
@@ -424,7 +440,14 @@
 
 	"extern int\n"
 	"wl_proxy_add_listener(struct wl_proxy *proxy,\n"
-	"\t\t      void (**implementation)(void), void *data);\n\n";
+	"\t\t      void (**implementation)(void), void *data);\n\n"
+
+	"extern void\n"
+	"wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data);\n\n"
+
+	"extern void *\n"
+	"wl_proxy_get_user_data(struct wl_proxy *proxy);\n\n";
+
 
 static void
 emit_header(struct protocol *protocol, int server)
diff --git a/wayland-client.c b/wayland-client.c
index 4435868..c79cc65 100644
--- a/wayland-client.c
+++ b/wayland-client.c
@@ -402,17 +402,13 @@
 }
 
 WL_EXPORT void
-wl_surface_set_user_data(struct wl_surface *surface, void *user_data)
+wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data)
 {
-	struct wl_proxy *proxy = (struct wl_proxy *) surface;
-
 	proxy->user_data = user_data;
 }
 
 WL_EXPORT void *
-wl_surface_get_user_data(struct wl_surface *surface)
+wl_proxy_get_user_data(struct wl_proxy *proxy)
 {
-	struct wl_proxy *proxy = (struct wl_proxy *) surface;
-
 	return proxy->user_data;
 }
diff --git a/wayland-client.h b/wayland-client.h
index 1a49fd7..68e5936 100644
--- a/wayland-client.h
+++ b/wayland-client.h
@@ -62,9 +62,6 @@
 struct wl_visual *
 wl_display_get_rgb_visual(struct wl_display *display);
 
-void wl_surface_set_user_data(struct wl_surface *surface, void *user_data);
-void *wl_surface_get_user_data(struct wl_surface *surface);
-
 #ifdef  __cplusplus
 }
 #endif
diff --git a/wayland-server.c b/wayland-server.c
index fe24f3f..196e67f 100644
--- a/wayland-server.c
+++ b/wayland-server.c
@@ -161,6 +161,12 @@
 	return wl_event_source_fd_update(client->source, mask);
 }
 
+WL_EXPORT struct wl_display *
+wl_client_get_display(struct wl_client *client)
+{
+	return client->display;
+}
+
 static void
 wl_display_post_range(struct wl_display *display, struct wl_client *client)
 {
diff --git a/wayland-server.h b/wayland-server.h
index a871d5a..9b7cef3 100644
--- a/wayland-server.h
+++ b/wayland-server.h
@@ -124,6 +124,22 @@
 	struct wl_object base;
 };
 
+struct wl_drag {
+	struct wl_object base;
+	struct wl_surface *source;
+	struct wl_surface *pointer_focus;
+	struct wl_client *target;
+	int32_t x, y, sx, sy;
+	struct wl_input_device *input_device;
+	struct wl_array types;
+	const char *type;
+	uint32_t time;
+
+	struct wl_buffer *buffer;
+	int32_t hotspot_x;
+	int32_t hotspot_y;
+};
+
 void
 wl_client_post_event(struct wl_client *client,
 		      struct wl_object *sender,
@@ -159,6 +175,9 @@
 wl_client_add_resource(struct wl_client *client,
 		       struct wl_resource *resource);
 
+struct wl_display *
+wl_client_get_display(struct wl_client *client);
+
 void
 wl_resource_destroy(struct wl_resource *resource, struct wl_client *client);