commit 8e9755c73d4ec8b2a355a17e2c1772cc74c636b1
parent 8025f6ea3dbe127caf38801dabaa435e06c0ab2e
Author: Dash Eclipse <dash@ezup.dev>
Date: Wed, 15 Jul 2020 13:49:21 +0000
dwm: systray patch and nordtheme based color
Diffstat:
6 files changed, 929 insertions(+), 521 deletions(-)
diff --git a/README b/README
@@ -0,0 +1,21 @@
+Dash Eclipse's Void Linux Repository
+------------------------------------
+
+Packages: dwm, st
+
+
+st
+--
+
+Font: Fira Code Medium
+
+https://st.suckless.org/patches/scrollback/
+https://st.suckless.org/patches/nordtheme/
+
+
+dwm
+---
+
+Color: nordtheme based
+
+https://dwm.suckless.org/patches/systray/
diff --git a/README.md b/README.md
@@ -1,521 +0,0 @@
-## The XBPS source packages collection
-
-This repository contains the XBPS source packages collection to build binary packages
-for the Void Linux distribution.
-
-The included `xbps-src` script will fetch and compile the sources, and install its
-files into a `fake destdir` to generate XBPS binary packages that can be installed
-or queried through the `xbps-install(1)` and `xbps-query(1)` utilities, respectively.
-
-See [Contributing](./CONTRIBUTING.md) for a general overview of how to contribute and the
-[Manual](./Manual.md) for details of how to create source packages.
-
-### Table of Contents
-
-- [Requirements](#requirements)
-- [Quick start](#quick-start)
-- [chroot methods](#chroot-methods)
-- [Install the bootstrap packages](#install-bootstrap)
-- [Configuration](#configuration)
-- [Directory hierarchy](#directory-hierarchy)
-- [Building packages](#building-packages)
-- [Package build options](#build-options)
-- [Sharing and signing your local repositories](#sharing-and-signing)
-- [Rebuilding and overwriting existing local packages](#rebuilding)
-- [Enabling distcc for distributed compilation](#distcc)
-- [Distfiles mirrors](#distfiles-mirrors)
-- [Cross compiling packages for a target architecture](#cross-compiling)
-- [Using xbps-src in a foreign Linux distribution](#foreign)
-- [Remaking the masterdir](#remaking-masterdir)
-- [Keeping your masterdir uptodate](#updating-masterdir)
-- [Building 32bit packages on x86_64](#building-32bit)
-- [Building packages natively for the musl C library](#building-for-musl)
-- [Building void base-system from scratch](#building-base-system)
-
-### Requirements
-
-- GNU bash
-- xbps >= 0.56
-- curl(1) - required by `xbps-src update-check`
-- flock(1) - util-linux
-- bsdtar or GNU tar (in that order of preference)
-- install(1) - GNU coreutils
-- objcopy(1), objdump(1), strip(1): binutils
-- other common POSIX utilities included by default in almost all UNIX systems.
-
-`xbps-src` requires a utility to chroot and bind mount existing directories
-into a `masterdir` that is used as its main `chroot` directory. `xbps-src` supports
-multiple utilities to accomplish this task:
-
- - `bwrap` - bubblewrap, see https://github.com/projectatomic/bubblewrap.
- - `ethereal` - only useful for one-shot containers, i.e docker (used with travis).
- - `xbps-uunshare(1)` - XBPS utility that uses `user_namespaces(7)` (part of xbps, default).
- - `xbps-uchroot(1)` - XBPS utility that uses `namespaces` and must be `setgid` (part of xbps).
- - `proot(1)` - utility that implements chroot/bind mounts in user space, see https://proot-me.github.io/.
-
-> NOTE: `xbps-src` does not allow building as root anymore. Use one of the chroot
-methods shown above.
-
-<a name="quick-start"></a>
-### Quick start
-
-Clone the `void-packages` git repository and install the bootstrap packages:
-
-```
-$ git clone git://github.com/void-linux/void-packages.git
-$ cd void-packages
-$ ./xbps-src binary-bootstrap
-```
-
-Build a package by specifying the `pkg` target and the package name:
-
-```
-$ ./xbps-src pkg <package_name>
-```
-
-Use `./xbps-src -h` to list all available targets and options.
-
-To build packages marked as 'restricted', modify `etc/conf`:
-
-```
-$ echo XBPS_ALLOW_RESTRICTED=yes >> etc/conf
-```
-
-Once built, the package will be available in `hostdir/binpkgs` or an appropriate subdirectory (e.g. `hostdir/binpkgs/nonfree`). To install the package:
-
-```
-# xbps-install --repository hostdir/binpkgs <package_name>
-```
-
-Alternatively, packages can be installed with the `xi` utility, from the `xtools` package. `xi` takes the repository of the current working directory into account.
-
-```
-# xi <package_name>
-```
-
-<a name="chroot-methods"></a>
-### chroot methods
-
-#### xbps-uunshare(1) (default)
-
-This utility requires these Linux kernel options:
-
-- CONFIG\_NAMESPACES
-- CONFIG\_IPC\_NS
-- CONFIG\_UTS\_NS
-- CONFIG\_USER\_NS
-
-This is the default method, and if your system does not support any of the required kernel
-options it will fail with `EINVAL (Invalid argument)`.
-
-#### xbps-uchroot(1)
-
-This utility requires these Linux kernel options:
-
-- CONFIG\_NAMESPACES
-- CONFIG\_IPC\_NS
-- CONFIG\_PID\_NS
-- CONFIG\_UTS\_NS
-
-Your user must be added to a special group to be able to use `xbps-uchroot(1)` and the
-executable must be `setgid`:
-
- # chown root:<group> xbps-uchroot
- # chmod 4750 xbps-uchroot
- # usermod -a -G <group> <user>
-
-> NOTE: by default in void you shouldn't do this manually, your user must be a member of
-the `xbuilder` group.
-
-To enable it:
-
- $ cd void-packages
- $ echo XBPS_CHROOT_CMD=uchroot >> etc/conf
-
-If for some reason it's erroring out as `ERROR clone (Operation not permitted)`, check that
-your user is a member of the required `group` and that `xbps-uchroot(1)` utility has the
-proper permissions and owner/group as explained above.
-
-#### proot(1)
-
-The `proot(1)` utility implements chroot and bind mounts support completely in user space,
-and can be used if your Linux kernel does not have support for namespaces. See https://proot-me.github.io/.
-for more information.
-
-To enable it:
-
- $ cd void-packages
- $ echo XBPS_CHROOT_CMD=proot >> etc/conf
-
-<a name="install-bootstrap"></a>
-### Install the bootstrap packages
-
-There is a set of packages that makes up the initial build container, called the `bootstrap`.
-These packages are installed into the `masterdir` in order to create the container.
-
-The primary and recommended way to set up this container is using the `binary-bootstrap`
-command. This will use pre-existing binary packages, either from remote `xbps` repositories
-or from your local repository.
-
-There is also the `bootstrap` command, which will build all necessary `bootstrap` packages from
-scratch. This is usually not recommended, since those packages are built using your host system's
-toolchain and are neither fully featured nor reproducible (your host system may influence the
-build) and thus should only be used as a stage 0 for bootstrapping new Void systems.
-
-If you still choose to use `bootstrap`, use the resulting stage 0 container to rebuild all
-`bootstrap` packages again, then use `binary-bootstrap` (stage 1) and rebuild the `bootstrap`
-packages once more (to gain stage 2, and then use `binary-bootstrap` again). Once you've done
-that, you will have a `bootstrap` set equivalent to using `binary-bootstrap` in the first place.
-
-Also keep in mind that a full source `bootstrap` is time consuming and will require having an
-assortment of utilities installed in your host system, such as `binutils`, `gcc`, `perl`,
-`texinfo` and others.
-
-### Configuration
-
-The `etc/defaults.conf` file contains the possible settings that can be overridden
-through the `etc/conf` configuration file for the `xbps-src` utility; if that file
-does not exist, will try to read configuration settings from `$XDG_CONFIG_HOME/xbps-src.conf`, `~/.config/xbps-src.conf`, `~/.xbps-src.conf`.
-
-If you want to customize default `CFLAGS`, `CXXFLAGS` and `LDFLAGS`, don't override
-those defined in `etc/defaults.conf`, set them on `etc/conf` instead i.e:
-
- $ echo 'XBPS_CFLAGS="your flags here"' >> etc/conf
- $ echo 'XBPS_LDFLAGS="your flags here"' >> etc/conf
-
-Native and cross compiler/linker flags are set per architecture in `common/build-profiles`
-and `common/cross-profiles` respectively. Ideally those settings are good enough by default,
-and there's no need to set your own unless you know what you are doing.
-
-#### Virtual packages
-
-The `etc/defaults.virtual` file contains the default replacements for virtual packages,
-used as dependencies in the source packages tree.
-
-If you want to customize those replacements, copy `etc/defaults.virtual` to `etc/virtual`
-and edit it accordingly to your needs.
-
-<a name="directory-hierarchy"></a>
-### Directory hierarchy
-
-The following directory hierarchy is used with a default configuration file:
-
- /void-packages
- |- common
- |- etc
- |- srcpkgs
- | |- xbps
- | |- template
- |
- |- hostdir
- | |- binpkgs ...
- | |- ccache ...
- | |- distcc-<arch> ...
- | |- repocache ...
- | |- sources ...
- |
- |- masterdir
- | |- builddir -> ...
- | |- destdir -> ...
- | |- host -> bind mounted from <hostdir>
- | |- void-packages -> bind mounted from <void-packages>
-
-
-The description of these directories is as follows:
-
- - `masterdir`: master directory to be used as rootfs to build/install packages.
- - `builddir`: to unpack package source tarballs and where packages are built.
- - `destdir`: to install packages, aka **fake destdir**.
- - `hostdir/ccache`: to store ccache data if the `XBPS_CCACHE` option is enabled.
- - `hostdir/distcc-<arch>`: to store distcc data if the `XBPS_DISTCC` option is enabled.
- - `hostdir/repocache`: to store binary packages from remote repositories.
- - `hostdir/sources`: to store package sources.
- - `hostdir/binpkgs`: local repository to store generated binary packages.
-
-<a name="building-packages"></a>
-### Building packages
-
-The simplest form of building package is accomplished by running the `pkg` target in `xbps-src`:
-
-```
-$ cd void-packages
-$ ./xbps-src pkg <pkgname>
-```
-
-When the package and its required dependencies are built, the binary packages will be created
-and registered in the default local repository at `hostdir/binpkgs`; the path to this local repository can be added to
-any xbps configuration file (see xbps.d(5)) or by explicitly appending them via cmdline, i.e:
-
- $ xbps-install --repository=hostdir/binpkgs ...
- $ xbps-query --repository=hostdir/binpkgs ...
-
-By default **xbps-src** will try to resolve package dependencies in this order:
-
- - If a dependency exists in the local repository, use it (`hostdir/binpkgs`).
- - If a dependency exists in a remote repository, use it.
- - If a dependency exists in a source package, use it.
-
-It is possible to avoid using remote repositories completely by using the `-N` flag.
-
-> The default local repository may contain multiple *sub-repositories*: `debug`, `multilib`, etc.
-
-<a name="build-options"></a>
-### Package build options
-
-The supported build options for a source package can be shown with `xbps-src show-options`:
-
- $ ./xbps-src show-options foo
-
-Build options can be enabled with the `-o` flag of `xbps-src`:
-
- $ ./xbps-src -o option,option1 pkg foo
-
-Build options can be disabled by prefixing them with `~`:
-
- $ ./xbps-src -o ~option,~option1 pkg foo
-
-Both ways can be used together to enable and/or disable multiple options
-at the same time with `xbps-src`:
-
- $ ./xbps-src -o option,~option1,~option2 pkg foo
-
-The build options can also be shown for binary packages via `xbps-query(1)`:
-
- $ xbps-query -R --property=build-options foo
-
-> NOTE: if you build a package with a custom option, and that package is available
-in an official void repository, an update will ignore those options. Put that package
-on `hold` mode via `xbps-pkgdb(1)`, i.e `xbps-pkgdb -m hold foo` to ignore updates
-with `xbps-install -u`. Once the package is on `hold`, the only way to update it
-is by declaring it explicitly: `xbps-install -u foo`.
-
-Permanent global package build options can be set via `XBPS_PKG_OPTIONS` variable in the
-`etc/conf` configuration file. Per package build options can be set via
-`XBPS_PKG_OPTIONS_<pkgname>`.
-
-> NOTE: if `pkgname` contains `dashes`, those should be replaced by `underscores`
-i.e `XBPS_PKG_OPTIONS_xorg_server=opt`.
-
-The list of supported package build options and its description is defined in the
-`common/options.description` file or in the `template` file.
-
-<a name="sharing-and-signing"></a>
-### Sharing and signing your local repositories
-
-To share a local repository remotely it's mandatory to sign it and the binary packages
-stored on it. This is accomplished with the `xbps-rindex(1)` utility.
-
-First a RSA key must be created with `openssl(1)` or `ssh-keygen(1)`:
-
- $ openssl genrsa -des3 -out privkey.pem 4096
-
-or
-
- $ ssh-keygen -t rsa -b 4096 -m PEM -f privkey.pem
-
-> Only RSA keys in PEM format are currently accepted by xbps.
-
-Once the RSA private key is ready you can use it to initialize the repository metadata:
-
- $ xbps-rindex --sign --signedby "I'm Groot" --privkey privkey.pem $PWD/hostdir/binpkgs
-
-And then make a signature per package:
-
- $ xbps-rindex --sign-pkg --privkey privkey.pem $PWD/hostdir/binpkgs/*.xbps
-
-> If --privkey is unset, it defaults to `~/.ssh/id_rsa`.
-
-If the RSA key was protected with a passphrase you'll have to type it, or alternatively set
-it via the `XBPS_PASSPHRASE` environment variable.
-
-Once the binary packages have been signed, check the repository contains the appropriate `hex fingerprint`:
-
- $ xbps-query --repository=hostdir/binpkgs -vL
- ...
-
-Each time a binary package is created, a package signature must be created with `--sign-pkg`.
-
-> It is not possible to sign a repository with multiple RSA keys.
-
-<a name="rebuilding"></a>
-### Rebuilding and overwriting existing local packages
-
-If for whatever reason a package has been built and it is available in your local repository
-and you have to rebuild it without bumping its `version` or `revision` fields, it is possible
-to accomplish this task easily with `xbps-src`:
-
- $ ./xbps-src -f pkg xbps
-
-Reinstalling this package in your target `rootdir` can be easily done too:
-
- $ xbps-install --repository=/path/to/local/repo -yff xbps-0.25_1
-
-> Please note that the `package expression` must be properly defined to explicitly pick up
-the package from the desired repository.
-
-<a name="distcc"></a>
-### Enabling distcc for distributed compilation
-
-Setup the slaves (machines that will compile the code):
-
- # xbps-install -Sy distcc
-
-Modify the configuration to allow your local network machines to use distcc (e.g. `192.168.2.0/24`):
-
- # echo "192.168.2.0/24" >> /etc/distcc/clients.allow
-
-Enable and start the `distccd` service:
-
- # ln -s /etc/sv/distccd /var/service
-
-Install distcc on the host (machine that executes xbps-src) as well.
-Unless you want to use the host as slave from other machines, there is no need
-to modify the configuration.
-
-On the host you can now enable distcc in the `void-packages/etc/conf` file:
-
- XBPS_DISTCC=yes
- XBPS_DISTCC_HOSTS="localhost/2 --localslots_cpp=24 192.168.2.101/9 192.168.2.102/2"
- XBPS_MAKEJOBS=16
-
-The example values assume a localhost CPU with 4 cores of which at most 2 are used for compiler jobs.
-The number of slots for preprocessor jobs is set to 24 in order to have enough preprocessed data for other CPUs to compile.
-The slave 192.168.2.101 has a CPU with 8 cores and the /9 for the number of jobs is a saturating choice.
-The slave 192.168.2.102 is set to run at most 2 compile jobs to keep its load low, even if its CPU has 4 cores.
-The XBPS_MAKEJOBS setting is increased to 16 to account for the possible parallelism (2 + 9 + 2 + some slack).
-
-<a name="distfiles-mirrors"></a>
-### Distfiles mirror(s)
-
-In etc/conf you may optionally define a mirror or a list of mirrors to search for distfiles.
-
- $ echo 'XBPS_DISTFILES_MIRROR="ftp://192.168.100.5/gentoo/distfiles"' >> etc/conf
-
-If more than one mirror is to be searched, you can either specify multiple URLs separated
-with blanks, or add to the variable like this
-
- $ echo 'XBPS_DISTFILES_MIRROR+=" https://sources.voidlinux.org/"' >> etc/conf
-
-Make sure to put the blank after the first double quote in this case.
-
-The mirrors are searched in order for the distfiles to build a package until the
-checksum of the downloaded file matches the one specified in the template.
-
-Ultimately, if no mirror carries the distfile, or in case all downloads failed the
-checksum verification, the original download location is used.
-
-If you use `proot` or `uchroot` for your XBPS_CHROOT_CMD, you may also specify a local path
-using the `file://` prefix or simply an absolute path on your build host (e.g. /mnt/distfiles).
-Mirror locations specified this way are bind mounted inside the chroot environment
-under $XBPS_MASTERDIR and searched for distfiles just the same as remote locations.
-
-<a name="cross-compiling"></a>
-### Cross compiling packages for a target architecture
-
-Currently `xbps-src` can cross build packages for some target architectures with a cross compiler.
-The supported target is shown with `./xbps-src -h`.
-
-If a source package has been adapted to be **cross buildable** `xbps-src` will automatically build the binary package(s) with a simple command:
-
- $ ./xbps-src -a <target> pkg <pkgname>
-
-If the build for whatever reason fails, might be a new build issue or simply because it hasn't been adapted to be **cross compiled**.
-
-<a name="foreign"></a>
-### Using xbps-src in a foreign Linux distribution
-
-xbps-src can be used in any recent Linux distribution matching the CPU architecture.
-
-To use xbps-src in your Linux distribution use the following instructions. Let's start downloading the xbps static binaries:
-
- $ wget http://alpha.de.repo.voidlinux.org/static/xbps-static-latest.<arch>-musl.tar.xz
- $ mkdir ~/XBPS
- $ tar xvf xbps-static-latest.<arch>.tar.xz -C ~/XBPS
- $ export PATH=~/XBPS/usr/bin:$PATH
-
-If your system does not support `user namespaces`, a privileged group is required to be able to use
-`xbps-uchroot(1)` with xbps-src, by default it's set to the `xbuilder` group, change this to your desired group:
-
- # chown root:<group> ~/XBPS/usr/bin/xbps-uchroot.static
- # chmod 4750 ~/XBPS/usr/bin/xbps-uchroot.static
-
-Clone the `void-packages` git repository:
-
- $ git clone git://github.com/void-linux/void-packages
-
-and `xbps-src` should be fully functional; just start the `bootstrap` process, i.e:
-
- $ ./xbps-src binary-bootstrap
-
-The default masterdir is created in the current working directory, i.e `void-packages/masterdir`.
-
-<a name="remaking-masterdir"></a>
-### Remaking the masterdir
-
-If for some reason you must update xbps-src and the `bootstrap-update` target is not enough, it's possible to recreate a masterdir with two simple commands (please note that `zap` keeps your `ccache/distcc/host` directories intact):
-
- $ ./xbps-src zap
- $ ./xbps-src binary-bootstrap
-
-<a name="updating-masterdir"></a>
-### Keeping your masterdir uptodate
-
-Sometimes the bootstrap packages must be updated to the latest available version in repositories, this is accomplished with the `bootstrap-update` target:
-
- $ ./xbps-src bootstrap-update
-
-<a name="building-32bit"></a>
-### Building 32bit packages on x86_64
-
-Two ways are available to build 32bit packages on x86\_64:
-
- - cross compilation mode
- - native mode with a 32bit masterdir
-
-The first mode (cross compilation) is as easy as:
-
- $ ./xbps-src -a i686 pkg ...
-
-The second mode (native) needs a new x86 `masterdir`:
-
- $ ./xbps-src -m masterdir-x86 binary-bootstrap i686
- $ ./xbps-src -m masterdir-x86 ...
-
-<a name="building-for-musl"></a>
-### Building packages natively for the musl C library
-
-A native build environment is required to be able to cross compile the bootstrap packages for the musl C library; this is accomplished by installing them via `binary-bootstrap`:
-
- $ ./xbps-src binary-bootstrap
-
-Now cross compile `base-chroot-musl` for your native architecture:
-
- $ ./xbps-src -a x86_64-musl pkg base-chroot-musl
-
-Wait until all packages are built and when ready, prepare a new masterdir with the musl packages:
-
- $ ./xbps-src -m masterdir-x86_64-musl binary-bootstrap x86_64-musl
-
-Your new masterdir is now ready to build packages natively for the musl C library. Try:
-
- $ ./xbps-src -m masterdir-x86_64-musl chroot
- $ ldd
-
-To see if the musl C dynamic linker is working as expected.
-
-<a name="building-base-system"></a>
-### Building void base-system from scratch
-
-To rebuild all packages in `base-system` for your native architecture:
-
- $ ./xbps-src -N pkg base-system
-
-It's also possible to cross compile everything from scratch:
-
- $ ./xbps-src -a <target> -N pkg base-system
-
-Once the build has finished, you can specify the path to the local repository to `void-mklive`, i.e:
-
- # cd void-mklive
- # make
- # ./mklive.sh ... -r /path/to/hostdir/binpkgs
diff --git a/srcpkgs/dwm/files/config.h b/srcpkgs/dwm/files/config.h
@@ -0,0 +1,129 @@
+/* See LICENSE file for copyright and license details. */
+
+/* appearance */
+static const unsigned int borderpx = 1; /* border pixel of windows */
+static const unsigned int snap = 32; /* snap pixel */
+static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
+static const unsigned int systrayspacing = 2; /* systray spacing */
+static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
+static const int showsystray = 1; /* 0 means no systray */
+static const int showbar = 1; /* 0 means no bar */
+static const int topbar = 1; /* 0 means bottom bar */
+static const char *fonts[] = { "monospace:size=10" };
+static const char dmenufont[] = "monospace:size=10";
+static const char col_gray1[] = "#2e3440";
+static const char col_gray2[] = "#2e3440";
+static const char col_gray3[] = "#81a1c1";
+static const char col_gray4[] = "#e5e9f0";
+static const char col_cyan[] = "#4c566a";
+static const char *colors[][3] = {
+ /* fg bg border */
+ [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
+ [SchemeSel] = { col_gray4, col_cyan, col_cyan },
+};
+
+/* tagging */
+static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+
+static const Rule rules[] = {
+ /* xprop(1):
+ * WM_CLASS(STRING) = instance, class
+ * WM_NAME(STRING) = title
+ */
+ /* class instance title tags mask isfloating monitor */
+ { "Gimp", NULL, NULL, 0, 1, -1 },
+ { "Firefox", NULL, NULL, 1 << 8, 0, -1 },
+ { "Fcitx-config-gtk3", NULL, NULL, 0, 1, -1 },
+ /* { "TelegramDesktop", NULL, NULL, 1 << 3, 0, -1 }, */
+ { "SimpleScreenRecorder", NULL, NULL, 0, 1, -1 },
+ { "Audacity", NULL, NULL, 0, 1, -1 },
+};
+
+/* layout(s) */
+static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
+static const int nmaster = 1; /* number of clients in master area */
+static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
+
+static const Layout layouts[] = {
+ /* symbol arrange function */
+ { "[]=", tile }, /* first entry is default */
+ { "><>", NULL }, /* no layout function means floating behavior */
+ { "[M]", monocle },
+};
+
+/* key definitions */
+#define MODKEY Mod4Mask
+#define TAGKEYS(KEY,TAG) \
+ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
+ { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
+ { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
+ { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
+
+/* helper for spawning shell commands in the pre dwm-5.0 fashion */
+#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
+
+/* commands */
+static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
+static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
+static const char *termcmd[] = { "st", NULL };
+static const char *mutecmd[] = {"amixer","-c","1","-q","sset","Master","toggle",NULL};
+static const char *lowervolcmd[] = {"amixer","-c","1","-q","sset","Master","1%-",NULL};
+static const char *raisevolcmd[] = {"amixer","-c","1","-q","sset","Master","1%+",NULL};
+
+static Key keys[] = {
+ /* modifier key function argument */
+ { MODKEY, XK_p, spawn, {.v = dmenucmd } },
+ { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
+ { MODKEY, XK_b, togglebar, {0} },
+ { MODKEY, XK_j, focusstack, {.i = +1 } },
+ { MODKEY, XK_k, focusstack, {.i = -1 } },
+ { MODKEY, XK_i, incnmaster, {.i = +1 } },
+ { MODKEY, XK_d, incnmaster, {.i = -1 } },
+ { MODKEY, XK_h, setmfact, {.f = -0.05} },
+ { MODKEY, XK_l, setmfact, {.f = +0.05} },
+ { MODKEY, XK_Return, zoom, {0} },
+ { MODKEY, XK_Tab, view, {0} },
+ { MODKEY|ShiftMask, XK_c, killclient, {0} },
+ { MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
+ { MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
+ { MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
+ { MODKEY, XK_space, setlayout, {0} },
+ { MODKEY|ShiftMask, XK_space, togglefloating, {0} },
+ { MODKEY, XK_0, view, {.ui = ~0 } },
+ { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
+ { MODKEY, XK_comma, focusmon, {.i = -1 } },
+ { MODKEY, XK_period, focusmon, {.i = +1 } },
+ { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
+ { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
+ TAGKEYS( XK_parenleft, 0)
+ TAGKEYS( XK_parenright, 1)
+ TAGKEYS( XK_braceright, 2)
+ TAGKEYS( XK_plus, 3)
+ TAGKEYS( XK_braceleft, 4)
+ TAGKEYS( XK_bracketright, 5)
+ TAGKEYS( XK_bracketleft, 6)
+ TAGKEYS( XK_exclam, 7)
+ TAGKEYS( XK_equal, 8)
+ { MODKEY|ShiftMask, XK_q, quit, {0} },
+ { 0, 0x1008ff12,spawn, {.v = mutecmd } },
+ { 0, 0x1008ff11,spawn, {.v = lowervolcmd } },
+ { 0, 0x1008ff13,spawn, {.v = raisevolcmd } },
+};
+
+/* button definitions */
+/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
+static Button buttons[] = {
+ /* click event mask button function argument */
+ { ClkLtSymbol, 0, Button1, setlayout, {0} },
+ { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
+ { ClkWinTitle, 0, Button2, zoom, {0} },
+ { ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
+ { ClkClientWin, MODKEY, Button1, movemouse, {0} },
+ { ClkClientWin, MODKEY, Button2, togglefloating, {0} },
+ { ClkClientWin, MODKEY, Button3, resizemouse, {0} },
+ { ClkTagBar, 0, Button1, view, {0} },
+ { ClkTagBar, 0, Button3, toggleview, {0} },
+ { ClkTagBar, MODKEY, Button1, tag, {0} },
+ { ClkTagBar, MODKEY, Button3, toggletag, {0} },
+};
+
diff --git a/srcpkgs/dwm/files/dwm.desktop b/srcpkgs/dwm/files/dwm.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Dwm
+Comment=Dynamic window manager
+Exec=dwm
+Icon=dwm
+Type=XSession
diff --git a/srcpkgs/dwm/patches/dwm-systray-6.2.diff b/srcpkgs/dwm/patches/dwm-systray-6.2.diff
@@ -0,0 +1,746 @@
+From 4001ccae7b1a41bdcb247b0cf095a51af7b68c28 Mon Sep 17 00:00:00 2001
+From: Igor Gevka <igor.gevka@gmail.com>
+Date: Sun, 16 Feb 2020 15:03:10 -0800
+Subject: [PATCH] [PATCH] Implements a system tray for dwm.
+
+Original author: Jan Christoph Ebersbach <jceb@e-jc.de>, inspired by http://code.google.com/p/dwm-plus
+URL: http://dwm.suckless.org/patches/systray
+dwm 6.2 port by Igor Gevka <igor.gevka@gmail.com>
+---
+ config.def.h | 4 +
+ dwm.c | 404 +++++++++++++++++++++++++++++++++++++++++++++++----
+ 2 files changed, 382 insertions(+), 26 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index 1c0b587..2d824d1 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -3,6 +3,10 @@
+ /* appearance */
+ static const unsigned int borderpx = 1; /* border pixel of windows */
+ static const unsigned int snap = 32; /* snap pixel */
++static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
++static const unsigned int systrayspacing = 2; /* systray spacing */
++static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
++static const int showsystray = 1; /* 0 means no systray */
+ static const int showbar = 1; /* 0 means no bar */
+ static const int topbar = 1; /* 0 means bottom bar */
+ static const char *fonts[] = { "monospace:size=10" };
+diff --git a/dwm.c b/dwm.c
+index 4465af1..3e361fa 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -57,12 +57,30 @@
+ #define TAGMASK ((1 << LENGTH(tags)) - 1)
+ #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
+
++#define SYSTEM_TRAY_REQUEST_DOCK 0
++
++/* XEMBED messages */
++#define XEMBED_EMBEDDED_NOTIFY 0
++#define XEMBED_WINDOW_ACTIVATE 1
++#define XEMBED_FOCUS_IN 4
++#define XEMBED_MODALITY_ON 10
++
++#define XEMBED_MAPPED (1 << 0)
++#define XEMBED_WINDOW_ACTIVATE 1
++#define XEMBED_WINDOW_DEACTIVATE 2
++
++#define VERSION_MAJOR 0
++#define VERSION_MINOR 0
++#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
++
+ /* enums */
+ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
+ enum { SchemeNorm, SchemeSel }; /* color schemes */
+ enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
++ NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz,
+ NetWMFullscreen, NetActiveWindow, NetWMWindowType,
+ NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
++enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
+ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
+ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
+ ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
+@@ -141,6 +159,12 @@ typedef struct {
+ int monitor;
+ } Rule;
+
++typedef struct Systray Systray;
++struct Systray {
++ Window win;
++ Client *icons;
++};
++
+ /* function declarations */
+ static void applyrules(Client *c);
+ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
+@@ -169,8 +193,10 @@ static void focus(Client *c);
+ static void focusin(XEvent *e);
+ static void focusmon(const Arg *arg);
+ static void focusstack(const Arg *arg);
++static Atom getatomprop(Client *c, Atom prop);
+ static int getrootptr(int *x, int *y);
+ static long getstate(Window w);
++static unsigned int getsystraywidth();
+ static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
+ static void grabbuttons(Client *c, int focused);
+ static void grabkeys(void);
+@@ -188,13 +214,16 @@ static void pop(Client *);
+ static void propertynotify(XEvent *e);
+ static void quit(const Arg *arg);
+ static Monitor *recttomon(int x, int y, int w, int h);
++static void removesystrayicon(Client *i);
+ static void resize(Client *c, int x, int y, int w, int h, int interact);
++static void resizebarwin(Monitor *m);
+ static void resizeclient(Client *c, int x, int y, int w, int h);
+ static void resizemouse(const Arg *arg);
++static void resizerequest(XEvent *e);
+ static void restack(Monitor *m);
+ static void run(void);
+ static void scan(void);
+-static int sendevent(Client *c, Atom proto);
++static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
+ static void sendmon(Client *c, Monitor *m);
+ static void setclientstate(Client *c, long state);
+ static void setfocus(Client *c);
+@@ -206,6 +235,7 @@ static void seturgent(Client *c, int urg);
+ static void showhide(Client *c);
+ static void sigchld(int unused);
+ static void spawn(const Arg *arg);
++static Monitor *systraytomon(Monitor *m);
+ static void tag(const Arg *arg);
+ static void tagmon(const Arg *arg);
+ static void tile(Monitor *);
+@@ -223,18 +253,23 @@ static int updategeom(void);
+ static void updatenumlockmask(void);
+ static void updatesizehints(Client *c);
+ static void updatestatus(void);
++static void updatesystray(void);
++static void updatesystrayicongeom(Client *i, int w, int h);
++static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
+ static void updatetitle(Client *c);
+ static void updatewindowtype(Client *c);
+ static void updatewmhints(Client *c);
+ static void view(const Arg *arg);
+ static Client *wintoclient(Window w);
+ static Monitor *wintomon(Window w);
++static Client *wintosystrayicon(Window w);
+ static int xerror(Display *dpy, XErrorEvent *ee);
+ static int xerrordummy(Display *dpy, XErrorEvent *ee);
+ static int xerrorstart(Display *dpy, XErrorEvent *ee);
+ static void zoom(const Arg *arg);
+
+ /* variables */
++static Systray *systray = NULL;
+ static const char broken[] = "broken";
+ static char stext[256];
+ static int screen;
+@@ -257,9 +292,10 @@ static void (*handler[LASTEvent]) (XEvent *) = {
+ [MapRequest] = maprequest,
+ [MotionNotify] = motionnotify,
+ [PropertyNotify] = propertynotify,
++ [ResizeRequest] = resizerequest,
+ [UnmapNotify] = unmapnotify
+ };
+-static Atom wmatom[WMLast], netatom[NetLast];
++static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
+ static int running = 1;
+ static Cur *cursor[CurLast];
+ static Clr **scheme;
+@@ -439,7 +475,7 @@ buttonpress(XEvent *e)
+ arg.ui = 1 << i;
+ } else if (ev->x < x + blw)
+ click = ClkLtSymbol;
+- else if (ev->x > selmon->ww - TEXTW(stext))
++ else if (ev->x > selmon->ww - TEXTW(stext) - getsystraywidth())
+ click = ClkStatusText;
+ else
+ click = ClkWinTitle;
+@@ -482,6 +518,11 @@ cleanup(void)
+ XUngrabKey(dpy, AnyKey, AnyModifier, root);
+ while (mons)
+ cleanupmon(mons);
++ if (showsystray) {
++ XUnmapWindow(dpy, systray->win);
++ XDestroyWindow(dpy, systray->win);
++ free(systray);
++ }
+ for (i = 0; i < CurLast; i++)
+ drw_cur_free(drw, cursor[i]);
+ for (i = 0; i < LENGTH(colors); i++)
+@@ -512,9 +553,57 @@ cleanupmon(Monitor *mon)
+ void
+ clientmessage(XEvent *e)
+ {
++ XWindowAttributes wa;
++ XSetWindowAttributes swa;
+ XClientMessageEvent *cme = &e->xclient;
+ Client *c = wintoclient(cme->window);
+
++ if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) {
++ /* add systray icons */
++ if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
++ if (!(c = (Client *)calloc(1, sizeof(Client))))
++ die("fatal: could not malloc() %u bytes\n", sizeof(Client));
++ if (!(c->win = cme->data.l[2])) {
++ free(c);
++ return;
++ }
++ c->mon = selmon;
++ c->next = systray->icons;
++ systray->icons = c;
++ if (!XGetWindowAttributes(dpy, c->win, &wa)) {
++ /* use sane defaults */
++ wa.width = bh;
++ wa.height = bh;
++ wa.border_width = 0;
++ }
++ c->x = c->oldx = c->y = c->oldy = 0;
++ c->w = c->oldw = wa.width;
++ c->h = c->oldh = wa.height;
++ c->oldbw = wa.border_width;
++ c->bw = 0;
++ c->isfloating = True;
++ /* reuse tags field as mapped status */
++ c->tags = 1;
++ updatesizehints(c);
++ updatesystrayicongeom(c, wa.width, wa.height);
++ XAddToSaveSet(dpy, c->win);
++ XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
++ XReparentWindow(dpy, c->win, systray->win, 0, 0);
++ /* use parents background color */
++ swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
++ XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa);
++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
++ /* FIXME not sure if I have to send these events, too */
++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
++ XSync(dpy, False);
++ resizebarwin(selmon);
++ updatesystray();
++ setclientstate(c, NormalState);
++ }
++ return;
++ }
+ if (!c)
+ return;
+ if (cme->message_type == netatom[NetWMState]) {
+@@ -567,7 +656,7 @@ configurenotify(XEvent *e)
+ for (c = m->clients; c; c = c->next)
+ if (c->isfullscreen)
+ resizeclient(c, m->mx, m->my, m->mw, m->mh);
+- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
++ resizebarwin(m);
+ }
+ focus(NULL);
+ arrange(NULL);
+@@ -652,6 +741,11 @@ destroynotify(XEvent *e)
+
+ if ((c = wintoclient(ev->window)))
+ unmanage(c, 1);
++ else if ((c = wintosystrayicon(ev->window))) {
++ removesystrayicon(c);
++ resizebarwin(selmon);
++ updatesystray();
++ }
+ }
+
+ void
+@@ -695,19 +789,23 @@ dirtomon(int dir)
+ void
+ drawbar(Monitor *m)
+ {
+- int x, w, sw = 0;
++ int x, w, sw = 0, stw = 0;
+ int boxs = drw->fonts->h / 9;
+ int boxw = drw->fonts->h / 6 + 2;
+ unsigned int i, occ = 0, urg = 0;
+ Client *c;
+
++ if(showsystray && m == systraytomon(m))
++ stw = getsystraywidth();
++
+ /* draw status first so it can be overdrawn by tags later */
+ if (m == selmon) { /* status is only drawn on selected monitor */
+ drw_setscheme(drw, scheme[SchemeNorm]);
+- sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
+- drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0);
++ sw = TEXTW(stext) - lrpad / 2 + 2; /* 2px right padding */
++ drw_text(drw, m->ww - sw - stw, 0, sw, bh, lrpad / 2 - 2, stext, 0);
+ }
+
++ resizebarwin(m);
+ for (c = m->clients; c; c = c->next) {
+ occ |= c->tags;
+ if (c->isurgent)
+@@ -728,7 +826,7 @@ drawbar(Monitor *m)
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
+
+- if ((w = m->ww - sw - x) > bh) {
++ if ((w = m->ww - sw - stw - x) > bh) {
+ if (m->sel) {
+ drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
+ drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
+@@ -739,7 +837,7 @@ drawbar(Monitor *m)
+ drw_rect(drw, x, 0, w, bh, 1, 1);
+ }
+ }
+- drw_map(drw, m->barwin, 0, 0, m->ww, bh);
++ drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh);
+ }
+
+ void
+@@ -776,8 +874,11 @@ expose(XEvent *e)
+ Monitor *m;
+ XExposeEvent *ev = &e->xexpose;
+
+- if (ev->count == 0 && (m = wintomon(ev->window)))
++ if (ev->count == 0 && (m = wintomon(ev->window))) {
+ drawbar(m);
++ if (m == selmon)
++ updatesystray();
++ }
+ }
+
+ void
+@@ -862,10 +963,17 @@ getatomprop(Client *c, Atom prop)
+ unsigned long dl;
+ unsigned char *p = NULL;
+ Atom da, atom = None;
++ /* FIXME getatomprop should return the number of items and a pointer to
++ * the stored data instead of this workaround */
++ Atom req = XA_ATOM;
++ if (prop == xatom[XembedInfo])
++ req = xatom[XembedInfo];
+
+- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
++ if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
+ &da, &di, &dl, &dl, &p) == Success && p) {
+ atom = *(Atom *)p;
++ if (da == xatom[XembedInfo] && dl == 2)
++ atom = ((Atom *)p)[1];
+ XFree(p);
+ }
+ return atom;
+@@ -899,6 +1007,16 @@ getstate(Window w)
+ return result;
+ }
+
++unsigned int
++getsystraywidth()
++{
++ unsigned int w = 0;
++ Client *i;
++ if(showsystray)
++ for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ;
++ return w ? w + systrayspacing : 1;
++}
++
+ int
+ gettextprop(Window w, Atom atom, char *text, unsigned int size)
+ {
+@@ -1003,7 +1121,7 @@ killclient(const Arg *arg)
+ {
+ if (!selmon->sel)
+ return;
+- if (!sendevent(selmon->sel, wmatom[WMDelete])) {
++ if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) {
+ XGrabServer(dpy);
+ XSetErrorHandler(xerrordummy);
+ XSetCloseDownMode(dpy, DestroyAll);
+@@ -1091,6 +1209,12 @@ maprequest(XEvent *e)
+ {
+ static XWindowAttributes wa;
+ XMapRequestEvent *ev = &e->xmaprequest;
++ Client *i;
++ if ((i = wintosystrayicon(ev->window))) {
++ sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION);
++ resizebarwin(selmon);
++ updatesystray();
++ }
+
+ if (!XGetWindowAttributes(dpy, ev->window, &wa))
+ return;
+@@ -1215,6 +1339,16 @@ propertynotify(XEvent *e)
+ Window trans;
+ XPropertyEvent *ev = &e->xproperty;
+
++ if ((c = wintosystrayicon(ev->window))) {
++ if (ev->atom == XA_WM_NORMAL_HINTS) {
++ updatesizehints(c);
++ updatesystrayicongeom(c, c->w, c->h);
++ }
++ else
++ updatesystrayiconstate(c, ev);
++ resizebarwin(selmon);
++ updatesystray();
++ }
+ if ((ev->window == root) && (ev->atom == XA_WM_NAME))
+ updatestatus();
+ else if (ev->state == PropertyDelete)
+@@ -1265,6 +1399,20 @@ recttomon(int x, int y, int w, int h)
+ return r;
+ }
+
++void
++removesystrayicon(Client *i)
++{
++ Client **ii;
++
++ if (!showsystray || !i)
++ return;
++ for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
++ if (ii)
++ *ii = i->next;
++ free(i);
++}
++
++
+ void
+ resize(Client *c, int x, int y, int w, int h, int interact)
+ {
+@@ -1272,6 +1420,14 @@ resize(Client *c, int x, int y, int w, int h, int interact)
+ resizeclient(c, x, y, w, h);
+ }
+
++void
++resizebarwin(Monitor *m) {
++ unsigned int w = m->ww;
++ if (showsystray && m == systraytomon(m))
++ w -= getsystraywidth();
++ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
++}
++
+ void
+ resizeclient(Client *c, int x, int y, int w, int h)
+ {
+@@ -1344,6 +1500,19 @@ resizemouse(const Arg *arg)
+ }
+ }
+
++void
++resizerequest(XEvent *e)
++{
++ XResizeRequestEvent *ev = &e->xresizerequest;
++ Client *i;
++
++ if ((i = wintosystrayicon(ev->window))) {
++ updatesystrayicongeom(i, ev->width, ev->height);
++ resizebarwin(selmon);
++ updatesystray();
++ }
++}
++
+ void
+ restack(Monitor *m)
+ {
+@@ -1433,26 +1602,36 @@ setclientstate(Client *c, long state)
+ }
+
+ int
+-sendevent(Client *c, Atom proto)
++sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4)
+ {
+ int n;
+- Atom *protocols;
++ Atom *protocols, mt;
+ int exists = 0;
+ XEvent ev;
+
+- if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
+- while (!exists && n--)
+- exists = protocols[n] == proto;
+- XFree(protocols);
++ if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
++ mt = wmatom[WMProtocols];
++ if (XGetWMProtocols(dpy, w, &protocols, &n)) {
++ while (!exists && n--)
++ exists = protocols[n] == proto;
++ XFree(protocols);
++ }
++ }
++ else {
++ exists = True;
++ mt = proto;
+ }
+ if (exists) {
+ ev.type = ClientMessage;
+- ev.xclient.window = c->win;
+- ev.xclient.message_type = wmatom[WMProtocols];
++ ev.xclient.window = w;
++ ev.xclient.message_type = mt;
+ ev.xclient.format = 32;
+- ev.xclient.data.l[0] = proto;
+- ev.xclient.data.l[1] = CurrentTime;
+- XSendEvent(dpy, c->win, False, NoEventMask, &ev);
++ ev.xclient.data.l[0] = d0;
++ ev.xclient.data.l[1] = d1;
++ ev.xclient.data.l[2] = d2;
++ ev.xclient.data.l[3] = d3;
++ ev.xclient.data.l[4] = d4;
++ XSendEvent(dpy, w, False, mask, &ev);
+ }
+ return exists;
+ }
+@@ -1466,7 +1645,7 @@ setfocus(Client *c)
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *) &(c->win), 1);
+ }
+- sendevent(c, wmatom[WMTakeFocus]);
++ sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
+ }
+
+ void
+@@ -1555,6 +1734,10 @@ setup(void)
+ wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
+ netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
+ netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
++ netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
++ netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
++ netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
++ netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False);
+ netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
+ netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
+ netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
+@@ -1562,6 +1745,9 @@ setup(void)
+ netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
+ netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
+ netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
++ xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
++ xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
++ xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
+ /* init cursors */
+ cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
+ cursor[CurResize] = drw_cur_create(drw, XC_sizing);
+@@ -1570,6 +1756,8 @@ setup(void)
+ scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
+ for (i = 0; i < LENGTH(colors); i++)
+ scheme[i] = drw_scm_create(drw, colors[i], 3);
++ /* init system tray */
++ updatesystray();
+ /* init bars */
+ updatebars();
+ updatestatus();
+@@ -1701,7 +1889,18 @@ togglebar(const Arg *arg)
+ {
+ selmon->showbar = !selmon->showbar;
+ updatebarpos(selmon);
+- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
++ resizebarwin(selmon);
++ if (showsystray) {
++ XWindowChanges wc;
++ if (!selmon->showbar)
++ wc.y = -bh;
++ else if (selmon->showbar) {
++ wc.y = 0;
++ if (!selmon->topbar)
++ wc.y = selmon->mh - bh;
++ }
++ XConfigureWindow(dpy, systray->win, CWY, &wc);
++ }
+ arrange(selmon);
+ }
+
+@@ -1796,11 +1995,18 @@ unmapnotify(XEvent *e)
+ else
+ unmanage(c, 0);
+ }
++ else if ((c = wintosystrayicon(ev->window))) {
++ /* KLUDGE! sometimes icons occasionally unmap their windows, but do
++ * _not_ destroy them. We map those windows back */
++ XMapRaised(dpy, c->win);
++ updatesystray();
++ }
+ }
+
+ void
+ updatebars(void)
+ {
++ unsigned int w;
+ Monitor *m;
+ XSetWindowAttributes wa = {
+ .override_redirect = True,
+@@ -1811,10 +2017,15 @@ updatebars(void)
+ for (m = mons; m; m = m->next) {
+ if (m->barwin)
+ continue;
+- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
++ w = m->ww;
++ if (showsystray && m == systraytomon(m))
++ w -= getsystraywidth();
++ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen),
+ CopyFromParent, DefaultVisual(dpy, screen),
+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
+ XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor);
++ if (showsystray && m == systraytomon(m))
++ XMapRaised(dpy, systray->win);
+ XMapRaised(dpy, m->barwin);
+ XSetClassHint(dpy, m->barwin, &ch);
+ }
+@@ -1990,6 +2201,121 @@ updatestatus(void)
+ if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
+ strcpy(stext, "dwm-"VERSION);
+ drawbar(selmon);
++ updatesystray();
++}
++
++void
++updatesystrayicongeom(Client *i, int w, int h)
++{
++ if (i) {
++ i->h = bh;
++ if (w == h)
++ i->w = bh;
++ else if (h == bh)
++ i->w = w;
++ else
++ i->w = (int) ((float)bh * ((float)w / (float)h));
++ applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
++ /* force icons into the systray dimensions if they don't want to */
++ if (i->h > bh) {
++ if (i->w == i->h)
++ i->w = bh;
++ else
++ i->w = (int) ((float)bh * ((float)i->w / (float)i->h));
++ i->h = bh;
++ }
++ }
++}
++
++void
++updatesystrayiconstate(Client *i, XPropertyEvent *ev)
++{
++ long flags;
++ int code = 0;
++
++ if (!showsystray || !i || ev->atom != xatom[XembedInfo] ||
++ !(flags = getatomprop(i, xatom[XembedInfo])))
++ return;
++
++ if (flags & XEMBED_MAPPED && !i->tags) {
++ i->tags = 1;
++ code = XEMBED_WINDOW_ACTIVATE;
++ XMapRaised(dpy, i->win);
++ setclientstate(i, NormalState);
++ }
++ else if (!(flags & XEMBED_MAPPED) && i->tags) {
++ i->tags = 0;
++ code = XEMBED_WINDOW_DEACTIVATE;
++ XUnmapWindow(dpy, i->win);
++ setclientstate(i, WithdrawnState);
++ }
++ else
++ return;
++ sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
++ systray->win, XEMBED_EMBEDDED_VERSION);
++}
++
++void
++updatesystray(void)
++{
++ XSetWindowAttributes wa;
++ XWindowChanges wc;
++ Client *i;
++ Monitor *m = systraytomon(NULL);
++ unsigned int x = m->mx + m->mw;
++ unsigned int w = 1;
++
++ if (!showsystray)
++ return;
++ if (!systray) {
++ /* init systray */
++ if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
++ die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
++ systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel][ColBg].pixel);
++ wa.event_mask = ButtonPressMask | ExposureMask;
++ wa.override_redirect = True;
++ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
++ XSelectInput(dpy, systray->win, SubstructureNotifyMask);
++ XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
++ PropModeReplace, (unsigned char *)&netatom[NetSystemTrayOrientationHorz], 1);
++ XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa);
++ XMapRaised(dpy, systray->win);
++ XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
++ if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
++ sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
++ XSync(dpy, False);
++ }
++ else {
++ fprintf(stderr, "dwm: unable to obtain system tray.\n");
++ free(systray);
++ systray = NULL;
++ return;
++ }
++ }
++ for (w = 0, i = systray->icons; i; i = i->next) {
++ /* make sure the background color stays the same */
++ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
++ XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
++ XMapRaised(dpy, i->win);
++ w += systrayspacing;
++ i->x = w;
++ XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
++ w += i->w;
++ if (i->mon != m)
++ i->mon = m;
++ }
++ w = w ? w + systrayspacing : 1;
++ x -= w;
++ XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh);
++ wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh;
++ wc.stack_mode = Above; wc.sibling = m->barwin;
++ XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc);
++ XMapWindow(dpy, systray->win);
++ XMapSubwindows(dpy, systray->win);
++ /* redraw background */
++ XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel);
++ XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh);
++ XSync(dpy, False);
+ }
+
+ void
+@@ -2057,6 +2383,16 @@ wintoclient(Window w)
+ return NULL;
+ }
+
++Client *
++wintosystrayicon(Window w) {
++ Client *i = NULL;
++
++ if (!showsystray || !w)
++ return i;
++ for (i = systray->icons; i && i->win != w; i = i->next) ;
++ return i;
++}
++
+ Monitor *
+ wintomon(Window w)
+ {
+@@ -2110,6 +2446,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee)
+ return -1;
+ }
+
++Monitor *
++systraytomon(Monitor *m) {
++ Monitor *t;
++ int i, n;
++ if(!systraypinning) {
++ if(!m)
++ return selmon;
++ return m == selmon ? m : NULL;
++ }
++ for(n = 1, t = mons; t && t->next; n++, t = t->next) ;
++ for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ;
++ if(systraypinningfailfirst && n < systraypinning)
++ return mons;
++ return t;
++}
++
+ void
+ zoom(const Arg *arg)
+ {
+--
+2.17.1
+
diff --git a/srcpkgs/dwm/template b/srcpkgs/dwm/template
@@ -0,0 +1,26 @@
+# Template file for 'dwm'
+pkgname=dwm
+version=6.2
+revision=1
+patch_args="-Np1"
+makedepends="libXinerama-devel libXft-devel freetype-devel"
+short_desc="Dynamic window manager for X"
+maintainer="Nathan Owens <ndowens04@gmail.com>"
+license="MIT"
+homepage="http://dwm.suckless.org"
+distfiles="https://dl.suckless.org/dwm/dwm-${version}.tar.gz"
+checksum=97902e2e007aaeaa3c6e3bed1f81785b817b7413947f1db1d3b62b8da4cd110e
+
+do_build() {
+ [ -e ${FILESDIR}/config.h ] && cp ${FILESDIR}/config.h config.h
+ sed -i "/CFLAGS/s|\${CPPFLAGS}|& $CFLAGS|g" config.mk
+ sed -i "/LDFLAGS/s|\-s|$LDFLAGS|g" config.mk
+ make CC=$CC INCS="-I. -I${XBPS_CROSS_BASE}/usr/include/freetype2" LIBS="-lX11 -lXinerama -lXft -lfontconfig"
+}
+
+do_install() {
+ make PREFIX=/usr DESTDIR=$DESTDIR install
+ vinstall README 644 usr/share/doc/$pkgname
+ vinstall ${FILESDIR}/dwm.desktop 644 usr/share/xsessions
+ vlicense LICENSE
+}