mirror of
https://codeberg.org/dnkl/yambar.git
synced 2025-04-26 04:15:42 +02:00
modules: Implement workspace rename event
A renamed workspace caused yambar to abort in a failed assertion, because workspace lookup was done by name and the `rename` event was not implemented. To resolve this issue this patch implements the `rename` event and as a necessity changes workspace_lookup() to use ids instead of names.
This commit is contained in:
parent
e4a0b375e5
commit
8b3919a8ea
1 changed files with 67 additions and 32 deletions
99
modules/i3.c
99
modules/i3.c
|
@ -29,6 +29,7 @@ struct ws_content {
|
|||
};
|
||||
|
||||
struct workspace {
|
||||
int id;
|
||||
char *name;
|
||||
int name_as_int; /* -1 is name is not a decimal number */
|
||||
|
||||
|
@ -62,12 +63,29 @@ struct private {
|
|||
tll(struct workspace) workspaces;
|
||||
};
|
||||
|
||||
static int
|
||||
name_as_int(const char *name_as_string)
|
||||
{
|
||||
int name_as_int = 0;
|
||||
for (const char *p = name_as_string; *p != '\0'; p++) {
|
||||
if (!(*p >= '0' && *p <= '9')) {
|
||||
name_as_int = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
name_as_int *= 10;
|
||||
name_as_int += *p - '0';
|
||||
}
|
||||
return name_as_int;
|
||||
}
|
||||
|
||||
static bool
|
||||
workspace_from_json(const struct json_object *json, struct workspace *ws)
|
||||
{
|
||||
/* Always present */
|
||||
struct json_object *name, *output;
|
||||
if (!json_object_object_get_ex(json, "name", &name) ||
|
||||
struct json_object *id, *name, *output;
|
||||
if (!json_object_object_get_ex(json, "id", &id) ||
|
||||
!json_object_object_get_ex(json, "name", &name) ||
|
||||
!json_object_object_get_ex(json, "output", &output))
|
||||
{
|
||||
LOG_ERR("workspace reply/event without 'name' and/or 'output' property");
|
||||
|
@ -82,20 +100,10 @@ workspace_from_json(const struct json_object *json, struct workspace *ws)
|
|||
|
||||
const char *name_as_string = json_object_get_string(name);
|
||||
|
||||
int name_as_int = 0;
|
||||
for (const char *p = name_as_string; *p != '\0'; p++) {
|
||||
if (!(*p >= '0' && *p <= '9')) {
|
||||
name_as_int = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
name_as_int *= 10;
|
||||
name_as_int += *p - '0';
|
||||
}
|
||||
|
||||
*ws = (struct workspace) {
|
||||
.id = json_object_get_int(id),
|
||||
.name = strdup(name_as_string),
|
||||
.name_as_int = name_as_int,
|
||||
.name_as_int = name_as_int(name_as_string),
|
||||
.output = strdup(json_object_get_string(output)),
|
||||
.visible = json_object_get_boolean(visible),
|
||||
.focused = json_object_get_boolean(focused),
|
||||
|
@ -179,12 +187,12 @@ workspace_add(struct private *m, struct workspace ws)
|
|||
}
|
||||
|
||||
static void
|
||||
workspace_del(struct private *m, const char *name)
|
||||
workspace_del(struct private *m, int id)
|
||||
{
|
||||
tll_foreach(m->workspaces, it) {
|
||||
struct workspace *ws = &it->item;
|
||||
|
||||
if (strcmp(ws->name, name) != 0)
|
||||
if (ws->id != id)
|
||||
continue;
|
||||
|
||||
workspace_free(ws);
|
||||
|
@ -194,11 +202,11 @@ workspace_del(struct private *m, const char *name)
|
|||
}
|
||||
|
||||
static struct workspace *
|
||||
workspace_lookup(struct private *m, const char *name)
|
||||
workspace_lookup(struct private *m, int id)
|
||||
{
|
||||
tll_foreach(m->workspaces, it) {
|
||||
struct workspace *ws = &it->item;
|
||||
if (strcmp(ws->name, name) == 0)
|
||||
if (ws->id == id)
|
||||
return ws;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -280,6 +288,7 @@ handle_workspace_event(int type, const struct json_object *json, void *_mod)
|
|||
bool is_init = strcmp(change_str, "init") == 0;
|
||||
bool is_empty = strcmp(change_str, "empty") == 0;
|
||||
bool is_focused = strcmp(change_str, "focus") == 0;
|
||||
bool is_rename = strcmp(change_str, "rename") == 0;
|
||||
bool is_urgent = strcmp(change_str, "urgent") == 0;
|
||||
bool is_reload = strcmp(change_str, "reload") == 0;
|
||||
|
||||
|
@ -288,22 +297,22 @@ handle_workspace_event(int type, const struct json_object *json, void *_mod)
|
|||
return true;
|
||||
}
|
||||
|
||||
struct json_object *current, *_current_name;
|
||||
struct json_object *current, *_current_id;
|
||||
if (!json_object_object_get_ex(json, "current", ¤t) ||
|
||||
!json_object_object_get_ex(current, "name", &_current_name))
|
||||
!json_object_object_get_ex(current, "id", &_current_id))
|
||||
{
|
||||
LOG_ERR("workspace event without 'current' and/or 'name' properties");
|
||||
LOG_ERR("workspace event without 'current' and/or 'id' properties");
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *current_name = json_object_get_string(_current_name);
|
||||
int current_id = json_object_get_int(_current_id);
|
||||
|
||||
mtx_lock(&mod->lock);
|
||||
|
||||
if (is_init) {
|
||||
struct workspace *already_exists = workspace_lookup(m, current_name);
|
||||
struct workspace *already_exists = workspace_lookup(m, current_id);
|
||||
if (already_exists != NULL) {
|
||||
LOG_WARN("workspace 'init' event for already existing workspace: %s", current_name);
|
||||
LOG_WARN("workspace 'init' event for already existing workspace: %d", current_id);
|
||||
workspace_free(already_exists);
|
||||
if (!workspace_from_json(current, already_exists))
|
||||
goto err;
|
||||
|
@ -317,14 +326,14 @@ handle_workspace_event(int type, const struct json_object *json, void *_mod)
|
|||
}
|
||||
|
||||
else if (is_empty) {
|
||||
assert(workspace_lookup(m, current_name) != NULL);
|
||||
workspace_del(m, current_name);
|
||||
assert(workspace_lookup(m, current_id) != NULL);
|
||||
workspace_del(m, current_id);
|
||||
}
|
||||
|
||||
else if (is_focused) {
|
||||
struct json_object *old, *_old_name, *urgent;
|
||||
struct json_object *old, *_old_id, *urgent;
|
||||
if (!json_object_object_get_ex(json, "old", &old) ||
|
||||
!json_object_object_get_ex(old, "name", &_old_name) ||
|
||||
!json_object_object_get_ex(old, "id", &_old_id) ||
|
||||
!json_object_object_get_ex(current, "urgent", &urgent))
|
||||
{
|
||||
LOG_ERR("workspace 'focused' event without 'old', 'name' and/or 'urgent' property");
|
||||
|
@ -332,7 +341,7 @@ handle_workspace_event(int type, const struct json_object *json, void *_mod)
|
|||
return false;
|
||||
}
|
||||
|
||||
struct workspace *w = workspace_lookup(m, current_name);
|
||||
struct workspace *w = workspace_lookup(m, current_id);
|
||||
assert(w != NULL);
|
||||
|
||||
LOG_DBG("w: %s", w->name);
|
||||
|
@ -349,12 +358,38 @@ handle_workspace_event(int type, const struct json_object *json, void *_mod)
|
|||
w->visible = true;
|
||||
|
||||
/* Old workspace is no longer focused */
|
||||
const char *old_name = json_object_get_string(_old_name);
|
||||
struct workspace *old_w = workspace_lookup(m, old_name);
|
||||
int old_id = json_object_get_int(_old_id);
|
||||
struct workspace *old_w = workspace_lookup(m, old_id);
|
||||
if (old_w != NULL)
|
||||
old_w->focused = false;
|
||||
}
|
||||
|
||||
else if (is_rename) {
|
||||
struct workspace *w = workspace_lookup(m, current_id);
|
||||
assert(w != NULL);
|
||||
|
||||
struct json_object *_current_name;
|
||||
if (!json_object_object_get_ex(current, "name", &_current_name)) {
|
||||
LOG_ERR("workspace 'rename' event without 'name' property");
|
||||
mtx_unlock(&mod->lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
free(w->name);
|
||||
w->name = strdup(json_object_get_string(_current_name));
|
||||
w->name_as_int = name_as_int(w->name);
|
||||
|
||||
/* Re-add the workspace to ensure correct sorting */
|
||||
struct workspace ws = *w;
|
||||
tll_foreach(m->workspaces, it) {
|
||||
if (it->item.id == current_id) {
|
||||
tll_remove(m->workspaces, it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
workspace_add(m, ws);
|
||||
}
|
||||
|
||||
else if (is_urgent) {
|
||||
struct json_object *urgent;
|
||||
if (!json_object_object_get_ex(current, "urgent", &urgent)) {
|
||||
|
@ -363,7 +398,7 @@ handle_workspace_event(int type, const struct json_object *json, void *_mod)
|
|||
return false;
|
||||
}
|
||||
|
||||
struct workspace *w = workspace_lookup(m, current_name);
|
||||
struct workspace *w = workspace_lookup(m, current_id);
|
||||
w->urgent = json_object_get_boolean(urgent);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue