diff --git a/include/con.h b/include/con.h index 8faf43fc..8ffa7ce2 100644 --- a/include/con.h +++ b/include/con.h @@ -195,4 +195,11 @@ int con_border_style(Con *con); */ void con_set_layout(Con *con, int layout); +/** + * Determines the minimum size of the given con by looking at its children (for + * split/stacked/tabbed cons). Will be called when resizing floating cons + * + */ +Rect con_minimum_size(Con *con); + #endif diff --git a/src/con.c b/src/con.c index 01381206..91f11d24 100644 --- a/src/con.c +++ b/src/con.c @@ -820,3 +820,61 @@ static void con_on_remove_child(Con *con) { return; } } + +/* + * Determines the minimum size of the given con by looking at its children (for + * split/stacked/tabbed cons). Will be called when resizing floating cons + * + */ +Rect con_minimum_size(Con *con) { + DLOG("Determining minimum size for con %p\n", con); + + if (con_is_leaf(con)) { + DLOG("leaf node, returning 75x50\n"); + return (Rect){ 0, 0, 75, 50 }; + } + + if (con->type == CT_FLOATING_CON) { + DLOG("floating con\n"); + Con *child = TAILQ_FIRST(&(con->nodes_head)); + return con_minimum_size(child); + } + + if (con->layout == L_STACKED || con->layout == L_TABBED) { + uint32_t max_width = 0, max_height = 0, deco_height = 0; + Con *child; + TAILQ_FOREACH(child, &(con->nodes_head), nodes) { + Rect min = con_minimum_size(child); + deco_height += child->deco_rect.height; + max_width = max(max_width, min.width); + max_height = max(max_height, min.height); + } + DLOG("stacked/tabbed now, returning %d x %d + deco_rect = %d\n", + max_width, max_height, deco_height); + return (Rect){ 0, 0, max_width, max_height + deco_height }; + } + + /* For horizontal/vertical split containers we sum up the width (h-split) + * or height (v-split) and use the maximum of the height (h-split) or width + * (v-split) as minimum size. */ + if (con->orientation == HORIZ || con->orientation == VERT) { + uint32_t width = 0, height = 0; + Con *child; + TAILQ_FOREACH(child, &(con->nodes_head), nodes) { + Rect min = con_minimum_size(child); + if (con->orientation == HORIZ) { + width += min.width; + height = max(height, min.height); + } else { + height += min.height; + width = max(width, min.width); + } + } + DLOG("split container, returning width = %d x height = %d\n", width, height); + return (Rect){ 0, 0, width, height }; + } + + ELOG("Unhandled case, type = %d, layout = %d, orientation = %d\n", + con->type, con->layout, con->orientation); + assert(false); +} diff --git a/src/floating.c b/src/floating.c index 2218da29..6aea7a91 100644 --- a/src/floating.c +++ b/src/floating.c @@ -284,12 +284,10 @@ DRAGGING_CB(resize_window_callback) { dest_height = old_rect->height - (new_y - event->root_y); else dest_height = old_rect->height + (new_y - event->root_y); - /* TODO: minimum window size */ -#if 0 /* Obey minimum window size */ - dest_width = max(dest_width, client_min_width(client)); - dest_height = max(dest_height, client_min_height(client)); -#endif + Rect minimum = con_minimum_size(con); + dest_width = max(dest_width, minimum.width); + dest_height = max(dest_height, minimum.height); /* User wants to keep proportions, so we may have to adjust our values */ if (params->proportional) {