From: Johan Malm Date: Fri, 16 Jul 2021 16:07:00 +0000 (+0100) Subject: Move corner textures from ssd.c to theme.c X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=e50bb45890354f1657b36a6d0d92e97aab93fc7b;p=proto%2Flabwc.git Move corner textures from ssd.c to theme.c It makes more sense to just keep one set of corner textures for server side view decorations, rather than storing a set for each view. This also keeps the code simpler when when changing theme parameters. --- diff --git a/include/ssd.h b/include/ssd.h index 8a18977d..54d7f105 100644 --- a/include/ssd.h +++ b/include/ssd.h @@ -19,14 +19,26 @@ enum ssd_part_type { struct ssd_part { struct wlr_box box; enum ssd_part_type type; + + /* + * The texture pointers are often held in other places such as the + * theme struct, so here we use ** in order to keep the code + * simple and avoid updating pointers as textures change. + */ struct { - struct wlr_texture *active; - struct wlr_texture *inactive; + struct wlr_texture **active; + struct wlr_texture **inactive; } texture; + + /* + * If a part does not contain textures, it'll just be rendered as a + * rectangle with the following colors. + */ struct { float *active; float *inactive; } color; + struct wl_list link; }; diff --git a/include/theme.h b/include/theme.h index b172cfb9..a00c7b33 100644 --- a/include/theme.h +++ b/include/theme.h @@ -1,7 +1,7 @@ /* - * Theme engine for labwc - trying to be consistent with openbox + * Theme engine for labwc * - * Copyright Johan Malm 2020 + * Copyright Johan Malm 2020-2021 */ #ifndef __LABWC_THEME_H @@ -36,7 +36,12 @@ struct theme { struct wlr_texture *xbm_maximize_inactive_unpressed; struct wlr_texture *xbm_iconify_inactive_unpressed; - /* not set in rc.xml or themerc, but derived from font and padding_height */ + struct wlr_texture *corner_top_left_active_normal; + struct wlr_texture *corner_top_right_active_normal; + struct wlr_texture *corner_top_left_inactive_normal; + struct wlr_texture *corner_top_right_inactive_normal; + + /* not set in rc.xml/themerc, but derived from font & padding_height */ int title_height; }; diff --git a/src/output.c b/src/output.c index 9db24e35..beb13bfe 100644 --- a/src/output.c +++ b/src/output.c @@ -478,16 +478,19 @@ render_deco(struct view *view, struct output *output, struct wlr_seat *seat = view->server->seat.seat; bool focused = view->surface == seat->keyboard_state.focused_surface; + /* render texture or rectangle */ struct ssd_part *part; wl_list_for_each_reverse(part, &view->ssd.parts, link) { - if (part->texture.active) { + if (part->texture.active && *(part->texture.active)) { struct wlr_texture *texture = focused ? - part->texture.active : part->texture.inactive; + *(part->texture.active) : + *(part->texture.inactive); render_texture_helper(output, output_damage, &part->box, texture); } else { float *color = focused ? - part->color.active : part->color.inactive; + part->color.active : + part->color.inactive; render_rect(output, output_damage, &part->box, color); } } diff --git a/src/ssd.c b/src/ssd.c index 606c6ce4..b0e7648c 100644 --- a/src/ssd.c +++ b/src/ssd.c @@ -1,13 +1,10 @@ /* * Helpers for view server side decorations * - * Copyright (C) 2020 Johan Malm + * Copyright (C) Johan Malm 2020-2021 */ #include -#include -#include -#include #include "config/rcxml.h" #include "labwc.h" #include "theme.h" @@ -135,106 +132,6 @@ add_part(struct view *view, enum ssd_part_type type) return part; } -struct rounded_corner_ctx { - struct wlr_box *box; - double radius; - double line_width; - float *fill_color; - float *border_color; - enum { - LAB_CORNER_UNKNOWN = 0, - LAB_CORNER_TOP_LEFT, - LAB_CORNER_TOP_RIGHT, - } corner; -}; - -static void set_source(cairo_t *cairo, float *c) -{ - cairo_set_source_rgba(cairo, c[0], c[1], c[2], c[3]); -} - -static struct wlr_texture * -rounded_rect(struct wlr_renderer *renderer, struct rounded_corner_ctx *ctx) -{ - /* 1 degree in radians (=2π/360) */ - double deg = 0.017453292519943295; - - if (ctx->corner == LAB_CORNER_UNKNOWN) { - return NULL; - } - - double w = ctx->box->width; - double h = ctx->box->height; - double r = ctx->radius; - - cairo_surface_t *surf = - cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); - cairo_t *cairo = cairo_create(surf); - - /* set transparent background */ - cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); - cairo_paint(cairo); - - /* fill */ - cairo_set_line_width(cairo, 0.0); - cairo_new_sub_path(cairo); - switch (ctx->corner) { - case LAB_CORNER_TOP_LEFT: - cairo_arc(cairo, r, r, r, 180 * deg, 270 * deg); - cairo_line_to(cairo, w, 0); - cairo_line_to(cairo, w, h); - cairo_line_to(cairo, 0, h); - break; - case LAB_CORNER_TOP_RIGHT: - cairo_arc(cairo, w - r, r, r, -90 * deg, 0 * deg); - cairo_line_to(cairo, w, h); - cairo_line_to(cairo, 0, h); - cairo_line_to(cairo, 0, 0); - break; - default: - warn("unknown corner type"); - } - cairo_close_path(cairo); - cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); - set_source(cairo, ctx->fill_color); - cairo_fill_preserve(cairo); - cairo_stroke(cairo); - - /* border */ - cairo_set_line_cap(cairo, CAIRO_LINE_CAP_ROUND); - set_source(cairo, ctx->border_color); - cairo_set_line_width(cairo, ctx->line_width); - double half_line_width = ctx->line_width / 2.0; - switch (ctx->corner) { - case LAB_CORNER_TOP_LEFT: - cairo_move_to(cairo, half_line_width, h); - cairo_line_to(cairo, half_line_width, r + half_line_width); - cairo_arc(cairo, r, r, r - half_line_width, 180 * deg, 270 * deg); - cairo_line_to(cairo, w, half_line_width); - break; - case LAB_CORNER_TOP_RIGHT: - cairo_move_to(cairo, 0, half_line_width); - cairo_line_to(cairo, w - r, half_line_width); - cairo_arc(cairo, w - r, r, r - half_line_width, -90 * deg, 0 * deg); - cairo_line_to(cairo, w - half_line_width, h); - break; - default: - warn("unknown corner type"); - } - cairo_stroke(cairo); - - /* convert to wlr_texture */ - cairo_surface_flush(surf); - unsigned char *data = cairo_image_surface_get_data(surf); - struct wlr_texture *texture = wlr_texture_from_pixels(renderer, - DRM_FORMAT_ARGB8888, cairo_image_surface_get_stride(surf), - w, h, data); - - cairo_destroy(cairo); - cairo_surface_destroy(surf); - return texture; -} - void ssd_create(struct view *view) { @@ -266,38 +163,17 @@ ssd_create(struct view *view) part->color.active = theme->window_active_title_bg_color; part->color.inactive = theme->window_inactive_title_bg_color; - /* titlebar active top left corner */ - struct wlr_renderer *renderer = view->server->renderer; + /* titlebar top-left corner */ part = add_part(view, LAB_SSD_PART_CORNER_TOP_LEFT); part->box = ssd_box(view, part->type); - struct rounded_corner_ctx ctx = { - .box = &part->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, - }; - part->texture.active = rounded_rect(renderer, &ctx); - - /* titlebar inactive top left corner */ - ctx.fill_color = theme->window_inactive_title_bg_color, - ctx.border_color = theme->window_inactive_border_color, - part->texture.inactive = rounded_rect(renderer, &ctx); + part->texture.active = &theme->corner_top_left_active_normal; + part->texture.inactive = &theme->corner_top_left_inactive_normal; - /* titlebar active top right corner */ + /* titlebar top-right corner */ part = add_part(view, LAB_SSD_PART_CORNER_TOP_RIGHT); part->box = ssd_box(view, part->type); - ctx.box = &part->box; - ctx.corner = LAB_CORNER_TOP_RIGHT; - ctx.fill_color = theme->window_active_title_bg_color, - ctx.border_color = theme->window_active_border_color, - part->texture.active = rounded_rect(renderer, &ctx); - - /* titlebar inactive top right corner */ - ctx.fill_color = theme->window_inactive_title_bg_color, - ctx.border_color = theme->window_inactive_border_color, - part->texture.inactive = rounded_rect(renderer, &ctx); + part->texture.active = &theme->corner_top_right_active_normal; + part->texture.inactive = &theme->corner_top_right_inactive_normal; } void diff --git a/src/theme.c b/src/theme.c index d2abea91..20cc34ae 100644 --- a/src/theme.c +++ b/src/theme.c @@ -1,10 +1,20 @@ +/* + * Theme engine for labwc + * + * Copyright (C) Johan Malm 2020-2021 + */ + #define _POSIX_C_SOURCE 200809L +#include #include +#include #include +#include #include #include #include #include +#include #include "common/dir.h" #include "common/font.h" @@ -197,6 +207,141 @@ theme_read(struct theme *theme, const char *theme_name) fclose(stream); } +struct rounded_corner_ctx { + struct wlr_box *box; + double radius; + double line_width; + float *fill_color; + float *border_color; + enum { + LAB_CORNER_UNKNOWN = 0, + LAB_CORNER_TOP_LEFT, + LAB_CORNER_TOP_RIGHT, + } corner; +}; + +static void set_source(cairo_t *cairo, float *c) +{ + cairo_set_source_rgba(cairo, c[0], c[1], c[2], c[3]); +} + +static struct wlr_texture * +rounded_rect(struct wlr_renderer *renderer, struct rounded_corner_ctx *ctx) +{ + /* 1 degree in radians (=2π/360) */ + double deg = 0.017453292519943295; + + if (ctx->corner == LAB_CORNER_UNKNOWN) { + return NULL; + } + + double w = ctx->box->width; + double h = ctx->box->height; + double r = ctx->radius; + + cairo_surface_t *surf = + cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); + cairo_t *cairo = cairo_create(surf); + + /* set transparent background */ + cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); + cairo_paint(cairo); + + /* fill */ + cairo_set_line_width(cairo, 0.0); + cairo_new_sub_path(cairo); + switch (ctx->corner) { + case LAB_CORNER_TOP_LEFT: + cairo_arc(cairo, r, r, r, 180 * deg, 270 * deg); + cairo_line_to(cairo, w, 0); + cairo_line_to(cairo, w, h); + cairo_line_to(cairo, 0, h); + break; + case LAB_CORNER_TOP_RIGHT: + cairo_arc(cairo, w - r, r, r, -90 * deg, 0 * deg); + cairo_line_to(cairo, w, h); + cairo_line_to(cairo, 0, h); + cairo_line_to(cairo, 0, 0); + break; + default: + warn("unknown corner type"); + } + cairo_close_path(cairo); + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); + set_source(cairo, ctx->fill_color); + cairo_fill_preserve(cairo); + cairo_stroke(cairo); + + /* border */ + cairo_set_line_cap(cairo, CAIRO_LINE_CAP_ROUND); + set_source(cairo, ctx->border_color); + cairo_set_line_width(cairo, ctx->line_width); + double half_line_width = ctx->line_width / 2.0; + switch (ctx->corner) { + case LAB_CORNER_TOP_LEFT: + cairo_move_to(cairo, half_line_width, h); + cairo_line_to(cairo, half_line_width, r + half_line_width); + cairo_arc(cairo, r, r, r - half_line_width, 180 * deg, 270 * deg); + cairo_line_to(cairo, w, half_line_width); + break; + case LAB_CORNER_TOP_RIGHT: + cairo_move_to(cairo, 0, half_line_width); + cairo_line_to(cairo, w - r, half_line_width); + cairo_arc(cairo, w - r, r, r - half_line_width, -90 * deg, 0 * deg); + cairo_line_to(cairo, w - half_line_width, h); + break; + default: + warn("unknown corner type"); + } + cairo_stroke(cairo); + + /* convert to wlr_texture */ + cairo_surface_flush(surf); + unsigned char *data = cairo_image_surface_get_data(surf); + struct wlr_texture *texture = wlr_texture_from_pixels(renderer, + DRM_FORMAT_ARGB8888, cairo_image_surface_get_stride(surf), + w, h, data); + + cairo_destroy(cairo); + cairo_surface_destroy(surf); + return texture; +} + +static void +create_corners(struct theme *theme, struct wlr_renderer *renderer) +{ + int corner_square = theme->title_height + theme->border_width; + struct wlr_box box = { + .x = 0, + .y = 0, + .width = corner_square, + .height = corner_square, + }; + + 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(renderer, &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(renderer, &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(renderer, &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(renderer, &ctx); +} + static void post_processing(struct theme *theme) { @@ -216,8 +361,9 @@ theme_init(struct theme *theme, struct wlr_renderer *renderer, const char *theme_name) { theme_read(theme, theme_name); - xbm_load(theme, renderer); post_processing(theme); + create_corners(theme, renderer); + xbm_load(theme, renderer); } void