Merge pull request #931 from emersion/redesign-resource-destroy

Redesign resource destruction
This commit is contained in:
Drew DeVault 2018-05-04 11:48:41 -04:00 committed by GitHub
commit 57d03a3eda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 516 additions and 182 deletions

View File

@ -171,7 +171,7 @@ Try to keep the use of macros to a minimum, especially if a function can do the
job. If you do need to use them, try to keep them close to where they're being job. If you do need to use them, try to keep them close to where they're being
used and `#undef` them after. used and `#undef` them after.
## Example ### Example
```c ```c
struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) { struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) {
@ -232,3 +232,125 @@ error_session:
return NULL; return NULL;
} }
``` ```
## Wayland protocol implementation
Each protocol generally lives in a file with the same name, usually containing
at leats one struct for each interface in the protocol. For instance,
`xdg_shell` lives in `types/wlr_xdg_shell.h` and has a `wlr_xdg_surface` struct.
### Globals
Global interfaces generally have public constructors and destructors. Their
struct has a field holding the `wl_global` itself, a list of resources clients
created by binding to the global, a destroy signal and a `wl_display` destroy
listener. Example:
```c
struct wlr_compositor {
struct wl_global *wl_global;
struct wl_list wl_resources;
struct wl_listener display_destroy;
struct {
struct wl_signal new_surface;
struct wl_signal destroy;
} events;
};
```
When the destructor is called, it should emit the destroy signal, remove the
display destroy listener, destroy the `wl_global`, destroy all bound resources
and then destroy the struct.
### Resources
Resources are the representation of Wayland objects on the compositor side. They
generally have an associated struct, called the _object struct_, stored in their
`user_data` field.
Object structs can be retrieved from resources via `wl_resource_get_data`. To
prevent bad casts, a safe helper function checking the type of the resource is
used:
```c
static const struct wl_surface_interface surface_impl;
struct wlr_surface *wlr_surface_from_resource(struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &wl_surface_interface,
&surface_impl));
return wl_resource_get_user_data(resource);
}
```
### Destroying resources
Object structs should only be destroyed when their resource is destroyed, ie.
in the resource destroy handler (set with `wl_resource_set_implementation`).
Destructor requests should only call `wl_resource_destroy`.
The compositor should not destroy resources on its own.
### Inert resources
Some resources can become inert in situations described in the protocol or when
the compositor decides to get rid of them. All requests made to inert resources
should be ignored, except the destructor. This is achieved by:
1. When the resource becomes inert: destroy the object struct and call
`wl_resource_set_user_data(resource, NULL)`. Do not destroy the resource.
2. For each request made to a resource that can be inert: add a NULL check to
ignore the request if the resource is inert.
3. When the client calls the destructor request on the resource: call
`wl_resource_destroy(resource)` as usual.
4. When the resource is destroyed, if the resource isn't inert, destroy the
object struct.
Example:
```c
// Handles the destroy request
static void subsurface_handle_destroy(struct wl_client *client,
struct wl_resource *resource) {
wl_resource_destroy(resource);
}
// Handles a regular request
static void subsurface_set_position(struct wl_client *client,
struct wl_resource *resource, int32_t x, int32_t y) {
struct wlr_subsurface *subsurface = subsurface_from_resource(resource);
if (subsurface == NULL) {
return;
}
}
// Destroys the wlr_subsurface struct
static void subsurface_destroy(struct wlr_subsurface *subsurface) {
if (subsurface == NULL) {
return;
}
wl_resource_set_user_data(subsurface->resource, NULL);
free(subsurface);
}
// Resource destroy listener
static void subsurface_handle_resource_destroy(struct wl_resource *resource) {
struct wlr_subsurface *subsurface = subsurface_from_resource(resource);
subsurface_destroy(subsurface);
}
// Makes the resource inert
static void subsurface_handle_surface_destroy(struct wl_listener *listener,
void *data) {
struct wlr_subsurface *subsurface =
wl_container_of(listener, subsurface, surface_destroy);
subsurface_destroy(subsurface);
}
```

View File

@ -18,7 +18,8 @@ struct wlr_data_offer *data_offer_create(struct wl_client *client,
void data_offer_update_action(struct wlr_data_offer *offer); void data_offer_update_action(struct wlr_data_offer *offer);
struct wlr_client_data_source *client_data_source_create( struct wlr_client_data_source *client_data_source_create(
struct wl_client *client, uint32_t version, uint32_t id); struct wl_client *client, uint32_t version, uint32_t id,
struct wl_list *resource_list);
struct wlr_client_data_source *client_data_source_from_resource( struct wlr_client_data_source *client_data_source_from_resource(
struct wl_resource *resource); struct wl_resource *resource);
struct wlr_data_offer *data_source_send_offer(struct wlr_data_source *source, struct wlr_data_offer *data_source_send_offer(struct wlr_data_source *source,

View File

@ -10,11 +10,14 @@ const struct wlr_touch_grab_interface default_touch_grab_impl;
void seat_client_create_pointer(struct wlr_seat_client *seat_client, void seat_client_create_pointer(struct wlr_seat_client *seat_client,
uint32_t version, uint32_t id); uint32_t version, uint32_t id);
void seat_client_destroy_pointer(struct wl_resource *resource);
void seat_client_create_keyboard(struct wlr_seat_client *seat_client, void seat_client_create_keyboard(struct wlr_seat_client *seat_client,
uint32_t version, uint32_t id); uint32_t version, uint32_t id);
void seat_client_destroy_keyboard(struct wl_resource *resource);
void seat_client_create_touch(struct wlr_seat_client *seat_client, void seat_client_create_touch(struct wlr_seat_client *seat_client,
uint32_t version, uint32_t id); uint32_t version, uint32_t id);
void seat_client_destroy_touch(struct wl_resource *resource);
#endif #endif

View File

@ -15,8 +15,16 @@ wlr_touch_grab_interface wlr_data_device_touch_drag_interface;
struct wlr_data_device_manager { struct wlr_data_device_manager {
struct wl_global *global; struct wl_global *global;
struct wl_list wl_resources;
struct wl_list data_sources;
struct wl_listener display_destroy; struct wl_listener display_destroy;
struct {
struct wl_signal destroy;
} events;
void *data;
}; };
struct wlr_data_offer { struct wlr_data_offer {

View File

@ -25,8 +25,7 @@ struct wlr_dmabuf_buffer_attribs {
uint64_t modifier[WLR_LINUX_DMABUF_MAX_PLANES]; uint64_t modifier[WLR_LINUX_DMABUF_MAX_PLANES];
int fd[WLR_LINUX_DMABUF_MAX_PLANES]; int fd[WLR_LINUX_DMABUF_MAX_PLANES];
/* set via params_create */ /* set via params_create */
int32_t width; int32_t width, height;
int32_t height;
uint32_t format; uint32_t format;
uint32_t flags; uint32_t flags;
}; };
@ -61,8 +60,15 @@ struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_params_resource(
/* the protocol interface */ /* the protocol interface */
struct wlr_linux_dmabuf { struct wlr_linux_dmabuf {
struct wl_global *wl_global; struct wl_global *wl_global;
struct wl_listener display_destroy;
struct wlr_renderer *renderer; struct wlr_renderer *renderer;
struct wl_list wl_resources;
struct {
struct wl_signal destroy;
} events;
struct wl_listener display_destroy;
struct wl_listener renderer_destroy;
}; };
/** /**

View File

@ -11,6 +11,8 @@
#include "types/wlr_data_device.h" #include "types/wlr_data_device.h"
#include "util/signal.h" #include "util/signal.h"
#define DATA_DEVICE_MANAGER_VERSION 3
static const struct wl_data_device_interface data_device_impl; static const struct wl_data_device_interface data_device_impl;
static struct wlr_seat_client *seat_client_from_data_device_resource( static struct wlr_seat_client *seat_client_from_data_device_resource(
@ -83,7 +85,7 @@ static const struct wl_data_device_interface data_device_impl = {
.release = data_device_release, .release = data_device_release,
}; };
static void data_device_destroy(struct wl_resource *resource) { static void data_device_handle_resource_destroy(struct wl_resource *resource) {
wl_list_remove(wl_resource_get_link(resource)); wl_list_remove(wl_resource_get_link(resource));
} }
@ -164,6 +166,15 @@ void wlr_seat_set_selection(struct wlr_seat *seat,
} }
static const struct wl_data_device_manager_interface data_device_manager_impl;
static struct wlr_data_device_manager *data_device_manager_from_resource(
struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &wl_data_device_manager_interface,
&data_device_manager_impl));
return wl_resource_get_user_data(resource);
}
static void data_device_manager_get_data_device(struct wl_client *client, static void data_device_manager_get_data_device(struct wl_client *client,
struct wl_resource *manager_resource, uint32_t id, struct wl_resource *manager_resource, uint32_t id,
struct wl_resource *seat_resource) { struct wl_resource *seat_resource) {
@ -178,13 +189,17 @@ static void data_device_manager_get_data_device(struct wl_client *client,
return; return;
} }
wl_resource_set_implementation(resource, &data_device_impl, seat_client, wl_resource_set_implementation(resource, &data_device_impl, seat_client,
&data_device_destroy); &data_device_handle_resource_destroy);
wl_list_insert(&seat_client->data_devices, wl_resource_get_link(resource)); wl_list_insert(&seat_client->data_devices, wl_resource_get_link(resource));
} }
static void data_device_manager_create_data_source(struct wl_client *client, static void data_device_manager_create_data_source(struct wl_client *client,
struct wl_resource *resource, uint32_t id) { struct wl_resource *manager_resource, uint32_t id) {
client_data_source_create(client, wl_resource_get_version(resource), id); struct wlr_data_device_manager *manager =
data_device_manager_from_resource(manager_resource);
client_data_source_create(client, wl_resource_get_version(manager_resource),
id, &manager->data_sources);
} }
static const struct wl_data_device_manager_interface static const struct wl_data_device_manager_interface
@ -193,8 +208,15 @@ static const struct wl_data_device_manager_interface
.get_data_device = data_device_manager_get_data_device, .get_data_device = data_device_manager_get_data_device,
}; };
static void data_device_manager_handle_resource_destroy(
struct wl_resource *resource) {
wl_list_remove(wl_resource_get_link(resource));
}
static void data_device_manager_bind(struct wl_client *client, static void data_device_manager_bind(struct wl_client *client,
void *data, uint32_t version, uint32_t id) { void *data, uint32_t version, uint32_t id) {
struct wlr_data_device_manager *manager = data;
struct wl_resource *resource = wl_resource_create(client, struct wl_resource *resource = wl_resource_create(client,
&wl_data_device_manager_interface, &wl_data_device_manager_interface,
version, id); version, id);
@ -202,18 +224,26 @@ static void data_device_manager_bind(struct wl_client *client,
wl_client_post_no_memory(client); wl_client_post_no_memory(client);
return; return;
} }
wl_resource_set_implementation(resource, &data_device_manager_impl, wl_resource_set_implementation(resource, &data_device_manager_impl,
NULL, NULL); manager, data_device_manager_handle_resource_destroy);
wl_list_insert(&manager->wl_resources, wl_resource_get_link(resource));
} }
void wlr_data_device_manager_destroy(struct wlr_data_device_manager *manager) { void wlr_data_device_manager_destroy(struct wlr_data_device_manager *manager) {
if (!manager) { if (!manager) {
return; return;
} }
wlr_signal_emit_safe(&manager->events.destroy, manager);
wl_list_remove(&manager->display_destroy.link); wl_list_remove(&manager->display_destroy.link);
// TODO: free wl_resources
wl_global_destroy(manager->global); wl_global_destroy(manager->global);
struct wl_resource *resource, *tmp;
wl_resource_for_each_safe(resource, tmp, &manager->wl_resources) {
wl_resource_destroy(resource);
}
wl_resource_for_each_safe(resource, tmp, &manager->data_sources) {
wl_resource_destroy(resource);
}
free(manager); free(manager);
} }
@ -232,11 +262,15 @@ struct wlr_data_device_manager *wlr_data_device_manager_create(
return NULL; return NULL;
} }
wl_list_init(&manager->wl_resources);
wl_list_init(&manager->data_sources);
wl_signal_init(&manager->events.destroy);
manager->global = manager->global =
wl_global_create(display, &wl_data_device_manager_interface, wl_global_create(display, &wl_data_device_manager_interface,
3, NULL, data_device_manager_bind); DATA_DEVICE_MANAGER_VERSION, manager, data_device_manager_bind);
if (!manager->global) { if (!manager->global) {
wlr_log(L_ERROR, "could not create data device manager wl global"); wlr_log(L_ERROR, "could not create data device manager wl_global");
free(manager); free(manager);
return NULL; return NULL;
} }

View File

@ -145,7 +145,7 @@ static void data_offer_set_actions(struct wl_client *client,
data_offer_update_action(offer); data_offer_update_action(offer);
} }
static void data_offer_resource_destroy(struct wl_resource *resource) { static void data_offer_handle_resource_destroy(struct wl_resource *resource) {
struct wlr_data_offer *offer = data_offer_from_resource(resource); struct wlr_data_offer *offer = data_offer_from_resource(resource);
if (!offer->source) { if (!offer->source) {
@ -208,7 +208,7 @@ struct wlr_data_offer *data_offer_create(struct wl_client *client,
return NULL; return NULL;
} }
wl_resource_set_implementation(offer->resource, &data_offer_impl, offer, wl_resource_set_implementation(offer->resource, &data_offer_impl, offer,
data_offer_resource_destroy); data_offer_handle_resource_destroy);
offer->source_destroy.notify = handle_offer_source_destroyed; offer->source_destroy.notify = handle_offer_source_destroyed;
wl_signal_add(&source->events.destroy, &offer->source_destroy); wl_signal_add(&source->events.destroy, &offer->source_destroy);

View File

@ -245,11 +245,13 @@ static void data_source_handle_resource_destroy(struct wl_resource *resource) {
struct wlr_client_data_source *source = struct wlr_client_data_source *source =
client_data_source_from_resource(resource); client_data_source_from_resource(resource);
wlr_data_source_finish(&source->source); wlr_data_source_finish(&source->source);
wl_list_remove(wl_resource_get_link(source->resource));
free(source); free(source);
} }
struct wlr_client_data_source *client_data_source_create( struct wlr_client_data_source *client_data_source_create(
struct wl_client *client, uint32_t version, uint32_t id) { struct wl_client *client, uint32_t version, uint32_t id,
struct wl_list *resource_list) {
struct wlr_client_data_source *source = struct wlr_client_data_source *source =
calloc(1, sizeof(struct wlr_client_data_source)); calloc(1, sizeof(struct wlr_client_data_source));
if (source == NULL) { if (source == NULL) {
@ -265,6 +267,7 @@ struct wlr_client_data_source *client_data_source_create(
} }
wl_resource_set_implementation(source->resource, &data_source_impl, wl_resource_set_implementation(source->resource, &data_source_impl,
source, data_source_handle_resource_destroy); source, data_source_handle_resource_destroy);
wl_list_insert(resource_list, wl_resource_get_link(source->resource));
source->impl.accept = client_data_source_accept; source->impl.accept = client_data_source_accept;
source->impl.send = client_data_source_send; source->impl.send = client_data_source_send;

View File

@ -12,11 +12,15 @@
#include "types/wlr_seat.h" #include "types/wlr_seat.h"
#include "util/signal.h" #include "util/signal.h"
#define SEAT_VERSION 6
static void seat_handle_get_pointer(struct wl_client *client, static void seat_handle_get_pointer(struct wl_client *client,
struct wl_resource *seat_resource, uint32_t id) { struct wl_resource *seat_resource, uint32_t id) {
struct wlr_seat_client *seat_client = struct wlr_seat_client *seat_client =
wlr_seat_client_from_resource(seat_resource); wlr_seat_client_from_resource(seat_resource);
if (!(seat_client->seat->capabilities & WL_SEAT_CAPABILITY_POINTER)) { if (!(seat_client->seat->capabilities & WL_SEAT_CAPABILITY_POINTER)) {
wlr_log(L_ERROR, "Client sent get_pointer on seat without the "
"pointer capability");
return; return;
} }
@ -29,6 +33,8 @@ static void seat_handle_get_keyboard(struct wl_client *client,
struct wlr_seat_client *seat_client = struct wlr_seat_client *seat_client =
wlr_seat_client_from_resource(seat_resource); wlr_seat_client_from_resource(seat_resource);
if (!(seat_client->seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD)) { if (!(seat_client->seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD)) {
wlr_log(L_ERROR, "Client sent get_keyboard on seat without the "
"keyboard capability");
return; return;
} }
@ -41,6 +47,8 @@ static void seat_handle_get_touch(struct wl_client *client,
struct wlr_seat_client *seat_client = struct wlr_seat_client *seat_client =
wlr_seat_client_from_resource(seat_resource); wlr_seat_client_from_resource(seat_resource);
if (!(seat_client->seat->capabilities & WL_SEAT_CAPABILITY_TOUCH)) { if (!(seat_client->seat->capabilities & WL_SEAT_CAPABILITY_TOUCH)) {
wlr_log(L_ERROR, "Client sent get_touch on seat without the "
"touch capability");
return; return;
} }
@ -48,7 +56,8 @@ static void seat_handle_get_touch(struct wl_client *client,
seat_client_create_touch(seat_client, version, id); seat_client_create_touch(seat_client, version, id);
} }
static void seat_client_resource_destroy(struct wl_resource *seat_resource) { static void seat_client_handle_resource_destroy(
struct wl_resource *seat_resource) {
struct wlr_seat_client *client = struct wlr_seat_client *client =
wlr_seat_client_from_resource(seat_resource); wlr_seat_client_from_resource(seat_resource);
wlr_signal_emit_safe(&client->events.destroy, client); wlr_signal_emit_safe(&client->events.destroy, client);
@ -120,7 +129,7 @@ static void seat_handle_bind(struct wl_client *client, void *_wlr_seat,
wl_list_init(&seat_client->data_devices); wl_list_init(&seat_client->data_devices);
wl_list_init(&seat_client->primary_selection_devices); wl_list_init(&seat_client->primary_selection_devices);
wl_resource_set_implementation(seat_client->wl_resource, &seat_impl, wl_resource_set_implementation(seat_client->wl_resource, &seat_impl,
seat_client, seat_client_resource_destroy); seat_client, seat_client_handle_resource_destroy);
wl_list_insert(&wlr_seat->clients, &seat_client->link); wl_list_insert(&wlr_seat->clients, &seat_client->link);
if (version >= WL_SEAT_NAME_SINCE_VERSION) { if (version >= WL_SEAT_NAME_SINCE_VERSION) {
wl_seat_send_name(seat_client->wl_resource, wlr_seat->name); wl_seat_send_name(seat_client->wl_resource, wlr_seat->name);
@ -170,41 +179,41 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) {
} }
struct wlr_seat *wlr_seat_create(struct wl_display *display, const char *name) { struct wlr_seat *wlr_seat_create(struct wl_display *display, const char *name) {
struct wlr_seat *wlr_seat = calloc(1, sizeof(struct wlr_seat)); struct wlr_seat *seat = calloc(1, sizeof(struct wlr_seat));
if (!wlr_seat) { if (!seat) {
return NULL; return NULL;
} }
// pointer state // pointer state
wlr_seat->pointer_state.seat = wlr_seat; seat->pointer_state.seat = seat;
wl_list_init(&wlr_seat->pointer_state.surface_destroy.link); wl_list_init(&seat->pointer_state.surface_destroy.link);
struct wlr_seat_pointer_grab *pointer_grab = struct wlr_seat_pointer_grab *pointer_grab =
calloc(1, sizeof(struct wlr_seat_pointer_grab)); calloc(1, sizeof(struct wlr_seat_pointer_grab));
if (!pointer_grab) { if (!pointer_grab) {
free(wlr_seat); free(seat);
return NULL; return NULL;
} }
pointer_grab->interface = &default_pointer_grab_impl; pointer_grab->interface = &default_pointer_grab_impl;
pointer_grab->seat = wlr_seat; pointer_grab->seat = seat;
wlr_seat->pointer_state.default_grab = pointer_grab; seat->pointer_state.default_grab = pointer_grab;
wlr_seat->pointer_state.grab = pointer_grab; seat->pointer_state.grab = pointer_grab;
// keyboard state // keyboard state
struct wlr_seat_keyboard_grab *keyboard_grab = struct wlr_seat_keyboard_grab *keyboard_grab =
calloc(1, sizeof(struct wlr_seat_keyboard_grab)); calloc(1, sizeof(struct wlr_seat_keyboard_grab));
if (!keyboard_grab) { if (!keyboard_grab) {
free(pointer_grab); free(pointer_grab);
free(wlr_seat); free(seat);
return NULL; return NULL;
} }
keyboard_grab->interface = &default_keyboard_grab_impl; keyboard_grab->interface = &default_keyboard_grab_impl;
keyboard_grab->seat = wlr_seat; keyboard_grab->seat = seat;
wlr_seat->keyboard_state.default_grab = keyboard_grab; seat->keyboard_state.default_grab = keyboard_grab;
wlr_seat->keyboard_state.grab = keyboard_grab; seat->keyboard_state.grab = keyboard_grab;
wlr_seat->keyboard_state.seat = wlr_seat; seat->keyboard_state.seat = seat;
wl_list_init(&wlr_seat->keyboard_state.surface_destroy.link); wl_list_init(&seat->keyboard_state.surface_destroy.link);
// touch state // touch state
struct wlr_seat_touch_grab *touch_grab = struct wlr_seat_touch_grab *touch_grab =
@ -212,57 +221,58 @@ struct wlr_seat *wlr_seat_create(struct wl_display *display, const char *name) {
if (!touch_grab) { if (!touch_grab) {
free(pointer_grab); free(pointer_grab);
free(keyboard_grab); free(keyboard_grab);
free(wlr_seat); free(seat);
return NULL; return NULL;
} }
touch_grab->interface = &default_touch_grab_impl; touch_grab->interface = &default_touch_grab_impl;
touch_grab->seat = wlr_seat; touch_grab->seat = seat;
wlr_seat->touch_state.default_grab = touch_grab; seat->touch_state.default_grab = touch_grab;
wlr_seat->touch_state.grab = touch_grab; seat->touch_state.grab = touch_grab;
wlr_seat->touch_state.seat = wlr_seat; seat->touch_state.seat = seat;
wl_list_init(&wlr_seat->touch_state.touch_points); wl_list_init(&seat->touch_state.touch_points);
struct wl_global *wl_global = wl_global_create(display, seat->wl_global = wl_global_create(display, &wl_seat_interface,
&wl_seat_interface, 6, wlr_seat, seat_handle_bind); SEAT_VERSION, seat, seat_handle_bind);
if (!wl_global) { if (seat->wl_global == NULL) {
free(wlr_seat); free(touch_grab);
free(pointer_grab);
free(keyboard_grab);
free(seat);
return NULL; return NULL;
} }
wlr_seat->wl_global = wl_global; seat->display = display;
wlr_seat->display = display; seat->name = strdup(name);
wlr_seat->name = strdup(name); wl_list_init(&seat->clients);
wl_list_init(&wlr_seat->clients); wl_list_init(&seat->drag_icons);
wl_list_init(&wlr_seat->drag_icons);
wl_signal_init(&wlr_seat->events.start_drag); wl_signal_init(&seat->events.start_drag);
wl_signal_init(&wlr_seat->events.new_drag_icon); wl_signal_init(&seat->events.new_drag_icon);
wl_signal_init(&wlr_seat->events.request_set_cursor); wl_signal_init(&seat->events.request_set_cursor);
wl_signal_init(&wlr_seat->events.selection); wl_signal_init(&seat->events.selection);
wl_signal_init(&wlr_seat->events.primary_selection); wl_signal_init(&seat->events.primary_selection);
wl_signal_init(&wlr_seat->events.pointer_grab_begin); wl_signal_init(&seat->events.pointer_grab_begin);
wl_signal_init(&wlr_seat->events.pointer_grab_end); wl_signal_init(&seat->events.pointer_grab_end);
wl_signal_init(&wlr_seat->events.keyboard_grab_begin); wl_signal_init(&seat->events.keyboard_grab_begin);
wl_signal_init(&wlr_seat->events.keyboard_grab_end); wl_signal_init(&seat->events.keyboard_grab_end);
wl_signal_init(&wlr_seat->events.touch_grab_begin); wl_signal_init(&seat->events.touch_grab_begin);
wl_signal_init(&wlr_seat->events.touch_grab_end); wl_signal_init(&seat->events.touch_grab_end);
wl_signal_init(&wlr_seat->events.destroy); wl_signal_init(&seat->events.destroy);
wlr_seat->display_destroy.notify = handle_display_destroy; seat->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &wlr_seat->display_destroy); wl_display_add_destroy_listener(display, &seat->display_destroy);
return wlr_seat; return seat;
} }
struct wlr_seat_client *wlr_seat_client_for_wl_client(struct wlr_seat *wlr_seat, struct wlr_seat_client *wlr_seat_client_for_wl_client(struct wlr_seat *wlr_seat,
struct wl_client *wl_client) { struct wl_client *wl_client) {
assert(wlr_seat);
struct wlr_seat_client *seat_client; struct wlr_seat_client *seat_client;
wl_list_for_each(seat_client, &wlr_seat->clients, link) { wl_list_for_each(seat_client, &wlr_seat->clients, link) {
if (seat_client->client == wl_client) { if (seat_client->client == wl_client) {
@ -275,8 +285,29 @@ struct wlr_seat_client *wlr_seat_client_for_wl_client(struct wlr_seat *wlr_seat,
void wlr_seat_set_capabilities(struct wlr_seat *wlr_seat, void wlr_seat_set_capabilities(struct wlr_seat *wlr_seat,
uint32_t capabilities) { uint32_t capabilities) {
wlr_seat->capabilities = capabilities; wlr_seat->capabilities = capabilities;
struct wlr_seat_client *client; struct wlr_seat_client *client;
wl_list_for_each(client, &wlr_seat->clients, link) { wl_list_for_each(client, &wlr_seat->clients, link) {
// Make resources inert if necessary
if ((capabilities & WL_SEAT_CAPABILITY_POINTER) == 0) {
struct wl_resource *resource, *tmp;
wl_resource_for_each_safe(resource, tmp, &client->pointers) {
seat_client_destroy_pointer(resource);
}
}
if ((capabilities & WL_SEAT_CAPABILITY_KEYBOARD) == 0) {
struct wl_resource *resource, *tmp;
wl_resource_for_each_safe(resource, tmp, &client->keyboards) {
seat_client_destroy_keyboard(resource);
}
}
if ((capabilities & WL_SEAT_CAPABILITY_TOUCH) == 0) {
struct wl_resource *resource, *tmp;
wl_resource_for_each_safe(resource, tmp, &client->touches) {
seat_client_destroy_touch(resource);
}
}
wl_seat_send_capabilities(client->wl_resource, capabilities); wl_seat_send_capabilities(client->wl_resource, capabilities);
} }
} }

View File

@ -48,8 +48,16 @@ static const struct wl_keyboard_interface keyboard_impl = {
.release = keyboard_release, .release = keyboard_release,
}; };
static struct wlr_seat_client *seat_client_from_keyboard_resource(
struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &wl_keyboard_interface,
&keyboard_impl));
return wl_resource_get_user_data(resource);
}
static void keyboard_handle_resource_destroy(struct wl_resource *resource) { static void keyboard_handle_resource_destroy(struct wl_resource *resource) {
wl_list_remove(wl_resource_get_link(resource)); wl_list_remove(wl_resource_get_link(resource));
seat_client_destroy_keyboard(resource);
} }
@ -63,6 +71,10 @@ void wlr_seat_keyboard_send_key(struct wlr_seat *wlr_seat, uint32_t time,
uint32_t serial = wl_display_next_serial(wlr_seat->display); uint32_t serial = wl_display_next_serial(wlr_seat->display);
struct wl_resource *resource; struct wl_resource *resource;
wl_resource_for_each(resource, &client->keyboards) { wl_resource_for_each(resource, &client->keyboards) {
if (seat_client_from_keyboard_resource(resource) == NULL) {
continue;
}
wl_keyboard_send_key(resource, serial, time, key, state); wl_keyboard_send_key(resource, serial, time, key, state);
} }
} }
@ -188,6 +200,10 @@ void wlr_seat_keyboard_send_modifiers(struct wlr_seat *seat,
uint32_t serial = wl_display_next_serial(seat->display); uint32_t serial = wl_display_next_serial(seat->display);
struct wl_resource *resource; struct wl_resource *resource;
wl_resource_for_each(resource, &client->keyboards) { wl_resource_for_each(resource, &client->keyboards) {
if (seat_client_from_keyboard_resource(resource) == NULL) {
continue;
}
if (modifiers == NULL) { if (modifiers == NULL) {
wl_keyboard_send_modifiers(resource, serial, 0, 0, 0, 0); wl_keyboard_send_modifiers(resource, serial, 0, 0, 0, 0);
} else { } else {
@ -223,6 +239,9 @@ void wlr_seat_keyboard_enter(struct wlr_seat *seat,
uint32_t serial = wl_display_next_serial(seat->display); uint32_t serial = wl_display_next_serial(seat->display);
struct wl_resource *resource; struct wl_resource *resource;
wl_resource_for_each(resource, &focused_client->keyboards) { wl_resource_for_each(resource, &focused_client->keyboards) {
if (seat_client_from_keyboard_resource(resource) == NULL) {
continue;
}
wl_keyboard_send_leave(resource, serial, focused_surface->resource); wl_keyboard_send_leave(resource, serial, focused_surface->resource);
} }
} }
@ -243,6 +262,9 @@ void wlr_seat_keyboard_enter(struct wlr_seat *seat,
uint32_t serial = wl_display_next_serial(seat->display); uint32_t serial = wl_display_next_serial(seat->display);
struct wl_resource *resource; struct wl_resource *resource;
wl_resource_for_each(resource, &client->keyboards) { wl_resource_for_each(resource, &client->keyboards) {
if (seat_client_from_keyboard_resource(resource) == NULL) {
continue;
}
wl_keyboard_send_enter(resource, serial, surface->resource, &keys); wl_keyboard_send_enter(resource, serial, surface->resource, &keys);
} }
wl_array_release(&keys); wl_array_release(&keys);
@ -312,6 +334,10 @@ static void seat_client_send_keymap(struct wlr_seat_client *client,
// keyboard // keyboard
struct wl_resource *resource; struct wl_resource *resource;
wl_resource_for_each(resource, &client->keyboards) { wl_resource_for_each(resource, &client->keyboards) {
if (seat_client_from_keyboard_resource(resource) == NULL) {
continue;
}
wl_keyboard_send_keymap(resource, wl_keyboard_send_keymap(resource,
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keyboard->keymap_fd, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keyboard->keymap_fd,
keyboard->keymap_size); keyboard->keymap_size);
@ -326,6 +352,10 @@ static void seat_client_send_repeat_info(struct wlr_seat_client *client,
struct wl_resource *resource; struct wl_resource *resource;
wl_resource_for_each(resource, &client->keyboards) { wl_resource_for_each(resource, &client->keyboards) {
if (seat_client_from_keyboard_resource(resource) == NULL) {
continue;
}
if (wl_resource_get_version(resource) >= if (wl_resource_get_version(resource) >=
WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) { WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
wl_keyboard_send_repeat_info(resource, wl_keyboard_send_repeat_info(resource,
@ -343,7 +373,7 @@ void seat_client_create_keyboard(struct wlr_seat_client *seat_client,
return; return;
} }
wl_resource_set_implementation(resource, &keyboard_impl, seat_client, wl_resource_set_implementation(resource, &keyboard_impl, seat_client,
&keyboard_handle_resource_destroy); keyboard_handle_resource_destroy);
wl_list_insert(&seat_client->keyboards, wl_resource_get_link(resource)); wl_list_insert(&seat_client->keyboards, wl_resource_get_link(resource));
struct wlr_keyboard *keyboard = seat_client->seat->keyboard_state.keyboard; struct wlr_keyboard *keyboard = seat_client->seat->keyboard_state.keyboard;
@ -353,3 +383,12 @@ void seat_client_create_keyboard(struct wlr_seat_client *seat_client,
// TODO possibly handle the case where this keyboard needs an enter // TODO possibly handle the case where this keyboard needs an enter
// right away // right away
} }
void seat_client_destroy_keyboard(struct wl_resource *resource) {
struct wlr_seat_client *seat_client =
seat_client_from_keyboard_resource(resource);
if (seat_client == NULL) {
return;
}
wl_resource_set_user_data(resource, NULL);
}

View File

@ -64,30 +64,27 @@ static void pointer_set_cursor(struct wl_client *client,
int32_t hotspot_x, int32_t hotspot_y) { int32_t hotspot_x, int32_t hotspot_y) {
struct wlr_seat_client *seat_client = struct wlr_seat_client *seat_client =
seat_client_from_pointer_resource(pointer_resource); seat_client_from_pointer_resource(pointer_resource);
if (seat_client == NULL) {
return;
}
struct wlr_surface *surface = NULL; struct wlr_surface *surface = NULL;
if (surface_resource != NULL) { if (surface_resource != NULL) {
surface = wlr_surface_from_resource(surface_resource); surface = wlr_surface_from_resource(surface_resource);
if (wlr_surface_set_role(surface, "wl_pointer-cursor", surface_resource, if (wlr_surface_set_role(surface, "wl_pointer-cursor", surface_resource,
WL_POINTER_ERROR_ROLE) < 0) { WL_POINTER_ERROR_ROLE) < 0) {
return; return;
} }
} }
struct wlr_seat_pointer_request_set_cursor_event *event = struct wlr_seat_pointer_request_set_cursor_event event = {
calloc(1, sizeof(struct wlr_seat_pointer_request_set_cursor_event)); .seat_client = seat_client,
if (event == NULL) { .surface = surface,
return; .serial = serial,
} .hotspot_x = hotspot_x,
event->seat_client = seat_client; .hotspot_y = hotspot_y,
event->surface = surface; };
event->serial = serial; wlr_signal_emit_safe(&seat_client->seat->events.request_set_cursor, &event);
event->hotspot_x = hotspot_x;
event->hotspot_y = hotspot_y;
wlr_signal_emit_safe(&seat_client->seat->events.request_set_cursor, event);
free(event);
} }
static void pointer_release(struct wl_client *client, static void pointer_release(struct wl_client *client,
@ -102,6 +99,7 @@ static const struct wl_pointer_interface pointer_impl = {
static void pointer_handle_resource_destroy(struct wl_resource *resource) { static void pointer_handle_resource_destroy(struct wl_resource *resource) {
wl_list_remove(wl_resource_get_link(resource)); wl_list_remove(wl_resource_get_link(resource));
seat_client_destroy_pointer(resource);
} }
@ -112,8 +110,8 @@ bool wlr_seat_pointer_surface_has_focus(struct wlr_seat *wlr_seat,
static void seat_pointer_handle_surface_destroy(struct wl_listener *listener, static void seat_pointer_handle_surface_destroy(struct wl_listener *listener,
void *data) { void *data) {
struct wlr_seat_pointer_state *state = wl_container_of( struct wlr_seat_pointer_state *state =
listener, state, surface_destroy); wl_container_of(listener, state, surface_destroy);
wl_list_remove(&state->surface_destroy.link); wl_list_remove(&state->surface_destroy.link);
wl_list_init(&state->surface_destroy.link); wl_list_init(&state->surface_destroy.link);
wlr_seat_pointer_clear_focus(state->seat); wlr_seat_pointer_clear_focus(state->seat);
@ -121,8 +119,6 @@ static void seat_pointer_handle_surface_destroy(struct wl_listener *listener,
void wlr_seat_pointer_enter(struct wlr_seat *wlr_seat, void wlr_seat_pointer_enter(struct wlr_seat *wlr_seat,
struct wlr_surface *surface, double sx, double sy) { struct wlr_surface *surface, double sx, double sy) {
assert(wlr_seat);
if (wlr_seat->pointer_state.focused_surface == surface) { if (wlr_seat->pointer_state.focused_surface == surface) {
// this surface already got an enter notify // this surface already got an enter notify
return; return;
@ -144,6 +140,10 @@ void wlr_seat_pointer_enter(struct wlr_seat *wlr_seat,
uint32_t serial = wl_display_next_serial(wlr_seat->display); uint32_t serial = wl_display_next_serial(wlr_seat->display);
struct wl_resource *resource; struct wl_resource *resource;
wl_resource_for_each(resource, &focused_client->pointers) { wl_resource_for_each(resource, &focused_client->pointers) {
if (seat_client_from_pointer_resource(resource) == NULL) {
continue;
}
wl_pointer_send_leave(resource, serial, focused_surface->resource); wl_pointer_send_leave(resource, serial, focused_surface->resource);
pointer_send_frame(resource); pointer_send_frame(resource);
} }
@ -154,6 +154,10 @@ void wlr_seat_pointer_enter(struct wlr_seat *wlr_seat,
uint32_t serial = wl_display_next_serial(wlr_seat->display); uint32_t serial = wl_display_next_serial(wlr_seat->display);
struct wl_resource *resource; struct wl_resource *resource;
wl_resource_for_each(resource, &client->pointers) { wl_resource_for_each(resource, &client->pointers) {
if (seat_client_from_pointer_resource(resource) == NULL) {
continue;
}
wl_pointer_send_enter(resource, serial, surface->resource, wl_pointer_send_enter(resource, serial, surface->resource,
wl_fixed_from_double(sx), wl_fixed_from_double(sy)); wl_fixed_from_double(sx), wl_fixed_from_double(sy));
pointer_send_frame(resource); pointer_send_frame(resource);
@ -189,6 +193,10 @@ void wlr_seat_pointer_send_motion(struct wlr_seat *wlr_seat, uint32_t time,
struct wl_resource *resource; struct wl_resource *resource;
wl_resource_for_each(resource, &client->pointers) { wl_resource_for_each(resource, &client->pointers) {
if (seat_client_from_pointer_resource(resource) == NULL) {
continue;
}
wl_pointer_send_motion(resource, time, wl_fixed_from_double(sx), wl_pointer_send_motion(resource, time, wl_fixed_from_double(sx),
wl_fixed_from_double(sy)); wl_fixed_from_double(sy));
pointer_send_frame(resource); pointer_send_frame(resource);
@ -205,6 +213,10 @@ uint32_t wlr_seat_pointer_send_button(struct wlr_seat *wlr_seat, uint32_t time,
uint32_t serial = wl_display_next_serial(wlr_seat->display); uint32_t serial = wl_display_next_serial(wlr_seat->display);
struct wl_resource *resource; struct wl_resource *resource;
wl_resource_for_each(resource, &client->pointers) { wl_resource_for_each(resource, &client->pointers) {
if (seat_client_from_pointer_resource(resource) == NULL) {
continue;
}
wl_pointer_send_button(resource, serial, time, button, state); wl_pointer_send_button(resource, serial, time, button, state);
pointer_send_frame(resource); pointer_send_frame(resource);
} }
@ -220,6 +232,10 @@ void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time,
struct wl_resource *resource; struct wl_resource *resource;
wl_resource_for_each(resource, &client->pointers) { wl_resource_for_each(resource, &client->pointers) {
if (seat_client_from_pointer_resource(resource) == NULL) {
continue;
}
if (value) { if (value) {
wl_pointer_send_axis(resource, time, orientation, wl_pointer_send_axis(resource, time, orientation,
wl_fixed_from_double(value)); wl_fixed_from_double(value));
@ -235,7 +251,6 @@ void wlr_seat_pointer_start_grab(struct wlr_seat *wlr_seat,
struct wlr_seat_pointer_grab *grab) { struct wlr_seat_pointer_grab *grab) {
assert(wlr_seat); assert(wlr_seat);
grab->seat = wlr_seat; grab->seat = wlr_seat;
assert(grab->seat);
wlr_seat->pointer_state.grab = grab; wlr_seat->pointer_state.grab = grab;
wlr_signal_emit_safe(&wlr_seat->events.pointer_grab_begin, grab); wlr_signal_emit_safe(&wlr_seat->events.pointer_grab_begin, grab);
@ -312,3 +327,12 @@ void seat_client_create_pointer(struct wlr_seat_client *seat_client,
&pointer_handle_resource_destroy); &pointer_handle_resource_destroy);
wl_list_insert(&seat_client->pointers, wl_resource_get_link(resource)); wl_list_insert(&seat_client->pointers, wl_resource_get_link(resource));
} }
void seat_client_destroy_pointer(struct wl_resource *resource) {
struct wlr_seat_client *seat_client =
seat_client_from_pointer_resource(resource);
if (seat_client == NULL) {
return;
}
wl_resource_set_user_data(resource, NULL);
}

View File

@ -9,8 +9,8 @@
#include "types/wlr_seat.h" #include "types/wlr_seat.h"
#include "util/signal.h" #include "util/signal.h"
static uint32_t default_touch_down(struct wlr_seat_touch_grab *grab, uint32_t time, static uint32_t default_touch_down(struct wlr_seat_touch_grab *grab,
struct wlr_touch_point *point) { uint32_t time, struct wlr_touch_point *point) {
return wlr_seat_touch_send_down(grab->seat, point->surface, time, return wlr_seat_touch_send_down(grab->seat, point->surface, time,
point->touch_id, point->sx, point->sy); point->touch_id, point->sx, point->sy);
} }
@ -57,6 +57,14 @@ static const struct wl_touch_interface touch_impl = {
static void touch_handle_resource_destroy(struct wl_resource *resource) { static void touch_handle_resource_destroy(struct wl_resource *resource) {
wl_list_remove(wl_resource_get_link(resource)); wl_list_remove(wl_resource_get_link(resource));
seat_client_destroy_touch(resource);
}
static struct wlr_seat_client *seat_client_from_touch_resource(
struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &wl_touch_interface,
&touch_impl));
return wl_resource_get_user_data(resource);
} }
@ -273,6 +281,9 @@ uint32_t wlr_seat_touch_send_down(struct wlr_seat *seat,
uint32_t serial = wl_display_next_serial(seat->display); uint32_t serial = wl_display_next_serial(seat->display);
struct wl_resource *resource; struct wl_resource *resource;
wl_resource_for_each(resource, &point->client->touches) { wl_resource_for_each(resource, &point->client->touches) {
if (seat_client_from_touch_resource(resource) == NULL) {
continue;
}
wl_touch_send_down(resource, serial, time, surface->resource, wl_touch_send_down(resource, serial, time, surface->resource,
touch_id, wl_fixed_from_double(sx), wl_fixed_from_double(sy)); touch_id, wl_fixed_from_double(sx), wl_fixed_from_double(sy));
wl_touch_send_frame(resource); wl_touch_send_frame(resource);
@ -291,6 +302,9 @@ void wlr_seat_touch_send_up(struct wlr_seat *seat, uint32_t time, int32_t touch_
uint32_t serial = wl_display_next_serial(seat->display); uint32_t serial = wl_display_next_serial(seat->display);
struct wl_resource *resource; struct wl_resource *resource;
wl_resource_for_each(resource, &point->client->touches) { wl_resource_for_each(resource, &point->client->touches) {
if (seat_client_from_touch_resource(resource) == NULL) {
continue;
}
wl_touch_send_up(resource, serial, time, touch_id); wl_touch_send_up(resource, serial, time, touch_id);
wl_touch_send_frame(resource); wl_touch_send_frame(resource);
} }
@ -306,6 +320,9 @@ void wlr_seat_touch_send_motion(struct wlr_seat *seat, uint32_t time, int32_t to
struct wl_resource *resource; struct wl_resource *resource;
wl_resource_for_each(resource, &point->client->touches) { wl_resource_for_each(resource, &point->client->touches) {
if (seat_client_from_touch_resource(resource) == NULL) {
continue;
}
wl_touch_send_motion(resource, time, touch_id, wl_fixed_from_double(sx), wl_touch_send_motion(resource, time, touch_id, wl_fixed_from_double(sx),
wl_fixed_from_double(sy)); wl_fixed_from_double(sy));
wl_touch_send_frame(resource); wl_touch_send_frame(resource);
@ -333,3 +350,12 @@ void seat_client_create_touch(struct wlr_seat_client *seat_client,
&touch_handle_resource_destroy); &touch_handle_resource_destroy);
wl_list_insert(&seat_client->touches, wl_resource_get_link(resource)); wl_list_insert(&seat_client->touches, wl_resource_get_link(resource));
} }
void seat_client_destroy_touch(struct wl_resource *resource) {
struct wlr_seat_client *seat_client =
seat_client_from_touch_resource(resource);
if (seat_client == NULL) {
return;
}
wl_resource_set_user_data(resource, NULL);
}

View File

@ -7,6 +7,9 @@
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include "util/signal.h" #include "util/signal.h"
#define COMPOSITOR_VERSION 4
#define SUBCOMPOSITOR_VERSION 1
static const char *subsurface_role = "wl_subsurface"; static const char *subsurface_role = "wl_subsurface";
bool wlr_surface_is_subsurface(struct wlr_surface *surface) { bool wlr_surface_is_subsurface(struct wlr_surface *surface) {
@ -105,7 +108,8 @@ static void subcompositor_bind(struct wl_client *client, void *data,
static void subcompositor_init(struct wlr_subcompositor *subcompositor, static void subcompositor_init(struct wlr_subcompositor *subcompositor,
struct wl_display *display) { struct wl_display *display) {
subcompositor->wl_global = wl_global_create(display, subcompositor->wl_global = wl_global_create(display,
&wl_subcompositor_interface, 1, subcompositor, subcompositor_bind); &wl_subcompositor_interface, SUBCOMPOSITOR_VERSION, subcompositor,
subcompositor_bind);
if (subcompositor->wl_global == NULL) { if (subcompositor->wl_global == NULL) {
wlr_log_errno(L_ERROR, "Could not allocate subcompositor global"); wlr_log_errno(L_ERROR, "Could not allocate subcompositor global");
return; return;
@ -136,7 +140,7 @@ static struct wlr_compositor *compositor_from_resource(
return wl_resource_get_user_data(resource); return wl_resource_get_user_data(resource);
} }
static void wl_compositor_create_surface(struct wl_client *client, static void compositor_create_surface(struct wl_client *client,
struct wl_resource *resource, uint32_t id) { struct wl_resource *resource, uint32_t id) {
struct wlr_compositor *compositor = compositor_from_resource(resource); struct wlr_compositor *compositor = compositor_from_resource(resource);
@ -150,7 +154,7 @@ static void wl_compositor_create_surface(struct wl_client *client,
wlr_signal_emit_safe(&compositor->events.new_surface, surface); wlr_signal_emit_safe(&compositor->events.new_surface, surface);
} }
static void wl_compositor_create_region(struct wl_client *client, static void compositor_create_region(struct wl_client *client,
struct wl_resource *resource, uint32_t id) { struct wl_resource *resource, uint32_t id) {
struct wlr_compositor *compositor = compositor_from_resource(resource); struct wlr_compositor *compositor = compositor_from_resource(resource);
@ -158,15 +162,15 @@ static void wl_compositor_create_region(struct wl_client *client,
} }
static const struct wl_compositor_interface compositor_impl = { static const struct wl_compositor_interface compositor_impl = {
.create_surface = wl_compositor_create_surface, .create_surface = compositor_create_surface,
.create_region = wl_compositor_create_region, .create_region = compositor_create_region,
}; };
static void compositor_resource_destroy(struct wl_resource *resource) { static void compositor_resource_destroy(struct wl_resource *resource) {
wl_list_remove(wl_resource_get_link(resource)); wl_list_remove(wl_resource_get_link(resource));
} }
static void wl_compositor_bind(struct wl_client *wl_client, void *data, static void compositor_bind(struct wl_client *wl_client, void *data,
uint32_t version, uint32_t id) { uint32_t version, uint32_t id) {
struct wlr_compositor *compositor = data; struct wlr_compositor *compositor = data;
assert(wl_client && compositor); assert(wl_client && compositor);
@ -218,14 +222,13 @@ struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
return NULL; return NULL;
} }
struct wl_global *compositor_global = wl_global_create(display, compositor->wl_global = wl_global_create(display, &wl_compositor_interface,
&wl_compositor_interface, 4, compositor, wl_compositor_bind); COMPOSITOR_VERSION, compositor, compositor_bind);
if (!compositor_global) { if (!compositor->wl_global) {
wlr_log_errno(L_ERROR, "Could not allocate compositor global");
free(compositor); free(compositor);
wlr_log_errno(L_ERROR, "Could not allocate compositor global");
return NULL; return NULL;
} }
compositor->wl_global = compositor_global;
compositor->renderer = renderer; compositor->renderer = renderer;
wl_list_init(&compositor->wl_resources); wl_list_init(&compositor->wl_resources);

View File

@ -7,19 +7,22 @@
#include <wlr/types/wlr_linux_dmabuf.h> #include <wlr/types/wlr_linux_dmabuf.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include "linux-dmabuf-unstable-v1-protocol.h" #include "linux-dmabuf-unstable-v1-protocol.h"
#include "util/signal.h"
static void wl_buffer_destroy(struct wl_client *client, #define LINUX_DMABUF_VERSION 3
static void buffer_handle_destroy(struct wl_client *client,
struct wl_resource *resource) { struct wl_resource *resource) {
wl_resource_destroy(resource); wl_resource_destroy(resource);
} }
static const struct wl_buffer_interface wl_buffer_impl = { static const struct wl_buffer_interface buffer_impl = {
wl_buffer_destroy, .destroy = buffer_handle_destroy,
}; };
bool wlr_dmabuf_resource_is_buffer(struct wl_resource *buffer_resource) { bool wlr_dmabuf_resource_is_buffer(struct wl_resource *buffer_resource) {
if (!wl_resource_instance_of(buffer_resource, &wl_buffer_interface, if (!wl_resource_instance_of(buffer_resource, &wl_buffer_interface,
&wl_buffer_impl)) { &buffer_impl)) {
return false; return false;
} }
@ -36,7 +39,7 @@ bool wlr_dmabuf_resource_is_buffer(struct wl_resource *buffer_resource) {
struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_buffer_resource( struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_buffer_resource(
struct wl_resource *buffer_resource) { struct wl_resource *buffer_resource) {
assert(wl_resource_instance_of(buffer_resource, &wl_buffer_interface, assert(wl_resource_instance_of(buffer_resource, &wl_buffer_interface,
&wl_buffer_impl)); &buffer_impl));
struct wlr_dmabuf_buffer *buffer = struct wlr_dmabuf_buffer *buffer =
wl_resource_get_user_data(buffer_resource); wl_resource_get_user_data(buffer_resource);
@ -103,11 +106,9 @@ static void params_add(struct wl_client *client,
buffer->attributes.n_planes++; buffer->attributes.n_planes++;
} }
static void handle_buffer_destroy(struct wl_resource *buffer_resource) static void buffer_handle_resource_destroy(struct wl_resource *buffer_resource) {
{
struct wlr_dmabuf_buffer *buffer = struct wlr_dmabuf_buffer *buffer =
wlr_dmabuf_buffer_from_buffer_resource(buffer_resource); wlr_dmabuf_buffer_from_buffer_resource(buffer_resource);
linux_dmabuf_buffer_destroy(buffer); linux_dmabuf_buffer_destroy(buffer);
} }
@ -144,7 +145,7 @@ static void params_create_common(struct wl_client *client,
if ((buffer->attributes.fd[3] >= 0 || buffer->attributes.fd[2] >= 0) && if ((buffer->attributes.fd[3] >= 0 || buffer->attributes.fd[2] >= 0) &&
(buffer->attributes.fd[2] == -1 || buffer->attributes.fd[1] == -1)) { (buffer->attributes.fd[2] == -1 || buffer->attributes.fd[1] == -1)) {
wl_resource_post_error (params_resource, wl_resource_post_error(params_resource,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE,
"gap in dmabuf planes"); "gap in dmabuf planes");
goto err_out; goto err_out;
@ -229,7 +230,7 @@ static void params_create_common(struct wl_client *client,
} }
wl_resource_set_implementation(buffer->buffer_resource, wl_resource_set_implementation(buffer->buffer_resource,
&wl_buffer_impl, buffer, handle_buffer_destroy); &buffer_impl, buffer, buffer_handle_resource_destroy);
/* send 'created' event when the request is not for an immediate /* send 'created' event when the request is not for an immediate
* import, that is buffer_id is zero */ * import, that is buffer_id is zero */
@ -324,8 +325,7 @@ static void linux_dmabuf_create_params(struct wl_client *client,
buffer->renderer = linux_dmabuf->renderer; buffer->renderer = linux_dmabuf->renderer;
buffer->params_resource = wl_resource_create(client, buffer->params_resource = wl_resource_create(client,
&zwp_linux_buffer_params_v1_interface, &zwp_linux_buffer_params_v1_interface, version, params_id);
version, params_id);
if (!buffer->params_resource) { if (!buffer->params_resource) {
goto err_free; goto err_free;
} }
@ -400,6 +400,10 @@ static void linux_dmabuf_send_modifiers(struct wlr_linux_dmabuf *linux_dmabuf,
free(formats); free(formats);
} }
static void linux_dmabuf_resource_destroy(struct wl_resource *resource) {
wl_list_remove(wl_resource_get_link(resource));
}
static void linux_dmabuf_bind(struct wl_client *client, void *data, static void linux_dmabuf_bind(struct wl_client *client, void *data,
uint32_t version, uint32_t id) { uint32_t version, uint32_t id) {
struct wlr_linux_dmabuf *linux_dmabuf = data; struct wlr_linux_dmabuf *linux_dmabuf = data;
@ -410,21 +414,29 @@ static void linux_dmabuf_bind(struct wl_client *client, void *data,
wl_client_post_no_memory(client); wl_client_post_no_memory(client);
return; return;
} }
wl_resource_set_implementation(resource, &linux_dmabuf_impl, wl_resource_set_implementation(resource, &linux_dmabuf_impl,
linux_dmabuf, NULL); linux_dmabuf, linux_dmabuf_resource_destroy);
if (version < ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) { wl_list_insert(&linux_dmabuf->wl_resources, wl_resource_get_link(resource));
return;
}
if (version >= ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) {
linux_dmabuf_send_modifiers(linux_dmabuf, resource); linux_dmabuf_send_modifiers(linux_dmabuf, resource);
}
} }
void wlr_linux_dmabuf_destroy(struct wlr_linux_dmabuf *linux_dmabuf) { void wlr_linux_dmabuf_destroy(struct wlr_linux_dmabuf *linux_dmabuf) {
if (!linux_dmabuf) { if (!linux_dmabuf) {
return; return;
} }
wlr_signal_emit_safe(&linux_dmabuf->events.destroy, linux_dmabuf);
wl_list_remove(&linux_dmabuf->display_destroy.link); wl_list_remove(&linux_dmabuf->display_destroy.link);
wl_list_remove(&linux_dmabuf->renderer_destroy.link);
struct wl_resource *resource, *tmp;
wl_resource_for_each_safe(resource, tmp, &linux_dmabuf->wl_resources) {
wl_resource_destroy(resource);
}
wl_global_destroy(linux_dmabuf->wl_global); wl_global_destroy(linux_dmabuf->wl_global);
free(linux_dmabuf); free(linux_dmabuf);
@ -436,6 +448,12 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) {
wlr_linux_dmabuf_destroy(linux_dmabuf); wlr_linux_dmabuf_destroy(linux_dmabuf);
} }
static void handle_renderer_destroy(struct wl_listener *listener, void *data) {
struct wlr_linux_dmabuf *linux_dmabuf =
wl_container_of(listener, linux_dmabuf, renderer_destroy);
wlr_linux_dmabuf_destroy(linux_dmabuf);
}
struct wlr_linux_dmabuf *wlr_linux_dmabuf_create(struct wl_display *display, struct wlr_linux_dmabuf *wlr_linux_dmabuf_create(struct wl_display *display,
struct wlr_renderer *renderer) { struct wlr_renderer *renderer) {
struct wlr_linux_dmabuf *linux_dmabuf = struct wlr_linux_dmabuf *linux_dmabuf =
@ -446,9 +464,12 @@ struct wlr_linux_dmabuf *wlr_linux_dmabuf_create(struct wl_display *display,
} }
linux_dmabuf->renderer = renderer; linux_dmabuf->renderer = renderer;
wl_list_init(&linux_dmabuf->wl_resources);
wl_signal_init(&linux_dmabuf->events.destroy);
linux_dmabuf->wl_global = linux_dmabuf->wl_global =
wl_global_create(display, &zwp_linux_dmabuf_v1_interface, wl_global_create(display, &zwp_linux_dmabuf_v1_interface,
3, linux_dmabuf, linux_dmabuf_bind); LINUX_DMABUF_VERSION, linux_dmabuf, linux_dmabuf_bind);
if (!linux_dmabuf->wl_global) { if (!linux_dmabuf->wl_global) {
wlr_log(L_ERROR, "could not create linux dmabuf v1 wl global"); wlr_log(L_ERROR, "could not create linux dmabuf v1 wl global");
free(linux_dmabuf); free(linux_dmabuf);
@ -458,5 +479,8 @@ struct wlr_linux_dmabuf *wlr_linux_dmabuf_create(struct wl_display *display,
linux_dmabuf->display_destroy.notify = handle_display_destroy; linux_dmabuf->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &linux_dmabuf->display_destroy); wl_display_add_destroy_listener(display, &linux_dmabuf->display_destroy);
linux_dmabuf->renderer_destroy.notify = handle_renderer_destroy;
wl_signal_add(&renderer->events.destroy, &linux_dmabuf->renderer_destroy);
return linux_dmabuf; return linux_dmabuf;
} }

View File

@ -7,15 +7,17 @@
#include <wayland-server.h> #include <wayland-server.h>
#include <wlr/interfaces/wlr_output.h> #include <wlr/interfaces/wlr_output.h>
#include <wlr/render/wlr_renderer.h> #include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_box.h> #include <wlr/types/wlr_box.h>
#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_output.h> #include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_surface.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include <wlr/util/region.h> #include <wlr/util/region.h>
#include "util/signal.h" #include "util/signal.h"
static void wl_output_send_to_resource(struct wl_resource *resource) { #define OUTPUT_VERSION 3
static void output_send_to_resource(struct wl_resource *resource) {
struct wlr_output *output = wlr_output_from_resource(resource); struct wlr_output *output = wlr_output_from_resource(resource);
const uint32_t version = wl_resource_get_version(resource); const uint32_t version = wl_resource_get_version(resource);
if (version >= WL_OUTPUT_GEOMETRY_SINCE_VERSION) { if (version >= WL_OUTPUT_GEOMETRY_SINCE_VERSION) {
@ -70,42 +72,33 @@ static void output_send_current_mode_to_resource(
} }
} }
static void wl_output_destroy(struct wl_resource *resource) { static void output_handle_resource_destroy(struct wl_resource *resource) {
struct wlr_output *output = wlr_output_from_resource(resource); wl_list_remove(wl_resource_get_link(resource));
struct wl_resource *_resource;
wl_resource_for_each(_resource, &output->wl_resources) {
if (_resource == resource) {
struct wl_list *link = wl_resource_get_link(_resource);
wl_list_remove(link);
break;
}
}
} }
static void wl_output_release(struct wl_client *client, static void output_handle_release(struct wl_client *client,
struct wl_resource *resource) { struct wl_resource *resource) {
wl_resource_destroy(resource); wl_resource_destroy(resource);
} }
static struct wl_output_interface wl_output_impl = { static const struct wl_output_interface output_impl = {
.release = wl_output_release, .release = output_handle_release,
}; };
static void wl_output_bind(struct wl_client *wl_client, void *data, static void wl_output_bind(struct wl_client *wl_client, void *data,
uint32_t version, uint32_t id) { uint32_t version, uint32_t id) {
struct wlr_output *wlr_output = data; struct wlr_output *wlr_output = data;
struct wl_resource *wl_resource = wl_resource_create(wl_client, struct wl_resource *resource = wl_resource_create(wl_client,
&wl_output_interface, version, id); &wl_output_interface, version, id);
if (wl_resource == NULL) { if (resource == NULL) {
wl_client_post_no_memory(wl_client); wl_client_post_no_memory(wl_client);
return; return;
} }
wl_resource_set_implementation(wl_resource, &wl_output_impl, wlr_output, wl_resource_set_implementation(resource, &output_impl, wlr_output,
wl_output_destroy); output_handle_resource_destroy);
wl_list_insert(&wlr_output->wl_resources, wl_list_insert(&wlr_output->wl_resources, wl_resource_get_link(resource));
wl_resource_get_link(wl_resource)); output_send_to_resource(resource);
wl_output_send_to_resource(wl_resource);
} }
void wlr_output_create_global(struct wlr_output *output) { void wlr_output_create_global(struct wlr_output *output) {
@ -113,7 +106,7 @@ void wlr_output_create_global(struct wlr_output *output) {
return; return;
} }
struct wl_global *wl_global = wl_global_create(output->display, struct wl_global *wl_global = wl_global_create(output->display,
&wl_output_interface, 3, output, wl_output_bind); &wl_output_interface, OUTPUT_VERSION, output, wl_output_bind);
output->wl_global = wl_global; output->wl_global = wl_global;
} }
@ -205,7 +198,7 @@ void wlr_output_set_transform(struct wlr_output *output,
// TODO: only send geometry and done // TODO: only send geometry and done
struct wl_resource *resource; struct wl_resource *resource;
wl_resource_for_each(resource, &output->wl_resources) { wl_resource_for_each(resource, &output->wl_resources) {
wl_output_send_to_resource(resource); output_send_to_resource(resource);
} }
wlr_signal_emit_safe(&output->events.transform, output); wlr_signal_emit_safe(&output->events.transform, output);
@ -223,7 +216,7 @@ void wlr_output_set_position(struct wlr_output *output, int32_t lx,
// TODO: only send geometry and done // TODO: only send geometry and done
struct wl_resource *resource; struct wl_resource *resource;
wl_resource_for_each(resource, &output->wl_resources) { wl_resource_for_each(resource, &output->wl_resources) {
wl_output_send_to_resource(resource); output_send_to_resource(resource);
} }
} }
@ -237,7 +230,7 @@ void wlr_output_set_scale(struct wlr_output *output, float scale) {
// TODO: only send mode and done // TODO: only send mode and done
struct wl_resource *resource; struct wl_resource *resource;
wl_resource_for_each(resource, &output->wl_resources) { wl_resource_for_each(resource, &output->wl_resources) {
wl_output_send_to_resource(resource); output_send_to_resource(resource);
} }
wlr_signal_emit_safe(&output->events.scale, output); wlr_signal_emit_safe(&output->events.scale, output);
@ -649,7 +642,7 @@ void wlr_output_set_fullscreen_surface(struct wlr_output *output,
struct wlr_output *wlr_output_from_resource(struct wl_resource *resource) { struct wlr_output *wlr_output_from_resource(struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &wl_output_interface, assert(wl_resource_instance_of(resource, &wl_output_interface,
&wl_output_impl)); &output_impl));
return wl_resource_get_user_data(resource); return wl_resource_get_user_data(resource);
} }

View File

@ -11,6 +11,10 @@
#include <wlr/util/region.h> #include <wlr/util/region.h>
#include "util/signal.h" #include "util/signal.h"
#define CALLBACK_VERSION 1
#define SURFACE_VERSION 4
#define SUBSURFACE_VERSION 1
static void surface_state_reset_buffer(struct wlr_surface_state *state) { static void surface_state_reset_buffer(struct wlr_surface_state *state) {
if (state->buffer) { if (state->buffer) {
wl_list_remove(&state->buffer_destroy_listener.link); wl_list_remove(&state->buffer_destroy_listener.link);
@ -18,29 +22,29 @@ static void surface_state_reset_buffer(struct wlr_surface_state *state) {
} }
} }
static void buffer_destroy(struct wl_listener *listener, void *data) { static void surface_handle_buffer_destroy(struct wl_listener *listener,
void *data) {
struct wlr_surface_state *state = struct wlr_surface_state *state =
wl_container_of(listener, state, buffer_destroy_listener); wl_container_of(listener, state, buffer_destroy_listener);
surface_state_reset_buffer(state);
wl_list_remove(&state->buffer_destroy_listener.link);
state->buffer = NULL;
} }
static void surface_state_release_buffer(struct wlr_surface_state *state) { static void surface_state_release_buffer(struct wlr_surface_state *state) {
if (state->buffer) { if (state->buffer) {
wl_resource_post_event(state->buffer, WL_BUFFER_RELEASE); wl_resource_post_event(state->buffer, WL_BUFFER_RELEASE);
wl_list_remove(&state->buffer_destroy_listener.link); surface_state_reset_buffer(state);
state->buffer = NULL;
} }
} }
static void surface_state_set_buffer(struct wlr_surface_state *state, static void surface_state_set_buffer(struct wlr_surface_state *state,
struct wl_resource *buffer) { struct wl_resource *buffer) {
surface_state_reset_buffer(state);
state->buffer = buffer; state->buffer = buffer;
if (buffer) { if (buffer) {
wl_resource_add_destroy_listener(buffer, wl_resource_add_destroy_listener(buffer,
&state->buffer_destroy_listener); &state->buffer_destroy_listener);
state->buffer_destroy_listener.notify = buffer_destroy; state->buffer_destroy_listener.notify = surface_handle_buffer_destroy;
} }
} }
@ -57,7 +61,6 @@ static void surface_attach(struct wl_client *client,
surface->pending->invalid |= WLR_SURFACE_INVALID_BUFFER; surface->pending->invalid |= WLR_SURFACE_INVALID_BUFFER;
surface->pending->sx = sx; surface->pending->sx = sx;
surface->pending->sy = sy; surface->pending->sy = sy;
surface_state_reset_buffer(surface->pending);
surface_state_set_buffer(surface->pending, buffer); surface_state_set_buffer(surface->pending, buffer);
} }
@ -80,7 +83,7 @@ static struct wlr_frame_callback *frame_callback_from_resource(
return wl_resource_get_user_data(resource); return wl_resource_get_user_data(resource);
} }
static void destroy_frame_callback(struct wl_resource *resource) { static void callback_handle_resource_destroy(struct wl_resource *resource) {
struct wlr_frame_callback *cb = frame_callback_from_resource(resource); struct wlr_frame_callback *cb = frame_callback_from_resource(resource);
wl_list_remove(&cb->link); wl_list_remove(&cb->link);
free(cb); free(cb);
@ -97,16 +100,15 @@ static void surface_frame(struct wl_client *client,
return; return;
} }
cb->resource = wl_resource_create(client, &wl_callback_interface, 1, cb->resource = wl_resource_create(client, &wl_callback_interface,
callback); CALLBACK_VERSION, callback);
if (cb->resource == NULL) { if (cb->resource == NULL) {
free(cb); free(cb);
wl_resource_post_no_memory(resource); wl_resource_post_no_memory(resource);
return; return;
} }
wl_resource_set_implementation(cb->resource, NULL, cb, wl_resource_set_implementation(cb->resource, NULL, cb,
destroy_frame_callback); callback_handle_resource_destroy);
wl_list_insert(surface->pending->frame_callback_list.prev, &cb->link); wl_list_insert(surface->pending->frame_callback_list.prev, &cb->link);
@ -548,7 +550,7 @@ static void surface_damage_buffer(struct wl_client *client,
x, y, width, height); x, y, width, height);
} }
const struct wl_surface_interface surface_interface = { static const struct wl_surface_interface surface_interface = {
.destroy = surface_destroy, .destroy = surface_destroy,
.attach = surface_attach, .attach = surface_attach,
.damage = surface_damage, .damage = surface_damage,
@ -584,7 +586,6 @@ static struct wlr_surface_state *surface_state_create() {
pixman_region32_init_rect(&state->input, pixman_region32_init_rect(&state->input,
INT32_MIN, INT32_MIN, UINT32_MAX, UINT32_MAX); INT32_MIN, INT32_MIN, UINT32_MAX, UINT32_MAX);
return state; return state;
} }
@ -604,6 +605,10 @@ static void surface_state_destroy(struct wlr_surface_state *state) {
} }
static void subsurface_destroy(struct wlr_subsurface *subsurface) { static void subsurface_destroy(struct wlr_subsurface *subsurface) {
if (subsurface == NULL) {
return;
}
wlr_signal_emit_safe(&subsurface->events.destroy, subsurface); wlr_signal_emit_safe(&subsurface->events.destroy, subsurface);
wl_list_remove(&subsurface->surface_destroy.link); wl_list_remove(&subsurface->surface_destroy.link);
@ -615,8 +620,6 @@ static void subsurface_destroy(struct wlr_subsurface *subsurface) {
wl_list_remove(&subsurface->parent_destroy.link); wl_list_remove(&subsurface->parent_destroy.link);
} }
wl_list_remove(wl_resource_get_link(subsurface->resource));
wl_resource_set_user_data(subsurface->resource, NULL); wl_resource_set_user_data(subsurface->resource, NULL);
if (subsurface->surface) { if (subsurface->surface) {
subsurface->surface->role_data = NULL; subsurface->surface->role_data = NULL;
@ -649,6 +652,8 @@ static void surface_handle_renderer_destroy(struct wl_listener *listener,
struct wlr_surface *wlr_surface_create(struct wl_client *client, struct wlr_surface *wlr_surface_create(struct wl_client *client,
uint32_t version, uint32_t id, struct wlr_renderer *renderer, uint32_t version, uint32_t id, struct wlr_renderer *renderer,
struct wl_list *resource_list) { struct wl_list *resource_list) {
assert(version <= SURFACE_VERSION);
struct wlr_surface *surface = calloc(1, sizeof(struct wlr_surface)); struct wlr_surface *surface = calloc(1, sizeof(struct wlr_surface));
if (!surface) { if (!surface) {
wl_client_post_no_memory(client); wl_client_post_no_memory(client);
@ -726,10 +731,8 @@ static struct wlr_subsurface *subsurface_from_resource(
static void subsurface_resource_destroy(struct wl_resource *resource) { static void subsurface_resource_destroy(struct wl_resource *resource) {
struct wlr_subsurface *subsurface = subsurface_from_resource(resource); struct wlr_subsurface *subsurface = subsurface_from_resource(resource);
wl_list_remove(wl_resource_get_link(resource));
if (subsurface) {
subsurface_destroy(subsurface); subsurface_destroy(subsurface);
}
} }
static void subsurface_handle_destroy(struct wl_client *client, static void subsurface_handle_destroy(struct wl_client *client,
@ -737,13 +740,15 @@ static void subsurface_handle_destroy(struct wl_client *client,
wl_resource_destroy(resource); wl_resource_destroy(resource);
} }
static void subsurface_set_position(struct wl_client *client, static void subsurface_handle_set_position(struct wl_client *client,
struct wl_resource *resource, int32_t x, int32_t y) { struct wl_resource *resource, int32_t x, int32_t y) {
struct wlr_subsurface *subsurface = subsurface_from_resource(resource); struct wlr_subsurface *subsurface = subsurface_from_resource(resource);
if (subsurface == NULL) {
return;
}
struct wlr_surface *surface = subsurface->surface; struct wlr_surface *surface = subsurface->surface;
surface->pending->invalid |= WLR_SURFACE_INVALID_SUBSURFACE_POSITION; surface->pending->invalid |= WLR_SURFACE_INVALID_SUBSURFACE_POSITION;
surface->pending->subsurface_position.x = x; surface->pending->subsurface_position.x = x;
surface->pending->subsurface_position.y = y; surface->pending->subsurface_position.y = y;
} }
@ -762,9 +767,12 @@ static struct wlr_subsurface *subsurface_find_sibling(
return NULL; return NULL;
} }
static void subsurface_place_above(struct wl_client *client, static void subsurface_handle_place_above(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *sibling_resource) { struct wl_resource *resource, struct wl_resource *sibling_resource) {
struct wlr_subsurface *subsurface = subsurface_from_resource(resource); struct wlr_subsurface *subsurface = subsurface_from_resource(resource);
if (subsurface == NULL) {
return;
}
struct wlr_surface *sibling_surface = struct wlr_surface *sibling_surface =
wlr_surface_from_resource(sibling_resource); wlr_surface_from_resource(sibling_resource);
@ -786,9 +794,12 @@ static void subsurface_place_above(struct wl_client *client,
subsurface->reordered = true; subsurface->reordered = true;
} }
static void subsurface_place_below(struct wl_client *client, static void subsurface_handle_place_below(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *sibling_resource) { struct wl_resource *resource, struct wl_resource *sibling_resource) {
struct wlr_subsurface *subsurface = subsurface_from_resource(resource); struct wlr_subsurface *subsurface = subsurface_from_resource(resource);
if (subsurface == NULL) {
return;
}
struct wlr_surface *sibling_surface = struct wlr_surface *sibling_surface =
wlr_surface_from_resource(sibling_resource); wlr_surface_from_resource(sibling_resource);
@ -810,20 +821,24 @@ static void subsurface_place_below(struct wl_client *client,
subsurface->reordered = true; subsurface->reordered = true;
} }
static void subsurface_set_sync(struct wl_client *client, static void subsurface_handle_set_sync(struct wl_client *client,
struct wl_resource *resource) { struct wl_resource *resource) {
struct wlr_subsurface *subsurface = subsurface_from_resource(resource); struct wlr_subsurface *subsurface = subsurface_from_resource(resource);
if (subsurface == NULL) {
if (subsurface) { return;
subsurface->synchronized = true;
} }
subsurface->synchronized = true;
} }
static void subsurface_set_desync(struct wl_client *client, static void subsurface_handle_set_desync(struct wl_client *client,
struct wl_resource *resource) { struct wl_resource *resource) {
struct wlr_subsurface *subsurface = subsurface_from_resource(resource); struct wlr_subsurface *subsurface = subsurface_from_resource(resource);
if (subsurface == NULL) {
return;
}
if (subsurface && subsurface->synchronized) { if (subsurface->synchronized) {
subsurface->synchronized = false; subsurface->synchronized = false;
if (!subsurface_is_synchronized(subsurface)) { if (!subsurface_is_synchronized(subsurface)) {
@ -835,11 +850,11 @@ static void subsurface_set_desync(struct wl_client *client,
static const struct wl_subsurface_interface subsurface_implementation = { static const struct wl_subsurface_interface subsurface_implementation = {
.destroy = subsurface_handle_destroy, .destroy = subsurface_handle_destroy,
.set_position = subsurface_set_position, .set_position = subsurface_handle_set_position,
.place_above = subsurface_place_above, .place_above = subsurface_handle_place_above,
.place_below = subsurface_place_below, .place_below = subsurface_handle_place_below,
.set_sync = subsurface_set_sync, .set_sync = subsurface_handle_set_sync,
.set_desync = subsurface_set_desync, .set_desync = subsurface_handle_set_desync,
}; };
static void subsurface_handle_parent_destroy(struct wl_listener *listener, static void subsurface_handle_parent_destroy(struct wl_listener *listener,
@ -862,6 +877,8 @@ static void subsurface_handle_surface_destroy(struct wl_listener *listener,
struct wlr_subsurface *wlr_subsurface_create(struct wlr_surface *surface, struct wlr_subsurface *wlr_subsurface_create(struct wlr_surface *surface,
struct wlr_surface *parent, uint32_t version, uint32_t id, struct wlr_surface *parent, uint32_t version, uint32_t id,
struct wl_list *resource_list) { struct wl_list *resource_list) {
assert(version <= SUBSURFACE_VERSION);
struct wl_client *client = wl_resource_get_client(surface->resource); struct wl_client *client = wl_resource_get_client(surface->resource);
struct wlr_subsurface *subsurface = struct wlr_subsurface *subsurface =