Compare commits
40 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
8e4f659772 | ||
|
99b45ee0d4 | ||
|
3f3811e80d | ||
|
fd9e12e7c5 | ||
|
4e8381c135 | ||
|
fa54da1744 | ||
|
6024c104c1 | ||
|
f0dd75e8c5 | ||
|
95131de64f | ||
|
e81decd079 | ||
|
ef6b5ee95a | ||
|
edb4762434 | ||
|
14dc678a7f | ||
|
9b7ba80925 | ||
|
833edb4d88 | ||
|
ba9a2ef74b | ||
|
215f92fabb | ||
|
0339db5604 | ||
|
ffcb42df85 | ||
|
84b5615062 | ||
|
3935b19814 | ||
|
9f219c6a08 | ||
|
904554033c | ||
|
0b87eae829 | ||
|
be9497bd75 | ||
|
9253bcdb53 | ||
|
1bdfed1d0d | ||
|
3eb84701d7 | ||
|
edc446997e | ||
|
873287e2ec | ||
|
5dee96918f | ||
|
45277ea35b | ||
|
cebe408f75 | ||
|
1950543da6 | ||
|
1dc6430ff6 | ||
|
586865823b | ||
|
7d0f7c5f99 | ||
|
92b735ffef | ||
|
a40a0f0bd6 | ||
|
c8f5653ecd |
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# DWM Files
|
||||
*.o
|
||||
*.orig
|
||||
dwm
|
||||
dwm-msg
|
||||
config.h
|
66
IPCClient.c
Normal file
66
IPCClient.c
Normal file
@ -0,0 +1,66 @@
|
||||
#include "IPCClient.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
IPCClient *
|
||||
ipc_client_new(int fd)
|
||||
{
|
||||
IPCClient *c = (IPCClient *)malloc(sizeof(IPCClient));
|
||||
|
||||
if (c == NULL) return NULL;
|
||||
|
||||
// Initialize struct
|
||||
memset(&c->event, 0, sizeof(struct epoll_event));
|
||||
|
||||
c->buffer_size = 0;
|
||||
c->buffer = NULL;
|
||||
c->fd = fd;
|
||||
c->event.data.fd = fd;
|
||||
c->next = NULL;
|
||||
c->prev = NULL;
|
||||
c->subscriptions = 0;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
ipc_list_add_client(IPCClientList *list, IPCClient *nc)
|
||||
{
|
||||
DEBUG("Adding client with fd %d to list\n", nc->fd);
|
||||
|
||||
if (*list == NULL) {
|
||||
// List is empty, point list at first client
|
||||
*list = nc;
|
||||
} else {
|
||||
IPCClient *c;
|
||||
// Go to last client in list
|
||||
for (c = *list; c && c->next; c = c->next)
|
||||
;
|
||||
c->next = nc;
|
||||
nc->prev = c;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ipc_list_remove_client(IPCClientList *list, IPCClient *c)
|
||||
{
|
||||
IPCClient *cprev = c->prev;
|
||||
IPCClient *cnext = c->next;
|
||||
|
||||
if (cprev != NULL) cprev->next = c->next;
|
||||
if (cnext != NULL) cnext->prev = c->prev;
|
||||
if (c == *list) *list = c->next;
|
||||
}
|
||||
|
||||
IPCClient *
|
||||
ipc_list_get_client(IPCClientList list, int fd)
|
||||
{
|
||||
for (IPCClient *c = list; c; c = c->next) {
|
||||
if (c->fd == fd) return c;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
61
IPCClient.h
Normal file
61
IPCClient.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef IPC_CLIENT_H_
|
||||
#define IPC_CLIENT_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
typedef struct IPCClient IPCClient;
|
||||
/**
|
||||
* This structure contains the details of an IPC Client and pointers for a
|
||||
* linked list
|
||||
*/
|
||||
struct IPCClient {
|
||||
int fd;
|
||||
int subscriptions;
|
||||
|
||||
char *buffer;
|
||||
uint32_t buffer_size;
|
||||
|
||||
struct epoll_event event;
|
||||
IPCClient *next;
|
||||
IPCClient *prev;
|
||||
};
|
||||
|
||||
typedef IPCClient *IPCClientList;
|
||||
|
||||
/**
|
||||
* Allocate memory for new IPCClient with the specified file descriptor and
|
||||
* initialize struct.
|
||||
*
|
||||
* @param fd File descriptor of IPC client
|
||||
*
|
||||
* @return Address to allocated IPCClient struct
|
||||
*/
|
||||
IPCClient *ipc_client_new(int fd);
|
||||
|
||||
/**
|
||||
* Add an IPC Client to the specified list
|
||||
*
|
||||
* @param list Address of the list to add the client to
|
||||
* @param nc Address of the IPCClient
|
||||
*/
|
||||
void ipc_list_add_client(IPCClientList *list, IPCClient *nc);
|
||||
|
||||
/**
|
||||
* Remove an IPCClient from the specified list
|
||||
*
|
||||
* @param list Address of the list to remove the client from
|
||||
* @param c Address of the IPCClient
|
||||
*/
|
||||
void ipc_list_remove_client(IPCClientList *list, IPCClient *c);
|
||||
|
||||
/**
|
||||
* Get an IPCClient from the specified IPCClient list
|
||||
*
|
||||
* @param list List to remove the client from
|
||||
* @param fd File descriptor of the IPCClient
|
||||
*/
|
||||
IPCClient *ipc_list_get_client(IPCClientList list, int fd);
|
||||
|
||||
#endif // IPC_CLIENT_H_
|
13
Makefile
13
Makefile
@ -6,7 +6,7 @@ include config.mk
|
||||
SRC = drw.c dwm.c util.c
|
||||
OBJ = ${SRC:.c=.o}
|
||||
|
||||
all: options dwm
|
||||
all: options dwm dwm-msg
|
||||
|
||||
options:
|
||||
@echo dwm build options:
|
||||
@ -25,8 +25,11 @@ config.h:
|
||||
dwm: ${OBJ}
|
||||
${CC} -o $@ ${OBJ} ${LDFLAGS}
|
||||
|
||||
dwm-msg: dwm-msg.o
|
||||
${CC} -o $@ $< ${LDFLAGS}
|
||||
|
||||
clean:
|
||||
rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz
|
||||
rm -f dwm dwm-msg ${OBJ} dwm-${VERSION}.tar.gz config.h
|
||||
|
||||
dist: clean
|
||||
mkdir -p dwm-${VERSION}
|
||||
@ -38,14 +41,16 @@ dist: clean
|
||||
|
||||
install: all
|
||||
mkdir -p ${DESTDIR}${PREFIX}/bin
|
||||
cp -f dwm ${DESTDIR}${PREFIX}/bin
|
||||
cp -f dwm dwmc dwm-msg ${DESTDIR}${PREFIX}/bin
|
||||
chmod 755 ${DESTDIR}${PREFIX}/bin/dwm
|
||||
chmod 755 ${DESTDIR}${PREFIX}/bin/dwmc
|
||||
chmod 755 ${DESTDIR}${PREFIX}/bin/dwm-msg
|
||||
mkdir -p ${DESTDIR}${MANPREFIX}/man1
|
||||
sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1
|
||||
chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1
|
||||
|
||||
uninstall:
|
||||
rm -f ${DESTDIR}${PREFIX}/bin/dwm\
|
||||
rm -f ${DESTDIR}${PREFIX}/bin/dwm*\
|
||||
${DESTDIR}${MANPREFIX}/man1/dwm.1
|
||||
|
||||
.PHONY: all options clean dist install uninstall
|
||||
|
48
README
48
README
@ -1,48 +0,0 @@
|
||||
dwm - dynamic window manager
|
||||
============================
|
||||
dwm is an extremely fast, small, and dynamic window manager for X.
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
In order to build dwm you need the Xlib header files.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
Edit config.mk to match your local setup (dwm is installed into
|
||||
the /usr/local namespace by default).
|
||||
|
||||
Afterwards enter the following command to build and install dwm (if
|
||||
necessary as root):
|
||||
|
||||
make clean install
|
||||
|
||||
|
||||
Running dwm
|
||||
-----------
|
||||
Add the following line to your .xinitrc to start dwm using startx:
|
||||
|
||||
exec dwm
|
||||
|
||||
In order to connect dwm to a specific display, make sure that
|
||||
the DISPLAY environment variable is set correctly, e.g.:
|
||||
|
||||
DISPLAY=foo.bar:1 exec dwm
|
||||
|
||||
(This will start dwm on display :1 of the host foo.bar.)
|
||||
|
||||
In order to display status info in the bar, you can do something
|
||||
like this in your .xinitrc:
|
||||
|
||||
while xsetroot -name "`date` `uptime | sed 's/.*,//'`"
|
||||
do
|
||||
sleep 1
|
||||
done &
|
||||
exec dwm
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
The configuration of dwm is done by creating a custom config.h
|
||||
and (re)compiling the source code.
|
86
README.md
Normal file
86
README.md
Normal file
@ -0,0 +1,86 @@
|
||||
# dwm - dynamic window manager
|
||||
|
||||
Sravan's custom build of dwm. Original dwm build by suckless team found here: [https://dwm.suckless.org/](https://dwm.suckless.org/)
|
||||
Choice of patches heavily inspired by [Palmdrop's custom build of dwm](https://github.com/palmdrop/dwm).
|
||||
|
||||
## Requirements
|
||||
|
||||
In order to build dwm you need the Xlib header files.
|
||||
|
||||
## Installation
|
||||
|
||||
Edit [config.mk](config.mk) to match your local setup (dwm is installed into
|
||||
the /usr/local namespace by default).
|
||||
|
||||
Afterwards enter the following command to build and install dwm (if
|
||||
necessary as root):
|
||||
|
||||
```
|
||||
make clean install
|
||||
```
|
||||
|
||||
## Running dwm
|
||||
|
||||
Add the following line to your .xinitrc to start dwm using startx:
|
||||
|
||||
```
|
||||
exec dwm
|
||||
```
|
||||
|
||||
In order to connect dwm to a specific display, make sure that
|
||||
the DISPLAY environment variable is set correctly, e.g.:
|
||||
|
||||
```
|
||||
DISPLAY=foo.bar:1 exec dwm
|
||||
```
|
||||
|
||||
(This will start dwm on display :1 of the host foo.bar.)
|
||||
|
||||
In order to display status info in the bar, you can do something
|
||||
like this in your .xinitrc:
|
||||
|
||||
```
|
||||
while xsetroot -name "`date` `uptime | sed 's/.*,//'`"
|
||||
do
|
||||
sleep 1
|
||||
done &
|
||||
exec dwm
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
The configuration of dwm is done by creating a custom config.h
|
||||
and (re)compiling the source code.
|
||||
|
||||
## Patches
|
||||
|
||||
Most patches can be found on the suckless website: [https://dwm.suckless.org/patches/](https://dwm.suckless.org/patches/)
|
||||
|
||||
* [actualfullscreen](https://dwm.suckless.org/patches/actualfullscreen/) - Actually toggle fullscreen for a window, instead of toggling the status bar and the monocle layout
|
||||
* [alwaysfullscreen](https://dwm.suckless.org/patches/alwaysfullscreen/) - Do not allow the focus to drift from the active fullscreen client when using focusstack()
|
||||
* [anybar](https://github.com/mihirlad55/dwm-anybar) (Polybar Tray Fix Version) - Enables dwm to manage external status bars such as lemonbar and polybar
|
||||
* [aspectresize](https://dwm.suckless.org/patches/aspectresize/) - Allows you to resize a window while maintaining aspect ratio
|
||||
* [attachbelow](https://dwm.suckless.org/patches/attachbelow/) (Toggleable) - Make new clients attach below the selected client, instead of always becoming the new master
|
||||
* [autoresize](https://dwm.suckless.org/patches/autoresize/) - Windows that are not visible when requesting a resize/move will get resized/moved
|
||||
* [center](https://dwm.suckless.org/patches/center/) - Add an `iscentered` rule to automatically center clients on the current monitor
|
||||
* [cfacts](https://dwm.suckless.org/patches/cfacts/) - Assign different weights to clients in their respective stack in tiled layout
|
||||
* [cfacts-vanitygaps](https://github.com/bakkeby/patches/blob/master/dwm/dwm-cfacts-vanitygaps-6.2.diff) - Vanity gaps patch compatible with cfacts patch
|
||||
* [combo](https://dwm.suckless.org/patches/combo/) - Select multiple tags for tag or view by pressing all the right keys as a combo
|
||||
* [cool autostart](https://dwm.suckless.org/patches/cool_autostart/) - Execute commands from `autostart` array in `config.h` on startup and kill processes upon dwm exit
|
||||
* [cyclelayouts](https://dwm.suckless.org/patches/cyclelayouts/) - Cycle through all available layouts
|
||||
* [dwmc](https://dwm.suckless.org/patches/dwmc/) - Simple dwmc client using a fork of [fsignal](https://dwm.suckless.org/patches/fsignal/) to communicate with dwm
|
||||
* [fixborders](https://dwm.suckless.org/patches/alpha/) - Make borders opaque
|
||||
* [ipc](https://github.com/mihirlad55/dwm-ipc) - Allows third party programs (e.g. polybar) to query window manager for information
|
||||
* [movestack](https://dwm.suckless.org/patches/movestack/) - Move clients around in the stack and swap them with the master
|
||||
* [noborder](https://dwm.suckless.org/patches/noborder/) (Floating Fix) - Remove the border when there is only one window visible
|
||||
* [swallow](https://dwm.suckless.org/patches/swallow/) - Programs opened from terminal will "swallow" the terminal
|
||||
* [unfloatvisible](https://dwm.suckless.org/patches/unfloatvisible/) - Resets `isfloating` on any visible windows that have it set
|
||||
* [xresources](https://dwm.suckless.org/patches/xresources/) - Allows dwm settings (e.g. colors) to be set in Xresources
|
||||
|
||||
## Polybar
|
||||
|
||||
The anybar and ipc patches above allow dwm to use an external status bar.
|
||||
I am using polybar. My config can be found [here](https://github.com/balajsra/polybar).
|
||||
|
||||
* [Polybar DWM Module](https://github.com/mihirlad55/polybar-dwm-module)
|
||||
* [Polybar](https://github.com/polybar/polybar)
|
299
config.def.h
299
config.def.h
@ -1,89 +1,236 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
/* appearance */
|
||||
static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
static unsigned int borderpx = 2; /* border pixel of windows */
|
||||
static const unsigned int snap = 32; /* snap pixel */
|
||||
static unsigned int gappih = 20; /* horiz inner gap between windows */
|
||||
static unsigned int gappiv = 20; /* vert inner gap between windows */
|
||||
static unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */
|
||||
static unsigned int gappov = 10; /* vert outer gap between windows and screen edge */
|
||||
static const int noborder = 0; /* 1 means no border when there is only one window */
|
||||
static const int swallowfloating = 0; /* 1 means swallow floating windows by default */
|
||||
static int smartgaps = 0; /* 1 means no outer gap when there is only one window */
|
||||
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[] = "#222222";
|
||||
static const char col_gray2[] = "#444444";
|
||||
static const char col_gray3[] = "#bbbbbb";
|
||||
static const char col_gray4[] = "#eeeeee";
|
||||
static const char col_cyan[] = "#005577";
|
||||
static const char *colors[][3] = {
|
||||
static const int usealtbar = 1; /* 1 means use non-dwm status bar */
|
||||
static const char *altbarclass = "Polybar"; /* Alternate bar class name */
|
||||
static const char *alttrayname = "tray"; /* Polybar tray instance name */
|
||||
static const char *altbarcmd = "$HOME/.config/polybar/launch.sh"; /* Alternate bar launch command */
|
||||
static const char *fonts[] = { "NotoSans Nerd Font:size=10" };
|
||||
static char normbgcolor[] = "#222222"; /* background color */
|
||||
static char normbordercolor[] = "#444444"; /* inactive window border color */
|
||||
static char normfgcolor[] = "#bbbbbb"; /* font color */
|
||||
static char selfgcolor[] = "#eeeeee"; /* current tag and current window font color */
|
||||
static char selbordercolor[] = "#005577"; /* Top bar second color and active window border color */
|
||||
static char selbgcolor[] = "#005577"; /* Top bar second color and active window border color */
|
||||
static char *colors[][3] = {
|
||||
/* fg bg border */
|
||||
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
|
||||
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
|
||||
[SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor },
|
||||
[SchemeSel] = { selfgcolor, selbgcolor, selbordercolor },
|
||||
};
|
||||
|
||||
static const char *const autostart[] = {
|
||||
// System Restore Processes
|
||||
"bash", "/home/sravan/.screenlayout/default-screen-layout.sh", NULL, // Restore default screen layout
|
||||
"nitrogen", "--restore", NULL, // Restore wallpaper
|
||||
"numlockx", "on", NULL, // NumLock on by default
|
||||
// System Tray Applications
|
||||
"volctl", NULL, // PulseAudio Volume Control
|
||||
"nyrna", NULL, // Nyrna Application Suspend
|
||||
"blueman-applet", NULL, // Blueman Bluetooth Manager
|
||||
"nm-applet", NULL, // Network Manager Applet
|
||||
"kdeconnect-indicator", NULL, // KDE Connect
|
||||
"flameshot", NULL, // Flameshot Screenshot Tool
|
||||
"xfce4-power-manager", NULL, // XFCE4 Power Manager
|
||||
// Background Processes
|
||||
"bash", "/home/sravan/.config/picom/toggle_picom.sh", NULL, // Picom Compositor
|
||||
"bash", "/home/sravan/.config/dunst/launch_dunst.sh", NULL, // Dunst Notification Daemon
|
||||
"greenclip", "daemon", NULL, // Greenclip Clipboard Manager
|
||||
"redshift", "-x", NULL, // Reset redshift display gamma
|
||||
"redshift-gtk", NULL, // Redshift Blue Light Filter
|
||||
"/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1", NULL, // GNOME Polkit Authentication Agent
|
||||
"xss-lock", "-l", "--", "multilockscreen", "--lock", NULL, // Session lock handler
|
||||
// Hardware Driver Applications
|
||||
"solaar", "--window=hide", NULL, // Logitech Mouse Driver
|
||||
"openrgb", "--startminimized", NULL, // OpenRGB
|
||||
"optimus-manager-qt", NULL, // Optimus Manager Qt
|
||||
NULL /* terminate */
|
||||
};
|
||||
|
||||
/* tagging */
|
||||
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
|
||||
static const char *tags[] = { " ₁", "龎 ₂", " ₃", " ₄", "爵 ₅", " ₆", " ₇", " ₈", " ₉" };
|
||||
|
||||
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 },
|
||||
/* class instance title tags mask isfloating isterminal noswallow monitor */
|
||||
{ NULL, NULL, "Origin", 0, 1, 0, 0, -1 },
|
||||
{ "kitty", NULL, NULL, 0, 0, 0, 1, -1 },
|
||||
{ NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */
|
||||
};
|
||||
|
||||
/* 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 int attachbelow = 1; /* 1 means attach after the currently active window */
|
||||
|
||||
#define FORCE_VSPLIT 1 /* nrowgrid layout: force two clients to always split vertically */
|
||||
#include "vanitygaps.c"
|
||||
|
||||
static const Layout layouts[] = {
|
||||
/* symbol arrange function */
|
||||
{ "[]=", tile }, /* first entry is default */
|
||||
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||
{ "[M]", monocle },
|
||||
{ "[@]", spiral },
|
||||
{ "[\\]", dwindle },
|
||||
{ "H[]", deck },
|
||||
{ "TTT", bstack },
|
||||
{ "===", bstackhoriz },
|
||||
{ "HHH", grid },
|
||||
{ "###", nrowgrid },
|
||||
{ "---", horizgrid },
|
||||
{ ":::", gaplessgrid },
|
||||
{ "|M|", centeredmaster },
|
||||
{ ">M>", centeredfloatingmaster },
|
||||
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||
};
|
||||
|
||||
/* key definitions */
|
||||
#define MODKEY Mod1Mask
|
||||
#define MODKEY Mod4Mask /* Mod1Mask = Alt, Mod4Mask = Super */
|
||||
#define TAGKEYS(KEY,TAG) \
|
||||
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY, KEY, comboview, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|ShiftMask, KEY, combotag, {.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 *rofiruncmd[] = { "rofi", "-show", "drun", NULL };
|
||||
static const char *roficlipcmd[] = { "rofi", "-show", "clipboard", NULL };
|
||||
static const char *lockcmd[] = { "loginctl", "lock-session", NULL };
|
||||
static const char *sleepcmd[] = { "systemctl", "suspend", NULL };
|
||||
static const char *termcmd[] = { "kitty", NULL };
|
||||
static const char *upvolcmd[] = { "/usr/bin/pactl", "set-sink-volume", "@DEFAULT_SINK@", "+1%", NULL };
|
||||
static const char *downvolcmd[] = { "/usr/bin/pactl", "set-sink-volume", "@DEFAULT_SINK@", "-1%", NULL };
|
||||
static const char *mutevolcmd[] = { "/usr/bin/pactl", "set-sink-mute", "@DEFAULT_SINK@", "toggle", NULL };
|
||||
static const char *playerplaypausecmd[] = { "playerctl", "--player=playerctld", "play-pause", NULL };
|
||||
static const char *playernextcmd[] = { "playerctl", "--player=playerctld", "next", NULL };
|
||||
static const char *playerprevcmd[] = { "playerctl", "--player=playerctld", "previous", NULL };
|
||||
static const char *playershiftcmd[] = { "playerctld", "shift", NULL};
|
||||
static const char *flameshotcmd[] = { "flameshot", "gui", NULL };
|
||||
static const char *notifycontextcmd[] = { "dunstctl", "context", NULL };
|
||||
static const char *notifyhistorycmd[] = { "dunstctl", "history-pop", NULL };
|
||||
static const char *notifyclosecmd[] = { "dunstctl", "close", NULL };
|
||||
static const char *notifytogglecmd[] = { "dunstctl", "set-paused", "toggle", NULL };
|
||||
static const char *compositortogglecmd[] = { "/bin/bash", "/home/sravan/.config/picom/toggle_picom.sh", NULL, };
|
||||
|
||||
/*
|
||||
* Xresources preferences to load at startup
|
||||
*/
|
||||
ResourcePref resources[] = {
|
||||
{ "normbgcolor", STRING, &normbgcolor },
|
||||
{ "normbordercolor", STRING, &normbordercolor },
|
||||
{ "normfgcolor", STRING, &normfgcolor },
|
||||
{ "selbgcolor", STRING, &selbgcolor },
|
||||
{ "selbordercolor", STRING, &selbordercolor },
|
||||
{ "selfgcolor", STRING, &selfgcolor },
|
||||
{ "borderpx", INTEGER, &borderpx },
|
||||
{ "gappih", INTEGER, &gappih },
|
||||
{ "gappiv", INTEGER, &gappiv },
|
||||
{ "gappoh", INTEGER, &gappoh },
|
||||
{ "gappov", INTEGER, &gappov },
|
||||
// { "snap", INTEGER, &snap },
|
||||
// { "showbar", INTEGER, &showbar },
|
||||
// { "topbar", INTEGER, &topbar },
|
||||
// { "nmaster", INTEGER, &nmaster },
|
||||
// { "resizehints", INTEGER, &resizehints },
|
||||
// { "mfact", FLOAT, &mfact },
|
||||
};
|
||||
|
||||
#include "movestack.c"
|
||||
#include "unfloat.c"
|
||||
#include <X11/XF86keysym.h>
|
||||
static Key keys[] = {
|
||||
/* modifier key function argument */
|
||||
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
||||
{ MODKEY, XK_p, spawn, {.v = rofiruncmd} },
|
||||
{ MODKEY, XK_c, spawn, {.v = roficlipcmd} },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_l, spawn, {.v = lockcmd} },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_s, spawn, {.v = sleepcmd} },
|
||||
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd} },
|
||||
{ MODKEY, XK_n, spawn, {.v = notifycontextcmd} },
|
||||
{ MODKEY|ShiftMask, XK_n, spawn, {.v = notifyhistorycmd} },
|
||||
{ MODKEY|ControlMask, XK_n, spawn, {.v = notifyclosecmd} },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_n, spawn, {.v = notifytogglecmd} },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_Escape, spawn, {.v = compositortogglecmd} },
|
||||
{ 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|ShiftMask, XK_j, movestack, {.i = +1 } },
|
||||
{ MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
|
||||
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
||||
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
||||
{ MODKEY|ShiftMask, XK_h, setcfact, {.f = +0.25} },
|
||||
{ MODKEY|ShiftMask, XK_l, setcfact, {.f = -0.25} },
|
||||
{ MODKEY|ShiftMask, XK_o, setcfact, {.f = 0.00} },
|
||||
{ MODKEY, XK_Return, zoom, {0} },
|
||||
{ MODKEY, XK_Tab, view, {0} },
|
||||
{ MODKEY|ControlMask, XK_u, incrgaps, {.i = +1 } },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_u, incrgaps, {.i = -1 } },
|
||||
{ MODKEY|ControlMask, XK_i, incrigaps, {.i = +1 } },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_i, incrigaps, {.i = -1 } },
|
||||
{ MODKEY|ControlMask, XK_o, incrogaps, {.i = +1 } },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_o, incrogaps, {.i = -1 } },
|
||||
{ MODKEY|ControlMask, XK_6, incrihgaps, {.i = +1 } },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_6, incrihgaps, {.i = -1 } },
|
||||
{ MODKEY|ControlMask, XK_7, incrivgaps, {.i = +1 } },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_7, incrivgaps, {.i = -1 } },
|
||||
{ MODKEY|ControlMask, XK_8, incrohgaps, {.i = +1 } },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_8, incrohgaps, {.i = -1 } },
|
||||
{ MODKEY|ControlMask, XK_9, incrovgaps, {.i = +1 } },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_9, incrovgaps, {.i = -1 } },
|
||||
{ MODKEY|ControlMask, XK_0, togglegaps, {0} },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_0, defaultgaps, {0} },
|
||||
{ MODKEY, XK_Tab, comboview, {0} },
|
||||
{ MODKEY|ControlMask, XK_j, aspectresize, {.i = +24} },
|
||||
{ MODKEY|ControlMask, XK_k, aspectresize, {.i = -24} },
|
||||
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_c, spawn, SHCMD("kill -SEGV ""\"$(xprop | grep PID| awk '{print $3}')""\"") },
|
||||
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
||||
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
||||
{ MODKEY|ShiftMask, XK_t, unfloatvisible, {.v = &layouts[0]} },
|
||||
{ MODKEY, XK_m, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY|ShiftMask, XK_m, unfloatvisible, {.v = &layouts[1]} },
|
||||
{ MODKEY, XK_g, setlayout, {.v = &layouts[7]} },
|
||||
{ MODKEY|ShiftMask, XK_g, unfloatvisible, {.v = &layouts[7]} },
|
||||
{ MODKEY, XK_u, setlayout, {.v = &layouts[11]} },
|
||||
{ MODKEY|ShiftMask, XK_u, unfloatvisible, {.v = &layouts[11]} },
|
||||
{ MODKEY, XK_f, setlayout, {.v = &layouts[13]} },
|
||||
{ MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } },
|
||||
{ MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } },
|
||||
{ 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|ShiftMask, XK_space, unfloatvisible, {0} },
|
||||
{ MODKEY|ControlMask, XK_space, togglefloating, {0} },
|
||||
{ MODKEY|ShiftMask, XK_f, togglefullscr, {0} },
|
||||
{ MODKEY|ShiftMask, XK_Tab, toggleAttachBelow, {0} },
|
||||
{ MODKEY, XK_0, comboview, {.ui = ~0 } },
|
||||
{ MODKEY|ShiftMask, XK_0, combotag, {.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 } },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_Tab, spawn, {.v = playershiftcmd} },
|
||||
{ 0, XF86XK_AudioLowerVolume, spawn, {.v = downvolcmd} },
|
||||
{ 0, XF86XK_AudioMute, spawn, {.v = mutevolcmd} },
|
||||
{ 0, XF86XK_AudioRaiseVolume, spawn, {.v = upvolcmd} },
|
||||
{ 0, XF86XK_AudioPlay, spawn, {.v = playerplaypausecmd} },
|
||||
{ 0, XF86XK_AudioNext, spawn, {.v = playernextcmd} },
|
||||
{ 0, XF86XK_AudioPrev, spawn, {.v = playerprevcmd} },
|
||||
{ 0, XK_Print, spawn, {.v = flameshotcmd} },
|
||||
TAGKEYS( XK_1, 0)
|
||||
TAGKEYS( XK_2, 1)
|
||||
TAGKEYS( XK_3, 2)
|
||||
@ -93,7 +240,7 @@ static Key keys[] = {
|
||||
TAGKEYS( XK_7, 6)
|
||||
TAGKEYS( XK_8, 7)
|
||||
TAGKEYS( XK_9, 8)
|
||||
{ MODKEY|ShiftMask, XK_q, quit, {0} },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_q, quit, {0} },
|
||||
};
|
||||
|
||||
/* button definitions */
|
||||
@ -107,9 +254,97 @@ static Button buttons[] = {
|
||||
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
||||
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
|
||||
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
|
||||
{ ClkTagBar, 0, Button1, view, {0} },
|
||||
{ ClkTagBar, 0, Button1, comboview, {0} },
|
||||
{ ClkTagBar, 0, Button3, toggleview, {0} },
|
||||
{ ClkTagBar, MODKEY, Button1, tag, {0} },
|
||||
{ ClkTagBar, MODKEY, Button1, combotag, {0} },
|
||||
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
|
||||
};
|
||||
|
||||
static const char *ipcsockpath = "/tmp/dwm.sock";
|
||||
static IPCCommand ipccommands[] = {
|
||||
IPCCOMMAND( view, 1, {ARG_TYPE_UINT} ),
|
||||
IPCCOMMAND( toggleview, 1, {ARG_TYPE_UINT} ),
|
||||
IPCCOMMAND( tag, 1, {ARG_TYPE_UINT} ),
|
||||
IPCCOMMAND( toggletag, 1, {ARG_TYPE_UINT} ),
|
||||
IPCCOMMAND( tagmon, 1, {ARG_TYPE_UINT} ),
|
||||
IPCCOMMAND( focusmon, 1, {ARG_TYPE_SINT} ),
|
||||
IPCCOMMAND( focusstack, 1, {ARG_TYPE_SINT} ),
|
||||
IPCCOMMAND( zoom, 1, {ARG_TYPE_NONE} ),
|
||||
IPCCOMMAND( incnmaster, 1, {ARG_TYPE_SINT} ),
|
||||
IPCCOMMAND( killclient, 1, {ARG_TYPE_SINT} ),
|
||||
IPCCOMMAND( togglefloating, 1, {ARG_TYPE_NONE} ),
|
||||
IPCCOMMAND( setmfact, 1, {ARG_TYPE_FLOAT} ),
|
||||
IPCCOMMAND( setlayoutsafe, 1, {ARG_TYPE_PTR} ),
|
||||
IPCCOMMAND( quit, 1, {ARG_TYPE_NONE} )
|
||||
};
|
||||
|
||||
void
|
||||
setlayoutex(const Arg *arg)
|
||||
{
|
||||
setlayout(&((Arg) { .v = &layouts[arg->i] }));
|
||||
}
|
||||
|
||||
void
|
||||
viewex(const Arg *arg)
|
||||
{
|
||||
view(&((Arg) { .ui = 1 << arg->ui }));
|
||||
}
|
||||
|
||||
void
|
||||
viewall(const Arg *arg)
|
||||
{
|
||||
view(&((Arg){.ui = ~0}));
|
||||
}
|
||||
|
||||
void
|
||||
toggleviewex(const Arg *arg)
|
||||
{
|
||||
toggleview(&((Arg) { .ui = 1 << arg->ui }));
|
||||
}
|
||||
|
||||
void
|
||||
tagex(const Arg *arg)
|
||||
{
|
||||
tag(&((Arg) { .ui = 1 << arg->ui }));
|
||||
}
|
||||
|
||||
void
|
||||
toggletagex(const Arg *arg)
|
||||
{
|
||||
toggletag(&((Arg) { .ui = 1 << arg->ui }));
|
||||
}
|
||||
|
||||
void
|
||||
tagall(const Arg *arg)
|
||||
{
|
||||
tag(&((Arg){.ui = ~0}));
|
||||
}
|
||||
|
||||
/* signal definitions */
|
||||
/* signum must be greater than 0 */
|
||||
/* trigger signals using `xsetroot -name "fsignal:<signame> [<type> <value>]"` */
|
||||
static Signal signals[] = {
|
||||
/* signum function */
|
||||
{ "focusstack", focusstack },
|
||||
{ "setmfact", setmfact },
|
||||
{ "togglebar", togglebar },
|
||||
{ "incnmaster", incnmaster },
|
||||
{ "togglefloating", togglefloating },
|
||||
{ "focusmon", focusmon },
|
||||
{ "tagmon", tagmon },
|
||||
{ "zoom", zoom },
|
||||
{ "view", view },
|
||||
{ "viewall", viewall },
|
||||
{ "viewex", viewex },
|
||||
{ "toggleview", view },
|
||||
{ "toggleviewex", toggleviewex },
|
||||
{ "tag", tag },
|
||||
{ "tagall", tagall },
|
||||
{ "tagex", tagex },
|
||||
{ "toggletag", tag },
|
||||
{ "toggletagex", toggletagex },
|
||||
{ "killclient", killclient },
|
||||
{ "quit", quit },
|
||||
{ "setlayout", setlayout },
|
||||
{ "setlayoutex", setlayoutex },
|
||||
};
|
||||
|
@ -19,10 +19,15 @@ FREETYPELIBS = -lfontconfig -lXft
|
||||
FREETYPEINC = /usr/include/freetype2
|
||||
# OpenBSD (uncomment)
|
||||
#FREETYPEINC = ${X11INC}/freetype2
|
||||
#KVMLIB = -lkvm
|
||||
|
||||
# yajl
|
||||
YAJLLIBS = -lyajl
|
||||
YAJLINC = /usr/include/yajl
|
||||
|
||||
# includes and libs
|
||||
INCS = -I${X11INC} -I${FREETYPEINC}
|
||||
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
|
||||
INCS = -I${X11INC} -I${FREETYPEINC} -I${YAJLINC}
|
||||
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${YAJLLIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB}
|
||||
|
||||
# flags
|
||||
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
|
||||
|
4
drw.c
4
drw.c
@ -203,12 +203,14 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
|
||||
DefaultColormap(drw->dpy, drw->screen),
|
||||
clrname, dest))
|
||||
die("error, cannot allocate color '%s'", clrname);
|
||||
|
||||
dest->pixel |= 0xff << 24;
|
||||
}
|
||||
|
||||
/* Wrapper to create color schemes. The caller has to call free(3) on the
|
||||
* returned color scheme when done using it. */
|
||||
Clr *
|
||||
drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
|
||||
drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount)
|
||||
{
|
||||
size_t i;
|
||||
Clr *ret;
|
||||
|
2
drw.h
2
drw.h
@ -39,7 +39,7 @@ void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned in
|
||||
|
||||
/* Colorscheme abstraction */
|
||||
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
|
||||
Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
|
||||
Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount);
|
||||
|
||||
/* Cursor abstraction */
|
||||
Cur *drw_cur_create(Drw *drw, int shape);
|
||||
|
548
dwm-msg.c
Normal file
548
dwm-msg.c
Normal file
@ -0,0 +1,548 @@
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include <yajl/yajl_gen.h>
|
||||
|
||||
#define IPC_MAGIC "DWM-IPC"
|
||||
// clang-format off
|
||||
#define IPC_MAGIC_ARR { 'D', 'W', 'M', '-', 'I', 'P', 'C' }
|
||||
// clang-format on
|
||||
#define IPC_MAGIC_LEN 7 // Not including null char
|
||||
|
||||
#define IPC_EVENT_TAG_CHANGE "tag_change_event"
|
||||
#define IPC_EVENT_CLIENT_FOCUS_CHANGE "client_focus_change_event"
|
||||
#define IPC_EVENT_LAYOUT_CHANGE "layout_change_event"
|
||||
#define IPC_EVENT_MONITOR_FOCUS_CHANGE "monitor_focus_change_event"
|
||||
#define IPC_EVENT_FOCUSED_TITLE_CHANGE "focused_title_change_event"
|
||||
#define IPC_EVENT_FOCUSED_STATE_CHANGE "focused_state_change_event"
|
||||
|
||||
#define YSTR(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str))
|
||||
#define YINT(num) yajl_gen_integer(gen, num)
|
||||
#define YDOUBLE(num) yajl_gen_double(gen, num)
|
||||
#define YBOOL(v) yajl_gen_bool(gen, v)
|
||||
#define YNULL() yajl_gen_null(gen)
|
||||
#define YARR(body) \
|
||||
{ \
|
||||
yajl_gen_array_open(gen); \
|
||||
body; \
|
||||
yajl_gen_array_close(gen); \
|
||||
}
|
||||
#define YMAP(body) \
|
||||
{ \
|
||||
yajl_gen_map_open(gen); \
|
||||
body; \
|
||||
yajl_gen_map_close(gen); \
|
||||
}
|
||||
|
||||
typedef unsigned long Window;
|
||||
|
||||
const char *DEFAULT_SOCKET_PATH = "/tmp/dwm.sock";
|
||||
static int sock_fd = -1;
|
||||
static unsigned int ignore_reply = 0;
|
||||
|
||||
typedef enum IPCMessageType {
|
||||
IPC_TYPE_RUN_COMMAND = 0,
|
||||
IPC_TYPE_GET_MONITORS = 1,
|
||||
IPC_TYPE_GET_TAGS = 2,
|
||||
IPC_TYPE_GET_LAYOUTS = 3,
|
||||
IPC_TYPE_GET_DWM_CLIENT = 4,
|
||||
IPC_TYPE_SUBSCRIBE = 5,
|
||||
IPC_TYPE_EVENT = 6
|
||||
} IPCMessageType;
|
||||
|
||||
// Every IPC message must begin with this
|
||||
typedef struct dwm_ipc_header {
|
||||
uint8_t magic[IPC_MAGIC_LEN];
|
||||
uint32_t size;
|
||||
uint8_t type;
|
||||
} __attribute((packed)) dwm_ipc_header_t;
|
||||
|
||||
static int
|
||||
recv_message(uint8_t *msg_type, uint32_t *reply_size, uint8_t **reply)
|
||||
{
|
||||
uint32_t read_bytes = 0;
|
||||
const int32_t to_read = sizeof(dwm_ipc_header_t);
|
||||
char header[to_read];
|
||||
char *walk = header;
|
||||
|
||||
// Try to read header
|
||||
while (read_bytes < to_read) {
|
||||
ssize_t n = read(sock_fd, header + read_bytes, to_read - read_bytes);
|
||||
|
||||
if (n == 0) {
|
||||
if (read_bytes == 0) {
|
||||
fprintf(stderr, "Unexpectedly reached EOF while reading header.");
|
||||
fprintf(stderr,
|
||||
"Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n",
|
||||
read_bytes, to_read);
|
||||
return -2;
|
||||
} else {
|
||||
fprintf(stderr, "Unexpectedly reached EOF while reading header.");
|
||||
fprintf(stderr,
|
||||
"Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n",
|
||||
read_bytes, to_read);
|
||||
return -3;
|
||||
}
|
||||
} else if (n == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
read_bytes += n;
|
||||
}
|
||||
|
||||
// Check if magic string in header matches
|
||||
if (memcmp(walk, IPC_MAGIC, IPC_MAGIC_LEN) != 0) {
|
||||
fprintf(stderr, "Invalid magic string. Got '%.*s', expected '%s'\n",
|
||||
IPC_MAGIC_LEN, walk, IPC_MAGIC);
|
||||
return -3;
|
||||
}
|
||||
|
||||
walk += IPC_MAGIC_LEN;
|
||||
|
||||
// Extract reply size
|
||||
memcpy(reply_size, walk, sizeof(uint32_t));
|
||||
walk += sizeof(uint32_t);
|
||||
|
||||
// Extract message type
|
||||
memcpy(msg_type, walk, sizeof(uint8_t));
|
||||
walk += sizeof(uint8_t);
|
||||
|
||||
(*reply) = malloc(*reply_size);
|
||||
|
||||
// Extract payload
|
||||
read_bytes = 0;
|
||||
while (read_bytes < *reply_size) {
|
||||
ssize_t n = read(sock_fd, *reply + read_bytes, *reply_size - read_bytes);
|
||||
|
||||
if (n == 0) {
|
||||
fprintf(stderr, "Unexpectedly reached EOF while reading payload.");
|
||||
fprintf(stderr, "Read %" PRIu32 " bytes, expected %" PRIu32 " bytes.\n",
|
||||
read_bytes, *reply_size);
|
||||
free(*reply);
|
||||
return -2;
|
||||
} else if (n == -1) {
|
||||
if (errno == EINTR || errno == EAGAIN) continue;
|
||||
free(*reply);
|
||||
return -1;
|
||||
}
|
||||
|
||||
read_bytes += n;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
read_socket(IPCMessageType *msg_type, uint32_t *msg_size, char **msg)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
while (ret != 0) {
|
||||
ret = recv_message((uint8_t *)msg_type, msg_size, (uint8_t **)msg);
|
||||
|
||||
if (ret < 0) {
|
||||
// Try again (non-fatal error)
|
||||
if (ret == -1 && (errno == EINTR || errno == EAGAIN)) continue;
|
||||
|
||||
fprintf(stderr, "Error receiving response from socket. ");
|
||||
fprintf(stderr, "The connection might have been lost.\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
write_socket(const void *buf, size_t count)
|
||||
{
|
||||
size_t written = 0;
|
||||
|
||||
while (written < count) {
|
||||
const ssize_t n =
|
||||
write(sock_fd, ((uint8_t *)buf) + written, count - written);
|
||||
|
||||
if (n == -1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
return n;
|
||||
}
|
||||
written += n;
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
static void
|
||||
connect_to_socket()
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
|
||||
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
// Initialize struct to 0
|
||||
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||||
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(addr.sun_path, DEFAULT_SOCKET_PATH);
|
||||
|
||||
connect(sock, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un));
|
||||
|
||||
sock_fd = sock;
|
||||
}
|
||||
|
||||
static int
|
||||
send_message(IPCMessageType msg_type, uint32_t msg_size, uint8_t *msg)
|
||||
{
|
||||
dwm_ipc_header_t header = {
|
||||
.magic = IPC_MAGIC_ARR, .size = msg_size, .type = msg_type};
|
||||
|
||||
size_t header_size = sizeof(dwm_ipc_header_t);
|
||||
size_t total_size = header_size + msg_size;
|
||||
|
||||
uint8_t buffer[total_size];
|
||||
|
||||
// Copy header to buffer
|
||||
memcpy(buffer, &header, header_size);
|
||||
// Copy message to buffer
|
||||
memcpy(buffer + header_size, msg, header.size);
|
||||
|
||||
write_socket(buffer, total_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
is_float(const char *s)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
int is_dot_used = 0;
|
||||
int is_minus_used = 0;
|
||||
|
||||
// Floats can only have one decimal point in between or digits
|
||||
// Optionally, floats can also be below zero (negative)
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (isdigit(s[i]))
|
||||
continue;
|
||||
else if (!is_dot_used && s[i] == '.' && i != 0 && i != len - 1) {
|
||||
is_dot_used = 1;
|
||||
continue;
|
||||
} else if (!is_minus_used && s[i] == '-' && i == 0) {
|
||||
is_minus_used = 1;
|
||||
continue;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
is_unsigned_int(const char *s)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
|
||||
// Unsigned int can only have digits
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (isdigit(s[i]))
|
||||
continue;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
is_signed_int(const char *s)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
|
||||
// Signed int can only have digits and a negative sign at the start
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (isdigit(s[i]))
|
||||
continue;
|
||||
else if (i == 0 && s[i] == '-') {
|
||||
continue;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
flush_socket_reply()
|
||||
{
|
||||
IPCMessageType reply_type;
|
||||
uint32_t reply_size;
|
||||
char *reply;
|
||||
|
||||
read_socket(&reply_type, &reply_size, &reply);
|
||||
|
||||
free(reply);
|
||||
}
|
||||
|
||||
static void
|
||||
print_socket_reply()
|
||||
{
|
||||
IPCMessageType reply_type;
|
||||
uint32_t reply_size;
|
||||
char *reply;
|
||||
|
||||
read_socket(&reply_type, &reply_size, &reply);
|
||||
|
||||
printf("%.*s\n", reply_size, reply);
|
||||
fflush(stdout);
|
||||
free(reply);
|
||||
}
|
||||
|
||||
static int
|
||||
run_command(const char *name, char *args[], int argc)
|
||||
{
|
||||
const unsigned char *msg;
|
||||
size_t msg_size;
|
||||
|
||||
yajl_gen gen = yajl_gen_alloc(NULL);
|
||||
|
||||
// Message format:
|
||||
// {
|
||||
// "command": "<name>",
|
||||
// "args": [ ... ]
|
||||
// }
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("command"); YSTR(name);
|
||||
YSTR("args"); YARR(
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (is_signed_int(args[i])) {
|
||||
long long num = atoll(args[i]);
|
||||
YINT(num);
|
||||
} else if (is_float(args[i])) {
|
||||
float num = atof(args[i]);
|
||||
YDOUBLE(num);
|
||||
} else {
|
||||
YSTR(args[i]);
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
yajl_gen_get_buf(gen, &msg, &msg_size);
|
||||
|
||||
send_message(IPC_TYPE_RUN_COMMAND, msg_size, (uint8_t *)msg);
|
||||
|
||||
if (!ignore_reply)
|
||||
print_socket_reply();
|
||||
else
|
||||
flush_socket_reply();
|
||||
|
||||
yajl_gen_free(gen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
get_monitors()
|
||||
{
|
||||
send_message(IPC_TYPE_GET_MONITORS, 1, (uint8_t *)"");
|
||||
print_socket_reply();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
get_tags()
|
||||
{
|
||||
send_message(IPC_TYPE_GET_TAGS, 1, (uint8_t *)"");
|
||||
print_socket_reply();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
get_layouts()
|
||||
{
|
||||
send_message(IPC_TYPE_GET_LAYOUTS, 1, (uint8_t *)"");
|
||||
print_socket_reply();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
get_dwm_client(Window win)
|
||||
{
|
||||
const unsigned char *msg;
|
||||
size_t msg_size;
|
||||
|
||||
yajl_gen gen = yajl_gen_alloc(NULL);
|
||||
|
||||
// Message format:
|
||||
// {
|
||||
// "client_window_id": "<win>"
|
||||
// }
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("client_window_id"); YINT(win);
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
yajl_gen_get_buf(gen, &msg, &msg_size);
|
||||
|
||||
send_message(IPC_TYPE_GET_DWM_CLIENT, msg_size, (uint8_t *)msg);
|
||||
|
||||
print_socket_reply();
|
||||
|
||||
yajl_gen_free(gen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
subscribe(const char *event)
|
||||
{
|
||||
const unsigned char *msg;
|
||||
size_t msg_size;
|
||||
|
||||
yajl_gen gen = yajl_gen_alloc(NULL);
|
||||
|
||||
// Message format:
|
||||
// {
|
||||
// "event": "<event>",
|
||||
// "action": "subscribe"
|
||||
// }
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("event"); YSTR(event);
|
||||
YSTR("action"); YSTR("subscribe");
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
yajl_gen_get_buf(gen, &msg, &msg_size);
|
||||
|
||||
send_message(IPC_TYPE_SUBSCRIBE, msg_size, (uint8_t *)msg);
|
||||
|
||||
if (!ignore_reply)
|
||||
print_socket_reply();
|
||||
else
|
||||
flush_socket_reply();
|
||||
|
||||
yajl_gen_free(gen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
usage_error(const char *prog_name, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
fprintf(stderr, "Error: ");
|
||||
vfprintf(stderr, format, args);
|
||||
fprintf(stderr, "\nusage: %s <command> [...]\n", prog_name);
|
||||
fprintf(stderr, "Try '%s help'\n", prog_name);
|
||||
|
||||
va_end(args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
print_usage(const char *name)
|
||||
{
|
||||
printf("usage: %s [options] <command> [...]\n", name);
|
||||
puts("");
|
||||
puts("Commands:");
|
||||
puts(" run_command <name> [args...] Run an IPC command");
|
||||
puts("");
|
||||
puts(" get_monitors Get monitor properties");
|
||||
puts("");
|
||||
puts(" get_tags Get list of tags");
|
||||
puts("");
|
||||
puts(" get_layouts Get list of layouts");
|
||||
puts("");
|
||||
puts(" get_dwm_client <window_id> Get dwm client proprties");
|
||||
puts("");
|
||||
puts(" subscribe [events...] Subscribe to specified events");
|
||||
puts(" Options: " IPC_EVENT_TAG_CHANGE ",");
|
||||
puts(" " IPC_EVENT_LAYOUT_CHANGE ",");
|
||||
puts(" " IPC_EVENT_CLIENT_FOCUS_CHANGE ",");
|
||||
puts(" " IPC_EVENT_MONITOR_FOCUS_CHANGE ",");
|
||||
puts(" " IPC_EVENT_FOCUSED_TITLE_CHANGE ",");
|
||||
puts(" " IPC_EVENT_FOCUSED_STATE_CHANGE);
|
||||
puts("");
|
||||
puts(" help Display this message");
|
||||
puts("");
|
||||
puts("Options:");
|
||||
puts(" --ignore-reply Don't print reply messages from");
|
||||
puts(" run_command and subscribe.");
|
||||
puts("");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const char *prog_name = argv[0];
|
||||
|
||||
connect_to_socket();
|
||||
if (sock_fd == -1) {
|
||||
fprintf(stderr, "Failed to connect to socket\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int i = 1;
|
||||
if (i < argc && strcmp(argv[i], "--ignore-reply") == 0) {
|
||||
ignore_reply = 1;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i >= argc) usage_error(prog_name, "Expected an argument, got none");
|
||||
|
||||
if (strcmp(argv[i], "help") == 0)
|
||||
print_usage(prog_name);
|
||||
else if (strcmp(argv[i], "run_command") == 0) {
|
||||
if (++i >= argc) usage_error(prog_name, "No command specified");
|
||||
// Command name
|
||||
char *command = argv[i];
|
||||
// Command arguments are everything after command name
|
||||
char **command_args = argv + ++i;
|
||||
// Number of command arguments
|
||||
int command_argc = argc - i;
|
||||
run_command(command, command_args, command_argc);
|
||||
} else if (strcmp(argv[i], "get_monitors") == 0) {
|
||||
get_monitors();
|
||||
} else if (strcmp(argv[i], "get_tags") == 0) {
|
||||
get_tags();
|
||||
} else if (strcmp(argv[i], "get_layouts") == 0) {
|
||||
get_layouts();
|
||||
} else if (strcmp(argv[i], "get_dwm_client") == 0) {
|
||||
if (++i < argc) {
|
||||
if (is_unsigned_int(argv[i])) {
|
||||
Window win = atol(argv[i]);
|
||||
get_dwm_client(win);
|
||||
} else
|
||||
usage_error(prog_name, "Expected unsigned integer argument");
|
||||
} else
|
||||
usage_error(prog_name, "Expected the window id");
|
||||
} else if (strcmp(argv[i], "subscribe") == 0) {
|
||||
if (++i < argc) {
|
||||
for (int j = i; j < argc; j++) subscribe(argv[j]);
|
||||
} else
|
||||
usage_error(prog_name, "Expected event name");
|
||||
// Keep listening for events forever
|
||||
while (1) {
|
||||
print_socket_reply();
|
||||
}
|
||||
} else
|
||||
usage_error(prog_name, "Invalid argument '%s'", argv[i]);
|
||||
|
||||
return 0;
|
||||
}
|
30
dwm.1
30
dwm.1
@ -29,6 +29,9 @@ color. The tags of the focused window are indicated with a filled square in the
|
||||
top left corner. The tags which are applied to one or more windows are
|
||||
indicated with an empty square in the top left corner.
|
||||
.P
|
||||
The attach below patch makes newly spawned windows attach after the currently
|
||||
selected window
|
||||
.P
|
||||
dwm draws a small border around windows to indicate the focus state.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
@ -92,6 +95,12 @@ Sets monocle layout.
|
||||
.B Mod1\-space
|
||||
Toggles between current and previous layout.
|
||||
.TP
|
||||
.B Mod1\-Control\-,
|
||||
Cycles backwards in layout list.
|
||||
.TP
|
||||
.B Mod1\-Control\-.
|
||||
Cycles forwards in layout list.
|
||||
.TP
|
||||
.B Mod1\-j
|
||||
Focus next window.
|
||||
.TP
|
||||
@ -110,6 +119,15 @@ Increase master area size.
|
||||
.B Mod1\-h
|
||||
Decrease master area size.
|
||||
.TP
|
||||
.B Mod1\-Shift\-l
|
||||
Increase client weight (cfacts patch).
|
||||
.TP
|
||||
.B Mod1\-Shift\-h
|
||||
Decrease client weight (cfacts patch).
|
||||
.TP
|
||||
.B Mod1\-Shift\-o
|
||||
Reset client weight (cfacts patch).
|
||||
.TP
|
||||
.B Mod1\-Return
|
||||
Zooms/cycles focused window to/from master area (tiled layouts only).
|
||||
.TP
|
||||
@ -119,9 +137,21 @@ Close focused window.
|
||||
.B Mod1\-Shift\-space
|
||||
Toggle focused window between tiled and floating state.
|
||||
.TP
|
||||
.B Mod1\-Control\-f
|
||||
Toggle fullscreen (actualfullscreen patch).
|
||||
.TP
|
||||
.B Mod1\-Control\-tab
|
||||
Toggle attach below (attachbelow patch).
|
||||
.TP
|
||||
.B Mod1\-Tab
|
||||
Toggles to the previously selected tags.
|
||||
.TP
|
||||
.B Mod1\-Shift\-j
|
||||
Increase window size while maintaining aspect ratio (aspectresize patch).
|
||||
.TP
|
||||
.B Mod1\-Shift\-k
|
||||
Decrease window size while maintaining aspect ratio (aspectresize patch).
|
||||
.TP
|
||||
.B Mod1\-Shift\-[1..n]
|
||||
Apply nth tag to focused window.
|
||||
.TP
|
||||
|
40
dwmc
Executable file
40
dwmc
Executable file
@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
signal() {
|
||||
xsetroot -name "fsignal:$*"
|
||||
}
|
||||
|
||||
case $# in
|
||||
1)
|
||||
case $1 in
|
||||
setlayout | view | viewall | togglebar | togglefloating | zoom | killclient | quit)
|
||||
signal $1
|
||||
;;
|
||||
*)
|
||||
echo "Unknown command or missing one argument."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
2)
|
||||
case $1 in
|
||||
view)
|
||||
signal $1 ui $2
|
||||
;;
|
||||
viewex | toggleviewex | tagex | toggletagex | setlayoutex | focusstack | incnmaster | focusmon | tagmon)
|
||||
signal $1 i $2
|
||||
;;
|
||||
setmfact)
|
||||
signal $1 f $2
|
||||
;;
|
||||
*)
|
||||
echo "Unknown command or one too many arguments."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "Too many arguments."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
320
ipc.h
Normal file
320
ipc.h
Normal file
@ -0,0 +1,320 @@
|
||||
#ifndef IPC_H_
|
||||
#define IPC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <yajl/yajl_gen.h>
|
||||
|
||||
#include "IPCClient.h"
|
||||
|
||||
// clang-format off
|
||||
#define IPC_MAGIC "DWM-IPC"
|
||||
#define IPC_MAGIC_ARR { 'D', 'W', 'M', '-', 'I', 'P', 'C'}
|
||||
#define IPC_MAGIC_LEN 7 // Not including null char
|
||||
|
||||
#define IPCCOMMAND(FUNC, ARGC, TYPES) \
|
||||
{ #FUNC, {FUNC }, ARGC, (ArgType[ARGC])TYPES }
|
||||
// clang-format on
|
||||
|
||||
typedef enum IPCMessageType {
|
||||
IPC_TYPE_RUN_COMMAND = 0,
|
||||
IPC_TYPE_GET_MONITORS = 1,
|
||||
IPC_TYPE_GET_TAGS = 2,
|
||||
IPC_TYPE_GET_LAYOUTS = 3,
|
||||
IPC_TYPE_GET_DWM_CLIENT = 4,
|
||||
IPC_TYPE_SUBSCRIBE = 5,
|
||||
IPC_TYPE_EVENT = 6
|
||||
} IPCMessageType;
|
||||
|
||||
typedef enum IPCEvent {
|
||||
IPC_EVENT_TAG_CHANGE = 1 << 0,
|
||||
IPC_EVENT_CLIENT_FOCUS_CHANGE = 1 << 1,
|
||||
IPC_EVENT_LAYOUT_CHANGE = 1 << 2,
|
||||
IPC_EVENT_MONITOR_FOCUS_CHANGE = 1 << 3,
|
||||
IPC_EVENT_FOCUSED_TITLE_CHANGE = 1 << 4,
|
||||
IPC_EVENT_FOCUSED_STATE_CHANGE = 1 << 5
|
||||
} IPCEvent;
|
||||
|
||||
typedef enum IPCSubscriptionAction {
|
||||
IPC_ACTION_UNSUBSCRIBE = 0,
|
||||
IPC_ACTION_SUBSCRIBE = 1
|
||||
} IPCSubscriptionAction;
|
||||
|
||||
/**
|
||||
* Every IPC packet starts with this structure
|
||||
*/
|
||||
typedef struct dwm_ipc_header {
|
||||
uint8_t magic[IPC_MAGIC_LEN];
|
||||
uint32_t size;
|
||||
uint8_t type;
|
||||
} __attribute((packed)) dwm_ipc_header_t;
|
||||
|
||||
typedef enum ArgType {
|
||||
ARG_TYPE_NONE = 0,
|
||||
ARG_TYPE_UINT = 1,
|
||||
ARG_TYPE_SINT = 2,
|
||||
ARG_TYPE_FLOAT = 3,
|
||||
ARG_TYPE_PTR = 4,
|
||||
ARG_TYPE_STR = 5
|
||||
} ArgType;
|
||||
|
||||
/**
|
||||
* An IPCCommand function can have either of these function signatures
|
||||
*/
|
||||
typedef union ArgFunction {
|
||||
void (*single_param)(const Arg *);
|
||||
void (*array_param)(const Arg *, int);
|
||||
} ArgFunction;
|
||||
|
||||
typedef struct IPCCommand {
|
||||
char *name;
|
||||
ArgFunction func;
|
||||
unsigned int argc;
|
||||
ArgType *arg_types;
|
||||
} IPCCommand;
|
||||
|
||||
typedef struct IPCParsedCommand {
|
||||
char *name;
|
||||
Arg *args;
|
||||
ArgType *arg_types;
|
||||
unsigned int argc;
|
||||
} IPCParsedCommand;
|
||||
|
||||
/**
|
||||
* Initialize the IPC socket and the IPC module
|
||||
*
|
||||
* @param socket_path Path to create the socket at
|
||||
* @param epoll_fd File descriptor for epoll
|
||||
* @param commands Address of IPCCommands array defined in config.h
|
||||
* @param commands_len Length of commands[] array
|
||||
*
|
||||
* @return int The file descriptor of the socket if it was successfully created,
|
||||
* -1 otherwise
|
||||
*/
|
||||
int ipc_init(const char *socket_path, const int p_epoll_fd,
|
||||
IPCCommand commands[], const int commands_len);
|
||||
|
||||
/**
|
||||
* Uninitialize the socket and module. Free allocated memory and restore static
|
||||
* variables to their state before ipc_init
|
||||
*/
|
||||
void ipc_cleanup();
|
||||
|
||||
/**
|
||||
* Get the file descriptor of the IPC socket
|
||||
*
|
||||
* @return int File descriptor of IPC socket, -1 if socket not created.
|
||||
*/
|
||||
int ipc_get_sock_fd();
|
||||
|
||||
/**
|
||||
* Get address to IPCClient with specified file descriptor
|
||||
*
|
||||
* @param fd File descriptor of IPC Client
|
||||
*
|
||||
* @return Address to IPCClient with specified file descriptor, -1 otherwise
|
||||
*/
|
||||
IPCClient *ipc_get_client(int fd);
|
||||
|
||||
/**
|
||||
* Check if an IPC client exists with the specified file descriptor
|
||||
*
|
||||
* @param fd File descriptor
|
||||
*
|
||||
* @return int 1 if client exists, 0 otherwise
|
||||
*/
|
||||
int ipc_is_client_registered(int fd);
|
||||
|
||||
/**
|
||||
* Disconnect an IPCClient from the socket and remove the client from the list
|
||||
* of known connected clients
|
||||
*
|
||||
* @param c Address of IPCClient
|
||||
*
|
||||
* @return 0 if the client's file descriptor was closed successfully, the
|
||||
* result of executing close() on the file descriptor otherwise.
|
||||
*/
|
||||
int ipc_drop_client(IPCClient *c);
|
||||
|
||||
/**
|
||||
* Accept an IPC Client requesting to connect to the socket and add it to the
|
||||
* list of clients
|
||||
*
|
||||
* @return File descriptor of new client, -1 on error
|
||||
*/
|
||||
int ipc_accept_client();
|
||||
|
||||
/**
|
||||
* Read an incoming message from an accepted IPC client
|
||||
*
|
||||
* @param c Address of IPCClient
|
||||
* @param msg_type Address to IPCMessageType variable which will be assigned
|
||||
* the message type of the received message
|
||||
* @param msg_size Address to uint32_t variable which will be assigned the size
|
||||
* of the received message
|
||||
* @param msg Address to char* variable which will be assigned the address of
|
||||
* the received message. This must be freed using free().
|
||||
*
|
||||
* @return 0 on success, -1 on error reading message, -2 if reading the message
|
||||
* resulted in EAGAIN, EINTR, or EWOULDBLOCK.
|
||||
*/
|
||||
int ipc_read_client(IPCClient *c, IPCMessageType *msg_type, uint32_t *msg_size,
|
||||
char **msg);
|
||||
|
||||
/**
|
||||
* Write any pending buffer of the client to the client's socket
|
||||
*
|
||||
* @param c Client whose buffer to write
|
||||
*
|
||||
* @return Number of bytes written >= 0, -1 otherwise. errno will still be set
|
||||
* from the write operation.
|
||||
*/
|
||||
ssize_t ipc_write_client(IPCClient *c);
|
||||
|
||||
/**
|
||||
* Prepare a message in the specified client's buffer.
|
||||
*
|
||||
* @param c Client to prepare message for
|
||||
* @param msg_type Type of message to prepare
|
||||
* @param msg_size Size of the message in bytes. Should not exceed
|
||||
* MAX_MESSAGE_SIZE
|
||||
* @param msg Message to prepare (not including header). This pointer can be
|
||||
* freed after the function invocation.
|
||||
*/
|
||||
void ipc_prepare_send_message(IPCClient *c, const IPCMessageType msg_type,
|
||||
const uint32_t msg_size, const char *msg);
|
||||
|
||||
/**
|
||||
* Prepare an error message in the specified client's buffer
|
||||
*
|
||||
* @param c Client to prepare message for
|
||||
* @param msg_type Type of message
|
||||
* @param format Format string following vsprintf
|
||||
* @param ... Arguments for format string
|
||||
*/
|
||||
void ipc_prepare_reply_failure(IPCClient *c, IPCMessageType msg_type,
|
||||
const char *format, ...);
|
||||
|
||||
/**
|
||||
* Prepare a success message in the specified client's buffer
|
||||
*
|
||||
* @param c Client to prepare message for
|
||||
* @param msg_type Type of message
|
||||
*/
|
||||
void ipc_prepare_reply_success(IPCClient *c, IPCMessageType msg_type);
|
||||
|
||||
/**
|
||||
* Send a tag_change_event to all subscribers. Should be called only when there
|
||||
* has been a tag state change.
|
||||
*
|
||||
* @param mon_num The index of the monitor (Monitor.num property)
|
||||
* @param old_state The old tag state
|
||||
* @param new_state The new (now current) tag state
|
||||
*/
|
||||
void ipc_tag_change_event(const int mon_num, TagState old_state,
|
||||
TagState new_state);
|
||||
|
||||
/**
|
||||
* Send a client_focus_change_event to all subscribers. Should be called only
|
||||
* when the client focus changes.
|
||||
*
|
||||
* @param mon_num The index of the monitor (Monitor.num property)
|
||||
* @param old_client The old DWM client selection (Monitor.oldsel)
|
||||
* @param new_client The new (now current) DWM client selection
|
||||
*/
|
||||
void ipc_client_focus_change_event(const int mon_num, Client *old_client,
|
||||
Client *new_client);
|
||||
|
||||
/**
|
||||
* Send a layout_change_event to all subscribers. Should be called only
|
||||
* when there has been a layout change.
|
||||
*
|
||||
* @param mon_num The index of the monitor (Monitor.num property)
|
||||
* @param old_symbol The old layout symbol
|
||||
* @param old_layout Address to the old Layout
|
||||
* @param new_symbol The new (now current) layout symbol
|
||||
* @param new_layout Address to the new Layout
|
||||
*/
|
||||
void ipc_layout_change_event(const int mon_num, const char *old_symbol,
|
||||
const Layout *old_layout, const char *new_symbol,
|
||||
const Layout *new_layout);
|
||||
|
||||
/**
|
||||
* Send a monitor_focus_change_event to all subscribers. Should be called only
|
||||
* when the monitor focus changes.
|
||||
*
|
||||
* @param last_mon_num The index of the previously selected monitor
|
||||
* @param new_mon_num The index of the newly selected monitor
|
||||
*/
|
||||
void ipc_monitor_focus_change_event(const int last_mon_num,
|
||||
const int new_mon_num);
|
||||
|
||||
/**
|
||||
* Send a focused_title_change_event to all subscribers. Should only be called
|
||||
* if a selected client has a title change.
|
||||
*
|
||||
* @param mon_num Index of the client's monitor
|
||||
* @param client_id Window XID of client
|
||||
* @param old_name Old name of the client window
|
||||
* @param new_name New name of the client window
|
||||
*/
|
||||
void ipc_focused_title_change_event(const int mon_num, const Window client_id,
|
||||
const char *old_name, const char *new_name);
|
||||
|
||||
/**
|
||||
* Send a focused_state_change_event to all subscribers. Should only be called
|
||||
* if a selected client has a state change.
|
||||
*
|
||||
* @param mon_num Index of the client's monitor
|
||||
* @param client_id Window XID of client
|
||||
* @param old_state Old state of the client
|
||||
* @param new_state New state of the client
|
||||
*/
|
||||
void ipc_focused_state_change_event(const int mon_num, const Window client_id,
|
||||
const ClientState *old_state,
|
||||
const ClientState *new_state);
|
||||
/**
|
||||
* Check to see if an event has occured and call the *_change_event functions
|
||||
* accordingly
|
||||
*
|
||||
* @param mons Address of Monitor pointing to start of linked list
|
||||
* @param lastselmon Address of pointer to previously selected monitor
|
||||
* @param selmon Address of selected Monitor
|
||||
*/
|
||||
void ipc_send_events(Monitor *mons, Monitor **lastselmon, Monitor *selmon);
|
||||
|
||||
/**
|
||||
* Handle an epoll event caused by a registered IPC client. Read, process, and
|
||||
* handle any received messages from clients. Write pending buffer to client if
|
||||
* the client is ready to receive messages. Drop clients that have sent an
|
||||
* EPOLLHUP.
|
||||
*
|
||||
* @param ev Associated epoll event returned by epoll_wait
|
||||
* @param mons Address of Monitor pointing to start of linked list
|
||||
* @param selmon Address of selected Monitor
|
||||
* @param lastselmon Address of pointer to previously selected monitor
|
||||
* @param tags Array of tag names
|
||||
* @param tags_len Length of tags array
|
||||
* @param layouts Array of available layouts
|
||||
* @param layouts_len Length of layouts array
|
||||
*
|
||||
* @return 0 if event was successfully handled, -1 on any error receiving
|
||||
* or handling incoming messages or unhandled epoll event.
|
||||
*/
|
||||
int ipc_handle_client_epoll_event(struct epoll_event *ev, Monitor *mons,
|
||||
Monitor **lastselmon, Monitor *selmon,
|
||||
const char *tags[], const int tags_len,
|
||||
const Layout *layouts, const int layouts_len);
|
||||
|
||||
/**
|
||||
* Handle an epoll event caused by the IPC socket. This function only handles an
|
||||
* EPOLLIN event indicating a new client requesting to connect to the socket.
|
||||
*
|
||||
* @param ev Associated epoll event returned by epoll_wait
|
||||
*
|
||||
* @return 0, if the event was successfully handled, -1 if not an EPOLLIN event
|
||||
* or if a new IPC client connection request could not be accepted.
|
||||
*/
|
||||
int ipc_handle_socket_epoll_event(struct epoll_event *ev);
|
||||
|
||||
#endif /* IPC_H_ */
|
49
movestack.c
Normal file
49
movestack.c
Normal file
@ -0,0 +1,49 @@
|
||||
void
|
||||
movestack(const Arg *arg) {
|
||||
Client *c = NULL, *p = NULL, *pc = NULL, *i;
|
||||
|
||||
if(arg->i > 0) {
|
||||
/* find the client after selmon->sel */
|
||||
for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
|
||||
if(!c)
|
||||
for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
|
||||
|
||||
}
|
||||
else {
|
||||
/* find the client before selmon->sel */
|
||||
for(i = selmon->clients; i != selmon->sel; i = i->next)
|
||||
if(ISVISIBLE(i) && !i->isfloating)
|
||||
c = i;
|
||||
if(!c)
|
||||
for(; i; i = i->next)
|
||||
if(ISVISIBLE(i) && !i->isfloating)
|
||||
c = i;
|
||||
}
|
||||
/* find the client before selmon->sel and c */
|
||||
for(i = selmon->clients; i && (!p || !pc); i = i->next) {
|
||||
if(i->next == selmon->sel)
|
||||
p = i;
|
||||
if(i->next == c)
|
||||
pc = i;
|
||||
}
|
||||
|
||||
/* swap c and selmon->sel selmon->clients in the selmon->clients list */
|
||||
if(c && c != selmon->sel) {
|
||||
Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next;
|
||||
selmon->sel->next = c->next==selmon->sel?c:c->next;
|
||||
c->next = temp;
|
||||
|
||||
if(p && p != c)
|
||||
p->next = c;
|
||||
if(pc && pc != selmon->sel)
|
||||
pc->next = selmon->sel;
|
||||
|
||||
if(selmon->sel == selmon->clients)
|
||||
selmon->clients = c;
|
||||
else if(c == selmon->clients)
|
||||
selmon->clients = selmon->sel;
|
||||
|
||||
arrange(selmon);
|
||||
}
|
||||
}
|
||||
|
53
patches/dwm-actualfullscreen-20191112-cb3f58a.diff
Normal file
53
patches/dwm-actualfullscreen-20191112-cb3f58a.diff
Normal file
@ -0,0 +1,53 @@
|
||||
From 3a16816a6f5d38014c2a06ce395873c545c8789a Mon Sep 17 00:00:00 2001
|
||||
From: Soenke Lambert <s.lambert@mittwald.de>
|
||||
Date: Tue, 12 Nov 2019 10:44:02 +0100
|
||||
Subject: [PATCH] Fullscreen current window with [Alt]+[Shift]+[f]
|
||||
|
||||
This actually fullscreens a window, instead of just hiding the statusbar
|
||||
and applying the monocle layout.
|
||||
---
|
||||
config.def.h | 1 +
|
||||
dwm.c | 8 ++++++++
|
||||
2 files changed, 9 insertions(+)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..8cd3204 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -78,6 +78,7 @@ static Key keys[] = {
|
||||
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
||||
{ MODKEY, XK_space, setlayout, {0} },
|
||||
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
||||
+ { MODKEY|ShiftMask, XK_f, togglefullscr, {0} },
|
||||
{ MODKEY, XK_0, view, {.ui = ~0 } },
|
||||
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
|
||||
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 4465af1..c1b899a 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -211,6 +211,7 @@ static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *);
|
||||
static void togglebar(const Arg *arg);
|
||||
static void togglefloating(const Arg *arg);
|
||||
+static void togglefullscr(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
static void toggleview(const Arg *arg);
|
||||
static void unfocus(Client *c, int setfocus);
|
||||
@@ -1719,6 +1720,13 @@ togglefloating(const Arg *arg)
|
||||
arrange(selmon);
|
||||
}
|
||||
|
||||
+void
|
||||
+togglefullscr(const Arg *arg)
|
||||
+{
|
||||
+ if(selmon->sel)
|
||||
+ setfullscreen(selmon->sel, !selmon->sel->isfullscreen);
|
||||
+}
|
||||
+
|
||||
void
|
||||
toggletag(const Arg *arg)
|
||||
{
|
||||
--
|
||||
2.17.1
|
||||
|
13
patches/dwm-alwaysfullscreen-6.1.diff
Normal file
13
patches/dwm-alwaysfullscreen-6.1.diff
Normal file
@ -0,0 +1,13 @@
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 0362114..a5cab76 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -847,7 +847,7 @@ focusstack(const Arg *arg)
|
||||
{
|
||||
Client *c = NULL, *i;
|
||||
|
||||
- if (!selmon->sel)
|
||||
+ if (!selmon->sel || selmon->sel->isfullscreen)
|
||||
return;
|
||||
if (arg->i > 0) {
|
||||
for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
|
446
patches/dwm-anybar-polybar-tray-fix-20200905-bb2e722.diff
Normal file
446
patches/dwm-anybar-polybar-tray-fix-20200905-bb2e722.diff
Normal file
@ -0,0 +1,446 @@
|
||||
From a046eabd24a430ee2a7348a807057dc7c42f7cec Mon Sep 17 00:00:00 2001
|
||||
From: mihirlad55 <mihirlad55@gmail.com>
|
||||
Date: Sat, 5 Sep 2020 00:51:33 +0000
|
||||
Subject: [PATCH] Add support for managing external status bars
|
||||
|
||||
This patch allows dwm to manage other status bars such as
|
||||
polybar/lemonbar without them needing to set override-redirect. For
|
||||
all intents and purposes, DWM treats this bar as if it were its own
|
||||
and as a result helps the status bar and DWM live in harmony.
|
||||
|
||||
This has a few advantages
|
||||
* The bar does not block fullscreen windows
|
||||
* DWM makes room for the status bar, so windows do not overlap the bar
|
||||
* The bar can be hidden/killed and DWM will not keep an unsightly gap
|
||||
where the bar was
|
||||
* DWM receives EnterNotify events when your cursor enters the bar
|
||||
|
||||
To use another status bar, set usealtbar to 1 in your config.h and set
|
||||
altbarclass to the class name (can be found using xprop) to the class
|
||||
name of your status bar. Also make sure that if your status bar will
|
||||
be displayed on top, topbar is set to 1 in your config, and if it will
|
||||
be displayed on bottom, topbar is set to 0. This patch does not
|
||||
support bars that are not docked at the top or at the bottom of your
|
||||
monitor.
|
||||
|
||||
This verison of the patch fixes handling of polybar's tray.
|
||||
|
||||
The patch is developed at https://github.com/mihirlad55/dwm-anybar
|
||||
---
|
||||
config.def.h | 4 ++
|
||||
dwm.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++----
|
||||
2 files changed, 182 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..f45211b 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -5,6 +5,10 @@ static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
static const unsigned int snap = 32; /* snap pixel */
|
||||
static const int showbar = 1; /* 0 means no bar */
|
||||
static const int topbar = 1; /* 0 means bottom bar */
|
||||
+static const int usealtbar = 1; /* 1 means use non-dwm status bar */
|
||||
+static const char *altbarclass = "Polybar"; /* Alternate bar class name */
|
||||
+static const char *alttrayname = "tray"; /* Polybar tray instance name */
|
||||
+static const char *altbarcmd = "$HOME/bar.sh"; /* Alternate bar launch command */
|
||||
static const char *fonts[] = { "monospace:size=10" };
|
||||
static const char dmenufont[] = "monospace:size=10";
|
||||
static const char col_gray1[] = "#222222";
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 9fd0286..7bb5307 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -47,8 +47,8 @@
|
||||
/* macros */
|
||||
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
|
||||
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
|
||||
-#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
|
||||
- * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
|
||||
+#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->mx+(m)->mw) - MAX((x),(m)->mx)) \
|
||||
+ * MAX(0, MIN((y)+(h),(m)->my+(m)->mh) - MAX((y),(m)->my)))
|
||||
#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
|
||||
#define LENGTH(X) (sizeof X / sizeof X[0])
|
||||
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
|
||||
@@ -116,7 +116,8 @@ struct Monitor {
|
||||
float mfact;
|
||||
int nmaster;
|
||||
int num;
|
||||
- int by; /* bar geometry */
|
||||
+ int by, bh; /* bar geometry */
|
||||
+ int tx, tw; /* bar tray geometry */
|
||||
int mx, my, mw, mh; /* screen size */
|
||||
int wx, wy, ww, wh; /* window area */
|
||||
unsigned int seltags;
|
||||
@@ -129,6 +130,7 @@ struct Monitor {
|
||||
Client *stack;
|
||||
Monitor *next;
|
||||
Window barwin;
|
||||
+ Window traywin;
|
||||
const Layout *lt[2];
|
||||
};
|
||||
|
||||
@@ -179,6 +181,8 @@ static void incnmaster(const Arg *arg);
|
||||
static void keypress(XEvent *e);
|
||||
static void killclient(const Arg *arg);
|
||||
static void manage(Window w, XWindowAttributes *wa);
|
||||
+static void managealtbar(Window win, XWindowAttributes *wa);
|
||||
+static void managetray(Window win, XWindowAttributes *wa);
|
||||
static void mappingnotify(XEvent *e);
|
||||
static void maprequest(XEvent *e);
|
||||
static void monocle(Monitor *m);
|
||||
@@ -195,6 +199,7 @@ static void resizemouse(const Arg *arg);
|
||||
static void restack(Monitor *m);
|
||||
static void run(void);
|
||||
static void scan(void);
|
||||
+static void scantray(void);
|
||||
static int sendevent(Client *c, Atom proto);
|
||||
static void sendmon(Client *c, Monitor *m);
|
||||
static void setclientstate(Client *c, long state);
|
||||
@@ -207,6 +212,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 void spawnbar();
|
||||
static void tag(const Arg *arg);
|
||||
static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *);
|
||||
@@ -216,6 +222,8 @@ static void toggletag(const Arg *arg);
|
||||
static void toggleview(const Arg *arg);
|
||||
static void unfocus(Client *c, int setfocus);
|
||||
static void unmanage(Client *c, int destroyed);
|
||||
+static void unmanagealtbar(Window w);
|
||||
+static void unmanagetray(Window w);
|
||||
static void unmapnotify(XEvent *e);
|
||||
static void updatebarpos(Monitor *m);
|
||||
static void updatebars(void);
|
||||
@@ -230,6 +238,7 @@ static void updatewmhints(Client *c);
|
||||
static void view(const Arg *arg);
|
||||
static Client *wintoclient(Window w);
|
||||
static Monitor *wintomon(Window w);
|
||||
+static int wmclasscontains(Window win, const char *class, const char *name);
|
||||
static int xerror(Display *dpy, XErrorEvent *ee);
|
||||
static int xerrordummy(Display *dpy, XErrorEvent *ee);
|
||||
static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
||||
@@ -505,8 +514,10 @@ cleanupmon(Monitor *mon)
|
||||
for (m = mons; m && m->next != mon; m = m->next);
|
||||
m->next = mon->next;
|
||||
}
|
||||
- XUnmapWindow(dpy, mon->barwin);
|
||||
- XDestroyWindow(dpy, mon->barwin);
|
||||
+ if (!usealtbar) {
|
||||
+ XUnmapWindow(dpy, mon->barwin);
|
||||
+ XDestroyWindow(dpy, mon->barwin);
|
||||
+ }
|
||||
free(mon);
|
||||
}
|
||||
|
||||
@@ -568,7 +579,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);
|
||||
+ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, m->bh);
|
||||
}
|
||||
focus(NULL);
|
||||
arrange(NULL);
|
||||
@@ -639,6 +650,7 @@ createmon(void)
|
||||
m->nmaster = nmaster;
|
||||
m->showbar = showbar;
|
||||
m->topbar = topbar;
|
||||
+ m->bh = bh;
|
||||
m->lt[0] = &layouts[0];
|
||||
m->lt[1] = &layouts[1 % LENGTH(layouts)];
|
||||
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
|
||||
@@ -649,10 +661,15 @@ void
|
||||
destroynotify(XEvent *e)
|
||||
{
|
||||
Client *c;
|
||||
+ Monitor *m;
|
||||
XDestroyWindowEvent *ev = &e->xdestroywindow;
|
||||
|
||||
if ((c = wintoclient(ev->window)))
|
||||
unmanage(c, 1);
|
||||
+ else if (usealtbar && (m = wintomon(ev->window)) && m->barwin == ev->window)
|
||||
+ unmanagealtbar(ev->window);
|
||||
+ else if (usealtbar && m->traywin == ev->window)
|
||||
+ unmanagetray(ev->window);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -696,6 +713,9 @@ dirtomon(int dir)
|
||||
void
|
||||
drawbar(Monitor *m)
|
||||
{
|
||||
+ if (usealtbar)
|
||||
+ return;
|
||||
+
|
||||
int x, w, tw = 0;
|
||||
int boxs = drw->fonts->h / 9;
|
||||
int boxw = drw->fonts->h / 6 + 2;
|
||||
@@ -1077,6 +1097,45 @@ manage(Window w, XWindowAttributes *wa)
|
||||
focus(NULL);
|
||||
}
|
||||
|
||||
+void
|
||||
+managealtbar(Window win, XWindowAttributes *wa)
|
||||
+{
|
||||
+ Monitor *m;
|
||||
+ if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height)))
|
||||
+ return;
|
||||
+
|
||||
+ m->barwin = win;
|
||||
+ m->by = wa->y;
|
||||
+ bh = m->bh = wa->height;
|
||||
+ updatebarpos(m);
|
||||
+ arrange(m);
|
||||
+ XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
|
||||
+ XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height);
|
||||
+ XMapWindow(dpy, win);
|
||||
+ XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
|
||||
+ (unsigned char *) &win, 1);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+managetray(Window win, XWindowAttributes *wa)
|
||||
+{
|
||||
+ Monitor *m;
|
||||
+ if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height)))
|
||||
+ return;
|
||||
+
|
||||
+ m->traywin = win;
|
||||
+ m->tx = wa->x;
|
||||
+ m->tw = wa->width;
|
||||
+ updatebarpos(m);
|
||||
+ arrange(m);
|
||||
+ XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
|
||||
+ XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height);
|
||||
+ XMapWindow(dpy, win);
|
||||
+ XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
|
||||
+ (unsigned char *) &win, 1);
|
||||
+}
|
||||
+
|
||||
+
|
||||
void
|
||||
mappingnotify(XEvent *e)
|
||||
{
|
||||
@@ -1097,7 +1156,9 @@ maprequest(XEvent *e)
|
||||
return;
|
||||
if (wa.override_redirect)
|
||||
return;
|
||||
- if (!wintoclient(ev->window))
|
||||
+ if (usealtbar && wmclasscontains(ev->window, altbarclass, ""))
|
||||
+ managealtbar(ev->window, &wa);
|
||||
+ else if (!wintoclient(ev->window))
|
||||
manage(ev->window, &wa);
|
||||
}
|
||||
|
||||
@@ -1393,7 +1454,9 @@ scan(void)
|
||||
if (!XGetWindowAttributes(dpy, wins[i], &wa)
|
||||
|| wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
|
||||
continue;
|
||||
- if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
|
||||
+ if (usealtbar && wmclasscontains(wins[i], altbarclass, ""))
|
||||
+ managealtbar(wins[i], &wa);
|
||||
+ else if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
|
||||
manage(wins[i], &wa);
|
||||
}
|
||||
for (i = 0; i < num; i++) { /* now the transients */
|
||||
@@ -1408,6 +1471,29 @@ scan(void)
|
||||
}
|
||||
}
|
||||
|
||||
+void
|
||||
+scantray(void)
|
||||
+{
|
||||
+ unsigned int num;
|
||||
+ Window d1, d2, *wins = NULL;
|
||||
+ XWindowAttributes wa;
|
||||
+
|
||||
+ if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
|
||||
+ for (unsigned int i = 0; i < num; i++) {
|
||||
+ if (wmclasscontains(wins[i], altbarclass, alttrayname)) {
|
||||
+ if (!XGetWindowAttributes(dpy, wins[i], &wa))
|
||||
+ break;
|
||||
+ managetray(wins[i], &wa);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (wins)
|
||||
+ XFree(wins);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
void
|
||||
sendmon(Client *c, Monitor *m)
|
||||
{
|
||||
@@ -1546,7 +1632,7 @@ setup(void)
|
||||
if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
|
||||
die("no fonts could be loaded.");
|
||||
lrpad = drw->fonts->h;
|
||||
- bh = drw->fonts->h + 2;
|
||||
+ bh = usealtbar ? 0 : drw->fonts->h + 2;
|
||||
updategeom();
|
||||
/* init atoms */
|
||||
utf8string = XInternAtom(dpy, "UTF8_STRING", False);
|
||||
@@ -1595,6 +1681,7 @@ setup(void)
|
||||
XSelectInput(dpy, root, wa.event_mask);
|
||||
grabkeys();
|
||||
focus(NULL);
|
||||
+ spawnbar();
|
||||
}
|
||||
|
||||
|
||||
@@ -1653,6 +1740,13 @@ spawn(const Arg *arg)
|
||||
}
|
||||
}
|
||||
|
||||
+void
|
||||
+spawnbar()
|
||||
+{
|
||||
+ if (*altbarcmd)
|
||||
+ system(altbarcmd);
|
||||
+}
|
||||
+
|
||||
void
|
||||
tag(const Arg *arg)
|
||||
{
|
||||
@@ -1702,9 +1796,19 @@ tile(Monitor *m)
|
||||
void
|
||||
togglebar(const Arg *arg)
|
||||
{
|
||||
+ /**
|
||||
+ * Polybar tray does not raise maprequest event. It must be manually scanned
|
||||
+ * for. Scanning it too early while the tray is being populated would give
|
||||
+ * wrong dimensions.
|
||||
+ */
|
||||
+ if (usealtbar && !selmon->traywin)
|
||||
+ scantray();
|
||||
+
|
||||
selmon->showbar = !selmon->showbar;
|
||||
updatebarpos(selmon);
|
||||
- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
|
||||
+ XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, selmon->bh);
|
||||
+ if (usealtbar)
|
||||
+ XMoveResizeWindow(dpy, selmon->traywin, selmon->tx, selmon->by, selmon->tw, selmon->bh);
|
||||
arrange(selmon);
|
||||
}
|
||||
|
||||
@@ -1787,10 +1891,41 @@ unmanage(Client *c, int destroyed)
|
||||
arrange(m);
|
||||
}
|
||||
|
||||
+void
|
||||
+unmanagealtbar(Window w)
|
||||
+{
|
||||
+ Monitor *m = wintomon(w);
|
||||
+
|
||||
+ if (!m)
|
||||
+ return;
|
||||
+
|
||||
+ m->barwin = 0;
|
||||
+ m->by = 0;
|
||||
+ m->bh = 0;
|
||||
+ updatebarpos(m);
|
||||
+ arrange(m);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+unmanagetray(Window w)
|
||||
+{
|
||||
+ Monitor *m = wintomon(w);
|
||||
+
|
||||
+ if (!m)
|
||||
+ return;
|
||||
+
|
||||
+ m->traywin = 0;
|
||||
+ m->tx = 0;
|
||||
+ m->tw = 0;
|
||||
+ updatebarpos(m);
|
||||
+ arrange(m);
|
||||
+}
|
||||
+
|
||||
void
|
||||
unmapnotify(XEvent *e)
|
||||
{
|
||||
Client *c;
|
||||
+ Monitor *m;
|
||||
XUnmapEvent *ev = &e->xunmap;
|
||||
|
||||
if ((c = wintoclient(ev->window))) {
|
||||
@@ -1798,12 +1933,18 @@ unmapnotify(XEvent *e)
|
||||
setclientstate(c, WithdrawnState);
|
||||
else
|
||||
unmanage(c, 0);
|
||||
- }
|
||||
+ } else if (usealtbar && (m = wintomon(ev->window)) && m->barwin == ev->window)
|
||||
+ unmanagealtbar(ev->window);
|
||||
+ else if (usealtbar && m->traywin == ev->window)
|
||||
+ unmanagetray(ev->window);
|
||||
}
|
||||
|
||||
void
|
||||
updatebars(void)
|
||||
{
|
||||
+ if (usealtbar)
|
||||
+ return;
|
||||
+
|
||||
Monitor *m;
|
||||
XSetWindowAttributes wa = {
|
||||
.override_redirect = True,
|
||||
@@ -1829,11 +1970,11 @@ updatebarpos(Monitor *m)
|
||||
m->wy = m->my;
|
||||
m->wh = m->mh;
|
||||
if (m->showbar) {
|
||||
- m->wh -= bh;
|
||||
+ m->wh -= m->bh;
|
||||
m->by = m->topbar ? m->wy : m->wy + m->wh;
|
||||
- m->wy = m->topbar ? m->wy + bh : m->wy;
|
||||
+ m->wy = m->topbar ? m->wy + m->bh : m->wy;
|
||||
} else
|
||||
- m->by = -bh;
|
||||
+ m->by = -m->bh;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2070,13 +2211,35 @@ wintomon(Window w)
|
||||
if (w == root && getrootptr(&x, &y))
|
||||
return recttomon(x, y, 1, 1);
|
||||
for (m = mons; m; m = m->next)
|
||||
- if (w == m->barwin)
|
||||
+ if (w == m->barwin || w == m->traywin)
|
||||
return m;
|
||||
if ((c = wintoclient(w)))
|
||||
return c->mon;
|
||||
return selmon;
|
||||
}
|
||||
|
||||
+int
|
||||
+wmclasscontains(Window win, const char *class, const char *name)
|
||||
+{
|
||||
+ XClassHint ch = { NULL, NULL };
|
||||
+ int res = 1;
|
||||
+
|
||||
+ if (XGetClassHint(dpy, win, &ch)) {
|
||||
+ if (ch.res_name && strstr(ch.res_name, name) == NULL)
|
||||
+ res = 0;
|
||||
+ if (ch.res_class && strstr(ch.res_class, class) == NULL)
|
||||
+ res = 0;
|
||||
+ } else
|
||||
+ res = 0;
|
||||
+
|
||||
+ if (ch.res_class)
|
||||
+ XFree(ch.res_class);
|
||||
+ if (ch.res_name)
|
||||
+ XFree(ch.res_name);
|
||||
+
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
/* There's no way to check accesses to destroyed windows, thus those cases are
|
||||
* ignored (especially on UnmapNotify's). Other types of errors call Xlibs
|
||||
* default error handler, which may call exit. */
|
||||
--
|
||||
2.28.0
|
||||
|
56
patches/dwm-aspectresize-6.2.diff
Normal file
56
patches/dwm-aspectresize-6.2.diff
Normal file
@ -0,0 +1,56 @@
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..2fcc30d 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -72,6 +72,8 @@ static Key keys[] = {
|
||||
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
||||
{ MODKEY, XK_Return, zoom, {0} },
|
||||
{ MODKEY, XK_Tab, view, {0} },
|
||||
+ { MODKEY|ShiftMask, XK_j, aspectresize, {.i = +24} },
|
||||
+ { MODKEY|ShiftMask, XK_k, aspectresize, {.i = -24} },
|
||||
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
|
||||
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
||||
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 9fd0286..6a02119 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -146,6 +146,7 @@ static void applyrules(Client *c);
|
||||
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
|
||||
static void arrange(Monitor *m);
|
||||
static void arrangemon(Monitor *m);
|
||||
+static void aspectresize(const Arg *arg);
|
||||
static void attach(Client *c);
|
||||
static void attachstack(Client *c);
|
||||
static void buttonpress(XEvent *e);
|
||||
@@ -400,6 +401,30 @@ arrangemon(Monitor *m)
|
||||
m->lt[m->sellt]->arrange(m);
|
||||
}
|
||||
|
||||
+void
|
||||
+aspectresize(const Arg *arg) {
|
||||
+ /* only floating windows can be moved */
|
||||
+ Client *c;
|
||||
+ c = selmon->sel;
|
||||
+ float ratio;
|
||||
+ int w, h,nw, nh;
|
||||
+
|
||||
+ if (!c || !arg)
|
||||
+ return;
|
||||
+ if (selmon->lt[selmon->sellt]->arrange && !c->isfloating)
|
||||
+ return;
|
||||
+
|
||||
+ ratio = (float)c->w / (float)c->h;
|
||||
+ h = arg->i;
|
||||
+ w = (int)(ratio * h);
|
||||
+
|
||||
+ nw = c->w + w;
|
||||
+ nh = c->h + h;
|
||||
+
|
||||
+ XRaiseWindow(dpy, c->win);
|
||||
+ resize(c, c->x, c->y, nw, nh, True);
|
||||
+}
|
||||
+
|
||||
void
|
||||
attach(Client *c)
|
||||
{
|
199
patches/dwm-attachbelow-toggleable-6.2.diff
Normal file
199
patches/dwm-attachbelow-toggleable-6.2.diff
Normal file
@ -0,0 +1,199 @@
|
||||
From ee036687ed9e1bb973b9e34694a57cf5dd67652d Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Hodgson <git@jonathanh.co.uk>
|
||||
Date: Mon, 6 May 2019 18:34:40 +0100
|
||||
Subject: [PATCH 1/4] Adds attach below option
|
||||
|
||||
---
|
||||
config.def.h | 1 +
|
||||
dwm.c | 31 ++++++++++++++++++++++++++++---
|
||||
2 files changed, 29 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..51ad933 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -35,6 +35,7 @@ static const Rule rules[] = {
|
||||
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 int attachbelow = 1; /* 1 means attach at the end */
|
||||
|
||||
static const Layout layouts[] = {
|
||||
/* symbol arrange function */
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 4465af1..bd715a2 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -147,6 +147,7 @@ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interac
|
||||
static void arrange(Monitor *m);
|
||||
static void arrangemon(Monitor *m);
|
||||
static void attach(Client *c);
|
||||
+static void attachBelow(Client *c);
|
||||
static void attachstack(Client *c);
|
||||
static void buttonpress(XEvent *e);
|
||||
static void checkotherwm(void);
|
||||
@@ -405,6 +406,21 @@ attach(Client *c)
|
||||
c->next = c->mon->clients;
|
||||
c->mon->clients = c;
|
||||
}
|
||||
+void
|
||||
+attachBelow(Client *c)
|
||||
+{
|
||||
+ //If there is nothing on the monitor or the selected client is floating, attach as normal
|
||||
+ if(c->mon->sel == NULL || c->mon->sel == c || c->mon->sel->isfloating) {
|
||||
+ attach(c);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ //Set the new client's next property to the same as the currently selected clients next
|
||||
+ c->next = c->mon->sel->next;
|
||||
+ //Set the currently selected clients next property to the new client
|
||||
+ c->mon->sel->next = c;
|
||||
+
|
||||
+}
|
||||
|
||||
void
|
||||
attachstack(Client *c)
|
||||
@@ -1062,7 +1078,10 @@ manage(Window w, XWindowAttributes *wa)
|
||||
c->isfloating = c->oldstate = trans != None || c->isfixed;
|
||||
if (c->isfloating)
|
||||
XRaiseWindow(dpy, c->win);
|
||||
- attach(c);
|
||||
+ if( attachbelow )
|
||||
+ attachBelow(c);
|
||||
+ else
|
||||
+ attach(c);
|
||||
attachstack(c);
|
||||
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
|
||||
(unsigned char *) &(c->win), 1);
|
||||
@@ -1417,7 +1436,10 @@ sendmon(Client *c, Monitor *m)
|
||||
detachstack(c);
|
||||
c->mon = m;
|
||||
c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
|
||||
- attach(c);
|
||||
+ if( attachbelow )
|
||||
+ attachBelow(c);
|
||||
+ else
|
||||
+ attach(c);
|
||||
attachstack(c);
|
||||
focus(NULL);
|
||||
arrange(NULL);
|
||||
@@ -1897,7 +1919,10 @@ updategeom(void)
|
||||
m->clients = c->next;
|
||||
detachstack(c);
|
||||
c->mon = mons;
|
||||
- attach(c);
|
||||
+ if( attachbelow )
|
||||
+ attachBelow(c);
|
||||
+ else
|
||||
+ attach(c);
|
||||
attachstack(c);
|
||||
}
|
||||
if (m == selmon)
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
||||
From e212c1d8cbdcc56c33c717131dfa7c1689e27e9f Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Hodgson <git@jonathanh.co.uk>
|
||||
Date: Mon, 6 May 2019 19:27:57 +0100
|
||||
Subject: [PATCH 2/4] fixes comment
|
||||
|
||||
---
|
||||
config.def.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 51ad933..cb8053a 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -35,7 +35,7 @@ static const Rule rules[] = {
|
||||
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 int attachbelow = 1; /* 1 means attach at the end */
|
||||
+static const int attachbelow = 1; /* 1 means attach after the currently active window */
|
||||
|
||||
static const Layout layouts[] = {
|
||||
/* symbol arrange function */
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
||||
From 7568ea3f8756e7e82b30c4943556ae646a445d1c Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Hodgson <git@jonathanh.co.uk>
|
||||
Date: Mon, 6 May 2019 20:00:30 +0100
|
||||
Subject: [PATCH 3/4] Makes changes to man page to reflect attach below patch
|
||||
|
||||
---
|
||||
dwm.1 | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/dwm.1 b/dwm.1
|
||||
index 13b3729..fb6e76c 100644
|
||||
--- a/dwm.1
|
||||
+++ b/dwm.1
|
||||
@@ -29,6 +29,9 @@ color. The tags of the focused window are indicated with a filled square in the
|
||||
top left corner. The tags which are applied to one or more windows are
|
||||
indicated with an empty square in the top left corner.
|
||||
.P
|
||||
+The attach below patch makes newly spawned windows attach after the currently
|
||||
+selected window
|
||||
+.P
|
||||
dwm draws a small border around windows to indicate the focus state.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
||||
From 362b95a5b9f91673f27f3e3343b5738df3c9d6e9 Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Hodgson <git@jonathanh.co.uk>
|
||||
Date: Sun, 2 Jun 2019 15:11:57 +0100
|
||||
Subject: [PATCH 4/4] Allows attach below to be toggled
|
||||
|
||||
---
|
||||
config.def.h | 2 +-
|
||||
dwm.c | 6 ++++++
|
||||
2 files changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index cb8053a..b4d35aa 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -35,7 +35,7 @@ static const Rule rules[] = {
|
||||
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 int attachbelow = 1; /* 1 means attach after the currently active window */
|
||||
+static int attachbelow = 1; /* 1 means attach after the currently active window */
|
||||
|
||||
static const Layout layouts[] = {
|
||||
/* symbol arrange function */
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index bd715a2..5d88653 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -148,6 +148,7 @@ static void arrange(Monitor *m);
|
||||
static void arrangemon(Monitor *m);
|
||||
static void attach(Client *c);
|
||||
static void attachBelow(Client *c);
|
||||
+static void toggleAttachBelow();
|
||||
static void attachstack(Client *c);
|
||||
static void buttonpress(XEvent *e);
|
||||
static void checkotherwm(void);
|
||||
@@ -422,6 +423,11 @@ attachBelow(Client *c)
|
||||
|
||||
}
|
||||
|
||||
+void toggleAttachBelow()
|
||||
+{
|
||||
+ attachbelow = !attachbelow;
|
||||
+}
|
||||
+
|
||||
void
|
||||
attachstack(Client *c)
|
||||
{
|
||||
--
|
||||
2.21.0
|
||||
|
35
patches/dwm-autoresize-6.1.diff
Normal file
35
patches/dwm-autoresize-6.1.diff
Normal file
@ -0,0 +1,35 @@
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 0362114..e4e8514 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -92,7 +92,7 @@ struct Client {
|
||||
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
|
||||
int bw, oldbw;
|
||||
unsigned int tags;
|
||||
- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
|
||||
+ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, needresize;
|
||||
Client *next;
|
||||
Client *snext;
|
||||
Monitor *mon;
|
||||
@@ -621,6 +621,8 @@ configurerequest(XEvent *e)
|
||||
configure(c);
|
||||
if (ISVISIBLE(c))
|
||||
XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
|
||||
+ else
|
||||
+ c->needresize = 1;
|
||||
} else
|
||||
configure(c);
|
||||
} else {
|
||||
@@ -1611,6 +1613,12 @@ showhide(Client *c)
|
||||
if (ISVISIBLE(c)) {
|
||||
/* show clients top down */
|
||||
XMoveWindow(dpy, c->win, c->x, c->y);
|
||||
+ if (c->needresize) {
|
||||
+ c->needresize = 0;
|
||||
+ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
|
||||
+ } else {
|
||||
+ XMoveWindow(dpy, c->win, c->x, c->y);
|
||||
+ }
|
||||
if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
|
||||
resize(c, c->x, c->y, c->w, c->h, 0);
|
||||
showhide(c->snext);
|
90
patches/dwm-center-6.2.diff
Normal file
90
patches/dwm-center-6.2.diff
Normal file
@ -0,0 +1,90 @@
|
||||
From 69f91089d9248fa9695eb925956e255a215171b8 Mon Sep 17 00:00:00 2001
|
||||
From: bakkeby <bakkeby@gmail.com>
|
||||
Date: Tue, 7 Apr 2020 12:29:08 +0200
|
||||
Subject: [PATCH] Adding 6.2 center patch with multi-monitor fix and
|
||||
auto-centering of floating popup windows
|
||||
---
|
||||
config.def.h | 6 +++---
|
||||
dwm.c | 13 +++++++++++--
|
||||
2 files changed, 14 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..44b46e5 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -26,9 +26,9 @@ static const Rule rules[] = {
|
||||
* 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 },
|
||||
+ /* class instance title tags mask iscentered isfloating monitor */
|
||||
+ { "Gimp", NULL, NULL, 0, 0, 1, -1 },
|
||||
+ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1 },
|
||||
};
|
||||
|
||||
/* layout(s) */
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 4465af1..ab33757 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -92,7 +92,7 @@ struct Client {
|
||||
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
|
||||
int bw, oldbw;
|
||||
unsigned int tags;
|
||||
- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
|
||||
+ int isfixed, iscentered, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
|
||||
Client *next;
|
||||
Client *snext;
|
||||
Monitor *mon;
|
||||
@@ -137,6 +137,7 @@ typedef struct {
|
||||
const char *instance;
|
||||
const char *title;
|
||||
unsigned int tags;
|
||||
+ int iscentered;
|
||||
int isfloating;
|
||||
int monitor;
|
||||
} Rule;
|
||||
@@ -285,6 +286,7 @@ applyrules(Client *c)
|
||||
XClassHint ch = { NULL, NULL };
|
||||
|
||||
/* rule matching */
|
||||
+ c->iscentered = 0;
|
||||
c->isfloating = 0;
|
||||
c->tags = 0;
|
||||
XGetClassHint(dpy, c->win, &ch);
|
||||
@@ -297,6 +299,7 @@ applyrules(Client *c)
|
||||
&& (!r->class || strstr(class, r->class))
|
||||
&& (!r->instance || strstr(instance, r->instance)))
|
||||
{
|
||||
+ c->iscentered = r->iscentered;
|
||||
c->isfloating = r->isfloating;
|
||||
c->tags |= r->tags;
|
||||
for (m = mons; m && m->num != r->monitor; m = m->next);
|
||||
@@ -1056,6 +1059,10 @@ manage(Window w, XWindowAttributes *wa)
|
||||
updatewindowtype(c);
|
||||
updatesizehints(c);
|
||||
updatewmhints(c);
|
||||
+ if (c->iscentered) {
|
||||
+ c->x = c->mon->mx + (c->mon->mw - WIDTH(c)) / 2;
|
||||
+ c->y = c->mon->my + (c->mon->mh - HEIGHT(c)) / 2;
|
||||
+ }
|
||||
XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
|
||||
grabbuttons(c, 0);
|
||||
if (!c->isfloating)
|
||||
@@ -2009,8 +2016,10 @@ updatewindowtype(Client *c)
|
||||
|
||||
if (state == netatom[NetWMFullscreen])
|
||||
setfullscreen(c, 1);
|
||||
- if (wtype == netatom[NetWMWindowTypeDialog])
|
||||
+ if (wtype == netatom[NetWMWindowTypeDialog]) {
|
||||
+ c->iscentered = 1;
|
||||
c->isfloating = 1;
|
||||
+ }
|
||||
}
|
||||
|
||||
void
|
||||
--
|
||||
2.17.1
|
||||
|
117
patches/dwm-cfacts-20200913-61bb8b2.diff
Normal file
117
patches/dwm-cfacts-20200913-61bb8b2.diff
Normal file
@ -0,0 +1,117 @@
|
||||
From c32a879432573d71dec7fcb4bf68927d2f4cdf10 Mon Sep 17 00:00:00 2001
|
||||
From: iofq <cjriddz@protonmail.com>
|
||||
Date: Sat, 12 Sep 2020 22:28:09 -0500
|
||||
Subject: [PATCH] Fixed 'cfacts' patch failure due to upstream commit
|
||||
'f09418bbb...'
|
||||
|
||||
---
|
||||
config.def.h | 3 +++
|
||||
dwm.c | 34 +++++++++++++++++++++++++++++++---
|
||||
2 files changed, 34 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..83910c1 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -70,6 +70,9 @@ static Key keys[] = {
|
||||
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
||||
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
||||
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
||||
+ { MODKEY|ShiftMask, XK_h, setcfact, {.f = +0.25} },
|
||||
+ { MODKEY|ShiftMask, XK_l, setcfact, {.f = -0.25} },
|
||||
+ { MODKEY|ShiftMask, XK_o, setcfact, {.f = 0.00} },
|
||||
{ MODKEY, XK_Return, zoom, {0} },
|
||||
{ MODKEY, XK_Tab, view, {0} },
|
||||
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 664c527..5233229 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -87,6 +87,7 @@ typedef struct Client Client;
|
||||
struct Client {
|
||||
char name[256];
|
||||
float mina, maxa;
|
||||
+ float cfact;
|
||||
int x, y, w, h;
|
||||
int oldx, oldy, oldw, oldh;
|
||||
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
|
||||
@@ -201,6 +202,7 @@ static void setclientstate(Client *c, long state);
|
||||
static void setfocus(Client *c);
|
||||
static void setfullscreen(Client *c, int fullscreen);
|
||||
static void setlayout(const Arg *arg);
|
||||
+static void setcfact(const Arg *arg);
|
||||
static void setmfact(const Arg *arg);
|
||||
static void setup(void);
|
||||
static void seturgent(Client *c, int urg);
|
||||
@@ -1030,6 +1032,7 @@ manage(Window w, XWindowAttributes *wa)
|
||||
c->w = c->oldw = wa->width;
|
||||
c->h = c->oldh = wa->height;
|
||||
c->oldbw = wa->border_width;
|
||||
+ c->cfact = 1.0;
|
||||
|
||||
updatetitle(c);
|
||||
if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
|
||||
@@ -1512,6 +1515,23 @@ setlayout(const Arg *arg)
|
||||
drawbar(selmon);
|
||||
}
|
||||
|
||||
+void setcfact(const Arg *arg) {
|
||||
+ float f;
|
||||
+ Client *c;
|
||||
+
|
||||
+ c = selmon->sel;
|
||||
+
|
||||
+ if(!arg || !c || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+ f = arg->f + c->cfact;
|
||||
+ if(arg->f == 0.0)
|
||||
+ f = 1.0;
|
||||
+ else if(f < 0.25 || f > 4.0)
|
||||
+ return;
|
||||
+ c->cfact = f;
|
||||
+ arrange(selmon);
|
||||
+}
|
||||
+
|
||||
/* arg > 1.0 will set mfact absolutely */
|
||||
void
|
||||
setmfact(const Arg *arg)
|
||||
@@ -1675,9 +1695,15 @@ void
|
||||
tile(Monitor *m)
|
||||
{
|
||||
unsigned int i, n, h, mw, my, ty;
|
||||
+ float mfacts = 0, sfacts = 0;
|
||||
Client *c;
|
||||
|
||||
- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
|
||||
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) {
|
||||
+ if (n < m->nmaster)
|
||||
+ mfacts += c->cfact;
|
||||
+ else
|
||||
+ sfacts += c->cfact;
|
||||
+ }
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
@@ -1687,15 +1713,17 @@ tile(Monitor *m)
|
||||
mw = m->ww;
|
||||
for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
if (i < m->nmaster) {
|
||||
- h = (m->wh - my) / (MIN(n, m->nmaster) - i);
|
||||
+ h = (m->wh - my) * (c->cfact / mfacts);
|
||||
resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0);
|
||||
if (my + HEIGHT(c) < m->wh)
|
||||
my += HEIGHT(c);
|
||||
+ mfacts -= c->cfact;
|
||||
} else {
|
||||
- h = (m->wh - ty) / (n - i);
|
||||
+ h = (m->wh - ty) * (c->cfact / sfacts);
|
||||
resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0);
|
||||
if (ty + HEIGHT(c) < m->wh)
|
||||
ty += HEIGHT(c);
|
||||
+ sfacts -= c->cfact;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.28.0
|
||||
|
992
patches/dwm-cfacts-vanitygaps-6.2.diff
Normal file
992
patches/dwm-cfacts-vanitygaps-6.2.diff
Normal file
@ -0,0 +1,992 @@
|
||||
From 051e4de72079bb0b8e50d2faa61b9a0ef36434b5 Mon Sep 17 00:00:00 2001
|
||||
From: bakkeby <bakkeby@gmail.com>
|
||||
Date: Fri, 8 May 2020 16:51:00 +0200
|
||||
Subject: [PATCH 2/2] vanitygaps - adds gaps to layouts
|
||||
|
||||
This patch differentiates between inner and outer gaps as well as
|
||||
horizontal and vertical gaps.
|
||||
|
||||
The logic of these layouts also aims to be pixel perfect by ensuring
|
||||
an even split of the available space and re-distributing the remainder
|
||||
among the available clients.
|
||||
---
|
||||
config.def.h | 38 ++-
|
||||
dwm.c | 43 +--
|
||||
vanitygaps.c | 822 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 867 insertions(+), 36 deletions(-)
|
||||
create mode 100644 vanitygaps.c
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 83910c1..91a9cfc 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -3,6 +3,11 @@
|
||||
/* appearance */
|
||||
static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
static const unsigned int snap = 32; /* snap pixel */
|
||||
+static const unsigned int gappih = 20; /* horiz inner gap between windows */
|
||||
+static const unsigned int gappiv = 10; /* vert inner gap between windows */
|
||||
+static const unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */
|
||||
+static const unsigned int gappov = 30; /* vert outer gap between windows and screen edge */
|
||||
+static int smartgaps = 0; /* 1 means no outer gap when there is only one window */
|
||||
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" };
|
||||
@@ -36,11 +41,26 @@ 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 */
|
||||
|
||||
+#define FORCE_VSPLIT 1 /* nrowgrid layout: force two clients to always split vertically */
|
||||
+#include "vanitygaps.c"
|
||||
+
|
||||
static const Layout layouts[] = {
|
||||
/* symbol arrange function */
|
||||
{ "[]=", tile }, /* first entry is default */
|
||||
- { "><>", NULL }, /* no layout function means floating behavior */
|
||||
{ "[M]", monocle },
|
||||
+ { "[@]", spiral },
|
||||
+ { "[\\]", dwindle },
|
||||
+ { "H[]", deck },
|
||||
+ { "TTT", bstack },
|
||||
+ { "===", bstackhoriz },
|
||||
+ { "HHH", grid },
|
||||
+ { "###", nrowgrid },
|
||||
+ { "---", horizgrid },
|
||||
+ { ":::", gaplessgrid },
|
||||
+ { "|M|", centeredmaster },
|
||||
+ { ">M>", centeredfloatingmaster },
|
||||
+ { "><>", NULL }, /* no layout function means floating behavior */
|
||||
+ { NULL, NULL },
|
||||
};
|
||||
|
||||
/* key definitions */
|
||||
@@ -74,6 +94,22 @@ static Key keys[] = {
|
||||
{ MODKEY|ShiftMask, XK_l, setcfact, {.f = -0.25} },
|
||||
{ MODKEY|ShiftMask, XK_o, setcfact, {.f = 0.00} },
|
||||
{ MODKEY, XK_Return, zoom, {0} },
|
||||
+ { MODKEY|Mod4Mask, XK_u, incrgaps, {.i = +1 } },
|
||||
+ { MODKEY|Mod4Mask|ShiftMask, XK_u, incrgaps, {.i = -1 } },
|
||||
+ { MODKEY|Mod4Mask, XK_i, incrigaps, {.i = +1 } },
|
||||
+ { MODKEY|Mod4Mask|ShiftMask, XK_i, incrigaps, {.i = -1 } },
|
||||
+ { MODKEY|Mod4Mask, XK_o, incrogaps, {.i = +1 } },
|
||||
+ { MODKEY|Mod4Mask|ShiftMask, XK_o, incrogaps, {.i = -1 } },
|
||||
+ { MODKEY|Mod4Mask, XK_6, incrihgaps, {.i = +1 } },
|
||||
+ { MODKEY|Mod4Mask|ShiftMask, XK_6, incrihgaps, {.i = -1 } },
|
||||
+ { MODKEY|Mod4Mask, XK_7, incrivgaps, {.i = +1 } },
|
||||
+ { MODKEY|Mod4Mask|ShiftMask, XK_7, incrivgaps, {.i = -1 } },
|
||||
+ { MODKEY|Mod4Mask, XK_8, incrohgaps, {.i = +1 } },
|
||||
+ { MODKEY|Mod4Mask|ShiftMask, XK_8, incrohgaps, {.i = -1 } },
|
||||
+ { MODKEY|Mod4Mask, XK_9, incrovgaps, {.i = +1 } },
|
||||
+ { MODKEY|Mod4Mask|ShiftMask, XK_9, incrovgaps, {.i = -1 } },
|
||||
+ { MODKEY|Mod4Mask, XK_0, togglegaps, {0} },
|
||||
+ { MODKEY|Mod4Mask|ShiftMask, XK_0, defaultgaps, {0} },
|
||||
{ MODKEY, XK_Tab, view, {0} },
|
||||
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
|
||||
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 5592c57..7d503cb 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -120,6 +120,10 @@ struct Monitor {
|
||||
int by; /* bar geometry */
|
||||
int mx, my, mw, mh; /* screen size */
|
||||
int wx, wy, ww, wh; /* window area */
|
||||
+ int gappih; /* horizontal gap between windows */
|
||||
+ int gappiv; /* vertical gap between windows */
|
||||
+ int gappoh; /* horizontal outer gaps */
|
||||
+ int gappov; /* vertical outer gaps */
|
||||
unsigned int seltags;
|
||||
unsigned int sellt;
|
||||
unsigned int tagset[2];
|
||||
@@ -210,7 +214,6 @@ static void sigchld(int unused);
|
||||
static void spawn(const Arg *arg);
|
||||
static void tag(const Arg *arg);
|
||||
static void tagmon(const Arg *arg);
|
||||
-static void tile(Monitor *);
|
||||
static void togglebar(const Arg *arg);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
@@ -640,6 +643,10 @@ createmon(void)
|
||||
m->nmaster = nmaster;
|
||||
m->showbar = showbar;
|
||||
m->topbar = topbar;
|
||||
+ m->gappih = gappih;
|
||||
+ m->gappiv = gappiv;
|
||||
+ m->gappoh = gappoh;
|
||||
+ m->gappov = gappov;
|
||||
m->lt[0] = &layouts[0];
|
||||
m->lt[1] = &layouts[1 % LENGTH(layouts)];
|
||||
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
|
||||
@@ -1691,40 +1698,6 @@ tagmon(const Arg *arg)
|
||||
sendmon(selmon->sel, dirtomon(arg->i));
|
||||
}
|
||||
|
||||
-void
|
||||
-tile(Monitor *m)
|
||||
-{
|
||||
- unsigned int i, n, h, mw, my, ty;
|
||||
- float mfacts = 0, sfacts = 0;
|
||||
- Client *c;
|
||||
-
|
||||
- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) {
|
||||
- if (n < m->nmaster)
|
||||
- mfacts += c->cfact;
|
||||
- else
|
||||
- sfacts += c->cfact;
|
||||
- }
|
||||
- if (n == 0)
|
||||
- return;
|
||||
-
|
||||
- if (n > m->nmaster)
|
||||
- mw = m->nmaster ? m->ww * m->mfact : 0;
|
||||
- else
|
||||
- mw = m->ww;
|
||||
- for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
- if (i < m->nmaster) {
|
||||
- h = (m->wh - my) * (c->cfact / mfacts);
|
||||
- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0);
|
||||
- my += HEIGHT(c);
|
||||
- mfacts -= c->cfact;
|
||||
- } else {
|
||||
- h = (m->wh - ty) * (c->cfact / sfacts);
|
||||
- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0);
|
||||
- ty += HEIGHT(c);
|
||||
- sfacts -= c->cfact;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
void
|
||||
togglebar(const Arg *arg)
|
||||
{
|
||||
diff --git a/vanitygaps.c b/vanitygaps.c
|
||||
new file mode 100644
|
||||
index 0000000..1a816b6
|
||||
--- /dev/null
|
||||
+++ b/vanitygaps.c
|
||||
@@ -0,0 +1,822 @@
|
||||
+/* Key binding functions */
|
||||
+static void defaultgaps(const Arg *arg);
|
||||
+static void incrgaps(const Arg *arg);
|
||||
+static void incrigaps(const Arg *arg);
|
||||
+static void incrogaps(const Arg *arg);
|
||||
+static void incrohgaps(const Arg *arg);
|
||||
+static void incrovgaps(const Arg *arg);
|
||||
+static void incrihgaps(const Arg *arg);
|
||||
+static void incrivgaps(const Arg *arg);
|
||||
+static void togglegaps(const Arg *arg);
|
||||
+/* Layouts (delete the ones you do not need) */
|
||||
+static void bstack(Monitor *m);
|
||||
+static void bstackhoriz(Monitor *m);
|
||||
+static void centeredmaster(Monitor *m);
|
||||
+static void centeredfloatingmaster(Monitor *m);
|
||||
+static void deck(Monitor *m);
|
||||
+static void dwindle(Monitor *m);
|
||||
+static void fibonacci(Monitor *m, int s);
|
||||
+static void grid(Monitor *m);
|
||||
+static void nrowgrid(Monitor *m);
|
||||
+static void spiral(Monitor *m);
|
||||
+static void tile(Monitor *m);
|
||||
+/* Internals */
|
||||
+static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc);
|
||||
+static void getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr);
|
||||
+static void setgaps(int oh, int ov, int ih, int iv);
|
||||
+
|
||||
+/* Settings */
|
||||
+#if !PERTAG_PATCH
|
||||
+static int enablegaps = 1;
|
||||
+#endif // PERTAG_PATCH
|
||||
+
|
||||
+void
|
||||
+setgaps(int oh, int ov, int ih, int iv)
|
||||
+{
|
||||
+ if (oh < 0) oh = 0;
|
||||
+ if (ov < 0) ov = 0;
|
||||
+ if (ih < 0) ih = 0;
|
||||
+ if (iv < 0) iv = 0;
|
||||
+
|
||||
+ selmon->gappoh = oh;
|
||||
+ selmon->gappov = ov;
|
||||
+ selmon->gappih = ih;
|
||||
+ selmon->gappiv = iv;
|
||||
+ arrange(selmon);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+togglegaps(const Arg *arg)
|
||||
+{
|
||||
+ #if PERTAG_PATCH
|
||||
+ selmon->pertag->enablegaps[selmon->pertag->curtag] = !selmon->pertag->enablegaps[selmon->pertag->curtag];
|
||||
+ #else
|
||||
+ enablegaps = !enablegaps;
|
||||
+ #endif // PERTAG_PATCH
|
||||
+ arrange(NULL);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+defaultgaps(const Arg *arg)
|
||||
+{
|
||||
+ setgaps(gappoh, gappov, gappih, gappiv);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+incrgaps(const Arg *arg)
|
||||
+{
|
||||
+ setgaps(
|
||||
+ selmon->gappoh + arg->i,
|
||||
+ selmon->gappov + arg->i,
|
||||
+ selmon->gappih + arg->i,
|
||||
+ selmon->gappiv + arg->i
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+incrigaps(const Arg *arg)
|
||||
+{
|
||||
+ setgaps(
|
||||
+ selmon->gappoh,
|
||||
+ selmon->gappov,
|
||||
+ selmon->gappih + arg->i,
|
||||
+ selmon->gappiv + arg->i
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+incrogaps(const Arg *arg)
|
||||
+{
|
||||
+ setgaps(
|
||||
+ selmon->gappoh + arg->i,
|
||||
+ selmon->gappov + arg->i,
|
||||
+ selmon->gappih,
|
||||
+ selmon->gappiv
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+incrohgaps(const Arg *arg)
|
||||
+{
|
||||
+ setgaps(
|
||||
+ selmon->gappoh + arg->i,
|
||||
+ selmon->gappov,
|
||||
+ selmon->gappih,
|
||||
+ selmon->gappiv
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+incrovgaps(const Arg *arg)
|
||||
+{
|
||||
+ setgaps(
|
||||
+ selmon->gappoh,
|
||||
+ selmon->gappov + arg->i,
|
||||
+ selmon->gappih,
|
||||
+ selmon->gappiv
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+incrihgaps(const Arg *arg)
|
||||
+{
|
||||
+ setgaps(
|
||||
+ selmon->gappoh,
|
||||
+ selmon->gappov,
|
||||
+ selmon->gappih + arg->i,
|
||||
+ selmon->gappiv
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+incrivgaps(const Arg *arg)
|
||||
+{
|
||||
+ setgaps(
|
||||
+ selmon->gappoh,
|
||||
+ selmon->gappov,
|
||||
+ selmon->gappih,
|
||||
+ selmon->gappiv + arg->i
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc)
|
||||
+{
|
||||
+ unsigned int n, oe, ie;
|
||||
+ #if PERTAG_PATCH
|
||||
+ oe = ie = selmon->pertag->enablegaps[selmon->pertag->curtag];
|
||||
+ #else
|
||||
+ oe = ie = enablegaps;
|
||||
+ #endif // PERTAG_PATCH
|
||||
+ Client *c;
|
||||
+
|
||||
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
|
||||
+ if (smartgaps && n == 1) {
|
||||
+ oe = 0; // outer gaps disabled when only one client
|
||||
+ }
|
||||
+
|
||||
+ *oh = m->gappoh*oe; // outer horizontal gap
|
||||
+ *ov = m->gappov*oe; // outer vertical gap
|
||||
+ *ih = m->gappih*ie; // inner horizontal gap
|
||||
+ *iv = m->gappiv*ie; // inner vertical gap
|
||||
+ *nc = n; // number of clients
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr)
|
||||
+{
|
||||
+ unsigned int n;
|
||||
+ float mfacts = 0, sfacts = 0;
|
||||
+ int mtotal = 0, stotal = 0;
|
||||
+ Client *c;
|
||||
+
|
||||
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
|
||||
+ if (n < m->nmaster)
|
||||
+ mfacts += c->cfact;
|
||||
+ else
|
||||
+ sfacts += c->cfact;
|
||||
+
|
||||
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
|
||||
+ if (n < m->nmaster)
|
||||
+ mtotal += msize * (c->cfact / mfacts);
|
||||
+ else
|
||||
+ stotal += ssize * (c->cfact / sfacts);
|
||||
+
|
||||
+ *mf = mfacts; // total factor of master area
|
||||
+ *sf = sfacts; // total factor of stack area
|
||||
+ *mr = msize - mtotal; // the remainder (rest) of pixels after a cfacts master split
|
||||
+ *sr = ssize - stotal; // the remainder (rest) of pixels after a cfacts stack split
|
||||
+}
|
||||
+
|
||||
+/***
|
||||
+ * Layouts
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Bottomstack layout + gaps
|
||||
+ * https://dwm.suckless.org/patches/bottomstack/
|
||||
+ */
|
||||
+static void
|
||||
+bstack(Monitor *m)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ int oh, ov, ih, iv;
|
||||
+ int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
+ int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
+ float mfacts, sfacts;
|
||||
+ int mrest, srest;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ sx = mx = m->wx + ov;
|
||||
+ sy = my = m->wy + oh;
|
||||
+ sh = mh = m->wh - 2*oh;
|
||||
+ mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
|
||||
+ sw = m->ww - 2*ov - iv * (n - m->nmaster - 1);
|
||||
+
|
||||
+ if (m->nmaster && n > m->nmaster) {
|
||||
+ sh = (mh - ih) * (1 - m->mfact);
|
||||
+ mh = mh - ih - sh;
|
||||
+ sx = mx;
|
||||
+ sy = my + mh + ih;
|
||||
+ }
|
||||
+
|
||||
+ getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
||||
+ if (i < m->nmaster) {
|
||||
+ resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
||||
+ mx += WIDTH(c) + iv;
|
||||
+ } else {
|
||||
+ resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
|
||||
+ sx += WIDTH(c) + iv;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+bstackhoriz(Monitor *m)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ int oh, ov, ih, iv;
|
||||
+ int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
+ int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
+ float mfacts, sfacts;
|
||||
+ int mrest, srest;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ sx = mx = m->wx + ov;
|
||||
+ sy = my = m->wy + oh;
|
||||
+ mh = m->wh - 2*oh;
|
||||
+ sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
|
||||
+ mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
|
||||
+ sw = m->ww - 2*ov;
|
||||
+
|
||||
+ if (m->nmaster && n > m->nmaster) {
|
||||
+ sh = (mh - ih) * (1 - m->mfact);
|
||||
+ mh = mh - ih - sh;
|
||||
+ sy = my + mh + ih;
|
||||
+ sh = m->wh - mh - 2*oh - ih * (n - m->nmaster);
|
||||
+ }
|
||||
+
|
||||
+ getfacts(m, mw, sh, &mfacts, &sfacts, &mrest, &srest);
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
||||
+ if (i < m->nmaster) {
|
||||
+ resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
||||
+ mx += WIDTH(c) + iv;
|
||||
+ } else {
|
||||
+ resize(c, sx, sy, sw - (2*c->bw), sh * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
|
||||
+ sy += HEIGHT(c) + ih;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Centred master layout + gaps
|
||||
+ * https://dwm.suckless.org/patches/centeredmaster/
|
||||
+ */
|
||||
+void
|
||||
+centeredmaster(Monitor *m)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ int oh, ov, ih, iv;
|
||||
+ int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
+ int lx = 0, ly = 0, lw = 0, lh = 0;
|
||||
+ int rx = 0, ry = 0, rw = 0, rh = 0;
|
||||
+ float mfacts = 0, lfacts = 0, rfacts = 0;
|
||||
+ int mtotal = 0, ltotal = 0, rtotal = 0;
|
||||
+ int mrest = 0, lrest = 0, rrest = 0;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ /* initialize areas */
|
||||
+ mx = m->wx + ov;
|
||||
+ my = m->wy + oh;
|
||||
+ mh = m->wh - 2*oh - ih * ((!m->nmaster ? n : MIN(n, m->nmaster)) - 1);
|
||||
+ mw = m->ww - 2*ov;
|
||||
+ lh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - 1);
|
||||
+ rh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - ((n - m->nmaster) % 2 ? 0 : 1));
|
||||
+
|
||||
+ if (m->nmaster && n > m->nmaster) {
|
||||
+ /* go mfact box in the center if more than nmaster clients */
|
||||
+ if (n - m->nmaster > 1) {
|
||||
+ /* ||<-S->|<---M--->|<-S->|| */
|
||||
+ mw = (m->ww - 2*ov - 2*iv) * m->mfact;
|
||||
+ lw = (m->ww - mw - 2*ov - 2*iv) / 2;
|
||||
+ rw = (m->ww - mw - 2*ov - 2*iv) - lw;
|
||||
+ mx += lw + iv;
|
||||
+ } else {
|
||||
+ /* ||<---M--->|<-S->|| */
|
||||
+ mw = (mw - iv) * m->mfact;
|
||||
+ lw = 0;
|
||||
+ rw = m->ww - mw - iv - 2*ov;
|
||||
+ }
|
||||
+ lx = m->wx + ov;
|
||||
+ ly = m->wy + oh;
|
||||
+ rx = mx + mw + iv;
|
||||
+ ry = m->wy + oh;
|
||||
+ }
|
||||
+
|
||||
+ /* calculate facts */
|
||||
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) {
|
||||
+ if (!m->nmaster || n < m->nmaster)
|
||||
+ mfacts += c->cfact;
|
||||
+ else if ((n - m->nmaster) % 2)
|
||||
+ lfacts += c->cfact; // total factor of left hand stack area
|
||||
+ else
|
||||
+ rfacts += c->cfact; // total factor of right hand stack area
|
||||
+ }
|
||||
+
|
||||
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
|
||||
+ if (!m->nmaster || n < m->nmaster)
|
||||
+ mtotal += mh * (c->cfact / mfacts);
|
||||
+ else if ((n - m->nmaster) % 2)
|
||||
+ ltotal += lh * (c->cfact / lfacts);
|
||||
+ else
|
||||
+ rtotal += rh * (c->cfact / rfacts);
|
||||
+
|
||||
+ mrest = mh - mtotal;
|
||||
+ lrest = lh - ltotal;
|
||||
+ rrest = rh - rtotal;
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
||||
+ if (!m->nmaster || i < m->nmaster) {
|
||||
+ /* nmaster clients are stacked vertically, in the center of the screen */
|
||||
+ resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
|
||||
+ my += HEIGHT(c) + ih;
|
||||
+ } else {
|
||||
+ /* stack clients are stacked vertically */
|
||||
+ if ((i - m->nmaster) % 2 ) {
|
||||
+ resize(c, lx, ly, lw - (2*c->bw), lh * (c->cfact / lfacts) + ((i - 2*m->nmaster) < 2*lrest ? 1 : 0) - (2*c->bw), 0);
|
||||
+ ly += HEIGHT(c) + ih;
|
||||
+ } else {
|
||||
+ resize(c, rx, ry, rw - (2*c->bw), rh * (c->cfact / rfacts) + ((i - 2*m->nmaster) < 2*rrest ? 1 : 0) - (2*c->bw), 0);
|
||||
+ ry += HEIGHT(c) + ih;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+centeredfloatingmaster(Monitor *m)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ float mfacts, sfacts;
|
||||
+ float mivf = 1.0; // master inner vertical gap factor
|
||||
+ int oh, ov, ih, iv, mrest, srest;
|
||||
+ int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
+ int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ sx = mx = m->wx + ov;
|
||||
+ sy = my = m->wy + oh;
|
||||
+ sh = mh = m->wh - 2*oh;
|
||||
+ mw = m->ww - 2*ov - iv*(n - 1);
|
||||
+ sw = m->ww - 2*ov - iv*(n - m->nmaster - 1);
|
||||
+
|
||||
+ if (m->nmaster && n > m->nmaster) {
|
||||
+ mivf = 0.8;
|
||||
+ /* go mfact box in the center if more than nmaster clients */
|
||||
+ if (m->ww > m->wh) {
|
||||
+ mw = m->ww * m->mfact - iv*mivf*(MIN(n, m->nmaster) - 1);
|
||||
+ mh = m->wh * 0.9;
|
||||
+ } else {
|
||||
+ mw = m->ww * 0.9 - iv*mivf*(MIN(n, m->nmaster) - 1);
|
||||
+ mh = m->wh * m->mfact;
|
||||
+ }
|
||||
+ mx = m->wx + (m->ww - mw) / 2;
|
||||
+ my = m->wy + (m->wh - mh - 2*oh) / 2;
|
||||
+
|
||||
+ sx = m->wx + ov;
|
||||
+ sy = m->wy + oh;
|
||||
+ sh = m->wh - 2*oh;
|
||||
+ }
|
||||
+
|
||||
+ getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
+ if (i < m->nmaster) {
|
||||
+ /* nmaster clients are stacked horizontally, in the center of the screen */
|
||||
+ resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
||||
+ mx += WIDTH(c) + iv*mivf;
|
||||
+ } else {
|
||||
+ /* stack clients are stacked horizontally */
|
||||
+ resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
|
||||
+ sx += WIDTH(c) + iv;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Deck layout + gaps
|
||||
+ * https://dwm.suckless.org/patches/deck/
|
||||
+ */
|
||||
+void
|
||||
+deck(Monitor *m)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ int oh, ov, ih, iv;
|
||||
+ int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
+ int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
+ float mfacts, sfacts;
|
||||
+ int mrest, srest;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ sx = mx = m->wx + ov;
|
||||
+ sy = my = m->wy + oh;
|
||||
+ sh = mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1);
|
||||
+ sw = mw = m->ww - 2*ov;
|
||||
+
|
||||
+ if (m->nmaster && n > m->nmaster) {
|
||||
+ sw = (mw - iv) * (1 - m->mfact);
|
||||
+ mw = mw - iv - sw;
|
||||
+ sx = mx + mw + iv;
|
||||
+ sh = m->wh - 2*oh;
|
||||
+ }
|
||||
+
|
||||
+ getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);
|
||||
+
|
||||
+ if (n - m->nmaster > 0) /* override layout symbol */
|
||||
+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "D %d", n - m->nmaster);
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
+ if (i < m->nmaster) {
|
||||
+ resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
|
||||
+ my += HEIGHT(c) + ih;
|
||||
+ } else {
|
||||
+ resize(c, sx, sy, sw - (2*c->bw), sh - (2*c->bw), 0);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Fibonacci layout + gaps
|
||||
+ * https://dwm.suckless.org/patches/fibonacci/
|
||||
+ */
|
||||
+void
|
||||
+fibonacci(Monitor *m, int s)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ int nx, ny, nw, nh;
|
||||
+ int oh, ov, ih, iv;
|
||||
+ int nv, hrest = 0, wrest = 0, r = 1;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ nx = m->wx + ov;
|
||||
+ ny = m->wy + oh;
|
||||
+ nw = m->ww - 2*ov;
|
||||
+ nh = m->wh - 2*oh;
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
|
||||
+ if (r) {
|
||||
+ if ((i % 2 && (nh - ih) / 2 <= (bh + 2*c->bw))
|
||||
+ || (!(i % 2) && (nw - iv) / 2 <= (bh + 2*c->bw))) {
|
||||
+ r = 0;
|
||||
+ }
|
||||
+ if (r && i < n - 1) {
|
||||
+ if (i % 2) {
|
||||
+ nv = (nh - ih) / 2;
|
||||
+ hrest = nh - 2*nv - ih;
|
||||
+ nh = nv;
|
||||
+ } else {
|
||||
+ nv = (nw - iv) / 2;
|
||||
+ wrest = nw - 2*nv - iv;
|
||||
+ nw = nv;
|
||||
+ }
|
||||
+
|
||||
+ if ((i % 4) == 2 && !s)
|
||||
+ nx += nw + iv;
|
||||
+ else if ((i % 4) == 3 && !s)
|
||||
+ ny += nh + ih;
|
||||
+ }
|
||||
+
|
||||
+ if ((i % 4) == 0) {
|
||||
+ if (s) {
|
||||
+ ny += nh + ih;
|
||||
+ nh += hrest;
|
||||
+ }
|
||||
+ else {
|
||||
+ nh -= hrest;
|
||||
+ ny -= nh + ih;
|
||||
+ }
|
||||
+ }
|
||||
+ else if ((i % 4) == 1) {
|
||||
+ nx += nw + iv;
|
||||
+ nw += wrest;
|
||||
+ }
|
||||
+ else if ((i % 4) == 2) {
|
||||
+ ny += nh + ih;
|
||||
+ nh += hrest;
|
||||
+ if (i < n - 1)
|
||||
+ nw += wrest;
|
||||
+ }
|
||||
+ else if ((i % 4) == 3) {
|
||||
+ if (s) {
|
||||
+ nx += nw + iv;
|
||||
+ nw -= wrest;
|
||||
+ } else {
|
||||
+ nw -= wrest;
|
||||
+ nx -= nw + iv;
|
||||
+ nh += hrest;
|
||||
+ }
|
||||
+ }
|
||||
+ if (i == 0) {
|
||||
+ if (n != 1) {
|
||||
+ nw = (m->ww - iv - 2*ov) - (m->ww - iv - 2*ov) * (1 - m->mfact);
|
||||
+ wrest = 0;
|
||||
+ }
|
||||
+ ny = m->wy + oh;
|
||||
+ }
|
||||
+ else if (i == 1)
|
||||
+ nw = m->ww - nw - iv - 2*ov;
|
||||
+ i++;
|
||||
+ }
|
||||
+
|
||||
+ resize(c, nx, ny, nw - (2*c->bw), nh - (2*c->bw), False);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+dwindle(Monitor *m)
|
||||
+{
|
||||
+ fibonacci(m, 1);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+spiral(Monitor *m)
|
||||
+{
|
||||
+ fibonacci(m, 0);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Gappless grid layout + gaps (ironically)
|
||||
+ * https://dwm.suckless.org/patches/gaplessgrid/
|
||||
+ */
|
||||
+void
|
||||
+gaplessgrid(Monitor *m)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters
|
||||
+ int oh, ov, ih, iv;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ /* grid dimensions */
|
||||
+ for (cols = 0; cols <= n/2; cols++)
|
||||
+ if (cols*cols >= n)
|
||||
+ break;
|
||||
+ if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
|
||||
+ cols = 2;
|
||||
+ rows = n/cols;
|
||||
+ cn = rn = 0; // reset column no, row no, client count
|
||||
+
|
||||
+ ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
|
||||
+ cw = (m->ww - 2*ov - iv * (cols - 1)) / cols;
|
||||
+ rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
|
||||
+ crest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
|
||||
+ x = m->wx + ov;
|
||||
+ y = m->wy + oh;
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) {
|
||||
+ if (i/rows + 1 > cols - n%cols) {
|
||||
+ rows = n/cols + 1;
|
||||
+ ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
|
||||
+ rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
|
||||
+ }
|
||||
+ resize(c,
|
||||
+ x,
|
||||
+ y + rn*(ch + ih) + MIN(rn, rrest),
|
||||
+ cw + (cn < crest ? 1 : 0) - 2*c->bw,
|
||||
+ ch + (rn < rrest ? 1 : 0) - 2*c->bw,
|
||||
+ 0);
|
||||
+ rn++;
|
||||
+ if (rn >= rows) {
|
||||
+ rn = 0;
|
||||
+ x += cw + ih + (cn < crest ? 1 : 0);
|
||||
+ cn++;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Gridmode layout + gaps
|
||||
+ * https://dwm.suckless.org/patches/gridmode/
|
||||
+ */
|
||||
+void
|
||||
+grid(Monitor *m)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ int cx, cy, cw, ch, cc, cr, chrest, cwrest, cols, rows;
|
||||
+ int oh, ov, ih, iv;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+
|
||||
+ /* grid dimensions */
|
||||
+ for (rows = 0; rows <= n/2; rows++)
|
||||
+ if (rows*rows >= n)
|
||||
+ break;
|
||||
+ cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;
|
||||
+
|
||||
+ /* window geoms (cell height/width) */
|
||||
+ ch = (m->wh - 2*oh - ih * (rows - 1)) / (rows ? rows : 1);
|
||||
+ cw = (m->ww - 2*ov - iv * (cols - 1)) / (cols ? cols : 1);
|
||||
+ chrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
|
||||
+ cwrest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
||||
+ cc = i / rows;
|
||||
+ cr = i % rows;
|
||||
+ cx = m->wx + ov + cc * (cw + iv) + MIN(cc, cwrest);
|
||||
+ cy = m->wy + oh + cr * (ch + ih) + MIN(cr, chrest);
|
||||
+ resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Horizontal grid layout + gaps
|
||||
+ * https://dwm.suckless.org/patches/horizgrid/
|
||||
+ */
|
||||
+void
|
||||
+horizgrid(Monitor *m) {
|
||||
+ Client *c;
|
||||
+ unsigned int n, i;
|
||||
+ int oh, ov, ih, iv;
|
||||
+ int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
+ int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
+ int ntop, nbottom = 1;
|
||||
+ float mfacts = 0, sfacts = 0;
|
||||
+ int mrest, srest, mtotal = 0, stotal = 0;
|
||||
+
|
||||
+ /* Count windows */
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ if (n <= 2)
|
||||
+ ntop = n;
|
||||
+ else {
|
||||
+ ntop = n / 2;
|
||||
+ nbottom = n - ntop;
|
||||
+ }
|
||||
+ sx = mx = m->wx + ov;
|
||||
+ sy = my = m->wy + oh;
|
||||
+ sh = mh = m->wh - 2*oh;
|
||||
+ sw = mw = m->ww - 2*ov;
|
||||
+
|
||||
+ if (n > ntop) {
|
||||
+ sh = (mh - ih) / 2;
|
||||
+ mh = mh - ih - sh;
|
||||
+ sy = my + mh + ih;
|
||||
+ mw = m->ww - 2*ov - iv * (ntop - 1);
|
||||
+ sw = m->ww - 2*ov - iv * (nbottom - 1);
|
||||
+ }
|
||||
+
|
||||
+ /* calculate facts */
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
+ if (i < ntop)
|
||||
+ mfacts += c->cfact;
|
||||
+ else
|
||||
+ sfacts += c->cfact;
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
+ if (i < ntop)
|
||||
+ mtotal += mh * (c->cfact / mfacts);
|
||||
+ else
|
||||
+ stotal += sw * (c->cfact / sfacts);
|
||||
+
|
||||
+ mrest = mh - mtotal;
|
||||
+ srest = sw - stotal;
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
+ if (i < ntop) {
|
||||
+ resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
||||
+ mx += WIDTH(c) + iv;
|
||||
+ } else {
|
||||
+ resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - ntop) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
|
||||
+ sx += WIDTH(c) + iv;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * nrowgrid layout + gaps
|
||||
+ * https://dwm.suckless.org/patches/nrowgrid/
|
||||
+ */
|
||||
+void
|
||||
+nrowgrid(Monitor *m)
|
||||
+{
|
||||
+ unsigned int n;
|
||||
+ int ri = 0, ci = 0; /* counters */
|
||||
+ int oh, ov, ih, iv; /* vanitygap settings */
|
||||
+ unsigned int cx, cy, cw, ch; /* client geometry */
|
||||
+ unsigned int uw = 0, uh = 0, uc = 0; /* utilization trackers */
|
||||
+ unsigned int cols, rows = m->nmaster + 1;
|
||||
+ Client *c;
|
||||
+
|
||||
+ /* count clients */
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+
|
||||
+ /* nothing to do here */
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ /* force 2 clients to always split vertically */
|
||||
+ if (FORCE_VSPLIT && n == 2)
|
||||
+ rows = 1;
|
||||
+
|
||||
+ /* never allow empty rows */
|
||||
+ if (n < rows)
|
||||
+ rows = n;
|
||||
+
|
||||
+ /* define first row */
|
||||
+ cols = n / rows;
|
||||
+ uc = cols;
|
||||
+ cy = m->wy + oh;
|
||||
+ ch = (m->wh - 2*oh - ih*(rows - 1)) / rows;
|
||||
+ uh = ch;
|
||||
+
|
||||
+ for (c = nexttiled(m->clients); c; c = nexttiled(c->next), ci++) {
|
||||
+ if (ci == cols) {
|
||||
+ uw = 0;
|
||||
+ ci = 0;
|
||||
+ ri++;
|
||||
+
|
||||
+ /* next row */
|
||||
+ cols = (n - uc) / (rows - ri);
|
||||
+ uc += cols;
|
||||
+ cy = m->wy + oh + uh + ih;
|
||||
+ uh += ch + ih;
|
||||
+ }
|
||||
+
|
||||
+ cx = m->wx + ov + uw;
|
||||
+ cw = (m->ww - 2*ov - uw) / (cols - ci);
|
||||
+ uw += cw + iv;
|
||||
+
|
||||
+ resize(c, cx, cy, cw - (2*c->bw), ch - (2*c->bw), 0);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Default tile layout + gaps
|
||||
+ */
|
||||
+static void
|
||||
+tile(Monitor *m)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ int oh, ov, ih, iv;
|
||||
+ int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
+ int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
+ float mfacts, sfacts;
|
||||
+ int mrest, srest;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ sx = mx = m->wx + ov;
|
||||
+ sy = my = m->wy + oh;
|
||||
+ mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1);
|
||||
+ sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
|
||||
+ sw = mw = m->ww - 2*ov;
|
||||
+
|
||||
+ if (m->nmaster && n > m->nmaster) {
|
||||
+ sw = (mw - iv) * (1 - m->mfact);
|
||||
+ mw = mw - iv - sw;
|
||||
+ sx = mx + mw + iv;
|
||||
+ }
|
||||
+
|
||||
+ getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
+ if (i < m->nmaster) {
|
||||
+ resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
|
||||
+ my += HEIGHT(c) + ih;
|
||||
+ } else {
|
||||
+ resize(c, sx, sy, sw - (2*c->bw), sh * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
|
||||
+ sy += HEIGHT(c) + ih;
|
||||
+ }
|
||||
+}
|
||||
\ No newline at end of file
|
||||
--
|
||||
2.19.1
|
||||
|
75
patches/dwm-combo-6.1.diff
Normal file
75
patches/dwm-combo-6.1.diff
Normal file
@ -0,0 +1,75 @@
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 0362114..40b7a99 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -234,6 +234,11 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee);
|
||||
static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
||||
static void zoom(const Arg *arg);
|
||||
|
||||
+static void keyrelease(XEvent *e);
|
||||
+static void combotag(const Arg *arg);
|
||||
+static void comboview(const Arg *arg);
|
||||
+
|
||||
+
|
||||
/* variables */
|
||||
static const char broken[] = "broken";
|
||||
static char stext[256];
|
||||
@@ -244,6 +249,7 @@ static int (*xerrorxlib)(Display *, XErrorEvent *);
|
||||
static unsigned int numlockmask = 0;
|
||||
static void (*handler[LASTEvent]) (XEvent *) = {
|
||||
[ButtonPress] = buttonpress,
|
||||
+ [ButtonRelease] = keyrelease,
|
||||
[ClientMessage] = clientmessage,
|
||||
[ConfigureRequest] = configurerequest,
|
||||
[ConfigureNotify] = configurenotify,
|
||||
@@ -251,6 +257,7 @@ static void (*handler[LASTEvent]) (XEvent *) = {
|
||||
[EnterNotify] = enternotify,
|
||||
[Expose] = expose,
|
||||
[FocusIn] = focusin,
|
||||
+ [KeyRelease] = keyrelease,
|
||||
[KeyPress] = keypress,
|
||||
[MappingNotify] = mappingnotify,
|
||||
[MapRequest] = maprequest,
|
||||
@@ -274,6 +281,42 @@ static Window root;
|
||||
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
|
||||
|
||||
/* function implementations */
|
||||
+static int combo = 0;
|
||||
+
|
||||
+void
|
||||
+keyrelease(XEvent *e) {
|
||||
+ combo = 0;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+combotag(const Arg *arg) {
|
||||
+ if(selmon->sel && arg->ui & TAGMASK) {
|
||||
+ if (combo) {
|
||||
+ selmon->sel->tags |= arg->ui & TAGMASK;
|
||||
+ } else {
|
||||
+ combo = 1;
|
||||
+ selmon->sel->tags = arg->ui & TAGMASK;
|
||||
+ }
|
||||
+ focus(NULL);
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+comboview(const Arg *arg) {
|
||||
+ unsigned newtags = arg->ui & TAGMASK;
|
||||
+ if (combo) {
|
||||
+ selmon->tagset[selmon->seltags] |= newtags;
|
||||
+ } else {
|
||||
+ selmon->seltags ^= 1; /*toggle tagset*/
|
||||
+ combo = 1;
|
||||
+ if (newtags)
|
||||
+ selmon->tagset[selmon->seltags] = newtags;
|
||||
+ }
|
||||
+ focus(NULL);
|
||||
+ arrange(selmon);
|
||||
+}
|
||||
+
|
||||
void
|
||||
applyrules(Client *c)
|
||||
{
|
116
patches/dwm-cool-autostart-6.2.diff
Normal file
116
patches/dwm-cool-autostart-6.2.diff
Normal file
@ -0,0 +1,116 @@
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..ed056a4 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -18,6 +18,11 @@ static const char *colors[][3] = {
|
||||
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
|
||||
};
|
||||
|
||||
+static const char *const autostart[] = {
|
||||
+ "st", NULL,
|
||||
+ NULL /* terminate */
|
||||
+};
|
||||
+
|
||||
/* tagging */
|
||||
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
|
||||
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 9fd0286..1facd56 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -234,6 +234,7 @@ 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);
|
||||
+static void autostart_exec(void);
|
||||
|
||||
/* variables */
|
||||
static const char broken[] = "broken";
|
||||
@@ -275,6 +276,34 @@ static Window root, wmcheckwin;
|
||||
/* compile-time check if all tags fit into an unsigned int bit array. */
|
||||
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
|
||||
|
||||
+/* dwm will keep pid's of processes from autostart array and kill them at quit */
|
||||
+static pid_t *autostart_pids;
|
||||
+static size_t autostart_len;
|
||||
+
|
||||
+/* execute command from autostart array */
|
||||
+static void
|
||||
+autostart_exec() {
|
||||
+ const char *const *p;
|
||||
+ size_t i = 0;
|
||||
+
|
||||
+ /* count entries */
|
||||
+ for (p = autostart; *p; autostart_len++, p++)
|
||||
+ while (*++p);
|
||||
+
|
||||
+ autostart_pids = malloc(autostart_len * sizeof(pid_t));
|
||||
+ for (p = autostart; *p; i++, p++) {
|
||||
+ if ((autostart_pids[i] = fork()) == 0) {
|
||||
+ setsid();
|
||||
+ execvp(*p, (char *const *)p);
|
||||
+ fprintf(stderr, "dwm: execvp %s\n", *p);
|
||||
+ perror(" failed");
|
||||
+ _exit(EXIT_FAILURE);
|
||||
+ }
|
||||
+ /* skip arguments */
|
||||
+ while (*++p);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* function implementations */
|
||||
void
|
||||
applyrules(Client *c)
|
||||
@@ -1249,6 +1278,16 @@ propertynotify(XEvent *e)
|
||||
void
|
||||
quit(const Arg *arg)
|
||||
{
|
||||
+ size_t i;
|
||||
+
|
||||
+ /* kill child processes */
|
||||
+ for (i = 0; i < autostart_len; i++) {
|
||||
+ if (0 < autostart_pids[i]) {
|
||||
+ kill(autostart_pids[i], SIGTERM);
|
||||
+ waitpid(autostart_pids[i], NULL, 0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
running = 0;
|
||||
}
|
||||
|
||||
@@ -1632,9 +1671,25 @@ showhide(Client *c)
|
||||
void
|
||||
sigchld(int unused)
|
||||
{
|
||||
+ pid_t pid;
|
||||
+
|
||||
if (signal(SIGCHLD, sigchld) == SIG_ERR)
|
||||
die("can't install SIGCHLD handler:");
|
||||
- while (0 < waitpid(-1, NULL, WNOHANG));
|
||||
+ while (0 < (pid = waitpid(-1, NULL, WNOHANG))) {
|
||||
+ pid_t *p, *lim;
|
||||
+
|
||||
+ if (!(p = autostart_pids))
|
||||
+ continue;
|
||||
+ lim = &p[autostart_len];
|
||||
+
|
||||
+ for (; p < lim; p++) {
|
||||
+ if (*p == pid) {
|
||||
+ *p = -1;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2139,6 +2194,7 @@ main(int argc, char *argv[])
|
||||
if (!(dpy = XOpenDisplay(NULL)))
|
||||
die("dwm: cannot open display");
|
||||
checkotherwm();
|
||||
+ autostart_exec();
|
||||
setup();
|
||||
#ifdef __OpenBSD__
|
||||
if (pledge("stdio rpath proc exec", NULL) == -1)
|
||||
|
93
patches/dwm-cyclelayouts-20180524-6.2.diff
Normal file
93
patches/dwm-cyclelayouts-20180524-6.2.diff
Normal file
@ -0,0 +1,93 @@
|
||||
From a09e766a4342f580582082a92b2de65f33208eb4 Mon Sep 17 00:00:00 2001
|
||||
From: Christopher Drelich <cd@cdrakka.com>
|
||||
Date: Thu, 24 May 2018 00:56:56 -0400
|
||||
Subject: [PATCH] Function to cycle through available layouts.
|
||||
|
||||
MOD-CTRL-, and MOD-CTRL-.
|
||||
cycle backwards and forwards through available layouts.
|
||||
Probably only useful if you have a lot of additional layouts.
|
||||
The NULL, NULL layout should always be the last layout in your list,
|
||||
in order to guarantee consistent behavior.
|
||||
---
|
||||
config.def.h | 3 +++
|
||||
dwm.1 | 6 ++++++
|
||||
dwm.c | 18 ++++++++++++++++++
|
||||
3 files changed, 27 insertions(+)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index a9ac303..153b880 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -41,6 +41,7 @@ static const Layout layouts[] = {
|
||||
{ "[]=", tile }, /* first entry is default */
|
||||
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||
{ "[M]", monocle },
|
||||
+ { NULL, NULL },
|
||||
};
|
||||
|
||||
/* key definitions */
|
||||
@@ -76,6 +77,8 @@ static Key keys[] = {
|
||||
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
||||
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
||||
+ { MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } },
|
||||
+ { MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } },
|
||||
{ MODKEY, XK_space, setlayout, {0} },
|
||||
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
||||
{ MODKEY, XK_0, view, {.ui = ~0 } },
|
||||
diff --git a/dwm.1 b/dwm.1
|
||||
index 13b3729..165891b 100644
|
||||
--- a/dwm.1
|
||||
+++ b/dwm.1
|
||||
@@ -92,6 +92,12 @@ Sets monocle layout.
|
||||
.B Mod1\-space
|
||||
Toggles between current and previous layout.
|
||||
.TP
|
||||
+.B Mod1\-Control\-,
|
||||
+Cycles backwards in layout list.
|
||||
+.TP
|
||||
+.B Mod1\-Control\-.
|
||||
+Cycles forwards in layout list.
|
||||
+.TP
|
||||
.B Mod1\-j
|
||||
Focus next window.
|
||||
.TP
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index bb95e26..db73000 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -157,6 +157,7 @@ static void configure(Client *c);
|
||||
static void configurenotify(XEvent *e);
|
||||
static void configurerequest(XEvent *e);
|
||||
static Monitor *createmon(void);
|
||||
+static void cyclelayout(const Arg *arg);
|
||||
static void destroynotify(XEvent *e);
|
||||
static void detach(Client *c);
|
||||
static void detachstack(Client *c);
|
||||
@@ -645,6 +646,23 @@ createmon(void)
|
||||
}
|
||||
|
||||
void
|
||||
+cyclelayout(const Arg *arg) {
|
||||
+ Layout *l;
|
||||
+ for(l = (Layout *)layouts; l != selmon->lt[selmon->sellt]; l++);
|
||||
+ if(arg->i > 0) {
|
||||
+ if(l->symbol && (l + 1)->symbol)
|
||||
+ setlayout(&((Arg) { .v = (l + 1) }));
|
||||
+ else
|
||||
+ setlayout(&((Arg) { .v = layouts }));
|
||||
+ } else {
|
||||
+ if(l != layouts && (l - 1)->symbol)
|
||||
+ setlayout(&((Arg) { .v = (l - 1) }));
|
||||
+ else
|
||||
+ setlayout(&((Arg) { .v = &layouts[LENGTH(layouts) - 2] }));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
destroynotify(XEvent *e)
|
||||
{
|
||||
Client *c;
|
||||
--
|
||||
2.7.4
|
||||
|
240
patches/dwm-dwmc-6.2.diff
Normal file
240
patches/dwm-dwmc-6.2.diff
Normal file
@ -0,0 +1,240 @@
|
||||
From d94cb6f1a553d19127f44dbdc96e8bb5041956c2 Mon Sep 17 00:00:00 2001
|
||||
From: Nihal Jere <noocsharp@gmail.com>
|
||||
Date: Sat, 21 Mar 2020 15:16:49 -0500
|
||||
Subject: [PATCH] dwm-client
|
||||
|
||||
---
|
||||
Makefile | 2 +-
|
||||
config.def.h | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
dwm.c | 55 +++++++++++++++++++++++++++++++++++++++--
|
||||
dwmc | 40 ++++++++++++++++++++++++++++++
|
||||
4 files changed, 164 insertions(+), 3 deletions(-)
|
||||
create mode 100755 dwmc
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 77bcbc0..f837f5c 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -38,7 +38,7 @@ dist: clean
|
||||
|
||||
install: all
|
||||
mkdir -p ${DESTDIR}${PREFIX}/bin
|
||||
- cp -f dwm ${DESTDIR}${PREFIX}/bin
|
||||
+ cp -f dwm dwmc ${DESTDIR}${PREFIX}/bin
|
||||
chmod 755 ${DESTDIR}${PREFIX}/bin/dwm
|
||||
mkdir -p ${DESTDIR}${MANPREFIX}/man1
|
||||
sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..efbae79 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -113,3 +113,73 @@ static Button buttons[] = {
|
||||
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
|
||||
};
|
||||
|
||||
+void
|
||||
+setlayoutex(const Arg *arg)
|
||||
+{
|
||||
+ setlayout(&((Arg) { .v = &layouts[arg->i] }));
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+viewex(const Arg *arg)
|
||||
+{
|
||||
+ view(&((Arg) { .ui = 1 << arg->ui }));
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+viewall(const Arg *arg)
|
||||
+{
|
||||
+ view(&((Arg){.ui = ~0}));
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+toggleviewex(const Arg *arg)
|
||||
+{
|
||||
+ toggleview(&((Arg) { .ui = 1 << arg->ui }));
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+tagex(const Arg *arg)
|
||||
+{
|
||||
+ tag(&((Arg) { .ui = 1 << arg->ui }));
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+toggletagex(const Arg *arg)
|
||||
+{
|
||||
+ toggletag(&((Arg) { .ui = 1 << arg->ui }));
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+tagall(const Arg *arg)
|
||||
+{
|
||||
+ tag(&((Arg){.ui = ~0}));
|
||||
+}
|
||||
+
|
||||
+/* signal definitions */
|
||||
+/* signum must be greater than 0 */
|
||||
+/* trigger signals using `xsetroot -name "fsignal:<signame> [<type> <value>]"` */
|
||||
+static Signal signals[] = {
|
||||
+ /* signum function */
|
||||
+ { "focusstack", focusstack },
|
||||
+ { "setmfact", setmfact },
|
||||
+ { "togglebar", togglebar },
|
||||
+ { "incnmaster", incnmaster },
|
||||
+ { "togglefloating", togglefloating },
|
||||
+ { "focusmon", focusmon },
|
||||
+ { "tagmon", tagmon },
|
||||
+ { "zoom", zoom },
|
||||
+ { "view", view },
|
||||
+ { "viewall", viewall },
|
||||
+ { "viewex", viewex },
|
||||
+ { "toggleview", view },
|
||||
+ { "toggleviewex", toggleviewex },
|
||||
+ { "tag", tag },
|
||||
+ { "tagall", tagall },
|
||||
+ { "tagex", tagex },
|
||||
+ { "toggletag", tag },
|
||||
+ { "toggletagex", toggletagex },
|
||||
+ { "killclient", killclient },
|
||||
+ { "quit", quit },
|
||||
+ { "setlayout", setlayout },
|
||||
+ { "setlayoutex", setlayoutex },
|
||||
+};
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 4465af1..aa53706 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -106,6 +106,11 @@ typedef struct {
|
||||
const Arg arg;
|
||||
} Key;
|
||||
|
||||
+typedef struct {
|
||||
+ const char * sig;
|
||||
+ void (*func)(const Arg *);
|
||||
+} Signal;
|
||||
+
|
||||
typedef struct {
|
||||
const char *symbol;
|
||||
void (*arrange)(Monitor *);
|
||||
@@ -148,6 +153,7 @@ static void arrange(Monitor *m);
|
||||
static void arrangemon(Monitor *m);
|
||||
static void attach(Client *c);
|
||||
static void attachstack(Client *c);
|
||||
+static int fake_signal(void);
|
||||
static void buttonpress(XEvent *e);
|
||||
static void checkotherwm(void);
|
||||
static void cleanup(void);
|
||||
@@ -998,6 +1004,49 @@ keypress(XEvent *e)
|
||||
keys[i].func(&(keys[i].arg));
|
||||
}
|
||||
|
||||
+int
|
||||
+fake_signal(void)
|
||||
+{
|
||||
+ char fsignal[256];
|
||||
+ char indicator[9] = "fsignal:";
|
||||
+ char str_sig[50];
|
||||
+ char param[16];
|
||||
+ int i, len_str_sig, n, paramn;
|
||||
+ size_t len_fsignal, len_indicator = strlen(indicator);
|
||||
+ Arg arg;
|
||||
+
|
||||
+ // Get root name property
|
||||
+ if (gettextprop(root, XA_WM_NAME, fsignal, sizeof(fsignal))) {
|
||||
+ len_fsignal = strlen(fsignal);
|
||||
+
|
||||
+ // Check if this is indeed a fake signal
|
||||
+ if (len_indicator > len_fsignal ? 0 : strncmp(indicator, fsignal, len_indicator) == 0) {
|
||||
+ paramn = sscanf(fsignal+len_indicator, "%s%n%s%n", str_sig, &len_str_sig, param, &n);
|
||||
+
|
||||
+ if (paramn == 1) arg = (Arg) {0};
|
||||
+ else if (paramn > 2) return 1;
|
||||
+ else if (strncmp(param, "i", n - len_str_sig) == 0)
|
||||
+ sscanf(fsignal + len_indicator + n, "%i", &(arg.i));
|
||||
+ else if (strncmp(param, "ui", n - len_str_sig) == 0)
|
||||
+ sscanf(fsignal + len_indicator + n, "%u", &(arg.ui));
|
||||
+ else if (strncmp(param, "f", n - len_str_sig) == 0)
|
||||
+ sscanf(fsignal + len_indicator + n, "%f", &(arg.f));
|
||||
+ else return 1;
|
||||
+
|
||||
+ // Check if a signal was found, and if so handle it
|
||||
+ for (i = 0; i < LENGTH(signals); i++)
|
||||
+ if (strncmp(str_sig, signals[i].sig, len_str_sig) == 0 && signals[i].func)
|
||||
+ signals[i].func(&(arg));
|
||||
+
|
||||
+ // A fake signal was sent
|
||||
+ return 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // No fake signal was sent, so proceed with update
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
void
|
||||
killclient(const Arg *arg)
|
||||
{
|
||||
@@ -1215,8 +1264,10 @@ propertynotify(XEvent *e)
|
||||
Window trans;
|
||||
XPropertyEvent *ev = &e->xproperty;
|
||||
|
||||
- if ((ev->window == root) && (ev->atom == XA_WM_NAME))
|
||||
- updatestatus();
|
||||
+ if ((ev->window == root) && (ev->atom == XA_WM_NAME)) {
|
||||
+ if (!fake_signal())
|
||||
+ updatestatus();
|
||||
+ }
|
||||
else if (ev->state == PropertyDelete)
|
||||
return; /* ignore */
|
||||
else if ((c = wintoclient(ev->window))) {
|
||||
diff --git a/dwmc b/dwmc
|
||||
new file mode 100755
|
||||
index 0000000..5ff8dbc
|
||||
--- /dev/null
|
||||
+++ b/dwmc
|
||||
@@ -0,0 +1,40 @@
|
||||
+#!/usr/bin/env sh
|
||||
+
|
||||
+signal() {
|
||||
+ xsetroot -name "fsignal:$*"
|
||||
+}
|
||||
+
|
||||
+case $# in
|
||||
+1)
|
||||
+ case $1 in
|
||||
+ setlayout | view | viewall | togglebar | togglefloating | zoom | killclient | quit)
|
||||
+ signal $1
|
||||
+ ;;
|
||||
+ *)
|
||||
+ echo "Unknown command or missing one argument."
|
||||
+ exit 1
|
||||
+ ;;
|
||||
+ esac
|
||||
+ ;;
|
||||
+2)
|
||||
+ case $1 in
|
||||
+ view)
|
||||
+ signal $1 ui $2
|
||||
+ ;;
|
||||
+ viewex | toggleviewex | tagex | toggletagex | setlayoutex | focusstack | incnmaster | focusmon | tagmon)
|
||||
+ signal $1 i $2
|
||||
+ ;;
|
||||
+ setmfact)
|
||||
+ signal $1 f $2
|
||||
+ ;;
|
||||
+ *)
|
||||
+ echo "Unknown command or one too many arguments."
|
||||
+ exit 1
|
||||
+ ;;
|
||||
+ esac
|
||||
+ ;;
|
||||
+*)
|
||||
+ echo "Too many arguments."
|
||||
+ exit 1
|
||||
+ ;;
|
||||
+esac
|
||||
--
|
||||
2.25.1
|
||||
|
27
patches/dwm-fixborders-6.2.diff
Normal file
27
patches/dwm-fixborders-6.2.diff
Normal file
@ -0,0 +1,27 @@
|
||||
From 1529909466206016f2101457bbf37c67195714c8 Mon Sep 17 00:00:00 2001
|
||||
From: Jakub Leszczak <szatan@gecc.xyz>
|
||||
Date: Fri, 22 Nov 2019 10:46:53 +0800
|
||||
Subject: [PATCH] Fix transparent borders
|
||||
|
||||
When terminal has transparency then its borders also become transparent.
|
||||
Fix it by removing transparency from any pixels drawn.
|
||||
---
|
||||
drw.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/drw.c b/drw.c
|
||||
index 8fd1ca4..490a592 100644
|
||||
--- a/drw.c
|
||||
+++ b/drw.c
|
||||
@@ -202,6 +202,8 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
|
||||
DefaultColormap(drw->dpy, drw->screen),
|
||||
clrname, dest))
|
||||
die("error, cannot allocate color '%s'", clrname);
|
||||
+
|
||||
+ dest->pixel |= 0xff << 24;
|
||||
}
|
||||
|
||||
/* Wrapper to create color schemes. The caller has to call free(3) on the
|
||||
--
|
||||
2.26.2
|
||||
|
3246
patches/dwm-ipc-20201106-f04cac6.diff
Normal file
3246
patches/dwm-ipc-20201106-f04cac6.diff
Normal file
File diff suppressed because it is too large
Load Diff
73
patches/dwm-movestack-6.1.diff
Normal file
73
patches/dwm-movestack-6.1.diff
Normal file
@ -0,0 +1,73 @@
|
||||
diff -r 050d521d66d8 config.def.h
|
||||
--- a/config.def.h Tue Aug 24 13:13:20 2010 +0100
|
||||
+++ b/config.def.h Sun Sep 05 18:43:07 2010 +0200
|
||||
@@ -57,6 +57,7 @@
|
||||
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
|
||||
static const char *termcmd[] = { "st", NULL };
|
||||
|
||||
+#include "movestack.c"
|
||||
static Key keys[] = {
|
||||
/* modifier key function argument */
|
||||
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
||||
@@ -68,6 +69,8 @@
|
||||
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
||||
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
||||
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
||||
+ { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
|
||||
+ { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
|
||||
{ MODKEY, XK_Return, zoom, {0} },
|
||||
{ MODKEY, XK_Tab, view, {0} },
|
||||
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
|
||||
diff -r 050d521d66d8 movestack.c
|
||||
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
|
||||
+++ b/movestack.c Sun Sep 05 18:43:07 2010 +0200
|
||||
@@ -0,0 +1,49 @@
|
||||
+void
|
||||
+movestack(const Arg *arg) {
|
||||
+ Client *c = NULL, *p = NULL, *pc = NULL, *i;
|
||||
+
|
||||
+ if(arg->i > 0) {
|
||||
+ /* find the client after selmon->sel */
|
||||
+ for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
|
||||
+ if(!c)
|
||||
+ for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
|
||||
+
|
||||
+ }
|
||||
+ else {
|
||||
+ /* find the client before selmon->sel */
|
||||
+ for(i = selmon->clients; i != selmon->sel; i = i->next)
|
||||
+ if(ISVISIBLE(i) && !i->isfloating)
|
||||
+ c = i;
|
||||
+ if(!c)
|
||||
+ for(; i; i = i->next)
|
||||
+ if(ISVISIBLE(i) && !i->isfloating)
|
||||
+ c = i;
|
||||
+ }
|
||||
+ /* find the client before selmon->sel and c */
|
||||
+ for(i = selmon->clients; i && (!p || !pc); i = i->next) {
|
||||
+ if(i->next == selmon->sel)
|
||||
+ p = i;
|
||||
+ if(i->next == c)
|
||||
+ pc = i;
|
||||
+ }
|
||||
+
|
||||
+ /* swap c and selmon->sel selmon->clients in the selmon->clients list */
|
||||
+ if(c && c != selmon->sel) {
|
||||
+ Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next;
|
||||
+ selmon->sel->next = c->next==selmon->sel?c:c->next;
|
||||
+ c->next = temp;
|
||||
+
|
||||
+ if(p && p != c)
|
||||
+ p->next = c;
|
||||
+ if(pc && pc != selmon->sel)
|
||||
+ pc->next = selmon->sel;
|
||||
+
|
||||
+ if(selmon->sel == selmon->clients)
|
||||
+ selmon->clients = c;
|
||||
+ else if(c == selmon->clients)
|
||||
+ selmon->clients = selmon->sel;
|
||||
+
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+}
|
||||
+
|
31
patches/dwm-noborderfloatingfix-6.2.diff
Normal file
31
patches/dwm-noborderfloatingfix-6.2.diff
Normal file
@ -0,0 +1,31 @@
|
||||
From 700b0bdea872f4c00182b2bd925b41fe03f8d222 Mon Sep 17 00:00:00 2001
|
||||
From: Aidan Hall <aidan.hall@outlook.com>
|
||||
Date: Tue, 2 Jun 2020 14:41:53 +0000
|
||||
Subject: [PATCH] Prevents hiding the border if layout is floating.
|
||||
|
||||
---
|
||||
dwm.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 4465af1..2dd959d 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -1282,6 +1282,14 @@ resizeclient(Client *c, int x, int y, int w, int h)
|
||||
c->oldw = c->w; c->w = wc.width = w;
|
||||
c->oldh = c->h; c->h = wc.height = h;
|
||||
wc.border_width = c->bw;
|
||||
+ if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next))
|
||||
+ || &monocle == c->mon->lt[c->mon->sellt]->arrange)
|
||||
+ && !c->isfullscreen && !c->isfloating
|
||||
+ && NULL != c->mon->lt[c->mon->sellt]->arrange) {
|
||||
+ c->w = wc.width += c->bw * 2;
|
||||
+ c->h = wc.height += c->bw * 2;
|
||||
+ wc.border_width = 0;
|
||||
+ }
|
||||
XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
|
||||
configure(c);
|
||||
XSync(dpy, False);
|
||||
--
|
||||
2.26.2
|
||||
|
412
patches/dwm-swallow-20200807-b2de9b0.diff
Normal file
412
patches/dwm-swallow-20200807-b2de9b0.diff
Normal file
@ -0,0 +1,412 @@
|
||||
From b2de9b0fd7988241db516a8f032f26cb9cf32be1 Mon Sep 17 00:00:00 2001
|
||||
From: Ben <ben@0x1bi.net>
|
||||
Date: Fri, 7 Aug 2020 20:14:29 -0400
|
||||
Subject: [PATCH] added openbsd support for swallowing
|
||||
|
||||
---
|
||||
config.def.h | 9 +-
|
||||
config.mk | 3 +-
|
||||
dwm.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++--
|
||||
3 files changed, 237 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..fe51476 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -3,6 +3,7 @@
|
||||
/* appearance */
|
||||
static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
static const unsigned int snap = 32; /* snap pixel */
|
||||
+static const int swallowfloating = 0; /* 1 means swallow floating windows by default */
|
||||
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" };
|
||||
@@ -26,9 +27,11 @@ static const Rule rules[] = {
|
||||
* 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 },
|
||||
+ /* class instance title tags mask isfloating isterminal noswallow monitor */
|
||||
+ { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 },
|
||||
+ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 },
|
||||
+ { "St", NULL, NULL, 0, 0, 1, 0, -1 },
|
||||
+ { NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */
|
||||
};
|
||||
|
||||
/* layout(s) */
|
||||
diff --git a/config.mk b/config.mk
|
||||
index 7084c33..ff9e508 100644
|
||||
--- a/config.mk
|
||||
+++ b/config.mk
|
||||
@@ -19,10 +19,11 @@ FREETYPELIBS = -lfontconfig -lXft
|
||||
FREETYPEINC = /usr/include/freetype2
|
||||
# OpenBSD (uncomment)
|
||||
#FREETYPEINC = ${X11INC}/freetype2
|
||||
+#KVMLIB = -lkvm
|
||||
|
||||
# includes and libs
|
||||
INCS = -I${X11INC} -I${FREETYPEINC}
|
||||
-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
|
||||
+LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB}
|
||||
|
||||
# flags
|
||||
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 9fd0286..e9f08f7 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -40,6 +40,12 @@
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
#endif /* XINERAMA */
|
||||
#include <X11/Xft/Xft.h>
|
||||
+#include <X11/Xlib-xcb.h>
|
||||
+#include <xcb/res.h>
|
||||
+#ifdef __OpenBSD__
|
||||
+#include <sys/sysctl.h>
|
||||
+#include <kvm.h>
|
||||
+#endif /* __OpenBSD */
|
||||
|
||||
#include "drw.h"
|
||||
#include "util.h"
|
||||
@@ -92,9 +98,11 @@ struct Client {
|
||||
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
|
||||
int bw, oldbw;
|
||||
unsigned int tags;
|
||||
- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
|
||||
+ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow;
|
||||
+ pid_t pid;
|
||||
Client *next;
|
||||
Client *snext;
|
||||
+ Client *swallowing;
|
||||
Monitor *mon;
|
||||
Window win;
|
||||
};
|
||||
@@ -138,6 +146,8 @@ typedef struct {
|
||||
const char *title;
|
||||
unsigned int tags;
|
||||
int isfloating;
|
||||
+ int isterminal;
|
||||
+ int noswallow;
|
||||
int monitor;
|
||||
} Rule;
|
||||
|
||||
@@ -235,6 +245,12 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee);
|
||||
static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
||||
static void zoom(const Arg *arg);
|
||||
|
||||
+static pid_t getparentprocess(pid_t p);
|
||||
+static int isdescprocess(pid_t p, pid_t c);
|
||||
+static Client *swallowingclient(Window w);
|
||||
+static Client *termforwin(const Client *c);
|
||||
+static pid_t winpid(Window w);
|
||||
+
|
||||
/* variables */
|
||||
static const char broken[] = "broken";
|
||||
static char stext[256];
|
||||
@@ -269,6 +285,8 @@ static Drw *drw;
|
||||
static Monitor *mons, *selmon;
|
||||
static Window root, wmcheckwin;
|
||||
|
||||
+static xcb_connection_t *xcon;
|
||||
+
|
||||
/* configuration, allows nested code to access above variables */
|
||||
#include "config.h"
|
||||
|
||||
@@ -298,6 +316,8 @@ applyrules(Client *c)
|
||||
&& (!r->class || strstr(class, r->class))
|
||||
&& (!r->instance || strstr(instance, r->instance)))
|
||||
{
|
||||
+ c->isterminal = r->isterminal;
|
||||
+ c->noswallow = r->noswallow;
|
||||
c->isfloating = r->isfloating;
|
||||
c->tags |= r->tags;
|
||||
for (m = mons; m && m->num != r->monitor; m = m->next);
|
||||
@@ -414,6 +434,53 @@ attachstack(Client *c)
|
||||
c->mon->stack = c;
|
||||
}
|
||||
|
||||
+void
|
||||
+swallow(Client *p, Client *c)
|
||||
+{
|
||||
+
|
||||
+ if (c->noswallow || c->isterminal)
|
||||
+ return;
|
||||
+ if (c->noswallow && !swallowfloating && c->isfloating)
|
||||
+ return;
|
||||
+
|
||||
+ detach(c);
|
||||
+ detachstack(c);
|
||||
+
|
||||
+ setclientstate(c, WithdrawnState);
|
||||
+ XUnmapWindow(dpy, p->win);
|
||||
+
|
||||
+ p->swallowing = c;
|
||||
+ c->mon = p->mon;
|
||||
+
|
||||
+ Window w = p->win;
|
||||
+ p->win = c->win;
|
||||
+ c->win = w;
|
||||
+ updatetitle(p);
|
||||
+ XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h);
|
||||
+ arrange(p->mon);
|
||||
+ configure(p);
|
||||
+ updateclientlist();
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+unswallow(Client *c)
|
||||
+{
|
||||
+ c->win = c->swallowing->win;
|
||||
+
|
||||
+ free(c->swallowing);
|
||||
+ c->swallowing = NULL;
|
||||
+
|
||||
+ /* unfullscreen the client */
|
||||
+ setfullscreen(c, 0);
|
||||
+ updatetitle(c);
|
||||
+ arrange(c->mon);
|
||||
+ XMapWindow(dpy, c->win);
|
||||
+ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
|
||||
+ setclientstate(c, NormalState);
|
||||
+ focus(NULL);
|
||||
+ arrange(c->mon);
|
||||
+}
|
||||
+
|
||||
void
|
||||
buttonpress(XEvent *e)
|
||||
{
|
||||
@@ -653,6 +720,9 @@ destroynotify(XEvent *e)
|
||||
|
||||
if ((c = wintoclient(ev->window)))
|
||||
unmanage(c, 1);
|
||||
+
|
||||
+ else if ((c = swallowingclient(ev->window)))
|
||||
+ unmanage(c->swallowing, 1);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1018,12 +1088,13 @@ killclient(const Arg *arg)
|
||||
void
|
||||
manage(Window w, XWindowAttributes *wa)
|
||||
{
|
||||
- Client *c, *t = NULL;
|
||||
+ Client *c, *t = NULL, *term = NULL;
|
||||
Window trans = None;
|
||||
XWindowChanges wc;
|
||||
|
||||
c = ecalloc(1, sizeof(Client));
|
||||
c->win = w;
|
||||
+ c->pid = winpid(w);
|
||||
/* geometry */
|
||||
c->x = c->oldx = wa->x;
|
||||
c->y = c->oldy = wa->y;
|
||||
@@ -1038,6 +1109,7 @@ manage(Window w, XWindowAttributes *wa)
|
||||
} else {
|
||||
c->mon = selmon;
|
||||
applyrules(c);
|
||||
+ term = termforwin(c);
|
||||
}
|
||||
|
||||
if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw)
|
||||
@@ -1074,6 +1146,8 @@ manage(Window w, XWindowAttributes *wa)
|
||||
c->mon->sel = c;
|
||||
arrange(c->mon);
|
||||
XMapWindow(dpy, c->win);
|
||||
+ if (term)
|
||||
+ swallow(term, c);
|
||||
focus(NULL);
|
||||
}
|
||||
|
||||
@@ -1768,6 +1842,20 @@ unmanage(Client *c, int destroyed)
|
||||
Monitor *m = c->mon;
|
||||
XWindowChanges wc;
|
||||
|
||||
+ if (c->swallowing) {
|
||||
+ unswallow(c);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ Client *s = swallowingclient(c->win);
|
||||
+ if (s) {
|
||||
+ free(s->swallowing);
|
||||
+ s->swallowing = NULL;
|
||||
+ arrange(m);
|
||||
+ focus(NULL);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
detach(c);
|
||||
detachstack(c);
|
||||
if (!destroyed) {
|
||||
@@ -1782,9 +1870,12 @@ unmanage(Client *c, int destroyed)
|
||||
XUngrabServer(dpy);
|
||||
}
|
||||
free(c);
|
||||
- focus(NULL);
|
||||
- updateclientlist();
|
||||
- arrange(m);
|
||||
+
|
||||
+ if (!s) {
|
||||
+ arrange(m);
|
||||
+ focus(NULL);
|
||||
+ updateclientlist();
|
||||
+ }
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2047,6 +2138,136 @@ view(const Arg *arg)
|
||||
arrange(selmon);
|
||||
}
|
||||
|
||||
+pid_t
|
||||
+winpid(Window w)
|
||||
+{
|
||||
+
|
||||
+ pid_t result = 0;
|
||||
+
|
||||
+ #ifdef __linux__
|
||||
+ xcb_res_client_id_spec_t spec = {0};
|
||||
+ spec.client = w;
|
||||
+ spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID;
|
||||
+
|
||||
+ xcb_generic_error_t *e = NULL;
|
||||
+ xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec);
|
||||
+ xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e);
|
||||
+
|
||||
+ if (!r)
|
||||
+ return (pid_t)0;
|
||||
+
|
||||
+ xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r);
|
||||
+ for (; i.rem; xcb_res_client_id_value_next(&i)) {
|
||||
+ spec = i.data->spec;
|
||||
+ if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) {
|
||||
+ uint32_t *t = xcb_res_client_id_value_value(i.data);
|
||||
+ result = *t;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ free(r);
|
||||
+
|
||||
+ if (result == (pid_t)-1)
|
||||
+ result = 0;
|
||||
+
|
||||
+ #endif /* __linux__ */
|
||||
+
|
||||
+ #ifdef __OpenBSD__
|
||||
+ Atom type;
|
||||
+ int format;
|
||||
+ unsigned long len, bytes;
|
||||
+ unsigned char *prop;
|
||||
+ pid_t ret;
|
||||
+
|
||||
+ if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 1), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop)
|
||||
+ return 0;
|
||||
+
|
||||
+ ret = *(pid_t*)prop;
|
||||
+ XFree(prop);
|
||||
+ result = ret;
|
||||
+
|
||||
+ #endif /* __OpenBSD__ */
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+pid_t
|
||||
+getparentprocess(pid_t p)
|
||||
+{
|
||||
+ unsigned int v = 0;
|
||||
+
|
||||
+#ifdef __linux__
|
||||
+ FILE *f;
|
||||
+ char buf[256];
|
||||
+ snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
|
||||
+
|
||||
+ if (!(f = fopen(buf, "r")))
|
||||
+ return 0;
|
||||
+
|
||||
+ fscanf(f, "%*u %*s %*c %u", &v);
|
||||
+ fclose(f);
|
||||
+#endif /* __linux__*/
|
||||
+
|
||||
+#ifdef __OpenBSD__
|
||||
+ int n;
|
||||
+ kvm_t *kd;
|
||||
+ struct kinfo_proc *kp;
|
||||
+
|
||||
+ kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL);
|
||||
+ if (!kd)
|
||||
+ return 0;
|
||||
+
|
||||
+ kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n);
|
||||
+ v = kp->p_ppid;
|
||||
+#endif /* __OpenBSD__ */
|
||||
+
|
||||
+ return (pid_t)v;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+isdescprocess(pid_t p, pid_t c)
|
||||
+{
|
||||
+ while (p != c && c != 0)
|
||||
+ c = getparentprocess(c);
|
||||
+
|
||||
+ return (int)c;
|
||||
+}
|
||||
+
|
||||
+Client *
|
||||
+termforwin(const Client *w)
|
||||
+{
|
||||
+ Client *c;
|
||||
+ Monitor *m;
|
||||
+
|
||||
+ if (!w->pid || w->isterminal)
|
||||
+ return NULL;
|
||||
+
|
||||
+ for (m = mons; m; m = m->next) {
|
||||
+ for (c = m->clients; c; c = c->next) {
|
||||
+ if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid))
|
||||
+ return c;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+Client *
|
||||
+swallowingclient(Window w)
|
||||
+{
|
||||
+ Client *c;
|
||||
+ Monitor *m;
|
||||
+
|
||||
+ for (m = mons; m; m = m->next) {
|
||||
+ for (c = m->clients; c; c = c->next) {
|
||||
+ if (c->swallowing && c->swallowing->win == w)
|
||||
+ return c;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
Client *
|
||||
wintoclient(Window w)
|
||||
{
|
||||
@@ -2138,10 +2359,12 @@ main(int argc, char *argv[])
|
||||
fputs("warning: no locale support\n", stderr);
|
||||
if (!(dpy = XOpenDisplay(NULL)))
|
||||
die("dwm: cannot open display");
|
||||
+ if (!(xcon = XGetXCBConnection(dpy)))
|
||||
+ die("dwm: cannot get xcb connection\n");
|
||||
checkotherwm();
|
||||
setup();
|
||||
#ifdef __OpenBSD__
|
||||
- if (pledge("stdio rpath proc exec", NULL) == -1)
|
||||
+ if (pledge("stdio rpath proc exec ps", NULL) == -1)
|
||||
die("pledge");
|
||||
#endif /* __OpenBSD__ */
|
||||
scan();
|
||||
--
|
||||
2.26.2
|
||||
|
38
patches/dwm-unfloatvisible-6.2.diff
Normal file
38
patches/dwm-unfloatvisible-6.2.diff
Normal file
@ -0,0 +1,38 @@
|
||||
From a972569532c9d46f79776b0f687ebbbd67a6b69f Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Courtis <alex@courtis.org>
|
||||
Date: Mon, 22 Apr 2019 22:23:12 +1000
|
||||
Subject: [PATCH] unfloat any visible windows which have isfloating set
|
||||
|
||||
optionally takes a layout to also apply
|
||||
|
||||
e.g.
|
||||
{ MODKEY|ShiftMask, XK_space, unfloatvisible, {0} },
|
||||
{ MODKEY|ShiftMask, XK_t, unfloatvisible, {.v = &layouts[1]} },
|
||||
---
|
||||
unfloat.c | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
create mode 100644 unfloat.c
|
||||
|
||||
diff --git a/unfloat.c b/unfloat.c
|
||||
new file mode 100644
|
||||
index 0000000..ef84111
|
||||
--- /dev/null
|
||||
+++ b/unfloat.c
|
||||
@@ -0,0 +1,14 @@
|
||||
+void
|
||||
+unfloatvisible(const Arg *arg)
|
||||
+{
|
||||
+ Client *c;
|
||||
+
|
||||
+ for (c = selmon->clients; c; c = c->next)
|
||||
+ if (ISVISIBLE(c) && c->isfloating)
|
||||
+ c->isfloating = c->isfixed;
|
||||
+
|
||||
+ if (arg && arg->v)
|
||||
+ setlayout(arg);
|
||||
+ else
|
||||
+ arrange(selmon);
|
||||
+}
|
||||
--
|
||||
2.21.0
|
||||
|
235
patches/dwm-xresources-6.2.diff
Normal file
235
patches/dwm-xresources-6.2.diff
Normal file
@ -0,0 +1,235 @@
|
||||
From 2832bd78a690606a48a7e1d370cd60fd92ee4988 Mon Sep 17 00:00:00 2001
|
||||
From: MLquest8 <miskuzius@gmail.com>
|
||||
Date: Fri, 12 Jun 2020 15:43:31 +0400
|
||||
Subject: [PATCH] handle various setting of various types from Xresources
|
||||
|
||||
---
|
||||
config.def.h | 54 ++++++++++++++++++++++++++-------------
|
||||
drw.c | 2 +-
|
||||
drw.h | 2 +-
|
||||
dwm.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 111 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..e69f288 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -1,21 +1,22 @@
|
||||
/* 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 int showbar = 1; /* 0 means no bar */
|
||||
-static const int topbar = 1; /* 0 means bottom bar */
|
||||
+static unsigned int borderpx = 1; /* border pixel of windows */
|
||||
+static unsigned int snap = 32; /* snap pixel */
|
||||
+static int showbar = 1; /* 0 means no bar */
|
||||
+static 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[] = "#222222";
|
||||
-static const char col_gray2[] = "#444444";
|
||||
-static const char col_gray3[] = "#bbbbbb";
|
||||
-static const char col_gray4[] = "#eeeeee";
|
||||
-static const char col_cyan[] = "#005577";
|
||||
-static const char *colors[][3] = {
|
||||
- /* fg bg border */
|
||||
- [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
|
||||
- [SchemeSel] = { col_gray4, col_cyan, col_cyan },
|
||||
+static char normbgcolor[] = "#222222";
|
||||
+static char normbordercolor[] = "#444444";
|
||||
+static char normfgcolor[] = "#bbbbbb";
|
||||
+static char selfgcolor[] = "#eeeeee";
|
||||
+static char selbordercolor[] = "#005577";
|
||||
+static char selbgcolor[] = "#005577";
|
||||
+static char *colors[][3] = {
|
||||
+ /* fg bg border */
|
||||
+ [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor },
|
||||
+ [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor },
|
||||
};
|
||||
|
||||
/* tagging */
|
||||
@@ -32,9 +33,9 @@ static const Rule rules[] = {
|
||||
};
|
||||
|
||||
/* 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 float mfact = 0.55; /* factor of master area size [0.05..0.95] */
|
||||
+static int nmaster = 1; /* number of clients in master area */
|
||||
+static int resizehints = 1; /* 1 means respect size hints in tiled resizals */
|
||||
|
||||
static const Layout layouts[] = {
|
||||
/* symbol arrange function */
|
||||
@@ -56,9 +57,28 @@ static const Layout layouts[] = {
|
||||
|
||||
/* 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 *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbordercolor, "-sf", selfgcolor, NULL };
|
||||
static const char *termcmd[] = { "st", NULL };
|
||||
|
||||
+/*
|
||||
+ * Xresources preferences to load at startup
|
||||
+ */
|
||||
+ResourcePref resources[] = {
|
||||
+ { "normbgcolor", STRING, &normbgcolor },
|
||||
+ { "normbordercolor", STRING, &normbordercolor },
|
||||
+ { "normfgcolor", STRING, &normfgcolor },
|
||||
+ { "selbgcolor", STRING, &selbgcolor },
|
||||
+ { "selbordercolor", STRING, &selbordercolor },
|
||||
+ { "selfgcolor", STRING, &selfgcolor },
|
||||
+ { "borderpx", INTEGER, &borderpx },
|
||||
+ { "snap", INTEGER, &snap },
|
||||
+ { "showbar", INTEGER, &showbar },
|
||||
+ { "topbar", INTEGER, &topbar },
|
||||
+ { "nmaster", INTEGER, &nmaster },
|
||||
+ { "resizehints", INTEGER, &resizehints },
|
||||
+ { "mfact", FLOAT, &mfact },
|
||||
+};
|
||||
+
|
||||
static Key keys[] = {
|
||||
/* modifier key function argument */
|
||||
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
||||
diff --git a/drw.c b/drw.c
|
||||
index 4cdbcbe..8f1059e 100644
|
||||
--- a/drw.c
|
||||
+++ b/drw.c
|
||||
@@ -208,7 +208,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
|
||||
/* Wrapper to create color schemes. The caller has to call free(3) on the
|
||||
* returned color scheme when done using it. */
|
||||
Clr *
|
||||
-drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
|
||||
+drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount)
|
||||
{
|
||||
size_t i;
|
||||
Clr *ret;
|
||||
diff --git a/drw.h b/drw.h
|
||||
index 4bcd5ad..42b04ce 100644
|
||||
--- a/drw.h
|
||||
+++ b/drw.h
|
||||
@@ -39,7 +39,7 @@ void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned in
|
||||
|
||||
/* Colorscheme abstraction */
|
||||
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
|
||||
-Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
|
||||
+Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount);
|
||||
|
||||
/* Cursor abstraction */
|
||||
Cur *drw_cur_create(Drw *drw, int shape);
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 9fd0286..dc0d219 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/Xutil.h>
|
||||
+#include <X11/Xresource.h>
|
||||
#ifdef XINERAMA
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
#endif /* XINERAMA */
|
||||
@@ -141,6 +142,19 @@ typedef struct {
|
||||
int monitor;
|
||||
} Rule;
|
||||
|
||||
+/* Xresources preferences */
|
||||
+enum resource_type {
|
||||
+ STRING = 0,
|
||||
+ INTEGER = 1,
|
||||
+ FLOAT = 2
|
||||
+};
|
||||
+
|
||||
+typedef struct {
|
||||
+ char *name;
|
||||
+ enum resource_type type;
|
||||
+ void *dst;
|
||||
+} ResourcePref;
|
||||
+
|
||||
/* function declarations */
|
||||
static void applyrules(Client *c);
|
||||
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
|
||||
@@ -234,6 +248,8 @@ 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);
|
||||
+static void load_xresources(void);
|
||||
+static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst);
|
||||
|
||||
/* variables */
|
||||
static const char broken[] = "broken";
|
||||
@@ -2127,6 +2143,60 @@ zoom(const Arg *arg)
|
||||
pop(c);
|
||||
}
|
||||
|
||||
+void
|
||||
+resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
|
||||
+{
|
||||
+ char *sdst = NULL;
|
||||
+ int *idst = NULL;
|
||||
+ float *fdst = NULL;
|
||||
+
|
||||
+ sdst = dst;
|
||||
+ idst = dst;
|
||||
+ fdst = dst;
|
||||
+
|
||||
+ char fullname[256];
|
||||
+ char *type;
|
||||
+ XrmValue ret;
|
||||
+
|
||||
+ snprintf(fullname, sizeof(fullname), "%s.%s", "dwm", name);
|
||||
+ fullname[sizeof(fullname) - 1] = '\0';
|
||||
+
|
||||
+ XrmGetResource(db, fullname, "*", &type, &ret);
|
||||
+ if (!(ret.addr == NULL || strncmp("String", type, 64)))
|
||||
+ {
|
||||
+ switch (rtype) {
|
||||
+ case STRING:
|
||||
+ strcpy(sdst, ret.addr);
|
||||
+ break;
|
||||
+ case INTEGER:
|
||||
+ *idst = strtoul(ret.addr, NULL, 10);
|
||||
+ break;
|
||||
+ case FLOAT:
|
||||
+ *fdst = strtof(ret.addr, NULL);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+load_xresources(void)
|
||||
+{
|
||||
+ Display *display;
|
||||
+ char *resm;
|
||||
+ XrmDatabase db;
|
||||
+ ResourcePref *p;
|
||||
+
|
||||
+ display = XOpenDisplay(NULL);
|
||||
+ resm = XResourceManagerString(display);
|
||||
+ if (!resm)
|
||||
+ return;
|
||||
+
|
||||
+ db = XrmGetStringDatabase(resm);
|
||||
+ for (p = resources; p < resources + LENGTH(resources); p++)
|
||||
+ resource_load(db, p->name, p->type, p->dst);
|
||||
+ XCloseDisplay(display);
|
||||
+}
|
||||
+
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
@@ -2139,6 +2209,8 @@ main(int argc, char *argv[])
|
||||
if (!(dpy = XOpenDisplay(NULL)))
|
||||
die("dwm: cannot open display");
|
||||
checkotherwm();
|
||||
+ XrmInitialize();
|
||||
+ load_xresources();
|
||||
setup();
|
||||
#ifdef __OpenBSD__
|
||||
if (pledge("stdio rpath proc exec", NULL) == -1)
|
||||
--
|
||||
2.26.2
|
||||
|
14
unfloat.c
Normal file
14
unfloat.c
Normal file
@ -0,0 +1,14 @@
|
||||
void
|
||||
unfloatvisible(const Arg *arg)
|
||||
{
|
||||
Client *c;
|
||||
|
||||
for (c = selmon->clients; c; c = c->next)
|
||||
if (ISVISIBLE(c) && c->isfloating)
|
||||
c->isfloating = c->isfixed;
|
||||
|
||||
if (arg && arg->v)
|
||||
setlayout(arg);
|
||||
else
|
||||
arrange(selmon);
|
||||
}
|
135
util.c
135
util.c
@ -3,6 +3,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
@ -33,3 +35,136 @@ die(const char *fmt, ...) {
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
normalizepath(const char *path, char **normal)
|
||||
{
|
||||
size_t len = strlen(path);
|
||||
*normal = (char *)malloc((len + 1) * sizeof(char));
|
||||
const char *walk = path;
|
||||
const char *match;
|
||||
size_t newlen = 0;
|
||||
|
||||
while ((match = strchr(walk, '/'))) {
|
||||
// Copy everything between match and walk
|
||||
strncpy(*normal + newlen, walk, match - walk);
|
||||
newlen += match - walk;
|
||||
walk += match - walk;
|
||||
|
||||
// Skip all repeating slashes
|
||||
while (*walk == '/')
|
||||
walk++;
|
||||
|
||||
// If not last character in path
|
||||
if (walk != path + len)
|
||||
(*normal)[newlen++] = '/';
|
||||
}
|
||||
|
||||
(*normal)[newlen++] = '\0';
|
||||
|
||||
// Copy remaining path
|
||||
strcat(*normal, walk);
|
||||
newlen += strlen(walk);
|
||||
|
||||
*normal = (char *)realloc(*normal, newlen * sizeof(char));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
parentdir(const char *path, char **parent)
|
||||
{
|
||||
char *normal;
|
||||
char *walk;
|
||||
|
||||
normalizepath(path, &normal);
|
||||
|
||||
// Pointer to last '/'
|
||||
if (!(walk = strrchr(normal, '/'))) {
|
||||
free(normal);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get path up to last '/'
|
||||
size_t len = walk - normal;
|
||||
*parent = (char *)malloc((len + 1) * sizeof(char));
|
||||
|
||||
// Copy path up to last '/'
|
||||
strncpy(*parent, normal, len);
|
||||
// Add null char
|
||||
(*parent)[len] = '\0';
|
||||
|
||||
free(normal);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mkdirp(const char *path)
|
||||
{
|
||||
char *normal;
|
||||
char *walk;
|
||||
size_t normallen;
|
||||
|
||||
normalizepath(path, &normal);
|
||||
normallen = strlen(normal);
|
||||
walk = normal;
|
||||
|
||||
while (walk < normal + normallen + 1) {
|
||||
// Get length from walk to next /
|
||||
size_t n = strcspn(walk, "/");
|
||||
|
||||
// Skip path /
|
||||
if (n == 0) {
|
||||
walk++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Length of current path segment
|
||||
size_t curpathlen = walk - normal + n;
|
||||
char curpath[curpathlen + 1];
|
||||
struct stat s;
|
||||
|
||||
// Copy path segment to stat
|
||||
strncpy(curpath, normal, curpathlen);
|
||||
strcpy(curpath + curpathlen, "");
|
||||
int res = stat(curpath, &s);
|
||||
|
||||
if (res < 0) {
|
||||
if (errno == ENOENT) {
|
||||
DEBUG("Making directory %s\n", curpath);
|
||||
if (mkdir(curpath, 0700) < 0) {
|
||||
fprintf(stderr, "Failed to make directory %s\n", curpath);
|
||||
perror("");
|
||||
free(normal);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Error statting directory %s\n", curpath);
|
||||
perror("");
|
||||
free(normal);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Continue to next path segment
|
||||
walk += n;
|
||||
}
|
||||
|
||||
free(normal);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nullterminate(char **str, size_t *len)
|
||||
{
|
||||
if ((*str)[*len - 1] == '\0')
|
||||
return 0;
|
||||
|
||||
(*len)++;
|
||||
*str = (char*)realloc(*str, *len * sizeof(char));
|
||||
(*str)[*len - 1] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
10
util.h
10
util.h
@ -4,5 +4,15 @@
|
||||
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG(...)
|
||||
#endif
|
||||
|
||||
void die(const char *fmt, ...);
|
||||
void *ecalloc(size_t nmemb, size_t size);
|
||||
int normalizepath(const char *path, char **normal);
|
||||
int mkdirp(const char *path);
|
||||
int parentdir(const char *path, char **parent);
|
||||
int nullterminate(char **str, size_t *len);
|
||||
|
822
vanitygaps.c
Normal file
822
vanitygaps.c
Normal file
@ -0,0 +1,822 @@
|
||||
/* Key binding functions */
|
||||
static void defaultgaps(const Arg *arg);
|
||||
static void incrgaps(const Arg *arg);
|
||||
static void incrigaps(const Arg *arg);
|
||||
static void incrogaps(const Arg *arg);
|
||||
static void incrohgaps(const Arg *arg);
|
||||
static void incrovgaps(const Arg *arg);
|
||||
static void incrihgaps(const Arg *arg);
|
||||
static void incrivgaps(const Arg *arg);
|
||||
static void togglegaps(const Arg *arg);
|
||||
/* Layouts (delete the ones you do not need) */
|
||||
static void bstack(Monitor *m);
|
||||
static void bstackhoriz(Monitor *m);
|
||||
static void centeredmaster(Monitor *m);
|
||||
static void centeredfloatingmaster(Monitor *m);
|
||||
static void deck(Monitor *m);
|
||||
static void dwindle(Monitor *m);
|
||||
static void fibonacci(Monitor *m, int s);
|
||||
static void grid(Monitor *m);
|
||||
static void nrowgrid(Monitor *m);
|
||||
static void spiral(Monitor *m);
|
||||
static void tile(Monitor *m);
|
||||
/* Internals */
|
||||
static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc);
|
||||
static void getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr);
|
||||
static void setgaps(int oh, int ov, int ih, int iv);
|
||||
|
||||
/* Settings */
|
||||
#if !PERTAG_PATCH
|
||||
static int enablegaps = 1;
|
||||
#endif // PERTAG_PATCH
|
||||
|
||||
void
|
||||
setgaps(int oh, int ov, int ih, int iv)
|
||||
{
|
||||
if (oh < 0) oh = 0;
|
||||
if (ov < 0) ov = 0;
|
||||
if (ih < 0) ih = 0;
|
||||
if (iv < 0) iv = 0;
|
||||
|
||||
selmon->gappoh = oh;
|
||||
selmon->gappov = ov;
|
||||
selmon->gappih = ih;
|
||||
selmon->gappiv = iv;
|
||||
arrange(selmon);
|
||||
}
|
||||
|
||||
void
|
||||
togglegaps(const Arg *arg)
|
||||
{
|
||||
#if PERTAG_PATCH
|
||||
selmon->pertag->enablegaps[selmon->pertag->curtag] = !selmon->pertag->enablegaps[selmon->pertag->curtag];
|
||||
#else
|
||||
enablegaps = !enablegaps;
|
||||
#endif // PERTAG_PATCH
|
||||
arrange(NULL);
|
||||
}
|
||||
|
||||
void
|
||||
defaultgaps(const Arg *arg)
|
||||
{
|
||||
setgaps(gappoh, gappov, gappih, gappiv);
|
||||
}
|
||||
|
||||
void
|
||||
incrgaps(const Arg *arg)
|
||||
{
|
||||
setgaps(
|
||||
selmon->gappoh + arg->i,
|
||||
selmon->gappov + arg->i,
|
||||
selmon->gappih + arg->i,
|
||||
selmon->gappiv + arg->i
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
incrigaps(const Arg *arg)
|
||||
{
|
||||
setgaps(
|
||||
selmon->gappoh,
|
||||
selmon->gappov,
|
||||
selmon->gappih + arg->i,
|
||||
selmon->gappiv + arg->i
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
incrogaps(const Arg *arg)
|
||||
{
|
||||
setgaps(
|
||||
selmon->gappoh + arg->i,
|
||||
selmon->gappov + arg->i,
|
||||
selmon->gappih,
|
||||
selmon->gappiv
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
incrohgaps(const Arg *arg)
|
||||
{
|
||||
setgaps(
|
||||
selmon->gappoh + arg->i,
|
||||
selmon->gappov,
|
||||
selmon->gappih,
|
||||
selmon->gappiv
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
incrovgaps(const Arg *arg)
|
||||
{
|
||||
setgaps(
|
||||
selmon->gappoh,
|
||||
selmon->gappov + arg->i,
|
||||
selmon->gappih,
|
||||
selmon->gappiv
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
incrihgaps(const Arg *arg)
|
||||
{
|
||||
setgaps(
|
||||
selmon->gappoh,
|
||||
selmon->gappov,
|
||||
selmon->gappih + arg->i,
|
||||
selmon->gappiv
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
incrivgaps(const Arg *arg)
|
||||
{
|
||||
setgaps(
|
||||
selmon->gappoh,
|
||||
selmon->gappov,
|
||||
selmon->gappih,
|
||||
selmon->gappiv + arg->i
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc)
|
||||
{
|
||||
unsigned int n, oe, ie;
|
||||
#if PERTAG_PATCH
|
||||
oe = ie = selmon->pertag->enablegaps[selmon->pertag->curtag];
|
||||
#else
|
||||
oe = ie = enablegaps;
|
||||
#endif // PERTAG_PATCH
|
||||
Client *c;
|
||||
|
||||
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
|
||||
if (smartgaps && n == 1) {
|
||||
oe = 0; // outer gaps disabled when only one client
|
||||
}
|
||||
|
||||
*oh = m->gappoh*oe; // outer horizontal gap
|
||||
*ov = m->gappov*oe; // outer vertical gap
|
||||
*ih = m->gappih*ie; // inner horizontal gap
|
||||
*iv = m->gappiv*ie; // inner vertical gap
|
||||
*nc = n; // number of clients
|
||||
}
|
||||
|
||||
void
|
||||
getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr)
|
||||
{
|
||||
unsigned int n;
|
||||
float mfacts = 0, sfacts = 0;
|
||||
int mtotal = 0, stotal = 0;
|
||||
Client *c;
|
||||
|
||||
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
|
||||
if (n < m->nmaster)
|
||||
mfacts += c->cfact;
|
||||
else
|
||||
sfacts += c->cfact;
|
||||
|
||||
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
|
||||
if (n < m->nmaster)
|
||||
mtotal += msize * (c->cfact / mfacts);
|
||||
else
|
||||
stotal += ssize * (c->cfact / sfacts);
|
||||
|
||||
*mf = mfacts; // total factor of master area
|
||||
*sf = sfacts; // total factor of stack area
|
||||
*mr = msize - mtotal; // the remainder (rest) of pixels after a cfacts master split
|
||||
*sr = ssize - stotal; // the remainder (rest) of pixels after a cfacts stack split
|
||||
}
|
||||
|
||||
/***
|
||||
* Layouts
|
||||
*/
|
||||
|
||||
/*
|
||||
* Bottomstack layout + gaps
|
||||
* https://dwm.suckless.org/patches/bottomstack/
|
||||
*/
|
||||
static void
|
||||
bstack(Monitor *m)
|
||||
{
|
||||
unsigned int i, n;
|
||||
int oh, ov, ih, iv;
|
||||
int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
float mfacts, sfacts;
|
||||
int mrest, srest;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
sx = mx = m->wx + ov;
|
||||
sy = my = m->wy + oh;
|
||||
sh = mh = m->wh - 2*oh;
|
||||
mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
|
||||
sw = m->ww - 2*ov - iv * (n - m->nmaster - 1);
|
||||
|
||||
if (m->nmaster && n > m->nmaster) {
|
||||
sh = (mh - ih) * (1 - m->mfact);
|
||||
mh = mh - ih - sh;
|
||||
sx = mx;
|
||||
sy = my + mh + ih;
|
||||
}
|
||||
|
||||
getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
||||
if (i < m->nmaster) {
|
||||
resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
||||
mx += WIDTH(c) + iv;
|
||||
} else {
|
||||
resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
|
||||
sx += WIDTH(c) + iv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bstackhoriz(Monitor *m)
|
||||
{
|
||||
unsigned int i, n;
|
||||
int oh, ov, ih, iv;
|
||||
int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
float mfacts, sfacts;
|
||||
int mrest, srest;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
sx = mx = m->wx + ov;
|
||||
sy = my = m->wy + oh;
|
||||
mh = m->wh - 2*oh;
|
||||
sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
|
||||
mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
|
||||
sw = m->ww - 2*ov;
|
||||
|
||||
if (m->nmaster && n > m->nmaster) {
|
||||
sh = (mh - ih) * (1 - m->mfact);
|
||||
mh = mh - ih - sh;
|
||||
sy = my + mh + ih;
|
||||
sh = m->wh - mh - 2*oh - ih * (n - m->nmaster);
|
||||
}
|
||||
|
||||
getfacts(m, mw, sh, &mfacts, &sfacts, &mrest, &srest);
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
||||
if (i < m->nmaster) {
|
||||
resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
||||
mx += WIDTH(c) + iv;
|
||||
} else {
|
||||
resize(c, sx, sy, sw - (2*c->bw), sh * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
|
||||
sy += HEIGHT(c) + ih;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Centred master layout + gaps
|
||||
* https://dwm.suckless.org/patches/centeredmaster/
|
||||
*/
|
||||
void
|
||||
centeredmaster(Monitor *m)
|
||||
{
|
||||
unsigned int i, n;
|
||||
int oh, ov, ih, iv;
|
||||
int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
int lx = 0, ly = 0, lw = 0, lh = 0;
|
||||
int rx = 0, ry = 0, rw = 0, rh = 0;
|
||||
float mfacts = 0, lfacts = 0, rfacts = 0;
|
||||
int mtotal = 0, ltotal = 0, rtotal = 0;
|
||||
int mrest = 0, lrest = 0, rrest = 0;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
/* initialize areas */
|
||||
mx = m->wx + ov;
|
||||
my = m->wy + oh;
|
||||
mh = m->wh - 2*oh - ih * ((!m->nmaster ? n : MIN(n, m->nmaster)) - 1);
|
||||
mw = m->ww - 2*ov;
|
||||
lh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - 1);
|
||||
rh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - ((n - m->nmaster) % 2 ? 0 : 1));
|
||||
|
||||
if (m->nmaster && n > m->nmaster) {
|
||||
/* go mfact box in the center if more than nmaster clients */
|
||||
if (n - m->nmaster > 1) {
|
||||
/* ||<-S->|<---M--->|<-S->|| */
|
||||
mw = (m->ww - 2*ov - 2*iv) * m->mfact;
|
||||
lw = (m->ww - mw - 2*ov - 2*iv) / 2;
|
||||
rw = (m->ww - mw - 2*ov - 2*iv) - lw;
|
||||
mx += lw + iv;
|
||||
} else {
|
||||
/* ||<---M--->|<-S->|| */
|
||||
mw = (mw - iv) * m->mfact;
|
||||
lw = 0;
|
||||
rw = m->ww - mw - iv - 2*ov;
|
||||
}
|
||||
lx = m->wx + ov;
|
||||
ly = m->wy + oh;
|
||||
rx = mx + mw + iv;
|
||||
ry = m->wy + oh;
|
||||
}
|
||||
|
||||
/* calculate facts */
|
||||
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) {
|
||||
if (!m->nmaster || n < m->nmaster)
|
||||
mfacts += c->cfact;
|
||||
else if ((n - m->nmaster) % 2)
|
||||
lfacts += c->cfact; // total factor of left hand stack area
|
||||
else
|
||||
rfacts += c->cfact; // total factor of right hand stack area
|
||||
}
|
||||
|
||||
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
|
||||
if (!m->nmaster || n < m->nmaster)
|
||||
mtotal += mh * (c->cfact / mfacts);
|
||||
else if ((n - m->nmaster) % 2)
|
||||
ltotal += lh * (c->cfact / lfacts);
|
||||
else
|
||||
rtotal += rh * (c->cfact / rfacts);
|
||||
|
||||
mrest = mh - mtotal;
|
||||
lrest = lh - ltotal;
|
||||
rrest = rh - rtotal;
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
||||
if (!m->nmaster || i < m->nmaster) {
|
||||
/* nmaster clients are stacked vertically, in the center of the screen */
|
||||
resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
|
||||
my += HEIGHT(c) + ih;
|
||||
} else {
|
||||
/* stack clients are stacked vertically */
|
||||
if ((i - m->nmaster) % 2 ) {
|
||||
resize(c, lx, ly, lw - (2*c->bw), lh * (c->cfact / lfacts) + ((i - 2*m->nmaster) < 2*lrest ? 1 : 0) - (2*c->bw), 0);
|
||||
ly += HEIGHT(c) + ih;
|
||||
} else {
|
||||
resize(c, rx, ry, rw - (2*c->bw), rh * (c->cfact / rfacts) + ((i - 2*m->nmaster) < 2*rrest ? 1 : 0) - (2*c->bw), 0);
|
||||
ry += HEIGHT(c) + ih;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
centeredfloatingmaster(Monitor *m)
|
||||
{
|
||||
unsigned int i, n;
|
||||
float mfacts, sfacts;
|
||||
float mivf = 1.0; // master inner vertical gap factor
|
||||
int oh, ov, ih, iv, mrest, srest;
|
||||
int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
sx = mx = m->wx + ov;
|
||||
sy = my = m->wy + oh;
|
||||
sh = mh = m->wh - 2*oh;
|
||||
mw = m->ww - 2*ov - iv*(n - 1);
|
||||
sw = m->ww - 2*ov - iv*(n - m->nmaster - 1);
|
||||
|
||||
if (m->nmaster && n > m->nmaster) {
|
||||
mivf = 0.8;
|
||||
/* go mfact box in the center if more than nmaster clients */
|
||||
if (m->ww > m->wh) {
|
||||
mw = m->ww * m->mfact - iv*mivf*(MIN(n, m->nmaster) - 1);
|
||||
mh = m->wh * 0.9;
|
||||
} else {
|
||||
mw = m->ww * 0.9 - iv*mivf*(MIN(n, m->nmaster) - 1);
|
||||
mh = m->wh * m->mfact;
|
||||
}
|
||||
mx = m->wx + (m->ww - mw) / 2;
|
||||
my = m->wy + (m->wh - mh - 2*oh) / 2;
|
||||
|
||||
sx = m->wx + ov;
|
||||
sy = m->wy + oh;
|
||||
sh = m->wh - 2*oh;
|
||||
}
|
||||
|
||||
getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
if (i < m->nmaster) {
|
||||
/* nmaster clients are stacked horizontally, in the center of the screen */
|
||||
resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
||||
mx += WIDTH(c) + iv*mivf;
|
||||
} else {
|
||||
/* stack clients are stacked horizontally */
|
||||
resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
|
||||
sx += WIDTH(c) + iv;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Deck layout + gaps
|
||||
* https://dwm.suckless.org/patches/deck/
|
||||
*/
|
||||
void
|
||||
deck(Monitor *m)
|
||||
{
|
||||
unsigned int i, n;
|
||||
int oh, ov, ih, iv;
|
||||
int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
float mfacts, sfacts;
|
||||
int mrest, srest;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
sx = mx = m->wx + ov;
|
||||
sy = my = m->wy + oh;
|
||||
sh = mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1);
|
||||
sw = mw = m->ww - 2*ov;
|
||||
|
||||
if (m->nmaster && n > m->nmaster) {
|
||||
sw = (mw - iv) * (1 - m->mfact);
|
||||
mw = mw - iv - sw;
|
||||
sx = mx + mw + iv;
|
||||
sh = m->wh - 2*oh;
|
||||
}
|
||||
|
||||
getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);
|
||||
|
||||
if (n - m->nmaster > 0) /* override layout symbol */
|
||||
snprintf(m->ltsymbol, sizeof m->ltsymbol, "D %d", n - m->nmaster);
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
if (i < m->nmaster) {
|
||||
resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
|
||||
my += HEIGHT(c) + ih;
|
||||
} else {
|
||||
resize(c, sx, sy, sw - (2*c->bw), sh - (2*c->bw), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fibonacci layout + gaps
|
||||
* https://dwm.suckless.org/patches/fibonacci/
|
||||
*/
|
||||
void
|
||||
fibonacci(Monitor *m, int s)
|
||||
{
|
||||
unsigned int i, n;
|
||||
int nx, ny, nw, nh;
|
||||
int oh, ov, ih, iv;
|
||||
int nv, hrest = 0, wrest = 0, r = 1;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
nx = m->wx + ov;
|
||||
ny = m->wy + oh;
|
||||
nw = m->ww - 2*ov;
|
||||
nh = m->wh - 2*oh;
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
|
||||
if (r) {
|
||||
if ((i % 2 && (nh - ih) / 2 <= (bh + 2*c->bw))
|
||||
|| (!(i % 2) && (nw - iv) / 2 <= (bh + 2*c->bw))) {
|
||||
r = 0;
|
||||
}
|
||||
if (r && i < n - 1) {
|
||||
if (i % 2) {
|
||||
nv = (nh - ih) / 2;
|
||||
hrest = nh - 2*nv - ih;
|
||||
nh = nv;
|
||||
} else {
|
||||
nv = (nw - iv) / 2;
|
||||
wrest = nw - 2*nv - iv;
|
||||
nw = nv;
|
||||
}
|
||||
|
||||
if ((i % 4) == 2 && !s)
|
||||
nx += nw + iv;
|
||||
else if ((i % 4) == 3 && !s)
|
||||
ny += nh + ih;
|
||||
}
|
||||
|
||||
if ((i % 4) == 0) {
|
||||
if (s) {
|
||||
ny += nh + ih;
|
||||
nh += hrest;
|
||||
}
|
||||
else {
|
||||
nh -= hrest;
|
||||
ny -= nh + ih;
|
||||
}
|
||||
}
|
||||
else if ((i % 4) == 1) {
|
||||
nx += nw + iv;
|
||||
nw += wrest;
|
||||
}
|
||||
else if ((i % 4) == 2) {
|
||||
ny += nh + ih;
|
||||
nh += hrest;
|
||||
if (i < n - 1)
|
||||
nw += wrest;
|
||||
}
|
||||
else if ((i % 4) == 3) {
|
||||
if (s) {
|
||||
nx += nw + iv;
|
||||
nw -= wrest;
|
||||
} else {
|
||||
nw -= wrest;
|
||||
nx -= nw + iv;
|
||||
nh += hrest;
|
||||
}
|
||||
}
|
||||
if (i == 0) {
|
||||
if (n != 1) {
|
||||
nw = (m->ww - iv - 2*ov) - (m->ww - iv - 2*ov) * (1 - m->mfact);
|
||||
wrest = 0;
|
||||
}
|
||||
ny = m->wy + oh;
|
||||
}
|
||||
else if (i == 1)
|
||||
nw = m->ww - nw - iv - 2*ov;
|
||||
i++;
|
||||
}
|
||||
|
||||
resize(c, nx, ny, nw - (2*c->bw), nh - (2*c->bw), False);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dwindle(Monitor *m)
|
||||
{
|
||||
fibonacci(m, 1);
|
||||
}
|
||||
|
||||
void
|
||||
spiral(Monitor *m)
|
||||
{
|
||||
fibonacci(m, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Gappless grid layout + gaps (ironically)
|
||||
* https://dwm.suckless.org/patches/gaplessgrid/
|
||||
*/
|
||||
void
|
||||
gaplessgrid(Monitor *m)
|
||||
{
|
||||
unsigned int i, n;
|
||||
int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters
|
||||
int oh, ov, ih, iv;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
/* grid dimensions */
|
||||
for (cols = 0; cols <= n/2; cols++)
|
||||
if (cols*cols >= n)
|
||||
break;
|
||||
if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
|
||||
cols = 2;
|
||||
rows = n/cols;
|
||||
cn = rn = 0; // reset column no, row no, client count
|
||||
|
||||
ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
|
||||
cw = (m->ww - 2*ov - iv * (cols - 1)) / cols;
|
||||
rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
|
||||
crest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
|
||||
x = m->wx + ov;
|
||||
y = m->wy + oh;
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) {
|
||||
if (i/rows + 1 > cols - n%cols) {
|
||||
rows = n/cols + 1;
|
||||
ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
|
||||
rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
|
||||
}
|
||||
resize(c,
|
||||
x,
|
||||
y + rn*(ch + ih) + MIN(rn, rrest),
|
||||
cw + (cn < crest ? 1 : 0) - 2*c->bw,
|
||||
ch + (rn < rrest ? 1 : 0) - 2*c->bw,
|
||||
0);
|
||||
rn++;
|
||||
if (rn >= rows) {
|
||||
rn = 0;
|
||||
x += cw + ih + (cn < crest ? 1 : 0);
|
||||
cn++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Gridmode layout + gaps
|
||||
* https://dwm.suckless.org/patches/gridmode/
|
||||
*/
|
||||
void
|
||||
grid(Monitor *m)
|
||||
{
|
||||
unsigned int i, n;
|
||||
int cx, cy, cw, ch, cc, cr, chrest, cwrest, cols, rows;
|
||||
int oh, ov, ih, iv;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
|
||||
/* grid dimensions */
|
||||
for (rows = 0; rows <= n/2; rows++)
|
||||
if (rows*rows >= n)
|
||||
break;
|
||||
cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;
|
||||
|
||||
/* window geoms (cell height/width) */
|
||||
ch = (m->wh - 2*oh - ih * (rows - 1)) / (rows ? rows : 1);
|
||||
cw = (m->ww - 2*ov - iv * (cols - 1)) / (cols ? cols : 1);
|
||||
chrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
|
||||
cwrest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
||||
cc = i / rows;
|
||||
cr = i % rows;
|
||||
cx = m->wx + ov + cc * (cw + iv) + MIN(cc, cwrest);
|
||||
cy = m->wy + oh + cr * (ch + ih) + MIN(cr, chrest);
|
||||
resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Horizontal grid layout + gaps
|
||||
* https://dwm.suckless.org/patches/horizgrid/
|
||||
*/
|
||||
void
|
||||
horizgrid(Monitor *m) {
|
||||
Client *c;
|
||||
unsigned int n, i;
|
||||
int oh, ov, ih, iv;
|
||||
int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
int ntop, nbottom = 1;
|
||||
float mfacts = 0, sfacts = 0;
|
||||
int mrest, srest, mtotal = 0, stotal = 0;
|
||||
|
||||
/* Count windows */
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
if (n <= 2)
|
||||
ntop = n;
|
||||
else {
|
||||
ntop = n / 2;
|
||||
nbottom = n - ntop;
|
||||
}
|
||||
sx = mx = m->wx + ov;
|
||||
sy = my = m->wy + oh;
|
||||
sh = mh = m->wh - 2*oh;
|
||||
sw = mw = m->ww - 2*ov;
|
||||
|
||||
if (n > ntop) {
|
||||
sh = (mh - ih) / 2;
|
||||
mh = mh - ih - sh;
|
||||
sy = my + mh + ih;
|
||||
mw = m->ww - 2*ov - iv * (ntop - 1);
|
||||
sw = m->ww - 2*ov - iv * (nbottom - 1);
|
||||
}
|
||||
|
||||
/* calculate facts */
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
if (i < ntop)
|
||||
mfacts += c->cfact;
|
||||
else
|
||||
sfacts += c->cfact;
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
if (i < ntop)
|
||||
mtotal += mh * (c->cfact / mfacts);
|
||||
else
|
||||
stotal += sw * (c->cfact / sfacts);
|
||||
|
||||
mrest = mh - mtotal;
|
||||
srest = sw - stotal;
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
if (i < ntop) {
|
||||
resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
||||
mx += WIDTH(c) + iv;
|
||||
} else {
|
||||
resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - ntop) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
|
||||
sx += WIDTH(c) + iv;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nrowgrid layout + gaps
|
||||
* https://dwm.suckless.org/patches/nrowgrid/
|
||||
*/
|
||||
void
|
||||
nrowgrid(Monitor *m)
|
||||
{
|
||||
unsigned int n;
|
||||
int ri = 0, ci = 0; /* counters */
|
||||
int oh, ov, ih, iv; /* vanitygap settings */
|
||||
unsigned int cx, cy, cw, ch; /* client geometry */
|
||||
unsigned int uw = 0, uh = 0, uc = 0; /* utilization trackers */
|
||||
unsigned int cols, rows = m->nmaster + 1;
|
||||
Client *c;
|
||||
|
||||
/* count clients */
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
|
||||
/* nothing to do here */
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
/* force 2 clients to always split vertically */
|
||||
if (FORCE_VSPLIT && n == 2)
|
||||
rows = 1;
|
||||
|
||||
/* never allow empty rows */
|
||||
if (n < rows)
|
||||
rows = n;
|
||||
|
||||
/* define first row */
|
||||
cols = n / rows;
|
||||
uc = cols;
|
||||
cy = m->wy + oh;
|
||||
ch = (m->wh - 2*oh - ih*(rows - 1)) / rows;
|
||||
uh = ch;
|
||||
|
||||
for (c = nexttiled(m->clients); c; c = nexttiled(c->next), ci++) {
|
||||
if (ci == cols) {
|
||||
uw = 0;
|
||||
ci = 0;
|
||||
ri++;
|
||||
|
||||
/* next row */
|
||||
cols = (n - uc) / (rows - ri);
|
||||
uc += cols;
|
||||
cy = m->wy + oh + uh + ih;
|
||||
uh += ch + ih;
|
||||
}
|
||||
|
||||
cx = m->wx + ov + uw;
|
||||
cw = (m->ww - 2*ov - uw) / (cols - ci);
|
||||
uw += cw + iv;
|
||||
|
||||
resize(c, cx, cy, cw - (2*c->bw), ch - (2*c->bw), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Default tile layout + gaps
|
||||
*/
|
||||
static void
|
||||
tile(Monitor *m)
|
||||
{
|
||||
unsigned int i, n;
|
||||
int oh, ov, ih, iv;
|
||||
int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
float mfacts, sfacts;
|
||||
int mrest, srest;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
sx = mx = m->wx + ov;
|
||||
sy = my = m->wy + oh;
|
||||
mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1);
|
||||
sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
|
||||
sw = mw = m->ww - 2*ov;
|
||||
|
||||
if (m->nmaster && n > m->nmaster) {
|
||||
sw = (mw - iv) * (1 - m->mfact);
|
||||
mw = mw - iv - sw;
|
||||
sx = mx + mw + iv;
|
||||
}
|
||||
|
||||
getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
if (i < m->nmaster) {
|
||||
resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
|
||||
my += HEIGHT(c) + ih;
|
||||
} else {
|
||||
resize(c, sx, sy, sw - (2*c->bw), sh * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
|
||||
sy += HEIGHT(c) + ih;
|
||||
}
|
||||
}
|
351
yajl_dumps.c
Normal file
351
yajl_dumps.c
Normal file
@ -0,0 +1,351 @@
|
||||
#include "yajl_dumps.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int
|
||||
dump_tag(yajl_gen gen, const char *name, const int tag_mask)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("bit_mask"); YINT(tag_mask);
|
||||
YSTR("name"); YSTR(name);
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_tags(yajl_gen gen, const char *tags[], int tags_len)
|
||||
{
|
||||
// clang-format off
|
||||
YARR(
|
||||
for (int i = 0; i < tags_len; i++)
|
||||
dump_tag(gen, tags[i], 1 << i);
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_client(yajl_gen gen, Client *c)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("name"); YSTR(c->name);
|
||||
YSTR("tags"); YINT(c->tags);
|
||||
YSTR("window_id"); YINT(c->win);
|
||||
YSTR("monitor_number"); YINT(c->mon->num);
|
||||
|
||||
YSTR("geometry"); YMAP(
|
||||
YSTR("current"); YMAP (
|
||||
YSTR("x"); YINT(c->x);
|
||||
YSTR("y"); YINT(c->y);
|
||||
YSTR("width"); YINT(c->w);
|
||||
YSTR("height"); YINT(c->h);
|
||||
)
|
||||
YSTR("old"); YMAP(
|
||||
YSTR("x"); YINT(c->oldx);
|
||||
YSTR("y"); YINT(c->oldy);
|
||||
YSTR("width"); YINT(c->oldw);
|
||||
YSTR("height"); YINT(c->oldh);
|
||||
)
|
||||
)
|
||||
|
||||
YSTR("size_hints"); YMAP(
|
||||
YSTR("base"); YMAP(
|
||||
YSTR("width"); YINT(c->basew);
|
||||
YSTR("height"); YINT(c->baseh);
|
||||
)
|
||||
YSTR("step"); YMAP(
|
||||
YSTR("width"); YINT(c->incw);
|
||||
YSTR("height"); YINT(c->inch);
|
||||
)
|
||||
YSTR("max"); YMAP(
|
||||
YSTR("width"); YINT(c->maxw);
|
||||
YSTR("height"); YINT(c->maxh);
|
||||
)
|
||||
YSTR("min"); YMAP(
|
||||
YSTR("width"); YINT(c->minw);
|
||||
YSTR("height"); YINT(c->minh);
|
||||
)
|
||||
YSTR("aspect_ratio"); YMAP(
|
||||
YSTR("min"); YDOUBLE(c->mina);
|
||||
YSTR("max"); YDOUBLE(c->maxa);
|
||||
)
|
||||
)
|
||||
|
||||
YSTR("border_width"); YMAP(
|
||||
YSTR("current"); YINT(c->bw);
|
||||
YSTR("old"); YINT(c->oldbw);
|
||||
)
|
||||
|
||||
YSTR("states"); YMAP(
|
||||
YSTR("is_fixed"); YBOOL(c->isfixed);
|
||||
YSTR("is_floating"); YBOOL(c->isfloating);
|
||||
YSTR("is_urgent"); YBOOL(c->isurgent);
|
||||
YSTR("never_focus"); YBOOL(c->neverfocus);
|
||||
YSTR("old_state"); YBOOL(c->oldstate);
|
||||
YSTR("is_fullscreen"); YBOOL(c->isfullscreen);
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_monitor(yajl_gen gen, Monitor *mon, int is_selected)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("master_factor"); YDOUBLE(mon->mfact);
|
||||
YSTR("num_master"); YINT(mon->nmaster);
|
||||
YSTR("num"); YINT(mon->num);
|
||||
YSTR("is_selected"); YBOOL(is_selected);
|
||||
|
||||
YSTR("monitor_geometry"); YMAP(
|
||||
YSTR("x"); YINT(mon->mx);
|
||||
YSTR("y"); YINT(mon->my);
|
||||
YSTR("width"); YINT(mon->mw);
|
||||
YSTR("height"); YINT(mon->mh);
|
||||
)
|
||||
|
||||
YSTR("window_geometry"); YMAP(
|
||||
YSTR("x"); YINT(mon->wx);
|
||||
YSTR("y"); YINT(mon->wy);
|
||||
YSTR("width"); YINT(mon->ww);
|
||||
YSTR("height"); YINT(mon->wh);
|
||||
)
|
||||
|
||||
YSTR("tagset"); YMAP(
|
||||
YSTR("current"); YINT(mon->tagset[mon->seltags]);
|
||||
YSTR("old"); YINT(mon->tagset[mon->seltags ^ 1]);
|
||||
)
|
||||
|
||||
YSTR("tag_state"); dump_tag_state(gen, mon->tagstate);
|
||||
|
||||
YSTR("clients"); YMAP(
|
||||
YSTR("selected"); YINT(mon->sel ? mon->sel->win : 0);
|
||||
YSTR("stack"); YARR(
|
||||
for (Client* c = mon->stack; c; c = c->snext)
|
||||
YINT(c->win);
|
||||
)
|
||||
YSTR("all"); YARR(
|
||||
for (Client* c = mon->clients; c; c = c->next)
|
||||
YINT(c->win);
|
||||
)
|
||||
)
|
||||
|
||||
YSTR("layout"); YMAP(
|
||||
YSTR("symbol"); YMAP(
|
||||
YSTR("current"); YSTR(mon->ltsymbol);
|
||||
YSTR("old"); YSTR(mon->lastltsymbol);
|
||||
)
|
||||
YSTR("address"); YMAP(
|
||||
YSTR("current"); YINT((uintptr_t)mon->lt[mon->sellt]);
|
||||
YSTR("old"); YINT((uintptr_t)mon->lt[mon->sellt ^ 1]);
|
||||
)
|
||||
)
|
||||
|
||||
YSTR("bar"); YMAP(
|
||||
YSTR("y"); YINT(mon->by);
|
||||
YSTR("is_shown"); YBOOL(mon->showbar);
|
||||
YSTR("is_top"); YBOOL(mon->topbar);
|
||||
YSTR("window_id"); YINT(mon->barwin);
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_monitors(yajl_gen gen, Monitor *mons, Monitor *selmon)
|
||||
{
|
||||
// clang-format off
|
||||
YARR(
|
||||
for (Monitor *mon = mons; mon; mon = mon->next) {
|
||||
if (mon == selmon)
|
||||
dump_monitor(gen, mon, 1);
|
||||
else
|
||||
dump_monitor(gen, mon, 0);
|
||||
}
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_layouts(yajl_gen gen, const Layout layouts[], const int layouts_len)
|
||||
{
|
||||
// clang-format off
|
||||
YARR(
|
||||
for (int i = 0; i < layouts_len; i++) {
|
||||
YMAP(
|
||||
// Check for a NULL pointer. The cycle layouts patch adds an entry at
|
||||
// the end of the layouts array with a NULL pointer for the symbol
|
||||
YSTR("symbol"); YSTR((layouts[i].symbol ? layouts[i].symbol : ""));
|
||||
YSTR("address"); YINT((uintptr_t)(layouts + i));
|
||||
)
|
||||
}
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_tag_state(yajl_gen gen, TagState state)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("selected"); YINT(state.selected);
|
||||
YSTR("occupied"); YINT(state.occupied);
|
||||
YSTR("urgent"); YINT(state.urgent);
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_tag_event(yajl_gen gen, int mon_num, TagState old_state,
|
||||
TagState new_state)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("tag_change_event"); YMAP(
|
||||
YSTR("monitor_number"); YINT(mon_num);
|
||||
YSTR("old_state"); dump_tag_state(gen, old_state);
|
||||
YSTR("new_state"); dump_tag_state(gen, new_state);
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_client_focus_change_event(yajl_gen gen, Client *old_client,
|
||||
Client *new_client, int mon_num)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("client_focus_change_event"); YMAP(
|
||||
YSTR("monitor_number"); YINT(mon_num);
|
||||
YSTR("old_win_id"); old_client == NULL ? YNULL() : YINT(old_client->win);
|
||||
YSTR("new_win_id"); new_client == NULL ? YNULL() : YINT(new_client->win);
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_layout_change_event(yajl_gen gen, const int mon_num,
|
||||
const char *old_symbol, const Layout *old_layout,
|
||||
const char *new_symbol, const Layout *new_layout)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("layout_change_event"); YMAP(
|
||||
YSTR("monitor_number"); YINT(mon_num);
|
||||
YSTR("old_symbol"); YSTR(old_symbol);
|
||||
YSTR("old_address"); YINT((uintptr_t)old_layout);
|
||||
YSTR("new_symbol"); YSTR(new_symbol);
|
||||
YSTR("new_address"); YINT((uintptr_t)new_layout);
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_monitor_focus_change_event(yajl_gen gen, const int last_mon_num,
|
||||
const int new_mon_num)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("monitor_focus_change_event"); YMAP(
|
||||
YSTR("old_monitor_number"); YINT(last_mon_num);
|
||||
YSTR("new_monitor_number"); YINT(new_mon_num);
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_focused_title_change_event(yajl_gen gen, const int mon_num,
|
||||
const Window client_id, const char *old_name,
|
||||
const char *new_name)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("focused_title_change_event"); YMAP(
|
||||
YSTR("monitor_number"); YINT(mon_num);
|
||||
YSTR("client_window_id"); YINT(client_id);
|
||||
YSTR("old_name"); YSTR(old_name);
|
||||
YSTR("new_name"); YSTR(new_name);
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_client_state(yajl_gen gen, const ClientState *state)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("old_state"); YBOOL(state->oldstate);
|
||||
YSTR("is_fixed"); YBOOL(state->isfixed);
|
||||
YSTR("is_floating"); YBOOL(state->isfloating);
|
||||
YSTR("is_fullscreen"); YBOOL(state->isfullscreen);
|
||||
YSTR("is_urgent"); YBOOL(state->isurgent);
|
||||
YSTR("never_focus"); YBOOL(state->neverfocus);
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_focused_state_change_event(yajl_gen gen, const int mon_num,
|
||||
const Window client_id,
|
||||
const ClientState *old_state,
|
||||
const ClientState *new_state)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("focused_state_change_event"); YMAP(
|
||||
YSTR("monitor_number"); YINT(mon_num);
|
||||
YSTR("client_window_id"); YINT(client_id);
|
||||
YSTR("old_state"); dump_client_state(gen, old_state);
|
||||
YSTR("new_state"); dump_client_state(gen, new_state);
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_error_message(yajl_gen gen, const char *reason)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("result"); YSTR("error");
|
||||
YSTR("reason"); YSTR(reason);
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
65
yajl_dumps.h
Normal file
65
yajl_dumps.h
Normal file
@ -0,0 +1,65 @@
|
||||
#ifndef YAJL_DUMPS_H_
|
||||
#define YAJL_DUMPS_H_
|
||||
|
||||
#include <string.h>
|
||||
#include <yajl/yajl_gen.h>
|
||||
|
||||
#define YSTR(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str))
|
||||
#define YINT(num) yajl_gen_integer(gen, num)
|
||||
#define YDOUBLE(num) yajl_gen_double(gen, num)
|
||||
#define YBOOL(v) yajl_gen_bool(gen, v)
|
||||
#define YNULL() yajl_gen_null(gen)
|
||||
#define YARR(body) \
|
||||
{ \
|
||||
yajl_gen_array_open(gen); \
|
||||
body; \
|
||||
yajl_gen_array_close(gen); \
|
||||
}
|
||||
#define YMAP(body) \
|
||||
{ \
|
||||
yajl_gen_map_open(gen); \
|
||||
body; \
|
||||
yajl_gen_map_close(gen); \
|
||||
}
|
||||
|
||||
int dump_tag(yajl_gen gen, const char *name, const int tag_mask);
|
||||
|
||||
int dump_tags(yajl_gen gen, const char *tags[], int tags_len);
|
||||
|
||||
int dump_client(yajl_gen gen, Client *c);
|
||||
|
||||
int dump_monitor(yajl_gen gen, Monitor *mon, int is_selected);
|
||||
|
||||
int dump_monitors(yajl_gen gen, Monitor *mons, Monitor *selmon);
|
||||
|
||||
int dump_layouts(yajl_gen gen, const Layout layouts[], const int layouts_len);
|
||||
|
||||
int dump_tag_state(yajl_gen gen, TagState state);
|
||||
|
||||
int dump_tag_event(yajl_gen gen, int mon_num, TagState old_state,
|
||||
TagState new_state);
|
||||
|
||||
int dump_client_focus_change_event(yajl_gen gen, Client *old_client,
|
||||
Client *new_client, int mon_num);
|
||||
|
||||
int dump_layout_change_event(yajl_gen gen, const int mon_num,
|
||||
const char *old_symbol, const Layout *old_layout,
|
||||
const char *new_symbol, const Layout *new_layout);
|
||||
|
||||
int dump_monitor_focus_change_event(yajl_gen gen, const int last_mon_num,
|
||||
const int new_mon_num);
|
||||
|
||||
int dump_focused_title_change_event(yajl_gen gen, const int mon_num,
|
||||
const Window client_id,
|
||||
const char *old_name, const char *new_name);
|
||||
|
||||
int dump_client_state(yajl_gen gen, const ClientState *state);
|
||||
|
||||
int dump_focused_state_change_event(yajl_gen gen, const int mon_num,
|
||||
const Window client_id,
|
||||
const ClientState *old_state,
|
||||
const ClientState *new_state);
|
||||
|
||||
int dump_error_message(yajl_gen gen, const char *reason);
|
||||
|
||||
#endif // YAJL_DUMPS_H_
|
Loading…
x
Reference in New Issue
Block a user