From 8210f486966625249f076b7bffc72a96f9b0a2c7 Mon Sep 17 00:00:00 2001 From: speedie Date: Tue, 6 Jun 2023 01:23:42 +0200 Subject: [PATCH] add ipc patch --- config.h | 6 +- dwl-ipc-unstable-v2-protocol.c | 68 ++++++ dwl-ipc-unstable-v2-protocol.h | 388 ++++++++++++++++++++++++++++++ dwl.c | 185 +++++++++++++- meson.build | 4 +- protocols/dwl-ipc-unstable-v2.xml | 166 +++++++++++++ 6 files changed, 812 insertions(+), 5 deletions(-) create mode 100644 dwl-ipc-unstable-v2-protocol.c create mode 100644 dwl-ipc-unstable-v2-protocol.h create mode 100644 protocols/dwl-ipc-unstable-v2.xml diff --git a/config.h b/config.h index d3b1f63..32d6e52 100644 --- a/config.h +++ b/config.h @@ -92,7 +92,7 @@ LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM; /* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */ -#define MODKEY WLR_MODIFIER_ALT +#define MODKEY WLR_MODIFIER_LOGO #define TAGKEYS(KEY,SKEY,TAG) \ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ @@ -120,7 +120,7 @@ static const Key keys[] = { { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05} }, { MODKEY, XKB_KEY_Return, zoom, {0} }, { MODKEY, XKB_KEY_Tab, view, {0} }, - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, killclient, {0} }, { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, @@ -142,7 +142,7 @@ static const Key keys[] = { TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6), TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7), TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8), - { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} }, + //{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} }, /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} }, diff --git a/dwl-ipc-unstable-v2-protocol.c b/dwl-ipc-unstable-v2-protocol.c new file mode 100644 index 0000000..aef5470 --- /dev/null +++ b/dwl-ipc-unstable-v2-protocol.c @@ -0,0 +1,68 @@ +/* Generated by wayland-scanner 1.22.0 */ + +#include +#include +#include "wayland-util.h" + +#ifndef __has_attribute +# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ +#endif + +#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) +#define WL_PRIVATE __attribute__ ((visibility("hidden"))) +#else +#define WL_PRIVATE +#endif + +extern const struct wl_interface wl_output_interface; +extern const struct wl_interface zdwl_ipc_output_v2_interface; + +static const struct wl_interface *dwl_ipc_unstable_v2_types[] = { + NULL, + NULL, + NULL, + NULL, + &zdwl_ipc_output_v2_interface, + &wl_output_interface, +}; + +static const struct wl_message zdwl_ipc_manager_v2_requests[] = { + { "release", "", dwl_ipc_unstable_v2_types + 0 }, + { "get_output", "no", dwl_ipc_unstable_v2_types + 4 }, +}; + +static const struct wl_message zdwl_ipc_manager_v2_events[] = { + { "tags", "u", dwl_ipc_unstable_v2_types + 0 }, + { "layout", "s", dwl_ipc_unstable_v2_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface zdwl_ipc_manager_v2_interface = { + "zdwl_ipc_manager_v2", 1, + 2, zdwl_ipc_manager_v2_requests, + 2, zdwl_ipc_manager_v2_events, +}; + +static const struct wl_message zdwl_ipc_output_v2_requests[] = { + { "release", "", dwl_ipc_unstable_v2_types + 0 }, + { "set_tags", "uu", dwl_ipc_unstable_v2_types + 0 }, + { "set_client_tags", "uu", dwl_ipc_unstable_v2_types + 0 }, + { "set_layout", "u", dwl_ipc_unstable_v2_types + 0 }, +}; + +static const struct wl_message zdwl_ipc_output_v2_events[] = { + { "toggle_visibility", "", dwl_ipc_unstable_v2_types + 0 }, + { "active", "u", dwl_ipc_unstable_v2_types + 0 }, + { "tag", "uuuu", dwl_ipc_unstable_v2_types + 0 }, + { "layout", "u", dwl_ipc_unstable_v2_types + 0 }, + { "title", "s", dwl_ipc_unstable_v2_types + 0 }, + { "appid", "s", dwl_ipc_unstable_v2_types + 0 }, + { "layout_symbol", "s", dwl_ipc_unstable_v2_types + 0 }, + { "frame", "", dwl_ipc_unstable_v2_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface zdwl_ipc_output_v2_interface = { + "zdwl_ipc_output_v2", 1, + 4, zdwl_ipc_output_v2_requests, + 8, zdwl_ipc_output_v2_events, +}; + diff --git a/dwl-ipc-unstable-v2-protocol.h b/dwl-ipc-unstable-v2-protocol.h new file mode 100644 index 0000000..da2c4f9 --- /dev/null +++ b/dwl-ipc-unstable-v2-protocol.h @@ -0,0 +1,388 @@ +/* Generated by wayland-scanner 1.22.0 */ + +#ifndef DWL_IPC_UNSTABLE_V2_SERVER_PROTOCOL_H +#define DWL_IPC_UNSTABLE_V2_SERVER_PROTOCOL_H + +#include +#include +#include "wayland-server.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct wl_client; +struct wl_resource; + +/** + * @page page_dwl_ipc_unstable_v2 The dwl_ipc_unstable_v2 protocol + * inter-proccess-communication about dwl's state + * + * @section page_desc_dwl_ipc_unstable_v2 Description + * + * 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. + * + * @section page_ifaces_dwl_ipc_unstable_v2 Interfaces + * - @subpage page_iface_zdwl_ipc_manager_v2 - manage dwl state + * - @subpage page_iface_zdwl_ipc_output_v2 - control dwl output + */ +struct wl_output; +struct zdwl_ipc_manager_v2; +struct zdwl_ipc_output_v2; + +#ifndef ZDWL_IPC_MANAGER_V2_INTERFACE +#define ZDWL_IPC_MANAGER_V2_INTERFACE +/** + * @page page_iface_zdwl_ipc_manager_v2 zdwl_ipc_manager_v2 + * @section page_iface_zdwl_ipc_manager_v2_desc Description + * + * 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. + * @section page_iface_zdwl_ipc_manager_v2_api API + * See @ref iface_zdwl_ipc_manager_v2. + */ +/** + * @defgroup iface_zdwl_ipc_manager_v2 The zdwl_ipc_manager_v2 interface + * + * 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. + */ +extern const struct wl_interface zdwl_ipc_manager_v2_interface; +#endif +#ifndef ZDWL_IPC_OUTPUT_V2_INTERFACE +#define ZDWL_IPC_OUTPUT_V2_INTERFACE +/** + * @page page_iface_zdwl_ipc_output_v2 zdwl_ipc_output_v2 + * @section page_iface_zdwl_ipc_output_v2_desc Description + * + * 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. + * @section page_iface_zdwl_ipc_output_v2_api API + * See @ref iface_zdwl_ipc_output_v2. + */ +/** + * @defgroup iface_zdwl_ipc_output_v2 The zdwl_ipc_output_v2 interface + * + * 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. + */ +extern const struct wl_interface zdwl_ipc_output_v2_interface; +#endif + +/** + * @ingroup iface_zdwl_ipc_manager_v2 + * @struct zdwl_ipc_manager_v2_interface + */ +struct zdwl_ipc_manager_v2_interface { + /** + * release dwl_ipc_manager + * + * Indicates that the client will not the dwl_ipc_manager object + * anymore. Objects created through this instance are not affected. + */ + void (*release)(struct wl_client *client, + struct wl_resource *resource); + /** + * get a dwl_ipc_outout for a wl_output + * + * Get a dwl_ipc_outout for the specified wl_output. + */ + void (*get_output)(struct wl_client *client, + struct wl_resource *resource, + uint32_t id, + struct wl_resource *output); +}; + +#define ZDWL_IPC_MANAGER_V2_TAGS 0 +#define ZDWL_IPC_MANAGER_V2_LAYOUT 1 + +/** + * @ingroup iface_zdwl_ipc_manager_v2 + */ +#define ZDWL_IPC_MANAGER_V2_TAGS_SINCE_VERSION 1 +/** + * @ingroup iface_zdwl_ipc_manager_v2 + */ +#define ZDWL_IPC_MANAGER_V2_LAYOUT_SINCE_VERSION 1 + +/** + * @ingroup iface_zdwl_ipc_manager_v2 + */ +#define ZDWL_IPC_MANAGER_V2_RELEASE_SINCE_VERSION 1 +/** + * @ingroup iface_zdwl_ipc_manager_v2 + */ +#define ZDWL_IPC_MANAGER_V2_GET_OUTPUT_SINCE_VERSION 1 + +/** + * @ingroup iface_zdwl_ipc_manager_v2 + * Sends an tags event to the client owning the resource. + * @param resource_ The client's resource + */ +static inline void +zdwl_ipc_manager_v2_send_tags(struct wl_resource *resource_, uint32_t amount) +{ + wl_resource_post_event(resource_, ZDWL_IPC_MANAGER_V2_TAGS, amount); +} + +/** + * @ingroup iface_zdwl_ipc_manager_v2 + * Sends an layout event to the client owning the resource. + * @param resource_ The client's resource + */ +static inline void +zdwl_ipc_manager_v2_send_layout(struct wl_resource *resource_, const char *name) +{ + wl_resource_post_event(resource_, ZDWL_IPC_MANAGER_V2_LAYOUT, name); +} + +#ifndef ZDWL_IPC_OUTPUT_V2_TAG_STATE_ENUM +#define ZDWL_IPC_OUTPUT_V2_TAG_STATE_ENUM +enum zdwl_ipc_output_v2_tag_state { + /** + * no state + */ + ZDWL_IPC_OUTPUT_V2_TAG_STATE_NONE = 0, + /** + * tag is active + */ + ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE = 1, + /** + * tag has at least one urgent client + */ + ZDWL_IPC_OUTPUT_V2_TAG_STATE_URGENT = 2, +}; +#endif /* ZDWL_IPC_OUTPUT_V2_TAG_STATE_ENUM */ + +/** + * @ingroup iface_zdwl_ipc_output_v2 + * @struct zdwl_ipc_output_v2_interface + */ +struct zdwl_ipc_output_v2_interface { + /** + * release dwl_ipc_outout + * + * Indicates to that the client no longer needs this + * dwl_ipc_output. + */ + void (*release)(struct wl_client *client, + struct wl_resource *resource); + /** + * Set the active tags of this output + * + * + * @param tagmask bitmask of the tags that should be set. + * @param toggle_tagset toggle the selected tagset, zero for invalid, nonzero for valid. + */ + void (*set_tags)(struct wl_client *client, + struct wl_resource *resource, + uint32_t tagmask, + uint32_t toggle_tagset); + /** + * Set the tags of the focused client. + * + * The tags are updated as follows: new_tags = (current_tags AND + * and_tags) XOR xor_tags + */ + void (*set_client_tags)(struct wl_client *client, + struct wl_resource *resource, + uint32_t and_tags, + uint32_t xor_tags); + /** + * Set the layout of this output + * + * + * @param index index of a layout recieved by dwl_ipc_manager.layout + */ + void (*set_layout)(struct wl_client *client, + struct wl_resource *resource, + uint32_t index); +}; + +#define ZDWL_IPC_OUTPUT_V2_TOGGLE_VISIBILITY 0 +#define ZDWL_IPC_OUTPUT_V2_ACTIVE 1 +#define ZDWL_IPC_OUTPUT_V2_TAG 2 +#define ZDWL_IPC_OUTPUT_V2_LAYOUT 3 +#define ZDWL_IPC_OUTPUT_V2_TITLE 4 +#define ZDWL_IPC_OUTPUT_V2_APPID 5 +#define ZDWL_IPC_OUTPUT_V2_LAYOUT_SYMBOL 6 +#define ZDWL_IPC_OUTPUT_V2_FRAME 7 + +/** + * @ingroup iface_zdwl_ipc_output_v2 + */ +#define ZDWL_IPC_OUTPUT_V2_TOGGLE_VISIBILITY_SINCE_VERSION 1 +/** + * @ingroup iface_zdwl_ipc_output_v2 + */ +#define ZDWL_IPC_OUTPUT_V2_ACTIVE_SINCE_VERSION 1 +/** + * @ingroup iface_zdwl_ipc_output_v2 + */ +#define ZDWL_IPC_OUTPUT_V2_TAG_SINCE_VERSION 1 +/** + * @ingroup iface_zdwl_ipc_output_v2 + */ +#define ZDWL_IPC_OUTPUT_V2_LAYOUT_SINCE_VERSION 1 +/** + * @ingroup iface_zdwl_ipc_output_v2 + */ +#define ZDWL_IPC_OUTPUT_V2_TITLE_SINCE_VERSION 1 +/** + * @ingroup iface_zdwl_ipc_output_v2 + */ +#define ZDWL_IPC_OUTPUT_V2_APPID_SINCE_VERSION 1 +/** + * @ingroup iface_zdwl_ipc_output_v2 + */ +#define ZDWL_IPC_OUTPUT_V2_LAYOUT_SYMBOL_SINCE_VERSION 1 +/** + * @ingroup iface_zdwl_ipc_output_v2 + */ +#define ZDWL_IPC_OUTPUT_V2_FRAME_SINCE_VERSION 1 + +/** + * @ingroup iface_zdwl_ipc_output_v2 + */ +#define ZDWL_IPC_OUTPUT_V2_RELEASE_SINCE_VERSION 1 +/** + * @ingroup iface_zdwl_ipc_output_v2 + */ +#define ZDWL_IPC_OUTPUT_V2_SET_TAGS_SINCE_VERSION 1 +/** + * @ingroup iface_zdwl_ipc_output_v2 + */ +#define ZDWL_IPC_OUTPUT_V2_SET_CLIENT_TAGS_SINCE_VERSION 1 +/** + * @ingroup iface_zdwl_ipc_output_v2 + */ +#define ZDWL_IPC_OUTPUT_V2_SET_LAYOUT_SINCE_VERSION 1 + +/** + * @ingroup iface_zdwl_ipc_output_v2 + * Sends an toggle_visibility event to the client owning the resource. + * @param resource_ The client's resource + */ +static inline void +zdwl_ipc_output_v2_send_toggle_visibility(struct wl_resource *resource_) +{ + wl_resource_post_event(resource_, ZDWL_IPC_OUTPUT_V2_TOGGLE_VISIBILITY); +} + +/** + * @ingroup iface_zdwl_ipc_output_v2 + * Sends an active event to the client owning the resource. + * @param resource_ The client's resource + */ +static inline void +zdwl_ipc_output_v2_send_active(struct wl_resource *resource_, uint32_t active) +{ + wl_resource_post_event(resource_, ZDWL_IPC_OUTPUT_V2_ACTIVE, active); +} + +/** + * @ingroup iface_zdwl_ipc_output_v2 + * Sends an tag event to the client owning the resource. + * @param resource_ The client's resource + * @param tag Index of the tag + * @param state The state of the tag. + * @param clients The number of clients in the tag. + * @param focused If there is a focused client. Nonzero being valid, zero being invalid. + */ +static inline void +zdwl_ipc_output_v2_send_tag(struct wl_resource *resource_, uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused) +{ + wl_resource_post_event(resource_, ZDWL_IPC_OUTPUT_V2_TAG, tag, state, clients, focused); +} + +/** + * @ingroup iface_zdwl_ipc_output_v2 + * Sends an layout event to the client owning the resource. + * @param resource_ The client's resource + * @param layout Index of the layout. + */ +static inline void +zdwl_ipc_output_v2_send_layout(struct wl_resource *resource_, uint32_t layout) +{ + wl_resource_post_event(resource_, ZDWL_IPC_OUTPUT_V2_LAYOUT, layout); +} + +/** + * @ingroup iface_zdwl_ipc_output_v2 + * Sends an title event to the client owning the resource. + * @param resource_ The client's resource + * @param title The new title name. + */ +static inline void +zdwl_ipc_output_v2_send_title(struct wl_resource *resource_, const char *title) +{ + wl_resource_post_event(resource_, ZDWL_IPC_OUTPUT_V2_TITLE, title); +} + +/** + * @ingroup iface_zdwl_ipc_output_v2 + * Sends an appid event to the client owning the resource. + * @param resource_ The client's resource + * @param appid The new appid. + */ +static inline void +zdwl_ipc_output_v2_send_appid(struct wl_resource *resource_, const char *appid) +{ + wl_resource_post_event(resource_, ZDWL_IPC_OUTPUT_V2_APPID, appid); +} + +/** + * @ingroup iface_zdwl_ipc_output_v2 + * Sends an layout_symbol event to the client owning the resource. + * @param resource_ The client's resource + * @param layout The new layout + */ +static inline void +zdwl_ipc_output_v2_send_layout_symbol(struct wl_resource *resource_, const char *layout) +{ + wl_resource_post_event(resource_, ZDWL_IPC_OUTPUT_V2_LAYOUT_SYMBOL, layout); +} + +/** + * @ingroup iface_zdwl_ipc_output_v2 + * Sends an frame event to the client owning the resource. + * @param resource_ The client's resource + */ +static inline void +zdwl_ipc_output_v2_send_frame(struct wl_resource *resource_) +{ + wl_resource_post_event(resource_, ZDWL_IPC_OUTPUT_V2_FRAME); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dwl.c b/dwl.c index 7f940c4..50aba3c 100644 --- a/dwl.c +++ b/dwl.c @@ -58,6 +58,7 @@ #include #endif +#include "dwl-ipc-unstable-v2-protocol.h" #include "util.h" /* macros */ @@ -128,6 +129,12 @@ typedef struct { uint32_t resize; /* configure serial of a pending resize */ } Client; +typedef struct { + struct wl_list link; + struct wl_resource *resource; + Monitor *monitor; +} DwlIpcOutput; + typedef struct { uint32_t mod; xkb_keysym_t keysym; @@ -169,6 +176,7 @@ typedef struct { struct Monitor { struct wl_list link; + struct wl_list dwl_ipc_outputs; struct wlr_output *wlr_output; struct wlr_scene_output *scene_output; struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */ @@ -248,6 +256,17 @@ static void destroynotify(struct wl_listener *listener, void *data); static void destroysessionlock(struct wl_listener *listener, void *data); static void destroysessionmgr(struct wl_listener *listener, void *data); static Monitor *dirtomon(enum wlr_direction dir); +static void dwl_ipc_manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id); +static void dwl_ipc_manager_destroy(struct wl_resource *resource); +static void dwl_ipc_manager_get_output(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *output); +static void dwl_ipc_manager_release(struct wl_client *client, struct wl_resource *resource); +static void dwl_ipc_output_destroy(struct wl_resource *resource); +static void dwl_ipc_output_printstatus(Monitor *monitor); +static void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output); +static void dwl_ipc_output_set_client_tags(struct wl_client *client, struct wl_resource *resource, uint32_t and_tags, uint32_t xor_tags); +static void dwl_ipc_output_set_layout(struct wl_client *client, struct wl_resource *resource, uint32_t index); +static void dwl_ipc_output_set_tags(struct wl_client *client, struct wl_resource *resource, uint32_t tagmask, uint32_t toggle_tagset); +static void dwl_ipc_output_release(struct wl_client *client, struct wl_resource *resource); static void focusclient(Client *c, int lift); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); @@ -363,6 +382,8 @@ static struct wl_listener cursor_frame = {.notify = cursorframe}; static struct wl_listener cursor_motion = {.notify = motionrelative}; static struct wl_listener cursor_motion_absolute = {.notify = motionabsolute}; static struct wl_listener drag_icon_destroy = {.notify = destroydragicon}; +static struct zdwl_ipc_manager_v2_interface dwl_manager_implementation = {.release = dwl_ipc_manager_release, .get_output = dwl_ipc_manager_get_output}; +static struct zdwl_ipc_output_v2_interface dwl_output_implementation = {.release = dwl_ipc_output_release, .set_tags = dwl_ipc_output_set_tags, .set_layout = dwl_ipc_output_set_layout, .set_client_tags = dwl_ipc_output_set_client_tags}; static struct wl_listener idle_inhibitor_create = {.notify = createidleinhibitor}; static struct wl_listener idle_inhibitor_destroy = {.notify = destroyidleinhibitor}; static struct wl_listener layout_change = {.notify = updatemons}; @@ -680,6 +701,9 @@ cleanupmon(struct wl_listener *listener, void *data) LayerSurface *l, *tmp; int i; + DwlIpcOutput *ipc_output; + wl_list_for_each(ipc_output, &m->dwl_ipc_outputs, link) + wl_resource_destroy(ipc_output->resource); for (i = 0; i <= ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY; i++) wl_list_for_each_safe(l, tmp, &m->layers[i], link) wlr_layer_surface_v1_destroy(l->layer_surface); @@ -894,6 +918,7 @@ createmon(struct wl_listener *listener, void *data) Monitor *m = wlr_output->data = ecalloc(1, sizeof(*m)); m->wlr_output = wlr_output; + wl_list_init(&m->dwl_ipc_outputs); wlr_output_init_render(wlr_output, alloc, drw); /* Initialize monitor state using configured rules */ @@ -1028,7 +1053,7 @@ createpointer(struct wlr_pointer *pointer) if (libinput_device_config_scroll_get_methods(libinput_device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL) libinput_device_config_scroll_set_method (libinput_device, scroll_method); - + if (libinput_device_config_click_get_methods(libinput_device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE) libinput_device_config_click_set_method (libinput_device, click_method); @@ -1180,6 +1205,162 @@ dirtomon(enum wlr_direction dir) return selmon; } +void dwl_ipc_manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) { + struct wl_resource *manager_resource = wl_resource_create(client, &zdwl_ipc_manager_v2_interface, version, id); + if (!manager_resource) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(manager_resource, &dwl_manager_implementation, NULL, dwl_ipc_manager_destroy); + + zdwl_ipc_manager_v2_send_tags(manager_resource, LENGTH(tags)); + + for (int i = 0; i < LENGTH(layouts); i++) + zdwl_ipc_manager_v2_send_layout(manager_resource, layouts[i].symbol); +} + +void dwl_ipc_manager_destroy(struct wl_resource *resource) { + /* No state to destroy */ +} + +void dwl_ipc_manager_get_output(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *output) { + DwlIpcOutput *ipc_output; + Monitor *monitor = wlr_output_from_resource(output)->data; + struct wl_resource *output_resource = wl_resource_create(client, &zdwl_ipc_output_v2_interface, wl_resource_get_version(resource), id); + if (!output_resource) + return; + + ipc_output = ecalloc(1, sizeof(*ipc_output)); + ipc_output->resource = output_resource; + ipc_output->monitor = monitor; + wl_resource_set_implementation(output_resource, &dwl_output_implementation, ipc_output, dwl_ipc_output_destroy); + wl_list_insert(&monitor->dwl_ipc_outputs, &ipc_output->link); + dwl_ipc_output_printstatus_to(ipc_output); +} + +void dwl_ipc_manager_release(struct wl_client *client, struct wl_resource *resource) { + wl_resource_destroy(resource); +} + +static void dwl_ipc_output_destroy(struct wl_resource *resource) { + DwlIpcOutput *ipc_output = wl_resource_get_user_data(resource); + wl_list_remove(&ipc_output->link); + free(ipc_output); +} + +void dwl_ipc_output_printstatus(Monitor *monitor) { + DwlIpcOutput *ipc_output; + wl_list_for_each(ipc_output, &monitor->dwl_ipc_outputs, link) + dwl_ipc_output_printstatus_to(ipc_output); +} + +void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output) { + Monitor *monitor = ipc_output->monitor; + Client *c, *focused; + int tagmask, state, numclients, focused_client, tag; + const char *title, *appid; + focused = focustop(monitor); + zdwl_ipc_output_v2_send_active(ipc_output->resource, monitor == selmon); + + for ( tag = 0 ; tag < LENGTH(tags); tag++) { + numclients = state = focused_client = 0; + tagmask = 1 << tag; + if ((tagmask & monitor->tagset[monitor->seltags]) != 0) + state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE; + + wl_list_for_each(c, &clients, link) { + if (c->mon != monitor) + continue; + if (!(c->tags & tagmask)) + continue; + if (c == focused) + focused_client = 1; + if (c->isurgent) + state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_URGENT; + + numclients++; + } + zdwl_ipc_output_v2_send_tag(ipc_output->resource, tag, state, numclients, focused_client); + } + title = focused ? client_get_title(focused) : ""; + appid = focused ? client_get_appid(focused) : ""; + + zdwl_ipc_output_v2_send_layout(ipc_output->resource, monitor->lt[monitor->sellt] - layouts); + zdwl_ipc_output_v2_send_title(ipc_output->resource, title ? title : broken); + zdwl_ipc_output_v2_send_appid(ipc_output->resource, appid ? appid : broken); + zdwl_ipc_output_v2_send_layout_symbol(ipc_output->resource, monitor->lt[monitor->sellt]->symbol); + zdwl_ipc_output_v2_send_frame(ipc_output->resource); +} + +void dwl_ipc_output_set_client_tags(struct wl_client *client, struct wl_resource *resource, uint32_t and_tags, uint32_t xor_tags) { + DwlIpcOutput *ipc_output; + Monitor *monitor; + Client *selected_client; + unsigned int newtags = 0; + + ipc_output = wl_resource_get_user_data(resource); + if (!ipc_output) + return; + + monitor = ipc_output->monitor; + selected_client = focustop(monitor); + if (!selected_client) + return; + + newtags = (selected_client->tags & and_tags) ^ xor_tags; + if (!newtags) + return; + + selected_client->tags = newtags; + focusclient(focustop(selmon), 1); + arrange(selmon); + printstatus(); +} + +void dwl_ipc_output_set_layout(struct wl_client *client, struct wl_resource *resource, uint32_t index) { + DwlIpcOutput *ipc_output; + Monitor *monitor; + + ipc_output = wl_resource_get_user_data(resource); + if (!ipc_output) + return; + + monitor = ipc_output->monitor; + if (index >= LENGTH(layouts)) + return; + if (index != monitor->lt[monitor->sellt] - layouts) + monitor->sellt ^= 1; + + monitor->lt[monitor->sellt] = &layouts[index]; + arrange(monitor); + printstatus(); +} + +void dwl_ipc_output_set_tags(struct wl_client *client, struct wl_resource *resource, uint32_t tagmask, uint32_t toggle_tagset) { + DwlIpcOutput *ipc_output; + Monitor *monitor; + unsigned int newtags = tagmask & TAGMASK; + + ipc_output = wl_resource_get_user_data(resource); + if (!ipc_output) + return; + monitor = ipc_output->monitor; + + if (!newtags || newtags == monitor->tagset[monitor->seltags]) + return; + if (toggle_tagset) + monitor->seltags ^= 1; + + monitor->tagset[monitor->seltags] = newtags; + focusclient(focustop(monitor), 1); + arrange(monitor); + printstatus(); +} + +void dwl_ipc_output_release(struct wl_client *client, struct wl_resource *resource) { + wl_resource_destroy(resource); +} + void focusclient(Client *c, int lift) { @@ -1810,6 +1991,7 @@ printstatus(void) printf("%s tags %u %u %u %u\n", m->wlr_output->name, occ, m->tagset[m->seltags], sel, urg); printf("%s layout %s\n", m->wlr_output->name, m->lt[m->sellt]->symbol); + dwl_ipc_output_printstatus(m); } fflush(stdout); } @@ -2237,6 +2419,7 @@ setup(void) wl_signal_add(&output_mgr->events.test, &output_mgr_test); wlr_scene_set_presentation(scene, wlr_presentation_create(dpy, backend)); + wl_global_create(dpy, &zdwl_ipc_manager_v2_interface, 1, NULL, dwl_ipc_manager_bind); #ifdef XWAYLAND /* diff --git a/meson.build b/meson.build index 738dea9..0e9c0fe 100644 --- a/meson.build +++ b/meson.build @@ -23,9 +23,11 @@ if xcb.found() and xlibs.found() c_args += '-DXWAYLAND' endif -executable('dwl', +executable('dwl', 'dwl.c', 'util.c', + 'dwl-ipc-unstable-v2-protocol.c', + 'dwl-ipc-unstable-v2-protocol.h', wayland_sources, dependencies : [ libm, diff --git a/protocols/dwl-ipc-unstable-v2.xml b/protocols/dwl-ipc-unstable-v2.xml new file mode 100644 index 0000000..74a212f --- /dev/null +++ b/protocols/dwl-ipc-unstable-v2.xml @@ -0,0 +1,166 @@ + + + + + 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 + + + + + + + + + + +