diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index a9f96b6..be4bc77 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -4,6 +4,12 @@
   <!-- The core global object. This is a special singleton object.
        It is used for internal wayland protocol features. -->
   <interface name="display" version="1">
+    <request name="bind">
+      <arg name="global_id" type="uint"/>
+      <arg name="version" type="uint"/>
+      <arg name="id" type="new_id" interface="object"/>
+    </request>
+
     <!-- sync is an just an echo, which will reply with a sync event.
          Since requests are handled in-order, this can be used as a
          barrier to ensure all previous requests have ben handled.
@@ -49,15 +55,6 @@
       <arg name="version" type="uint"/>
     </event>
 
-    <!-- Internal, deprecated, and will be changed.  This is an object
-         IDs range that is used by the client to allocate object IDs
-         in "new_id" type arguments.  The server sends range
-         allocations to the client before the next range is about to
-         be depleted. -->
-    <event name="range">
-      <arg name="base" type="uint"/>
-    </event>
-
     <!-- A reply to the frame or sync request.  The key is the one
          used in the request.  time is in millisecond units, and
          denotes the time when the frame was posted on the
diff --git a/wayland/connection.c b/wayland/connection.c
index 4a00470..bbb6162 100644
--- a/wayland/connection.c
+++ b/wayland/connection.c
@@ -62,6 +62,8 @@ struct wl_connection {
 	void *data;
 	wl_connection_update_func_t update;
 	struct wl_closure receive_closure, send_closure;
+	struct wl_hash_table *objects;
+	uint32_t id;
 };
 
 union wl_value {
@@ -169,6 +171,9 @@ wl_connection_create(int fd,
 			   WL_CONNECTION_READABLE,
 			   connection->data);
 
+	connection->objects = wl_hash_table_create();
+	connection->id = 1;
+
 	return connection;
 }
 
@@ -191,6 +196,26 @@ wl_connection_consume(struct wl_connection *connection, size_t size)
 	connection->in.tail += size;
 }
 
+void
+wl_connection_add_object(struct wl_connection *connection,
+			 struct wl_object *object)
+{
+	wl_hash_table_insert(connection->objects, connection->id++, object);
+}
+
+void
+wl_connection_remove_object(struct wl_connection *connection,
+			    struct wl_object *object)
+{
+	wl_hash_table_remove(connection->objects, object->id);
+}
+
+struct wl_object *
+wl_connection_lookup_object(struct wl_connection *connection, uint32_t id)
+{
+	return wl_hash_table_lookup(connection->objects, id);
+}
+
 static void
 build_cmsg(struct wl_buffer *buffer, char *data, int *clen)
 {
@@ -485,9 +510,7 @@ wl_connection_vmarshal(struct wl_connection *connection,
 
 struct wl_closure *
 wl_connection_demarshal(struct wl_connection *connection,
-			uint32_t size,
-			struct wl_hash_table *objects,
-			const struct wl_message *message)
+			uint32_t size, const struct wl_message *message)
 {
 	uint32_t *p, *next, *end, length;
 	int *fd;
@@ -573,7 +596,8 @@ wl_connection_demarshal(struct wl_connection *connection,
 			extra += sizeof *object;
 			closure->args[i] = object;
 
-			*object = wl_hash_table_lookup(objects, *p);
+			*object =
+				wl_hash_table_lookup(connection->objects, *p);
 			if (*object == NULL && *p != 0) {
 				printf("unknown object (%d), message %s(%s)\n",
 				       *p, message->name, message->signature);
@@ -586,7 +610,7 @@ wl_connection_demarshal(struct wl_connection *connection,
 		case 'n':
 			closure->types[i] = &ffi_type_uint32;
 			closure->args[i] = p;
-			object = wl_hash_table_lookup(objects, *p);
+			object = wl_hash_table_lookup(connection->objects, *p);
 			if (object != NULL) {
 				printf("not a new object (%d), "
 				       "message %s(%s)\n",
diff --git a/wayland/connection.h b/wayland/connection.h
index 413977d..1e265ad 100644
--- a/wayland/connection.h
+++ b/wayland/connection.h
@@ -44,6 +44,13 @@ void wl_connection_consume(struct wl_connection *connection, size_t size);
 int wl_connection_data(struct wl_connection *connection, uint32_t mask);
 void wl_connection_write(struct wl_connection *connection, const void *data, size_t count);
 
+void wl_connection_add_object(struct wl_connection *connection,
+			      struct wl_object *object);
+void wl_connection_remove_object(struct wl_connection *connection,
+				 struct wl_object *object);
+struct wl_object *wl_connection_lookup_object(struct wl_connection *connection,
+					      uint32_t id);
+
 struct wl_closure *
 wl_connection_vmarshal(struct wl_connection *connection,
 		       struct wl_object *sender,
@@ -52,9 +59,7 @@ wl_connection_vmarshal(struct wl_connection *connection,
 
 struct wl_closure *
 wl_connection_demarshal(struct wl_connection *connection,
-			uint32_t size,
-			struct wl_hash_table *objects,
-			const struct wl_message *message);
+			uint32_t size, const struct wl_message *message);
 void
 wl_closure_invoke(struct wl_closure *closure,
 		  struct wl_object *target, void (*func)(void), void *data);
diff --git a/wayland/scanner.c b/wayland/scanner.c
index 43e6fa3..f915f13 100644
--- a/wayland/scanner.c
+++ b/wayland/scanner.c
@@ -327,10 +327,10 @@ emit_stubs(struct wl_list *message_list, struct interface *interface)
 	/* We provide a hand written constructor for the display object */
 	if (strcmp(interface->name, "display") != 0)
 		printf("static inline struct wl_%s *\n"
-		       "wl_%s_create(struct wl_display *display, uint32_t id)\n"
+		       "wl_%s_create(struct wl_display *display, uint32_t id, uint32_t version)\n"
 		       "{\n"
 		       "\treturn (struct wl_%s *)\n"
-		       "\t\twl_proxy_create_for_id(display, &wl_%s_interface, id);\n"
+		       "\t\twl_proxy_create_for_id(display, &wl_%s_interface, id, version);\n"
 		       "}\n\n",
 		       interface->name,
 		       interface->name,
@@ -543,34 +543,6 @@ emit_structs(struct wl_list *message_list, struct interface *interface)
 	}
 }
 
-static const char client_prototypes[] =
-	"struct wl_proxy;\n\n"
-
-	"extern void\n"
-	"wl_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...);\n"
-
-	"extern struct wl_proxy *\n"
-	"wl_proxy_create(struct wl_proxy *factory,\n"
-	"\t\tconst struct wl_interface *interface);\n"
-
-	"extern struct wl_proxy *\n"
-	"wl_proxy_create_for_id(struct wl_display *display,\n"
-	"\t\t       const struct wl_interface *interface, uint32_t id);\n"
-
-	"extern void\n"
-	"wl_proxy_destroy(struct wl_proxy *proxy);\n\n"
-
-	"extern int\n"
-	"wl_proxy_add_listener(struct wl_proxy *proxy,\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)
 {
@@ -593,12 +565,13 @@ emit_header(struct protocol *protocol, int server)
 	       protocol->uppercase_name, s,
 	       protocol->uppercase_name, s);
 
+	if (!server)
+		printf("#include <wayland-client.h>\n");
+
 	wl_list_for_each(i, &protocol->interface_list, link)
 		printf("struct wl_%s;\n", i->name);
 	printf("\n");
 
-	if (!server)
-		printf(client_prototypes);
 
 	wl_list_for_each(i, &protocol->interface_list, link) {
 		printf("extern const struct wl_interface "
diff --git a/wayland/wayland-client.c b/wayland/wayland-client.c
index ad35c30..cf7beaf 100644
--- a/wayland/wayland-client.c
+++ b/wayland/wayland-client.c
@@ -44,12 +44,6 @@ struct wl_global_listener {
 	struct wl_list link;
 };
 
-struct wl_proxy {
-	struct wl_object object;
-	struct wl_display *display;
-	void *user_data;
-};
-
 struct wl_sync_handler {
 	wl_display_sync_func_t func;
 	uint32_t key;
@@ -70,7 +64,6 @@ struct wl_display {
 	int fd;
 	uint32_t id, id_count, next_range;
 	uint32_t mask;
-	struct wl_hash_table *objects;
 	struct wl_list global_listener_list;
 
 	struct wl_visual *argb_visual;
@@ -129,8 +122,8 @@ wl_display_remove_global_listener(struct wl_display *display,
 }
 
 WL_EXPORT struct wl_proxy *
-wl_proxy_create_for_id(struct wl_display *display,
-		       const struct wl_interface *interface, uint32_t id)
+wl_proxy_create(struct wl_proxy *factory,
+		const struct wl_interface *interface)
 {
 	struct wl_proxy *proxy;
 
@@ -140,25 +133,33 @@ wl_proxy_create_for_id(struct wl_display *display,
 
 	proxy->object.interface = interface;
 	proxy->object.implementation = NULL;
-	proxy->object.id = id;
-	proxy->display = display;
-	wl_hash_table_insert(display->objects, proxy->object.id, proxy);
+	proxy->connection = factory->connection;
+	wl_connection_add_object(factory->connection, &proxy->object);
 
 	return proxy;
 }
 
 WL_EXPORT struct wl_proxy *
-wl_proxy_create(struct wl_proxy *factory,
-		const struct wl_interface *interface)
+wl_proxy_create_for_id(struct wl_display *display,
+		       const struct wl_interface *interface,
+		       uint32_t id, uint32_t version)
 {
-	return wl_proxy_create_for_id(factory->display, interface,
-				      wl_display_allocate_id(factory->display));
+	struct wl_proxy *proxy;
+
+	proxy = wl_proxy_create(&display->proxy, interface);
+	if (proxy == NULL)
+		return NULL;
+
+	wl_proxy_marshal((struct wl_proxy *) display,
+			 WL_DISPLAY_BIND, id, version, proxy->object.id);
+
+	return proxy;
 }
 
 WL_EXPORT void
 wl_proxy_destroy(struct wl_proxy *proxy)
 {
-	wl_hash_table_remove(proxy->display->objects, proxy->object.id);
+	wl_connection_remove_object(proxy->connection, &proxy->object);
 	free(proxy);
 }
 
@@ -184,12 +185,12 @@ wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
 	va_list ap;
 
 	va_start(ap, opcode);
-	closure = wl_connection_vmarshal(proxy->display->connection,
+	closure = wl_connection_vmarshal(proxy->connection,
 					 &proxy->object, opcode, ap,
 					 &proxy->object.interface->methods[opcode]);
 	va_end(ap);
 
-	wl_closure_send(closure, proxy->display->connection);
+	wl_closure_send(closure, proxy->connection);
 
 	if (wl_debug) {
 		fprintf(stderr, " -> ");
@@ -205,7 +206,7 @@ add_visual(struct wl_display *display, uint32_t id)
 	struct wl_visual *visual;
 
 	visual = (struct wl_visual *)
-		wl_proxy_create_for_id(display, &wl_visual_interface, id);
+		wl_proxy_create_for_id(display, &wl_visual_interface, id, 1);
 	if (display->argb_visual == NULL)
 		display->argb_visual = visual;
 	else if (display->premultiplied_argb_visual == NULL)
@@ -239,7 +240,7 @@ display_handle_invalid_object(void *data,
 	fprintf(stderr, "sent request to invalid object\n");
 	abort();
 }
-			      
+
 static void
 display_handle_invalid_method(void *data, 
 			      struct wl_display *display,
@@ -265,8 +266,7 @@ display_handle_global(void *data,
 	struct wl_global_listener *listener;
 
 	if (strcmp(interface, "display") == 0)
-		wl_hash_table_insert(display->objects,
-				     id, &display->proxy.object);
+		return;
 	else if (strcmp(interface, "visual") == 0)
 		add_visual(display, id);
 
@@ -276,13 +276,6 @@ display_handle_global(void *data,
 }
 
 static void
-display_handle_range(void *data,
-		     struct wl_display *display, uint32_t range)
-{
-	display->next_range = range;
-}
-
-static void
 display_handle_key(void *data,
 		   struct wl_display *display, uint32_t key, uint32_t time)
 {
@@ -316,7 +309,6 @@ static const struct wl_display_listener display_listener = {
 	display_handle_invalid_method,
 	display_handle_no_memory,
 	display_handle_global,
-	display_handle_range,
 	display_handle_key
 };
 
@@ -372,23 +364,20 @@ wl_display_connect(const char *name)
 		return NULL;
 	}
 
-	display->objects = wl_hash_table_create();
 	wl_list_init(&display->global_listener_list);
 
-	display->proxy.object.interface = &wl_display_interface;
-	display->proxy.object.id = 1;
-	display->proxy.display = display;
-
 	wl_list_init(&display->sync_list);
 	wl_list_init(&display->frame_list);
 
+	display->connection =
+		wl_connection_create(display->fd, connection_update, display);
+
+	display->proxy.object.interface = &wl_display_interface;
 	display->proxy.object.implementation =
 		(void(**)(void)) &display_listener;
 	display->proxy.user_data = display;
-
-	display->connection = wl_connection_create(display->fd,
-						   connection_update,
-						   display);
+	display->proxy.connection = display->connection;
+	wl_connection_add_object(display->connection, &display->proxy.object);
 
 	return display;
 }
@@ -463,10 +452,8 @@ handle_event(struct wl_display *display,
 	const struct wl_message *message;
 
 	wl_connection_copy(display->connection, p, size);
-	if (id == 1)
-		proxy = &display->proxy;
-	else
-		proxy = wl_hash_table_lookup(display->objects, id);
+	proxy = (struct wl_proxy *)
+		wl_connection_lookup_object(display->connection, id);
 
 	if (proxy == NULL || proxy->object.implementation == NULL) {
 		wl_connection_consume(display->connection, size);
@@ -474,8 +461,7 @@ handle_event(struct wl_display *display,
 	}
 
 	message = &proxy->object.interface->events[opcode];
-	closure = wl_connection_demarshal(display->connection,
-					  size, display->objects, message);
+	closure = wl_connection_demarshal(display->connection, size, message);
 
 	if (wl_debug)
 		wl_closure_print(closure, &proxy->object);
@@ -522,19 +508,6 @@ wl_display_iterate(struct wl_display *display, uint32_t mask)
 	}
 }
 
-WL_EXPORT uint32_t
-wl_display_allocate_id(struct wl_display *display)
-{
-	if (display->id_count == 0) {
-		display->id_count = 256;
-		display->id = display->next_range;
-	}
-
-	display->id_count--;
-
-	return display->id++;
-}
-
 WL_EXPORT void
 wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data)
 {
diff --git a/wayland/wayland-client.h b/wayland/wayland-client.h
index d207b07..1f4cb85 100644
--- a/wayland/wayland-client.h
+++ b/wayland/wayland-client.h
@@ -33,6 +33,21 @@ extern "C" {
 #define WL_DISPLAY_READABLE 0x01
 #define WL_DISPLAY_WRITABLE 0x02
 
+	struct wl_display;
+struct wl_proxy;
+
+void wl_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...);
+struct wl_proxy *wl_proxy_create(struct wl_proxy *factory,
+				 const struct wl_interface *interface);
+struct wl_proxy *wl_proxy_create_for_id(struct wl_display *display,
+					const struct wl_interface *interface,
+					uint32_t id, uint32_t version);
+void wl_proxy_destroy(struct wl_proxy *proxy);
+int wl_proxy_add_listener(struct wl_proxy *proxy,
+			  void (**implementation)(void), void *data);
+void wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data);
+void *wl_proxy_get_user_data(struct wl_proxy *proxy);
+
 typedef int (*wl_display_update_func_t)(uint32_t mask, void *data);
 typedef void (*wl_display_sync_func_t)(void *data);
 typedef void (*wl_display_frame_func_t)(void *data, uint32_t time);
diff --git a/wayland/wayland-hash.c b/wayland/wayland-hash.c
index b299a33..9c406c5 100644
--- a/wayland/wayland-hash.c
+++ b/wayland/wayland-hash.c
@@ -198,6 +198,22 @@ wl_hash_table_lookup(struct wl_hash_table *ht, uint32_t hash)
 	return NULL;
 }
 
+WL_EXPORT int
+wl_hash_table_index(struct wl_hash_table *ht, int index, void **data)
+{
+	struct hash_entry *entry = ht->table + index;
+
+	if (index >= ht->size)
+		return 0;
+
+	if (entry_is_present(entry))
+		*data = entry->data;
+	else
+		*data = NULL;
+
+	return 1;
+}
+
 static void
 hash_table_rehash(struct wl_hash_table *ht, int new_size_index)
 {
diff --git a/wayland/wayland-server.c b/wayland/wayland-server.c
index dece0d1..53d6a89 100644
--- a/wayland/wayland-server.c
+++ b/wayland/wayland-server.c
@@ -54,9 +54,9 @@ struct wl_client {
 };
 
 struct wl_display {
-	struct wl_object object;
+	struct wl_global global;
 	struct wl_event_loop *loop;
-	struct wl_hash_table *objects;
+	struct wl_hash_table *globals;
 	int run;
 
 	struct wl_list frame_list;
@@ -74,12 +74,6 @@ struct wl_frame_listener {
 	struct wl_list link;
 };
 
-struct wl_global {
-	struct wl_object *object;
-	wl_client_connect_func_t func;
-	struct wl_list link;
-};
-
 static int wl_debug = 0;
 
 WL_EXPORT void
@@ -135,9 +129,9 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
 		if (len < size)
 			break;
 
-		object = wl_hash_table_lookup(client->display->objects, p[0]);
+		object = wl_connection_lookup_object(client->connection, p[0]);
 		if (object == NULL) {
-			wl_client_post_event(client, &client->display->object,
+			wl_client_post_event(client, &client->display->global.object,
 					     WL_DISPLAY_INVALID_OBJECT, p[0]);
 			wl_connection_consume(connection, size);
 			len -= size;
@@ -145,7 +139,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
 		}
 
 		if (opcode >= object->interface->method_count) {
-			wl_client_post_event(client, &client->display->object,
+			wl_client_post_event(client, &client->display->global.object,
 					     WL_DISPLAY_INVALID_METHOD, p[0], opcode);
 			wl_connection_consume(connection, size);
 			len -= size;
@@ -153,13 +147,12 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
 		}
 
 		message = &object->interface->methods[opcode];
-		closure = wl_connection_demarshal(client->connection, size,
-						  client->display->objects,
-						  message);
+		closure = wl_connection_demarshal(client->connection,
+						  size, message);
 		len -= size;
 
 		if (closure == NULL && errno == EINVAL) {
-			wl_client_post_event(client, &client->display->object,
+			wl_client_post_event(client, &client->display->global.object,
 					     WL_DISPLAY_INVALID_METHOD,
 					     p[0], opcode);
 			continue;
@@ -200,20 +193,12 @@ 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)
-{
-	wl_client_post_event(client, &client->display->object,
-			     WL_DISPLAY_RANGE, display->client_id_range);
-	display->client_id_range += 256;
-	client->id_count += 256;
-}
-
 static struct wl_client *
 wl_client_create(struct wl_display *display, int fd)
 {
 	struct wl_client *client;
 	struct wl_global *global;
+	int i;
 
 	client = malloc(sizeof *client);
 	if (client == NULL)
@@ -229,18 +214,8 @@ wl_client_create(struct wl_display *display, int fd)
 
 	wl_list_init(&client->resource_list);
 
-	wl_display_post_range(display, client);
-
-	wl_list_for_each(global, &display->global_list, link)
-		wl_client_post_event(client, &client->display->object,
-				     WL_DISPLAY_GLOBAL,
-				     global->object,
-				     global->object->interface->name,
-				     global->object->interface->version);
-
-	wl_list_for_each(global, &display->global_list, link)
-		if (global->func)
-			global->func(client, global->object);
+	for (i = 0; wl_hash_table_index(display->globals, i, (void **) &global); i++)
+		wl_client_post_global(client, global);
 
 	return client;
 }
@@ -249,13 +224,7 @@ WL_EXPORT void
 wl_client_add_resource(struct wl_client *client,
 		       struct wl_resource *resource)
 {
-	struct wl_display *display = client->display;
-
-	if (client->id_count-- < 64)
-		wl_display_post_range(display, client);
-
-	wl_hash_table_insert(client->display->objects,
-			     resource->object.id, resource);
+	wl_connection_add_object(client->connection, &resource->object);
 	wl_list_insert(client->resource_list.prev, &resource->link);
 }
 
@@ -263,29 +232,28 @@ WL_EXPORT void
 wl_client_post_no_memory(struct wl_client *client)
 {
 	wl_client_post_event(client,
-			     &client->display->object,
+			     &client->display->global.object,
 			     WL_DISPLAY_NO_MEMORY);
 }
 
 WL_EXPORT void
-wl_client_post_global(struct wl_client *client, struct wl_object *object)
+wl_client_post_global(struct wl_client *client, struct wl_global *global)
 {
 	wl_client_post_event(client,
-			     &client->display->object,
+			     &client->display->global.object,
 			     WL_DISPLAY_GLOBAL,
-			     object,
-			     object->interface->name,
-			     object->interface->version);
+			     global->object,
+			     global->object.interface->name,
+			     global->object.interface->version);
 }
 
 WL_EXPORT void
 wl_resource_destroy(struct wl_resource *resource, struct wl_client *client)
 {
-	struct wl_display *display = client->display;
-
 	wl_list_remove(&resource->link);
 	if (resource->object.id > 0)
-		wl_hash_table_remove(display->objects, resource->object.id);
+		wl_connection_remove_object(client->connection,
+					    &resource->object);
 	resource->destroy(resource, client);
 }
 
@@ -462,10 +430,36 @@ wl_input_device_update_grab(struct wl_input_device *device,
 }
 
 static void
+display_bind(struct wl_client *client, struct wl_display *display,
+	     uint32_t global_id, uint32_t version, uint32_t id)
+{
+	struct wl_global *global;
+	struct wl_proxy *proxy;
+
+	global = (struct wl_global *)
+		wl_hash_table_lookup(display->globals, global_id);
+
+	proxy = malloc(sizeof *proxy);
+	if (proxy == NULL) {
+		wl_client_post_no_memory(client);
+		return;
+	}
+
+	proxy->object.interface = object->interface;
+	proxy->object.implementation = object->implementation;
+	proxy->object.id = id;
+	proxy->connection = client->connection;
+
+	wl_connection_add_object(client->connection, &proxy->object);
+	global->bind(global, client, proxy);
+}
+
+static void
 display_sync(struct wl_client *client,
 	       struct wl_display *display, uint32_t key)
 {
-	wl_client_post_event(client, &display->object, WL_DISPLAY_KEY, key, 0);
+	wl_client_post_event(client,
+			     &display->global.object, WL_DISPLAY_KEY, key, 0);
 }
 
 static void
@@ -501,6 +495,7 @@ display_frame(struct wl_client *client,
 }
 
 struct wl_display_interface display_interface = {
+	display_bind,
 	display_sync,
 	display_frame
 };
@@ -526,8 +521,8 @@ wl_display_create(void)
 		return NULL;
 	}
 
-	display->objects = wl_hash_table_create();
-	if (display->objects == NULL) {
+	display->globals = wl_hash_table_create();
+	if (display->globals == NULL) {
 		free(display);
 		return NULL;
 	}
@@ -539,10 +534,9 @@ wl_display_create(void)
 	display->client_id_range = 256; /* Gah, arbitrary... */
 
 	display->id = 1;
-	display->object.interface = &wl_display_interface;
-	display->object.implementation = (void (**)(void)) &display_interface;
-	wl_display_add_object(display, &display->object);
-	if (wl_display_add_global(display, &display->object, NULL)) {
+	if (wl_display_add_global(display, &display->global,
+				  &wl_display_interface,
+				  (void (**)(void)) &display_interface, NULL)) {
 		wl_event_loop_destroy(display->loop);
 		free(display);
 		return NULL;
@@ -557,7 +551,7 @@ wl_display_destroy(struct wl_display *display)
 	struct wl_socket *s, *next;
 
 	wl_event_loop_destroy(display->loop);
-	wl_hash_table_destroy(display->objects);
+	wl_hash_table_destroy(display->globals);
 	
 	wl_list_for_each_safe(s, next, &display->socket_list, link) {
 		close(s->fd);
@@ -568,28 +562,20 @@ wl_display_destroy(struct wl_display *display)
 	free(display);
 }
 
-WL_EXPORT void
-wl_display_add_object(struct wl_display *display, struct wl_object *object)
-{
-	object->id = display->id++;
-	wl_hash_table_insert(display->objects, object->id, object);
-}
-
 WL_EXPORT int
 wl_display_add_global(struct wl_display *display,
-		      struct wl_object *object, wl_client_connect_func_t func)
-{
-	struct wl_global *global;
-
-	global = malloc(sizeof *global);
-	if (global == NULL)
-		return -1;
-
-	global->object = object;
+		      struct wl_global *global,
+		      const struct wl_interface *interface,
+		      void (**implementation)(void),
+		      wl_client_bind_func_t func)
+{
+	global->object.interface = interface;
+	global->object.implementation = implementation;
+	global->object.id = display->id++;
 	global->func = func;
-	wl_list_insert(display->global_list.prev, &global->link);
+	wl_hash_table_insert(display->globals, global->object.id, global);
 
-	return 0;	
+	return 0;
 }
 
 WL_EXPORT void
@@ -598,7 +584,7 @@ wl_display_post_frame(struct wl_display *display, uint32_t time)
 	struct wl_frame_listener *listener, *next;
 
 	wl_list_for_each_safe(listener, next, &display->frame_list, link) {
-		wl_client_post_event(listener->client, &display->object,
+		wl_client_post_event(listener->client, &display->global.object,
 				     WL_DISPLAY_KEY, listener->key, time);
 		wl_resource_destroy(&listener->resource, listener->client);
 	}
@@ -695,32 +681,18 @@ wl_compositor_init(struct wl_compositor *compositor,
 		   const struct wl_compositor_interface *interface,
 		   struct wl_display *display)
 {
-	compositor->object.interface = &wl_compositor_interface;
-	compositor->object.implementation = (void (**)(void)) interface;
-	wl_display_add_object(display, &compositor->object);
-	if (wl_display_add_global(display, &compositor->object, NULL))
+	if (wl_display_add_global(display, &compositor->global,
+				  &wl_compositor_interface,
+				  (void (**)(void)) interface, NULL))
 		return -1;
 
-	compositor->argb_visual.object.interface = &wl_visual_interface;
-	compositor->argb_visual.object.implementation = NULL;
-	wl_display_add_object(display, &compositor->argb_visual.object);
-	wl_display_add_global(display, &compositor->argb_visual.object, NULL);
-
-	compositor->premultiplied_argb_visual.object.interface =
-		&wl_visual_interface;
-	compositor->premultiplied_argb_visual.object.implementation = NULL;
-	wl_display_add_object(display,
-			      &compositor->premultiplied_argb_visual.object);
-	wl_display_add_global(display,
-			      &compositor->premultiplied_argb_visual.object,
-			      NULL);
-
-	compositor->rgb_visual.object.interface = &wl_visual_interface;
-	compositor->rgb_visual.object.implementation = NULL;
-	wl_display_add_object(display,
-			      &compositor->rgb_visual.object);
+	wl_display_add_global(display, &compositor->argb_visual.global,
+			      &wl_visual_interface, NULL, NULL);
 	wl_display_add_global(display,
-			      &compositor->rgb_visual.object, NULL);
+			      &compositor->premultiplied_argb_visual.global,
+			      &wl_visual_interface, NULL, NULL);
+	wl_display_add_global(display, &compositor->rgb_visual.global,
+			      &wl_visual_interface, NULL, NULL);
 
 	return 0;
 }
diff --git a/wayland/wayland-server.h b/wayland/wayland-server.h
index f74cbae..12d047e 100644
--- a/wayland/wayland-server.h
+++ b/wayland/wayland-server.h
@@ -71,8 +71,10 @@ struct wl_event_source *wl_event_loop_add_idle(struct wl_event_loop *loop,
 int wl_event_loop_get_fd(struct wl_event_loop *loop);
 
 struct wl_client;
+struct wl_surface;
 struct wl_display;
 struct wl_input_device;
+struct wl_compositor_interface;
 
 struct wl_display *wl_display_create(void);
 void wl_display_destroy(struct wl_display *display);
@@ -81,22 +83,32 @@ int wl_display_add_socket(struct wl_display *display, const char *name);
 void wl_display_terminate(struct wl_display *display);
 void wl_display_run(struct wl_display *display);
 
-void wl_display_add_object(struct wl_display *display, struct wl_object *object);
+typedef void (*wl_client_bind_func_t)(struct wl_object *global,
+				      struct wl_client *client,
+				      struct wl_proxy *proxy);
 
-typedef void (*wl_client_connect_func_t)(struct wl_client *client, struct wl_object *global);
+struct wl_global {
+	struct wl_object object;
+	wl_client_bind_func_t bind;
+};
 
-int wl_display_add_global(struct wl_display *display, struct wl_object *object, wl_client_connect_func_t func);
+int
+wl_display_add_global(struct wl_display *display,
+		      struct wl_global *global,
+		      const struct wl_interface *interface,
+		      void (**implementation)(void),
+		      wl_client_bind_func_t func);
 
 void wl_client_destroy(struct wl_client *client);
 void wl_client_post_no_memory(struct wl_client *client);
-void wl_client_post_global(struct wl_client *client, struct wl_object *object);
+void wl_client_post_global(struct wl_client *client, struct wl_global *global);
 
 struct wl_visual {
-	struct wl_object object;
+	struct wl_global global;
 };
 
 struct wl_compositor {
-	struct wl_object object;
+	struct wl_global global;
 	struct wl_visual argb_visual;
 	struct wl_visual premultiplied_argb_visual;
 	struct wl_visual rgb_visual;
@@ -133,7 +145,7 @@ struct wl_surface {
 };
 
 struct wl_shell {
-	struct wl_object object;
+	struct wl_object global;
 };
 
 struct wl_grab;
diff --git a/wayland/wayland-util.h b/wayland/wayland-util.h
index 6c1231a..f89af29 100644
--- a/wayland/wayland-util.h
+++ b/wayland/wayland-util.h
@@ -70,12 +70,19 @@ struct wl_object {
 	uint32_t id;
 };
 
+struct wl_proxy {
+	struct wl_object object;
+	struct wl_connection *connection;
+	void *user_data;
+};
+
 struct wl_hash_table;
 struct wl_hash_table *wl_hash_table_create(void);
 void wl_hash_table_destroy(struct wl_hash_table *ht);
 void *wl_hash_table_lookup(struct wl_hash_table *ht, uint32_t hash);
 int wl_hash_table_insert(struct wl_hash_table *ht, uint32_t hash, void *data);
 void wl_hash_table_remove(struct wl_hash_table *ht, uint32_t hash);
+int wl_hash_table_index(struct wl_hash_table *ht, int index, void **data);
 
 /**
  * wl_list - linked list
