mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-11-09 13:29:46 -05:00
types/wlr_compositor: Change to new design
- wlr_surface and wlr_region are bundled into the same file - Allows extensions to add state to wl_surface commits Old surface code has not been removed yet.
This commit is contained in:
parent
cf3b083c32
commit
e76d4581ce
12 changed files with 619 additions and 261 deletions
|
|
@ -31,7 +31,6 @@ install_headers(
|
||||||
'wlr_presentation_time.h',
|
'wlr_presentation_time.h',
|
||||||
'wlr_primary_selection_v1.h',
|
'wlr_primary_selection_v1.h',
|
||||||
'wlr_primary_selection.h',
|
'wlr_primary_selection.h',
|
||||||
'wlr_region.h',
|
|
||||||
'wlr_relative_pointer_v1.h',
|
'wlr_relative_pointer_v1.h',
|
||||||
'wlr_screencopy_v1.h',
|
'wlr_screencopy_v1.h',
|
||||||
'wlr_screenshooter.h',
|
'wlr_screenshooter.h',
|
||||||
|
|
|
||||||
|
|
@ -12,34 +12,105 @@
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
#include <wlr/render/wlr_renderer.h>
|
#include <wlr/render/wlr_renderer.h>
|
||||||
|
|
||||||
|
struct wlr_commit;
|
||||||
|
struct wlr_output;
|
||||||
struct wlr_surface;
|
struct wlr_surface;
|
||||||
|
|
||||||
struct wlr_subcompositor {
|
struct wlr_subcompositor {
|
||||||
struct wl_global *global;
|
struct wl_global *global;
|
||||||
struct wl_list resources;
|
|
||||||
struct wl_list subsurface_resources;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_compositor {
|
struct wlr_compositor {
|
||||||
struct wl_global *global;
|
struct wl_global *global;
|
||||||
struct wl_list resources;
|
|
||||||
struct wlr_renderer *renderer;
|
struct wlr_renderer *renderer;
|
||||||
struct wl_list surface_resources;
|
|
||||||
struct wl_list region_resources;
|
uint32_t ids;
|
||||||
|
|
||||||
struct wlr_subcompositor subcompositor;
|
struct wlr_subcompositor subcompositor;
|
||||||
|
|
||||||
struct wl_listener display_destroy;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct wl_signal new_surface;
|
struct wl_signal new_surface;
|
||||||
|
struct wl_signal new_surface_2;
|
||||||
|
struct wl_signal new_state;
|
||||||
|
} events;
|
||||||
|
|
||||||
|
struct wl_listener display_destroy;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_surface_2 {
|
||||||
|
struct wl_resource *resource;
|
||||||
|
struct wlr_compositor *compositor;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct wl_signal commit;
|
||||||
|
struct wl_signal destroy;
|
||||||
|
} events;
|
||||||
|
|
||||||
|
struct wlr_commit *pending;
|
||||||
|
struct wl_list committed;
|
||||||
|
|
||||||
|
struct wl_list frame_callbacks;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_commit {
|
||||||
|
struct wl_list link;
|
||||||
|
struct wlr_surface_2 *surface;
|
||||||
|
|
||||||
|
// If the user has called wl_surface.commit
|
||||||
|
bool committed;
|
||||||
|
// See wlr_commit_inhibit
|
||||||
|
size_t inhibit;
|
||||||
|
size_t ref_cnt;
|
||||||
|
|
||||||
|
// wl_surface.attach
|
||||||
|
struct wl_resource *buffer_resource;
|
||||||
|
int32_t sx, sy;
|
||||||
|
// wl_surface.damage
|
||||||
|
pixman_region32_t surface_damage;
|
||||||
|
// wl_surface.frame
|
||||||
|
struct wl_list frame_callbacks;
|
||||||
|
// wl_surface.set_opaque_region
|
||||||
|
pixman_region32_t opaque_region;
|
||||||
|
// wl_surface.set_input_region
|
||||||
|
pixman_region32_t input_region;
|
||||||
|
// wl_surface.set_buffer_transform
|
||||||
|
enum wl_output_transform transform;
|
||||||
|
// wl_surface.set_buffer_scale
|
||||||
|
int32_t scale;
|
||||||
|
// wl_surface.damage_buffer
|
||||||
|
pixman_region32_t buffer_damage;
|
||||||
|
|
||||||
|
size_t state_len;
|
||||||
|
void **state;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct wl_signal commit;
|
||||||
|
struct wl_signal complete;
|
||||||
struct wl_signal destroy;
|
struct wl_signal destroy;
|
||||||
} events;
|
} events;
|
||||||
};
|
};
|
||||||
|
|
||||||
void wlr_compositor_destroy(struct wlr_compositor *wlr_compositor);
|
struct wlr_compositor_new_state_args {
|
||||||
|
struct wlr_commit *old;
|
||||||
|
struct wlr_commit *new;
|
||||||
|
};
|
||||||
|
|
||||||
struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
|
struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
|
||||||
struct wlr_renderer *renderer);
|
struct wlr_renderer *renderer);
|
||||||
|
uint32_t wlr_compositor_register(struct wlr_compositor *compositor);
|
||||||
|
|
||||||
|
struct wlr_surface_2 *wlr_surface_from_resource_2(struct wl_resource *resource);
|
||||||
|
|
||||||
|
struct wlr_commit *wlr_surface_get_commit(struct wlr_surface_2 *surface);
|
||||||
|
struct wlr_commit *wlr_surface_get_pending(struct wlr_surface_2 *surface);
|
||||||
|
|
||||||
|
void wlr_surface_send_enter_2(struct wlr_surface_2 *surf, struct wlr_output *output);
|
||||||
|
void wlr_surface_send_leave_2(struct wlr_surface_2 *surf, struct wlr_output *output);
|
||||||
|
|
||||||
|
void wlr_commit_unref(struct wlr_commit *commit);
|
||||||
|
|
||||||
|
void wlr_commit_inhibit(struct wlr_commit *commit);
|
||||||
|
void wlr_commit_uninhibit(struct wlr_commit *commit);
|
||||||
|
|
||||||
bool wlr_surface_is_subsurface(struct wlr_surface *surface);
|
bool wlr_surface_is_subsurface(struct wlr_surface *surface);
|
||||||
|
|
||||||
|
|
@ -50,4 +121,6 @@ bool wlr_surface_is_subsurface(struct wlr_surface *surface);
|
||||||
struct wlr_subsurface *wlr_subsurface_from_wlr_surface(
|
struct wlr_subsurface *wlr_subsurface_from_wlr_surface(
|
||||||
struct wlr_surface *surface);
|
struct wlr_surface *surface);
|
||||||
|
|
||||||
|
pixman_region32_t *wlr_region_from_resource(struct wl_resource *resource);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
/*
|
|
||||||
* This an unstable interface of wlroots. No guarantees are made regarding the
|
|
||||||
* future consistency of this API.
|
|
||||||
*/
|
|
||||||
#ifndef WLR_USE_UNSTABLE
|
|
||||||
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef WLR_TYPES_WLR_REGION_H
|
|
||||||
#define WLR_TYPES_WLR_REGION_H
|
|
||||||
|
|
||||||
#include <pixman.h>
|
|
||||||
#include <wayland-server-protocol.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Creates a new region resource with the provided new ID. If `resource_list` is
|
|
||||||
* non-NULL, adds the region's resource to the list.
|
|
||||||
*/
|
|
||||||
struct wl_resource *wlr_region_create(struct wl_client *client,
|
|
||||||
uint32_t version, uint32_t id, struct wl_list *resource_list);
|
|
||||||
|
|
||||||
pixman_region32_t *wlr_region_from_resource(struct wl_resource *resource);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -157,8 +157,7 @@ struct wlr_renderer;
|
||||||
* is non-NULL, adds the surface's resource to the list.
|
* is non-NULL, adds the surface's resource to the list.
|
||||||
*/
|
*/
|
||||||
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);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the lifetime role for this surface. Returns 0 on success or -1 if the
|
* Set the lifetime role for this surface. Returns 0 on success or -1 if the
|
||||||
|
|
@ -188,8 +187,7 @@ struct wlr_texture *wlr_surface_get_texture(struct wlr_surface *surface);
|
||||||
* is non-NULL, adds the subsurface's resource to the list.
|
* is non-NULL, adds the subsurface's resource to the list.
|
||||||
*/
|
*/
|
||||||
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);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the root of the subsurface tree for this surface.
|
* Get the root of the subsurface tree for this surface.
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,6 @@ struct wlr_xwm {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct wl_listener compositor_new_surface;
|
struct wl_listener compositor_new_surface;
|
||||||
struct wl_listener compositor_destroy;
|
|
||||||
struct wl_listener seat_set_selection;
|
struct wl_listener seat_set_selection;
|
||||||
struct wl_listener seat_set_primary_selection;
|
struct wl_listener seat_set_primary_selection;
|
||||||
struct wl_listener seat_start_drag;
|
struct wl_listener seat_start_drag;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wlr/types/wlr_region.h>
|
#include <wlr/types/wlr_compositor.h>
|
||||||
#include <wlr/types/wlr_xcursor_manager.h>
|
#include <wlr/types/wlr_xcursor_manager.h>
|
||||||
#include <wlr/util/edges.h>
|
#include <wlr/util/edges.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,6 @@ lib_wlr_types = static_library(
|
||||||
'wlr_presentation_time.c',
|
'wlr_presentation_time.c',
|
||||||
'wlr_primary_selection_v1.c',
|
'wlr_primary_selection_v1.c',
|
||||||
'wlr_primary_selection.c',
|
'wlr_primary_selection.c',
|
||||||
'wlr_region.c',
|
|
||||||
'wlr_relative_pointer_v1.c',
|
'wlr_relative_pointer_v1.c',
|
||||||
'wlr_screencopy_v1.c',
|
'wlr_screencopy_v1.c',
|
||||||
'wlr_screenshooter.c',
|
'wlr_screenshooter.c',
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
#include <wlr/types/wlr_compositor.h>
|
#include <wlr/types/wlr_compositor.h>
|
||||||
#include <wlr/types/wlr_region.h>
|
|
||||||
#include <wlr/types/wlr_surface.h>
|
#include <wlr/types/wlr_surface.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
#include "util/signal.h"
|
#include "util/signal.h"
|
||||||
|
|
@ -22,15 +23,6 @@ struct wlr_subsurface *wlr_subsurface_from_wlr_surface(
|
||||||
return (struct wlr_subsurface *)surface->role_data;
|
return (struct wlr_subsurface *)surface->role_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_subcompositor_interface subcompositor_impl;
|
|
||||||
|
|
||||||
static struct wlr_subcompositor *subcompositor_from_resource(
|
|
||||||
struct wl_resource *resource) {
|
|
||||||
assert(wl_resource_instance_of(resource, &wl_subcompositor_interface,
|
|
||||||
&subcompositor_impl));
|
|
||||||
return wl_resource_get_user_data(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void subcompositor_handle_destroy(struct wl_client *client,
|
static void subcompositor_handle_destroy(struct wl_client *client,
|
||||||
struct wl_resource *resource) {
|
struct wl_resource *resource) {
|
||||||
wl_resource_destroy(resource);
|
wl_resource_destroy(resource);
|
||||||
|
|
@ -40,8 +32,6 @@ static void subcompositor_handle_get_subsurface(struct wl_client *client,
|
||||||
struct wl_resource *resource, uint32_t id,
|
struct wl_resource *resource, uint32_t id,
|
||||||
struct wl_resource *surface_resource,
|
struct wl_resource *surface_resource,
|
||||||
struct wl_resource *parent_resource) {
|
struct wl_resource *parent_resource) {
|
||||||
struct wlr_subcompositor *subcompositor =
|
|
||||||
subcompositor_from_resource(resource);
|
|
||||||
struct wlr_surface *surface = wlr_surface_from_resource(surface_resource);
|
struct wlr_surface *surface = wlr_surface_from_resource(surface_resource);
|
||||||
struct wlr_surface *parent = wlr_surface_from_resource(parent_resource);
|
struct wlr_surface *parent = wlr_surface_from_resource(parent_resource);
|
||||||
|
|
||||||
|
|
@ -77,8 +67,8 @@ static void subcompositor_handle_get_subsurface(struct wl_client *client,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_subsurface_create(surface, parent, wl_resource_get_version(resource),
|
wlr_subsurface_create(surface, parent,
|
||||||
id, &subcompositor->subsurface_resources);
|
wl_resource_get_version(resource), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_subcompositor_interface subcompositor_impl = {
|
static const struct wl_subcompositor_interface subcompositor_impl = {
|
||||||
|
|
@ -86,54 +76,405 @@ static const struct wl_subcompositor_interface subcompositor_impl = {
|
||||||
.get_subsurface = subcompositor_handle_get_subsurface,
|
.get_subsurface = subcompositor_handle_get_subsurface,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void subcompositor_resource_destroy(struct wl_resource *resource) {
|
|
||||||
wl_list_remove(wl_resource_get_link(resource));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void subcompositor_bind(struct wl_client *client, void *data,
|
static void subcompositor_bind(struct wl_client *client, void *data,
|
||||||
uint32_t version, uint32_t id) {
|
uint32_t version, uint32_t id) {
|
||||||
struct wlr_subcompositor *subcompositor = data;
|
|
||||||
struct wl_resource *resource =
|
struct wl_resource *resource =
|
||||||
wl_resource_create(client, &wl_subcompositor_interface, 1, id);
|
wl_resource_create(client, &wl_subcompositor_interface, 1, id);
|
||||||
if (resource == NULL) {
|
if (resource == NULL) {
|
||||||
wl_client_post_no_memory(client);
|
wl_client_post_no_memory(client);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wl_resource_set_implementation(resource, &subcompositor_impl,
|
wl_resource_set_implementation(resource, &subcompositor_impl, NULL, NULL);
|
||||||
subcompositor, subcompositor_resource_destroy);
|
|
||||||
wl_list_insert(&subcompositor->resources, wl_resource_get_link(resource));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void subcompositor_init(struct wlr_subcompositor *subcompositor,
|
static void subcompositor_init(struct wlr_subcompositor *sc,
|
||||||
struct wl_display *display) {
|
struct wl_display *display) {
|
||||||
subcompositor->global = wl_global_create(display,
|
sc->global = wl_global_create(display, &wl_subcompositor_interface,
|
||||||
&wl_subcompositor_interface, SUBCOMPOSITOR_VERSION, subcompositor,
|
SUBCOMPOSITOR_VERSION, NULL, subcompositor_bind);
|
||||||
subcompositor_bind);
|
if (sc->global == NULL) {
|
||||||
if (subcompositor->global == NULL) {
|
wlr_log_errno(WLR_ERROR, "Failed to create subcompositor global");
|
||||||
wlr_log_errno(WLR_ERROR, "Could not allocate subcompositor global");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wl_list_init(&subcompositor->resources);
|
|
||||||
wl_list_init(&subcompositor->subsurface_resources);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void subcompositor_finish(struct wlr_subcompositor *subcompositor) {
|
static void subcompositor_finish(struct wlr_subcompositor *sc) {
|
||||||
wl_global_destroy(subcompositor->global);
|
wl_global_destroy(sc->global);
|
||||||
struct wl_resource *resource, *tmp;
|
}
|
||||||
wl_resource_for_each_safe(resource, tmp,
|
|
||||||
&subcompositor->subsurface_resources) {
|
static const struct wl_region_interface region_impl;
|
||||||
|
|
||||||
|
pixman_region32_t *wlr_region_from_resource(struct wl_resource *resource) {
|
||||||
|
assert(wl_resource_instance_of(resource, &wl_region_interface,
|
||||||
|
®ion_impl));
|
||||||
|
return wl_resource_get_user_data(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void region_destroy(struct wl_client *client, struct wl_resource *resource) {
|
||||||
wl_resource_destroy(resource);
|
wl_resource_destroy(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void region_add(struct wl_client *client, struct wl_resource *resource,
|
||||||
|
int32_t x, int32_t y, int32_t width, int32_t height) {
|
||||||
|
pixman_region32_t *region = wlr_region_from_resource(resource);
|
||||||
|
pixman_region32_union_rect(region, region, x, y, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void region_subtract(struct wl_client *client, struct wl_resource *resource,
|
||||||
|
int32_t x, int32_t y, int32_t width, int32_t height) {
|
||||||
|
pixman_region32_t *region = wlr_region_from_resource(resource);
|
||||||
|
pixman_region32_union_rect(region, region, x, y, width, height);
|
||||||
|
|
||||||
|
pixman_region32_t rect;
|
||||||
|
pixman_region32_init_rect(&rect, x, y, width, height);
|
||||||
|
pixman_region32_subtract(region, region, &rect);
|
||||||
|
pixman_region32_fini(&rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_region_interface region_impl = {
|
||||||
|
.destroy = region_destroy,
|
||||||
|
.add = region_add,
|
||||||
|
.subtract = region_subtract,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void region_resource_destroy(struct wl_resource *resource) {
|
||||||
|
pixman_region32_t *region = wlr_region_from_resource(resource);
|
||||||
|
|
||||||
|
pixman_region32_fini(region);
|
||||||
|
free(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct wlr_commit *commit_create(struct wlr_surface_2 *surf) {
|
||||||
|
struct wlr_compositor *comp = surf->compositor;
|
||||||
|
|
||||||
|
struct wlr_commit *c = calloc(1, sizeof(*c));
|
||||||
|
if (!c) {
|
||||||
|
wlr_log_errno(WLR_ERROR, "Allocation failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent a zero allocation
|
||||||
|
size_t len = comp->ids ? comp->ids : 1;
|
||||||
|
|
||||||
|
c->state = calloc(len, sizeof(*c->state));
|
||||||
|
if (!c->state) {
|
||||||
|
wlr_log_errno(WLR_ERROR, "Allocation failed");
|
||||||
|
free(c);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
c->state_len = len;
|
||||||
|
|
||||||
|
c->surface = surf;
|
||||||
|
|
||||||
|
pixman_region32_init(&c->surface_damage);
|
||||||
|
wl_list_init(&c->frame_callbacks);
|
||||||
|
pixman_region32_init(&c->opaque_region);
|
||||||
|
pixman_region32_init_rect(&c->input_region,
|
||||||
|
INT_MIN, INT_MIN, UINT_MAX, UINT_MAX);
|
||||||
|
c->scale = 1;
|
||||||
|
pixman_region32_init(&c->buffer_damage);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void commit_destroy(struct wlr_commit *c) {
|
||||||
|
pixman_region32_fini(&c->surface_damage);
|
||||||
|
pixman_region32_fini(&c->opaque_region);
|
||||||
|
pixman_region32_fini(&c->input_region);
|
||||||
|
pixman_region32_fini(&c->buffer_damage);
|
||||||
|
|
||||||
|
wlr_signal_emit_safe(&c->events.destroy, c);
|
||||||
|
|
||||||
|
free(c->state);
|
||||||
|
free(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool commit_is_complete(struct wlr_commit *c) {
|
||||||
|
return c->committed && c->inhibit == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool commit_is_latest(struct wlr_commit *c) {
|
||||||
|
assert(c->committed);
|
||||||
|
|
||||||
|
struct wlr_surface_2 *surf = c->surface;
|
||||||
|
struct wlr_commit *iter;
|
||||||
|
wl_list_for_each(iter, &surf->committed, link) {
|
||||||
|
if (iter == c) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commit_is_complete(iter)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// You shouldn't be able to get here.
|
||||||
|
assert(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void surface_prune_commits(struct wlr_surface_2 *surf) {
|
||||||
|
bool complete = false;
|
||||||
|
struct wlr_commit *iter, *tmp;
|
||||||
|
wl_list_for_each_safe(iter, tmp, &surf->committed, link) {
|
||||||
|
if (!complete) {
|
||||||
|
complete = commit_is_complete(iter);
|
||||||
|
} else if (iter->ref_cnt == 0) {
|
||||||
|
commit_destroy(iter);
|
||||||
}
|
}
|
||||||
wl_resource_for_each_safe(resource, tmp, &subcompositor->resources) {
|
|
||||||
wl_resource_destroy(resource);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wlr_commit_inhibit(struct wlr_commit *commit) {
|
||||||
|
assert(commit && !commit_is_complete(commit));
|
||||||
|
++commit->inhibit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_commit_uninhibit(struct wlr_commit *commit) {
|
||||||
|
assert(commit && commit->inhibit > 0);
|
||||||
|
--commit->inhibit;
|
||||||
|
|
||||||
|
if (commit_is_complete(commit)) {
|
||||||
|
wlr_signal_emit_safe(&commit->events.complete, commit);
|
||||||
|
|
||||||
|
if (commit_is_latest(commit)) {
|
||||||
|
struct wlr_surface_2 *surf = commit->surface;
|
||||||
|
surface_prune_commits(surf);
|
||||||
|
wlr_signal_emit_safe(&surf->events.commit, surf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_commit_set(struct wlr_commit *commit, uint32_t id, void *data) {
|
||||||
|
struct wlr_compositor *comp = commit->surface->compositor;
|
||||||
|
|
||||||
|
// They didn't get their ID from wlr_compositor_register
|
||||||
|
assert(id < comp->ids);
|
||||||
|
|
||||||
|
// This can happen if wlr_compositor_register is called after
|
||||||
|
// the commit was created.
|
||||||
|
if (commit->state_len < comp->ids) {
|
||||||
|
void **tmp = realloc(commit->state,
|
||||||
|
sizeof(*commit->state) * comp->ids);
|
||||||
|
if (!tmp) {
|
||||||
|
wlr_log_errno(WLR_ERROR, "Allocation failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
commit->state = tmp;
|
||||||
|
for (size_t i = commit->state_len; i < comp->ids; ++i) {
|
||||||
|
commit->state[i] = NULL;
|
||||||
|
}
|
||||||
|
commit->state_len = comp->ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
commit->state[id] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *wlr_commit_get(struct wlr_commit *commit, uint32_t id) {
|
||||||
|
if (id >= commit->state_len) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return commit->state[id];
|
||||||
|
};
|
||||||
|
|
||||||
|
static void surface_destroy(struct wl_client *client, struct wl_resource *res) {
|
||||||
|
wl_resource_destroy(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void surface_attach(struct wl_client *client, struct wl_resource *res,
|
||||||
|
struct wl_resource *buffer, int32_t dx, int32_t dy) {
|
||||||
|
struct wlr_surface_2 *surf = wlr_surface_from_resource_2(res);
|
||||||
|
struct wlr_commit *commit = wlr_surface_get_pending(surf);
|
||||||
|
|
||||||
|
commit->buffer_resource = buffer;
|
||||||
|
commit->sx = dx;
|
||||||
|
commit->sy = dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void surface_damage(struct wl_client *client, struct wl_resource *res,
|
||||||
|
int32_t x, int32_t y, int32_t width, int32_t height) {
|
||||||
|
struct wlr_surface_2 *surf = wlr_surface_from_resource_2(res);
|
||||||
|
struct wlr_commit *commit = wlr_surface_get_pending(surf);
|
||||||
|
|
||||||
|
pixman_region32_union_rect(&commit->surface_damage,
|
||||||
|
&commit->surface_damage, x, y, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void callback_resource_destroy(struct wl_resource *resource) {
|
||||||
|
wl_list_remove(wl_resource_get_link(resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void surface_frame(struct wl_client *client, struct wl_resource *res,
|
||||||
|
uint32_t id) {
|
||||||
|
struct wlr_surface_2 *surf = wlr_surface_from_resource_2(res);
|
||||||
|
struct wlr_commit *commit = wlr_surface_get_pending(surf);
|
||||||
|
|
||||||
|
struct wl_resource *callback =
|
||||||
|
wl_resource_create(client, &wl_callback_interface, 1, id);
|
||||||
|
if (!callback) {
|
||||||
|
wlr_log_errno(WLR_ERROR, "Failed to create callback resource");
|
||||||
|
wl_resource_post_no_memory(surf->resource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_resource_set_implementation(callback, NULL, NULL,
|
||||||
|
callback_resource_destroy);
|
||||||
|
|
||||||
|
wl_list_insert(&commit->frame_callbacks, wl_resource_get_link(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void surface_set_opaque_region(struct wl_client *client,
|
||||||
|
struct wl_resource *res, struct wl_resource *region_res) {
|
||||||
|
struct wlr_surface_2 *surf = wlr_surface_from_resource_2(res);
|
||||||
|
struct wlr_commit *commit = wlr_surface_get_pending(surf);
|
||||||
|
|
||||||
|
if (region_res) {
|
||||||
|
pixman_region32_t *region = wlr_region_from_resource(region_res);
|
||||||
|
pixman_region32_copy(&commit->opaque_region, region);
|
||||||
|
} else {
|
||||||
|
pixman_region32_clear(&commit->opaque_region);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void surface_set_input_region(struct wl_client *client,
|
||||||
|
struct wl_resource *res, struct wl_resource *input_res) {
|
||||||
|
struct wlr_surface_2 *surf = wlr_surface_from_resource_2(res);
|
||||||
|
struct wlr_commit *commit = wlr_surface_get_pending(surf);
|
||||||
|
|
||||||
|
if (input_res) {
|
||||||
|
pixman_region32_t *region = wlr_region_from_resource(input_res);
|
||||||
|
pixman_region32_copy(&commit->input_region, region);
|
||||||
|
} else {
|
||||||
|
pixman_region32_union_rect(&commit->input_region,
|
||||||
|
&commit->input_region, INT_MIN, INT_MIN, UINT_MAX, UINT_MAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void surface_set_buffer_transform(struct wl_client *client,
|
||||||
|
struct wl_resource *res, int32_t transform) {
|
||||||
|
struct wlr_surface_2 *surf = wlr_surface_from_resource_2(res);
|
||||||
|
struct wlr_commit *commit = wlr_surface_get_pending(surf);
|
||||||
|
|
||||||
|
if (transform < 0 || transform > WL_OUTPUT_TRANSFORM_FLIPPED_270) {
|
||||||
|
wl_resource_post_error(surf->resource,
|
||||||
|
WL_SURFACE_ERROR_INVALID_TRANSFORM,
|
||||||
|
"transform value (%"PRId32") is not valid wl_output.transform enum",
|
||||||
|
transform);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
commit->transform = transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void surface_set_buffer_scale(struct wl_client *client,
|
||||||
|
struct wl_resource *res, int32_t scale) {
|
||||||
|
struct wlr_surface_2 *surf = wlr_surface_from_resource_2(res);
|
||||||
|
struct wlr_commit *commit = wlr_surface_get_pending(surf);
|
||||||
|
|
||||||
|
if (scale <= 0) {
|
||||||
|
wl_resource_post_error(surf->resource,
|
||||||
|
WL_SURFACE_ERROR_INVALID_SCALE,
|
||||||
|
"scale value (%"PRId32") is not positive",
|
||||||
|
scale);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
commit->scale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void surface_damage_buffer(struct wl_client *client, struct wl_resource *res,
|
||||||
|
int32_t x, int32_t y, int32_t width, int32_t height) {
|
||||||
|
struct wlr_surface_2 *surf = wlr_surface_from_resource_2(res);
|
||||||
|
struct wlr_commit *commit = wlr_surface_get_pending(surf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The client is being extremely stupid, but there is nothing in the
|
||||||
|
* standard mentioning that this is an error, so we just ignore it.
|
||||||
|
*/
|
||||||
|
if (width < 0 || height < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixman_region32_union_rect(&commit->buffer_damage,
|
||||||
|
&commit->buffer_damage, x, y, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void surface_commit(struct wl_client *client, struct wl_resource *res) {
|
||||||
|
struct wlr_surface_2 *surf = wlr_surface_from_resource_2(res);
|
||||||
|
struct wlr_commit *commit = wlr_surface_get_pending(surf);
|
||||||
|
|
||||||
|
commit->committed = true;
|
||||||
|
wl_list_insert(&surf->committed, &commit->link);
|
||||||
|
|
||||||
|
surf->pending = commit_create(surf);
|
||||||
|
if (!surf->pending) {
|
||||||
|
wl_resource_post_no_memory(surf->resource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
surf->pending->buffer_resource = commit->buffer_resource;
|
||||||
|
pixman_region32_copy(&surf->pending->opaque_region, &commit->opaque_region);
|
||||||
|
pixman_region32_copy(&surf->pending->input_region, &commit->input_region);
|
||||||
|
surf->pending->transform = commit->transform;
|
||||||
|
surf->pending->scale = commit->scale;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The wayland protocol says we'll signal these in the order they're
|
||||||
|
* committed, so we make sure to add them to the end of the list.
|
||||||
|
*/
|
||||||
|
wl_list_insert_list(surf->frame_callbacks.prev, &commit->frame_callbacks);
|
||||||
|
wl_list_init(&commit->frame_callbacks);
|
||||||
|
|
||||||
|
struct wlr_compositor_new_state_args args = {
|
||||||
|
.old = commit,
|
||||||
|
.new = surf->pending,
|
||||||
|
};
|
||||||
|
|
||||||
|
wlr_signal_emit_safe(&commit->events.commit, commit);
|
||||||
|
wlr_signal_emit_safe(&surf->compositor->events.new_state, &args);
|
||||||
|
|
||||||
|
surface_prune_commits(surf);
|
||||||
|
|
||||||
|
if (commit_is_complete(commit)) {
|
||||||
|
wlr_signal_emit_safe(&commit->events.complete, commit);
|
||||||
|
wlr_signal_emit_safe(&surf->events.commit, surf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct wl_surface_interface surface_impl = {
|
||||||
|
.destroy = surface_destroy,
|
||||||
|
.attach = surface_attach,
|
||||||
|
.damage = surface_damage,
|
||||||
|
.frame = surface_frame,
|
||||||
|
.set_opaque_region = surface_set_opaque_region,
|
||||||
|
.set_input_region = surface_set_input_region,
|
||||||
|
.set_buffer_transform = surface_set_buffer_transform,
|
||||||
|
.set_buffer_scale = surface_set_buffer_scale,
|
||||||
|
.damage_buffer = surface_damage_buffer,
|
||||||
|
.commit = surface_commit,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_surface_2 *wlr_surface_from_resource_2(struct wl_resource *resource) {
|
||||||
|
assert(wl_resource_instance_of(resource, &wl_compositor_interface,
|
||||||
|
&surface_impl));
|
||||||
|
return wl_resource_get_user_data(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void surface_resource_destroy(struct wl_resource *resource) {
|
||||||
|
struct wlr_surface_2 *surf = wlr_surface_from_resource_2(resource);
|
||||||
|
|
||||||
|
wlr_signal_emit_safe(&surf->events.destroy, surf);
|
||||||
|
|
||||||
|
struct wlr_commit *iter, *tmp;
|
||||||
|
wl_list_for_each_reverse_safe(iter, tmp, &surf->committed, link) {
|
||||||
|
commit_destroy(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(surf);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct wl_compositor_interface compositor_impl;
|
static const struct wl_compositor_interface compositor_impl;
|
||||||
|
static struct wlr_compositor *compositor_from_resource(struct wl_resource *resource) {
|
||||||
static struct wlr_compositor *compositor_from_resource(
|
|
||||||
struct wl_resource *resource) {
|
|
||||||
assert(wl_resource_instance_of(resource, &wl_compositor_interface,
|
assert(wl_resource_instance_of(resource, &wl_compositor_interface,
|
||||||
&compositor_impl));
|
&compositor_impl));
|
||||||
return wl_resource_get_user_data(resource);
|
return wl_resource_get_user_data(resource);
|
||||||
|
|
@ -143,21 +484,68 @@ 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);
|
||||||
|
|
||||||
struct wlr_surface *surface = wlr_surface_create(client,
|
struct wlr_surface_2 *surf = calloc(1, sizeof(*surf));
|
||||||
wl_resource_get_version(resource), id, compositor->renderer,
|
if (!surf) {
|
||||||
&compositor->surface_resources);
|
wlr_log_errno(WLR_ERROR, "Allocation failed");
|
||||||
if (surface == NULL) {
|
goto error_post;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_signal_emit_safe(&compositor->events.new_surface, surface);
|
surf->resource = wl_resource_create(client, &wl_surface_interface,
|
||||||
|
wl_resource_get_version(resource), id);
|
||||||
|
if (!surf->resource) {
|
||||||
|
wlr_log_errno(WLR_ERROR, "Failed to create surface resource");
|
||||||
|
goto error_surf;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_resource_set_implementation(surf->resource, &surface_impl,
|
||||||
|
surf, surface_resource_destroy);
|
||||||
|
|
||||||
|
wl_signal_init(&surf->events.destroy);
|
||||||
|
wl_list_init(&surf->committed);
|
||||||
|
|
||||||
|
surf->pending = commit_create(surf);
|
||||||
|
if (!surf->pending) {
|
||||||
|
goto error_resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_compositor_new_state_args args = {
|
||||||
|
.old = NULL,
|
||||||
|
.new = surf->pending,
|
||||||
|
};
|
||||||
|
|
||||||
|
wlr_signal_emit_safe(&compositor->events.new_surface_2, surf);
|
||||||
|
wlr_signal_emit_safe(&compositor->events.new_state, &args);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
error_resource:
|
||||||
|
wl_resource_destroy(surf->resource);
|
||||||
|
error_surf:
|
||||||
|
free(surf);
|
||||||
|
error_post:
|
||||||
|
wl_client_post_no_memory(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void 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);
|
pixman_region32_t *region = calloc(1, sizeof(*region));
|
||||||
|
if (!region) {
|
||||||
|
wlr_log_errno(WLR_ERROR, "Allocation failed");
|
||||||
|
wl_client_post_no_memory(client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wlr_region_create(client, 1, id, &compositor->region_resources);
|
pixman_region32_init(region);
|
||||||
|
|
||||||
|
struct wl_resource *res =
|
||||||
|
wl_resource_create(client, &wl_region_interface, 1, id);
|
||||||
|
if (!res) {
|
||||||
|
free(region);
|
||||||
|
wl_client_post_no_memory(client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wl_resource_set_implementation(res, ®ion_impl, region,
|
||||||
|
region_resource_destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_compositor_interface compositor_impl = {
|
static const struct wl_compositor_interface compositor_impl = {
|
||||||
|
|
@ -165,81 +553,119 @@ static const struct wl_compositor_interface compositor_impl = {
|
||||||
.create_region = compositor_create_region,
|
.create_region = compositor_create_region,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void compositor_resource_destroy(struct wl_resource *resource) {
|
static void compositor_bind(struct wl_client *client, void *data,
|
||||||
wl_list_remove(wl_resource_get_link(resource));
|
|
||||||
}
|
|
||||||
|
|
||||||
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 *comp = data;
|
||||||
assert(wl_client && compositor);
|
|
||||||
|
|
||||||
struct wl_resource *resource =
|
struct wl_resource *res =
|
||||||
wl_resource_create(wl_client, &wl_compositor_interface, version, id);
|
wl_resource_create(client, &wl_compositor_interface, version, id);
|
||||||
if (resource == NULL) {
|
if (!res) {
|
||||||
wl_client_post_no_memory(wl_client);
|
wlr_log_errno(WLR_ERROR, "Failed to create compositor resource");
|
||||||
|
wl_client_post_no_memory(client);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wl_resource_set_implementation(resource, &compositor_impl,
|
|
||||||
compositor, compositor_resource_destroy);
|
wl_resource_set_implementation(res, &compositor_impl, comp, NULL);
|
||||||
wl_list_insert(&compositor->resources, wl_resource_get_link(resource));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_compositor_destroy(struct wlr_compositor *compositor) {
|
static void compositor_display_destroy(struct wl_listener *listener, void *data) {
|
||||||
if (compositor == NULL) {
|
struct wlr_compositor *comp = wl_container_of(listener, comp, display_destroy);
|
||||||
return;
|
|
||||||
}
|
|
||||||
wlr_signal_emit_safe(&compositor->events.destroy, compositor);
|
|
||||||
subcompositor_finish(&compositor->subcompositor);
|
|
||||||
wl_list_remove(&compositor->display_destroy.link);
|
|
||||||
wl_global_destroy(compositor->global);
|
|
||||||
struct wl_resource *resource, *tmp;
|
|
||||||
wl_resource_for_each_safe(resource, tmp, &compositor->surface_resources) {
|
|
||||||
wl_resource_destroy(resource);
|
|
||||||
}
|
|
||||||
wl_resource_for_each_safe(resource, tmp, &compositor->region_resources) {
|
|
||||||
wl_resource_destroy(resource);
|
|
||||||
}
|
|
||||||
wl_resource_for_each_safe(resource, tmp, &compositor->resources) {
|
|
||||||
wl_resource_destroy(resource);
|
|
||||||
}
|
|
||||||
free(compositor);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_display_destroy(struct wl_listener *listener, void *data) {
|
subcompositor_finish(&comp->subcompositor);
|
||||||
struct wlr_compositor *compositor =
|
wl_list_remove(&comp->display_destroy.link);
|
||||||
wl_container_of(listener, compositor, display_destroy);
|
wl_global_destroy(comp->global);
|
||||||
wlr_compositor_destroy(compositor);
|
|
||||||
|
free(comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
|
struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
|
||||||
struct wlr_renderer *renderer) {
|
struct wlr_renderer *renderer) {
|
||||||
struct wlr_compositor *compositor =
|
struct wlr_compositor *comp = calloc(1, sizeof(*comp));
|
||||||
calloc(1, sizeof(struct wlr_compositor));
|
if (!comp) {
|
||||||
if (!compositor) {
|
wlr_log_errno(WLR_ERROR, "Allocation failed");
|
||||||
wlr_log_errno(WLR_ERROR, "Could not allocate wlr compositor");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
compositor->global = wl_global_create(display, &wl_compositor_interface,
|
comp->global = wl_global_create(display, &wl_compositor_interface,
|
||||||
COMPOSITOR_VERSION, compositor, compositor_bind);
|
COMPOSITOR_VERSION, comp, compositor_bind);
|
||||||
if (!compositor->global) {
|
if (!comp->global) {
|
||||||
free(compositor);
|
wlr_log_errno(WLR_ERROR, "Failed to create wayland global");
|
||||||
wlr_log_errno(WLR_ERROR, "Could not allocate compositor global");
|
free(comp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
compositor->renderer = renderer;
|
comp->renderer = renderer;
|
||||||
|
|
||||||
wl_list_init(&compositor->resources);
|
wl_signal_init(&comp->events.new_surface);
|
||||||
wl_list_init(&compositor->surface_resources);
|
wl_signal_init(&comp->events.new_surface_2);
|
||||||
wl_list_init(&compositor->region_resources);
|
wl_signal_init(&comp->events.new_state);
|
||||||
wl_signal_init(&compositor->events.new_surface);
|
|
||||||
wl_signal_init(&compositor->events.destroy);
|
|
||||||
|
|
||||||
subcompositor_init(&compositor->subcompositor, display);
|
subcompositor_init(&comp->subcompositor, display);
|
||||||
|
|
||||||
compositor->display_destroy.notify = handle_display_destroy;
|
comp->display_destroy.notify = compositor_display_destroy;
|
||||||
wl_display_add_destroy_listener(display, &compositor->display_destroy);
|
wl_display_add_destroy_listener(display, &comp->display_destroy);
|
||||||
|
|
||||||
return compositor;
|
return comp;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t wlr_compositor_register(struct wlr_compositor *compositor) {
|
||||||
|
assert(compositor);
|
||||||
|
return compositor->ids++;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_commit *wlr_surface_get_commit(struct wlr_surface_2 *surf) {
|
||||||
|
surface_prune_commits(surf);
|
||||||
|
|
||||||
|
struct wlr_commit *iter;
|
||||||
|
wl_list_for_each(iter, &surf->committed, link) {
|
||||||
|
if (commit_is_complete(iter)) {
|
||||||
|
++iter->ref_cnt;
|
||||||
|
return iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_commit *wlr_surface_get_pending(struct wlr_surface_2 *surf) {
|
||||||
|
return surf->pending;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_surface_send_enter_2(struct wlr_surface_2 *surf, struct wlr_output *output) {
|
||||||
|
struct wl_client *client = wl_resource_get_client(surf->resource);
|
||||||
|
struct wl_resource *iter;
|
||||||
|
wl_resource_for_each(iter, &output->resources) {
|
||||||
|
if (wl_resource_get_client(iter) == client) {
|
||||||
|
wl_surface_send_enter(surf->resource, iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_surface_send_leave_2(struct wlr_surface_2 *surf, struct wlr_output *output) {
|
||||||
|
struct wl_client *client = wl_resource_get_client(surf->resource);
|
||||||
|
struct wl_resource *iter;
|
||||||
|
wl_resource_for_each(iter, &output->resources) {
|
||||||
|
if (wl_resource_get_client(iter) == client) {
|
||||||
|
wl_surface_send_leave(surf->resource, iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int64_t timespec_to_msec(const struct timespec *a) {
|
||||||
|
return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_surface_send_frame_done_2(struct wlr_surface_2 *surf,
|
||||||
|
const struct timespec *ts) {
|
||||||
|
struct wl_resource *iter, *tmp;
|
||||||
|
wl_resource_for_each_safe(iter, tmp, &surf->frame_callbacks) {
|
||||||
|
wl_callback_send_done(iter, timespec_to_msec(ts));
|
||||||
|
wl_resource_destroy(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_commit_unref(struct wlr_commit *commit) {
|
||||||
|
assert(commit && commit->ref_cnt > 0);
|
||||||
|
--commit->ref_cnt;
|
||||||
|
|
||||||
|
surface_prune_commits(commit->surface);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
#include <wlr/types/wlr_box.h>
|
#include <wlr/types/wlr_box.h>
|
||||||
|
#include <wlr/types/wlr_compositor.h>
|
||||||
#include <wlr/types/wlr_pointer_constraints_v1.h>
|
#include <wlr/types/wlr_pointer_constraints_v1.h>
|
||||||
#include <wlr/types/wlr_region.h>
|
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
#include "util/signal.h"
|
#include "util/signal.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
#include <assert.h>
|
|
||||||
#include <pixman.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <wayland-server.h>
|
|
||||||
#include <wlr/types/wlr_region.h>
|
|
||||||
|
|
||||||
static void region_add(struct wl_client *client, struct wl_resource *resource,
|
|
||||||
int32_t x, int32_t y, int32_t width, int32_t height) {
|
|
||||||
pixman_region32_t *region = wlr_region_from_resource(resource);
|
|
||||||
pixman_region32_union_rect(region, region, x, y, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void region_subtract(struct wl_client *client, struct wl_resource *resource,
|
|
||||||
int32_t x, int32_t y, int32_t width, int32_t height) {
|
|
||||||
pixman_region32_t *region = wlr_region_from_resource(resource);
|
|
||||||
pixman_region32_union_rect(region, region, x, y, width, height);
|
|
||||||
|
|
||||||
pixman_region32_t rect;
|
|
||||||
pixman_region32_init_rect(&rect, x, y, width, height);
|
|
||||||
pixman_region32_subtract(region, region, &rect);
|
|
||||||
pixman_region32_fini(&rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void region_destroy(struct wl_client *client, struct wl_resource *resource) {
|
|
||||||
wl_resource_destroy(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wl_region_interface region_impl = {
|
|
||||||
.destroy = region_destroy,
|
|
||||||
.add = region_add,
|
|
||||||
.subtract = region_subtract,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void region_handle_resource_destroy(struct wl_resource *resource) {
|
|
||||||
pixman_region32_t *reg = wlr_region_from_resource(resource);
|
|
||||||
|
|
||||||
wl_list_remove(wl_resource_get_link(resource));
|
|
||||||
|
|
||||||
pixman_region32_fini(reg);
|
|
||||||
free(reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wl_resource *wlr_region_create(struct wl_client *client,
|
|
||||||
uint32_t version, uint32_t id, struct wl_list *resource_list) {
|
|
||||||
pixman_region32_t *region = calloc(1, sizeof(pixman_region32_t));
|
|
||||||
if (region == NULL) {
|
|
||||||
wl_client_post_no_memory(client);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pixman_region32_init(region);
|
|
||||||
|
|
||||||
struct wl_resource *region_resource = wl_resource_create(client,
|
|
||||||
&wl_region_interface, version, id);
|
|
||||||
if (region_resource == NULL) {
|
|
||||||
free(region);
|
|
||||||
wl_client_post_no_memory(client);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
wl_resource_set_implementation(region_resource, ®ion_impl, region,
|
|
||||||
region_handle_resource_destroy);
|
|
||||||
|
|
||||||
struct wl_list *resource_link = wl_resource_get_link(region_resource);
|
|
||||||
if (resource_list != NULL) {
|
|
||||||
wl_list_insert(resource_list, resource_link);
|
|
||||||
} else {
|
|
||||||
wl_list_init(resource_link);
|
|
||||||
}
|
|
||||||
|
|
||||||
return region_resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
pixman_region32_t *wlr_region_from_resource(struct wl_resource *resource) {
|
|
||||||
assert(wl_resource_instance_of(resource, &wl_region_interface,
|
|
||||||
®ion_impl));
|
|
||||||
return wl_resource_get_user_data(resource);
|
|
||||||
}
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
#include <wlr/types/wlr_buffer.h>
|
#include <wlr/types/wlr_buffer.h>
|
||||||
#include <wlr/types/wlr_compositor.h>
|
#include <wlr/types/wlr_compositor.h>
|
||||||
#include <wlr/types/wlr_matrix.h>
|
#include <wlr/types/wlr_matrix.h>
|
||||||
#include <wlr/types/wlr_region.h>
|
|
||||||
#include <wlr/types/wlr_surface.h>
|
#include <wlr/types/wlr_surface.h>
|
||||||
#include <wlr/types/wlr_output.h>
|
#include <wlr/types/wlr_output.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
|
|
@ -566,8 +565,6 @@ static void surface_handle_resource_destroy(struct wl_resource *resource) {
|
||||||
|
|
||||||
wlr_signal_emit_safe(&surface->events.destroy, surface);
|
wlr_signal_emit_safe(&surface->events.destroy, surface);
|
||||||
|
|
||||||
wl_list_remove(wl_resource_get_link(surface->resource));
|
|
||||||
|
|
||||||
wl_list_remove(&surface->renderer_destroy.link);
|
wl_list_remove(&surface->renderer_destroy.link);
|
||||||
surface_state_finish(&surface->pending);
|
surface_state_finish(&surface->pending);
|
||||||
surface_state_finish(&surface->current);
|
surface_state_finish(&surface->current);
|
||||||
|
|
@ -587,8 +584,7 @@ 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) {
|
|
||||||
assert(version <= SURFACE_VERSION);
|
assert(version <= SURFACE_VERSION);
|
||||||
|
|
||||||
struct wlr_surface *surface = calloc(1, sizeof(struct wlr_surface));
|
struct wlr_surface *surface = calloc(1, sizeof(struct wlr_surface));
|
||||||
|
|
@ -626,13 +622,6 @@ struct wlr_surface *wlr_surface_create(struct wl_client *client,
|
||||||
wl_signal_add(&renderer->events.destroy, &surface->renderer_destroy);
|
wl_signal_add(&renderer->events.destroy, &surface->renderer_destroy);
|
||||||
surface->renderer_destroy.notify = surface_handle_renderer_destroy;
|
surface->renderer_destroy.notify = surface_handle_renderer_destroy;
|
||||||
|
|
||||||
struct wl_list *resource_link = wl_resource_get_link(surface->resource);
|
|
||||||
if (resource_list != NULL) {
|
|
||||||
wl_list_insert(resource_list, resource_link);
|
|
||||||
} else {
|
|
||||||
wl_list_init(resource_link);
|
|
||||||
}
|
|
||||||
|
|
||||||
return surface;
|
return surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -679,7 +668,6 @@ 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));
|
|
||||||
subsurface_destroy(subsurface);
|
subsurface_destroy(subsurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -930,8 +918,7 @@ 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) {
|
|
||||||
assert(version <= SUBSURFACE_VERSION);
|
assert(version <= SUBSURFACE_VERSION);
|
||||||
|
|
||||||
struct wl_client *client = wl_resource_get_client(surface->resource);
|
struct wl_client *client = wl_resource_get_client(surface->resource);
|
||||||
|
|
@ -974,13 +961,6 @@ struct wlr_subsurface *wlr_subsurface_create(struct wlr_surface *surface,
|
||||||
|
|
||||||
surface->role_data = subsurface;
|
surface->role_data = subsurface;
|
||||||
|
|
||||||
struct wl_list *resource_link = wl_resource_get_link(subsurface->resource);
|
|
||||||
if (resource_list != NULL) {
|
|
||||||
wl_list_insert(resource_list, resource_link);
|
|
||||||
} else {
|
|
||||||
wl_list_init(resource_link);
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_signal_emit_safe(&parent->events.new_subsurface, subsurface);
|
wlr_signal_emit_safe(&parent->events.new_subsurface, subsurface);
|
||||||
|
|
||||||
return subsurface;
|
return subsurface;
|
||||||
|
|
|
||||||
|
|
@ -1387,16 +1387,6 @@ static void handle_compositor_new_surface(struct wl_listener *listener,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_compositor_destroy(struct wl_listener *listener,
|
|
||||||
void *data) {
|
|
||||||
struct wlr_xwm *xwm =
|
|
||||||
wl_container_of(listener, xwm, compositor_destroy);
|
|
||||||
wl_list_remove(&xwm->compositor_new_surface.link);
|
|
||||||
wl_list_remove(&xwm->compositor_destroy.link);
|
|
||||||
wl_list_init(&xwm->compositor_new_surface.link);
|
|
||||||
wl_list_init(&xwm->compositor_destroy.link);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_xwayland_surface_activate(struct wlr_xwayland_surface *xsurface,
|
void wlr_xwayland_surface_activate(struct wlr_xwayland_surface *xsurface,
|
||||||
bool activated) {
|
bool activated) {
|
||||||
struct wlr_xwayland_surface *focused = xsurface->xwm->focus_surface;
|
struct wlr_xwayland_surface *focused = xsurface->xwm->focus_surface;
|
||||||
|
|
@ -1475,7 +1465,6 @@ void xwm_destroy(struct wlr_xwm *xwm) {
|
||||||
xwayland_surface_destroy(xsurface);
|
xwayland_surface_destroy(xsurface);
|
||||||
}
|
}
|
||||||
wl_list_remove(&xwm->compositor_new_surface.link);
|
wl_list_remove(&xwm->compositor_new_surface.link);
|
||||||
wl_list_remove(&xwm->compositor_destroy.link);
|
|
||||||
xcb_disconnect(xwm->xcb_conn);
|
xcb_disconnect(xwm->xcb_conn);
|
||||||
|
|
||||||
free(xwm);
|
free(xwm);
|
||||||
|
|
@ -1770,9 +1759,6 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland) {
|
||||||
xwm->compositor_new_surface.notify = handle_compositor_new_surface;
|
xwm->compositor_new_surface.notify = handle_compositor_new_surface;
|
||||||
wl_signal_add(&wlr_xwayland->compositor->events.new_surface,
|
wl_signal_add(&wlr_xwayland->compositor->events.new_surface,
|
||||||
&xwm->compositor_new_surface);
|
&xwm->compositor_new_surface);
|
||||||
xwm->compositor_destroy.notify = handle_compositor_destroy;
|
|
||||||
wl_signal_add(&wlr_xwayland->compositor->events.destroy,
|
|
||||||
&xwm->compositor_destroy);
|
|
||||||
|
|
||||||
xwm_create_wm_window(xwm);
|
xwm_create_wm_window(xwm);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue