Compare commits
	
		
			14 Commits
		
	
	
		
			281a9ec38d
			...
			228a973572
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 228a973572 | |||
| 17aef25baa | |||
| 28cc4026fb | |||
| 7598234552 | |||
| 7dae37c366 | |||
| 6a8f6b4aa1 | |||
| a42e4c8813 | |||
| 6f4234021d | |||
| 7d2d152126 | |||
| 14703cc679 | |||
| 0a0a1cfdfa | |||
| d49c9a793e | |||
|  | 67d76bdc68 | ||
|  | 61bb8b2241 | 
							
								
								
									
										41
									
								
								config.def.h
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								config.def.h
									
									
									
									
									
								
							| @ -2,7 +2,8 @@ | ||||
| 
 | ||||
| /* appearance */ | ||||
| static const unsigned int borderpx  = 2;        /* border pixel of windows */ | ||||
| static const unsigned int gappx     = 6;        /* gaps between windows */ | ||||
| static const int startwithgaps[]    = { 1 };	/* 1 means gaps are used by default, this can be customized for each tag */ | ||||
| static const unsigned int gappx[]   = { 10 };   /* default gap between windows in pixels, this can be customized for each tag */ | ||||
| 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 */ | ||||
| @ -34,19 +35,18 @@ static const Rule rules[] = { | ||||
| 	 *	WM_CLASS(STRING) = instance, class | ||||
| 	 *	WM_NAME(STRING) = title | ||||
| 	 */ | ||||
| 	/* class      instance    title       tags mask     iscentered   isfloating   monitor */ | ||||
| 	{ "Gimp",     NULL,       NULL,       0,            0,           1,           -1 }, | ||||
| 	{ "Firefox",  NULL,       NULL,       0,            1,           0,           -1 }, | ||||
| 	{ "firefox",  NULL,       NULL,       0,            1,           0,           -1 }, | ||||
| 	{ "St",       NULL,       NULL,       0,            1,           0,           -1 }, | ||||
| 	{ "Gcr-prompt", NULL,     NULL,       0,            1,           0,           -1 }, | ||||
| 	/* 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.55; /* factor of master area size [0.05..0.95] */ | ||||
| static const int nmaster     = 1;    /* number of clients in master area */ | ||||
| static const int resizehints = 1;    /* 1 means respect size hints in tiled resizals */ | ||||
| static const int attachbelow = 1;    /* 1 means attach after the currently active window */ | ||||
| 
 | ||||
| /* mouse scroll resize */ | ||||
| static const int scrollsensetivity = 30; /* 1 means resize window by 1 pixel for each scroll event */ | ||||
| 
 | ||||
| #include "fibonacci.c" | ||||
| static const Layout layouts[] = { | ||||
| @ -54,9 +54,9 @@ static const Layout layouts[] = { | ||||
| 	{ "[]=",      tile },    /* first entry is default */ | ||||
| 	{ "><>",      NULL },    /* no layout function means floating behavior */ | ||||
| 	{ "[M]",      monocle }, | ||||
| 	{ "[D]",      deck }, | ||||
| 	{ "[@]",      spiral }, | ||||
| 	{ "[\\]",      dwindle }, | ||||
| 	{ "DD",       doubledeck }, | ||||
| }; | ||||
| 
 | ||||
| /* key definitions */ | ||||
| @ -92,9 +92,9 @@ static Key keys[] = { | ||||
| 	{ MODKEY,                       XK_t,      setlayout,      {.v = &layouts[0]} }, | ||||
| 	{ MODKEY,                       XK_f,      setlayout,      {.v = &layouts[1]} }, | ||||
| 	{ MODKEY,                       XK_m,      setlayout,      {.v = &layouts[2]} }, | ||||
| 	{ MODKEY,                       XK_c,      setlayout,      {.v = &layouts[3]} }, | ||||
| 	{ MODKEY,                       XK_r,      setlayout,      {.v = &layouts[4]} }, | ||||
| 	{ MODKEY|ShiftMask,             XK_r,      setlayout,      {.v = &layouts[5]} }, | ||||
| 	{ MODKEY,                       XK_r,      setlayout,      {.v = &layouts[3]} }, | ||||
| 	{ MODKEY|ShiftMask,             XK_r,      setlayout,      {.v = &layouts[4]} }, | ||||
| 	{ MODKEY|ShiftMask,             XK_d,      setlayout,      {.v = &layouts[5]} }, | ||||
| 	{ MODKEY,                       XK_space,  setlayout,      {0} }, | ||||
| 	{ MODKEY|ShiftMask,             XK_space,  togglefloating, {0} }, | ||||
| 	{ MODKEY,                       XK_0,      view,           {.ui = ~0 } }, | ||||
| @ -103,6 +103,10 @@ static 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 = -5 } }, | ||||
| 	{ MODKEY,                       XK_equal,  setgaps,        {.i = +5 } }, | ||||
| 	{ MODKEY|ShiftMask,             XK_minus,  setgaps,        {.i = GAP_RESET } }, | ||||
| 	{ MODKEY|ShiftMask,             XK_equal,  setgaps,        {.i = GAP_TOGGLE} }, | ||||
| 	TAGKEYS(                        XK_1,                      0) | ||||
| 	TAGKEYS(                        XK_2,                      1) | ||||
| 	TAGKEYS(                        XK_3,                      2) | ||||
| @ -115,6 +119,15 @@ static Key keys[] = { | ||||
| 	{ MODKEY|ShiftMask,             XK_q,      quit,           {0} }, | ||||
| }; | ||||
| 
 | ||||
| /* resizemousescroll direction argument list */ | ||||
| static const int scrollargs[][2] = { | ||||
| 	/* width change         height change */ | ||||
| 	{ +scrollsensetivity,	0 }, | ||||
| 	{ -scrollsensetivity,	0 }, | ||||
| 	{ 0, 				  	+scrollsensetivity }, | ||||
| 	{ 0, 					-scrollsensetivity }, | ||||
| }; | ||||
| 
 | ||||
| /* button definitions */ | ||||
| /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ | ||||
| static Button buttons[] = { | ||||
| @ -126,6 +139,10 @@ static Button buttons[] = { | ||||
| 	{ ClkClientWin,         MODKEY,         Button1,        movemouse,      {0} }, | ||||
| 	{ ClkClientWin,         MODKEY,         Button2,        togglefloating, {0} }, | ||||
| 	{ ClkClientWin,         MODKEY,         Button3,        resizemouse,    {0} }, | ||||
| 	{ ClkClientWin,         MODKEY,         Button4,        resizemousescroll, {.v = &scrollargs[0]} }, | ||||
| 	{ ClkClientWin,         MODKEY,         Button5,        resizemousescroll, {.v = &scrollargs[1]} }, | ||||
| 	{ ClkClientWin,         MODKEY,         Button6,        resizemousescroll, {.v = &scrollargs[2]} }, | ||||
| 	{ ClkClientWin,         MODKEY,         Button7,        resizemousescroll, {.v = &scrollargs[3]} }, | ||||
| 	{ ClkTagBar,            0,              Button1,        view,           {0} }, | ||||
| 	{ ClkTagBar,            0,              Button3,        toggleview,     {0} }, | ||||
| 	{ ClkTagBar,            MODKEY,         Button1,        tag,            {0} }, | ||||
|  | ||||
							
								
								
									
										26
									
								
								dwm.1
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								dwm.1
									
									
									
									
									
								
							| @ -29,10 +29,15 @@ color. The tags of the focused window are indicated with a filled square in the | ||||
| top left corner.  The tags which are applied to one or more windows are | ||||
| indicated with an empty square in the top left corner. | ||||
| .P | ||||
| The attach below patch makes newly spawned windows attach after the currently | ||||
| selected window | ||||
| .P | ||||
| dwm draws a small border around windows to indicate the focus state. | ||||
| .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 | ||||
| .TP | ||||
| .B \-v | ||||
| @ -155,6 +160,21 @@ Toggles focused window between floating and tiled state. | ||||
| .TP | ||||
| .B Mod1\-Button3 | ||||
| Resize focused window while dragging. Tiled windows will be toggled to the floating state. | ||||
| .SH 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 | ||||
| dwm is customized by creating a custom config.h and (re)compiling the source | ||||
| code. This keeps it fast, secure and simple. | ||||
|  | ||||
							
								
								
									
										346
									
								
								dwm.c
									
									
									
									
									
								
							
							
						
						
									
										346
									
								
								dwm.c
									
									
									
									
									
								
							| @ -29,6 +29,7 @@ | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <sys/wait.h> | ||||
| #include <X11/cursorfont.h> | ||||
| #include <X11/keysym.h> | ||||
| @ -49,15 +50,23 @@ | ||||
| #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) | ||||
| #define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ | ||||
|                                * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) | ||||
| #define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags])) | ||||
| #define ISVISIBLEONTAG(C, T)    ((C->tags & T)) | ||||
| #define ISVISIBLE(C)            ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags]) | ||||
| #define LENGTH(X)               (sizeof X / sizeof X[0]) | ||||
| #define MOUSEMASK               (BUTTONMASK|PointerMotionMask) | ||||
| #define WIDTH(X)                ((X)->w + 2 * (X)->bw + gappx) | ||||
| #define HEIGHT(X)               ((X)->h + 2 * (X)->bw + gappx) | ||||
| #define WIDTH(X)                ((X)->w + 2 * (X)->bw) | ||||
| #define HEIGHT(X)               ((X)->h + 2 * (X)->bw) | ||||
| #define TAGMASK                 ((1 << LENGTH(tags)) - 1) | ||||
| #define TEXTW(X)                (drw_fontset_getwidth(drw, (X)) + lrpad) | ||||
| 
 | ||||
| #define GAP_TOGGLE 100 | ||||
| #define GAP_RESET  0 | ||||
| #define OPAQUE                  0xffU | ||||
| /* Undefined in X11/X.h buttons that are actualy exist and correspond to
 | ||||
|  * horizontal scroll | ||||
|  */ | ||||
| #define Button6			6 | ||||
| #define Button7			7 | ||||
| 
 | ||||
| /* enums */ | ||||
| enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ | ||||
| @ -94,7 +103,7 @@ struct Client { | ||||
| 	int basew, baseh, incw, inch, maxw, maxh, minw, minh; | ||||
| 	int bw, oldbw; | ||||
| 	unsigned int tags; | ||||
| 	int isfixed, iscentered, isfloating, isurgent, neverfocus, oldstate, isfullscreen; | ||||
| 	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; | ||||
| 	Client *next; | ||||
| 	Client *snext; | ||||
| 	Monitor *mon; | ||||
| @ -114,6 +123,7 @@ typedef struct { | ||||
| } Layout; | ||||
| 
 | ||||
| typedef struct Pertag Pertag; | ||||
| 
 | ||||
| struct Monitor { | ||||
| 	char ltsymbol[16]; | ||||
| 	float mfact; | ||||
| @ -141,7 +151,6 @@ typedef struct { | ||||
| 	const char *instance; | ||||
| 	const char *title; | ||||
| 	unsigned int tags; | ||||
| 	int iscentered; | ||||
| 	int isfloating; | ||||
| 	int monitor; | ||||
| } Rule; | ||||
| @ -163,11 +172,11 @@ static void configure(Client *c); | ||||
| static void configurenotify(XEvent *e); | ||||
| static void configurerequest(XEvent *e); | ||||
| static Monitor *createmon(void); | ||||
| static void deck(Monitor *m); | ||||
| static void destroynotify(XEvent *e); | ||||
| static void detach(Client *c); | ||||
| static void detachstack(Client *c); | ||||
| static Monitor *dirtomon(int dir); | ||||
| static void doubledeck(Monitor *m); | ||||
| static void drawbar(Monitor *m); | ||||
| static void drawbars(void); | ||||
| static void enternotify(XEvent *e); | ||||
| @ -191,6 +200,7 @@ static void maprequest(XEvent *e); | ||||
| static void monocle(Monitor *m); | ||||
| static void motionnotify(XEvent *e); | ||||
| static void movemouse(const Arg *arg); | ||||
| static Client *nexttagged(Client *c); | ||||
| static Client *nexttiled(Client *c); | ||||
| static void pop(Client *); | ||||
| static void propertynotify(XEvent *e); | ||||
| @ -199,15 +209,17 @@ static Monitor *recttomon(int x, int y, int w, int h); | ||||
| 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); | ||||
| static void resizemousescroll(const Arg *arg); | ||||
| static void restack(Monitor *m); | ||||
| static void run(void); | ||||
| static void runAutostart(void); | ||||
| static void runautostart(void); | ||||
| static void scan(void); | ||||
| static int sendevent(Client *c, Atom proto); | ||||
| static void sendmon(Client *c, Monitor *m); | ||||
| 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); | ||||
| @ -245,7 +257,11 @@ static void xinitvisual(); | ||||
| static void zoom(const Arg *arg); | ||||
| 
 | ||||
| /* variables */ | ||||
| static const char autostartblocksh[] = "autostart_blocking.sh"; | ||||
| static const char autostartsh[] = "autostart.sh"; | ||||
| static const char broken[] = "broken"; | ||||
| static const char dwmdir[] = "dwm"; | ||||
| static const char localshare[] = ".local/share"; | ||||
| static char stext[256]; | ||||
| static int screen; | ||||
| static int sw, sh;           /* X display screen geometry width, height */ | ||||
| @ -293,6 +309,9 @@ struct Pertag { | ||||
| 	unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ | ||||
| 	const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes  */ | ||||
| 	int showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ | ||||
| 
 | ||||
| 	int drawwithgaps[LENGTH(tags) + 1]; /* gaps toggle for each tag */ | ||||
| 	int gappx[LENGTH(tags) + 1]; /* gaps for each tag */ | ||||
| }; | ||||
| 
 | ||||
| /* compile-time check if all tags fit into an unsigned int bit array. */ | ||||
| @ -309,7 +328,6 @@ applyrules(Client *c) | ||||
| 	XClassHint ch = { NULL, NULL }; | ||||
| 
 | ||||
| 	/* rule matching */ | ||||
| 	c->iscentered = 0; | ||||
| 	c->isfloating = 0; | ||||
| 	c->tags = 0; | ||||
| 	XGetClassHint(dpy, c->win, &ch); | ||||
| @ -322,7 +340,6 @@ applyrules(Client *c) | ||||
| 		&& (!r->class || strstr(class, r->class)) | ||||
| 		&& (!r->instance || strstr(instance, r->instance))) | ||||
| 		{ | ||||
| 			c->iscentered = r->iscentered; | ||||
| 			c->isfloating = r->isfloating; | ||||
| 			c->tags |= r->tags; | ||||
| 			for (m = mons; m && m->num != r->monitor; m = m->next); | ||||
| @ -435,10 +452,16 @@ void | ||||
| attachBelow(Client *c) | ||||
| { | ||||
| 	//If there is nothing on the monitor or the selected client is floating, attach as normal
 | ||||
| 	if(c->mon->sel == NULL || c->mon->sel == c || c->mon->sel->isfloating) { | ||||
| 	if(c->mon->sel == NULL || c->mon->sel->isfloating) { | ||||
|         Client *at = nexttagged(c); | ||||
|         if(!at) { | ||||
|             attach(c); | ||||
|             return; | ||||
|             } | ||||
|         c->next = at->next; | ||||
|         at->next = c; | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	//Set the new client's next property to the same as the currently selected clients next
 | ||||
| 	c->next = c->mon->sel->next; | ||||
| @ -480,7 +503,7 @@ buttonpress(XEvent *e) | ||||
| 			arg.ui = 1 << i; | ||||
| 		} else if (ev->x < x + blw) | ||||
| 			click = ClkLtSymbol; | ||||
| 		else if (ev->x > selmon->ww - TEXTW(stext)) | ||||
| 		else if (ev->x > selmon->ww - (int)TEXTW(stext)) | ||||
| 			click = ClkStatusText; | ||||
| 		else | ||||
| 			click = ClkWinTitle; | ||||
| @ -695,7 +718,14 @@ createmon(void) | ||||
| 		m->pertag->sellts[i] = m->sellt; | ||||
| 
 | ||||
| 		m->pertag->showbars[i] = m->showbar; | ||||
| 
 | ||||
| 		if (i > 0) { | ||||
| 			m->pertag->drawwithgaps[i] = startwithgaps[(i - 1) % LENGTH(gappx)]; | ||||
| 			m->pertag->gappx[i] = gappx[(i - 1) % LENGTH(gappx)]; | ||||
| 		} | ||||
| 	} | ||||
| 	m->pertag->drawwithgaps[0] = startwithgaps[0]; | ||||
| 	m->pertag->gappx[0] = gappx[0]; | ||||
| 
 | ||||
| 	return m; | ||||
| } | ||||
| @ -710,31 +740,6 @@ destroynotify(XEvent *e) | ||||
| 		unmanage(c, 1); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| deck(Monitor *m) { | ||||
| 	unsigned int i, n, h, mw, my; | ||||
| 	Client *c; | ||||
| 
 | ||||
| 	for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); | ||||
| 	if(n == 0) | ||||
| 		return; | ||||
| 
 | ||||
| 	if(n > m->nmaster) { | ||||
| 		mw = m->nmaster ? m->ww * m->mfact : 0; | ||||
| 		snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n - m->nmaster); | ||||
| 	} | ||||
| 	else | ||||
| 		mw = m->ww; | ||||
| 	for(i = my = 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), False); | ||||
| 			my += HEIGHT(c); | ||||
| 		} | ||||
| 		else | ||||
| 			resize(c, m->wx + mw, m->wy, m->ww - mw - (2*c->bw), m->wh - (2*c->bw), False); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| detach(Client *c) | ||||
| { | ||||
| @ -773,6 +778,27 @@ dirtomon(int dir) | ||||
| 	return m; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| doubledeck(Monitor *m) { | ||||
| 	unsigned int i, n, mw; | ||||
| 	Client *c; | ||||
| 
 | ||||
| 	for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); | ||||
| 	if(n == 0) | ||||
| 		return; | ||||
| 
 | ||||
| 	if(n > m->nmaster) | ||||
| 		mw = m->nmaster ? m->ww * m->mfact : 0; | ||||
| 	else | ||||
| 		mw = m->ww; | ||||
| 
 | ||||
| 	for(i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) | ||||
| 		if(i < m->nmaster) | ||||
| 			resize(c, m->wx, m->wy, mw - (2*c->bw), m->wh - (2*c->bw), False); | ||||
| 		else | ||||
| 			resize(c, m->wx + mw, m->wy, m->ww - mw - (2*c->bw), m->wh - (2*c->bw), False); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| drawbar(Monitor *m) | ||||
| { | ||||
| @ -877,6 +903,12 @@ focus(Client *c) | ||||
| 		attachstack(c); | ||||
| 		grabbuttons(c, 1); | ||||
| 		XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); | ||||
|                 if (!selmon->pertag->drawwithgaps[selmon->pertag->curtag] && !c->isfloating) { | ||||
| 			XWindowChanges wc; | ||||
|                         wc.sibling = selmon->barwin; | ||||
|                         wc.stack_mode = Below; | ||||
|                         XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc); | ||||
|                 } | ||||
| 		setfocus(c); | ||||
| 	} else { | ||||
| 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); | ||||
| @ -915,7 +947,7 @@ focusstack(const Arg *arg) | ||||
| { | ||||
| 	Client *c = NULL, *i; | ||||
| 
 | ||||
| 	if (!selmon->sel) | ||||
| 	if (!selmon->sel || selmon->sel->isfullscreen) | ||||
| 		return; | ||||
| 	if (arg->i > 0) { | ||||
| 		for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); | ||||
| @ -1137,20 +1169,15 @@ manage(Window w, XWindowAttributes *wa) | ||||
| 	updatewindowtype(c); | ||||
| 	updatesizehints(c); | ||||
| 	updatewmhints(c); | ||||
| 	if (c->iscentered) { | ||||
| 	c->x = c->mon->mx + (c->mon->mw - WIDTH(c)) / 2; | ||||
| 	c->y = c->mon->my + (c->mon->mh - HEIGHT(c)) / 2; | ||||
| 	} | ||||
| 	XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); | ||||
| 	grabbuttons(c, 0); | ||||
| 	if (!c->isfloating) | ||||
| 		c->isfloating = c->oldstate = trans != None || c->isfixed; | ||||
| 	if (c->isfloating) | ||||
| 		XRaiseWindow(dpy, c->win); | ||||
| 	if( attachbelow ) | ||||
| 	attachBelow(c); | ||||
| 	else | ||||
| 		attach(c); | ||||
| 	attachstack(c); | ||||
| 	XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, | ||||
| 		(unsigned char *) &(c->win), 1); | ||||
| @ -1200,7 +1227,10 @@ monocle(Monitor *m) | ||||
| 	if (n > 0) /* override layout symbol */ | ||||
| 		snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); | ||||
| 	for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) | ||||
| 		if (selmon->pertag->drawwithgaps[selmon->pertag->curtag]) | ||||
| 			resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); | ||||
| 		else | ||||
| 			resize(c, m->wx - c->bw, m->wy, m->ww, m->wh, False); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| @ -1280,6 +1310,16 @@ movemouse(const Arg *arg) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  Client * | ||||
| nexttagged(Client *c) { | ||||
| 	Client *walked = c->mon->clients; | ||||
| 	for(; | ||||
| 		walked && (walked->isfloating || !ISVISIBLEONTAG(walked, c->tags)); | ||||
| 		walked = walked->next | ||||
| 	); | ||||
| 	return walked; | ||||
| } | ||||
| 
 | ||||
| Client * | ||||
| nexttiled(Client *c) | ||||
| { | ||||
| @ -1364,36 +1404,21 @@ void | ||||
| resizeclient(Client *c, int x, int y, int w, int h) | ||||
| { | ||||
| 	XWindowChanges wc; | ||||
| 	unsigned int n; | ||||
| 	unsigned int gapoffset; | ||||
| 	unsigned int gapincr; | ||||
| 	Client *nbc; | ||||
| 
 | ||||
| 	c->oldx = c->x; c->x = wc.x = x; | ||||
| 	c->oldy = c->y; c->y = wc.y = y; | ||||
| 	c->oldw = c->w; c->w = wc.width = w; | ||||
| 	c->oldh = c->h; c->h = wc.height = h; | ||||
| 	wc.border_width = c->bw; | ||||
| 
 | ||||
| 	/* Get number of clients for the selected monitor */ | ||||
| 	for (n = 0, nbc = nexttiled(selmon->clients); nbc; nbc = nexttiled(nbc->next), n++); | ||||
| 
 | ||||
| 	/* Do nothing if layout is floating */ | ||||
| 	if (c->isfloating || selmon->lt[selmon->sellt]->arrange == NULL) { | ||||
| 		gapincr = gapoffset = 0; | ||||
| 	} else { | ||||
| 		/* Remove border and gap if layout is monocle or only one client */ | ||||
| 		if (selmon->lt[selmon->sellt]->arrange == monocle || n == 1) { | ||||
| 			gapoffset = 0; | ||||
| 			gapincr = -2 * borderpx; | ||||
| 	if (!selmon->pertag->drawwithgaps[selmon->pertag->curtag] && /* this is the noborderfloatingfix patch, slightly modified so that it will work if, and only if, gaps are disabled. */ | ||||
| 	    (((nexttiled(c->mon->clients) == c && !nexttiled(c->next)) /* these two first lines are the only ones changed. if you are manually patching and have noborder installed already, just change these lines; or conversely, just remove this section if the noborder patch is not desired;) */ | ||||
| 	    || &monocle == c->mon->lt[c->mon->sellt]->arrange)) | ||||
| 	    && !c->isfullscreen && !c->isfloating | ||||
| 	    && NULL != c->mon->lt[c->mon->sellt]->arrange) { | ||||
| 	        c->w = wc.width += c->bw * 2; | ||||
| 	        c->h = wc.height += c->bw * 2; | ||||
| 	        wc.border_width = 0; | ||||
| 		} else { | ||||
| 			gapoffset = gappx; | ||||
| 			gapincr = 2 * gappx; | ||||
| 	} | ||||
| 	} | ||||
| 
 | ||||
| 	c->oldx = c->x; c->x = wc.x = x + gapoffset; | ||||
| 	c->oldy = c->y; c->y = wc.y = y + gapoffset; | ||||
| 	c->oldw = c->w; c->w = wc.width = w - gapincr; | ||||
| 	c->oldh = c->h; c->h = wc.height = h - gapincr; | ||||
| 
 | ||||
| 	XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); | ||||
| 	configure(c); | ||||
| 	XSync(dpy, False); | ||||
| @ -1456,6 +1481,45 @@ resizemouse(const Arg *arg) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void | ||||
| resizemousescroll(const Arg *arg) | ||||
| { | ||||
| 	int nw, nh; | ||||
| 	Client *c; | ||||
| 	Monitor *m; | ||||
| 	XEvent ev; | ||||
| 	int dw = *((int*)arg->v + 1); | ||||
| 	int dh = *(int*)arg->v; | ||||
| 
 | ||||
| 	if (!(c = selmon->sel)) | ||||
| 		return; | ||||
| 	if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ | ||||
| 		return; | ||||
| 	restack(selmon); | ||||
| 	if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, | ||||
| 		None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) | ||||
| 		return; | ||||
| 	nw = MAX(c->w + dw, 1); | ||||
| 	nh = MAX(c->h + dh, 1); | ||||
| 	if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww | ||||
| 	&& c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) | ||||
| 	{ | ||||
| 		if (!c->isfloating && selmon->lt[selmon->sellt]->arrange | ||||
| 		&& (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) | ||||
| 			togglefloating(NULL); | ||||
| 	} | ||||
| 	if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) | ||||
| 		resize(c, c->x, c->y, nw, nh, 1); | ||||
| 	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); | ||||
| 	XUngrabPointer(dpy, CurrentTime); | ||||
| 	while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); | ||||
| 	if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { | ||||
| 		sendmon(c, m); | ||||
| 		selmon = m; | ||||
| 		focus(NULL); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void | ||||
| restack(Monitor *m) | ||||
| { | ||||
| @ -1493,9 +1557,80 @@ run(void) | ||||
| } | ||||
| 
 | ||||
| void | ||||
| runAutostart(void) { | ||||
| 	system("cd ~/.dwm; ./autostart_blocking.sh"); | ||||
| 	system("cd ~/.dwm; ./autostart.sh &"); | ||||
| runautostart(void) | ||||
| { | ||||
| 	char *pathpfx; | ||||
| 	char *path; | ||||
| 	char *xdgdatahome; | ||||
| 	char *home; | ||||
| 	struct stat sb; | ||||
| 
 | ||||
| 	if ((home = getenv("HOME")) == NULL) | ||||
| 		/* this is almost impossible */ | ||||
| 		return; | ||||
| 
 | ||||
| 	/* if $XDG_DATA_HOME is set and not empty, use $XDG_DATA_HOME/dwm,
 | ||||
| 	 * otherwise use ~/.local/share/dwm as autostart script directory | ||||
| 	 */ | ||||
| 	xdgdatahome = getenv("XDG_DATA_HOME"); | ||||
| 	if (xdgdatahome != NULL && *xdgdatahome != '\0') { | ||||
| 		/* space for path segments, separators and nul */ | ||||
| 		pathpfx = ecalloc(1, strlen(xdgdatahome) + strlen(dwmdir) + 2); | ||||
| 
 | ||||
| 		if (sprintf(pathpfx, "%s/%s", xdgdatahome, dwmdir) <= 0) { | ||||
| 			free(pathpfx); | ||||
| 			return; | ||||
| 		} | ||||
| 	} else { | ||||
| 		/* space for path segments, separators and nul */ | ||||
| 		pathpfx = ecalloc(1, strlen(home) + strlen(localshare) | ||||
| 		                     + strlen(dwmdir) + 3); | ||||
| 
 | ||||
| 		if (sprintf(pathpfx, "%s/%s/%s", home, localshare, dwmdir) < 0) { | ||||
| 			free(pathpfx); | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* check if the autostart script directory exists */ | ||||
| 	if (! (stat(pathpfx, &sb) == 0 && S_ISDIR(sb.st_mode))) { | ||||
| 		/* the XDG conformant path does not exist or is no directory
 | ||||
| 		 * so we try ~/.dwm instead | ||||
| 		 */ | ||||
| 		char *pathpfx_new = realloc(pathpfx, strlen(home) + strlen(dwmdir) + 3); | ||||
| 		if(pathpfx_new == NULL) { | ||||
| 			free(pathpfx); | ||||
| 			return; | ||||
| 		} | ||||
| 		pathpfx = pathpfx_new; | ||||
| 
 | ||||
| 		if (sprintf(pathpfx, "%s/.%s", home, dwmdir) <= 0) { | ||||
| 			free(pathpfx); | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* try the blocking script first */ | ||||
| 	path = ecalloc(1, strlen(pathpfx) + strlen(autostartblocksh) + 2); | ||||
| 	if (sprintf(path, "%s/%s", pathpfx, autostartblocksh) <= 0) { | ||||
| 		free(path); | ||||
| 		free(pathpfx); | ||||
| 	} | ||||
| 
 | ||||
| 	if (access(path, X_OK) == 0) | ||||
| 		system(path); | ||||
| 
 | ||||
| 	/* now the non-blocking script */ | ||||
| 	if (sprintf(path, "%s/%s", pathpfx, autostartsh) <= 0) { | ||||
| 		free(path); | ||||
| 		free(pathpfx); | ||||
| 	} | ||||
| 
 | ||||
| 	if (access(path, X_OK) == 0) | ||||
| 		system(strcat(path, " &")); | ||||
| 
 | ||||
| 	free(pathpfx); | ||||
| 	free(path); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| @ -1535,10 +1670,7 @@ sendmon(Client *c, Monitor *m) | ||||
| 	detachstack(c); | ||||
| 	c->mon = m; | ||||
| 	c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ | ||||
| 	if( attachbelow ) | ||||
| 	attachBelow(c); | ||||
| 	else | ||||
| 		attach(c); | ||||
| 	attachstack(c); | ||||
| 	focus(NULL); | ||||
| 	arrange(NULL); | ||||
| @ -1618,6 +1750,29 @@ setfullscreen(Client *c, int fullscreen) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void | ||||
| setgaps(const Arg *arg) | ||||
| { | ||||
| 	switch(arg->i) | ||||
| 	{ | ||||
| 		case GAP_TOGGLE: | ||||
| 			selmon->pertag->drawwithgaps[selmon->pertag->curtag] = !selmon->pertag->drawwithgaps[selmon->pertag->curtag]; | ||||
| 			break; | ||||
| 		case GAP_RESET: | ||||
| 			if (selmon->pertag->curtag > 0) | ||||
| 				selmon->pertag->gappx[selmon->pertag->curtag] = gappx[selmon->pertag->curtag - 1 % LENGTH(gappx)]; | ||||
| 			else | ||||
| 				selmon->pertag->gappx[0] = gappx[0]; | ||||
| 			break; | ||||
| 		default: | ||||
| 			if (selmon->pertag->gappx[selmon->pertag->curtag] + arg->i < 0) | ||||
| 				selmon->pertag->gappx[selmon->pertag->curtag] = 0; | ||||
| 			else | ||||
| 				selmon->pertag->gappx[selmon->pertag->curtag] += arg->i; | ||||
| 	} | ||||
| 	arrange(selmon); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| setlayout(const Arg *arg) | ||||
| { | ||||
| @ -1801,7 +1956,24 @@ tile(Monitor *m) | ||||
| 	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); | ||||
| 	if (n == 0) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (m->pertag->drawwithgaps[m->pertag->curtag]) { /* draw with fullgaps logic */ | ||||
| 	        if (n > m->nmaster) | ||||
| 	                mw = m->nmaster ? m->ww * m->mfact : 0; | ||||
| 	        else | ||||
| 	                mw = m->ww - m->pertag->gappx[m->pertag->curtag]; | ||||
| 	        for (i = 0, my = ty = m->pertag->gappx[m->pertag->curtag], c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) | ||||
| 	                if (i < m->nmaster) { | ||||
| 	                        h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->pertag->gappx[m->pertag->curtag]; | ||||
| 	                        resize(c, m->wx + m->pertag->gappx[m->pertag->curtag], m->wy + my, mw - (2*c->bw) - m->pertag->gappx[m->pertag->curtag], h - (2*c->bw), 0); | ||||
| 	                        if (my + HEIGHT(c) + m->pertag->gappx[m->pertag->curtag] < m->wh) | ||||
| 	                                my += HEIGHT(c) + m->pertag->gappx[m->pertag->curtag]; | ||||
| 	                } else { | ||||
| 	                        h = (m->wh - ty) / (n - i) - m->pertag->gappx[m->pertag->curtag]; | ||||
| 	                        resize(c, m->wx + mw + m->pertag->gappx[m->pertag->curtag], m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->pertag->gappx[m->pertag->curtag], h - (2*c->bw), 0); | ||||
| 	                        if (ty + HEIGHT(c) + m->pertag->gappx[m->pertag->curtag] < m->wh) | ||||
| 	                                ty += HEIGHT(c) + m->pertag->gappx[m->pertag->curtag]; | ||||
| 	                } | ||||
| 	} else { /* draw with singularborders logic */ | ||||
| 	        if (n > m->nmaster) | ||||
| 	                mw = m->nmaster ? m->ww * m->mfact : 0; | ||||
| 	        else | ||||
| @ -1809,14 +1981,16 @@ tile(Monitor *m) | ||||
| 	        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); | ||||
| 	                        if (n == 1) | ||||
| 	                                resize(c, m->wx - c->bw, m->wy, m->ww, m->wh, False); | ||||
| 	                        else | ||||
| 	                                resize(c, m->wx - c->bw, m->wy + my, mw - c->bw, h - c->bw, False); | ||||
| 	                        my += HEIGHT(c) - c->bw; | ||||
| 	                } 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); | ||||
| 	                        resize(c, m->wx + mw - c->bw, m->wy + ty, m->ww - mw, h - c->bw, False); | ||||
| 	                        ty += HEIGHT(c) - c->bw; | ||||
| 	                } | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -2047,10 +2221,8 @@ updategeom(void) | ||||
| 					m->clients = c->next; | ||||
| 					detachstack(c); | ||||
| 					c->mon = mons; | ||||
| 					if( attachbelow ) | ||||
| 						attachBelow(c); | ||||
| 					else | ||||
| 					attach(c); | ||||
| 					attachBelow(c); | ||||
| 					attachstack(c); | ||||
| 				} | ||||
| 				if (m == selmon) | ||||
| @ -2162,11 +2334,9 @@ updatewindowtype(Client *c) | ||||
| 
 | ||||
| 	if (state == netatom[NetWMFullscreen]) | ||||
| 		setfullscreen(c, 1); | ||||
| 	if (wtype == netatom[NetWMWindowTypeDialog]) { | ||||
| 		c->iscentered = 1; | ||||
| 	if (wtype == netatom[NetWMWindowTypeDialog]) | ||||
| 		c->isfloating = 1; | ||||
| } | ||||
| } | ||||
| 
 | ||||
| void | ||||
| updatewmhints(Client *c) | ||||
| @ -2360,7 +2530,7 @@ main(int argc, char *argv[]) | ||||
| 		die("pledge"); | ||||
| #endif /* __OpenBSD__ */ | ||||
| 	scan(); | ||||
| 	runAutostart(); | ||||
| 	runautostart(); | ||||
| 	run(); | ||||
| 	cleanup(); | ||||
| 	XCloseDisplay(dpy); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user