first commit
This commit is contained in:
commit
84c06e3578
LICENSEMakefileREADMEconfig.def.hconfig.hconfig.h.tmpconfig.mkdrw.cdrw.hdrw.odwmdwm.1dwm.cdwm.odwm.png
patch
autostart.cautostart.hbar_alpha.cbar_alpha.hbar_dwmblocks.cbar_dwmblocks.hbar_ewmhtags.cbar_ewmhtags.hbar_indicators.cbar_indicators.hbar_ltsymbol.cbar_ltsymbol.hbar_powerline_tags.cbar_powerline_tags.hbar_status.cbar_status.hbar_statuscmd.cbar_statuscmd.hbar_systray.cbar_systray.hbar_tabgroups.cbar_tabgroups.hbar_tagicons.cbar_tagicons.hbar_tags.cbar_tags.hbar_wintitle.cbar_wintitle.hbar_wintitleactions.cbar_wintitleactions.hdecorationhints.cdecorationhints.hfakefullscreenclient.cfakefullscreenclient.hfocusadjacenttag.cfocusadjacenttag.hinclude.cinclude.hinplacerotate.cinplacerotate.h
transient.cutil.cutil.hutil.oipc
layout_centeredfloatingmaster.clayout_centeredfloatingmaster.hlayout_centeredmaster.clayout_centeredmaster.hlayout_facts.clayout_fibonacci.clayout_fibonacci.hlayout_monocle.clayout_monocle.hlayout_nrowgrid.clayout_nrowgrid.hlayout_tile.clayout_tile.hpertag.cpertag.hscratchpad_alt_1.cscratchpad_alt_1.hsticky.csticky.hswallow.cswallow.htagallmon.ctagallmon.htagswapmon.ctagswapmon.htransfer.ctransfer.hvanitygaps.cvanitygaps.h
37
LICENSE
Normal file
37
LICENSE
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
MIT/X Consortium License
|
||||||
|
|
||||||
|
© 2006-2019 Anselm R Garbe <anselm@garbe.ca>
|
||||||
|
© 2006-2009 Jukka Salmi <jukka at salmi dot ch>
|
||||||
|
© 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
|
||||||
|
© 2007-2011 Peter Hartlich <sgkkr at hartlich dot com>
|
||||||
|
© 2007-2009 Szabolcs Nagy <nszabolcs at gmail dot com>
|
||||||
|
© 2007-2009 Christof Musik <christof at sendfax dot de>
|
||||||
|
© 2007-2009 Premysl Hruby <dfenze at gmail dot com>
|
||||||
|
© 2007-2008 Enno Gottox Boland <gottox at s01 dot de>
|
||||||
|
© 2008 Martin Hurton <martin dot hurton at gmail dot com>
|
||||||
|
© 2008 Neale Pickett <neale dot woozle dot org>
|
||||||
|
© 2009 Mate Nagy <mnagy at port70 dot net>
|
||||||
|
© 2010-2016 Hiltjo Posthuma <hiltjo@codemadness.org>
|
||||||
|
© 2010-2012 Connor Lane Smith <cls@lubutu.com>
|
||||||
|
© 2011 Christoph Lohmann <20h@r-36.net>
|
||||||
|
© 2015-2016 Quentin Rameau <quinq@fifth.space>
|
||||||
|
© 2015-2016 Eric Pruitt <eric.pruitt@gmail.com>
|
||||||
|
© 2016-2017 Markus Teich <markus.teich@stusta.mhn.de>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
69
Makefile
Normal file
69
Makefile
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# dwm - dynamic window manager
|
||||||
|
# See LICENSE file for copyright and license details.
|
||||||
|
|
||||||
|
include config.mk
|
||||||
|
|
||||||
|
SRC = drw.c dwm.c util.c
|
||||||
|
OBJ = ${SRC:.c=.o}
|
||||||
|
|
||||||
|
# FreeBSD users, prefix all ifdef, else and endif statements with a . for this to work (e.g. .ifdef)
|
||||||
|
|
||||||
|
ifdef YAJLLIBS
|
||||||
|
all: options dwm dwm-msg
|
||||||
|
else
|
||||||
|
all: options dwm
|
||||||
|
endif
|
||||||
|
|
||||||
|
options:
|
||||||
|
@echo dwm build options:
|
||||||
|
@echo "CFLAGS = ${CFLAGS}"
|
||||||
|
@echo "LDFLAGS = ${LDFLAGS}"
|
||||||
|
@echo "CC = ${CC}"
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
${CC} -c ${CFLAGS} $<
|
||||||
|
|
||||||
|
${OBJ}: config.h config.mk
|
||||||
|
|
||||||
|
config.h:
|
||||||
|
cp config.def.h $@
|
||||||
|
|
||||||
|
dwm: ${OBJ}
|
||||||
|
${CC} -o $@ ${OBJ} ${LDFLAGS}
|
||||||
|
|
||||||
|
ifdef YAJLLIBS
|
||||||
|
dwm-msg:
|
||||||
|
${CC} -o $@ patch/ipc/dwm-msg.c ${LDFLAGS}
|
||||||
|
endif
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz
|
||||||
|
rm -f dwm-msg
|
||||||
|
|
||||||
|
dist: clean
|
||||||
|
mkdir -p dwm-${VERSION}
|
||||||
|
cp -R LICENSE Makefile README config.def.h config.mk\
|
||||||
|
dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION}
|
||||||
|
tar -cf dwm-${VERSION}.tar dwm-${VERSION}
|
||||||
|
gzip dwm-${VERSION}.tar
|
||||||
|
rm -rf dwm-${VERSION}
|
||||||
|
|
||||||
|
install: all
|
||||||
|
mkdir -p ${DESTDIR}${PREFIX}/bin
|
||||||
|
cp -f dwm ${DESTDIR}${PREFIX}/bin
|
||||||
|
ifdef YAJLLIBS
|
||||||
|
cp -f dwm-msg ${DESTDIR}${PREFIX}/bin
|
||||||
|
endif
|
||||||
|
chmod 755 ${DESTDIR}${PREFIX}/bin/dwm
|
||||||
|
ifdef YAJLLIBS
|
||||||
|
chmod 755 ${DESTDIR}${PREFIX}/bin/dwm-msg
|
||||||
|
endif
|
||||||
|
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\
|
||||||
|
${DESTDIR}${MANPREFIX}/man1/dwm.1
|
||||||
|
|
||||||
|
.PHONY: all options clean dist install uninstall
|
48
README
Normal file
48
README
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
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.
|
345
config.def.h
Normal file
345
config.def.h
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
/* 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 swallowfloating = 0; /* 1 means swallow floating windows by default */
|
||||||
|
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 const int smartgaps_fact = 1; /* gap factor when there is only one client; 0 = no gaps, 3 = 3x outer gaps */
|
||||||
|
static const char autostartblocksh[] = "autostart_blocking.sh";
|
||||||
|
static const char autostartsh[] = "autostart.sh";
|
||||||
|
static const char dwmdir[] = "dwm";
|
||||||
|
static const char localshare[] = ".local/share";
|
||||||
|
static const int showbar = 1; /* 0 means no bar */
|
||||||
|
static const int topbar = 1; /* 0 means bottom bar */
|
||||||
|
/* Status is to be shown on: -1 (all monitors), 0 (a specific monitor by index), 'A' (active monitor) */
|
||||||
|
static const int statusmon = 'A';
|
||||||
|
static const unsigned int systrayspacing = 2; /* systray spacing */
|
||||||
|
static const int showsystray = 1; /* 0 means no systray */
|
||||||
|
/* Indicators: see patch/bar_indicators.h for options */
|
||||||
|
static int tagindicatortype = INDICATOR_TOP_LEFT_SQUARE;
|
||||||
|
static int tiledindicatortype = INDICATOR_NONE;
|
||||||
|
static int floatindicatortype = INDICATOR_TOP_LEFT_SQUARE;
|
||||||
|
static int fakefsindicatortype = INDICATOR_PLUS;
|
||||||
|
static int floatfakefsindicatortype = INDICATOR_PLUS_AND_LARGER_SQUARE;
|
||||||
|
static void (*bartabmonfns[])(Monitor *) = { monocle /* , customlayoutfn */ };
|
||||||
|
static const char *fonts[] = { "monospace:size=10" };
|
||||||
|
static const char dmenufont[] = "monospace:size=10";
|
||||||
|
|
||||||
|
static char c000000[] = "#000000"; // placeholder value
|
||||||
|
|
||||||
|
static char normfgcolor[] = "#bbbbbb";
|
||||||
|
static char normbgcolor[] = "#222222";
|
||||||
|
static char normbordercolor[] = "#444444";
|
||||||
|
static char normfloatcolor[] = "#db8fd9";
|
||||||
|
|
||||||
|
static char selfgcolor[] = "#eeeeee";
|
||||||
|
static char selbgcolor[] = "#005577";
|
||||||
|
static char selbordercolor[] = "#005577";
|
||||||
|
static char selfloatcolor[] = "#005577";
|
||||||
|
|
||||||
|
static char titlenormfgcolor[] = "#bbbbbb";
|
||||||
|
static char titlenormbgcolor[] = "#222222";
|
||||||
|
static char titlenormbordercolor[] = "#444444";
|
||||||
|
static char titlenormfloatcolor[] = "#db8fd9";
|
||||||
|
|
||||||
|
static char titleselfgcolor[] = "#eeeeee";
|
||||||
|
static char titleselbgcolor[] = "#005577";
|
||||||
|
static char titleselbordercolor[] = "#005577";
|
||||||
|
static char titleselfloatcolor[] = "#005577";
|
||||||
|
|
||||||
|
static char tagsnormfgcolor[] = "#bbbbbb";
|
||||||
|
static char tagsnormbgcolor[] = "#222222";
|
||||||
|
static char tagsnormbordercolor[] = "#444444";
|
||||||
|
static char tagsnormfloatcolor[] = "#db8fd9";
|
||||||
|
|
||||||
|
static char tagsselfgcolor[] = "#eeeeee";
|
||||||
|
static char tagsselbgcolor[] = "#005577";
|
||||||
|
static char tagsselbordercolor[] = "#005577";
|
||||||
|
static char tagsselfloatcolor[] = "#005577";
|
||||||
|
|
||||||
|
static char hidnormfgcolor[] = "#005577";
|
||||||
|
static char hidselfgcolor[] = "#227799";
|
||||||
|
static char hidnormbgcolor[] = "#222222";
|
||||||
|
static char hidselbgcolor[] = "#222222";
|
||||||
|
|
||||||
|
static char urgfgcolor[] = "#bbbbbb";
|
||||||
|
static char urgbgcolor[] = "#222222";
|
||||||
|
static char urgbordercolor[] = "#ff0000";
|
||||||
|
static char urgfloatcolor[] = "#db8fd9";
|
||||||
|
|
||||||
|
|
||||||
|
static const unsigned int baralpha = 0xd0;
|
||||||
|
static const unsigned int borderalpha = OPAQUE;
|
||||||
|
static const unsigned int alphas[][3] = {
|
||||||
|
/* fg bg border */
|
||||||
|
[SchemeNorm] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeSel] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeTitleNorm] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeTitleSel] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeTagsNorm] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeTagsSel] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeHidNorm] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeHidSel] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeUrg] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *colors[][ColCount] = {
|
||||||
|
/* fg bg border float */
|
||||||
|
[SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor, normfloatcolor },
|
||||||
|
[SchemeSel] = { selfgcolor, selbgcolor, selbordercolor, selfloatcolor },
|
||||||
|
[SchemeTitleNorm] = { titlenormfgcolor, titlenormbgcolor, titlenormbordercolor, titlenormfloatcolor },
|
||||||
|
[SchemeTitleSel] = { titleselfgcolor, titleselbgcolor, titleselbordercolor, titleselfloatcolor },
|
||||||
|
[SchemeTagsNorm] = { tagsnormfgcolor, tagsnormbgcolor, tagsnormbordercolor, tagsnormfloatcolor },
|
||||||
|
[SchemeTagsSel] = { tagsselfgcolor, tagsselbgcolor, tagsselbordercolor, tagsselfloatcolor },
|
||||||
|
[SchemeHidNorm] = { hidnormfgcolor, hidnormbgcolor, c000000, c000000 },
|
||||||
|
[SchemeHidSel] = { hidselfgcolor, hidselbgcolor, c000000, c000000 },
|
||||||
|
[SchemeUrg] = { urgfgcolor, urgbgcolor, urgbordercolor, urgfloatcolor },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Tags
|
||||||
|
* In a traditional dwm the number of tags in use can be changed simply by changing the number
|
||||||
|
* of strings in the tags array. This build does things a bit different which has some added
|
||||||
|
* benefits. If you need to change the number of tags here then change the NUMTAGS macro in dwm.c.
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
*
|
||||||
|
* 1) static char *tagicons[][NUMTAGS*2] = {
|
||||||
|
* [DEFAULT_TAGS] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I" },
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* 2) static char *tagicons[][1] = {
|
||||||
|
* [DEFAULT_TAGS] = { "•" },
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* The first example would result in the tags on the first monitor to be 1 through 9, while the
|
||||||
|
* tags for the second monitor would be named A through I. A third monitor would start again at
|
||||||
|
* 1 through 9 while the tags on a fourth monitor would also be named A through I. Note the tags
|
||||||
|
* count of NUMTAGS*2 in the array initialiser which defines how many tag text / icon exists in
|
||||||
|
* the array. This can be changed to *3 to add separate icons for a third monitor.
|
||||||
|
*
|
||||||
|
* For the second example each tag would be represented as a bullet point. Both cases work the
|
||||||
|
* same from a technical standpoint - the icon index is derived from the tag index and the monitor
|
||||||
|
* index. If the icon index is is greater than the number of tag icons then it will wrap around
|
||||||
|
* until it an icon matches. Similarly if there are two tag icons then it would alternate between
|
||||||
|
* them. This works seamlessly with alternative tags and alttagsdecoration patches.
|
||||||
|
*/
|
||||||
|
static char *tagicons[][NUMTAGS] = {
|
||||||
|
[DEFAULT_TAGS] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" },
|
||||||
|
[ALTERNATIVE_TAGS] = { "A", "B", "C", "D", "E", "F", "G", "H", "I" },
|
||||||
|
[ALT_TAGS_DECORATION] = { "<1>", "<2>", "<3>", "<4>", "<5>", "<6>", "<7>", "<8>", "<9>" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* There are two options when it comes to per-client rules:
|
||||||
|
* - a typical struct table or
|
||||||
|
* - using the RULE macro
|
||||||
|
*
|
||||||
|
* A traditional struct table looks like this:
|
||||||
|
* // class instance title wintype tags mask isfloating monitor
|
||||||
|
* { "Gimp", NULL, NULL, NULL, 1 << 4, 0, -1 },
|
||||||
|
* { "Firefox", NULL, NULL, NULL, 1 << 7, 0, -1 },
|
||||||
|
*
|
||||||
|
* The RULE macro has the default values set for each field allowing you to only
|
||||||
|
* specify the values that are relevant for your rule, e.g.
|
||||||
|
*
|
||||||
|
* RULE(.class = "Gimp", .tags = 1 << 4)
|
||||||
|
* RULE(.class = "Firefox", .tags = 1 << 7)
|
||||||
|
*
|
||||||
|
* Refer to the Rule struct definition for the list of available fields depending on
|
||||||
|
* the patches you enable.
|
||||||
|
*/
|
||||||
|
static const Rule rules[] = {
|
||||||
|
/* xprop(1):
|
||||||
|
* WM_CLASS(STRING) = instance, class
|
||||||
|
* WM_NAME(STRING) = title
|
||||||
|
* WM_WINDOW_ROLE(STRING) = role
|
||||||
|
* _NET_WM_WINDOW_TYPE(ATOM) = wintype
|
||||||
|
*/
|
||||||
|
RULE(.wintype = WTYPE "DIALOG", .isfloating = 1)
|
||||||
|
RULE(.wintype = WTYPE "UTILITY", .isfloating = 1)
|
||||||
|
RULE(.wintype = WTYPE "TOOLBAR", .isfloating = 1)
|
||||||
|
RULE(.wintype = WTYPE "SPLASH", .isfloating = 1)
|
||||||
|
RULE(.class = "Gimp", .tags = 1 << 4)
|
||||||
|
RULE(.class = "Firefox", .tags = 1 << 7)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Bar rules allow you to configure what is shown where on the bar, as well as
|
||||||
|
* introducing your own bar modules.
|
||||||
|
*
|
||||||
|
* monitor:
|
||||||
|
* -1 show on all monitors
|
||||||
|
* 0 show on monitor 0
|
||||||
|
* 'A' show on active monitor (i.e. focused / selected) (or just -1 for active?)
|
||||||
|
* bar - bar index, 0 is default, 1 is extrabar
|
||||||
|
* alignment - how the module is aligned compared to other modules
|
||||||
|
* widthfunc, drawfunc, clickfunc - providing bar module width, draw and click functions
|
||||||
|
* name - does nothing, intended for visual clue and for logging / debugging
|
||||||
|
*/
|
||||||
|
static const BarRule barrules[] = {
|
||||||
|
/* monitor bar alignment widthfunc drawfunc clickfunc name */
|
||||||
|
{ 0, 0, BAR_ALIGN_LEFT, width_pwrl_tags, draw_pwrl_tags, click_pwrl_tags, "powerline_tags" },
|
||||||
|
{ -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, "tags" },
|
||||||
|
{ 0, 0, BAR_ALIGN_RIGHT, width_systray, draw_systray, click_systray, "systray" },
|
||||||
|
{ -1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, "layout" },
|
||||||
|
{ statusmon, 0, BAR_ALIGN_RIGHT, width_status, draw_status, click_statuscmd, "status" },
|
||||||
|
{ -1, 0, BAR_ALIGN_NONE, width_bartabgroups, draw_bartabgroups, click_bartabgroups, "bartabgroups" },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 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 = 0; /* 1 means respect size hints in tiled resizals */
|
||||||
|
static const int decorhints = 1; /* 1 means respect decoration hints */
|
||||||
|
|
||||||
|
#define FORCE_VSPLIT 1
|
||||||
|
|
||||||
|
|
||||||
|
static const Layout layouts[] = {
|
||||||
|
/* symbol arrange function */
|
||||||
|
{ "[]=", tile }, /* first entry is default */
|
||||||
|
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||||
|
{ "[M]", monocle },
|
||||||
|
{ "|M|", centeredmaster },
|
||||||
|
{ ">M>", centeredfloatingmaster },
|
||||||
|
{ "[\\]", dwindle },
|
||||||
|
{ "###", nrowgrid },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* key definitions */
|
||||||
|
#define MODKEY Mod1Mask
|
||||||
|
#define TAGKEYS(KEY,TAG) \
|
||||||
|
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
||||||
|
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
|
||||||
|
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
|
||||||
|
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
||||||
|
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
||||||
|
|
||||||
|
/* commands */
|
||||||
|
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
|
||||||
|
static const char *dmenucmd[] = {
|
||||||
|
"dmenu_run",
|
||||||
|
"-m", dmenumon,
|
||||||
|
"-fn", dmenufont,
|
||||||
|
"-nb", normbgcolor,
|
||||||
|
"-nf", normfgcolor,
|
||||||
|
"-sb", selbgcolor,
|
||||||
|
"-sf", selfgcolor,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
static const char *termcmd[] = { "st", NULL };
|
||||||
|
|
||||||
|
/* This defines the name of the executable that handles the bar (used for signalling purposes) */
|
||||||
|
#define STATUSBAR "dwmblocks"
|
||||||
|
|
||||||
|
|
||||||
|
static Key keys[] = {
|
||||||
|
/* modifier key function argument */
|
||||||
|
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
||||||
|
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
|
||||||
|
{ MODKEY, XK_b, togglebar, {0} },
|
||||||
|
{ MODKEY, XK_j, focusstack, {.i = +1 } },
|
||||||
|
{ MODKEY, XK_k, focusstack, {.i = -1 } },
|
||||||
|
{ MODKEY|Mod4Mask, XK_j, inplacerotate, {.i = +2 } }, // same as rotatestack
|
||||||
|
{ MODKEY|Mod4Mask, XK_k, inplacerotate, {.i = -2 } }, // same as reotatestack
|
||||||
|
{ MODKEY|Mod4Mask|ShiftMask, XK_j, inplacerotate, {.i = +1} },
|
||||||
|
{ MODKEY|Mod4Mask|ShiftMask, XK_k, inplacerotate, {.i = -1} },
|
||||||
|
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
|
||||||
|
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
||||||
|
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
||||||
|
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
||||||
|
{ MODKEY, XK_x, transfer, {0} },
|
||||||
|
{ 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|ControlMask, XK_z, showhideclient, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_q, quit, {0} },
|
||||||
|
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
||||||
|
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
|
||||||
|
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
||||||
|
{ MODKEY, XK_space, setlayout, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_y, togglefakefullscreen, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_s, togglesticky, {0} },
|
||||||
|
{ MODKEY, XK_minus, scratchpad_show, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_minus, scratchpad_hide, {0} },
|
||||||
|
{ MODKEY, XK_equal, scratchpad_remove, {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, XK_Left, viewtoleft, {0} }, // note keybinding conflict with focusdir
|
||||||
|
{ MODKEY, XK_Right, viewtoright, {0} }, // note keybinding conflict with focusdir
|
||||||
|
{ MODKEY|ShiftMask, XK_Left, tagtoleft, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_Right, tagtoright, {0} },
|
||||||
|
{ MODKEY|ControlMask, XK_Left, tagandviewtoleft, {0} },
|
||||||
|
{ MODKEY|ControlMask, XK_Right, tagandviewtoright, {0} },
|
||||||
|
{ MODKEY|Mod4Mask|ShiftMask, XK_comma, tagallmon, {.i = +1 } },
|
||||||
|
{ MODKEY|Mod4Mask|ShiftMask, XK_period, tagallmon, {.i = -1 } },
|
||||||
|
{ MODKEY|Mod4Mask|ControlMask, XK_comma, tagswapmon, {.i = +1 } },
|
||||||
|
{ MODKEY|Mod4Mask|ControlMask, XK_period, tagswapmon, {.i = -1 } },
|
||||||
|
TAGKEYS( XK_1, 0)
|
||||||
|
TAGKEYS( XK_2, 1)
|
||||||
|
TAGKEYS( XK_3, 2)
|
||||||
|
TAGKEYS( XK_4, 3)
|
||||||
|
TAGKEYS( XK_5, 4)
|
||||||
|
TAGKEYS( XK_6, 5)
|
||||||
|
TAGKEYS( XK_7, 6)
|
||||||
|
TAGKEYS( XK_8, 7)
|
||||||
|
TAGKEYS( XK_9, 8)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* button definitions */
|
||||||
|
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
|
||||||
|
static Button buttons[] = {
|
||||||
|
/* click event mask button function argument */
|
||||||
|
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
|
||||||
|
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
||||||
|
{ ClkWinTitle, 0, Button1, togglewin, {0} },
|
||||||
|
{ ClkWinTitle, 0, Button3, showhideclient, {0} },
|
||||||
|
{ ClkWinTitle, 0, Button2, zoom, {0} },
|
||||||
|
{ ClkStatusText, 0, Button1, sigstatusbar, {.i = 1 } },
|
||||||
|
{ ClkStatusText, 0, Button2, sigstatusbar, {.i = 2 } },
|
||||||
|
{ ClkStatusText, 0, Button3, sigstatusbar, {.i = 3 } },
|
||||||
|
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
||||||
|
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
|
||||||
|
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
|
||||||
|
{ ClkTagBar, 0, Button1, view, {0} },
|
||||||
|
{ ClkTagBar, 0, Button3, toggleview, {0} },
|
||||||
|
{ ClkTagBar, MODKEY, Button1, tag, {0} },
|
||||||
|
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
416
config.h
Normal file
416
config.h
Normal file
@ -0,0 +1,416 @@
|
|||||||
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
|
||||||
|
/* appearance */
|
||||||
|
static const unsigned int borderpx = 2; /* border pixel of windows */
|
||||||
|
static const unsigned int snap = 16; /* snap pixel */
|
||||||
|
static const int swallowfloating = 0; /* 1 means swallow floating windows by default */
|
||||||
|
static const unsigned int gappih = 10; /* 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 = 10; /* vert outer gap between windows and screen edge */
|
||||||
|
static const int smartgaps_fact = 0; /* 1 means no outer gap when there is only one window */
|
||||||
|
static const char autostartblocksh[] = "autostart_blocking.sh";
|
||||||
|
static const char autostartsh[] = "autostart.sh";
|
||||||
|
static const char dwmdir[] = "dwm";
|
||||||
|
static const char localshare[] = ".local/share";
|
||||||
|
static const int showbar = 1; /* 0 means no bar */
|
||||||
|
static const int topbar = 1; /* 0 means bottom bar */
|
||||||
|
/* Status is to be shown on: -1 (all monitors), 0 (a specific monitor by index), 'A' (active monitor) */
|
||||||
|
static const int statusmon = 'A';
|
||||||
|
static const unsigned int systrayspacing = 2; /* systray spacing */
|
||||||
|
static const int showsystray = 1; /* 0 means no systray */
|
||||||
|
/* Indicators: see patch/bar_indicators.h for options */
|
||||||
|
static int tagindicatortype = INDICATOR_TOP_LEFT_SQUARE;
|
||||||
|
static int tiledindicatortype = INDICATOR_NONE;
|
||||||
|
static int floatindicatortype = INDICATOR_TOP_LEFT_SQUARE;
|
||||||
|
static int fakefsindicatortype = INDICATOR_PLUS;
|
||||||
|
static int floatfakefsindicatortype = INDICATOR_PLUS_AND_LARGER_SQUARE;
|
||||||
|
static void (*bartabmonfns[])(Monitor *) = { monocle /* , customlayoutfn */ };
|
||||||
|
static const char *fonts[] = {
|
||||||
|
"FontAwesome:size=12",
|
||||||
|
"mononoki:size=12",
|
||||||
|
};
|
||||||
|
static const char dmenufont[] = "mononoki:size=12";
|
||||||
|
|
||||||
|
static char normfgcolor[] = "#bbbbbb";
|
||||||
|
static char normbgcolor[] = "#222222";
|
||||||
|
static char normbordercolor[] = "#444444";
|
||||||
|
static char normfloatcolor[] = "#db8fd9";
|
||||||
|
|
||||||
|
static char selfgcolor[] = "#111111";
|
||||||
|
static char selbgcolor[] = "#ffd700";
|
||||||
|
static char selbordercolor[] = "#ffd700";
|
||||||
|
static char selfloatcolor[] = "#ffd700";
|
||||||
|
|
||||||
|
static char titlenormfgcolor[] = "#bbbbbb";
|
||||||
|
static char titlenormbgcolor[] = "#222222";
|
||||||
|
static char titlenormbordercolor[] = "#444444";
|
||||||
|
static char titlenormfloatcolor[] = "#db8fd9";
|
||||||
|
|
||||||
|
static char titleselfgcolor[] = "#111111";
|
||||||
|
static char titleselbgcolor[] = "#ffd700";
|
||||||
|
static char titleselbordercolor[] = "#ffd700";
|
||||||
|
static char titleselfloatcolor[] = "#ffd700";
|
||||||
|
|
||||||
|
static char tagsnormfgcolor[] = "#bbbbbb";
|
||||||
|
static char tagsnormbgcolor[] = "#222222";
|
||||||
|
static char tagsnormbordercolor[] = "#444444";
|
||||||
|
static char tagsnormfloatcolor[] = "#db8fd9";
|
||||||
|
|
||||||
|
static char tagsselfgcolor[] = "#111111";
|
||||||
|
static char tagsselbgcolor[] = "#ffd700";
|
||||||
|
static char tagsselbordercolor[] = "#ffd700";
|
||||||
|
static char tagsselfloatcolor[] = "#ffd700";
|
||||||
|
|
||||||
|
static char hidnormfgcolor[] = "#ffd700";
|
||||||
|
static char hidnormbgcolor[] = "#222222";
|
||||||
|
static char hidselfgcolor[] = "#ffd700";
|
||||||
|
static char hidselbgcolor[] = "#ffd700";
|
||||||
|
static char hidbordercolor[] = "#ffd700";
|
||||||
|
static char hidfloatcolor[] = "#f76e0c";
|
||||||
|
|
||||||
|
static char urgfgcolor[] = "#bbbbbb";
|
||||||
|
static char urgbgcolor[] = "#222222";
|
||||||
|
static char urgbordercolor[] = "#ff0000";
|
||||||
|
static char urgfloatcolor[] = "#db8fd9";
|
||||||
|
|
||||||
|
|
||||||
|
static const unsigned int baralpha = 0xd0;
|
||||||
|
static const unsigned int borderalpha = OPAQUE;
|
||||||
|
static const unsigned int alphas[][3] = {
|
||||||
|
/* fg bg border */
|
||||||
|
[SchemeNorm] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeSel] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeTitleNorm] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeTitleSel] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeTagsNorm] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeTagsSel] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeHidNorm] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeHidSel] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeUrg] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *colors[][ColCount] = {
|
||||||
|
/* fg bg border float */
|
||||||
|
[SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor, normfloatcolor },
|
||||||
|
[SchemeSel] = { selfgcolor, selbgcolor, selbordercolor, selfloatcolor },
|
||||||
|
[SchemeTitleNorm] = { titlenormfgcolor, titlenormbgcolor, titlenormbordercolor, titlenormfloatcolor },
|
||||||
|
[SchemeTitleSel] = { titleselfgcolor, titleselbgcolor, titleselbordercolor, titleselfloatcolor },
|
||||||
|
[SchemeTagsNorm] = { tagsnormfgcolor, tagsnormbgcolor, tagsnormbordercolor, tagsnormfloatcolor },
|
||||||
|
[SchemeTagsSel] = { tagsselfgcolor, tagsselbgcolor, tagsselbordercolor, tagsselfloatcolor },
|
||||||
|
[SchemeHidNorm] = { hidnormfgcolor, hidnormbgcolor, hidbordercolor, hidfloatcolor },
|
||||||
|
[SchemeHidSel] = { hidselfgcolor, hidselbgcolor, hidbordercolor, hidfloatcolor },
|
||||||
|
[SchemeUrg] = { urgfgcolor, urgbgcolor, urgbordercolor, urgfloatcolor },
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
static char *statuscolors[][ColCount] = {
|
||||||
|
// fg bg border float
|
||||||
|
[SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor, normfloatcolor },
|
||||||
|
[SchemeSel] = { selfgcolor, selbgcolor, selbordercolor, selfloatcolor },
|
||||||
|
[SchemeTitleNorm] = { titlenormfgcolor, titlenormbgcolor, titlenormbordercolor, titlenormfloatcolor },
|
||||||
|
[SchemeTitleSel] = { titleselfgcolor, titleselbgcolor, titleselbordercolor, titleselfloatcolor },
|
||||||
|
[SchemeTagsNorm] = { tagsnormfgcolor, tagsnormbgcolor, tagsnormbordercolor, tagsnormfloatcolor },
|
||||||
|
[SchemeTagsSel] = { tagsselfgcolor, tagsselbgcolor, tagsselbordercolor, tagsselfloatcolor },
|
||||||
|
[SchemeHidNorm] = { hidnormfgcolor, hidnormbgcolor, hidbordercolor, hidfloatcolor },
|
||||||
|
[SchemeHidSel] = { hidselfgcolor, hidselbgcolor, hidbordercolor, hidfloatcolor },
|
||||||
|
[SchemeUrg] = { urgfgcolor, urgbgcolor, urgbordercolor, urgfloatcolor },
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Tags
|
||||||
|
* In a traditional dwm the number of tags in use can be changed simply by changing the number
|
||||||
|
* of strings in the tags array. This build does things a bit different which has some added
|
||||||
|
* benefits. If you need to change the number of tags here then change the NUMTAGS macro in dwm.c.
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
*
|
||||||
|
* 1) static char *tagicons[][NUMTAGS*2] = {
|
||||||
|
* [DEFAULT_TAGS] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I" },
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* 2) static char *tagicons[][1] = {
|
||||||
|
* [DEFAULT_TAGS] = { "•" },
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* The first example would result in the tags on the first monitor to be 1 through 9, while the
|
||||||
|
* tags for the second monitor would be named A through I. A third monitor would start again at
|
||||||
|
* 1 through 9 while the tags on a fourth monitor would also be named A through I. Note the tags
|
||||||
|
* count of NUMTAGS*2 in the array initialiser which defines how many tag text / icon exists in
|
||||||
|
* the array. This can be changed to *3 to add separate icons for a third monitor.
|
||||||
|
*
|
||||||
|
* For the second example each tag would be represented as a bullet point. Both cases work the
|
||||||
|
* same from a technical standpoint - the icon index is derived from the tag index and the monitor
|
||||||
|
* index. If the icon index is is greater than the number of tag icons then it will wrap around
|
||||||
|
* until it an icon matches. Similarly if there are two tag icons then it would alternate between
|
||||||
|
* them. This works seamlessly with alternative tags and alttagsdecoration patches.
|
||||||
|
*/
|
||||||
|
static char *tagicons[][NUMTAGS] = {
|
||||||
|
// [DEFAULT_TAGS] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" },
|
||||||
|
[DEFAULT_TAGS] = { "₁", "₂", "₃", "₄", "₅", "₆", "₇", "₈", "₉" },
|
||||||
|
[ALTERNATIVE_TAGS] = { "A", "B", "C", "D", "E", "F", "G", "H", "I" },
|
||||||
|
[ALT_TAGS_DECORATION] = { "<1>", "<2>", "<3>", "<4>", "<5>", "<6>", "<7>", "<8>", "<9>" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* There are two options when it comes to per-client rules:
|
||||||
|
* - a typical struct table or
|
||||||
|
* - using the RULE macro
|
||||||
|
*
|
||||||
|
* A traditional struct table looks like this:
|
||||||
|
* // class instance title wintype tags mask isfloating monitor
|
||||||
|
* { "Gimp", NULL, NULL, NULL, 1 << 4, 0, -1 },
|
||||||
|
* { "Firefox", NULL, NULL, NULL, 1 << 7, 0, -1 },
|
||||||
|
*
|
||||||
|
* The RULE macro has the default values set for each field allowing you to only
|
||||||
|
* specify the values that are relevant for your rule, e.g.
|
||||||
|
*
|
||||||
|
* RULE(.class = "Gimp", .tags = 1 << 4)
|
||||||
|
* RULE(.class = "Firefox", .tags = 1 << 7)
|
||||||
|
*
|
||||||
|
* Refer to the Rule struct definition for the list of available fields depending on
|
||||||
|
* the patches you enable.
|
||||||
|
*/
|
||||||
|
static const Rule rules[] = {
|
||||||
|
/* xprop(1):
|
||||||
|
* WM_CLASS(STRING) = instance, class
|
||||||
|
* WM_NAME(STRING) = title
|
||||||
|
* WM_WINDOW_ROLE(STRING) = role
|
||||||
|
* _NET_WM_WINDOW_TYPE(ATOM) = wintype
|
||||||
|
*/
|
||||||
|
RULE(.wintype = WTYPE "DIALOG", .isfloating = 1)
|
||||||
|
RULE(.wintype = WTYPE "UTILITY", .isfloating = 1)
|
||||||
|
RULE(.wintype = WTYPE "TOOLBAR", .isfloating = 1)
|
||||||
|
RULE(.wintype = WTYPE "SPLASH", .isfloating = 1)
|
||||||
|
RULE(.instance= "main", .class = "Psi+", .tags = 1 << 3)
|
||||||
|
RULE(.instance= "tabs", .class = "Psi+", .tags = 1 << 3)
|
||||||
|
RULE(.class = "Claws-mail", .tags = 1 << 3)
|
||||||
|
RULE(.class = "Zoiper", .tags = 1 << 3)
|
||||||
|
RULE(.class = "linphone", .tags = 1 << 3)
|
||||||
|
RULE(.class = "Skype", .tags = 1 << 3)
|
||||||
|
RULE(.class = "Mattermost", .tags = 1 << 3)
|
||||||
|
|
||||||
|
RULE(.class = "pinentry-qt", .isfloating = 1)
|
||||||
|
RULE(.class = "pinentry-qt5", .isfloating = 1)
|
||||||
|
RULE(.class = "Nm-connection-editor", .isfloating = 1)
|
||||||
|
RULE(.class = "pavucontrol-qt", .isfloating = 0)
|
||||||
|
RULE(.class = "Firefox", .wintype = WTYPE "NORMAL", .tags = 1 << 2)
|
||||||
|
|
||||||
|
RULE(.class = "Spotify", .tags = 1 << 8)
|
||||||
|
RULE(.class = "Kasts", .tags = 1 << 8)
|
||||||
|
|
||||||
|
RULE(.class = "st-tilda", .isfloating = 1)
|
||||||
|
RULE(.class = "st-256color", .isterminal = 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Bar rules allow you to configure what is shown where on the bar, as well as
|
||||||
|
* introducing your own bar modules.
|
||||||
|
*
|
||||||
|
* monitor:
|
||||||
|
* -1 show on all monitors
|
||||||
|
* 0 show on monitor 0
|
||||||
|
* 'A' show on active monitor (i.e. focused / selected) (or just -1 for active?)
|
||||||
|
* bar - bar index, 0 is default, 1 is extrabar
|
||||||
|
* alignment - how the module is aligned compared to other modules
|
||||||
|
* widthfunc, drawfunc, clickfunc - providing bar module width, draw and click functions
|
||||||
|
* name - does nothing, intended for visual clue and for logging / debugging
|
||||||
|
*/
|
||||||
|
static const BarRule barrules[] = {
|
||||||
|
/* monitor bar alignment widthfunc drawfunc clickfunc name */
|
||||||
|
{ -1, 0, BAR_ALIGN_LEFT, width_pwrl_tags, draw_pwrl_tags, click_pwrl_tags, "powerline_tags" },
|
||||||
|
//{ -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, "tags" },
|
||||||
|
{ 'A', 0, BAR_ALIGN_RIGHT, width_systray, draw_systray, click_systray, "systray" },
|
||||||
|
{ -1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, "layout" },
|
||||||
|
// { 'A', 0, BAR_ALIGN_RIGHT, width_pwrl_status, draw_pwrl_status, click_pwrl_status, "powerline_status" },
|
||||||
|
{ statusmon, 0, BAR_ALIGN_RIGHT, width_status, draw_status, click_statuscmd, "status" },
|
||||||
|
{ -1, 0, BAR_ALIGN_NONE, width_bartabgroups, draw_bartabgroups, click_bartabgroups, "bartabgroups" },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 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 = 0; /* 1 means respect size hints in tiled resizals */
|
||||||
|
static const int decorhints = 1; /* 1 means respect decoration hints */
|
||||||
|
|
||||||
|
#define FORCE_VSPLIT 1
|
||||||
|
|
||||||
|
|
||||||
|
static const Layout layouts[] = {
|
||||||
|
/* symbol arrange function */
|
||||||
|
{ "[]=", tile }, /* first entry is default */
|
||||||
|
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||||
|
{ "[M]", monocle },
|
||||||
|
{ "|M|", centeredmaster },
|
||||||
|
{ ">M>", centeredfloatingmaster },
|
||||||
|
{ "[\\]", dwindle },
|
||||||
|
{ "###", nrowgrid },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* key definitions */
|
||||||
|
#define MODKEY Mod4Mask
|
||||||
|
#define AltMask Mod1Mask
|
||||||
|
#define ALTKEY Mod1Mask
|
||||||
|
#define TAGKEYS(KEY,TAG) \
|
||||||
|
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
||||||
|
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
|
||||||
|
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
|
||||||
|
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
||||||
|
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
||||||
|
|
||||||
|
/* commands */
|
||||||
|
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
|
||||||
|
static const char *dmenucmd[] = {
|
||||||
|
"dmenu_run",
|
||||||
|
"-m", dmenumon,
|
||||||
|
"-fn", dmenufont,
|
||||||
|
"-nb", normbgcolor,
|
||||||
|
"-nf", normfgcolor,
|
||||||
|
"-sb", selbgcolor,
|
||||||
|
"-sf", selfgcolor,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
static const char *termcmd[] = { "st", NULL };
|
||||||
|
static const char *tmuxcmd[] = { "st", "-c", "st-tmux", "-e", "/home/wiebel/sync/bin/tmux-spawn.sh", NULL };
|
||||||
|
// static const char scratchpadname[] = "tilda";
|
||||||
|
/* static const char *scratchpadcmd[] = { "st", "-t", scratchpadname, "-g", "120x34", NULL }; */
|
||||||
|
// static const char *scratchpadcmd[] = { "st", "-t", scratchpadname, "-c", "st-tilda", "-g", "180x18", "-e", "tmux", "new-session", "-A", "-s", "tilda", NULL };
|
||||||
|
|
||||||
|
static const char *volup[] = { "/opt/pavolume/pavolume", "volup", "10", NULL };
|
||||||
|
static const char *voldn[] = { "/opt/pavolume/pavolume", "voldown", "10", NULL };
|
||||||
|
static const char *volmute[] = { "/opt/pavolume/pavolume", "mutetoggle", NULL };
|
||||||
|
static const char *playpause[] = { "/usr/bin/playerctl", "play-pause", NULL };
|
||||||
|
#include <X11/XF86keysym.h>
|
||||||
|
|
||||||
|
/* This defines the name of the executable that handles the bar (used for signalling purposes) */
|
||||||
|
#define STATUSBAR "dwmblocks"
|
||||||
|
|
||||||
|
|
||||||
|
static Key keys[] = {
|
||||||
|
/* modifier key function argument */
|
||||||
|
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
||||||
|
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = tmuxcmd } },
|
||||||
|
{ MODKEY|ControlMask, XK_Return, spawn, {.v = termcmd } },
|
||||||
|
{ MODKEY, XK_b, togglebar, {0} },
|
||||||
|
{ MODKEY|ControlMask, XK_s, spawn, SHCMD("transset -a --dec .1") },
|
||||||
|
{ MODKEY|ControlMask, XK_d, spawn, SHCMD("transset -a --inc .1") },
|
||||||
|
{ ALTKEY, XK_w, spawn, SHCMD("pass-wrapper.sh") },
|
||||||
|
{ MODKEY, XK_n, spawn, SHCMD("networkmanager_dmenu") },
|
||||||
|
// { MODKEY, XK_grave, spawn, SHCMD("/home/wiebel/sync/bin/st-tilda.sh") },
|
||||||
|
{ ALTKEY|ControlMask, XK_l, spawn, SHCMD("/usr/local/bin/lock.me") },
|
||||||
|
/* Media Keys */
|
||||||
|
{ 0, XF86XK_MonBrightnessUp, spawn, SHCMD("xbacklight -inc 5") },
|
||||||
|
{ 0, XF86XK_MonBrightnessDown, spawn, SHCMD("xbacklight -dec 5") },
|
||||||
|
{ 0, XF86XK_AudioRaiseVolume, spawn, {.v = volup } },
|
||||||
|
{ 0, XF86XK_AudioLowerVolume, spawn, {.v = voldn } },
|
||||||
|
{ 0, XF86XK_AudioMute, spawn, {.v = volmute } },
|
||||||
|
{ 0, XF86XK_AudioPlay, spawn, {.v = playpause } },
|
||||||
|
{ MODKEY, XK_j, focusstack, {.i = +1 } },
|
||||||
|
{ MODKEY, XK_k, focusstack, {.i = -1 } },
|
||||||
|
{ MODKEY|ShiftMask, XK_j, inplacerotate, {.i = +1} },
|
||||||
|
{ MODKEY|ShiftMask, XK_k, inplacerotate, {.i = -1} },
|
||||||
|
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
|
||||||
|
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
||||||
|
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
||||||
|
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
||||||
|
{ MODKEY, XK_x, transfer, {0} },
|
||||||
|
{ MODKEY, XK_Return, zoom, {0} },
|
||||||
|
// { MODKEY|AltMask, XK_u, incrgaps, {.i = +1 } },
|
||||||
|
// { MODKEY|AltMask|ShiftMask, XK_u, incrgaps, {.i = -1 } },
|
||||||
|
// { MODKEY|AltMask, XK_i, incrigaps, {.i = +1 } },
|
||||||
|
// { MODKEY|AltMask|ShiftMask, XK_i, incrigaps, {.i = -1 } },
|
||||||
|
// { MODKEY|AltMask, XK_o, incrogaps, {.i = +1 } },
|
||||||
|
// { MODKEY|AltMask|ShiftMask, XK_o, incrogaps, {.i = -1 } },
|
||||||
|
// { MODKEY|AltMask, XK_6, incrihgaps, {.i = +1 } },
|
||||||
|
// { MODKEY|AltMask|ShiftMask, XK_6, incrihgaps, {.i = -1 } },
|
||||||
|
// { MODKEY|AltMask, XK_7, incrivgaps, {.i = +1 } },
|
||||||
|
// { MODKEY|AltMask|ShiftMask, XK_7, incrivgaps, {.i = -1 } },
|
||||||
|
// { MODKEY|AltMask, XK_8, incrohgaps, {.i = +1 } },
|
||||||
|
// { MODKEY|AltMask|ShiftMask, XK_8, incrohgaps, {.i = -1 } },
|
||||||
|
// { MODKEY|AltMask, XK_9, incrovgaps, {.i = +1 } },
|
||||||
|
// { MODKEY|AltMask|ShiftMask, XK_9, incrovgaps, {.i = -1 } },
|
||||||
|
// { MODKEY|AltMask, XK_0, togglegaps, {0} },
|
||||||
|
// { MODKEY|AltMask|ShiftMask, XK_0, defaultgaps, {0} },
|
||||||
|
{ MODKEY, XK_Tab, view, {0} },
|
||||||
|
{ MODKEY|ControlMask, XK_z, showhideclient, {0} },
|
||||||
|
{ MODKEY, XK_q, killclient, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_q, quit, {0} },
|
||||||
|
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
||||||
|
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
|
||||||
|
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
||||||
|
{ MODKEY, XK_u, setlayout, {.v = &layouts[3]} },
|
||||||
|
{ MODKEY, XK_o, setlayout, {.v = &layouts[4]} },
|
||||||
|
{ MODKEY|ShiftMask, XK_t, setlayout, {.v = &layouts[5]} },
|
||||||
|
{ MODKEY, XK_g, setlayout, {.v = &layouts[6]} },
|
||||||
|
{ MODKEY, XK_space, setlayout, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_y, togglefakefullscreen, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_s, togglesticky, {0} },
|
||||||
|
{ MODKEY, XK_grave, scratchpad_show, {0} },
|
||||||
|
{ MODKEY, XK_Escape, scratchpad_show, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_grave, scratchpad_hide, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_Escape, scratchpad_hide, {0} },
|
||||||
|
{ MODKEY|ShiftMask|ControlMask, XK_grave, scratchpad_remove, {0} },
|
||||||
|
{ MODKEY|ShiftMask|ControlMask, XK_Escape, scratchpad_remove, {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, XK_Left, viewtoleft, {0} },
|
||||||
|
{ MODKEY, XK_Right, viewtoright, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_Left, tagtoleft, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_Right, tagtoright, {0} },
|
||||||
|
{ MODKEY|ControlMask, XK_Left, tagandviewtoleft, {0} },
|
||||||
|
{ MODKEY|ControlMask, XK_Right, tagandviewtoright, {0} },
|
||||||
|
{ MODKEY|ControlMask, XK_comma, tagallmon, {.i = +1 } },
|
||||||
|
{ MODKEY|ControlMask, XK_period, tagallmon, {.i = -1 } },
|
||||||
|
{ MODKEY|ShiftMask|ControlMask, XK_comma, tagswapmon, {.i = +1 } },
|
||||||
|
{ MODKEY|ShiftMask|ControlMask, XK_period, tagswapmon, {.i = -1 } },
|
||||||
|
|
||||||
|
{ MODKEY, XK_0, view, {.ui = ~0 } },
|
||||||
|
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
|
||||||
|
TAGKEYS( XK_1, 0)
|
||||||
|
TAGKEYS( XK_2, 1)
|
||||||
|
TAGKEYS( XK_3, 2)
|
||||||
|
TAGKEYS( XK_4, 3)
|
||||||
|
TAGKEYS( XK_5, 4)
|
||||||
|
TAGKEYS( XK_6, 5)
|
||||||
|
TAGKEYS( XK_7, 6)
|
||||||
|
TAGKEYS( XK_8, 7)
|
||||||
|
TAGKEYS( XK_9, 8)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* button definitions */
|
||||||
|
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
|
||||||
|
static Button buttons[] = {
|
||||||
|
/* click event mask button function argument */
|
||||||
|
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
|
||||||
|
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
||||||
|
{ ClkWinTitle, 0, Button1, togglewin, {0} },
|
||||||
|
{ ClkWinTitle, 0, Button3, showhideclient, {0} },
|
||||||
|
{ ClkWinTitle, 0, Button2, zoom, {0} },
|
||||||
|
{ ClkStatusText, 0, Button1, sigstatusbar, {.i = 1 } },
|
||||||
|
{ ClkStatusText, 0, Button2, sigstatusbar, {.i = 2 } },
|
||||||
|
{ ClkStatusText, 0, Button3, sigstatusbar, {.i = 3 } },
|
||||||
|
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
||||||
|
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
|
||||||
|
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
|
||||||
|
{ ClkTagBar, 0, Button1, view, {0} },
|
||||||
|
{ ClkTagBar, 0, Button3, toggleview, {0} },
|
||||||
|
{ ClkTagBar, MODKEY, Button1, tag, {0} },
|
||||||
|
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
416
config.h.tmp
Normal file
416
config.h.tmp
Normal file
@ -0,0 +1,416 @@
|
|||||||
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
|
||||||
|
/* appearance */
|
||||||
|
static const unsigned int borderpx = 2; /* border pixel of windows */
|
||||||
|
static const unsigned int snap = 16; /* snap pixel */
|
||||||
|
static const int swallowfloating = 0; /* 1 means swallow floating windows by default */
|
||||||
|
static const unsigned int gappih = 10; /* 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 = 10; /* vert outer gap between windows and screen edge */
|
||||||
|
static const int smartgaps_fact = 0; /* 1 means no outer gap when there is only one window */
|
||||||
|
static const char autostartblocksh[] = "autostart_blocking.sh";
|
||||||
|
static const char autostartsh[] = "autostart.sh";
|
||||||
|
static const char dwmdir[] = "dwm";
|
||||||
|
static const char localshare[] = ".local/share";
|
||||||
|
static const int showbar = 1; /* 0 means no bar */
|
||||||
|
static const int topbar = 1; /* 0 means bottom bar */
|
||||||
|
/* Status is to be shown on: -1 (all monitors), 0 (a specific monitor by index), 'A' (active monitor) */
|
||||||
|
static const int statusmon = 'A';
|
||||||
|
static const unsigned int systrayspacing = 2; /* systray spacing */
|
||||||
|
static const int showsystray = 1; /* 0 means no systray */
|
||||||
|
/* Indicators: see patch/bar_indicators.h for options */
|
||||||
|
static int tagindicatortype = INDICATOR_TOP_LEFT_SQUARE;
|
||||||
|
static int tiledindicatortype = INDICATOR_NONE;
|
||||||
|
static int floatindicatortype = INDICATOR_TOP_LEFT_SQUARE;
|
||||||
|
static int fakefsindicatortype = INDICATOR_PLUS;
|
||||||
|
static int floatfakefsindicatortype = INDICATOR_PLUS_AND_LARGER_SQUARE;
|
||||||
|
static void (*bartabmonfns[])(Monitor *) = { monocle /* , customlayoutfn */ };
|
||||||
|
static const char *fonts[] = {
|
||||||
|
"FontAwesome:size=12",
|
||||||
|
"mononoki:size=12",
|
||||||
|
};
|
||||||
|
static const char dmenufont[] = "mononoki:size=12";
|
||||||
|
|
||||||
|
static char normfgcolor[] = "#bbbbbb";
|
||||||
|
static char normbgcolor[] = "#222222";
|
||||||
|
static char normbordercolor[] = "#444444";
|
||||||
|
static char normfloatcolor[] = "#db8fd9";
|
||||||
|
|
||||||
|
static char selfgcolor[] = "#111111";
|
||||||
|
static char selbgcolor[] = "#ffd700";
|
||||||
|
static char selbordercolor[] = "#ffd700";
|
||||||
|
static char selfloatcolor[] = "#ffd700";
|
||||||
|
|
||||||
|
static char titlenormfgcolor[] = "#bbbbbb";
|
||||||
|
static char titlenormbgcolor[] = "#222222";
|
||||||
|
static char titlenormbordercolor[] = "#444444";
|
||||||
|
static char titlenormfloatcolor[] = "#db8fd9";
|
||||||
|
|
||||||
|
static char titleselfgcolor[] = "#111111";
|
||||||
|
static char titleselbgcolor[] = "#ffd700";
|
||||||
|
static char titleselbordercolor[] = "#ffd700";
|
||||||
|
static char titleselfloatcolor[] = "#ffd700";
|
||||||
|
|
||||||
|
static char tagsnormfgcolor[] = "#bbbbbb";
|
||||||
|
static char tagsnormbgcolor[] = "#222222";
|
||||||
|
static char tagsnormbordercolor[] = "#444444";
|
||||||
|
static char tagsnormfloatcolor[] = "#db8fd9";
|
||||||
|
|
||||||
|
static char tagsselfgcolor[] = "#111111";
|
||||||
|
static char tagsselbgcolor[] = "#ffd700";
|
||||||
|
static char tagsselbordercolor[] = "#ffd700";
|
||||||
|
static char tagsselfloatcolor[] = "#ffd700";
|
||||||
|
|
||||||
|
static char hidnormfgcolor[] = "#ffd700";
|
||||||
|
static char hidnormbgcolor[] = "#222222";
|
||||||
|
static char hidselfgcolor[] = "#ffd700";
|
||||||
|
static char hidselbgcolor[] = "#ffd700";
|
||||||
|
static char hidbordercolor[] = "#ffd700";
|
||||||
|
static char hidfloatcolor[] = "#f76e0c";
|
||||||
|
|
||||||
|
static char urgfgcolor[] = "#bbbbbb";
|
||||||
|
static char urgbgcolor[] = "#222222";
|
||||||
|
static char urgbordercolor[] = "#ff0000";
|
||||||
|
static char urgfloatcolor[] = "#db8fd9";
|
||||||
|
|
||||||
|
|
||||||
|
static const unsigned int baralpha = 0xd0;
|
||||||
|
static const unsigned int borderalpha = OPAQUE;
|
||||||
|
static const unsigned int alphas[][3] = {
|
||||||
|
/* fg bg border */
|
||||||
|
[SchemeNorm] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeSel] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeTitleNorm] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeTitleSel] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeTagsNorm] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeTagsSel] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeHidNorm] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeHidSel] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
[SchemeUrg] = { OPAQUE, baralpha, borderalpha },
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *colors[][ColCount] = {
|
||||||
|
/* fg bg border float */
|
||||||
|
[SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor, normfloatcolor },
|
||||||
|
[SchemeSel] = { selfgcolor, selbgcolor, selbordercolor, selfloatcolor },
|
||||||
|
[SchemeTitleNorm] = { titlenormfgcolor, titlenormbgcolor, titlenormbordercolor, titlenormfloatcolor },
|
||||||
|
[SchemeTitleSel] = { titleselfgcolor, titleselbgcolor, titleselbordercolor, titleselfloatcolor },
|
||||||
|
[SchemeTagsNorm] = { tagsnormfgcolor, tagsnormbgcolor, tagsnormbordercolor, tagsnormfloatcolor },
|
||||||
|
[SchemeTagsSel] = { tagsselfgcolor, tagsselbgcolor, tagsselbordercolor, tagsselfloatcolor },
|
||||||
|
[SchemeHidNorm] = { hidnormfgcolor, hidnormbgcolor, hidbordercolor, hidfloatcolor },
|
||||||
|
[SchemeHidSel] = { hidselfgcolor, hidselbgcolor, hidbordercolor, hidfloatcolor },
|
||||||
|
[SchemeUrg] = { urgfgcolor, urgbgcolor, urgbordercolor, urgfloatcolor },
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
static char *statuscolors[][ColCount] = {
|
||||||
|
// fg bg border float
|
||||||
|
[SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor, normfloatcolor },
|
||||||
|
[SchemeSel] = { selfgcolor, selbgcolor, selbordercolor, selfloatcolor },
|
||||||
|
[SchemeTitleNorm] = { titlenormfgcolor, titlenormbgcolor, titlenormbordercolor, titlenormfloatcolor },
|
||||||
|
[SchemeTitleSel] = { titleselfgcolor, titleselbgcolor, titleselbordercolor, titleselfloatcolor },
|
||||||
|
[SchemeTagsNorm] = { tagsnormfgcolor, tagsnormbgcolor, tagsnormbordercolor, tagsnormfloatcolor },
|
||||||
|
[SchemeTagsSel] = { tagsselfgcolor, tagsselbgcolor, tagsselbordercolor, tagsselfloatcolor },
|
||||||
|
[SchemeHidNorm] = { hidnormfgcolor, hidnormbgcolor, hidbordercolor, hidfloatcolor },
|
||||||
|
[SchemeHidSel] = { hidselfgcolor, hidselbgcolor, hidbordercolor, hidfloatcolor },
|
||||||
|
[SchemeUrg] = { urgfgcolor, urgbgcolor, urgbordercolor, urgfloatcolor },
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Tags
|
||||||
|
* In a traditional dwm the number of tags in use can be changed simply by changing the number
|
||||||
|
* of strings in the tags array. This build does things a bit different which has some added
|
||||||
|
* benefits. If you need to change the number of tags here then change the NUMTAGS macro in dwm.c.
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
*
|
||||||
|
* 1) static char *tagicons[][NUMTAGS*2] = {
|
||||||
|
* [DEFAULT_TAGS] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I" },
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* 2) static char *tagicons[][1] = {
|
||||||
|
* [DEFAULT_TAGS] = { "•" },
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* The first example would result in the tags on the first monitor to be 1 through 9, while the
|
||||||
|
* tags for the second monitor would be named A through I. A third monitor would start again at
|
||||||
|
* 1 through 9 while the tags on a fourth monitor would also be named A through I. Note the tags
|
||||||
|
* count of NUMTAGS*2 in the array initialiser which defines how many tag text / icon exists in
|
||||||
|
* the array. This can be changed to *3 to add separate icons for a third monitor.
|
||||||
|
*
|
||||||
|
* For the second example each tag would be represented as a bullet point. Both cases work the
|
||||||
|
* same from a technical standpoint - the icon index is derived from the tag index and the monitor
|
||||||
|
* index. If the icon index is is greater than the number of tag icons then it will wrap around
|
||||||
|
* until it an icon matches. Similarly if there are two tag icons then it would alternate between
|
||||||
|
* them. This works seamlessly with alternative tags and alttagsdecoration patches.
|
||||||
|
*/
|
||||||
|
static char *tagicons[][NUMTAGS] = {
|
||||||
|
// [DEFAULT_TAGS] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" },
|
||||||
|
[DEFAULT_TAGS] = { "₁", "₂", "₃", "₄", "₅", "₆", "₇", "₈", "₉" },
|
||||||
|
[ALTERNATIVE_TAGS] = { "A", "B", "C", "D", "E", "F", "G", "H", "I" },
|
||||||
|
[ALT_TAGS_DECORATION] = { "<1>", "<2>", "<3>", "<4>", "<5>", "<6>", "<7>", "<8>", "<9>" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* There are two options when it comes to per-client rules:
|
||||||
|
* - a typical struct table or
|
||||||
|
* - using the RULE macro
|
||||||
|
*
|
||||||
|
* A traditional struct table looks like this:
|
||||||
|
* // class instance title wintype tags mask isfloating monitor
|
||||||
|
* { "Gimp", NULL, NULL, NULL, 1 << 4, 0, -1 },
|
||||||
|
* { "Firefox", NULL, NULL, NULL, 1 << 7, 0, -1 },
|
||||||
|
*
|
||||||
|
* The RULE macro has the default values set for each field allowing you to only
|
||||||
|
* specify the values that are relevant for your rule, e.g.
|
||||||
|
*
|
||||||
|
* RULE(.class = "Gimp", .tags = 1 << 4)
|
||||||
|
* RULE(.class = "Firefox", .tags = 1 << 7)
|
||||||
|
*
|
||||||
|
* Refer to the Rule struct definition for the list of available fields depending on
|
||||||
|
* the patches you enable.
|
||||||
|
*/
|
||||||
|
static const Rule rules[] = {
|
||||||
|
/* xprop(1):
|
||||||
|
* WM_CLASS(STRING) = instance, class
|
||||||
|
* WM_NAME(STRING) = title
|
||||||
|
* WM_WINDOW_ROLE(STRING) = role
|
||||||
|
* _NET_WM_WINDOW_TYPE(ATOM) = wintype
|
||||||
|
*/
|
||||||
|
RULE(.wintype = WTYPE "DIALOG", .isfloating = 1)
|
||||||
|
RULE(.wintype = WTYPE "UTILITY", .isfloating = 1)
|
||||||
|
RULE(.wintype = WTYPE "TOOLBAR", .isfloating = 1)
|
||||||
|
RULE(.wintype = WTYPE "SPLASH", .isfloating = 1)
|
||||||
|
RULE(.instance= "main", .class = "Psi+", .tags = 1 << 2)
|
||||||
|
RULE(.instance= "tabs", .class = "Psi+", .tags = 1 << 2)
|
||||||
|
RULE(.class = "Claws-mail", .tags = 1 << 2)
|
||||||
|
RULE(.class = "Zoiper", .tags = 1 << 2)
|
||||||
|
RULE(.class = "linphone", .tags = 1 << 2)
|
||||||
|
RULE(.class = "Skype", .tags = 1 << 2)
|
||||||
|
RULE(.class = "Mattermost", .tags = 1 << 2)
|
||||||
|
|
||||||
|
RULE(.class = "pinentry-qt", .isfloating = 1)
|
||||||
|
RULE(.class = "pinentry-qt5", .isfloating = 1)
|
||||||
|
RULE(.class = "Nm-connection-editor", .isfloating = 1)
|
||||||
|
RULE(.class = "pavucontrol-qt", .isfloating = 0)
|
||||||
|
RULE(.class = "Gimp", .tags = 1 << 4)
|
||||||
|
RULE(.class = "Firefox", .wintype = WTYPE "NORMAL", .tags = 1 << 1)
|
||||||
|
|
||||||
|
RULE(.class = "Spotify", .tags = 1 << 7)
|
||||||
|
|
||||||
|
RULE(.class = "st-tilda", .isfloating = 1)
|
||||||
|
RULE(.class = "st-256color", .isterminal = 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Bar rules allow you to configure what is shown where on the bar, as well as
|
||||||
|
* introducing your own bar modules.
|
||||||
|
*
|
||||||
|
* monitor:
|
||||||
|
* -1 show on all monitors
|
||||||
|
* 0 show on monitor 0
|
||||||
|
* 'A' show on active monitor (i.e. focused / selected) (or just -1 for active?)
|
||||||
|
* bar - bar index, 0 is default, 1 is extrabar
|
||||||
|
* alignment - how the module is aligned compared to other modules
|
||||||
|
* widthfunc, drawfunc, clickfunc - providing bar module width, draw and click functions
|
||||||
|
* name - does nothing, intended for visual clue and for logging / debugging
|
||||||
|
*/
|
||||||
|
static const BarRule barrules[] = {
|
||||||
|
/* monitor bar alignment widthfunc drawfunc clickfunc name */
|
||||||
|
{ -1, 0, BAR_ALIGN_LEFT, width_pwrl_tags, draw_pwrl_tags, click_pwrl_tags, "powerline_tags" },
|
||||||
|
//{ -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, "tags" },
|
||||||
|
{ 'A', 0, BAR_ALIGN_RIGHT, width_systray, draw_systray, click_systray, "systray" },
|
||||||
|
{ -1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, "layout" },
|
||||||
|
// { 'A', 0, BAR_ALIGN_RIGHT, width_pwrl_status, draw_pwrl_status, click_pwrl_status, "powerline_status" },
|
||||||
|
{ statusmon, 0, BAR_ALIGN_RIGHT, width_status, draw_status, click_statuscmd, "status" },
|
||||||
|
{ -1, 0, BAR_ALIGN_NONE, width_bartabgroups, draw_bartabgroups, click_bartabgroups, "bartabgroups" },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 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 = 0; /* 1 means respect size hints in tiled resizals */
|
||||||
|
static const int decorhints = 1; /* 1 means respect decoration hints */
|
||||||
|
|
||||||
|
#define FORCE_VSPLIT 1
|
||||||
|
|
||||||
|
|
||||||
|
static const Layout layouts[] = {
|
||||||
|
/* symbol arrange function */
|
||||||
|
{ "[]=", tile }, /* first entry is default */
|
||||||
|
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||||
|
{ "[M]", monocle },
|
||||||
|
{ "|M|", centeredmaster },
|
||||||
|
{ ">M>", centeredfloatingmaster },
|
||||||
|
{ "[\\]", dwindle },
|
||||||
|
{ "###", nrowgrid },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* key definitions */
|
||||||
|
#define MODKEY Mod4Mask
|
||||||
|
#define AltMask Mod1Mask
|
||||||
|
#define ALTKEY Mod1Mask
|
||||||
|
#define TAGKEYS(KEY,TAG) \
|
||||||
|
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
||||||
|
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
|
||||||
|
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
|
||||||
|
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
||||||
|
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
||||||
|
|
||||||
|
/* commands */
|
||||||
|
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
|
||||||
|
static const char *dmenucmd[] = {
|
||||||
|
"dmenu_run",
|
||||||
|
"-m", dmenumon,
|
||||||
|
"-fn", dmenufont,
|
||||||
|
"-nb", normbgcolor,
|
||||||
|
"-nf", normfgcolor,
|
||||||
|
"-sb", selbgcolor,
|
||||||
|
"-sf", selfgcolor,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
static const char *termcmd[] = { "st", NULL };
|
||||||
|
static const char *tmuxcmd[] = { "st", "-c", "st-tmux", "-e", "/home/wiebel/sync/bin/tmux-spawn.sh", NULL };
|
||||||
|
// static const char scratchpadname[] = "tilda";
|
||||||
|
/* static const char *scratchpadcmd[] = { "st", "-t", scratchpadname, "-g", "120x34", NULL }; */
|
||||||
|
// static const char *scratchpadcmd[] = { "st", "-t", scratchpadname, "-c", "st-tilda", "-g", "180x18", "-e", "tmux", "new-session", "-A", "-s", "tilda", NULL };
|
||||||
|
|
||||||
|
static const char *volup[] = { "/opt/pavolume/pavolume", "volup", "10", NULL };
|
||||||
|
static const char *voldn[] = { "/opt/pavolume/pavolume", "voldown", "10", NULL };
|
||||||
|
static const char *volmute[] = { "/opt/pavolume/pavolume", "mutetoggle", NULL };
|
||||||
|
static const char *playpause[] = { "/usr/bin/playerctl", "play-pause", NULL };
|
||||||
|
#include <X11/XF86keysym.h>
|
||||||
|
|
||||||
|
/* This defines the name of the executable that handles the bar (used for signalling purposes) */
|
||||||
|
#define STATUSBAR "dwmblocks"
|
||||||
|
|
||||||
|
|
||||||
|
static Key keys[] = {
|
||||||
|
/* modifier key function argument */
|
||||||
|
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
||||||
|
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = tmuxcmd } },
|
||||||
|
{ MODKEY|ControlMask, XK_Return, spawn, {.v = termcmd } },
|
||||||
|
{ MODKEY, XK_b, togglebar, {0} },
|
||||||
|
{ MODKEY|ControlMask, XK_s, spawn, SHCMD("transset -a --dec .1") },
|
||||||
|
{ MODKEY|ControlMask, XK_d, spawn, SHCMD("transset -a --inc .1") },
|
||||||
|
{ ALTKEY, XK_w, spawn, SHCMD("pass-wrapper.sh") },
|
||||||
|
{ MODKEY, XK_n, spawn, SHCMD("networkmanager_dmenu") },
|
||||||
|
// { MODKEY, XK_grave, spawn, SHCMD("/home/wiebel/sync/bin/st-tilda.sh") },
|
||||||
|
{ ALTKEY|ControlMask, XK_l, spawn, SHCMD("/usr/local/bin/lock.me") },
|
||||||
|
/* Media Keys */
|
||||||
|
{ 0, XF86XK_MonBrightnessUp, spawn, SHCMD("xbacklight -inc 5") },
|
||||||
|
{ 0, XF86XK_MonBrightnessDown, spawn, SHCMD("xbacklight -dec 5") },
|
||||||
|
{ 0, XF86XK_AudioRaiseVolume, spawn, {.v = volup } },
|
||||||
|
{ 0, XF86XK_AudioLowerVolume, spawn, {.v = voldn } },
|
||||||
|
{ 0, XF86XK_AudioMute, spawn, {.v = volmute } },
|
||||||
|
{ 0, XF86XK_AudioPlay, spawn, {.v = playpause } },
|
||||||
|
{ MODKEY, XK_j, focusstack, {.i = +1 } },
|
||||||
|
{ MODKEY, XK_k, focusstack, {.i = -1 } },
|
||||||
|
{ MODKEY|ShiftMask, XK_j, inplacerotate, {.i = +1} },
|
||||||
|
{ MODKEY|ShiftMask, XK_k, inplacerotate, {.i = -1} },
|
||||||
|
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
|
||||||
|
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
||||||
|
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
||||||
|
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
||||||
|
{ MODKEY, XK_x, transfer, {0} },
|
||||||
|
{ MODKEY, XK_Return, zoom, {0} },
|
||||||
|
// { MODKEY|AltMask, XK_u, incrgaps, {.i = +1 } },
|
||||||
|
// { MODKEY|AltMask|ShiftMask, XK_u, incrgaps, {.i = -1 } },
|
||||||
|
// { MODKEY|AltMask, XK_i, incrigaps, {.i = +1 } },
|
||||||
|
// { MODKEY|AltMask|ShiftMask, XK_i, incrigaps, {.i = -1 } },
|
||||||
|
// { MODKEY|AltMask, XK_o, incrogaps, {.i = +1 } },
|
||||||
|
// { MODKEY|AltMask|ShiftMask, XK_o, incrogaps, {.i = -1 } },
|
||||||
|
// { MODKEY|AltMask, XK_6, incrihgaps, {.i = +1 } },
|
||||||
|
// { MODKEY|AltMask|ShiftMask, XK_6, incrihgaps, {.i = -1 } },
|
||||||
|
// { MODKEY|AltMask, XK_7, incrivgaps, {.i = +1 } },
|
||||||
|
// { MODKEY|AltMask|ShiftMask, XK_7, incrivgaps, {.i = -1 } },
|
||||||
|
// { MODKEY|AltMask, XK_8, incrohgaps, {.i = +1 } },
|
||||||
|
// { MODKEY|AltMask|ShiftMask, XK_8, incrohgaps, {.i = -1 } },
|
||||||
|
// { MODKEY|AltMask, XK_9, incrovgaps, {.i = +1 } },
|
||||||
|
// { MODKEY|AltMask|ShiftMask, XK_9, incrovgaps, {.i = -1 } },
|
||||||
|
// { MODKEY|AltMask, XK_0, togglegaps, {0} },
|
||||||
|
// { MODKEY|AltMask|ShiftMask, XK_0, defaultgaps, {0} },
|
||||||
|
{ MODKEY, XK_Tab, view, {0} },
|
||||||
|
{ MODKEY|ControlMask, XK_z, showhideclient, {0} },
|
||||||
|
{ MODKEY, XK_q, killclient, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_q, quit, {0} },
|
||||||
|
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
||||||
|
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
|
||||||
|
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
||||||
|
{ MODKEY, XK_u, setlayout, {.v = &layouts[3]} },
|
||||||
|
{ MODKEY, XK_o, setlayout, {.v = &layouts[4]} },
|
||||||
|
{ MODKEY|ShiftMask, XK_t, setlayout, {.v = &layouts[5]} },
|
||||||
|
{ MODKEY, XK_g, setlayout, {.v = &layouts[6]} },
|
||||||
|
{ MODKEY, XK_space, setlayout, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_y, togglefakefullscreen, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_s, togglesticky, {0} },
|
||||||
|
{ MODKEY, XK_grave, scratchpad_show, {0} },
|
||||||
|
{ MODKEY, XK_Escape, scratchpad_show, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_grave, scratchpad_hide, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_Escape, scratchpad_hide, {0} },
|
||||||
|
{ MODKEY|ShiftMask|ControlMask, XK_grave, scratchpad_remove, {0} },
|
||||||
|
{ MODKEY|ShiftMask|ControlMask, XK_Escape, scratchpad_remove, {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, XK_Left, viewtoleft, {0} },
|
||||||
|
{ MODKEY, XK_Right, viewtoright, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_Left, tagtoleft, {0} },
|
||||||
|
{ MODKEY|ShiftMask, XK_Right, tagtoright, {0} },
|
||||||
|
{ MODKEY|ControlMask, XK_Left, tagandviewtoleft, {0} },
|
||||||
|
{ MODKEY|ControlMask, XK_Right, tagandviewtoright, {0} },
|
||||||
|
{ MODKEY|ControlMask, XK_comma, tagallmon, {.i = +1 } },
|
||||||
|
{ MODKEY|ControlMask, XK_period, tagallmon, {.i = -1 } },
|
||||||
|
{ MODKEY|ShiftMask|ControlMask, XK_comma, tagswap:mon, {.i = +1 } },
|
||||||
|
{ MODKEY|ShiftMask|ControlMask, XK_period, tagswapmon, {.i = -1 } },
|
||||||
|
|
||||||
|
{ MODKEY, XK_0, view, {.ui = ~0 } },
|
||||||
|
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
|
||||||
|
TAGKEYS( XK_1, 0)
|
||||||
|
TAGKEYS( XK_2, 1)
|
||||||
|
TAGKEYS( XK_3, 2)
|
||||||
|
TAGKEYS( XK_4, 3)
|
||||||
|
TAGKEYS( XK_5, 4)
|
||||||
|
TAGKEYS( XK_6, 5)
|
||||||
|
TAGKEYS( XK_7, 6)
|
||||||
|
TAGKEYS( XK_8, 7)
|
||||||
|
TAGKEYS( XK_9, 8)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* button definitions */
|
||||||
|
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
|
||||||
|
static Button buttons[] = {
|
||||||
|
/* click event mask button function argument */
|
||||||
|
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
|
||||||
|
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
||||||
|
{ ClkWinTitle, 0, Button1, togglewin, {0} },
|
||||||
|
{ ClkWinTitle, 0, Button3, showhideclient, {0} },
|
||||||
|
{ ClkWinTitle, 0, Button2, zoom, {0} },
|
||||||
|
{ ClkStatusText, 0, Button1, sigstatusbar, {.i = 1 } },
|
||||||
|
{ ClkStatusText, 0, Button2, sigstatusbar, {.i = 2 } },
|
||||||
|
{ ClkStatusText, 0, Button3, sigstatusbar, {.i = 3 } },
|
||||||
|
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
||||||
|
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
|
||||||
|
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
|
||||||
|
{ ClkTagBar, 0, Button1, view, {0} },
|
||||||
|
{ ClkTagBar, 0, Button3, toggleview, {0} },
|
||||||
|
{ ClkTagBar, MODKEY, Button1, tag, {0} },
|
||||||
|
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
70
config.mk
Normal file
70
config.mk
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# dwm version
|
||||||
|
VERSION = 6.2
|
||||||
|
|
||||||
|
# Customize below to fit your system
|
||||||
|
|
||||||
|
# paths
|
||||||
|
PREFIX = /usr/local
|
||||||
|
MANPREFIX = ${PREFIX}/share/man
|
||||||
|
|
||||||
|
X11INC = /usr/X11R6/include
|
||||||
|
X11LIB = /usr/X11R6/lib
|
||||||
|
|
||||||
|
# FreeBSD (uncomment)
|
||||||
|
#X11INC = /usr/local/include
|
||||||
|
#X11LIB = /usr/local/lib
|
||||||
|
|
||||||
|
# Xinerama, comment if you don't want it
|
||||||
|
XINERAMALIBS = -lXinerama
|
||||||
|
XINERAMAFLAGS = -DXINERAMA
|
||||||
|
|
||||||
|
# freetype
|
||||||
|
FREETYPELIBS = -lfontconfig -lXft
|
||||||
|
FREETYPEINC = /usr/include/freetype2
|
||||||
|
# FreeBSD (uncomment)
|
||||||
|
#FREETYPEINC = /usr/local/include/freetype2
|
||||||
|
# OpenBSD (uncomment)
|
||||||
|
#FREETYPEINC = ${X11INC}/freetype2
|
||||||
|
# OpenBSD - Uncomment this for the swallow patch / SWALLOW_PATCH
|
||||||
|
#KVMLIB = -lkvm
|
||||||
|
|
||||||
|
# Uncomment this for the alpha patch / BAR_ALPHA_PATCH
|
||||||
|
XRENDER = -lXrender
|
||||||
|
|
||||||
|
# Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH
|
||||||
|
#MPDCLIENT = -lmpdclient
|
||||||
|
|
||||||
|
# Uncomment for the pango patch / BAR_PANGO_PATCH
|
||||||
|
#PANGOINC = `pkg-config --cflags xft pango pangoxft`
|
||||||
|
#PANGOLIB = `pkg-config --libs xft pango pangoxft`
|
||||||
|
|
||||||
|
# Uncomment for the ipc patch / IPC_PATCH
|
||||||
|
#YAJLLIBS = -lyajl
|
||||||
|
#YAJLINC = -I/usr/include/yajl
|
||||||
|
|
||||||
|
# Uncomment this for the rounded corners patch / ROUNDED_CORNERS_PATCH
|
||||||
|
#XEXTLIB = -lXext
|
||||||
|
|
||||||
|
# Uncomment this for the swallow patch / SWALLOW_PATCH
|
||||||
|
XCBLIBS = -lX11-xcb -lxcb -lxcb-res
|
||||||
|
|
||||||
|
# This is needed for the winicon patch / BAR_WINICON_PATCH
|
||||||
|
#IMLIB2LIBS = -lImlib2
|
||||||
|
|
||||||
|
# includes and libs
|
||||||
|
INCS = -I${X11INC} -I${FREETYPEINC} ${YAJLINC} ${PANGOINC}
|
||||||
|
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${KVMLIB} ${PANGOLIB} ${YAJLLIBS} ${IMLIB2LIBS}
|
||||||
|
|
||||||
|
# flags
|
||||||
|
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
|
||||||
|
#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
|
||||||
|
#CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS}
|
||||||
|
CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -march=native -O3 -flto ${INCS} ${CPPFLAGS}
|
||||||
|
LDFLAGS = -flto ${LIBS}
|
||||||
|
|
||||||
|
# Solaris
|
||||||
|
#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\"
|
||||||
|
#LDFLAGS = ${LIBS}
|
||||||
|
|
||||||
|
# compiler and linker
|
||||||
|
CC = cc
|
490
drw.c
Normal file
490
drw.c
Normal file
@ -0,0 +1,490 @@
|
|||||||
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xft/Xft.h>
|
||||||
|
|
||||||
|
#include "drw.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define UTF_INVALID 0xFFFD
|
||||||
|
#define UTF_SIZ 4
|
||||||
|
|
||||||
|
static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
|
||||||
|
static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
|
||||||
|
static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000};
|
||||||
|
static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
|
||||||
|
|
||||||
|
Clr transcheme[3];
|
||||||
|
|
||||||
|
static long
|
||||||
|
utf8decodebyte(const char c, size_t *i)
|
||||||
|
{
|
||||||
|
for (*i = 0; *i < (UTF_SIZ + 1); ++(*i))
|
||||||
|
if (((unsigned char)c & utfmask[*i]) == utfbyte[*i])
|
||||||
|
return (unsigned char)c & ~utfmask[*i];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
utf8validate(long *u, size_t i)
|
||||||
|
{
|
||||||
|
if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
|
||||||
|
*u = UTF_INVALID;
|
||||||
|
for (i = 1; *u > utfmax[i]; ++i)
|
||||||
|
;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
utf8decode(const char *c, long *u, size_t clen)
|
||||||
|
{
|
||||||
|
size_t i, j, len, type;
|
||||||
|
long udecoded;
|
||||||
|
|
||||||
|
*u = UTF_INVALID;
|
||||||
|
if (!clen)
|
||||||
|
return 0;
|
||||||
|
udecoded = utf8decodebyte(c[0], &len);
|
||||||
|
if (!BETWEEN(len, 1, UTF_SIZ))
|
||||||
|
return 1;
|
||||||
|
for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
|
||||||
|
udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
|
||||||
|
if (type)
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
if (j < len)
|
||||||
|
return 0;
|
||||||
|
*u = udecoded;
|
||||||
|
utf8validate(u, len);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
Drw *
|
||||||
|
drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap)
|
||||||
|
{
|
||||||
|
Drw *drw = ecalloc(1, sizeof(Drw));
|
||||||
|
|
||||||
|
drw->dpy = dpy;
|
||||||
|
drw->screen = screen;
|
||||||
|
drw->root = root;
|
||||||
|
drw->w = w;
|
||||||
|
drw->h = h;
|
||||||
|
|
||||||
|
drw->visual = visual;
|
||||||
|
drw->depth = depth;
|
||||||
|
drw->cmap = cmap;
|
||||||
|
drw->drawable = XCreatePixmap(dpy, root, w, h, depth);
|
||||||
|
drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL);
|
||||||
|
XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
|
||||||
|
|
||||||
|
return drw;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drw_resize(Drw *drw, unsigned int w, unsigned int h)
|
||||||
|
{
|
||||||
|
if (!drw)
|
||||||
|
return;
|
||||||
|
|
||||||
|
drw->w = w;
|
||||||
|
drw->h = h;
|
||||||
|
if (drw->drawable)
|
||||||
|
XFreePixmap(drw->dpy, drw->drawable);
|
||||||
|
drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drw_free(Drw *drw)
|
||||||
|
{
|
||||||
|
XFreePixmap(drw->dpy, drw->drawable);
|
||||||
|
XFreeGC(drw->dpy, drw->gc);
|
||||||
|
drw_fontset_free(drw->fonts);
|
||||||
|
free(drw);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function is an implementation detail. Library users should use
|
||||||
|
* drw_fontset_create instead.
|
||||||
|
*/
|
||||||
|
static Fnt *
|
||||||
|
xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
|
||||||
|
{
|
||||||
|
Fnt *font;
|
||||||
|
XftFont *xfont = NULL;
|
||||||
|
FcPattern *pattern = NULL;
|
||||||
|
|
||||||
|
if (fontname) {
|
||||||
|
/* Using the pattern found at font->xfont->pattern does not yield the
|
||||||
|
* same substitution results as using the pattern returned by
|
||||||
|
* FcNameParse; using the latter results in the desired fallback
|
||||||
|
* behaviour whereas the former just results in missing-character
|
||||||
|
* rectangles being drawn, at least with some fonts. */
|
||||||
|
if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) {
|
||||||
|
fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!(pattern = FcNameParse((FcChar8 *) fontname))) {
|
||||||
|
fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname);
|
||||||
|
XftFontClose(drw->dpy, xfont);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else if (fontpattern) {
|
||||||
|
if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
|
||||||
|
fprintf(stderr, "error, cannot load font from pattern.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
die("no font specified.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do not allow using color fonts. This is a workaround for a BadLength
|
||||||
|
* error from Xft with color glyphs. Modelled on the Xterm workaround. See
|
||||||
|
* https://bugzilla.redhat.com/show_bug.cgi?id=1498269
|
||||||
|
* https://lists.suckless.org/dev/1701/30932.html
|
||||||
|
* https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349
|
||||||
|
* and lots more all over the internet.
|
||||||
|
*/
|
||||||
|
FcBool iscol;
|
||||||
|
if (FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) {
|
||||||
|
XftFontClose(drw->dpy, xfont);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
font = ecalloc(1, sizeof(Fnt));
|
||||||
|
font->xfont = xfont;
|
||||||
|
font->pattern = pattern;
|
||||||
|
font->h = xfont->ascent + xfont->descent;
|
||||||
|
font->dpy = drw->dpy;
|
||||||
|
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xfont_free(Fnt *font)
|
||||||
|
{
|
||||||
|
if (!font)
|
||||||
|
return;
|
||||||
|
if (font->pattern)
|
||||||
|
FcPatternDestroy(font->pattern);
|
||||||
|
XftFontClose(font->dpy, font->xfont);
|
||||||
|
free(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
Fnt*
|
||||||
|
drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
|
||||||
|
{
|
||||||
|
Fnt *cur, *ret = NULL;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (!drw || !fonts)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 1; i <= fontcount; i++) {
|
||||||
|
if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) {
|
||||||
|
cur->next = ret;
|
||||||
|
ret = cur;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (drw->fonts = ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drw_fontset_free(Fnt *font)
|
||||||
|
{
|
||||||
|
if (font) {
|
||||||
|
drw_fontset_free(font->next);
|
||||||
|
xfont_free(font);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drw_clr_create(
|
||||||
|
Drw *drw,
|
||||||
|
Clr *dest,
|
||||||
|
const char *clrname
|
||||||
|
, unsigned int alpha
|
||||||
|
) {
|
||||||
|
if (!drw || !dest || !clrname)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap,
|
||||||
|
clrname, dest))
|
||||||
|
die("error, cannot allocate color '%s'", clrname);
|
||||||
|
|
||||||
|
dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 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,
|
||||||
|
char *clrnames[],
|
||||||
|
const unsigned int alphas[],
|
||||||
|
size_t clrcount
|
||||||
|
) {
|
||||||
|
size_t i;
|
||||||
|
Clr *ret;
|
||||||
|
|
||||||
|
/* need at least two colors for a scheme */
|
||||||
|
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < clrcount; i++)
|
||||||
|
drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drw_setfontset(Drw *drw, Fnt *set)
|
||||||
|
{
|
||||||
|
if (drw)
|
||||||
|
drw->fonts = set;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drw_setscheme(Drw *drw, Clr *scm)
|
||||||
|
{
|
||||||
|
if (drw)
|
||||||
|
drw->scheme = scm;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drw_settrans(Drw *drw, Clr *psc, Clr *nsc)
|
||||||
|
{
|
||||||
|
if (drw) {
|
||||||
|
transcheme[0] = psc[ColBg]; transcheme[1] = nsc[ColBg]; transcheme[2] = psc[ColBorder];
|
||||||
|
drw->scheme = transcheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert)
|
||||||
|
{
|
||||||
|
if (!drw || !drw->scheme)
|
||||||
|
return;
|
||||||
|
XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
|
||||||
|
if (filled)
|
||||||
|
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
||||||
|
else
|
||||||
|
XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool ignored)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
int ty;
|
||||||
|
unsigned int ew;
|
||||||
|
XftDraw *d = NULL;
|
||||||
|
Fnt *usedfont, *curfont, *nextfont;
|
||||||
|
size_t i, len;
|
||||||
|
int utf8strlen, utf8charlen, render = x || y || w || h;
|
||||||
|
long utf8codepoint = 0;
|
||||||
|
const char *utf8str;
|
||||||
|
FcCharSet *fccharset;
|
||||||
|
FcPattern *fcpattern;
|
||||||
|
FcPattern *match;
|
||||||
|
XftResult result;
|
||||||
|
int charexists = 0;
|
||||||
|
|
||||||
|
if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!render) {
|
||||||
|
w = ~w;
|
||||||
|
} else {
|
||||||
|
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
||||||
|
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
||||||
|
d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap);
|
||||||
|
x += lpad;
|
||||||
|
w -= lpad;
|
||||||
|
}
|
||||||
|
|
||||||
|
usedfont = drw->fonts;
|
||||||
|
while (1) {
|
||||||
|
utf8strlen = 0;
|
||||||
|
utf8str = text;
|
||||||
|
nextfont = NULL;
|
||||||
|
while (*text) {
|
||||||
|
utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
|
||||||
|
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
|
||||||
|
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
||||||
|
if (charexists) {
|
||||||
|
if (curfont == usedfont) {
|
||||||
|
utf8strlen += utf8charlen;
|
||||||
|
text += utf8charlen;
|
||||||
|
} else {
|
||||||
|
nextfont = curfont;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!charexists || nextfont)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
charexists = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (utf8strlen) {
|
||||||
|
drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL);
|
||||||
|
/* shorten text if necessary */
|
||||||
|
for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--)
|
||||||
|
drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
|
||||||
|
|
||||||
|
if (len) {
|
||||||
|
memcpy(buf, utf8str, len);
|
||||||
|
buf[len] = '\0';
|
||||||
|
if (len < utf8strlen)
|
||||||
|
for (i = len; i && i > len - 3; buf[--i] = '.')
|
||||||
|
; /* NOP */
|
||||||
|
|
||||||
|
if (render) {
|
||||||
|
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
|
||||||
|
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
|
||||||
|
usedfont->xfont, x, ty, (XftChar8 *)buf, len);
|
||||||
|
}
|
||||||
|
x += ew;
|
||||||
|
w -= ew;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*text) {
|
||||||
|
break;
|
||||||
|
} else if (nextfont) {
|
||||||
|
charexists = 0;
|
||||||
|
usedfont = nextfont;
|
||||||
|
} else {
|
||||||
|
/* Regardless of whether or not a fallback font is found, the
|
||||||
|
* character must be drawn. */
|
||||||
|
charexists = 1;
|
||||||
|
|
||||||
|
fccharset = FcCharSetCreate();
|
||||||
|
FcCharSetAddChar(fccharset, utf8codepoint);
|
||||||
|
|
||||||
|
if (!drw->fonts->pattern) {
|
||||||
|
/* Refer to the comment in xfont_create for more information. */
|
||||||
|
die("the first font in the cache must be loaded from a font string.");
|
||||||
|
}
|
||||||
|
|
||||||
|
fcpattern = FcPatternDuplicate(drw->fonts->pattern);
|
||||||
|
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
|
||||||
|
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
|
||||||
|
FcPatternAddBool(fcpattern, FC_COLOR, FcFalse);
|
||||||
|
|
||||||
|
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
|
||||||
|
FcDefaultSubstitute(fcpattern);
|
||||||
|
match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
|
||||||
|
|
||||||
|
FcCharSetDestroy(fccharset);
|
||||||
|
FcPatternDestroy(fcpattern);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
usedfont = xfont_create(drw, NULL, match);
|
||||||
|
if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
|
||||||
|
for (curfont = drw->fonts; curfont->next; curfont = curfont->next)
|
||||||
|
; /* NOP */
|
||||||
|
curfont->next = usedfont;
|
||||||
|
} else {
|
||||||
|
xfont_free(usedfont);
|
||||||
|
usedfont = drw->fonts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (d)
|
||||||
|
XftDrawDestroy(d);
|
||||||
|
|
||||||
|
return x + (render ? w : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drw_arrow(Drw *drw, int x, int y, unsigned int w, unsigned int h, int direction, int slash)
|
||||||
|
{
|
||||||
|
if (!drw || !drw->scheme)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* direction=1 draws right arrow */
|
||||||
|
x = direction ? x : x + w;
|
||||||
|
w = direction ? w : -w;
|
||||||
|
/* slash=1 draws slash instead of arrow */
|
||||||
|
unsigned int hh = slash ? (direction ? 0 : h) : h/2;
|
||||||
|
|
||||||
|
XPoint points[] = {
|
||||||
|
{x , y },
|
||||||
|
{x + w, y + hh },
|
||||||
|
{x , y + h },
|
||||||
|
};
|
||||||
|
|
||||||
|
XPoint bg[] = {
|
||||||
|
{x , y },
|
||||||
|
{x + w, y },
|
||||||
|
{x + w, y + h},
|
||||||
|
{x , y + h},
|
||||||
|
};
|
||||||
|
|
||||||
|
XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel);
|
||||||
|
XFillPolygon(drw->dpy, drw->drawable, drw->gc, bg, 4, Convex, CoordModeOrigin);
|
||||||
|
XSetForeground(drw->dpy, drw->gc, drw->scheme[ColFg].pixel);
|
||||||
|
XFillPolygon(drw->dpy, drw->drawable, drw->gc, points, 3, Nonconvex, CoordModeOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
|
||||||
|
{
|
||||||
|
if (!drw)
|
||||||
|
return;
|
||||||
|
|
||||||
|
XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
|
||||||
|
XSync(drw->dpy, False);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
drw_fontset_getwidth(Drw *drw, const char *text, Bool markup)
|
||||||
|
{
|
||||||
|
if (!drw || !drw->fonts || !text)
|
||||||
|
return 0;
|
||||||
|
return drw_text(drw, 0, 0, 0, 0, 0, text, 0, markup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
|
||||||
|
{
|
||||||
|
XGlyphInfo ext;
|
||||||
|
|
||||||
|
if (!font || !text)
|
||||||
|
return;
|
||||||
|
|
||||||
|
XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext);
|
||||||
|
if (w)
|
||||||
|
*w = ext.xOff;
|
||||||
|
if (h)
|
||||||
|
*h = font->h;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cur *
|
||||||
|
drw_cur_create(Drw *drw, int shape)
|
||||||
|
{
|
||||||
|
Cur *cur;
|
||||||
|
|
||||||
|
if (!drw || !(cur = ecalloc(1, sizeof(Cur))))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
cur->cursor = XCreateFontCursor(drw->dpy, shape);
|
||||||
|
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drw_cur_free(Drw *drw, Cur *cursor)
|
||||||
|
{
|
||||||
|
if (!cursor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
XFreeCursor(drw->dpy, cursor->cursor);
|
||||||
|
free(cursor);
|
||||||
|
}
|
||||||
|
|
74
drw.h
Normal file
74
drw.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Cursor cursor;
|
||||||
|
} Cur;
|
||||||
|
|
||||||
|
typedef struct Fnt {
|
||||||
|
Display *dpy;
|
||||||
|
unsigned int h;
|
||||||
|
XftFont *xfont;
|
||||||
|
FcPattern *pattern;
|
||||||
|
struct Fnt *next;
|
||||||
|
} Fnt;
|
||||||
|
|
||||||
|
enum { ColFg, ColBg, ColBorder, ColFloat, ColCount }; /* Clr scheme index */
|
||||||
|
typedef XftColor Clr;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int w, h;
|
||||||
|
Display *dpy;
|
||||||
|
int screen;
|
||||||
|
Window root;
|
||||||
|
Visual *visual;
|
||||||
|
unsigned int depth;
|
||||||
|
Colormap cmap;
|
||||||
|
Drawable drawable;
|
||||||
|
GC gc;
|
||||||
|
Clr *scheme;
|
||||||
|
Fnt *fonts;
|
||||||
|
} Drw;
|
||||||
|
|
||||||
|
/* Drawable abstraction */
|
||||||
|
Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap);
|
||||||
|
void drw_resize(Drw *drw, unsigned int w, unsigned int h);
|
||||||
|
void drw_free(Drw *drw);
|
||||||
|
|
||||||
|
/* Fnt abstraction */
|
||||||
|
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
|
||||||
|
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
|
||||||
|
void drw_fontset_free(Fnt* set);
|
||||||
|
unsigned int drw_fontset_getwidth(Drw *drw, const char *text, Bool markup);
|
||||||
|
|
||||||
|
/* Colorscheme abstraction */
|
||||||
|
void drw_clr_create(
|
||||||
|
Drw *drw,
|
||||||
|
Clr *dest,
|
||||||
|
const char *clrname
|
||||||
|
, unsigned int alpha
|
||||||
|
);
|
||||||
|
Clr *drw_scm_create(
|
||||||
|
Drw *drw,
|
||||||
|
char *clrnames[],
|
||||||
|
const unsigned int alphas[],
|
||||||
|
size_t clrcount
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Cursor abstraction */
|
||||||
|
Cur *drw_cur_create(Drw *drw, int shape);
|
||||||
|
void drw_cur_free(Drw *drw, Cur *cursor);
|
||||||
|
|
||||||
|
/* Drawing context manipulation */
|
||||||
|
void drw_setfontset(Drw *drw, Fnt *set);
|
||||||
|
void drw_setscheme(Drw *drw, Clr *scm);
|
||||||
|
void drw_settrans(Drw *drw, Clr *psc, Clr *nsc);
|
||||||
|
|
||||||
|
/* Drawing functions */
|
||||||
|
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
|
||||||
|
int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup);
|
||||||
|
void drw_arrow(Drw *drw, int x, int y, unsigned int w, unsigned int h, int direction, int slash);
|
||||||
|
|
||||||
|
/* Map functions */
|
||||||
|
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
|
||||||
|
|
BIN
drw.o
Normal file
BIN
drw.o
Normal file
Binary file not shown.
BIN
dwm
Executable file
BIN
dwm
Executable file
Binary file not shown.
176
dwm.1
Normal file
176
dwm.1
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
.TH DWM 1 dwm\-VERSION
|
||||||
|
.SH NAME
|
||||||
|
dwm \- dynamic window manager
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B dwm
|
||||||
|
.RB [ \-v ]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
dwm is a dynamic window manager for X. It manages windows in tiled, monocle
|
||||||
|
and floating layouts. Either layout can be applied dynamically, optimising the
|
||||||
|
environment for the application in use and the task performed.
|
||||||
|
.P
|
||||||
|
In tiled layouts windows are managed in a master and stacking area. The master
|
||||||
|
area on the left contains one window by default, and the stacking area on the
|
||||||
|
right contains all other windows. The number of master area windows can be
|
||||||
|
adjusted from zero to an arbitrary number. In monocle layout all windows are
|
||||||
|
maximised to the screen size. In floating layout windows can be resized and
|
||||||
|
moved freely. Dialog windows are always managed floating, regardless of the
|
||||||
|
layout applied.
|
||||||
|
.P
|
||||||
|
Windows are grouped by tags. Each window can be tagged with one or multiple
|
||||||
|
tags. Selecting certain tags displays all windows with these tags.
|
||||||
|
.P
|
||||||
|
Each screen contains a small status bar which displays all available tags, the
|
||||||
|
layout, the title of the focused window, and the text read from the root window
|
||||||
|
name property, if the screen is focused. A floating window is indicated with an
|
||||||
|
empty square and a maximised floating window is indicated with a filled square
|
||||||
|
before the windows title. The selected tags are indicated with a different
|
||||||
|
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
|
||||||
|
dwm draws a small border around windows to indicate the focus state.
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.B \-v
|
||||||
|
prints version information to stderr, then exits.
|
||||||
|
.SH USAGE
|
||||||
|
.SS Status bar
|
||||||
|
.TP
|
||||||
|
.B X root window name
|
||||||
|
is read and displayed in the status text area. It can be set with the
|
||||||
|
.BR xsetroot (1)
|
||||||
|
command.
|
||||||
|
.TP
|
||||||
|
.B Button1
|
||||||
|
click on a tag label to display all windows with that tag, click on the layout
|
||||||
|
label toggles between tiled and floating layout.
|
||||||
|
.TP
|
||||||
|
.B Button3
|
||||||
|
click on a tag label adds/removes all windows with that tag to/from the view.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-Button1
|
||||||
|
click on a tag label applies that tag to the focused window.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-Button3
|
||||||
|
click on a tag label adds/removes that tag to/from the focused window.
|
||||||
|
.SS Keyboard commands
|
||||||
|
.TP
|
||||||
|
.B Mod1\-Shift\-Return
|
||||||
|
Start
|
||||||
|
.BR st(1).
|
||||||
|
.TP
|
||||||
|
.B Mod1\-p
|
||||||
|
Spawn
|
||||||
|
.BR dmenu(1)
|
||||||
|
for launching other programs.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-,
|
||||||
|
Focus previous screen, if any.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-.
|
||||||
|
Focus next screen, if any.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-Shift\-,
|
||||||
|
Send focused window to previous screen, if any.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-Shift\-.
|
||||||
|
Send focused window to next screen, if any.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-b
|
||||||
|
Toggles bar on and off.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-t
|
||||||
|
Sets tiled layout.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-f
|
||||||
|
Sets floating layout.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-m
|
||||||
|
Sets monocle layout.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-space
|
||||||
|
Toggles between current and previous layout.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-j
|
||||||
|
Focus next window.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-k
|
||||||
|
Focus previous window.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-i
|
||||||
|
Increase number of windows in master area.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-d
|
||||||
|
Decrease number of windows in master area.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-l
|
||||||
|
Increase master area size.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-h
|
||||||
|
Decrease master area size.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-Return
|
||||||
|
Zooms/cycles focused window to/from master area (tiled layouts only).
|
||||||
|
.TP
|
||||||
|
.B Mod1\-Shift\-c
|
||||||
|
Close focused window.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-Shift\-space
|
||||||
|
Toggle focused window between tiled and floating state.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-Tab
|
||||||
|
Toggles to the previously selected tags.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-Shift\-[1..n]
|
||||||
|
Apply nth tag to focused window.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-Shift\-0
|
||||||
|
Apply all tags to focused window.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-Control\-Shift\-[1..n]
|
||||||
|
Add/remove nth tag to/from focused window.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-[1..n]
|
||||||
|
View all windows with nth tag.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-0
|
||||||
|
View all windows with any tag.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-Control\-[1..n]
|
||||||
|
Add/remove all windows with nth tag to/from the view.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-Shift\-q
|
||||||
|
Quit dwm.
|
||||||
|
.SS Mouse commands
|
||||||
|
.TP
|
||||||
|
.B Mod1\-Button1
|
||||||
|
Move focused window while dragging. Tiled windows will be toggled to the floating state.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-Button2
|
||||||
|
Toggles focused window between floating and tiled state.
|
||||||
|
.TP
|
||||||
|
.B Mod1\-Button3
|
||||||
|
Resize focused window while dragging. Tiled windows will be toggled to the floating state.
|
||||||
|
.SH CUSTOMIZATION
|
||||||
|
dwm is customized by creating a custom config.h and (re)compiling the source
|
||||||
|
code. This keeps it fast, secure and simple.
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR dmenu (1),
|
||||||
|
.BR st (1)
|
||||||
|
.SH ISSUES
|
||||||
|
Java applications which use the XToolkit/XAWT backend may draw grey windows
|
||||||
|
only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early
|
||||||
|
JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds
|
||||||
|
are using JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or setting the
|
||||||
|
environment variable
|
||||||
|
.BR AWT_TOOLKIT=MToolkit
|
||||||
|
(to use the older Motif backend instead) or running
|
||||||
|
.B xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D
|
||||||
|
or
|
||||||
|
.B wmname LG3D
|
||||||
|
(to pretend that a non-reparenting window manager is running that the
|
||||||
|
XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable
|
||||||
|
.BR _JAVA_AWT_WM_NONREPARENTING=1 .
|
||||||
|
.SH BUGS
|
||||||
|
Send all bug reports with a patch to hackers@suckless.org.
|
BIN
dwm.o
Normal file
BIN
dwm.o
Normal file
Binary file not shown.
BIN
dwm.png
Normal file
BIN
dwm.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 373 B |
84
patch/autostart.c
Normal file
84
patch/autostart.c
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
void
|
||||||
|
runautostart(void)
|
||||||
|
{
|
||||||
|
char *pathpfx;
|
||||||
|
char *path;
|
||||||
|
char *xdgdatahome;
|
||||||
|
char *home;
|
||||||
|
|
||||||
|
if ((home = getenv("HOME")) == NULL)
|
||||||
|
/* this is almost impossible */
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* if $XDG_DATA_HOME is defined, use $XDG_DATA_HOME/dwm,
|
||||||
|
* otherwise use ~/.local/share/dwm as autostart script directory
|
||||||
|
*/
|
||||||
|
if ((xdgdatahome = getenv("XDG_DATA_HOME")) != NULL) {
|
||||||
|
/* space for path segments, separators and nul */
|
||||||
|
if ((pathpfx = malloc(strlen(xdgdatahome) + strlen(dwmdir) + 2)) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sprintf(pathpfx, "%s/%s", xdgdatahome, dwmdir) <= 0) {
|
||||||
|
free(pathpfx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* space for path segments, separators and nul */
|
||||||
|
if ((pathpfx = malloc(strlen(home) + strlen(localshare) + strlen(dwmdir) + 3)) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sprintf(pathpfx, "%s/%s/%s", home, localshare, dwmdir) < 0) {
|
||||||
|
free(pathpfx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if the autostart script directory exists */
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
if (! (stat(pathpfx, &sb) == 0 && S_ISDIR(sb.st_mode))) {
|
||||||
|
/* the XDG conformant path does not exist or are not directories
|
||||||
|
* so we try ~/.dwm instead
|
||||||
|
*/
|
||||||
|
if (realloc(pathpfx, strlen(home) + strlen(dwmdir) + 3) == NULL) {
|
||||||
|
free(pathpfx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sprintf(pathpfx, "%s/.%s", home, dwmdir) <= 0) {
|
||||||
|
free(pathpfx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try the blocking script first */
|
||||||
|
if ((path = malloc(strlen(pathpfx) + strlen(autostartblocksh) + 2)) == NULL) {
|
||||||
|
free(pathpfx);
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
if (sprintf(path, "%s/%s", pathpfx, autostartblocksh) <= 0) {
|
||||||
|
free(path);
|
||||||
|
free(pathpfx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (access(path, X_OK) == 0)
|
||||||
|
system(path);
|
||||||
|
|
||||||
|
/* now the non-blocking script */
|
||||||
|
if ((path = realloc(path, strlen(pathpfx) + strlen(autostartsh) + 4)) == NULL) {
|
||||||
|
free(pathpfx);
|
||||||
|
free(path);
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
if (sprintf(path, "%s/%s", pathpfx, autostartsh) <= 0) {
|
||||||
|
free(path);
|
||||||
|
free(pathpfx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (access(path, X_OK) == 0) {
|
||||||
|
system(strcat(path, " &"));
|
||||||
|
free(pathpfx);
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2
patch/autostart.h
Normal file
2
patch/autostart.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
static void runautostart(void);
|
||||||
|
|
43
patch/bar_alpha.c
Normal file
43
patch/bar_alpha.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
|
||||||
|
static int useargb = 0;
|
||||||
|
static Visual *visual;
|
||||||
|
static int depth;
|
||||||
|
static Colormap cmap;
|
||||||
|
|
||||||
|
void
|
||||||
|
xinitvisual()
|
||||||
|
{
|
||||||
|
XVisualInfo *infos;
|
||||||
|
XRenderPictFormat *fmt;
|
||||||
|
int nitems;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
XVisualInfo tpl = {
|
||||||
|
.screen = screen,
|
||||||
|
.depth = 32,
|
||||||
|
.class = TrueColor
|
||||||
|
};
|
||||||
|
long masks = VisualScreenMask | VisualDepthMask | VisualClassMask;
|
||||||
|
|
||||||
|
infos = XGetVisualInfo(dpy, masks, &tpl, &nitems);
|
||||||
|
visual = NULL;
|
||||||
|
for (i = 0; i < nitems; i ++) {
|
||||||
|
fmt = XRenderFindVisualFormat(dpy, infos[i].visual);
|
||||||
|
if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) {
|
||||||
|
visual = infos[i].visual;
|
||||||
|
depth = infos[i].depth;
|
||||||
|
cmap = XCreateColormap(dpy, root, visual, AllocNone);
|
||||||
|
useargb = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XFree(infos);
|
||||||
|
|
||||||
|
if (!visual) {
|
||||||
|
visual = DefaultVisual(dpy, screen);
|
||||||
|
depth = DefaultDepth(dpy, screen);
|
||||||
|
cmap = DefaultColormap(dpy, screen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
4
patch/bar_alpha.h
Normal file
4
patch/bar_alpha.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#define OPAQUE 0xffU
|
||||||
|
|
||||||
|
static void xinitvisual();
|
||||||
|
|
41
patch/bar_dwmblocks.c
Normal file
41
patch/bar_dwmblocks.c
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
static int statussig;
|
||||||
|
pid_t statuspid = -1;
|
||||||
|
|
||||||
|
pid_t
|
||||||
|
getstatusbarpid()
|
||||||
|
{
|
||||||
|
char buf[32], *str = buf, *c;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if (statuspid > 0) {
|
||||||
|
snprintf(buf, sizeof(buf), "/proc/%u/cmdline", statuspid);
|
||||||
|
if ((fp = fopen(buf, "r"))) {
|
||||||
|
fgets(buf, sizeof(buf), fp);
|
||||||
|
while ((c = strchr(str, '/')))
|
||||||
|
str = c + 1;
|
||||||
|
fclose(fp);
|
||||||
|
if (!strcmp(str, STATUSBAR))
|
||||||
|
return statuspid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!(fp = popen("pgrep -o "STATUSBAR, "r")))
|
||||||
|
return -1;
|
||||||
|
fgets(buf, sizeof(buf), fp);
|
||||||
|
pclose(fp);
|
||||||
|
return strtol(buf, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sigstatusbar(const Arg *arg)
|
||||||
|
{
|
||||||
|
union sigval sv;
|
||||||
|
|
||||||
|
if (!statussig)
|
||||||
|
return;
|
||||||
|
if ((statuspid = getstatusbarpid()) <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sv.sival_int = arg->i;
|
||||||
|
sigqueue(statuspid, SIGRTMIN+statussig, sv);
|
||||||
|
}
|
||||||
|
|
3
patch/bar_dwmblocks.h
Normal file
3
patch/bar_dwmblocks.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
static int getstatusbarpid();
|
||||||
|
static void sigstatusbar(const Arg *arg);
|
||||||
|
|
53
patch/bar_ewmhtags.c
Normal file
53
patch/bar_ewmhtags.c
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
void
|
||||||
|
setcurrentdesktop(void)
|
||||||
|
{
|
||||||
|
long data[] = { 0 };
|
||||||
|
XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
setdesktopnames(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
XTextProperty text;
|
||||||
|
char *tags[NUMTAGS];
|
||||||
|
for (i = 0; i < NUMTAGS; i++)
|
||||||
|
tags[i] = tagicon(selmon, i);
|
||||||
|
Xutf8TextListToTextProperty(dpy, tags, NUMTAGS, XUTF8StringStyle, &text);
|
||||||
|
XSetTextProperty(dpy, root, &text, netatom[NetDesktopNames]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
setfloatinghint(Client *c)
|
||||||
|
{
|
||||||
|
Atom target = XInternAtom(dpy, "_IS_FLOATING", 0);
|
||||||
|
unsigned int floating[1] = {c->isfloating};
|
||||||
|
XChangeProperty(dpy, c->win, target, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)floating, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
setnumdesktops(void)
|
||||||
|
{
|
||||||
|
long data[] = { NUMTAGS };
|
||||||
|
XChangeProperty(dpy, root, netatom[NetNumberOfDesktops], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
setviewport(void)
|
||||||
|
{
|
||||||
|
long data[] = { 0, 0 };
|
||||||
|
XChangeProperty(dpy, root, netatom[NetDesktopViewport], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
updatecurrentdesktop(void)
|
||||||
|
{
|
||||||
|
long rawdata[] = { selmon->tagset[selmon->seltags] };
|
||||||
|
int i = 0;
|
||||||
|
while (*rawdata >> (i + 1)) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
long data[] = { i };
|
||||||
|
XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
|
||||||
|
}
|
||||||
|
|
7
patch/bar_ewmhtags.h
Normal file
7
patch/bar_ewmhtags.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
static void setcurrentdesktop(void);
|
||||||
|
static void setdesktopnames(void);
|
||||||
|
static void setfloatinghint(Client *c);
|
||||||
|
static void setnumdesktops(void);
|
||||||
|
static void setviewport(void);
|
||||||
|
static void updatecurrentdesktop(void);
|
||||||
|
|
109
patch/bar_indicators.c
Normal file
109
patch/bar_indicators.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/* Indicator properties, you can override these in your config.h if you want. */
|
||||||
|
#ifndef TAGSINDICATOR
|
||||||
|
#define TAGSINDICATOR 1 // 0 = off, 1 = on if >1 client/view tag, 2 = always on
|
||||||
|
#endif
|
||||||
|
#ifndef TAGSPX
|
||||||
|
#define TAGSPX 5 // # pixels for tag grid boxes
|
||||||
|
#endif
|
||||||
|
#ifndef TAGSROWS
|
||||||
|
#define TAGSROWS 3 // # rows in tag grid (9 tags, e.g. 3x3)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
drawindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert, int type)
|
||||||
|
{
|
||||||
|
int i, boxw, boxs, indn = 0;
|
||||||
|
if (!(occ & 1 << tag) || type == INDICATOR_NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
boxs = drw->fonts->h / 9;
|
||||||
|
boxw = drw->fonts->h / 6 + 2;
|
||||||
|
if (filled == -1)
|
||||||
|
filled = m == selmon && m->sel && m->sel->tags & 1 << tag;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
default:
|
||||||
|
case INDICATOR_TOP_LEFT_SQUARE:
|
||||||
|
drw_rect(drw, x + boxs, y + boxs, boxw, boxw, filled, invert);
|
||||||
|
break;
|
||||||
|
case INDICATOR_TOP_LEFT_LARGER_SQUARE:
|
||||||
|
drw_rect(drw, x + boxs + 2, y + boxs+1, boxw+1, boxw+1, filled, invert);
|
||||||
|
break;
|
||||||
|
case INDICATOR_TOP_BAR:
|
||||||
|
drw_rect(drw, x + boxw, y, w - ( 2 * boxw + 1), boxw/2, filled, invert);
|
||||||
|
break;
|
||||||
|
case INDICATOR_TOP_BAR_SLIM:
|
||||||
|
drw_rect(drw, x + boxw, y, w - ( 2 * boxw + 1), 1, 0, invert);
|
||||||
|
break;
|
||||||
|
case INDICATOR_BOTTOM_BAR:
|
||||||
|
drw_rect(drw, x + boxw, y + h - boxw/2, w - ( 2 * boxw + 1), boxw/2, filled, invert);
|
||||||
|
break;
|
||||||
|
case INDICATOR_BOTTOM_BAR_SLIM:
|
||||||
|
drw_rect(drw, x + boxw, y + h - 1, w - ( 2 * boxw + 1), 1, 0, invert);
|
||||||
|
break;
|
||||||
|
case INDICATOR_BOX:
|
||||||
|
drw_rect(drw, x + boxw, y, w - 2 * boxw, h, 0, invert);
|
||||||
|
break;
|
||||||
|
case INDICATOR_BOX_WIDER:
|
||||||
|
drw_rect(drw, x + boxw/2, y, w - boxw, h, 0, invert);
|
||||||
|
break;
|
||||||
|
case INDICATOR_BOX_FULL:
|
||||||
|
drw_rect(drw, x, y, w - 2, h, 0, invert);
|
||||||
|
break;
|
||||||
|
case INDICATOR_CLIENT_DOTS:
|
||||||
|
for (c = m->clients; c; c = c->next) {
|
||||||
|
if (c->tags & (1 << tag)) {
|
||||||
|
drw_rect(drw, x, 1 + (indn * 2), m->sel == c ? 6 : 1, 1, 1, invert);
|
||||||
|
indn++;
|
||||||
|
}
|
||||||
|
if (h <= 1 + (indn * 2)) {
|
||||||
|
indn = 0;
|
||||||
|
x += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case INDICATOR_RIGHT_TAGS:
|
||||||
|
if (!c)
|
||||||
|
break;
|
||||||
|
for (i = 0; i < NUMTAGS; i++) {
|
||||||
|
drw_rect(drw,
|
||||||
|
( x + w - 2 - ((NUMTAGS / TAGSROWS) * TAGSPX)
|
||||||
|
- (i % (NUMTAGS/TAGSROWS)) + ((i % (NUMTAGS / TAGSROWS)) * TAGSPX)
|
||||||
|
),
|
||||||
|
( y + 2 + ((i / (NUMTAGS/TAGSROWS)) * TAGSPX)
|
||||||
|
- ((i / (NUMTAGS/TAGSROWS)))
|
||||||
|
),
|
||||||
|
TAGSPX, TAGSPX, (c->tags >> i) & 1, 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case INDICATOR_PLUS_AND_LARGER_SQUARE:
|
||||||
|
boxs += 2;
|
||||||
|
boxw += 2;
|
||||||
|
/* falls through */
|
||||||
|
case INDICATOR_PLUS_AND_SQUARE:
|
||||||
|
drw_rect(drw, x + boxs, y + boxs, boxw % 2 ? boxw : boxw + 1, boxw % 2 ? boxw : boxw + 1, filled, invert);
|
||||||
|
/* falls through */
|
||||||
|
case INDICATOR_PLUS:
|
||||||
|
if (!(boxw % 2))
|
||||||
|
boxw += 1;
|
||||||
|
drw_rect(drw, x + boxs + boxw / 2, y + boxs, 1, boxw, filled, invert); // |
|
||||||
|
drw_rect(drw, x + boxs, y + boxs + boxw / 2, boxw + 1, 1, filled, invert); // ‒
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drawstateindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert)
|
||||||
|
{
|
||||||
|
if (c->fakefullscreen && c->isfloating)
|
||||||
|
drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, floatfakefsindicatortype);
|
||||||
|
else if (c->fakefullscreen)
|
||||||
|
drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, fakefsindicatortype);
|
||||||
|
else
|
||||||
|
if (c->isfloating)
|
||||||
|
drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, floatindicatortype);
|
||||||
|
else
|
||||||
|
drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, tiledindicatortype);
|
||||||
|
}
|
||||||
|
|
21
patch/bar_indicators.h
Normal file
21
patch/bar_indicators.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
enum {
|
||||||
|
INDICATOR_NONE,
|
||||||
|
INDICATOR_TOP_LEFT_SQUARE,
|
||||||
|
INDICATOR_TOP_LEFT_LARGER_SQUARE,
|
||||||
|
INDICATOR_TOP_BAR,
|
||||||
|
INDICATOR_TOP_BAR_SLIM,
|
||||||
|
INDICATOR_BOTTOM_BAR,
|
||||||
|
INDICATOR_BOTTOM_BAR_SLIM,
|
||||||
|
INDICATOR_BOX,
|
||||||
|
INDICATOR_BOX_WIDER,
|
||||||
|
INDICATOR_BOX_FULL,
|
||||||
|
INDICATOR_CLIENT_DOTS,
|
||||||
|
INDICATOR_RIGHT_TAGS,
|
||||||
|
INDICATOR_PLUS,
|
||||||
|
INDICATOR_PLUS_AND_SQUARE,
|
||||||
|
INDICATOR_PLUS_AND_LARGER_SQUARE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void drawindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert, int type);
|
||||||
|
static void drawstateindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert);
|
||||||
|
|
18
patch/bar_ltsymbol.c
Normal file
18
patch/bar_ltsymbol.c
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
int
|
||||||
|
width_ltsymbol(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
return TEXTW(bar->mon->ltsymbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
draw_ltsymbol(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
return drw_text(drw, a->x, a->y, a->w, a->h, lrpad / 2, bar->mon->ltsymbol, 0, False);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
click_ltsymbol(Bar *bar, Arg *arg, BarArg *a)
|
||||||
|
{
|
||||||
|
return ClkLtSymbol;
|
||||||
|
}
|
||||||
|
|
4
patch/bar_ltsymbol.h
Normal file
4
patch/bar_ltsymbol.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
static int width_ltsymbol(Bar *bar, BarArg *a);
|
||||||
|
static int draw_ltsymbol(Bar *bar, BarArg *a);
|
||||||
|
static int click_ltsymbol(Bar *bar, Arg *arg, BarArg *a);
|
||||||
|
|
85
patch/bar_powerline_tags.c
Normal file
85
patch/bar_powerline_tags.c
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
int
|
||||||
|
width_pwrl_tags(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
int w, i;
|
||||||
|
int plw = drw->fonts->h / 2 + 1;
|
||||||
|
Client *c;
|
||||||
|
unsigned int occ = 0;
|
||||||
|
for (c = bar->mon->clients; c; c = c->next)
|
||||||
|
occ |= c->tags == 255 ? 0 : c->tags;
|
||||||
|
|
||||||
|
for (w = 0, i = 0; i < NUMTAGS; i++) {
|
||||||
|
if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i))
|
||||||
|
continue;
|
||||||
|
w += TEXTW(tagicon(bar->mon, i)) + plw;
|
||||||
|
}
|
||||||
|
return w + lrpad;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
draw_pwrl_tags(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
int x, w;
|
||||||
|
int invert;
|
||||||
|
int plw = drw->fonts->h / 2 + 1;
|
||||||
|
unsigned int i, occ = 0, urg = 0;
|
||||||
|
char *icon;
|
||||||
|
Client *c;
|
||||||
|
Clr *prevscheme, *nxtscheme;
|
||||||
|
|
||||||
|
for (c = bar->mon->clients; c; c = c->next) {
|
||||||
|
occ |= c->tags == 255 ? 0 : c->tags;
|
||||||
|
if (c->isurgent)
|
||||||
|
urg |= c->tags;
|
||||||
|
}
|
||||||
|
x = a->x;
|
||||||
|
prevscheme = scheme[SchemeNorm];
|
||||||
|
for (i = 0; i < NUMTAGS; i++) {
|
||||||
|
/* do not draw vacant tags */
|
||||||
|
if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
icon = tagicon(bar->mon, i);
|
||||||
|
invert = 0;
|
||||||
|
w = TEXTW(icon);
|
||||||
|
if (urg & 1 << i) {
|
||||||
|
drw_settrans(drw, prevscheme, (nxtscheme = scheme[bar->mon->tagset[bar->mon->seltags] & 1 << i ? SchemeSel : SchemeUrg]));
|
||||||
|
} else {
|
||||||
|
drw_settrans(drw, prevscheme, (nxtscheme = scheme[bar->mon->tagset[bar->mon->seltags] & 1 << i ? SchemeSel : SchemeNorm]));
|
||||||
|
}
|
||||||
|
drw_arrow(drw, x, a->y, plw, a->h, 1, 1);
|
||||||
|
x += plw;
|
||||||
|
drw_setscheme(drw, nxtscheme);
|
||||||
|
drw_text(drw, x, a->y, w, a->h, lrpad / 2, icon, invert, False);
|
||||||
|
drawindicator(bar->mon, NULL, occ, x, a->y, w, a->h, i, -1, invert, tagindicatortype);
|
||||||
|
x += w;
|
||||||
|
prevscheme = nxtscheme;
|
||||||
|
}
|
||||||
|
nxtscheme = scheme[SchemeNorm];
|
||||||
|
|
||||||
|
drw_settrans(drw, prevscheme, nxtscheme);
|
||||||
|
drw_arrow(drw, x, a->y, plw, a->h, 1, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
click_pwrl_tags(Bar *bar, Arg *arg, BarArg *a)
|
||||||
|
{
|
||||||
|
int i = 0, x = lrpad / 2;
|
||||||
|
int plw = drw->fonts->h / 2 + 1;
|
||||||
|
Client *c;
|
||||||
|
unsigned int occ = 0;
|
||||||
|
for (c = bar->mon->clients; c; c = c->next)
|
||||||
|
occ |= c->tags == 255 ? 0 : c->tags;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i))
|
||||||
|
continue;
|
||||||
|
x += TEXTW(tagicon(bar->mon, i)) + plw;
|
||||||
|
} while (a->x >= x && ++i < NUMTAGS);
|
||||||
|
if (i < NUMTAGS) {
|
||||||
|
arg->ui = 1 << i;
|
||||||
|
}
|
||||||
|
return ClkTagBar;
|
||||||
|
}
|
||||||
|
|
4
patch/bar_powerline_tags.h
Normal file
4
patch/bar_powerline_tags.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
static int width_pwrl_tags(Bar *bar, BarArg *a);
|
||||||
|
static int draw_pwrl_tags(Bar *bar, BarArg *a);
|
||||||
|
static int click_pwrl_tags(Bar *bar, Arg *arg, BarArg *a);
|
||||||
|
|
20
patch/bar_status.c
Normal file
20
patch/bar_status.c
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
int
|
||||||
|
width_status(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
return TEXTWM(stext);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
draw_status(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
return drw_text(drw, a->x, a->y, a->w, a->h, lrpad / 2, stext, 0, True);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
click_status(Bar *bar, Arg *arg, BarArg *a)
|
||||||
|
{
|
||||||
|
return ClkStatusText;
|
||||||
|
}
|
||||||
|
|
4
patch/bar_status.h
Normal file
4
patch/bar_status.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
static int width_status(Bar *bar, BarArg *a);
|
||||||
|
static int draw_status(Bar *bar, BarArg *a);
|
||||||
|
static int click_status(Bar *bar, Arg *arg, BarArg *a);
|
||||||
|
|
46
patch/bar_statuscmd.c
Normal file
46
patch/bar_statuscmd.c
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
int
|
||||||
|
click_statuscmd(Bar *bar, Arg *arg, BarArg *a)
|
||||||
|
{
|
||||||
|
return click_statuscmd_text(arg, a->x, rawstext);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
click_statuscmd_text(Arg *arg, int rel_x, char *text)
|
||||||
|
{
|
||||||
|
int i = -1;
|
||||||
|
int x = 0;
|
||||||
|
char ch;
|
||||||
|
statussig = -1;
|
||||||
|
while (text[++i]) {
|
||||||
|
if ((unsigned char)text[i] < ' ') {
|
||||||
|
ch = text[i];
|
||||||
|
text[i] = '\0';
|
||||||
|
x += TEXTWM(text) - lrpad;
|
||||||
|
text[i] = ch;
|
||||||
|
text += i+1;
|
||||||
|
i = -1;
|
||||||
|
if (x >= rel_x && statussig != -1)
|
||||||
|
break;
|
||||||
|
statussig = ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (statussig == -1)
|
||||||
|
statussig = 0;
|
||||||
|
return ClkStatusText;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
copyvalidchars(char *text, char *rawtext)
|
||||||
|
{
|
||||||
|
int i = -1, j = 0;
|
||||||
|
|
||||||
|
while (rawtext[++i]) {
|
||||||
|
if ((unsigned char)rawtext[i] >= ' ') {
|
||||||
|
text[j++] = rawtext[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text[j] = '\0';
|
||||||
|
}
|
||||||
|
|
9
patch/bar_statuscmd.h
Normal file
9
patch/bar_statuscmd.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
static int click_statuscmd(Bar *bar, Arg *arg, BarArg *a);
|
||||||
|
static int click_statuscmd_text(Arg *arg, int rel_x, char *text);
|
||||||
|
static void copyvalidchars(char *text, char *rawtext);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *cmd;
|
||||||
|
int id;
|
||||||
|
} StatusCmd;
|
||||||
|
|
186
patch/bar_systray.c
Normal file
186
patch/bar_systray.c
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
static Systray *systray = NULL;
|
||||||
|
static unsigned long systrayorientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
|
||||||
|
|
||||||
|
int
|
||||||
|
width_systray(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
unsigned int w = 0;
|
||||||
|
Client *i;
|
||||||
|
if (!systray)
|
||||||
|
return 1;
|
||||||
|
if (showsystray)
|
||||||
|
for (i = systray->icons; i; w += i->w + systrayspacing, i = i->next);
|
||||||
|
return w ? w + lrpad - systrayspacing : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
draw_systray(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
if (!showsystray)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
XSetWindowAttributes wa;
|
||||||
|
XWindowChanges wc;
|
||||||
|
Client *i;
|
||||||
|
unsigned int w;
|
||||||
|
|
||||||
|
if (!systray) {
|
||||||
|
/* init systray */
|
||||||
|
if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
|
||||||
|
die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
|
||||||
|
|
||||||
|
wa.override_redirect = True;
|
||||||
|
wa.event_mask = ButtonPressMask|ExposureMask;
|
||||||
|
wa.border_pixel = 0;
|
||||||
|
systray->h = MIN(a->h, drw->fonts->h);
|
||||||
|
wa.background_pixel = 0;
|
||||||
|
wa.colormap = cmap;
|
||||||
|
systray->win = XCreateWindow(dpy, root, bar->bx + a->x + lrpad / 2, bar->by + a->y + (a->h - systray->h) / 2, MAX(a->w + 40, 1), systray->h, 0, depth,
|
||||||
|
InputOutput, visual,
|
||||||
|
CWOverrideRedirect|CWBorderPixel|CWBackPixel|CWColormap|CWEventMask, &wa); // CWBackPixmap
|
||||||
|
|
||||||
|
XSelectInput(dpy, systray->win, SubstructureNotifyMask);
|
||||||
|
XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
|
||||||
|
PropModeReplace, (unsigned char *)&systrayorientation, 1);
|
||||||
|
XChangeProperty(dpy, systray->win, netatom[NetSystemTrayVisual], XA_VISUALID, 32,
|
||||||
|
PropModeReplace, (unsigned char *)&visual->visualid, 1);
|
||||||
|
XChangeProperty(dpy, systray->win, netatom[NetWMWindowType], XA_ATOM, 32,
|
||||||
|
PropModeReplace, (unsigned char *)&netatom[NetWMWindowTypeDock], 1);
|
||||||
|
XMapRaised(dpy, systray->win);
|
||||||
|
XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
|
||||||
|
if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
|
||||||
|
sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
|
||||||
|
XSync(dpy, False);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "dwm: unable to obtain system tray.\n");
|
||||||
|
free(systray);
|
||||||
|
systray = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
systray->bar = bar;
|
||||||
|
|
||||||
|
wc.stack_mode = Above;
|
||||||
|
wc.sibling = bar->win;
|
||||||
|
XConfigureWindow(dpy, systray->win, CWSibling|CWStackMode, &wc);
|
||||||
|
|
||||||
|
drw_setscheme(drw, scheme[SchemeNorm]);
|
||||||
|
for (w = 0, i = systray->icons; i; i = i->next) {
|
||||||
|
wa.background_pixel = 0;
|
||||||
|
XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
|
||||||
|
XMapRaised(dpy, i->win);
|
||||||
|
i->x = w;
|
||||||
|
XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
|
||||||
|
w += i->w;
|
||||||
|
if (i->next)
|
||||||
|
w += systrayspacing;
|
||||||
|
if (i->mon != bar->mon)
|
||||||
|
i->mon = bar->mon;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMoveResizeWindow(dpy, systray->win, bar->bx + a->x + lrpad / 2, (w ? bar->by + a->y + (a->h - systray->h) / 2: -bar->by - a->y), MAX(w, 1), systray->h);
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
click_systray(Bar *bar, Arg *arg, BarArg *a)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
removesystrayicon(Client *i)
|
||||||
|
{
|
||||||
|
Client **ii;
|
||||||
|
|
||||||
|
if (!showsystray || !i)
|
||||||
|
return;
|
||||||
|
for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
|
||||||
|
if (ii)
|
||||||
|
*ii = i->next;
|
||||||
|
free(i);
|
||||||
|
drawbarwin(systray->bar);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
resizerequest(XEvent *e)
|
||||||
|
{
|
||||||
|
XResizeRequestEvent *ev = &e->xresizerequest;
|
||||||
|
Client *i;
|
||||||
|
|
||||||
|
if ((i = wintosystrayicon(ev->window))) {
|
||||||
|
updatesystrayicongeom(i, ev->width, ev->height);
|
||||||
|
drawbarwin(systray->bar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
updatesystrayicongeom(Client *i, int w, int h)
|
||||||
|
{
|
||||||
|
if (!systray)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int icon_height = systray->h;
|
||||||
|
if (i) {
|
||||||
|
i->h = icon_height;
|
||||||
|
if (w == h)
|
||||||
|
i->w = icon_height;
|
||||||
|
else if (h == icon_height)
|
||||||
|
i->w = w;
|
||||||
|
else
|
||||||
|
i->w = (int) ((float)icon_height * ((float)w / (float)h));
|
||||||
|
applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
|
||||||
|
/* force icons into the systray dimensions if they don't want to */
|
||||||
|
if (i->h > icon_height) {
|
||||||
|
if (i->w == i->h)
|
||||||
|
i->w = icon_height;
|
||||||
|
else
|
||||||
|
i->w = (int) ((float)icon_height * ((float)i->w / (float)i->h));
|
||||||
|
i->h = icon_height;
|
||||||
|
}
|
||||||
|
if (i->w > 2 * icon_height)
|
||||||
|
i->w = icon_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
updatesystrayiconstate(Client *i, XPropertyEvent *ev)
|
||||||
|
{
|
||||||
|
long flags;
|
||||||
|
int code = 0;
|
||||||
|
|
||||||
|
if (!showsystray || !systray || !i || ev->atom != xatom[XembedInfo] ||
|
||||||
|
!(flags = getatomprop(i, xatom[XembedInfo])))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (flags & XEMBED_MAPPED && !i->tags) {
|
||||||
|
i->tags = 1;
|
||||||
|
code = XEMBED_WINDOW_ACTIVATE;
|
||||||
|
XMapRaised(dpy, i->win);
|
||||||
|
setclientstate(i, NormalState);
|
||||||
|
}
|
||||||
|
else if (!(flags & XEMBED_MAPPED) && i->tags) {
|
||||||
|
i->tags = 0;
|
||||||
|
code = XEMBED_WINDOW_DEACTIVATE;
|
||||||
|
XUnmapWindow(dpy, i->win);
|
||||||
|
setclientstate(i, WithdrawnState);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
|
||||||
|
systray->win, XEMBED_EMBEDDED_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
Client *
|
||||||
|
wintosystrayicon(Window w)
|
||||||
|
{
|
||||||
|
if (!systray)
|
||||||
|
return NULL;
|
||||||
|
Client *i = NULL;
|
||||||
|
if (!showsystray || !w)
|
||||||
|
return i;
|
||||||
|
for (i = systray->icons; i && i->win != w; i = i->next);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
42
patch/bar_systray.h
Normal file
42
patch/bar_systray.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#define SYSTEM_TRAY_REQUEST_DOCK 0
|
||||||
|
#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0
|
||||||
|
|
||||||
|
/* XEMBED messages */
|
||||||
|
#define XEMBED_EMBEDDED_NOTIFY 0
|
||||||
|
#define XEMBED_WINDOW_ACTIVATE 1
|
||||||
|
#define XEMBED_FOCUS_IN 4
|
||||||
|
#define XEMBED_MODALITY_ON 10
|
||||||
|
|
||||||
|
#define XEMBED_MAPPED (1 << 0)
|
||||||
|
#define XEMBED_WINDOW_ACTIVATE 1
|
||||||
|
#define XEMBED_WINDOW_DEACTIVATE 2
|
||||||
|
|
||||||
|
#define VERSION_MAJOR 0
|
||||||
|
#define VERSION_MINOR 0
|
||||||
|
#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
|
||||||
|
|
||||||
|
/* enums */
|
||||||
|
enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
|
||||||
|
|
||||||
|
typedef struct Systray Systray;
|
||||||
|
struct Systray {
|
||||||
|
Window win;
|
||||||
|
Client *icons;
|
||||||
|
Bar *bar;
|
||||||
|
int h;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* bar integration */
|
||||||
|
static int width_systray(Bar *bar, BarArg *a);
|
||||||
|
static int draw_systray(Bar *bar, BarArg *a);
|
||||||
|
static int click_systray(Bar *bar, Arg *arg, BarArg *a);
|
||||||
|
|
||||||
|
/* function declarations */
|
||||||
|
static Atom getatomprop(Client *c, Atom prop);
|
||||||
|
static void removesystrayicon(Client *i);
|
||||||
|
static void resizerequest(XEvent *e);
|
||||||
|
static void updatesystrayicongeom(Client *i, int w, int h);
|
||||||
|
static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
|
||||||
|
static Client *wintosystrayicon(Window w);
|
||||||
|
|
||||||
|
|
223
patch/bar_tabgroups.c
Normal file
223
patch/bar_tabgroups.c
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
/* Bartabgroups properties, you can override these in your config.h if you want. */
|
||||||
|
#ifndef BARTAB_BORDERS
|
||||||
|
#define BARTAB_BORDERS 1 // 0 = off, 1 = on
|
||||||
|
#endif
|
||||||
|
#ifndef BARTAB_SHOWFLOATING
|
||||||
|
#define BARTAB_SHOWFLOATING 0 // whether to show titles for floating windows, hidden clients are always shown
|
||||||
|
#endif
|
||||||
|
#ifndef BARTAB_STACKWEIGHT
|
||||||
|
#define BARTAB_STACKWEIGHT 1 // stack weight compared to hidden and floating window titles
|
||||||
|
#endif
|
||||||
|
#ifndef BARTAB_HIDDENWEIGHT
|
||||||
|
#define BARTAB_HIDDENWEIGHT 1 // hidden window title weight
|
||||||
|
#endif
|
||||||
|
#ifndef BARTAB_FLOATWEIGHT
|
||||||
|
#define BARTAB_FLOATWEIGHT 1 // floating window title weight, set to 0 to not show floating windows
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
width_bartabgroups(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
return a->w;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
draw_bartabgroups(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
drw_rect(drw, a->x, a->y, a->w, a->h, 1, 1);
|
||||||
|
return bartabcalculate(bar->mon, a->x, a->w, -1, bartabdraw, NULL, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
click_bartabgroups(Bar *bar, Arg *arg, BarArg *a)
|
||||||
|
{
|
||||||
|
bartabcalculate(bar->mon, 0, a->w, a->x, bartabclick, arg, a);
|
||||||
|
return ClkWinTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg *arg, BarArg *barg)
|
||||||
|
{
|
||||||
|
if (!c)
|
||||||
|
return;
|
||||||
|
int i, nclienttags = 0, nviewtags = 0, pad = lrpad / 2;
|
||||||
|
drw_setscheme(drw, scheme[
|
||||||
|
m->sel == c
|
||||||
|
#ifdef HIDDEN
|
||||||
|
&& HIDDEN(c)
|
||||||
|
? SchemeHidSel
|
||||||
|
: HIDDEN(c)
|
||||||
|
? SchemeHidNorm
|
||||||
|
: m->sel == c
|
||||||
|
#endif
|
||||||
|
? SchemeSel
|
||||||
|
: groupactive
|
||||||
|
? SchemeTitleSel
|
||||||
|
: SchemeTitleNorm
|
||||||
|
]);
|
||||||
|
if (w <= TEXTW("A") - lrpad + pad) // reduce text padding if wintitle is too small
|
||||||
|
pad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2);
|
||||||
|
else if (TEXTW(c->name) < w)
|
||||||
|
pad = (w - TEXTW(c->name) + lrpad) / 2;
|
||||||
|
|
||||||
|
drw_text(drw, x, barg->y, w, barg->h, pad, c->name, 0, False);
|
||||||
|
|
||||||
|
drawstateindicator(m, c, 1, x, barg->y, w, barg->h, 0, 0, c->isfixed);
|
||||||
|
|
||||||
|
if (BARTAB_BORDERS) {
|
||||||
|
XSetForeground(drw->dpy, drw->gc, scheme[SchemeSel][ColBorder].pixel);
|
||||||
|
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, barg->y, 1, barg->h);
|
||||||
|
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w - (x + w >= barg->w ? 1 : 0), barg->y, 1, barg->h);
|
||||||
|
}
|
||||||
|
/* Optional tags icons */
|
||||||
|
for (i = 0; i < NUMTAGS; i++) {
|
||||||
|
if ((m->tagset[m->seltags] >> i) & 1)
|
||||||
|
nviewtags++;
|
||||||
|
if ((c->tags >> i) & 1)
|
||||||
|
nclienttags++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TAGSINDICATOR == 2 || nclienttags > 1 || nviewtags > 1)
|
||||||
|
drawindicator(m, c, 1, x, barg->y, w, barg->h, 0, 0, 0, INDICATOR_RIGHT_TAGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef HIDDEN
|
||||||
|
#define HIDDEN(C) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
bartabclick(Monitor *m, Client *c, int passx, int x, int w, int unused, Arg *arg, BarArg *barg)
|
||||||
|
{
|
||||||
|
if (passx >= x && passx <= x + w)
|
||||||
|
arg->v = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
bartabcalculate(
|
||||||
|
Monitor *m, int offx, int tabw, int passx,
|
||||||
|
void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg),
|
||||||
|
Arg *arg, BarArg *barg
|
||||||
|
) {
|
||||||
|
Client *c;
|
||||||
|
int
|
||||||
|
i, clientsnmaster = 0, clientsnstack = 0, clientsnfloating = 0, clientsnhidden = 0,
|
||||||
|
masteractive = 0, fulllayout = 0,
|
||||||
|
x = offx, w, r, num = 0, den, tgactive;
|
||||||
|
|
||||||
|
for (i = 0; i < LENGTH(bartabmonfns); i++)
|
||||||
|
if (m ->lt[m->sellt]->arrange == bartabmonfns[i]) {
|
||||||
|
fulllayout = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0, c = m->clients; c; c = c->next) {
|
||||||
|
if (!ISVISIBLE(c))
|
||||||
|
continue;
|
||||||
|
if (HIDDEN(c)) {
|
||||||
|
clientsnhidden++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c->isfloating) {
|
||||||
|
clientsnfloating++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (m->sel == c)
|
||||||
|
masteractive = i < m->nmaster;
|
||||||
|
if (i < m->nmaster)
|
||||||
|
clientsnmaster++;
|
||||||
|
else
|
||||||
|
clientsnstack++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clientsnmaster + clientsnstack + clientsnfloating + clientsnhidden == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
tgactive = 1;
|
||||||
|
num = tabw;
|
||||||
|
/* floating mode */
|
||||||
|
if ((fulllayout && BARTAB_FLOATWEIGHT) || clientsnmaster + clientsnstack == 0 || !m->lt[m->sellt]->arrange) {
|
||||||
|
den = clientsnmaster + clientsnstack + clientsnfloating + clientsnhidden;
|
||||||
|
r = num % den;
|
||||||
|
w = num / den;
|
||||||
|
for (c = m->clients, i = 0; c; c = c->next) {
|
||||||
|
if (!ISVISIBLE(c))
|
||||||
|
continue;
|
||||||
|
tabfn(m, c, passx, x, w + (i < r ? 1 : 0), tgactive, arg, barg);
|
||||||
|
x += w + (i < r ? 1 : 0);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
/* no master and stack mode, e.g. monocole, grid layouts, fibonacci */
|
||||||
|
} else if (fulllayout) {
|
||||||
|
den = clientsnmaster + clientsnstack + clientsnhidden;
|
||||||
|
r = num % den;
|
||||||
|
w = num / den;
|
||||||
|
for (c = m->clients, i = 0; c; c = c->next) {
|
||||||
|
if (!ISVISIBLE(c) || (c->isfloating && !HIDDEN(c)))
|
||||||
|
continue;
|
||||||
|
tabfn(m, c, passx, x, w + (i < r ? 1 : 0), tgactive, arg, barg);
|
||||||
|
x += w + (i < r ? 1 : 0);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
/* tiled mode */
|
||||||
|
} else {
|
||||||
|
den = clientsnmaster;
|
||||||
|
c = m->clients;
|
||||||
|
i = 0;
|
||||||
|
if (den) {
|
||||||
|
if (clientsnstack + clientsnfloating * BARTAB_FLOATWEIGHT + clientsnhidden) {
|
||||||
|
tgactive = masteractive;
|
||||||
|
num = tabw * m->mfact;
|
||||||
|
}
|
||||||
|
r = num % den;
|
||||||
|
w = num / den;
|
||||||
|
for (; c && i < m->nmaster; c = c->next) { // tiled master
|
||||||
|
if (!ISVISIBLE(c) || c->isfloating || HIDDEN(c))
|
||||||
|
continue;
|
||||||
|
tabfn(m, c, passx, x, w + (i < r ? 1 : 0), tgactive, arg, barg);
|
||||||
|
x += w + (i < r ? 1 : 0);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
tgactive = !tgactive;
|
||||||
|
num = tabw - num;
|
||||||
|
}
|
||||||
|
|
||||||
|
den = clientsnstack * BARTAB_STACKWEIGHT + clientsnfloating * BARTAB_FLOATWEIGHT + clientsnhidden * BARTAB_HIDDENWEIGHT;
|
||||||
|
if (!den)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
r = num % den;
|
||||||
|
w = num / den;
|
||||||
|
#if BARTAB_STACKWEIGHT
|
||||||
|
for (; c; c = c->next) { // tiled stack
|
||||||
|
if (!ISVISIBLE(c) || HIDDEN(c) || c->isfloating)
|
||||||
|
continue;
|
||||||
|
tabfn(m, c, passx, x, w * BARTAB_STACKWEIGHT + (i - m->nmaster < r ? 1 : 0), tgactive, arg, barg);
|
||||||
|
x += w * BARTAB_STACKWEIGHT + (i - m->nmaster < r ? 1 : 0);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
#endif // BARTAB_STACKWEIGHT
|
||||||
|
|
||||||
|
#if BARTAB_HIDDENWEIGHT
|
||||||
|
for (c = m->clients; c; c = c->next) { // hidden windows
|
||||||
|
if (!ISVISIBLE(c) || !HIDDEN(c))
|
||||||
|
continue;
|
||||||
|
tabfn(m, c, passx, x, w * BARTAB_HIDDENWEIGHT + (i - m->nmaster < r ? 1 : 0), tgactive, arg, barg);
|
||||||
|
x += w * BARTAB_HIDDENWEIGHT + (i - m->nmaster < r ? 1 : 0);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
#endif // BARTAB_HIDDENWEIGHT
|
||||||
|
|
||||||
|
#if BARTAB_FLOATWEIGHT
|
||||||
|
for (c = m->clients; c; c = c->next) { // floating windows
|
||||||
|
if (!ISVISIBLE(c) || HIDDEN(c) || !c->isfloating)
|
||||||
|
continue;
|
||||||
|
tabfn(m, c, passx, x, w * BARTAB_FLOATWEIGHT + (i - m->nmaster < r ? 1 : 0), tgactive, arg, barg);
|
||||||
|
x += w * BARTAB_FLOATWEIGHT + (i - m->nmaster < r ? 1 : 0);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
#endif // BARTAB_FLOATWEIGHT
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
8
patch/bar_tabgroups.h
Normal file
8
patch/bar_tabgroups.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
static int width_bartabgroups(Bar *bar, BarArg *a);
|
||||||
|
static int draw_bartabgroups(Bar *bar, BarArg *a);
|
||||||
|
static int click_bartabgroups(Bar *bar, Arg *arg, BarArg *a);
|
||||||
|
|
||||||
|
static void bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg *arg, BarArg *barg);
|
||||||
|
static void bartabclick(Monitor *m, Client *c, int passx, int x, int w, int unused, Arg *arg, BarArg *barg);
|
||||||
|
static int bartabcalculate(Monitor *m, int offx, int w, int passx, void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), Arg *arg, BarArg *barg);
|
||||||
|
|
9
patch/bar_tagicons.c
Normal file
9
patch/bar_tagicons.c
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
char *
|
||||||
|
tagicon(Monitor *m, int tag)
|
||||||
|
{
|
||||||
|
int tagindex = tag + NUMTAGS * m->index;
|
||||||
|
if (tagindex >= LENGTH(tagicons[DEFAULT_TAGS]))
|
||||||
|
tagindex = tagindex % LENGTH(tagicons[DEFAULT_TAGS]);
|
||||||
|
return tagicons[DEFAULT_TAGS][tagindex];
|
||||||
|
}
|
||||||
|
|
8
patch/bar_tagicons.h
Normal file
8
patch/bar_tagicons.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
enum {
|
||||||
|
DEFAULT_TAGS,
|
||||||
|
ALTERNATIVE_TAGS,
|
||||||
|
ALT_TAGS_DECORATION,
|
||||||
|
};
|
||||||
|
|
||||||
|
static char * tagicon(Monitor *m, int tag);
|
||||||
|
|
75
patch/bar_tags.c
Normal file
75
patch/bar_tags.c
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
int
|
||||||
|
width_tags(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
int w, i;
|
||||||
|
Client *c;
|
||||||
|
unsigned int occ = 0;
|
||||||
|
for (c = bar->mon->clients; c; c = c->next)
|
||||||
|
occ |= c->tags == 255 ? 0 : c->tags;
|
||||||
|
|
||||||
|
for (w = 0, i = 0; i < NUMTAGS; i++) {
|
||||||
|
if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i))
|
||||||
|
continue;
|
||||||
|
w += TEXTW(tagicon(bar->mon, i));
|
||||||
|
}
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
draw_tags(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
int invert;
|
||||||
|
int w, x = a->x;
|
||||||
|
unsigned int i, occ = 0, urg = 0;
|
||||||
|
char *icon;
|
||||||
|
Client *c;
|
||||||
|
Monitor *m = bar->mon;
|
||||||
|
|
||||||
|
for (c = m->clients; c; c = c->next) {
|
||||||
|
occ |= c->tags == 255 ? 0 : c->tags;
|
||||||
|
if (c->isurgent)
|
||||||
|
urg |= c->tags;
|
||||||
|
}
|
||||||
|
for (i = 0; i < NUMTAGS; i++) {
|
||||||
|
/* do not draw vacant tags */
|
||||||
|
if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
icon = tagicon(bar->mon, i);
|
||||||
|
invert = 0;
|
||||||
|
w = TEXTW(icon);
|
||||||
|
drw_setscheme(drw, scheme[
|
||||||
|
m->tagset[m->seltags] & 1 << i
|
||||||
|
? SchemeTagsSel
|
||||||
|
: urg & 1 << i
|
||||||
|
? SchemeUrg
|
||||||
|
: SchemeTagsNorm
|
||||||
|
]);
|
||||||
|
drw_text(drw, x, a->y, w, a->h, lrpad / 2, icon, invert, False);
|
||||||
|
drawindicator(m, NULL, occ, x, a->y, w, a->h, i, -1, invert, tagindicatortype);
|
||||||
|
x += w;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
click_tags(Bar *bar, Arg *arg, BarArg *a)
|
||||||
|
{
|
||||||
|
int i = 0, x = lrpad / 2;
|
||||||
|
Client *c;
|
||||||
|
unsigned int occ = 0;
|
||||||
|
for (c = bar->mon->clients; c; c = c->next)
|
||||||
|
occ |= c->tags == 255 ? 0 : c->tags;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i))
|
||||||
|
continue;
|
||||||
|
x += TEXTW(tagicon(bar->mon, i));
|
||||||
|
} while (a->x >= x && ++i < NUMTAGS);
|
||||||
|
if (i < NUMTAGS) {
|
||||||
|
arg->ui = 1 << i;
|
||||||
|
}
|
||||||
|
return ClkTagBar;
|
||||||
|
}
|
||||||
|
|
4
patch/bar_tags.h
Normal file
4
patch/bar_tags.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
static int width_tags(Bar *bar, BarArg *a);
|
||||||
|
static int draw_tags(Bar *bar, BarArg *a);
|
||||||
|
static int click_tags(Bar *bar, Arg *arg, BarArg *a);
|
||||||
|
|
39
patch/bar_wintitle.c
Normal file
39
patch/bar_wintitle.c
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
int
|
||||||
|
width_wintitle(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
return a->w;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
draw_wintitle(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
int x = a->x + lrpad / 2, w = a->w - lrpad / 2;
|
||||||
|
Monitor *m = bar->mon;
|
||||||
|
Client *c = m->sel;
|
||||||
|
int pad = lrpad / 2;
|
||||||
|
|
||||||
|
if (!c) {
|
||||||
|
drw_setscheme(drw, scheme[SchemeTitleNorm]);
|
||||||
|
drw_rect(drw, x, a->y, w, a->h, 1, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
drw_setscheme(drw, scheme[m == selmon ? SchemeTitleSel : SchemeTitleNorm]);
|
||||||
|
XSetErrorHandler(xerrordummy);
|
||||||
|
if (TEXTW(c->name) < w)
|
||||||
|
pad = (w - TEXTW(c->name) + lrpad) / 2;
|
||||||
|
|
||||||
|
drw_text(drw, x, a->y, w, a->h, pad, c->name, 0, False);
|
||||||
|
|
||||||
|
XSync(dpy, False);
|
||||||
|
XSetErrorHandler(xerror);
|
||||||
|
drawstateindicator(m, c, 1, x, a->y, w, a->h, 0, 0, c->isfixed);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
click_wintitle(Bar *bar, Arg *arg, BarArg *a)
|
||||||
|
{
|
||||||
|
return ClkWinTitle;
|
||||||
|
}
|
||||||
|
|
4
patch/bar_wintitle.h
Normal file
4
patch/bar_wintitle.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
static int width_wintitle(Bar *bar, BarArg *a);
|
||||||
|
static int draw_wintitle(Bar *bar, BarArg *a);
|
||||||
|
static int click_wintitle(Bar *bar, Arg *arg, BarArg *a);
|
||||||
|
|
91
patch/bar_wintitleactions.c
Normal file
91
patch/bar_wintitleactions.c
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
void
|
||||||
|
hide(Client *c) {
|
||||||
|
|
||||||
|
Client *n;
|
||||||
|
if (!c || HIDDEN(c))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Window w = c->win;
|
||||||
|
static XWindowAttributes ra, ca;
|
||||||
|
|
||||||
|
// more or less taken directly from blackbox's hide() function
|
||||||
|
XGrabServer(dpy);
|
||||||
|
XGetWindowAttributes(dpy, root, &ra);
|
||||||
|
XGetWindowAttributes(dpy, w, &ca);
|
||||||
|
// prevent UnmapNotify events
|
||||||
|
XSelectInput(dpy, root, ra.your_event_mask & ~SubstructureNotifyMask);
|
||||||
|
XSelectInput(dpy, w, ca.your_event_mask & ~StructureNotifyMask);
|
||||||
|
XUnmapWindow(dpy, w);
|
||||||
|
setclientstate(c, IconicState);
|
||||||
|
XSelectInput(dpy, root, ra.your_event_mask);
|
||||||
|
XSelectInput(dpy, w, ca.your_event_mask);
|
||||||
|
XUngrabServer(dpy);
|
||||||
|
|
||||||
|
if (c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) {
|
||||||
|
for (n = c->snext; n && (!ISVISIBLE(n) || HIDDEN(n)); n = n->snext);
|
||||||
|
if (!n)
|
||||||
|
for (n = c->mon->stack; n && (!ISVISIBLE(n) || HIDDEN(n)); n = n->snext);
|
||||||
|
} else {
|
||||||
|
n = nexttiled(c);
|
||||||
|
if (!n)
|
||||||
|
n = prevtiled(c);
|
||||||
|
}
|
||||||
|
focus(n);
|
||||||
|
arrange(c->mon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
show(Client *c)
|
||||||
|
{
|
||||||
|
if (!c || !HIDDEN(c))
|
||||||
|
return;
|
||||||
|
|
||||||
|
XMapWindow(dpy, c->win);
|
||||||
|
setclientstate(c, NormalState);
|
||||||
|
arrange(c->mon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
togglewin(const Arg *arg)
|
||||||
|
{
|
||||||
|
Client *c = (Client*)arg->v;
|
||||||
|
if (!c)
|
||||||
|
return;
|
||||||
|
if (c == selmon->sel)
|
||||||
|
hide(c);
|
||||||
|
else {
|
||||||
|
if (HIDDEN(c))
|
||||||
|
show(c);
|
||||||
|
focus(c);
|
||||||
|
restack(c->mon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Client *
|
||||||
|
prevtiled(Client *c)
|
||||||
|
{
|
||||||
|
Client *p, *i;
|
||||||
|
for (p = NULL, i = c->mon->clients; c && i != c; i = i->next)
|
||||||
|
if (ISVISIBLE(i) && !HIDDEN(i))
|
||||||
|
p = i;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
showhideclient(const Arg *arg)
|
||||||
|
{
|
||||||
|
Client *c = (Client*)arg->v;
|
||||||
|
if (!c)
|
||||||
|
c = selmon->sel;
|
||||||
|
if (!c)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (HIDDEN(c)) {
|
||||||
|
show(c);
|
||||||
|
focus(c);
|
||||||
|
restack(c->mon);
|
||||||
|
} else {
|
||||||
|
hide(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
6
patch/bar_wintitleactions.h
Normal file
6
patch/bar_wintitleactions.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
static void hide(Client *c);
|
||||||
|
static void show(Client *c);
|
||||||
|
static void togglewin(const Arg *arg);
|
||||||
|
static Client * prevtiled(Client *c);
|
||||||
|
static void showhideclient(const Arg *arg);
|
||||||
|
|
35
patch/decorationhints.c
Normal file
35
patch/decorationhints.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
static Atom motifatom;
|
||||||
|
|
||||||
|
void
|
||||||
|
updatemotifhints(Client *c)
|
||||||
|
{
|
||||||
|
Atom real;
|
||||||
|
int format;
|
||||||
|
unsigned char *p = NULL;
|
||||||
|
unsigned long n, extra;
|
||||||
|
unsigned long *motif;
|
||||||
|
int width, height;
|
||||||
|
|
||||||
|
if (!decorhints)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (XGetWindowProperty(dpy, c->win, motifatom, 0L, 5L, False, motifatom,
|
||||||
|
&real, &format, &n, &extra, &p) == Success && p != NULL) {
|
||||||
|
motif = (unsigned long*)p;
|
||||||
|
if (motif[MWM_HINTS_FLAGS_FIELD] & MWM_HINTS_DECORATIONS) {
|
||||||
|
width = WIDTH(c);
|
||||||
|
height = HEIGHT(c);
|
||||||
|
|
||||||
|
if (motif[MWM_HINTS_DECORATIONS_FIELD] & MWM_DECOR_ALL ||
|
||||||
|
motif[MWM_HINTS_DECORATIONS_FIELD] & MWM_DECOR_BORDER ||
|
||||||
|
motif[MWM_HINTS_DECORATIONS_FIELD] & MWM_DECOR_TITLE)
|
||||||
|
c->bw = c->oldbw = borderpx;
|
||||||
|
else
|
||||||
|
c->bw = c->oldbw = 0;
|
||||||
|
|
||||||
|
resize(c, c->x, c->y, width - (2*c->bw), height - (2*c->bw), 0);
|
||||||
|
}
|
||||||
|
XFree(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
9
patch/decorationhints.h
Normal file
9
patch/decorationhints.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#define MWM_HINTS_FLAGS_FIELD 0
|
||||||
|
#define MWM_HINTS_DECORATIONS_FIELD 2
|
||||||
|
#define MWM_HINTS_DECORATIONS (1 << 1)
|
||||||
|
#define MWM_DECOR_ALL (1 << 0)
|
||||||
|
#define MWM_DECOR_BORDER (1 << 1)
|
||||||
|
#define MWM_DECOR_TITLE (1 << 3)
|
||||||
|
|
||||||
|
static void updatemotifhints(Client *c);
|
||||||
|
|
19
patch/fakefullscreenclient.c
Normal file
19
patch/fakefullscreenclient.c
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
void
|
||||||
|
togglefakefullscreen(const Arg *arg)
|
||||||
|
{
|
||||||
|
Client *c = selmon->sel;
|
||||||
|
if (!c)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (c->fakefullscreen != 1 && c->isfullscreen) { // exit fullscreen --> fake fullscreen
|
||||||
|
c->fakefullscreen = 2;
|
||||||
|
setfullscreen(c, 0);
|
||||||
|
} else if (c->fakefullscreen == 1) {
|
||||||
|
setfullscreen(c, 0);
|
||||||
|
c->fakefullscreen = 0;
|
||||||
|
} else {
|
||||||
|
c->fakefullscreen = 1;
|
||||||
|
setfullscreen(c, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2
patch/fakefullscreenclient.h
Normal file
2
patch/fakefullscreenclient.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
static void togglefakefullscreen(const Arg *arg);
|
||||||
|
|
80
patch/focusadjacenttag.c
Normal file
80
patch/focusadjacenttag.c
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
void
|
||||||
|
tagtoleft(const Arg *arg)
|
||||||
|
{
|
||||||
|
if (selmon->sel != NULL
|
||||||
|
&& __builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1
|
||||||
|
&& selmon->tagset[selmon->seltags] > 1) {
|
||||||
|
selmon->sel->tags >>= 1;
|
||||||
|
focus(NULL);
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tagtoright(const Arg *arg)
|
||||||
|
{
|
||||||
|
if (selmon->sel != NULL
|
||||||
|
&& __builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1
|
||||||
|
&& selmon->tagset[selmon->seltags] & (TAGMASK >> 1)) {
|
||||||
|
selmon->sel->tags <<= 1;
|
||||||
|
focus(NULL);
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
viewtoleft(const Arg *arg)
|
||||||
|
{
|
||||||
|
if (__builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1
|
||||||
|
&& selmon->tagset[selmon->seltags] > 1) {
|
||||||
|
selmon->seltags ^= 1; /* toggle sel tagset */
|
||||||
|
pertagview(&((Arg) { .ui = selmon->tagset[selmon->seltags ^ 1] >> 1 }));
|
||||||
|
focus(NULL);
|
||||||
|
arrange(selmon);
|
||||||
|
updatecurrentdesktop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
viewtoright(const Arg *arg)
|
||||||
|
{
|
||||||
|
if (__builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1
|
||||||
|
&& selmon->tagset[selmon->seltags] & (TAGMASK >> 1)) {
|
||||||
|
selmon->seltags ^= 1; /* toggle sel tagset */
|
||||||
|
pertagview(&((Arg) { .ui = selmon->tagset[selmon->seltags ^ 1] << 1 }));
|
||||||
|
focus(NULL);
|
||||||
|
arrange(selmon);
|
||||||
|
updatecurrentdesktop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tagandviewtoleft(const Arg *arg)
|
||||||
|
{
|
||||||
|
if (selmon->sel != NULL
|
||||||
|
&& __builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1
|
||||||
|
&& selmon->tagset[selmon->seltags] > 1) {
|
||||||
|
selmon->sel->tags >>= 1;
|
||||||
|
selmon->seltags ^= 1; /* toggle sel tagset */
|
||||||
|
pertagview(&((Arg) { .ui = selmon->tagset[selmon->seltags ^ 1] >> 1 }));
|
||||||
|
focus(selmon->sel);
|
||||||
|
arrange(selmon);
|
||||||
|
updatecurrentdesktop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tagandviewtoright(const Arg *arg)
|
||||||
|
{
|
||||||
|
if (selmon->sel != NULL
|
||||||
|
&& __builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1
|
||||||
|
&& selmon->tagset[selmon->seltags] & (TAGMASK >> 1)) {
|
||||||
|
selmon->sel->tags <<= 1;
|
||||||
|
selmon->seltags ^= 1; /* toggle sel tagset */
|
||||||
|
pertagview(&((Arg) { .ui = selmon->tagset[selmon->seltags ^ 1] << 1 }));
|
||||||
|
focus(selmon->sel);
|
||||||
|
arrange(selmon);
|
||||||
|
updatecurrentdesktop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
7
patch/focusadjacenttag.h
Normal file
7
patch/focusadjacenttag.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
static void tagtoleft(const Arg *arg);
|
||||||
|
static void tagtoright(const Arg *arg);
|
||||||
|
static void viewtoleft(const Arg *arg);
|
||||||
|
static void viewtoright(const Arg *arg);
|
||||||
|
static void tagandviewtoleft(const Arg *arg);
|
||||||
|
static void tagandviewtoright(const Arg *arg);
|
||||||
|
|
40
patch/include.c
Normal file
40
patch/include.c
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* Bar functionality */
|
||||||
|
#include "bar_indicators.c"
|
||||||
|
#include "bar_tagicons.c"
|
||||||
|
|
||||||
|
#include "bar_alpha.c"
|
||||||
|
#include "bar_dwmblocks.c"
|
||||||
|
#include "bar_ewmhtags.c"
|
||||||
|
#include "bar_ltsymbol.c"
|
||||||
|
#include "bar_powerline_tags.c"
|
||||||
|
#include "bar_status.c"
|
||||||
|
#include "bar_statuscmd.c"
|
||||||
|
#include "bar_tabgroups.c"
|
||||||
|
#include "bar_tags.c"
|
||||||
|
#include "bar_wintitle.c"
|
||||||
|
#include "bar_systray.c"
|
||||||
|
#include "bar_wintitleactions.c"
|
||||||
|
|
||||||
|
/* Other patches */
|
||||||
|
#include "autostart.c"
|
||||||
|
#include "decorationhints.c"
|
||||||
|
#include "fakefullscreenclient.c"
|
||||||
|
#include "focusadjacenttag.c"
|
||||||
|
#include "inplacerotate.c"
|
||||||
|
#include "pertag.c"
|
||||||
|
#include "scratchpad_alt_1.c"
|
||||||
|
#include "sticky.c"
|
||||||
|
#include "swallow.c"
|
||||||
|
#include "tagallmon.c"
|
||||||
|
#include "tagswapmon.c"
|
||||||
|
#include "transfer.c"
|
||||||
|
#include "vanitygaps.c"
|
||||||
|
/* Layouts */
|
||||||
|
#include "layout_facts.c"
|
||||||
|
#include "layout_centeredmaster.c"
|
||||||
|
#include "layout_centeredfloatingmaster.c"
|
||||||
|
#include "layout_fibonacci.c"
|
||||||
|
#include "layout_monocle.c"
|
||||||
|
#include "layout_nrowgrid.c"
|
||||||
|
#include "layout_tile.c"
|
||||||
|
|
39
patch/include.h
Normal file
39
patch/include.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/* Bar functionality */
|
||||||
|
#include "bar_indicators.h"
|
||||||
|
#include "bar_tagicons.h"
|
||||||
|
|
||||||
|
#include "bar_alpha.h"
|
||||||
|
#include "bar_dwmblocks.h"
|
||||||
|
#include "bar_ewmhtags.h"
|
||||||
|
#include "bar_ltsymbol.h"
|
||||||
|
#include "bar_powerline_tags.h"
|
||||||
|
#include "bar_status.h"
|
||||||
|
#include "bar_statuscmd.h"
|
||||||
|
#include "bar_tabgroups.h"
|
||||||
|
#include "bar_tags.h"
|
||||||
|
#include "bar_wintitle.h"
|
||||||
|
#include "bar_systray.h"
|
||||||
|
#include "bar_wintitleactions.h"
|
||||||
|
|
||||||
|
/* Other patches */
|
||||||
|
#include "autostart.h"
|
||||||
|
#include "decorationhints.h"
|
||||||
|
#include "fakefullscreenclient.h"
|
||||||
|
#include "focusadjacenttag.h"
|
||||||
|
#include "inplacerotate.h"
|
||||||
|
#include "pertag.h"
|
||||||
|
#include "scratchpad_alt_1.h"
|
||||||
|
#include "sticky.h"
|
||||||
|
#include "swallow.h"
|
||||||
|
#include "tagallmon.h"
|
||||||
|
#include "tagswapmon.h"
|
||||||
|
#include "transfer.h"
|
||||||
|
#include "vanitygaps.h"
|
||||||
|
/* Layouts */
|
||||||
|
#include "layout_centeredmaster.h"
|
||||||
|
#include "layout_centeredfloatingmaster.h"
|
||||||
|
#include "layout_fibonacci.h"
|
||||||
|
#include "layout_monocle.h"
|
||||||
|
#include "layout_nrowgrid.h"
|
||||||
|
#include "layout_tile.h"
|
||||||
|
|
84
patch/inplacerotate.c
Normal file
84
patch/inplacerotate.c
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
void
|
||||||
|
insertclient(Client *item, Client *insertItem, int after)
|
||||||
|
{
|
||||||
|
Client *c;
|
||||||
|
if (item == NULL || insertItem == NULL || item == insertItem)
|
||||||
|
return;
|
||||||
|
detach(insertItem);
|
||||||
|
if (!after && selmon->clients == item) {
|
||||||
|
attach(insertItem);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (after) {
|
||||||
|
c = item;
|
||||||
|
} else {
|
||||||
|
for (c = selmon->clients; c; c = c->next) {
|
||||||
|
if (c->next == item)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
insertItem->next = c->next;
|
||||||
|
c->next = insertItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
inplacerotate(const Arg *arg)
|
||||||
|
{
|
||||||
|
if (!selmon->sel || (selmon->sel->isfloating && !arg->f))
|
||||||
|
return;
|
||||||
|
|
||||||
|
unsigned int selidx = 0, i = 0;
|
||||||
|
Client *c = NULL, *stail = NULL, *mhead = NULL, *mtail = NULL, *shead = NULL;
|
||||||
|
|
||||||
|
// Determine positionings for insertclient
|
||||||
|
for (c = selmon->clients; c; c = c->next) {
|
||||||
|
if (ISVISIBLE(c) && !(c->isfloating)) {
|
||||||
|
if (selmon->sel == c)
|
||||||
|
selidx = i;
|
||||||
|
if (i == selmon->nmaster - 1)
|
||||||
|
mtail = c;
|
||||||
|
if (i == selmon->nmaster)
|
||||||
|
shead = c;
|
||||||
|
if (mhead == NULL)
|
||||||
|
mhead = c;
|
||||||
|
stail = c;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(arg->i) {
|
||||||
|
case 1:
|
||||||
|
if (selidx >= selmon->nmaster)
|
||||||
|
insertclient(shead, stail, 0);
|
||||||
|
else
|
||||||
|
insertclient(mhead, mtail, 0);
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
if (selidx >= selmon->nmaster)
|
||||||
|
insertclient(stail, shead, 1);
|
||||||
|
else
|
||||||
|
insertclient(mtail, mhead, 1);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
insertclient(selmon->clients, stail, 0);
|
||||||
|
break;
|
||||||
|
case -2:
|
||||||
|
insertclient(stail, selmon->clients, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore focus position
|
||||||
|
i = 0;
|
||||||
|
for (c = selmon->clients; c; c = c->next) {
|
||||||
|
if (!ISVISIBLE(c) || (c->isfloating))
|
||||||
|
continue;
|
||||||
|
if (i == selidx) {
|
||||||
|
focus(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
arrange(selmon);
|
||||||
|
focus(c);
|
||||||
|
}
|
||||||
|
|
2
patch/inplacerotate.h
Normal file
2
patch/inplacerotate.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
static void inplacerotate(const Arg *arg);
|
||||||
|
|
62
patch/ipc/IPCClient.h
Normal file
62
patch/ipc/IPCClient.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#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_
|
||||||
|
|
549
patch/ipc/dwm-msg.c
Normal file
549
patch/ipc/dwm-msg.c
Normal file
@ -0,0 +1,549 @@
|
|||||||
|
#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 (!argc || 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;
|
||||||
|
}
|
||||||
|
|
66
patch/ipc/yajl_dumps.h
Normal file
66
patch/ipc/yajl_dumps.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#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, 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_
|
||||||
|
|
55
patch/layout_centeredfloatingmaster.c
Normal file
55
patch/layout_centeredfloatingmaster.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
void
|
||||||
|
centeredfloatingmaster(Monitor *m)
|
||||||
|
{
|
||||||
|
unsigned int i, n;
|
||||||
|
float mfacts, sfacts;
|
||||||
|
int mrest, srest;
|
||||||
|
int mx = 0, my = 0, mh = 0, mw = 0;
|
||||||
|
int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||||
|
Client *c;
|
||||||
|
|
||||||
|
float mivf = 1.0; // master inner vertical gap factor
|
||||||
|
int oh, ov, ih, iv;
|
||||||
|
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 / 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 / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
|
||||||
|
sx += WIDTH(c) + iv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2
patch/layout_centeredfloatingmaster.h
Normal file
2
patch/layout_centeredfloatingmaster.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
static void centeredfloatingmaster(Monitor *m);
|
||||||
|
|
85
patch/layout_centeredmaster.c
Normal file
85
patch/layout_centeredmaster.c
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
void
|
||||||
|
centeredmaster(Monitor *m)
|
||||||
|
{
|
||||||
|
unsigned int i, n;
|
||||||
|
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;
|
||||||
|
|
||||||
|
int oh, ov, ih, iv;
|
||||||
|
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;
|
||||||
|
mx += lw + iv;
|
||||||
|
} else {
|
||||||
|
/* ||<---M--->|<-S->|| */
|
||||||
|
mw = (mw - iv) * m->mfact;
|
||||||
|
lw = m->ww - mw - iv - 2*ov;
|
||||||
|
}
|
||||||
|
rw = lw;
|
||||||
|
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 += 1;
|
||||||
|
else if ((n - m->nmaster) % 2)
|
||||||
|
lfacts += 1; // total factor of left hand stack area
|
||||||
|
else
|
||||||
|
rfacts += 1; // 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 / mfacts;
|
||||||
|
else if ((n - m->nmaster) % 2)
|
||||||
|
ltotal += lh / lfacts;
|
||||||
|
else
|
||||||
|
rtotal += rh / 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 / 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 / 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 / rfacts) + ((i - 2*m->nmaster) < 2*rrest ? 1 : 0) - (2*c->bw), 0);
|
||||||
|
ry += HEIGHT(c) + ih;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2
patch/layout_centeredmaster.h
Normal file
2
patch/layout_centeredmaster.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
static void centeredmaster(Monitor *m);
|
||||||
|
|
24
patch/layout_facts.c
Normal file
24
patch/layout_facts.c
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
void
|
||||||
|
getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr)
|
||||||
|
{
|
||||||
|
unsigned int n;
|
||||||
|
float mfacts, sfacts;
|
||||||
|
int mtotal = 0, stotal = 0;
|
||||||
|
Client *c;
|
||||||
|
|
||||||
|
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
|
||||||
|
mfacts = MIN(n, m->nmaster);
|
||||||
|
sfacts = n - m->nmaster;
|
||||||
|
|
||||||
|
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
|
||||||
|
if (n < m->nmaster)
|
||||||
|
mtotal += msize / mfacts;
|
||||||
|
else
|
||||||
|
stotal += ssize / sfacts;
|
||||||
|
|
||||||
|
*mf = mfacts; // total factor of master area
|
||||||
|
*sf = sfacts; // total factor of stack area
|
||||||
|
*mr = msize - mtotal; // the remainder (rest) of pixels after an even master split
|
||||||
|
*sr = ssize - stotal; // the remainder (rest) of pixels after an even stack split
|
||||||
|
}
|
||||||
|
|
94
patch/layout_fibonacci.c
Normal file
94
patch/layout_fibonacci.c
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
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 = 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dwindle(Monitor *m)
|
||||||
|
{
|
||||||
|
fibonacci(m, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
3
patch/layout_fibonacci.h
Normal file
3
patch/layout_fibonacci.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
static void dwindle(Monitor *m);
|
||||||
|
static void fibonacci(Monitor *m, int s);
|
||||||
|
|
15
patch/layout_monocle.c
Normal file
15
patch/layout_monocle.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
void
|
||||||
|
monocle(Monitor *m)
|
||||||
|
{
|
||||||
|
unsigned int n = 0;
|
||||||
|
Client *c;
|
||||||
|
|
||||||
|
for (c = m->clients; c; c = c->next)
|
||||||
|
if (ISVISIBLE(c))
|
||||||
|
n++;
|
||||||
|
if (n > 0) /* override layout symbol */
|
||||||
|
snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
|
||||||
|
for (c = nexttiled(m->clients); c; c = nexttiled(c->next))
|
||||||
|
resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0);
|
||||||
|
}
|
||||||
|
|
2
patch/layout_monocle.h
Normal file
2
patch/layout_monocle.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
static void monocle(Monitor *m);
|
||||||
|
|
53
patch/layout_nrowgrid.c
Normal file
53
patch/layout_nrowgrid.c
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
void
|
||||||
|
nrowgrid(Monitor *m)
|
||||||
|
{
|
||||||
|
unsigned int n = 0, i = 0, 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), i++, 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2
patch/layout_nrowgrid.h
Normal file
2
patch/layout_nrowgrid.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
static void nrowgrid(Monitor *m);
|
||||||
|
|
41
patch/layout_tile.c
Normal file
41
patch/layout_tile.c
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
static void
|
||||||
|
tile(Monitor *m)
|
||||||
|
{
|
||||||
|
unsigned int i, n;
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
int oh, ov, ih, iv;
|
||||||
|
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) * m->mfact;
|
||||||
|
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 / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
|
||||||
|
my += HEIGHT(c) + ih;
|
||||||
|
} else {
|
||||||
|
resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
|
||||||
|
sy += HEIGHT(c) + ih;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2
patch/layout_tile.h
Normal file
2
patch/layout_tile.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
static void tile(Monitor *);
|
||||||
|
|
36
patch/pertag.c
Normal file
36
patch/pertag.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
struct Pertag {
|
||||||
|
unsigned int curtag, prevtag; /* current and previous tag */
|
||||||
|
int nmasters[NUMTAGS + 1]; /* number of windows in master area */
|
||||||
|
const Layout *ltidxs[NUMTAGS + 1][2]; /* matrix of tags and layouts indexes */
|
||||||
|
float mfacts[NUMTAGS + 1]; /* mfacts per tag */
|
||||||
|
unsigned int sellts[NUMTAGS + 1]; /* selected layouts */
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
pertagview(const Arg *arg)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned int tmptag;
|
||||||
|
if (arg->ui & TAGMASK) {
|
||||||
|
selmon->pertag->prevtag = selmon->pertag->curtag;
|
||||||
|
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
|
||||||
|
if (arg->ui == ~0)
|
||||||
|
selmon->pertag->curtag = 0;
|
||||||
|
else {
|
||||||
|
for (i = 0; !(arg->ui & 1 << i); i++) ;
|
||||||
|
selmon->pertag->curtag = i + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tmptag = selmon->pertag->prevtag;
|
||||||
|
selmon->pertag->prevtag = selmon->pertag->curtag;
|
||||||
|
selmon->pertag->curtag = tmptag;
|
||||||
|
}
|
||||||
|
selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
|
||||||
|
selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
|
||||||
|
selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
|
||||||
|
selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
|
||||||
|
selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
2
patch/pertag.h
Normal file
2
patch/pertag.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
static void pertagview(const Arg *arg);
|
||||||
|
|
72
patch/scratchpad_alt_1.c
Normal file
72
patch/scratchpad_alt_1.c
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
static Client * scratchpad_last_showed = NULL;
|
||||||
|
|
||||||
|
void
|
||||||
|
scratchpad_hide()
|
||||||
|
{
|
||||||
|
if (selmon->sel) {
|
||||||
|
selmon->sel->tags = SCRATCHPAD_MASK;
|
||||||
|
selmon->sel->isfloating = 1;
|
||||||
|
focus(NULL);
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_Bool
|
||||||
|
scratchpad_last_showed_is_killed(void)
|
||||||
|
{
|
||||||
|
Client *c;
|
||||||
|
for (c = selmon->clients; c && c != scratchpad_last_showed; c = c->next);
|
||||||
|
return (c == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
scratchpad_remove()
|
||||||
|
{
|
||||||
|
if (selmon->sel && scratchpad_last_showed != NULL && selmon->sel == scratchpad_last_showed)
|
||||||
|
scratchpad_last_showed = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
scratchpad_show()
|
||||||
|
{
|
||||||
|
if (scratchpad_last_showed == NULL || scratchpad_last_showed_is_killed()) {
|
||||||
|
scratchpad_show_first();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scratchpad_last_showed->tags != SCRATCHPAD_MASK) {
|
||||||
|
scratchpad_last_showed->tags = SCRATCHPAD_MASK;
|
||||||
|
focus(NULL);
|
||||||
|
arrange(selmon);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Client *c;
|
||||||
|
|
||||||
|
for (c = selmon->clients; c && c != scratchpad_last_showed; c = c->next);
|
||||||
|
for (c = (c ? c->next : NULL); c && c->tags != SCRATCHPAD_MASK; c = c->next);
|
||||||
|
|
||||||
|
if (c)
|
||||||
|
scratchpad_show_client(c);
|
||||||
|
else
|
||||||
|
scratchpad_show_first();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
scratchpad_show_client(Client* c)
|
||||||
|
{
|
||||||
|
scratchpad_last_showed = c;
|
||||||
|
c->tags = selmon->tagset[selmon->seltags];
|
||||||
|
focus(c);
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
scratchpad_show_first(void)
|
||||||
|
{
|
||||||
|
Client *c;
|
||||||
|
for (c = selmon->clients; c && c->tags != SCRATCHPAD_MASK; c = c->next);
|
||||||
|
if (c)
|
||||||
|
scratchpad_show_client(c);
|
||||||
|
}
|
||||||
|
|
9
patch/scratchpad_alt_1.h
Normal file
9
patch/scratchpad_alt_1.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#define SCRATCHPAD_MASK (1u << NUMTAGS)
|
||||||
|
|
||||||
|
static void scratchpad_hide();
|
||||||
|
static _Bool scratchpad_last_showed_is_killed(void);
|
||||||
|
static void scratchpad_remove();
|
||||||
|
static void scratchpad_show();
|
||||||
|
static void scratchpad_show_client(Client *c);
|
||||||
|
static void scratchpad_show_first(void);
|
||||||
|
|
9
patch/sticky.c
Normal file
9
patch/sticky.c
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
void
|
||||||
|
togglesticky(const Arg *arg)
|
||||||
|
{
|
||||||
|
if (!selmon->sel)
|
||||||
|
return;
|
||||||
|
selmon->sel->issticky = !selmon->sel->issticky;
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
|
2
patch/sticky.h
Normal file
2
patch/sticky.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
static void togglesticky(const Arg *arg);
|
||||||
|
|
214
patch/swallow.c
Normal file
214
patch/swallow.c
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
#include <X11/Xlib-xcb.h>
|
||||||
|
#include <xcb/res.h>
|
||||||
|
#ifdef __OpenBSD__
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <kvm.h>
|
||||||
|
#endif /* __OpenBSD__ */
|
||||||
|
|
||||||
|
static int scanner;
|
||||||
|
static xcb_connection_t *xcon;
|
||||||
|
|
||||||
|
int
|
||||||
|
swallow(Client *p, Client *c)
|
||||||
|
{
|
||||||
|
Client *s;
|
||||||
|
XWindowChanges wc;
|
||||||
|
|
||||||
|
if (c->noswallow > 0 || c->isterminal)
|
||||||
|
return 0;
|
||||||
|
if (c->noswallow < 0 && !swallowfloating && c->isfloating)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
XMapWindow(dpy, c->win);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
XChangeProperty(dpy, c->win, netatom[NetClientList], XA_WINDOW, 32, PropModeReplace,
|
||||||
|
(unsigned char *) &(p->win), 1);
|
||||||
|
|
||||||
|
updatetitle(p);
|
||||||
|
s = scanner ? c : p;
|
||||||
|
setfloatinghint(s);
|
||||||
|
|
||||||
|
wc.border_width = p->bw;
|
||||||
|
XConfigureWindow(dpy, p->win, CWBorderWidth, &wc);
|
||||||
|
XMoveResizeWindow(dpy, p->win, s->x, s->y, s->w, s->h);
|
||||||
|
XSetWindowBorder(dpy, p->win, scheme[SchemeNorm][ColBorder].pixel);
|
||||||
|
|
||||||
|
arrange(p->mon);
|
||||||
|
configure(p);
|
||||||
|
updateclientlist();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
unswallow(Client *c)
|
||||||
|
{
|
||||||
|
XWindowChanges wc;
|
||||||
|
c->win = c->swallowing->win;
|
||||||
|
|
||||||
|
free(c->swallowing);
|
||||||
|
c->swallowing = NULL;
|
||||||
|
|
||||||
|
XDeleteProperty(dpy, c->win, netatom[NetClientList]);
|
||||||
|
|
||||||
|
/* unfullscreen the client */
|
||||||
|
setfullscreen(c, 0);
|
||||||
|
updatetitle(c);
|
||||||
|
arrange(c->mon);
|
||||||
|
XMapWindow(dpy, c->win);
|
||||||
|
|
||||||
|
wc.border_width = c->bw;
|
||||||
|
XConfigureWindow(dpy, c->win, CWBorderWidth, &wc);
|
||||||
|
XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
|
||||||
|
XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel);
|
||||||
|
|
||||||
|
setfloatinghint(c);
|
||||||
|
setclientstate(c, NormalState);
|
||||||
|
focus(NULL);
|
||||||
|
arrange(c->mon);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (pid_t)0;
|
||||||
|
|
||||||
|
if (fscanf(f, "%*u %*s %*c %u", (unsigned *)&v) != 1)
|
||||||
|
v = (pid_t)0;
|
||||||
|
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;
|
||||||
|
|
||||||
|
c = selmon->sel;
|
||||||
|
if (c && c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid))
|
||||||
|
return c;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
8
patch/swallow.h
Normal file
8
patch/swallow.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
static pid_t getparentprocess(pid_t p);
|
||||||
|
static int isdescprocess(pid_t p, pid_t c);
|
||||||
|
static int swallow(Client *p, Client *c);
|
||||||
|
static Client *swallowingclient(Window w);
|
||||||
|
static Client *termforwin(const Client *c);
|
||||||
|
static void unswallow(Client *c);
|
||||||
|
static pid_t winpid(Window w);
|
||||||
|
|
44
patch/tagallmon.c
Normal file
44
patch/tagallmon.c
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
void
|
||||||
|
tagallmon(const Arg *arg)
|
||||||
|
{
|
||||||
|
Monitor *m;
|
||||||
|
Client *c, *last, *slast, *next;
|
||||||
|
|
||||||
|
if (!mons->next)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m = dirtomon(arg->i);
|
||||||
|
for (last = m->clients; last && last->next; last = last->next);
|
||||||
|
for (slast = m->stack; slast && slast->snext; slast = slast->snext);
|
||||||
|
|
||||||
|
for (c = selmon->clients; c; c = next) {
|
||||||
|
next = c->next;
|
||||||
|
if (!ISVISIBLE(c))
|
||||||
|
continue;
|
||||||
|
unfocus(c, 1, NULL);
|
||||||
|
detach(c);
|
||||||
|
detachstack(c);
|
||||||
|
c->mon = m;
|
||||||
|
c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
|
||||||
|
c->next = NULL;
|
||||||
|
c->snext = NULL;
|
||||||
|
if (last)
|
||||||
|
last = last->next = c;
|
||||||
|
else
|
||||||
|
m->clients = last = c;
|
||||||
|
if (slast)
|
||||||
|
slast = slast->snext = c;
|
||||||
|
else
|
||||||
|
m->stack = slast = c;
|
||||||
|
if (c->isfullscreen) {
|
||||||
|
if (c->fakefullscreen != 1) {
|
||||||
|
resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
|
||||||
|
XRaiseWindow(dpy, c->win);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
focus(NULL);
|
||||||
|
arrange(NULL);
|
||||||
|
}
|
||||||
|
|
2
patch/tagallmon.h
Normal file
2
patch/tagallmon.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
static void tagallmon(const Arg *arg);
|
||||||
|
|
65
patch/tagswapmon.c
Normal file
65
patch/tagswapmon.c
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
void
|
||||||
|
tagswapmon(const Arg *arg)
|
||||||
|
{
|
||||||
|
Monitor *m;
|
||||||
|
Client *c, *sc = NULL, *mc = NULL, *next;
|
||||||
|
|
||||||
|
if (!mons->next)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m = dirtomon(arg->i);
|
||||||
|
|
||||||
|
for (c = selmon->clients; c; c = next) {
|
||||||
|
next = c->next;
|
||||||
|
if (!ISVISIBLE(c))
|
||||||
|
continue;
|
||||||
|
unfocus(c, 1, NULL);
|
||||||
|
detach(c);
|
||||||
|
detachstack(c);
|
||||||
|
c->next = sc;
|
||||||
|
sc = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (c = m->clients; c; c = next) {
|
||||||
|
next = c->next;
|
||||||
|
if (!ISVISIBLE(c))
|
||||||
|
continue;
|
||||||
|
unfocus(c, 1, NULL);
|
||||||
|
detach(c);
|
||||||
|
detachstack(c);
|
||||||
|
c->next = mc;
|
||||||
|
mc = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (c = sc; c; c = next) {
|
||||||
|
next = c->next;
|
||||||
|
c->mon = m;
|
||||||
|
c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
|
||||||
|
attach(c);
|
||||||
|
attachstack(c);
|
||||||
|
if (c->isfullscreen) {
|
||||||
|
if (c->fakefullscreen != 1) {
|
||||||
|
resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
|
||||||
|
XRaiseWindow(dpy, c->win);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (c = mc; c; c = next) {
|
||||||
|
next = c->next;
|
||||||
|
c->mon = selmon;
|
||||||
|
c->tags = selmon->tagset[selmon->seltags]; /* assign tags of target monitor */
|
||||||
|
attach(c);
|
||||||
|
attachstack(c);
|
||||||
|
if (c->isfullscreen) {
|
||||||
|
if (c->fakefullscreen != 1) {
|
||||||
|
resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
|
||||||
|
XRaiseWindow(dpy, c->win);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
focus(NULL);
|
||||||
|
arrange(NULL);
|
||||||
|
}
|
||||||
|
|
2
patch/tagswapmon.h
Normal file
2
patch/tagswapmon.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
static void tagswapmon(const Arg *arg);
|
||||||
|
|
34
patch/transfer.c
Normal file
34
patch/transfer.c
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
void
|
||||||
|
transfer(const Arg *arg)
|
||||||
|
{
|
||||||
|
Client *c, *mtail = selmon->clients, *stail = NULL, *insertafter;
|
||||||
|
int transfertostack = 0, i, nmasterclients;
|
||||||
|
|
||||||
|
for (i = 0, c = selmon->clients; c; c = c->next) {
|
||||||
|
if (!ISVISIBLE(c) || c->isfloating) continue;
|
||||||
|
if (selmon->sel == c) { transfertostack = i < selmon->nmaster && selmon->nmaster != 0; }
|
||||||
|
if (i < selmon->nmaster) { nmasterclients++; mtail = c; }
|
||||||
|
stail = c;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (!selmon->sel || selmon->sel->isfloating || i == 0) {
|
||||||
|
return;
|
||||||
|
} else if (transfertostack) {
|
||||||
|
selmon->nmaster = MIN(i, selmon->nmaster) - 1;
|
||||||
|
insertafter = stail;
|
||||||
|
} else {
|
||||||
|
selmon->nmaster = selmon->nmaster + 1;
|
||||||
|
insertafter = mtail;
|
||||||
|
}
|
||||||
|
if (insertafter != selmon->sel) {
|
||||||
|
detach(selmon->sel);
|
||||||
|
if (selmon->nmaster == 1 && !transfertostack) {
|
||||||
|
attach(selmon->sel); // Head prepend case
|
||||||
|
} else {
|
||||||
|
selmon->sel->next = insertafter->next;
|
||||||
|
insertafter->next = selmon->sel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
|
2
patch/transfer.h
Normal file
2
patch/transfer.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
static void transfer(const Arg *arg);
|
||||||
|
|
130
patch/vanitygaps.c
Normal file
130
patch/vanitygaps.c
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/* Settings */
|
||||||
|
static int enablegaps = 1;
|
||||||
|
|
||||||
|
static 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
togglegaps(const Arg *arg)
|
||||||
|
{
|
||||||
|
enablegaps = !enablegaps;
|
||||||
|
arrange(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
defaultgaps(const Arg *arg)
|
||||||
|
{
|
||||||
|
setgaps(gappoh, gappov, gappih, gappiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
incrgaps(const Arg *arg)
|
||||||
|
{
|
||||||
|
setgaps(
|
||||||
|
selmon->gappoh + arg->i,
|
||||||
|
selmon->gappov + arg->i,
|
||||||
|
selmon->gappih + arg->i,
|
||||||
|
selmon->gappiv + arg->i
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
incrigaps(const Arg *arg)
|
||||||
|
{
|
||||||
|
setgaps(
|
||||||
|
selmon->gappoh,
|
||||||
|
selmon->gappov,
|
||||||
|
selmon->gappih + arg->i,
|
||||||
|
selmon->gappiv + arg->i
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
incrogaps(const Arg *arg)
|
||||||
|
{
|
||||||
|
setgaps(
|
||||||
|
selmon->gappoh + arg->i,
|
||||||
|
selmon->gappov + arg->i,
|
||||||
|
selmon->gappih,
|
||||||
|
selmon->gappiv
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
incrohgaps(const Arg *arg)
|
||||||
|
{
|
||||||
|
setgaps(
|
||||||
|
selmon->gappoh + arg->i,
|
||||||
|
selmon->gappov,
|
||||||
|
selmon->gappih,
|
||||||
|
selmon->gappiv
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
incrovgaps(const Arg *arg)
|
||||||
|
{
|
||||||
|
setgaps(
|
||||||
|
selmon->gappoh,
|
||||||
|
selmon->gappov + arg->i,
|
||||||
|
selmon->gappih,
|
||||||
|
selmon->gappiv
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
incrihgaps(const Arg *arg)
|
||||||
|
{
|
||||||
|
setgaps(
|
||||||
|
selmon->gappoh,
|
||||||
|
selmon->gappov,
|
||||||
|
selmon->gappih + arg->i,
|
||||||
|
selmon->gappiv
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
incrivgaps(const Arg *arg)
|
||||||
|
{
|
||||||
|
setgaps(
|
||||||
|
selmon->gappoh,
|
||||||
|
selmon->gappov,
|
||||||
|
selmon->gappih,
|
||||||
|
selmon->gappiv + arg->i
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc)
|
||||||
|
{
|
||||||
|
unsigned int n, oe, ie;
|
||||||
|
oe = ie = enablegaps;
|
||||||
|
Client *c;
|
||||||
|
|
||||||
|
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
|
||||||
|
if (n == 1) {
|
||||||
|
oe *= smartgaps_fact; // outer gaps disabled or multiplied 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
|
||||||
|
}
|
||||||
|
|
15
patch/vanitygaps.h
Normal file
15
patch/vanitygaps.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* 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);
|
||||||
|
|
||||||
|
/* Internals */
|
||||||
|
static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc);
|
||||||
|
static void setgaps(int oh, int ov, int ih, int iv);
|
||||||
|
|
43
transient.c
Normal file
43
transient.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/* cc transient.c -o transient -lX11 */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
Display *d;
|
||||||
|
Window r, f, t = None;
|
||||||
|
XSizeHints h;
|
||||||
|
XEvent e;
|
||||||
|
|
||||||
|
d = XOpenDisplay(NULL);
|
||||||
|
if (!d)
|
||||||
|
exit(1);
|
||||||
|
r = DefaultRootWindow(d);
|
||||||
|
|
||||||
|
f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0);
|
||||||
|
h.min_width = h.max_width = h.min_height = h.max_height = 400;
|
||||||
|
h.flags = PMinSize | PMaxSize;
|
||||||
|
XSetWMNormalHints(d, f, &h);
|
||||||
|
XStoreName(d, f, "floating");
|
||||||
|
XMapWindow(d, f);
|
||||||
|
|
||||||
|
XSelectInput(d, f, ExposureMask);
|
||||||
|
while (1) {
|
||||||
|
XNextEvent(d, &e);
|
||||||
|
|
||||||
|
if (t == None) {
|
||||||
|
sleep(5);
|
||||||
|
t = XCreateSimpleWindow(d, r, 50, 50, 100, 100, 0, 0, 0);
|
||||||
|
XSetTransientForHint(d, t, f);
|
||||||
|
XStoreName(d, t, "transient");
|
||||||
|
XMapWindow(d, t);
|
||||||
|
XSelectInput(d, t, ExposureMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XCloseDisplay(d);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
36
util.c
Normal file
36
util.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
void *
|
||||||
|
ecalloc(size_t nmemb, size_t size)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
if (!(p = calloc(nmemb, size)))
|
||||||
|
die("calloc:");
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
die(const char *fmt, ...) {
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
|
||||||
|
fputc(' ', stderr);
|
||||||
|
perror(NULL);
|
||||||
|
} else {
|
||||||
|
fputc('\n', stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
19
util.h
Normal file
19
util.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
|
||||||
|
#ifndef MAX
|
||||||
|
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||||
|
#endif
|
||||||
|
#ifndef MIN
|
||||||
|
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||||
|
#endif
|
||||||
|
#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);
|
||||||
|
|
BIN
util.o
Normal file
BIN
util.o
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user