Refactored layer_effects command to parse multiline configs
Now supports commands like these: ``` layer_effects "waybar" { blur enable; shadows disable; corner_radius 6; } ``` Also now able to override previous criterias and add criterias during runtime
This commit is contained in:
parent
cdf106c43c
commit
fba74b3617
14 changed files with 190 additions and 151 deletions
|
@ -34,6 +34,7 @@ Sway is an incredible window manager, and certainly one of the most well establi
|
||||||
+ LayerShell effects: *ONLY ON SWAYFX-GIT, NOT YET RELEASED*
|
+ LayerShell effects: *ONLY ON SWAYFX-GIT, NOT YET RELEASED*
|
||||||
- `layer_effects <layer namespace> <effects>`
|
- `layer_effects <layer namespace> <effects>`
|
||||||
- Example: `layer_effects "waybar" blur enable; shadows enable; corner_radius 6`
|
- 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:
|
- Available Effects:
|
||||||
- `blur <enable|disable>`
|
- `blur <enable|disable>`
|
||||||
- `shadows <enable|disable>`
|
- `shadows <enable|disable>`
|
||||||
|
|
|
@ -476,11 +476,6 @@ struct blur_parameters {
|
||||||
int radius;
|
int radius;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct layer_effects {
|
|
||||||
char *namespace;
|
|
||||||
struct decoration_data deco_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The configuration struct. The result of loading a config file.
|
* The configuration struct. The result of loading a config file.
|
||||||
*/
|
*/
|
||||||
|
@ -506,7 +501,7 @@ struct sway_config {
|
||||||
bool titlebar_separator;
|
bool titlebar_separator;
|
||||||
bool scratchpad_minimize;
|
bool scratchpad_minimize;
|
||||||
|
|
||||||
list_t *layer_effects;
|
list_t *layer_criteria;
|
||||||
|
|
||||||
char *swaynag_command;
|
char *swaynag_command;
|
||||||
struct swaynag_instance swaynag_config_errors;
|
struct swaynag_instance swaynag_config_errors;
|
||||||
|
|
19
include/sway/layer_criteria.h
Normal file
19
include/sway/layer_criteria.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "sway/layers.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);
|
|
@ -29,7 +29,7 @@ struct sway_layer_surface {
|
||||||
|
|
||||||
struct wl_list subsurfaces;
|
struct wl_list subsurfaces;
|
||||||
|
|
||||||
struct layer_effects *effects;
|
struct decoration_data deco_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sway_layer_popup {
|
struct sway_layer_popup {
|
||||||
|
|
|
@ -84,6 +84,7 @@ static const struct cmd_handler handlers[] = {
|
||||||
{ "gaps", cmd_gaps },
|
{ "gaps", cmd_gaps },
|
||||||
{ "hide_edge_borders", cmd_hide_edge_borders },
|
{ "hide_edge_borders", cmd_hide_edge_borders },
|
||||||
{ "input", cmd_input },
|
{ "input", cmd_input },
|
||||||
|
{ "layer_effects", cmd_layer_effects },
|
||||||
{ "mode", cmd_mode },
|
{ "mode", cmd_mode },
|
||||||
{ "mouse_warping", cmd_mouse_warping },
|
{ "mouse_warping", cmd_mouse_warping },
|
||||||
{ "new_float", cmd_new_float },
|
{ "new_float", cmd_new_float },
|
||||||
|
@ -119,7 +120,6 @@ static const struct cmd_handler handlers[] = {
|
||||||
static const struct cmd_handler config_handlers[] = {
|
static const struct cmd_handler config_handlers[] = {
|
||||||
{ "default_orientation", cmd_default_orientation },
|
{ "default_orientation", cmd_default_orientation },
|
||||||
{ "include", cmd_include },
|
{ "include", cmd_include },
|
||||||
{ "layer_effects", cmd_layer_effects },
|
|
||||||
{ "scratchpad_minimize", cmd_scratchpad_minimize },
|
{ "scratchpad_minimize", cmd_scratchpad_minimize },
|
||||||
{ "swaybg_command", cmd_swaybg_command },
|
{ "swaybg_command", cmd_swaybg_command },
|
||||||
{ "swaynag_command", cmd_swaynag_command },
|
{ "swaynag_command", cmd_swaynag_command },
|
||||||
|
|
|
@ -3,101 +3,31 @@
|
||||||
#include "stringop.h"
|
#include "stringop.h"
|
||||||
#include "sway/commands.h"
|
#include "sway/commands.h"
|
||||||
#include "sway/config.h"
|
#include "sway/config.h"
|
||||||
|
#include "sway/layer_criteria.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))) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct layer_effects *effect = malloc(sizeof(struct layer_effects));
|
struct layer_criteria *criteria = malloc(sizeof(struct layer_criteria));
|
||||||
size_t len = sizeof(argv[0]);
|
criteria->namespace = malloc(strlen(argv[0]) + 1);
|
||||||
effect->namespace = malloc(len + 1);
|
strcpy(criteria->namespace, argv[0]);
|
||||||
memcpy(effect->namespace, argv[0], len);
|
criteria->cmdlist = join_args(argv + 1, argc - 1);
|
||||||
effect->deco_data = get_undecorated_decoration_data();
|
|
||||||
|
|
||||||
// Parse the commands
|
// Check if the rule already exists
|
||||||
if ((error = parse_effects(argc, argv, effect))) {
|
if (layer_criteria_already_exists(criteria)) {
|
||||||
return error;
|
sway_log(SWAY_DEBUG, "layer_effect already exists: '%s' '%s'",
|
||||||
}
|
criteria->namespace, criteria->cmdlist);
|
||||||
|
layer_criteria_destroy(criteria);
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the rule already exists
|
list_add(config->layer_criteria, criteria);
|
||||||
list_t *effects = config->layer_effects;
|
sway_log(SWAY_DEBUG, "layer_effect: '%s' '%s' added", criteria->namespace, criteria->cmdlist);
|
||||||
for (int i = 0; i < effects->length; ++i) {
|
|
||||||
struct layer_effects *existing = effects->items[i];
|
|
||||||
// Replace the duplicate entry
|
|
||||||
if (strcmp(existing->namespace, effect->namespace) == 0) {
|
|
||||||
memcpy(existing, effect, sizeof(struct layer_effects));
|
|
||||||
free(effect);
|
|
||||||
effect = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (effect) {
|
|
||||||
list_add(effects, effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "sway/commands.h"
|
#include "sway/commands.h"
|
||||||
#include "sway/config.h"
|
#include "sway/config.h"
|
||||||
#include "sway/criteria.h"
|
#include "sway/criteria.h"
|
||||||
|
#include "sway/layer_criteria.h"
|
||||||
#include "sway/desktop/transaction.h"
|
#include "sway/desktop/transaction.h"
|
||||||
#include "sway/swaynag.h"
|
#include "sway/swaynag.h"
|
||||||
#include "sway/tree/arrange.h"
|
#include "sway/tree/arrange.h"
|
||||||
|
@ -157,13 +158,11 @@ void free_config(struct sway_config *config) {
|
||||||
}
|
}
|
||||||
list_free(config->criteria);
|
list_free(config->criteria);
|
||||||
}
|
}
|
||||||
if (config->layer_effects) {
|
if (config->layer_criteria) {
|
||||||
for (int i = 0; i < config->layer_effects->length; ++i) {
|
for (int i = 0; i < config->layer_criteria->length; ++i) {
|
||||||
struct layer_effects *effect = config->layer_effects->items[i];
|
layer_criteria_destroy(config->layer_criteria->items[i]);
|
||||||
free(effect->namespace);
|
|
||||||
free(effect);
|
|
||||||
}
|
}
|
||||||
list_free(config->layer_effects);
|
list_free(config->layer_criteria);
|
||||||
}
|
}
|
||||||
list_free(config->no_focus);
|
list_free(config->no_focus);
|
||||||
list_free(config->active_bar_modifiers);
|
list_free(config->active_bar_modifiers);
|
||||||
|
@ -362,7 +361,7 @@ static void config_defaults(struct sway_config *config) {
|
||||||
config->titlebar_separator = true;
|
config->titlebar_separator = true;
|
||||||
config->scratchpad_minimize = true;
|
config->scratchpad_minimize = true;
|
||||||
|
|
||||||
if (!(config->layer_effects = create_list())) goto cleanup;
|
if (!(config->layer_criteria = create_list())) goto cleanup;
|
||||||
|
|
||||||
// The keysym to keycode translation
|
// The keysym to keycode translation
|
||||||
struct xkb_rule_names rules = {0};
|
struct xkb_rule_names rules = {0};
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <wlr/types/wlr_output.h>
|
#include <wlr/types/wlr_output.h>
|
||||||
#include <wlr/types/wlr_subcompositor.h>
|
#include <wlr/types/wlr_subcompositor.h>
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "sway/layer_criteria.h"
|
||||||
#include "sway/desktop/transaction.h"
|
#include "sway/desktop/transaction.h"
|
||||||
#include "sway/input/cursor.h"
|
#include "sway/input/cursor.h"
|
||||||
#include "sway/input/input-manager.h"
|
#include "sway/input/input-manager.h"
|
||||||
|
@ -17,6 +18,22 @@
|
||||||
#include "sway/tree/workspace.h"
|
#include "sway/tree/workspace.h"
|
||||||
#include "wlr-layer-shell-unstable-v1-protocol.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
sway_layer->deco_data.can_blur_xray = layer != ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM;
|
||||||
|
|
||||||
|
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,
|
static void apply_exclusive(struct wlr_box *usable_area,
|
||||||
uint32_t anchor, int32_t exclusive,
|
uint32_t anchor, int32_t exclusive,
|
||||||
int32_t margin_top, int32_t margin_right,
|
int32_t margin_top, int32_t margin_right,
|
||||||
|
@ -307,6 +324,7 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
|
||||||
wl_list_insert(&output->layers[layer_surface->current.layer],
|
wl_list_insert(&output->layers[layer_surface->current.layer],
|
||||||
&layer->link);
|
&layer->link);
|
||||||
layer->layer = layer_surface->current.layer;
|
layer->layer = layer_surface->current.layer;
|
||||||
|
layer_parse_criteria(layer);
|
||||||
}
|
}
|
||||||
arrange_layers(output);
|
arrange_layers(output);
|
||||||
}
|
}
|
||||||
|
@ -394,6 +412,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
|
||||||
struct wlr_output *wlr_output = sway_layer->layer_surface->output;
|
struct wlr_output *wlr_output = sway_layer->layer_surface->output;
|
||||||
sway_assert(wlr_output, "wlr_layer_surface_v1 has null output");
|
sway_assert(wlr_output, "wlr_layer_surface_v1 has null output");
|
||||||
struct sway_output *output = wlr_output->data;
|
struct sway_output *output = wlr_output->data;
|
||||||
|
layer_parse_criteria(sway_layer);
|
||||||
output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y,
|
output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y,
|
||||||
sway_layer->layer_surface->surface, true);
|
sway_layer->layer_surface->surface, true);
|
||||||
wlr_surface_send_enter(sway_layer->layer_surface->surface,
|
wlr_surface_send_enter(sway_layer->layer_surface->surface,
|
||||||
|
@ -686,18 +705,7 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
|
||||||
sway_layer->layer_surface = layer_surface;
|
sway_layer->layer_surface = layer_surface;
|
||||||
layer_surface->data = sway_layer;
|
layer_surface->data = sway_layer;
|
||||||
|
|
||||||
enum zwlr_layer_shell_v1_layer layer = layer_surface->current.layer;
|
sway_layer->deco_data = get_undecorated_decoration_data();
|
||||||
if (layer != ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND) {
|
|
||||||
for (int i = 0; i < config->layer_effects->length; ++i) {
|
|
||||||
struct layer_effects *effect = config->layer_effects->items[i];
|
|
||||||
if (strcmp(effect->namespace, layer_surface->namespace) == 0) {
|
|
||||||
sway_layer->effects = effect;
|
|
||||||
// Blur optimization won't work for BOTTOM layered surfaces
|
|
||||||
sway_layer->effects->deco_data.can_blur_xray = layer != ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sway_output *output = layer_surface->output->data;
|
struct sway_output *output = layer_surface->output->data;
|
||||||
sway_layer->output_destroy.notify = handle_output_destroy;
|
sway_layer->output_destroy.notify = handle_output_destroy;
|
||||||
|
|
|
@ -201,9 +201,7 @@ void output_layer_for_each_toplevel_surface(struct sway_output *output,
|
||||||
layer_surface->layer_surface;
|
layer_surface->layer_surface;
|
||||||
struct render_data *data = user_data;
|
struct render_data *data = user_data;
|
||||||
data->sway_layer = layer_surface;
|
data->sway_layer = layer_surface;
|
||||||
if (layer_surface->effects) {
|
data->deco_data = layer_surface->deco_data;
|
||||||
data->deco_data = layer_surface->effects->deco_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
output_surface_for_each_surface(output, wlr_layer_surface_v1->surface,
|
output_surface_for_each_surface(output, wlr_layer_surface_v1->surface,
|
||||||
layer_surface->geo.x, layer_surface->geo.y, iterator,
|
layer_surface->geo.x, layer_surface->geo.y, iterator,
|
||||||
|
|
|
@ -1848,9 +1848,8 @@ static struct workspace_effect_info get_workspace_effect_info(struct sway_output
|
||||||
for (size_t i = 0; i < len; ++i) {
|
for (size_t i = 0; i < len; ++i) {
|
||||||
struct sway_layer_surface *lsurface;
|
struct sway_layer_surface *lsurface;
|
||||||
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 decoration_data deco_data = lsurface->deco_data;
|
||||||
if (layer_effects) {
|
if (deco_data.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
|
||||||
|
@ -1859,10 +1858,10 @@ static struct workspace_effect_info get_workspace_effect_info(struct sway_output
|
||||||
effect_info.should_render_optimized_blur = true;
|
effect_info.should_render_optimized_blur = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (layer_effects->deco_data.shadow) {
|
if (deco_data.shadow) {
|
||||||
effect_info.container_wants_shadow = true;
|
effect_info.container_wants_shadow = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (effect_info.container_wants_blur
|
if (effect_info.container_wants_blur
|
||||||
&& effect_info.container_wants_shadow
|
&& effect_info.container_wants_shadow
|
||||||
&& effect_info.should_render_optimized_blur) {
|
&& effect_info.should_render_optimized_blur) {
|
||||||
|
|
|
@ -374,18 +374,16 @@ static void ipc_json_describe_enabled_output(struct sway_output *output,
|
||||||
json_object_object_add(layer, "extent", extent);
|
json_object_object_add(layer, "extent", extent);
|
||||||
|
|
||||||
json_object *effects = json_object_new_array();
|
json_object *effects = json_object_new_array();
|
||||||
struct layer_effects *layer_effects = lsurface->effects;
|
struct decoration_data deco_data = lsurface->deco_data;
|
||||||
if (layer_effects) {
|
if (deco_data.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->deco_data.shadow) {
|
if (deco_data.shadow) {
|
||||||
json_object_array_add(effects, json_object_new_string("shadows"));
|
json_object_array_add(effects, json_object_new_string("shadows"));
|
||||||
}
|
}
|
||||||
if (layer_effects->deco_data.corner_radius > 0) {
|
if (deco_data.corner_radius > 0) {
|
||||||
json_object_array_add(effects, json_object_new_string("corner_radius"));
|
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);
|
||||||
|
|
||||||
json_object_array_add(layers, layer);
|
json_object_array_add(layers, layer);
|
||||||
|
|
87
sway/layer_criteria.c
Normal file
87
sway/layer_criteria.c
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "log.h"
|
||||||
|
#include "stringop.h"
|
||||||
|
#include "sway/commands.h"
|
||||||
|
#include "sway/layer_criteria.h"
|
||||||
|
|
||||||
|
void layer_criteria_destroy(struct layer_criteria *criteria) {
|
||||||
|
free(criteria->namespace);
|
||||||
|
free(criteria->cmdlist);
|
||||||
|
free(criteria);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool layer_criteria_is_equal(struct layer_criteria *a, struct layer_criteria *b) {
|
||||||
|
return strcmp(a->namespace, b->namespace) == 0
|
||||||
|
&& strcmp(a->cmdlist, b->cmdlist) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool layer_criteria_already_exists(struct layer_criteria *criteria) {
|
||||||
|
list_t *criterias = config->layer_criteria;
|
||||||
|
for (int i = 0; i < criterias->length; ++i) {
|
||||||
|
struct layer_criteria *existing = criterias->items[i];
|
||||||
|
if (layer_criteria_is_equal(criteria, existing)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_t *layer_criterias_for_sway_layer_surface(struct sway_layer_surface *sway_layer) {
|
||||||
|
list_t *criterias = config->layer_criteria;
|
||||||
|
list_t *matches = create_list();
|
||||||
|
for (int i = 0; i < criterias->length; ++i) {
|
||||||
|
struct layer_criteria *criteria = criterias->items[i];
|
||||||
|
if (strcmp(criteria->namespace, sway_layer->layer_surface->namespace) == 0) {
|
||||||
|
list_add(matches, criteria);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
void layer_criteria_parse(struct sway_layer_surface *sway_layer, struct layer_criteria *criteria) {
|
||||||
|
char matched_delim = ';';
|
||||||
|
char *head = malloc(strlen(criteria->cmdlist) + 1);
|
||||||
|
strcpy(head, criteria->cmdlist);
|
||||||
|
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) {
|
||||||
|
sway_layer->deco_data.blur = cmd_blur_parse_value(argv[1]);
|
||||||
|
continue;
|
||||||
|
} else if (strcmp(argv[0], "shadows") == 0) {
|
||||||
|
sway_layer->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)) {
|
||||||
|
sway_layer->deco_data.corner_radius = value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sway_log(SWAY_ERROR,
|
||||||
|
"Invalid layer_effects corner_radius size! Got \"%s\"",
|
||||||
|
argv[1]);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
sway_log(SWAY_ERROR, "Invalid layer_effects effect! Got \"%s\"", cmd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while(head);
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ sway_sources = files(
|
||||||
'decoration.c',
|
'decoration.c',
|
||||||
'ipc-json.c',
|
'ipc-json.c',
|
||||||
'ipc-server.c',
|
'ipc-server.c',
|
||||||
|
'layer_criteria.c',
|
||||||
'lock.c',
|
'lock.c',
|
||||||
'main.c',
|
'main.c',
|
||||||
'realtime.c',
|
'realtime.c',
|
||||||
|
|
|
@ -71,21 +71,6 @@ The following commands may only be used in the configuration file.
|
||||||
*wordexp*(3) for details). The same include file can only be included once;
|
*wordexp*(3) for details). The same include file can only be included once;
|
||||||
subsequent attempts will be ignored.
|
subsequent attempts will be ignored.
|
||||||
|
|
||||||
*layer_effects* <layer-namespace> <effects>
|
|
||||||
Apply effects on specific layer shell surfaces, eg waybar or rofi.
|
|
||||||
At least one effect needs to be provided. The <layer-namespace> can be
|
|
||||||
gotten through *sway-ipc*. Note: Surfaces in the _bottom_ layer cannot
|
|
||||||
use these effects.
|
|
||||||
|
|
||||||
Effects:
|
|
||||||
- *blur* <enable|disable>
|
|
||||||
- *shadows* <enable|disable>
|
|
||||||
- *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.
|
||||||
Must be set at config-time (when starting sway).
|
Must be set at config-time (when starting sway).
|
||||||
|
@ -802,6 +787,25 @@ The default colors are:
|
||||||
Whenever a window that matches _criteria_ appears, run list of commands.
|
Whenever a window that matches _criteria_ appears, run list of commands.
|
||||||
See *CRITERIA* for more details.
|
See *CRITERIA* for more details.
|
||||||
|
|
||||||
|
*layer_effects* <layer-namespace> <effects>
|
||||||
|
Apply effects on specific layer shell surfaces, eg "waybar" or "rofi".
|
||||||
|
At least one effect needs to be provided. The <layer-namespace> can be
|
||||||
|
gotten through *sway-ipc*. Note: Surfaces in the _bottom_ layer cannot
|
||||||
|
use these effects.
|
||||||
|
|
||||||
|
Effects:
|
||||||
|
- *blur* <enable|disable>
|
||||||
|
- *shadows* <enable|disable>
|
||||||
|
- *corner_radius* <integer>
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
layer_effects "waybar" blur enable; shadows enable; corner_radius 6
|
||||||
|
|
||||||
|
SwayIPC Example:
|
||||||
|
|
||||||
|
swaymsg "layer_effects 'waybar' 'blur enable; shadows enable'"
|
||||||
|
|
||||||
*gaps* inner|outer|horizontal|vertical|top|right|bottom|left <amount>
|
*gaps* inner|outer|horizontal|vertical|top|right|bottom|left <amount>
|
||||||
Sets default _amount_ pixels of _inner_ or _outer_ gap, where the inner
|
Sets default _amount_ pixels of _inner_ or _outer_ gap, where the inner
|
||||||
affects spacing around each view and outer affects the spacing around each
|
affects spacing around each view and outer affects the spacing around each
|
||||||
|
|
Loading…
Add table
Reference in a new issue