Implement shadow_offset (#255)

This commit is contained in:
famfo 2023-12-22 06:08:09 +00:00 committed by GitHub
parent 5e866d0345
commit ca42d41453
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 64 additions and 27 deletions

View file

@ -36,6 +36,7 @@ Sway is an incredible window manager, and certainly one of the most well establi
- `shadows_on_csd enable|disable` (**Note**: The shadow might not fit some windows) - `shadows_on_csd enable|disable` (**Note**: The shadow might not fit some windows)
- `shadow_blur_radius <integer value 0 - 100>` - `shadow_blur_radius <integer value 0 - 100>`
- `shadow_color <hex color with alpha> ex, #0000007F` - `shadow_color <hex color with alpha> ex, #0000007F`
- `shadow_offset <x offset> <y offset>`
- `shadow_inactive_color <hex color with alpha> ex, #0000007F` - `shadow_inactive_color <hex color with alpha> ex, #0000007F`
+ LayerShell effects (to blur panels / notifications etc): + LayerShell effects (to blur panels / notifications etc):
- `layer_effects <layer namespace> <effects>` - `layer_effects <layer namespace> <effects>`

View file

@ -192,6 +192,7 @@ sway_cmd cmd_set;
sway_cmd cmd_shortcuts_inhibitor; sway_cmd cmd_shortcuts_inhibitor;
sway_cmd cmd_shadow_blur_radius; sway_cmd cmd_shadow_blur_radius;
sway_cmd cmd_shadow_color; sway_cmd cmd_shadow_color;
sway_cmd cmd_shadow_offset;
sway_cmd cmd_shadow_inactive_color; sway_cmd cmd_shadow_inactive_color;
sway_cmd cmd_shadows; sway_cmd cmd_shadows;
sway_cmd cmd_shadows_on_csd; sway_cmd cmd_shadows_on_csd;

View file

@ -493,6 +493,7 @@ struct sway_config {
int shadow_blur_sigma; int shadow_blur_sigma;
float shadow_color[4]; float shadow_color[4];
float shadow_inactive_color[4]; float shadow_inactive_color[4];
float shadow_offset_x, shadow_offset_y;
bool blur_enabled; bool blur_enabled;
bool blur_xray; bool blur_xray;

View file

@ -207,8 +207,8 @@ void fx_render_border_corner(struct fx_renderer *renderer, const struct wlr_box
enum corner_location corner_location, int radius, int border_thickness); enum corner_location corner_location, int radius, int border_thickness);
void fx_render_box_shadow(struct fx_renderer *renderer, const struct wlr_box *box, void fx_render_box_shadow(struct fx_renderer *renderer, const struct wlr_box *box,
const float color[static 4], const float matrix[static 9], int radius, const struct wlr_box *inner_box, const float color[static 4],
float blur_sigma); const float matrix[static 9], int corner_radius, float blur_sigma);
void fx_render_blur(struct fx_renderer *renderer, const float matrix[static 9], void fx_render_blur(struct fx_renderer *renderer, const float matrix[static 9],
struct fx_framebuffer **buffer, struct blur_shader *shader, const struct wlr_box *box, struct fx_framebuffer **buffer, struct blur_shader *shader, const struct wlr_box *box,

View file

@ -96,6 +96,7 @@ static const struct cmd_handler handlers[] = {
{ "set", cmd_set }, { "set", cmd_set },
{ "shadow_blur_radius", cmd_shadow_blur_radius }, { "shadow_blur_radius", cmd_shadow_blur_radius },
{ "shadow_color", cmd_shadow_color }, { "shadow_color", cmd_shadow_color },
{ "shadow_offset", cmd_shadow_offset },
{ "shadow_inactive_color", cmd_shadow_inactive_color }, { "shadow_inactive_color", cmd_shadow_inactive_color },
{ "shadows", cmd_shadows }, { "shadows", cmd_shadows },
{ "shadows_on_csd", cmd_shadows_on_csd }, { "shadows_on_csd", cmd_shadows_on_csd },

View file

@ -0,0 +1,27 @@
#include <string.h>
#include "log.h"
#include "sway/commands.h"
#include "sway/config.h"
struct cmd_results *cmd_shadow_offset(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "shadow_offset", EXPECTED_AT_LEAST, 2))) {
return error;
}
char *err;
float offset_x = strtof(argv[0], &err);
float offset_y = strtof(argv[1], &err);
if (*err || offset_x < -99.9f || offset_x > 99.9f) {
return cmd_results_new(CMD_INVALID, "x offset float invalid");
}
if (*err || offset_y < -99.9f || offset_y > 99.9f) {
return cmd_results_new(CMD_INVALID, "y offset float invalid");
}
config->shadow_offset_x = offset_x;
config->shadow_offset_y = offset_y;
return cmd_results_new(CMD_SUCCESS, NULL);
}

View file

@ -351,6 +351,8 @@ static void config_defaults(struct sway_config *config) {
config->shadow_enabled = false; config->shadow_enabled = false;
config->shadows_on_csd_enabled = false; config->shadows_on_csd_enabled = false;
config->shadow_blur_sigma = 20.0f; config->shadow_blur_sigma = 20.0f;
config->shadow_offset_x = 0.0f;
config->shadow_offset_y = 0.0f;
color_to_rgba(config->shadow_color, 0x0000007F); color_to_rgba(config->shadow_color, 0x0000007F);
color_to_rgba(config->shadow_inactive_color, 0x0000007F); color_to_rgba(config->shadow_inactive_color, 0x0000007F);

View file

@ -799,8 +799,8 @@ void fx_render_stencil_mask(struct fx_renderer *renderer, const struct wlr_box *
// TODO: alpha input arg? // TODO: alpha input arg?
void fx_render_box_shadow(struct fx_renderer *renderer, const struct wlr_box *box, void fx_render_box_shadow(struct fx_renderer *renderer, const struct wlr_box *box,
const float color[static 4], const float matrix[static 9], int corner_radius, const struct wlr_box *inner_box, const float color[static 4],
float blur_sigma) { const float matrix[static 9], int corner_radius, float blur_sigma) {
if (box->width == 0 || box->height == 0) { if (box->width == 0 || box->height == 0) {
return; return;
} }
@ -821,17 +821,9 @@ void fx_render_box_shadow(struct fx_renderer *renderer, const struct wlr_box *bo
wlr_matrix_transpose(gl_matrix, gl_matrix); wlr_matrix_transpose(gl_matrix, gl_matrix);
// Init stencil work
struct wlr_box inner_box;
memcpy(&inner_box, box, sizeof(struct wlr_box));
inner_box.x += blur_sigma;
inner_box.y += blur_sigma;
inner_box.width -= blur_sigma * 2;
inner_box.height -= blur_sigma * 2;
fx_renderer_stencil_mask_init(); fx_renderer_stencil_mask_init();
// Draw the rounded rect as a mask // Draw the rounded rect as a mask
fx_render_stencil_mask(renderer, &inner_box, matrix, corner_radius); fx_render_stencil_mask(renderer, inner_box, matrix, corner_radius);
fx_renderer_stencil_mask_close(false); fx_renderer_stencil_mask_close(false);
// blending will practically always be needed (unless we have a madman // blending will practically always be needed (unless we have a madman

View file

@ -758,8 +758,8 @@ void output_damage_whole_container(struct sway_output *output,
// Pad the box by 1px, because the width is a double and might be a fraction // Pad the box by 1px, because the width is a double and might be a fraction
struct wlr_box box = { struct wlr_box box = {
.x = con->current.x - output->lx - 1 - shadow_sigma, .x = con->current.x - output->lx - 1 - shadow_sigma + config->shadow_offset_x,
.y = con->current.y - output->ly - 1 - shadow_sigma, .y = con->current.y - output->ly - 1 - shadow_sigma + config->shadow_offset_y,
.width = con->current.width + 2 + shadow_sigma * 2, .width = con->current.width + 2 + shadow_sigma * 2,
.height = con->current.height + 2 + shadow_sigma * 2, .height = con->current.height + 2 + shadow_sigma * 2,
}; };

View file

@ -342,15 +342,15 @@ damage_finish:
// _box.x and .y are expected to be layout-local // _box.x and .y are expected to be layout-local
// _box.width and .height are expected to be output-buffer-local // _box.width and .height are expected to be output-buffer-local
void render_box_shadow(struct sway_output *output, pixman_region32_t *output_damage, void render_box_shadow(struct sway_output *output, pixman_region32_t *output_damage,
const struct wlr_box *_box, const float color[static 4], const struct wlr_box *_box, const float color[static 4], float blur_sigma,
float blur_sigma, float corner_radius) { float corner_radius, float offset_x, float offset_y) {
struct wlr_output *wlr_output = output->wlr_output; struct wlr_output *wlr_output = output->wlr_output;
struct fx_renderer *renderer = output->renderer; struct fx_renderer *renderer = output->renderer;
struct wlr_box box; struct wlr_box box;
memcpy(&box, _box, sizeof(struct wlr_box)); memcpy(&box, _box, sizeof(struct wlr_box));
box.x -= blur_sigma; box.x -= blur_sigma - offset_x;
box.y -= blur_sigma; box.y -= blur_sigma - offset_y;
box.width += 2 * blur_sigma; box.width += 2 * blur_sigma;
box.height += 2 * blur_sigma; box.height += 2 * blur_sigma;
@ -365,6 +365,7 @@ void render_box_shadow(struct sway_output *output, pixman_region32_t *output_dam
inner_box.height -= 2 * corner_radius; inner_box.height -= 2 * corner_radius;
pixman_region32_t inner_damage = create_damage(inner_box, output_damage); pixman_region32_t inner_damage = create_damage(inner_box, output_damage);
pixman_region32_subtract(&damage, &damage, &inner_damage); pixman_region32_subtract(&damage, &damage, &inner_damage);
pixman_region32_fini(&inner_damage);
bool damaged = pixman_region32_not_empty(&damage); bool damaged = pixman_region32_not_empty(&damage);
if (!damaged) { if (!damaged) {
@ -375,20 +376,23 @@ void render_box_shadow(struct sway_output *output, pixman_region32_t *output_dam
wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0, wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0,
wlr_output->transform_matrix); wlr_output->transform_matrix);
// ensure the box is updated as per the output orientation
struct wlr_box transformed_box;
int width, height; int width, height;
wlr_output_transformed_resolution(wlr_output, &width, &height); wlr_output_transformed_resolution(wlr_output, &width, &height);
wlr_box_transform(&transformed_box, &box, enum wl_output_transform transform = wlr_output_transform_invert(wlr_output->transform);
wlr_output_transform_invert(wlr_output->transform), width, height); // ensure the shadow_box is updated as per the output orientation
struct wlr_box transformed_shadow_box;
wlr_box_transform(&transformed_shadow_box, &box, transform, width, height);
// ensure the box is updated as per the output orientation
struct wlr_box transformed_box;
wlr_box_transform(&transformed_box, _box, transform, width, height);
int nrects; int nrects;
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
for (int i = 0; i < nrects; ++i) { for (int i = 0; i < nrects; ++i) {
scissor_output(wlr_output, &rects[i]); scissor_output(wlr_output, &rects[i]);
fx_render_box_shadow(renderer, &transformed_box, color, matrix, fx_render_box_shadow(renderer, &transformed_shadow_box, &transformed_box,
corner_radius, blur_sigma); color, matrix, corner_radius, blur_sigma);
} }
damage_finish: damage_finish:
@ -488,9 +492,11 @@ static void render_layer_iterator(struct sway_output *output,
// render shadow // render shadow
if (deco_data.shadow && config_should_parameters_shadow()) { if (deco_data.shadow && config_should_parameters_shadow()) {
int corner_radius = deco_data.corner_radius *= output->wlr_output->scale; int corner_radius = deco_data.corner_radius *= output->wlr_output->scale;
int offset_x = config->shadow_offset_x * output->wlr_output->scale;
int offset_y = config->shadow_offset_y * output->wlr_output->scale;
scale_box(_box, output->wlr_output->scale); scale_box(_box, output->wlr_output->scale);
render_box_shadow(output, data->damage, _box, config->shadow_color, render_box_shadow(output, data->damage, _box, config->shadow_color,
config->shadow_blur_sigma, corner_radius); config->shadow_blur_sigma, corner_radius, offset_x, offset_y);
} }
} }
@ -886,8 +892,10 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,
0 : (deco_data.corner_radius + state->border_thickness) * output_scale; 0 : (deco_data.corner_radius + state->border_thickness) * output_scale;
float* shadow_color = view_is_urgent(view) || state->focused ? float* shadow_color = view_is_urgent(view) || state->focused ?
config->shadow_color : config->shadow_inactive_color; config->shadow_color : config->shadow_inactive_color;
int offset_x = config->shadow_offset_x * output->wlr_output->scale;
int offset_y = config->shadow_offset_y * output->wlr_output->scale;
render_box_shadow(output, damage, &box, shadow_color, config->shadow_blur_sigma, render_box_shadow(output, damage, &box, shadow_color, config->shadow_blur_sigma,
scaled_corner_radius); scaled_corner_radius, offset_x, offset_y);
} }
if (state->border == B_NONE || state->border == B_CSD) { if (state->border == B_NONE || state->border == B_CSD) {

View file

@ -123,6 +123,7 @@ sway_sources = files(
'commands/set.c', 'commands/set.c',
'commands/shadow_blur_radius.c', 'commands/shadow_blur_radius.c',
'commands/shadow_color.c', 'commands/shadow_color.c',
'commands/shadow_offset.c',
'commands/shadow_inactive_color.c', 'commands/shadow_inactive_color.c',
'commands/shadows.c', 'commands/shadows.c',
'commands/shadows_on_csd.c', 'commands/shadows_on_csd.c',

View file

@ -689,6 +689,9 @@ The default colors are:
*shadow_inactive_color* <hex color with alpha> *shadow_inactive_color* <hex color with alpha>
The shadow color for inactive windows. Default value: *shadow_color* The shadow color for inactive windows. Default value: *shadow_color*
*shadow_offset* <x offset> <y offset>
Offset all box shadows by the given value.
*blur* enable|disable *blur* enable|disable
Sets whether blur should be drawn. Can also be set per window with Sets whether blur should be drawn. Can also be set per window with
*for_window*. *for_window*.