xresource
authorDaniel Liu <mr.picklepinosaur@gmail.com>
Fri, 18 Sep 2020 03:07:02 +0000 (23:07 -0400)
committerDaniel Liu <mr.picklepinosaur@gmail.com>
Fri, 18 Sep 2020 03:07:02 +0000 (23:07 -0400)
1  2 
config.def.h
slock.c

diff --combined config.def.h
@@@ -1,6 -1,6 +1,6 @@@
  /* user and group to drop privileges to */
 -static const char *user  = "nobody";
 -static const char *group = "nogroup";
 +static const char *user  = "pinosaur";
 +static const char *group = "pinosaur";
  
  static const char *colorname[NUMCOLS] = {
        [INIT] =   "black",     /* after initialization */
@@@ -8,16 -8,14 +8,25 @@@
        [FAILED] = "#CC3333",   /* wrong password */
  };
  
 +
 +/*
 + * Xresources preferences to load at startup
 + */
 +ResourcePref resources[] = {
 +              { "color0",       STRING,  &colorname[INIT] },
 +              { "color4",       STRING,  &colorname[INPUT] },
 +              { "color1",       STRING,  &colorname[FAILED] },
 +              { "color3",       STRING,  &colorname[CAPS] },
 +};
 +
  /* treat a cleared input like a wrong password (color) */
  static const int failonclear = 1;
+ /* default message */
+ static const char * message = "Suckless: Software that sucks less.";
+ /* text color */
+ static const char * text_color = "#ffffff";
+ /* text size (must be a valid size) */
+ static const char * font_name = "9x15";
diff --combined slock.c
+++ b/slock.c
@@@ -6,7 -6,6 +6,7 @@@
  
  #include <ctype.h>
  #include <errno.h>
 +#include <math.h>
  #include <grp.h>
  #include <pwd.h>
  #include <stdarg.h>
  #include <unistd.h>
  #include <sys/types.h>
  #include <X11/extensions/Xrandr.h>
+ #include <X11/extensions/Xinerama.h>
  #include <X11/keysym.h>
  #include <X11/Xlib.h>
  #include <X11/Xutil.h>
 +#include <X11/Xresource.h>
  
  #include "arg.h"
  #include "util.h"
  
  char *argv0;
  
+ /* global count to prevent repeated error messages */
+ int count_error = 0;
  enum {
        INIT,
        INPUT,
@@@ -46,19 -48,6 +50,19 @@@ struct xrandr 
        int errbase;
  };
  
 +/* Xresources preferences */
 +enum resource_type {
 +      STRING = 0,
 +      INTEGER = 1,
 +      FLOAT = 2
 +};
 +
 +typedef struct {
 +      char *name;
 +      enum resource_type type;
 +      void *dst;
 +} ResourcePref;
 +
  #include "config.h"
  
  static void
@@@ -98,6 -87,98 +102,98 @@@ dontkillme(void
  }
  #endif
  
+ static void
+ writemessage(Display *dpy, Window win, int screen)
+ {
+       int len, line_len, width, height, s_width, s_height, i, j, k, tab_replace, tab_size;
+       XGCValues gr_values;
+       XFontStruct *fontinfo;
+       XColor color, dummy;
+       XineramaScreenInfo *xsi;
+       GC gc;
+       fontinfo = XLoadQueryFont(dpy, font_name);
+       if (fontinfo == NULL) {
+               if (count_error == 0) {
+                       fprintf(stderr, "slock: Unable to load font \"%s\"\n", font_name);
+                       fprintf(stderr, "slock: Try listing fonts with 'slock -f'\n");
+                       count_error++;
+               }
+               return;
+       }
+       tab_size = 8 * XTextWidth(fontinfo, " ", 1);
+       XAllocNamedColor(dpy, DefaultColormap(dpy, screen),
+                text_color, &color, &dummy);
+       gr_values.font = fontinfo->fid;
+       gr_values.foreground = color.pixel;
+       gc=XCreateGC(dpy,win,GCFont+GCForeground, &gr_values);
+       /*  To prevent "Uninitialized" warnings. */
+       xsi = NULL;
+       /*
+        * Start formatting and drawing text
+        */
+       len = strlen(message);
+       /* Max max line length (cut at '\n') */
+       line_len = 0;
+       k = 0;
+       for (i = j = 0; i < len; i++) {
+               if (message[i] == '\n') {
+                       if (i - j > line_len)
+                               line_len = i - j;
+                       k++;
+                       i++;
+                       j = i;
+               }
+       }
+       /* If there is only one line */
+       if (line_len == 0)
+               line_len = len;
+       if (XineramaIsActive(dpy)) {
+               xsi = XineramaQueryScreens(dpy, &i);
+               s_width = xsi[0].width;
+               s_height = xsi[0].height;
+       } else {
+               s_width = DisplayWidth(dpy, screen);
+               s_height = DisplayHeight(dpy, screen);
+       }
+       height = s_height*3/7 - (k*20)/3;
+       width  = (s_width - XTextWidth(fontinfo, message, line_len))/2;
+       /* Look for '\n' and print the text between them. */
+       for (i = j = k = 0; i <= len; i++) {
+               /* i == len is the special case for the last line */
+               if (i == len || message[i] == '\n') {
+                       tab_replace = 0;
+                       while (message[j] == '\t' && j < i) {
+                               tab_replace++;
+                               j++;
+                       }
+                       XDrawString(dpy, win, gc, width + tab_size*tab_replace, height + 20*k, message + j, i - j);
+                       while (i < len && message[i] == '\n') {
+                               i++;
+                               j = i;
+                               k++;
+                       }
+               }
+       }
+       /* xsi should not be NULL anyway if Xinerama is active, but to be safe */
+       if (XineramaIsActive(dpy) && xsi != NULL)
+                       XFree(xsi);
+ }
  static const char *
  gethash(void)
  {
@@@ -209,6 -290,7 +305,7 @@@ readpw(Display *dpy, struct xrandr *rr
                                                             locks[screen]->win,
                                                             locks[screen]->colors[color]);
                                        XClearWindow(dpy, locks[screen]->win);
+                                       writemessage(dpy, locks[screen]->win, screen);
                                }
                                oldc = color;
                        }
@@@ -312,61 -394,10 +409,61 @@@ lockscreen(Display *dpy, struct xrandr 
        return NULL;
  }
  
 +int
 +resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
 +{
 +      char **sdst = dst;
 +      int *idst = dst;
 +      float *fdst = dst;
 +
 +      char fullname[256];
 +      char fullclass[256];
 +      char *type;
 +      XrmValue ret;
 +
 +      snprintf(fullname, sizeof(fullname), "%s.%s", "slock", name);
 +      snprintf(fullclass, sizeof(fullclass), "%s.%s", "Slock", name);
 +      fullname[sizeof(fullname) - 1] = fullclass[sizeof(fullclass) - 1] = '\0';
 +
 +      XrmGetResource(db, fullname, fullclass, &type, &ret);
 +      if (ret.addr == NULL || strncmp("String", type, 64))
 +              return 1;
 +
 +      switch (rtype) {
 +      case STRING:
 +              *sdst = ret.addr;
 +              break;
 +      case INTEGER:
 +              *idst = strtoul(ret.addr, NULL, 10);
 +              break;
 +      case FLOAT:
 +              *fdst = strtof(ret.addr, NULL);
 +              break;
 +      }
 +      return 0;
 +}
 +
 +void
 +config_init(Display *dpy)
 +{
 +      char *resm;
 +      XrmDatabase db;
 +      ResourcePref *p;
 +
 +      XrmInitialize();
 +      resm = XResourceManagerString(dpy);
 +      if (!resm)
 +              return;
 +
 +      db = XrmGetStringDatabase(resm);
 +      for (p = resources; p < resources + LEN(resources); p++)
 +              resource_load(db, p->name, p->type, p->dst);
 +}
 +
  static void
  usage(void)
  {
-       die("usage: slock [-v] [cmd [arg ...]]\n");
+       die("usage: slock [-v] [-f] [-m message] [cmd [arg ...]]\n");
  }
  
  int
@@@ -379,12 -410,25 +476,25 @@@ main(int argc, char **argv) 
        gid_t dgid;
        const char *hash;
        Display *dpy;
-       int s, nlocks, nscreens;
+       int i, s, nlocks, nscreens;
+       int count_fonts;
+       char **font_names;
  
        ARGBEGIN {
        case 'v':
                fprintf(stderr, "slock-"VERSION"\n");
                return 0;
+       case 'm':
+               message = EARGF(usage());
+               break;
+       case 'f':
+               if (!(dpy = XOpenDisplay(NULL)))
+                       die("slock: cannot open display\n");
+               font_names = XListFonts(dpy, "*", 10000 /* list 10000 fonts*/, &count_fonts);
+               for (i=0; i<count_fonts; i++) {
+                       fprintf(stderr, "%s\n", *(font_names+i));
+               }
+               return 0;
        default:
                usage();
        } ARGEND
        if (setuid(duid) < 0)
                die("slock: setuid: %s\n", strerror(errno));
  
 +      config_init(dpy);
 +
        /* check for Xrandr support */
        rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase);
  
        if (!(locks = calloc(nscreens, sizeof(struct lock *))))
                die("slock: out of memory\n");
        for (nlocks = 0, s = 0; s < nscreens; s++) {
-               if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL)
+               if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL) {
+                       writemessage(dpy, locks[s]->win, s);
                        nlocks++;
-               else
+               } else {
                        break;
+               }
        }
        XSync(dpy, 0);