Skip to content

Commit

Permalink
Add blur, shadow, and corner radius to layer-shell surfaces (#144)
Browse files Browse the repository at this point in the history
Co-authored-by: Will McKinnon <contact@willmckinnon.com>
  • Loading branch information
ErikReider and WillPower3309 committed May 19, 2023
1 parent 6707842 commit 415e072
Show file tree
Hide file tree
Showing 22 changed files with 456 additions and 78 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ Sway is an incredible window manager, and certainly one of the most well establi
- `blur_xray enable|disable`
- `blur_passes <integer value 0 - 10>`
- `blur_radius <integer value 0 - 10>`
+ LayerShell effects: *ONLY ON SWAYFX-GIT, NOT YET RELEASED*
- `layer_effects <layer namespace> <effects>`
- Example: `layer_effects "waybar" blur enable; shadows enable; corner_radius 6`
- SwayIPC Example: `swaymsg "layer_effects 'waybar' 'blur enable; shadows enable; corner_radius 6'"`
- Available Effects:
- `blur <enable|disable>`
- `shadows <enable|disable>`
- `corner_radius <int>`
+ Dim unfocused windows:
- `default_dim_inactive <float value 0.0 - 1.0>`
- `for_window [CRITERIA_HERE] dim_inactive <float value 0.0 - 1.0>`
Expand Down
6 changes: 6 additions & 0 deletions include/sway/commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ void container_resize_tiled(struct sway_container *parent, uint32_t axis,
struct sway_container *container_find_resize_parent(struct sway_container *con,
uint32_t edge);

/**
* Effect handlers value parsers
*/
bool cmd_corner_radius_parse_value(char *arg, int* result);

/**
* Handlers shared by exec and exec_always.
*/
Expand Down Expand Up @@ -157,6 +162,7 @@ sway_cmd cmd_input;
sway_cmd cmd_seat;
sway_cmd cmd_ipc;
sway_cmd cmd_kill;
sway_cmd cmd_layer_effects;
sway_cmd cmd_layout;
sway_cmd cmd_log_colors;
sway_cmd cmd_mark;
Expand Down
4 changes: 4 additions & 0 deletions include/sway/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,8 @@ struct sway_config {
bool titlebar_separator;
bool scratchpad_minimize;

list_t *layer_criteria;

char *swaynag_command;
struct swaynag_instance swaynag_config_errors;
list_t *symbols;
Expand Down Expand Up @@ -765,6 +767,8 @@ int config_get_blur_size();

bool config_should_parameters_blur();

bool config_should_parameters_shadow();

/* Global config singleton. */
extern struct sway_config *config;

Expand Down
1 change: 1 addition & 0 deletions include/sway/desktop/fx_renderer/fx_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ struct decoration_data {
float *dim_color;
bool has_titlebar;
bool blur;
bool shadow;
};

struct blur_shader {
Expand Down
20 changes: 20 additions & 0 deletions include/sway/layer_criteria.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include <stdbool.h>
#include "sway/layers.h"
#include "sway/config.h"

struct layer_criteria {
char *namespace;
char *cmdlist;
};

void layer_criteria_destroy(struct layer_criteria *criteria);

bool layer_criteria_is_equal(struct layer_criteria *a, struct layer_criteria *b);

bool layer_criteria_already_exists(struct layer_criteria *criteria);

// Gathers all of the matching criterias for a specified `sway_layer_surface`
list_t *layer_criterias_for_sway_layer_surface(struct sway_layer_surface *sway_layer);

// Parses the `layer_criteria` and applies the effects to the `sway_layer_surface`
void layer_criteria_parse(struct sway_layer_surface *sway_layer, struct layer_criteria *criteria);
4 changes: 4 additions & 0 deletions include/sway/layers.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ struct sway_layer_surface {
enum zwlr_layer_shell_v1_layer layer;

struct wl_list subsurfaces;

bool has_shadow;
bool has_blur;
int corner_radius;
};

struct sway_layer_popup {
Expand Down
6 changes: 6 additions & 0 deletions include/sway/output.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
struct sway_server;
struct sway_container;

struct render_data {
pixman_region32_t *damage;
struct wlr_box *clip_box;
struct decoration_data deco_data;
};

struct sway_output_state {
list_t *workspaces;
struct sway_workspace *active_workspace;
Expand Down
1 change: 1 addition & 0 deletions sway/commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ static const struct cmd_handler handlers[] = {
{ "gaps", cmd_gaps },
{ "hide_edge_borders", cmd_hide_edge_borders },
{ "input", cmd_input },
{ "layer_effects", cmd_layer_effects },
{ "mode", cmd_mode },
{ "mouse_warping", cmd_mouse_warping },
{ "new_float", cmd_new_float },
Expand Down
2 changes: 1 addition & 1 deletion sway/commands/blur.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct cmd_results *cmd_blur(int argc, char **argv) {

struct sway_container *con = config->handler_context.container;

bool result = parse_boolean(argv[0], config->blur_enabled);
bool result = parse_boolean(argv[0], true);
if (con == NULL) {
config->blur_enabled = result;
} else {
Expand Down
15 changes: 12 additions & 3 deletions sway/commands/corner_radius.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,24 @@
#include "sway/tree/container.h"
#include "log.h"

bool cmd_corner_radius_parse_value(char *arg, int* result) {
char *inv;
int value = strtol(arg, &inv, 10);
if (*inv != '\0' || value < 0 || value > 99) {
return false;
}
*result = value;
return true;
}

struct cmd_results *cmd_corner_radius(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "corner_radius", EXPECTED_EQUAL_TO, 1))) {
return error;
}

char *inv;
int value = strtol(argv[0], &inv, 10);
if (*inv != '\0' || value < 0 || value > 99) {
int value = 0;
if (!cmd_corner_radius_parse_value(argv[0], &value)) {
return cmd_results_new(CMD_FAILURE, "Invalid size specified");
}

Expand Down
33 changes: 33 additions & 0 deletions sway/commands/layer_effects.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include <ctype.h>
#include "log.h"
#include "stringop.h"
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/layer_criteria.h"
#include "sway/output.h"
#include "util.h"

struct cmd_results *cmd_layer_effects(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "layer_effects", EXPECTED_AT_LEAST, 2))) {
return error;
}

struct layer_criteria *criteria = malloc(sizeof(struct layer_criteria));
criteria->namespace = malloc(strlen(argv[0]) + 1);
strcpy(criteria->namespace, argv[0]);
criteria->cmdlist = join_args(argv + 1, argc - 1);

// Check if the rule already exists
if (layer_criteria_already_exists(criteria)) {
sway_log(SWAY_DEBUG, "layer_effect already exists: '%s' '%s'",
criteria->namespace, criteria->cmdlist);
layer_criteria_destroy(criteria);
return cmd_results_new(CMD_SUCCESS, NULL);
}

list_add(config->layer_criteria, criteria);
sway_log(SWAY_DEBUG, "layer_effect: '%s' '%s' added", criteria->namespace, criteria->cmdlist);

return cmd_results_new(CMD_SUCCESS, NULL);
}
2 changes: 1 addition & 1 deletion sway/commands/shadows.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct cmd_results *cmd_shadows(int argc, char **argv) {

struct sway_container *con = config->handler_context.container;

bool result = parse_boolean(argv[0], config->shadow_enabled);
bool result = parse_boolean(argv[0], true);
if (con == NULL) {
config->shadow_enabled = result;
} else {
Expand Down
13 changes: 13 additions & 0 deletions sway/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/criteria.h"
#include "sway/layer_criteria.h"
#include "sway/desktop/transaction.h"
#include "sway/swaynag.h"
#include "sway/tree/arrange.h"
Expand Down Expand Up @@ -157,6 +158,12 @@ void free_config(struct sway_config *config) {
}
list_free(config->criteria);
}
if (config->layer_criteria) {
for (int i = 0; i < config->layer_criteria->length; ++i) {
layer_criteria_destroy(config->layer_criteria->items[i]);
}
list_free(config->layer_criteria);
}
list_free(config->no_focus);
list_free(config->active_bar_modifiers);
list_free_items_and_destroy(config->config_chain);
Expand Down Expand Up @@ -354,6 +361,8 @@ static void config_defaults(struct sway_config *config) {
config->titlebar_separator = true;
config->scratchpad_minimize = true;

if (!(config->layer_criteria = create_list())) goto cleanup;

// The keysym to keycode translation
struct xkb_rule_names rules = {0};
config->keysym_translation_state =
Expand Down Expand Up @@ -1092,3 +1101,7 @@ int config_get_blur_size() {
bool config_should_parameters_blur() {
return config->blur_params.radius > 0 && config->blur_params.num_passes > 0;
}

bool config_should_parameters_shadow() {
return config->shadow_blur_sigma > 0 && config->shadow_color[3] > 0.0;
}
22 changes: 22 additions & 0 deletions sway/desktop/layer_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_subcompositor.h>
#include "log.h"
#include "sway/layer_criteria.h"
#include "sway/desktop/transaction.h"
#include "sway/input/cursor.h"
#include "sway/input/input-manager.h"
Expand All @@ -15,6 +16,21 @@
#include "sway/server.h"
#include "sway/tree/arrange.h"
#include "sway/tree/workspace.h"
#include "wlr-layer-shell-unstable-v1-protocol.h"

static void layer_parse_criteria(struct sway_layer_surface *sway_layer) {
enum zwlr_layer_shell_v1_layer layer = sway_layer->layer;
if (layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND) {
return;
}

list_t *criterias = layer_criterias_for_sway_layer_surface(sway_layer);
for (int i = 0; i < criterias->length; i++) {
struct layer_criteria *criteria = criterias->items[i];
layer_criteria_parse(sway_layer, criteria);
}
list_free(criterias);
}

static void apply_exclusive(struct wlr_box *usable_area,
uint32_t anchor, int32_t exclusive,
Expand Down Expand Up @@ -306,6 +322,7 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
wl_list_insert(&output->layers[layer_surface->current.layer],
&layer->link);
layer->layer = layer_surface->current.layer;
layer_parse_criteria(layer);
}
arrange_layers(output);
}
Expand Down Expand Up @@ -393,6 +410,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
struct wlr_output *wlr_output = sway_layer->layer_surface->output;
sway_assert(wlr_output, "wlr_layer_surface_v1 has null output");
struct sway_output *output = wlr_output->data;
layer_parse_criteria(sway_layer);
output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y,
sway_layer->layer_surface->surface, true);
wlr_surface_send_enter(sway_layer->layer_surface->surface,
Expand Down Expand Up @@ -685,6 +703,10 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
sway_layer->layer_surface = layer_surface;
layer_surface->data = sway_layer;

sway_layer->has_blur = false;
sway_layer->has_shadow = false;
sway_layer->corner_radius = 0;

struct sway_output *output = layer_surface->output->data;
sway_layer->output_destroy.notify = handle_output_destroy;
wl_signal_add(&output->events.disable, &sway_layer->output_destroy);
Expand Down
7 changes: 7 additions & 0 deletions sway/desktop/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,13 @@ void output_layer_for_each_toplevel_surface(struct sway_output *output,
wl_list_for_each(layer_surface, layer_surfaces, link) {
struct wlr_layer_surface_v1 *wlr_layer_surface_v1 =
layer_surface->layer_surface;

struct render_data *data = user_data;
data->deco_data.blur = layer_surface->layer != ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND ?
layer_surface->has_blur : false;
data->deco_data.shadow = layer_surface->has_shadow;
data->deco_data.corner_radius = layer_surface->corner_radius;

output_surface_for_each_surface(output, wlr_layer_surface_v1->surface,
layer_surface->geo.x, layer_surface->geo.y, iterator,
user_data);
Expand Down
Loading

3 comments on commit 415e072

@felixity1917
Copy link

@felixity1917 felixity1917 commented on 415e072 May 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ErikReider After this commit, swaync starts showing default borders around notifications and control centre. Do you know how I can disable this? I have added a snippet below.
https://autumn.revolt.chat/attachments/D4VtcUP6Yxap9Uk_lCVIfcHaboLwHoDngqCGDblfVN

@ErikReider
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Red1922 borders are never drawn on layer surfaces. Might be a custom CSS issue. Test with the default CSS :)

@felixity1917
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Red1922 borders are never drawn on layer surfaces. Might be a custom CSS issue. Test with the default CSS :)

Oh yep. Sorry, my bad. When you mentioned that I remembered that I had tweaked the window borders in the gtk css file in the morning to try to have the file picker have borders as it uses client-side decorations so my sway defined borders don't work and it looks really off. It didn't cross my mind that it would show borders here as well. I removed that part of the css and now it's all fine.

Please sign in to comment.