From e67f3543332349e63b5099a241fdd85ce28ea54b Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Mon, 30 Apr 2018 21:24:13 +1000 Subject: [PATCH 01/17] 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 e0aa6c0c..26e1a108 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, @@ -305,23 +353,13 @@ void view_unmap(struct sway_view *view) { 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) { 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); From abcad0ece9290233652832de17b3ad3e13263c29 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 1 May 2018 17:36:12 +1000 Subject: [PATCH 02/17] Move docblock and fix indenting of switch/case. --- include/sway/tree/view.h | 4 ++++ sway/tree/view.c | 42 ++++++++++++++++++---------------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 352a62bc..4395e94a 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -167,6 +167,10 @@ const char *view_get_instance(struct sway_view *view); void view_configure(struct sway_view *view, double ox, double oy, int width, int height); +/** + * 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); void view_set_activated(struct sway_view *view, bool activated); diff --git a/sway/tree/view.c b/sway/tree/view.c index 26e1a108..7d493af9 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -74,10 +74,6 @@ 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")) { @@ -93,25 +89,25 @@ void view_autoconfigure(struct sway_view *view) { 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; + 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; From 2ceed512a82dbfdcf34305969c6d429cf0961816 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 1 May 2018 18:23:40 +1000 Subject: [PATCH 03/17] Fix surface offset when using borders --- sway/tree/container.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 03d7e49c..cb0233db 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -423,8 +423,8 @@ struct sway_container *container_at(struct sway_container *parent, soutput->sway_output->wlr_output); double ox = lx - output_box->x; double oy = ly - output_box->y; - double view_sx = ox - swayc->x; - double view_sy = oy - swayc->y; + double view_sx = ox - sview->x; + double view_sy = oy - sview->y; double _sx, _sy; struct wlr_surface *_surface; From d847ac1120b87bfe0ac5747964a1299cabd3bc19 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 1 May 2018 18:35:58 +1000 Subject: [PATCH 04/17] Scale borders according to output scale --- sway/desktop/output.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 2511c610..498a3a2e 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -240,6 +240,7 @@ static void render_container_simple_border_normal(struct sway_output *output, box.y = con->y + 1; box.width = con->sway_view->border_thickness; box.height = con->height - 1; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -248,6 +249,7 @@ static void render_container_simple_border_normal(struct sway_output *output, box.y = con->y + 1; box.width = con->sway_view->border_thickness; box.height = con->height - 1; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -256,6 +258,7 @@ static void render_container_simple_border_normal(struct sway_output *output, box.y = con->y + con->height - con->sway_view->border_thickness; box.width = con->width; box.height = con->sway_view->border_thickness; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -265,6 +268,7 @@ static void render_container_simple_border_normal(struct sway_output *output, box.y = con->y; box.width = con->width; box.height = 1; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -273,6 +277,7 @@ static void render_container_simple_border_normal(struct sway_output *output, box.y = con->sway_view->y - 1; box.width = con->width - con->sway_view->border_thickness * 2; box.height = 1; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -282,6 +287,7 @@ static void render_container_simple_border_normal(struct sway_output *output, box.y = con->y + 1; box.width = con->width - con->sway_view->border_thickness * 2; box.height = con->sway_view->y - con->y - 2; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -306,6 +312,7 @@ static void render_container_simple_border_pixel(struct sway_output *output, box.y = con->y; box.width = con->sway_view->border_thickness; box.height = con->height; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -314,6 +321,7 @@ static void render_container_simple_border_pixel(struct sway_output *output, box.y = con->y; box.width = con->sway_view->border_thickness; box.height = con->height; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -322,6 +330,7 @@ static void render_container_simple_border_pixel(struct sway_output *output, box.y = con->y; box.width = con->width; box.height = con->sway_view->border_thickness; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -330,6 +339,7 @@ static void render_container_simple_border_pixel(struct sway_output *output, box.y = con->y + con->height - con->sway_view->border_thickness; box.width = con->width; box.height = con->sway_view->border_thickness; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); } From a19a511b90d214f200bfca1cffad0376b855caac Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 1 May 2018 19:21:29 +1000 Subject: [PATCH 05/17] Implement indicator border --- sway/desktop/output.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 498a3a2e..e0a211d1 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -245,6 +245,11 @@ static void render_container_simple_border_normal(struct sway_output *output, output->wlr_output->transform_matrix); // Child border - right edge + if (con->parent->children->length == 1 && con->parent->layout == L_HORIZ) { + memcpy(&color, colors->indicator, sizeof(float) * 3); + } else { + memcpy(&color, colors->child_border, sizeof(float) * 3); + } box.x = con->x + con->width - con->sway_view->border_thickness; box.y = con->y + 1; box.width = con->sway_view->border_thickness; @@ -254,6 +259,11 @@ static void render_container_simple_border_normal(struct sway_output *output, output->wlr_output->transform_matrix); // Child border - bottom edge + if (con->parent->children->length == 1 && con->parent->layout == L_VERT) { + memcpy(&color, colors->indicator, sizeof(float) * 3); + } else { + memcpy(&color, colors->child_border, sizeof(float) * 3); + } box.x = con->x; box.y = con->y + con->height - con->sway_view->border_thickness; box.width = con->width; @@ -317,6 +327,11 @@ static void render_container_simple_border_pixel(struct sway_output *output, output->wlr_output->transform_matrix); // Child border - right edge + if (con->parent->children->length == 1 && con->parent->layout == L_HORIZ) { + memcpy(&color, colors->indicator, sizeof(float) * 3); + } else { + memcpy(&color, colors->child_border, sizeof(float) * 3); + } box.x = con->x + con->width - con->sway_view->border_thickness; box.y = con->y; box.width = con->sway_view->border_thickness; @@ -335,6 +350,11 @@ static void render_container_simple_border_pixel(struct sway_output *output, output->wlr_output->transform_matrix); // Child border - bottom edge + if (con->parent->children->length == 1 && con->parent->layout == L_VERT) { + memcpy(&color, colors->indicator, sizeof(float) * 3); + } else { + memcpy(&color, colors->child_border, sizeof(float) * 3); + } box.x = con->x; box.y = con->y + con->height - con->sway_view->border_thickness; box.width = con->width; From 19d6cc395dfcb73fa7fc70a0691a38005afc334f Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 1 May 2018 19:50:54 +1000 Subject: [PATCH 06/17] Allow clicking view decorations to focus view --- sway/tree/container.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sway/tree/container.c b/sway/tree/container.c index cb0233db..995da5ce 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -455,6 +455,16 @@ struct sway_container *container_at(struct sway_container *parent, *surface = _surface; return swayc; } + // Check the view's decorations + struct wlr_box swayc_box = { + .x = swayc->x, + .y = swayc->y, + .width = swayc->width, + .height = swayc->height, + }; + if (wlr_box_contains_point(&swayc_box, ox, oy)) { + return swayc; + } } else { list_cat(queue, swayc->children); } From 6ef14e99eec0d741104be3a1483b7e92de870c96 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 1 May 2018 19:59:36 +1000 Subject: [PATCH 07/17] Restore view_update_position() --- include/sway/tree/view.h | 2 ++ sway/tree/view.c | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 4395e94a..21127ab1 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -197,6 +197,8 @@ 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/tree/view.c b/sway/tree/view.c index 7d493af9..80949c89 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -349,6 +349,19 @@ void view_unmap(struct sway_view *view) { 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; + } + + // TODO: Only allow this if the view is floating (this function will only be + // called in response to wayland clients wanting to reposition themselves). + 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; From 630ba30e3c60cfe3f1018b4a1701f0c2a0f6da9a Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Mon, 30 Apr 2018 21:24:13 +1000 Subject: [PATCH 08/17] 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); From fa5de2876e3e8db4966d3404f01ba9600204d75b Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 1 May 2018 17:36:12 +1000 Subject: [PATCH 09/17] Move docblock and fix indenting of switch/case. --- include/sway/tree/view.h | 4 ++++ sway/tree/view.c | 42 ++++++++++++++++++---------------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 352a62bc..4395e94a 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -167,6 +167,10 @@ const char *view_get_instance(struct sway_view *view); void view_configure(struct sway_view *view, double ox, double oy, int width, int height); +/** + * 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); void view_set_activated(struct sway_view *view, bool activated); diff --git a/sway/tree/view.c b/sway/tree/view.c index 26902c23..4903b3a4 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -74,10 +74,6 @@ 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")) { @@ -93,25 +89,25 @@ void view_autoconfigure(struct sway_view *view) { 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; + 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; From 0375f966f19c0d404e08fad3cf8548ce9376a95b Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 1 May 2018 18:23:40 +1000 Subject: [PATCH 10/17] Fix surface offset when using borders --- sway/tree/container.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sway/tree/container.c b/sway/tree/container.c index 03d7e49c..cb0233db 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -423,8 +423,8 @@ struct sway_container *container_at(struct sway_container *parent, soutput->sway_output->wlr_output); double ox = lx - output_box->x; double oy = ly - output_box->y; - double view_sx = ox - swayc->x; - double view_sy = oy - swayc->y; + double view_sx = ox - sview->x; + double view_sy = oy - sview->y; double _sx, _sy; struct wlr_surface *_surface; From ed9e2015b24617bddd6c43556094fba9865ae522 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 1 May 2018 18:35:58 +1000 Subject: [PATCH 11/17] Scale borders according to output scale --- sway/desktop/output.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 2511c610..498a3a2e 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -240,6 +240,7 @@ static void render_container_simple_border_normal(struct sway_output *output, box.y = con->y + 1; box.width = con->sway_view->border_thickness; box.height = con->height - 1; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -248,6 +249,7 @@ static void render_container_simple_border_normal(struct sway_output *output, box.y = con->y + 1; box.width = con->sway_view->border_thickness; box.height = con->height - 1; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -256,6 +258,7 @@ static void render_container_simple_border_normal(struct sway_output *output, box.y = con->y + con->height - con->sway_view->border_thickness; box.width = con->width; box.height = con->sway_view->border_thickness; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -265,6 +268,7 @@ static void render_container_simple_border_normal(struct sway_output *output, box.y = con->y; box.width = con->width; box.height = 1; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -273,6 +277,7 @@ static void render_container_simple_border_normal(struct sway_output *output, box.y = con->sway_view->y - 1; box.width = con->width - con->sway_view->border_thickness * 2; box.height = 1; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -282,6 +287,7 @@ static void render_container_simple_border_normal(struct sway_output *output, box.y = con->y + 1; box.width = con->width - con->sway_view->border_thickness * 2; box.height = con->sway_view->y - con->y - 2; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -306,6 +312,7 @@ static void render_container_simple_border_pixel(struct sway_output *output, box.y = con->y; box.width = con->sway_view->border_thickness; box.height = con->height; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -314,6 +321,7 @@ static void render_container_simple_border_pixel(struct sway_output *output, box.y = con->y; box.width = con->sway_view->border_thickness; box.height = con->height; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -322,6 +330,7 @@ static void render_container_simple_border_pixel(struct sway_output *output, box.y = con->y; box.width = con->width; box.height = con->sway_view->border_thickness; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); @@ -330,6 +339,7 @@ static void render_container_simple_border_pixel(struct sway_output *output, box.y = con->y + con->height - con->sway_view->border_thickness; box.width = con->width; box.height = con->sway_view->border_thickness; + scale_box(&box, output->wlr_output->scale); wlr_render_rect(renderer, &box, color, output->wlr_output->transform_matrix); } From 700510b45e22e6021bcfa08c1c05d73f9bacb6eb Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 1 May 2018 19:21:29 +1000 Subject: [PATCH 12/17] Implement indicator border --- sway/desktop/output.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 498a3a2e..e0a211d1 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -245,6 +245,11 @@ static void render_container_simple_border_normal(struct sway_output *output, output->wlr_output->transform_matrix); // Child border - right edge + if (con->parent->children->length == 1 && con->parent->layout == L_HORIZ) { + memcpy(&color, colors->indicator, sizeof(float) * 3); + } else { + memcpy(&color, colors->child_border, sizeof(float) * 3); + } box.x = con->x + con->width - con->sway_view->border_thickness; box.y = con->y + 1; box.width = con->sway_view->border_thickness; @@ -254,6 +259,11 @@ static void render_container_simple_border_normal(struct sway_output *output, output->wlr_output->transform_matrix); // Child border - bottom edge + if (con->parent->children->length == 1 && con->parent->layout == L_VERT) { + memcpy(&color, colors->indicator, sizeof(float) * 3); + } else { + memcpy(&color, colors->child_border, sizeof(float) * 3); + } box.x = con->x; box.y = con->y + con->height - con->sway_view->border_thickness; box.width = con->width; @@ -317,6 +327,11 @@ static void render_container_simple_border_pixel(struct sway_output *output, output->wlr_output->transform_matrix); // Child border - right edge + if (con->parent->children->length == 1 && con->parent->layout == L_HORIZ) { + memcpy(&color, colors->indicator, sizeof(float) * 3); + } else { + memcpy(&color, colors->child_border, sizeof(float) * 3); + } box.x = con->x + con->width - con->sway_view->border_thickness; box.y = con->y; box.width = con->sway_view->border_thickness; @@ -335,6 +350,11 @@ static void render_container_simple_border_pixel(struct sway_output *output, output->wlr_output->transform_matrix); // Child border - bottom edge + if (con->parent->children->length == 1 && con->parent->layout == L_VERT) { + memcpy(&color, colors->indicator, sizeof(float) * 3); + } else { + memcpy(&color, colors->child_border, sizeof(float) * 3); + } box.x = con->x; box.y = con->y + con->height - con->sway_view->border_thickness; box.width = con->width; From 55577498c0b9b3e330351f14704c4bbb0ea10dff Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 1 May 2018 19:50:54 +1000 Subject: [PATCH 13/17] Allow clicking view decorations to focus view --- sway/tree/container.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sway/tree/container.c b/sway/tree/container.c index cb0233db..995da5ce 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -455,6 +455,16 @@ struct sway_container *container_at(struct sway_container *parent, *surface = _surface; return swayc; } + // Check the view's decorations + struct wlr_box swayc_box = { + .x = swayc->x, + .y = swayc->y, + .width = swayc->width, + .height = swayc->height, + }; + if (wlr_box_contains_point(&swayc_box, ox, oy)) { + return swayc; + } } else { list_cat(queue, swayc->children); } From 83952c52019ceee95e9293398bdc5f723db773eb Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 1 May 2018 19:59:36 +1000 Subject: [PATCH 14/17] Restore view_update_position() --- include/sway/tree/view.h | 2 ++ sway/tree/view.c | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 4395e94a..21127ab1 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -197,6 +197,8 @@ 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/tree/view.c b/sway/tree/view.c index 4903b3a4..05a9b277 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -353,6 +353,19 @@ 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; + } + + // TODO: Only allow this if the view is floating (this function will only be + // called in response to wayland clients wanting to reposition themselves). + 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; From 7f574c538db6bfc42166181b25ad5ef0831be63f Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 1 May 2018 07:46:28 -0400 Subject: [PATCH 15/17] Fix alphabetization of commands array --- sway/commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/commands.c b/sway/commands.c index 575859c9..8abfd40b 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -101,9 +101,9 @@ static struct cmd_handler handlers[] = { { "client.focused_inactive", cmd_client_focused_inactive }, { "client.unfocused", cmd_client_unfocused }, { "client.urgent", cmd_client_urgent }, + { "default_border", cmd_default_border }, { "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 }, From 51df1d4ff864f9ba6658d568e24554169363df7b Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 1 May 2018 22:42:08 +1000 Subject: [PATCH 16/17] Update cursor when border is changed --- sway/commands/border.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sway/commands/border.c b/sway/commands/border.c index 873abb68..1eb06a21 100644 --- a/sway/commands/border.c +++ b/sway/commands/border.c @@ -1,6 +1,8 @@ #include "log.h" #include "sway/commands.h" #include "sway/config.h" +#include "sway/input/cursor.h" +#include "sway/input/input-manager.h" #include "sway/tree/container.h" #include "sway/tree/view.h" @@ -37,5 +39,10 @@ struct cmd_results *cmd_border(int argc, char **argv) { view_autoconfigure(view); + struct sway_seat *seat = input_manager_current_seat(input_manager); + if (seat->cursor) { + cursor_send_pointer_motion(seat->cursor, 0); + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } From cb07434913b89580a4025824cb181733b2db1eb7 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 1 May 2018 22:48:57 +1000 Subject: [PATCH 17/17] Remove unnecessary pointers --- sway/commands/client.c | 20 ++++++------ sway/config.c | 74 +++++++++++++++++++++--------------------- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/sway/commands/client.c b/sway/commands/client.c index ce519381..156ff95c 100644 --- a/sway/commands/client.c +++ b/sway/commands/client.c @@ -3,7 +3,7 @@ #include "sway/config.h" #include "sway/tree/container.h" -static bool parse_color(char *hexstring, float (*dest)[4]) { +static bool parse_color(char *hexstring, float dest[static 4]) { if (hexstring[0] != '#') { return false; } @@ -20,10 +20,10 @@ static bool parse_color(char *hexstring, float (*dest)[4]) { 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; + 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; } @@ -34,27 +34,27 @@ static struct cmd_results *handle_command(int argc, char **argv, return error; } - if (!parse_color(argv[0], &class->border)) { + 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)) { + 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)) { + 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)) { + 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)) { + if (!parse_color(argv[4], class->child_border)) { return cmd_results_new(CMD_INVALID, cmd_name, "Unable to parse child border color"); } diff --git a/sway/config.c b/sway/config.c index ed291450..f4d78e19 100644 --- a/sway/config.c +++ b/sway/config.c @@ -130,11 +130,11 @@ 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 set_color(float dest[static 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) { @@ -205,38 +205,38 @@ static void config_defaults(struct sway_config *config) { config->hide_edge_borders = E_NONE; // border colors - 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); + 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;