Compare commits
2 Commits
patch-anyb
...
patch-auto
Author | SHA1 | Date | |
---|---|---|---|
7b100d9bf0 | |||
60674bdb3f |
@ -5,10 +5,6 @@ static const unsigned int borderpx = 1; /* border pixel of 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 */
|
||||||
static const int usealtbar = 1; /* 1 means use non-dwm status bar */
|
|
||||||
static const char *altbarclass = "Polybar"; /* Alternate bar class name */
|
|
||||||
static const char *alttrayname = "tray"; /* Polybar tray instance name */
|
|
||||||
static const char *altbarcmd = "$HOME/bar.sh"; /* Alternate bar launch command */
|
|
||||||
static const char *fonts[] = { "monospace:size=10" };
|
static const char *fonts[] = { "monospace:size=10" };
|
||||||
static const char dmenufont[] = "monospace:size=10";
|
static const char dmenufont[] = "monospace:size=10";
|
||||||
static const char col_gray1[] = "#222222";
|
static const char col_gray1[] = "#222222";
|
||||||
|
@ -1,445 +0,0 @@
|
|||||||
From 9b5719969ce85c3ecc0238d49c0255c5c2cc79f0 Mon Sep 17 00:00:00 2001
|
|
||||||
From: mihirlad55 <mihirlad55@gmail.com>
|
|
||||||
Date: Mon, 10 Aug 2020 01:39:28 +0000
|
|
||||||
Subject: [PATCH] Add support for managing external status bars
|
|
||||||
|
|
||||||
This patch allows dwm to manage other status bars such as
|
|
||||||
polybar/lemonbar without them needing to set override-redirect. For
|
|
||||||
all intents and purposes, DWM treats this bar as if it were its own
|
|
||||||
and as a result helps the status bar and DWM live in harmony.
|
|
||||||
|
|
||||||
This has a few advantages
|
|
||||||
* The bar does not block fullscreen windows
|
|
||||||
* DWM makes room for the status bar, so windows do not overlap the bar
|
|
||||||
* The bar can be hidden/killed and DWM will not keep an unsightly gap
|
|
||||||
where the bar was
|
|
||||||
* DWM receives EnterNotify events when your cursor enters the bar
|
|
||||||
|
|
||||||
To use another status bar, set usealtbar to 1 in your config.h and set
|
|
||||||
altbarclass to the class name (can be found using xprop) to the class
|
|
||||||
name of your status bar. Also make sure that if your status bar will
|
|
||||||
be displayed on top, topbar is set to 1 in your config, and if it will
|
|
||||||
be displayed on bottom, topbar is set to 0. This patch does not
|
|
||||||
support bars that are not docked at the top or at the bottom of your
|
|
||||||
monitor.
|
|
||||||
|
|
||||||
This verison of the patch fixes handling of polybar's tray.
|
|
||||||
|
|
||||||
The patch is developed at https://github.com/mihirlad55/dwm-anybar
|
|
||||||
---
|
|
||||||
config.def.h | 4 ++
|
|
||||||
dwm.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++----
|
|
||||||
2 files changed, 181 insertions(+), 15 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 1c0b587..f45211b 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -5,6 +5,10 @@ static const unsigned int borderpx = 1; /* border pixel of windows */
|
|
||||||
static const unsigned int snap = 32; /* snap pixel */
|
|
||||||
static const int showbar = 1; /* 0 means no bar */
|
|
||||||
static const int topbar = 1; /* 0 means bottom bar */
|
|
||||||
+static const int usealtbar = 1; /* 1 means use non-dwm status bar */
|
|
||||||
+static const char *altbarclass = "Polybar"; /* Alternate bar class name */
|
|
||||||
+static const char *alttrayname = "tray"; /* Polybar tray instance name */
|
|
||||||
+static const char *altbarcmd = "$HOME/bar.sh"; /* Alternate bar launch command */
|
|
||||||
static const char *fonts[] = { "monospace:size=10" };
|
|
||||||
static const char dmenufont[] = "monospace:size=10";
|
|
||||||
static const char col_gray1[] = "#222222";
|
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index 9fd0286..c1d8ce0 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -47,8 +47,8 @@
|
|
||||||
/* macros */
|
|
||||||
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
|
|
||||||
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
|
|
||||||
-#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
|
|
||||||
- * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
|
|
||||||
+#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->mx+(m)->mw) - MAX((x),(m)->mx)) \
|
|
||||||
+ * MAX(0, MIN((y)+(h),(m)->my+(m)->mh) - MAX((y),(m)->my)))
|
|
||||||
#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
|
|
||||||
#define LENGTH(X) (sizeof X / sizeof X[0])
|
|
||||||
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
|
|
||||||
@@ -116,7 +116,8 @@ struct Monitor {
|
|
||||||
float mfact;
|
|
||||||
int nmaster;
|
|
||||||
int num;
|
|
||||||
- int by; /* bar geometry */
|
|
||||||
+ int by, bh; /* bar geometry */
|
|
||||||
+ int tx, tw; /* bar tray geometry */
|
|
||||||
int mx, my, mw, mh; /* screen size */
|
|
||||||
int wx, wy, ww, wh; /* window area */
|
|
||||||
unsigned int seltags;
|
|
||||||
@@ -129,6 +130,7 @@ struct Monitor {
|
|
||||||
Client *stack;
|
|
||||||
Monitor *next;
|
|
||||||
Window barwin;
|
|
||||||
+ Window traywin;
|
|
||||||
const Layout *lt[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -179,6 +181,8 @@ static void incnmaster(const Arg *arg);
|
|
||||||
static void keypress(XEvent *e);
|
|
||||||
static void killclient(const Arg *arg);
|
|
||||||
static void manage(Window w, XWindowAttributes *wa);
|
|
||||||
+static void managealtbar(Window win, XWindowAttributes *wa);
|
|
||||||
+static void managetray(Window win, XWindowAttributes *wa);
|
|
||||||
static void mappingnotify(XEvent *e);
|
|
||||||
static void maprequest(XEvent *e);
|
|
||||||
static void monocle(Monitor *m);
|
|
||||||
@@ -195,6 +199,7 @@ static void resizemouse(const Arg *arg);
|
|
||||||
static void restack(Monitor *m);
|
|
||||||
static void run(void);
|
|
||||||
static void scan(void);
|
|
||||||
+static void scantray(void);
|
|
||||||
static int sendevent(Client *c, Atom proto);
|
|
||||||
static void sendmon(Client *c, Monitor *m);
|
|
||||||
static void setclientstate(Client *c, long state);
|
|
||||||
@@ -207,6 +212,7 @@ static void seturgent(Client *c, int urg);
|
|
||||||
static void showhide(Client *c);
|
|
||||||
static void sigchld(int unused);
|
|
||||||
static void spawn(const Arg *arg);
|
|
||||||
+static void spawnbar();
|
|
||||||
static void tag(const Arg *arg);
|
|
||||||
static void tagmon(const Arg *arg);
|
|
||||||
static void tile(Monitor *);
|
|
||||||
@@ -216,6 +222,8 @@ static void toggletag(const Arg *arg);
|
|
||||||
static void toggleview(const Arg *arg);
|
|
||||||
static void unfocus(Client *c, int setfocus);
|
|
||||||
static void unmanage(Client *c, int destroyed);
|
|
||||||
+static void unmanagealtbar(Window w);
|
|
||||||
+static void unmanagetray(Window w);
|
|
||||||
static void unmapnotify(XEvent *e);
|
|
||||||
static void updatebarpos(Monitor *m);
|
|
||||||
static void updatebars(void);
|
|
||||||
@@ -230,6 +238,7 @@ static void updatewmhints(Client *c);
|
|
||||||
static void view(const Arg *arg);
|
|
||||||
static Client *wintoclient(Window w);
|
|
||||||
static Monitor *wintomon(Window w);
|
|
||||||
+static int wmclasscontains(Window win, const char *class, const char *name);
|
|
||||||
static int xerror(Display *dpy, XErrorEvent *ee);
|
|
||||||
static int xerrordummy(Display *dpy, XErrorEvent *ee);
|
|
||||||
static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
|
||||||
@@ -505,8 +514,10 @@ cleanupmon(Monitor *mon)
|
|
||||||
for (m = mons; m && m->next != mon; m = m->next);
|
|
||||||
m->next = mon->next;
|
|
||||||
}
|
|
||||||
- XUnmapWindow(dpy, mon->barwin);
|
|
||||||
- XDestroyWindow(dpy, mon->barwin);
|
|
||||||
+ if (!usealtbar) {
|
|
||||||
+ XUnmapWindow(dpy, mon->barwin);
|
|
||||||
+ XDestroyWindow(dpy, mon->barwin);
|
|
||||||
+ }
|
|
||||||
free(mon);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -568,7 +579,7 @@ configurenotify(XEvent *e)
|
|
||||||
for (c = m->clients; c; c = c->next)
|
|
||||||
if (c->isfullscreen)
|
|
||||||
resizeclient(c, m->mx, m->my, m->mw, m->mh);
|
|
||||||
- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
|
|
||||||
+ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, m->bh);
|
|
||||||
}
|
|
||||||
focus(NULL);
|
|
||||||
arrange(NULL);
|
|
||||||
@@ -639,6 +650,7 @@ createmon(void)
|
|
||||||
m->nmaster = nmaster;
|
|
||||||
m->showbar = showbar;
|
|
||||||
m->topbar = topbar;
|
|
||||||
+ m->bh = bh;
|
|
||||||
m->lt[0] = &layouts[0];
|
|
||||||
m->lt[1] = &layouts[1 % LENGTH(layouts)];
|
|
||||||
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
|
|
||||||
@@ -649,10 +661,15 @@ void
|
|
||||||
destroynotify(XEvent *e)
|
|
||||||
{
|
|
||||||
Client *c;
|
|
||||||
+ Monitor *m;
|
|
||||||
XDestroyWindowEvent *ev = &e->xdestroywindow;
|
|
||||||
|
|
||||||
if ((c = wintoclient(ev->window)))
|
|
||||||
unmanage(c, 1);
|
|
||||||
+ else if ((m = wintomon(ev->window)) && m->barwin == ev->window)
|
|
||||||
+ unmanagealtbar(ev->window);
|
|
||||||
+ else if (m->traywin == ev->window)
|
|
||||||
+ unmanagetray(ev->window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
@@ -696,6 +713,9 @@ dirtomon(int dir)
|
|
||||||
void
|
|
||||||
drawbar(Monitor *m)
|
|
||||||
{
|
|
||||||
+ if (usealtbar)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
int x, w, tw = 0;
|
|
||||||
int boxs = drw->fonts->h / 9;
|
|
||||||
int boxw = drw->fonts->h / 6 + 2;
|
|
||||||
@@ -1077,6 +1097,45 @@ manage(Window w, XWindowAttributes *wa)
|
|
||||||
focus(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+managealtbar(Window win, XWindowAttributes *wa)
|
|
||||||
+{
|
|
||||||
+ Monitor *m;
|
|
||||||
+ if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height)))
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ m->barwin = win;
|
|
||||||
+ m->by = wa->y;
|
|
||||||
+ bh = m->bh = wa->height;
|
|
||||||
+ updatebarpos(m);
|
|
||||||
+ arrange(m);
|
|
||||||
+ XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
|
|
||||||
+ XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height);
|
|
||||||
+ XMapWindow(dpy, win);
|
|
||||||
+ XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
|
|
||||||
+ (unsigned char *) &win, 1);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+managetray(Window win, XWindowAttributes *wa)
|
|
||||||
+{
|
|
||||||
+ Monitor *m;
|
|
||||||
+ if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height)))
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ m->traywin = win;
|
|
||||||
+ m->tx = wa->x;
|
|
||||||
+ m->tw = wa->width;
|
|
||||||
+ updatebarpos(m);
|
|
||||||
+ arrange(m);
|
|
||||||
+ XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
|
|
||||||
+ XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height);
|
|
||||||
+ XMapWindow(dpy, win);
|
|
||||||
+ XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
|
|
||||||
+ (unsigned char *) &win, 1);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
void
|
|
||||||
mappingnotify(XEvent *e)
|
|
||||||
{
|
|
||||||
@@ -1097,7 +1156,9 @@ maprequest(XEvent *e)
|
|
||||||
return;
|
|
||||||
if (wa.override_redirect)
|
|
||||||
return;
|
|
||||||
- if (!wintoclient(ev->window))
|
|
||||||
+ if (wmclasscontains(ev->window, altbarclass, ""))
|
|
||||||
+ managealtbar(ev->window, &wa);
|
|
||||||
+ else if (!wintoclient(ev->window))
|
|
||||||
manage(ev->window, &wa);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1393,7 +1454,9 @@ scan(void)
|
|
||||||
if (!XGetWindowAttributes(dpy, wins[i], &wa)
|
|
||||||
|| wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
|
|
||||||
continue;
|
|
||||||
- if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
|
|
||||||
+ if (wmclasscontains(wins[i], altbarclass, ""))
|
|
||||||
+ managealtbar(wins[i], &wa);
|
|
||||||
+ else if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
|
|
||||||
manage(wins[i], &wa);
|
|
||||||
}
|
|
||||||
for (i = 0; i < num; i++) { /* now the transients */
|
|
||||||
@@ -1408,6 +1471,29 @@ scan(void)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+scantray(void)
|
|
||||||
+{
|
|
||||||
+ unsigned int num;
|
|
||||||
+ Window d1, d2, *wins = NULL;
|
|
||||||
+ XWindowAttributes wa;
|
|
||||||
+
|
|
||||||
+ if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
|
|
||||||
+ for (unsigned int i = 0; i < num; i++) {
|
|
||||||
+ if (wmclasscontains(wins[i], altbarclass, alttrayname)) {
|
|
||||||
+ if (!XGetWindowAttributes(dpy, wins[i], &wa))
|
|
||||||
+ break;
|
|
||||||
+ managetray(wins[i], &wa);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (wins)
|
|
||||||
+ XFree(wins);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
void
|
|
||||||
sendmon(Client *c, Monitor *m)
|
|
||||||
{
|
|
||||||
@@ -1546,7 +1632,7 @@ setup(void)
|
|
||||||
if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
|
|
||||||
die("no fonts could be loaded.");
|
|
||||||
lrpad = drw->fonts->h;
|
|
||||||
- bh = drw->fonts->h + 2;
|
|
||||||
+ bh = usealtbar ? 0 : drw->fonts->h + 2;
|
|
||||||
updategeom();
|
|
||||||
/* init atoms */
|
|
||||||
utf8string = XInternAtom(dpy, "UTF8_STRING", False);
|
|
||||||
@@ -1595,6 +1681,7 @@ setup(void)
|
|
||||||
XSelectInput(dpy, root, wa.event_mask);
|
|
||||||
grabkeys();
|
|
||||||
focus(NULL);
|
|
||||||
+ spawnbar();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1653,6 +1740,13 @@ spawn(const Arg *arg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+spawnbar()
|
|
||||||
+{
|
|
||||||
+ if (*altbarcmd)
|
|
||||||
+ system(altbarcmd);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
tag(const Arg *arg)
|
|
||||||
{
|
|
||||||
@@ -1702,9 +1796,18 @@ tile(Monitor *m)
|
|
||||||
void
|
|
||||||
togglebar(const Arg *arg)
|
|
||||||
{
|
|
||||||
+ /**
|
|
||||||
+ * Polybar tray does not raise maprequest event. It must be manually scanned
|
|
||||||
+ * for. Scanning it too early while the tray is being populated would give
|
|
||||||
+ * wrong dimensions.
|
|
||||||
+ */
|
|
||||||
+ if (!selmon->traywin)
|
|
||||||
+ scantray();
|
|
||||||
+
|
|
||||||
selmon->showbar = !selmon->showbar;
|
|
||||||
updatebarpos(selmon);
|
|
||||||
- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
|
|
||||||
+ XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, selmon->bh);
|
|
||||||
+ XMoveResizeWindow(dpy, selmon->traywin, selmon->tx, selmon->by, selmon->tw, selmon->bh);
|
|
||||||
arrange(selmon);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1787,10 +1890,41 @@ unmanage(Client *c, int destroyed)
|
|
||||||
arrange(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+unmanagealtbar(Window w)
|
|
||||||
+{
|
|
||||||
+ Monitor *m = wintomon(w);
|
|
||||||
+
|
|
||||||
+ if (!m)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ m->barwin = 0;
|
|
||||||
+ m->by = 0;
|
|
||||||
+ m->bh = 0;
|
|
||||||
+ updatebarpos(m);
|
|
||||||
+ arrange(m);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+unmanagetray(Window w)
|
|
||||||
+{
|
|
||||||
+ Monitor *m = wintomon(w);
|
|
||||||
+
|
|
||||||
+ if (!m)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ m->traywin = 0;
|
|
||||||
+ m->tx = 0;
|
|
||||||
+ m->tw = 0;
|
|
||||||
+ updatebarpos(m);
|
|
||||||
+ arrange(m);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
unmapnotify(XEvent *e)
|
|
||||||
{
|
|
||||||
Client *c;
|
|
||||||
+ Monitor *m;
|
|
||||||
XUnmapEvent *ev = &e->xunmap;
|
|
||||||
|
|
||||||
if ((c = wintoclient(ev->window))) {
|
|
||||||
@@ -1798,12 +1932,18 @@ unmapnotify(XEvent *e)
|
|
||||||
setclientstate(c, WithdrawnState);
|
|
||||||
else
|
|
||||||
unmanage(c, 0);
|
|
||||||
- }
|
|
||||||
+ } else if ((m = wintomon(ev->window)) && m->barwin == ev->window)
|
|
||||||
+ unmanagealtbar(ev->window);
|
|
||||||
+ else if (m->traywin == ev->window)
|
|
||||||
+ unmanagetray(ev->window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
updatebars(void)
|
|
||||||
{
|
|
||||||
+ if (usealtbar)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
Monitor *m;
|
|
||||||
XSetWindowAttributes wa = {
|
|
||||||
.override_redirect = True,
|
|
||||||
@@ -1829,11 +1969,11 @@ updatebarpos(Monitor *m)
|
|
||||||
m->wy = m->my;
|
|
||||||
m->wh = m->mh;
|
|
||||||
if (m->showbar) {
|
|
||||||
- m->wh -= bh;
|
|
||||||
+ m->wh -= m->bh;
|
|
||||||
m->by = m->topbar ? m->wy : m->wy + m->wh;
|
|
||||||
- m->wy = m->topbar ? m->wy + bh : m->wy;
|
|
||||||
+ m->wy = m->topbar ? m->wy + m->bh : m->wy;
|
|
||||||
} else
|
|
||||||
- m->by = -bh;
|
|
||||||
+ m->by = -m->bh;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
@@ -2070,13 +2210,35 @@ wintomon(Window w)
|
|
||||||
if (w == root && getrootptr(&x, &y))
|
|
||||||
return recttomon(x, y, 1, 1);
|
|
||||||
for (m = mons; m; m = m->next)
|
|
||||||
- if (w == m->barwin)
|
|
||||||
+ if (w == m->barwin || w == m->traywin)
|
|
||||||
return m;
|
|
||||||
if ((c = wintoclient(w)))
|
|
||||||
return c->mon;
|
|
||||||
return selmon;
|
|
||||||
}
|
|
||||||
|
|
||||||
+int
|
|
||||||
+wmclasscontains(Window win, const char *class, const char *name)
|
|
||||||
+{
|
|
||||||
+ XClassHint ch = { NULL, NULL };
|
|
||||||
+ int res = 1;
|
|
||||||
+
|
|
||||||
+ if (XGetClassHint(dpy, win, &ch)) {
|
|
||||||
+ if (ch.res_name && strstr(ch.res_name, name) == NULL)
|
|
||||||
+ res = 0;
|
|
||||||
+ if (ch.res_class && strstr(ch.res_class, class) == NULL)
|
|
||||||
+ res = 0;
|
|
||||||
+ } else
|
|
||||||
+ res = 0;
|
|
||||||
+
|
|
||||||
+ if (ch.res_class)
|
|
||||||
+ XFree(ch.res_class);
|
|
||||||
+ if (ch.res_name)
|
|
||||||
+ XFree(ch.res_name);
|
|
||||||
+
|
|
||||||
+ return res;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/* There's no way to check accesses to destroyed windows, thus those cases are
|
|
||||||
* ignored (especially on UnmapNotify's). Other types of errors call Xlibs
|
|
||||||
* default error handler, which may call exit. */
|
|
||||||
--
|
|
||||||
2.28.0
|
|
||||||
|
|
179
dwm-autostart-20210120-cb3f58a.diff
Normal file
179
dwm-autostart-20210120-cb3f58a.diff
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
From 37e970479dc5d40e57fc0cbfeaa5e39941483237 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Gan Ainm <gan.ainm.riomhphost@gmail.com>
|
||||||
|
Date: Wed, 10 Jun 2020 10:59:02 +0000
|
||||||
|
Subject: [PATCH] dwm-xdgautostart-6.2.diff
|
||||||
|
|
||||||
|
===================================================================
|
||||||
|
---
|
||||||
|
dwm.1 | 23 +++++++++++++++++
|
||||||
|
dwm.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 105 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/dwm.1 b/dwm.1
|
||||||
|
index 13b3729..9533aa6 100644
|
||||||
|
--- a/dwm.1
|
||||||
|
+++ b/dwm.1
|
||||||
|
@@ -30,6 +30,14 @@ top left corner. The tags which are applied to one or more windows are
|
||||||
|
indicated with an empty square in the top left corner.
|
||||||
|
.P
|
||||||
|
dwm draws a small border around windows to indicate the focus state.
|
||||||
|
+.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
|
||||||
|
@@ -152,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.
|
||||||
|
diff --git a/dwm.c b/dwm.c
|
||||||
|
index 4465af1..2156b49 100644
|
||||||
|
--- a/dwm.c
|
||||||
|
+++ b/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>
|
||||||
|
@@ -193,6 +194,7 @@ static void resizeclient(Client *c, int x, int y, int w, int h);
|
||||||
|
static void resizemouse(const Arg *arg);
|
||||||
|
static void restack(Monitor *m);
|
||||||
|
static void run(void);
|
||||||
|
+static void runautostart(void);
|
||||||
|
static void scan(void);
|
||||||
|
static int sendevent(Client *c, Atom proto);
|
||||||
|
static void sendmon(Client *c, Monitor *m);
|
||||||
|
@@ -235,7 +237,11 @@ static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
||||||
|
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 */
|
||||||
|
@@ -1380,6 +1386,83 @@ run(void)
|
||||||
|
handler[ev.type](&ev); /* call handler */
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+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
|
||||||
|
scan(void)
|
||||||
|
{
|
||||||
|
@@ -2142,6 +2223,7 @@ main(int argc, char *argv[])
|
||||||
|
die("pledge");
|
||||||
|
#endif /* __OpenBSD__ */
|
||||||
|
scan();
|
||||||
|
+ runautostart();
|
||||||
|
run();
|
||||||
|
cleanup();
|
||||||
|
XCloseDisplay(dpy);
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
23
dwm.1
23
dwm.1
@ -30,6 +30,14 @@ 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
|
||||||
@ -152,6 +160,21 @@ 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.
|
||||||
|
276
dwm.c
276
dwm.c
@ -29,6 +29,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <X11/cursorfont.h>
|
#include <X11/cursorfont.h>
|
||||||
#include <X11/keysym.h>
|
#include <X11/keysym.h>
|
||||||
@ -47,8 +48,8 @@
|
|||||||
/* macros */
|
/* macros */
|
||||||
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
|
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
|
||||||
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
|
#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)->mx+(m)->mw) - MAX((x),(m)->mx)) \
|
#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)->my+(m)->mh) - MAX((y),(m)->my)))
|
* 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 ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
|
||||||
#define LENGTH(X) (sizeof X / sizeof X[0])
|
#define LENGTH(X) (sizeof X / sizeof X[0])
|
||||||
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
|
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
|
||||||
@ -116,8 +117,7 @@ struct Monitor {
|
|||||||
float mfact;
|
float mfact;
|
||||||
int nmaster;
|
int nmaster;
|
||||||
int num;
|
int num;
|
||||||
int by, bh; /* bar geometry */
|
int by; /* bar geometry */
|
||||||
int tx, tw; /* bar tray 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 */
|
||||||
unsigned int seltags;
|
unsigned int seltags;
|
||||||
@ -130,7 +130,6 @@ struct Monitor {
|
|||||||
Client *stack;
|
Client *stack;
|
||||||
Monitor *next;
|
Monitor *next;
|
||||||
Window barwin;
|
Window barwin;
|
||||||
Window traywin;
|
|
||||||
const Layout *lt[2];
|
const Layout *lt[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -181,8 +180,6 @@ static void incnmaster(const Arg *arg);
|
|||||||
static void keypress(XEvent *e);
|
static void keypress(XEvent *e);
|
||||||
static void killclient(const Arg *arg);
|
static void killclient(const Arg *arg);
|
||||||
static void manage(Window w, XWindowAttributes *wa);
|
static void manage(Window w, XWindowAttributes *wa);
|
||||||
static void managealtbar(Window win, XWindowAttributes *wa);
|
|
||||||
static void managetray(Window win, XWindowAttributes *wa);
|
|
||||||
static void mappingnotify(XEvent *e);
|
static void mappingnotify(XEvent *e);
|
||||||
static void maprequest(XEvent *e);
|
static void maprequest(XEvent *e);
|
||||||
static void monocle(Monitor *m);
|
static void monocle(Monitor *m);
|
||||||
@ -198,8 +195,8 @@ 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);
|
||||||
static void restack(Monitor *m);
|
static void restack(Monitor *m);
|
||||||
static void run(void);
|
static void run(void);
|
||||||
|
static void runautostart(void);
|
||||||
static void scan(void);
|
static void scan(void);
|
||||||
static void scantray(void);
|
|
||||||
static int sendevent(Client *c, Atom proto);
|
static int sendevent(Client *c, Atom proto);
|
||||||
static void sendmon(Client *c, Monitor *m);
|
static void sendmon(Client *c, Monitor *m);
|
||||||
static void setclientstate(Client *c, long state);
|
static void setclientstate(Client *c, long state);
|
||||||
@ -212,7 +209,6 @@ static void seturgent(Client *c, int urg);
|
|||||||
static void showhide(Client *c);
|
static void showhide(Client *c);
|
||||||
static void sigchld(int unused);
|
static void sigchld(int unused);
|
||||||
static void spawn(const Arg *arg);
|
static void spawn(const Arg *arg);
|
||||||
static void spawnbar();
|
|
||||||
static void tag(const Arg *arg);
|
static void tag(const Arg *arg);
|
||||||
static void tagmon(const Arg *arg);
|
static void tagmon(const Arg *arg);
|
||||||
static void tile(Monitor *);
|
static void tile(Monitor *);
|
||||||
@ -222,8 +218,6 @@ static void toggletag(const Arg *arg);
|
|||||||
static void toggleview(const Arg *arg);
|
static void toggleview(const Arg *arg);
|
||||||
static void unfocus(Client *c, int setfocus);
|
static void unfocus(Client *c, int setfocus);
|
||||||
static void unmanage(Client *c, int destroyed);
|
static void unmanage(Client *c, int destroyed);
|
||||||
static void unmanagealtbar(Window w);
|
|
||||||
static void unmanagetray(Window w);
|
|
||||||
static void unmapnotify(XEvent *e);
|
static void unmapnotify(XEvent *e);
|
||||||
static void updatebarpos(Monitor *m);
|
static void updatebarpos(Monitor *m);
|
||||||
static void updatebars(void);
|
static void updatebars(void);
|
||||||
@ -238,14 +232,17 @@ static void updatewmhints(Client *c);
|
|||||||
static void view(const Arg *arg);
|
static void view(const Arg *arg);
|
||||||
static Client *wintoclient(Window w);
|
static Client *wintoclient(Window w);
|
||||||
static Monitor *wintomon(Window w);
|
static Monitor *wintomon(Window w);
|
||||||
static int wmclasscontains(Window win, const char *class, const char *name);
|
|
||||||
static int xerror(Display *dpy, XErrorEvent *ee);
|
static int xerror(Display *dpy, XErrorEvent *ee);
|
||||||
static int xerrordummy(Display *dpy, XErrorEvent *ee);
|
static int xerrordummy(Display *dpy, XErrorEvent *ee);
|
||||||
static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
||||||
static void zoom(const Arg *arg);
|
static void zoom(const Arg *arg);
|
||||||
|
|
||||||
/* variables */
|
/* variables */
|
||||||
|
static const char autostartblocksh[] = "autostart_blocking.sh";
|
||||||
|
static const char autostartsh[] = "autostart.sh";
|
||||||
static const char broken[] = "broken";
|
static const char broken[] = "broken";
|
||||||
|
static const char dwmdir[] = "dwm";
|
||||||
|
static const char localshare[] = ".local/share";
|
||||||
static char stext[256];
|
static char stext[256];
|
||||||
static int screen;
|
static int screen;
|
||||||
static int sw, sh; /* X display screen geometry width, height */
|
static int sw, sh; /* X display screen geometry width, height */
|
||||||
@ -514,10 +511,8 @@ cleanupmon(Monitor *mon)
|
|||||||
for (m = mons; m && m->next != mon; m = m->next);
|
for (m = mons; m && m->next != mon; m = m->next);
|
||||||
m->next = mon->next;
|
m->next = mon->next;
|
||||||
}
|
}
|
||||||
if (!usealtbar) {
|
XUnmapWindow(dpy, mon->barwin);
|
||||||
XUnmapWindow(dpy, mon->barwin);
|
XDestroyWindow(dpy, mon->barwin);
|
||||||
XDestroyWindow(dpy, mon->barwin);
|
|
||||||
}
|
|
||||||
free(mon);
|
free(mon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -579,7 +574,7 @@ configurenotify(XEvent *e)
|
|||||||
for (c = m->clients; c; c = c->next)
|
for (c = m->clients; c; c = c->next)
|
||||||
if (c->isfullscreen)
|
if (c->isfullscreen)
|
||||||
resizeclient(c, m->mx, m->my, m->mw, m->mh);
|
resizeclient(c, m->mx, m->my, m->mw, m->mh);
|
||||||
XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, m->bh);
|
XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
|
||||||
}
|
}
|
||||||
focus(NULL);
|
focus(NULL);
|
||||||
arrange(NULL);
|
arrange(NULL);
|
||||||
@ -650,7 +645,6 @@ createmon(void)
|
|||||||
m->nmaster = nmaster;
|
m->nmaster = nmaster;
|
||||||
m->showbar = showbar;
|
m->showbar = showbar;
|
||||||
m->topbar = topbar;
|
m->topbar = topbar;
|
||||||
m->bh = bh;
|
|
||||||
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);
|
||||||
@ -661,15 +655,10 @@ void
|
|||||||
destroynotify(XEvent *e)
|
destroynotify(XEvent *e)
|
||||||
{
|
{
|
||||||
Client *c;
|
Client *c;
|
||||||
Monitor *m;
|
|
||||||
XDestroyWindowEvent *ev = &e->xdestroywindow;
|
XDestroyWindowEvent *ev = &e->xdestroywindow;
|
||||||
|
|
||||||
if ((c = wintoclient(ev->window)))
|
if ((c = wintoclient(ev->window)))
|
||||||
unmanage(c, 1);
|
unmanage(c, 1);
|
||||||
else if ((m = wintomon(ev->window)) && m->barwin == ev->window)
|
|
||||||
unmanagealtbar(ev->window);
|
|
||||||
else if (m->traywin == ev->window)
|
|
||||||
unmanagetray(ev->window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -713,9 +702,6 @@ dirtomon(int dir)
|
|||||||
void
|
void
|
||||||
drawbar(Monitor *m)
|
drawbar(Monitor *m)
|
||||||
{
|
{
|
||||||
if (usealtbar)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int x, w, tw = 0;
|
int x, w, tw = 0;
|
||||||
int boxs = drw->fonts->h / 9;
|
int boxs = drw->fonts->h / 9;
|
||||||
int boxw = drw->fonts->h / 6 + 2;
|
int boxw = drw->fonts->h / 6 + 2;
|
||||||
@ -1100,45 +1086,6 @@ manage(Window w, XWindowAttributes *wa)
|
|||||||
focus(NULL);
|
focus(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
managealtbar(Window win, XWindowAttributes *wa)
|
|
||||||
{
|
|
||||||
Monitor *m;
|
|
||||||
if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
m->barwin = win;
|
|
||||||
m->by = wa->y;
|
|
||||||
bh = m->bh = wa->height;
|
|
||||||
updatebarpos(m);
|
|
||||||
arrange(m);
|
|
||||||
XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
|
|
||||||
XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height);
|
|
||||||
XMapWindow(dpy, win);
|
|
||||||
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
|
|
||||||
(unsigned char *) &win, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
managetray(Window win, XWindowAttributes *wa)
|
|
||||||
{
|
|
||||||
Monitor *m;
|
|
||||||
if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
m->traywin = win;
|
|
||||||
m->tx = wa->x;
|
|
||||||
m->tw = wa->width;
|
|
||||||
updatebarpos(m);
|
|
||||||
arrange(m);
|
|
||||||
XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
|
|
||||||
XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height);
|
|
||||||
XMapWindow(dpy, win);
|
|
||||||
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
|
|
||||||
(unsigned char *) &win, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
mappingnotify(XEvent *e)
|
mappingnotify(XEvent *e)
|
||||||
{
|
{
|
||||||
@ -1159,9 +1106,7 @@ maprequest(XEvent *e)
|
|||||||
return;
|
return;
|
||||||
if (wa.override_redirect)
|
if (wa.override_redirect)
|
||||||
return;
|
return;
|
||||||
if (wmclasscontains(ev->window, altbarclass, ""))
|
if (!wintoclient(ev->window))
|
||||||
managealtbar(ev->window, &wa);
|
|
||||||
else if (!wintoclient(ev->window))
|
|
||||||
manage(ev->window, &wa);
|
manage(ev->window, &wa);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1445,6 +1390,83 @@ run(void)
|
|||||||
handler[ev.type](&ev); /* call handler */
|
handler[ev.type](&ev); /* call handler */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
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
|
void
|
||||||
scan(void)
|
scan(void)
|
||||||
{
|
{
|
||||||
@ -1457,9 +1479,7 @@ scan(void)
|
|||||||
if (!XGetWindowAttributes(dpy, wins[i], &wa)
|
if (!XGetWindowAttributes(dpy, wins[i], &wa)
|
||||||
|| wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
|
|| wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
|
||||||
continue;
|
continue;
|
||||||
if (wmclasscontains(wins[i], altbarclass, ""))
|
if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
|
||||||
managealtbar(wins[i], &wa);
|
|
||||||
else if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
|
|
||||||
manage(wins[i], &wa);
|
manage(wins[i], &wa);
|
||||||
}
|
}
|
||||||
for (i = 0; i < num; i++) { /* now the transients */
|
for (i = 0; i < num; i++) { /* now the transients */
|
||||||
@ -1474,29 +1494,6 @@ scan(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
scantray(void)
|
|
||||||
{
|
|
||||||
unsigned int num;
|
|
||||||
Window d1, d2, *wins = NULL;
|
|
||||||
XWindowAttributes wa;
|
|
||||||
|
|
||||||
if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
|
|
||||||
for (unsigned int i = 0; i < num; i++) {
|
|
||||||
if (wmclasscontains(wins[i], altbarclass, alttrayname)) {
|
|
||||||
if (!XGetWindowAttributes(dpy, wins[i], &wa))
|
|
||||||
break;
|
|
||||||
managetray(wins[i], &wa);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wins)
|
|
||||||
XFree(wins);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
sendmon(Client *c, Monitor *m)
|
sendmon(Client *c, Monitor *m)
|
||||||
{
|
{
|
||||||
@ -1635,7 +1632,7 @@ setup(void)
|
|||||||
if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
|
if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
|
||||||
die("no fonts could be loaded.");
|
die("no fonts could be loaded.");
|
||||||
lrpad = drw->fonts->h;
|
lrpad = drw->fonts->h;
|
||||||
bh = usealtbar ? 0 : drw->fonts->h + 2;
|
bh = drw->fonts->h + 2;
|
||||||
updategeom();
|
updategeom();
|
||||||
/* init atoms */
|
/* init atoms */
|
||||||
utf8string = XInternAtom(dpy, "UTF8_STRING", False);
|
utf8string = XInternAtom(dpy, "UTF8_STRING", False);
|
||||||
@ -1684,7 +1681,6 @@ setup(void)
|
|||||||
XSelectInput(dpy, root, wa.event_mask);
|
XSelectInput(dpy, root, wa.event_mask);
|
||||||
grabkeys();
|
grabkeys();
|
||||||
focus(NULL);
|
focus(NULL);
|
||||||
spawnbar();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1743,13 +1739,6 @@ spawn(const Arg *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
spawnbar()
|
|
||||||
{
|
|
||||||
if (*altbarcmd)
|
|
||||||
system(altbarcmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
tag(const Arg *arg)
|
tag(const Arg *arg)
|
||||||
{
|
{
|
||||||
@ -1799,18 +1788,9 @@ tile(Monitor *m)
|
|||||||
void
|
void
|
||||||
togglebar(const Arg *arg)
|
togglebar(const Arg *arg)
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Polybar tray does not raise maprequest event. It must be manually scanned
|
|
||||||
* for. Scanning it too early while the tray is being populated would give
|
|
||||||
* wrong dimensions.
|
|
||||||
*/
|
|
||||||
if (!selmon->traywin)
|
|
||||||
scantray();
|
|
||||||
|
|
||||||
selmon->showbar = !selmon->showbar;
|
selmon->showbar = !selmon->showbar;
|
||||||
updatebarpos(selmon);
|
updatebarpos(selmon);
|
||||||
XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, selmon->bh);
|
XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
|
||||||
XMoveResizeWindow(dpy, selmon->traywin, selmon->tx, selmon->by, selmon->tw, selmon->bh);
|
|
||||||
arrange(selmon);
|
arrange(selmon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1893,41 +1873,10 @@ unmanage(Client *c, int destroyed)
|
|||||||
arrange(m);
|
arrange(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
unmanagealtbar(Window w)
|
|
||||||
{
|
|
||||||
Monitor *m = wintomon(w);
|
|
||||||
|
|
||||||
if (!m)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m->barwin = 0;
|
|
||||||
m->by = 0;
|
|
||||||
m->bh = 0;
|
|
||||||
updatebarpos(m);
|
|
||||||
arrange(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
unmanagetray(Window w)
|
|
||||||
{
|
|
||||||
Monitor *m = wintomon(w);
|
|
||||||
|
|
||||||
if (!m)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m->traywin = 0;
|
|
||||||
m->tx = 0;
|
|
||||||
m->tw = 0;
|
|
||||||
updatebarpos(m);
|
|
||||||
arrange(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
unmapnotify(XEvent *e)
|
unmapnotify(XEvent *e)
|
||||||
{
|
{
|
||||||
Client *c;
|
Client *c;
|
||||||
Monitor *m;
|
|
||||||
XUnmapEvent *ev = &e->xunmap;
|
XUnmapEvent *ev = &e->xunmap;
|
||||||
|
|
||||||
if ((c = wintoclient(ev->window))) {
|
if ((c = wintoclient(ev->window))) {
|
||||||
@ -1935,18 +1884,12 @@ unmapnotify(XEvent *e)
|
|||||||
setclientstate(c, WithdrawnState);
|
setclientstate(c, WithdrawnState);
|
||||||
else
|
else
|
||||||
unmanage(c, 0);
|
unmanage(c, 0);
|
||||||
} else if ((m = wintomon(ev->window)) && m->barwin == ev->window)
|
}
|
||||||
unmanagealtbar(ev->window);
|
|
||||||
else if (m->traywin == ev->window)
|
|
||||||
unmanagetray(ev->window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
updatebars(void)
|
updatebars(void)
|
||||||
{
|
{
|
||||||
if (usealtbar)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Monitor *m;
|
Monitor *m;
|
||||||
XSetWindowAttributes wa = {
|
XSetWindowAttributes wa = {
|
||||||
.override_redirect = True,
|
.override_redirect = True,
|
||||||
@ -1972,11 +1915,11 @@ updatebarpos(Monitor *m)
|
|||||||
m->wy = m->my;
|
m->wy = m->my;
|
||||||
m->wh = m->mh;
|
m->wh = m->mh;
|
||||||
if (m->showbar) {
|
if (m->showbar) {
|
||||||
m->wh -= m->bh;
|
m->wh -= bh;
|
||||||
m->by = m->topbar ? m->wy : m->wy + m->wh;
|
m->by = m->topbar ? m->wy : m->wy + m->wh;
|
||||||
m->wy = m->topbar ? m->wy + m->bh : m->wy;
|
m->wy = m->topbar ? m->wy + bh : m->wy;
|
||||||
} else
|
} else
|
||||||
m->by = -m->bh;
|
m->by = -bh;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2213,35 +2156,13 @@ wintomon(Window w)
|
|||||||
if (w == root && getrootptr(&x, &y))
|
if (w == root && getrootptr(&x, &y))
|
||||||
return recttomon(x, y, 1, 1);
|
return recttomon(x, y, 1, 1);
|
||||||
for (m = mons; m; m = m->next)
|
for (m = mons; m; m = m->next)
|
||||||
if (w == m->barwin || w == m->traywin)
|
if (w == m->barwin)
|
||||||
return m;
|
return m;
|
||||||
if ((c = wintoclient(w)))
|
if ((c = wintoclient(w)))
|
||||||
return c->mon;
|
return c->mon;
|
||||||
return selmon;
|
return selmon;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
wmclasscontains(Window win, const char *class, const char *name)
|
|
||||||
{
|
|
||||||
XClassHint ch = { NULL, NULL };
|
|
||||||
int res = 1;
|
|
||||||
|
|
||||||
if (XGetClassHint(dpy, win, &ch)) {
|
|
||||||
if (ch.res_name && strstr(ch.res_name, name) == NULL)
|
|
||||||
res = 0;
|
|
||||||
if (ch.res_class && strstr(ch.res_class, class) == NULL)
|
|
||||||
res = 0;
|
|
||||||
} else
|
|
||||||
res = 0;
|
|
||||||
|
|
||||||
if (ch.res_class)
|
|
||||||
XFree(ch.res_class);
|
|
||||||
if (ch.res_name)
|
|
||||||
XFree(ch.res_name);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* There's no way to check accesses to destroyed windows, thus those cases are
|
/* There's no way to check accesses to destroyed windows, thus those cases are
|
||||||
* ignored (especially on UnmapNotify's). Other types of errors call Xlibs
|
* ignored (especially on UnmapNotify's). Other types of errors call Xlibs
|
||||||
* default error handler, which may call exit. */
|
* default error handler, which may call exit. */
|
||||||
@ -2310,6 +2231,7 @@ main(int argc, char *argv[])
|
|||||||
die("pledge");
|
die("pledge");
|
||||||
#endif /* __OpenBSD__ */
|
#endif /* __OpenBSD__ */
|
||||||
scan();
|
scan();
|
||||||
|
runautostart();
|
||||||
run();
|
run();
|
||||||
cleanup();
|
cleanup();
|
||||||
XCloseDisplay(dpy);
|
XCloseDisplay(dpy);
|
||||||
|
Reference in New Issue
Block a user