diff --git a/include/view.h b/include/view.h index ea8ce5a7..99cb7bd7 100644 --- a/include/view.h +++ b/include/view.h @@ -395,6 +395,13 @@ bool view_compute_centered_position(struct view *view, bool view_adjust_floating_geometry(struct view *view, struct wlr_box *geometry); void view_store_natural_geometry(struct view *view); +/** + * view_effective_height - effective height of view, with respect to shaded state + * @view: view for which effective height is desired + * @use_pending: if false, report current height; otherwise, report pending height + */ +int view_effective_height(struct view *view, bool use_pending); + /** * view_center - center view within some region * @view: view to be centered diff --git a/src/placement.c b/src/placement.c index c2a724af..c64b7570 100644 --- a/src/placement.c +++ b/src/placement.c @@ -169,7 +169,7 @@ build_grid(struct overlap_bitmap *bmp, struct view *view) } x = v->pending.x + v->pending.width + margin.right; - y = v->pending.y + v->pending.height + margin.bottom; + y = v->pending.y + view_effective_height(v, true) + margin.bottom; /* Add a column if the right view edge is in the usable region */ if (x > usable.x && x < usable_right) { @@ -260,7 +260,8 @@ build_overlap(struct overlap_bitmap *bmp, struct view *view) int lx = v->pending.x - margin.left; int ly = v->pending.y - margin.top; int hx = v->pending.x + v->pending.width + margin.right; - int hy = v->pending.y + v->pending.height + margin.bottom; + int hy = v->pending.y + + view_effective_height(v, true) + margin.bottom; /* * Find the first and last row and column intervals spanned by diff --git a/src/snap.c b/src/snap.c index 7128f167..d8dc32dd 100644 --- a/src/snap.c +++ b/src/snap.c @@ -37,8 +37,9 @@ snap_get_view_edge(struct view *view) struct border edge = { .left = view->pending.x - margin.left, .top = view->pending.y - margin.top, - .right = view->pending.x + view->pending.width + margin.right, - .bottom = view->pending.y + view->pending.height + margin.bottom + .right = view->pending.x + view->pending.width + margin.right, + .bottom = view->pending.y + + view_effective_height(view, true) + margin.bottom }; return edge; } @@ -52,9 +53,11 @@ snap_get_max_distance(struct view *view) struct border distance = { .left = usable.x + margin.left + rc.gap - view->pending.x, .top = usable.y + margin.top + rc.gap - view->pending.y, - .right = usable.x + usable.width - view->pending.width + .right = usable.x + usable.width + - view->pending.width - margin.right - rc.gap - view->pending.x, - .bottom = usable.y + usable.height - view->pending.height + .bottom = usable.y + usable.height + - view_effective_height(view, true) - margin.bottom - rc.gap - view->pending.y }; return distance; @@ -115,7 +118,7 @@ _snap_next_edge(struct view *view, int start_pos, const struct snap_search def, vp += def.add_view_x * v->pending.x; vp += def.add_view_y * v->pending.y; vp += def.add_view_width * v->pending.width; - vp += def.add_view_height * v->pending.height; + vp += def.add_view_height * view_effective_height(v, true); vp += gap; if (def.search_dir * vp > 0 && def.search_dir * (vp - p) < 0) { @@ -131,12 +134,14 @@ _snap_move_resize_to_edge(struct view *view, enum view_edge direction, enum snap { struct border edge = snap_get_view_edge(view); struct border dmax; + if (mode == SNAP_MODE_SHRINK) { /* limit to half of current size */ + int eff_height = view_effective_height(view, true); int width_max_dx = max(view->pending.width - LAB_MIN_VIEW_WIDTH, 0); - int height_max_dy = max(view->pending.height - LAB_MIN_VIEW_HEIGHT, 0); + int height_max_dy = max(eff_height - LAB_MIN_VIEW_HEIGHT, 0); dmax.right = min(width_max_dx, view->pending.width / 2); - dmax.bottom = min(height_max_dy, view->pending.height / 2); + dmax.bottom = min(height_max_dy, eff_height / 2); dmax.left = -dmax.right; dmax.top = -dmax.bottom; } else { diff --git a/src/ssd/ssd_border.c b/src/ssd/ssd_border.c index 996cb70d..6c9db9b1 100644 --- a/src/ssd/ssd_border.c +++ b/src/ssd/ssd_border.c @@ -20,7 +20,7 @@ ssd_border_create(struct ssd *ssd) struct view *view = ssd->view; struct theme *theme = view->server->theme; int width = view->current.width; - int height = view->current.height; + int height = view_effective_height(view, false); int full_width = width + 2 * theme->border_width; float *color; @@ -83,7 +83,7 @@ ssd_border_update(struct ssd *ssd) struct theme *theme = view->server->theme; int width = view->current.width; - int height = view->shaded ? 0 : view->current.height; + int height = view_effective_height(view, false); int full_width = width + 2 * theme->border_width; struct ssd_part *part; diff --git a/src/view.c b/src/view.c index 6e6689cf..73575c2d 100644 --- a/src/view.c +++ b/src/view.c @@ -703,6 +703,18 @@ view_store_natural_geometry(struct view *view) } } +int +view_effective_height(struct view *view, bool use_pending) +{ + assert(view); + + if (view->shaded) { + return 0; + } + + return use_pending ? view->pending.height : view->current.height; +} + void view_center(struct view *view, const struct wlr_box *ref) { @@ -1561,7 +1573,7 @@ view_move_to_edge(struct view *view, enum view_edge direction, bool snap_to_wind destination_y = top; break; case VIEW_EDGE_DOWN: - destination_y = bottom - view->pending.height; + destination_y = bottom - view_effective_height(view, true); break; default: return; @@ -1578,9 +1590,9 @@ view_move_to_edge(struct view *view, enum view_edge direction, bool snap_to_wind destination_x = MAX(destination_x, left); /* If more than half the view is below usable region, align to bottom */ - midpoint = destination_y + view->pending.height / 2; + midpoint = destination_y + view_effective_height(view, true) / 2; if (destination_y >= top && midpoint > usable.y + usable.height) { - destination_y = bottom - view->pending.height; + destination_y = bottom - view_effective_height(view, true); } /* Never allow the window to start above the usable edge */ @@ -1599,11 +1611,16 @@ view_grow_to_edge(struct view *view, enum view_edge direction) if (view->fullscreen || view->maximized != VIEW_AXIS_NONE) { return; } + if (!output_is_usable(view->output)) { wlr_log(WLR_ERROR, "view has no output, not growing view"); return; } + if (view->shaded) { + view_toggle_shade(view); + } + struct wlr_box geo = view->pending; snap_grow_to_next_edge(view, direction, &geo); view_move_resize(view, geo); @@ -1613,10 +1630,17 @@ void view_shrink_to_edge(struct view *view, enum view_edge direction) { assert(view); + /* TODO: allow shrink to edge if maximized along the other axis */ if (view->fullscreen || view->maximized != VIEW_AXIS_NONE) { return; } + + /* Shrinking doesn't make a lot of sense in shaded mode */ + if (view->shaded) { + return; + } + if (!output_is_usable(view->output)) { wlr_log(WLR_ERROR, "view has no output, not shrinking view"); return;