#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>
#include <X11/Xlib.h>
#include <X11/Xproto.h>
#include <X11/Xutil.h>
+#include <X11/Xresource.h>
#ifdef XINERAMA
#include <X11/extensions/Xinerama.h>
#endif /* XINERAMA */
int monitor;
} Rule;
+/* Xresources preferences */
+enum resource_type {
+ STRING = 0,
+ INTEGER = 1,
+ FLOAT = 2
+};
+
+typedef struct {
+ char *name;
+ enum resource_type type;
+ void *dst;
+} ResourcePref;
+
/* function declarations */
static void applyrules(Client *c);
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
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);
static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
static void zoom(const Arg *arg);
+static void load_xresources(void);
+static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst);
/* 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 */
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)
{
pop(c);
}
+void
+resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
+{
+ char *sdst = NULL;
+ int *idst = NULL;
+ float *fdst = NULL;
+
+ sdst = dst;
+ idst = dst;
+ fdst = dst;
+
+ char fullname[256];
+ char *type;
+ XrmValue ret;
+
+ snprintf(fullname, sizeof(fullname), "%s.%s", "dwm", name);
+ fullname[sizeof(fullname) - 1] = '\0';
+
+ XrmGetResource(db, fullname, "*", &type, &ret);
+ if (!(ret.addr == NULL || strncmp("String", type, 64)))
+ {
+ switch (rtype) {
+ case STRING:
+ strcpy(sdst, ret.addr);
+ break;
+ case INTEGER:
+ *idst = strtoul(ret.addr, NULL, 10);
+ break;
+ case FLOAT:
+ *fdst = strtof(ret.addr, NULL);
+ break;
+ }
+ }
+}
+
+void
+load_xresources(void)
+{
+ Display *display;
+ char *resm;
+ XrmDatabase db;
+ ResourcePref *p;
+
+ display = XOpenDisplay(NULL);
+ resm = XResourceManagerString(display);
+ if (!resm)
+ return;
+
+ db = XrmGetStringDatabase(resm);
+ for (p = resources; p < resources + LENGTH(resources); p++)
+ resource_load(db, p->name, p->type, p->dst);
+ XCloseDisplay(display);
+}
+
int
main(int argc, char *argv[])
{
if (!(dpy = XOpenDisplay(NULL)))
die("dwm: cannot open display");
checkotherwm();
+ XrmInitialize();
+ load_xresources();
setup();
#ifdef __OpenBSD__
if (pledge("stdio rpath proc exec", NULL) == -1)
die("pledge");
#endif /* __OpenBSD__ */
scan();
+ runautostart();
run();
cleanup();
XCloseDisplay(dpy);