New drag and drop / selection protocol

This commit brings a big change to the DND and copy/paste interfaces.
Most importantly the functionality is now independent of wl_shell.
The wl_shell interface is intended for desktop style UI interaction and
an optional and experimental interface.

The new interface also allows receiving the DND data multiple times or
multiple times during the drag, and the mechanism for offering and receiving
data is now shared between DND and selections.
diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index 7e6392a..51a83ef 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -157,6 +157,115 @@
     <event name="release"/>
   </interface>
 
+
+  <interface name="wl_data_offer" version="1">
+    <!-- Indicate that the client can accept the given mime-type, or
+         NULL for not accepted.  Use for feedback during drag and
+         drop. -->
+    <request name="accept">
+      <arg name="time" type="uint"/>
+      <arg name="type" type="string"/>
+    </request>
+
+    <request name="receive">
+      <arg name="mime_type" type="string"/>
+      <arg name="fd" type="fd"/>
+    </request>
+
+    <request name="destroy" type="destructor"/>
+
+    <!-- Sent immediately after creating the wl_data_offer object.  One
+         event per offered mime type. -->
+    <event name="offer">
+      <arg name="type" type="string"/>
+    </event>
+  </interface>
+
+  <interface name="wl_data_source" version="1">
+    <!-- Add an offered mime type.  Can be called several times to
+         offer multiple types. -->
+    <request name="offer">
+      <arg name="type" type="string"/>
+    </request>
+
+    <!-- Destroy the selection. -->
+    <request name="destroy" type="destructor"/>
+
+    <!-- Sent when a target accepts pointer_focus or 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>
+
+    <!-- Request for data from another client.  Send the data in the
+         specified mime-type over the passed fd, the close it. -->
+    <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="wl_data_device" version="1">
+    <request name="start_drag">
+      <arg name="source" type="object" interface="wl_data_source"/>
+      <arg name="surface" type="object" interface="wl_surface"/>
+      <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>
+
+    <request name="set_selection">
+      <arg name="source" type="object" interface="wl_data_source"/>
+      <arg name="time" type="uint"/>
+    </request>
+
+    <event name="data_offer">
+      <arg name="id" type="new_id" interface="wl_data_offer"/>
+    </event>
+
+    <event name="enter">
+      <arg name="time" type="uint"/>
+      <arg name="surface" type="object" interface="wl_surface"/>
+      <arg name="x" type="int"/>
+      <arg name="y" type="int"/>
+      <arg name="id" type="object" interface="wl_data_offer"/>
+    </event>
+
+    <event name="leave"/>
+
+    <event name="motion">
+      <arg name="time" type="uint"/>
+      <arg name="x" type="int"/>
+      <arg name="y" type="int"/>
+    </event>
+
+    <event name="drop"/>
+
+    <event name="selection">
+      <arg name="id" type="object" interface="wl_data_offer"/>
+    </event>
+  </interface>
+
+  <interface name="wl_data_device_manager" version="1">
+    <request name="create_data_source">
+      <arg name="id" type="new_id" interface="wl_data_source"/>
+    </request>
+
+    <request name="get_data_device">
+      <arg name="id" type="new_id" interface="wl_data_device"/>
+      <arg name="input_device" type="object" interface="wl_input_device"/>
+    </request>
+  </interface>
+
   <interface name="wl_shell" version="1">
     <request name="move">
       <arg name="surface" type="object" interface="wl_surface"/>
@@ -184,14 +293,6 @@
       <arg name="edges" type="uint"/>
     </request>
 
-    <request name="create_drag">
-      <arg name="id" type="new_id" interface="wl_drag"/>
-    </request>
-
-    <request name="create_selection">
-      <arg name="id" type="new_id" interface="wl_selection"/>
-    </request>
-
     <!-- Make the surface visible as a toplevel window. -->
     <request name="set_toplevel">
       <arg name="surface" type="object" interface="wl_surface"/>
@@ -240,145 +341,6 @@
     </event>
   </interface>
 
-  <interface name="wl_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="wl_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="wl_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="wl_input_device"/>
-    </event>
-  </interface>
-
-  <interface name="wl_drag" 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>
-
-    <request name="activate">
-      <arg name="surface" type="object" interface="wl_surface"/>
-      <arg name="input_device" type="object" interface="wl_input_device"/>
-      <arg name="time" type="uint"/>
-    </request>
-
-    <!-- Destroy the drag and cancel the session. -->
-    <request name="destroy" type="destructor"/>
-
-    <!-- Sent when a target accepts pointer_focus or 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 when the drag is finished.  The final mime type is that
-         of the last target event.  If that was NULL, no drag target
-         was valid when the drag finished, fd is undefined and the
-         source should not send data.  The event is also sent in case
-         a drag source tries to activate a drag after the grab was
-         released, in which case mime_type will also be NULL. -->
-    <event name="finish">
-      <arg name="fd" type="fd"/>
-    </event>
-
-    <event name="reject"/>
-  </interface>
-
-
-  <interface name="wl_drag_offer" version="1">
-    <!-- Call to accept the offer of the given type -->
-    <request name="accept">
-      <arg name="time" type="uint"/>
-      <arg name="type" type="string"/>
-    </request>
-
-    <!-- Called to initiate the drag finish sequence.  Sends the pipe
-         fd to the compositor, which forwards it to the source in the
-         'finish' event -->
-    <request name="receive">
-      <arg name="fd" type="fd"/>
-    </request>
-
-    <!-- Called to reject a drop  -->
-    <request name="reject"/>
-
-    <!-- Sent before 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::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, at which point the
-         drag object may no longer be valid. -->
-    <event name="pointer_focus">
-      <arg name="time" type="uint"/>
-      <arg name="surface" type="object" interface="wl_surface"/>
-      <arg name="x" type="int"/>
-      <arg name="y" type="int"/>
-      <arg name="surface_x" type="int"/>
-      <arg name="surface_y" type="int"/>
-    </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 indicate that the drag is finishing.  The last
-         motion/pointer_focus event gives the location of the drop.
-         Target must respond with the 'receive' request, which sends
-         an fd to the source for writing the drag data. -->
-    <event name="drop"/>
-  </interface>
-
 
   <!-- A surface. This is an image that is displayed on the screen.
        It has a location, size and pixel contents. Similar to a window. -->
diff --git a/src/connection.c b/src/connection.c
index 8c9a64d..f19280a 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -449,7 +449,7 @@
 			closure->types[i] = &ffi_type_uint32;
 			closure->args[i] = p;
 			object = va_arg(ap, struct wl_object *);
-			*p++ = object->id;
+			*p++ = object ? object->id : 0;
 			break;
 
 		case 'a':
@@ -493,6 +493,8 @@
 				      &dup_fd, sizeof dup_fd);
 			break;
 		default:
+			fprintf(stderr, "unhandled format code: '%c'\n",
+				message->signature[i - 2]);
 			assert(0);
 			break;
 		}
@@ -632,7 +634,7 @@
 			closure->types[i] = &ffi_type_uint32;
 			closure->args[i] = p;
 			object = wl_map_lookup(objects, *p);
-			if (*p == 0 || object != NULL) {
+			if (object != NULL) {
 				printf("not a new object (%d), "
 				       "message %s(%s)\n",
 				       *p, message->name, message->signature);
diff --git a/src/wayland-client.c b/src/wayland-client.c
index c8bbe8f..939c17d 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -152,8 +152,9 @@
 
 	proxy->object.interface = interface;
 	proxy->object.implementation = NULL;
-	proxy->object.id = wl_map_insert_at(&display->objects, id, proxy);
+	proxy->object.id = id;
 	proxy->display = display;
+	wl_map_insert_at(&display->objects, id, proxy);
 
 	return proxy;
 }
diff --git a/src/wayland-server.c b/src/wayland-server.c
index 4811639..7c93e3f 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -874,3 +874,16 @@
 
 	return resource;
 }
+
+WL_EXPORT struct wl_resource *
+wl_client_new_object(struct wl_client *client,
+		     const struct wl_interface *interface,
+		     const void *implementation, void *data)
+{
+	uint32_t id;
+
+	id = wl_map_insert_new(&client->objects, WL_MAP_SERVER_SIDE, NULL);
+	return wl_client_add_object(client,
+				    interface, implementation, id, data);
+
+}
diff --git a/src/wayland-server.h b/src/wayland-server.h
index 269a079..4de2e83 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -104,6 +104,10 @@
 wl_client_add_object(struct wl_client *client,
 		     const struct wl_interface *interface,
 		     const void *implementation, uint32_t id, void *data);
+struct wl_resource *
+wl_client_new_object(struct wl_client *client,
+		     const struct wl_interface *interface,
+		     const void *implementation, void *data);
 
 struct wl_resource {
 	struct wl_object object;
@@ -176,39 +180,6 @@
 	struct wl_listener grab_listener;
 };
 
-struct wl_drag_offer {
-	struct wl_resource resource;
-};
-
-struct wl_drag {
-	struct wl_resource resource;
-	struct wl_grab grab;
-	struct wl_drag_offer drag_offer;
-	struct wl_surface *source;
-	struct wl_surface *drag_focus;
-	struct wl_client *target;
-	int32_t x, y, sx, sy;
-	struct wl_array types;
-	const char *type;
-	uint32_t pointer_focus_time;
-	struct wl_listener drag_focus_listener;
-};
-
-struct wl_selection_offer {
-	struct wl_resource resource;
-};
-
-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_resource_post_event(struct wl_resource *resource,
 			    uint32_t opcode, ...);
 void wl_resource_queue_event(struct wl_resource *resource,
@@ -217,11 +188,6 @@
 			    uint32_t code, const char *msg, ...);
 void wl_resource_post_no_memory(struct wl_resource *resource);
 
-int
-wl_display_set_compositor(struct wl_display *display,
-			  struct wl_compositor *compositor,
-			  const struct wl_compositor_interface *implementation);
-
 void
 wl_display_post_frame(struct wl_display *display, struct wl_surface *surface,
 		      uint32_t msecs);
@@ -287,11 +253,6 @@
 void
 wl_shm_finish(struct wl_shm *shm);
 
-int
-wl_compositor_init(struct wl_compositor *compositor,
-		   const struct wl_compositor_interface *interface,
-		   struct wl_display *display);
-
 #ifdef  __cplusplus
 }
 #endif