discomfitor pushed a commit to branch master.

http://git.enlightenment.org/core/enlightenment.git/commit/?id=5aadf3b3ffe3c6876f795cea03566105625c9748

commit 5aadf3b3ffe3c6876f795cea03566105625c9748
Author: Mike Blumenkrantz <zm...@osg.samsung.com>
Date:   Fri Jan 13 11:35:26 2017 -0500

    implement xdg-foreign v1
    
    Reviewed-by: Derek Foreman <der...@osg.samsung.com>
---
 src/bin/Makefile.mk                      |   8 +-
 src/bin/e_comp_wl.h                      |  11 ++
 src/bin/e_comp_wl_extensions.c           | 226 +++++++++++++++++++++++++++++++
 src/protocol/xdg-foreign-unstable-v1.xml | 182 +++++++++++++++++++++++++
 4 files changed, 425 insertions(+), 2 deletions(-)

diff --git a/src/bin/Makefile.mk b/src/bin/Makefile.mk
index e214a7d..667a644 100644
--- a/src/bin/Makefile.mk
+++ b/src/bin/Makefile.mk
@@ -443,11 +443,15 @@ src/bin/generated/session-recovery-server-protocol.h \
 src/bin/generated/www-protocol.c \
 src/bin/generated/www-server-protocol.h \
 src/bin/generated/screenshooter-protocol.c \
-src/bin/generated/screenshooter-server-protocol.h
+src/bin/generated/screenshooter-server-protocol.h \
+src/bin/generated/xdg-foreign-unstable-v1-protocol.c \
+src/bin/generated/xdg-foreign-unstable-v1-server-protocol.h
 
 src/bin/e_comp_wl_extensions.c: \
  src/bin/generated/screenshooter-server-protocol.h \
- src/bin/generated/session-recovery-server-protocol.h
+ src/bin/generated/session-recovery-server-protocol.h \
+ src/bin/generated/xdg-foreign-unstable-v1-protocol.c \
+ src/bin/generated/xdg-foreign-unstable-v1-server-protocol.h
 
 src/bin/e_comp_wl.c: \
  src/bin/generated/www-server-protocol.h
diff --git a/src/bin/e_comp_wl.h b/src/bin/e_comp_wl.h
index 48ff97a..8d0ac5a 100644
--- a/src/bin/e_comp_wl.h
+++ b/src/bin/e_comp_wl.h
@@ -110,6 +110,17 @@ typedef struct E_Comp_Wl_Extension_Data
    {
        struct wl_global *global;
    } www;
+   /* begin xdg-foreign */
+   struct
+   {
+      struct wl_global *global;
+      Eina_Hash *surfaces;
+   } zxdg_exporter_v1;
+   struct
+   {
+      struct wl_global *global;
+   } zxdg_importer_v1;
+   /* end xdg-foreign */
 } E_Comp_Wl_Extension_Data;
 
 struct _E_Comp_Wl_Data
diff --git a/src/bin/e_comp_wl_extensions.c b/src/bin/e_comp_wl_extensions.c
index ea9833d..517579b 100644
--- a/src/bin/e_comp_wl_extensions.c
+++ b/src/bin/e_comp_wl_extensions.c
@@ -6,6 +6,26 @@
 #include "screenshooter-server-protocol.h"
 #include "session-recovery-server-protocol.h"
 #include "www-server-protocol.h"
+#include "xdg-foreign-unstable-v1-server-protocol.h"
+
+/* mutter uses 32, seems reasonable */
+#define HANDLE_LEN 32
+
+typedef struct Exported
+{
+   E_Client *ec;
+   struct wl_resource *res;
+   char handle[HANDLE_LEN + 1];
+   Eina_List *imported;
+} Exported;
+
+typedef struct Imported
+{
+   /* child */
+   E_Client *ec;
+   struct wl_resource *res;
+   Exported *ex;
+} Imported;
 
 static void
 _e_comp_wl_extensions_client_move_begin(void *d EINA_UNUSED, E_Client *ec)
@@ -207,6 +227,195 @@ _e_comp_wl_www_cb_create(struct wl_client *client, struct 
wl_resource *resource,
     e_object_ref(E_OBJECT(ec));
 }
 
+///////////////////////////////////////////////////////
+
+static void
+_e_comp_wl_zxdg_exported_v1_destroy(struct wl_client *client EINA_UNUSED, 
struct wl_resource *resource)
+{
+   wl_resource_destroy(resource);
+}
+
+static void _imported_v1_del(Imported *im);
+static void _exported_del(void *data, Evas *e, Evas_Object *obj, void 
*event_info);
+
+static void
+_exported_v1_del(Exported *ex)
+{
+   while (ex->imported)
+     {
+        Imported *im = eina_list_data_get(ex->imported);
+
+        zxdg_imported_v1_send_destroyed(im->res);
+        _imported_v1_del(im);
+     }
+   evas_object_event_callback_del(ex->ec->frame, EVAS_CALLBACK_DEL, 
_exported_del);
+   wl_resource_set_user_data(ex->res, NULL);
+   eina_hash_del_by_key(e_comp_wl->extensions->zxdg_exporter_v1.surfaces, 
ex->handle);
+   free(ex);
+}
+
+static void
+_e_zxdg_exported_v1_del(struct wl_resource *resource)
+{
+   Exported *ex = wl_resource_get_user_data(resource);
+
+   if (ex) _exported_v1_del(ex);
+}
+
+static void
+_exported_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, 
void *event_info EINA_UNUSED)
+{
+   _exported_v1_del(data);
+}
+
+static void
+_e_comp_wl_zxdg_exporter_v1_exporter_destroy(struct wl_client *client 
EINA_UNUSED, struct wl_resource *resource)
+{
+   wl_resource_destroy(resource);
+}
+
+static const struct zxdg_exported_v1_interface _e_zxdg_exported_v1_interface =
+{
+   _e_comp_wl_zxdg_exported_v1_destroy,
+};
+
+static void
+_e_comp_wl_zxdg_exporter_v1_export(struct wl_client *client, struct 
wl_resource *resource, uint32_t id, struct wl_resource *surface)
+{
+   E_Client *ec = wl_resource_get_user_data(surface);
+   Exported *ex;
+
+   if ((!ec) || (!ec->comp_data->is_xdg_surface) || ec->comp_data->cursor)
+     {
+        wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, 
"invalid role for exported surface");
+        return;
+     }
+
+   ex = E_NEW(Exported, 1);
+   ex->ec = ec;
+   ex->res = wl_resource_create(client, &zxdg_exported_v1_interface, 
wl_resource_get_version(resource), id);
+   wl_resource_set_implementation(ex->res, &_e_zxdg_exported_v1_interface, ex, 
_e_zxdg_exported_v1_del);
+   evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_DEL, _exported_del, 
ex);
+
+   do
+     {
+        int n;
+
+        for (n = 0; n < HANDLE_LEN; n++)
+          {
+             /* only printable ascii */
+             ex->handle[n] = (rand() % (127 - 32)) + 32;
+          }
+     } while (eina_hash_find(e_comp_wl->extensions->zxdg_exporter_v1.surfaces, 
ex->handle));
+   eina_hash_add(e_comp_wl->extensions->zxdg_exporter_v1.surfaces, ex->handle, 
ex);
+
+   zxdg_exported_v1_send_handle(ex->res, ex->handle);
+}
+
+
+static void
+_e_comp_wl_zxdg_imported_v1_destroy(struct wl_client *client EINA_UNUSED, 
struct wl_resource *resource)
+{
+   wl_resource_destroy(resource);
+}
+
+static void _imported_del(void *data, Evas *e, Evas_Object *obj, void 
*event_info);
+
+static void
+_imported_v1_del(Imported *im)
+{
+   im->ex->imported = eina_list_remove(im->ex->imported, im);
+   if (im->ec)
+     {
+        evas_object_event_callback_del(im->ec->frame, EVAS_CALLBACK_DEL, 
_imported_del);
+        e_client_parent_set(im->ec, NULL);
+     }
+   if (im->res) wl_resource_set_user_data(im->res, NULL);
+   free(im);
+}
+
+static void
+_e_zxdg_imported_v1_del(struct wl_resource *resource)
+{
+   Imported *im = wl_resource_get_user_data(resource);
+
+   if (im) _imported_v1_del(im);
+}
+
+static void
+_imported_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, 
void *event_info EINA_UNUSED)
+{
+   Imported *im = data;
+
+   im->ec = NULL;
+}
+
+static void
+_e_comp_wl_zxdg_importer_v1_importer_destroy(struct wl_client *client 
EINA_UNUSED, struct wl_resource *resource)
+{
+   wl_resource_destroy(resource);
+}
+
+static void
+_e_comp_wl_zxdg_imported_v1_set_parent_of(struct wl_client *client 
EINA_UNUSED, struct wl_resource *resource, struct wl_resource *surface_resource)
+{
+   Imported *im = wl_resource_get_user_data(resource);
+   E_Client *ec = NULL;
+
+   if (surface_resource) ec = wl_resource_get_user_data(surface_resource);
+
+   if (ec && ((ec->netwm.type != E_WINDOW_TYPE_NORMAL) || 
(!ec->comp_data->is_xdg_surface)))
+     {
+        wl_resource_post_error(im->res, WL_DISPLAY_ERROR_INVALID_OBJECT,
+          "xdg_imported.set_parent_of called with invalid surface");
+        return;
+     }
+
+   if (im->ec)
+     evas_object_event_callback_del(im->ec->frame, EVAS_CALLBACK_DEL, 
_imported_del);
+
+   im->ec = ec;
+
+   if (ec)
+     {
+        evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_DEL, 
_imported_del, im);
+        e_client_parent_set(ec, im->ex->ec);
+        ec->parent->modal = ec;
+        ec->parent->lock_close = 1;
+     }
+}
+
+static const struct zxdg_imported_v1_interface _e_zxdg_imported_v1_interface =
+{
+   _e_comp_wl_zxdg_imported_v1_destroy,
+   _e_comp_wl_zxdg_imported_v1_set_parent_of,
+};
+
+static void
+_e_comp_wl_zxdg_importer_v1_import(struct wl_client *client, struct 
wl_resource *resource, uint32_t id, const char *handle)
+{
+   Imported *im;
+   Exported *ex;
+
+   im = E_NEW(Imported, 1);
+   im->res = wl_resource_create(client, &zxdg_imported_v1_interface, 
wl_resource_get_version(resource), id);
+   wl_resource_set_implementation(im->res, &_e_zxdg_imported_v1_interface, 
NULL, _e_zxdg_imported_v1_del);
+
+   ex = eina_hash_find(e_comp_wl->extensions->zxdg_exporter_v1.surfaces, 
handle);
+   if ((!ex) || (!ex->ec->netwm.type))
+     {
+        zxdg_imported_v1_send_destroyed(im->res);
+        free(im);
+        return;
+     }
+
+   im->ex = ex;
+   wl_resource_set_user_data(im->res, im);
+   ex->imported = eina_list_append(ex->imported, im);
+}
+
+/////////////////////////////////////////////////////////
+
 static const struct zwp_e_session_recovery_interface 
_e_session_recovery_interface =
 {
    _e_comp_wl_session_recovery_get_uuid,
@@ -224,6 +433,18 @@ static const struct www_interface _e_www_interface =
    _e_comp_wl_www_cb_create
 };
 
+static const struct zxdg_exporter_v1_interface _e_zxdg_exporter_v1_interface =
+{
+   _e_comp_wl_zxdg_exporter_v1_exporter_destroy,
+   _e_comp_wl_zxdg_exporter_v1_export,
+};
+
+static const struct zxdg_importer_v1_interface _e_zxdg_importer_v1_interface =
+{
+   _e_comp_wl_zxdg_importer_v1_importer_destroy,
+   _e_comp_wl_zxdg_importer_v1_import,
+};
+
 
 #define GLOBAL_BIND_CB(NAME, IFACE, ...) \
 static void \
@@ -244,6 +465,8 @@ _e_comp_wl_##NAME##_cb_bind(struct wl_client *client, void 
*data EINA_UNUSED, ui
 GLOBAL_BIND_CB(session_recovery, zwp_e_session_recovery_interface)
 GLOBAL_BIND_CB(screenshooter, zwp_screenshooter_interface)
 GLOBAL_BIND_CB(www, www_interface)
+GLOBAL_BIND_CB(zxdg_exporter_v1, zxdg_exporter_v1_interface)
+GLOBAL_BIND_CB(zxdg_importer_v1, zxdg_importer_v1_interface)
 
 
 #define GLOBAL_CREATE_OR_RETURN(NAME, IFACE, VERSION) \
@@ -285,6 +508,9 @@ e_comp_wl_extensions_init(void)
    GLOBAL_CREATE_OR_RETURN(session_recovery, zwp_e_session_recovery_interface, 
1);
    GLOBAL_CREATE_OR_RETURN(screenshooter, zwp_screenshooter_interface, 1);
    GLOBAL_CREATE_OR_RETURN(www, www_interface, 1);
+   GLOBAL_CREATE_OR_RETURN(zxdg_exporter_v1, zxdg_exporter_v1_interface, 1);
+   e_comp_wl->extensions->zxdg_exporter_v1.surfaces = 
eina_hash_string_superfast_new(NULL);
+   GLOBAL_CREATE_OR_RETURN(zxdg_importer_v1, zxdg_importer_v1_interface, 1);
 
    ecore_event_handler_add(ECORE_WL2_EVENT_SYNC_DONE, _dmabuf_add, NULL);
 
diff --git a/src/protocol/xdg-foreign-unstable-v1.xml 
b/src/protocol/xdg-foreign-unstable-v1.xml
new file mode 100644
index 0000000..062b090
--- /dev/null
+++ b/src/protocol/xdg-foreign-unstable-v1.xml
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="xdg_foreign_unstable_v1">
+
+  <copyright>
+    Copyright © 2015-2016 Red Hat Inc.
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the "Software"),
+    to deal in the Software without restriction, including without limitation
+    the rights to use, copy, modify, merge, publish, distribute, sublicense,
+    and/or sell copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice (including the next
+    paragraph) shall be included in all copies or substantial portions of the
+    Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+    DEALINGS IN THE SOFTWARE.
+  </copyright>
+
+  <description summary="Protocol for exporting xdg surface handles">
+    This protocol specifies a way for making it possible to reference a surface
+    of a different client. With such a reference, a client can, by using the
+    interfaces provided by this protocol, manipulate the relationship between
+    its own surfaces and the surface of some other client. For example, stack
+    some of its own surface above the other clients surface.
+
+    In order for a client A to get a reference of a surface of client B, client
+    B must first export its surface using xdg_exporter.export. Upon doing this,
+    client B will receive a handle (a unique string) that it may share with
+    client A in some way (for example D-Bus). After client A has received the
+    handle from client B, it may use xdg_importer.import to create a reference
+    to the surface client B just exported. See the corresponding requests for
+    details.
+
+    A possible use case for this is out-of-process dialogs. For example when a
+    sandboxed client without file system access needs the user to select a file
+    on the file system, given sandbox environment support, it can export its
+    surface, passing the exported surface handle to an unsandboxed process that
+    can show a file browser dialog and stack it above the sandboxed client's
+    surface.
+
+    Warning! The protocol described in this file is experimental and backward
+    incompatible changes may be made. Backward compatible changes may be added
+    together with the corresponding interface version bump. Backward
+    incompatible changes are done by bumping the version number in the protocol
+    and interface names and resetting the interface version. Once the protocol
+    is to be declared stable, the 'z' prefix and the version number in the
+    protocol and interface names are removed and the interface version number 
is
+    reset.
+  </description>
+
+  <interface name="zxdg_exporter_v1" version="1">
+    <description summary="interface for exporting surfaces">
+      A global interface used for exporting surfaces that can later be imported
+      using xdg_importer.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="destroy the xdg_exporter object">
+       Notify the compositor that the xdg_exporter object will no longer be
+       used.
+      </description>
+    </request>
+
+    <request name="export">
+      <description summary="export a surface">
+       The export request exports the passed surface so that it can later be
+       imported via xdg_importer. When called, a new xdg_exported object will
+       be created and xdg_exported.handle will be sent immediately. See the
+       corresponding interface and event for details.
+
+       A surface may be exported multiple times, and each exported handle may
+       be used to create a xdg_imported multiple times. Only xdg_surface
+       surfaces may be exported.
+      </description>
+      <arg name="id" type="new_id" interface="zxdg_exported_v1"
+          summary="the new xdg_exported object"/>
+      <arg name="surface" type="object" interface="wl_surface"
+          summary="the surface to export"/>
+    </request>
+  </interface>
+
+  <interface name="zxdg_importer_v1" version="1">
+    <description summary="interface for importing surfaces">
+      A global interface used for importing surfaces exported by xdg_exporter.
+      With this interface, a client can create a reference to a surface of
+      another client.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="destroy the xdg_importer object">
+       Notify the compositor that the xdg_importer object will no longer be
+       used.
+      </description>
+    </request>
+
+    <request name="import">
+      <description summary="import a surface">
+       The import request imports a surface from any client given a handle
+       retrieved by exporting said surface using xdg_exporter.export. When
+       called, a new xdg_imported object will be created. This new object
+       represents the imported surface, and the importing client can
+       manipulate its relationship using it. See xdg_imported for details.
+      </description>
+      <arg name="id" type="new_id" interface="zxdg_imported_v1"
+          summary="the new xdg_imported object"/>
+      <arg name="handle" type="string"
+          summary="the exported surface handle"/>
+    </request>
+  </interface>
+
+  <interface name="zxdg_exported_v1" version="1">
+    <description summary="an exported surface handle">
+      A xdg_exported object represents an exported reference to a surface. The
+      exported surface may be referenced as long as the xdg_exported object not
+      destroyed. Destroying the xdg_exported invalidates any relationship the
+      importer may have established using xdg_imported.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="unexport the exported surface">
+       Revoke the previously exported surface. This invalidates any
+       relationship the importer may have set up using the xdg_imported created
+       given the handle sent via xdg_exported.handle.
+      </description>
+    </request>
+
+    <event name="handle">
+      <description summary="the exported surface handle">
+       The handle event contains the unique handle of this exported surface
+       reference. It may be shared with any client, which then can use it to
+       import the surface by calling xdg_importer.import. A handle may be
+       used to import the surface multiple times.
+      </description>
+      <arg name="handle" type="string" summary="the exported surface handle"/>
+    </event>
+  </interface>
+
+  <interface name="zxdg_imported_v1" version="1">
+    <description summary="an imported surface handle">
+      A xdg_imported object represents an imported reference to surface 
exported
+      by some client. A client can use this interface to manipulate
+      relationships between its own surfaces and the imported surface.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="destroy the xdg_imported object">
+       Notify the compositor that it will no longer use the xdg_imported
+       object. Any relationship that may have been set up will at this point
+       be invalidated.
+      </description>
+    </request>
+
+    <request name="set_parent_of">
+      <description summary="set as the parent of some surface">
+       Set the imported surface as the parent of some surface of the client.
+       The passed surface must be a toplevel xdg_surface. Calling this function
+       sets up a surface to surface relation with the same stacking and 
positioning
+       semantics as xdg_surface.set_parent.
+      </description>
+      <arg name="surface" type="object" interface="wl_surface"
+          summary="the child surface"/>
+    </request>
+
+    <event name="destroyed">
+      <description summary="the imported surface handle has been destroyed">
+       The imported surface handle has been destroyed and any relationship set
+       up has been invalidated. This may happen for various reasons, for
+       example if the exported surface or the exported surface handle has been
+       destroyed, if the handle used for importing was invalid.
+      </description>
+    </event>
+  </interface>
+
+</protocol>

-- 


Reply via email to