xresources
authorDaniel Liu <mr.picklepinosaur@gmail.com>
Thu, 30 Jul 2020 03:31:32 +0000 (23:31 -0400)
committerDaniel Liu <mr.picklepinosaur@gmail.com>
Thu, 30 Jul 2020 03:31:32 +0000 (23:31 -0400)
1  2 
dwm.c

diff --combined dwm.c
--- 1/dwm.c
--- 2/dwm.c
+++ b/dwm.c
@@@ -29,7 -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>
@@@ -37,6 -36,7 +37,7 @@@
  #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 */
@@@ -143,6 -143,19 +144,19 @@@ typedef struct 
        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);
@@@ -196,7 -209,6 +210,7 @@@ static void resizeclient(Client *c, in
  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);
@@@ -238,13 -250,11 +252,15 @@@ static int xerror(Display *dpy, XErrorE
  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 */
@@@ -1390,83 -1400,6 +1406,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)
  {
@@@ -2223,6 -2156,60 +2239,60 @@@ zoom(const Arg *arg
        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);