Some changes
parent
1b91a8df3d
commit
202a8614cd
32
Makefile
32
Makefile
|
@ -6,13 +6,13 @@ include config.mk
|
||||||
SRC = drw.c dwm.c util.c
|
SRC = drw.c dwm.c util.c
|
||||||
OBJ = ${SRC:.c=.o}
|
OBJ = ${SRC:.c=.o}
|
||||||
|
|
||||||
all: options dwm
|
# FreeBSD users, prefix all ifdef, else and endif statements with a . for this to work (e.g. .ifdef)
|
||||||
|
|
||||||
options:
|
ifdef YAJLLIBS
|
||||||
@echo dwm build options:
|
all: dwm dwm-msg
|
||||||
@echo "CFLAGS = ${CFLAGS}"
|
else
|
||||||
@echo "LDFLAGS = ${LDFLAGS}"
|
all: dwm
|
||||||
@echo "CC = ${CC}"
|
endif
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
${CC} -c ${CFLAGS} $<
|
${CC} -c ${CFLAGS} $<
|
||||||
|
@ -25,8 +25,14 @@ config.h:
|
||||||
dwm: ${OBJ}
|
dwm: ${OBJ}
|
||||||
${CC} -o $@ ${OBJ} ${LDFLAGS}
|
${CC} -o $@ ${OBJ} ${LDFLAGS}
|
||||||
|
|
||||||
|
ifdef YAJLLIBS
|
||||||
|
dwm-msg:
|
||||||
|
${CC} -o $@ patch/ipc/dwm-msg.c ${LDFLAGS}
|
||||||
|
endif
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz
|
rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz
|
||||||
|
rm -f dwm-msg
|
||||||
|
|
||||||
dist: clean
|
dist: clean
|
||||||
mkdir -p dwm-${VERSION}
|
mkdir -p dwm-${VERSION}
|
||||||
|
@ -39,13 +45,23 @@ dist: clean
|
||||||
install: all
|
install: all
|
||||||
mkdir -p ${DESTDIR}${PREFIX}/bin
|
mkdir -p ${DESTDIR}${PREFIX}/bin
|
||||||
cp -f dwm ${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
|
chmod 755 ${DESTDIR}${PREFIX}/bin/dwm
|
||||||
|
ifdef YAJLLIBS
|
||||||
|
chmod 755 ${DESTDIR}${PREFIX}/bin/dwm-msg
|
||||||
|
endif
|
||||||
mkdir -p ${DESTDIR}${MANPREFIX}/man1
|
mkdir -p ${DESTDIR}${MANPREFIX}/man1
|
||||||
sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1
|
sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1
|
||||||
chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1
|
chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1
|
||||||
|
mkdir -p ${DESTDIR}${PREFIX}/share/xsessions
|
||||||
|
test -f ${DESTDIR}${PREFIX}/share/xsessions/dwm.desktop || cp -n dwm.desktop ${DESTDIR}${PREFIX}/share/xsessions
|
||||||
|
chmod 644 ${DESTDIR}${PREFIX}/share/xsessions/dwm.desktop
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
rm -f ${DESTDIR}${PREFIX}/bin/dwm\
|
rm -f ${DESTDIR}${PREFIX}/bin/dwm\
|
||||||
${DESTDIR}${MANPREFIX}/man1/dwm.1
|
${DESTDIR}${MANPREFIX}/man1/dwm.1\
|
||||||
|
${DESTDIR}${PREFIX}/share/xsessions/dwm.desktop
|
||||||
|
|
||||||
.PHONY: all options clean dist install uninstall
|
.PHONY: all clean dist install uninstall
|
||||||
|
|
|
@ -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.
|
483
config.def.h
483
config.def.h
|
@ -1,227 +1,314 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
|
||||||
/* appearance */
|
/* appearance */
|
||||||
#include <X11/XF86keysym.h>
|
static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||||
static const unsigned int borderpx = 1; /* border pixel of windows */
|
static const unsigned int snap = 32; /* snap pixel */
|
||||||
static const int user_bh = 27; /* 0 means that dwm will calculate bar height, >=
|
static const unsigned int gappih = 20; /* horiz inner gap between windows */
|
||||||
1 means dwm will user_bh as bar height */
|
static const unsigned int gappiv = 10; /* vert inner gap between windows */
|
||||||
static const int swallowfloating =
|
static const unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */
|
||||||
0; /* 1 means swallow floating windows by default */
|
static const unsigned int gappov = 30; /* vert outer gap between windows and screen edge */
|
||||||
static const unsigned int snap = 1; /* snap pixel */
|
static const int smartgaps_fact = 1; /* gap factor when there is only one client; 0 = no gaps, 3 = 3x outer gaps */
|
||||||
static const unsigned int gappih = 6; /* horiz inner gap between windows */
|
static const int showbar = 1; /* 0 means no bar */
|
||||||
static const unsigned int gappiv = 6; /* vert inner gap between windows */
|
static const int topbar = 1; /* 0 means bottom bar */
|
||||||
static const unsigned int gappoh =
|
static const int bar_height = 0; /* 0 means derive from font, >= 1 explicit height */
|
||||||
6; /* horiz outer gap between windows and screen edge */
|
/* Status is to be shown on: -1 (all monitors), 0 (a specific monitor by index), 'A' (active monitor) */
|
||||||
static const unsigned int gappov =
|
static const int statusmon = 'A';
|
||||||
6; /* vert outer gap between windows and screen edge */
|
static const unsigned int ulinepad = 5; /* horizontal padding between the underline and tag */
|
||||||
static const char buttonbar[] = " ";
|
static const unsigned int ulinestroke = 2; /* thickness / height of the underline */
|
||||||
static int smartgaps =
|
static const unsigned int ulinevoffset = 0; /* how far above the bottom of the bar the line should appear */
|
||||||
0; /* 1 means no outer gap when there is only one window */
|
static const int ulineall = 0; /* 1 to show underline on all tags, 0 for just the active ones */
|
||||||
static const int showbar = 1; /* 0 means no bar */
|
|
||||||
static const int topbar = 1; /* 0 means bottom bar */
|
|
||||||
static const int horizpadbar = 3; /* horizontal padding for statusbar */
|
|
||||||
static const int vertpadbar = 10; /* vertical padding for statusbar */
|
|
||||||
static const int vertpad = 0; /* vertical padding of bar */
|
|
||||||
static const int sidepad = 0; /* horizontal padding of bar */
|
|
||||||
static const unsigned int systraypinning =
|
|
||||||
0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor
|
|
||||||
X */
|
|
||||||
static const unsigned int systrayonleft =
|
|
||||||
0; /* 0: systray in the right corner, >0: systray on left of status text */
|
|
||||||
static const unsigned int systrayspacing = 2; /* systray spacing */
|
|
||||||
static const int systraypinningfailfirst =
|
|
||||||
1; /* 1: if pinning fails, display systray on the first monitor, False:
|
|
||||||
display systray on the last monitor*/
|
|
||||||
static const unsigned int systrayiconsize = 20; /* systray icon size in px */
|
|
||||||
static const int showsystray = 1; /* 0 means no systray */
|
|
||||||
static const char *fonts[] = {
|
|
||||||
"Iosevka Nerd Font:size=12:style=Regular",
|
|
||||||
"Noto Color Emoji:size=12:antialias=true:autohint=true",
|
|
||||||
"Material Design Icons Desktop:size=11"};
|
|
||||||
static const char dmenufont[] = "Iosevka Nerd Font:size=12";
|
|
||||||
static const char col_back[] = "#121111";
|
|
||||||
static const char col_gray1[] = "#212126";
|
|
||||||
static const char col_gray2[] = "#444444";
|
|
||||||
static const char col_gray3[] = "#bbbbbb";
|
|
||||||
static const char col_gray4[] = "#dbdfdf";
|
|
||||||
static const char col_blue[] = "#808fbe";
|
|
||||||
static const char col_orange[] = "#eaac79";
|
|
||||||
static const char col_red[] = "#c15a5e";
|
|
||||||
static const char col_green[] = "#8fa176";
|
|
||||||
static const char col_cyan[] = "#8cb5af";
|
|
||||||
static const char col_yellow[] = "#d8b170";
|
|
||||||
static const char col_magenta[] = "#b183ba";
|
|
||||||
|
|
||||||
static const char *colors[][3] = {
|
|
||||||
/* fg bg border */
|
|
||||||
[SchemeNorm] = {col_gray3, col_back, col_gray2},
|
/* Indicators: see patch/bar_indicators.h for options */
|
||||||
[SchemeBtn] = {col_blue, col_gray1, col_gray2},
|
static int tagindicatortype = INDICATOR_TOP_LEFT_SQUARE;
|
||||||
[SchemeLt] = {col_gray4, col_back, col_gray2},
|
static int tiledindicatortype = INDICATOR_NONE;
|
||||||
[SchemeSel] = {col_gray4, col_blue, col_blue},
|
static int floatindicatortype = INDICATOR_TOP_LEFT_SQUARE;
|
||||||
};
|
static const char *fonts[] = { "monospace:size=10" };
|
||||||
static const char *tagsel[][2] = {
|
static const char dmenufont[] = "monospace:size=10";
|
||||||
{col_green, col_back}, {col_red, col_back}, {col_yellow, col_back},
|
|
||||||
{col_blue, col_back}, {col_magenta, col_back}, {col_cyan, col_back},
|
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 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 },
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const char *name;
|
|
||||||
const void *cmd;
|
|
||||||
} Sp;
|
|
||||||
const char *spcmd1[] = {"st", "-n", "spterm", "-g", "120x28", NULL};
|
/* Tags
|
||||||
const char *spcmd2[] = {"st", "-n", "spmpd", "-e", "ncmpcpp", NULL};
|
* In a traditional dwm the number of tags in use can be changed simply by changing the number
|
||||||
static Sp scratchpads[] = {
|
* of strings in the tags array. This build does things a bit different which has some added
|
||||||
/* name cmd */
|
* benefits. If you need to change the number of tags here then change the NUMTAGS macro in dwm.c.
|
||||||
{"spterm", spcmd1},
|
*
|
||||||
{"spmpd", spcmd2},
|
* 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>" },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const StatusCmd statuscmds[] = {
|
|
||||||
{"~/.local/bin/statusbar/power", 1},
|
|
||||||
{"~/.local/bin/statusbar/wifi", 2},
|
|
||||||
{"~/.local/bin/statusbar/calendar", 3},
|
|
||||||
{"~/.local/bin/statusbar/battery", 4},
|
|
||||||
{"~/.local/bin/statusbar/sound", 5},
|
|
||||||
{"~/.local/bin/statusbar/mindash", 6},
|
|
||||||
{"~/.local/bin/statusbar/mincalendar", 7},
|
|
||||||
{"~/.local/bin/statusbar/notifications", 8},
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *statuscmd[] = {"/bin/bash", "-c", NULL, NULL};
|
|
||||||
|
|
||||||
/* tagging */
|
|
||||||
static char *tags[] = {"cmd", "www", "dev", "chat", "sys", "med"};
|
|
||||||
static char *alttags[] = {"[cmd]", "[www]", "[dev]",
|
|
||||||
"[chat]", "[sys]", "[med]"};
|
|
||||||
static const unsigned int ulinepad =
|
|
||||||
2; /* horizontal padding between the underline and tag */
|
|
||||||
static const unsigned int ulinestroke =
|
|
||||||
2; /* thickness / height of the underline */
|
|
||||||
static const unsigned int ulinevoffset =
|
|
||||||
0; /* how far above the bottom of the bar the line should appear */
|
|
||||||
static const int ulineall =
|
|
||||||
0; /* 1 to show underline on all tags, 0 for just the active ones */
|
|
||||||
|
|
||||||
|
/* 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[] = {
|
static const Rule rules[] = {
|
||||||
/* xprop(1):
|
/* xprop(1):
|
||||||
* WM_CLASS(STRING) = instance, class
|
* WM_CLASS(STRING) = instance, class
|
||||||
* WM_NAME(STRING) = title
|
* WM_NAME(STRING) = title
|
||||||
*/
|
* WM_WINDOW_ROLE(STRING) = role
|
||||||
/* class instance title tags mask isfloating isterminal
|
* _NET_WM_WINDOW_TYPE(ATOM) = wintype
|
||||||
noswallow monitor */
|
*/
|
||||||
{"Gimp", NULL, NULL, 0, 1, 0, 0, -1},
|
RULE(.wintype = WTYPE "DIALOG", .isfloating = 1)
|
||||||
{"Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1},
|
RULE(.wintype = WTYPE "UTILITY", .isfloating = 1)
|
||||||
{"st-256color", NULL, NULL, 0, 0, 1, 0, -1},
|
RULE(.wintype = WTYPE "TOOLBAR", .isfloating = 1)
|
||||||
{NULL, NULL, "Event Tester", 0, 0, 0, 1, -1}, /* xev */
|
RULE(.wintype = WTYPE "SPLASH", .isfloating = 1)
|
||||||
{NULL, "spterm", NULL, SPTAG(0), 1, 1, 0, -1},
|
RULE(.class = "Gimp", .tags = 1 << 4)
|
||||||
{NULL, "spmpd", NULL, SPTAG(1), 1, 1, 0, -1},
|
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 hoverfunc name */
|
||||||
|
{ -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, hover_tags, "tags" },
|
||||||
|
{ -1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, NULL, "layout" },
|
||||||
|
{ statusmon, 0, BAR_ALIGN_RIGHT, width_status2d, draw_status2d, click_status2d, NULL, "status2d" },
|
||||||
|
{ -1, 0, BAR_ALIGN_NONE, width_wintitle, draw_wintitle, click_wintitle, NULL, "wintitle" },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* layout(s) */
|
/* layout(s) */
|
||||||
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
|
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 nmaster = 1; /* number of clients in master area */
|
||||||
static const int resizehints =
|
static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */
|
||||||
1; /* 1 means respect size hints in tiled resizals */
|
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
|
||||||
static const int lockfullscreen =
|
|
||||||
1; /* 1 will force focus on the fullscreen window */
|
|
||||||
|
|
||||||
#define FORCE_VSPLIT \
|
|
||||||
1 /* nrowgrid layout: force two clients to always split vertically */
|
|
||||||
#include "vanitygaps.c"
|
|
||||||
|
|
||||||
static const Layout layouts[] = {
|
static const Layout layouts[] = {
|
||||||
/* symbol arrange function */
|
/* symbol arrange function */
|
||||||
{"[]", tile}, /* first entry is default */
|
{ "[]=", tile }, /* first entry is default */
|
||||||
{"//", NULL}, /* no layout function means floating behavior */
|
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||||
{"[@]", spiral}, {"[\\]", dwindle},
|
{ "[M]", monocle },
|
||||||
{"[M]", monocle}, {"|M|", centeredmaster},
|
{ ":::", gaplessgrid },
|
||||||
{NULL, NULL},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* key definitions */
|
/* key definitions */
|
||||||
#define MODKEY Mod4Mask
|
#define MODKEY Mod1Mask
|
||||||
#define TAGKEYS(KEY, TAG) \
|
#define TAGKEYS(KEY,TAG) \
|
||||||
{MODKEY, KEY, view, {.ui = 1 << TAG}}, \
|
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
||||||
{MODKEY | ControlMask, KEY, toggleview, {.ui = 1 << TAG}}, \
|
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
|
||||||
{MODKEY | ShiftMask, KEY, tag, {.ui = 1 << TAG}}, \
|
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
|
||||||
{MODKEY | ControlMask | ShiftMask, KEY, toggletag, {.ui = 1 << TAG}},
|
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
||||||
#define SHCMD(cmd) \
|
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
||||||
{ \
|
|
||||||
.v = (const char *[]) { "/bin/sh", "-c", cmd, NULL } \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* commands */
|
/* commands */
|
||||||
static const char *btncmd[] = {"rofi", "-show", "drun", NULL};
|
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 Key keys[] = {
|
static const Key keys[] = {
|
||||||
/* modifier key function argument */
|
/* modifier key function argument */
|
||||||
{MODKEY, XK_b, togglebar, {0}},
|
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
||||||
{MODKEY, XK_j, focusstack, {.i = +1}},
|
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
|
||||||
{MODKEY, XK_k, focusstack, {.i = -1}},
|
{ MODKEY, XK_b, togglebar, {0} },
|
||||||
{MODKEY, XK_i, incnmaster, {.i = +1}},
|
{ MODKEY, XK_j, focusstack, {.i = +1 } },
|
||||||
{MODKEY, XK_d, incnmaster, {.i = -1}},
|
{ MODKEY, XK_k, focusstack, {.i = -1 } },
|
||||||
{MODKEY, XK_h, setmfact, {.f = -0.05}},
|
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
|
||||||
{MODKEY, XK_l, setmfact, {.f = +0.05}},
|
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
||||||
{MODKEY | ShiftMask, XK_h, setcfact, {.f = +0.25}},
|
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
||||||
{MODKEY | ShiftMask, XK_l, setcfact, {.f = -0.25}},
|
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
||||||
{MODKEY | ShiftMask, XK_o, setcfact, {.f = 0.00}},
|
{ MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
|
||||||
{MODKEY, XK_Return, zoom, {0}},
|
{ MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
|
||||||
{MODKEY | Mod4Mask, XK_u, incrgaps, {.i = +1}},
|
{ MODKEY, XK_Return, zoom, {0} },
|
||||||
{MODKEY | Mod4Mask | ShiftMask, XK_u, incrgaps, {.i = -1}},
|
{ MODKEY|Mod4Mask, XK_u, incrgaps, {.i = +1 } },
|
||||||
{MODKEY | Mod4Mask, XK_i, incrigaps, {.i = +1}},
|
{ MODKEY|Mod4Mask|ShiftMask, XK_u, incrgaps, {.i = -1 } },
|
||||||
{MODKEY | Mod4Mask | ShiftMask, XK_i, incrigaps, {.i = -1}},
|
{ MODKEY|Mod4Mask, XK_i, incrigaps, {.i = +1 } },
|
||||||
{MODKEY | Mod4Mask, XK_o, incrogaps, {.i = +1}},
|
{ MODKEY|Mod4Mask|ShiftMask, XK_i, incrigaps, {.i = -1 } },
|
||||||
{MODKEY | Mod4Mask | ShiftMask, XK_o, incrogaps, {.i = -1}},
|
{ MODKEY|Mod4Mask, XK_o, incrogaps, {.i = +1 } },
|
||||||
{MODKEY | Mod4Mask, XK_6, incrihgaps, {.i = +1}},
|
{ MODKEY|Mod4Mask|ShiftMask, XK_o, incrogaps, {.i = -1 } },
|
||||||
{MODKEY | Mod4Mask | ShiftMask, XK_6, incrihgaps, {.i = -1}},
|
{ MODKEY|Mod4Mask, XK_6, incrihgaps, {.i = +1 } },
|
||||||
{MODKEY | Mod4Mask, XK_7, incrivgaps, {.i = +1}},
|
{ MODKEY|Mod4Mask|ShiftMask, XK_6, incrihgaps, {.i = -1 } },
|
||||||
{MODKEY | Mod4Mask | ShiftMask, XK_7, incrivgaps, {.i = -1}},
|
{ MODKEY|Mod4Mask, XK_7, incrivgaps, {.i = +1 } },
|
||||||
{MODKEY | Mod4Mask, XK_8, incrohgaps, {.i = +1}},
|
{ MODKEY|Mod4Mask|ShiftMask, XK_7, incrivgaps, {.i = -1 } },
|
||||||
{MODKEY | Mod4Mask | ShiftMask, XK_8, incrohgaps, {.i = -1}},
|
{ MODKEY|Mod4Mask, XK_8, incrohgaps, {.i = +1 } },
|
||||||
{MODKEY | Mod4Mask, XK_9, incrovgaps, {.i = +1}},
|
{ MODKEY|Mod4Mask|ShiftMask, XK_8, incrohgaps, {.i = -1 } },
|
||||||
{MODKEY | Mod4Mask | ShiftMask, XK_9, incrovgaps, {.i = -1}},
|
{ MODKEY|Mod4Mask, XK_9, incrovgaps, {.i = +1 } },
|
||||||
{MODKEY | Mod4Mask, XK_0, togglegaps, {0}},
|
{ MODKEY|Mod4Mask|ShiftMask, XK_9, incrovgaps, {.i = -1 } },
|
||||||
{MODKEY | Mod4Mask | ShiftMask, XK_0, defaultgaps, {0}},
|
{ MODKEY|Mod4Mask, XK_0, togglegaps, {0} },
|
||||||
{MODKEY, XK_Tab, view, {0}},
|
{ MODKEY|Mod4Mask|ShiftMask, XK_0, defaultgaps, {0} },
|
||||||
{MODKEY | ShiftMask, XK_c, killclient, {0}},
|
{ MODKEY, XK_Tab, view, {0} },
|
||||||
{MODKEY, XK_t, setlayout, {.v = &layouts[0]}},
|
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
|
||||||
{MODKEY, XK_f, setlayout, {.v = &layouts[1]}},
|
{ MODKEY|ShiftMask, XK_q, quit, {0} },
|
||||||
{MODKEY, XK_m, setlayout, {.v = &layouts[2]}},
|
{ MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} },
|
||||||
{MODKEY | ControlMask, XK_comma, cyclelayout, {.i = -1}},
|
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
||||||
{MODKEY | ControlMask, XK_period, cyclelayout, {.i = +1}},
|
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
|
||||||
{MODKEY, XK_space, setlayout, {0}},
|
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
||||||
{MODKEY | ShiftMask, XK_space, togglefloating, {0}},
|
{ MODKEY, XK_space, setlayout, {0} },
|
||||||
{MODKEY | ShiftMask, XK_f, togglefullscr, {0}},
|
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
||||||
{MODKEY, XK_0, view, {.ui = ~0}},
|
{ MODKEY, XK_y, togglefullscreen, {0} },
|
||||||
{MODKEY | ShiftMask, XK_0, tag, {.ui = ~0}},
|
{ MODKEY|ShiftMask, XK_f, fullscreen, {0} },
|
||||||
{MODKEY, XK_comma, focusmon, {.i = -1}},
|
{ MODKEY, XK_0, view, {.ui = ~0 } },
|
||||||
{MODKEY, XK_period, focusmon, {.i = +1}},
|
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
|
||||||
{MODKEY | ShiftMask, XK_comma, tagmon, {.i = -1}},
|
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
|
||||||
{MODKEY | ShiftMask, XK_period, tagmon, {.i = +1}},
|
{ MODKEY, XK_period, focusmon, {.i = +1 } },
|
||||||
{MODKEY | ShiftMask, XK_b, togglescratch, {.ui = 0}},
|
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
|
||||||
{MODKEY | ShiftMask, XK_v, togglescratch, {.ui = 1}},
|
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
|
||||||
TAGKEYS(XK_1, 0) TAGKEYS(XK_2, 1) TAGKEYS(XK_3, 2) TAGKEYS(XK_4, 3)
|
TAGKEYS( XK_1, 0)
|
||||||
TAGKEYS(XK_5, 4) TAGKEYS(XK_6, 5)
|
TAGKEYS( XK_2, 1)
|
||||||
TAGKEYS(XK_7, 6){MODKEY | ShiftMask, XK_q, quit, {0}},
|
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 */
|
/* button definitions */
|
||||||
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
|
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
|
||||||
* ClkClientWin, or ClkRootWin */
|
|
||||||
static const Button buttons[] = {
|
static const Button buttons[] = {
|
||||||
/* click event mask button function argument */
|
/* click event mask button function argument */
|
||||||
{ClkButton, 0, Button1, spawn, {.v = btncmd}},
|
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
|
||||||
{ClkLtSymbol, 0, Button1, setlayout, {0}},
|
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
||||||
{ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]}},
|
{ ClkWinTitle, 0, Button2, zoom, {0} },
|
||||||
{ClkStatusText, 0, Button1, spawn, {.v = statuscmd}},
|
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
|
||||||
{ClkStatusText, 0, Button2, spawn, {.v = statuscmd}},
|
/* placemouse options, choose which feels more natural:
|
||||||
{ClkStatusText, 0, Button3, spawn, {.v = statuscmd}},
|
* 0 - tiled position is relative to mouse cursor
|
||||||
{ClkClientWin, MODKEY, Button1, movemouse, {0}},
|
* 1 - tiled postiion is relative to window center
|
||||||
{ClkClientWin, MODKEY, Button2, togglefloating, {0}},
|
* 2 - mouse pointer warps to window center
|
||||||
{ClkClientWin, MODKEY, Button3, resizemouse, {0}},
|
*
|
||||||
{ClkTagBar, 0, Button1, view, {0}},
|
* The moveorplace uses movemouse or placemouse depending on the floating state
|
||||||
{ClkTagBar, 0, Button3, toggleview, {0}},
|
* of the selected client. Set up individual keybindings for the two if you want
|
||||||
{ClkTagBar, MODKEY, Button1, tag, {0}},
|
* to control these separately (i.e. to retain the feature to move a tiled window
|
||||||
{ClkTagBar, MODKEY, Button3, toggletag, {0}},
|
* into a floating position).
|
||||||
|
*/
|
||||||
|
{ ClkClientWin, MODKEY, Button1, moveorplace, {.i = 1} },
|
||||||
|
{ 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} },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
421
config.h
421
config.h
|
@ -1,249 +1,238 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
|
||||||
/* appearance */
|
/* appearance */
|
||||||
#include <X11/XF86keysym.h>
|
static const unsigned int borderpx = 2; /* border pixel of windows */
|
||||||
|
static const unsigned int snap = 32; /* snap pixel */
|
||||||
|
static const unsigned int gappih = 7; /* horiz inner gap between windows */
|
||||||
|
static const unsigned int gappiv = 7; /* vert inner gap between windows */
|
||||||
|
static const unsigned int gappoh = 7; /* horiz outer gap between windows and screen edge */
|
||||||
|
static const unsigned int gappov = 7; /* 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 int showbar = 1; /* 0 means no bar */
|
||||||
|
static const int topbar = 1; /* 0 means bottom bar */
|
||||||
|
static const int bar_height = 37; /* 0 means derive from font, >= 1 explicit height */
|
||||||
|
/* 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 ulinepad = 3; /* horizontal padding between the underline and tag */
|
||||||
|
static const unsigned int ulinestroke = 3; /* thickness / height of the underline */
|
||||||
|
static const unsigned int ulinevoffset = 0; /* how far above the bottom of the bar the line should appear */
|
||||||
|
static const int ulineall = 0; /* 1 to show underline on all tags, 0 for just the active ones */
|
||||||
|
|
||||||
static const unsigned int borderpx = 2; /* border pixel of windows */
|
|
||||||
static const int user_bh = 27; /* 0 means that dwm will calculate bar height, >=
|
|
||||||
1 means dwm will user_bh as bar height */
|
/* Indicators: see patch/bar_indicators.h for options */
|
||||||
static const int swallowfloating =
|
static int tagindicatortype = INDICATOR_NONE;
|
||||||
0; /* 1 means swallow floating windows by default */
|
static int tiledindicatortype = INDICATOR_NONE;
|
||||||
static const unsigned int snap = 1; /* snap pixel */
|
static int floatindicatortype = INDICATOR_NONE;
|
||||||
static const unsigned int gappih = 7; /* horiz inner gap between windows */
|
static const char *fonts[] = {
|
||||||
static const unsigned int gappiv = 7; /* vert inner gap between windows */
|
|
||||||
static const unsigned int gappoh =
|
|
||||||
7; /* horiz outer gap between windows and screen edge */
|
|
||||||
static const unsigned int gappov =
|
|
||||||
7; /* vert outer gap between windows and screen edge */
|
|
||||||
static int smartgaps =
|
|
||||||
0; /* 1 means no outer gap when there is only one window */
|
|
||||||
static const int showbar = 1; /* 0 means no bar */
|
|
||||||
static const int topbar = 1; /* 0 means bottom bar */
|
|
||||||
static const int horizpadbar = 10; /* horizontal padding for statusbar */
|
|
||||||
static const int vertpadbar = 10; /* vertical padding for statusbar */
|
|
||||||
static const int vertpad = 0; /* vertical padding of bar */
|
|
||||||
static const int sidepad = 0; /* horizontal padding of bar */
|
|
||||||
static const unsigned int systraypinning =
|
|
||||||
0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor
|
|
||||||
X */
|
|
||||||
static const unsigned int systrayonleft =
|
|
||||||
0; /* 0: systray in the right corner, >0: systray on left of status text */
|
|
||||||
static const unsigned int systrayspacing = 2; /* systray spacing */
|
|
||||||
static const int systraypinningfailfirst =
|
|
||||||
1; /* 1: if pinning fails, display systray on the first monitor, False:
|
|
||||||
display systray on the last monitor*/
|
|
||||||
static const unsigned int systrayiconsize = 20; /* systray icon size in px */
|
|
||||||
static const int showsystray = 1; /* 0 means no systray */
|
|
||||||
static const char *fonts[] = {
|
|
||||||
"Iosevka Nerd Font:size=12:style=Regular",
|
"Iosevka Nerd Font:size=12:style=Regular",
|
||||||
"Noto Color Emoji:size=12:antialias=true:autohint=true",
|
"Noto Color Emoji:size=12:antialias=true:autohint=true",
|
||||||
"Material Design Icons Desktop:size=11"};
|
"Material Design Icons Desktop:size=11"};
|
||||||
static const char dmenufont[] = "Iosevka Nerd Font:size=12";
|
static char c000000[] = "#000000"; // placeholder value
|
||||||
static const char col_back[] = "#010101";
|
|
||||||
static const char col_gray1[] = "#212126";
|
|
||||||
static const char col_gray2[] = "#444444";
|
|
||||||
static const char col_gray3[] = "#bbbbbb";
|
|
||||||
static const char col_gray4[] = "#dbdfdf";
|
|
||||||
static const char col_blue[] = "#808fbe";
|
|
||||||
static const char col_orange[] = "#eaac79";
|
|
||||||
static const char col_red[] = "#c15a5e";
|
|
||||||
static const char col_green[] = "#8fa176";
|
|
||||||
static const char col_cyan[] = "#8cb5af";
|
|
||||||
static const char col_yellow[] = "#d8b170";
|
|
||||||
static const char col_magenta[] = "#b183ba";
|
|
||||||
|
|
||||||
static const char *colors[][3] = {
|
static char normfgcolor[] = "#bbbbbb";
|
||||||
/* fg bg border */
|
static char normbgcolor[] = "#010101";
|
||||||
[SchemeNorm] = {col_gray3, col_back, col_gray1},
|
static char normbordercolor[] = "#212126";
|
||||||
[SchemeBtn] = {col_blue, col_gray1, col_gray1},
|
static char normfloatcolor[] = "#212126";
|
||||||
[SchemeLt] = {col_gray4, col_back, col_gray1},
|
|
||||||
[SchemeSel] = {col_gray4, col_blue, col_gray2},
|
static char selfgcolor[] = "#dbdbdf";
|
||||||
};
|
static char selbgcolor[] = "#bbbbbb";
|
||||||
static const char *tagsel[][2] = {
|
static char selbordercolor[] = "#444444";
|
||||||
{col_green, col_back}, {col_red, col_back}, {col_yellow, col_back},
|
static char selfloatcolor[] = "#444444";
|
||||||
{col_blue, col_back}, {col_magenta, col_back}, {col_cyan, col_back},
|
|
||||||
|
static char titlenormfgcolor[] = "#bbbbbb";
|
||||||
|
static char titlenormbgcolor[] = "#010101";
|
||||||
|
static char titlenormbordercolor[] = "#212126";
|
||||||
|
static char titlenormfloatcolor[] = "#212126";
|
||||||
|
|
||||||
|
static char titleselfgcolor[] = "#bbbbbb";
|
||||||
|
static char titleselbgcolor[] = "#010101";
|
||||||
|
static char titleselbordercolor[] = "#212126";
|
||||||
|
static char titleselfloatcolor[] = "#212126";
|
||||||
|
|
||||||
|
static char tagsnormfgcolor[] = "#dbdbdf";
|
||||||
|
static char tagsnormbgcolor[] = "#010101";
|
||||||
|
static char tagsnormbordercolor[] = "#dbdbdf";
|
||||||
|
static char tagsnormfloatcolor[] = "#dbdbdf";
|
||||||
|
|
||||||
|
static char tagsselfgcolor[] = "#656565";
|
||||||
|
static char tagsselbgcolor[] = "#010101";
|
||||||
|
static char tagsselbordercolor[] = "#656565";
|
||||||
|
static char tagsselfloatcolor[] = "#656565";
|
||||||
|
|
||||||
|
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 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 },
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
static char *tagicons[][NUMTAGS] =
|
||||||
const char *name;
|
{
|
||||||
const void *cmd;
|
[DEFAULT_TAGS] = { " cmd ", " www ", " dev ", " chat ", " sys ", " med " },
|
||||||
} Sp;
|
[ALT_TAGS_DECORATION] = { "[cmd]", "[www]", "[dev]", "[chat]", "[sys]", "[med]" },
|
||||||
const char *terminal[] = {"st", NULL};
|
|
||||||
const char *scrot[] = {"screenshot_fullscreen", NULL};
|
|
||||||
const char *scrots[] = {"screenshot_select", NULL};
|
|
||||||
/*const char *launch[] = {"dmenu_run", "-h '37'", "-nf '#bbbbbb'", "-nb '#000000'", "-sf '#dbdfdf'", "-sb '#000000'", "-p ' |Search:'", "-fn 'Iosevka Nerd Font:size=12:style=regular," ,NULL};*/
|
|
||||||
const char *launch[] = {"run", NULL};
|
|
||||||
|
|
||||||
static Sp scratchpads[] = {
|
|
||||||
/* name cmd */
|
|
||||||
{"launch", launch},
|
|
||||||
{"terminal", terminal},
|
|
||||||
{"scrot", scrot},
|
|
||||||
{"scrots", scrots},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <X11/XF86keysym.h>
|
|
||||||
|
|
||||||
/* Add somewhere in your constants definition section */
|
|
||||||
static const char *upvol[] = { "pactl", "set-sink-volume", "0", "+5%", NULL };
|
|
||||||
static const char *downvol[] = { "pactl", "set-sink-volume", "0", "-5%", NULL };
|
|
||||||
static const char *mutevol[] = { "pactl", "set-sink-mute", "0", "toggle", NULL };
|
|
||||||
|
|
||||||
static const StatusCmd statuscmds[] = {
|
|
||||||
{"~/.local/bin/statusbar/power", 1},
|
|
||||||
{"~/.local/bin/statusbar/wifi", 2},
|
|
||||||
{"~/.local/bin/statusbar/calendar", 3},
|
|
||||||
{"~/.local/bin/statusbar/battery", 4},
|
|
||||||
{"~/.local/bin/statusbar/sound", 5},
|
|
||||||
{"~/.local/bin/statusbar/mindash", 6},
|
|
||||||
{"~/.local/bin/statusbar/mincalendar", 7},
|
|
||||||
{"~/.local/bin/statusbar/notifications", 8},
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *statuscmd[] = {"/bin/bash", "-c", NULL, NULL};
|
|
||||||
|
|
||||||
/* tagging */
|
|
||||||
static char *tags[] = {"cmd", "www", "dev", "chat", "sys", "med"};
|
|
||||||
static char *alttags[] = {"[cmd]", "[www]", "[dev]",
|
|
||||||
"[chat]", "[sys]", "[med]"};
|
|
||||||
static const unsigned int ulinepad =
|
|
||||||
2; /* horizontal padding between the underline and tag */
|
|
||||||
static const unsigned int ulinestroke =
|
|
||||||
2; /* thickness / height of the underline */
|
|
||||||
static const unsigned int ulinevoffset =
|
|
||||||
0; /* how far above the bottom of the bar the line should appear */
|
|
||||||
static const int ulineall =
|
|
||||||
0; /* 1 to show underline on all tags, 0 for just the active ones */
|
|
||||||
|
|
||||||
static const Rule rules[] = {
|
static const Rule rules[] = {
|
||||||
/* xprop(1):
|
RULE(.wintype = WTYPE "DIALOG", .isfloating = 1)
|
||||||
* WM_CLASS(STRING) = instance, class
|
RULE(.wintype = WTYPE "UTILITY", .isfloating = 1)
|
||||||
* WM_NAME(STRING) = title
|
RULE(.wintype = WTYPE "TOOLBAR", .isfloating = 1)
|
||||||
*/
|
RULE(.wintype = WTYPE "SPLASH", .isfloating = 1)
|
||||||
/* class instance title tags mask isfloating isterminal
|
RULE(.class = "Gimp", .tags = 1 << 4)
|
||||||
noswallow monitor */
|
RULE(.class = "Firefox", .tags = 1 << 7)
|
||||||
{"Gimp", NULL, NULL, 0, 1, 0, 0, -1},
|
};
|
||||||
{"Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1},
|
|
||||||
{"st-256color", NULL, NULL, 0, 0, 1, 0, -1},
|
static const BarRule barrules[] = {
|
||||||
{NULL, NULL, "Event Tester", 0, 0, 0, 1, -1}, /* xev */
|
/* monitor bar alignment widthfunc drawfunc clickfunc hoverfunc name */
|
||||||
{NULL, "spterm", NULL, SPTAG(0), 1, 1, 0, -1},
|
{ -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, hover_tags, "tags" },
|
||||||
{NULL, "spmpd", NULL, SPTAG(1), 1, 1, 0, -1},
|
{ -1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, NULL, "layout" },
|
||||||
|
{ statusmon, 0, BAR_ALIGN_RIGHT, width_status2d, draw_status2d, click_status2d, NULL, "status2d" },
|
||||||
|
{ -1, 0, BAR_ALIGN_NONE, width_wintitle, draw_wintitle, click_wintitle, NULL, "wintitle" },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* layout(s) */
|
/* layout(s) */
|
||||||
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
|
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 nmaster = 1; /* number of clients in master area */
|
||||||
static const int resizehints =
|
static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */
|
||||||
1; /* 1 means respect size hints in tiled resizals */
|
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
|
||||||
static const int lockfullscreen =
|
|
||||||
1; /* 1 will force focus on the fullscreen window */
|
|
||||||
|
|
||||||
#define FORCE_VSPLIT \
|
|
||||||
1 /* nrowgrid layout: force two clients to always split vertically */
|
|
||||||
#include "vanitygaps.c"
|
|
||||||
|
|
||||||
/*#include "layout_grid.h"
|
|
||||||
#include "layout_grid.c"*/
|
|
||||||
static const Layout layouts[] = {
|
static const Layout layouts[] = {
|
||||||
/* symbol arrange function */
|
/* symbol arrange function */
|
||||||
{"[]", tile}, /* first entry is default */
|
{ "[]", tile }, /* first entry is default */
|
||||||
{"{}", spiral},
|
{ "//", NULL }, /* no layout function means floating behavior */
|
||||||
{"//", NULL}, /* no layout function means floating behavior */
|
{ "[M]", monocle },
|
||||||
/* {"[@]", spiral}, {"[\\]", dwindle},*/
|
{ "#", gaplessgrid },
|
||||||
{"[M]", monocle}, {"|M|", centeredmaster},
|
|
||||||
{NULL, NULL},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* key definitions */
|
/* key definitions */
|
||||||
#define MODKEY Mod4Mask
|
#define MODKEY Mod4Mask
|
||||||
#define TAGKEYS(KEY, TAG) \
|
#define TAGKEYS(KEY,TAG) \
|
||||||
{MODKEY, KEY, view, {.ui = 1 << TAG}}, \
|
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
||||||
{MODKEY | ControlMask, KEY, toggleview, {.ui = 1 << TAG}}, \
|
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
|
||||||
{MODKEY | ShiftMask, KEY, tag, {.ui = 1 << TAG}}, \
|
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
|
||||||
{MODKEY | ControlMask | ShiftMask, KEY, toggletag, {.ui = 1 << TAG}},
|
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
||||||
#define SHCMD(cmd) \
|
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
||||||
{ \
|
|
||||||
.v = (const char *[]) { "/bin/sh", "-c", cmd, NULL } \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* commands */
|
/* commands */
|
||||||
|
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
|
||||||
|
static const char *dmenucmd[] = {
|
||||||
|
"dmenu_run",
|
||||||
|
"-h", "37",
|
||||||
|
"-nf", "#bbbbbb",
|
||||||
|
"-nb", "#010101",
|
||||||
|
"-sf", "#dbdfdf",
|
||||||
|
"-sb", "#010101",
|
||||||
|
"-p", " | Search:",
|
||||||
|
"-fn", "Iosevka Nerd Font:size=12:style=large",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
static const char *termcmd[] = { "st", NULL };
|
||||||
|
|
||||||
|
static const char *screenshot_selectcmd[] = { "screenshot_select", NULL };
|
||||||
|
static const char *screenshotcmd[] = { "screenshot_fullscreen", NULL };
|
||||||
|
|
||||||
|
|
||||||
|
#include <X11/XF86keysym.h>
|
||||||
|
|
||||||
static const Key keys[] = {
|
static const Key keys[] = {
|
||||||
/* modifier key function argument */
|
/* modifier key function argument */
|
||||||
{MODKEY, XK_Print, spawn, {.v = scrot} },
|
{ MODKEY, XK_d, spawn, {.v = dmenucmd } },
|
||||||
{MODKEY | ShiftMask, XK_Print, spawn, {.v = scrots } },
|
{ MODKEY, XK_e, spawn, {.v = termcmd } },
|
||||||
{MODKEY, XK_e, spawn, {.v = terminal } },
|
{ MODKEY, XK_Print, spawn, {.v = screenshotcmd} },
|
||||||
{MODKEY, XK_d, spawn, {.v = launch } },
|
{ MODKEY|ShiftMask, XK_Print, spawn, {.v = screenshot_selectcmd } },
|
||||||
{MODKEY, XK_b, togglebar, {0}},
|
{ MODKEY, XK_b, togglebar, {0} },
|
||||||
{ 0, XK_F11, spawn, {.v = downvol } },
|
{ MODKEY, XK_j, focusstack, {.i = +1 } },
|
||||||
{ 0, XK_F10, spawn, {.v = mutevol } },
|
{ MODKEY, XK_k, focusstack, {.i = -1 } },
|
||||||
{ 0, XK_F12, spawn, {.v = upvol } },
|
{ MODKEY|ShiftMask, XK_i, incnmaster, {.i = +1 } },
|
||||||
/*boring stuff*/
|
{ MODKEY|ShiftMask, XK_d, incnmaster, {.i = -1 } },
|
||||||
{MODKEY, XK_j, focusstack, {.i = +1}},
|
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
||||||
{MODKEY, XK_k, focusstack, {.i = -1}},
|
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
||||||
{MODKEY, XK_i, incnmaster, {.i = +1}},
|
{ MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
|
||||||
{MODKEY, XK_h, setmfact, {.f = -0.05}},
|
{ MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
|
||||||
{MODKEY, XK_l, setmfact, {.f = +0.05}},
|
{ MODKEY, XK_Return, zoom, {0} },
|
||||||
{MODKEY | ShiftMask, XK_h, setcfact, {.f = +0.25}},
|
{ MODKEY|Mod1Mask, XK_u, incrgaps, {.i = +1 } },
|
||||||
{MODKEY | ShiftMask, XK_l, setcfact, {.f = -0.25}},
|
{ MODKEY|Mod1Mask|ShiftMask, XK_u, incrgaps, {.i = -1 } },
|
||||||
{MODKEY | ShiftMask, XK_o, setcfact, {.f = 0.00}},
|
{ MODKEY|Mod1Mask, XK_i, incrigaps, {.i = +1 } },
|
||||||
{MODKEY, XK_Return, zoom, {0}},
|
{ MODKEY|Mod1Mask|ShiftMask, XK_i, incrigaps, {.i = -1 } },
|
||||||
{MODKEY | Mod4Mask, XK_u, incrgaps, {.i = +1}},
|
{ MODKEY|Mod1Mask, XK_o, incrogaps, {.i = +1 } },
|
||||||
{MODKEY | Mod4Mask | ShiftMask, XK_u, incrgaps, {.i = -1}},
|
{ MODKEY|Mod1Mask|ShiftMask, XK_o, incrogaps, {.i = -1 } },
|
||||||
{MODKEY | Mod4Mask, XK_i, incrigaps, {.i = +1}},
|
{ MODKEY|Mod1Mask, XK_6, incrihgaps, {.i = +1 } },
|
||||||
{MODKEY | Mod4Mask | ShiftMask, XK_i, incrigaps, {.i = -1}},
|
{ MODKEY|Mod1Mask|ShiftMask, XK_6, incrihgaps, {.i = -1 } },
|
||||||
{MODKEY | Mod4Mask, XK_o, incrogaps, {.i = +1}},
|
{ MODKEY|Mod1Mask, XK_7, incrivgaps, {.i = +1 } },
|
||||||
{MODKEY | Mod4Mask | ShiftMask, XK_o, incrogaps, {.i = -1}},
|
{ MODKEY|Mod1Mask|ShiftMask, XK_7, incrivgaps, {.i = -1 } },
|
||||||
{MODKEY | Mod4Mask, XK_6, incrihgaps, {.i = +1}},
|
{ MODKEY|Mod1Mask, XK_8, incrohgaps, {.i = +1 } },
|
||||||
{MODKEY | Mod4Mask | ShiftMask, XK_6, incrihgaps, {.i = -1}},
|
{ MODKEY|Mod1Mask|ShiftMask, XK_8, incrohgaps, {.i = -1 } },
|
||||||
{MODKEY | Mod4Mask, XK_7, incrivgaps, {.i = +1}},
|
{ MODKEY|Mod1Mask, XK_9, incrovgaps, {.i = +1 } },
|
||||||
{MODKEY | Mod4Mask | ShiftMask, XK_7, incrivgaps, {.i = -1}},
|
{ MODKEY|Mod1Mask|ShiftMask, XK_9, incrovgaps, {.i = -1 } },
|
||||||
{MODKEY | Mod4Mask, XK_8, incrohgaps, {.i = +1}},
|
{ MODKEY|Mod1Mask, XK_0, togglegaps, {0} },
|
||||||
{MODKEY | Mod4Mask | ShiftMask, XK_8, incrohgaps, {.i = -1}},
|
{ MODKEY|Mod1Mask|ShiftMask, XK_0, defaultgaps, {0} },
|
||||||
{MODKEY | Mod4Mask, XK_9, incrovgaps, {.i = +1}},
|
{ MODKEY, XK_Tab, view, {0} },
|
||||||
{MODKEY | Mod4Mask | ShiftMask, XK_9, incrovgaps, {.i = -1}},
|
{ MODKEY, XK_w, killclient, {0} },
|
||||||
{MODKEY | Mod4Mask, XK_0, togglegaps, {0}},
|
{ MODKEY|ShiftMask, XK_q, quit, {0} },
|
||||||
{MODKEY | Mod4Mask | ShiftMask, XK_0, defaultgaps, {0}},
|
{ MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} },
|
||||||
{MODKEY, XK_Tab, view, {0}},
|
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
||||||
{MODKEY, XK_w, killclient, {0}},
|
{ MODKEY, XK_z, setlayout, {.v = &layouts[1]} },
|
||||||
{MODKEY, XK_t, setlayout, {.v = &layouts[0]}},
|
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
||||||
{MODKEY | ShiftMask, XK_f, setlayout, {.v = &layouts[1]}},
|
{ MODKEY, XK_x, setlayout, {.v = &layouts[3]} },
|
||||||
{MODKEY, XK_m, setlayout, {.v = &layouts[2]}},
|
{ MODKEY, XK_space, setlayout, {0} },
|
||||||
{MODKEY | ControlMask, XK_comma, cyclelayout, {.i = -1}},
|
{ MODKEY, XK_s, togglefloating, {0} },
|
||||||
{MODKEY | ControlMask, XK_period, cyclelayout, {.i = +1}},
|
{ MODKEY, XK_f, togglefullscreen, {0} },
|
||||||
{MODKEY, XK_space, setlayout, {0}},
|
{ MODKEY|ShiftMask, XK_f, fullscreen, {0} },
|
||||||
{MODKEY, XK_s, togglefloating, {0}},
|
{ MODKEY, XK_0, view, {.ui = ~0 } },
|
||||||
{MODKEY, XK_f, togglefullscr, {0}},
|
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
|
||||||
{MODKEY, XK_0, view, {.ui = ~0}},
|
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
|
||||||
{MODKEY | ShiftMask, XK_0, tag, {.ui = ~0}},
|
{ MODKEY, XK_period, focusmon, {.i = +1 } },
|
||||||
{MODKEY, XK_comma, focusmon, {.i = -1}},
|
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
|
||||||
{MODKEY, XK_period, focusmon, {.i = +1}},
|
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
|
||||||
{MODKEY | ShiftMask, XK_comma, tagmon, {.i = -1}},
|
TAGKEYS( XK_1, 0)
|
||||||
{MODKEY | ShiftMask, XK_period, tagmon, {.i = +1}},
|
TAGKEYS( XK_2, 1)
|
||||||
{MODKEY | ShiftMask, XK_b, togglescratch, {.ui = 0}},
|
TAGKEYS( XK_3, 2)
|
||||||
{MODKEY | ShiftMask, XK_v, togglescratch, {.ui = 1}},
|
TAGKEYS( XK_4, 3)
|
||||||
TAGKEYS(XK_1, 0) TAGKEYS(XK_2, 1) TAGKEYS(XK_3, 2) TAGKEYS(XK_4, 3)
|
TAGKEYS( XK_5, 4)
|
||||||
TAGKEYS(XK_5, 4) TAGKEYS(XK_6, 5)
|
TAGKEYS( XK_6, 5)
|
||||||
TAGKEYS(XK_7, 6){MODKEY | ShiftMask, XK_q, quit, {0}},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* button definitions */
|
/* button definitions */
|
||||||
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
|
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
|
||||||
* ClkClientWin, or ClkRootWin */
|
|
||||||
static const Button buttons[] = {
|
static const Button buttons[] = {
|
||||||
/* click event mask button function argument */
|
/* click event mask button function argument */
|
||||||
{ClkButton, 0, Button1, spawn, {.v = launch}},
|
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
|
||||||
{ClkLtSymbol, 0, Button1, setlayout, {0}},
|
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
||||||
{ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]}},
|
{ ClkWinTitle, 0, Button2, zoom, {0} },
|
||||||
{ClkStatusText, 0, Button1, spawn, {.v = statuscmd}},
|
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
|
||||||
{ClkStatusText, 0, Button2, spawn, {.v = statuscmd}},
|
{ ClkClientWin, MODKEY, Button1, moveorplace, {.i = 1} },
|
||||||
{ClkStatusText, 0, Button3, spawn, {.v = statuscmd}},
|
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
|
||||||
{ClkClientWin, MODKEY, Button1, movemouse, {0}},
|
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
|
||||||
{ClkClientWin, MODKEY, Button2, togglefloating, {0}},
|
{ ClkTagBar, 0, Button1, view, {0} },
|
||||||
{ClkClientWin, MODKEY, Button3, resizemouse, {0}},
|
{ ClkTagBar, 0, Button3, toggleview, {0} },
|
||||||
{ClkTagBar, 0, Button1, view, {0}},
|
{ ClkTagBar, MODKEY, Button1, tag, {0} },
|
||||||
{ClkTagBar, 0, Button3, toggleview, {0}},
|
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
|
||||||
{ClkTagBar, MODKEY, Button1, tag, {0}},
|
|
||||||
{ClkTagBar, MODKEY, Button3, toggletag, {0}},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
46
config.mk
46
config.mk
|
@ -1,5 +1,5 @@
|
||||||
# dwm version
|
# dwm version
|
||||||
VERSION = 6.3
|
VERSION = 6.4
|
||||||
|
|
||||||
# Customize below to fit your system
|
# Customize below to fit your system
|
||||||
|
|
||||||
|
@ -10,6 +10,10 @@ MANPREFIX = ${PREFIX}/share/man
|
||||||
X11INC = /usr/X11R6/include
|
X11INC = /usr/X11R6/include
|
||||||
X11LIB = /usr/X11R6/lib
|
X11LIB = /usr/X11R6/lib
|
||||||
|
|
||||||
|
# FreeBSD (uncomment)
|
||||||
|
#X11INC = /usr/local/include
|
||||||
|
#X11LIB = /usr/local/lib
|
||||||
|
|
||||||
# Xinerama, comment if you don't want it
|
# Xinerama, comment if you don't want it
|
||||||
XINERAMALIBS = -lXinerama
|
XINERAMALIBS = -lXinerama
|
||||||
XINERAMAFLAGS = -DXINERAMA
|
XINERAMAFLAGS = -DXINERAMA
|
||||||
|
@ -17,18 +21,48 @@ XINERAMAFLAGS = -DXINERAMA
|
||||||
# freetype
|
# freetype
|
||||||
FREETYPELIBS = -lfontconfig -lXft
|
FREETYPELIBS = -lfontconfig -lXft
|
||||||
FREETYPEINC = /usr/include/freetype2
|
FREETYPEINC = /usr/include/freetype2
|
||||||
|
# FreeBSD (uncomment)
|
||||||
|
#FREETYPEINC = /usr/local/include/freetype2
|
||||||
# OpenBSD (uncomment)
|
# OpenBSD (uncomment)
|
||||||
#FREETYPEINC = ${X11INC}/freetype2
|
#FREETYPEINC = ${X11INC}/freetype2
|
||||||
#MANPREFIX = ${PREFIX}/man
|
# OpenBSD - Uncomment this for the swallow patch / SWALLOW_PATCH
|
||||||
|
#KVMLIB = -lkvm
|
||||||
|
|
||||||
|
# Uncomment this for the alpha patch and the winicon patch (BAR_ALPHA_PATCH, BAR_WINICON_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 and tagpreview patches / BAR_WINICON_PATCH / BAR_TAGPREVIEW_PATCH
|
||||||
|
#IMLIB2LIBS = -lImlib2
|
||||||
|
|
||||||
|
# Uncomment for the bidi patch
|
||||||
|
#BDINC = `pkg-config --cflags fribidi`
|
||||||
|
#BDLIBS = `pkg-config --libs fribidi`
|
||||||
|
|
||||||
# includes and libs
|
# includes and libs
|
||||||
INCS = -I${X11INC} -I${FREETYPEINC}
|
INCS = -I${X11INC} -I${FREETYPEINC} ${YAJLINC} ${PANGOINC} ${BDINC}
|
||||||
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB}
|
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${KVMLIB} ${PANGOLIB} ${YAJLLIBS} ${IMLIB2LIBS} $(BDLIBS)
|
||||||
|
|
||||||
# flags
|
# flags
|
||||||
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
|
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
|
||||||
#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
|
#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-unused-function -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS}
|
||||||
LDFLAGS = ${LIBS}
|
LDFLAGS = ${LIBS}
|
||||||
|
|
||||||
# Solaris
|
# Solaris
|
||||||
|
|
122
drw.c
122
drw.c
|
@ -8,6 +8,7 @@
|
||||||
#include "drw.h"
|
#include "drw.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
#define UTF_INVALID 0xFFFD
|
#define UTF_INVALID 0xFFFD
|
||||||
#define UTF_SIZ 4
|
#define UTF_SIZ 4
|
||||||
|
|
||||||
|
@ -16,6 +17,7 @@ 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 utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000};
|
||||||
static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
|
static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
|
||||||
|
|
||||||
|
|
||||||
static long
|
static long
|
||||||
utf8decodebyte(const char c, size_t *i)
|
utf8decodebyte(const char c, size_t *i)
|
||||||
{
|
{
|
||||||
|
@ -70,6 +72,7 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h
|
||||||
drw->root = root;
|
drw->root = root;
|
||||||
drw->w = w;
|
drw->w = w;
|
||||||
drw->h = h;
|
drw->h = h;
|
||||||
|
|
||||||
drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
|
drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
|
||||||
drw->gc = XCreateGC(dpy, root, 0, NULL);
|
drw->gc = XCreateGC(dpy, root, 0, NULL);
|
||||||
XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
|
XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
|
||||||
|
@ -133,6 +136,7 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
|
||||||
die("no font specified.");
|
die("no font specified.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
font = ecalloc(1, sizeof(Fnt));
|
font = ecalloc(1, sizeof(Fnt));
|
||||||
font->xfont = xfont;
|
font->xfont = xfont;
|
||||||
font->pattern = pattern;
|
font->pattern = pattern;
|
||||||
|
@ -169,7 +173,6 @@ drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (drw->fonts = ret);
|
return (drw->fonts = ret);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -182,8 +185,11 @@ drw_fontset_free(Fnt *font)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
|
drw_clr_create(
|
||||||
{
|
Drw *drw,
|
||||||
|
Clr *dest,
|
||||||
|
const char *clrname
|
||||||
|
) {
|
||||||
if (!drw || !dest || !clrname)
|
if (!drw || !dest || !clrname)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -198,8 +204,11 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
|
||||||
/* Wrapper to create color schemes. The caller has to call free(3) on the
|
/* Wrapper to create color schemes. The caller has to call free(3) on the
|
||||||
* returned color scheme when done using it. */
|
* returned color scheme when done using it. */
|
||||||
Clr *
|
Clr *
|
||||||
drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
|
drw_scm_create(
|
||||||
{
|
Drw *drw,
|
||||||
|
char *clrnames[],
|
||||||
|
size_t clrcount
|
||||||
|
) {
|
||||||
size_t i;
|
size_t i;
|
||||||
Clr *ret;
|
Clr *ret;
|
||||||
|
|
||||||
|
@ -226,6 +235,7 @@ drw_setscheme(Drw *drw, Clr *scm)
|
||||||
drw->scheme = scm;
|
drw->scheme = scm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert)
|
drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert)
|
||||||
{
|
{
|
||||||
|
@ -239,12 +249,14 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
|
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup)
|
||||||
{
|
{
|
||||||
int i, ty, ellipsis_x = 0;
|
char buf[1024];
|
||||||
unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len;
|
int ty;
|
||||||
|
unsigned int ew;
|
||||||
XftDraw *d = NULL;
|
XftDraw *d = NULL;
|
||||||
Fnt *usedfont, *curfont, *nextfont;
|
Fnt *usedfont, *curfont, *nextfont;
|
||||||
|
size_t i, len;
|
||||||
int utf8strlen, utf8charlen, render = x || y || w || h;
|
int utf8strlen, utf8charlen, render = x || y || w || h;
|
||||||
long utf8codepoint = 0;
|
long utf8codepoint = 0;
|
||||||
const char *utf8str;
|
const char *utf8str;
|
||||||
|
@ -252,17 +264,13 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
FcPattern *fcpattern;
|
FcPattern *fcpattern;
|
||||||
FcPattern *match;
|
FcPattern *match;
|
||||||
XftResult result;
|
XftResult result;
|
||||||
int charexists = 0, overflow = 0;
|
int charexists = 0;
|
||||||
/* keep track of a couple codepoints for which we have no match. */
|
|
||||||
enum { nomatches_len = 64 };
|
|
||||||
static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches;
|
|
||||||
static unsigned int ellipsis_width = 0;
|
|
||||||
|
|
||||||
if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
|
if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!render) {
|
if (!render) {
|
||||||
w = invert ? invert : ~invert;
|
w = ~w;
|
||||||
} else {
|
} else {
|
||||||
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
||||||
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
||||||
|
@ -274,10 +282,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
}
|
}
|
||||||
|
|
||||||
usedfont = drw->fonts;
|
usedfont = drw->fonts;
|
||||||
if (!ellipsis_width && render)
|
|
||||||
ellipsis_width = drw_fontset_getwidth(drw, "...");
|
|
||||||
while (1) {
|
while (1) {
|
||||||
ew = ellipsis_len = utf8strlen = 0;
|
utf8strlen = 0;
|
||||||
utf8str = text;
|
utf8str = text;
|
||||||
nextfont = NULL;
|
nextfont = NULL;
|
||||||
while (*text) {
|
while (*text) {
|
||||||
|
@ -285,27 +291,9 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
|
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
|
||||||
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
||||||
if (charexists) {
|
if (charexists) {
|
||||||
drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL);
|
if (curfont == usedfont) {
|
||||||
if (ew + ellipsis_width <= w) {
|
|
||||||
/* keep track where the ellipsis still fits */
|
|
||||||
ellipsis_x = x + ew;
|
|
||||||
ellipsis_w = w - ew;
|
|
||||||
ellipsis_len = utf8strlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ew + tmpw > w) {
|
|
||||||
overflow = 1;
|
|
||||||
/* called from drw_fontset_getwidth_clamp():
|
|
||||||
* it wants the width AFTER the overflow
|
|
||||||
*/
|
|
||||||
if (!render)
|
|
||||||
x += tmpw;
|
|
||||||
else
|
|
||||||
utf8strlen = ellipsis_len;
|
|
||||||
} else if (curfont == usedfont) {
|
|
||||||
utf8strlen += utf8charlen;
|
utf8strlen += utf8charlen;
|
||||||
text += utf8charlen;
|
text += utf8charlen;
|
||||||
ew += tmpw;
|
|
||||||
} else {
|
} else {
|
||||||
nextfont = curfont;
|
nextfont = curfont;
|
||||||
}
|
}
|
||||||
|
@ -313,25 +301,36 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overflow || !charexists || nextfont)
|
if (!charexists || nextfont)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
charexists = 0;
|
charexists = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (utf8strlen) {
|
if (utf8strlen) {
|
||||||
if (render) {
|
drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL);
|
||||||
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
|
/* shorten text if necessary */
|
||||||
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
|
for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; drw_font_getexts(usedfont, utf8str, len, &ew, NULL))
|
||||||
usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen);
|
len--;
|
||||||
}
|
|
||||||
x += ew;
|
|
||||||
w -= ew;
|
|
||||||
}
|
|
||||||
if (render && overflow)
|
|
||||||
drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert);
|
|
||||||
|
|
||||||
if (!*text || overflow) {
|
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;
|
break;
|
||||||
} else if (nextfont) {
|
} else if (nextfont) {
|
||||||
charexists = 0;
|
charexists = 0;
|
||||||
|
@ -341,12 +340,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
* character must be drawn. */
|
* character must be drawn. */
|
||||||
charexists = 1;
|
charexists = 1;
|
||||||
|
|
||||||
for (i = 0; i < nomatches_len; ++i) {
|
|
||||||
/* avoid calling XftFontMatch if we know we won't find a match */
|
|
||||||
if (utf8codepoint == nomatches.codepoint[i])
|
|
||||||
goto no_match;
|
|
||||||
}
|
|
||||||
|
|
||||||
fccharset = FcCharSetCreate();
|
fccharset = FcCharSetCreate();
|
||||||
FcCharSetAddChar(fccharset, utf8codepoint);
|
FcCharSetAddChar(fccharset, utf8codepoint);
|
||||||
|
|
||||||
|
@ -358,7 +351,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
fcpattern = FcPatternDuplicate(drw->fonts->pattern);
|
fcpattern = FcPatternDuplicate(drw->fonts->pattern);
|
||||||
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
|
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
|
||||||
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
|
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
|
||||||
FcPatternAddBool(fcpattern, FC_COLOR, FcFalse);
|
|
||||||
|
|
||||||
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
|
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
|
||||||
FcDefaultSubstitute(fcpattern);
|
FcDefaultSubstitute(fcpattern);
|
||||||
|
@ -375,8 +367,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
curfont->next = usedfont;
|
curfont->next = usedfont;
|
||||||
} else {
|
} else {
|
||||||
xfont_free(usedfont);
|
xfont_free(usedfont);
|
||||||
nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint;
|
|
||||||
no_match:
|
|
||||||
usedfont = drw->fonts;
|
usedfont = drw->fonts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -388,6 +378,8 @@ no_match:
|
||||||
return x + (render ? w : 0);
|
return x + (render ? w : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
|
drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
|
||||||
{
|
{
|
||||||
|
@ -399,20 +391,11 @@ drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
drw_fontset_getwidth(Drw *drw, const char *text)
|
drw_fontset_getwidth(Drw *drw, const char *text, Bool markup)
|
||||||
{
|
{
|
||||||
if (!drw || !drw->fonts || !text)
|
if (!drw || !drw->fonts || !text)
|
||||||
return 0;
|
return 0;
|
||||||
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
|
return drw_text(drw, 0, 0, 0, 0, 0, text, 0, markup);
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n)
|
|
||||||
{
|
|
||||||
unsigned int tmp = 0;
|
|
||||||
if (drw && drw->fonts && text && n)
|
|
||||||
tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n);
|
|
||||||
return MIN(n, tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -452,3 +435,4 @@ drw_cur_free(Drw *drw, Cur *cursor)
|
||||||
XFreeCursor(drw->dpy, cursor->cursor);
|
XFreeCursor(drw->dpy, cursor->cursor);
|
||||||
free(cursor);
|
free(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
23
drw.h
23
drw.h
|
@ -1,5 +1,6 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Cursor cursor;
|
Cursor cursor;
|
||||||
} Cur;
|
} Cur;
|
||||||
|
@ -12,7 +13,7 @@ typedef struct Fnt {
|
||||||
struct Fnt *next;
|
struct Fnt *next;
|
||||||
} Fnt;
|
} Fnt;
|
||||||
|
|
||||||
enum { ColFg, ColBg, ColBorder }; /* Clr scheme index */
|
enum { ColFg, ColBg, ColBorder, ColFloat, ColCount }; /* Clr scheme index */
|
||||||
typedef XftColor Clr;
|
typedef XftColor Clr;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -33,14 +34,21 @@ void drw_free(Drw *drw);
|
||||||
|
|
||||||
/* Fnt abstraction */
|
/* Fnt abstraction */
|
||||||
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
|
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
|
||||||
void drw_fontset_free(Fnt* set);
|
|
||||||
unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
|
|
||||||
unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n);
|
|
||||||
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
|
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 */
|
/* Colorscheme abstraction */
|
||||||
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
|
void drw_clr_create(
|
||||||
Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
|
Drw *drw,
|
||||||
|
Clr *dest,
|
||||||
|
const char *clrname
|
||||||
|
);
|
||||||
|
Clr *drw_scm_create(
|
||||||
|
Drw *drw,
|
||||||
|
char *clrnames[],
|
||||||
|
size_t clrcount
|
||||||
|
);
|
||||||
|
|
||||||
/* Cursor abstraction */
|
/* Cursor abstraction */
|
||||||
Cur *drw_cur_create(Drw *drw, int shape);
|
Cur *drw_cur_create(Drw *drw, int shape);
|
||||||
|
@ -52,7 +60,8 @@ void drw_setscheme(Drw *drw, Clr *scm);
|
||||||
|
|
||||||
/* Drawing functions */
|
/* Drawing functions */
|
||||||
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
|
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);
|
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);
|
||||||
|
|
||||||
/* Map functions */
|
/* Map functions */
|
||||||
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
|
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
|
||||||
|
|
||||||
|
|
32
dwm.1
32
dwm.1
|
@ -30,14 +30,6 @@ top left corner. The tags which are applied to one or more windows are
|
||||||
indicated with an empty square in the top left corner.
|
indicated with an empty square in the top left corner.
|
||||||
.P
|
.P
|
||||||
dwm draws a small border around windows to indicate the focus state.
|
dwm draws a small border around windows to indicate the focus state.
|
||||||
.P
|
|
||||||
On start, dwm can start additional programs that may be specified in two special
|
|
||||||
shell scripts (see the FILES section below), autostart_blocking.sh and
|
|
||||||
autostart.sh. The former is executed first and dwm will wait for its
|
|
||||||
termination before starting. The latter is executed in the background before
|
|
||||||
dwm enters its handler loop.
|
|
||||||
.P
|
|
||||||
Either of these files may be omitted.
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.B \-v
|
.B \-v
|
||||||
|
@ -100,12 +92,6 @@ Sets monocle layout.
|
||||||
.B Mod1\-space
|
.B Mod1\-space
|
||||||
Toggles between current and previous layout.
|
Toggles between current and previous layout.
|
||||||
.TP
|
.TP
|
||||||
.B Mod1\-Control\-,
|
|
||||||
Cycles backwards in layout list.
|
|
||||||
.TP
|
|
||||||
.B Mod1\-Control\-.
|
|
||||||
Cycles forwards in layout list.
|
|
||||||
.TP
|
|
||||||
.B Mod1\-j
|
.B Mod1\-j
|
||||||
Focus next window.
|
Focus next window.
|
||||||
.TP
|
.TP
|
||||||
|
@ -130,9 +116,6 @@ Zooms/cycles focused window to/from master area (tiled layouts only).
|
||||||
.B Mod1\-Shift\-c
|
.B Mod1\-Shift\-c
|
||||||
Close focused window.
|
Close focused window.
|
||||||
.TP
|
.TP
|
||||||
.B Mod1\-Shift\-f
|
|
||||||
Toggle fullscreen for focused window.
|
|
||||||
.TP
|
|
||||||
.B Mod1\-Shift\-space
|
.B Mod1\-Shift\-space
|
||||||
Toggle focused window between tiled and floating state.
|
Toggle focused window between tiled and floating state.
|
||||||
.TP
|
.TP
|
||||||
|
@ -169,21 +152,6 @@ Toggles focused window between floating and tiled state.
|
||||||
.TP
|
.TP
|
||||||
.B Mod1\-Button3
|
.B Mod1\-Button3
|
||||||
Resize focused window while dragging. Tiled windows will be toggled to the floating state.
|
Resize focused window while dragging. Tiled windows will be toggled to the floating state.
|
||||||
.SH FILES
|
|
||||||
The files containing programs to be started along with dwm are searched for in
|
|
||||||
the following directories:
|
|
||||||
.IP "1. $XDG_DATA_HOME/dwm"
|
|
||||||
.IP "2. $HOME/.local/share/dwm"
|
|
||||||
.IP "3. $HOME/.dwm"
|
|
||||||
.P
|
|
||||||
The first existing directory is scanned for any of the autostart files below.
|
|
||||||
.TP 15
|
|
||||||
autostart.sh
|
|
||||||
This file is started as a shell background process before dwm enters its handler
|
|
||||||
loop.
|
|
||||||
.TP 15
|
|
||||||
autostart_blocking.sh
|
|
||||||
This file is started before any autostart.sh; dwm waits for its termination.
|
|
||||||
.SH CUSTOMIZATION
|
.SH CUSTOMIZATION
|
||||||
dwm is customized by creating a custom config.h and (re)compiling the source
|
dwm is customized by creating a custom config.h and (re)compiling the source
|
||||||
code. This keeps it fast, secure and simple.
|
code. This keeps it fast, secure and simple.
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Encoding=UTF-8
|
||||||
|
Name=Dwm
|
||||||
|
Comment=Dynamic window manager
|
||||||
|
Exec=dwm
|
||||||
|
Icon=dwm
|
||||||
|
Type=XSession
|
|
@ -0,0 +1,39 @@
|
||||||
|
void
|
||||||
|
barhover(XEvent *e, Bar *bar)
|
||||||
|
{
|
||||||
|
const BarRule *br;
|
||||||
|
Monitor *m = bar->mon;
|
||||||
|
XMotionEvent *ev = &e->xmotion;
|
||||||
|
BarArg barg = { 0, 0, 0, 0 };
|
||||||
|
int r;
|
||||||
|
|
||||||
|
for (r = 0; r < LENGTH(barrules); r++) {
|
||||||
|
br = &barrules[r];
|
||||||
|
if (br->bar != bar->idx || (br->monitor == 'A' && m != selmon) || br->hoverfunc == NULL)
|
||||||
|
continue;
|
||||||
|
if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num)
|
||||||
|
continue;
|
||||||
|
if (bar->x[r] > ev->x || ev->x > bar->x[r] + bar->w[r])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
barg.x = ev->x - bar->x[r];
|
||||||
|
barg.y = ev->y - bar->borderpx;
|
||||||
|
barg.w = bar->w[r];
|
||||||
|
barg.h = bar->bh - 2 * bar->borderpx;
|
||||||
|
|
||||||
|
br->hoverfunc(bar, &barg, ev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bar *
|
||||||
|
wintobar(Window win)
|
||||||
|
{
|
||||||
|
Monitor *m;
|
||||||
|
Bar *bar;
|
||||||
|
for (m = mons; m; m = m->next)
|
||||||
|
for (bar = m->bar; bar; bar = bar->next)
|
||||||
|
if (bar->win == win)
|
||||||
|
return bar;
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
static void barhover(XEvent *e, Bar *bar);
|
||||||
|
static Bar *wintobar(Window win);
|
|
@ -0,0 +1,104 @@
|
||||||
|
/* 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->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);
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
|
||||||
|
int
|
||||||
|
width_status2d(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
width = status2dtextlength(stext);
|
||||||
|
return width ? width + lrpad : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
draw_status2d(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
return drawstatusbar(a, stext);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
click_status2d(Bar *bar, Arg *arg, BarArg *a)
|
||||||
|
{
|
||||||
|
return ClkStatusText;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
drawstatusbar(BarArg *a, char* stext)
|
||||||
|
{
|
||||||
|
int i, w, len;
|
||||||
|
int x = a->x;
|
||||||
|
int y = a->y;
|
||||||
|
short isCode = 0;
|
||||||
|
char *text;
|
||||||
|
char *p;
|
||||||
|
Clr oldbg, oldfg;
|
||||||
|
len = strlen(stext);
|
||||||
|
if (!(text = (char*) malloc(sizeof(char)*(len + 1))))
|
||||||
|
die("malloc");
|
||||||
|
p = text;
|
||||||
|
memcpy(text, stext, len);
|
||||||
|
|
||||||
|
x += lrpad / 2;
|
||||||
|
drw_setscheme(drw, scheme[LENGTH(colors)]);
|
||||||
|
drw->scheme[ColFg] = scheme[SchemeNorm][ColFg];
|
||||||
|
drw->scheme[ColBg] = scheme[SchemeNorm][ColBg];
|
||||||
|
|
||||||
|
/* process status text */
|
||||||
|
i = -1;
|
||||||
|
while (text[++i]) {
|
||||||
|
if (text[i] == '^' && !isCode) {
|
||||||
|
isCode = 1;
|
||||||
|
|
||||||
|
text[i] = '\0';
|
||||||
|
w = TEXTWM(text) - lrpad;
|
||||||
|
drw_text(drw, x, y, w, bh, 0, text, 0, True);
|
||||||
|
|
||||||
|
x += w;
|
||||||
|
|
||||||
|
/* process code */
|
||||||
|
while (text[++i] != '^') {
|
||||||
|
if (text[i] == 'c') {
|
||||||
|
char buf[8];
|
||||||
|
if (i + 7 >= len) {
|
||||||
|
i += 7;
|
||||||
|
len = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memcpy(buf, (char*)text+i+1, 7);
|
||||||
|
buf[7] = '\0';
|
||||||
|
drw_clr_create(drw, &drw->scheme[ColFg], buf);
|
||||||
|
i += 7;
|
||||||
|
} else if (text[i] == 'b') {
|
||||||
|
char buf[8];
|
||||||
|
if (i + 7 >= len) {
|
||||||
|
i += 7;
|
||||||
|
len = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memcpy(buf, (char*)text+i+1, 7);
|
||||||
|
buf[7] = '\0';
|
||||||
|
drw_clr_create(drw, &drw->scheme[ColBg], buf);
|
||||||
|
i += 7;
|
||||||
|
} else if (text[i] == 'd') {
|
||||||
|
drw->scheme[ColFg] = scheme[SchemeNorm][ColFg];
|
||||||
|
drw->scheme[ColBg] = scheme[SchemeNorm][ColBg];
|
||||||
|
} else if (text[i] == 'w') {
|
||||||
|
Clr swp;
|
||||||
|
swp = drw->scheme[ColFg];
|
||||||
|
drw->scheme[ColFg] = drw->scheme[ColBg];
|
||||||
|
drw->scheme[ColBg] = swp;
|
||||||
|
} else if (text[i] == 'v') {
|
||||||
|
oldfg = drw->scheme[ColFg];
|
||||||
|
oldbg = drw->scheme[ColBg];
|
||||||
|
} else if (text[i] == 't') {
|
||||||
|
drw->scheme[ColFg] = oldfg;
|
||||||
|
drw->scheme[ColBg] = oldbg;
|
||||||
|
} else if (text[i] == 'r') {
|
||||||
|
int rx = atoi(text + ++i);
|
||||||
|
while (text[++i] != ',');
|
||||||
|
int ry = atoi(text + ++i);
|
||||||
|
while (text[++i] != ',');
|
||||||
|
int rw = atoi(text + ++i);
|
||||||
|
while (text[++i] != ',');
|
||||||
|
int rh = atoi(text + ++i);
|
||||||
|
|
||||||
|
if (ry < 0)
|
||||||
|
ry = 0;
|
||||||
|
if (rx < 0)
|
||||||
|
rx = 0;
|
||||||
|
|
||||||
|
drw_rect(drw, rx + x, y + ry, rw, rh, 1, 0);
|
||||||
|
} else if (text[i] == 'f') {
|
||||||
|
x += atoi(text + ++i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
text = text + i + 1;
|
||||||
|
len -= i + 1;
|
||||||
|
i = -1;
|
||||||
|
isCode = 0;
|
||||||
|
if (len <= 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isCode && len > 0) {
|
||||||
|
w = TEXTWM(text) - lrpad;
|
||||||
|
drw_text(drw, x, y, w, bh, 0, text, 0, True);
|
||||||
|
x += w;
|
||||||
|
}
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
drw_setscheme(drw, scheme[SchemeNorm]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
status2dtextlength(char* stext)
|
||||||
|
{
|
||||||
|
int i, w, len;
|
||||||
|
short isCode = 0;
|
||||||
|
char *text;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
len = strlen(stext) + 1;
|
||||||
|
if (!(text = (char*) malloc(sizeof(char)*len)))
|
||||||
|
die("malloc");
|
||||||
|
p = text;
|
||||||
|
memcpy(text, stext, len);
|
||||||
|
|
||||||
|
/* compute width of the status text */
|
||||||
|
w = 0;
|
||||||
|
i = -1;
|
||||||
|
while (text[++i]) {
|
||||||
|
if (text[i] == '^') {
|
||||||
|
if (!isCode) {
|
||||||
|
isCode = 1;
|
||||||
|
text[i] = '\0';
|
||||||
|
w += TEXTWM(text) - lrpad;
|
||||||
|
text[i] = '^';
|
||||||
|
if (text[++i] == 'f')
|
||||||
|
w += atoi(text + ++i);
|
||||||
|
} else {
|
||||||
|
isCode = 0;
|
||||||
|
text = text + i + 1;
|
||||||
|
i = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isCode)
|
||||||
|
w += TEXTWM(text) - lrpad;
|
||||||
|
free(p);
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
static int width_status2d(Bar *bar, BarArg *a);
|
||||||
|
static int draw_status2d(Bar *bar, BarArg *a);
|
||||||
|
static int click_status2d(Bar *bar, Arg *arg, BarArg *a);
|
||||||
|
static int drawstatusbar(BarArg *a, char *text);
|
||||||
|
static int status2dtextlength(char *stext);
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
char *
|
||||||
|
tagicon(Monitor *m, int tag)
|
||||||
|
{
|
||||||
|
Client *c;
|
||||||
|
int tagindex = tag + NUMTAGS * m->num;
|
||||||
|
if (tagindex >= LENGTH(tagicons[DEFAULT_TAGS]))
|
||||||
|
tagindex = tagindex % LENGTH(tagicons[DEFAULT_TAGS]);
|
||||||
|
for (c = m->clients; c && (!(c->tags & 1 << tag) || HIDDEN(c)); c = c->next);
|
||||||
|
if (c)
|
||||||
|
return tagicons[ALT_TAGS_DECORATION][tagindex];
|
||||||
|
return tagicons[DEFAULT_TAGS][tagindex];
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
enum {
|
||||||
|
DEFAULT_TAGS,
|
||||||
|
ALTERNATIVE_TAGS,
|
||||||
|
ALT_TAGS_DECORATION,
|
||||||
|
};
|
||||||
|
|
||||||
|
static char * tagicon(Monitor *m, int tag);
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
int
|
||||||
|
width_tags(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
int w, i;
|
||||||
|
|
||||||
|
for (w = 0, i = 0; i < NUMTAGS; i++) {
|
||||||
|
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;
|
||||||
|
if (c->isurgent)
|
||||||
|
urg |= c->tags;
|
||||||
|
}
|
||||||
|
for (i = 0; i < NUMTAGS; i++) {
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (ulineall || m->tagset[m->seltags] & 1 << i)
|
||||||
|
drw_rect(drw, x + ulinepad, bh - ulinestroke - ulinevoffset, w - (ulinepad * 2), ulinestroke, 1, 0);
|
||||||
|
x += w;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
click_tags(Bar *bar, Arg *arg, BarArg *a)
|
||||||
|
{
|
||||||
|
int i = 0, x = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
x += TEXTW(tagicon(bar->mon, i));
|
||||||
|
} while (a->x >= x && ++i < NUMTAGS);
|
||||||
|
if (i < NUMTAGS) {
|
||||||
|
arg->ui = 1 << i;
|
||||||
|
}
|
||||||
|
return ClkTagBar;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
hover_tags(Bar *bar, BarArg *a, XMotionEvent *ev)
|
||||||
|
{
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
static int hover_tags(Bar *bar, BarArg *a, XMotionEvent *ev);
|
|
@ -0,0 +1,51 @@
|
||||||
|
int
|
||||||
|
width_wintitle(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
return a->w;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
draw_wintitle(Bar *bar, BarArg *a)
|
||||||
|
{
|
||||||
|
int x = a->x, w = a->w;
|
||||||
|
Monitor *m = bar->mon;
|
||||||
|
Client *c = m->sel;
|
||||||
|
|
||||||
|
if (!c) {
|
||||||
|
drw_setscheme(drw, scheme[SchemeTitleNorm]);
|
||||||
|
drw_rect(drw, x, a->y, w, a->h, 1, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tpad = lrpad / 2;
|
||||||
|
int tx = x;
|
||||||
|
int tw = w;
|
||||||
|
|
||||||
|
drw_setscheme(drw, scheme[m == selmon ? SchemeTitleSel : SchemeTitleNorm]);
|
||||||
|
XSetErrorHandler(xerrordummy);
|
||||||
|
|
||||||
|
if (w <= TEXTW("A") - lrpad + tpad) // reduce text padding if wintitle is too small
|
||||||
|
tpad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2);
|
||||||
|
|
||||||
|
XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel);
|
||||||
|
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, w, a->h);
|
||||||
|
|
||||||
|
|
||||||
|
tx += tpad;
|
||||||
|
tw -= lrpad;
|
||||||
|
|
||||||
|
|
||||||
|
drw_text(drw, tx, a->y, tw, a->h, 0, 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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
Layout *last_layout;
|
||||||
|
|
||||||
|
void
|
||||||
|
fullscreen(const Arg *arg)
|
||||||
|
{
|
||||||
|
int monocle_pos = 0;
|
||||||
|
if (selmon->showbar || last_layout == NULL) {
|
||||||
|
for (monocle_pos = 0, last_layout = (Layout *)layouts; !last_layout->arrange || last_layout->arrange != &monocle; monocle_pos++, last_layout++ );
|
||||||
|
for (last_layout = (Layout *)layouts; last_layout != selmon->lt[selmon->sellt]; last_layout++);
|
||||||
|
setlayout(&((Arg) { .v = &layouts[monocle_pos] }));
|
||||||
|
} else {
|
||||||
|
setlayout(&((Arg) { .v = last_layout }));
|
||||||
|
}
|
||||||
|
togglebar(arg);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
static void fullscreen(const Arg *arg);
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/* Bar functionality */
|
||||||
|
#include "bar_indicators.c"
|
||||||
|
#include "bar_tagicons.c"
|
||||||
|
#include "bar.c"
|
||||||
|
|
||||||
|
#include "bar_ltsymbol.c"
|
||||||
|
#include "bar_status.c"
|
||||||
|
#include "bar_status2d.c"
|
||||||
|
#include "bar_tags.c"
|
||||||
|
#include "bar_wintitle.c"
|
||||||
|
|
||||||
|
/* Other patches */
|
||||||
|
#include "fullscreen.c"
|
||||||
|
#include "movestack.c"
|
||||||
|
#include "placemouse.c"
|
||||||
|
#include "restartsig.c"
|
||||||
|
#include "togglefullscreen.c"
|
||||||
|
#include "vanitygaps.c"
|
||||||
|
/* Layouts */
|
||||||
|
#include "layout_facts.c"
|
||||||
|
#include "layout_gapplessgrid.c"
|
||||||
|
#include "layout_monocle.c"
|
||||||
|
#include "layout_tile.c"
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
/* Bar functionality */
|
||||||
|
#include "bar_indicators.h"
|
||||||
|
#include "bar_tagicons.h"
|
||||||
|
#include "bar.h"
|
||||||
|
|
||||||
|
#include "bar_ltsymbol.h"
|
||||||
|
#include "bar_status.h"
|
||||||
|
#include "bar_status2d.h"
|
||||||
|
#include "bar_tags.h"
|
||||||
|
#include "bar_wintitle.h"
|
||||||
|
|
||||||
|
/* Other patches */
|
||||||
|
#include "fullscreen.h"
|
||||||
|
#include "movestack.h"
|
||||||
|
#include "placemouse.h"
|
||||||
|
#include "restartsig.h"
|
||||||
|
#include "togglefullscreen.h"
|
||||||
|
#include "vanitygaps.h"
|
||||||
|
/* Layouts */
|
||||||
|
#include "layout_gapplessgrid.h"
|
||||||
|
#include "layout_monocle.h"
|
||||||
|
#include "layout_tile.h"
|
||||||
|
|
|
@ -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_
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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_
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
void
|
||||||
|
gaplessgrid(Monitor *m)
|
||||||
|
{
|
||||||
|
unsigned int i, n;
|
||||||
|
int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters
|
||||||
|
int oh, ov, ih, iv;
|
||||||
|
Client *c;
|
||||||
|
|
||||||
|
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||||
|
if (n == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* grid dimensions */
|
||||||
|
for (cols = 0; cols <= n/2; cols++)
|
||||||
|
if (cols*cols >= n)
|
||||||
|
break;
|
||||||
|
if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
|
||||||
|
cols = 2;
|
||||||
|
rows = n/cols;
|
||||||
|
cn = rn = 0; // reset column no, row no, client count
|
||||||
|
|
||||||
|
ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
|
||||||
|
cw = (m->ww - 2*ov - iv * (cols - 1)) / cols;
|
||||||
|
rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
|
||||||
|
crest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
|
||||||
|
x = m->wx + ov;
|
||||||
|
y = m->wy + oh;
|
||||||
|
|
||||||
|
for (i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) {
|
||||||
|
if (i/rows + 1 > cols - n%cols) {
|
||||||
|
rows = n/cols + 1;
|
||||||
|
ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
|
||||||
|
rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
|
||||||
|
}
|
||||||
|
resize(c,
|
||||||
|
x,
|
||||||
|
y + rn*(ch + ih) + MIN(rn, rrest),
|
||||||
|
cw + (cn < crest ? 1 : 0) - 2*c->bw,
|
||||||
|
ch + (rn < rrest ? 1 : 0) - 2*c->bw,
|
||||||
|
0);
|
||||||
|
rn++;
|
||||||
|
if (rn >= rows) {
|
||||||
|
rn = 0;
|
||||||
|
x += cw + ih + (cn < crest ? 1 : 0);
|
||||||
|
cn++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
static void gaplessgrid(Monitor *m);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
static void monocle(Monitor *m);
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
static void tile(Monitor *m);
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
void
|
||||||
|
movestack(const Arg *arg)
|
||||||
|
{
|
||||||
|
Client *c = NULL, *p = NULL, *pc = NULL, *i;
|
||||||
|
if (arg->i > 0) {
|
||||||
|
if (!selmon->sel)
|
||||||
|
return;
|
||||||
|
/* find the client after selmon->sel */
|
||||||
|
for (c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
|
||||||
|
if (!c)
|
||||||
|
for (c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* find the client before selmon->sel */
|
||||||
|
for (i = selmon->clients; i != selmon->sel; i = i->next)
|
||||||
|
if(ISVISIBLE(i) && !i->isfloating)
|
||||||
|
c = i;
|
||||||
|
if (!c)
|
||||||
|
for (; i; i = i->next)
|
||||||
|
if (ISVISIBLE(i) && !i->isfloating)
|
||||||
|
c = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find the client before selmon->sel and c */
|
||||||
|
for (i = selmon->clients; i && (!p || !pc); i = i->next) {
|
||||||
|
if (i->next == selmon->sel)
|
||||||
|
p = i;
|
||||||
|
if (i->next == c)
|
||||||
|
pc = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* swap c and selmon->sel selmon->clients in the selmon->clients list */
|
||||||
|
if (c && c != selmon->sel) {
|
||||||
|
Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next;
|
||||||
|
selmon->sel->next = c->next==selmon->sel?c:c->next;
|
||||||
|
c->next = temp;
|
||||||
|
|
||||||
|
if (p && p != c)
|
||||||
|
p->next = c;
|
||||||
|
if (pc && pc != selmon->sel)
|
||||||
|
pc->next = selmon->sel;
|
||||||
|
|
||||||
|
if (selmon->sel == selmon->clients)
|
||||||
|
selmon->clients = c;
|
||||||
|
else if (c == selmon->clients)
|
||||||
|
selmon->clients = selmon->sel;
|
||||||
|
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
static void movestack(const Arg *arg);
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
void
|
||||||
|
moveorplace(const Arg *arg) {
|
||||||
|
if ((!selmon->lt[selmon->sellt]->arrange || (selmon->sel && selmon->sel->isfloating)))
|
||||||
|
movemouse(arg);
|
||||||
|
else
|
||||||
|
placemouse(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
placemouse(const Arg *arg)
|
||||||
|
{
|
||||||
|
int x, y, px, py, ocx, ocy, nx = -9999, ny = -9999, freemove = 0;
|
||||||
|
Client *c, *r = NULL, *at, *prevr;
|
||||||
|
Monitor *m;
|
||||||
|
XEvent ev;
|
||||||
|
XWindowAttributes wa;
|
||||||
|
Time lasttime = 0;
|
||||||
|
int attachmode, prevattachmode;
|
||||||
|
attachmode = prevattachmode = -1;
|
||||||
|
|
||||||
|
if (!(c = selmon->sel) || !c->mon->lt[c->mon->sellt]->arrange) /* no support for placemouse when floating layout is used */
|
||||||
|
return;
|
||||||
|
if (c->isfullscreen) /* no support placing fullscreen windows by mouse */
|
||||||
|
return;
|
||||||
|
restack(selmon);
|
||||||
|
prevr = c;
|
||||||
|
if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
|
||||||
|
None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
|
||||||
|
return;
|
||||||
|
|
||||||
|
c->isfloating = 0;
|
||||||
|
c->beingmoved = 1;
|
||||||
|
|
||||||
|
XGetWindowAttributes(dpy, c->win, &wa);
|
||||||
|
ocx = wa.x;
|
||||||
|
ocy = wa.y;
|
||||||
|
|
||||||
|
if (arg->i == 2) // warp cursor to client center
|
||||||
|
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, WIDTH(c) / 2, HEIGHT(c) / 2);
|
||||||
|
|
||||||
|
if (!getrootptr(&x, &y))
|
||||||
|
return;
|
||||||
|
|
||||||
|
do {
|
||||||
|
XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
|
||||||
|
switch (ev.type) {
|
||||||
|
case ConfigureRequest:
|
||||||
|
case Expose:
|
||||||
|
case MapRequest:
|
||||||
|
handler[ev.type](&ev);
|
||||||
|
break;
|
||||||
|
case MotionNotify:
|
||||||
|
if ((ev.xmotion.time - lasttime) <= (1000 / 60))
|
||||||
|
continue;
|
||||||
|
lasttime = ev.xmotion.time;
|
||||||
|
|
||||||
|
nx = ocx + (ev.xmotion.x - x);
|
||||||
|
ny = ocy + (ev.xmotion.y - y);
|
||||||
|
|
||||||
|
if (!freemove && (abs(nx - ocx) > snap || abs(ny - ocy) > snap))
|
||||||
|
freemove = 1;
|
||||||
|
|
||||||
|
if (freemove)
|
||||||
|
XMoveWindow(dpy, c->win, nx, ny);
|
||||||
|
|
||||||
|
if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != selmon)
|
||||||
|
selmon = m;
|
||||||
|
|
||||||
|
if (arg->i == 1) { // tiled position is relative to the client window center point
|
||||||
|
px = nx + wa.width / 2;
|
||||||
|
py = ny + wa.height / 2;
|
||||||
|
} else { // tiled position is relative to the mouse cursor
|
||||||
|
px = ev.xmotion.x;
|
||||||
|
py = ev.xmotion.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = recttoclient(px, py, 1, 1);
|
||||||
|
|
||||||
|
if (!r || r == c)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ((((float)(r->y + r->h - py) / r->h) > ((float)(r->x + r->w - px) / r->w)
|
||||||
|
&& (abs(r->y - py) < r->h / 2)) || (abs(r->x - px) < r->w / 2))
|
||||||
|
attachmode = 1; // above
|
||||||
|
else
|
||||||
|
attachmode = 0; // below
|
||||||
|
|
||||||
|
if ((r && r != prevr) || (attachmode != prevattachmode)) {
|
||||||
|
detachstack(c);
|
||||||
|
detach(c);
|
||||||
|
if (c->mon != r->mon) {
|
||||||
|
arrangemon(c->mon);
|
||||||
|
c->tags = r->mon->tagset[r->mon->seltags];
|
||||||
|
}
|
||||||
|
|
||||||
|
c->mon = r->mon;
|
||||||
|
r->mon->sel = r;
|
||||||
|
|
||||||
|
if (attachmode) {
|
||||||
|
if (r == r->mon->clients)
|
||||||
|
attach(c);
|
||||||
|
else {
|
||||||
|
for (at = r->mon->clients; at->next != r; at = at->next);
|
||||||
|
c->next = at->next;
|
||||||
|
at->next = c;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c->next = r->next;
|
||||||
|
r->next = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
attachstack(c);
|
||||||
|
arrangemon(r->mon);
|
||||||
|
prevr = r;
|
||||||
|
prevattachmode = attachmode;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (ev.type != ButtonRelease);
|
||||||
|
XUngrabPointer(dpy, CurrentTime);
|
||||||
|
|
||||||
|
if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != c->mon) {
|
||||||
|
detach(c);
|
||||||
|
detachstack(c);
|
||||||
|
arrangemon(c->mon);
|
||||||
|
c->mon = m;
|
||||||
|
c->tags = m->tagset[m->seltags];
|
||||||
|
attach(c);
|
||||||
|
attachstack(c);
|
||||||
|
selmon = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
focus(c);
|
||||||
|
c->beingmoved = 0;
|
||||||
|
|
||||||
|
if (nx != -9999)
|
||||||
|
resize(c, nx, ny, c->w, c->h, 0);
|
||||||
|
arrangemon(c->mon);
|
||||||
|
}
|
||||||
|
|
||||||
|
Client *
|
||||||
|
recttoclient(int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
Client *c, *r = NULL;
|
||||||
|
int a, area = 0;
|
||||||
|
|
||||||
|
for (c = nexttiled(selmon->clients); c; c = nexttiled(c->next)) {
|
||||||
|
if ((a = INTERSECTC(x, y, w, h, c)) > area) {
|
||||||
|
area = a;
|
||||||
|
r = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
#define INTERSECTC(x,y,w,h,z) (MAX(0, MIN((x)+(w),(z)->x+(z)->w) - MAX((x),(z)->x)) \
|
||||||
|
* MAX(0, MIN((y)+(h),(z)->y+(z)->h) - MAX((y),(z)->y)))
|
||||||
|
|
||||||
|
static void moveorplace(const Arg *arg);
|
||||||
|
static void placemouse(const Arg *arg);
|
||||||
|
static Client *recttoclient(int x, int y, int w, int h);
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
static int restart = 0;
|
||||||
|
|
||||||
|
void
|
||||||
|
sighup(int unused)
|
||||||
|
{
|
||||||
|
Arg a = {.i = 1};
|
||||||
|
quit(&a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sigterm(int unused)
|
||||||
|
{
|
||||||
|
Arg a = {.i = 0};
|
||||||
|
quit(&a);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
static void sighup(int unused);
|
||||||
|
static void sigterm(int unused);
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
void
|
||||||
|
togglefullscreen(const Arg *arg)
|
||||||
|
{
|
||||||
|
Client *c = selmon->sel;
|
||||||
|
if (!c)
|
||||||
|
return;
|
||||||
|
|
||||||
|
setfullscreen(c, !c->isfullscreen);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
static void togglefullscreen(const Arg *arg);
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
/* 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
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -40,3 +40,4 @@ int main(void) {
|
||||||
XCloseDisplay(d);
|
XCloseDisplay(d);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
util.h
11
util.h
|
@ -1,8 +1,19 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
|
||||||
|
#ifndef MAX
|
||||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||||
|
#endif
|
||||||
|
#ifndef MIN
|
||||||
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||||
|
#endif
|
||||||
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
|
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define DEBUG(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
void die(const char *fmt, ...);
|
void die(const char *fmt, ...);
|
||||||
void *ecalloc(size_t nmemb, size_t size);
|
void *ecalloc(size_t nmemb, size_t size);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue