Implement shadow_offset (#255)
This commit is contained in:
parent
5e866d0345
commit
ca42d41453
|
@ -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>`
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 },
|
||||||
|
|
27
sway/commands/shadow_offset.c
Normal file
27
sway/commands/shadow_offset.c
Normal 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);
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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*.
|
||||||
|
|
Loading…
Reference in a new issue