Implement borders
Implements rendering of borders. Title text is still to do. Implements the following configuration directives: * client.focused * client.focused_inactive * client.unfocused * client.urgent * border * default_border
This commit is contained in:
parent
b84dfa794c
commit
e67f354333
|
@ -204,11 +204,11 @@ struct bar_config {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct border_colors {
|
struct border_colors {
|
||||||
uint32_t border;
|
float border[4];
|
||||||
uint32_t background;
|
float background[4];
|
||||||
uint32_t text;
|
float text[4];
|
||||||
uint32_t indicator;
|
float indicator[4];
|
||||||
uint32_t child_border;
|
float child_border[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum edge_border_types {
|
enum edge_border_types {
|
||||||
|
@ -338,7 +338,7 @@ struct sway_config {
|
||||||
struct border_colors unfocused;
|
struct border_colors unfocused;
|
||||||
struct border_colors urgent;
|
struct border_colors urgent;
|
||||||
struct border_colors placeholder;
|
struct border_colors placeholder;
|
||||||
uint32_t background;
|
float background[4];
|
||||||
} border_colors;
|
} border_colors;
|
||||||
|
|
||||||
// floating view
|
// floating view
|
||||||
|
|
|
@ -72,8 +72,8 @@ struct sway_container {
|
||||||
// For C_ROOT, this has no meaning
|
// For C_ROOT, this has no meaning
|
||||||
// For C_OUTPUT, this is the output position in layout coordinates
|
// For C_OUTPUT, this is the output position in layout coordinates
|
||||||
// For other types, this is the position in output-local coordinates
|
// For other types, this is the position in output-local coordinates
|
||||||
|
// Includes borders
|
||||||
double x, y;
|
double x, y;
|
||||||
// does not include borders or gaps.
|
|
||||||
double width, height;
|
double width, height;
|
||||||
double saved_width, saved_height;
|
double saved_width, saved_height;
|
||||||
|
|
||||||
|
|
|
@ -41,9 +41,16 @@ struct sway_view {
|
||||||
|
|
||||||
struct sway_container *swayc; // NULL for unmapped views
|
struct sway_container *swayc; // NULL for unmapped views
|
||||||
struct wlr_surface *surface; // NULL for unmapped views
|
struct wlr_surface *surface; // NULL for unmapped views
|
||||||
|
|
||||||
|
// Geometry of the view itself (excludes borders)
|
||||||
|
double x, y;
|
||||||
int width, height;
|
int width, height;
|
||||||
|
|
||||||
bool is_fullscreen;
|
bool is_fullscreen;
|
||||||
|
|
||||||
|
enum sway_container_border border;
|
||||||
|
int border_thickness;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6;
|
struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6;
|
||||||
struct wlr_xwayland_surface *wlr_xwayland_surface;
|
struct wlr_xwayland_surface *wlr_xwayland_surface;
|
||||||
|
@ -160,6 +167,8 @@ const char *view_get_instance(struct sway_view *view);
|
||||||
void view_configure(struct sway_view *view, double ox, double oy, int width,
|
void view_configure(struct sway_view *view, double ox, double oy, int width,
|
||||||
int height);
|
int height);
|
||||||
|
|
||||||
|
void view_autoconfigure(struct sway_view *view);
|
||||||
|
|
||||||
void view_set_activated(struct sway_view *view, bool activated);
|
void view_set_activated(struct sway_view *view, bool activated);
|
||||||
|
|
||||||
void view_set_fullscreen_raw(struct sway_view *view, bool fullscreen);
|
void view_set_fullscreen_raw(struct sway_view *view, bool fullscreen);
|
||||||
|
@ -184,8 +193,6 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface);
|
||||||
|
|
||||||
void view_unmap(struct sway_view *view);
|
void view_unmap(struct sway_view *view);
|
||||||
|
|
||||||
void view_update_position(struct sway_view *view, double ox, double oy);
|
|
||||||
|
|
||||||
void view_update_size(struct sway_view *view, int width, int height);
|
void view_update_size(struct sway_view *view, int width, int height);
|
||||||
|
|
||||||
void view_child_init(struct sway_view_child *child,
|
void view_child_init(struct sway_view_child *child,
|
||||||
|
|
|
@ -97,8 +97,13 @@ static struct cmd_handler handlers[] = {
|
||||||
{ "bar", cmd_bar },
|
{ "bar", cmd_bar },
|
||||||
{ "bindcode", cmd_bindcode },
|
{ "bindcode", cmd_bindcode },
|
||||||
{ "bindsym", cmd_bindsym },
|
{ "bindsym", cmd_bindsym },
|
||||||
|
{ "client.focused", cmd_client_focused },
|
||||||
|
{ "client.focused_inactive", cmd_client_focused_inactive },
|
||||||
|
{ "client.unfocused", cmd_client_unfocused },
|
||||||
|
{ "client.urgent", cmd_client_urgent },
|
||||||
{ "exec", cmd_exec },
|
{ "exec", cmd_exec },
|
||||||
{ "exec_always", cmd_exec_always },
|
{ "exec_always", cmd_exec_always },
|
||||||
|
{ "default_border", cmd_default_border },
|
||||||
{ "focus_follows_mouse", cmd_focus_follows_mouse },
|
{ "focus_follows_mouse", cmd_focus_follows_mouse },
|
||||||
{ "for_window", cmd_for_window },
|
{ "for_window", cmd_for_window },
|
||||||
{ "fullscreen", cmd_fullscreen },
|
{ "fullscreen", cmd_fullscreen },
|
||||||
|
@ -162,6 +167,7 @@ static struct cmd_handler config_handlers[] = {
|
||||||
|
|
||||||
/* Runtime-only commands. Keep alphabetized */
|
/* Runtime-only commands. Keep alphabetized */
|
||||||
static struct cmd_handler command_handlers[] = {
|
static struct cmd_handler command_handlers[] = {
|
||||||
|
{ "border", cmd_border },
|
||||||
{ "exit", cmd_exit },
|
{ "exit", cmd_exit },
|
||||||
{ "focus", cmd_focus },
|
{ "focus", cmd_focus },
|
||||||
{ "kill", cmd_kill },
|
{ "kill", cmd_kill },
|
||||||
|
|
41
sway/commands/border.c
Normal file
41
sway/commands/border.c
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#include "log.h"
|
||||||
|
#include "sway/commands.h"
|
||||||
|
#include "sway/config.h"
|
||||||
|
#include "sway/tree/container.h"
|
||||||
|
#include "sway/tree/view.h"
|
||||||
|
|
||||||
|
struct cmd_results *cmd_border(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "border", EXPECTED_AT_LEAST, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sway_container *container =
|
||||||
|
config->handler_context.current_container;
|
||||||
|
if (container->type != C_VIEW) {
|
||||||
|
return cmd_results_new(CMD_INVALID, "border",
|
||||||
|
"Only views can have borders");
|
||||||
|
}
|
||||||
|
struct sway_view *view = container->sway_view;
|
||||||
|
|
||||||
|
if (strcmp(argv[0], "none") == 0) {
|
||||||
|
view->border = B_NONE;
|
||||||
|
} else if (strcmp(argv[0], "normal") == 0) {
|
||||||
|
view->border = B_NORMAL;
|
||||||
|
} else if (strcmp(argv[0], "pixel") == 0) {
|
||||||
|
view->border = B_PIXEL;
|
||||||
|
if (argc == 2) {
|
||||||
|
view->border_thickness = atoi(argv[1]);
|
||||||
|
}
|
||||||
|
} else if (strcmp(argv[0], "toggle") == 0) {
|
||||||
|
view->border = (view->border + 1) % 3;
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, "border",
|
||||||
|
"Expected 'border <none|normal|pixel|toggle>' "
|
||||||
|
"or 'border pixel <px>'");
|
||||||
|
}
|
||||||
|
|
||||||
|
view_autoconfigure(view);
|
||||||
|
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
79
sway/commands/client.c
Normal file
79
sway/commands/client.c
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
#include "log.h"
|
||||||
|
#include "sway/commands.h"
|
||||||
|
#include "sway/config.h"
|
||||||
|
#include "sway/tree/container.h"
|
||||||
|
|
||||||
|
static bool parse_color(char *hexstring, float (*dest)[4]) {
|
||||||
|
if (hexstring[0] != '#') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(hexstring) != 7) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
++hexstring;
|
||||||
|
char *end;
|
||||||
|
uint32_t decimal = strtol(hexstring, &end, 16);
|
||||||
|
|
||||||
|
if (*end != '\0') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*dest)[0] = ((decimal >> 16) & 0xff) / 255.0;
|
||||||
|
(*dest)[1] = ((decimal >> 8) & 0xff) / 255.0;
|
||||||
|
(*dest)[2] = (decimal & 0xff) / 255.0;
|
||||||
|
(*dest)[3] = 1.0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cmd_results *handle_command(int argc, char **argv,
|
||||||
|
struct border_colors *class, char *cmd_name) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 5))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parse_color(argv[0], &class->border)) {
|
||||||
|
return cmd_results_new(CMD_INVALID, cmd_name,
|
||||||
|
"Unable to parse border color");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parse_color(argv[1], &class->background)) {
|
||||||
|
return cmd_results_new(CMD_INVALID, cmd_name,
|
||||||
|
"Unable to parse background color");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parse_color(argv[2], &class->text)) {
|
||||||
|
return cmd_results_new(CMD_INVALID, cmd_name,
|
||||||
|
"Unable to parse text color");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parse_color(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)) {
|
||||||
|
return cmd_results_new(CMD_INVALID, cmd_name,
|
||||||
|
"Unable to parse child border color");
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cmd_results *cmd_client_focused(int argc, char **argv) {
|
||||||
|
return handle_command(argc, argv, &config->border_colors.focused, "client.focused");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cmd_results *cmd_client_focused_inactive(int argc, char **argv) {
|
||||||
|
return handle_command(argc, argv, &config->border_colors.focused_inactive, "client.focused_inactive");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cmd_results *cmd_client_unfocused(int argc, char **argv) {
|
||||||
|
return handle_command(argc, argv, &config->border_colors.unfocused, "client.unfocused");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cmd_results *cmd_client_urgent(int argc, char **argv) {
|
||||||
|
return handle_command(argc, argv, &config->border_colors.urgent, "client.urgent");
|
||||||
|
}
|
27
sway/commands/default_border.c
Normal file
27
sway/commands/default_border.c
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#include "log.h"
|
||||||
|
#include "sway/commands.h"
|
||||||
|
#include "sway/config.h"
|
||||||
|
#include "sway/tree/container.h"
|
||||||
|
|
||||||
|
struct cmd_results *cmd_default_border(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "default_border", EXPECTED_AT_LEAST, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(argv[0], "none") == 0) {
|
||||||
|
config->border = B_NONE;
|
||||||
|
} else if (strcmp(argv[0], "normal") == 0) {
|
||||||
|
config->border = B_NORMAL;
|
||||||
|
} else if (strcmp(argv[0], "pixel") == 0) {
|
||||||
|
config->border = B_PIXEL;
|
||||||
|
if (argc == 2) {
|
||||||
|
config->border_thickness = atoi(argv[1]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, "default_border",
|
||||||
|
"Expected 'default_border <none|normal|pixel>' or 'default_border pixel <px>'");
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
|
@ -130,6 +130,13 @@ static void destroy_removed_seats(struct sway_config *old_config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_color(float (*dest)[4], uint32_t color) {
|
||||||
|
(*dest)[0] = ((color >> 16) & 0xff) / 255.0;
|
||||||
|
(*dest)[1] = ((color >> 8) & 0xff) / 255.0;
|
||||||
|
(*dest)[2] = (color & 0xff) / 255.0;
|
||||||
|
(*dest)[3] = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
static void config_defaults(struct sway_config *config) {
|
static void config_defaults(struct sway_config *config) {
|
||||||
if (!(config->symbols = create_list())) goto cleanup;
|
if (!(config->symbols = create_list())) goto cleanup;
|
||||||
if (!(config->modes = create_list())) goto cleanup;
|
if (!(config->modes = create_list())) goto cleanup;
|
||||||
|
@ -162,7 +169,6 @@ 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;
|
||||||
// TODO: border
|
|
||||||
//config->font_height = get_font_text_height(config->font);
|
//config->font_height = get_font_text_height(config->font);
|
||||||
|
|
||||||
// floating view
|
// floating view
|
||||||
|
@ -199,37 +205,38 @@ static void config_defaults(struct sway_config *config) {
|
||||||
config->hide_edge_borders = E_NONE;
|
config->hide_edge_borders = E_NONE;
|
||||||
|
|
||||||
// border colors
|
// border colors
|
||||||
config->border_colors.focused.border = 0x4C7899FF;
|
set_color(&config->border_colors.focused.border, 0x4C7899);
|
||||||
config->border_colors.focused.background = 0x285577FF;
|
set_color(&config->border_colors.focused.border, 0x4C7899);
|
||||||
config->border_colors.focused.text = 0xFFFFFFFF;
|
set_color(&config->border_colors.focused.background, 0x285577);
|
||||||
config->border_colors.focused.indicator = 0x2E9EF4FF;
|
set_color(&config->border_colors.focused.text, 0xFFFFFF);
|
||||||
config->border_colors.focused.child_border = 0x285577FF;
|
set_color(&config->border_colors.focused.indicator, 0x2E9EF4);
|
||||||
|
set_color(&config->border_colors.focused.child_border, 0x285577);
|
||||||
|
|
||||||
config->border_colors.focused_inactive.border = 0x333333FF;
|
set_color(&config->border_colors.focused_inactive.border, 0x333333);
|
||||||
config->border_colors.focused_inactive.background = 0x5F676AFF;
|
set_color(&config->border_colors.focused_inactive.background, 0x5F676A);
|
||||||
config->border_colors.focused_inactive.text = 0xFFFFFFFF;
|
set_color(&config->border_colors.focused_inactive.text, 0xFFFFFF);
|
||||||
config->border_colors.focused_inactive.indicator = 0x484E50FF;
|
set_color(&config->border_colors.focused_inactive.indicator, 0x484E50);
|
||||||
config->border_colors.focused_inactive.child_border = 0x5F676AFF;
|
set_color(&config->border_colors.focused_inactive.child_border, 0x5F676A);
|
||||||
|
|
||||||
config->border_colors.unfocused.border = 0x333333FF;
|
set_color(&config->border_colors.unfocused.border, 0x333333);
|
||||||
config->border_colors.unfocused.background = 0x222222FF;
|
set_color(&config->border_colors.unfocused.background, 0x222222);
|
||||||
config->border_colors.unfocused.text = 0x888888FF;
|
set_color(&config->border_colors.unfocused.text, 0x888888);
|
||||||
config->border_colors.unfocused.indicator = 0x292D2EFF;
|
set_color(&config->border_colors.unfocused.indicator, 0x292D2E);
|
||||||
config->border_colors.unfocused.child_border = 0x222222FF;
|
set_color(&config->border_colors.unfocused.child_border, 0x222222);
|
||||||
|
|
||||||
config->border_colors.urgent.border = 0x2F343AFF;
|
set_color(&config->border_colors.urgent.border, 0x2F343A);
|
||||||
config->border_colors.urgent.background = 0x900000FF;
|
set_color(&config->border_colors.urgent.background, 0x900000);
|
||||||
config->border_colors.urgent.text = 0xFFFFFFFF;
|
set_color(&config->border_colors.urgent.text, 0xFFFFFF);
|
||||||
config->border_colors.urgent.indicator = 0x900000FF;
|
set_color(&config->border_colors.urgent.indicator, 0x900000);
|
||||||
config->border_colors.urgent.child_border = 0x900000FF;
|
set_color(&config->border_colors.urgent.child_border, 0x900000);
|
||||||
|
|
||||||
config->border_colors.placeholder.border = 0x000000FF;
|
set_color(&config->border_colors.placeholder.border, 0x000000);
|
||||||
config->border_colors.placeholder.background = 0x0C0C0CFF;
|
set_color(&config->border_colors.placeholder.background, 0x0C0C0C);
|
||||||
config->border_colors.placeholder.text = 0xFFFFFFFF;
|
set_color(&config->border_colors.placeholder.text, 0xFFFFFF);
|
||||||
config->border_colors.placeholder.indicator = 0x000000FF;
|
set_color(&config->border_colors.placeholder.indicator, 0x000000);
|
||||||
config->border_colors.placeholder.child_border = 0x0C0C0CFF;
|
set_color(&config->border_colors.placeholder.child_border, 0x0C0C0C);
|
||||||
|
|
||||||
config->border_colors.background = 0xFFFFFFFF;
|
set_color(&config->border_colors.background, 0xFFFFFF);
|
||||||
|
|
||||||
// Security
|
// Security
|
||||||
if (!(config->command_policies = create_list())) goto cleanup;
|
if (!(config->command_policies = create_list())) goto cleanup;
|
||||||
|
|
|
@ -116,8 +116,8 @@ static void surface_for_each_surface(struct wlr_surface *surface,
|
||||||
static void output_view_for_each_surface(struct sway_view *view,
|
static void output_view_for_each_surface(struct sway_view *view,
|
||||||
struct root_geometry *geo, wlr_surface_iterator_func_t iterator,
|
struct root_geometry *geo, wlr_surface_iterator_func_t iterator,
|
||||||
void *user_data) {
|
void *user_data) {
|
||||||
geo->x = view->swayc->x;
|
geo->x = view->x;
|
||||||
geo->y = view->swayc->y;
|
geo->y = view->y;
|
||||||
geo->width = view->surface->current->width;
|
geo->width = view->surface->current->width;
|
||||||
geo->height = view->surface->current->height;
|
geo->height = view->surface->current->height;
|
||||||
geo->rotation = 0; // TODO
|
geo->rotation = 0; // TODO
|
||||||
|
@ -217,23 +217,198 @@ static void render_unmanaged(struct sway_output *output,
|
||||||
render_surface_iterator, &data);
|
render_surface_iterator, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void render_container_iterator(struct sway_container *con,
|
static void render_view(struct sway_view *view, struct sway_output *output) {
|
||||||
void *_data) {
|
struct render_data data = { .output = output, .alpha = view->swayc->alpha };
|
||||||
struct sway_output *output = _data;
|
output_view_for_each_surface(
|
||||||
if (!sway_assert(con->type == C_VIEW, "expected a view")) {
|
view, &data.root_geo, render_surface_iterator, &data);
|
||||||
return;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 wlr_renderer *renderer =
|
||||||
|
wlr_backend_get_renderer(output->wlr_output->backend);
|
||||||
|
struct wlr_box box;
|
||||||
|
float color[4];
|
||||||
|
color[3] = con->alpha;
|
||||||
|
|
||||||
|
// Child border - left edge
|
||||||
|
memcpy(&color, colors->child_border, sizeof(float) * 3);
|
||||||
|
box.x = con->x;
|
||||||
|
box.y = con->y + 1;
|
||||||
|
box.width = con->sway_view->border_thickness;
|
||||||
|
box.height = con->height - 1;
|
||||||
|
wlr_render_rect(renderer, &box, color,
|
||||||
|
output->wlr_output->transform_matrix);
|
||||||
|
|
||||||
|
// Child border - right edge
|
||||||
|
box.x = con->x + con->width - con->sway_view->border_thickness;
|
||||||
|
box.y = con->y + 1;
|
||||||
|
box.width = con->sway_view->border_thickness;
|
||||||
|
box.height = con->height - 1;
|
||||||
|
wlr_render_rect(renderer, &box, color,
|
||||||
|
output->wlr_output->transform_matrix);
|
||||||
|
|
||||||
|
// Child border - bottom edge
|
||||||
|
box.x = con->x;
|
||||||
|
box.y = con->y + con->height - con->sway_view->border_thickness;
|
||||||
|
box.width = con->width;
|
||||||
|
box.height = con->sway_view->border_thickness;
|
||||||
|
wlr_render_rect(renderer, &box, color,
|
||||||
|
output->wlr_output->transform_matrix);
|
||||||
|
|
||||||
|
// Single pixel bar above title
|
||||||
|
memcpy(&color, colors->border, sizeof(float) * 3);
|
||||||
|
box.x = con->x;
|
||||||
|
box.y = con->y;
|
||||||
|
box.width = con->width;
|
||||||
|
box.height = 1;
|
||||||
|
wlr_render_rect(renderer, &box, color,
|
||||||
|
output->wlr_output->transform_matrix);
|
||||||
|
|
||||||
|
// Single pixel bar below title
|
||||||
|
box.x = con->x + con->sway_view->border_thickness;
|
||||||
|
box.y = con->sway_view->y - 1;
|
||||||
|
box.width = con->width - con->sway_view->border_thickness * 2;
|
||||||
|
box.height = 1;
|
||||||
|
wlr_render_rect(renderer, &box, color,
|
||||||
|
output->wlr_output->transform_matrix);
|
||||||
|
|
||||||
|
// Title background
|
||||||
|
memcpy(&color, colors->background, sizeof(float) * 3);
|
||||||
|
box.x = con->x + con->sway_view->border_thickness;
|
||||||
|
box.y = con->y + 1;
|
||||||
|
box.width = con->width - con->sway_view->border_thickness * 2;
|
||||||
|
box.height = con->sway_view->y - con->y - 2;
|
||||||
|
wlr_render_rect(renderer, &box, color,
|
||||||
|
output->wlr_output->transform_matrix);
|
||||||
|
|
||||||
|
// Title text
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render decorations for a view with "border pixel".
|
||||||
|
*/
|
||||||
|
static void render_container_simple_border_pixel(struct sway_output *output,
|
||||||
|
struct sway_container *con, struct border_colors *colors) {
|
||||||
|
struct wlr_renderer *renderer =
|
||||||
|
wlr_backend_get_renderer(output->wlr_output->backend);
|
||||||
|
struct wlr_box box;
|
||||||
|
float color[4];
|
||||||
|
color[3] = con->alpha;
|
||||||
|
|
||||||
|
// Child border - left edge
|
||||||
|
memcpy(&color, colors->child_border, sizeof(float) * 3);
|
||||||
|
box.x = con->x;
|
||||||
|
box.y = con->y;
|
||||||
|
box.width = con->sway_view->border_thickness;
|
||||||
|
box.height = con->height;
|
||||||
|
wlr_render_rect(renderer, &box, color,
|
||||||
|
output->wlr_output->transform_matrix);
|
||||||
|
|
||||||
|
// Child border - right edge
|
||||||
|
box.x = con->x + con->width - con->sway_view->border_thickness;
|
||||||
|
box.y = con->y;
|
||||||
|
box.width = con->sway_view->border_thickness;
|
||||||
|
box.height = con->height;
|
||||||
|
wlr_render_rect(renderer, &box, color,
|
||||||
|
output->wlr_output->transform_matrix);
|
||||||
|
|
||||||
|
// Child border - top edge
|
||||||
|
box.x = con->x;
|
||||||
|
box.y = con->y;
|
||||||
|
box.width = con->width;
|
||||||
|
box.height = con->sway_view->border_thickness;
|
||||||
|
wlr_render_rect(renderer, &box, color,
|
||||||
|
output->wlr_output->transform_matrix);
|
||||||
|
|
||||||
|
// Child border - bottom edge
|
||||||
|
box.x = con->x;
|
||||||
|
box.y = con->y + con->height - con->sway_view->border_thickness;
|
||||||
|
box.width = con->width;
|
||||||
|
box.height = con->sway_view->border_thickness;
|
||||||
|
wlr_render_rect(renderer, &box, color,
|
||||||
|
output->wlr_output->transform_matrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void render_container(struct sway_output *output,
|
||||||
|
struct sway_container *con);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render a container's children using a L_HORIZ or L_VERT layout.
|
||||||
|
*
|
||||||
|
* Wrap child views in borders and leave child containers borderless because
|
||||||
|
* they'll apply their own borders to their children.
|
||||||
|
*/
|
||||||
|
static void render_container_simple(struct sway_output *output,
|
||||||
|
struct sway_container *con) {
|
||||||
|
struct sway_seat *seat = input_manager_current_seat(input_manager);
|
||||||
|
struct sway_container *focus = seat_get_focus(seat);
|
||||||
|
|
||||||
|
for (int i = 0; i < con->children->length; ++i) {
|
||||||
|
struct sway_container *child = con->children->items[i];
|
||||||
|
|
||||||
|
if (child->type == C_VIEW) {
|
||||||
|
if (child->sway_view->border != B_NONE) {
|
||||||
|
struct border_colors *colors;
|
||||||
|
if (focus == child) {
|
||||||
|
colors = &config->border_colors.focused;
|
||||||
|
} else if (seat_get_focus_inactive(seat, con) == child) {
|
||||||
|
colors = &config->border_colors.focused_inactive;
|
||||||
|
} else {
|
||||||
|
colors = &config->border_colors.unfocused;
|
||||||
}
|
}
|
||||||
struct render_data data = { .output = output, .alpha = con->alpha };
|
|
||||||
output_view_for_each_surface(con->sway_view, &data.root_geo,
|
if (child->sway_view->border == B_NORMAL) {
|
||||||
render_surface_iterator, &data);
|
render_container_simple_border_normal(output, child,
|
||||||
|
colors);
|
||||||
|
} else {
|
||||||
|
render_container_simple_border_pixel(output, child, colors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render_view(child->sway_view, output);
|
||||||
|
} else {
|
||||||
|
render_container(output, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render a container's children using the L_TABBED layout.
|
||||||
|
*/
|
||||||
|
static void render_container_tabbed(struct sway_output *output,
|
||||||
|
struct sway_container *con) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render a container's children using the L_STACKED layout.
|
||||||
|
*/
|
||||||
|
static void render_container_stacked(struct sway_output *output,
|
||||||
|
struct sway_container *con) {
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
static void render_container(struct sway_output *output,
|
static void render_container(struct sway_output *output,
|
||||||
struct sway_container *con) {
|
struct sway_container *con) {
|
||||||
if (con->type == C_VIEW) { // Happens if a view is fullscreened
|
switch (con->layout) {
|
||||||
render_container_iterator(con, output);
|
case L_NONE:
|
||||||
} else {
|
case L_HORIZ:
|
||||||
container_descendants(con, C_VIEW, render_container_iterator, output);
|
case L_VERT:
|
||||||
|
render_container_simple(output, con);
|
||||||
|
break;
|
||||||
|
case L_STACKED:
|
||||||
|
render_container_stacked(output, con);
|
||||||
|
break;
|
||||||
|
case L_TABBED:
|
||||||
|
render_container_tabbed(output, con);
|
||||||
|
break;
|
||||||
|
case L_FLOATING:
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +457,7 @@ static void render_output(struct sway_output *output, struct timespec *when,
|
||||||
float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
|
float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
wlr_renderer_clear(renderer, clear_color);
|
wlr_renderer_clear(renderer, clear_color);
|
||||||
// TODO: handle views smaller than the output
|
// TODO: handle views smaller than the output
|
||||||
render_container(output, workspace->sway_workspace->fullscreen->swayc);
|
render_view(workspace->sway_workspace->fullscreen, output);
|
||||||
|
|
||||||
if (workspace->sway_workspace->fullscreen->type == SWAY_VIEW_XWAYLAND) {
|
if (workspace->sway_workspace->fullscreen->type == SWAY_VIEW_XWAYLAND) {
|
||||||
render_unmanaged(output,
|
render_unmanaged(output,
|
||||||
|
|
|
@ -40,7 +40,6 @@ static void configure(struct sway_view *view, double ox, double oy, int width,
|
||||||
if (wl_shell_view == NULL) {
|
if (wl_shell_view == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
view_update_position(view, ox, oy);
|
|
||||||
wl_shell_view->pending_width = width;
|
wl_shell_view->pending_width = width;
|
||||||
wl_shell_view->pending_height = height;
|
wl_shell_view->pending_height = height;
|
||||||
wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height);
|
wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height);
|
||||||
|
|
|
@ -102,7 +102,6 @@ static void configure(struct sway_view *view, double ox, double oy, int width,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
view_update_position(view, ox, oy);
|
|
||||||
xdg_shell_v6_view->pending_width = width;
|
xdg_shell_v6_view->pending_width = width;
|
||||||
xdg_shell_v6_view->pending_height = height;
|
xdg_shell_v6_view->pending_height = height;
|
||||||
wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height);
|
wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height);
|
||||||
|
|
|
@ -163,8 +163,6 @@ static void configure(struct sway_view *view, double ox, double oy, int width,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
view_update_position(view, ox, oy);
|
|
||||||
|
|
||||||
xwayland_view->pending_width = width;
|
xwayland_view->pending_width = width;
|
||||||
xwayland_view->pending_height = height;
|
xwayland_view->pending_height = height;
|
||||||
wlr_xwayland_surface_configure(xsurface, ox + loutput->x, oy + loutput->y,
|
wlr_xwayland_surface_configure(xsurface, ox + loutput->x, oy + loutput->y,
|
||||||
|
|
|
@ -29,6 +29,9 @@ sway_sources = files(
|
||||||
'commands/assign.c',
|
'commands/assign.c',
|
||||||
'commands/bar.c',
|
'commands/bar.c',
|
||||||
'commands/bind.c',
|
'commands/bind.c',
|
||||||
|
'commands/border.c',
|
||||||
|
'commands/client.c',
|
||||||
|
'commands/default_border.c',
|
||||||
'commands/default_orientation.c',
|
'commands/default_orientation.c',
|
||||||
'commands/exit.c',
|
'commands/exit.c',
|
||||||
'commands/exec.c',
|
'commands/exec.c',
|
||||||
|
|
|
@ -174,12 +174,7 @@ void arrange_children_of(struct sway_container *parent) {
|
||||||
}
|
}
|
||||||
if (workspace->sway_workspace->fullscreen) {
|
if (workspace->sway_workspace->fullscreen) {
|
||||||
// Just arrange the fullscreen view and jump out
|
// Just arrange the fullscreen view and jump out
|
||||||
struct sway_container *view =
|
view_autoconfigure(workspace->sway_workspace->fullscreen);
|
||||||
workspace->sway_workspace->fullscreen->swayc;
|
|
||||||
view_configure(view->sway_view, 0, 0,
|
|
||||||
workspace->parent->width, workspace->parent->height);
|
|
||||||
view->width = workspace->parent->width;
|
|
||||||
view->height = workspace->parent->height;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,8 +199,7 @@ void arrange_children_of(struct sway_container *parent) {
|
||||||
for (int i = 0; i < parent->children->length; ++i) {
|
for (int i = 0; i < parent->children->length; ++i) {
|
||||||
struct sway_container *child = parent->children->items[i];
|
struct sway_container *child = parent->children->items[i];
|
||||||
if (child->type == C_VIEW) {
|
if (child->type == C_VIEW) {
|
||||||
view_configure(child->sway_view, child->x, child->y,
|
view_autoconfigure(child->sway_view);
|
||||||
child->width, child->height);
|
|
||||||
} else {
|
} else {
|
||||||
arrange_children_of(child);
|
arrange_children_of(child);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
|
#include <wlr/render/wlr_renderer.h>
|
||||||
#include <wlr/types/wlr_output_layout.h>
|
#include <wlr/types/wlr_output_layout.h>
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "sway/criteria.h"
|
#include "sway/criteria.h"
|
||||||
|
@ -73,6 +74,51 @@ void view_configure(struct sway_view *view, double ox, double oy, int width,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the view's position and size based on the swayc's position and
|
||||||
|
* size, taking borders into consideration.
|
||||||
|
*/
|
||||||
|
void view_autoconfigure(struct sway_view *view) {
|
||||||
|
if (!sway_assert(view->swayc,
|
||||||
|
"Called view_autoconfigure() on a view without a swayc")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (view->is_fullscreen) {
|
||||||
|
struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
|
||||||
|
view_configure(view, 0, 0, output->width, output->height);
|
||||||
|
view->x = view->y = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double x, y, width, height;
|
||||||
|
switch (view->border) {
|
||||||
|
case B_NONE:
|
||||||
|
x = view->swayc->x;
|
||||||
|
y = view->swayc->y;
|
||||||
|
width = view->swayc->width;
|
||||||
|
height = view->swayc->height;
|
||||||
|
break;
|
||||||
|
case B_PIXEL:
|
||||||
|
x = view->swayc->x + view->border_thickness;
|
||||||
|
y = view->swayc->y + view->border_thickness;
|
||||||
|
width = view->swayc->width - view->border_thickness * 2;
|
||||||
|
height = view->swayc->height - view->border_thickness * 2;
|
||||||
|
break;
|
||||||
|
case B_NORMAL:
|
||||||
|
// TODO: Size the title bar by checking the font
|
||||||
|
x = view->swayc->x + view->border_thickness;
|
||||||
|
y = view->swayc->y + 20;
|
||||||
|
width = view->swayc->width - view->border_thickness * 2;
|
||||||
|
height = view->swayc->height - view->border_thickness - 20;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
view->x = x;
|
||||||
|
view->y = y;
|
||||||
|
view_configure(view, x, y, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
void view_set_activated(struct sway_view *view, bool activated) {
|
void view_set_activated(struct sway_view *view, bool activated) {
|
||||||
if (view->impl->set_activated) {
|
if (view->impl->set_activated) {
|
||||||
view->impl->set_activated(view, activated);
|
view->impl->set_activated(view, activated);
|
||||||
|
@ -262,6 +308,8 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
|
||||||
|
|
||||||
view->surface = wlr_surface;
|
view->surface = wlr_surface;
|
||||||
view->swayc = cont;
|
view->swayc = cont;
|
||||||
|
view->border = config->border;
|
||||||
|
view->border_thickness = config->border_thickness;
|
||||||
|
|
||||||
view_init_subsurfaces(view, wlr_surface);
|
view_init_subsurfaces(view, wlr_surface);
|
||||||
wl_signal_add(&wlr_surface->events.new_subsurface,
|
wl_signal_add(&wlr_surface->events.new_subsurface,
|
||||||
|
@ -305,23 +353,13 @@ void view_unmap(struct sway_view *view) {
|
||||||
arrange_children_of(parent);
|
arrange_children_of(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void view_update_position(struct sway_view *view, double ox, double oy) {
|
|
||||||
if (view->swayc->x == ox && view->swayc->y == oy) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
view_damage(view, true);
|
|
||||||
view->swayc->x = ox;
|
|
||||||
view->swayc->y = oy;
|
|
||||||
view_damage(view, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void view_update_size(struct sway_view *view, int width, int height) {
|
void view_update_size(struct sway_view *view, int width, int height) {
|
||||||
if (view->width == width && view->height == height) {
|
if (view->width == width && view->height == height) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
view_damage(view, true);
|
view_damage(view, true);
|
||||||
|
// Should we update the swayc width/height here too?
|
||||||
view->width = width;
|
view->width = width;
|
||||||
view->height = height;
|
view->height = height;
|
||||||
view_damage(view, true);
|
view_damage(view, true);
|
||||||
|
|
Loading…
Reference in a new issue