From 55c1c7e5bf0a5b9fae04cad352d7fa09b65a8008 Mon Sep 17 00:00:00 2001 From: Nikita Ivanov Date: Fri, 21 Jul 2023 07:25:19 +0200 Subject: [PATCH] Add support for dwl ipc patch https://github.com/djpohly/dwl/wiki/ipc --- .gitignore | 4 +- Makefile | 14 +- config.def.h | 4 +- dwlb.c | 298 ++++++++++-------- protocols/dwl-ipc-unstable-v2.xml | 181 +++++++++++ .../net-tapesoftware-dwl-wm-unstable-v1.xml | 164 ---------- 6 files changed, 360 insertions(+), 305 deletions(-) create mode 100644 protocols/dwl-ipc-unstable-v2.xml delete mode 100644 protocols/net-tapesoftware-dwl-wm-unstable-v1.xml diff --git a/.gitignore b/.gitignore index 79e08a9..48f0d83 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,5 @@ xdg-shell-protocol.c xdg-shell-protocol.h xdg-output-unstable-v1-protocol.c xdg-output-unstable-v1-protocol.h -net-tapesoftware-dwl-wm-unstable-v1-protocol.c -net-tapesoftware-dwl-wm-unstable-v1-protocol.h +dwl-ipc-unstable-v2-protocol.c +dwl-ipc-unstable-v2-protocol.h diff --git a/Makefile b/Makefile index 54314b5..bea7da7 100644 --- a/Makefile +++ b/Makefile @@ -35,16 +35,16 @@ wlr-layer-shell-unstable-v1-protocol.c: $(WAYLAND_SCANNER) private-code protocols/wlr-layer-shell-unstable-v1.xml $@ wlr-layer-shell-unstable-v1-protocol.o: wlr-layer-shell-unstable-v1-protocol.h -net-tapesoftware-dwl-wm-unstable-v1-protocol.h: - $(WAYLAND_SCANNER) client-header protocols/net-tapesoftware-dwl-wm-unstable-v1.xml $@ -net-tapesoftware-dwl-wm-unstable-v1-protocol.c: - $(WAYLAND_SCANNER) private-code protocols/net-tapesoftware-dwl-wm-unstable-v1.xml $@ -net-tapesoftware-dwl-wm-unstable-v1-protocol.o: net-tapesoftware-dwl-wm-unstable-v1-protocol.h +dwl-ipc-unstable-v2-protocol.h: + $(WAYLAND_SCANNER) client-header protocols/dwl-ipc-unstable-v2.xml $@ +dwl-ipc-unstable-v2-protocol.c: + $(WAYLAND_SCANNER) private-code protocols/dwl-ipc-unstable-v2.xml $@ +dwl-ipc-unstable-v2-protocol.o: dwl-ipc-unstable-v2-protocol.h -dwlb.o: utf8.h config.h xdg-shell-protocol.h xdg-output-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h net-tapesoftware-dwl-wm-unstable-v1-protocol.o +dwlb.o: utf8.h config.h xdg-shell-protocol.h xdg-output-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h dwl-ipc-unstable-v2-protocol.h # Protocol dependencies -dwlb: xdg-shell-protocol.o xdg-output-unstable-v1-protocol.o wlr-layer-shell-unstable-v1-protocol.o net-tapesoftware-dwl-wm-unstable-v1-protocol.o +dwlb: xdg-shell-protocol.o xdg-output-unstable-v1-protocol.o wlr-layer-shell-unstable-v1-protocol.o dwl-ipc-unstable-v2-protocol.o # Library dependencies dwlb: CFLAGS+=$(shell pkg-config --cflags wayland-client wayland-cursor fcft pixman-1) diff --git a/config.def.h b/config.def.h index f91787b..5b8b71d 100644 --- a/config.def.h +++ b/config.def.h @@ -18,8 +18,8 @@ static bool custom_title = false; static uint32_t buffer_scale = 1; // font static char *fontstr = "monospace:size=16"; -// tag names if ipc is disabled -static char *tags_noipc[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; +// tag names +static char *tags_names[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; // set 16-bit colors for bar // 8-bit color can be converted to 16-bit color by simply duplicating values e.g diff --git a/dwlb.c b/dwlb.c index 3d59236..404c3db 100644 --- a/dwlb.c +++ b/dwlb.c @@ -25,7 +25,7 @@ #include "xdg-shell-protocol.h" #include "xdg-output-unstable-v1-protocol.h" #include "wlr-layer-shell-unstable-v1-protocol.h" -#include "net-tapesoftware-dwl-wm-unstable-v1-protocol.h" +#include "dwl-ipc-unstable-v2-protocol.h" #define DIE(fmt, ...) \ do { \ @@ -133,7 +133,7 @@ typedef struct { struct wl_surface *wl_surface; struct zwlr_layer_surface_v1 *layer_surface; struct zxdg_output_v1 *xdg_output; - struct znet_tapesoftware_dwl_wm_monitor_v1 *dwl_wm_monitor; + struct zdwl_ipc_output_v2 *dwl_wm_output; uint32_t registry_name; char *xdg_output_name; @@ -179,7 +179,7 @@ static struct wl_compositor *compositor; static struct wl_shm *shm; static struct zwlr_layer_shell_v1 *layer_shell; static struct zxdg_output_manager_v1 *output_manager; -static struct znet_tapesoftware_dwl_wm_v1 *dwl_wm; +static struct zdwl_ipc_manager_v2 *dwl_wm; static struct wl_cursor_image *cursor_image; static struct wl_surface *cursor_surface; @@ -649,19 +649,19 @@ pointer_frame(void *data, struct wl_pointer *pointer) /* Clicked on tags */ if (ipc) { if (seat->pointer_button == BTN_LEFT) - znet_tapesoftware_dwl_wm_monitor_v1_set_tags(seat->bar->dwl_wm_monitor, 1 << i, 1); + zdwl_ipc_output_v2_set_tags(seat->bar->dwl_wm_output, 1 << i, 1); else if (seat->pointer_button == BTN_MIDDLE) - znet_tapesoftware_dwl_wm_monitor_v1_set_tags(seat->bar->dwl_wm_monitor, ~0, 1 << i); + zdwl_ipc_output_v2_set_tags(seat->bar->dwl_wm_output, ~0, 1); else if (seat->pointer_button == BTN_RIGHT) - znet_tapesoftware_dwl_wm_monitor_v1_set_tags(seat->bar->dwl_wm_monitor, 0, 1 << i); + zdwl_ipc_output_v2_set_tags(seat->bar->dwl_wm_output, seat->bar->mtags ^ (1 << i), 0); } } else if (seat->pointer_x < (x += TEXT_WIDTH(seat->bar->layout, seat->bar->width - x, seat->bar->textpadding))) { /* Clicked on layout */ if (ipc) { if (seat->pointer_button == BTN_LEFT) - znet_tapesoftware_dwl_wm_monitor_v1_set_layout(seat->bar->dwl_wm_monitor, seat->bar->last_layout_idx); + zdwl_ipc_output_v2_set_layout(seat->bar->dwl_wm_output, seat->bar->last_layout_idx); else if (seat->pointer_button == BTN_RIGHT) - znet_tapesoftware_dwl_wm_monitor_v1_set_layout(seat->bar->dwl_wm_monitor, 2); + zdwl_ipc_output_v2_set_layout(seat->bar->dwl_wm_output, 2); } } else { uint32_t status_x = seat->bar->width / buffer_scale - TEXT_WIDTH(seat->bar->status.text, seat->bar->width - x, seat->bar->textpadding) / buffer_scale; @@ -768,109 +768,6 @@ static const struct wl_seat_listener seat_listener = { .name = seat_name, }; -static void -dwl_wm_tag(void *data, struct znet_tapesoftware_dwl_wm_v1 *dwl_wm, const char *name) -{ - char **ptr; - ARRAY_APPEND(tags, tags_l, tags_c, ptr); - if (!(*ptr = strdup(name))) - EDIE("strdup"); -} - -static void -dwl_wm_layout(void *data, struct znet_tapesoftware_dwl_wm_v1 *dwl_wm, const char *name) -{ - char **ptr; - ARRAY_APPEND(layouts, layouts_l, layouts_c, ptr); - if (!(*ptr = strdup(name))) - EDIE("strdup"); -} - -static const struct znet_tapesoftware_dwl_wm_v1_listener dwl_wm_listener = { - .tag = dwl_wm_tag, - .layout = dwl_wm_layout -}; - -static void -dwl_wm_monitor_selected(void *data, struct znet_tapesoftware_dwl_wm_monitor_v1 *dwl_wm_monitor, - uint32_t selected) -{ - Bar *bar = (Bar *)data; - - if (selected != bar->sel) { - bar->sel = selected; - bar->redraw = true; - } -} - -static void -dwl_wm_monitor_tag(void *data, struct znet_tapesoftware_dwl_wm_monitor_v1 *dwl_wm_monitor, - uint32_t tag, uint32_t state, uint32_t clients, int32_t focused_client) -{ - Bar *bar = (Bar *)data; - - uint32_t imtags = bar->mtags; - uint32_t ictags = bar->ctags; - uint32_t iurg = bar->urg; - - if (state & ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_ACTIVE) - bar->mtags |= 1 << tag; - else - bar->mtags &= ~(1 << tag); - if (clients > 0) - bar->ctags |= 1 << tag; - else - bar->ctags &= ~(1 << tag); - if (state & ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_URGENT) - bar->urg |= 1 << tag; - else - bar->urg &= ~(1 << tag); - - if (bar->mtags != imtags || bar->ctags != ictags || bar->urg != iurg) - bar->redraw = true; -} - -static void -dwl_wm_monitor_layout(void *data, struct znet_tapesoftware_dwl_wm_monitor_v1 *dwl_wm_monitor, - uint32_t layout) -{ - Bar *bar = (Bar *)data; - - bar->layout = layouts[layout]; - bar->last_layout_idx = bar->layout_idx; - bar->layout_idx = layout; - bar->redraw = true; -} - -static void -dwl_wm_monitor_title(void *data, struct znet_tapesoftware_dwl_wm_monitor_v1 *dwl_wm_monitor, - const char *title) -{ - if (custom_title) - return; - - Bar *bar = (Bar *)data; - - if (bar->window_title) - free(bar->window_title); - if (!(bar->window_title = strdup(title))) - EDIE("strdup"); - bar->redraw = true; -} - -static void -dwl_wm_monitor_frame(void *data, struct znet_tapesoftware_dwl_wm_monitor_v1 *dwl_wm_monitor) -{ -} - -static const struct znet_tapesoftware_dwl_wm_monitor_v1_listener dwl_wm_monitor_listener = { - .selected = dwl_wm_monitor_selected, - .tag = dwl_wm_monitor_tag, - .layout = dwl_wm_monitor_layout, - .title = dwl_wm_monitor_title, - .frame = dwl_wm_monitor_frame -}; - static void show_bar(Bar *bar) { @@ -905,6 +802,151 @@ hide_bar(Bar *bar) bar->hidden = true; } +static void +dwl_wm_tags(void *data, struct zdwl_ipc_manager_v2 *dwl_wm, + uint32_t amount) +{ + if (!tags && !(tags = malloc(amount * sizeof(char *)))) + EDIE("malloc"); + uint32_t i = tags_l; + ARRAY_EXPAND(tags, tags_l, tags_c, MAX(0, (int)amount - (int)tags_l)); + for (; i < amount; i++) + if (!(tags[i] = strdup(tags_names[MIN(i, LENGTH(tags_names)-1)]))) + EDIE("strdup"); +} + +static void +dwl_wm_layout(void *data, struct zdwl_ipc_manager_v2 *dwl_wm, + const char *name) +{ + char **ptr; + ARRAY_APPEND(layouts, layouts_l, layouts_c, ptr); + if (!(*ptr = strdup(name))) + EDIE("strdup"); +} + +static const struct zdwl_ipc_manager_v2_listener dwl_wm_listener = { + .tags = dwl_wm_tags, + .layout = dwl_wm_layout +}; + +static void +dwl_wm_output_toggle_visibility(void *data, struct zdwl_ipc_output_v2 *dwl_wm_output) +{ + Bar *bar = (Bar *)data; + + if (bar->hidden) + show_bar(bar); + else + hide_bar(bar); +} + +static void +dwl_wm_output_active(void *data, struct zdwl_ipc_output_v2 *dwl_wm_output, + uint32_t active) +{ + Bar *bar = (Bar *)data; + + if (active != bar->sel) + bar->sel = active; +} + +static void +dwl_wm_output_tag(void *data, struct zdwl_ipc_output_v2 *dwl_wm_output, + uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused) +{ + Bar *bar = (Bar *)data; + + if (state & ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE) + bar->mtags |= 1 << tag; + else + bar->mtags &= ~(1 << tag); + if (clients > 0) + bar->ctags |= 1 << tag; + else + bar->ctags &= ~(1 << tag); + if (state & ZDWL_IPC_OUTPUT_V2_TAG_STATE_URGENT) + bar->urg |= 1 << tag; + else + bar->urg &= ~(1 << tag); +} + +static void +dwl_wm_output_layout(void *data, struct zdwl_ipc_output_v2 *dwl_wm_output, + uint32_t layout) +{ + Bar *bar = (Bar *)data; + + bar->last_layout_idx = bar->layout_idx; + bar->layout_idx = layout; +} + +static void +dwl_wm_output_title(void *data, struct zdwl_ipc_output_v2 *dwl_wm_output, + const char *title) +{ + if (custom_title) + return; + + Bar *bar = (Bar *)data; + + if (bar->window_title) + free(bar->window_title); + if (!(bar->window_title = strdup(title))) + EDIE("strdup"); +} + +static void +dwl_wm_output_appid(void *data, struct zdwl_ipc_output_v2 *dwl_wm_output, + const char *appid) +{ +} + +static void +dwl_wm_output_layout_symbol(void *data, struct zdwl_ipc_output_v2 *dwl_wm_output, + const char *layout) +{ + Bar *bar = (Bar *)data; + + if (layouts[bar->layout_idx]) + free(layouts[bar->layout_idx]); + if (!(layouts[bar->layout_idx] = strdup(layout))) + EDIE("strdup"); + bar->layout = layouts[bar->layout_idx]; +} + +static void +dwl_wm_output_frame(void *data, struct zdwl_ipc_output_v2 *dwl_wm_output) +{ + Bar *bar = (Bar *)data; + bar->redraw = true; +} + +static void +dwl_wm_output_fullscreen(void *data, struct zdwl_ipc_output_v2 *dwl_wm_output, + uint32_t is_fullscreen) +{ +} + +static void +dwl_wm_output_floating(void *data, struct zdwl_ipc_output_v2 *dwl_wm_output, + uint32_t is_floating) +{ +} + +static const struct zdwl_ipc_output_v2_listener dwl_wm_output_listener = { + .toggle_visibility = dwl_wm_output_toggle_visibility, + .active = dwl_wm_output_active, + .tag = dwl_wm_output_tag, + .layout = dwl_wm_output_layout, + .title = dwl_wm_output_title, + .appid = dwl_wm_output_appid, + .layout_symbol = dwl_wm_output_layout_symbol, + .frame = dwl_wm_output_frame, + .fullscreen = dwl_wm_output_fullscreen, + .floating = dwl_wm_output_floating +}; + static void setup_bar(Bar *bar) { @@ -919,10 +961,10 @@ setup_bar(Bar *bar) zxdg_output_v1_add_listener(bar->xdg_output, &output_listener, bar); if (ipc) { - bar->dwl_wm_monitor = znet_tapesoftware_dwl_wm_v1_get_monitor(dwl_wm, bar->wl_output); - if (!bar->dwl_wm_monitor) - DIE("Could not create dwl_wm_monitor"); - znet_tapesoftware_dwl_wm_monitor_v1_add_listener(bar->dwl_wm_monitor, &dwl_wm_monitor_listener, bar); + bar->dwl_wm_output = zdwl_ipc_manager_v2_get_output(dwl_wm, bar->wl_output); + if (!bar->dwl_wm_output) + DIE("Could not create dwl_wm_output"); + zdwl_ipc_output_v2_add_listener(bar->dwl_wm_output, &dwl_wm_output_listener, bar); } if (!bar->hidden) @@ -941,10 +983,10 @@ handle_global(void *data, struct wl_registry *registry, layer_shell = wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 1); } else if (!strcmp(interface, zxdg_output_manager_v1_interface.name)) { output_manager = wl_registry_bind(registry, name, &zxdg_output_manager_v1_interface, 2); - } else if (!strcmp(interface, znet_tapesoftware_dwl_wm_v1_interface.name)) { + } else if (!strcmp(interface, zdwl_ipc_manager_v2_interface.name)) { if (ipc) { - dwl_wm = wl_registry_bind(registry, name, &znet_tapesoftware_dwl_wm_v1_interface, 1); - znet_tapesoftware_dwl_wm_v1_add_listener(dwl_wm, &dwl_wm_listener, NULL); + dwl_wm = wl_registry_bind(registry, name, &zdwl_ipc_manager_v2_interface, 2); + zdwl_ipc_manager_v2_add_listener(dwl_wm, &dwl_wm_listener, NULL); } } else if (!strcmp(interface, wl_output_interface.name)) { Bar *bar = calloc(1, sizeof(Bar)); @@ -977,10 +1019,12 @@ teardown_bar(Bar *bar) free(bar->title.colors); if (bar->title.buttons) free(bar->title.buttons); + if (bar->window_title) + free(bar->window_title); if (!ipc && bar->layout) free(bar->layout); if (ipc) - znet_tapesoftware_dwl_wm_monitor_v1_destroy(bar->dwl_wm_monitor); + zdwl_ipc_output_v2_destroy(bar->dwl_wm_output); if (bar->xdg_output_name) free(bar->xdg_output_name); if (!bar->hidden) { @@ -1739,18 +1783,12 @@ main(int argc, char **argv) height = font->height / buffer_scale + vertical_padding * 2; /* Configure tag names */ - if (ipc && tags) { - for (uint32_t i = 0; i < tags_l; i++) - free(tags[i]); - free(tags); - tags_l = tags_c = 0; - tags = NULL; - } else if (!ipc && !tags) { - if (!(tags = malloc(LENGTH(tags_noipc) * sizeof(char *)))) + if (!ipc && !tags) { + if (!(tags = malloc(LENGTH(tags_names) * sizeof(char *)))) EDIE("malloc"); - tags_l = tags_c = LENGTH(tags_noipc); + tags_l = tags_c = LENGTH(tags_names); for (uint32_t i = 0; i < tags_l; i++) - if (!(tags[i] = strdup(tags_noipc[i]))) + if (!(tags[i] = strdup(tags_names[i]))) EDIE("strdup"); } @@ -1829,7 +1867,7 @@ main(int argc, char **argv) zwlr_layer_shell_v1_destroy(layer_shell); zxdg_output_manager_v1_destroy(output_manager); if (ipc) - znet_tapesoftware_dwl_wm_v1_destroy(dwl_wm); + zdwl_ipc_manager_v2_destroy(dwl_wm); fcft_destroy(font); fcft_fini(); diff --git a/protocols/dwl-ipc-unstable-v2.xml b/protocols/dwl-ipc-unstable-v2.xml new file mode 100644 index 0000000..0a6e7e5 --- /dev/null +++ b/protocols/dwl-ipc-unstable-v2.xml @@ -0,0 +1,181 @@ + + + + + This protocol allows clients to update and get updates from dwl. + + Warning! The protocol described in this file is experimental and + backward incompatible changes may be made. Backward compatible + changes may be added together with the corresponding interface + version bump. + Backward incompatible changes are done by bumping the version + number in the protocol and interface names and resetting the + interface version. Once the protocol is to be declared stable, + the 'z' prefix and the version number in the protocol and + interface names are removed and the interface version number is + reset. + + + + + This interface is exposed as a global in wl_registry. + + Clients can use this interface to get a dwl_ipc_output. + After binding the client will recieve the dwl_ipc_manager.tags and dwl_ipc_manager.layout events. + The dwl_ipc_manager.tags and dwl_ipc_manager.layout events expose tags and layouts to the client. + + + + + Indicates that the client will not the dwl_ipc_manager object anymore. + Objects created through this instance are not affected. + + + + + + Get a dwl_ipc_outout for the specified wl_output. + + + + + + + + This event is sent after binding. + A roundtrip after binding guarantees the client recieved all tags. + + + + + + + This event is sent after binding. + A roundtrip after binding guarantees the client recieved all layouts. + + + + + + + + Observe and control a dwl output. + + Events are double-buffered: + Clients should cache events and redraw when a dwl_ipc_output.frame event is sent. + + Request are not double-buffered: + The compositor will update immediately upon request. + + + + + + + + + + + Indicates to that the client no longer needs this dwl_ipc_output. + + + + + + Indicates the client should hide or show themselves. + If the client is visible then hide, if hidden then show. + + + + + + Indicates if the output is active. Zero is invalid, nonzero is valid. + + + + + + + Indicates that a tag has been updated. + + + + + + + + + + Indicates a new layout is selected. + + + + + + + Indicates the title has changed. + + + + + + + Indicates the appid has changed. + + + + + + + Indicates the layout has changed. Since layout symbols are dynamic. + As opposed to the zdwl_ipc_manager.layout event, this should take precendence when displaying. + You can ignore the zdwl_ipc_output.layout event. + + + + + + + Indicates that a sequence of status updates have finished and the client should redraw. + + + + + + + + + + + + The tags are updated as follows: + new_tags = (current_tags AND and_tags) XOR xor_tags + + + + + + + + + + + + + + Indicates if the selected client on this output is fullscreen. + + + + + + + Indicates if the selected client on this output is floating. + + + + + diff --git a/protocols/net-tapesoftware-dwl-wm-unstable-v1.xml b/protocols/net-tapesoftware-dwl-wm-unstable-v1.xml deleted file mode 100644 index 4fe5b73..0000000 --- a/protocols/net-tapesoftware-dwl-wm-unstable-v1.xml +++ /dev/null @@ -1,164 +0,0 @@ - - - - Copyright (c) 2021 Raphael Robatsch - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice (including the - next paragraph) shall be included in all copies or substantial portions - of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - - - This interface is exposed as a global in the wl_registry. - - Clients can use this protocol to receive updates of the window manager - state (active tags, active layout, and focused window). - Clients can also control this state. - - After binding, the client will receive the available tags and layouts - with the 'tag' and 'layout' events. These can be used in subsequent - dwl_wm_monitor_v1.set_tags/set_layout requests, and to interpret the - dwl_wm_monitor_v1.layout/tag events. - - - - - This request indicates that the client will not use the dwl_wm - object any more. Objects that have been created through this instance - are not affected. - - - - - - Gets a dwl monitor for the specified output. The window manager - state on the output can be controlled using the monitor. - - - - - - - - This event is sent immediately after binding. - A roundtrip after binding guarantees that the client has received all tags. - - - - - - - This event is sent immediately after binding. - A roundtrip after binding guarantees that the client has received all layouts. - - - - - - - - Observes and controls one monitor. - - Events are double-buffered: Clients should cache all events and only - redraw themselves once the 'frame' event is sent. - - Requests are not double-buffered: The compositor will update itself - immediately. - - - - - - - - - - - This request indicates that the client is done with this dwl_monitor. - All further requests are ignored. - - - - - - If 'selected' is nonzero, this monitor is the currently selected one. - - - - - - - Announces the update of a tag. num_clients and focused_client can be - used to draw client indicators. - - - - - - - - - - Announces the update of the selected layout. - - - - - - - Announces the update of the selected client. - - - - - - - Sent after all other events belonging to the status update has been sent. - Clients should redraw themselves now. - - - - - - Changes are applied immediately. - - - - - - - - tags are updated as follows: - new_tags = (current_tags AND and_tags) XOR xor_tags - - Changes are applied immediately. - - - - - - - - Changes are applied immediately. - - - - -