implement xdg-foreign v1
Reviewed-by: Derek Foreman <derekf@osg.samsung.com>
This commit is contained in:
parent
d1bb23954f
commit
5aadf3b3ff
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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>
|
Loading…
Reference in New Issue