WIP: Implement more workspace events #70

Open
clktmr wants to merge 4 commits from clktmr/yambar:i3-workspace-rename into master
  1. 2
      modules/i3-common.c
  2. 2
      modules/i3-common.h
  3. 147
      modules/i3.c
  4. 4
      modules/sway-xkb.c

2
modules/i3-common.c

@ -309,7 +309,7 @@ i3_receive_loop(int abort_fd, int sock,
}
if (pkt_handler != NULL)
err = !pkt_handler(hdr->type, json, data);
err = !pkt_handler(sock, hdr->type, json, data);
else
LOG_DBG("no handler for reply/event %d; ignoring", hdr->type);

2
modules/i3-common.h

@ -11,7 +11,7 @@
bool i3_get_socket_address(struct sockaddr_un *addr);
bool i3_send_pkg(int sock, int cmd, char *data);
typedef bool (*i3_ipc_callback_t)(int type, const struct json_object *json, void *data);
typedef bool (*i3_ipc_callback_t)(int sock, int type, const struct json_object *json, void *data);
struct i3_ipc_callbacks {
void (*burst_done)(void *data);

147
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,18 +202,18 @@ 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;
}
static bool
handle_get_version_reply(int type, const struct json_object *json, void *_m)
handle_get_version_reply(int sock, int type, const struct json_object *json, void *_m)
{
struct json_object *version;
if (!json_object_object_get_ex(json, "human_readable", &version)) {
@ -218,7 +226,7 @@ handle_get_version_reply(int type, const struct json_object *json, void *_m)
}
static bool
handle_subscribe_reply(int type, const struct json_object *json, void *_m)
handle_subscribe_reply(int sock, int type, const struct json_object *json, void *_m)
{
struct json_object *success;
if (!json_object_object_get_ex(json, "success", &success)) {
@ -235,7 +243,7 @@ handle_subscribe_reply(int type, const struct json_object *json, void *_m)
}
static bool
handle_get_workspaces_reply(int type, const struct json_object *json, void *_mod)
handle_get_workspaces_reply(int sock, int type, const struct json_object *json, void *_mod)
{
struct module *mod = _mod;
struct private *m = mod->private;
@ -255,7 +263,7 @@ handle_get_workspaces_reply(int type, const struct json_object *json, void *_mod
return false;
}
LOG_DBG("#%zu: %s", i, m->workspaces.v[i].name);
LOG_DBG("#%zu: %s", i, ws.name);
workspace_add(m, ws);
}
@ -264,7 +272,7 @@ handle_get_workspaces_reply(int type, const struct json_object *json, void *_mod
}
static bool
handle_workspace_event(int type, const struct json_object *json, void *_mod)
handle_workspace_event(int sock, int type, const struct json_object *json, void *_mod)
{
struct module *mod = _mod;
struct private *m = mod->private;
@ -280,30 +288,26 @@ 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_move = strcmp(change_str, "move") == 0;
bool is_urgent = strcmp(change_str, "urgent") == 0;
bool is_reload = strcmp(change_str, "reload") == 0;
if (is_reload) {
LOG_WARN("unimplemented: 'reload' event");
return true;
}
struct json_object *current, *_current_name;
struct json_object *current, *_current_id;
if (!json_object_object_get_ex(json, "current", &current) ||
!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 +321,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 +336,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 +353,61 @@ 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_move) {
struct workspace *w = workspace_lookup(m, current_id);
assert(w != NULL);
struct json_object *_current_output;
if (!json_object_object_get_ex(current, "output", &_current_output)) {
LOG_ERR("workspace 'move' event without 'output' property");
mtx_unlock(&mod->lock);
return false;
}
free(w->output);
w->output = strdup(json_object_get_string(_current_output));
/*
* If the moved workspace was focused, schedule a full update because
* visibility for other workspaces may have changed.
*/
if (w->focused) {
i3_send_pkg(sock, I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL);
}
}
else if (is_urgent) {
struct json_object *urgent;
if (!json_object_object_get_ex(current, "urgent", &urgent)) {
@ -363,10 +416,14 @@ 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);
}
else {
LOG_WARN("unimplemented workspace event '%s'", change_str);
}
m->dirty = true;
mtx_unlock(&mod->lock);
return true;
@ -377,7 +434,7 @@ err:
}
static bool
handle_window_event(int type, const struct json_object *json, void *_mod)
handle_window_event(int sock, int type, const struct json_object *json, void *_mod)
{
struct module *mod = _mod;
struct private *m = mod->private;
@ -503,7 +560,7 @@ handle_window_event(int type, const struct json_object *json, void *_mod)
}
static bool
handle_mode_event(int type, const struct json_object *json, void *_mod)
handle_mode_event(int sock, int type, const struct json_object *json, void *_mod)
{
struct module *mod = _mod;
struct private *m = mod->private;

4
modules/sway-xkb.c

@ -90,7 +90,7 @@ content(struct module *mod)
}
static bool
handle_input_reply(int type, const struct json_object *json, void *_mod)
handle_input_reply(int sock, int type, const struct json_object *json, void *_mod)
{
struct module *mod = _mod;
struct private *m = mod->private;
@ -155,7 +155,7 @@ handle_input_reply(int type, const struct json_object *json, void *_mod)
}
static bool
handle_input_event(int type, const struct json_object *json, void *_mod)
handle_input_event(int sock, int type, const struct json_object *json, void *_mod)
{
struct module *mod = _mod;
struct private *m = mod->private;

Loading…
Cancel
Save