From: Mike Lowis Date: Fri, 16 Sep 2016 19:27:27 +0000 (-0400) Subject: Tweak dwm and st settings and fixed a warning in st.c X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=d6cd83a082bfa77e402f9a3f2bf124af94dbcce3;p=proto%2Fiwe.git Tweak dwm and st settings and fixed a warning in st.c --- diff --git a/config/dwm.h b/config/dwm.h index 7054c06..c7b3ca0 100644 --- a/config/dwm.h +++ b/config/dwm.h @@ -2,7 +2,7 @@ /* appearance */ static const char *fonts[] = { - "monospace:size=10" + "monospace:size=10" }; static const char dmenufont[] = "monospace:size=10"; static const char normbordercolor[] = "#444444"; @@ -20,13 +20,13 @@ static const int topbar = 1; /* 0 means bottom bar */ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; static const Rule rules[] = { - /* xprop(1): - * WM_CLASS(STRING) = instance, class - * WM_NAME(STRING) = title - */ - /* class instance title tags mask isfloating monitor */ - { "Gimp", NULL, NULL, 0, 1, -1 }, - { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, + /* xprop(1): + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ + /* class instance title tags mask isfloating monitor */ + { "Gimp", NULL, NULL, 0, 1, -1 }, + { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, }; /* layout(s) */ @@ -35,79 +35,81 @@ 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 Layout layouts[] = { - /* symbol arrange function */ - { "[]=", tile }, /* first entry is default */ - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, + /* symbol arrange function */ + { "[]=", tile }, /* first entry is default */ + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, }; /* key definitions */ #define MODKEY Mod1Mask #define TAGKEYS(KEY,TAG) \ - { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ - { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, /* helper for spawning shell commands in the pre dwm-5.0 fashion */ #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } /* commands */ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; -static const char *termcmd[] = { "st", NULL }; +static const char* dmenucmd[] = { "dmenu_run", NULL }; +static const char* termcmd[] = { "st", NULL }; +static const char* lockcmd[] = { "slock", NULL }; static Key keys[] = { - /* modifier key function argument */ - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, - { MODKEY, XK_d, incnmaster, {.i = -1 } }, - { MODKEY, XK_h, setmfact, {.f = -0.05} }, - { MODKEY, XK_l, setmfact, {.f = +0.05} }, - { MODKEY, XK_Return, zoom, {0} }, - { MODKEY, XK_Tab, view, {0} }, - { MODKEY|ShiftMask, XK_c, killclient, {0} }, - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, - { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, - { MODKEY, XK_space, setlayout, {0} }, - { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, - { MODKEY, XK_0, view, {.ui = ~0 } }, - { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, - { MODKEY, XK_comma, focusmon, {.i = -1 } }, - { MODKEY, XK_period, focusmon, {.i = +1 } }, - { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, - { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, - TAGKEYS( XK_1, 0) - TAGKEYS( XK_2, 1) - TAGKEYS( XK_3, 2) - TAGKEYS( XK_4, 3) - TAGKEYS( XK_5, 4) - TAGKEYS( XK_6, 5) - TAGKEYS( XK_7, 6) - TAGKEYS( XK_8, 7) - TAGKEYS( XK_9, 8) - { MODKEY|ShiftMask, XK_q, quit, {0} }, + /* modifier key function argument */ + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, + { MODKEY|ShiftMask, XK_l, spawn, {.v = lockcmd } }, + { MODKEY, XK_b, togglebar, {0} }, + { MODKEY, XK_j, focusstack, {.i = +1 } }, + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, + { MODKEY, XK_comma, focusmon, {.i = -1 } }, + { MODKEY, XK_period, focusmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) + TAGKEYS( XK_4, 3) + TAGKEYS( XK_5, 4) + TAGKEYS( XK_6, 5) + TAGKEYS( XK_7, 6) + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, }; /* button definitions */ /* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ static Button buttons[] = { - /* click event mask button function argument */ - { ClkLtSymbol, 0, Button1, setlayout, {0} }, - { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, - { ClkWinTitle, 0, Button2, zoom, {0} }, - { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, - { ClkClientWin, MODKEY, Button1, movemouse, {0} }, - { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, - { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, - { ClkTagBar, 0, Button1, view, {0} }, - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + /* click event mask button function argument */ + { ClkLtSymbol, 0, Button1, setlayout, {0} }, + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, }; diff --git a/config/st.h b/config/st.h index 2da445e..740c556 100644 --- a/config/st.h +++ b/config/st.h @@ -5,9 +5,9 @@ * * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ -static char font[] = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; +static char font[] = "Liberation Mono:pixelsize=14:antialias=true:autohint=true"; static int borderpx = 2; -#define histsize 2000 +#define histsize 5000 /* * What program is execed by st depends of these precedence rules: diff --git a/slock/slock.c b/slock/slock.c index 7127ebe..19ae93b 100644 --- a/slock/slock.c +++ b/slock/slock.c @@ -1,5 +1,4 @@ /* See LICENSE file for license details. */ -#define _XOPEN_SOURCE 500 #if HAVE_SHADOW_H #include #endif @@ -25,19 +24,19 @@ char *argv0; enum { - INIT, - INPUT, - FAILED, - NUMCOLS + INIT, + INPUT, + FAILED, + NUMCOLS }; #include "config.h" typedef struct { - int screen; - Window root, win; - Pixmap pmap; - unsigned long colors[NUMCOLS]; + int screen; + Window root, win; + Pixmap pmap; + unsigned long colors[NUMCOLS]; } Lock; static Lock **locks; @@ -49,12 +48,12 @@ static int rrerrbase; static void die(const char *errstr, ...) { - va_list ap; + va_list ap; - va_start(ap, errstr); - vfprintf(stderr, errstr, ap); - va_end(ap); - exit(1); + va_start(ap, errstr); + vfprintf(stderr, errstr, ap); + va_end(ap); + exit(1); } #ifdef __linux__ @@ -64,345 +63,345 @@ die(const char *errstr, ...) static void dontkillme(void) { - FILE *f; - const char oomfile[] = "/proc/self/oom_score_adj"; - - if (!(f = fopen(oomfile, "w"))) { - if (errno == ENOENT) - return; - die("slock: fopen %s: %s\n", oomfile, strerror(errno)); - } - fprintf(f, "%d", OOM_SCORE_ADJ_MIN); - if (fclose(f)) { - if (errno == EACCES) - die("slock: unable to disable OOM killer. " - "suid or sgid set?\n"); - else - die("slock: fclose %s: %s\n", oomfile, - strerror(errno)); - } + FILE *f; + const char oomfile[] = "/proc/self/oom_score_adj"; + + if (!(f = fopen(oomfile, "w"))) { + if (errno == ENOENT) + return; + die("slock: fopen %s: %s\n", oomfile, strerror(errno)); + } + fprintf(f, "%d", OOM_SCORE_ADJ_MIN); + if (fclose(f)) { + if (errno == EACCES) + die("slock: unable to disable OOM killer. " + "suid or sgid set?\n"); + else + die("slock: fclose %s: %s\n", oomfile, + strerror(errno)); + } } #endif static const char * getpw(void) { - const char *rval; - struct passwd *pw; - - /* Check if the current user has a password entry */ - errno = 0; - if (!(pw = getpwuid(getuid()))) { - if (errno) - die("slock: getpwuid: %s\n", strerror(errno)); - else - die("slock: cannot retrieve password entry\n"); - } - rval = pw->pw_passwd; + const char *rval; + struct passwd *pw; + + /* Check if the current user has a password entry */ + errno = 0; + if (!(pw = getpwuid(getuid()))) { + if (errno) + die("slock: getpwuid: %s\n", strerror(errno)); + else + die("slock: cannot retrieve password entry\n"); + } + rval = pw->pw_passwd; #if HAVE_SHADOW_H - if (rval[0] == 'x' && rval[1] == '\0') { - struct spwd *sp; - if (!(sp = getspnam(getenv("USER")))) - die("slock: getspnam: cannot retrieve shadow entry (make sure to suid or sgid slock)\n"); - rval = sp->sp_pwdp; - } + if (rval[0] == 'x' && rval[1] == '\0') { + struct spwd *sp; + if (!(sp = getspnam(getenv("USER")))) + die("slock: getspnam: cannot retrieve shadow entry (make sure to suid or sgid slock)\n"); + rval = sp->sp_pwdp; + } #else - if (rval[0] == '*' && rval[1] == '\0') { + if (rval[0] == '*' && rval[1] == '\0') { #ifdef __OpenBSD__ - if (!(pw = getpwnam_shadow(getenv("USER")))) - die("slock: getpwnam_shadow: cannot retrieve shadow entry (make sure to suid or sgid slock)\n"); - rval = pw->pw_passwd; + if (!(pw = getpwnam_shadow(getenv("USER")))) + die("slock: getpwnam_shadow: cannot retrieve shadow entry (make sure to suid or sgid slock)\n"); + rval = pw->pw_passwd; #else - die("slock: getpwuid: cannot retrieve shadow entry (make sure to suid or sgid slock)\n"); + die("slock: getpwuid: cannot retrieve shadow entry (make sure to suid or sgid slock)\n"); #endif /* __OpenBSD__ */ - } + } #endif /* HAVE_SHADOW_H */ - return rval; + return rval; } static void readpw(Display *dpy, const char *pws) { - char buf[32], passwd[256], *encrypted; - int num, screen, running, failure; - unsigned int len, color; - KeySym ksym; - XEvent ev; - static int oldc = INIT; - - len = 0; - running = 1; - failure = 0; - - /* As "slock" stands for "Simple X display locker", the DPMS settings - * had been removed and you can set it with "xset" or some other - * utility. This way the user can easily set a customized DPMS - * timeout. */ - while (running && !XNextEvent(dpy, &ev)) { - if (ev.type == KeyPress) { - explicit_bzero(&buf, sizeof(buf)); - num = XLookupString(&ev.xkey, buf, sizeof(buf), &ksym, 0); - if (IsKeypadKey(ksym)) { - if (ksym == XK_KP_Enter) - ksym = XK_Return; - else if (ksym >= XK_KP_0 && ksym <= XK_KP_9) - ksym = (ksym - XK_KP_0) + XK_0; - } - if (IsFunctionKey(ksym) || - IsKeypadKey(ksym) || - IsMiscFunctionKey(ksym) || - IsPFKey(ksym) || - IsPrivateKeypadKey(ksym)) - continue; - switch (ksym) { - case XK_Return: - passwd[len] = 0; - errno = 0; - if (!(encrypted = crypt(passwd, pws))) - fprintf(stderr, "slock: crypt: %s\n", strerror(errno)); - else - running = !!strcmp(encrypted, pws); - if (running) { - XBell(dpy, 100); - failure = True; - } - explicit_bzero(&passwd, sizeof(passwd)); - len = 0; - break; - case XK_Escape: - explicit_bzero(&passwd, sizeof(passwd)); - len = 0; - break; - case XK_BackSpace: - if (len) - passwd[len--] = 0; - break; - default: - if (num && !iscntrl((int)buf[0]) && (len + num < sizeof(passwd))) { - memcpy(passwd + len, buf, num); - len += num; - } - break; - } - color = len ? INPUT : (failure || failonclear ? FAILED : INIT); - if (running && oldc != color) { - for (screen = 0; screen < nscreens; screen++) { - XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[color]); - XClearWindow(dpy, locks[screen]->win); - } - oldc = color; - } - } else if (rr && ev.type == rrevbase + RRScreenChangeNotify) { - XRRScreenChangeNotifyEvent *rre = (XRRScreenChangeNotifyEvent*)&ev; - for (screen = 0; screen < nscreens; screen++) { - if (locks[screen]->win == rre->window) { - XResizeWindow(dpy, locks[screen]->win, rre->width, rre->height); - XClearWindow(dpy, locks[screen]->win); - } - } - } else for (screen = 0; screen < nscreens; screen++) - XRaiseWindow(dpy, locks[screen]->win); - } + char buf[32], passwd[256], *encrypted; + int num, screen, running, failure; + unsigned int len, color; + KeySym ksym; + XEvent ev; + static int oldc = INIT; + + len = 0; + running = 1; + failure = 0; + + /* As "slock" stands for "Simple X display locker", the DPMS settings + * had been removed and you can set it with "xset" or some other + * utility. This way the user can easily set a customized DPMS + * timeout. */ + while (running && !XNextEvent(dpy, &ev)) { + if (ev.type == KeyPress) { + explicit_bzero(&buf, sizeof(buf)); + num = XLookupString(&ev.xkey, buf, sizeof(buf), &ksym, 0); + if (IsKeypadKey(ksym)) { + if (ksym == XK_KP_Enter) + ksym = XK_Return; + else if (ksym >= XK_KP_0 && ksym <= XK_KP_9) + ksym = (ksym - XK_KP_0) + XK_0; + } + if (IsFunctionKey(ksym) || + IsKeypadKey(ksym) || + IsMiscFunctionKey(ksym) || + IsPFKey(ksym) || + IsPrivateKeypadKey(ksym)) + continue; + switch (ksym) { + case XK_Return: + passwd[len] = 0; + errno = 0; + if (!(encrypted = crypt(passwd, pws))) + fprintf(stderr, "slock: crypt: %s\n", strerror(errno)); + else + running = !!strcmp(encrypted, pws); + if (running) { + XBell(dpy, 100); + failure = True; + } + explicit_bzero(&passwd, sizeof(passwd)); + len = 0; + break; + case XK_Escape: + explicit_bzero(&passwd, sizeof(passwd)); + len = 0; + break; + case XK_BackSpace: + if (len) + passwd[len--] = 0; + break; + default: + if (num && !iscntrl((int)buf[0]) && (len + num < sizeof(passwd))) { + memcpy(passwd + len, buf, num); + len += num; + } + break; + } + color = len ? INPUT : (failure || failonclear ? FAILED : INIT); + if (running && oldc != color) { + for (screen = 0; screen < nscreens; screen++) { + XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[color]); + XClearWindow(dpy, locks[screen]->win); + } + oldc = color; + } + } else if (rr && ev.type == rrevbase + RRScreenChangeNotify) { + XRRScreenChangeNotifyEvent *rre = (XRRScreenChangeNotifyEvent*)&ev; + for (screen = 0; screen < nscreens; screen++) { + if (locks[screen]->win == rre->window) { + XResizeWindow(dpy, locks[screen]->win, rre->width, rre->height); + XClearWindow(dpy, locks[screen]->win); + } + } + } else for (screen = 0; screen < nscreens; screen++) + XRaiseWindow(dpy, locks[screen]->win); + } } static void unlockscreen(Display *dpy, Lock *lock) { - if(dpy == NULL || lock == NULL) - return; + if(dpy == NULL || lock == NULL) + return; - XUngrabPointer(dpy, CurrentTime); - XUngrabKeyboard(dpy, CurrentTime); - XFreeColors(dpy, DefaultColormap(dpy, lock->screen), lock->colors, NUMCOLS, 0); - XFreePixmap(dpy, lock->pmap); - XDestroyWindow(dpy, lock->win); + XUngrabPointer(dpy, CurrentTime); + XUngrabKeyboard(dpy, CurrentTime); + XFreeColors(dpy, DefaultColormap(dpy, lock->screen), lock->colors, NUMCOLS, 0); + XFreePixmap(dpy, lock->pmap); + XDestroyWindow(dpy, lock->win); - free(lock); + free(lock); } static void cleanup(Display *dpy) { - int s; + int s; - for (s = 0; s < nscreens; ++s) - unlockscreen(dpy, locks[s]); + for (s = 0; s < nscreens; ++s) + unlockscreen(dpy, locks[s]); - free(locks); - XCloseDisplay(dpy); + free(locks); + XCloseDisplay(dpy); } static Lock * lockscreen(Display *dpy, int screen) { - char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; - int i, ptgrab, kbgrab; - Lock *lock; - XColor color, dummy; - XSetWindowAttributes wa; - Cursor invisible; - - if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(Lock)))) - return NULL; - - lock->screen = screen; - lock->root = RootWindow(dpy, lock->screen); - - for (i = 0; i < NUMCOLS; i++) { - XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), colorname[i], &color, &dummy); - lock->colors[i] = color.pixel; - } - - /* init */ - wa.override_redirect = 1; - wa.background_pixel = lock->colors[INIT]; - lock->win = XCreateWindow(dpy, lock->root, 0, 0, DisplayWidth(dpy, lock->screen), DisplayHeight(dpy, lock->screen), - 0, DefaultDepth(dpy, lock->screen), CopyFromParent, - DefaultVisual(dpy, lock->screen), CWOverrideRedirect | CWBackPixel, &wa); - lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8); - invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, &color, &color, 0, 0); - XDefineCursor(dpy, lock->win, invisible); - - /* Try to grab mouse pointer *and* keyboard for 600ms, else fail the lock */ - for (i = 0, ptgrab = kbgrab = -1; i < 6; i++) { - if (ptgrab != GrabSuccess) { - ptgrab = XGrabPointer(dpy, lock->root, False, - ButtonPressMask | ButtonReleaseMask | - PointerMotionMask, GrabModeAsync, - GrabModeAsync, None, invisible, CurrentTime); - } - if (kbgrab != GrabSuccess) { - kbgrab = XGrabKeyboard(dpy, lock->root, True, - GrabModeAsync, GrabModeAsync, CurrentTime); - } - - /* input is grabbed: we can lock the screen */ - if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) { - XMapRaised(dpy, lock->win); - if (rr) - XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask); - - XSelectInput(dpy, lock->root, SubstructureNotifyMask); - return lock; - } - - /* retry on AlreadyGrabbed but fail on other errors */ - if ((ptgrab != AlreadyGrabbed && ptgrab != GrabSuccess) || - (kbgrab != AlreadyGrabbed && kbgrab != GrabSuccess)) - break; - - usleep(100000); - } - - /* we couldn't grab all input: fail out */ - if (ptgrab != GrabSuccess) - fprintf(stderr, "slock: unable to grab mouse pointer for screen %d\n", screen); - if (kbgrab != GrabSuccess) - fprintf(stderr, "slock: unable to grab keyboard for screen %d\n", screen); - return NULL; + char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; + int i, ptgrab, kbgrab; + Lock *lock; + XColor color, dummy; + XSetWindowAttributes wa; + Cursor invisible; + + if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(Lock)))) + return NULL; + + lock->screen = screen; + lock->root = RootWindow(dpy, lock->screen); + + for (i = 0; i < NUMCOLS; i++) { + XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), colorname[i], &color, &dummy); + lock->colors[i] = color.pixel; + } + + /* init */ + wa.override_redirect = 1; + wa.background_pixel = lock->colors[INIT]; + lock->win = XCreateWindow(dpy, lock->root, 0, 0, DisplayWidth(dpy, lock->screen), DisplayHeight(dpy, lock->screen), + 0, DefaultDepth(dpy, lock->screen), CopyFromParent, + DefaultVisual(dpy, lock->screen), CWOverrideRedirect | CWBackPixel, &wa); + lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8); + invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, &color, &color, 0, 0); + XDefineCursor(dpy, lock->win, invisible); + + /* Try to grab mouse pointer *and* keyboard for 600ms, else fail the lock */ + for (i = 0, ptgrab = kbgrab = -1; i < 6; i++) { + if (ptgrab != GrabSuccess) { + ptgrab = XGrabPointer(dpy, lock->root, False, + ButtonPressMask | ButtonReleaseMask | + PointerMotionMask, GrabModeAsync, + GrabModeAsync, None, invisible, CurrentTime); + } + if (kbgrab != GrabSuccess) { + kbgrab = XGrabKeyboard(dpy, lock->root, True, + GrabModeAsync, GrabModeAsync, CurrentTime); + } + + /* input is grabbed: we can lock the screen */ + if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) { + XMapRaised(dpy, lock->win); + if (rr) + XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask); + + XSelectInput(dpy, lock->root, SubstructureNotifyMask); + return lock; + } + + /* retry on AlreadyGrabbed but fail on other errors */ + if ((ptgrab != AlreadyGrabbed && ptgrab != GrabSuccess) || + (kbgrab != AlreadyGrabbed && kbgrab != GrabSuccess)) + break; + + usleep(100000); + } + + /* we couldn't grab all input: fail out */ + if (ptgrab != GrabSuccess) + fprintf(stderr, "slock: unable to grab mouse pointer for screen %d\n", screen); + if (kbgrab != GrabSuccess) + fprintf(stderr, "slock: unable to grab keyboard for screen %d\n", screen); + return NULL; } static void usage(void) { - die("usage: slock [-v] [cmd [arg ...]]\n"); + die("usage: slock [-v] [cmd [arg ...]]\n"); } int main(int argc, char **argv) { - struct passwd *pwd; - struct group *grp; - uid_t duid; - gid_t dgid; - const char *pws; - Display *dpy; - int s, nlocks; - - ARGBEGIN { - case 'v': - fprintf(stderr, "slock-"VERSION"\n"); - return 0; - default: - usage(); - } ARGEND - - /* validate drop-user and -group */ - errno = 0; - if (!(pwd = getpwnam(user))) - die("slock: getpwnam %s: %s\n", user, errno ? - strerror(errno) : "user entry not found"); - duid = pwd->pw_uid; - errno = 0; - if (!(grp = getgrnam(group))) - die("slock: getgrnam %s: %s\n", group, errno ? - strerror(errno) : "group entry not found"); - dgid = grp->gr_gid; + struct passwd *pwd; + struct group *grp; + uid_t duid; + gid_t dgid; + const char *pws; + Display *dpy; + int s, nlocks; + + ARGBEGIN { + case 'v': + fprintf(stderr, "slock-"VERSION"\n"); + return 0; + default: + usage(); + } ARGEND + + /* validate drop-user and -group */ + errno = 0; + if (!(pwd = getpwnam(user))) + die("slock: getpwnam %s: %s\n", user, errno ? + strerror(errno) : "user entry not found"); + duid = pwd->pw_uid; + errno = 0; + if (!(grp = getgrnam(group))) + die("slock: getgrnam %s: %s\n", group, errno ? + strerror(errno) : "group entry not found"); + dgid = grp->gr_gid; #ifdef __linux__ - dontkillme(); + dontkillme(); #endif - pws = getpw(); - if (strlen(pws) < 2) - die("slock: failed to get user password hash.\n"); - - if (!(dpy = XOpenDisplay(NULL))) - die("slock: cannot open display\n"); - - /* drop privileges */ - if (setgroups(0, NULL) < 0) - die("slock: setgroups: %s\n", strerror(errno)); - if (setgid(dgid) < 0) - die("slock: setgid: %s\n", strerror(errno)); - if (setuid(duid) < 0) - die("slock: setuid: %s\n", strerror(errno)); - - /* check for Xrandr support */ - rr = XRRQueryExtension(dpy, &rrevbase, &rrerrbase); - - /* get number of screens in display "dpy" and blank them */ - nscreens = ScreenCount(dpy); - if (!(locks = calloc(nscreens, sizeof(Lock *)))) { - XCloseDisplay(dpy); - die("slock: out of memory\n"); - } - for (nlocks = 0, s = 0; s < nscreens; s++) { - if ((locks[s] = lockscreen(dpy, s)) != NULL) - nlocks++; - else - break; - } - XSync(dpy, 0); - - /* did we manage to lock everything? */ - if (nlocks != nscreens) { - cleanup(dpy); - return 1; - } - - /* run post-lock command */ - if (argc > 0) { - switch (fork()) { - case -1: - cleanup(dpy); - die("slock: fork failed: %s\n", strerror(errno)); - case 0: - if (close(ConnectionNumber(dpy)) < 0) - die("slock: close: %s\n", strerror(errno)); - execvp(argv[0], argv); - fprintf(stderr, "slock: execvp %s: %s\n", argv[0], - strerror(errno)); - _exit(1); - } - } - - /* everything is now blank. Wait for the correct password */ - readpw(dpy, pws); - - /* password ok, unlock everything and quit */ - cleanup(dpy); - - return 0; + pws = getpw(); + if (strlen(pws) < 2) + die("slock: failed to get user password hash.\n"); + + if (!(dpy = XOpenDisplay(NULL))) + die("slock: cannot open display\n"); + + /* drop privileges */ + if (setgroups(0, NULL) < 0) + die("slock: setgroups: %s\n", strerror(errno)); + if (setgid(dgid) < 0) + die("slock: setgid: %s\n", strerror(errno)); + if (setuid(duid) < 0) + die("slock: setuid: %s\n", strerror(errno)); + + /* check for Xrandr support */ + rr = XRRQueryExtension(dpy, &rrevbase, &rrerrbase); + + /* get number of screens in display "dpy" and blank them */ + nscreens = ScreenCount(dpy); + if (!(locks = calloc(nscreens, sizeof(Lock *)))) { + XCloseDisplay(dpy); + die("slock: out of memory\n"); + } + for (nlocks = 0, s = 0; s < nscreens; s++) { + if ((locks[s] = lockscreen(dpy, s)) != NULL) + nlocks++; + else + break; + } + XSync(dpy, 0); + + /* did we manage to lock everything? */ + if (nlocks != nscreens) { + cleanup(dpy); + return 1; + } + + /* run post-lock command */ + if (argc > 0) { + switch (fork()) { + case -1: + cleanup(dpy); + die("slock: fork failed: %s\n", strerror(errno)); + case 0: + if (close(ConnectionNumber(dpy)) < 0) + die("slock: close: %s\n", strerror(errno)); + execvp(argv[0], argv); + fprintf(stderr, "slock: execvp %s: %s\n", argv[0], + strerror(errno)); + _exit(1); + } + } + + /* everything is now blank. Wait for the correct password */ + readpw(dpy, pws); + + /* password ok, unlock everything and quit */ + cleanup(dpy); + + return 0; }