mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2026-03-23 05:35:51 -04:00
Merge branch 'jorth/display-upgrade' into 'main'
protocol: add wl_display_upgrade global See merge request wayland/wayland!534
This commit is contained in:
commit
ccf3be1fc9
5 changed files with 218 additions and 4 deletions
|
|
@ -28,10 +28,14 @@
|
|||
SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="wl_display" version="1">
|
||||
<interface name="wl_display" version="2">
|
||||
<description summary="core global object">
|
||||
The core global object. This is a special singleton object. It
|
||||
is used for internal Wayland protocol features.
|
||||
|
||||
This interface guarantees that the semantics of requests of this interface
|
||||
are unaffected by the minor version of this interface. The semantics of
|
||||
events may change and new events may be added.
|
||||
</description>
|
||||
|
||||
<request name="sync">
|
||||
|
|
@ -110,7 +114,7 @@
|
|||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_registry" version="1">
|
||||
<interface name="wl_registry" version="2">
|
||||
<description summary="global registry object">
|
||||
The singleton global registry object. The server has a number of
|
||||
global objects that are available to all clients. These objects
|
||||
|
|
@ -132,6 +136,10 @@
|
|||
request. This creates a client-side handle that lets the object
|
||||
emit events to the client and lets the client invoke requests on
|
||||
the object.
|
||||
|
||||
This interface guarantees that the semantics of the messages of this
|
||||
interface are unaffected by the minor version of this interface; and that
|
||||
no new events will be added to any minor version of this interface.
|
||||
</description>
|
||||
|
||||
<request name="bind">
|
||||
|
|
@ -171,6 +179,14 @@
|
|||
</description>
|
||||
<arg name="name" type="uint" summary="numeric name of the global object"/>
|
||||
</event>
|
||||
|
||||
<!-- Version 2 additions -->
|
||||
|
||||
<request name="release" type="destructor" since="2">
|
||||
<description summary="destroys this registry">
|
||||
Objects created from this registry are not affected by this request.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_callback" version="1" frozen="true">
|
||||
|
|
@ -3362,4 +3378,56 @@
|
|||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="wl_display_upgrade" version="2">
|
||||
<description summary="wayland upgrade object">
|
||||
This global allows the IPC library to upgrade the version of the
|
||||
wl_display object.
|
||||
|
||||
This global must not be bound more than once over the lifetime of the
|
||||
connection, otherwise the already_bound error is emitted.
|
||||
|
||||
This global should only be bound by the IPC library because the IPC
|
||||
library must be aware of the version of the wl_display object.
|
||||
|
||||
A compositor that advertises this global must also advertise the wl_fixes
|
||||
global.
|
||||
</description>
|
||||
|
||||
<enum name="error">
|
||||
<description summary="wl_display_upgrade error values">
|
||||
These errors can be emitted in response to wl_display_upgrade requests.
|
||||
</description>
|
||||
<entry name="already_bound" value="0"
|
||||
summary="the wl_display_upgrade global was bound more than once"/>
|
||||
<entry name="has_objects" value="1"
|
||||
summary="objects other than wl_display and this object exist"/>
|
||||
<entry name="out_of_bounds" value="2"
|
||||
summary="the version requested by the upgrade request is out of bounds"/>
|
||||
</enum>
|
||||
|
||||
<event name="max_version">
|
||||
<description summary="the version supported by the compositor">
|
||||
This event informs the client of the maximum wl_display version
|
||||
supported by the compositor. It is sent immediately after this global
|
||||
has been bound. The version is guaranteed to be at least 1.
|
||||
</description>
|
||||
<arg name="version" type="uint" summary="the version"/>
|
||||
</event>
|
||||
|
||||
<request name="upgrade" type="destructor">
|
||||
<description summary="upgrade the wl_display version">
|
||||
Negotiates an upgrade of the version of the wl_display object.
|
||||
|
||||
At the time of the request, no objects other than the wl_display and
|
||||
this object must exist, otherwise the has_objects error is emitted. In
|
||||
particular, the client must use wl_fixes to destroy the registry from
|
||||
which this object was created.
|
||||
|
||||
The version must be at least 1 and must not be larger than the version
|
||||
sent in the version event, otherwise the out_of_bounds error is emitted.
|
||||
</description>
|
||||
<arg name="version" type="uint" summary="the version"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
</protocol>
|
||||
|
|
|
|||
|
|
@ -245,6 +245,9 @@ wl_display_connect_to_fd(int fd);
|
|||
void
|
||||
wl_display_disconnect(struct wl_display *display);
|
||||
|
||||
void
|
||||
wl_display_upgrade(struct wl_display *display);
|
||||
|
||||
int
|
||||
wl_display_get_fd(struct wl_display *display);
|
||||
|
||||
|
|
|
|||
|
|
@ -1405,6 +1405,84 @@ wl_display_disconnect(struct wl_display *display)
|
|||
free(display);
|
||||
}
|
||||
|
||||
struct upgrade_listener {
|
||||
struct wl_fixes *wl_fixes;
|
||||
struct wl_display_upgrade *wl_display_upgrade;
|
||||
uint32_t version;
|
||||
};
|
||||
|
||||
static void upgrade_max_version(void *data,
|
||||
struct wl_display_upgrade *wl_display_upgrade,
|
||||
uint32_t version)
|
||||
{
|
||||
struct upgrade_listener *listener = data;
|
||||
listener->version = version;
|
||||
}
|
||||
|
||||
static struct wl_display_upgrade_listener upgrade_upgrade_listener = {
|
||||
.max_version = upgrade_max_version,
|
||||
};
|
||||
|
||||
static void upgrade_global(void *data, struct wl_registry *wl_registry,
|
||||
uint32_t name, const char *interface,
|
||||
uint32_t version)
|
||||
{
|
||||
struct upgrade_listener *listener = data;
|
||||
if (!listener->wl_fixes && strcmp(interface, wl_fixes_interface.name) == 0)
|
||||
listener->wl_fixes = wl_registry_bind(wl_registry, name, &wl_fixes_interface, 1);
|
||||
else if (!listener->wl_display_upgrade && strcmp(interface, wl_display_upgrade_interface.name) == 0) {
|
||||
listener->wl_display_upgrade = wl_registry_bind(wl_registry, name, &wl_display_upgrade_interface, 1);
|
||||
wl_display_upgrade_add_listener(listener->wl_display_upgrade, &upgrade_upgrade_listener, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void upgrade_global_remove(void *data, struct wl_registry *wl_registry,
|
||||
uint32_t name)
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
static struct wl_registry_listener upgrade_registry_listener = {
|
||||
.global = upgrade_global,
|
||||
.global_remove = upgrade_global_remove,
|
||||
};
|
||||
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
/** Upgrade the wl_display version.
|
||||
*
|
||||
* \param display The display context object
|
||||
*
|
||||
* Tries to upgrade the version of the wl_display. After this function returns,
|
||||
* wl_display_get_version can be used to retrieve the new version of the
|
||||
* wl_display.
|
||||
*
|
||||
* This function should be called immediately after creating the display. It
|
||||
* must not be called any later than that or multiple times, otherwise a
|
||||
* protocol error might occur.
|
||||
*
|
||||
* \memberof wl_display
|
||||
*/
|
||||
WL_EXPORT void
|
||||
wl_display_upgrade(struct wl_display *display)
|
||||
{
|
||||
struct wl_registry *registry = wl_display_get_registry(display);
|
||||
struct upgrade_listener listener = { };
|
||||
wl_registry_add_listener(registry, &upgrade_registry_listener, &listener);
|
||||
wl_display_roundtrip(display);
|
||||
if (listener.wl_display_upgrade)
|
||||
wl_display_roundtrip(display);
|
||||
if (listener.wl_fixes) {
|
||||
wl_fixes_destroy_registry(listener.wl_fixes, registry);
|
||||
wl_fixes_destroy(listener.wl_fixes);
|
||||
}
|
||||
if (listener.wl_display_upgrade) {
|
||||
uint32_t version = min(listener.version, (uint32_t)wl_display_interface.version);
|
||||
wl_display_upgrade_upgrade(listener.wl_display_upgrade, version);
|
||||
display->proxy.version = version;
|
||||
}
|
||||
}
|
||||
|
||||
/** Get a display context's file descriptor
|
||||
*
|
||||
* \param display The display context object
|
||||
|
|
|
|||
|
|
@ -697,6 +697,9 @@ wl_shm_buffer_create(struct wl_client *client,
|
|||
uint32_t id, int32_t width, int32_t height,
|
||||
int32_t stride, uint32_t format);
|
||||
|
||||
int
|
||||
wl_display_init_upgrade(struct wl_display *display, uint32_t max_version);
|
||||
|
||||
void
|
||||
wl_log_set_handler_server(wl_log_func_t handler);
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ struct wl_client {
|
|||
struct wl_priv_signal resource_created_signal;
|
||||
void *data;
|
||||
wl_user_data_destroy_func_t data_dtor;
|
||||
bool has_upgrade;
|
||||
};
|
||||
|
||||
struct wl_display {
|
||||
|
|
@ -113,6 +114,7 @@ struct wl_display {
|
|||
struct wl_event_source *term_source;
|
||||
|
||||
size_t max_buffer_size;
|
||||
uint32_t max_upgrade_version;
|
||||
};
|
||||
|
||||
struct wl_global {
|
||||
|
|
@ -1077,8 +1079,15 @@ registry_bind(struct wl_client *client,
|
|||
global->bind(client, global->data, version, id);
|
||||
}
|
||||
|
||||
static void
|
||||
registry_release(struct wl_client *client, struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static const struct wl_registry_interface registry_interface = {
|
||||
registry_bind
|
||||
.bind = registry_bind,
|
||||
.release = registry_release,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -1114,7 +1123,7 @@ display_get_registry(struct wl_client *client,
|
|||
struct wl_global *global;
|
||||
|
||||
registry_resource =
|
||||
wl_resource_create(client, &wl_registry_interface, 1, id);
|
||||
wl_resource_create(client, &wl_registry_interface, resource->version, id);
|
||||
if (registry_resource == NULL) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
|
|
@ -2428,6 +2437,59 @@ wl_client_set_max_buffer_size(struct wl_client *client, size_t max_buffer_size)
|
|||
wl_connection_set_max_buffer_size(client->connection, max_buffer_size);
|
||||
}
|
||||
|
||||
static void
|
||||
upgrade_display(struct wl_client *client, struct wl_resource *resource,
|
||||
uint32_t version)
|
||||
{
|
||||
wl_resource_destroy(resource);
|
||||
// TODO: Check that there are no other objects.
|
||||
if (version < 1 || version > client->display->max_upgrade_version) {
|
||||
wl_resource_post_error(resource,
|
||||
WL_DISPLAY_UPGRADE_ERROR_OUT_OF_BOUNDS,
|
||||
"version is out of bounds");
|
||||
return;
|
||||
}
|
||||
client->display_resource->version = (int)version;
|
||||
}
|
||||
|
||||
static struct wl_display_upgrade_interface upgrade_interface = {
|
||||
.upgrade = upgrade_display,
|
||||
};
|
||||
|
||||
static void
|
||||
bind_upgrade(struct wl_client *client, void *data, uint32_t version,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
resource = wl_resource_create(client, &wl_display_upgrade_interface,
|
||||
(int)version, id);
|
||||
if (!resource) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
if (client->has_upgrade) {
|
||||
wl_resource_post_error(resource,
|
||||
WL_DISPLAY_UPGRADE_ERROR_ALREADY_BOUND,
|
||||
"wl_display_upgrade has already been bound");
|
||||
return;
|
||||
}
|
||||
client->has_upgrade = true;
|
||||
wl_display_upgrade_send_max_version(resource,
|
||||
client->display->max_upgrade_version);
|
||||
wl_resource_set_implementation(resource, &upgrade_interface, NULL, NULL);
|
||||
}
|
||||
|
||||
WL_EXPORT int
|
||||
wl_display_init_upgrade(struct wl_display *display, uint32_t max_version)
|
||||
{
|
||||
if (max_version > (uint32_t)wl_display_upgrade_interface.version)
|
||||
max_version = wl_display_upgrade_interface.version;
|
||||
display->max_upgrade_version = max_version;
|
||||
if (!wl_global_create(display, &wl_display_upgrade_interface, 1, NULL, bind_upgrade))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \cond INTERNAL */
|
||||
|
||||
/** Initialize a wl_priv_signal object
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue