Made layer_effects syntax similar to the for_window command

Example: `layer_effects "waybar" blur on; shadows on; corner_radius 6`.
This commit is contained in:
Erik Reider 2023-05-02 18:12:01 +02:00
parent 90a8795492
commit 8a7bb48e75
12 changed files with 127 additions and 54 deletions

View file

@ -32,7 +32,12 @@ Sway is an incredible window manager, and certainly one of the most well establi
- `blur_passes <integer value 0 - 10>` - `blur_passes <integer value 0 - 10>`
- `blur_radius <integer value 0 - 10>` - `blur_radius <integer value 0 - 10>`
+ LayerShell effects: *ONLY ON SWAYFX-GIT, NOT YET RELEASED* + LayerShell effects: *ONLY ON SWAYFX-GIT, NOT YET RELEASED*
- `layer_effects <layer namespace, eg: "waybar"> blur shadow corner_radius` - `layer_effects <layer namespace> <effects>`
- Example: `layer_effects "waybar" blur enable; shadows enable; corner_radius 6`
- Available Effects:
- `blur <enable|disable>`
- `shadows <enable|disable>`
- `corner_radius <int>`
+ Dim unfocused windows: + Dim unfocused windows:
- `default_dim_inactive <float value 0.0 - 1.0>` - `default_dim_inactive <float value 0.0 - 1.0>`
- `for_window [CRITERIA_HERE] dim_inactive <float value 0.0 - 1.0>` - `for_window [CRITERIA_HERE] dim_inactive <float value 0.0 - 1.0>`

View file

@ -97,6 +97,13 @@ void container_resize_tiled(struct sway_container *parent, uint32_t axis,
struct sway_container *container_find_resize_parent(struct sway_container *con, struct sway_container *container_find_resize_parent(struct sway_container *con,
uint32_t edge); uint32_t edge);
/**
* Effect handlers value parsers
*/
bool cmd_blur_parse_value(char *arg);
bool cmd_corner_radius_parse_value(char *arg, int* result);
bool cmd_shadows_parse_value(char *arg);
/** /**
* Handlers shared by exec and exec_always. * Handlers shared by exec and exec_always.
*/ */

View file

@ -12,6 +12,7 @@
#include "../include/config.h" #include "../include/config.h"
#include "gesture.h" #include "gesture.h"
#include "list.h" #include "list.h"
#include "sway/desktop/fx_renderer/fx_renderer.h"
#include "swaynag.h" #include "swaynag.h"
#include "tree/container.h" #include "tree/container.h"
#include "sway/input/tablet.h" #include "sway/input/tablet.h"
@ -477,9 +478,7 @@ struct blur_parameters {
struct layer_effects { struct layer_effects {
char *namespace; char *namespace;
bool blur; struct decoration_data deco_data;
bool shadow;
bool corner_rounding;
}; };
/** /**

View file

@ -9,6 +9,18 @@
#include "sway/desktop/fx_renderer/fx_framebuffer.h" #include "sway/desktop/fx_renderer/fx_framebuffer.h"
#include "sway/desktop/fx_renderer/fx_texture.h" #include "sway/desktop/fx_renderer/fx_texture.h"
#define get_undecorated_decoration_data() \
(struct decoration_data) { \
.alpha = 1.0f, \
.dim = 0.0f, \
.dim_color = config->dim_inactive_colors.unfocused, \
.corner_radius = 0, \
.saturation = 1.0f, \
.has_titlebar = false, \
.blur = false, \
.shadow = false, \
}
enum corner_location { TOP_LEFT, TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT, ALL, NONE }; enum corner_location { TOP_LEFT, TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT, ALL, NONE };
enum fx_tex_shader_source { enum fx_tex_shader_source {

View file

@ -3,6 +3,10 @@
#include "sway/output.h" #include "sway/output.h"
#include "util.h" #include "util.h"
bool cmd_blur_parse_value(char *arg) {
return parse_boolean(arg, true);
}
struct cmd_results *cmd_blur(int argc, char **argv) { struct cmd_results *cmd_blur(int argc, char **argv) {
struct cmd_results *error = checkarg(argc, "blur", EXPECTED_AT_LEAST, 1); struct cmd_results *error = checkarg(argc, "blur", EXPECTED_AT_LEAST, 1);
@ -12,7 +16,7 @@ struct cmd_results *cmd_blur(int argc, char **argv) {
struct sway_container *con = config->handler_context.container; struct sway_container *con = config->handler_context.container;
bool result = parse_boolean(argv[0], config->blur_enabled); bool result = cmd_blur_parse_value(argv[0]);
if (con == NULL) { if (con == NULL) {
config->blur_enabled = result; config->blur_enabled = result;
} else { } else {

View file

@ -4,15 +4,24 @@
#include "sway/tree/container.h" #include "sway/tree/container.h"
#include "log.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 *cmd_corner_radius(int argc, char **argv) {
struct cmd_results *error = NULL; struct cmd_results *error = NULL;
if ((error = checkarg(argc, "corner_radius", EXPECTED_EQUAL_TO, 1))) { if ((error = checkarg(argc, "corner_radius", EXPECTED_EQUAL_TO, 1))) {
return error; return error;
} }
char *inv; int value = 0;
int value = strtol(argv[0], &inv, 10); if (!cmd_corner_radius_parse_value(argv[0], &value)) {
if (*inv != '\0' || value < 0 || value > 99) {
return cmd_results_new(CMD_FAILURE, "Invalid size specified"); return cmd_results_new(CMD_FAILURE, "Invalid size specified");
} }

View file

@ -1,8 +1,59 @@
#include <ctype.h>
#include "log.h"
#include "stringop.h"
#include "sway/commands.h" #include "sway/commands.h"
#include "sway/config.h" #include "sway/config.h"
#include "sway/output.h" #include "sway/output.h"
#include "util.h" #include "util.h"
struct cmd_results *parse_effects(int argc, char **argv, struct layer_effects *effect) {
char matched_delim = ';';
char *head = join_args(argv + 1, argc - 1);
do {
// Trim leading whitespaces
for (; isspace(*head); ++head) {}
// Split command list
char *cmd = argsep(&head, ";,", &matched_delim);
for (; isspace(*cmd); ++cmd) {}
if (strcmp(cmd, "") == 0) {
sway_log(SWAY_INFO, "Ignoring empty layer effect.");
continue;
}
sway_log(SWAY_INFO, "Handling layer effect '%s'", cmd);
int argc;
char **argv = split_args(cmd, &argc);
// Strip all quotes from each token
for (int i = 1; i < argc; ++i) {
if (*argv[i] == '\"' || *argv[i] == '\'') {
strip_quotes(argv[i]);
}
}
if (strcmp(argv[0], "blur") == 0) {
effect->deco_data.blur = cmd_blur_parse_value(argv[1]);
continue;
} else if (strcmp(argv[0], "shadows") == 0) {
effect->deco_data.shadow = cmd_shadows_parse_value(argv[1]);
continue;
} else if (strcmp(argv[0], "corner_radius") == 0) {
int value;
if (cmd_corner_radius_parse_value(argv[1], &value)) {
effect->deco_data.corner_radius = value;
continue;
}
return cmd_results_new(CMD_INVALID,
"Invalid layer_effects corner_radius size! Got \"%s\"",
argv[1]);
} else {
return cmd_results_new(CMD_INVALID,
"Invalid layer_effects effect! Got \"%s\"",
cmd);
}
} while(head);
return NULL;
}
struct cmd_results *cmd_layer_effects(int argc, char **argv) { struct cmd_results *cmd_layer_effects(int argc, char **argv) {
struct cmd_results *error = NULL; struct cmd_results *error = NULL;
if ((error = checkarg(argc, "layer_effects", EXPECTED_AT_LEAST, 2))) { if ((error = checkarg(argc, "layer_effects", EXPECTED_AT_LEAST, 2))) {
@ -13,27 +64,21 @@ struct cmd_results *cmd_layer_effects(int argc, char **argv) {
size_t len = sizeof(argv[0]); size_t len = sizeof(argv[0]);
effect->namespace = malloc(len + 1); effect->namespace = malloc(len + 1);
memcpy(effect->namespace, argv[0], len); memcpy(effect->namespace, argv[0], len);
effect->blur = false; effect->deco_data = get_undecorated_decoration_data();
effect->shadow = false;
effect->corner_rounding = false;
// Parse the commands // Parse the commands
for (int i = 1; i < argc; i++) { if ((error = parse_effects(argc, argv, effect))) {
char *arg = argv[i]; return error;
if (strcmp(arg, "blur") == 0) {
effect->blur = true;
continue;
} else if (strcmp(arg, "shadow") == 0) {
effect->shadow = true;
continue;
} else if (strcmp(arg, "corner_rounding") == 0) {
effect->corner_rounding = true;
continue;
}
return cmd_results_new(CMD_INVALID, "Invalid layer_effects effect! Got \"%s\"", arg);
} }
if (!effect->blur && !effect->shadow && !effect->corner_rounding) { // Ignore if nothing has changed
// TODO: Add deco_data cmp function?
if (!effect->deco_data.blur
&& !effect->deco_data.shadow
&& effect->deco_data.corner_radius < 1) {
sway_log(SWAY_ERROR,
"Ignoring layer effect \"%s\". Nothing changed\n",
join_args(argv + 1, argc - 1));
return cmd_results_new(CMD_SUCCESS, NULL); return cmd_results_new(CMD_SUCCESS, NULL);
} }

View file

@ -8,6 +8,10 @@
#include "stringop.h" #include "stringop.h"
#include "util.h" #include "util.h"
bool cmd_shadows_parse_value(char *arg) {
return parse_boolean(arg, true);
}
struct cmd_results *cmd_shadows(int argc, char **argv) { struct cmd_results *cmd_shadows(int argc, char **argv) {
struct cmd_results *error = checkarg(argc, "shadows", EXPECTED_AT_LEAST, 1); struct cmd_results *error = checkarg(argc, "shadows", EXPECTED_AT_LEAST, 1);
@ -17,7 +21,7 @@ struct cmd_results *cmd_shadows(int argc, char **argv) {
struct sway_container *con = config->handler_context.container; struct sway_container *con = config->handler_context.container;
bool result = parse_boolean(argv[0], config->shadow_enabled); bool result = cmd_shadows_parse_value(argv[0]);
if (con == NULL) { if (con == NULL) {
config->shadow_enabled = result; config->shadow_enabled = result;
} else { } else {

View file

@ -200,11 +200,8 @@ void output_layer_for_each_toplevel_surface(struct sway_output *output,
struct wlr_layer_surface_v1 *wlr_layer_surface_v1 = struct wlr_layer_surface_v1 *wlr_layer_surface_v1 =
layer_surface->layer_surface; layer_surface->layer_surface;
struct render_data *data = user_data; struct render_data *data = user_data;
struct layer_effects *effects = layer_surface->effects; if (layer_surface->effects) {
if (effects) { data->deco_data = layer_surface->effects->deco_data;
data->deco_data.blur = effects->blur;
data->deco_data.shadow = effects->shadow;
data->deco_data.corner_radius = effects->corner_rounding? config->corner_radius: 0;
} }
output_surface_for_each_surface(output, wlr_layer_surface_v1->surface, output_surface_for_each_surface(output, wlr_layer_surface_v1->surface,

View file

@ -39,19 +39,6 @@ struct workspace_effect_info {
int expanded_size; int expanded_size;
}; };
struct decoration_data get_undecorated_decoration_data() {
return (struct decoration_data) {
.alpha = 1.0f,
.dim = 0.0f,
.dim_color = config->dim_inactive_colors.unfocused,
.corner_radius = 0,
.saturation = 1.0f,
.has_titlebar = false,
.blur = false,
.shadow = false,
};
}
int get_blur_size() { int get_blur_size() {
return pow(2, config->blur_params.num_passes) * config->blur_params.radius; return pow(2, config->blur_params.num_passes) * config->blur_params.radius;
} }
@ -1865,14 +1852,14 @@ static struct workspace_effect_info get_workspace_effect_info(struct sway_output
wl_list_for_each(lsurface, &sway_output->layers[i], link) { wl_list_for_each(lsurface, &sway_output->layers[i], link) {
struct layer_effects *layer_effects = lsurface->effects; struct layer_effects *layer_effects = lsurface->effects;
if (layer_effects) { if (layer_effects) {
if (layer_effects->blur && !lsurface->layer_surface->surface->opaque) { if (layer_effects->deco_data.blur && !lsurface->layer_surface->surface->opaque) {
effect_info.container_wants_blur = true; effect_info.container_wants_blur = true;
// Check if we should render optimized blur // Check if we should render optimized blur
if (renderer->blur_buffer_dirty && config->blur_xray) { if (renderer->blur_buffer_dirty && config->blur_xray) {
effect_info.should_render_optimized_blur = true; effect_info.should_render_optimized_blur = true;
} }
} }
if (layer_effects->shadow) { if (layer_effects->deco_data.shadow) {
effect_info.container_wants_shadow = true; effect_info.container_wants_shadow = true;
} }
} }

View file

@ -376,14 +376,14 @@ static void ipc_json_describe_enabled_output(struct sway_output *output,
json_object *effects = json_object_new_array(); json_object *effects = json_object_new_array();
struct layer_effects *layer_effects = lsurface->effects; struct layer_effects *layer_effects = lsurface->effects;
if (layer_effects) { if (layer_effects) {
if (layer_effects->blur) { if (layer_effects->deco_data.blur) {
json_object_array_add(effects, json_object_new_string("blur")); json_object_array_add(effects, json_object_new_string("blur"));
} }
if (layer_effects->shadow) { if (layer_effects->deco_data.shadow) {
json_object_array_add(effects, json_object_new_string("shadow")); json_object_array_add(effects, json_object_new_string("shadows"));
} }
if (layer_effects->corner_rounding) { if (layer_effects->deco_data.corner_radius > 0) {
json_object_array_add(effects, json_object_new_string("corner_rounding")); json_object_array_add(effects, json_object_new_string("corner_radius"));
} }
} }
json_object_object_add(layer, "effects", effects); json_object_object_add(layer, "effects", effects);

View file

@ -78,9 +78,13 @@ The following commands may only be used in the configuration file.
layers can use these effects. layers can use these effects.
Effects: Effects:
- *blur* - *blur* <enable|disable>
- *shadow* - *shadows* <enable|disable>
- *corner_rounding* - *corner_radius* <integer>
Example:
layer_effects "waybar" blur enable; shadows enable; corner_radius 6
*scratchpad_minimize* enable|disable *scratchpad_minimize* enable|disable
Adjusts if minimized windows should be moved into the scratchpad. Adjusts if minimized windows should be moved into the scratchpad.