From b903f7f655479b9ed095cf5b5950d963d525dd8c Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 13 Mar 2016 21:10:46 -0400 Subject: Implement some more on borders Note that this segfaults ALL THE TIME in wlc code. Paging @Cloudef for help, I'm at a loss. --- include/container.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'include/container.h') diff --git a/include/container.h b/include/container.h index a96beab9..815898d7 100644 --- a/include/container.h +++ b/include/container.h @@ -36,6 +36,12 @@ enum swayc_layouts { L_LAYOUTS, }; +enum swayc_border_types { + B_NONE, /**< No border */ + B_PIXEL, /**< 1px border */ + B_NORMAL /**< Normal border with title bar */ +}; + /** * Stores information about a container. * @@ -109,6 +115,15 @@ struct sway_container { * If this container's children include a fullscreen view, this is that view. */ struct sway_container *fullscreen; + /** + * If this container is a view, this may be set to the window's decoration + * buffer (or NULL). + */ + unsigned char *border; + enum swayc_border_types border_type; + struct wlc_geometry border_geometry; + struct wlc_geometry presumed_geometry; + int border_thickness; }; enum visibility_mask { -- cgit v1.2.3-54-g00ecf From 3b05f92f76c3bd9400320844e485eb06e94772cd Mon Sep 17 00:00:00 2001 From: Mikkel Oscar Lyderik Date: Tue, 29 Mar 2016 14:40:25 +0200 Subject: Add border config --- include/config.h | 2 ++ include/container.h | 8 ++++---- sway/commands.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ sway/config.c | 3 +++ sway/sway.5.txt | 9 +++++++++ 5 files changed, 69 insertions(+), 4 deletions(-) (limited to 'include/container.h') diff --git a/include/config.h b/include/config.h index fe69e310..a35cfd0a 100644 --- a/include/config.h +++ b/include/config.h @@ -203,6 +203,8 @@ struct sway_config { list_t *config_chain; const char *current_config; + enum swayc_border_types border; + int border_thickness; enum edge_border_types hide_edge_borders; // border colors diff --git a/include/container.h b/include/container.h index 815898d7..07514c8a 100644 --- a/include/container.h +++ b/include/container.h @@ -8,7 +8,7 @@ typedef struct sway_container swayc_t; /** * Different kinds of containers. - * + * * This enum is in order. A container will never be inside of a container below * it on this list. */ @@ -37,9 +37,9 @@ enum swayc_layouts { }; enum swayc_border_types { - B_NONE, /**< No border */ - B_PIXEL, /**< 1px border */ - B_NORMAL /**< Normal border with title bar */ + B_NONE, /**< No border */ + B_PIXEL, /**< 1px border */ + B_NORMAL /**< Normal border with title bar */ }; /** diff --git a/sway/commands.c b/sway/commands.c index 4a3ebf9e..bc182cee 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -43,6 +43,7 @@ static sway_cmd cmd_assign; static sway_cmd cmd_bar; static sway_cmd cmd_bindcode; static sway_cmd cmd_bindsym; +static sway_cmd cmd_border; static sway_cmd cmd_debuglog; static sway_cmd cmd_exec; static sway_cmd cmd_exec_always; @@ -346,6 +347,55 @@ static struct cmd_results *cmd_bindcode(int argc, char **argv) { return cmd_results_new(CMD_SUCCESS, NULL, NULL); } +static 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; + } + + if (argc > 2) { + return cmd_results_new(CMD_FAILURE, "border", + "Expected 'border []"); + } + + enum swayc_border_types border = config->border; + + if (strcasecmp(argv[0], "none") == 0) { + border = B_NONE; + } else if (strcasecmp(argv[0], "normal") == 0) { + border = B_NORMAL; + } else if (strcasecmp(argv[0], "pixel") == 0) { + border = B_PIXEL; + } else if (strcasecmp(argv[0], "toggle") == 0) { + switch (config->border) { + case B_NONE: + border = B_PIXEL; + break; + case B_NORMAL: + border = B_NONE; + break; + case B_PIXEL: + border = B_NORMAL; + break; + } + } else { + return cmd_results_new(CMD_FAILURE, "border", + "Expected 'border "); + } + + if (argc == 2 && (border == B_NORMAL || border == B_PIXEL)) { + int thickness = (int)strtol(argv[1], NULL, 10); + if (errno == ERANGE || thickness < 0) { + errno = 0; + return cmd_results_new(CMD_INVALID, "border", "Number is out out of range."); + } + config->border_thickness = thickness; + } + + config->border = border; + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} + static struct cmd_results *cmd_exec_always(int argc, char **argv) { struct cmd_results *error = NULL; if (!config->active) return cmd_results_new(CMD_DEFER, NULL, NULL); @@ -2074,6 +2124,7 @@ static struct cmd_handler handlers[] = { { "bar", cmd_bar }, { "bindcode", cmd_bindcode }, { "bindsym", cmd_bindsym }, + { "border", cmd_border }, { "debuglog", cmd_debuglog }, { "default_orientation", cmd_orientation }, { "exec", cmd_exec }, diff --git a/sway/config.c b/sway/config.c index 565acd05..193cfad2 100644 --- a/sway/config.c +++ b/sway/config.c @@ -182,6 +182,9 @@ static void config_defaults(struct sway_config *config) { config->config_chain = create_list(); config->current_config = NULL; + // borders + config->border = B_NORMAL; + config->border_thickness = 2; config->hide_edge_borders = E_NONE; // border colors diff --git a/sway/sway.5.txt b/sway/sway.5.txt index 13d304bb..2eb0276c 100644 --- a/sway/sway.5.txt +++ b/sway/sway.5.txt @@ -43,6 +43,15 @@ The following commands may only be used in the configuration file. The following commands cannot be used directly in the configuration file. They are expected to be used with **bindsym** or at runtime through **swaymsg**(1). +**border** []:: + Set border style for windows. _normal_ includes a border of thickness _n_ and + a title bar. _pixel_ is just the border without title bar. Default is _normal_ + with border thickness 2. + +**border** :: + Set border style to _none_ or _toggle_ between the available border styles: + _normal_, _pixel_, _none_. + **exit**:: Exit sway and end your Wayland session. -- cgit v1.2.3-54-g00ecf From 5a13cb0ed136906a4370235214601b0129548c49 Mon Sep 17 00:00:00 2001 From: Mikkel Oscar Lyderik Date: Tue, 29 Mar 2016 14:47:30 +0200 Subject: Implement borders The borders are implemented as a surface/buffer attached to each view which is sent to and rendered by wlc in the view_pre_render callback. All the drawing logic is handled in sway/border.c and all the logic for calculating the geometry of the border/view is handled in `update_geometry` in sway/layout.c (same place as gaps are calculated). --- include/border.h | 10 +++ include/config.h | 1 + include/container.h | 17 ++-- include/render.h | 9 -- sway/CMakeLists.txt | 3 +- sway/border.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++++++++ sway/commands.c | 29 ++++-- sway/config.c | 2 + sway/container.c | 22 ++--- sway/focus.c | 3 + sway/handlers.c | 17 ++-- sway/layout.c | 76 +++++++++++++++- sway/render.c | 113 ------------------------ 13 files changed, 393 insertions(+), 156 deletions(-) create mode 100644 include/border.h delete mode 100644 include/render.h create mode 100644 sway/border.c delete mode 100644 sway/render.c (limited to 'include/container.h') diff --git a/include/border.h b/include/border.h new file mode 100644 index 00000000..63cd63d2 --- /dev/null +++ b/include/border.h @@ -0,0 +1,10 @@ +#ifndef _SWAY_BORDER_H +#define _SWAY_BORDER_H +#include +#include "container.h" + +void render_view_borders(wlc_handle view); +void update_view_border(swayc_t *view); +int get_font_text_height(const char *font); + +#endif diff --git a/include/config.h b/include/config.h index a35cfd0a..fb84423c 100644 --- a/include/config.h +++ b/include/config.h @@ -184,6 +184,7 @@ struct sway_config { enum swayc_layouts default_orientation; enum swayc_layouts default_layout; char *font; + int font_height; // Flags bool focus_follows_mouse; diff --git a/include/container.h b/include/container.h index 07514c8a..26da851e 100644 --- a/include/container.h +++ b/include/container.h @@ -115,15 +115,16 @@ struct sway_container { * If this container's children include a fullscreen view, this is that view. */ struct sway_container *fullscreen; - /** - * If this container is a view, this may be set to the window's decoration - * buffer (or NULL). - */ - unsigned char *border; - enum swayc_border_types border_type; + /** + * If this container is a view, this may be set to the window's decoration + * buffer (or NULL). + */ + unsigned char *border; + enum swayc_border_types border_type; struct wlc_geometry border_geometry; - struct wlc_geometry presumed_geometry; - int border_thickness; + struct wlc_geometry title_bar_geometry; + struct wlc_geometry actual_geometry; + int border_thickness; }; enum visibility_mask { diff --git a/include/render.h b/include/render.h deleted file mode 100644 index c3d1ca87..00000000 --- a/include/render.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _SWAY_RENDER_H -#define _SWAY_RENDER_H -#include -#include "container.h" - -void render_view_borders(wlc_handle view); -void update_view_border(swayc_t *view); - -#endif diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index 6c62d676..51f27a05 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt @@ -26,7 +26,7 @@ add_executable(sway output.c resize.c workspace.c - render.c + border.c ) add_definitions( @@ -36,6 +36,7 @@ add_definitions( target_link_libraries(sway sway-common sway-protocols + sway-wayland ${WLC_LIBRARIES} ${XKBCOMMON_LIBRARIES} ${PCRE_LIBRARIES} diff --git a/sway/border.c b/sway/border.c new file mode 100644 index 00000000..8c9106e4 --- /dev/null +++ b/sway/border.c @@ -0,0 +1,247 @@ +#include "border.h" +#include +#include +#include +#include +#include +#include "container.h" +#include "config.h" +#include "client/pango.h" + +void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { + int endian = 1; + if (*(char *)&endian == 1) { + cairo_set_source_rgba(cairo, + (color >> (1*8) & 0xFF) / 255.0, + (color >> (2*8) & 0xFF) / 255.0, + (color >> (3*8) & 0xFF) / 255.0, + (color >> (0*8) & 0xFF) / 255.0); + } else { + cairo_set_source_rgba(cairo, + (color >> (0*8) & 0xFF) / 255.0, + (color >> (3*8) & 0xFF) / 255.0, + (color >> (2*8) & 0xFF) / 255.0, + (color >> (1*8) & 0xFF) / 255.0); + } +} + +static cairo_t *create_border_buffer(swayc_t *view, struct wlc_geometry geo, cairo_surface_t **surface) { + cairo_t *cr; + view->border_geometry = geo; + int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, geo.size.w); + view->border = calloc(stride * geo.size.h, sizeof(unsigned char)); + if (!view->border) { + sway_log(L_DEBUG, "Unable to allocate buffer"); + return NULL; + } + *surface = cairo_image_surface_create_for_data(view->border, + CAIRO_FORMAT_ARGB32, geo.size.w, geo.size.h, stride); + if (cairo_surface_status(*surface) != CAIRO_STATUS_SUCCESS) { + free(view->border); + view->border = NULL; + sway_log(L_DEBUG, "Unable to allocate surface"); + return NULL; + } + cr = cairo_create(*surface); + if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) { + cairo_surface_destroy(*surface); + free(view->border); + view->border = NULL; + sway_log(L_DEBUG, "Unable to create cairo context"); + return NULL; + } + return cr; +} + +// TODO: move to client/cairo.h when local set_source_u32 is fixed. +/** + * Renders a sharp line of any width and height. + * + * The line is drawn from (x,y) to (x+width,y+height) where width/height is 0 + * if the line has a width/height of one pixel, respectively. + */ +static void render_sharp_line(cairo_t *cairo, uint32_t color, double x, double y, double width, double height) { + cairo_set_source_u32(cairo, color); + + if (width > 1 && height > 1) { + cairo_rectangle(cairo, x, y, width, height); + cairo_fill(cairo); + } else { + if (width == 1) { + x += 0.5; + height += y; + width = x; + } + + if (height == 1) { + y += 0.5; + width += x; + height = y; + } + + cairo_move_to(cairo, x, y); + cairo_set_line_width(cairo, 1.0); + cairo_line_to(cairo, width, height); + cairo_stroke(cairo); + } +} + +int get_font_text_height(const char *font) { + cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 200, 200); + cairo_t *cr = cairo_create(surface); + int width, height; + get_text_size(cr, font, &width, &height, "Gg"); + return height; +} + +static void render_borders(swayc_t *view, cairo_t *cr, struct border_colors *colors) { + struct wlc_geometry *b = &view->border_geometry; + struct wlc_geometry *v = &view->actual_geometry; + + // left border + int left_border = v->origin.x - b->origin.x; + if (left_border > 0) { + render_sharp_line(cr, + colors->child_border, + 0, 0, + left_border, + b->size.h); + } + + // right border + int right_border = b->size.w - v->size.w - left_border; + if (right_border > 0) { + render_sharp_line(cr, + colors->child_border, + b->size.w - right_border, + 0, + right_border, + b->size.h); + } + + // top border + int top_border = v->origin.y - b->origin.y; + if (top_border > 0) { + render_sharp_line(cr, + colors->child_border, + 0, 0, + b->size.w, + top_border); + } + + // bottom border + int bottom_border = b->size.h - (top_border + v->size.h); + if (bottom_border > 0) { + render_sharp_line(cr, + colors->child_border, + 0, + b->size.h - bottom_border, + b->size.w, + bottom_border); + } +} + +static void render_with_title_bar(swayc_t *view, cairo_t *cr, struct border_colors *colors) { + struct wlc_geometry *tb = &view->title_bar_geometry; + struct wlc_geometry *b = &view->border_geometry; + + // borders + render_borders(view, cr, colors); + + // title bar background + cairo_set_source_u32(cr, colors->child_border); + cairo_rectangle(cr, 0, 0, tb->size.w, tb->size.h); + cairo_fill(cr); + + // header top line + render_sharp_line(cr, colors->border, 0, 0, tb->size.w, 1); + + // text + int width, height; + get_text_size(cr, config->font, &width, &height, "%s", view->name); + cairo_move_to(cr, view->border_thickness, 2); + cairo_set_source_u32(cr, colors->text); + pango_printf(cr, config->font, "%s", view->name); + + // header bottom line + render_sharp_line(cr, colors->border, + view->actual_geometry.origin.x - b->origin.x, + tb->size.h - 1, + view->actual_geometry.size.w, 1); +} + +void update_view_border(swayc_t *view) { + cairo_t *cr = NULL; + cairo_surface_t *surface = NULL; + + if (view->border) { + free(view->border); + view->border = NULL; + } + + swayc_t *focused = get_focused_view(&root_container); + swayc_t *container = swayc_parent_by_type(view, C_CONTAINER); + swayc_t *focused_inactive = NULL; + if (container) { + focused_inactive = swayc_focus_by_type(container, C_VIEW); + } else { + container = swayc_parent_by_type(view, C_WORKSPACE); + if (container) { + focused_inactive = swayc_focus_by_type(container, C_VIEW); + } + } + + switch (view->border_type) { + case B_NONE: + break; + case B_PIXEL: + cr = create_border_buffer(view, view->border_geometry, &surface); + if (!cr) { + break; + } + + if (focused == view) { + render_borders(view, cr, &config->border_colors.focused); + } else if (focused_inactive == view) { + render_borders(view, cr, &config->border_colors.focused_inactive); + } else { + render_borders(view, cr, &config->border_colors.unfocused); + } + + break; + case B_NORMAL: + cr = create_border_buffer(view, view->border_geometry, &surface); + if (!cr) { + break; + } + + if (focused == view) { + render_with_title_bar(view, cr, &config->border_colors.focused); + } else if (focused_inactive == view) { + render_with_title_bar(view, cr, &config->border_colors.focused_inactive); + } else { + render_with_title_bar(view, cr, &config->border_colors.unfocused); + } + + break; + } + if (surface) { + cairo_surface_flush(surface); + cairo_surface_destroy(surface); + } + if (cr) { + cairo_destroy(cr); + } +} + +void render_view_borders(wlc_handle view) { + swayc_t *c = swayc_by_handle(view); + + if (!c || c->border_type == B_NONE) { + return; + } + + if (c->border) { + wlc_pixels_write(WLC_RGBA8888, &c->border_geometry, c->border); + } +} diff --git a/sway/commands.c b/sway/commands.c index bc182cee..c53b13c3 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -31,6 +31,7 @@ #include "ipc-server.h" #include "list.h" #include "input.h" +#include "border.h" typedef struct cmd_results *sway_cmd(int argc, char **argv); @@ -359,6 +360,14 @@ static struct cmd_results *cmd_border(int argc, char **argv) { } enum swayc_border_types border = config->border; + int thickness = config->border_thickness; + + swayc_t *view = NULL; + if (config->active) { + view = get_focused_view(&root_container); + border = view->border_type; + thickness = view->border_thickness; + } if (strcasecmp(argv[0], "none") == 0) { border = B_NONE; @@ -367,7 +376,7 @@ static struct cmd_results *cmd_border(int argc, char **argv) { } else if (strcasecmp(argv[0], "pixel") == 0) { border = B_PIXEL; } else if (strcasecmp(argv[0], "toggle") == 0) { - switch (config->border) { + switch (border) { case B_NONE: border = B_PIXEL; break; @@ -383,16 +392,24 @@ static struct cmd_results *cmd_border(int argc, char **argv) { "Expected 'border "); } + if (argc == 2 && (border == B_NORMAL || border == B_PIXEL)) { - int thickness = (int)strtol(argv[1], NULL, 10); + thickness = (int)strtol(argv[1], NULL, 10); if (errno == ERANGE || thickness < 0) { errno = 0; return cmd_results_new(CMD_INVALID, "border", "Number is out out of range."); } + } + + if (config->active && view) { + view->border_type = border; + view->border_thickness = thickness; + update_geometry(view); + } else { + config->border = border; config->border_thickness = thickness; } - config->border = border; return cmd_results_new(CMD_SUCCESS, NULL, NULL); } @@ -904,9 +921,9 @@ static struct cmd_results *cmd_move(int argc, char **argv) { } else if (strcasecmp(argv[0], "position") == 0 && strcasecmp(argv[1], "mouse") == 0) { if (view->is_floating) { swayc_t *output = swayc_parent_by_type(view, C_OUTPUT); - const struct wlc_geometry *geometry = wlc_view_get_geometry(view->handle); + struct wlc_geometry g; + wlc_view_get_visible_geometry(view->handle, &g); const struct wlc_size *size = wlc_output_get_resolution(output->handle); - struct wlc_geometry g = *geometry; struct wlc_point origin; wlc_pointer_get_position(&origin); @@ -1954,6 +1971,8 @@ static struct cmd_results *cmd_font(int argc, char **argv) { config->font = font; } + config->font_height = get_font_text_height(config->font); + sway_log(L_DEBUG, "Settings font %s", config->font); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/config.c b/sway/config.c index 193cfad2..5501ab31 100644 --- a/sway/config.c +++ b/sway/config.c @@ -22,6 +22,7 @@ #include "input_state.h" #include "criteria.h" #include "input.h" +#include "border.h" struct sway_config *config = NULL; @@ -161,6 +162,7 @@ static void config_defaults(struct sway_config *config) { config->default_layout = L_NONE; config->default_orientation = L_NONE; config->font = strdup("monospace 10"); + config->font_height = get_font_text_height(config->font); // Flags config->focus_follows_mouse = true; diff --git a/sway/container.c b/sway/container.c index ac0d3231..21a929b9 100644 --- a/sway/container.c +++ b/sway/container.c @@ -22,8 +22,8 @@ static swayc_t *new_swayc(enum swayc_types type) { c->gaps = -1; c->layout = L_NONE; c->type = type; - c->border_type = B_PIXEL; // TODO: Load default from config - c->border_thickness = 2; + c->border_type = config->border; + c->border_thickness = config->border_thickness; if (type != C_VIEW) { c->children = create_list(); c->border_type = B_NONE; @@ -269,11 +269,12 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { view->is_focused = true; view->sticky = false; // Setup geometry - const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); + struct wlc_geometry geometry; + wlc_view_get_visible_geometry(handle, &geometry); view->width = 0; view->height = 0; - view->desired_width = geometry->size.w; - view->desired_height = geometry->size.h; + view->desired_width = geometry.size.w; + view->desired_height = geometry.size.h; view->is_floating = false; @@ -306,13 +307,14 @@ swayc_t *new_floating_view(wlc_handle handle) { view->sticky = false; // Set the geometry of the floating view - const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); + struct wlc_geometry geometry; + wlc_view_get_visible_geometry(handle, &geometry); // give it requested geometry, but place in center - view->x = (swayc_active_workspace()->width - geometry->size.w) / 2; - view->y = (swayc_active_workspace()->height- geometry->size.h) / 2; - view->width = geometry->size.w; - view->height = geometry->size.h; + view->x = (swayc_active_workspace()->width - geometry.size.w) / 2; + view->y = (swayc_active_workspace()->height- geometry.size.h) / 2; + view->width = geometry.size.w; + view->height = geometry.size.h; view->desired_width = view->width; view->desired_height = view->height; diff --git a/sway/focus.c b/sway/focus.c index 7f96eda7..4cae3b47 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -7,6 +7,7 @@ #include "config.h" #include "input_state.h" #include "ipc-server.h" +#include "border.h" bool locked_container_focus = false; bool locked_view_focus = false; @@ -130,6 +131,7 @@ bool set_focused_container(swayc_t *c) { // unactivate previous focus if (focused->type == C_VIEW) { wlc_view_set_state(focused->handle, WLC_BIT_ACTIVATED, false); + update_view_border(focused); } // activate current focus if (p->type == C_VIEW) { @@ -137,6 +139,7 @@ bool set_focused_container(swayc_t *c) { // set focus if view_focus is unlocked if (!locked_view_focus) { wlc_view_focus(p->handle); + update_view_border(p); } } } else if (p->type == C_WORKSPACE) { diff --git a/sway/handlers.c b/sway/handlers.c index 47b649fd..fc473640 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -9,7 +9,7 @@ #include #include "handlers.h" -#include "render.h" +#include "border.h" #include "log.h" #include "layout.h" #include "config.h" @@ -349,15 +349,14 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo view->desired_width = geometry->size.w; view->desired_height = geometry->size.h; - if (view->is_floating) { - view->width = view->desired_width; - view->height = view->desired_height; - view->x = geometry->origin.x; - view->y = geometry->origin.y; - arrange_windows(view->parent, -1, -1); - } + /* if (view->is_floating) { */ + /* view->width = view->desired_width; */ + /* view->height = view->desired_height; */ + /* view->x = geometry->origin.x; */ + /* view->y = geometry->origin.y; */ + /* /1* arrange_windows(view->parent, -1, -1); *1/ */ + /* } */ } - update_view_border(view); } static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { diff --git a/sway/layout.c b/sway/layout.c index be898c58..a282f36e 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -12,7 +12,7 @@ #include "focus.h" #include "output.h" #include "ipc-server.h" -#include "render.h" +#include "border.h" swayc_t root_container; list_t *scratchpad; @@ -427,6 +427,80 @@ void update_geometry(swayc_t *container) { geometry.size.h = ws->y + ws->height - geometry.origin.y; } } + + if (swayc_is_fullscreen(container)) { + container->border_geometry = (const struct wlc_geometry){0}; + container->title_bar_geometry = (const struct wlc_geometry){0}; + } else { + // make room for border + container->border_geometry = geometry; + + int border_top = container->border_thickness; + int border_bottom = container->border_thickness; + int border_left = container->border_thickness; + int border_right = container->border_thickness; + + // handle hide_edge_borders + if (config->hide_edge_borders != E_NONE && gap <= 0) { + swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); + const struct wlc_size *size = wlc_output_get_resolution(output->handle); + + if (config->hide_edge_borders == E_HORIZONTAL || config->hide_edge_borders == E_BOTH) { + if (geometry.origin.x == 0) { + border_left = 0; + } + + if (geometry.origin.x + geometry.size.w == size->w) { + border_right = 0; + } + } + + if (config->hide_edge_borders == E_VERTICAL || config->hide_edge_borders == E_BOTH) { + if (geometry.origin.y == 0) { + border_top = 0; + } + + if (geometry.origin.y + geometry.size.h == size->h) { + border_bottom = 0; + } + } + } + + switch (container->border_type) { + case B_NONE: + break; + case B_PIXEL: + geometry.origin.x += border_left; + geometry.origin.y += border_top; + geometry.size.w -= (border_left + border_right); + geometry.size.h -= (border_top + border_bottom); + break; + case B_NORMAL: + { + struct wlc_geometry title_bar = { + .origin = { + .x = container->border_geometry.origin.x, + .y = container->border_geometry.origin.y + }, + .size = { + .w = container->border_geometry.size.w, + .h = config->font_height + 4 // borders + padding + } + }; + geometry.origin.x += border_left; + geometry.origin.y += title_bar.size.h; + geometry.size.w -= (border_left + border_right); + geometry.size.h -= (border_bottom + title_bar.size.h); + container->title_bar_geometry = title_bar; + break; + } + } + + container->actual_geometry = geometry; + + update_view_border(container); + } + wlc_view_set_geometry(container->handle, 0, &geometry); } diff --git a/sway/render.c b/sway/render.c deleted file mode 100644 index 9388c1d0..00000000 --- a/sway/render.c +++ /dev/null @@ -1,113 +0,0 @@ -#include "render.h" -#include -#include -#include -#include -#include "container.h" - -void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { - cairo_set_source_rgba(cairo, - (color >> (3*8) & 0xFF) / 255.0, - (color >> (2*8) & 0xFF) / 255.0, - (color >> (1*8) & 0xFF) / 255.0, - (color >> (0*8) & 0xFF) / 255.0); -} - -cairo_t *create_border_buffer(swayc_t *view, struct wlc_geometry geo, - cairo_surface_t **surface) { - const int channels = 4; - cairo_t *cr; - view->border_geometry = geo; - view->border = calloc(channels * geo.size.w * geo.size.h, - sizeof(unsigned char)); - if (!view->border) { - sway_log(L_DEBUG, "Unable to allocate buffer"); - return NULL; - } - *surface = cairo_image_surface_create_for_data(view->border, - CAIRO_FORMAT_ARGB32, geo.size.w, geo.size.h, channels * geo.size.w); - if (cairo_surface_status(*surface) != CAIRO_STATUS_SUCCESS) { - free(view->border); - view->border = NULL; - sway_log(L_DEBUG, "Unable to allocate surface"); - return NULL; - } - cr = cairo_create(*surface); - if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) { - cairo_surface_destroy(*surface); - free(view->border); - view->border = NULL; - sway_log(L_DEBUG, "Unable to create cairo context"); - return NULL; - } - return cr; -} - -void update_view_border(swayc_t *view) { - struct wlc_geometry geo; - wlc_view_get_visible_geometry(view->handle, &geo); - cairo_t *cr = NULL; - cairo_surface_t *surface = NULL; - - if (view->border) { - free(view->border); - view->border = NULL; - } - - switch (view->border_type) { - case B_NONE: - view->border_geometry = geo; - break; - case B_PIXEL: - geo.origin.x -= view->border_thickness; - geo.origin.y -= view->border_thickness; - geo.size.w += view->border_thickness * 2; - geo.size.h += view->border_thickness * 2; - if (geo.size.w <= 0 || geo.size.h <= 0) { - view->border = NULL; - break; - } - cr = create_border_buffer(view, geo, &surface); - if (!cr) { - break; - } - cairo_set_source_u32(cr, 0x0000FFFF); - cairo_paint(cr); - break; - case B_NORMAL: - // TODO - break; - } - if (surface) { - cairo_surface_flush(surface); - cairo_surface_destroy(surface); - } - if (cr) { - cairo_destroy(cr); - sway_log(L_DEBUG, "Created border for %p (%dx%d+%d,%d)", view, - geo.size.w, geo.size.h, geo.origin.x, geo.origin.y); - } - view->border_geometry = geo; -} - -void render_view_borders(wlc_handle view) { - swayc_t *c = swayc_by_handle(view); - if (!c || c->border_type == B_NONE) { - return; - } - struct wlc_geometry geo; - wlc_view_get_visible_geometry(view, &geo); - if (geo.size.w != c->presumed_geometry.size.w - || geo.size.h != c->presumed_geometry.size.h - || geo.origin.x != c->presumed_geometry.origin.x - || geo.origin.y != c->presumed_geometry.origin.y) { - update_view_border(c); - c->presumed_geometry = geo; - } - if (c->border) { - geo = c->border_geometry; - sway_log(L_DEBUG, "Rendering border for %p (%dx%d+%d,%d)", c, - geo.size.w, geo.size.h, geo.origin.x, geo.origin.y); - wlc_pixels_write(WLC_RGBA8888, &c->border_geometry, c->border); - } -} -- cgit v1.2.3-54-g00ecf