diff --git a/include/labwc.h b/include/labwc.h index d6442228..4fa67c78 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -111,17 +111,19 @@ struct view { struct wlr_xdg_surface *xdg_surface; struct wlr_xwayland_surface *xwayland_surface; struct wlr_surface *surface; - struct wl_listener map; - struct wl_listener unmap; - struct wl_listener destroy; - struct wl_listener request_move; - struct wl_listener request_resize; - struct wl_listener request_configure; bool mapped; bool been_mapped; - int x, y; + int x, y, w, h; bool show_server_side_deco; + + struct wl_listener map; + struct wl_listener unmap; + struct wl_listener destroy; + struct wl_listener commit; + struct wl_listener request_move; + struct wl_listener request_resize; + struct wl_listener request_configure; }; struct keyboard { diff --git a/src/deco.c b/src/deco.c index 62799e27..f24cb2b0 100644 --- a/src/deco.c +++ b/src/deco.c @@ -17,9 +17,8 @@ struct wlr_box deco_max_extents(struct view *view) struct wlr_box box = { .x = view->x - BORDER_WIDTH, .y = view->y - rc.title_height - BORDER_WIDTH, - .width = view->surface->current.width + 2 * BORDER_WIDTH, - .height = view->surface->current.height + rc.title_height + - 2 * BORDER_WIDTH, + .width = view->w + 2 * BORDER_WIDTH, + .height = view->h + rc.title_height + 2 * BORDER_WIDTH, }; return box; } @@ -35,8 +34,7 @@ struct wlr_box deco_box(struct view *view, enum deco_part deco_part) return box; BUG_ON(!view->been_mapped); BUG_ON(!view->show_server_side_deco); - if ((view->surface->current.width < 1) || - (view->surface->current.height < 1)) { + if ((view->w < 1) || (view->h < 1)) { warn("view (%p) has no width/height", view); return box; } @@ -45,55 +43,52 @@ struct wlr_box deco_box(struct view *view, enum deco_part deco_part) wlr_texture_get_size(theme.xbm_close_active_unpressed, &box.width, &box.height); margin = (rc.title_height - box.height) / 2; - box.x = view->x + view->surface->current.width + margin - - rc.title_height; + box.x = view->x + view->w + margin - rc.title_height; box.y = view->y - rc.title_height + margin; break; case LAB_DECO_BUTTON_MAXIMIZE: wlr_texture_get_size(theme.xbm_maximize_active_unpressed, &box.width, &box.height); margin = (rc.title_height - box.height) / 2; - box.x = view->x + view->surface->current.width + margin - - rc.title_height * 2; + box.x = view->x + view->w + margin - rc.title_height * 2; box.y = view->y - rc.title_height + margin; break; case LAB_DECO_BUTTON_ICONIFY: wlr_texture_get_size(theme.xbm_iconify_active_unpressed, &box.width, &box.height); margin = (rc.title_height - box.height) / 2; - box.x = view->x + view->surface->current.width + margin - - rc.title_height * 3; + box.x = view->x + view->w + margin - rc.title_height * 3; box.y = view->y - rc.title_height + margin; break; case LAB_DECO_PART_TITLE: box.x = view->x; box.y = view->y - rc.title_height; - box.width = view->surface->current.width; + box.width = view->w; box.height = rc.title_height; break; case LAB_DECO_PART_TOP: box.x = view->x - BORDER_WIDTH; box.y = view->y - rc.title_height - BORDER_WIDTH; - box.width = view->surface->current.width + 2 * BORDER_WIDTH; + box.width = view->w + 2 * BORDER_WIDTH; box.height = BORDER_WIDTH; break; case LAB_DECO_PART_RIGHT: - box.x = view->x + view->surface->current.width; + box.x = view->x + view->w; box.y = view->y - rc.title_height; box.width = BORDER_WIDTH; - box.height = view->surface->current.height + rc.title_height; + box.height = view->h + rc.title_height; break; case LAB_DECO_PART_BOTTOM: box.x = view->x - BORDER_WIDTH; - box.y = view->y + view->surface->current.height; - box.width = view->surface->current.width + 2 * BORDER_WIDTH; + box.y = view->y + view->h; + box.width = view->w + 2 * BORDER_WIDTH; box.height = +BORDER_WIDTH; break; case LAB_DECO_PART_LEFT: box.x = view->x - BORDER_WIDTH; box.y = view->y - rc.title_height; box.width = BORDER_WIDTH; - box.height = view->surface->current.height + rc.title_height; + box.height = view->h + rc.title_height; break; default: break; diff --git a/src/xdg.c b/src/xdg.c index 7c53d6be..e728f038 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -1,4 +1,6 @@ #include "labwc.h" +#include "common/log.h" +#include "common/bug-on.h" struct xdg_deco { struct wlr_xdg_toplevel_decoration_v1 *wlr_decoration; @@ -63,6 +65,14 @@ static bool has_ssd(struct view *view) return true; } +static void handle_commit(struct wl_listener *listener, void *data) +{ + struct view *view = wl_container_of(listener, view, commit); + BUG_ON(!view->surface); + view->w = view->surface->current.width; + view->h = view->surface->current.height; +} + void xdg_surface_map(struct wl_listener *listener, void *data) { struct view *view = wl_container_of(listener, view, map); @@ -73,6 +83,9 @@ void xdg_surface_map(struct wl_listener *listener, void *data) view_init_position(view); } view->been_mapped = true; + wl_signal_add(&view->xdg_surface->surface->events.commit, + &view->commit); + view->commit.notify = handle_commit; view_focus(view); } @@ -80,6 +93,7 @@ void xdg_surface_unmap(struct wl_listener *listener, void *data) { struct view *view = wl_container_of(listener, view, unmap); view->mapped = false; + wl_list_remove(&view->commit.link); view_focus(next_toplevel(view)); } diff --git a/src/xwl.c b/src/xwl.c index 30adef43..274a590c 100644 --- a/src/xwl.c +++ b/src/xwl.c @@ -1,5 +1,6 @@ #include "labwc.h" #include "common/log.h" +#include "common/bug-on.h" static bool has_ssd(struct view *view) { @@ -11,6 +12,16 @@ static bool has_ssd(struct view *view) return true; } +static void handle_commit(struct wl_listener *listener, void *data) +{ + struct view *view = wl_container_of(listener, view, commit); + BUG_ON(!view->surface); + + /* Must receive commit signal before accessing surface->current* */ + view->w = view->surface->current.width; + view->h = view->surface->current.height; +} + void xwl_surface_map(struct wl_listener *listener, void *data) { struct view *view = wl_container_of(listener, view, map); @@ -23,6 +34,15 @@ void xwl_surface_map(struct wl_listener *listener, void *data) view_init_position(view); } view->been_mapped = true; + + /* + * Add commit listener here, because xwayland map/unmap can change + * the wlr_surface + */ + wl_signal_add(&view->xwayland_surface->surface->events.commit, + &view->commit); + view->commit.notify = handle_commit; + view_focus(view); } @@ -30,6 +50,7 @@ void xwl_surface_unmap(struct wl_listener *listener, void *data) { struct view *view = wl_container_of(listener, view, unmap); view->mapped = false; + wl_list_remove(&view->commit.link); /* * Note that if 'view' is not a toplevel view, the 'front' toplevel view * will be focussed on; but if 'view' is a toplevel view, the 'next'