mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-22 04:45:58 +01:00
xdg-shell: drop automatic surface configuration
Compositors now are expected to wait for an initial commit by checking wlr_xdg_surface.initial_commit on every surface commit and send (schedule) configure events manually.
This commit is contained in:
parent
d368028bd5
commit
811ca199c4
6 changed files with 69 additions and 37 deletions
|
@ -21,7 +21,6 @@ void create_xdg_popup(struct wlr_xdg_surface *surface,
|
||||||
void reset_xdg_popup(struct wlr_xdg_popup *popup);
|
void reset_xdg_popup(struct wlr_xdg_popup *popup);
|
||||||
void destroy_xdg_popup(struct wlr_xdg_popup *popup);
|
void destroy_xdg_popup(struct wlr_xdg_popup *popup);
|
||||||
void handle_xdg_popup_client_commit(struct wlr_xdg_popup *popup);
|
void handle_xdg_popup_client_commit(struct wlr_xdg_popup *popup);
|
||||||
void handle_xdg_popup_committed(struct wlr_xdg_popup *popup);
|
|
||||||
struct wlr_xdg_popup_configure *send_xdg_popup_configure(
|
struct wlr_xdg_popup_configure *send_xdg_popup_configure(
|
||||||
struct wlr_xdg_popup *popup);
|
struct wlr_xdg_popup *popup);
|
||||||
void handle_xdg_popup_ack_configure(struct wlr_xdg_popup *popup,
|
void handle_xdg_popup_ack_configure(struct wlr_xdg_popup *popup,
|
||||||
|
@ -32,7 +31,6 @@ void create_xdg_toplevel(struct wlr_xdg_surface *surface,
|
||||||
void reset_xdg_toplevel(struct wlr_xdg_toplevel *toplevel);
|
void reset_xdg_toplevel(struct wlr_xdg_toplevel *toplevel);
|
||||||
void destroy_xdg_toplevel(struct wlr_xdg_toplevel *toplevel);
|
void destroy_xdg_toplevel(struct wlr_xdg_toplevel *toplevel);
|
||||||
void handle_xdg_toplevel_client_commit(struct wlr_xdg_toplevel *toplevel);
|
void handle_xdg_toplevel_client_commit(struct wlr_xdg_toplevel *toplevel);
|
||||||
void handle_xdg_toplevel_committed(struct wlr_xdg_toplevel *toplevel);
|
|
||||||
struct wlr_xdg_toplevel_configure *send_xdg_toplevel_configure(
|
struct wlr_xdg_toplevel_configure *send_xdg_toplevel_configure(
|
||||||
struct wlr_xdg_toplevel *toplevel);
|
struct wlr_xdg_toplevel *toplevel);
|
||||||
void handle_xdg_toplevel_ack_configure(struct wlr_xdg_toplevel *toplevel,
|
void handle_xdg_toplevel_ack_configure(struct wlr_xdg_toplevel *toplevel,
|
||||||
|
|
|
@ -95,7 +95,6 @@ struct wlr_xdg_popup {
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
|
|
||||||
struct wl_resource *resource;
|
struct wl_resource *resource;
|
||||||
bool sent_initial_configure;
|
|
||||||
struct wlr_surface *parent;
|
struct wlr_surface *parent;
|
||||||
struct wlr_seat *seat;
|
struct wlr_seat *seat;
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,7 @@ struct tinywl_toplevel {
|
||||||
struct wlr_scene_tree *scene_tree;
|
struct wlr_scene_tree *scene_tree;
|
||||||
struct wl_listener map;
|
struct wl_listener map;
|
||||||
struct wl_listener unmap;
|
struct wl_listener unmap;
|
||||||
|
struct wl_listener commit;
|
||||||
struct wl_listener destroy;
|
struct wl_listener destroy;
|
||||||
struct wl_listener request_move;
|
struct wl_listener request_move;
|
||||||
struct wl_listener request_resize;
|
struct wl_listener request_resize;
|
||||||
|
@ -93,6 +94,12 @@ struct tinywl_toplevel {
|
||||||
struct wl_listener request_fullscreen;
|
struct wl_listener request_fullscreen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct tinywl_popup {
|
||||||
|
struct wlr_xdg_popup *xdg_popup;
|
||||||
|
struct wl_listener commit;
|
||||||
|
struct wl_listener destroy;
|
||||||
|
};
|
||||||
|
|
||||||
struct tinywl_keyboard {
|
struct tinywl_keyboard {
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
struct tinywl_server *server;
|
struct tinywl_server *server;
|
||||||
|
@ -672,12 +679,26 @@ static void xdg_toplevel_unmap(struct wl_listener *listener, void *data) {
|
||||||
wl_list_remove(&toplevel->link);
|
wl_list_remove(&toplevel->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void xdg_toplevel_commit(struct wl_listener *listener, void *data) {
|
||||||
|
/* Called when a new surface state is committed. */
|
||||||
|
struct tinywl_toplevel *toplevel = wl_container_of(listener, toplevel, commit);
|
||||||
|
|
||||||
|
if (toplevel->xdg_toplevel->base->initial_commit) {
|
||||||
|
/* When an xdg_surface performs an initial commit, the compositor must
|
||||||
|
* reply with a configure so the client can map the surface. tinywl
|
||||||
|
* configures the xdg_toplevel with 0,0 size to let the client pick the
|
||||||
|
* dimensions itself. */
|
||||||
|
wlr_xdg_toplevel_set_size(toplevel->xdg_toplevel, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void xdg_toplevel_destroy(struct wl_listener *listener, void *data) {
|
static void xdg_toplevel_destroy(struct wl_listener *listener, void *data) {
|
||||||
/* Called when the xdg_toplevel is destroyed. */
|
/* Called when the xdg_toplevel is destroyed. */
|
||||||
struct tinywl_toplevel *toplevel = wl_container_of(listener, toplevel, destroy);
|
struct tinywl_toplevel *toplevel = wl_container_of(listener, toplevel, destroy);
|
||||||
|
|
||||||
wl_list_remove(&toplevel->map.link);
|
wl_list_remove(&toplevel->map.link);
|
||||||
wl_list_remove(&toplevel->unmap.link);
|
wl_list_remove(&toplevel->unmap.link);
|
||||||
|
wl_list_remove(&toplevel->commit.link);
|
||||||
wl_list_remove(&toplevel->destroy.link);
|
wl_list_remove(&toplevel->destroy.link);
|
||||||
wl_list_remove(&toplevel->request_move.link);
|
wl_list_remove(&toplevel->request_move.link);
|
||||||
wl_list_remove(&toplevel->request_resize.link);
|
wl_list_remove(&toplevel->request_resize.link);
|
||||||
|
@ -793,6 +814,8 @@ static void server_new_xdg_toplevel(struct wl_listener *listener, void *data) {
|
||||||
wl_signal_add(&xdg_toplevel->base->surface->events.map, &toplevel->map);
|
wl_signal_add(&xdg_toplevel->base->surface->events.map, &toplevel->map);
|
||||||
toplevel->unmap.notify = xdg_toplevel_unmap;
|
toplevel->unmap.notify = xdg_toplevel_unmap;
|
||||||
wl_signal_add(&xdg_toplevel->base->surface->events.unmap, &toplevel->unmap);
|
wl_signal_add(&xdg_toplevel->base->surface->events.unmap, &toplevel->unmap);
|
||||||
|
toplevel->commit.notify = xdg_toplevel_commit;
|
||||||
|
wl_signal_add(&xdg_toplevel->base->surface->events.commit, &toplevel->commit);
|
||||||
|
|
||||||
toplevel->destroy.notify = xdg_toplevel_destroy;
|
toplevel->destroy.notify = xdg_toplevel_destroy;
|
||||||
wl_signal_add(&xdg_toplevel->events.destroy, &toplevel->destroy);
|
wl_signal_add(&xdg_toplevel->events.destroy, &toplevel->destroy);
|
||||||
|
@ -808,10 +831,37 @@ static void server_new_xdg_toplevel(struct wl_listener *listener, void *data) {
|
||||||
wl_signal_add(&xdg_toplevel->events.request_fullscreen, &toplevel->request_fullscreen);
|
wl_signal_add(&xdg_toplevel->events.request_fullscreen, &toplevel->request_fullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void xdg_popup_commit(struct wl_listener *listener, void *data) {
|
||||||
|
/* Called when a new surface state is committed. */
|
||||||
|
struct tinywl_popup *popup = wl_container_of(listener, popup, commit);
|
||||||
|
|
||||||
|
if (popup->xdg_popup->base->initial_commit) {
|
||||||
|
/* When an xdg_surface performs an initial commit, the compositor must
|
||||||
|
* reply with a configure so the client can map the surface.
|
||||||
|
* tinywl sends an empty configure. A more sophisticated compositor
|
||||||
|
* might change an xdg_popup's geometry to ensure it's not positioned
|
||||||
|
* off-screen, for example. */
|
||||||
|
wlr_xdg_surface_schedule_configure(popup->xdg_popup->base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xdg_popup_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
/* Called when the xdg_popup is destroyed. */
|
||||||
|
struct tinywl_popup *popup = wl_container_of(listener, popup, destroy);
|
||||||
|
|
||||||
|
wl_list_remove(&popup->commit.link);
|
||||||
|
wl_list_remove(&popup->destroy.link);
|
||||||
|
|
||||||
|
free(popup);
|
||||||
|
}
|
||||||
|
|
||||||
static void server_new_xdg_popup(struct wl_listener *listener, void *data) {
|
static void server_new_xdg_popup(struct wl_listener *listener, void *data) {
|
||||||
/* This event is raised when a client creates a new popup. */
|
/* This event is raised when a client creates a new popup. */
|
||||||
struct wlr_xdg_popup *xdg_popup = data;
|
struct wlr_xdg_popup *xdg_popup = data;
|
||||||
|
|
||||||
|
struct tinywl_popup *popup = calloc(1, sizeof(*popup));
|
||||||
|
popup->xdg_popup = xdg_popup;
|
||||||
|
|
||||||
/* We must add xdg popups to the scene graph so they get rendered. The
|
/* We must add xdg popups to the scene graph so they get rendered. The
|
||||||
* wlroots scene graph provides a helper for this, but to use it we must
|
* wlroots scene graph provides a helper for this, but to use it we must
|
||||||
* provide the proper parent scene node of the xdg popup. To enable this,
|
* provide the proper parent scene node of the xdg popup. To enable this,
|
||||||
|
@ -821,6 +871,12 @@ static void server_new_xdg_popup(struct wl_listener *listener, void *data) {
|
||||||
assert(parent != NULL);
|
assert(parent != NULL);
|
||||||
struct wlr_scene_tree *parent_tree = parent->data;
|
struct wlr_scene_tree *parent_tree = parent->data;
|
||||||
xdg_popup->base->data = wlr_scene_xdg_surface_create(parent_tree, xdg_popup->base);
|
xdg_popup->base->data = wlr_scene_xdg_surface_create(parent_tree, xdg_popup->base);
|
||||||
|
|
||||||
|
popup->commit.notify = xdg_popup_commit;
|
||||||
|
wl_signal_add(&xdg_popup->base->surface->events.commit, &popup->commit);
|
||||||
|
|
||||||
|
popup->destroy.notify = xdg_popup_destroy;
|
||||||
|
wl_signal_add(&xdg_popup->events.destroy, &popup->destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
|
@ -246,13 +246,6 @@ void handle_xdg_popup_client_commit(struct wlr_xdg_popup *popup) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_xdg_popup_committed(struct wlr_xdg_popup *popup) {
|
|
||||||
if (popup->base->initial_commit && !popup->sent_initial_configure) {
|
|
||||||
wlr_xdg_surface_schedule_configure(popup->base);
|
|
||||||
popup->sent_initial_configure = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct xdg_popup_interface xdg_popup_implementation;
|
static const struct xdg_popup_interface xdg_popup_implementation;
|
||||||
|
|
||||||
struct wlr_xdg_popup *wlr_xdg_popup_from_resource(
|
struct wlr_xdg_popup *wlr_xdg_popup_from_resource(
|
||||||
|
@ -285,7 +278,7 @@ static void xdg_popup_handle_grab(struct wl_client *client,
|
||||||
wlr_xdg_popup_destroy(popup);
|
wlr_xdg_popup_destroy(popup);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (popup->sent_initial_configure) {
|
if (popup->base->surface->mapped) {
|
||||||
wl_resource_post_error(popup->resource,
|
wl_resource_post_error(popup->resource,
|
||||||
XDG_POPUP_ERROR_INVALID_GRAB,
|
XDG_POPUP_ERROR_INVALID_GRAB,
|
||||||
"xdg_popup is already mapped");
|
"xdg_popup is already mapped");
|
||||||
|
@ -472,8 +465,6 @@ void reset_xdg_popup(struct wlr_xdg_popup *popup) {
|
||||||
|
|
||||||
popup->seat = NULL;
|
popup->seat = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
popup->sent_initial_configure = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy_xdg_popup(struct wlr_xdg_popup *popup) {
|
void destroy_xdg_popup(struct wlr_xdg_popup *popup) {
|
||||||
|
|
|
@ -309,16 +309,12 @@ static void xdg_surface_role_commit(struct wlr_surface *wlr_surface) {
|
||||||
assert(0 && "not reached");
|
assert(0 && "not reached");
|
||||||
return;
|
return;
|
||||||
case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
|
case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
|
||||||
if (surface->toplevel != NULL) {
|
if (surface->toplevel == NULL) {
|
||||||
handle_xdg_toplevel_committed(surface->toplevel);
|
|
||||||
} else {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WLR_XDG_SURFACE_ROLE_POPUP:
|
case WLR_XDG_SURFACE_ROLE_POPUP:
|
||||||
if (surface->popup != NULL) {
|
if (surface->popup == NULL) {
|
||||||
handle_xdg_popup_committed(surface->popup);
|
|
||||||
} else {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -131,24 +131,6 @@ void handle_xdg_toplevel_client_commit(struct wlr_xdg_toplevel *toplevel) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_xdg_toplevel_committed(struct wlr_xdg_toplevel *toplevel) {
|
|
||||||
if (toplevel->base->initial_commit) {
|
|
||||||
// On the initial commit, send a configure request to tell the client it
|
|
||||||
// is added
|
|
||||||
wlr_xdg_surface_schedule_configure(toplevel->base);
|
|
||||||
|
|
||||||
if (toplevel->base->client->shell->version >=
|
|
||||||
XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) {
|
|
||||||
// The first configure event must carry WM capabilities
|
|
||||||
wlr_xdg_toplevel_set_wm_capabilities(toplevel,
|
|
||||||
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU |
|
|
||||||
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE |
|
|
||||||
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN |
|
|
||||||
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct xdg_toplevel_interface xdg_toplevel_implementation;
|
static const struct xdg_toplevel_interface xdg_toplevel_implementation;
|
||||||
|
|
||||||
struct wlr_xdg_toplevel *wlr_xdg_toplevel_from_resource(
|
struct wlr_xdg_toplevel *wlr_xdg_toplevel_from_resource(
|
||||||
|
@ -506,6 +488,16 @@ void create_xdg_toplevel(struct wlr_xdg_surface *surface,
|
||||||
|
|
||||||
set_xdg_surface_role_object(surface, surface->toplevel->resource);
|
set_xdg_surface_role_object(surface, surface->toplevel->resource);
|
||||||
|
|
||||||
|
if (surface->client->shell->version >= XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) {
|
||||||
|
// The first configure event must carry WM capabilities
|
||||||
|
surface->toplevel->scheduled.wm_capabilities =
|
||||||
|
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU |
|
||||||
|
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE |
|
||||||
|
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN |
|
||||||
|
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE;
|
||||||
|
surface->toplevel->scheduled.fields |= WLR_XDG_TOPLEVEL_CONFIGURE_WM_CAPABILITIES;
|
||||||
|
}
|
||||||
|
|
||||||
wl_signal_emit_mutable(&surface->client->shell->events.new_toplevel, surface->toplevel);
|
wl_signal_emit_mutable(&surface->client->shell->events.new_toplevel, surface->toplevel);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in a new issue