diff --git a/include/ssd-internal.h b/include/ssd-internal.h index 600b9076..8adbcbd1 100644 --- a/include/ssd-internal.h +++ b/include/ssd-internal.h @@ -114,7 +114,7 @@ struct ssd { struct wlr_scene_tree *tree; struct ssd_border_subtree { struct wlr_scene_tree *tree; - struct wlr_scene_rect *top, *bottom, *left, *right; + struct wlr_scene_buffer *top, *bottom, *left, *right; } subtrees[2]; /* indexed by enum ssd_active_state */ } border; diff --git a/include/theme.h b/include/theme.h index beba06cc..16362c82 100644 --- a/include/theme.h +++ b/include/theme.h @@ -14,6 +14,11 @@ struct lab_img; +/* XXX: using fixed border widths for now */ +/* (top is narrower to blend with titlebar) */ +#define BORDER_PX_TOP 2 +#define BORDER_PX_SIDE 4 + /* * Openbox defines 7 types of Gradient background in addition to Solid. * Currently, labwc supports only Vertical and SplitVertical. diff --git a/src/ssd/ssd-border.c b/src/ssd/ssd-border.c index f0db4fff..d84e9e8b 100644 --- a/src/ssd/ssd-border.c +++ b/src/ssd/ssd-border.c @@ -2,7 +2,9 @@ #include #include +#include "buffer.h" #include "common/macros.h" +#include "common/mem.h" #include "labwc.h" #include "ssd.h" #include "ssd-internal.h" @@ -17,13 +19,19 @@ ssd_border_create(struct ssd *ssd) struct view *view = ssd->view; struct theme *theme = view->server->theme; +#if 0 + /* XXX: not using with textured borders */ int width = view->current.width; int height = view_effective_height(view, /* use_pending */ false); int full_width = width + 2 * theme->border_width; int corner_width = ssd_get_corner_width(); +#endif ssd->border.tree = wlr_scene_tree_create(ssd->tree); +#if 0 + /* XXX: eliminated this offset */ wlr_scene_node_set_position(&ssd->border.tree->node, -theme->border_width, 0); +#endif enum ssd_active_state active; FOR_EACH_ACTIVE_STATE(active) { @@ -31,8 +39,10 @@ ssd_border_create(struct ssd *ssd) subtree->tree = wlr_scene_tree_create(ssd->border.tree); struct wlr_scene_tree *parent = subtree->tree; wlr_scene_node_set_enabled(&parent->node, active); - float *color = theme->window[active].border_color; + float *color = theme->window[active].title_bg.color; +#if 0 + /* XXX: old solid color borders */ subtree->left = wlr_scene_rect_create(parent, theme->border_width, height, color); wlr_scene_node_set_position(&subtree->left->node, 0, 0); @@ -52,8 +62,79 @@ ssd_border_create(struct ssd *ssd) wlr_scene_node_set_position(&subtree->top->node, theme->border_width + corner_width, -(ssd->titlebar.height + theme->border_width)); +#endif + + uint8_t r = color[0] * 255; + uint8_t g = color[1] * 255; + uint8_t b = color[2] * 255; + uint8_t a = color[3] * 255; + + /* darker outline */ + uint8_t r0 = r / 2; + uint8_t g0 = g / 2; + uint8_t b0 = b / 2; + + /* highlight */ + uint8_t r1 = MIN(r * 5 / 4, a); + uint8_t g1 = MIN(g * 5 / 4, a); + uint8_t b1 = MIN(b * 5 / 4, a); + + uint32_t col = ((uint32_t)a << 24) | ((uint32_t)r << 16) + | ((uint32_t)g << 8) | b; + uint32_t col0 = ((uint32_t)a << 24) | ((uint32_t)r0 << 16) + | ((uint32_t)g0 << 8) | b0; + uint32_t col1 = ((uint32_t)a << 24) | ((uint32_t)r1 << 16) + | ((uint32_t)g1 << 8) | b1; + + /* top and left start out the same */ + uint32_t *left_data = znew_n(uint32_t, BORDER_PX_SIDE); + uint32_t *top_data = znew_n(uint32_t, BORDER_PX_TOP); + left_data[0] = top_data[0] = col0; + left_data[1] = top_data[1] = col1; + for (int i = 2; i < BORDER_PX_SIDE; i++) { + left_data[i] = col; + } + for (int i = 2; i < BORDER_PX_TOP; i++) { + top_data[i] = col; + } + + /* bottom and right are identical */ + uint32_t *right_data = znew_n(uint32_t, BORDER_PX_SIDE); + uint32_t *bottom_data = znew_n(uint32_t, BORDER_PX_SIDE); + for (int i = 0; i < BORDER_PX_SIDE - 1; i++) { + right_data[i] = col; + bottom_data[i] = col; + } + right_data[BORDER_PX_SIDE - 1] = col0; + bottom_data[BORDER_PX_SIDE - 1] = col0; + + /* order matters here since the border overlap */ + struct lab_data_buffer *bottom_buffer = + buffer_create_from_data(bottom_data, 1, BORDER_PX_SIDE, 4); + subtree->bottom = wlr_scene_buffer_create(parent, &bottom_buffer->base); + wlr_buffer_drop(&bottom_buffer->base); + + struct lab_data_buffer *right_buffer = + buffer_create_from_data(right_data, BORDER_PX_SIDE, 1, + 4 * BORDER_PX_SIDE); + subtree->right = wlr_scene_buffer_create(parent, &right_buffer->base); + wlr_buffer_drop(&right_buffer->base); + + struct lab_data_buffer *left_buffer = + buffer_create_from_data(left_data, BORDER_PX_SIDE, 1, + 4 * BORDER_PX_SIDE); + subtree->left = wlr_scene_buffer_create(parent, &left_buffer->base); + wlr_buffer_drop(&left_buffer->base); + + struct lab_data_buffer *top_buffer = + buffer_create_from_data(top_data, 1, BORDER_PX_TOP, 4); + subtree->top = wlr_scene_buffer_create(parent, &top_buffer->base); + wlr_buffer_drop(&top_buffer->base); } + /* Lower textured borders below titlebar for overlap */ + wlr_scene_node_lower_to_bottom(&ssd->border.tree->node); + if (view->maximized == VIEW_AXIS_BOTH) { wlr_scene_node_set_enabled(&ssd->border.tree->node, false); } @@ -89,10 +170,10 @@ ssd_border_update(struct ssd *ssd) ssd->margin = ssd_thickness(ssd->view); } - struct theme *theme = view->server->theme; - int width = view->current.width; int height = view_effective_height(view, /* use_pending */ false); +#if 0 + /* XXX: ignoring lots of possible cases */ int full_width = width + 2 * theme->border_width; int corner_width = ssd_get_corner_width(); @@ -127,11 +208,19 @@ ssd_border_update(struct ssd *ssd) int top_x = ssd->titlebar.height <= 0 || ssd->state.was_squared ? 0 : theme->border_width + corner_width; +#endif + int title_h = ssd->titlebar.height; + int side_y = -title_h - (BORDER_PX_TOP - 1); + int side_height = title_h + height + (BORDER_PX_TOP - 1) + (BORDER_PX_SIDE - 1); + int top_x = -(BORDER_PX_SIDE - 1); + int top_width = width + 2 * (BORDER_PX_SIDE - 1); enum ssd_active_state active; FOR_EACH_ACTIVE_STATE(active) { struct ssd_border_subtree *subtree = &ssd->border.subtrees[active]; +#if 0 + /* XXX: old solid color borders */ wlr_scene_rect_set_size(subtree->left, theme->border_width, side_height); wlr_scene_node_set_position(&subtree->left->node, @@ -151,6 +240,27 @@ ssd_border_update(struct ssd *ssd) top_width, theme->border_width); wlr_scene_node_set_position(&subtree->top->node, top_x, -(ssd->titlebar.height + theme->border_width)); +#endif + + wlr_scene_node_set_position(&subtree->left->node, + -BORDER_PX_SIDE, side_y); + wlr_scene_buffer_set_dest_size(subtree->left, + BORDER_PX_SIDE, side_height); + + wlr_scene_node_set_position(&subtree->right->node, + width, side_y); + wlr_scene_buffer_set_dest_size(subtree->right, + BORDER_PX_SIDE, side_height); + + wlr_scene_node_set_position(&subtree->bottom->node, + top_x, height); + wlr_scene_buffer_set_dest_size(subtree->bottom, + top_width, BORDER_PX_SIDE); + + wlr_scene_node_set_position(&subtree->top->node, + top_x, -title_h - BORDER_PX_TOP); + wlr_scene_buffer_set_dest_size(subtree->top, + top_width, BORDER_PX_TOP); } } diff --git a/src/ssd/ssd-titlebar.c b/src/ssd/ssd-titlebar.c index 8e9fbc97..98074b97 100644 --- a/src/ssd/ssd-titlebar.c +++ b/src/ssd/ssd-titlebar.c @@ -29,6 +29,7 @@ ssd_titlebar_create(struct ssd *ssd) struct view *view = ssd->view; struct theme *theme = view->server->theme; int width = view->current.width; + bool maximized = view->maximized == VIEW_AXIS_BOTH; int corner_width = ssd_get_corner_width(); ssd->titlebar.tree = wlr_scene_tree_create(ssd->tree); @@ -62,7 +63,10 @@ ssd_titlebar_create(struct ssd *ssd) wlr_scene_buffer_set_filter_mode( subtree->bar, WLR_SCALE_FILTER_NEAREST); } - wlr_scene_node_set_position(&subtree->bar->node, corner_width, 0); + int overlap = maximized ? 0 : BORDER_PX_SIDE - 2; + wlr_scene_node_set_position(&subtree->bar->node, -overlap, 0); + wlr_scene_buffer_set_dest_size(subtree->bar, + width + 2 * overlap, theme->titlebar_height); subtree->corner_left = wlr_scene_buffer_create(parent, corner_top_left); wlr_scene_node_set_position(&subtree->corner_left->node, @@ -113,7 +117,6 @@ ssd_titlebar_create(struct ssd *ssd) ssd_update_title(ssd); - bool maximized = view->maximized == VIEW_AXIS_BOTH; bool squared = ssd_should_be_squared(ssd); if (maximized) { set_alt_button_icon(ssd, LAB_NODE_BUTTON_MAXIMIZE, true); @@ -157,20 +160,25 @@ update_button_state(struct ssd_button *button, enum lab_button_state state, static void set_squared_corners(struct ssd *ssd, bool enable) { +#if 0 struct view *view = ssd->view; int width = view->current.width; int corner_width = ssd_get_corner_width(); struct theme *theme = view->server->theme; int x = enable ? 0 : corner_width; +#endif enum ssd_active_state active; FOR_EACH_ACTIVE_STATE(active) { struct ssd_titlebar_subtree *subtree = &ssd->titlebar.subtrees[active]; +#if 0 + /* XXX: conflicts with overlap of textured borders */ wlr_scene_node_set_position(&subtree->bar->node, x, 0); wlr_scene_buffer_set_dest_size(subtree->bar, MAX(width - 2 * x, 0), theme->titlebar_height); +#endif wlr_scene_node_set_enabled(&subtree->corner_left->node, !enable); @@ -284,7 +292,6 @@ ssd_titlebar_update(struct ssd *ssd) if (ssd->state.was_maximized != maximized) { set_alt_button_icon(ssd, LAB_NODE_BUTTON_MAXIMIZE, maximized); } - ssd->state.was_maximized = maximized; ssd->state.was_squared = squared; } @@ -299,22 +306,25 @@ ssd_titlebar_update(struct ssd *ssd) ssd->state.was_omnipresent = view->visible_on_all_workspaces; } - if (width == ssd->state.geometry.width) { + if (ssd->state.was_maximized == maximized + && ssd->state.geometry.width == width) { return; } + ssd->state.was_maximized = maximized; update_visible_buttons(ssd); /* Center buttons vertically within titlebar */ int y = (theme->titlebar_height - theme->window_button_height) / 2; int x; - int bg_offset = maximized || squared ? 0 : corner_width; enum ssd_active_state active; FOR_EACH_ACTIVE_STATE(active) { struct ssd_titlebar_subtree *subtree = &ssd->titlebar.subtrees[active]; + int overlap = maximized ? 0 : BORDER_PX_SIDE - 2; + wlr_scene_node_set_position(&subtree->bar->node, -overlap, 0); wlr_scene_buffer_set_dest_size(subtree->bar, - MAX(width - bg_offset * 2, 0), theme->titlebar_height); + width + 2 * overlap, theme->titlebar_height); x = theme->window_titlebar_padding_width; struct ssd_button *button; @@ -512,10 +522,15 @@ ssd_update_hovered_button(struct server *server, struct wlr_scene_node *node) bool ssd_should_be_squared(struct ssd *ssd) { +#if 1 + /* XXX: force squared corners with textured borders */ + return true; +#else struct view *view = ssd->view; int corner_width = ssd_get_corner_width(); return (view_is_tiled_and_notify_tiled(view) || view->current.width < corner_width * 2) && view->maximized != VIEW_AXIS_BOTH; +#endif } diff --git a/src/ssd/ssd.c b/src/ssd/ssd.c index d1381c1a..3e7aa962 100644 --- a/src/ssd/ssd.c +++ b/src/ssd/ssd.c @@ -49,10 +49,10 @@ ssd_thickness(struct view *view) } struct border thickness = { - .top = theme->titlebar_height + theme->border_width, - .right = theme->border_width, - .bottom = theme->border_width, - .left = theme->border_width, + .top = theme->titlebar_height + BORDER_PX_TOP, + .right = BORDER_PX_SIDE, + .bottom = BORDER_PX_SIDE, + .left = BORDER_PX_SIDE, }; if (!view_titlebar_visible(view)) { @@ -346,10 +346,13 @@ ssd_enable_keybind_inhibit_indicator(struct ssd *ssd, bool enable) return; } +#if 0 + /* XXX: doesn't work with textured borders */ float *color = enable ? rc.theme->window_toggled_keybinds_color : rc.theme->window[SSD_ACTIVE].border_color; wlr_scene_rect_set_color(ssd->border.subtrees[SSD_ACTIVE].top, color); +#endif } bool