mirror of
https://github.com/swaywm/sway.git
synced 2024-11-22 16:01:27 +00:00
Implement title alignment
This adds support for `i3 4.16`'s ability to set the title alignment. The command is `title_align left|center|right`. When the title is on the right, marks are moved to the left. Otherwise, they are on the right.
This commit is contained in:
parent
91bbb2a7dd
commit
e6562c8cd2
|
@ -172,6 +172,7 @@ sway_cmd cmd_swaybg_command;
|
||||||
sway_cmd cmd_swaynag_command;
|
sway_cmd cmd_swaynag_command;
|
||||||
sway_cmd cmd_swap;
|
sway_cmd cmd_swap;
|
||||||
sway_cmd cmd_tiling_drag;
|
sway_cmd cmd_tiling_drag;
|
||||||
|
sway_cmd cmd_title_align;
|
||||||
sway_cmd cmd_title_format;
|
sway_cmd cmd_title_format;
|
||||||
sway_cmd cmd_titlebar_border_thickness;
|
sway_cmd cmd_titlebar_border_thickness;
|
||||||
sway_cmd cmd_titlebar_padding;
|
sway_cmd cmd_titlebar_padding;
|
||||||
|
|
|
@ -357,6 +357,12 @@ enum mouse_warping_mode {
|
||||||
WARP_CONTAINER
|
WARP_CONTAINER
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum alignment {
|
||||||
|
ALIGN_LEFT,
|
||||||
|
ALIGN_CENTER,
|
||||||
|
ALIGN_RIGHT
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The configuration struct. The result of loading a config file.
|
* The configuration struct. The result of loading a config file.
|
||||||
*/
|
*/
|
||||||
|
@ -409,6 +415,7 @@ struct sway_config {
|
||||||
bool validating;
|
bool validating;
|
||||||
bool auto_back_and_forth;
|
bool auto_back_and_forth;
|
||||||
bool show_marks;
|
bool show_marks;
|
||||||
|
enum alignment title_align;
|
||||||
bool tiling_drag;
|
bool tiling_drag;
|
||||||
|
|
||||||
bool smart_gaps;
|
bool smart_gaps;
|
||||||
|
|
|
@ -103,6 +103,7 @@ static struct cmd_handler handlers[] = {
|
||||||
{ "smart_borders", cmd_smart_borders },
|
{ "smart_borders", cmd_smart_borders },
|
||||||
{ "smart_gaps", cmd_smart_gaps },
|
{ "smart_gaps", cmd_smart_gaps },
|
||||||
{ "tiling_drag", cmd_tiling_drag },
|
{ "tiling_drag", cmd_tiling_drag },
|
||||||
|
{ "title_align", cmd_title_align },
|
||||||
{ "titlebar_border_thickness", cmd_titlebar_border_thickness },
|
{ "titlebar_border_thickness", cmd_titlebar_border_thickness },
|
||||||
{ "titlebar_padding", cmd_titlebar_padding },
|
{ "titlebar_padding", cmd_titlebar_padding },
|
||||||
{ "workspace", cmd_workspace },
|
{ "workspace", cmd_workspace },
|
||||||
|
|
30
sway/commands/title_align.c
Normal file
30
sway/commands/title_align.c
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#include "sway/commands.h"
|
||||||
|
#include "sway/config.h"
|
||||||
|
#include "sway/output.h"
|
||||||
|
#include "sway/tree/container.h"
|
||||||
|
#include "sway/tree/root.h"
|
||||||
|
|
||||||
|
struct cmd_results *cmd_title_align(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "title_align", EXPECTED_AT_LEAST, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(argv[0], "left") == 0) {
|
||||||
|
config->title_align = ALIGN_LEFT;
|
||||||
|
} else if (strcmp(argv[0], "center") == 0) {
|
||||||
|
config->title_align = ALIGN_CENTER;
|
||||||
|
} else if (strcmp(argv[0], "right") == 0) {
|
||||||
|
config->title_align = ALIGN_RIGHT;
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, "title_align",
|
||||||
|
"Expected 'title_align left|center|right'");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < root->outputs->length; ++i) {
|
||||||
|
struct sway_output *output = root->outputs->items[i];
|
||||||
|
output_damage_whole(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
|
@ -234,6 +234,7 @@ static void config_defaults(struct sway_config *config) {
|
||||||
config->auto_back_and_forth = false;
|
config->auto_back_and_forth = false;
|
||||||
config->reading = false;
|
config->reading = false;
|
||||||
config->show_marks = true;
|
config->show_marks = true;
|
||||||
|
config->title_align = ALIGN_LEFT;
|
||||||
config->tiling_drag = true;
|
config->tiling_drag = true;
|
||||||
|
|
||||||
config->smart_gaps = false;
|
config->smart_gaps = false;
|
||||||
|
|
|
@ -371,6 +371,7 @@ static void render_titlebar(struct sway_output *output,
|
||||||
int titlebar_border_thickness = config->titlebar_border_thickness;
|
int titlebar_border_thickness = config->titlebar_border_thickness;
|
||||||
int titlebar_h_padding = config->titlebar_h_padding;
|
int titlebar_h_padding = config->titlebar_h_padding;
|
||||||
int titlebar_v_padding = config->titlebar_v_padding;
|
int titlebar_v_padding = config->titlebar_v_padding;
|
||||||
|
enum alignment title_align = config->title_align;
|
||||||
|
|
||||||
// Single pixel bar above title
|
// Single pixel bar above title
|
||||||
memcpy(&color, colors->border, sizeof(float) * 4);
|
memcpy(&color, colors->border, sizeof(float) * 4);
|
||||||
|
@ -420,19 +421,25 @@ static void render_titlebar(struct sway_output *output,
|
||||||
render_rect(output->wlr_output, output_damage, &box, color);
|
render_rect(output->wlr_output, output_damage, &box, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t inner_width = width - titlebar_h_padding * 2;
|
int inner_x = x - output_x + titlebar_h_padding;
|
||||||
int bg_y = y + titlebar_border_thickness;
|
int bg_y = y + titlebar_border_thickness;
|
||||||
|
size_t inner_width = width - titlebar_h_padding * 2;
|
||||||
|
|
||||||
|
// output-buffer local
|
||||||
|
int ob_inner_x = round(inner_x * output_scale);
|
||||||
|
int ob_inner_width = scale_length(inner_width, inner_x, output_scale);
|
||||||
int ob_bg_height = scale_length(
|
int ob_bg_height = scale_length(
|
||||||
(titlebar_v_padding - titlebar_border_thickness) * 2 +
|
(titlebar_v_padding - titlebar_border_thickness) * 2 +
|
||||||
config->font_height, bg_y, output_scale);
|
config->font_height, bg_y, output_scale);
|
||||||
|
|
||||||
// Marks
|
// Marks
|
||||||
int marks_ob_width = 0; // output-buffer-local
|
int ob_marks_x = 0; // output-buffer-local
|
||||||
|
int ob_marks_width = 0; // output-buffer-local
|
||||||
if (config->show_marks && marks_texture) {
|
if (config->show_marks && marks_texture) {
|
||||||
struct wlr_box texture_box;
|
struct wlr_box texture_box;
|
||||||
wlr_texture_get_size(marks_texture,
|
wlr_texture_get_size(marks_texture,
|
||||||
&texture_box.width, &texture_box.height);
|
&texture_box.width, &texture_box.height);
|
||||||
marks_ob_width = texture_box.width;
|
ob_marks_width = texture_box.width;
|
||||||
|
|
||||||
// The marks texture might be shorter than the config->font_height, in
|
// The marks texture might be shorter than the config->font_height, in
|
||||||
// which case we need to pad it as evenly as possible above and below.
|
// which case we need to pad it as evenly as possible above and below.
|
||||||
|
@ -440,9 +447,15 @@ static void render_titlebar(struct sway_output *output,
|
||||||
int ob_padding_above = floor(ob_padding_total / 2.0);
|
int ob_padding_above = floor(ob_padding_total / 2.0);
|
||||||
int ob_padding_below = ceil(ob_padding_total / 2.0);
|
int ob_padding_below = ceil(ob_padding_total / 2.0);
|
||||||
|
|
||||||
// Render texture
|
// Render texture. If the title is on the right, the marks will be on
|
||||||
texture_box.x = round((x - output_x + width - titlebar_h_padding)
|
// the left. Otherwise, they will be on the right.
|
||||||
* output_scale) - texture_box.width;
|
if (title_align == ALIGN_RIGHT || texture_box.width > ob_inner_width) {
|
||||||
|
texture_box.x = ob_inner_x;
|
||||||
|
} else {
|
||||||
|
texture_box.x = ob_inner_x + ob_inner_width - texture_box.width;
|
||||||
|
}
|
||||||
|
ob_marks_x = texture_box.x;
|
||||||
|
|
||||||
texture_box.y = round((bg_y - output_y) * output_scale) +
|
texture_box.y = round((bg_y - output_y) * output_scale) +
|
||||||
ob_padding_above;
|
ob_padding_above;
|
||||||
|
|
||||||
|
@ -451,8 +464,8 @@ static void render_titlebar(struct sway_output *output,
|
||||||
WL_OUTPUT_TRANSFORM_NORMAL,
|
WL_OUTPUT_TRANSFORM_NORMAL,
|
||||||
0.0, output->wlr_output->transform_matrix);
|
0.0, output->wlr_output->transform_matrix);
|
||||||
|
|
||||||
if (inner_width * output_scale < texture_box.width) {
|
if (ob_inner_width < texture_box.width) {
|
||||||
texture_box.width = inner_width * output_scale;
|
texture_box.width = ob_inner_width;
|
||||||
}
|
}
|
||||||
render_texture(output->wlr_output, output_damage, marks_texture,
|
render_texture(output->wlr_output, output_damage, marks_texture,
|
||||||
&texture_box, matrix, con->alpha);
|
&texture_box, matrix, con->alpha);
|
||||||
|
@ -473,12 +486,13 @@ static void render_titlebar(struct sway_output *output,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Title text
|
// Title text
|
||||||
size_t title_ob_width = 0; // output-buffer-local
|
int ob_title_x = 0; // output-buffer-local
|
||||||
|
int ob_title_width = 0; // output-buffer-local
|
||||||
if (title_texture) {
|
if (title_texture) {
|
||||||
struct wlr_box texture_box;
|
struct wlr_box texture_box;
|
||||||
wlr_texture_get_size(title_texture,
|
wlr_texture_get_size(title_texture,
|
||||||
&texture_box.width, &texture_box.height);
|
&texture_box.width, &texture_box.height);
|
||||||
title_ob_width = texture_box.width;
|
ob_title_width = texture_box.width;
|
||||||
|
|
||||||
// The title texture might be shorter than the config->font_height,
|
// The title texture might be shorter than the config->font_height,
|
||||||
// in which case we need to pad it above and below.
|
// in which case we need to pad it above and below.
|
||||||
|
@ -489,8 +503,26 @@ static void render_titlebar(struct sway_output *output,
|
||||||
texture_box.height;
|
texture_box.height;
|
||||||
|
|
||||||
// Render texture
|
// Render texture
|
||||||
texture_box.x =
|
if (texture_box.width > ob_inner_width - ob_marks_width) {
|
||||||
round((x - output_x + titlebar_h_padding) * output_scale);
|
texture_box.x = (title_align == ALIGN_RIGHT && ob_marks_width)
|
||||||
|
? ob_marks_x + ob_marks_width : ob_inner_x;
|
||||||
|
} else if (title_align == ALIGN_LEFT) {
|
||||||
|
texture_box.x = ob_inner_x;
|
||||||
|
} else if (title_align == ALIGN_CENTER) {
|
||||||
|
// If there are marks visible, center between the edge and marks.
|
||||||
|
// Otherwise, center in the inner area.
|
||||||
|
if (ob_marks_width) {
|
||||||
|
texture_box.x = (ob_inner_x + ob_marks_x) / 2
|
||||||
|
- texture_box.width / 2;
|
||||||
|
} else {
|
||||||
|
texture_box.x = ob_inner_x + ob_inner_width / 2
|
||||||
|
- texture_box.width / 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
texture_box.x = ob_inner_x + ob_inner_width - texture_box.width;
|
||||||
|
}
|
||||||
|
ob_title_x = texture_box.x;
|
||||||
|
|
||||||
texture_box.y =
|
texture_box.y =
|
||||||
round((bg_y - output_y) * output_scale) + ob_padding_above;
|
round((bg_y - output_y) * output_scale) + ob_padding_above;
|
||||||
|
|
||||||
|
@ -499,11 +531,10 @@ static void render_titlebar(struct sway_output *output,
|
||||||
WL_OUTPUT_TRANSFORM_NORMAL,
|
WL_OUTPUT_TRANSFORM_NORMAL,
|
||||||
0.0, output->wlr_output->transform_matrix);
|
0.0, output->wlr_output->transform_matrix);
|
||||||
|
|
||||||
int inner_x = x - output_x + titlebar_h_padding;
|
if (ob_inner_width - ob_marks_width < texture_box.width) {
|
||||||
int ob_inner_width = scale_length(inner_width, inner_x, output_scale);
|
texture_box.width = ob_inner_width - ob_marks_width;
|
||||||
if (ob_inner_width - marks_ob_width < texture_box.width) {
|
|
||||||
texture_box.width = ob_inner_width - marks_ob_width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render_texture(output->wlr_output, output_damage, title_texture,
|
render_texture(output->wlr_output, output_damage, title_texture,
|
||||||
&texture_box, matrix, con->alpha);
|
&texture_box, matrix, con->alpha);
|
||||||
|
|
||||||
|
@ -522,17 +553,36 @@ static void render_titlebar(struct sway_output *output,
|
||||||
render_rect(output->wlr_output, output_damage, &box, color);
|
render_rect(output->wlr_output, output_damage, &box, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine the left + right extends of the textures (output-buffer local)
|
||||||
|
int ob_left_x, ob_left_width, ob_right_x, ob_right_width;
|
||||||
|
if (ob_title_x < ob_marks_x) {
|
||||||
|
ob_left_x = ob_title_x;
|
||||||
|
ob_left_width = ob_title_width;
|
||||||
|
ob_right_x = ob_marks_x;
|
||||||
|
ob_right_width = ob_marks_width;
|
||||||
|
} else {
|
||||||
|
ob_left_x = ob_marks_x;
|
||||||
|
ob_left_width = ob_marks_width;
|
||||||
|
ob_right_x = ob_title_x;
|
||||||
|
ob_right_width = ob_title_width;
|
||||||
|
}
|
||||||
|
if (ob_left_x < ob_inner_x) {
|
||||||
|
ob_left_x = ob_inner_x;
|
||||||
|
} else if (ob_left_x + ob_left_width > ob_right_x + ob_right_width) {
|
||||||
|
ob_right_x = ob_left_x;
|
||||||
|
ob_right_width = ob_left_width;
|
||||||
|
}
|
||||||
|
|
||||||
// Filler between title and marks
|
// Filler between title and marks
|
||||||
box.width =
|
box.width = ob_right_x - ob_left_x - ob_left_width;
|
||||||
round(inner_width * output_scale) - title_ob_width - marks_ob_width;
|
|
||||||
if (box.width > 0) {
|
if (box.width > 0) {
|
||||||
box.x = round((x + titlebar_h_padding) * output_scale) + title_ob_width;
|
box.x = ob_left_x + ob_left_width + round(output_x * output_scale);
|
||||||
box.y = round(bg_y * output_scale);
|
box.y = round(bg_y * output_scale);
|
||||||
box.height = ob_bg_height;
|
box.height = ob_bg_height;
|
||||||
render_rect(output->wlr_output, output_damage, &box, color);
|
render_rect(output->wlr_output, output_damage, &box, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Padding left of title
|
// Padding on left side
|
||||||
left_offset = (layout == L_TABBED) * titlebar_border_thickness;
|
left_offset = (layout == L_TABBED) * titlebar_border_thickness;
|
||||||
box.x = x + left_offset;
|
box.x = x + left_offset;
|
||||||
box.y = y + titlebar_border_thickness;
|
box.y = y + titlebar_border_thickness;
|
||||||
|
@ -540,9 +590,13 @@ static void render_titlebar(struct sway_output *output,
|
||||||
box.height = (titlebar_v_padding - titlebar_border_thickness) * 2 +
|
box.height = (titlebar_v_padding - titlebar_border_thickness) * 2 +
|
||||||
config->font_height;
|
config->font_height;
|
||||||
scale_box(&box, output_scale);
|
scale_box(&box, output_scale);
|
||||||
|
int left_x = ob_left_x + round(output_x * output_scale);
|
||||||
|
if (box.x + box.width < left_x) {
|
||||||
|
box.width += left_x - box.x - box.width;
|
||||||
|
}
|
||||||
render_rect(output->wlr_output, output_damage, &box, color);
|
render_rect(output->wlr_output, output_damage, &box, color);
|
||||||
|
|
||||||
// Padding right of marks
|
// Padding on right side
|
||||||
right_offset = (layout == L_TABBED) * titlebar_border_thickness;
|
right_offset = (layout == L_TABBED) * titlebar_border_thickness;
|
||||||
box.x = x + width - titlebar_h_padding;
|
box.x = x + width - titlebar_h_padding;
|
||||||
box.y = y + titlebar_border_thickness;
|
box.y = y + titlebar_border_thickness;
|
||||||
|
@ -550,6 +604,11 @@ static void render_titlebar(struct sway_output *output,
|
||||||
box.height = (titlebar_v_padding - titlebar_border_thickness) * 2 +
|
box.height = (titlebar_v_padding - titlebar_border_thickness) * 2 +
|
||||||
config->font_height;
|
config->font_height;
|
||||||
scale_box(&box, output_scale);
|
scale_box(&box, output_scale);
|
||||||
|
int right_rx = ob_right_x + ob_right_width + round(output_x * output_scale);
|
||||||
|
if (right_rx < box.x) {
|
||||||
|
box.width += box.x - right_rx;
|
||||||
|
box.x = right_rx;
|
||||||
|
}
|
||||||
render_rect(output->wlr_output, output_damage, &box, color);
|
render_rect(output->wlr_output, output_damage, &box, color);
|
||||||
|
|
||||||
if (connects_sides) {
|
if (connects_sides) {
|
||||||
|
|
|
@ -88,6 +88,7 @@ sway_sources = files(
|
||||||
'commands/swaynag_command.c',
|
'commands/swaynag_command.c',
|
||||||
'commands/swap.c',
|
'commands/swap.c',
|
||||||
'commands/tiling_drag.c',
|
'commands/tiling_drag.c',
|
||||||
|
'commands/title_align.c',
|
||||||
'commands/title_format.c',
|
'commands/title_format.c',
|
||||||
'commands/titlebar_border_thickness.c',
|
'commands/titlebar_border_thickness.c',
|
||||||
'commands/titlebar_padding.c',
|
'commands/titlebar_padding.c',
|
||||||
|
|
|
@ -555,6 +555,11 @@ The default colors are:
|
||||||
Set the opacity of the window between 0 (completely transparent) and 1
|
Set the opacity of the window between 0 (completely transparent) and 1
|
||||||
(completely opaque).
|
(completely opaque).
|
||||||
|
|
||||||
|
*title\_align* left|center|right
|
||||||
|
Sets the title alignment. If _right_ is selected and _show\_marks_ is set
|
||||||
|
to _yes_, the marks will be shown on the _left_ side instead of the
|
||||||
|
_right_ side.
|
||||||
|
|
||||||
*unmark* [<identifier>]
|
*unmark* [<identifier>]
|
||||||
*unmark* will remove _identifier_ from the list of current marks on a
|
*unmark* will remove _identifier_ from the list of current marks on a
|
||||||
window. If _identifier_ is omitted, all marks are removed.
|
window. If _identifier_ is omitted, all marks are removed.
|
||||||
|
|
Loading…
Reference in a new issue