diff --git a/include/ssd-internal.h b/include/ssd-internal.h index fda196e6..5a215a52 100644 --- a/include/ssd-internal.h +++ b/include/ssd-internal.h @@ -59,6 +59,8 @@ struct ssd { } title; } state; + struct wlr_scene_rect *view_background; + /* An invisible area around the view which allows resizing */ struct ssd_sub_tree extents; diff --git a/src/ssd/ssd-border.c b/src/ssd/ssd-border.c index 63604244..120c2fba 100644 --- a/src/ssd/ssd-border.c +++ b/src/ssd/ssd-border.c @@ -82,7 +82,7 @@ ssd_border_update(struct ssd *ssd) struct theme *theme = view->server->theme; - int width = view->current.width; + int width = MAX(view->current.width, LAB_MIN_VIEW_WIDTH); int height = view_effective_height(view, /* use_pending */ false); int full_width = width + 2 * theme->border_width; diff --git a/src/ssd/ssd-extents.c b/src/ssd/ssd-extents.c index 4bb5b69d..c8edcd1e 100644 --- a/src/ssd/ssd-extents.c +++ b/src/ssd/ssd-extents.c @@ -104,7 +104,7 @@ ssd_extents_update(struct ssd *ssd) struct theme *theme = view->server->theme; - int width = view->current.width; + int width = MAX(view->current.width, LAB_MIN_VIEW_WIDTH); int height = view_effective_height(view, /* use_pending */ false); int full_height = height + theme->border_width * 2 + ssd->titlebar.height; int full_width = width + 2 * theme->border_width; diff --git a/src/ssd/ssd-shadow.c b/src/ssd/ssd-shadow.c index 3e6227aa..57212866 100644 --- a/src/ssd/ssd-shadow.c +++ b/src/ssd/ssd-shadow.c @@ -169,7 +169,7 @@ set_shadow_geometry(struct ssd *ssd) struct view *view = ssd->view; struct theme *theme = view->server->theme; int titlebar_height = ssd->titlebar.height; - int width = view->current.width; + int width = MAX(view->current.width, LAB_MIN_VIEW_WIDTH); int height = view_effective_height(view, false) + titlebar_height; struct ssd_part *part; diff --git a/src/ssd/ssd-titlebar.c b/src/ssd/ssd-titlebar.c index 32d6131a..26800b89 100644 --- a/src/ssd/ssd-titlebar.c +++ b/src/ssd/ssd-titlebar.c @@ -210,6 +210,8 @@ ssd_titlebar_update(struct ssd *ssd) return; } + int title_bar_width = MAX(0, width - SSD_BUTTON_WIDTH * SSD_BUTTON_COUNT); + struct ssd_part *part; struct ssd_sub_tree *subtree; FOR_EACH_STATE(ssd, subtree) { @@ -218,25 +220,25 @@ ssd_titlebar_update(struct ssd *ssd) case LAB_SSD_PART_TITLEBAR: wlr_scene_rect_set_size( wlr_scene_rect_from_node(part->node), - width - SSD_BUTTON_WIDTH * SSD_BUTTON_COUNT, + title_bar_width, theme->title_height); continue; case LAB_SSD_BUTTON_ICONIFY: if (is_direct_child(part->node, subtree)) { wlr_scene_node_set_position(part->node, - width - SSD_BUTTON_WIDTH * 3, 0); + title_bar_width + 1 * SSD_BUTTON_WIDTH, 0); } continue; case LAB_SSD_BUTTON_MAXIMIZE: if (is_direct_child(part->node, subtree)) { wlr_scene_node_set_position(part->node, - width - SSD_BUTTON_WIDTH * 2, 0); + title_bar_width + 2 * SSD_BUTTON_WIDTH, 0); } continue; case LAB_SSD_PART_CORNER_TOP_RIGHT: if (is_direct_child(part->node, subtree)) { wlr_scene_node_set_position(part->node, - width - SSD_BUTTON_WIDTH * 1, 0); + title_bar_width + 3 * SSD_BUTTON_WIDTH, 0); } continue; default: diff --git a/src/ssd/ssd.c b/src/ssd/ssd.c index 86ac1272..e2da63b2 100644 --- a/src/ssd/ssd.c +++ b/src/ssd/ssd.c @@ -138,6 +138,11 @@ ssd_get_part_type(const struct ssd *ssd, struct wlr_scene_node *node) } } } + + if (ssd->view_background && node == &ssd->view_background->node) { + return LAB_SSD_CLIENT; + } + return LAB_SSD_NONE; } @@ -230,16 +235,6 @@ ssd_update_geometry(struct ssd *ssd) int eff_width = current.width; int eff_height = view_effective_height(ssd->view, /* use_pending */ false); - if (eff_width > 0 && eff_width < LAB_MIN_VIEW_WIDTH) { - /* - * Prevent negative values in calculations like - * `width - SSD_BUTTON_WIDTH * SSD_BUTTON_COUNT` - */ - wlr_log(WLR_ERROR, - "view width is smaller than its minimal value"); - return; - } - if (eff_width == cached.width && eff_height == cached.height) { if (current.x != cached.x || current.y != cached.y) { /* Dynamically resize extents based on position and usable_area */ @@ -267,6 +262,25 @@ ssd_update_geometry(struct ssd *ssd) } return; } + + if (current.width < LAB_MIN_VIEW_WIDTH) { + /* + * This draws a border-colored background behind the + * view for poorly behaving clients that don't follow + * our requested minimal size. + */ + if (!ssd->view_background) { + ssd->view_background = wlr_scene_rect_create(ssd->tree, 0, 0, + ssd->view == ssd->view->server->active_view + ? rc.theme->window_active_border_color + : rc.theme->window_inactive_border_color); + } + wlr_scene_rect_set_size(ssd->view_background, LAB_MIN_VIEW_WIDTH, current.height); + wlr_scene_node_set_enabled(&ssd->view_background->node, true); + } else if (ssd->view_background) { + wlr_scene_node_set_enabled(&ssd->view_background->node, false); + } + ssd_extents_update(ssd); ssd_titlebar_update(ssd); ssd_border_update(ssd); @@ -385,6 +399,11 @@ ssd_set_active(struct ssd *ssd, bool active) wlr_scene_node_set_enabled( &ssd->shadow.inactive.tree->node, !active); } + if (ssd->view_background) { + wlr_scene_rect_set_color(ssd->view_background, active + ? rc.theme->window_active_border_color + : rc.theme->window_inactive_border_color); + } } void @@ -465,5 +484,17 @@ ssd_debug_get_node_name(const struct ssd *ssd, struct wlr_scene_node *node) if (node == &ssd->extents.tree->node) { return "extents"; } + + /* These are only created on demand */ + if (ssd->shadow.active.tree && node == &ssd->shadow.active.tree->node) { + return "shadow.active"; + } + if (ssd->shadow.inactive.tree && node == &ssd->shadow.inactive.tree->node) { + return "shadow.inactive"; + } + if (ssd->view_background && node == &ssd->view_background->node) { + return "view_background"; + } + return NULL; }