mirror of
https://codeberg.org/dnkl/yambar.git
synced 2025-04-23 12:35:41 +02:00
module/i3: allow 'content' to also contain a regular 'label'
Previously, the 'content' of i3 was a map, where the keys where i3 workspace names, mapping to a particle template. Now, that configuration type is still allowed. But we also allow a variant where the 'content' is a list, of either 1 or 2 entries. Both entries *must* be dictionaries. The key is either 'dynlist', which is the same as the dictionary-only type of configuration. I.e. it maps to a dictionary where the keys are workspace names, mapping to particle templates. If the key is *not* dynlist, then it is assumed to be a particle name, and we treat that as a "regular" label, that will be appended after the workspace dynlist when instantiating the content. This particle will be instantiated with, for now, the title and application of the _currently focused_ workspace.
This commit is contained in:
parent
d565fbe2f0
commit
4100922b7a
1 changed files with 120 additions and 12 deletions
132
modules/i3.c
132
modules/i3.c
|
@ -69,6 +69,8 @@ struct private {
|
||||||
struct workspace *v;
|
struct workspace *v;
|
||||||
size_t count;
|
size_t count;
|
||||||
} workspaces;
|
} workspaces;
|
||||||
|
|
||||||
|
struct particle *label;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -736,6 +738,9 @@ destroy(struct module *mod)
|
||||||
free(m->ws_content.v);
|
free(m->ws_content.v);
|
||||||
workspaces_free(m);
|
workspaces_free(m);
|
||||||
|
|
||||||
|
if (m->label != NULL)
|
||||||
|
m->label->destroy(m->label);
|
||||||
|
|
||||||
free(m);
|
free(m);
|
||||||
module_default_destroy(mod);
|
module_default_destroy(mod);
|
||||||
}
|
}
|
||||||
|
@ -759,7 +764,7 @@ content(struct module *mod)
|
||||||
|
|
||||||
mtx_lock(&mod->lock);
|
mtx_lock(&mod->lock);
|
||||||
|
|
||||||
struct exposable *particles[m->workspaces.count];
|
struct exposable *particles[m->workspaces.count + (m->label != NULL)];
|
||||||
|
|
||||||
size_t particle_count = 0;
|
size_t particle_count = 0;
|
||||||
for (size_t i = 0; i < m->workspaces.count; i++) {
|
for (size_t i = 0; i < m->workspaces.count; i++) {
|
||||||
|
@ -805,6 +810,32 @@ content(struct module *mod)
|
||||||
tag_set_destroy(&tags);
|
tag_set_destroy(&tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find currently focused workspace */
|
||||||
|
const struct workspace *ws = NULL;
|
||||||
|
size_t count = 0;
|
||||||
|
for (size_t i = 0; i < m->workspaces.count; i++) {
|
||||||
|
if (m->workspaces.v[i].focused) {
|
||||||
|
ws = &m->workspaces.v[i];
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(count <= 1);
|
||||||
|
assert(count == 0 || ws != NULL);
|
||||||
|
|
||||||
|
if (ws != NULL && m->label != NULL) {
|
||||||
|
struct tag_set tags = {
|
||||||
|
.tags = (struct tag *[]){
|
||||||
|
tag_new_string(mod, "application", ws->window.application),
|
||||||
|
tag_new_string(mod, "title", ws->window.title),
|
||||||
|
},
|
||||||
|
.count = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
particles[particle_count++] = m->label->instantiate(m->label, &tags);
|
||||||
|
tag_set_destroy(&tags);
|
||||||
|
}
|
||||||
|
|
||||||
mtx_unlock(&mod->lock);
|
mtx_unlock(&mod->lock);
|
||||||
return dynlist_exposable_new(
|
return dynlist_exposable_new(
|
||||||
particles, particle_count, m->left_spacing, m->right_spacing);
|
particles, particle_count, m->left_spacing, m->right_spacing);
|
||||||
|
@ -818,7 +849,7 @@ struct i3_workspaces {
|
||||||
|
|
||||||
static struct module *
|
static struct module *
|
||||||
i3_new(struct i3_workspaces workspaces[], size_t workspace_count,
|
i3_new(struct i3_workspaces workspaces[], size_t workspace_count,
|
||||||
int left_spacing, int right_spacing)
|
struct particle *label, int left_spacing, int right_spacing)
|
||||||
{
|
{
|
||||||
struct private *m = calloc(1, sizeof(*m));
|
struct private *m = calloc(1, sizeof(*m));
|
||||||
|
|
||||||
|
@ -833,6 +864,8 @@ i3_new(struct i3_workspaces workspaces[], size_t workspace_count,
|
||||||
m->ws_content.v[i].content = workspaces[i].content;
|
m->ws_content.v[i].content = workspaces[i].content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m->label = label;
|
||||||
|
|
||||||
struct module *mod = module_common_new();
|
struct module *mod = module_common_new();
|
||||||
mod->private = m;
|
mod->private = m;
|
||||||
mod->run = &run;
|
mod->run = &run;
|
||||||
|
@ -854,10 +887,37 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
|
||||||
int right = spacing != NULL ? yml_value_as_int(spacing) :
|
int right = spacing != NULL ? yml_value_as_int(spacing) :
|
||||||
right_spacing != NULL ? yml_value_as_int(right_spacing) : 0;
|
right_spacing != NULL ? yml_value_as_int(right_spacing) : 0;
|
||||||
|
|
||||||
struct i3_workspaces workspaces[yml_dict_length(c)];
|
const struct yml_node *ws_root_node = NULL;
|
||||||
|
struct particle *label = NULL;
|
||||||
|
|
||||||
|
if (yml_is_dict(c)) {
|
||||||
|
ws_root_node = c;
|
||||||
|
} else {
|
||||||
|
for (struct yml_list_iter it = yml_list_iter(c);
|
||||||
|
it.node != NULL;
|
||||||
|
yml_list_next(&it))
|
||||||
|
{
|
||||||
|
assert(yml_is_dict(it.node));
|
||||||
|
assert(yml_dict_length(it.node) == 1);
|
||||||
|
|
||||||
|
const struct yml_dict_iter item = yml_dict_iter(it.node);
|
||||||
|
const char *key = yml_value_as_string(item.key);
|
||||||
|
|
||||||
|
if (strcmp(key, "dynlist") == 0) {
|
||||||
|
ws_root_node = item.value;
|
||||||
|
} else {
|
||||||
|
assert(label == NULL);
|
||||||
|
label = conf_to_particle(it.node, inherited);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(yml_is_dict(ws_root_node));
|
||||||
|
const size_t ws_count = yml_dict_length(ws_root_node);
|
||||||
|
struct i3_workspaces workspaces[ws_count];
|
||||||
|
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
for (struct yml_dict_iter it = yml_dict_iter(c);
|
for (struct yml_dict_iter it = yml_dict_iter(ws_root_node);
|
||||||
it.key != NULL;
|
it.key != NULL;
|
||||||
yml_dict_next(&it), idx++)
|
yml_dict_next(&it), idx++)
|
||||||
{
|
{
|
||||||
|
@ -865,18 +925,13 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
|
||||||
workspaces[idx].content = conf_to_particle(it.value, inherited);
|
workspaces[idx].content = conf_to_particle(it.value, inherited);
|
||||||
}
|
}
|
||||||
|
|
||||||
return i3_new(workspaces, yml_dict_length(c), left, right);
|
return i3_new(workspaces, ws_count, label, left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
verify_content(keychain_t *chain, const struct yml_node *node)
|
verify_content_dynlist(keychain_t *chain, const struct yml_node *node)
|
||||||
{
|
{
|
||||||
if (!yml_is_dict(node)) {
|
assert(yml_is_dict(node));
|
||||||
LOG_ERR(
|
|
||||||
"%s: must be a dictionary of workspace-name: particle mappings",
|
|
||||||
conf_err_prefix(chain, node));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (struct yml_dict_iter it = yml_dict_iter(node);
|
for (struct yml_dict_iter it = yml_dict_iter(node);
|
||||||
it.key != NULL;
|
it.key != NULL;
|
||||||
|
@ -898,6 +953,59 @@ verify_content(keychain_t *chain, const struct yml_node *node)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
verify_content(keychain_t *chain, const struct yml_node *node)
|
||||||
|
{
|
||||||
|
if (!yml_is_dict(node) && !yml_is_list(node)) {
|
||||||
|
LOG_ERR(
|
||||||
|
"%s: must be a dictionary of workspace-name: particle mappings",
|
||||||
|
conf_err_prefix(chain, node));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yml_is_dict(node))
|
||||||
|
return verify_content_dynlist(chain, node);
|
||||||
|
|
||||||
|
if (yml_list_length(node) > 2) {
|
||||||
|
LOG_ERR("%s: must be a list of at most 2 entries",
|
||||||
|
conf_err_prefix(chain, node));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (struct yml_list_iter it = yml_list_iter(node);
|
||||||
|
it.node != NULL;
|
||||||
|
yml_list_next(&it))
|
||||||
|
{
|
||||||
|
if (!yml_is_dict(it.node) || yml_dict_length(it.node) != 1) {
|
||||||
|
LOG_ERR(
|
||||||
|
"%s: item must be a dictionary with a single item; "
|
||||||
|
"either a 'dynlist', or a particle name",
|
||||||
|
conf_err_prefix(chain, it.node));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct yml_dict_iter item = yml_dict_iter(it.node);
|
||||||
|
const char *key = yml_value_as_string(item.key);
|
||||||
|
if (key == NULL) {
|
||||||
|
LOG_ERR("%s: key must be a string; either 'dynlist', or a particle name",
|
||||||
|
conf_err_prefix(chain, item.key));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(key, "dynlist") == 0) {
|
||||||
|
if (!verify_content_dynlist(chain_push(chain, key), item.value))
|
||||||
|
return false;
|
||||||
|
chain_pop(chain);
|
||||||
|
} else {
|
||||||
|
if (!conf_verify_particle(chain, it.node))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
verify_conf(keychain_t *chain, const struct yml_node *node)
|
verify_conf(keychain_t *chain, const struct yml_node *node)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue