Seemingly proper client-side decorations

This commit is contained in:
Keith Bowes 2022-02-15 09:22:24 -05:00
parent f0d50cb57d
commit bed7e244c2
4 changed files with 36 additions and 20 deletions

View file

@ -33,12 +33,15 @@ struct wb_view {
struct wb_server *server;
struct wlr_xdg_surface *xdg_surface;
struct wlr_xdg_toplevel_decoration_v1 *decoration;
struct wl_listener ack_configure;
struct wl_listener map;
struct wl_listener unmap;
struct wl_listener destroy;
struct wl_listener request_move;
struct wl_listener request_resize;
bool mapped;
bool configured, mapped;
int x, y;
};

View file

@ -18,27 +18,14 @@ static void handle_xdg_decoration_mode(struct wl_listener *listener, void *data)
{
struct wlr_xdg_toplevel_decoration_v1 *toplevel_decoration = data;
struct wb_decoration *decoration = wl_container_of(listener, decoration, request_mode);
struct wb_view *view = wl_container_of(decoration->server->views.next, view, link);
wlr_xdg_toplevel_decoration_v1_set_mode(toplevel_decoration, WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE);
if (decoration->server)
{
struct wb_view *view = wl_container_of(decoration->server->views.next, view, link);
struct wlr_box geo_box;
wlr_xdg_surface_get_geometry(toplevel_decoration->surface, &geo_box);
/* TODO: Figure out how to get the actual height of the CSD
* titlebar, which may or may not be 30px.
* Logically, geo_box.height should have the height of the
* decoration, but for some reason, it's 0. */
/* view->y += geo_box.height; */
view->y = view->y > 0 ? view->y : (geo_box.height > 0 ? geo_box.height : 30);
wlr_xdg_surface_get_geometry(view->xdg_surface, &geo_box);
wlr_xdg_toplevel_set_size(view->xdg_surface, geo_box.width - view->x, geo_box.height - view->y);
}
view->decoration = toplevel_decoration;
}
static void handle_new_xdg_toplevel_decoration(struct wl_listener *listener, void *data)
{
struct wb_decoration *decoration = (struct wb_decoration *) calloc(1, sizeof(struct wb_decoration));
handle_xdg_decoration_mode(&decoration->request_mode, data);
struct wb_server *server = wl_container_of(listener, server, new_xdg_decoration);
decoration->server = server;
struct wlr_xdg_toplevel_decoration_v1 *toplevel_decoration = data;
@ -48,8 +35,7 @@ static void handle_new_xdg_toplevel_decoration(struct wl_listener *listener, voi
wl_signal_add(&toplevel_decoration->events.request_mode, &decoration->request_mode);
decoration->mode_destroy.notify = free_xdg_decoration_mode;
wl_signal_add(&toplevel_decoration->events.destroy, &decoration->mode_destroy);
/* TODO: Only call when the user's settings specify to always apply
* decorations */
/* For some reason, a lot of clients don't emit the request_mode signal. */
handle_xdg_decoration_mode(&decoration->request_mode, toplevel_decoration);
}

View file

@ -7,8 +7,6 @@
struct wb_decoration {
struct wb_server *server;
struct wlr_xdg_decoration_manager_v1 *decoration_manager;
struct wlr_xdg_toplevel_decoration_v1 *toplevel_decoration;
struct wl_listener toplevel_decoration_destroy;
struct wl_listener request_mode;

View file

@ -41,6 +41,33 @@ void focus_view(struct wb_view *view, struct wlr_surface *surface) {
keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers);
}
static void xdg_surface_ack_configure(struct wl_listener *listener, void *data) {
/* Called after the surface is configured */
struct wb_view *view = wl_container_of(listener, view, ack_configure);
/* If there's no decoration, there's no need to change the size and
* cause endless reconfigures. */
if (!view->decoration)
return;
if (!view->configured)
{
/* With client-side decorations, after setting the size, it'll
* return a negative y value, which can be used to determine the
* size of the CSD titlebar. */
struct wlr_box geo_box;
wlr_xdg_surface_get_geometry(view->xdg_surface, &geo_box);
if (geo_box.y < 0)
{
view->y = geo_box.y * -1;
view->configured = true;
}
/* Set size here, so the view->y value will be known */
wlr_xdg_toplevel_set_size(view->xdg_surface, geo_box.width - view->x, geo_box.height - view->y);
}
}
static void xdg_surface_map(struct wl_listener *listener, void *data) {
/* Called when the surface is mapped, or ready to display on-screen. */
struct wb_view *view = wl_container_of(listener, view, map);
@ -149,6 +176,8 @@ static void handle_new_xdg_surface(struct wl_listener *listener, void *data) {
view->xdg_surface = xdg_surface;
/* Listen to the various events it can emit */
view->ack_configure.notify = xdg_surface_ack_configure;
wl_signal_add(&xdg_surface->events.ack_configure, &view->ack_configure);
view->map.notify = xdg_surface_map;
wl_signal_add(&xdg_surface->events.map, &view->map);
view->unmap.notify = xdg_surface_unmap;