Render titles

This commit is contained in:
Ryan Dwyer 2018-05-02 23:07:52 +10:00
parent f3d0885524
commit b667298a0a
11 changed files with 155 additions and 19 deletions

View file

@ -206,7 +206,7 @@ struct bar_config {
struct border_colors { struct border_colors {
float border[4]; float border[4];
float background[4]; float background[4];
float text[4]; uint32_t text; /**< uint32_t because that's the format that cairo uses */
float indicator[4]; float indicator[4];
float child_border[4]; float child_border[4];
}; };
@ -461,6 +461,8 @@ struct bar_config *default_bar_config(void);
void free_bar_config(struct bar_config *bar); void free_bar_config(struct bar_config *bar);
int get_font_text_height(char *font);
/* Global config singleton. */ /* Global config singleton. */
extern struct sway_config *config; extern struct sway_config *config;

View file

@ -85,6 +85,11 @@ struct sway_container {
float alpha; float alpha;
struct wlr_texture *title_focused;
struct wlr_texture *title_focused_inactive;
struct wlr_texture *title_unfocused;
struct wlr_texture *title_urgent;
struct { struct {
struct wl_signal destroy; struct wl_signal destroy;
// Raised after the tree updates, but before arrange_windows // Raised after the tree updates, but before arrange_windows
@ -191,4 +196,6 @@ struct sway_container *container_reap_empty_recursive(
struct sway_container *container_flatten(struct sway_container *container); struct sway_container *container_flatten(struct sway_container *container);
void container_update_title_textures(struct sway_container *container);
#endif #endif

View file

@ -106,6 +106,7 @@ static struct cmd_handler handlers[] = {
{ "exec_always", cmd_exec_always }, { "exec_always", cmd_exec_always },
{ "focus_follows_mouse", cmd_focus_follows_mouse }, { "focus_follows_mouse", cmd_focus_follows_mouse },
{ "for_window", cmd_for_window }, { "for_window", cmd_for_window },
{ "font", cmd_font },
{ "fullscreen", cmd_fullscreen }, { "fullscreen", cmd_fullscreen },
{ "include", cmd_include }, { "include", cmd_include },
{ "input", cmd_input }, { "input", cmd_input },

View file

@ -3,7 +3,10 @@
#include "sway/config.h" #include "sway/config.h"
#include "sway/tree/container.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] != '#') { if (hexstring[0] != '#') {
return false; return false;
} }
@ -25,6 +28,18 @@ static bool parse_color(char *hexstring, float dest[static 4]) {
decimal = (decimal << 8) | 0xff; 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[0] = ((decimal >> 24) & 0xff) / 255.0;
dest[1] = ((decimal >> 16) & 0xff) / 255.0; dest[1] = ((decimal >> 16) & 0xff) / 255.0;
dest[2] = ((decimal >> 8) & 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; 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, return cmd_results_new(CMD_INVALID, cmd_name,
"Unable to parse border color"); "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, return cmd_results_new(CMD_INVALID, cmd_name,
"Unable to parse background color"); "Unable to parse background color");
} }
if (!parse_color(argv[2], class->text)) { if (!parse_color_int(argv[2], &class->text)) {
return cmd_results_new(CMD_INVALID, cmd_name, return cmd_results_new(CMD_INVALID, cmd_name,
"Unable to parse text color"); "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, return cmd_results_new(CMD_INVALID, cmd_name,
"Unable to parse indicator color"); "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, return cmd_results_new(CMD_INVALID, cmd_name,
"Unable to parse child border color"); "Unable to parse child border color");
} }

18
sway/commands/font.c Normal file
View file

@ -0,0 +1,18 @@
#define _POSIX_C_SOURCE 200809L
#include <string.h>
#include "sway/commands.h"
#include "sway/config.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->font_height = get_font_text_height(font);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}

View file

@ -25,6 +25,8 @@
#include "sway/commands.h" #include "sway/commands.h"
#include "sway/config.h" #include "sway/config.h"
#include "sway/tree/layout.h" #include "sway/tree/layout.h"
#include "cairo.h"
#include "pango.h"
#include "readline.h" #include "readline.h"
#include "stringop.h" #include "stringop.h"
#include "list.h" #include "list.h"
@ -130,6 +132,17 @@ static void destroy_removed_seats(struct sway_config *old_config,
} }
} }
int get_font_text_height(char *font) {
cairo_t *cairo = cairo_create(NULL);
int text_height;
get_text_size(cairo, font, NULL, &text_height, 1, false,
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"!@#$%^&*([{|");
cairo_destroy(cairo);
return text_height;
}
static void set_color(float dest[static 4], uint32_t color) { static void set_color(float dest[static 4], uint32_t color) {
dest[0] = ((color >> 16) & 0xff) / 255.0; dest[0] = ((color >> 16) & 0xff) / 255.0;
dest[1] = ((color >> 8) & 0xff) / 255.0; dest[1] = ((color >> 8) & 0xff) / 255.0;
@ -169,7 +182,7 @@ static void config_defaults(struct sway_config *config) {
config->default_layout = L_NONE; config->default_layout = L_NONE;
config->default_orientation = L_NONE; config->default_orientation = L_NONE;
if (!(config->font = strdup("monospace 10"))) goto cleanup; if (!(config->font = strdup("monospace 10"))) goto cleanup;
//config->font_height = get_font_text_height(config->font); config->font_height = get_font_text_height(config->font);
// floating view // floating view
config->floating_maximum_width = 0; config->floating_maximum_width = 0;
@ -208,31 +221,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.border, 0x4C7899); set_color(config->border_colors.focused.border, 0x4C7899);
set_color(config->border_colors.focused.background, 0x285577); set_color(config->border_colors.focused.background, 0x285577);
set_color(config->border_colors.focused.text, 0xFFFFFF); config->border_colors.focused.text = 0xFFFFFFFF;
set_color(config->border_colors.focused.indicator, 0x2E9EF4); set_color(config->border_colors.focused.indicator, 0x2E9EF4);
set_color(config->border_colors.focused.child_border, 0x285577); 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.border, 0x333333);
set_color(config->border_colors.focused_inactive.background, 0x5F676A); set_color(config->border_colors.focused_inactive.background, 0x5F676A);
set_color(config->border_colors.focused_inactive.text, 0xFFFFFF); config->border_colors.focused_inactive.text = 0xFFFFFFFF;
set_color(config->border_colors.focused_inactive.indicator, 0x484E50); set_color(config->border_colors.focused_inactive.indicator, 0x484E50);
set_color(config->border_colors.focused_inactive.child_border, 0x5F676A); set_color(config->border_colors.focused_inactive.child_border, 0x5F676A);
set_color(config->border_colors.unfocused.border, 0x333333); set_color(config->border_colors.unfocused.border, 0x333333);
set_color(config->border_colors.unfocused.background, 0x222222); set_color(config->border_colors.unfocused.background, 0x222222);
set_color(config->border_colors.unfocused.text, 0x888888); config->border_colors.unfocused.text = 0x888888FF;
set_color(config->border_colors.unfocused.indicator, 0x292D2E); set_color(config->border_colors.unfocused.indicator, 0x292D2E);
set_color(config->border_colors.unfocused.child_border, 0x222222); set_color(config->border_colors.unfocused.child_border, 0x222222);
set_color(config->border_colors.urgent.border, 0x2F343A); set_color(config->border_colors.urgent.border, 0x2F343A);
set_color(config->border_colors.urgent.background, 0x900000); set_color(config->border_colors.urgent.background, 0x900000);
set_color(config->border_colors.urgent.text, 0xFFFFFF); config->border_colors.urgent.text = 0xFFFFFFFF;
set_color(config->border_colors.urgent.indicator, 0x900000); set_color(config->border_colors.urgent.indicator, 0x900000);
set_color(config->border_colors.urgent.child_border, 0x900000); set_color(config->border_colors.urgent.child_border, 0x900000);
set_color(config->border_colors.placeholder.border, 0x000000); set_color(config->border_colors.placeholder.border, 0x000000);
set_color(config->border_colors.placeholder.background, 0x0C0C0C); set_color(config->border_colors.placeholder.background, 0x0C0C0C);
set_color(config->border_colors.placeholder.text, 0xFFFFFF); config->border_colors.placeholder.text = 0xFFFFFFFF;
set_color(config->border_colors.placeholder.indicator, 0x000000); set_color(config->border_colors.placeholder.indicator, 0x000000);
set_color(config->border_colors.placeholder.child_border, 0x0C0C0C); set_color(config->border_colors.placeholder.child_border, 0x0C0C0C);

View file

@ -227,7 +227,8 @@ static void render_view(struct sway_view *view, struct sway_output *output) {
* Render decorations for a view with "border normal". * Render decorations for a view with "border normal".
*/ */
static void render_container_simple_border_normal(struct sway_output *output, 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 = struct wlr_renderer *renderer =
wlr_backend_get_renderer(output->wlr_output->backend); wlr_backend_get_renderer(output->wlr_output->backend);
struct wlr_box box; struct wlr_box box;
@ -306,7 +307,14 @@ static void render_container_simple_border_normal(struct sway_output *output,
output->wlr_output->transform_matrix); output->wlr_output->transform_matrix);
// Title text // 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->type == C_VIEW) {
if (child->sway_view->border != B_NONE) { if (child->sway_view->border != B_NONE) {
struct border_colors *colors; struct border_colors *colors;
struct wlr_texture *title_texture;
if (focus == child) { if (focus == child) {
colors = &config->border_colors.focused; colors = &config->border_colors.focused;
title_texture = child->title_focused;
} else if (seat_get_focus_inactive(seat, con) == child) { } else if (seat_get_focus_inactive(seat, con) == child) {
colors = &config->border_colors.focused_inactive; colors = &config->border_colors.focused_inactive;
title_texture = child->title_focused_inactive;
} else { } else {
colors = &config->border_colors.unfocused; colors = &config->border_colors.unfocused;
title_texture = child->title_unfocused;
} }
if (child->sway_view->border == B_NORMAL) { if (child->sway_view->border == B_NORMAL) {
render_container_simple_border_normal(output, child, render_container_simple_border_normal(output, child,
colors); colors, title_texture);
} else { } else {
render_container_simple_border_pixel(output, child, colors); render_container_simple_border_pixel(output, child, colors);
} }

View file

@ -38,6 +38,7 @@ sway_sources = files(
'commands/exec_always.c', 'commands/exec_always.c',
'commands/focus.c', 'commands/focus.c',
'commands/focus_follows_mouse.c', 'commands/focus_follows_mouse.c',
'commands/font.c',
'commands/for_window.c', 'commands/for_window.c',
'commands/fullscreen.c', 'commands/fullscreen.c',
'commands/kill.c', 'commands/kill.c',

View file

@ -203,6 +203,7 @@ void arrange_children_of(struct sway_container *parent) {
} else { } else {
arrange_children_of(child); arrange_children_of(child);
} }
container_update_title_textures(child);
} }
container_damage_whole(parent); container_damage_whole(parent);
update_debug_tree(); update_debug_tree();

View file

@ -7,6 +7,8 @@
#include <wayland-server.h> #include <wayland-server.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_wl_shell.h> #include <wlr/types/wlr_wl_shell.h>
#include "cairo.h"
#include "pango.h"
#include "sway/config.h" #include "sway/config.h"
#include "sway/input/input-manager.h" #include "sway/input/input-manager.h"
#include "sway/input/seat.h" #include "sway/input/seat.h"
@ -120,6 +122,13 @@ static void _container_destroy(struct sway_container *cont) {
if (cont->name) { if (cont->name) {
free(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); list_free(cont->children);
cont->children = NULL; cont->children = NULL;
free(cont); free(cont);
@ -546,3 +555,59 @@ void container_damage_whole(struct sway_container *con) {
} }
output_damage_whole_container(output->sway_output, 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);
PangoContext *pango = pango_cairo_create_context(cairo);
cairo_set_source_u32(cairo, class->text);
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);
}

View file

@ -103,11 +103,12 @@ void view_autoconfigure(struct sway_view *view) {
height = view->swayc->height - view->border_thickness * 2; height = view->swayc->height - view->border_thickness * 2;
break; break;
case B_NORMAL: 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; 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; 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; break;
} }