aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/types/wlr_xdg_shell.h3
-rw-r--r--include/types/wlr_xdg_shell_v6.h3
-rw-r--r--include/wlr/types/wlr_surface.h1
-rw-r--r--types/wlr_surface.c8
-rw-r--r--types/xdg_shell/wlr_xdg_popup.c3
-rw-r--r--types/xdg_shell/wlr_xdg_surface.c18
-rw-r--r--types/xdg_shell/wlr_xdg_toplevel.c3
-rw-r--r--types/xdg_shell_v6/wlr_xdg_popup_v6.c3
-rw-r--r--types/xdg_shell_v6/wlr_xdg_surface_v6.c20
-rw-r--r--types/xdg_shell_v6/wlr_xdg_toplevel_v6.c3
-rw-r--r--xwayland/xwm.c18
11 files changed, 70 insertions, 13 deletions
diff --git a/include/types/wlr_xdg_shell.h b/include/types/wlr_xdg_shell.h
index 7a17d286..93fdc670 100644
--- a/include/types/wlr_xdg_shell.h
+++ b/include/types/wlr_xdg_shell.h
@@ -19,7 +19,8 @@ struct wlr_xdg_surface *create_xdg_surface(
uint32_t id);
void unmap_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);
struct wlr_xdg_positioner_resource *get_xdg_positioner_from_resource(
diff --git a/include/types/wlr_xdg_shell_v6.h b/include/types/wlr_xdg_shell_v6.h
index 030c10e4..59fca667 100644
--- a/include/types/wlr_xdg_shell_v6.h
+++ b/include/types/wlr_xdg_shell_v6.h
@@ -19,7 +19,8 @@ struct wlr_xdg_surface_v6 *create_xdg_surface_v6(
uint32_t id);
void unmap_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);
struct wlr_xdg_positioner_v6_resource *get_xdg_positioner_v6_from_resource(
diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h
index 0e3b5ff4..ee9afa86 100644
--- a/include/wlr/types/wlr_surface.h
+++ b/include/wlr/types/wlr_surface.h
@@ -39,6 +39,7 @@ struct wlr_surface_state {
struct wlr_surface_role {
const char *name;
void (*commit)(struct wlr_surface *surface);
+ void (*precommit)(struct wlr_surface *surface);
};
struct wlr_surface {
diff --git a/types/wlr_surface.c b/types/wlr_surface.c
index f2b248ca..ab1dfc2d 100644
--- a/types/wlr_surface.c
+++ b/types/wlr_surface.c
@@ -360,10 +360,14 @@ static void surface_update_opaque_region(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);
+ 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->sy += surface->pending.dy;
surface_update_damage(&surface->buffer_damage,
diff --git a/types/xdg_shell/wlr_xdg_popup.c b/types/xdg_shell/wlr_xdg_popup.c
index 26d248e1..b3409261 100644
--- a/types/xdg_shell/wlr_xdg_popup.c
+++ b/types/xdg_shell/wlr_xdg_popup.c
@@ -214,7 +214,8 @@ static void xdg_popup_handle_resource_destroy(struct wl_resource *resource) {
const struct wlr_surface_role xdg_popup_surface_role = {
.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,
diff --git a/types/xdg_shell/wlr_xdg_surface.c b/types/xdg_shell/wlr_xdg_surface.c
index dc98a3a5..0ff47a04 100644
--- a/types/xdg_shell/wlr_xdg_surface.c
+++ b/types/xdg_shell/wlr_xdg_surface.c
@@ -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 =
wlr_xdg_surface_from_wlr_surface(wlr_surface);
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,
void *data) {
struct wlr_xdg_surface *xdg_surface =
diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c
index 0a1b9bfd..3bf7fd67 100644
--- a/types/xdg_shell/wlr_xdg_toplevel.c
+++ b/types/xdg_shell/wlr_xdg_toplevel.c
@@ -451,7 +451,8 @@ static void xdg_toplevel_handle_resource_destroy(struct wl_resource *resource) {
const struct wlr_surface_role xdg_toplevel_surface_role = {
.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,
diff --git a/types/xdg_shell_v6/wlr_xdg_popup_v6.c b/types/xdg_shell_v6/wlr_xdg_popup_v6.c
index 59af020f..097e0253 100644
--- a/types/xdg_shell_v6/wlr_xdg_popup_v6.c
+++ b/types/xdg_shell_v6/wlr_xdg_popup_v6.c
@@ -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 = {
.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,
diff --git a/types/xdg_shell_v6/wlr_xdg_surface_v6.c b/types/xdg_shell_v6/wlr_xdg_surface_v6.c
index ca729c48..c4007c71 100644
--- a/types/xdg_shell_v6/wlr_xdg_surface_v6.c
+++ b/types/xdg_shell_v6/wlr_xdg_surface_v6.c
@@ -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 =
wlr_xdg_surface_v6_from_wlr_surface(wlr_surface);
if (surface == NULL) {
@@ -407,9 +407,21 @@ void handle_xdg_surface_v6_committed(struct wlr_surface *wlr_surface) {
surface->mapped = true;
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);
+ }
}
}
diff --git a/types/xdg_shell_v6/wlr_xdg_toplevel_v6.c b/types/xdg_shell_v6/wlr_xdg_toplevel_v6.c
index 3490f337..297f49f5 100644
--- a/types/xdg_shell_v6/wlr_xdg_toplevel_v6.c
+++ b/types/xdg_shell_v6/wlr_xdg_toplevel_v6.c
@@ -421,7 +421,8 @@ static void xdg_toplevel_handle_resource_destroy(struct wl_resource *resource) {
const struct wlr_surface_role xdg_toplevel_v6_surface_role = {
.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,
diff --git a/xwayland/xwm.c b/xwayland/xwm.c
index 6632b5fc..7999480a 100644
--- a/xwayland/xwm.c
+++ b/xwayland/xwm.c
@@ -654,9 +654,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 = {
.name = "wlr_xwayland_surface",
.commit = xwayland_surface_role_commit,
+ .precommit = xwayland_surface_role_precommit,
};
static void handle_surface_destroy(struct wl_listener *listener, void *data) {