Compare commits

...

10 Commits

Author SHA1 Message Date
cacdd16200
fix colors 2024-09-08 22:55:37 -07:00
29bfe5688a apply setstatus patch 2024-09-01 20:07:50 -07:00
9a51d0912b
add fullgaps patch 2024-09-01 20:03:47 -07:00
33081ed8e6 initial commit 2024-09-01 13:48:37 -07:00
Pontus Stenetorp
5687f46964 Add missing void to updateclientlist definition
Caught by -pedantic implying -Wstrict-prototypes for OpenBSD's 16.0.6 Clang.
2024-06-08 18:21:00 +02:00
Hiltjo Posthuma
061e9fe9a7 bump version to 6.5 2024-03-19 12:13:16 +01:00
Hiltjo Posthuma
9f8855343c Makefile: remove the options target
The Makefile used to suppress output (by using @), so this target made sense at
the time.

But the Makefile should be simple and make debugging with less abstractions or
fancy printing.  The Makefile was made verbose and doesn't hide the build
output, so remove this target.

Prompted by a question on the mailing list about the options target.
2023-09-22 15:13:29 +02:00
Hiltjo Posthuma
e81f17d4c1 restore SIGCHLD sighandler to default before spawning a program
From sigaction(2):
A child created via fork(2) inherits a copy of its parent's signal dispositions.
During an execve(2), the dispositions of handled signals are reset to the default;
the dispositions of ignored signals are left unchanged.

This refused to start directly some programs from configuring in config.h:

static Key keys[] = {
	MODKEY,                       XK_o,      spawn,          {.v = cmd } },
};

Some reported programs that didn't start were: mpv, anki, dmenu_extended.

Reported by pfx.
Initial patch suggestion by Storkman.
2023-04-09 12:37:14 +02:00
NRK
348f6559ab config.mk: update to _XOPEN_SOURCE=700L
SA_NOCLDWAIT is marked as XSI in the posix spec [0] and FreeBSD and NetBSD
seems to more be strict about the feature test macro [1].

so update the macro to use _XOPEN_SOURCE=700L instead, which is equivalent to
_POSIX_C_SOURCE=200809L except that it also unlocks the X/Open System
Interfaces.

[0]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html#tag_13_42
[1]: https://lists.suckless.org/dev/2302/35111.html

Tested on:
* NetBSD 9.3 (fixed).
* FreeBSD 13 (fixed).
* Void Linux musl.
* Void Linux glibc.
* OpenBSD 7.2 (stable).
* Slackware 11.

Reported-by: beastie <pufferfish@riseup.net>
2023-02-17 15:27:34 +01:00
Chris Down
712d6639ff Use sigaction(SA_NOCLDWAIT) for SIGCHLD handling
signal() semantics are pretty unclearly specified. For example, depending on OS
kernel and libc, the handler may be returned to SIG_DFL (hence the inner call
to read the signal handler). Moving to sigaction() means the behaviour is
consistently defined.

Using SA_NOCLDWAIT also allows us to avoid calling the non-reentrant function
die() in the handler.

Some addditional notes for archival purposes:

* NRK pointed out errno of waitpid could also theoretically get clobbered.
* The original patch was iterated on and modified by NRK and Hiltjo:
  * SIG_DFL was changed to SIG_IGN, this is required, atleast on older systems
    such as tested on Slackware 11.
  * signals are not blocked using sigprocmask, because in theory it would
    briefly for example also ignore a SIGTERM signal. It is OK if waitpid() is (in
    theory interrupted).

POSIX reference:
"Consequences of Process Termination":
https://pubs.opengroup.org/onlinepubs/9699919799/functions/_Exit.html#tag_16_01_03_01
2023-01-28 13:34:43 +01:00
12 changed files with 858 additions and 36 deletions

138
.clang-format Normal file
View File

@ -0,0 +1,138 @@
AccessModifierOffset: 0
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
Enabled: false
AlignConsecutiveBitFields:
Enabled: true
AcrossEmptyLines: false
AcrossComments: false
AlignConsecutiveDeclarations:
Enabled: false
AlignConsecutiveMacros:
Enabled: true
AcrossEmptyLines: false
AcrossComments: false
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments: true
# Kind: Always
# OverEmptyLines: 1
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: None
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: TopLevelDefinitions
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
AttributeMacros: []
BinPackArguments: true
BinPackParameters: true
BitFieldColonSpacing: Both
BreakAfterJavaFieldAnnotations: false
#BreakArrays: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: WebKit
BreakBeforeConceptDeclarations: Always
#BreakBeforeInlineASMColon: Always
BreakBeforeTernaryOperators: false
BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterComma
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: ""
CompactNamespaces: false
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
DeriveLineEnding: false
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: Never
FixNamespaceComments: true
ForEachMacros: []
IfMacros: []
IncludeBlocks: Preserve
IncludeIsMainRegex: ""
IncludeIsMainSourceRegex: ""
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: false
IndentExternBlock: NoIndent
IndentGotoLabels: false
IndentPPDirectives: BeforeHash
IndentRequiresClause: false
IndentWidth: 8
IndentWrappedFunctionNames: false
InsertBraces: true
InsertTrailingCommas: None
JavaImportGroups: []
JavaScriptQuotes: Double
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
LambdaBodyIndentation: Signature
Language: Cpp
MacroBlockBegin: ""
MacroBlockEnd: ""
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
NamespaceMacros: []
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 8
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PPIndentWidth: 0
PackConstructorInitializers: Never
PointerAlignment: Right
QualifierAlignment: Left
RawStringFormats: []
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
#RemoveSemicolon: false
RequiresClausePosition: OwnLine
#RequiresExpressionIndentation: Keyword
SeparateDefinitionBlocks: Always
ShortNamespaceLines: 0
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceAroundPointerQualifiers: Before
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 4
SpacesInAngles: Never
SpacesInCStyleCastParentheses: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: 1
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
StatementAttributeLikeMacros: []
StatementMacros: []
TabWidth: 8
TypenameMacros: []
UseCRLF: false
UseTab: AlignWithSpaces
#WhitespaceSensitiveMacros: []

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.o
dwm

View File

@ -6,13 +6,7 @@ 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 all: dwm
options:
@echo dwm build options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
.c.o: .c.o:
${CC} -c ${CFLAGS} $< ${CC} -c ${CFLAGS} $<
@ -48,4 +42,4 @@ uninstall:
rm -f ${DESTDIR}${PREFIX}/bin/dwm\ rm -f ${DESTDIR}${PREFIX}/bin/dwm\
${DESTDIR}${MANPREFIX}/man1/dwm.1 ${DESTDIR}${MANPREFIX}/man1/dwm.1
.PHONY: all options clean dist install uninstall .PHONY: all clean dist install uninstall

View File

@ -2,6 +2,7 @@
/* appearance */ /* appearance */
static const unsigned int borderpx = 1; /* border pixel of windows */ static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int gappx = 5; /* gaps between windows */
static const unsigned int snap = 32; /* snap pixel */ static const unsigned int snap = 32; /* snap pixel */
static const int showbar = 1; /* 0 means no bar */ static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */ static const int topbar = 1; /* 0 means bottom bar */
@ -85,6 +86,9 @@ static const Key keys[] = {
{ MODKEY, XK_period, focusmon, {.i = +1 } }, { MODKEY, XK_period, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
{ MODKEY, XK_minus, setgaps, {.i = -1 } },
{ MODKEY, XK_equal, setgaps, {.i = +1 } },
{ MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } },
TAGKEYS( XK_1, 0) TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1) TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2) TAGKEYS( XK_3, 2)
@ -114,3 +118,6 @@ static const Button buttons[] = {
{ ClkTagBar, MODKEY, Button3, toggletag, {0} }, { ClkTagBar, MODKEY, Button3, toggletag, {0} },
}; };
/* torus config */
static int torusenabled = 1;
static int wormholedelta = 1; // how close to the edge do we get before we take a wormhole to the other side.

127
config.h Normal file
View File

@ -0,0 +1,127 @@
/* See LICENSE file for copyright and license details. */
/* appearance */
static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int gappx = 5; /* gaps between windows */
static const unsigned int snap = 32; /* snap pixel */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
static const char *fonts[] = { "JetBrainsMono Nerd Font Mono:size=9", "FontAwesome:style=Regular:size=9" };
static const char dmenufont[] = "JetBrainsMono Nerd Font Mono:size=9";
static const char col_fg[] = "#f09db9";
static const char col_bg[] = "#141322";
static const char col_grey[] = "#747c84";
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = { col_fg, col_bg, col_grey },
[SchemeSel] = { col_bg, col_fg, col_grey },
};
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5" };
static const Rule rules[] = {
/* xprop(1):
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
/* class instance title tags mask isfloating monitor */
{ "Gimp", NULL, NULL, 0, 1, -1 },
{ "Firefox", NULL, NULL, 1 << 8, 0, -1 },
};
/* layout(s) */
static const float mfact = 0.50; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
static const Layout layouts[] = {
/* symbol arrange function */
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
};
/* key definitions */
#define MODKEY Mod4Mask
#define TAGKEYS(KEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
/* commands */
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_bg, "-nf", col_fg, "-sb", col_fg, "-sf", col_bg, NULL };
static const char *termcmd[] = { "alacritty", NULL };
static const char *editorcmd[] = { "emacs", NULL };
static const char *browsercmd[] = { "chromium", "https://simponic.xyz/dvd-logo" , NULL };
static const char *increasebrightnesscmd[] = { "brightnessctl", "set", "-c", "backlight", "+10%", NULL };
static const char *decreasebrightnesscmd[] = { "brightnessctl", "set", "-c", "backlight", "10%-", NULL };
static const Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_d, spawn, {.v = dmenucmd } },
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
{ MODKEY|ShiftMask, XK_b, spawn, {.v = browsercmd } },
{ MODKEY|ShiftMask, XK_e, spawn, {.v = editorcmd } },
{ MODKEY|ShiftMask, XK_w, spawn, {.v = increasebrightnesscmd } },
{ MODKEY|ShiftMask, XK_s, spawn, {.v = decreasebrightnesscmd } },
{ MODKEY, XK_b, togglebar, {0} },
{ MODKEY, XK_j, focusstack, {.i = +1 } },
{ MODKEY, XK_k, focusstack, {.i = -1 } },
{ MODKEY|ShiftMask, XK_i, incnmaster, {.i = +1 } },
{ MODKEY|ShiftMask, XK_d, incnmaster, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
{ MODKEY, XK_Return, zoom, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY|ShiftMask, XK_q, killclient, {0} },
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
{ MODKEY, XK_period, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
TAGKEYS( XK_4, 3)
TAGKEYS( XK_5, 4)
TAGKEYS( XK_6, 5)
TAGKEYS( XK_7, 6)
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
{ MODKEY|ShiftMask, XK_c, quit, {0} },
};
/* button definitions */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static const Button buttons[] = {
/* click event mask button function argument */
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
};
/* torus config */
static int torusenabled = 1;
static int wormholedelta = 1; // how close to the edge do we get before we take a wormhole to the other side.

View File

@ -1,5 +1,5 @@
# dwm version # dwm version
VERSION = 6.4 VERSION = 6.5
# Customize below to fit your system # Customize below to fit your system
@ -14,6 +14,10 @@ X11LIB = /usr/X11R6/lib
XINERAMALIBS = -lXinerama XINERAMALIBS = -lXinerama
XINERAMAFLAGS = -DXINERAMA XINERAMAFLAGS = -DXINERAMA
# Xinput extensions, comment if you don't want it
XINPUTLIBS = -lXi
XINPUTFLAGS = -DXINPUT
# freetype # freetype
FREETYPELIBS = -lfontconfig -lXft FREETYPELIBS = -lfontconfig -lXft
FREETYPEINC = /usr/include/freetype2 FREETYPEINC = /usr/include/freetype2
@ -23,10 +27,10 @@ FREETYPEINC = /usr/include/freetype2
# includes and libs # includes and libs
INCS = -I${X11INC} -I${FREETYPEINC} INCS = -I${X11INC} -I${FREETYPEINC}
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XINPUTLIBS}
# 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} ${XINPUTFLAGS}
#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-deprecated-declarations -Os ${INCS} ${CPPFLAGS}
LDFLAGS = ${LIBS} LDFLAGS = ${LIBS}

195
dwm.c
View File

@ -39,6 +39,9 @@
#ifdef XINERAMA #ifdef XINERAMA
#include <X11/extensions/Xinerama.h> #include <X11/extensions/Xinerama.h>
#endif /* XINERAMA */ #endif /* XINERAMA */
#ifdef XINPUT
#include <X11/extensions/XInput2.h>
#endif /* XINPUT */
#include <X11/Xft/Xft.h> #include <X11/Xft/Xft.h>
#include "drw.h" #include "drw.h"
@ -119,6 +122,7 @@ struct Monitor {
int by; /* bar geometry */ int by; /* bar geometry */
int mx, my, mw, mh; /* screen size */ int mx, my, mw, mh; /* screen size */
int wx, wy, ww, wh; /* window area */ int wx, wy, ww, wh; /* window area */
int gappx; /* gaps between windows */
unsigned int seltags; unsigned int seltags;
unsigned int sellt; unsigned int sellt;
unsigned int tagset[2]; unsigned int tagset[2];
@ -183,12 +187,16 @@ static void mappingnotify(XEvent *e);
static void maprequest(XEvent *e); static void maprequest(XEvent *e);
static void monocle(Monitor *m); static void monocle(Monitor *m);
static void motionnotify(XEvent *e); static void motionnotify(XEvent *e);
static void rawmotionnotify(XEvent *e);
static void genericeventnotify(XEvent *e);
static void movemouse(const Arg *arg); static void movemouse(const Arg *arg);
static Client *nexttiled(Client *c); static Client *nexttiled(Client *c);
static void pop(Client *c); static void pop(Client *c);
static void propertynotify(XEvent *e); static void propertynotify(XEvent *e);
static void quit(const Arg *arg); static void quit(const Arg *arg);
static Monitor *recttomon(int x, int y, int w, int h); static Monitor *recttomon(int x, int y, int w, int h);
static Monitor *raycastx(Monitor *src, int y, int dx);
static Monitor *raycasty(Monitor *src, int x, int dy);
static void resize(Client *c, int x, int y, int w, int h, int interact); static void resize(Client *c, int x, int y, int w, int h, int interact);
static void resizeclient(Client *c, int x, int y, int w, int h); static void resizeclient(Client *c, int x, int y, int w, int h);
static void resizemouse(const Arg *arg); static void resizemouse(const Arg *arg);
@ -200,12 +208,12 @@ static void sendmon(Client *c, Monitor *m);
static void setclientstate(Client *c, long state); static void setclientstate(Client *c, long state);
static void setfocus(Client *c); static void setfocus(Client *c);
static void setfullscreen(Client *c, int fullscreen); static void setfullscreen(Client *c, int fullscreen);
static void setgaps(const Arg *arg);
static void setlayout(const Arg *arg); static void setlayout(const Arg *arg);
static void setmfact(const Arg *arg); static void setmfact(const Arg *arg);
static void setup(void); static void setup(void);
static void seturgent(Client *c, int urg); static void seturgent(Client *c, int urg);
static void showhide(Client *c); static void showhide(Client *c);
static void sigchld(int unused);
static void spawn(const Arg *arg); static void spawn(const Arg *arg);
static void tag(const Arg *arg); static void tag(const Arg *arg);
static void tagmon(const Arg *arg); static void tagmon(const Arg *arg);
@ -243,6 +251,9 @@ static int sw, sh; /* X display screen geometry width, height */
static int bh; /* bar height */ static int bh; /* bar height */
static int lrpad; /* sum of left and right padding for text */ static int lrpad; /* sum of left and right padding for text */
static int (*xerrorxlib)(Display *, XErrorEvent *); static int (*xerrorxlib)(Display *, XErrorEvent *);
#ifdef XINPUT
static int xinputextensionop;
#endif /* XINPUT */
static unsigned int numlockmask = 0; static unsigned int numlockmask = 0;
static void (*handler[LASTEvent]) (XEvent *) = { static void (*handler[LASTEvent]) (XEvent *) = {
[ButtonPress] = buttonpress, [ButtonPress] = buttonpress,
@ -258,7 +269,8 @@ static void (*handler[LASTEvent]) (XEvent *) = {
[MapRequest] = maprequest, [MapRequest] = maprequest,
[MotionNotify] = motionnotify, [MotionNotify] = motionnotify,
[PropertyNotify] = propertynotify, [PropertyNotify] = propertynotify,
[UnmapNotify] = unmapnotify [UnmapNotify] = unmapnotify,
[GenericEvent] = genericeventnotify,
}; };
static Atom wmatom[WMLast], netatom[NetLast]; static Atom wmatom[WMLast], netatom[NetLast];
static int running = 1; static int running = 1;
@ -642,6 +654,7 @@ createmon(void)
m->nmaster = nmaster; m->nmaster = nmaster;
m->showbar = showbar; m->showbar = showbar;
m->topbar = topbar; m->topbar = topbar;
m->gappx = gappx;
m->lt[0] = &layouts[0]; m->lt[0] = &layouts[0];
m->lt[1] = &layouts[1 % LENGTH(layouts)]; m->lt[1] = &layouts[1 % LENGTH(layouts)];
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
@ -834,6 +847,8 @@ focusmon(const Arg *arg)
unfocus(selmon->sel, 0); unfocus(selmon->sel, 0);
selmon = m; selmon = m;
focus(NULL); focus(NULL);
if (selmon->sel)
XWarpPointer(dpy, None, selmon->sel->win, 0, 0, 0, 0, selmon->sel->w/2, selmon->sel->h/2);
} }
void void
@ -859,6 +874,7 @@ focusstack(const Arg *arg)
if (c) { if (c) {
focus(c); focus(c);
restack(selmon); restack(selmon);
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2);
} }
} }
@ -1143,6 +1159,58 @@ motionnotify(XEvent *e)
mon = m; mon = m;
} }
void
genericeventnotify(XEvent *e)
{
if (e->xcookie.extension == xinputextensionop &&
e->xcookie.evtype == XI_RawMotion) {
rawmotionnotify(e);
}
}
void
rawmotionnotify(XEvent *e)
{
if (torusenabled == 0) return;
int x, y;
if (!getrootptr(&x, &y)) return;
int warpx = x;
int warpy = y;
if (BETWEEN(x, selmon->mx, selmon->mx + wormholedelta)) {
/* ensure there's no monitor to the left */
if (recttomon(selmon->mx - 1, y, 1, 1) != selmon)
return;
/* take the wormhole */
Monitor *farright = raycastx(selmon, y, 1);
warpx = farright->mx + farright->mw - wormholedelta - 1;
} else if (BETWEEN(x, selmon->mx + selmon->mw - wormholedelta,
selmon->mx + selmon->mw)) {
/* ensure there's no monitor to the right */
if (recttomon(selmon->mx + selmon->mw + 1, y, 1, 1) != selmon)
return;
Monitor *farleft = raycastx(selmon, y, -1);
warpx = farleft->mx + wormholedelta + 1;
} else if (BETWEEN(y, selmon->my, selmon->my + wormholedelta)) {
/* ensure there's no monitor under us */
if (recttomon(x, y, selmon->my - 1, 1) != selmon)
return;
Monitor *farup = raycasty(selmon, x, 1);
warpy = farup->my + farup->mh - wormholedelta - 1;
} else if (BETWEEN(y, selmon->my + selmon->mh - wormholedelta,
selmon->my + selmon->mh)) {
/* ensure there's no monitor above us */
if (recttomon(x, y, selmon->my + selmon->mh + 1, 1) != selmon)
return;
Monitor *fardown = raycasty(selmon, x, -1);
warpy = fardown->my + wormholedelta + 1;
}
if (warpx != x || warpy != y)
XWarpPointer(dpy, None, root, 0, 0, 0, 0, warpx, warpy);
}
void void
movemouse(const Arg *arg) movemouse(const Arg *arg)
{ {
@ -1276,6 +1344,44 @@ recttomon(int x, int y, int w, int h)
return r; return r;
} }
Monitor *
raycastx(Monitor *src, int y, int dx)
{
Monitor *farthest = src;
for (Monitor *m = mons; m; m = m->next) {
int scansy = BETWEEN(y, m->my, m->my + m->mh);
if (!scansy) {
continue;
}
if (dx == 1 && (m->mx + m->mw > farthest->mx + farthest->mw)) {
farthest = m;
}
if (dx == -1 && (m->mx < farthest->mx)) {
farthest = m;
}
}
return farthest;
}
Monitor *
raycasty(Monitor *src, int x, int dy)
{
Monitor *farthest = src;
for (Monitor *m = mons; m; m = m->next) {
int scansx = BETWEEN(x, m->mx, m->mx + m->mw);
if (!scansx) {
continue;
}
if (dy == 1 && (m->my + m->mh > farthest->my + farthest->mh)) {
farthest = m;
}
if (dy == -1 && (m->my < farthest->my)) {
farthest = m;
}
}
return farthest;
}
void void
resize(Client *c, int x, int y, int w, int h, int interact) resize(Client *c, int x, int y, int w, int h, int interact)
{ {
@ -1508,6 +1614,16 @@ setfullscreen(Client *c, int fullscreen)
} }
} }
void
setgaps(const Arg *arg)
{
if ((arg->i == 0) || (selmon->gappx + arg->i < 0))
selmon->gappx = 0;
else
selmon->gappx += arg->i;
arrange(selmon);
}
void void
setlayout(const Arg *arg) setlayout(const Arg *arg)
{ {
@ -1543,9 +1659,16 @@ setup(void)
int i; int i;
XSetWindowAttributes wa; XSetWindowAttributes wa;
Atom utf8string; Atom utf8string;
struct sigaction sa;
/* clean up any zombies immediately */ /* do not transform children into zombies when they terminate */
sigchld(0); sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART;
sa.sa_handler = SIG_IGN;
sigaction(SIGCHLD, &sa, NULL);
/* clean up any zombies (inherited from .xinitrc etc) immediately */
while (waitpid(-1, NULL, WNOHANG) > 0);
/* init screen */ /* init screen */
screen = DefaultScreen(dpy); screen = DefaultScreen(dpy);
@ -1603,6 +1726,23 @@ setup(void)
|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
XSelectInput(dpy, root, wa.event_mask); XSelectInput(dpy, root, wa.event_mask);
#ifdef XINPUT
/* select XInput raw motion events; we can't hook into PointerMotionMask since some windows block it. */
size_t maskbyteslen = XIMaskLen(XI_RawMotion);
unsigned char *maskbytes = calloc(maskbyteslen, sizeof(unsigned char));
XISetMask(maskbytes, XI_RawMotion);
XIEventMask mask;
int _unused;
if (!XQueryExtension(dpy, "XInputExtension", &xinputextensionop,
&_unused, &_unused)) {
fprintf(stderr, "XInputExtension not found");
exit(1);
}
mask.deviceid = XIAllMasterDevices;
mask.mask_len = maskbyteslen * sizeof(unsigned char);
mask.mask = maskbytes;
XISelectEvents(dpy, root, &mask, 1);
#endif /* XINPUT */
grabkeys(); grabkeys();
focus(NULL); focus(NULL);
} }
@ -1638,23 +1778,23 @@ showhide(Client *c)
} }
} }
void
sigchld(int unused)
{
if (signal(SIGCHLD, sigchld) == SIG_ERR)
die("can't install SIGCHLD handler:");
while (0 < waitpid(-1, NULL, WNOHANG));
}
void void
spawn(const Arg *arg) spawn(const Arg *arg)
{ {
struct sigaction sa;
if (arg->v == dmenucmd) if (arg->v == dmenucmd)
dmenumon[0] = '0' + selmon->num; dmenumon[0] = '0' + selmon->num;
if (fork() == 0) { if (fork() == 0) {
if (dpy) if (dpy)
close(ConnectionNumber(dpy)); close(ConnectionNumber(dpy));
setsid(); setsid();
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = SIG_DFL;
sigaction(SIGCHLD, &sa, NULL);
execvp(((char **)arg->v)[0], (char **)arg->v); execvp(((char **)arg->v)[0], (char **)arg->v);
die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]); die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]);
} }
@ -1691,18 +1831,18 @@ tile(Monitor *m)
if (n > m->nmaster) if (n > m->nmaster)
mw = m->nmaster ? m->ww * m->mfact : 0; mw = m->nmaster ? m->ww * m->mfact : 0;
else else
mw = m->ww; mw = m->ww - m->gappx;
for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
if (i < m->nmaster) { if (i < m->nmaster) {
h = (m->wh - my) / (MIN(n, m->nmaster) - i); h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx;
resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0);
if (my + HEIGHT(c) < m->wh) if (my + HEIGHT(c) + m->gappx < m->wh)
my += HEIGHT(c); my += HEIGHT(c) + m->gappx;
} else { } else {
h = (m->wh - ty) / (n - i); h = (m->wh - ty) / (n - i) - m->gappx;
resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0);
if (ty + HEIGHT(c) < m->wh) if (ty + HEIGHT(c) + m->gappx < m->wh)
ty += HEIGHT(c); ty += HEIGHT(c) + m->gappx;
} }
} }
@ -1845,7 +1985,7 @@ updatebarpos(Monitor *m)
} }
void void
updateclientlist() updateclientlist(void)
{ {
Client *c; Client *c;
Monitor *m; Monitor *m;
@ -2139,12 +2279,17 @@ main(int argc, char *argv[])
{ {
if (argc == 2 && !strcmp("-v", argv[1])) if (argc == 2 && !strcmp("-v", argv[1]))
die("dwm-"VERSION); die("dwm-"VERSION);
else if (argc != 1) else if (argc != 1 && strcmp("-s", argv[1]))
die("usage: dwm [-v]"); die("usage: dwm [-v]");
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
fputs("warning: no locale support\n", stderr); fputs("warning: no locale support\n", stderr);
if (!(dpy = XOpenDisplay(NULL))) if (!(dpy = XOpenDisplay(NULL)))
die("dwm: cannot open display"); die("dwm: cannot open display");
if (argc > 1 && !strcmp("-s", argv[1])) {
XStoreName(dpy, RootWindow(dpy, DefaultScreen(dpy)), argv[2]);
XCloseDisplay(dpy);
return 0;
}
checkotherwm(); checkotherwm();
setup(); setup();
#ifdef __OpenBSD__ #ifdef __OpenBSD__

11
patch Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash
order=("dwm-cursorwarp" "dwm-fullgaps" "dwm-torus")
for patch in ${order[@]}; do
patch_file=$(ls patches | grep $patch)
echo "applying patch $patch_file..."
git apply "patches/$patch_file" || patch < "patches/$patch_file" || echo "failed to patch $patch_file. it may've already been applied!"
done
rm *.orig

View File

@ -0,0 +1,33 @@
From 1e4936416fa5517fe447e3388e1d44c913e29f56 Mon Sep 17 00:00:00 2001
From: Markus Dam <markus.dam123@gmail.com>
Date: Mon, 22 Feb 2021 13:40:13 +0100
Subject: [PATCH] Add cursor warping
---
dwm.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/dwm.c b/dwm.c
index 331a309..c80ef8a 100644
--- a/dwm.c
+++ b/dwm.c
@@ -882,6 +882,8 @@ focusmon(const Arg *arg)
unfocus(selmon->sel, 0);
selmon = m;
focus(NULL);
+ if (selmon->sel)
+ XWarpPointer(dpy, None, selmon->sel->win, 0, 0, 0, 0, selmon->sel->w/2, selmon->sel->h/2);
}
void
@@ -906,6 +908,7 @@ focusstack(const Arg *arg)
if (c) {
focus(c);
restack(selmon);
+ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2);
}
}
--
2.30.1

View File

@ -0,0 +1,94 @@
diff -up a/config.def.h b/config.def.h
--- a/config.def.h
+++ b/config.def.h
@@ -2,6 +2,7 @@
/* appearance */
static const unsigned int borderpx = 1; /* border pixel of windows */
+static const unsigned int gappx = 5; /* gaps between windows */
static const unsigned int snap = 32; /* snap pixel */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
@@ -85,6 +86,9 @@ static const Key keys[] = {
{ MODKEY, XK_period, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
+ { MODKEY, XK_minus, setgaps, {.i = -1 } },
+ { MODKEY, XK_equal, setgaps, {.i = +1 } },
+ { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } },
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
diff -up a/dwm.c b/dwm.c
--- a/dwm.c 2023-04-30
+++ b/dwm.c 2023-04-30
@@ -119,6 +119,7 @@ struct Monitor {
int by; /* bar geometry */
int mx, my, mw, mh; /* screen size */
int wx, wy, ww, wh; /* window area */
+ int gappx; /* gaps between windows */
unsigned int seltags;
unsigned int sellt;
unsigned int tagset[2];
@@ -200,6 +201,7 @@ static void sendmon(Client *c, Monitor *
static void setclientstate(Client *c, long state);
static void setfocus(Client *c);
static void setfullscreen(Client *c, int fullscreen);
+static void setgaps(const Arg *arg);
static void setlayout(const Arg *arg);
static void setmfact(const Arg *arg);
static void setup(void);
@@ -641,6 +643,7 @@ createmon(void)
m->nmaster = nmaster;
m->showbar = showbar;
m->topbar = topbar;
+ m->gappx = gappx;
m->lt[0] = &layouts[0];
m->lt[1] = &layouts[1 % LENGTH(layouts)];
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
@@ -1508,6 +1511,16 @@ setfullscreen(Client *c, int fullscreen)
}
void
+setgaps(const Arg *arg)
+{
+ if ((arg->i == 0) || (selmon->gappx + arg->i < 0))
+ selmon->gappx = 0;
+ else
+ selmon->gappx += arg->i;
+ arrange(selmon);
+}
+
+void
setlayout(const Arg *arg)
{
if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
@@ -1697,18 +1710,18 @@ tile(Monitor *m)
if (n > m->nmaster)
mw = m->nmaster ? m->ww * m->mfact : 0;
else
- mw = m->ww;
- for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
- if (i < m->nmaster) {
- h = (m->wh - my) / (MIN(n, m->nmaster) - i);
- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0);
- if (my + HEIGHT(c) < m->wh)
- my += HEIGHT(c);
+ mw = m->ww - m->gappx;
+ for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
+ if (i < m->nmaster) {
+ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx;
+ resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0);
+ if (my + HEIGHT(c) + m->gappx < m->wh)
+ my += HEIGHT(c) + m->gappx;
} else {
- h = (m->wh - ty) / (n - i);
- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0);
- if (ty + HEIGHT(c) < m->wh)
- ty += HEIGHT(c);
+ h = (m->wh - ty) / (n - i) - m->gappx;
+ resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0);
+ if (ty + HEIGHT(c) + m->gappx < m->wh)
+ ty += HEIGHT(c) + m->gappx;
}
}

View File

@ -0,0 +1,49 @@
From dbfb346a86c79b50bfa27c75547b42e34cb54715 Mon Sep 17 00:00:00 2001
From: aleks <aleks.stier@icloud.com>
Date: Fri, 11 Sep 2020 17:42:50 +0200
Subject: [PATCH] Apply setstatus-6.2
Enables to set the status with dwm itself. No more xsetroot bloat!
To change the status to `foo bar` execute:
dwm -s "foo bar"
Piping into `dwm -s` is currently not supported but you can set the
status to the output of any command by doing something like:
dwm -s "$(run_command_which_outputs_the_status)"
For example to set the status to the current date run:
dwm -s "$(date)"
---
dwm.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/dwm.c b/dwm.c
index 4465af1..b3c8f71 100644
--- a/dwm.c
+++ b/dwm.c
@@ -2129,12 +2129,17 @@ main(int argc, char *argv[])
{
if (argc == 2 && !strcmp("-v", argv[1]))
die("dwm-"VERSION);
- else if (argc != 1)
+ else if (argc != 1 && strcmp("-s", argv[1]))
die("usage: dwm [-v]");
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
fputs("warning: no locale support\n", stderr);
if (!(dpy = XOpenDisplay(NULL)))
die("dwm: cannot open display");
+ if (argc > 1 && !strcmp("-s", argv[1])) {
+ XStoreName(dpy, RootWindow(dpy, DefaultScreen(dpy)), argv[2]);
+ XCloseDisplay(dpy);
+ return 0;
+ }
checkotherwm();
setup();
#ifdef __OpenBSD__
--
2.28.0

View File

@ -0,0 +1,218 @@
diff --git a/config.def.h b/config.def.h
index 9efa774..8251624 100644
--- a/config.def.h
+++ b/config.def.h
@@ -114,3 +114,6 @@ static const Button buttons[] = {
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
};
+/* torus config */
+static int torusenabled = 1;
+static int wormholedelta = 1; // how close to the edge do we get before we take a wormhole to the other side.
diff --git a/config.mk b/config.mk
index 8efca9a..5f7634f 100644
--- a/config.mk
+++ b/config.mk
@@ -14,6 +14,10 @@ X11LIB = /usr/X11R6/lib
XINERAMALIBS = -lXinerama
XINERAMAFLAGS = -DXINERAMA
+# Xinput extensions, comment if you don't want it
+XINPUTLIBS = -lXi
+XINPUTFLAGS = -DXINPUT
+
# freetype
FREETYPELIBS = -lfontconfig -lXft
FREETYPEINC = /usr/include/freetype2
@@ -23,10 +27,10 @@ FREETYPEINC = /usr/include/freetype2
# includes and libs
INCS = -I${X11INC} -I${FREETYPEINC}
-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
+LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XINPUTLIBS}
# flags
-CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
+CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} ${XINPUTFLAGS}
#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS}
LDFLAGS = ${LIBS}
diff --git a/dwm.c b/dwm.c
index 67c6b2b..392496e 100644
--- a/dwm.c
+++ b/dwm.c
@@ -39,6 +39,9 @@
#ifdef XINERAMA
#include <X11/extensions/Xinerama.h>
#endif /* XINERAMA */
+#ifdef XINPUT
+#include <X11/extensions/XInput2.h>
+#endif /* XINPUT */
#include <X11/Xft/Xft.h>
#include "drw.h"
@@ -183,12 +186,16 @@ static void mappingnotify(XEvent *e);
static void maprequest(XEvent *e);
static void monocle(Monitor *m);
static void motionnotify(XEvent *e);
+static void rawmotionnotify(XEvent *e);
+static void genericeventnotify(XEvent *e);
static void movemouse(const Arg *arg);
static Client *nexttiled(Client *c);
static void pop(Client *c);
static void propertynotify(XEvent *e);
static void quit(const Arg *arg);
static Monitor *recttomon(int x, int y, int w, int h);
+static Monitor *raycastx(Monitor *src, int y, int dx);
+static Monitor *raycasty(Monitor *src, int x, int dy);
static void resize(Client *c, int x, int y, int w, int h, int interact);
static void resizeclient(Client *c, int x, int y, int w, int h);
static void resizemouse(const Arg *arg);
@@ -242,6 +249,9 @@ static int sw, sh; /* X display screen geometry width, height */
static int bh; /* bar height */
static int lrpad; /* sum of left and right padding for text */
static int (*xerrorxlib)(Display *, XErrorEvent *);
+#ifdef XINPUT
+static int xinputextensionop;
+#endif /* XINPUT */
static unsigned int numlockmask = 0;
static void (*handler[LASTEvent]) (XEvent *) = {
[ButtonPress] = buttonpress,
@@ -257,7 +267,8 @@ static void (*handler[LASTEvent]) (XEvent *) = {
[MapRequest] = maprequest,
[MotionNotify] = motionnotify,
[PropertyNotify] = propertynotify,
- [UnmapNotify] = unmapnotify
+ [UnmapNotify] = unmapnotify,
+ [GenericEvent] = genericeventnotify,
};
static Atom wmatom[WMLast], netatom[NetLast];
static int running = 1;
@@ -1142,6 +1153,58 @@ motionnotify(XEvent *e)
mon = m;
}
+void
+genericeventnotify(XEvent *e)
+{
+ if (e->xcookie.extension == xinputextensionop &&
+ e->xcookie.evtype == XI_RawMotion) {
+ rawmotionnotify(e);
+ }
+}
+
+void
+rawmotionnotify(XEvent *e)
+{
+ if (torusenabled == 0) return;
+
+ int x, y;
+ if (!getrootptr(&x, &y)) return;
+
+ int warpx = x;
+ int warpy = y;
+ if (BETWEEN(x, selmon->mx, selmon->mx + wormholedelta)) {
+ /* ensure there's no monitor to the left */
+ if (recttomon(selmon->mx - 1, y, 1, 1) != selmon)
+ return;
+ /* take the wormhole */
+ Monitor *farright = raycastx(selmon, y, 1);
+ warpx = farright->mx + farright->mw - wormholedelta - 1;
+ } else if (BETWEEN(x, selmon->mx + selmon->mw - wormholedelta,
+ selmon->mx + selmon->mw)) {
+ /* ensure there's no monitor to the right */
+ if (recttomon(selmon->mx + selmon->mw + 1, y, 1, 1) != selmon)
+ return;
+ Monitor *farleft = raycastx(selmon, y, -1);
+ warpx = farleft->mx + wormholedelta + 1;
+ } else if (BETWEEN(y, selmon->my, selmon->my + wormholedelta)) {
+ /* ensure there's no monitor under us */
+ if (recttomon(x, y, selmon->my - 1, 1) != selmon)
+ return;
+ Monitor *farup = raycasty(selmon, x, 1);
+ warpy = farup->my + farup->mh - wormholedelta - 1;
+ } else if (BETWEEN(y, selmon->my + selmon->mh - wormholedelta,
+ selmon->my + selmon->mh)) {
+ /* ensure there's no monitor above us */
+ if (recttomon(x, y, selmon->my + selmon->mh + 1, 1) != selmon)
+ return;
+ Monitor *fardown = raycasty(selmon, x, -1);
+ warpy = fardown->my + wormholedelta + 1;
+ }
+
+ if (warpx != x || warpy != y)
+ XWarpPointer(dpy, None, root, 0, 0, 0, 0, warpx, warpy);
+}
+
void
movemouse(const Arg *arg)
{
@@ -1275,6 +1338,44 @@ recttomon(int x, int y, int w, int h)
return r;
}
+Monitor *
+raycastx(Monitor *src, int y, int dx)
+{
+ Monitor *farthest = src;
+ for (Monitor *m = mons; m; m = m->next) {
+ int scansy = BETWEEN(y, m->my, m->my + m->mh);
+ if (!scansy) {
+ continue;
+ }
+ if (dx == 1 && (m->mx + m->mw > farthest->mx + farthest->mw)) {
+ farthest = m;
+ }
+ if (dx == -1 && (m->mx < farthest->mx)) {
+ farthest = m;
+ }
+ }
+ return farthest;
+}
+
+Monitor *
+raycasty(Monitor *src, int x, int dy)
+{
+ Monitor *farthest = src;
+ for (Monitor *m = mons; m; m = m->next) {
+ int scansx = BETWEEN(x, m->mx, m->mx + m->mw);
+ if (!scansx) {
+ continue;
+ }
+ if (dy == 1 && (m->my + m->mh > farthest->my + farthest->mh)) {
+ farthest = m;
+ }
+ if (dy == -1 && (m->my < farthest->my)) {
+ farthest = m;
+ }
+ }
+ return farthest;
+}
+
void
resize(Client *c, int x, int y, int w, int h, int interact)
{
@@ -1609,6 +1710,23 @@ setup(void)
|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
XSelectInput(dpy, root, wa.event_mask);
+#ifdef XINPUT
+ /* select XInput raw motion events; we can't hook into PointerMotionMask since some windows block it. */
+ size_t maskbyteslen = XIMaskLen(XI_RawMotion);
+ unsigned char *maskbytes = calloc(maskbyteslen, sizeof(unsigned char));
+ XISetMask(maskbytes, XI_RawMotion);
+ XIEventMask mask;
+ int _unused;
+ if (!XQueryExtension(dpy, "XInputExtension", &xinputextensionop,
+ &_unused, &_unused)) {
+ fprintf(stderr, "XInputExtension not found");
+ exit(1);
+ }
+ mask.deviceid = XIAllMasterDevices;
+ mask.mask_len = maskbyteslen * sizeof(unsigned char);
+ mask.mask = maskbytes;
+ XISelectEvents(dpy, root, &mask, 1);
+#endif /* XINPUT */
grabkeys();
focus(NULL);
}