Implement tabbed layout

This commit is contained in:
Ryan Dwyer 2018-05-19 22:54:50 +10:00
parent ec1c4c6c36
commit c08f9bf257
8 changed files with 438 additions and 87 deletions

View file

@ -599,12 +599,198 @@ static void render_container_simple(struct sway_output *output,
}
}
static void render_tab(struct sway_output *output, pixman_region32_t *damage,
struct sway_container *parent, int child_index,
struct border_colors *colors, struct wlr_texture *title_texture) {
float output_scale = output->wlr_output->scale;
float color[4];
struct wlr_box box;
bool is_first = (child_index == 0);
bool is_last = (child_index == parent->children->length - 1);
int tab_width = parent->width / parent->children->length;
int x = parent->x + tab_width * child_index;
// Make last tab use the remaining width of the parent
if (is_last) {
tab_width = parent->width - tab_width * child_index;
}
// Single pixel bar above title
memcpy(&color, colors->border, sizeof(float) * 4);
box.x = x;
box.y = parent->y;
box.width = tab_width;
box.height = 1;
scale_box(&box, output_scale);
render_rect(output->wlr_output, damage, &box, color);
// Single pixel bar below title
memcpy(&color, colors->border, sizeof(float) * 4);
box.x = x + config->border_thickness * is_first;
box.y = parent->y + config->border_thickness * 2 + config->font_height - 1;
box.width = tab_width - config->border_thickness * is_first
- config->border_thickness * is_last;
box.height = 1;
scale_box(&box, output_scale);
render_rect(output->wlr_output, damage, &box, color);
// Title text
size_t title_width = 0;
if (title_texture) {
struct wlr_box texture_box;
wlr_texture_get_size(title_texture,
&texture_box.width, &texture_box.height);
texture_box.x = (x + config->border_thickness) * output_scale;
texture_box.y = (parent->y + config->border_thickness) * output_scale;
float matrix[9];
wlr_matrix_project_box(matrix, &texture_box,
WL_OUTPUT_TRANSFORM_NORMAL,
0.0, output->wlr_output->transform_matrix);
int available = (tab_width - config->border_thickness * 2)
* output_scale;
if (texture_box.width > available) {
texture_box.width = available;
}
render_texture(output->wlr_output, damage, title_texture,
&texture_box, matrix, 1.0);
title_width = texture_box.width;
}
// Title background - above the text
memcpy(&color, colors->background, sizeof(float) * 4);
box.x = x + config->border_thickness;
box.y = parent->y + 1;
box.width = tab_width - config->border_thickness * 2;
box.height = config->border_thickness - 1;
scale_box(&box, output_scale);
render_rect(output->wlr_output, damage, &box, color);
// Title background - below the text
box.y = (parent->y + config->border_thickness + config->font_height)
* output_scale;
render_rect(output->wlr_output, damage, &box, color);
// Title background - left border
box.x = x;
box.y = parent->y + 1;
box.width = config->border_thickness;
box.height = config->border_thickness * 2
+ config->font_height - 1 - !is_first;
scale_box(&box, output_scale);
render_rect(output->wlr_output, damage, &box, color);
// Title background - right border
box.x = x + tab_width - config->border_thickness;
box.y = parent->y + 1;
box.width = config->border_thickness;
box.height = config->border_thickness * 2
+ config->font_height - 1 - !is_last;
scale_box(&box, output_scale);
render_rect(output->wlr_output, damage, &box, color);
// Title background - right of text
box.x = (x + config->border_thickness) * output_scale + title_width;
box.y = (parent->y + config->border_thickness) * output_scale;
box.width = (tab_width - config->border_thickness * 2) * output_scale
- title_width;
box.height = config->font_height * output_scale;
render_rect(output->wlr_output, damage, &box, color);
}
static void render_tab_content(struct sway_output *output,
pixman_region32_t *damage, struct sway_container *con,
struct border_colors *colors) {
struct sway_view *view = con->sway_view;
render_view(view, output, damage);
struct wlr_box box;
float output_scale = output->wlr_output->scale;
float color[4];
if (view->border_left) {
memcpy(&color, colors->child_border, sizeof(float) * 4);
color[3] *= con->alpha;
box.x = con->x;
box.y = con->y + config->border_thickness * 2 + config->font_height;
box.width = view->border_thickness;
box.height = view->height;
scale_box(&box, output_scale);
render_rect(output->wlr_output, damage, &box, color);
}
if (view->border_right) {
memcpy(&color, colors->child_border, sizeof(float) * 4);
color[3] *= con->alpha;
box.x = view->x + view->width;
box.y = con->y + config->border_thickness * 2 + config->font_height;
box.width = view->border_thickness;
box.height = view->height;
scale_box(&box, output_scale);
render_rect(output->wlr_output, damage, &box, color);
}
if (view->border_bottom) {
memcpy(&color, colors->child_border, sizeof(float) * 4);
color[3] *= con->alpha;
box.x = con->x;
box.y = view->y + view->height;
box.width = con->width;
box.height = view->border_thickness;
scale_box(&box, output_scale);
render_rect(output->wlr_output, damage, &box, color);
}
}
/**
* Render a container's children using the L_TABBED layout.
*/
static void render_container_tabbed(struct sway_output *output,
pixman_region32_t *damage, struct sway_container *con) {
// TODO
pixman_region32_t *damage, struct sway_container *con,
bool parent_focused) {
if (!con->children->length) {
return;
}
struct sway_seat *seat = input_manager_current_seat(input_manager);
struct sway_container *focus = seat_get_focus(seat);
struct sway_container *current = seat_get_focus_inactive(seat, con);
while (current->parent != con) {
current = current->parent;
}
struct border_colors *current_colors = NULL;
// Render tabs
for (int i = 0; i < con->children->length; ++i) {
struct sway_container *child = con->children->items[i];
struct border_colors *colors;
struct wlr_texture *title_texture;
if (focus == child || parent_focused) {
colors = &config->border_colors.focused;
title_texture = child->title_focused;
} else if (child == current) {
colors = &config->border_colors.focused_inactive;
title_texture = child->title_focused_inactive;
} else {
colors = &config->border_colors.unfocused;
title_texture = child->title_unfocused;
}
render_tab(output, damage, con, i, colors, title_texture);
if (child == current) {
current_colors = colors;
}
}
// Render surface and left/right/bottom borders
if (current->type == C_VIEW) {
render_tab_content(output, damage, current, current_colors);
} else {
render_container(output, damage, current,
parent_focused || current == focus);
}
}
/**
@ -628,7 +814,7 @@ static void render_container(struct sway_output *output,
render_container_stacked(output, damage, con);
break;
case L_TABBED:
render_container_tabbed(output, damage, con);
render_container_tabbed(output, damage, con, parent_focused);
break;
case L_FLOATING:
// TODO