Mercurial > myrepo
view include/dwl-ipc.h @ 1:50bab568625d default tip
lol
| author | tsukasa <qwerasdnoob@gmail.com> |
|---|---|
| date | Sat, 11 Jul 2026 17:56:41 +0800 |
| parents | |
| children |
line wrap: on
line source
#include "dwl-ipc-unstable-v2-protocol.h" /* Forward declarations for dwl.c static functions */ static void arrange(Monitor *m); static void focusclient(Client *c, int lift); static Client *focustop(Monitor *m); static void printstatus(void); /* globals */ static struct wl_global *ipc_global = NULL; /* All bound manager objects */ static struct wl_list ipc_managers; /* IpcManager.link */ typedef struct { struct wl_resource *resource; struct wl_list link; /* ipc_managers */ struct wl_list outputs; /* IpcOutput.link */ } IpcManager; typedef struct { struct wl_resource *resource; Monitor *mon; struct wl_list link; /* IpcManager.outputs */ } IpcOutput; /* helpers */ static IpcOutput * ipc_output_for_mon(IpcManager *mgr, Monitor *m) { IpcOutput *o; wl_list_for_each(o, &mgr->outputs, link) if (o->mon == m) return o; return NULL; } /* Send the full state of monitor m to one IpcOutput resource */ static void ipc_send_output_state(IpcOutput *ipc_out) { Monitor *m = ipc_out->mon; struct wl_resource *res = ipc_out->resource; Client *c; uint32_t occ = 0, urg = 0, sel_tags = 0; int tag, focused; /* Compute occupancy/urgency (same logic as printstatus, I think) */ wl_list_for_each(c, &clients, link) { if (c->mon != m) continue; occ |= c->tags; if (c->isurgent) urg |= c->tags; } c = focustop(m); sel_tags = c ? c->tags : 0; /* active */ zdwl_ipc_output_v2_send_active(res, m == selmon ? 1 : 0); /* per-tag state */ for (tag = 0; tag < TAGCOUNT; tag++) { uint32_t mask = 1u << tag; uint32_t state = ZDWL_IPC_OUTPUT_V2_TAG_STATE_NONE; uint32_t clients_on_tag = 0; if (m->tagset[m->seltags] & mask) state = ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE; if (urg & mask) state = ZDWL_IPC_OUTPUT_V2_TAG_STATE_URGENT; if (occ & mask) clients_on_tag = 1; /* report ≥1, not exact count */ focused = (sel_tags & mask) ? 1 : 0; zdwl_ipc_output_v2_send_tag(res, tag, state, clients_on_tag, focused); } /* layout index */ { uint32_t i; for (i = 0; i < LENGTH(layouts); i++) if (&layouts[i] == m->lt[m->sellt]) break; zdwl_ipc_output_v2_send_layout(res, i); } /* layout symbol */ zdwl_ipc_output_v2_send_layout_symbol(res, m->ltsymbol); /* title/appid/fullscreen/floating */ if (c) { zdwl_ipc_output_v2_send_title(res, client_get_title(c)); zdwl_ipc_output_v2_send_appid(res, client_get_appid(c)); if (wl_resource_get_version(res) >= 2) { zdwl_ipc_output_v2_send_fullscreen(res, c->isfullscreen ? 1 : 0); zdwl_ipc_output_v2_send_floating(res, c->isfloating ? 1 : 0); } } else { zdwl_ipc_output_v2_send_title(res, ""); zdwl_ipc_output_v2_send_appid(res, ""); if (wl_resource_get_version(res) >= 2) { zdwl_ipc_output_v2_send_fullscreen(res, 0); zdwl_ipc_output_v2_send_floating(res, 0); } } /* frame — signals end of this batch of events */ zdwl_ipc_output_v2_send_frame(res); } /* Called instead of (or alongside) the old printstatus() */ static void ipc_printstatus(void) { IpcManager *mgr; Monitor *m; wl_list_for_each(mgr, &ipc_managers, link) { wl_list_for_each(m, &mons, link) { IpcOutput *out = ipc_output_for_mon(mgr, m); if (out) ipc_send_output_state(out); } } } /* zdwl_ipc_output_v2 requests */ static void ipc_output_handle_release(struct wl_client *client, struct wl_resource *resource) { wl_resource_destroy(resource); } static void ipc_output_handle_set_tags(struct wl_client *client, struct wl_resource *resource, uint32_t tagmask, uint32_t toggle_tagset) { IpcOutput *out = wl_resource_get_user_data(resource); Monitor *m = out->mon; if (!m) return; if (toggle_tagset) m->seltags ^= 1; m->tagset[m->seltags] = tagmask & TAGMASK; focusclient(focustop(m), 1); arrange(m); printstatus(); } static void ipc_output_handle_set_client_tags(struct wl_client *client, struct wl_resource *resource, uint32_t and_tags, uint32_t xor_tags) { IpcOutput *out = wl_resource_get_user_data(resource); Monitor *m = out->mon; Client *sel; uint32_t newtags; if (!m) return; sel = focustop(m); if (!sel) return; newtags = (sel->tags & and_tags) ^ xor_tags; if (!newtags) return; sel->tags = newtags; focusclient(focustop(m), 1); arrange(m); printstatus(); } static void ipc_output_handle_set_layout(struct wl_client *client, struct wl_resource *resource, uint32_t idx) { IpcOutput *out = wl_resource_get_user_data(resource); Monitor *m = out->mon; if (!m || idx >= LENGTH(layouts)) return; m->lt[m->sellt] = &layouts[idx]; strncpy(m->ltsymbol, layouts[idx].symbol, LENGTH(m->ltsymbol)); arrange(m); printstatus(); } static const struct zdwl_ipc_output_v2_interface ipc_output_impl = { .release = ipc_output_handle_release, .set_tags = ipc_output_handle_set_tags, .set_client_tags = ipc_output_handle_set_client_tags, .set_layout = ipc_output_handle_set_layout, }; static void ipc_output_destroy(struct wl_resource *resource) { IpcOutput *out = wl_resource_get_user_data(resource); wl_list_remove(&out->link); free(out); } /* zdwl_ipc_manager_v2 requests */ static void ipc_manager_handle_release(struct wl_client *client, struct wl_resource *resource) { wl_resource_destroy(resource); } static void ipc_manager_handle_get_output(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *output_resource) { IpcManager *mgr = wl_resource_get_user_data(resource); struct wlr_output *wlr_out = wlr_output_from_resource(output_resource); Monitor *m = (wlr_out && wlr_out->data) ? wlr_out->data : NULL; IpcOutput *out = ecalloc(1, sizeof(*out)); out->mon = m; out->resource = wl_resource_create(client, &zdwl_ipc_output_v2_interface, wl_resource_get_version(resource), id); if (!out->resource) { free(out); wl_client_post_no_memory(client); return; } wl_resource_set_implementation(out->resource, &ipc_output_impl, out, ipc_output_destroy); wl_list_insert(&mgr->outputs, &out->link); if (m) ipc_send_output_state(out); } static const struct zdwl_ipc_manager_v2_interface ipc_manager_impl = { .release = ipc_manager_handle_release, .get_output = ipc_manager_handle_get_output, }; static void ipc_manager_destroy(struct wl_resource *resource) { IpcManager *mgr = wl_resource_get_user_data(resource); IpcOutput *out, *tmp; wl_list_for_each_safe(out, tmp, &mgr->outputs, link) wl_resource_destroy(out->resource); wl_list_remove(&mgr->link); free(mgr); } /* global bind */ static void ipc_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) { IpcManager *mgr = ecalloc(1, sizeof(*mgr)); wl_list_init(&mgr->outputs); mgr->resource = wl_resource_create(client, &zdwl_ipc_manager_v2_interface, version, id); if (!mgr->resource) { free(mgr); wl_client_post_no_memory(client); return; } wl_resource_set_implementation(mgr->resource, &ipc_manager_impl, mgr, ipc_manager_destroy); wl_list_insert(&ipc_managers, &mgr->link); /* Announce tags and layouts */ zdwl_ipc_manager_v2_send_tags(mgr->resource, TAGCOUNT); for (uint32_t i = 0; i < LENGTH(layouts); i++) zdwl_ipc_manager_v2_send_layout(mgr->resource, layouts[i].symbol); } static void ipc_init(void) { wl_list_init(&ipc_managers); ipc_global = wl_global_create(dpy, &zdwl_ipc_manager_v2_interface, 2, NULL, ipc_bind); }
