surface: add wlr_surface_role.precommit

This allows to emit the unmap event before the surface becomes
actually unmapped for most shells.
This commit is contained in:
emersion 2018-07-09 23:02:03 +01:00
parent 4984ea49ee
commit 16d7e09d99
11 changed files with 70 additions and 13 deletions

View File

@ -19,7 +19,8 @@ struct wlr_xdg_surface *create_xdg_surface(
uint32_t id); uint32_t id);
void unmap_xdg_surface(struct wlr_xdg_surface *surface); void unmap_xdg_surface(struct wlr_xdg_surface *surface);
void destroy_xdg_surface(struct wlr_xdg_surface *surface); void destroy_xdg_surface(struct wlr_xdg_surface *surface);
void handle_xdg_surface_committed(struct wlr_surface *wlr_surface); void handle_xdg_surface_commit(struct wlr_surface *wlr_surface);
void handle_xdg_surface_precommit(struct wlr_surface *wlr_surface);
void create_xdg_positioner(struct wlr_xdg_client *client, uint32_t id); void create_xdg_positioner(struct wlr_xdg_client *client, uint32_t id);
struct wlr_xdg_positioner_resource *get_xdg_positioner_from_resource( struct wlr_xdg_positioner_resource *get_xdg_positioner_from_resource(

View File

@ -19,7 +19,8 @@ struct wlr_xdg_surface_v6 *create_xdg_surface_v6(
uint32_t id); uint32_t id);
void unmap_xdg_surface_v6(struct wlr_xdg_surface_v6 *surface); void unmap_xdg_surface_v6(struct wlr_xdg_surface_v6 *surface);
void destroy_xdg_surface_v6(struct wlr_xdg_surface_v6 *surface); void destroy_xdg_surface_v6(struct wlr_xdg_surface_v6 *surface);
void handle_xdg_surface_v6_committed(struct wlr_surface *wlr_surface); void handle_xdg_surface_v6_commit(struct wlr_surface *wlr_surface);
void handle_xdg_surface_v6_precommit(struct wlr_surface *wlr_surface);
void create_xdg_positioner_v6(struct wlr_xdg_client_v6 *client, uint32_t id); void create_xdg_positioner_v6(struct wlr_xdg_client_v6 *client, uint32_t id);
struct wlr_xdg_positioner_v6_resource *get_xdg_positioner_v6_from_resource( struct wlr_xdg_positioner_v6_resource *get_xdg_positioner_v6_from_resource(

View File

@ -39,6 +39,7 @@ struct wlr_surface_state {
struct wlr_surface_role { struct wlr_surface_role {
const char *name; const char *name;
void (*commit)(struct wlr_surface *surface); void (*commit)(struct wlr_surface *surface);
void (*precommit)(struct wlr_surface *surface);
}; };
struct wlr_surface { struct wlr_surface {

View File

@ -360,10 +360,14 @@ static void surface_update_opaque_region(struct wlr_surface *surface) {
} }
static void surface_commit_pending(struct wlr_surface *surface) { static void surface_commit_pending(struct wlr_surface *surface) {
bool invalid_buffer = surface->pending.committed & WLR_SURFACE_STATE_BUFFER;
surface_state_finalize(surface, &surface->pending); surface_state_finalize(surface, &surface->pending);
if (surface->role && surface->role->precommit) {
surface->role->precommit(surface);
}
bool invalid_buffer = surface->pending.committed & WLR_SURFACE_STATE_BUFFER;
surface->sx += surface->pending.dx; surface->sx += surface->pending.dx;
surface->sy += surface->pending.dy; surface->sy += surface->pending.dy;
surface_update_damage(&surface->buffer_damage, surface_update_damage(&surface->buffer_damage,

View File

@ -214,7 +214,8 @@ static void xdg_popup_handle_resource_destroy(struct wl_resource *resource) {
const struct wlr_surface_role xdg_popup_surface_role = { const struct wlr_surface_role xdg_popup_surface_role = {
.name = "xdg_popup", .name = "xdg_popup",
.commit = handle_xdg_surface_committed, .commit = handle_xdg_surface_commit,
.precommit = handle_xdg_surface_precommit,
}; };
void create_xdg_popup(struct wlr_xdg_surface *xdg_surface, void create_xdg_popup(struct wlr_xdg_surface *xdg_surface,

View File

@ -313,7 +313,7 @@ static void xdg_surface_handle_surface_commit(struct wl_listener *listener,
} }
} }
void handle_xdg_surface_committed(struct wlr_surface *wlr_surface) { void handle_xdg_surface_commit(struct wlr_surface *wlr_surface) {
struct wlr_xdg_surface *surface = struct wlr_xdg_surface *surface =
wlr_xdg_surface_from_wlr_surface(wlr_surface); wlr_xdg_surface_from_wlr_surface(wlr_surface);
if (surface == NULL) { if (surface == NULL) {
@ -355,6 +355,22 @@ void handle_xdg_surface_committed(struct wlr_surface *wlr_surface) {
} }
} }
void handle_xdg_surface_precommit(struct wlr_surface *wlr_surface) {
struct wlr_xdg_surface *surface =
wlr_xdg_surface_from_wlr_surface(wlr_surface);
if (surface == NULL) {
return;
}
if (wlr_surface->pending.committed & WLR_SURFACE_STATE_BUFFER &&
wlr_surface->pending.buffer_resource == NULL) {
// This is a NULL commit
if (surface->configured && surface->mapped) {
unmap_xdg_surface(surface);
}
}
}
static void xdg_surface_handle_surface_destroy(struct wl_listener *listener, static void xdg_surface_handle_surface_destroy(struct wl_listener *listener,
void *data) { void *data) {
struct wlr_xdg_surface *xdg_surface = struct wlr_xdg_surface *xdg_surface =

View File

@ -449,7 +449,8 @@ static void xdg_toplevel_handle_resource_destroy(struct wl_resource *resource) {
const struct wlr_surface_role xdg_toplevel_surface_role = { const struct wlr_surface_role xdg_toplevel_surface_role = {
.name = "xdg_toplevel", .name = "xdg_toplevel",
.commit = handle_xdg_surface_committed, .commit = handle_xdg_surface_commit,
.precommit = handle_xdg_surface_precommit,
}; };
void create_xdg_toplevel(struct wlr_xdg_surface *xdg_surface, void create_xdg_toplevel(struct wlr_xdg_surface *xdg_surface,

View File

@ -251,7 +251,8 @@ void handle_xdg_surface_v6_popup_committed(struct wlr_xdg_surface_v6 *surface) {
const struct wlr_surface_role xdg_popup_v6_surface_role = { const struct wlr_surface_role xdg_popup_v6_surface_role = {
.name = "xdg_popup_v6", .name = "xdg_popup_v6",
.commit = handle_xdg_surface_v6_committed, .commit = handle_xdg_surface_v6_commit,
.precommit = handle_xdg_surface_v6_precommit,
}; };
void create_xdg_popup_v6(struct wlr_xdg_surface_v6 *xdg_surface, void create_xdg_popup_v6(struct wlr_xdg_surface_v6 *xdg_surface,

View File

@ -371,7 +371,7 @@ static void xdg_surface_handle_surface_commit(struct wl_listener *listener,
} }
} }
void handle_xdg_surface_v6_committed(struct wlr_surface *wlr_surface) { void handle_xdg_surface_v6_commit(struct wlr_surface *wlr_surface) {
struct wlr_xdg_surface_v6 *surface = struct wlr_xdg_surface_v6 *surface =
wlr_xdg_surface_v6_from_wlr_surface(wlr_surface); wlr_xdg_surface_v6_from_wlr_surface(wlr_surface);
if (surface == NULL) { if (surface == NULL) {
@ -407,9 +407,21 @@ void handle_xdg_surface_v6_committed(struct wlr_surface *wlr_surface) {
surface->mapped = true; surface->mapped = true;
wlr_signal_emit_safe(&surface->events.map, surface); wlr_signal_emit_safe(&surface->events.map, surface);
} }
if (surface->configured && !wlr_surface_has_buffer(surface->surface) && }
surface->mapped) {
unmap_xdg_surface_v6(surface); void handle_xdg_surface_v6_precommit(struct wlr_surface *wlr_surface) {
struct wlr_xdg_surface_v6 *surface =
wlr_xdg_surface_v6_from_wlr_surface(wlr_surface);
if (surface == NULL) {
return;
}
if (wlr_surface->pending.committed & WLR_SURFACE_STATE_BUFFER &&
wlr_surface->pending.buffer_resource == NULL) {
// This is a NULL commit
if (surface->configured && surface->mapped) {
unmap_xdg_surface_v6(surface);
}
} }
} }

View File

@ -419,7 +419,8 @@ static void xdg_toplevel_handle_resource_destroy(struct wl_resource *resource) {
const struct wlr_surface_role xdg_toplevel_v6_surface_role = { const struct wlr_surface_role xdg_toplevel_v6_surface_role = {
.name = "xdg_toplevel_v6", .name = "xdg_toplevel_v6",
.commit = handle_xdg_surface_v6_committed, .commit = handle_xdg_surface_v6_commit,
.precommit = handle_xdg_surface_v6_precommit,
}; };
void create_xdg_toplevel_v6(struct wlr_xdg_surface_v6 *xdg_surface, void create_xdg_toplevel_v6(struct wlr_xdg_surface_v6 *xdg_surface,

View File

@ -652,9 +652,27 @@ static void xwayland_surface_role_commit(struct wlr_surface *wlr_surface) {
} }
} }
static void xwayland_surface_role_precommit(struct wlr_surface *wlr_surface) {
assert(wlr_surface->role == &xwayland_surface_role);
struct wlr_xwayland_surface *surface = wlr_surface->role_data;
if (surface == NULL) {
return;
}
if (wlr_surface->pending.committed & WLR_SURFACE_STATE_BUFFER &&
wlr_surface->pending.buffer_resource == NULL) {
// This is a NULL commit
if (surface->mapped) {
wlr_signal_emit_safe(&surface->events.unmap, surface);
surface->mapped = false;
}
}
}
static const struct wlr_surface_role xwayland_surface_role = { static const struct wlr_surface_role xwayland_surface_role = {
.name = "wlr_xwayland_surface", .name = "wlr_xwayland_surface",
.commit = xwayland_surface_role_commit, .commit = xwayland_surface_role_commit,
.precommit = xwayland_surface_role_precommit,
}; };
static void handle_surface_destroy(struct wl_listener *listener, void *data) { static void handle_surface_destroy(struct wl_listener *listener, void *data) {