From 630ba30e3c60cfe3f1018b4a1701f0c2a0f6da9a Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Mon, 30 Apr 2018 21:24:13 +1000 Subject: [PATCH] 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 --- include/sway/config.h | 12 +- include/sway/tree/container.h | 2 +- include/sway/tree/view.h | 11 +- sway/commands.c | 6 + sway/commands/border.c | 41 +++++++ sway/commands/client.c | 79 +++++++++++++ sway/commands/default_border.c | 27 +++++ sway/config.c | 71 +++++++----- sway/desktop/output.c | 205 ++++++++++++++++++++++++++++++--- sway/desktop/wl_shell.c | 1 - sway/desktop/xdg_shell_v6.c | 1 - sway/desktop/xwayland.c | 2 - sway/meson.build | 3 + sway/tree/arrange.c | 10 +- sway/tree/view.c | 60 ++++++++-- 15 files changed, 452 insertions(+), 79 deletions(-) create mode 100644 sway/commands/border.c create mode 100644 sway/commands/client.c create mode 100644 sway/commands/default_border.c diff --git a/include/sway/config.h b/include/sway/config.h index 87123289..a0113e98 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -204,11 +204,11 @@ struct bar_config { }; struct border_colors { - uint32_t border; - uint32_t background; - uint32_t text; - uint32_t indicator; - uint32_t child_border; + float border[4]; + float background[4]; + float text[4]; + float indicator[4]; + float child_border[4]; }; enum edge_border_types { @@ -338,7 +338,7 @@ struct sway_config { struct border_colors unfocused; struct border_colors urgent; struct border_colors placeholder; - uint32_t background; + float background[4]; } border_colors; // floating view diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 9c921fc4..d092af49 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -72,8 +72,8 @@ struct sway_container { // For C_ROOT, this has no meaning // For C_OUTPUT, this is the output position in layout coordinates // For other types, this is the position in output-local coordinates + // Includes borders double x, y; - // does not include borders or gaps. double width, height; double saved_width, saved_height; diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index a4ad9971..352a62bc 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -41,9 +41,16 @@ struct sway_view { struct sway_container *swayc; // 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; + bool is_fullscreen; + enum sway_container_border border; + int border_thickness; + union { struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; 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, int height); +void view_autoconfigure(struct sway_view *view); + void view_set_activated(struct sway_view *view, bool activated); 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_update_position(struct sway_view *view, double ox, double oy); - void view_update_size(struct sway_view *view, int width, int height); void view_child_init(struct sway_view_child *child, diff --git a/sway/commands.c b/sway/commands.c index a67bc127..575859c9 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -97,8 +97,13 @@ static struct cmd_handler handlers[] = { { "bar", cmd_bar }, { "bindcode", cmd_bindcode }, { "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_always", cmd_exec_always }, + { "default_border", cmd_default_border }, { "focus_follows_mouse", cmd_focus_follows_mouse }, { "for_window", cmd_for_window }, { "fullscreen", cmd_fullscreen }, @@ -162,6 +167,7 @@ static struct cmd_handler config_handlers[] = { /* Runtime-only commands. Keep alphabetized */ static struct cmd_handler command_handlers[] = { + { "border", cmd_border }, { "exit", cmd_exit }, { "focus", cmd_focus }, { "kill", cmd_kill }, diff --git a/sway/commands/border.c b/sway/commands/border.c new file mode 100644 index 00000000..873abb68 --- /dev/null +++ b/sway/commands/border.c @@ -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 ' " + "or 'border pixel '"); + } + + view_autoconfigure(view); + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/client.c b/sway/commands/client.c new file mode 100644 index 00000000..ce519381 --- /dev/null +++ b/sway/commands/client.c @@ -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"); +} diff --git a/sway/commands/default_border.c b/sway/commands/default_border.c new file mode 100644 index 00000000..fcd2c075 --- /dev/null +++ b/sway/commands/default_border.c @@ -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 ' or 'default_border pixel '"); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/config.c b/sway/config.c index 90b833ab..ed291450 100644 --- a/sway/config.c +++ b/sway/config.c @@ -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) { if (!(config->symbols = 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_orientation = L_NONE; if (!(config->font = strdup("monospace 10"))) goto cleanup; - // TODO: border //config->font_height = get_font_text_height(config->font); // floating view @@ -199,37 +205,38 @@ static void config_defaults(struct sway_config *config) { config->hide_edge_borders = E_NONE; // border colors - config->border_colors.focused.border = 0x4C7899FF; - config->border_colors.focused.background = 0x285577FF; - config->border_colors.focused.text = 0xFFFFFFFF; - config->border_colors.focused.indicator = 0x2E9EF4FF; - config->border_colors.focused.child_border = 0x285577FF; - - config->border_colors.focused_inactive.border = 0x333333FF; - config->border_colors.focused_inactive.background = 0x5F676AFF; - config->border_colors.focused_inactive.text = 0xFFFFFFFF; - config->border_colors.focused_inactive.indicator = 0x484E50FF; - config->border_colors.focused_inactive.child_border = 0x5F676AFF; - - config->border_colors.unfocused.border = 0x333333FF; - config->border_colors.unfocused.background = 0x222222FF; - config->border_colors.unfocused.text = 0x888888FF; - config->border_colors.unfocused.indicator = 0x292D2EFF; - config->border_colors.unfocused.child_border = 0x222222FF; - - config->border_colors.urgent.border = 0x2F343AFF; - config->border_colors.urgent.background = 0x900000FF; - config->border_colors.urgent.text = 0xFFFFFFFF; - config->border_colors.urgent.indicator = 0x900000FF; - config->border_colors.urgent.child_border = 0x900000FF; - - config->border_colors.placeholder.border = 0x000000FF; - config->border_colors.placeholder.background = 0x0C0C0CFF; - config->border_colors.placeholder.text = 0xFFFFFFFF; - config->border_colors.placeholder.indicator = 0x000000FF; - config->border_colors.placeholder.child_border = 0x0C0C0CFF; - - config->border_colors.background = 0xFFFFFFFF; + 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.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.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.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.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.indicator, 0x000000); + set_color(&config->border_colors.placeholder.child_border, 0x0C0C0C); + + set_color(&config->border_colors.background, 0xFFFFFF); // Security if (!(config->command_policies = create_list())) goto cleanup; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index d9ae890f..2511c610 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -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, struct root_geometry *geo, wlr_surface_iterator_func_t iterator, void *user_data) { - geo->x = view->swayc->x; - geo->y = view->swayc->y; + geo->x = view->x; + geo->y = view->y; geo->width = view->surface->current->width; geo->height = view->surface->current->height; geo->rotation = 0; // TODO @@ -217,23 +217,198 @@ static void render_unmanaged(struct sway_output *output, render_surface_iterator, &data); } -static void render_container_iterator(struct sway_container *con, - void *_data) { - struct sway_output *output = _data; - if (!sway_assert(con->type == C_VIEW, "expected a view")) { - return; +static void render_view(struct sway_view *view, struct sway_output *output) { + struct render_data data = { .output = output, .alpha = view->swayc->alpha }; + output_view_for_each_surface( + view, &data.root_geo, render_surface_iterator, &data); +} + +/** + * 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; + } + + if (child->sway_view->border == B_NORMAL) { + 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); + } } - struct render_data data = { .output = output, .alpha = con->alpha }; - output_view_for_each_surface(con->sway_view, &data.root_geo, - render_surface_iterator, &data); +} + +/** + * 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, struct sway_container *con) { - if (con->type == C_VIEW) { // Happens if a view is fullscreened - render_container_iterator(con, output); - } else { - container_descendants(con, C_VIEW, render_container_iterator, output); + switch (con->layout) { + case L_NONE: + case L_HORIZ: + 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}; wlr_renderer_clear(renderer, clear_color); // 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) { render_unmanaged(output, diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 2d666d95..e97a898e 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -40,7 +40,6 @@ static void configure(struct sway_view *view, double ox, double oy, int width, if (wl_shell_view == NULL) { return; } - view_update_position(view, ox, oy); wl_shell_view->pending_width = width; wl_shell_view->pending_height = height; wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height); diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 2aaedd6c..94556231 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -102,7 +102,6 @@ static void configure(struct sway_view *view, double ox, double oy, int width, return; } - view_update_position(view, ox, oy); xdg_shell_v6_view->pending_width = width; xdg_shell_v6_view->pending_height = height; wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index aa9e1797..28f93d6e 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -163,8 +163,6 @@ static void configure(struct sway_view *view, double ox, double oy, int width, return; } - view_update_position(view, ox, oy); - xwayland_view->pending_width = width; xwayland_view->pending_height = height; wlr_xwayland_surface_configure(xsurface, ox + loutput->x, oy + loutput->y, diff --git a/sway/meson.build b/sway/meson.build index 146ad4b8..83e8e656 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -29,6 +29,9 @@ sway_sources = files( 'commands/assign.c', 'commands/bar.c', 'commands/bind.c', + 'commands/border.c', + 'commands/client.c', + 'commands/default_border.c', 'commands/default_orientation.c', 'commands/exit.c', 'commands/exec.c', diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c index e1f3ad13..83bb20fb 100644 --- a/sway/tree/arrange.c +++ b/sway/tree/arrange.c @@ -174,12 +174,7 @@ void arrange_children_of(struct sway_container *parent) { } if (workspace->sway_workspace->fullscreen) { // Just arrange the fullscreen view and jump out - struct sway_container *view = - 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; + view_autoconfigure(workspace->sway_workspace->fullscreen); return; } @@ -204,8 +199,7 @@ void arrange_children_of(struct sway_container *parent) { for (int i = 0; i < parent->children->length; ++i) { struct sway_container *child = parent->children->items[i]; if (child->type == C_VIEW) { - view_configure(child->sway_view, child->x, child->y, - child->width, child->height); + view_autoconfigure(child->sway_view); } else { arrange_children_of(child); } diff --git a/sway/tree/view.c b/sway/tree/view.c index 519c3c78..26902c23 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1,5 +1,6 @@ #include #include +#include #include #include "log.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) { if (view->impl->set_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->swayc = cont; + view->border = config->border; + view->border_thickness = config->border_thickness; view_init_subsurfaces(view, wlr_surface); wl_signal_add(&wlr_surface->events.new_subsurface, @@ -309,23 +357,13 @@ void view_unmap(struct sway_view *view) { } } -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) { if (view->width == width && view->height == height) { return; } view_damage(view, true); + // Should we update the swayc width/height here too? view->width = width; view->height = height; view_damage(view, true);