e83e5487be
This allows the title's texture to always be the full width of the text, and clipped at render time according to the desired width (eg. tabs...). As an added bonus, the texture no longer needs to be updated when containers are arranged.
210 lines
6.1 KiB
C
210 lines
6.1 KiB
C
#define _POSIX_C_SOURCE 200809L
|
|
#include <ctype.h>
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <wlr/types/wlr_output.h>
|
|
#include <wlr/types/wlr_output_layout.h>
|
|
#include "sway/debug.h"
|
|
#include "sway/tree/arrange.h"
|
|
#include "sway/tree/container.h"
|
|
#include "sway/tree/layout.h"
|
|
#include "sway/output.h"
|
|
#include "sway/tree/workspace.h"
|
|
#include "sway/tree/view.h"
|
|
#include "list.h"
|
|
#include "log.h"
|
|
|
|
struct sway_container root_container;
|
|
|
|
void arrange_root() {
|
|
if (config->reloading) {
|
|
return;
|
|
}
|
|
struct wlr_output_layout *output_layout =
|
|
root_container.sway_root->output_layout;
|
|
const struct wlr_box *layout_box =
|
|
wlr_output_layout_get_box(output_layout, NULL);
|
|
root_container.x = layout_box->x;
|
|
root_container.y = layout_box->y;
|
|
root_container.width = layout_box->width;
|
|
root_container.height = layout_box->height;
|
|
for (int i = 0; i < root_container.children->length; ++i) {
|
|
struct sway_container *output = root_container.children->items[i];
|
|
arrange_output(output);
|
|
}
|
|
}
|
|
|
|
void arrange_output(struct sway_container *output) {
|
|
if (config->reloading) {
|
|
return;
|
|
}
|
|
if (!sway_assert(output->type == C_OUTPUT,
|
|
"called arrange_output() on non-output container")) {
|
|
return;
|
|
}
|
|
const struct wlr_box *output_box = wlr_output_layout_get_box(
|
|
root_container.sway_root->output_layout,
|
|
output->sway_output->wlr_output);
|
|
output->x = output_box->x;
|
|
output->y = output_box->y;
|
|
output->width = output_box->width;
|
|
output->height = output_box->height;
|
|
wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f",
|
|
output->name, output->x, output->y);
|
|
for (int i = 0; i < output->children->length; ++i) {
|
|
struct sway_container *workspace = output->children->items[i];
|
|
arrange_workspace(workspace);
|
|
}
|
|
container_damage_whole(output);
|
|
}
|
|
|
|
void arrange_workspace(struct sway_container *workspace) {
|
|
if (config->reloading) {
|
|
return;
|
|
}
|
|
if (!sway_assert(workspace->type == C_WORKSPACE,
|
|
"called arrange_workspace() on non-workspace container")) {
|
|
return;
|
|
}
|
|
struct sway_container *output = workspace->parent;
|
|
struct wlr_box *area = &output->sway_output->usable_area;
|
|
wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d",
|
|
area->width, area->height, area->x, area->y);
|
|
workspace->width = area->width;
|
|
workspace->height = area->height;
|
|
workspace->x = area->x;
|
|
workspace->y = area->y;
|
|
wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f",
|
|
workspace->name, workspace->x, workspace->y);
|
|
arrange_children_of(workspace);
|
|
container_damage_whole(workspace);
|
|
}
|
|
|
|
static void apply_horiz_layout(struct sway_container *parent) {
|
|
size_t num_children = parent->children->length;
|
|
if (!num_children) {
|
|
return;
|
|
}
|
|
// Calculate total width of children
|
|
double total_width = 0;
|
|
for (size_t i = 0; i < num_children; ++i) {
|
|
struct sway_container *child = parent->children->items[i];
|
|
if (child->width <= 0) {
|
|
if (num_children > 1) {
|
|
child->width = parent->width / (num_children - 1);
|
|
} else {
|
|
child->width = parent->width;
|
|
}
|
|
}
|
|
total_width += child->width;
|
|
}
|
|
double scale = parent->width / total_width;
|
|
|
|
// Resize windows
|
|
wlr_log(L_DEBUG, "Arranging %p horizontally", parent);
|
|
double child_x = parent->x;
|
|
struct sway_container *child;
|
|
for (size_t i = 0; i < num_children; ++i) {
|
|
child = parent->children->items[i];
|
|
wlr_log(L_DEBUG,
|
|
"Calculating arrangement for %p:%d (will scale %f by %f)",
|
|
child, child->type, child->width, scale);
|
|
child->x = child_x;
|
|
child->y = parent->y;
|
|
child->width = floor(child->width * scale);
|
|
child->height = parent->height;
|
|
child_x += child->width;
|
|
}
|
|
// Make last child use remaining width of parent
|
|
child->width = parent->x + parent->width - child->x;
|
|
}
|
|
|
|
static void apply_vert_layout(struct sway_container *parent) {
|
|
size_t num_children = parent->children->length;
|
|
if (!num_children) {
|
|
return;
|
|
}
|
|
// Calculate total height of children
|
|
double total_height = 0;
|
|
for (size_t i = 0; i < num_children; ++i) {
|
|
struct sway_container *child = parent->children->items[i];
|
|
if (child->height <= 0) {
|
|
if (num_children > 1) {
|
|
child->height = parent->height / (num_children - 1);
|
|
} else {
|
|
child->height = parent->height;
|
|
}
|
|
}
|
|
total_height += child->height;
|
|
}
|
|
double scale = parent->height / total_height;
|
|
|
|
// Resize
|
|
wlr_log(L_DEBUG, "Arranging %p vertically", parent);
|
|
double child_y = parent->y;
|
|
struct sway_container *child;
|
|
for (size_t i = 0; i < num_children; ++i) {
|
|
child = parent->children->items[i];
|
|
wlr_log(L_DEBUG,
|
|
"Calculating arrangement for %p:%d (will scale %f by %f)",
|
|
child, child->type, child->height, scale);
|
|
child->x = parent->x;
|
|
child->y = child_y;
|
|
child->width = parent->width;
|
|
child->height = floor(child->height * scale);
|
|
child_y += child->height;
|
|
}
|
|
// Make last child use remaining height of parent
|
|
child->height = parent->y + parent->height - child->y;
|
|
}
|
|
|
|
void arrange_children_of(struct sway_container *parent) {
|
|
if (config->reloading) {
|
|
return;
|
|
}
|
|
if (!sway_assert(parent->type == C_WORKSPACE || parent->type == C_CONTAINER,
|
|
"container is a %s", container_type_to_str(parent->type))) {
|
|
return;
|
|
}
|
|
|
|
struct sway_container *workspace = parent;
|
|
if (workspace->type != C_WORKSPACE) {
|
|
workspace = container_parent(workspace, C_WORKSPACE);
|
|
}
|
|
if (workspace->sway_workspace->fullscreen) {
|
|
// Just arrange the fullscreen view and jump out
|
|
view_autoconfigure(workspace->sway_workspace->fullscreen);
|
|
return;
|
|
}
|
|
|
|
wlr_log(L_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
|
|
switch (parent->layout) {
|
|
case L_HORIZ:
|
|
apply_horiz_layout(parent);
|
|
break;
|
|
case L_VERT:
|
|
apply_vert_layout(parent);
|
|
break;
|
|
default:
|
|
wlr_log(L_DEBUG, "TODO: arrange layout type %d", parent->layout);
|
|
apply_horiz_layout(parent);
|
|
break;
|
|
}
|
|
|
|
// Apply x, y, width and height to children and recurse if needed
|
|
for (int i = 0; i < parent->children->length; ++i) {
|
|
struct sway_container *child = parent->children->items[i];
|
|
if (child->type == C_VIEW) {
|
|
view_autoconfigure(child->sway_view);
|
|
} else {
|
|
arrange_children_of(child);
|
|
}
|
|
}
|
|
container_damage_whole(parent);
|
|
update_debug_tree();
|
|
}
|