diff --git a/include/theme.h b/include/theme.h index e1773e6c..46016aa9 100644 --- a/include/theme.h +++ b/include/theme.h @@ -46,17 +46,7 @@ struct theme { int title_height; - /* colors */ - float window_active_border_color[4]; - float window_inactive_border_color[4]; - float window_toggled_keybinds_color[4]; - - float window_active_title_bg_color[4]; - float window_inactive_title_bg_color[4]; - - float window_active_label_text_color[4]; - float window_inactive_label_text_color[4]; enum lab_justification window_label_text_justify; /* buttons */ @@ -67,13 +57,23 @@ struct theme { /* the corner radius of the hover effect */ int window_button_hover_bg_corner_radius; - /* window drop-shadows */ - int window_active_shadow_size; - int window_inactive_shadow_size; - float window_active_shadow_color[4]; - float window_inactive_shadow_color[4]; - + /* + * Themes/textures for each active/inactive window. Indexed by + * THEME_INACTIVE and THEME_ACTIVE. + */ struct { + /* TODO: add toggled/hover/pressed/disabled colors for buttons */ + float button_colors[LAB_SSD_BUTTON_LAST + 1][4]; + + float border_color[4]; + float toggled_keybinds_color[4]; + float title_bg_color[4]; + float label_text_color[4]; + + /* window drop-shadows */ + int shadow_size; + float shadow_color[4]; + /* * The texture of a window buttons for each hover/toggled/rounded * state. This can be accessed like: @@ -85,13 +85,15 @@ struct theme { struct lab_data_buffer *buttons [LAB_SSD_BUTTON_LAST + 1][LAB_BS_ALL + 1]; - /* TODO: add toggled/hover/pressed/disabled colors for buttons */ - float button_colors[LAB_SSD_BUTTON_LAST + 1][4]; + struct lab_data_buffer *corner_top_left_normal; + struct lab_data_buffer *corner_top_right_normal; - /* TODO: move other window.(in)active.* entries to here */ - - } window[2]; /* indexed by THEME_INACTIVE and THEME_ACTIVE */ + struct lab_data_buffer *shadow_corner_top; + struct lab_data_buffer *shadow_corner_bottom; + struct lab_data_buffer *shadow_edge; + } window[2]; + /* Derived from font sizes */ int menu_item_height; int menu_header_height; @@ -137,19 +139,6 @@ struct theme { struct theme_snapping_overlay snapping_overlay_region, snapping_overlay_edge; - /* textures */ - struct lab_data_buffer *corner_top_left_active_normal; - struct lab_data_buffer *corner_top_right_active_normal; - struct lab_data_buffer *corner_top_left_inactive_normal; - struct lab_data_buffer *corner_top_right_inactive_normal; - - struct lab_data_buffer *shadow_corner_top_active; - struct lab_data_buffer *shadow_corner_bottom_active; - struct lab_data_buffer *shadow_edge_active; - struct lab_data_buffer *shadow_corner_top_inactive; - struct lab_data_buffer *shadow_corner_bottom_inactive; - struct lab_data_buffer *shadow_edge_inactive; - /* * Not set in rc.xml/themerc, but derived from the tallest titlebar * object plus 2 * window_titlebar_padding_height diff --git a/src/ssd/ssd-border.c b/src/ssd/ssd-border.c index aa7c4d5f..435119e2 100644 --- a/src/ssd/ssd-border.c +++ b/src/ssd/ssd-border.c @@ -27,6 +27,7 @@ ssd_border_create(struct ssd *ssd) float *color; struct wlr_scene_tree *parent; struct ssd_sub_tree *subtree; + int active; ssd->border.tree = wlr_scene_tree_create(ssd->tree); wlr_scene_node_set_position(&ssd->border.tree->node, -theme->border_width, 0); @@ -34,12 +35,11 @@ ssd_border_create(struct ssd *ssd) FOR_EACH_STATE(ssd, subtree) { subtree->tree = wlr_scene_tree_create(ssd->border.tree); parent = subtree->tree; - if (subtree == &ssd->border.active) { - color = theme->window_active_border_color; - } else { - color = theme->window_inactive_border_color; - wlr_scene_node_set_enabled(&parent->node, false); - } + active = (subtree == &ssd->border.active) ? + THEME_ACTIVE : THEME_INACTIVE; + wlr_scene_node_set_enabled(&parent->node, active); + color = theme->window[active].border_color; + wl_list_init(&subtree->parts); add_scene_rect(&subtree->parts, LAB_SSD_PART_LEFT, parent, theme->border_width, height, 0, 0, color); diff --git a/src/ssd/ssd-shadow.c b/src/ssd/ssd-shadow.c index dfd18bd2..34dec3a9 100644 --- a/src/ssd/ssd-shadow.c +++ b/src/ssd/ssd-shadow.c @@ -181,10 +181,9 @@ set_shadow_geometry(struct ssd *ssd) continue; } - bool active = subtree == &ssd->shadow.active; - int visible_shadow_width = active - ? theme->window_active_shadow_size - : theme->window_inactive_shadow_size; + int active = (subtree == &ssd->shadow.active) ? + THEME_ACTIVE : THEME_INACTIVE; + int visible_shadow_width = theme->window[active].shadow_size; /* inset as a proportion of shadow width */ double inset_proportion = SSD_SHADOW_INSET; /* inset in actual pixels */ @@ -195,9 +194,8 @@ set_shadow_geometry(struct ssd *ssd) * portion. Top and bottom are the same size (only the cutout * is different). The buffers are square so width == height. */ - int corner_size = active - ? theme->shadow_corner_top_active->logical_height - : theme->shadow_corner_top_inactive->logical_height; + int corner_size = + theme->window[active].shadow_corner_top->logical_height; wl_list_for_each(part, &subtree->parts, link) { set_shadow_part_geometry(part, width, height, @@ -239,6 +237,7 @@ ssd_shadow_create(struct ssd *ssd) struct wlr_buffer *edge_buffer; struct ssd_sub_tree *subtree; struct wlr_scene_tree *parent; + int active; FOR_EACH_STATE(ssd, subtree) { wl_list_init(&subtree->parts); @@ -246,29 +245,19 @@ ssd_shadow_create(struct ssd *ssd) if (!rc.shadows_enabled) { /* Shadows are globally disabled */ continue; - } else if (subtree == &ssd->shadow.active) { - if (theme->window_active_shadow_size == 0) { - /* Active window shadows are disabled */ - continue; - } - } else { - if (theme->window_inactive_shadow_size == 0) { - /* Inactive window shadows are disabled */ - continue; - } + } + active = (subtree == &ssd->shadow.active) ? + THEME_ACTIVE : THEME_INACTIVE; + if (theme->window[active].shadow_size == 0) { + /* Window shadows are disabled */ + continue; } subtree->tree = wlr_scene_tree_create(ssd->shadow.tree); parent = subtree->tree; - if (subtree == &ssd->shadow.active) { - corner_top_buffer = &theme->shadow_corner_top_active->base; - corner_bottom_buffer = &theme->shadow_corner_bottom_active->base; - edge_buffer = &theme->shadow_edge_active->base; - } else { - corner_top_buffer = &theme->shadow_corner_top_inactive->base; - corner_bottom_buffer = &theme->shadow_corner_bottom_inactive->base; - edge_buffer = &theme->shadow_edge_inactive->base; - } + corner_top_buffer = &theme->window[active].shadow_corner_top->base; + corner_bottom_buffer = &theme->window[active].shadow_corner_bottom->base; + edge_buffer = &theme->window[active].shadow_edge->base; make_shadow(&subtree->parts, LAB_SSD_PART_CORNER_BOTTOM_RIGHT, parent, diff --git a/src/ssd/ssd-titlebar.c b/src/ssd/ssd-titlebar.c index 8591759a..3c1c92b9 100644 --- a/src/ssd/ssd-titlebar.c +++ b/src/ssd/ssd-titlebar.c @@ -38,6 +38,7 @@ ssd_titlebar_create(struct ssd *ssd) struct wlr_scene_tree *parent; struct wlr_buffer *corner_top_left; struct wlr_buffer *corner_top_right; + int active; ssd->titlebar.tree = wlr_scene_tree_create(ssd->tree); @@ -45,18 +46,13 @@ ssd_titlebar_create(struct ssd *ssd) FOR_EACH_STATE(ssd, subtree) { subtree->tree = wlr_scene_tree_create(ssd->titlebar.tree); parent = subtree->tree; + active = (subtree == &ssd->titlebar.active) ? + THEME_ACTIVE : THEME_INACTIVE; + color = theme->window[active].title_bg_color; + corner_top_left = &theme->window[active].corner_top_left_normal->base; + corner_top_right = &theme->window[active].corner_top_right_normal->base; + wlr_scene_node_set_enabled(&parent->node, active); wlr_scene_node_set_position(&parent->node, 0, -theme->title_height); - if (subtree == &ssd->titlebar.active) { - color = theme->window_active_title_bg_color; - corner_top_left = &theme->corner_top_left_active_normal->base; - corner_top_right = &theme->corner_top_right_active_normal->base; - } else { - color = theme->window_inactive_title_bg_color; - corner_top_left = &theme->corner_top_left_inactive_normal->base; - corner_top_right = &theme->corner_top_right_inactive_normal->base; - - wlr_scene_node_set_enabled(&parent->node, false); - } wl_list_init(&subtree->parts); /* Background */ @@ -69,9 +65,6 @@ ssd_titlebar_create(struct ssd *ssd) corner_top_right, width - corner_width, -rc.theme->border_width); - int active = (subtree == &ssd->titlebar.active) ? - THEME_ACTIVE : THEME_INACTIVE; - /* Buttons */ struct title_button *b; int x = theme->window_titlebar_padding_width; @@ -474,23 +467,19 @@ ssd_update_title(struct ssd *ssd) struct ssd_part *part; struct ssd_sub_tree *subtree; struct ssd_state_title_width *dstate; + int active; int offset_left, offset_right; get_title_offsets(ssd, &offset_left, &offset_right); int title_bg_width = view->current.width - offset_left - offset_right; FOR_EACH_STATE(ssd, subtree) { - if (subtree == &ssd->titlebar.active) { - dstate = &state->active; - text_color = theme->window_active_label_text_color; - bg_color = theme->window_active_title_bg_color; - font = &rc.font_activewindow; - } else { - dstate = &state->inactive; - text_color = theme->window_inactive_label_text_color; - bg_color = theme->window_inactive_title_bg_color; - font = &rc.font_inactivewindow; - } + active = (subtree == &ssd->titlebar.active) ? + THEME_ACTIVE : THEME_INACTIVE; + dstate = active ? &state->active : &state->inactive; + text_color = theme->window[active].label_text_color; + bg_color = theme->window[active].title_bg_color; + font = &rc.font_activewindow; if (title_bg_width <= 0) { dstate->truncated = true; diff --git a/src/ssd/ssd.c b/src/ssd/ssd.c index a9fc1abc..149bf586 100644 --- a/src/ssd/ssd.c +++ b/src/ssd/ssd.c @@ -404,7 +404,7 @@ ssd_enable_keybind_inhibit_indicator(struct ssd *ssd, bool enable) float *color = enable ? rc.theme->window_toggled_keybinds_color - : rc.theme->window_active_border_color; + : rc.theme->window[THEME_ACTIVE].border_color; struct ssd_part *part = ssd_get_part(&ssd->border.active.parts, LAB_SSD_PART_TOP); struct wlr_scene_rect *rect = wlr_scene_rect_from_node(part->node); diff --git a/src/theme.c b/src/theme.c index 8f5e3d0e..05c668b9 100644 --- a/src/theme.c +++ b/src/theme.c @@ -564,16 +564,16 @@ theme_builtin(struct theme *theme, struct server *server) theme->window_titlebar_padding_width = 0; theme->title_height = INT_MIN; - parse_hexstr("#e1dedb", theme->window_active_border_color); - parse_hexstr("#f6f5f4", theme->window_inactive_border_color); + parse_hexstr("#e1dedb", theme->window[THEME_ACTIVE].border_color); + parse_hexstr("#f6f5f4", theme->window[THEME_INACTIVE].border_color); parse_hexstr("#ff0000", theme->window_toggled_keybinds_color); - parse_hexstr("#e1dedb", theme->window_active_title_bg_color); - parse_hexstr("#f6f5f4", theme->window_inactive_title_bg_color); + parse_hexstr("#e1dedb", theme->window[THEME_ACTIVE].title_bg_color); + parse_hexstr("#f6f5f4", theme->window[THEME_INACTIVE].title_bg_color); - parse_hexstr("#000000", theme->window_active_label_text_color); - parse_hexstr("#000000", theme->window_inactive_label_text_color); + parse_hexstr("#000000", theme->window[THEME_ACTIVE].label_text_color); + parse_hexstr("#000000", theme->window[THEME_INACTIVE].label_text_color); theme->window_label_text_justify = parse_justification("Center"); theme->window_button_width = 26; @@ -589,10 +589,10 @@ theme_builtin(struct theme *theme, struct server *server) theme->window[THEME_ACTIVE].button_colors[type]); } - theme->window_active_shadow_size = 60; - theme->window_inactive_shadow_size = 40; - parse_hexstr("#00000060", theme->window_active_shadow_color); - parse_hexstr("#00000040", theme->window_inactive_shadow_color); + theme->window[THEME_ACTIVE].shadow_size = 60; + theme->window[THEME_INACTIVE].shadow_size = 40; + parse_hexstr("#00000060", theme->window[THEME_ACTIVE].shadow_color); + parse_hexstr("#00000040", theme->window[THEME_INACTIVE].shadow_color); theme->menu_overlap_x = 0; theme->menu_overlap_y = 0; @@ -708,15 +708,15 @@ entry(struct theme *theme, const char *key, const char *value) } if (match_glob(key, "window.active.border.color")) { - parse_hexstr(value, theme->window_active_border_color); + parse_hexstr(value, theme->window[THEME_ACTIVE].border_color); } if (match_glob(key, "window.inactive.border.color")) { - parse_hexstr(value, theme->window_inactive_border_color); + parse_hexstr(value, theme->window[THEME_INACTIVE].border_color); } /* border.color is obsolete, but handled for backward compatibility */ if (match_glob(key, "border.color")) { - parse_hexstr(value, theme->window_active_border_color); - parse_hexstr(value, theme->window_inactive_border_color); + parse_hexstr(value, theme->window[THEME_ACTIVE].border_color); + parse_hexstr(value, theme->window[THEME_INACTIVE].border_color); } if (match_glob(key, "window.active.indicator.toggled-keybind.color")) { @@ -724,17 +724,17 @@ entry(struct theme *theme, const char *key, const char *value) } if (match_glob(key, "window.active.title.bg.color")) { - parse_hexstr(value, theme->window_active_title_bg_color); + parse_hexstr(value, theme->window[THEME_ACTIVE].title_bg_color); } if (match_glob(key, "window.inactive.title.bg.color")) { - parse_hexstr(value, theme->window_inactive_title_bg_color); + parse_hexstr(value, theme->window[THEME_INACTIVE].title_bg_color); } if (match_glob(key, "window.active.label.text.color")) { - parse_hexstr(value, theme->window_active_label_text_color); + parse_hexstr(value, theme->window[THEME_ACTIVE].label_text_color); } if (match_glob(key, "window.inactive.label.text.color")) { - parse_hexstr(value, theme->window_inactive_label_text_color); + parse_hexstr(value, theme->window[THEME_INACTIVE].label_text_color); } if (match_glob(key, "window.label.text.justify")) { theme->window_label_text_justify = parse_justification(value); @@ -837,18 +837,18 @@ entry(struct theme *theme, const char *key, const char *value) /* window drop-shadows */ if (match_glob(key, "window.active.shadow.size")) { - theme->window_active_shadow_size = get_int_if_positive( + theme->window[THEME_ACTIVE].shadow_size = get_int_if_positive( value, "window.active.shadow.size"); } if (match_glob(key, "window.inactive.shadow.size")) { - theme->window_inactive_shadow_size = get_int_if_positive( + theme->window[THEME_INACTIVE].shadow_size = get_int_if_positive( value, "window.inactive.shadow.size"); } if (match_glob(key, "window.active.shadow.color")) { - parse_hexstr(value, theme->window_active_shadow_color); + parse_hexstr(value, theme->window[THEME_ACTIVE].shadow_color); } if (match_glob(key, "window.inactive.shadow.color")) { - parse_hexstr(value, theme->window_inactive_shadow_color); + parse_hexstr(value, theme->window[THEME_INACTIVE].shadow_color); } if (match_glob(key, "menu.overlap.x")) { @@ -1246,28 +1246,19 @@ create_corners(struct theme *theme) .height = theme->title_height + theme->border_width, }; - struct rounded_corner_ctx ctx = { - .box = &box, - .radius = rc.corner_radius, - .line_width = theme->border_width, - .fill_color = theme->window_active_title_bg_color, - .border_color = theme->window_active_border_color, - .corner = LAB_CORNER_TOP_LEFT, - }; - theme->corner_top_left_active_normal = rounded_rect(&ctx); - - ctx.fill_color = theme->window_inactive_title_bg_color, - ctx.border_color = theme->window_inactive_border_color, - theme->corner_top_left_inactive_normal = rounded_rect(&ctx); - - ctx.corner = LAB_CORNER_TOP_RIGHT; - ctx.fill_color = theme->window_active_title_bg_color, - ctx.border_color = theme->window_active_border_color, - theme->corner_top_right_active_normal = rounded_rect(&ctx); - - ctx.fill_color = theme->window_inactive_title_bg_color, - ctx.border_color = theme->window_inactive_border_color, - theme->corner_top_right_inactive_normal = rounded_rect(&ctx); + for (int active = THEME_INACTIVE; active <= THEME_ACTIVE; active++) { + struct rounded_corner_ctx ctx = { + .box = &box, + .radius = rc.corner_radius, + .line_width = theme->border_width, + .fill_color = theme->window[active].title_bg_color, + .border_color = theme->window[active].border_color, + .corner = LAB_CORNER_TOP_LEFT, + }; + theme->window[active].corner_top_left_normal = rounded_rect(&ctx); + ctx.corner = LAB_CORNER_TOP_RIGHT; + theme->window[active].corner_top_right_normal = rounded_rect(&ctx); + } } /* @@ -1385,68 +1376,50 @@ shadow_corner_gradient(struct lab_data_buffer *buffer, int visible_size, } static void -create_shadows(struct theme *theme) +create_shadow(struct theme *theme, int active) { /* Size of shadow visible extending beyond the window */ - int visible_active_size = theme->window_active_shadow_size; - int visible_inactive_size = theme->window_inactive_shadow_size; + int visible_size = theme->window[active].shadow_size; /* How far inside the window the shadow inset begins */ - int inset_active = (double)visible_active_size * SSD_SHADOW_INSET; - int inset_inactive = (double)visible_inactive_size * SSD_SHADOW_INSET; + int inset = (double)visible_size * SSD_SHADOW_INSET; /* Total width including visible and obscured portion */ - int total_active_size = visible_active_size + inset_active; - int total_inactive_size = visible_inactive_size + inset_inactive; + int total_size = visible_size + inset; /* * Edge shadows don't need to be inset so the buffers are sized just for * the visible width. Corners are inset so the buffers are larger for * this. */ - if (visible_active_size > 0) { - theme->shadow_edge_active = buffer_create_cairo( - visible_active_size, 1, 1.0); - theme->shadow_corner_top_active = buffer_create_cairo( - total_active_size, total_active_size, 1.0); - theme->shadow_corner_bottom_active = buffer_create_cairo( - total_active_size, total_active_size, 1.0); - if (!theme->shadow_corner_top_active - || !theme->shadow_corner_bottom_active - || !theme->shadow_edge_active) { - wlr_log(WLR_ERROR, "Failed to allocate shadow buffer"); - return; - } - } - if (visible_inactive_size > 0) { - theme->shadow_edge_inactive = buffer_create_cairo( - visible_inactive_size, 1, 1.0); - theme->shadow_corner_top_inactive = buffer_create_cairo( - total_inactive_size, total_inactive_size, 1.0); - theme->shadow_corner_bottom_inactive = buffer_create_cairo( - total_inactive_size, total_inactive_size, 1.0); - if (!theme->shadow_corner_top_inactive - || !theme->shadow_corner_bottom_inactive - || !theme->shadow_edge_inactive) { + if (visible_size > 0) { + theme->window[active].shadow_edge = buffer_create_cairo( + visible_size, 1, 1.0); + theme->window[active].shadow_corner_top = buffer_create_cairo( + total_size, total_size, 1.0); + theme->window[active].shadow_corner_bottom = buffer_create_cairo( + total_size, total_size, 1.0); + if (!theme->window[active].shadow_corner_top + || !theme->window[active].shadow_corner_bottom + || !theme->window[active].shadow_edge) { wlr_log(WLR_ERROR, "Failed to allocate shadow buffer"); return; } } - shadow_edge_gradient(theme->shadow_edge_active, visible_active_size, - total_active_size, theme->window_active_shadow_color); - shadow_edge_gradient(theme->shadow_edge_inactive, visible_inactive_size, - total_inactive_size, theme->window_inactive_shadow_color); - shadow_corner_gradient(theme->shadow_corner_top_active, - visible_active_size, total_active_size, - theme->title_height, theme->window_active_shadow_color); - shadow_corner_gradient(theme->shadow_corner_bottom_active, - visible_active_size, total_active_size, 0, - theme->window_active_shadow_color); - shadow_corner_gradient(theme->shadow_corner_top_inactive, - visible_inactive_size, total_inactive_size, - theme->title_height, theme->window_inactive_shadow_color); - shadow_corner_gradient(theme->shadow_corner_bottom_inactive, - visible_inactive_size, total_inactive_size, 0, - theme->window_inactive_shadow_color); + shadow_edge_gradient(theme->window[active].shadow_edge, visible_size, + total_size, theme->window[active].shadow_color); + shadow_corner_gradient(theme->window[active].shadow_corner_top, + visible_size, total_size, + theme->title_height, theme->window[active].shadow_color); + shadow_corner_gradient(theme->window[active].shadow_corner_bottom, + visible_size, total_size, 0, + theme->window[active].shadow_color); +} + +static void +create_shadows(struct theme *theme) +{ + create_shadow(theme, THEME_INACTIVE); + create_shadow(theme, THEME_ACTIVE); } static void @@ -1504,7 +1477,7 @@ post_processing(struct theme *theme) /* Inherit OSD settings if not set */ if (theme->osd_bg_color[0] == FLT_MIN) { memcpy(theme->osd_bg_color, - theme->window_active_title_bg_color, + theme->window[THEME_ACTIVE].title_bg_color, sizeof(theme->osd_bg_color)); } if (theme->osd_border_width == INT_MIN) { @@ -1512,19 +1485,19 @@ post_processing(struct theme *theme) } if (theme->osd_label_text_color[0] == FLT_MIN) { memcpy(theme->osd_label_text_color, - theme->window_active_label_text_color, + theme->window[THEME_ACTIVE].label_text_color, sizeof(theme->osd_label_text_color)); } if (theme->osd_border_color[0] == FLT_MIN) { /* * As per https://openbox.org/help/Themes#osd.border.color - * we should fall back to window_active_border_color but - * that is usually the same as window_active_title_bg_color - * and thus the fallback for osd_bg_color. Which would mean + * we should fall back to window.active.border.color but + * that is usually the same as window.active.title.bg.color + * and thus the fallback for osd.bg.color. Which would mean * they are both the same color and thus the border is invisible. * - * Instead, we fall back to osd_label_text_color which in turn - * falls back to window_active_label_text_color. + * Instead, we fall back to osd.label.text.color which in turn + * falls back to window.active.label.text.color. */ memcpy(theme->osd_border_color, theme->osd_label_text_color, sizeof(theme->osd_border_color)); @@ -1606,15 +1579,11 @@ theme_finish(struct theme *theme) } } - zdrop(&theme->corner_top_left_active_normal); - zdrop(&theme->corner_top_left_inactive_normal); - zdrop(&theme->corner_top_right_active_normal); - zdrop(&theme->corner_top_right_inactive_normal); - - zdrop(&theme->shadow_corner_top_active); - zdrop(&theme->shadow_corner_bottom_active); - zdrop(&theme->shadow_edge_active); - zdrop(&theme->shadow_corner_top_inactive); - zdrop(&theme->shadow_corner_bottom_inactive); - zdrop(&theme->shadow_edge_inactive); + for (int active = THEME_INACTIVE; active <= THEME_ACTIVE; active++) { + zdrop(&theme->window[active].corner_top_left_normal); + zdrop(&theme->window[active].corner_top_right_normal); + zdrop(&theme->window[active].shadow_corner_top); + zdrop(&theme->window[active].shadow_corner_bottom); + zdrop(&theme->window[active].shadow_edge); + } }