Prepare arrange code for type safe arguments

This commit changes the arrange code in a way that will support type
safe arguments.

The arrange_output et al functions are now public, however I opted not
to use them directly yet. I've kept the generic arrange_windows there
for convenience until type safety is fully implemented. This means this
patch has much less risk of breaking things as it would otherwise.

To be type safe, arrange_children_of cannot exist in its previous form
because the thing passed to it could be either a workspace or a
container. So it's now renamed to arrange_children and accepts a list_t,
as well as the parent layout and parent's box.

There was some code which checked the grandparent's layout to see if it
was tabbed or stacked and adjusted the Y offset of the grandchild
accordingly. Accessing the grandparent layout isn't easy when using type
safe arguments, and it seemed odd to even need to do this. I determined
that this was needed because a child of a tabbed container would have a
swayc Y matching the top of the tab bar. I've changed this so a child of
a tabbed container will have a swayc Y matching the bottom of the tab
bar, which means we don't need to access the grandparent layout.  Some
tweaks to the rendering and autoconfigure code have been made to
implement this, and the container_at code appears to work without
needing any changes.

arrange_children_of (now arrange_children) would check if the parent had
gaps and would copy them to the child, effectively making the
workspace's gaps recurse into all children. We can't do this any more
without passing has_gaps, gaps_inner and gaps_outer as arguments to
arrange_children, so I've changed the add_gaps function to retrieve it
from the workspace directly.

apply_tabbed_or_stacked_layout has been split into two functions, as it
had different logic depending on the layout.

Lastly, arrange.h had an unnecessary include of transaction.h. I've
removed it, which means I've had to add it to several other files.
master
Ryan Dwyer 6 years ago
parent 98ef29c228
commit f5b9815128

@ -1,12 +1,16 @@
#ifndef _SWAY_ARRANGE_H #ifndef _SWAY_ARRANGE_H
#define _SWAY_ARRANGE_H #define _SWAY_ARRANGE_H
#include "sway/desktop/transaction.h"
struct sway_container; struct sway_container;
/** void arrange_container(struct sway_container *container);
* Arrange layout for all the children of the given container.
*/ void arrange_workspace(struct sway_container *workspace);
void arrange_output(struct sway_container *output);
void arrange_root(void);
void arrange_windows(struct sway_container *container); void arrange_windows(struct sway_container *container);
#endif #endif

@ -16,6 +16,7 @@
#include "log.h" #include "log.h"
#include "config.h" #include "config.h"
#include "sway/config.h" #include "sway/config.h"
#include "sway/desktop/transaction.h"
#include "sway/input/input-manager.h" #include "sway/input/input-manager.h"
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include "sway/layers.h" #include "sway/layers.h"

@ -660,7 +660,7 @@ static void render_container_tabbed(struct sway_output *output,
pstate->swayc_width - width_gap_adjustment - tab_width * i; pstate->swayc_width - width_gap_adjustment - tab_width * i;
} }
render_titlebar(output, damage, child, x, cstate->swayc_y, tab_width, render_titlebar(output, damage, child, x, pstate->swayc_y, tab_width,
colors, title_texture, marks_texture); colors, title_texture, marks_texture);
if (child == current) { if (child == current) {
@ -721,9 +721,9 @@ static void render_container_stacked(struct sway_output *output,
marks_texture = view ? view->marks_unfocused : NULL; marks_texture = view ? view->marks_unfocused : NULL;
} }
int y = cstate->swayc_y + titlebar_height * i; int y = pstate->swayc_y + titlebar_height * i;
render_titlebar(output, damage, child, cstate->swayc_x, y, render_titlebar(output, damage, child, pstate->swayc_x, y,
cstate->swayc_width, colors, title_texture, marks_texture); pstate->swayc_width, colors, title_texture, marks_texture);
if (child == current) { if (child == current) {
current_colors = colors; current_colors = colors;

@ -8,6 +8,7 @@
#include "log.h" #include "log.h"
#include "sway/decoration.h" #include "sway/decoration.h"
#include "sway/desktop.h" #include "sway/desktop.h"
#include "sway/desktop/transaction.h"
#include "sway/input/input-manager.h" #include "sway/input/input-manager.h"
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include "sway/server.h" #include "sway/server.h"

@ -7,6 +7,7 @@
#include "log.h" #include "log.h"
#include "sway/decoration.h" #include "sway/decoration.h"
#include "sway/desktop.h" #include "sway/desktop.h"
#include "sway/desktop/transaction.h"
#include "sway/input/input-manager.h" #include "sway/input/input-manager.h"
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include "sway/server.h" #include "sway/server.h"

@ -13,27 +13,18 @@
#include "list.h" #include "list.h"
#include "log.h" #include "log.h"
static void apply_horiz_layout(struct sway_container *parent) { static void apply_horiz_layout(list_t *children, struct wlr_box *parent) {
size_t num_children = parent->children->length; if (!children->length) {
if (!num_children) {
return; return;
} }
size_t parent_offset = 0;
if (parent->parent->layout == L_TABBED) {
parent_offset = container_titlebar_height();
} else if (parent->parent->layout == L_STACKED) {
parent_offset = container_titlebar_height() *
parent->parent->children->length;
}
size_t parent_height = parent->height - parent_offset;
// Calculate total width of children // Calculate total width of children
double total_width = 0; double total_width = 0;
for (size_t i = 0; i < num_children; ++i) { for (int i = 0; i < children->length; ++i) {
struct sway_container *child = parent->children->items[i]; struct sway_container *child = children->items[i];
if (child->width <= 0) { if (child->width <= 0) {
if (num_children > 1) { if (children->length > 1) {
child->width = parent->width / (num_children - 1); child->width = parent->width / (children->length - 1);
} else { } else {
child->width = parent->width; child->width = parent->width;
} }
@ -46,63 +37,48 @@ static void apply_horiz_layout(struct sway_container *parent) {
// Resize windows // Resize windows
wlr_log(WLR_DEBUG, "Arranging %p horizontally", parent); wlr_log(WLR_DEBUG, "Arranging %p horizontally", parent);
double child_x = parent->x; double child_x = parent->x;
for (size_t i = 0; i < num_children; ++i) { for (int i = 0; i < children->length; ++i) {
struct sway_container *child = parent->children->items[i]; struct sway_container *child = children->items[i];
wlr_log(WLR_DEBUG,
"Calculating arrangement for %p:%d (will scale %f by %f)",
child, child->type, child->width, scale);
child->x = child_x; child->x = child_x;
child->y = parent->y + parent_offset; child->y = parent->y;
child->width = floor(child->width * scale); child->width = floor(child->width * scale);
child->height = parent_height; child->height = parent->height;
child_x += child->width; child_x += child->width;
// Make last child use remaining width of parent // Make last child use remaining width of parent
if (i == num_children - 1) { if (i == children->length - 1) {
child->width = parent->x + parent->width - child->x; child->width = parent->x + parent->width - child->x;
} }
container_add_gaps(child); container_add_gaps(child);
} }
} }
static void apply_vert_layout(struct sway_container *parent) { static void apply_vert_layout(list_t *children, struct wlr_box *parent) {
size_t num_children = parent->children->length; if (!children->length) {
if (!num_children) {
return; return;
} }
size_t parent_offset = 0;
if (parent->parent->layout == L_TABBED) {
parent_offset = container_titlebar_height();
} else if (parent->parent->layout == L_STACKED) {
parent_offset =
container_titlebar_height() * parent->parent->children->length;
}
size_t parent_height = parent->height + parent_offset;
// Calculate total height of children // Calculate total height of children
double total_height = 0; double total_height = 0;
for (size_t i = 0; i < num_children; ++i) { for (int i = 0; i < children->length; ++i) {
struct sway_container *child = parent->children->items[i]; struct sway_container *child = children->items[i];
if (child->height <= 0) { if (child->height <= 0) {
if (num_children > 1) { if (children->length > 1) {
child->height = parent_height / (num_children - 1); child->height = parent->height / (children->length - 1);
} else { } else {
child->height = parent_height; child->height = parent->height;
} }
} }
container_remove_gaps(child); container_remove_gaps(child);
total_height += child->height; total_height += child->height;
} }
double scale = parent_height / total_height; double scale = parent->height / total_height;
// Resize // Resize
wlr_log(WLR_DEBUG, "Arranging %p vertically", parent); wlr_log(WLR_DEBUG, "Arranging %p vertically", parent);
double child_y = parent->y + parent_offset; double child_y = parent->y;
for (size_t i = 0; i < num_children; ++i) { for (int i = 0; i < children->length; ++i) {
struct sway_container *child = parent->children->items[i]; struct sway_container *child = children->items[i];
wlr_log(WLR_DEBUG,
"Calculating arrangement for %p:%d (will scale %f by %f)",
child, child->type, child->height, scale);
child->x = parent->x; child->x = parent->x;
child->y = child_y; child->y = child_y;
child->width = parent->width; child->width = parent->width;
@ -110,28 +86,21 @@ static void apply_vert_layout(struct sway_container *parent) {
child_y += child->height; child_y += child->height;
// Make last child use remaining height of parent // Make last child use remaining height of parent
if (i == num_children - 1) { if (i == children->length - 1) {
child->height = child->height = parent->y + parent->height - child->y;
parent->y + parent_offset + parent_height - child->y;
} }
container_add_gaps(child); container_add_gaps(child);
} }
} }
static void apply_tabbed_or_stacked_layout(struct sway_container *parent) { static void apply_tabbed_layout(list_t *children, struct wlr_box *parent) {
if (!parent->children->length) { if (!children->length) {
return; return;
} }
size_t parent_offset = 0; size_t parent_offset = container_titlebar_height();
if (parent->parent->layout == L_TABBED) {
parent_offset = container_titlebar_height();
} else if (parent->parent->layout == L_STACKED) {
parent_offset =
container_titlebar_height() * parent->parent->children->length;
}
size_t parent_height = parent->height - parent_offset; size_t parent_height = parent->height - parent_offset;
for (int i = 0; i < parent->children->length; ++i) { for (int i = 0; i < children->length; ++i) {
struct sway_container *child = parent->children->items[i]; struct sway_container *child = children->items[i];
container_remove_gaps(child); container_remove_gaps(child);
child->x = parent->x; child->x = parent->x;
child->y = parent->y + parent_offset; child->y = parent->y + parent_offset;
@ -141,65 +110,83 @@ static void apply_tabbed_or_stacked_layout(struct sway_container *parent) {
} }
} }
static void arrange_children_of(struct sway_container *parent); static void apply_stacked_layout(list_t *children, struct wlr_box *parent) {
if (!children->length) {
return;
}
size_t parent_offset = container_titlebar_height() * children->length;
size_t parent_height = parent->height - parent_offset;
for (int i = 0; i < children->length; ++i) {
struct sway_container *child = children->items[i];
container_remove_gaps(child);
child->x = parent->x;
child->y = parent->y + parent_offset;
child->width = parent->width;
child->height = parent_height;
container_add_gaps(child);
}
}
static void arrange_floating(list_t *floating) { static void arrange_floating(list_t *floating) {
for (int i = 0; i < floating->length; ++i) { for (int i = 0; i < floating->length; ++i) {
struct sway_container *floater = floating->items[i]; struct sway_container *floater = floating->items[i];
if (floater->type == C_VIEW) { arrange_container(floater);
view_autoconfigure(floater->sway_view);
} else {
arrange_children_of(floater);
}
container_set_dirty(floater);
} }
} }
static void arrange_children_of(struct sway_container *parent) { static void arrange_children(list_t *children,
if (config->reloading) { enum sway_container_layout layout, struct wlr_box *parent) {
return;
}
wlr_log(WLR_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", parent,
parent->name, parent->width, parent->height, parent->x, parent->y);
// Calculate x, y, width and height of children // Calculate x, y, width and height of children
switch (parent->layout) { switch (layout) {
case L_HORIZ: case L_HORIZ:
apply_horiz_layout(parent); apply_horiz_layout(children, parent);
break; break;
case L_VERT: case L_VERT:
apply_vert_layout(parent); apply_vert_layout(children, parent);
break; break;
case L_TABBED: case L_TABBED:
apply_tabbed_layout(children, parent);
break;
case L_STACKED: case L_STACKED:
apply_tabbed_or_stacked_layout(parent); apply_stacked_layout(children, parent);
break; break;
case L_NONE: case L_NONE:
apply_horiz_layout(parent); apply_horiz_layout(children, parent);
break; break;
} }
// Recurse into child containers // Recurse into child containers
for (int i = 0; i < parent->children->length; ++i) { for (int i = 0; i < children->length; ++i) {
struct sway_container *child = parent->children->items[i]; struct sway_container *child = children->items[i];
if (parent->has_gaps && !child->has_gaps) { arrange_container(child);
child->has_gaps = true; }
child->gaps_inner = parent->gaps_inner; }
child->gaps_outer = parent->gaps_outer;
} void arrange_container(struct sway_container *container) {
if (child->type == C_VIEW) { if (config->reloading) {
view_autoconfigure(child->sway_view); return;
} else { }
arrange_children_of(child); if (container->type == C_VIEW) {
} view_autoconfigure(container->sway_view);
container_set_dirty(child); container_set_dirty(container);
return;
} }
if (!sway_assert(container->type == C_CONTAINER, "Expected a container")) {
return;
}
struct wlr_box box;
container_get_box(container, &box);
arrange_children(container->children, container->layout, &box);
container_set_dirty(container);
} }
static void arrange_workspace(struct sway_container *workspace) { void arrange_workspace(struct sway_container *workspace) {
if (config->reloading) { if (config->reloading) {
return; return;
} }
if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
return;
}
struct sway_container *output = workspace->parent; struct sway_container *output = workspace->parent;
struct wlr_box *area = &output->sway_output->usable_area; struct wlr_box *area = &output->sway_output->usable_area;
wlr_log(WLR_DEBUG, "Usable area for ws: %dx%d@%d,%d", wlr_log(WLR_DEBUG, "Usable area for ws: %dx%d@%d,%d",
@ -241,22 +228,22 @@ static void arrange_workspace(struct sway_container *workspace) {
fs->y = workspace->parent->y; fs->y = workspace->parent->y;
fs->width = workspace->parent->width; fs->width = workspace->parent->width;
fs->height = workspace->parent->height; fs->height = workspace->parent->height;
if (fs->type == C_VIEW) { arrange_container(fs);
view_autoconfigure(fs->sway_view);
} else {
arrange_children_of(fs);
}
container_set_dirty(fs);
} else { } else {
struct wlr_box box;
container_get_box(workspace, &box);
arrange_children(workspace->children, workspace->layout, &box);
arrange_floating(workspace->sway_workspace->floating); arrange_floating(workspace->sway_workspace->floating);
arrange_children_of(workspace);
} }
} }
static void arrange_output(struct sway_container *output) { void arrange_output(struct sway_container *output) {
if (config->reloading) { if (config->reloading) {
return; return;
} }
if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
return;
}
const struct wlr_box *output_box = wlr_output_layout_get_box( const struct wlr_box *output_box = wlr_output_layout_get_box(
root_container.sway_root->output_layout, root_container.sway_root->output_layout,
output->sway_output->wlr_output); output->sway_output->wlr_output);
@ -273,7 +260,7 @@ static void arrange_output(struct sway_container *output) {
} }
} }
static void arrange_root() { void arrange_root(void) {
if (config->reloading) { if (config->reloading) {
return; return;
} }
@ -304,12 +291,8 @@ void arrange_windows(struct sway_container *container) {
arrange_workspace(container); arrange_workspace(container);
break; break;
case C_CONTAINER: case C_CONTAINER:
arrange_children_of(container);
container_set_dirty(container);
break;
case C_VIEW: case C_VIEW:
view_autoconfigure(container->sway_view); arrange_container(container);
container_set_dirty(container);
break; break;
case C_TYPES: case C_TYPES:
break; break;

@ -1163,7 +1163,9 @@ void container_add_gaps(struct sway_container *c) {
return; return;
} }
c->current_gaps = c->has_gaps ? c->gaps_inner : config->gaps_inner; struct sway_container *ws = container_parent(c, C_WORKSPACE);
c->current_gaps = ws->has_gaps ? ws->gaps_inner : config->gaps_inner;
c->x += c->current_gaps; c->x += c->current_gaps;
c->y += c->current_gaps; c->y += c->current_gaps;
c->width -= 2 * c->current_gaps; c->width -= 2 * c->current_gaps;

@ -3,6 +3,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include "sway/desktop/transaction.h"
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include "sway/output.h" #include "sway/output.h"
#include "sway/tree/arrange.h" #include "sway/tree/arrange.h"

@ -13,6 +13,7 @@
#include "log.h" #include "log.h"
#include "sway/criteria.h" #include "sway/criteria.h"
#include "sway/commands.h" #include "sway/commands.h"
#include "sway/desktop/transaction.h"
#include "sway/ipc-server.h" #include "sway/ipc-server.h"
#include "sway/output.h" #include "sway/output.h"
#include "sway/input/seat.h" #include "sway/input/seat.h"
@ -224,15 +225,13 @@ void view_autoconfigure(struct sway_view *view) {
x = y = width = height = 0; x = y = width = height = 0;
double y_offset = 0; double y_offset = 0;
// In a tabbed or stacked container, the swayc's y is the top of the title // In a tabbed or stacked container, the swayc's y is the bottom of the
// area. We have to offset the surface y by the height of the title bar, and // title area. We have to disable any top border because the title bar is
// disable any top border because we'll always have the title bar. // rendered by the parent.
if (con->parent->layout == L_TABBED) { if (con->parent->layout == L_TABBED || con->parent->layout == L_STACKED) {
y_offset = container_titlebar_height();
view->border_top = false;
} else if (con->parent->layout == L_STACKED) {
y_offset = container_titlebar_height() * con->parent->children->length;
view->border_top = false; view->border_top = false;
} else {
y_offset = container_titlebar_height();
} }
enum sway_container_border border = view->border; enum sway_container_border border = view->border;
@ -243,17 +242,17 @@ void view_autoconfigure(struct sway_view *view) {
switch (border) { switch (border) {
case B_NONE: case B_NONE:
x = con->x; x = con->x;
y = con->y + y_offset; y = con->y;
width = con->width; width = con->width;
height = con->height - y_offset; height = con->height;
break; break;
case B_PIXEL: case B_PIXEL:
x = con->x + view->border_thickness * view->border_left; x = con->x + view->border_thickness * view->border_left;
y = con->y + view->border_thickness * view->border_top + y_offset; y = con->y + view->border_thickness * view->border_top;
width = con->width width = con->width
- view->border_thickness * view->border_left - view->border_thickness * view->border_left
- view->border_thickness * view->border_right; - view->border_thickness * view->border_right;
height = con->height - y_offset height = con->height
- view->border_thickness * view->border_top - view->border_thickness * view->border_top
- view->border_thickness * view->border_bottom; - view->border_thickness * view->border_bottom;
break; break;
@ -263,15 +262,9 @@ void view_autoconfigure(struct sway_view *view) {
width = con->width width = con->width
- view->border_thickness * view->border_left - view->border_thickness * view->border_left
- view->border_thickness * view->border_right; - view->border_thickness * view->border_right;
if (y_offset) { y = con->y + y_offset;
y = con->y + y_offset; height = con->height - y_offset
height = con->height - y_offset - view->border_thickness * view->border_bottom;
- view->border_thickness * view->border_bottom;
} else {
y = con->y + container_titlebar_height();
height = con->height - container_titlebar_height()
- view->border_thickness * view->border_bottom;
}
break; break;
} }

Loading…
Cancel
Save