23 Commits

Author SHA1 Message Date
4155500f47 updated readme 2025-12-23 06:31:15 +01:00
24cf868dff updated readme 2025-12-23 06:29:14 +01:00
2faad84c08 added compose key as rctrl 2025-12-23 06:03:37 +01:00
b5ac3f0ef6 updated config 2025-11-12 04:47:05 +01:00
829ce5f142 updated config 2025-09-02 06:48:54 +02:00
ffd7ccf9d4 updated config 2025-06-28 04:30:19 +02:00
c387264009 changed config 2025-05-12 05:07:24 +02:00
fb055648f3 updated config 2025-04-28 06:04:57 +02:00
cc70169bb0 change config 2025-04-15 17:46:47 +02:00
d1df3a67ab changed config 2025-04-15 17:25:05 +02:00
d2c8482e83 changed config 2025-04-12 01:32:40 +02:00
39351e4e48 changed config 2025-04-11 04:32:10 +02:00
3c6a2ce936 updated config 2025-04-10 02:45:32 +02:00
96d128e180 updated config 2025-04-08 02:54:17 +02:00
b9dd17fa78 fixed config 2025-04-07 04:29:04 +02:00
ba88ae522a fixed config 2025-04-07 04:05:25 +02:00
ff888db172 changed config 2025-04-06 01:35:12 +02:00
84e2e34a0f updated config 2025-04-06 00:32:40 +02:00
6143acb000 updated monocle layout string 2025-04-05 16:18:46 +02:00
8fb4b35259 updated config 2025-04-05 16:17:45 +02:00
a09bf92943 updated config 2025-03-31 02:18:25 +02:00
2b70425a99 fixed config 2025-03-30 07:49:55 +02:00
f493de341e added config branch 2025-03-30 07:34:19 +02:00
7 changed files with 225 additions and 1255 deletions

View File

@@ -17,14 +17,12 @@ DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) $(DWLCPPFLAGS) $(DWLDEV
LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS) LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS)
all: dwl all: dwl
dwl: dwl.o util.o dwl-ipc-unstable-v2-protocol.o dwl: dwl.o util.o
$(CC) dwl.o util.o dwl-ipc-unstable-v2-protocol.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ $(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@
dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \
pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \
wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h \ wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h
dwl-ipc-unstable-v2-protocol.h
util.o: util.c util.h util.o: util.c util.h
dwl-ipc-unstable-v2-protocol.o: dwl-ipc-unstable-v2-protocol.c dwl-ipc-unstable-v2-protocol.h
# wayland-scanner is a tool which generates C headers and rigging for Wayland # wayland-scanner is a tool which generates C headers and rigging for Wayland
# protocols, which are specified in XML. wlroots requires you to rig these up # protocols, which are specified in XML. wlroots requires you to rig these up
@@ -47,12 +45,6 @@ wlr-output-power-management-unstable-v1-protocol.h:
xdg-shell-protocol.h: xdg-shell-protocol.h:
$(WAYLAND_SCANNER) server-header \ $(WAYLAND_SCANNER) server-header \
$(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@
dwl-ipc-unstable-v2-protocol.h:
$(WAYLAND_SCANNER) server-header \
protocols/dwl-ipc-unstable-v2.xml $@
dwl-ipc-unstable-v2-protocol.c:
$(WAYLAND_SCANNER) private-code \
protocols/dwl-ipc-unstable-v2.xml $@
config.h: config.h:
cp config.def.h $@ cp config.def.h $@

250
README.md
View File

@@ -1,199 +1,77 @@
# dwl - dwm for Wayland # dwl
Join us on our IRC channel: [#dwl on Libera Chat] This is my patched version of dwl.
Or on the community-maintained [Discord server]. This belongs to my larbs installation script and depends heavily on its scripts
and programs.
It is supposed to work in the environment after the
[larbs base installation](https://github.com/tiyn/larbs).
This repository is set up according to the
[suckless entry of my wiki](https://github.com/tiyn/wiki/blob/master/wiki/linux/suckless.md).
dwl is a compact, hackable compositor for [Wayland] based on [wlroots]. It is ## Patches
intended to fill the same space in the Wayland world that dwm does in X11,
primarily in terms of functionality, and secondarily in terms of
philosophy. Like dwm, dwl is:
- Easy to understand, hack on, and extend with patches The list below shows the currently applied patches to the master branch.
- One C source file (or a very small number) configurable via `config.h`
- Tied to as few external dependencies as possible
## Getting Started: - attachtop.patch (new clients are attached at the top of the stack)
- bottomstack.patch (adds bottomstack and bottomstackhorizontal layouts)
- deck.patch (adds deck layout with one master and stacked clients)
- en-keycodes.patch (always uses the english keycodes)
- fakefullscreenclient.patch (enables per-client fake fullscreen)
- foreign-toplevel-management.patch (allows external programs to query/control windows)
- hide-behind-monocle.patch (hides unfocused windows in monocle layout)
- hide-behind-fullscreen.patch (hides other windows behind fullscreen clients)
- inputdevicerules-v0.7.patch (adds per-input-device configuration rules)
- ipc.patch (adds IPC for external control and scripting)
- pertag.patch (stores layout, mfact, nmaster, bar state per tag)
- swallow.patch (replaces terminal with spawned application)
- togglekblayoutandoptions.patch (toggles keyboard layouts and XKB options at runtime)
- unclutter.patch (hides cursor after inactivity)
- warpcursor.patch (moves cursor to the focused window)
- xwayland-handle-minimize.patch (improves minimize/restore handling for XWayland)
### Latest semi-stable [release] ## Hotkeys
This is probably where you want to start. This builds against the dependent
packages' versions currently shipping in major distributions. If your
distribution's wlroots version is older, use an earlier dwl [release] or [0.x
branch].
### Development branch [main] There are various shortcuts and hotkeys used in this version. Included in my
Active development progresses on the `main` branch. The `main` branch is built build are the following.
against a late (and often changing) git commit of wlroots. While the adventurous
are welcome to use `main`, it is a rocky road. Using `main` requires that the
user be willing to chase git commits of wlroots. Testing development pull
requests may involve merging unmerged pull requests in [wlroots]' git repository
and/or git commits of wayland.
### Building dwl | ModKey | Shift | Key | Function |
dwl has the following dependencies: | ------ | ----- | ----------- | ------------------------------------------------------- |
- libinput | Super | | h | (Tiling/Deck) Focus window higher in stack than current |
- wayland | Super | | j | (Tiling/Deck) Focus window lower in stack than current |
- wlroots (compiled with the libinput backend) | Super | | k | (Tiling/Deck) Focus window higher in stack than current |
- xkbcommon | Super | | l | (Tiling/Deck) Focus window lower in stack than current |
- wayland-protocols (compile-time only) | Super | | 1/2/.../9/0 | Show tag 1/2/.../9/0 |
- pkg-config (compile-time only) | Super | | . | Show monitor lower in stack |
| Super | | , | Show monitor higher in stack |
| Super | Shift | Escape | Quit dwl with call for confirmation |
| Super | Shift | c | Enable deck(/card) layout |
| Super | Shift | d | Toggle floating/tiled for selected window |
| Super | Shift | f | Toggle fullscreen |
| Super | Shift | h | (Tiling/Deck) Make current window the master window |
| Super | Shift | j | (Tiling/Deck) Make current window the master window |
| Super | Shift | k | (Tiling/Deck) Make current window the master window |
| Super | Shift | l | (Keyboard) Cycle through the keymap layouts |
| Super | Shift | m | Enable monocle layout |
| Super | Shift | o | (Tiling/Deck) Increase master window size |
| Super | Shift | q | Close current window |
| Super | Shift | t | Enable tiling layout |
| Super | Shift | u | Enable bottomstack layout |
| Super | Shift | v | Enable bottomstackhorizontal layout |
| Super | Shift | z | (Tiling/Deck) Decrease master window size |
| Super | Shift | 1/2/.../9/0 | Add current window to tag 1/2/.../9/0 |
| Super | Shift | . | Add to monitor lower in stack |
| Super | Shift | , | Add to monitor higher in stack |
| Alt | | Tab | (Tiling/Deck) Focus window lower in stack than current |
dwl has the following additional dependencies if XWayland support is enabled: Additionally the right hand side control key is set to be used as the compose key.
- libxcb
- libxcb-wm
- wlroots (compiled with X11 support)
- Xwayland (runtime only)
Install these (and their `-devel` versions if your distro has separate ## Installation
development packages) and run `make`. If you wish to build against a released
version of wlroots (*you probably do*), use a [release] or a [0.x branch]. If
you want to use the unstable development `main` branch, you need to use the git
version of [wlroots].
To enable XWayland, you should uncomment its flags in `config.mk`. The following programs are required to be installed for full functionality.
## Configuration - [dmenu](https://github.com/tiyn/dmenu)
All configuration is done by editing `config.h` and recompiling, in the same The most basic way is to clone the repository and then invoke make.
manner as dwm. There is no way to separately restart the window manager in
Wayland without restarting the entire display server, so any changes will take
effect the next time dwl is executed.
As in the dwm community, we encourage users to share patches they have - `git clone https://github.com/tiyn/dwl`
created. Check out the [dwl-patches] repository! - `make clean install`
## Running dwl
dwl can be run on any of the backends supported by wlroots. This means you can
run it as a separate window inside either an X11 or Wayland session, as well as
directly from a VT console. Depending on your distro's setup, you may need to
add your user to the `video` and `input` groups before you can run dwl on a
VT. If you are using `elogind` or `systemd-logind` you need to install polkit;
otherwise you need to add yourself in the `seat` group and enable/start the
seatd daemon.
When dwl is run with no arguments, it will launch the server and begin handling
any shortcuts configured in `config.h`. There is no status bar or other
decoration initially; these are instead clients that can be run within the
Wayland session. Do note that the default background color is black. This can be
modified in `config.h`.
If you would like to run a script or command automatically at startup, you can
specify the command using the `-s` option. This command will be executed as a
shell command using `/bin/sh -c`. It serves a similar function to `.xinitrc`,
but differs in that the display server will not shut down when this process
terminates. Instead, dwl will send this process a SIGTERM at shutdown and wait
for it to terminate (if it hasn't already). This makes it ideal for execing into
a user service manager like [s6], [anopa], [runit], [dinit], or [`systemd
--user`].
Note: The `-s` command is run as a *child process* of dwl, which means that it
does not have the ability to affect the environment of dwl or of any processes
that it spawns. If you need to set environment variables that affect the entire
dwl session, these must be set prior to running dwl. For example, Wayland
requires a valid `XDG_RUNTIME_DIR`, which is usually set up by a session manager
such as `elogind` or `systemd-logind`. If your system doesn't do this
automatically, you will need to configure it prior to launching `dwl`, e.g.:
export XDG_RUNTIME_DIR=/tmp/xdg-runtime-$(id -u)
mkdir -p $XDG_RUNTIME_DIR
dwl
### Status information
Information about selected layouts, current window title, app-id, and
selected/occupied/urgent tags is written to the stdin of the `-s` command (see
the `printstatus()` function for details). This information can be used to
populate an external status bar with a script that parses the
information. Failing to read this information will cause dwl to block, so if you
do want to run a startup command that does not consume the status information,
you can close standard input with the `<&-` shell redirection, for example:
dwl -s 'foot --server <&-'
If your startup command is a shell script, you can achieve the same inside the
script with the line
exec <&-
To get a list of status bars that work with dwl consult our [wiki].
## Replacements for X applications
You can find a [list of useful resources on our wiki].
## Background
dwl is not meant to provide every feature under the sun. Instead, like dwm, it
sticks to features which are necessary, simple, and straightforward to implement
given the base on which it is built. Implemented default features are:
- Any features provided by dwm/Xlib: simple window borders, tags, keybindings,
client rules, mouse move/resize. Providing a built-in status bar is an
exception to this goal, to avoid dependencies on font rendering and/or drawing
libraries when an external bar could work well.
- Configurable multi-monitor layout support, including position and rotation
- Configurable HiDPI/multi-DPI support
- Idle-inhibit protocol which lets applications such as mpv disable idle
monitoring
- Provide information to external status bars via stdout/stdin
- Urgency hints via xdg-activate protocol
- Support screen lockers via ext-session-lock-v1 protocol
- Various Wayland protocols
- XWayland support as provided by wlroots (can be enabled in `config.mk`)
- Zero flickering - Wayland users naturally expect that "every frame is perfect"
- Layer shell popups (used by Waybar)
- Damage tracking provided by scenegraph API
Given the Wayland architecture, dwl has to implement features from dwm **and**
the xorg-server. Because of this, it is impossible to maintain the original
project goal of 2000 SLOC and have a reasonably complete compositor with
features comparable to dwm. However, this does not mean that the code will grow
indiscriminately. We will try to keep the code as small as possible.
Features under consideration (possibly as patches) are:
- Protocols made trivial by wlroots
- Implement the text-input and input-method protocols to support IME once ibus
implements input-method v2 (see https://github.com/ibus/ibus/pull/2256 and
https://codeberg.org/dwl/dwl/pulls/235)
Feature *non-goals* for the main codebase include:
- Client-side decoration (any more than is necessary to tell the clients not to)
- Client-initiated window management, such as move, resize, and close, which can
be done through the compositor
- Animations and visual effects
## Acknowledgements
dwl began by extending the TinyWL example provided (CC0) by the sway/wlroots
developers. This was made possible in many cases by looking at how sway
accomplished something, then trying to do the same in as suckless a way as
possible.
Many thanks to suckless.org and the dwm developers and community for the
inspiration, and to the various contributors to the project, including:
- **Devin J. Pohly for creating and nurturing the fledgling project**
- Alexander Courtis for the XWayland implementation
- Guido Cella for the layer-shell protocol implementation, patch maintenance,
and for helping to keep the project running
- Stivvo for output management and fullscreen support, and patch maintenance
[`systemd --user`]: https://wiki.archlinux.org/title/Systemd/User
[#dwl on Libera Chat]: https://web.libera.chat/?channels=#dwl
[0.7-rc1]: https://codeberg.org/dwl/dwl/releases/tag/v0.7-rc1
[0.x branch]: https://codeberg.org/dwl/dwl/branches
[anopa]: https://jjacky.com/anopa/
[dinit]: https://davmac.org/projects/dinit/
[dwl-patches]: https://codeberg.org/dwl/dwl-patches
[list of useful resources on our wiki]: https://codeberg.org/dwl/dwl/wiki/Home#migrating-from-x
[main]: https://codeberg.org/dwl/dwl/src/branch/main
[release]: https://codeberg.org/dwl/dwl/releases
[runit]: http://smarden.org/runit/faq.html#userservices
[s6]: https://skarnet.org/software/s6/
[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots/
[wiki]: https://codeberg.org/dwl/dwl/wiki/Home#compatible-status-bars
[Discord server]: https://discord.gg/jJxZnrGPWN
[Wayland]: https://wayland.freedesktop.org/

View File

@@ -6,6 +6,7 @@
/* appearance */ /* appearance */
static const int sloppyfocus = 1; /* focus follows mouse */ static const int sloppyfocus = 1; /* focus follows mouse */
static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */
static const int smartborders = 1;
static const unsigned int borderpx = 1; /* border pixel of windows */ static const unsigned int borderpx = 1; /* border pixel of windows */
static const float rootcolor[] = COLOR(0x222222ff); static const float rootcolor[] = COLOR(0x222222ff);
static const float bordercolor[] = COLOR(0x444444ff); static const float bordercolor[] = COLOR(0x444444ff);
@@ -13,27 +14,54 @@ static const float focuscolor[] = COLOR(0x005577ff);
static const float urgentcolor[] = COLOR(0xff0000ff); static const float urgentcolor[] = COLOR(0xff0000ff);
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
static int enableautoswallow = 0; /* enables autoswallowing newly spawned clients */
static float swallowborder = 1.0f; /* add this multiplied by borderpx to border when a client is swallowed */
/* tagging - TAGCOUNT must be no greater than 31 */ /* tagging - TAGCOUNT must be no greater than 31 */
#define TAGCOUNT (9) #define TAGCOUNT (10)
/* logging */ /* logging */
static int log_level = WLR_ERROR; static int log_level = WLR_ERROR;
/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */
static const Rule rules[] = { static const Rule rules[] = {
/* app_id title tags mask isfloating monitor */ /* app_id title tags mask isfloating isterm noswallow monitor */
/* examples: */ /* examples: */
{ "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ { "firefox", NULL, 1 << 1, 0, 0, 0, -1 },
{ "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ { "zen", NULL, 1 << 1, 0, 0, 0, -1 },
{ "Lutris", NULL, 1 << 2, 0, 0, 0, 0 },
{ "zenity", NULL, 0, 1, 0, 0, -1 },
{ "steam", NULL, 1 << 2, 0, 0, 0, 0 },
{ "discord", NULL, 1 << 2, 0, 0, 0, 1 },
{ "vesktop", NULL, 1 << 2, 0, 0, 0, 1 },
{ "TeamSpeak", NULL, 1 << 2, 0, 0, 0, 1 },
{ "Mattermost", NULL, 1 << 2, 0, 0, 0, 1 },
{ "Element", NULL, 1 << 2, 0, 0, 0, 1 },
{ "signal", NULL, 1 << 4, 0, 0, 0, 1 },
{ "telegram", NULL, 1 << 4, 0, 0, 0, 1 },
{ "Threema", NULL, 1 << 4, 0, 0, 0, 1 },
{ "Thunderbird", NULL, 1 << 4, 0, 0, 0, 1 },
{ "Sonixd", NULL, 1 << 8, 0, 0, 0, 1 },
{ "KeePassXC", "Unlock Database - KeePassXC", 1 << 1, 1, 0, 0, 0 },
{ "KeePassXC", NULL, 1 << 9, 0, 0, 0, 0 },
{ "com.obsproject.Studio",NULL, 1 << 7, 0, 0, 0, 1 },
{ "easyeffects", NULL, 1 << 9, 0, 0, 0, 1 },
{ "pavucontrol", NULL, 1 << 9, 0, 0, 0, 1 },
{ "nextcloud", NULL, 0, 1, 0, 0, -1 },
{ "st", NULL, 0, 0, 1, 0, -1 },
{ "vifm", NULL, 0, 0, 1, 0, -1 },
{ "vifmrun", NULL, 0, 0, 1, 0, -1 },
}; };
/* layout(s) */ /* layout(s) */
static const Layout layouts[] = { static const Layout layouts[] = {
/* symbol arrange function */ /* symbol arrange function */
{ "[]=", tile }, { "M", monocle },
{ "><>", NULL }, /* no layout function means floating behavior */ { "T", tile },
{ "[M]", monocle }, { "D", deck },
{ "B", bstack },
{ "B", bstackhoriz },
{ "F", NULL }, /* no layout function means floating behavior */
}; };
/* monitors */ /* monitors */
@@ -52,12 +80,33 @@ static const MonitorRule monrules[] = {
}; };
/* keyboard */ /* keyboard */
static const struct xkb_rule_names xkb_rules = { static const struct xkb_rule_names xkb_rules[] = {
/* can specify fields: rules, model, layout, variant, options */ {
/* example: .layout = "de",
.options = "ctrl:nocaps", .options = "compose:rctrl",
*/ },
.options = NULL, {
.layout = "de",
.variant = "nodeadkeys",
.options = "compose:rctrl",
},
{
.layout = "de",
.variant = "ru",
.options = "compose:rctrl",
}
};
/* input devices */
static const InputRule inputrules[] = {
/* name kbcreate ptrcreate */
/* ignore bad device - like a touchpad ;) */
{ "BAD DEVICE", NULL, NULL },
/* ungroup ydotool device - fixes a bug */
{ "ydotoold virtual device", createungroupedkeyboard, createpointer },
/* put your touchpad name here to enable toggle touchpad */
{ "SYNA8020:00 06CB:CE5C Touchpad", createkeyboard, createtogglepointer },
{ NULL, createkeyboard, createpointer },
}; };
static const int repeat_rate = 25; static const int repeat_rate = 25;
@@ -106,8 +155,10 @@ 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; static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM;
static const int cursor_timeout = 5;
/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */ /* 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) \ #define TAGKEYS(KEY,SKEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
@@ -119,45 +170,66 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
/* commands */ /* commands */
static const char *termcmd[] = { "foot", NULL }; static const char *termcmd[] = { "st", NULL };
static const char *menucmd[] = { "wmenu-run", NULL }; static const char *filecmd[] = { "st", "-e", "vifmrun", NULL };
static const char *menucmd[] = { "dmenu_run", "-F", "-i", "-c", "-l", "20", NULL };
static const Key keys[] = { static const Key keys[] = {
/* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */
/* modifier key function argument */ /* modifier key function argument */
{ MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Escape, quit, {0} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_D, togglefloating, {0} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_F, togglefullscreen, {0} },
{ MODKEY|WLR_MODIFIER_SHIFT|WLR_MODIFIER_CTRL, XKB_KEY_F, togglefakefullscreen, {0} },
{ MODKEY, XKB_KEY_h, focusstack, {.i = -1} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_H, zoom, {0} },
{ MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, { MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_J, incnmaster, {.i = -1} },
{ MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, { MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
{ MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, incnmaster, {.i = +1} },
{ MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, { MODKEY, XKB_KEY_l, focusstack, {.i = +1} },
{ MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_M, setlayout, {.v = &layouts[0]} },
{ MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_U, setmfact, {.f = -0.05f} },
{ MODKEY, XKB_KEY_Return, zoom, {0} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_I, setmfact, {.f = -0.05f} },
{ MODKEY, XKB_KEY_Tab, view, {0} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_O, setmfact, {.f = +0.05f} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_P, setmfact, {.f = +0.05f} },
{ MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, killclient, {0} },
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_T, setlayout, {.v = &layouts[1]} },
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, setlayout, {.v = &layouts[2]} },
{ MODKEY, XKB_KEY_space, setlayout, {0} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_V, setlayout, {.v = &layouts[3]} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_S, setlayout, {.v = &layouts[4]} },
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_H, setmfact, {.f = -0.05f} },
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_L, incxkbrules, {.i = +1} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
{ MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_semicolon, tagmon, {.i = WLR_DIRECTION_LEFT} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} }, { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_colon, tagmon, {.i = WLR_DIRECTION_RIGHT} },
{ MODKEY, XKB_KEY_r, spawn, {.v = menucmd} },
{ MODKEY, XKB_KEY_f, spawn, {.v = filecmd} },
{ MODKEY, XKB_KEY_Return, spawn, {.v = termcmd} },
{ MODKEY, XKB_KEY_space, togglepointer, {0} },
{ WLR_MODIFIER_ALT, XKB_KEY_Tab, focusstack, {.i = +1} },
TAGKEYS(XKB_KEY_1, XKB_KEY_exclam, 0), TAGKEYS(XKB_KEY_1, XKB_KEY_exclam, 0),
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1), TAGKEYS(XKB_KEY_2, XKB_KEY_quotedbl, 1),
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2), TAGKEYS(XKB_KEY_3, XKB_KEY_section, 2),
TAGKEYS(XKB_KEY_4, XKB_KEY_dollar, 3), TAGKEYS(XKB_KEY_4, XKB_KEY_dollar, 3),
TAGKEYS(XKB_KEY_5, XKB_KEY_percent, 4), TAGKEYS(XKB_KEY_5, XKB_KEY_percent, 4),
TAGKEYS( XKB_KEY_6, XKB_KEY_asciicircum, 5), TAGKEYS(XKB_KEY_6, XKB_KEY_ampersand, 5),
TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6), TAGKEYS(XKB_KEY_7, XKB_KEY_slash, 6),
TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7), TAGKEYS(XKB_KEY_8, XKB_KEY_parenleft, 7),
TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8), TAGKEYS(XKB_KEY_9, XKB_KEY_parenright, 8),
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} }, TAGKEYS(XKB_KEY_0, XKB_KEY_equal, 9),
// TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0),
// TAGKEYS( XKB_KEY_2, XKB_KEY_quotedbl, 1),
// TAGKEYS( XKB_KEY_3, XKB_KEY_paragraph, 2),
// TAGKEYS( XKB_KEY_4, XKB_KEY_dollar, 3),
// TAGKEYS( XKB_KEY_5, XKB_KEY_percent, 4),
// TAGKEYS( XKB_KEY_6, XKB_KEY_ampersand, 5),
// TAGKEYS( XKB_KEY_7, XKB_KEY_asciicircum, 6),
// TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 7),
// TAGKEYS( XKB_KEY_9, XKB_KEY_parenright, 8),
/* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */ /* 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} }, { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} },

View File

@@ -24,11 +24,11 @@ WLR_LIBS = `$(PKG_CONFIG) --libs wlroots-0.19`
# -I$(PWD)/wlroots/0.19/include/wlroots-0.19 # -I$(PWD)/wlroots/0.19/include/wlroots-0.19
#WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/0.19/lib64 -L$(PWD)/wlroots/0.19/lib64 -lwlroots-0.19 #WLR_LIBS = -Wl,-rpath,$(PWD)/wlroots/0.19/lib64 -L$(PWD)/wlroots/0.19/lib64 -lwlroots-0.19
XWAYLAND = # XWAYLAND =
XLIBS = # XLIBS =
# Uncomment to build XWayland support # Uncomment to build XWayland support
#XWAYLAND = -DXWAYLAND XWAYLAND = -DXWAYLAND
#XLIBS = xcb xcb-icccm XLIBS = xcb xcb-icccm
# dwl itself only uses C99 features, but wlroots' headers use anonymous unions (C11). # dwl itself only uses C99 features, but wlroots' headers use anonymous unions (C11).
# To avoid warnings about them, we do not use -std=c99 and instead of using the # To avoid warnings about them, we do not use -std=c99 and instead of using the

259
dwl.c
View File

@@ -68,7 +68,6 @@
#include <xcb/xcb_icccm.h> #include <xcb/xcb_icccm.h>
#endif #endif
#include "dwl-ipc-unstable-v2-protocol.h"
#include "util.h" #include "util.h"
/* macros */ /* macros */
@@ -142,12 +141,6 @@ typedef struct {
uint32_t resize; /* configure serial of a pending resize */ uint32_t resize; /* configure serial of a pending resize */
} Client; } Client;
typedef struct {
struct wl_list link;
struct wl_resource *resource;
Monitor *mon;
} DwlIpcOutput;
typedef struct { typedef struct {
uint32_t mod; uint32_t mod;
xkb_keysym_t keysym; xkb_keysym_t keysym;
@@ -192,7 +185,6 @@ typedef struct {
struct Monitor { struct Monitor {
struct wl_list link; struct wl_list link;
struct wl_list dwl_ipc_outputs;
struct wlr_output *wlr_output; struct wlr_output *wlr_output;
struct wlr_scene_output *scene_output; struct wlr_scene_output *scene_output;
struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */ struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */
@@ -290,17 +282,6 @@ static void destroypointerconstraint(struct wl_listener *listener, void *data);
static void destroysessionlock(struct wl_listener *listener, void *data); static void destroysessionlock(struct wl_listener *listener, void *data);
static void destroykeyboardgroup(struct wl_listener *listener, void *data); static void destroykeyboardgroup(struct wl_listener *listener, void *data);
static Monitor *dirtomon(enum wlr_direction dir); 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 focusclient(Client *c, int lift);
static void focusmon(const Arg *arg); static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg); static void focusstack(const Arg *arg);
@@ -353,7 +334,6 @@ static void startdrag(struct wl_listener *listener, void *data);
static void tag(const Arg *arg); static void tag(const Arg *arg);
static void tagmon(const Arg *arg); static void tagmon(const Arg *arg);
static void tile(Monitor *m); static void tile(Monitor *m);
static void togglebar(const Arg *arg);
static void togglefloating(const Arg *arg); static void togglefloating(const Arg *arg);
static void togglefullscreen(const Arg *arg); static void togglefullscreen(const Arg *arg);
static void toggletag(const Arg *arg); static void toggletag(const Arg *arg);
@@ -456,9 +436,6 @@ static struct wl_listener request_start_drag = {.notify = requeststartdrag};
static struct wl_listener start_drag = {.notify = startdrag}; static struct wl_listener start_drag = {.notify = startdrag};
static struct wl_listener new_session_lock = {.notify = locksession}; static struct wl_listener new_session_lock = {.notify = locksession};
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};
#ifdef XWAYLAND #ifdef XWAYLAND
static void activatex11(struct wl_listener *listener, void *data); static void activatex11(struct wl_listener *listener, void *data);
static void associatex11(struct wl_listener *listener, void *data); static void associatex11(struct wl_listener *listener, void *data);
@@ -752,10 +729,6 @@ cleanupmon(struct wl_listener *listener, void *data)
LayerSurface *l, *tmp; LayerSurface *l, *tmp;
size_t i; size_t i;
DwlIpcOutput *ipc_output, *ipc_output_tmp;
wl_list_for_each_safe(ipc_output, ipc_output_tmp, &m->dwl_ipc_outputs, link)
wl_resource_destroy(ipc_output->resource);
/* m->layers[i] are intentionally not unlinked */ /* m->layers[i] are intentionally not unlinked */
for (i = 0; i < LENGTH(m->layers); i++) { for (i = 0; i < LENGTH(m->layers); i++) {
wl_list_for_each_safe(l, tmp, &m->layers[i], link) wl_list_for_each_safe(l, tmp, &m->layers[i], link)
@@ -1076,8 +1049,6 @@ createmon(struct wl_listener *listener, void *data)
m = wlr_output->data = ecalloc(1, sizeof(*m)); m = wlr_output->data = ecalloc(1, sizeof(*m));
m->wlr_output = wlr_output; m->wlr_output = wlr_output;
wl_list_init(&m->dwl_ipc_outputs);
for (i = 0; i < LENGTH(m->layers); i++) for (i = 0; i < LENGTH(m->layers); i++)
wl_list_init(&m->layers[i]); wl_list_init(&m->layers[i]);
@@ -1425,192 +1396,6 @@ dirtomon(enum wlr_direction dir)
return selmon; 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, TAGCOUNT);
for (unsigned 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->mon = 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->mon;
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 < TAGCOUNT; 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);
zdwl_ipc_output_v2_send_appid(ipc_output->resource, appid);
zdwl_ipc_output_v2_send_layout_symbol(ipc_output->resource, monitor->ltsymbol);
if (wl_resource_get_version(ipc_output->resource) >= ZDWL_IPC_OUTPUT_V2_FULLSCREEN_SINCE_VERSION) {
zdwl_ipc_output_v2_send_fullscreen(ipc_output->resource, focused ? focused->isfullscreen : 0);
}
if (wl_resource_get_version(ipc_output->resource) >= ZDWL_IPC_OUTPUT_V2_FLOATING_SINCE_VERSION) {
zdwl_ipc_output_v2_send_floating(ipc_output->resource, focused ? focused->isfloating : 0);
}
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->mon;
selected_client = focustop(monitor);
if (!selected_client)
return;
newtags = (selected_client->tags & and_tags) ^ xor_tags;
if (!newtags)
return;
selected_client->tags = newtags;
if (selmon == monitor)
focusclient(focustop(monitor), 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->mon;
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->mon;
if (!newtags || newtags == monitor->tagset[monitor->seltags])
return;
if (toggle_tagset)
monitor->seltags ^= 1;
monitor->tagset[monitor->seltags] = newtags;
if (selmon == monitor)
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 void
focusclient(Client *c, int lift) focusclient(Client *c, int lift)
{ {
@@ -2044,7 +1829,7 @@ monocle(Monitor *m)
n++; n++;
} }
if (n) if (n)
snprintf(m->ltsymbol, LENGTH(m->ltsymbol), "[%d]", n); snprintf(m->ltsymbol, LENGTH(m->ltsymbol), "%d", n);
if ((c = focustop(m))) if ((c = focustop(m)))
wlr_scene_node_raise_to_top(&c->scene->node); wlr_scene_node_raise_to_top(&c->scene->node);
} }
@@ -2301,9 +2086,38 @@ void
printstatus(void) printstatus(void)
{ {
Monitor *m = NULL; Monitor *m = NULL;
Client *c;
uint32_t occ, urg, sel;
wl_list_for_each(m, &mons, link) wl_list_for_each(m, &mons, link) {
dwl_ipc_output_printstatus(m); occ = urg = 0;
wl_list_for_each(c, &clients, link) {
if (c->mon != m)
continue;
occ |= c->tags;
if (c->isurgent)
urg |= c->tags;
}
if ((c = focustop(m))) {
printf("%s title %s\n", m->wlr_output->name, client_get_title(c));
printf("%s appid %s\n", m->wlr_output->name, client_get_appid(c));
printf("%s fullscreen %d\n", m->wlr_output->name, c->isfullscreen);
printf("%s floating %d\n", m->wlr_output->name, c->isfloating);
sel = c->tags;
} else {
printf("%s title \n", m->wlr_output->name);
printf("%s appid \n", m->wlr_output->name);
printf("%s fullscreen \n", m->wlr_output->name);
printf("%s floating \n", m->wlr_output->name);
sel = 0;
}
printf("%s selmon %u\n", m->wlr_output->name, m == selmon);
printf("%s tags %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32"\n",
m->wlr_output->name, occ, m->tagset[m->seltags], sel, urg);
printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol);
}
fflush(stdout);
} }
void void
@@ -2827,8 +2641,6 @@ setup(void)
wl_signal_add(&output_mgr->events.apply, &output_mgr_apply); wl_signal_add(&output_mgr->events.apply, &output_mgr_apply);
wl_signal_add(&output_mgr->events.test, &output_mgr_test); wl_signal_add(&output_mgr->events.test, &output_mgr_test);
wl_global_create(dpy, &zdwl_ipc_manager_v2_interface, 2, NULL, dwl_ipc_manager_bind);
/* Make sure XWayland clients don't connect to the parent X server, /* Make sure XWayland clients don't connect to the parent X server,
* e.g when running in the x11 backend or the wayland backend and the * e.g when running in the x11 backend or the wayland backend and the
* compositor has Xwayland support */ * compositor has Xwayland support */
@@ -2926,13 +2738,6 @@ tile(Monitor *m)
} }
} }
void
togglebar(const Arg *arg) {
DwlIpcOutput *ipc_output;
wl_list_for_each(ipc_output, &selmon->dwl_ipc_outputs, link)
zdwl_ipc_output_v2_send_toggle_visibility(ipc_output->resource);
}
void void
togglefloating(const Arg *arg) togglefloating(const Arg *arg)
{ {

596
ipc.patch
View File

@@ -1,596 +0,0 @@
From 6c6d655b68770ce82a24fde9b58c4d97b672553a Mon Sep 17 00:00:00 2001
From: choc <notchoc@proton.me>
Date: Mon, 23 Oct 2023 10:35:17 +0800
Subject: [PATCH] implement dwl-ipc-unstable-v2
https://codeberg.org/dwl/dwl-patches/wiki/ipc
---
Makefile | 14 +-
config.def.h | 1 +
dwl.c | 257 ++++++++++++++++++++++++++----
protocols/dwl-ipc-unstable-v2.xml | 181 +++++++++++++++++++++
4 files changed, 419 insertions(+), 34 deletions(-)
create mode 100644 protocols/dwl-ipc-unstable-v2.xml
diff --git a/Makefile b/Makefile
index 8db7409..a79a080 100644
--- a/Makefile
+++ b/Makefile
@@ -17,12 +17,14 @@ DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(WLR_INCS) $(DWLCPPFLAGS) $(DWLDEV
LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(WLR_LIBS) -lm $(LIBS)
all: dwl
-dwl: dwl.o util.o
- $(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@
+dwl: dwl.o util.o dwl-ipc-unstable-v2-protocol.o
+ $(CC) dwl.o util.o dwl-ipc-unstable-v2-protocol.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@
dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \
pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \
- wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h
+ wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h \
+ dwl-ipc-unstable-v2-protocol.h
util.o: util.c util.h
+dwl-ipc-unstable-v2-protocol.o: dwl-ipc-unstable-v2-protocol.c dwl-ipc-unstable-v2-protocol.h
# wayland-scanner is a tool which generates C headers and rigging for Wayland
# protocols, which are specified in XML. wlroots requires you to rig these up
@@ -45,6 +47,12 @@ wlr-output-power-management-unstable-v1-protocol.h:
xdg-shell-protocol.h:
$(WAYLAND_SCANNER) server-header \
$(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@
+dwl-ipc-unstable-v2-protocol.h:
+ $(WAYLAND_SCANNER) server-header \
+ protocols/dwl-ipc-unstable-v2.xml $@
+dwl-ipc-unstable-v2-protocol.c:
+ $(WAYLAND_SCANNER) private-code \
+ protocols/dwl-ipc-unstable-v2.xml $@
config.h:
cp config.def.h $@
diff --git a/config.def.h b/config.def.h
index 22d2171..1593033 100644
--- a/config.def.h
+++ b/config.def.h
@@ -127,6 +127,7 @@ static const Key keys[] = {
/* modifier key function argument */
{ MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
+ { MODKEY, XKB_KEY_b, togglebar, {0} },
{ MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
{ MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
{ MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
diff --git a/dwl.c b/dwl.c
index 8a587d1..7a4949b 100644
--- a/dwl.c
+++ b/dwl.c
@@ -68,6 +68,7 @@
#include <xcb/xcb_icccm.h>
#endif
+#include "dwl-ipc-unstable-v2-protocol.h"
#include "util.h"
/* macros */
@@ -144,6 +145,12 @@ typedef struct {
uint32_t resize; /* configure serial of a pending resize */
} Client;
+typedef struct {
+ struct wl_list link;
+ struct wl_resource *resource;
+ Monitor *mon;
+} DwlIpcOutput;
+
typedef struct {
uint32_t mod;
xkb_keysym_t keysym;
@@ -189,6 +196,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 */
@@ -286,6 +294,17 @@ static void destroysessionlock(struct wl_listener *listener, void *data);
static void destroysessionmgr(struct wl_listener *listener, void *data);
static void destroykeyboardgroup(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);
@@ -338,6 +357,7 @@ static void startdrag(struct wl_listener *listener, void *data);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static void tile(Monitor *m);
+static void togglebar(const Arg *arg);
static void togglefloating(const Arg *arg);
static void togglefullscreen(const Arg *arg);
static void toggletag(const Arg *arg);
@@ -411,6 +431,9 @@ static struct wlr_box sgeom;
static struct wl_list mons;
static Monitor *selmon;
+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};
+
#ifdef XWAYLAND
static void activatex11(struct wl_listener *listener, void *data);
static void associatex11(struct wl_listener *listener, void *data);
@@ -703,6 +726,10 @@ cleanupmon(struct wl_listener *listener, void *data)
LayerSurface *l, *tmp;
size_t i;
+ DwlIpcOutput *ipc_output, *ipc_output_tmp;
+ wl_list_for_each_safe(ipc_output, ipc_output_tmp, &m->dwl_ipc_outputs, link)
+ wl_resource_destroy(ipc_output->resource);
+
/* m->layers[i] are intentionally not unlinked */
for (i = 0; i < LENGTH(m->layers); i++) {
wl_list_for_each_safe(l, tmp, &m->layers[i], link)
@@ -983,6 +1010,8 @@ createmon(struct wl_listener *listener, void *data)
m = wlr_output->data = ecalloc(1, sizeof(*m));
m->wlr_output = wlr_output;
+ wl_list_init(&m->dwl_ipc_outputs);
+
for (i = 0; i < LENGTH(m->layers); i++)
wl_list_init(&m->layers[i]);
@@ -1334,6 +1363,192 @@ 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, TAGCOUNT);
+
+ for (unsigned 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->mon = 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->mon;
+ 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 < TAGCOUNT; 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);
+ zdwl_ipc_output_v2_send_appid(ipc_output->resource, appid);
+ zdwl_ipc_output_v2_send_layout_symbol(ipc_output->resource, monitor->ltsymbol);
+ if (wl_resource_get_version(ipc_output->resource) >= ZDWL_IPC_OUTPUT_V2_FULLSCREEN_SINCE_VERSION) {
+ zdwl_ipc_output_v2_send_fullscreen(ipc_output->resource, focused ? focused->isfullscreen : 0);
+ }
+ if (wl_resource_get_version(ipc_output->resource) >= ZDWL_IPC_OUTPUT_V2_FLOATING_SINCE_VERSION) {
+ zdwl_ipc_output_v2_send_floating(ipc_output->resource, focused ? focused->isfloating : 0);
+ }
+ 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->mon;
+ selected_client = focustop(monitor);
+ if (!selected_client)
+ return;
+
+ newtags = (selected_client->tags & and_tags) ^ xor_tags;
+ if (!newtags)
+ return;
+
+ selected_client->tags = newtags;
+ if (selmon == monitor)
+ focusclient(focustop(monitor), 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->mon;
+ 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->mon;
+
+ if (!newtags || newtags == monitor->tagset[monitor->seltags])
+ return;
+ if (toggle_tagset)
+ monitor->seltags ^= 1;
+
+ monitor->tagset[monitor->seltags] = newtags;
+ if (selmon == monitor)
+ 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)
{
@@ -2033,38 +2248,9 @@ void
printstatus(void)
{
Monitor *m = NULL;
- Client *c;
- uint32_t occ, urg, sel;
- wl_list_for_each(m, &mons, link) {
- occ = urg = 0;
- wl_list_for_each(c, &clients, link) {
- if (c->mon != m)
- continue;
- occ |= c->tags;
- if (c->isurgent)
- urg |= c->tags;
- }
- if ((c = focustop(m))) {
- printf("%s title %s\n", m->wlr_output->name, client_get_title(c));
- printf("%s appid %s\n", m->wlr_output->name, client_get_appid(c));
- printf("%s fullscreen %d\n", m->wlr_output->name, c->isfullscreen);
- printf("%s floating %d\n", m->wlr_output->name, c->isfloating);
- sel = c->tags;
- } else {
- printf("%s title \n", m->wlr_output->name);
- printf("%s appid \n", m->wlr_output->name);
- printf("%s fullscreen \n", m->wlr_output->name);
- printf("%s floating \n", m->wlr_output->name);
- sel = 0;
- }
-
- printf("%s selmon %u\n", m->wlr_output->name, m == selmon);
- printf("%s tags %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32"\n",
- m->wlr_output->name, occ, m->tagset[m->seltags], sel, urg);
- printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol);
- }
- fflush(stdout);
+ wl_list_for_each(m, &mons, link)
+ dwl_ipc_output_printstatus(m);
}
void
@@ -2584,6 +2770,8 @@ setup(void)
LISTEN_STATIC(&output_mgr->events.apply, outputmgrapply);
LISTEN_STATIC(&output_mgr->events.test, outputmgrtest);
+ wl_global_create(dpy, &zdwl_ipc_manager_v2_interface, 2, NULL, dwl_ipc_manager_bind);
+
/* Make sure XWayland clients don't connect to the parent X server,
* e.g when running in the x11 backend or the wayland backend and the
* compositor has Xwayland support */
@@ -2681,6 +2869,13 @@ tile(Monitor *m)
}
}
+void
+togglebar(const Arg *arg) {
+ DwlIpcOutput *ipc_output;
+ wl_list_for_each(ipc_output, &selmon->dwl_ipc_outputs, link)
+ zdwl_ipc_output_v2_send_toggle_visibility(ipc_output->resource);
+}
+
void
togglefloating(const Arg *arg)
{
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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This is largely ripped from somebar's ipc patchset; just with some personal modifications.
+I would probably just submit raphi's patchset but I don't think that would be polite.
+-->
+<protocol name="dwl_ipc_unstable_v2">
+ <description summary="inter-proccess-communication about dwl's state">
+ 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.
+ </description>
+
+ <interface name="zdwl_ipc_manager_v2" version="2">
+ <description summary="manage dwl state">
+ 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.
+ </description>
+
+ <request name="release" type="destructor">
+ <description summary="release dwl_ipc_manager">
+ Indicates that the client will not the dwl_ipc_manager object anymore.
+ Objects created through this instance are not affected.
+ </description>
+ </request>
+
+ <request name="get_output">
+ <description summary="get a dwl_ipc_outout for a wl_output">
+ Get a dwl_ipc_outout for the specified wl_output.
+ </description>
+ <arg name="id" type="new_id" interface="zdwl_ipc_output_v2"/>
+ <arg name="output" type="object" interface="wl_output"/>
+ </request>
+
+ <event name="tags">
+ <description summary="Announces tag amount">
+ This event is sent after binding.
+ A roundtrip after binding guarantees the client recieved all tags.
+ </description>
+ <arg name="amount" type="uint"/>
+ </event>
+
+ <event name="layout">
+ <description summary="Announces a layout">
+ This event is sent after binding.
+ A roundtrip after binding guarantees the client recieved all layouts.
+ </description>
+ <arg name="name" type="string"/>
+ </event>
+ </interface>
+
+ <interface name="zdwl_ipc_output_v2" version="2">
+ <description summary="control dwl output">
+ 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.
+ </description>
+
+ <enum name="tag_state">
+ <entry name="none" value="0" summary="no state"/>
+ <entry name="active" value="1" summary="tag is active"/>
+ <entry name="urgent" value="2" summary="tag has at least one urgent client"/>
+ </enum>
+
+ <request name="release" type="destructor">
+ <description summary="release dwl_ipc_outout">
+ Indicates to that the client no longer needs this dwl_ipc_output.
+ </description>
+ </request>
+
+ <event name="toggle_visibility">
+ <description summary="Toggle client visibilty">
+ Indicates the client should hide or show themselves.
+ If the client is visible then hide, if hidden then show.
+ </description>
+ </event>
+
+ <event name="active">
+ <description summary="Update the selected output.">
+ Indicates if the output is active. Zero is invalid, nonzero is valid.
+ </description>
+ <arg name="active" type="uint"/>
+ </event>
+
+ <event name="tag">
+ <description summary="Update the state of a tag.">
+ Indicates that a tag has been updated.
+ </description>
+ <arg name="tag" type="uint" summary="Index of the tag"/>
+ <arg name="state" type="uint" enum="tag_state" summary="The state of the tag."/>
+ <arg name="clients" type="uint" summary="The number of clients in the tag."/>
+ <arg name="focused" type="uint" summary="If there is a focused client. Nonzero being valid, zero being invalid."/>
+ </event>
+
+ <event name="layout">
+ <description summary="Update the layout.">
+ Indicates a new layout is selected.
+ </description>
+ <arg name="layout" type="uint" summary="Index of the layout."/>
+ </event>
+
+ <event name="title">
+ <description summary="Update the title.">
+ Indicates the title has changed.
+ </description>
+ <arg name="title" type="string" summary="The new title name."/>
+ </event>
+
+ <event name="appid" since="1">
+ <description summary="Update the appid.">
+ Indicates the appid has changed.
+ </description>
+ <arg name="appid" type="string" summary="The new appid."/>
+ </event>
+
+ <event name="layout_symbol" since="1">
+ <description summary="Update the current layout symbol">
+ 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.
+ </description>
+ <arg name="layout" type="string" summary="The new layout"/>
+ </event>
+
+ <event name="frame">
+ <description summary="The update sequence is done.">
+ Indicates that a sequence of status updates have finished and the client should redraw.
+ </description>
+ </event>
+
+ <request name="set_tags">
+ <description summary="Set the active tags of this output"/>
+ <arg name="tagmask" type="uint" summary="bitmask of the tags that should be set."/>
+ <arg name="toggle_tagset" type="uint" summary="toggle the selected tagset, zero for invalid, nonzero for valid."/>
+ </request>
+
+ <request name="set_client_tags">
+ <description summary="Set the tags of the focused client.">
+ The tags are updated as follows:
+ new_tags = (current_tags AND and_tags) XOR xor_tags
+ </description>
+ <arg name="and_tags" type="uint"/>
+ <arg name="xor_tags" type="uint"/>
+ </request>
+
+ <request name="set_layout">
+ <description summary="Set the layout of this output"/>
+ <arg name="index" type="uint" summary="index of a layout recieved by dwl_ipc_manager.layout"/>
+ </request>
+
+ <!-- Version 2 -->
+ <event name="fullscreen" since="2">
+ <description summary="Update fullscreen status">
+ Indicates if the selected client on this output is fullscreen.
+ </description>
+ <arg name="is_fullscreen" type="uint" summary="If the selected client is fullscreen. Nonzero is valid, zero invalid"/>
+ </event>
+
+ <event name="floating" since="2">
+ <description summary="Update the floating status">
+ Indicates if the selected client on this output is floating.
+ </description>
+ <arg name="is_floating" type="uint" summary="If the selected client is floating. Nonzero is valid, zero invalid"/>
+ </event>
+ </interface>
+</protocol>
--
2.43.0

View File

@@ -1,181 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This is largely ripped from somebar's ipc patchset; just with some personal modifications.
I would probably just submit raphi's patchset but I don't think that would be polite.
-->
<protocol name="dwl_ipc_unstable_v2">
<description summary="inter-proccess-communication about dwl's state">
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.
</description>
<interface name="zdwl_ipc_manager_v2" version="2">
<description summary="manage dwl state">
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.
</description>
<request name="release" type="destructor">
<description summary="release dwl_ipc_manager">
Indicates that the client will not the dwl_ipc_manager object anymore.
Objects created through this instance are not affected.
</description>
</request>
<request name="get_output">
<description summary="get a dwl_ipc_outout for a wl_output">
Get a dwl_ipc_outout for the specified wl_output.
</description>
<arg name="id" type="new_id" interface="zdwl_ipc_output_v2"/>
<arg name="output" type="object" interface="wl_output"/>
</request>
<event name="tags">
<description summary="Announces tag amount">
This event is sent after binding.
A roundtrip after binding guarantees the client recieved all tags.
</description>
<arg name="amount" type="uint"/>
</event>
<event name="layout">
<description summary="Announces a layout">
This event is sent after binding.
A roundtrip after binding guarantees the client recieved all layouts.
</description>
<arg name="name" type="string"/>
</event>
</interface>
<interface name="zdwl_ipc_output_v2" version="2">
<description summary="control dwl output">
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.
</description>
<enum name="tag_state">
<entry name="none" value="0" summary="no state"/>
<entry name="active" value="1" summary="tag is active"/>
<entry name="urgent" value="2" summary="tag has at least one urgent client"/>
</enum>
<request name="release" type="destructor">
<description summary="release dwl_ipc_outout">
Indicates to that the client no longer needs this dwl_ipc_output.
</description>
</request>
<event name="toggle_visibility">
<description summary="Toggle client visibilty">
Indicates the client should hide or show themselves.
If the client is visible then hide, if hidden then show.
</description>
</event>
<event name="active">
<description summary="Update the selected output.">
Indicates if the output is active. Zero is invalid, nonzero is valid.
</description>
<arg name="active" type="uint"/>
</event>
<event name="tag">
<description summary="Update the state of a tag.">
Indicates that a tag has been updated.
</description>
<arg name="tag" type="uint" summary="Index of the tag"/>
<arg name="state" type="uint" enum="tag_state" summary="The state of the tag."/>
<arg name="clients" type="uint" summary="The number of clients in the tag."/>
<arg name="focused" type="uint" summary="If there is a focused client. Nonzero being valid, zero being invalid."/>
</event>
<event name="layout">
<description summary="Update the layout.">
Indicates a new layout is selected.
</description>
<arg name="layout" type="uint" summary="Index of the layout."/>
</event>
<event name="title">
<description summary="Update the title.">
Indicates the title has changed.
</description>
<arg name="title" type="string" summary="The new title name."/>
</event>
<event name="appid" since="1">
<description summary="Update the appid.">
Indicates the appid has changed.
</description>
<arg name="appid" type="string" summary="The new appid."/>
</event>
<event name="layout_symbol" since="1">
<description summary="Update the current layout symbol">
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.
</description>
<arg name="layout" type="string" summary="The new layout"/>
</event>
<event name="frame">
<description summary="The update sequence is done.">
Indicates that a sequence of status updates have finished and the client should redraw.
</description>
</event>
<request name="set_tags">
<description summary="Set the active tags of this output"/>
<arg name="tagmask" type="uint" summary="bitmask of the tags that should be set."/>
<arg name="toggle_tagset" type="uint" summary="toggle the selected tagset, zero for invalid, nonzero for valid."/>
</request>
<request name="set_client_tags">
<description summary="Set the tags of the focused client.">
The tags are updated as follows:
new_tags = (current_tags AND and_tags) XOR xor_tags
</description>
<arg name="and_tags" type="uint"/>
<arg name="xor_tags" type="uint"/>
</request>
<request name="set_layout">
<description summary="Set the layout of this output"/>
<arg name="index" type="uint" summary="index of a layout recieved by dwl_ipc_manager.layout"/>
</request>
<!-- Version 2 -->
<event name="fullscreen" since="2">
<description summary="Update fullscreen status">
Indicates if the selected client on this output is fullscreen.
</description>
<arg name="is_fullscreen" type="uint" summary="If the selected client is fullscreen. Nonzero is valid, zero invalid"/>
</event>
<event name="floating" since="2">
<description summary="Update the floating status">
Indicates if the selected client on this output is floating.
</description>
<arg name="is_floating" type="uint" summary="If the selected client is floating. Nonzero is valid, zero invalid"/>
</event>
</interface>
</protocol>