mirror of
https://codeberg.org/dnkl/yambar.git
synced 2025-04-19 19:25:41 +02:00
commit
9b93b0794a
5 changed files with 93 additions and 39 deletions
|
@ -33,6 +33,8 @@
|
||||||
* pipewire: add a new module for pipewire ([#224][224])
|
* pipewire: add a new module for pipewire ([#224][224])
|
||||||
* on-click: support `next`/`previous` mouse buttons ([#228][228]).
|
* on-click: support `next`/`previous` mouse buttons ([#228][228]).
|
||||||
* dwl: add a new module for DWL ([#218][218])
|
* dwl: add a new module for DWL ([#218][218])
|
||||||
|
* sway: support for workspace ‘rename’ and ‘move’ events
|
||||||
|
([#216][216]).
|
||||||
|
|
||||||
[153]: https://codeberg.org/dnkl/yambar/issues/153
|
[153]: https://codeberg.org/dnkl/yambar/issues/153
|
||||||
[159]: https://codeberg.org/dnkl/yambar/issues/159
|
[159]: https://codeberg.org/dnkl/yambar/issues/159
|
||||||
|
@ -43,6 +45,7 @@
|
||||||
[223]: https://codeberg.org/dnkl/yambar/pulls/223
|
[223]: https://codeberg.org/dnkl/yambar/pulls/223
|
||||||
[224]: https://codeberg.org/dnkl/yambar/pulls/224
|
[224]: https://codeberg.org/dnkl/yambar/pulls/224
|
||||||
[228]: https://codeberg.org/dnkl/yambar/pulls/228
|
[228]: https://codeberg.org/dnkl/yambar/pulls/228
|
||||||
|
[216]: https://codeberg.org/dnkl/yambar/issues/216
|
||||||
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
@ -309,7 +309,7 @@ i3_receive_loop(int abort_fd, int sock,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkt_handler != NULL)
|
if (pkt_handler != NULL)
|
||||||
err = !pkt_handler(hdr->type, json, data);
|
err = !pkt_handler(sock, hdr->type, json, data);
|
||||||
else
|
else
|
||||||
LOG_DBG("no handler for reply/event %d; ignoring", hdr->type);
|
LOG_DBG("no handler for reply/event %d; ignoring", hdr->type);
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
bool i3_get_socket_address(struct sockaddr_un *addr);
|
bool i3_get_socket_address(struct sockaddr_un *addr);
|
||||||
bool i3_send_pkg(int sock, int cmd, char *data);
|
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 {
|
struct i3_ipc_callbacks {
|
||||||
void (*burst_done)(void *data);
|
void (*burst_done)(void *data);
|
||||||
|
|
121
modules/i3.c
121
modules/i3.c
|
@ -29,6 +29,7 @@ struct ws_content {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct workspace {
|
struct workspace {
|
||||||
|
int id;
|
||||||
char *name;
|
char *name;
|
||||||
int name_as_int; /* -1 if name is not a decimal number */
|
int name_as_int; /* -1 if name is not a decimal number */
|
||||||
bool persistent;
|
bool persistent;
|
||||||
|
@ -103,8 +104,9 @@ static bool
|
||||||
workspace_from_json(const struct json_object *json, struct workspace *ws)
|
workspace_from_json(const struct json_object *json, struct workspace *ws)
|
||||||
{
|
{
|
||||||
/* Always present */
|
/* Always present */
|
||||||
struct json_object *name, *output;
|
struct json_object *id, *name, *output;
|
||||||
if (!json_object_object_get_ex(json, "name", &name) ||
|
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))
|
!json_object_object_get_ex(json, "output", &output))
|
||||||
{
|
{
|
||||||
LOG_ERR("workspace reply/event without 'name' and/or 'output' "
|
LOG_ERR("workspace reply/event without 'name' and/or 'output' "
|
||||||
|
@ -132,6 +134,7 @@ workspace_from_json(const struct json_object *json, struct workspace *ws)
|
||||||
int name_as_int = workspace_name_as_int(name_as_string);
|
int name_as_int = workspace_name_as_int(name_as_string);
|
||||||
|
|
||||||
*ws = (struct workspace) {
|
*ws = (struct workspace) {
|
||||||
|
.id = json_object_get_int(id),
|
||||||
.name = strdup(name_as_string),
|
.name = strdup(name_as_string),
|
||||||
.name_as_int = name_as_int,
|
.name_as_int = name_as_int,
|
||||||
.persistent = false,
|
.persistent = false,
|
||||||
|
@ -222,12 +225,12 @@ workspace_add(struct private *m, struct workspace ws)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
workspace_del(struct private *m, const char *name)
|
workspace_del(struct private *m, int id)
|
||||||
{
|
{
|
||||||
tll_foreach(m->workspaces, it) {
|
tll_foreach(m->workspaces, it) {
|
||||||
struct workspace *ws = &it->item;
|
struct workspace *ws = &it->item;
|
||||||
|
|
||||||
if (strcmp(ws->name, name) != 0)
|
if (ws->id != id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
workspace_free(ws);
|
workspace_free(ws);
|
||||||
|
@ -237,18 +240,18 @@ workspace_del(struct private *m, const char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct workspace *
|
static struct workspace *
|
||||||
workspace_lookup(struct private *m, const char *name)
|
workspace_lookup(struct private *m, int id)
|
||||||
{
|
{
|
||||||
tll_foreach(m->workspaces, it) {
|
tll_foreach(m->workspaces, it) {
|
||||||
struct workspace *ws = &it->item;
|
struct workspace *ws = &it->item;
|
||||||
if (strcmp(ws->name, name) == 0)
|
if (ws->id == id)
|
||||||
return ws;
|
return ws;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
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;
|
struct json_object *version;
|
||||||
if (!json_object_object_get_ex(json, "human_readable", &version)) {
|
if (!json_object_object_get_ex(json, "human_readable", &version)) {
|
||||||
|
@ -261,7 +264,7 @@ handle_get_version_reply(int type, const struct json_object *json, void *_m)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
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;
|
struct json_object *success;
|
||||||
if (!json_object_object_get_ex(json, "success", &success)) {
|
if (!json_object_object_get_ex(json, "success", &success)) {
|
||||||
|
@ -280,12 +283,12 @@ handle_subscribe_reply(int type, const struct json_object *json, void *_m)
|
||||||
static bool
|
static bool
|
||||||
workspace_update_or_add(struct private *m, const struct json_object *ws_json)
|
workspace_update_or_add(struct private *m, const struct json_object *ws_json)
|
||||||
{
|
{
|
||||||
struct json_object *name;
|
struct json_object *_id;
|
||||||
if (!json_object_object_get_ex(ws_json, "name", &name))
|
if (!json_object_object_get_ex(ws_json, "id", &_id))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const char *name_as_string = json_object_get_string(name);
|
const int id = json_object_get_int(_id);
|
||||||
struct workspace *already_exists = workspace_lookup(m, name_as_string);
|
struct workspace *already_exists = workspace_lookup(m, id);
|
||||||
|
|
||||||
if (already_exists != NULL) {
|
if (already_exists != NULL) {
|
||||||
bool persistent = already_exists->persistent;
|
bool persistent = already_exists->persistent;
|
||||||
|
@ -307,7 +310,7 @@ workspace_update_or_add(struct private *m, const struct json_object *ws_json)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
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 module *mod = _mod;
|
||||||
struct private *m = mod->private;
|
struct private *m = mod->private;
|
||||||
|
@ -334,7 +337,7 @@ err:
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
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 module *mod = _mod;
|
||||||
struct private *m = mod->private;
|
struct private *m = mod->private;
|
||||||
|
@ -350,23 +353,19 @@ handle_workspace_event(int type, const struct json_object *json, void *_mod)
|
||||||
bool is_init = strcmp(change_str, "init") == 0;
|
bool is_init = strcmp(change_str, "init") == 0;
|
||||||
bool is_empty = strcmp(change_str, "empty") == 0;
|
bool is_empty = strcmp(change_str, "empty") == 0;
|
||||||
bool is_focused = strcmp(change_str, "focus") == 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_urgent = strcmp(change_str, "urgent") == 0;
|
||||||
bool is_reload = strcmp(change_str, "reload") == 0;
|
|
||||||
|
|
||||||
if (is_reload) {
|
struct json_object *current, *_current_id;
|
||||||
LOG_WARN("unimplemented: 'reload' event");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct json_object *current, *_current_name;
|
|
||||||
if (!json_object_object_get_ex(json, "current", ¤t) ||
|
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;
|
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);
|
mtx_lock(&mod->lock);
|
||||||
|
|
||||||
|
@ -376,23 +375,22 @@ handle_workspace_event(int type, const struct json_object *json, void *_mod)
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (is_empty) {
|
else if (is_empty) {
|
||||||
struct workspace *ws = workspace_lookup(m, current_name);
|
struct workspace *ws = workspace_lookup(m, current_id);
|
||||||
assert(ws != NULL);
|
assert(ws != NULL);
|
||||||
|
|
||||||
if (!ws->persistent)
|
if (!ws->persistent)
|
||||||
workspace_del(m, current_name);
|
workspace_del(m, current_id);
|
||||||
else {
|
else {
|
||||||
workspace_free(ws);
|
workspace_free(ws);
|
||||||
ws->name = strdup(current_name);
|
|
||||||
ws->empty = true;
|
ws->empty = true;
|
||||||
assert(ws->persistent);
|
assert(ws->persistent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (is_focused) {
|
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) ||
|
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))
|
!json_object_object_get_ex(current, "urgent", &urgent))
|
||||||
{
|
{
|
||||||
LOG_ERR("workspace 'focused' event without 'old', 'name' and/or 'urgent' property");
|
LOG_ERR("workspace 'focused' event without 'old', 'name' and/or 'urgent' property");
|
||||||
|
@ -400,7 +398,7 @@ handle_workspace_event(int type, const struct json_object *json, void *_mod)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct workspace *w = workspace_lookup(m, current_name);
|
struct workspace *w = workspace_lookup(m, current_id);
|
||||||
assert(w != NULL);
|
assert(w != NULL);
|
||||||
|
|
||||||
LOG_DBG("w: %s", w->name);
|
LOG_DBG("w: %s", w->name);
|
||||||
|
@ -417,12 +415,61 @@ handle_workspace_event(int type, const struct json_object *json, void *_mod)
|
||||||
w->visible = true;
|
w->visible = true;
|
||||||
|
|
||||||
/* Old workspace is no longer focused */
|
/* Old workspace is no longer focused */
|
||||||
const char *old_name = json_object_get_string(_old_name);
|
int old_id = json_object_get_int(_old_id);
|
||||||
struct workspace *old_w = workspace_lookup(m, old_name);
|
struct workspace *old_w = workspace_lookup(m, old_id);
|
||||||
if (old_w != NULL)
|
if (old_w != NULL)
|
||||||
old_w->focused = false;
|
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 = workspace_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) {
|
else if (is_urgent) {
|
||||||
struct json_object *urgent;
|
struct json_object *urgent;
|
||||||
if (!json_object_object_get_ex(current, "urgent", &urgent)) {
|
if (!json_object_object_get_ex(current, "urgent", &urgent)) {
|
||||||
|
@ -431,10 +478,14 @@ handle_workspace_event(int type, const struct json_object *json, void *_mod)
|
||||||
return false;
|
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);
|
w->urgent = json_object_get_boolean(urgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
LOG_WARN("unimplemented workspace event '%s'", change_str);
|
||||||
|
}
|
||||||
|
|
||||||
m->dirty = true;
|
m->dirty = true;
|
||||||
mtx_unlock(&mod->lock);
|
mtx_unlock(&mod->lock);
|
||||||
return true;
|
return true;
|
||||||
|
@ -445,7 +496,7 @@ err:
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
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 module *mod = _mod;
|
||||||
struct private *m = mod->private;
|
struct private *m = mod->private;
|
||||||
|
@ -579,7 +630,7 @@ handle_window_event(int type, const struct json_object *json, void *_mod)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
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 module *mod = _mod;
|
||||||
struct private *m = mod->private;
|
struct private *m = mod->private;
|
||||||
|
|
|
@ -94,7 +94,7 @@ content(struct module *mod)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
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 module *mod = _mod;
|
||||||
struct private *m = mod->private;
|
struct private *m = mod->private;
|
||||||
|
@ -162,7 +162,7 @@ handle_input_reply(int type, const struct json_object *json, void *_mod)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
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 module *mod = _mod;
|
||||||
struct private *m = mod->private;
|
struct private *m = mod->private;
|
||||||
|
|
Loading…
Add table
Reference in a new issue