commit
87e65e5c5b
|
@ -304,7 +304,7 @@ struct sway_config {
|
|||
enum sway_container_layout default_orientation;
|
||||
enum sway_container_layout default_layout;
|
||||
char *font;
|
||||
int font_height;
|
||||
size_t font_height;
|
||||
|
||||
// Flags
|
||||
bool focus_follows_mouse;
|
||||
|
@ -461,6 +461,13 @@ struct bar_config *default_bar_config(void);
|
|||
|
||||
void free_bar_config(struct bar_config *bar);
|
||||
|
||||
/**
|
||||
* Updates the value of config->font_height based on the max title height
|
||||
* reported by each container. If recalculate is true, the containers will
|
||||
* recalculate their heights before reporting.
|
||||
*/
|
||||
void config_find_font_height(bool recalculate);
|
||||
|
||||
/* Global config singleton. */
|
||||
extern struct sway_config *config;
|
||||
|
||||
|
|
|
@ -85,6 +85,12 @@ struct sway_container {
|
|||
|
||||
float alpha;
|
||||
|
||||
struct wlr_texture *title_focused;
|
||||
struct wlr_texture *title_focused_inactive;
|
||||
struct wlr_texture *title_unfocused;
|
||||
struct wlr_texture *title_urgent;
|
||||
size_t title_height;
|
||||
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
// Raised after the tree updates, but before arrange_windows
|
||||
|
@ -191,4 +197,14 @@ struct sway_container *container_reap_empty_recursive(
|
|||
|
||||
struct sway_container *container_flatten(struct sway_container *container);
|
||||
|
||||
void container_update_title_textures(struct sway_container *container);
|
||||
|
||||
/**
|
||||
* Calculate the container's title_height property.
|
||||
*/
|
||||
void container_calculate_title_height(struct sway_container *container);
|
||||
|
||||
void container_update_title(struct sway_container *container,
|
||||
const char *new_title);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -106,6 +106,7 @@ static struct cmd_handler handlers[] = {
|
|||
{ "exec_always", cmd_exec_always },
|
||||
{ "focus_follows_mouse", cmd_focus_follows_mouse },
|
||||
{ "for_window", cmd_for_window },
|
||||
{ "font", cmd_font },
|
||||
{ "fullscreen", cmd_fullscreen },
|
||||
{ "include", cmd_include },
|
||||
{ "input", cmd_input },
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
#include "sway/config.h"
|
||||
#include "sway/tree/container.h"
|
||||
|
||||
static bool parse_color(char *hexstring, float dest[static 4]) {
|
||||
/**
|
||||
* Parse the hex string into an integer.
|
||||
*/
|
||||
static bool parse_color_int(char *hexstring, uint32_t *dest) {
|
||||
if (hexstring[0] != '#') {
|
||||
return false;
|
||||
}
|
||||
|
@ -25,6 +28,18 @@ static bool parse_color(char *hexstring, float dest[static 4]) {
|
|||
decimal = (decimal << 8) | 0xff;
|
||||
}
|
||||
|
||||
*dest = decimal;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the hex string into a float value.
|
||||
*/
|
||||
static bool parse_color_float(char *hexstring, float dest[static 4]) {
|
||||
uint32_t decimal;
|
||||
if (!parse_color_int(hexstring, &decimal)) {
|
||||
return false;
|
||||
}
|
||||
dest[0] = ((decimal >> 24) & 0xff) / 255.0;
|
||||
dest[1] = ((decimal >> 16) & 0xff) / 255.0;
|
||||
dest[2] = ((decimal >> 8) & 0xff) / 255.0;
|
||||
|
@ -39,27 +54,27 @@ static struct cmd_results *handle_command(int argc, char **argv,
|
|||
return error;
|
||||
}
|
||||
|
||||
if (!parse_color(argv[0], class->border)) {
|
||||
if (!parse_color_float(argv[0], class->border)) {
|
||||
return cmd_results_new(CMD_INVALID, cmd_name,
|
||||
"Unable to parse border color");
|
||||
}
|
||||
|
||||
if (!parse_color(argv[1], class->background)) {
|
||||
if (!parse_color_float(argv[1], class->background)) {
|
||||
return cmd_results_new(CMD_INVALID, cmd_name,
|
||||
"Unable to parse background color");
|
||||
}
|
||||
|
||||
if (!parse_color(argv[2], class->text)) {
|
||||
if (!parse_color_float(argv[2], class->text)) {
|
||||
return cmd_results_new(CMD_INVALID, cmd_name,
|
||||
"Unable to parse text color");
|
||||
}
|
||||
|
||||
if (!parse_color(argv[3], class->indicator)) {
|
||||
if (!parse_color_float(argv[3], class->indicator)) {
|
||||
return cmd_results_new(CMD_INVALID, cmd_name,
|
||||
"Unable to parse indicator color");
|
||||
}
|
||||
|
||||
if (!parse_color(argv[4], class->child_border)) {
|
||||
if (!parse_color_float(argv[4], class->child_border)) {
|
||||
return cmd_results_new(CMD_INVALID, cmd_name,
|
||||
"Unable to parse child border color");
|
||||
}
|
||||
|
|
22
sway/commands/font.c
Normal file
22
sway/commands/font.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <string.h>
|
||||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/tree/arrange.h"
|
||||
#include "log.h"
|
||||
#include "stringop.h"
|
||||
|
||||
struct cmd_results *cmd_font(int argc, char **argv) {
|
||||
struct cmd_results *error = NULL;
|
||||
if ((error = checkarg(argc, "font", EXPECTED_AT_LEAST, 1))) {
|
||||
return error;
|
||||
}
|
||||
char *font = join_args(argv, argc);
|
||||
free(config->font);
|
||||
config->font = strdup(font);
|
||||
config_find_font_height(true);
|
||||
if (!config->reading) {
|
||||
arrange_root();
|
||||
}
|
||||
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||
}
|
|
@ -25,6 +25,8 @@
|
|||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/tree/layout.h"
|
||||
#include "cairo.h"
|
||||
#include "pango.h"
|
||||
#include "readline.h"
|
||||
#include "stringop.h"
|
||||
#include "list.h"
|
||||
|
@ -169,7 +171,7 @@ static void config_defaults(struct sway_config *config) {
|
|||
config->default_layout = L_NONE;
|
||||
config->default_orientation = L_NONE;
|
||||
if (!(config->font = strdup("monospace 10"))) goto cleanup;
|
||||
//config->font_height = get_font_text_height(config->font);
|
||||
config->font_height = 0;
|
||||
|
||||
// floating view
|
||||
config->floating_maximum_width = 0;
|
||||
|
@ -208,31 +210,31 @@ static void config_defaults(struct sway_config *config) {
|
|||
set_color(config->border_colors.focused.border, 0x4C7899);
|
||||
set_color(config->border_colors.focused.border, 0x4C7899);
|
||||
set_color(config->border_colors.focused.background, 0x285577);
|
||||
set_color(config->border_colors.focused.text, 0xFFFFFF);
|
||||
set_color(config->border_colors.focused.text, 0xFFFFFFFF);
|
||||
set_color(config->border_colors.focused.indicator, 0x2E9EF4);
|
||||
set_color(config->border_colors.focused.child_border, 0x285577);
|
||||
|
||||
set_color(config->border_colors.focused_inactive.border, 0x333333);
|
||||
set_color(config->border_colors.focused_inactive.background, 0x5F676A);
|
||||
set_color(config->border_colors.focused_inactive.text, 0xFFFFFF);
|
||||
set_color(config->border_colors.focused_inactive.text, 0xFFFFFFFF);
|
||||
set_color(config->border_colors.focused_inactive.indicator, 0x484E50);
|
||||
set_color(config->border_colors.focused_inactive.child_border, 0x5F676A);
|
||||
|
||||
set_color(config->border_colors.unfocused.border, 0x333333);
|
||||
set_color(config->border_colors.unfocused.background, 0x222222);
|
||||
set_color(config->border_colors.unfocused.text, 0x888888);
|
||||
set_color(config->border_colors.unfocused.text, 0xFFFFFFFF);
|
||||
set_color(config->border_colors.unfocused.indicator, 0x292D2E);
|
||||
set_color(config->border_colors.unfocused.child_border, 0x222222);
|
||||
|
||||
set_color(config->border_colors.urgent.border, 0x2F343A);
|
||||
set_color(config->border_colors.urgent.background, 0x900000);
|
||||
set_color(config->border_colors.urgent.text, 0xFFFFFF);
|
||||
set_color(config->border_colors.urgent.text, 0xFFFFFFFF);
|
||||
set_color(config->border_colors.urgent.indicator, 0x900000);
|
||||
set_color(config->border_colors.urgent.child_border, 0x900000);
|
||||
|
||||
set_color(config->border_colors.placeholder.border, 0x000000);
|
||||
set_color(config->border_colors.placeholder.background, 0x0C0C0C);
|
||||
set_color(config->border_colors.placeholder.text, 0xFFFFFF);
|
||||
set_color(config->border_colors.placeholder.text, 0xFFFFFFFF);
|
||||
set_color(config->border_colors.placeholder.indicator, 0x000000);
|
||||
set_color(config->border_colors.placeholder.child_border, 0x0C0C0C);
|
||||
|
||||
|
@ -727,3 +729,20 @@ int workspace_output_cmp_workspace(const void *a, const void *b) {
|
|||
const struct workspace_output *wsa = a, *wsb = b;
|
||||
return lenient_strcmp(wsa->workspace, wsb->workspace);
|
||||
}
|
||||
|
||||
static void find_font_height_iterator(struct sway_container *container,
|
||||
void *data) {
|
||||
bool *recalculate = data;
|
||||
if (*recalculate) {
|
||||
container_calculate_title_height(container);
|
||||
}
|
||||
if (container->title_height > config->font_height) {
|
||||
config->font_height = container->title_height;
|
||||
}
|
||||
}
|
||||
|
||||
void config_find_font_height(bool recalculate) {
|
||||
config->font_height = 0;
|
||||
container_for_each_descendant_dfs(&root_container,
|
||||
find_font_height_iterator, &recalculate);
|
||||
}
|
||||
|
|
|
@ -227,7 +227,8 @@ static void render_view(struct sway_view *view, struct sway_output *output) {
|
|||
* Render decorations for a view with "border normal".
|
||||
*/
|
||||
static void render_container_simple_border_normal(struct sway_output *output,
|
||||
struct sway_container *con, struct border_colors *colors) {
|
||||
struct sway_container *con, struct border_colors *colors,
|
||||
struct wlr_texture *title_texture) {
|
||||
struct wlr_renderer *renderer =
|
||||
wlr_backend_get_renderer(output->wlr_output->backend);
|
||||
struct wlr_box box;
|
||||
|
@ -306,7 +307,14 @@ static void render_container_simple_border_normal(struct sway_output *output,
|
|||
output->wlr_output->transform_matrix);
|
||||
|
||||
// Title text
|
||||
// TODO
|
||||
if (title_texture) {
|
||||
double x = (con->x + con->sway_view->border_thickness)
|
||||
* output->wlr_output->scale;
|
||||
double y = (con->y + con->sway_view->border_thickness)
|
||||
* output->wlr_output->scale;
|
||||
wlr_render_texture(renderer, title_texture,
|
||||
output->wlr_output->transform_matrix, x, y, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -390,17 +398,21 @@ static void render_container_simple(struct sway_output *output,
|
|||
if (child->type == C_VIEW) {
|
||||
if (child->sway_view->border != B_NONE) {
|
||||
struct border_colors *colors;
|
||||
struct wlr_texture *title_texture;
|
||||
if (focus == child) {
|
||||
colors = &config->border_colors.focused;
|
||||
title_texture = child->title_focused;
|
||||
} else if (seat_get_focus_inactive(seat, con) == child) {
|
||||
colors = &config->border_colors.focused_inactive;
|
||||
title_texture = child->title_focused_inactive;
|
||||
} else {
|
||||
colors = &config->border_colors.unfocused;
|
||||
title_texture = child->title_unfocused;
|
||||
}
|
||||
|
||||
if (child->sway_view->border == B_NORMAL) {
|
||||
render_container_simple_border_normal(output, child,
|
||||
colors);
|
||||
colors, title_texture);
|
||||
} else {
|
||||
render_container_simple_border_pixel(output, child, colors);
|
||||
}
|
||||
|
|
|
@ -176,6 +176,8 @@ static void handle_commit(struct wl_listener *listener, void *data) {
|
|||
// TODO: Let floating views do whatever
|
||||
view_update_size(view, xdg_shell_v6_view->pending_width,
|
||||
xdg_shell_v6_view->pending_height);
|
||||
container_update_title(view->swayc,
|
||||
view->wlr_xdg_surface_v6->toplevel->title);
|
||||
view_damage(view, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -223,6 +223,7 @@ static void handle_commit(struct wl_listener *listener, void *data) {
|
|||
view_update_size(view, xwayland_view->pending_width,
|
||||
xwayland_view->pending_height);
|
||||
view_damage(view, false);
|
||||
container_update_title(view->swayc, view->wlr_xwayland_surface->title);
|
||||
}
|
||||
|
||||
static void handle_unmap(struct wl_listener *listener, void *data) {
|
||||
|
|
|
@ -38,6 +38,7 @@ sway_sources = files(
|
|||
'commands/exec_always.c',
|
||||
'commands/focus.c',
|
||||
'commands/focus_follows_mouse.c',
|
||||
'commands/font.c',
|
||||
'commands/for_window.c',
|
||||
'commands/fullscreen.c',
|
||||
'commands/kill.c',
|
||||
|
|
|
@ -203,6 +203,7 @@ void arrange_children_of(struct sway_container *parent) {
|
|||
} else {
|
||||
arrange_children_of(child);
|
||||
}
|
||||
container_update_title_textures(child);
|
||||
}
|
||||
container_damage_whole(parent);
|
||||
update_debug_tree();
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include <wayland-server.h>
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
#include <wlr/types/wlr_wl_shell.h>
|
||||
#include "cairo.h"
|
||||
#include "pango.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/input/input-manager.h"
|
||||
#include "sway/input/seat.h"
|
||||
|
@ -120,6 +122,13 @@ static void _container_destroy(struct sway_container *cont) {
|
|||
if (cont->name) {
|
||||
free(cont->name);
|
||||
}
|
||||
if (cont->title_focused) {
|
||||
// If one is set then all of these are set
|
||||
wlr_texture_destroy(cont->title_focused);
|
||||
wlr_texture_destroy(cont->title_focused_inactive);
|
||||
wlr_texture_destroy(cont->title_unfocused);
|
||||
wlr_texture_destroy(cont->title_urgent);
|
||||
}
|
||||
list_free(cont->children);
|
||||
cont->children = NULL;
|
||||
free(cont);
|
||||
|
@ -339,7 +348,7 @@ struct sway_container *container_view_create(struct sway_container *sibling,
|
|||
swayc, title, sibling, sibling ? sibling->type : 0, sibling->name);
|
||||
// Setup values
|
||||
swayc->sway_view = sway_view;
|
||||
swayc->name = title ? strdup(title) : NULL;
|
||||
container_update_title(swayc, title ? title : "");
|
||||
swayc->width = 0;
|
||||
swayc->height = 0;
|
||||
|
||||
|
@ -546,3 +555,115 @@ void container_damage_whole(struct sway_container *con) {
|
|||
}
|
||||
output_damage_whole_container(output->sway_output, con);
|
||||
}
|
||||
|
||||
static void update_title_texture(struct sway_container *con,
|
||||
struct wlr_texture **texture, struct border_colors *class) {
|
||||
if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW,
|
||||
"Unexpected type %s", container_type_to_str(con->type))) {
|
||||
return;
|
||||
}
|
||||
if (!con->width) {
|
||||
return;
|
||||
}
|
||||
struct sway_container *output = container_parent(con, C_OUTPUT);
|
||||
if (!output) {
|
||||
return;
|
||||
}
|
||||
if (*texture) {
|
||||
wlr_texture_destroy(*texture);
|
||||
}
|
||||
if (!con->name) {
|
||||
return;
|
||||
}
|
||||
|
||||
int width = con->width * output->sway_output->wlr_output->scale;
|
||||
int height = config->font_height * output->sway_output->wlr_output->scale;
|
||||
|
||||
cairo_surface_t *surface = cairo_image_surface_create(
|
||||
CAIRO_FORMAT_ARGB32, width, height);
|
||||
cairo_t *cairo = cairo_create(surface);
|
||||
cairo_set_source_rgba(cairo, class->background[0], class->background[1],
|
||||
class->background[2], class->background[3]);
|
||||
cairo_paint(cairo);
|
||||
PangoContext *pango = pango_cairo_create_context(cairo);
|
||||
cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST);
|
||||
cairo_set_source_rgba(cairo, class->text[0], class->text[1],
|
||||
class->text[2], class->text[3]);
|
||||
cairo_move_to(cairo, 0, 0);
|
||||
|
||||
pango_printf(cairo, config->font, output->sway_output->wlr_output->scale,
|
||||
false, "%s", con->name);
|
||||
|
||||
cairo_surface_flush(surface);
|
||||
unsigned char *data = cairo_image_surface_get_data(surface);
|
||||
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
|
||||
struct wlr_renderer *renderer = wlr_backend_get_renderer(
|
||||
output->sway_output->wlr_output->backend);
|
||||
*texture = wlr_texture_from_pixels(
|
||||
renderer, WL_SHM_FORMAT_ARGB8888, stride, width, height, data);
|
||||
cairo_surface_destroy(surface);
|
||||
g_object_unref(pango);
|
||||
cairo_destroy(cairo);
|
||||
}
|
||||
|
||||
void container_update_title_textures(struct sway_container *container) {
|
||||
update_title_texture(container, &container->title_focused,
|
||||
&config->border_colors.focused);
|
||||
update_title_texture(container, &container->title_focused_inactive,
|
||||
&config->border_colors.focused_inactive);
|
||||
update_title_texture(container, &container->title_unfocused,
|
||||
&config->border_colors.unfocused);
|
||||
update_title_texture(container, &container->title_urgent,
|
||||
&config->border_colors.urgent);
|
||||
}
|
||||
|
||||
void container_calculate_title_height(struct sway_container *container) {
|
||||
if (!container->name) {
|
||||
container->title_height = 0;
|
||||
return;
|
||||
}
|
||||
cairo_t *cairo = cairo_create(NULL);
|
||||
int height;
|
||||
get_text_size(cairo, config->font, NULL, &height, 1, false,
|
||||
"%s", container->name);
|
||||
cairo_destroy(cairo);
|
||||
container->title_height = height;
|
||||
}
|
||||
|
||||
static void container_notify_child_title_changed(
|
||||
struct sway_container *container) {
|
||||
if (!container || container->type != C_CONTAINER) {
|
||||
return;
|
||||
}
|
||||
if (container->layout != L_TABBED && container->layout != L_STACKED) {
|
||||
return;
|
||||
}
|
||||
if (container->name) {
|
||||
free(container->name);
|
||||
}
|
||||
// TODO: iterate children and concatenate their titles
|
||||
container->name = strdup("");
|
||||
container_calculate_title_height(container);
|
||||
container_update_title_textures(container);
|
||||
container_notify_child_title_changed(container->parent);
|
||||
}
|
||||
|
||||
void container_update_title(struct sway_container *container,
|
||||
const char *new_title) {
|
||||
if (container->name && strcmp(container->name, new_title) == 0) {
|
||||
return;
|
||||
}
|
||||
if (container->name) {
|
||||
free(container->name);
|
||||
}
|
||||
container->name = strdup(new_title);
|
||||
container_calculate_title_height(container);
|
||||
container_update_title_textures(container);
|
||||
container_notify_child_title_changed(container->parent);
|
||||
|
||||
size_t prev_max_height = config->font_height;
|
||||
config_find_font_height(false);
|
||||
if (config->font_height != prev_max_height) {
|
||||
arrange_root();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,11 +103,12 @@ void view_autoconfigure(struct sway_view *view) {
|
|||
height = view->swayc->height - view->border_thickness * 2;
|
||||
break;
|
||||
case B_NORMAL:
|
||||
// TODO: Size the title bar by checking the font
|
||||
// Height is: border + title height + border + view height + border
|
||||
x = view->swayc->x + view->border_thickness;
|
||||
y = view->swayc->y + 20;
|
||||
y = view->swayc->y + config->font_height + view->border_thickness * 2;
|
||||
width = view->swayc->width - view->border_thickness * 2;
|
||||
height = view->swayc->height - view->border_thickness - 20;
|
||||
height = view->swayc->height - config->font_height
|
||||
- view->border_thickness * 3;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue