From 818a3c3f5c845ed9f6e1208f13633948792e0db7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= <krh@bitplanet.net>
Date: Thu, 19 Jan 2012 18:35:29 -0500
Subject: [PATCH] import foreign objects

---
 protocol/wayland.xml |   12 ++++++++++++
 src/wayland-client.c |   15 +++++++++++++++
 src/wayland-client.h |    1 +
 src/wayland-server.c |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 74 insertions(+)

diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index cad2507..5b047ff 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -53,6 +53,11 @@
       <arg name="callback" type="new_id" interface="wl_callback"/>
     </request>
 
+    <request name="create_client">
+      <arg name="id" type="new_id" interface="wl_client"/>
+      <arg name="fd" type="fd"/>
+    </request>
+
     <event name="error">
       <description summary="fatal error event">
 	The error event is sent out when a fatal (non-recoverable)
@@ -685,4 +690,11 @@
     </event>
   </interface>
 
+  <interface name="wl_client" version="1">
+    <request name="import">
+      <arg name="foreign_id" type="uint"/>
+      <arg name="id" type="new_id" interface="wl_surface"/>
+    </request>
+  </interface>
+
 </protocol>
diff --git a/src/wayland-client.c b/src/wayland-client.c
index 7814379..e8c81f0 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -565,6 +565,21 @@ wl_display_sync(struct wl_display *display)
 	return (struct wl_callback *) proxy;
 }
 
+WL_EXPORT struct wl_client *
+wl_display_create_client(struct wl_display *display, int fd)
+{
+	struct wl_proxy *proxy;
+
+	proxy = wl_proxy_create(&display->proxy, &wl_client_interface);
+
+	if (!proxy)
+		return NULL;
+
+	wl_proxy_marshal(&display->proxy, WL_DISPLAY_CREATE_CLIENT, proxy, fd);
+
+	return (struct wl_client *) proxy;
+}
+
 WL_EXPORT void
 wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data)
 {
diff --git a/src/wayland-client.h b/src/wayland-client.h
index efeee4a..2ef1cbb 100644
--- a/src/wayland-client.h
+++ b/src/wayland-client.h
@@ -61,6 +61,7 @@ wl_display_get_user_data(struct wl_display *display)
 }
 
 struct wl_callback *wl_display_sync(struct wl_display *display);
+struct wl_client *wl_display_create_client(struct wl_display *display, int fd);
 
 #include "wayland-client-protocol.h"
 
diff --git a/src/wayland-server.c b/src/wayland-server.c
index 70adf28..4436ea8 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -642,9 +642,55 @@ display_sync(struct wl_client *client,
 	wl_resource_destroy(callback, 0);
 }
 
+static void
+client_import(struct wl_client *client,
+	      struct wl_resource *resource, uint32_t foreign_id, uint32_t id)
+{
+	struct wl_object *object;
+	struct wl_client *other = resource->data;
+
+	object = wl_map_lookup(&other->objects, foreign_id);
+	if (object == NULL) {
+		wl_resource_post_error(client->display_resource,
+				       WL_DISPLAY_ERROR_INVALID_OBJECT,
+				       "invalid object %d", foreign_id);
+		return;
+	}
+
+	/* FIXME: What happens when the other client destroys the object? */
+	resource = wl_client_add_object(client,
+					object->interface,
+					object->implementation,
+					id, object);
+	if (resource == NULL)
+		wl_resource_post_no_memory(resource);
+}
+
+static const struct wl_client_interface client_interface = {
+	client_import
+};
+
+static void
+display_create_client(struct wl_client *client,
+		      struct wl_resource *resource, uint32_t id, int fd)
+{
+	struct wl_resource *client_resource;
+	struct wl_client *new_client;
+
+	new_client = wl_client_create(client->display, fd);
+
+	client_resource = wl_client_add_object(client,
+					       &wl_client_interface,
+					       &client_interface,
+					       id, new_client);
+	if (client_resource == NULL)
+		wl_resource_post_no_memory(resource);
+}
+
 struct wl_display_interface display_interface = {
 	display_bind,
 	display_sync,
+	display_create_client
 };
 
 static void
-- 
1.7.10

