mirror of
https://codeberg.org/dnkl/yambar.git
synced 2025-04-23 04:25:42 +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;
|
||||
size_t count;
|
||||
} workspaces;
|
||||
|
||||
struct particle *label;
|
||||
};
|
||||
|
||||
static bool
|
||||
|
@ -736,6 +738,9 @@ destroy(struct module *mod)
|
|||
free(m->ws_content.v);
|
||||
workspaces_free(m);
|
||||
|
||||
if (m->label != NULL)
|
||||
m->label->destroy(m->label);
|
||||
|
||||
free(m);
|
||||
module_default_destroy(mod);
|
||||
}
|
||||
|
@ -759,7 +764,7 @@ content(struct module *mod)
|
|||
|
||||
mtx_lock(&mod->lock);
|
||||
|
||||
struct exposable *particles[m->workspaces.count];
|
||||
struct exposable *particles[m->workspaces.count + (m->label != NULL)];
|
||||
|
||||
size_t particle_count = 0;
|
||||
for (size_t i = 0; i < m->workspaces.count; i++) {
|
||||
|
@ -805,6 +810,32 @@ content(struct module *mod)
|
|||
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);
|
||||
return dynlist_exposable_new(
|
||||
particles, particle_count, m->left_spacing, m->right_spacing);
|
||||
|
@ -818,7 +849,7 @@ struct i3_workspaces {
|
|||
|
||||
static struct module *
|
||||
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));
|
||||
|
||||
|
@ -833,6 +864,8 @@ i3_new(struct i3_workspaces workspaces[], size_t workspace_count,
|
|||
m->ws_content.v[i].content = workspaces[i].content;
|
||||
}
|
||||
|
||||
m->label = label;
|
||||
|
||||
struct module *mod = module_common_new();
|
||||
mod->private = m;
|
||||
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) :
|
||||
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;
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
return i3_new(workspaces, yml_dict_length(c), left, right);
|
||||
return i3_new(workspaces, ws_count, label, left, right);
|
||||
}
|
||||
|
||||
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)) {
|
||||
LOG_ERR(
|
||||
"%s: must be a dictionary of workspace-name: particle mappings",
|
||||
conf_err_prefix(chain, node));
|
||||
return false;
|
||||
}
|
||||
assert(yml_is_dict(node));
|
||||
|
||||
for (struct yml_dict_iter it = yml_dict_iter(node);
|
||||
it.key != NULL;
|
||||
|
@ -898,6 +953,59 @@ verify_content(keychain_t *chain, const struct yml_node *node)
|
|||
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
|
||||
verify_conf(keychain_t *chain, const struct yml_node *node)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue