diff --git a/dwm/config.def.h b/dwm/config.def.h index 674ac07..87e61ce 100644 --- a/dwm/config.def.h +++ b/dwm/config.def.h @@ -4,7 +4,6 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ static const unsigned int gappx = 5; /* gaps between windows */ static const unsigned int snap = 32; /* snap pixel */ -static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ static const char *fonts[] = { "monospace:size=10" }; @@ -28,11 +27,9 @@ static const Rule rules[] = { * WM_CLASS(STRING) = instance, class * WM_NAME(STRING) = title */ - /* class instance title tags mask isfloating isterminal noswallow monitor */ - { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 }, - { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 }, - { "St", NULL, NULL, 0, 0, 1, 0, -1 }, - { NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */ + /* class instance title tags mask isfloating monitor */ + { "Gimp", NULL, NULL, 0, 1, -1 }, + { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, }; /* layout(s) */ @@ -65,12 +62,6 @@ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; static const char *termcmd[] = { "st", NULL }; -/* commands spawned when clicking statusbar, the mouse button pressed is exported as BUTTON */ -static const StatusCmd statuscmds[] = { - { "notify-send Mouse$BUTTON", 1 }, -}; -static const char *statuscmd[] = { "/bin/sh", "-c", NULL, NULL }; - static const Key keys[] = { /* modifier key function argument */ { MODKEY, XK_p, spawn, {.v = dmenucmd } }, @@ -109,7 +100,6 @@ static const Key keys[] = { TAGKEYS( XK_8, 7) TAGKEYS( XK_9, 8) { MODKEY|ShiftMask, XK_q, quit, {0} }, - { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, }; /* button definitions */ @@ -119,9 +109,7 @@ static const Button buttons[] = { { ClkLtSymbol, 0, Button1, setlayout, {0} }, { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, { ClkWinTitle, 0, Button2, zoom, {0} }, - { ClkStatusText, 0, Button1, spawn, {.v = statuscmd } }, - { ClkStatusText, 0, Button2, spawn, {.v = statuscmd } }, - { ClkStatusText, 0, Button3, spawn, {.v = statuscmd } }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, { ClkClientWin, MODKEY, Button1, movemouse, {0} }, { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, diff --git a/dwm/config.h b/dwm/config.h index 8ed1c90..dc970d6 100644 --- a/dwm/config.h +++ b/dwm/config.h @@ -6,7 +6,6 @@ static const unsigned int borderpx = 2; /* border pixel of windows */ static const unsigned int gappx = 4; /* gaps between windows */ static const unsigned int snap = 32; /* snap pixel */ -static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ static const char *fonts[] = { "Fira Code:size=11:antialias=true:autohint=true" }; @@ -33,18 +32,8 @@ static const Rule rules[] = { * WM_CLASS(STRING) = instance, class * WM_NAME(STRING) = title */ - /* Las ventanas que flotan por una regla se abren centradas. - * swallow: lo que se abre desde una terminal (isterminal) la sustituye - * hasta que se cierra; noswallow = 1 lo evita para esa ventana. */ - /* class instance title tags mask isfloating isterminal noswallow monitor */ - { "st-256color", NULL, NULL, 0, 0, 1, 0, -1 }, - { "st-float", NULL, NULL, 0, 1, 0, 1, -1 }, /* st -c st-float (p. ej. nmtui) */ - { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 }, - { NULL, "pavucontrol", NULL, 0, 1, 0, 0, -1 }, - { NULL, "blueman-manager", NULL, 0, 1, 0, 0, -1 }, - { "Firefox", "Places", NULL, 0, 1, 0, 0, -1 }, /* biblioteca/descargas */ - { "Firefox", "Toolkit", NULL, 0, 1, 0, 0, -1 }, /* picture-in-picture */ - { NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */ + /* class instance title tags mask isfloating monitor */ + { "Gimp", NULL, NULL, 0, 1, -1 }, }; /* layout(s) */ @@ -81,42 +70,10 @@ static const char *lockcmd[] = { "slock", NULL }; /* Audio: tras cada cambio se avisa a slstatus (SIGUSR1) para que refresque la barra al momento */ #define STATUSREFRESH "; pkill -USR1 -x slstatus" -#define VOLUPCMD "wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 5%+" STATUSREFRESH -#define VOLDOWNCMD "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-" STATUSREFRESH -#define VOLMUTECMD "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle" STATUSREFRESH -#define MICMUTECMD "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle" STATUSREFRESH -#define VOLUP SHCMD(VOLUPCMD) -#define VOLDOWN SHCMD(VOLDOWNCMD) -#define VOLMUTE SHCMD(VOLMUTECMD) -#define MICMUTE SHCMD(MICMUTECMD) - -/* - * Clics en la barra (parche statuscmd). El número es el byte que rodea cada - * zona en el config.h de slstatus; el botón pulsado llega en $BUTTON - * (1 izquierdo, 2 central, 3 derecho, 4/5 rueda arriba/abajo). - */ -static const StatusCmd statuscmds[] = { - /* red: izquierdo conectarse a una red, derecho el menú completo de nmtui */ - { "case $BUTTON in " - "1) st -c st-float -g 90x30 -e nmtui connect ;; " - "3) st -c st-float -g 90x30 -e nmtui ;; " - "esac", 1 }, - /* volumen: izquierdo pavucontrol, central silenciar, derecho micro, rueda subir/bajar */ - { "case $BUTTON in " - "1) pavucontrol ;; " - "2) " VOLMUTECMD " ;; " - "3) " MICMUTECMD " ;; " - "4) " VOLUPCMD " ;; " - "5) " VOLDOWNCMD " ;; " - "esac", 2 }, - /* bluetooth: izquierdo blueman, derecho encender/apagar el adaptador */ - { "case $BUTTON in " - "1) blueman-manager ;; " - "3) if bluetoothctl show | grep -q 'Powered: yes'; " - "then bluetoothctl power off; else bluetoothctl power on; fi >/dev/null" STATUSREFRESH " ;; " - "esac", 3 }, -}; -static const char *statuscmd[] = { "/bin/sh", "-c", NULL, NULL }; +#define VOLUP SHCMD("wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 5%+" STATUSREFRESH) +#define VOLDOWN SHCMD("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-" STATUSREFRESH) +#define VOLMUTE SHCMD("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle" STATUSREFRESH) +#define MICMUTE SHCMD("wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle" STATUSREFRESH) /* Capturas: se guardan en ~/Imágenes/Capturas y se copian al portapapeles */ #define SCREENSHOT(opts) SHCMD( \ @@ -166,7 +123,6 @@ static const Key keys[] = { TAGKEYS( XK_8, 7) TAGKEYS( XK_9, 8) { MODKEY|ShiftMask, XK_m, quit, {0} }, - { MODKEY|ShiftMask, XK_r, quit, {1} }, /* reiniciar dwm sin cerrar ventanas */ /* audio */ { 0, XF86XK_AudioRaiseVolume, spawn, VOLUP }, @@ -187,11 +143,7 @@ static const Button buttons[] = { { ClkLtSymbol, 0, Button1, setlayout, {0} }, { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, { ClkWinTitle, 0, Button2, zoom, {0} }, - { ClkStatusText, 0, Button1, spawn, {.v = statuscmd } }, - { ClkStatusText, 0, Button2, spawn, {.v = statuscmd } }, - { ClkStatusText, 0, Button3, spawn, {.v = statuscmd } }, - { ClkStatusText, 0, Button4, spawn, {.v = statuscmd } }, - { ClkStatusText, 0, Button5, spawn, {.v = statuscmd } }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, { ClkClientWin, MODKEY, Button1, movemouse, {0} }, { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, diff --git a/dwm/config.mk b/dwm/config.mk index 49b3c6c..982dc21 100644 --- a/dwm/config.mk +++ b/dwm/config.mk @@ -20,11 +20,10 @@ FREETYPEINC = /usr/include/freetype2 # OpenBSD (uncomment) #FREETYPEINC = ${X11INC}/freetype2 #MANPREFIX = ${PREFIX}/man -#KVMLIB = -lkvm # includes and libs INCS = -I${X11INC} -I${FREETYPEINC} -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} # flags CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} diff --git a/dwm/drw.c b/dwm/drw.c index 5bc9da2..9fdd1a4 100644 --- a/dwm/drw.c +++ b/dwm/drw.c @@ -176,9 +176,6 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname) DefaultColormap(drw->dpy, drw->screen), clrname, dest)) die("error, cannot allocate color '%s'", clrname); - - /* alfa opaco: si no, el borde de las ventanas ARGB (st con alpha) sale transparente */ - dest->pixel |= 0xffU << 24; } /* Create color schemes. */ diff --git a/dwm/dwm.1 b/dwm/dwm.1 index 7b6cadb..ddc8321 100644 --- a/dwm/dwm.1 +++ b/dwm/dwm.1 @@ -142,9 +142,6 @@ Add/remove all windows with nth tag to/from the view. .TP .B Mod1\-Shift\-q Quit dwm. -.TP -.B Mod1\-Control\-Shift\-q -Restart dwm. .SS Mouse commands .TP .B Mod1\-Button1 @@ -158,13 +155,6 @@ Resize focused window while dragging. Tiled windows will be toggled to the float .SH CUSTOMIZATION dwm is customized by creating a custom config.h and (re)compiling the source code. This keeps it fast, secure and simple. -.SH SIGNALS -.TP -.B SIGHUP - 1 -Restart the dwm process. -.TP -.B SIGTERM - 15 -Cleanly terminate the dwm process. .SH SEE ALSO .BR dmenu (1), .BR st (1) diff --git a/dwm/dwm.c b/dwm/dwm.c index 70c0df2..c27ae47 100644 --- a/dwm/dwm.c +++ b/dwm/dwm.c @@ -40,12 +40,6 @@ #include #endif /* XINERAMA */ #include -#include -#include -#ifdef __OpenBSD__ -#include -#include -#endif /* __OpenBSD */ #include "drw.h" #include "util.h" @@ -67,7 +61,7 @@ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ enum { SchemeNorm, SchemeSel }; /* color schemes */ enum { NetSupported, NetWMName, NetWMState, NetWMCheck, NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetClientInfo, NetLast }; /* EWMH atoms */ + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ @@ -97,11 +91,9 @@ struct Client { int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; int bw, oldbw; unsigned int tags; - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow; - pid_t pid; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; Client *next; Client *snext; - Client *swallowing; Monitor *mon; Window win; }; @@ -146,16 +138,9 @@ typedef struct { const char *title; unsigned int tags; int isfloating; - int isterminal; - int noswallow; int monitor; } Rule; -typedef struct { - const char *cmd; - int id; -} StatusCmd; - /* function declarations */ static void applyrules(Client *c); static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); @@ -213,7 +198,6 @@ static void scan(void); static int sendevent(Client *c, Atom proto); static void sendmon(Client *c, Monitor *m); static void setclientstate(Client *c, long state); -static void setclienttagprop(Client *c); static void setfocus(Client *c); static void setfullscreen(Client *c, int fullscreen); static void setgaps(const Arg *arg); @@ -222,8 +206,6 @@ static void setmfact(const Arg *arg); static void setup(void); static void seturgent(Client *c, int urg); static void showhide(Client *c); -static void sighup(int unused); -static void sigterm(int unused); static void spawn(const Arg *arg); static void tag(const Arg *arg); static void tagmon(const Arg *arg); @@ -253,18 +235,9 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee); static int xerrorstart(Display *dpy, XErrorEvent *ee); static void zoom(const Arg *arg); -static pid_t getparentprocess(pid_t p); -static int isdescprocess(pid_t p, pid_t c); -static Client *swallowingclient(Window w); -static Client *termforwin(const Client *c); -static pid_t winpid(Window w); - /* variables */ static const char broken[] = "broken"; static char stext[256]; -static int statusw; -static int statuscmdn; -static char lastbutton[] = "-"; static int screen; static int sw, sh; /* X display screen geometry width, height */ static int bh; /* bar height */ @@ -288,7 +261,6 @@ static void (*handler[LASTEvent]) (XEvent *) = { [UnmapNotify] = unmapnotify }; static Atom wmatom[WMLast], netatom[NetLast]; -static int restart = 0; static int running = 1; static Cur *cursor[CurLast]; static Clr **scheme; @@ -297,8 +269,6 @@ static Drw *drw; static Monitor *mons, *selmon; static Window root, wmcheckwin; -static xcb_connection_t *xcon; - /* configuration, allows nested code to access above variables */ #include "config.h" @@ -328,8 +298,6 @@ applyrules(Client *c) && (!r->class || strstr(class, r->class)) && (!r->instance || strstr(instance, r->instance))) { - c->isterminal = r->isterminal; - c->noswallow = r->noswallow; c->isfloating = r->isfloating; c->tags |= r->tags; for (m = mons; m && m->num != r->monitor; m = m->next); @@ -448,53 +416,6 @@ attachstack(Client *c) c->mon->stack = c; } -void -swallow(Client *p, Client *c) -{ - - if (c->noswallow > 0 || c->isterminal) - return; - if (c->noswallow < 0 && !swallowfloating && c->isfloating) - return; - - detach(c); - detachstack(c); - - setclientstate(c, WithdrawnState); - XUnmapWindow(dpy, p->win); - - p->swallowing = c; - c->mon = p->mon; - - Window w = p->win; - p->win = c->win; - c->win = w; - updatetitle(p); - XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h); - arrange(p->mon); - configure(p); - updateclientlist(); -} - -void -unswallow(Client *c) -{ - c->win = c->swallowing->win; - - free(c->swallowing); - c->swallowing = NULL; - - /* unfullscreen the client */ - setfullscreen(c, 0); - updatetitle(c); - arrange(c->mon); - XMapWindow(dpy, c->win); - XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); - setclientstate(c, NormalState); - focus(NULL); - arrange(c->mon); -} - void buttonpress(XEvent *e) { @@ -521,28 +442,9 @@ buttonpress(XEvent *e) arg.ui = 1 << i; } else if (ev->x < x + TEXTW(selmon->ltsymbol)) click = ClkLtSymbol; - else if (ev->x > selmon->ww - statusw) { - char *text, *s, ch; - *lastbutton = '0' + ev->button; - - x = selmon->ww - statusw; + else if (ev->x > selmon->ww - (int)TEXTW(stext) + lrpad - 2) click = ClkStatusText; - - statuscmdn = 0; - for (text = s = stext; *s && x <= ev->x; s++) { - if ((unsigned char)(*s) < ' ') { - ch = *s; - *s = '\0'; - x += TEXTW(text) - lrpad; - *s = ch; - text = s + 1; - if (x >= ev->x) - break; - /* el mismo byte al final cierra la sección clicable */ - statuscmdn = (statuscmdn == ch) ? 0 : ch; - } - } - } else + else click = ClkWinTitle; } else if ((c = wintoclient(ev->window))) { focus(c); @@ -755,9 +657,6 @@ destroynotify(XEvent *e) if ((c = wintoclient(ev->window))) unmanage(c, 1); - - else if ((c = swallowingclient(ev->window))) - unmanage(c->swallowing, 1); } void @@ -812,24 +711,9 @@ drawbar(Monitor *m) /* draw status first so it can be overdrawn by tags later */ if (m == selmon) { /* status is only drawn on selected monitor */ - char *text, *s, ch; drw_setscheme(drw, scheme[SchemeNorm]); - - x = 0; - for (text = s = stext; *s; s++) { - if ((unsigned char)(*s) < ' ') { - ch = *s; - *s = '\0'; - tw = TEXTW(text) - lrpad; - drw_text(drw, m->ww - statusw + x, 0, tw, bh, 0, text, 0); - x += tw; - *s = ch; - text = s + 1; - } - } - tw = TEXTW(text) - lrpad + 2; - drw_text(drw, m->ww - statusw + x, 0, tw, bh, 0, text, 0); - tw = statusw; + tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ + drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); } for (c = m->clients; c; c = c->next) { @@ -1150,13 +1034,12 @@ killclient(const Arg *arg) void manage(Window w, XWindowAttributes *wa) { - Client *c, *t = NULL, *term = NULL; + Client *c, *t = NULL; Window trans = None; XWindowChanges wc; c = ecalloc(1, sizeof(Client)); c->win = w; - c->pid = winpid(w); /* geometry */ c->x = c->oldx = wa->x; c->y = c->oldy = wa->y; @@ -1171,12 +1054,6 @@ manage(Window w, XWindowAttributes *wa) } else { c->mon = selmon; applyrules(c); - /* las ventanas que flotan por una regla se abren centradas */ - if (c->isfloating) { - c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2; - c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2; - } - term = termforwin(c); } if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) @@ -1194,26 +1071,6 @@ manage(Window w, XWindowAttributes *wa) updatewindowtype(c); updatesizehints(c); updatewmhints(c); - { - int format; - unsigned long *data = NULL, n = 0, extra; - Monitor *m; - Atom atom; - if (XGetWindowProperty(dpy, c->win, netatom[NetClientInfo], 0L, 2L, False, XA_CARDINAL, - &atom, &format, &n, &extra, (unsigned char **)&data) == Success && n == 2 && (*data & TAGMASK)) { - c->tags = *data & TAGMASK; - for (m = mons; m; m = m->next) { - if (m->num == *(data+1)) { - c->mon = m; - break; - } - } - } - if (data) - XFree(data); - } - setclienttagprop(c); - XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); grabbuttons(c, 0); if (!c->isfloating) @@ -1231,8 +1088,6 @@ manage(Window w, XWindowAttributes *wa) c->mon->sel = c; arrange(c->mon); XMapWindow(dpy, c->win); - if (term) - swallow(term, c); focus(NULL); } @@ -1406,7 +1261,6 @@ propertynotify(XEvent *e) void quit(const Arg *arg) { - if(arg->i) restart = 1; running = 0; } @@ -1578,7 +1432,6 @@ sendmon(Client *c, Monitor *m) c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ attach(c); attachstack(c); - setclienttagprop(c); if (c->isfullscreen) resizeclient(c, m->mx, m->my, m->mw, m->mh); focus(NULL); @@ -1713,9 +1566,6 @@ setup(void) /* clean up any zombies (inherited from .xinitrc etc) immediately */ while (waitpid(-1, NULL, WNOHANG) > 0); - signal(SIGHUP, sighup); - signal(SIGTERM, sigterm); - /* init screen */ screen = DefaultScreen(dpy); sw = DisplayWidth(dpy, screen); @@ -1742,7 +1592,6 @@ setup(void) netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); - netatom[NetClientInfo] = XInternAtom(dpy, "_NET_CLIENT_INFO", False); /* init cursors */ cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); cursor[CurResize] = drw_cur_create(drw, XC_sizing); @@ -1766,7 +1615,6 @@ setup(void) XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, PropModeReplace, (unsigned char *) netatom, NetLast); XDeleteProperty(dpy, root, netatom[NetClientList]); - XDeleteProperty(dpy, root, netatom[NetClientInfo]); /* select events */ wa.cursor = cursor[CurNormal]->cursor; wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask @@ -1809,20 +1657,6 @@ showhide(Client *c) } } -void -sighup(int unused) -{ - Arg a = {.i = 1}; - quit(&a); -} - -void -sigterm(int unused) -{ - Arg a = {.i = 0}; - quit(&a); -} - void spawn(const Arg *arg) { @@ -1833,17 +1667,6 @@ spawn(const Arg *arg) if (fork() == 0) { if (dpy) close(ConnectionNumber(dpy)); - if (arg->v == statuscmd) { - for (int i = 0; i < LENGTH(statuscmds); i++) { - if (statuscmdn == statuscmds[i].id) { - statuscmd[2] = statuscmds[i].cmd; - setenv("BUTTON", lastbutton, 1); - break; - } - } - if (!statuscmd[2]) - exit(EXIT_SUCCESS); - } setsid(); sigemptyset(&sa.sa_mask); @@ -1856,22 +1679,11 @@ spawn(const Arg *arg) } } -void -setclienttagprop(Client *c) -{ - long data[] = { (long) c->tags, (long) c->mon->num }; - XChangeProperty(dpy, c->win, netatom[NetClientInfo], XA_CARDINAL, 32, - PropModeReplace, (unsigned char *) data, 2); -} - void tag(const Arg *arg) { - Client *c; if (selmon->sel && arg->ui & TAGMASK) { - c = selmon->sel; selmon->sel->tags = arg->ui & TAGMASK; - setclienttagprop(c); focus(NULL); arrange(selmon); } @@ -1946,7 +1758,6 @@ toggletag(const Arg *arg) newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); if (newtags) { selmon->sel->tags = newtags; - setclienttagprop(selmon->sel); focus(NULL); arrange(selmon); } @@ -1983,20 +1794,6 @@ unmanage(Client *c, int destroyed) Monitor *m = c->mon; XWindowChanges wc; - if (c->swallowing) { - unswallow(c); - return; - } - - Client *s = swallowingclient(c->win); - if (s) { - free(s->swallowing); - s->swallowing = NULL; - arrange(m); - focus(NULL); - return; - } - detach(c); detachstack(c); if (!destroyed) { @@ -2012,12 +1809,9 @@ unmanage(Client *c, int destroyed) XUngrabServer(dpy); } free(c); - - if (!s) { - arrange(m); - focus(NULL); - updateclientlist(); - } + focus(NULL); + updateclientlist(); + arrange(m); } void @@ -2224,23 +2018,8 @@ updatesizehints(Client *c) void updatestatus(void) { - if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) { + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) strcpy(stext, "dwm-"VERSION); - statusw = TEXTW(stext) - lrpad + 2; - } else { - char *text, *s, ch; - statusw = 0; - for (text = s = stext; *s; s++) { - if ((unsigned char)(*s) < ' ') { - ch = *s; - *s = '\0'; - statusw += TEXTW(text) - lrpad; - *s = ch; - text = s + 1; - } - } - statusw += TEXTW(text) - lrpad + 2; - } drawbar(selmon); } @@ -2296,136 +2075,6 @@ view(const Arg *arg) arrange(selmon); } -pid_t -winpid(Window w) -{ - - pid_t result = 0; - -#ifdef __linux__ - xcb_res_client_id_spec_t spec = {0}; - spec.client = w; - spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; - - xcb_generic_error_t *e = NULL; - xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); - xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); - - if (!r) - return (pid_t)0; - - xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); - for (; i.rem; xcb_res_client_id_value_next(&i)) { - spec = i.data->spec; - if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { - uint32_t *t = xcb_res_client_id_value_value(i.data); - result = *t; - break; - } - } - - free(r); - - if (result == (pid_t)-1) - result = 0; - -#endif /* __linux__ */ - -#ifdef __OpenBSD__ - Atom type; - int format; - unsigned long len, bytes; - unsigned char *prop; - pid_t ret; - - if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 0), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop) - return 0; - - ret = *(pid_t*)prop; - XFree(prop); - result = ret; - -#endif /* __OpenBSD__ */ - return result; -} - -pid_t -getparentprocess(pid_t p) -{ - unsigned int v = 0; - -#ifdef __linux__ - FILE *f; - char buf[256]; - snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); - - if (!(f = fopen(buf, "r"))) - return 0; - - fscanf(f, "%*u %*s %*c %u", &v); - fclose(f); -#endif /* __linux__*/ - -#ifdef __OpenBSD__ - int n; - kvm_t *kd; - struct kinfo_proc *kp; - - kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL); - if (!kd) - return 0; - - kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n); - v = kp->p_ppid; -#endif /* __OpenBSD__ */ - - return (pid_t)v; -} - -int -isdescprocess(pid_t p, pid_t c) -{ - while (p != c && c != 0) - c = getparentprocess(c); - - return (int)c; -} - -Client * -termforwin(const Client *w) -{ - Client *c; - Monitor *m; - - if (!w->pid || w->isterminal) - return NULL; - - for (m = mons; m; m = m->next) { - for (c = m->clients; c; c = c->next) { - if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) - return c; - } - } - - return NULL; -} - -Client * -swallowingclient(Window w) -{ - Client *c; - Monitor *m; - - for (m = mons; m; m = m->next) { - for (c = m->clients; c; c = c->next) { - if (c->swallowing && c->swallowing->win == w) - return c; - } - } - - return NULL; -} - Client * wintoclient(Window w) { @@ -2515,26 +2164,14 @@ main(int argc, char *argv[]) fputs("warning: no locale support\n", stderr); if (!(dpy = XOpenDisplay(NULL))) die("dwm: cannot open display"); - if (!(xcon = XGetXCBConnection(dpy))) - die("dwm: cannot get xcb connection\n"); checkotherwm(); setup(); #ifdef __OpenBSD__ - if (pledge("stdio rpath proc exec ps", NULL) == -1) + if (pledge("stdio rpath proc exec", NULL) == -1) die("pledge"); #endif /* __OpenBSD__ */ scan(); run(); - if (restart) { - /* volver a mostrar las terminales tragadas (swallow); si no, el dwm - * nuevo no las ve y se quedan ocultas para siempre */ - for (Monitor *m = mons; m; m = m->next) - for (Client *c = m->clients; c; c = c->next) - if (c->swallowing) - XMapWindow(dpy, c->swallowing->win); - XSync(dpy, False); - execvp(argv[0], argv); - } cleanup(); XCloseDisplay(dpy); return EXIT_SUCCESS; diff --git a/dwm/patches/dwm-preserveonrestart-6.3.diff b/dwm/patches/dwm-preserveonrestart-6.3.diff deleted file mode 100644 index 079cf05..0000000 --- a/dwm/patches/dwm-preserveonrestart-6.3.diff +++ /dev/null @@ -1,118 +0,0 @@ -From 713fa8650f5a20006451ebcccf57a4512e83bae8 Mon Sep 17 00:00:00 2001 -From: Arda Atci -Date: Wed, 18 May 2022 17:23:16 +0300 -Subject: [PATCH] preserve clients on old tags when renewing dwm - -By default, when dwm is recompiled-restarted all clients will -lose it's current tag and collapse to first tag. This patch preserves -clients on old tags, however note that layout order is not preserved. - ---- - dwm.c | 38 +++++++++++++++++++++++++++++++++++++- - 1 file changed, 37 insertions(+), 1 deletion(-) - -diff --git a/dwm.c b/dwm.c -index a96f33c..a12e0bd 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -62,7 +62,7 @@ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ - enum { SchemeNorm, SchemeSel }; /* color schemes */ - enum { NetSupported, NetWMName, NetWMState, NetWMCheck, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, -- NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ -+ NetWMWindowTypeDialog, NetClientList, NetClientInfo, NetLast }; /* EWMH atoms */ - enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ - enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ -@@ -198,6 +198,7 @@ static void scan(void); - static int sendevent(Client *c, Atom proto); - static void sendmon(Client *c, Monitor *m); - static void setclientstate(Client *c, long state); -+static void setclienttagprop(Client *c); - static void setfocus(Client *c); - static void setfullscreen(Client *c, int fullscreen); - static void setlayout(const Arg *arg); -@@ -1060,6 +1061,26 @@ manage(Window w, XWindowAttributes *wa) - updatewindowtype(c); - updatesizehints(c); - updatewmhints(c); -+ { -+ int format; -+ unsigned long *data, n, extra; -+ Monitor *m; -+ Atom atom; -+ if (XGetWindowProperty(dpy, c->win, netatom[NetClientInfo], 0L, 2L, False, XA_CARDINAL, -+ &atom, &format, &n, &extra, (unsigned char **)&data) == Success && n == 2) { -+ c->tags = *data; -+ for (m = mons; m; m = m->next) { -+ if (m->num == *(data+1)) { -+ c->mon = m; -+ break; -+ } -+ } -+ } -+ if (n > 0) -+ XFree(data); -+ } -+ setclienttagprop(c); -+ - XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); - grabbuttons(c, 0); - if (!c->isfloating) -@@ -1423,6 +1444,7 @@ sendmon(Client *c, Monitor *m) - c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ - attach(c); - attachstack(c); -+ setclienttagprop(c); - focus(NULL); - arrange(NULL); - } -@@ -1566,6 +1588,7 @@ setup(void) - netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); - netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); - netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); -+ netatom[NetClientInfo] = XInternAtom(dpy, "_NET_CLIENT_INFO", False); - /* init cursors */ - cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); - cursor[CurResize] = drw_cur_create(drw, XC_sizing); -@@ -1589,6 +1612,7 @@ setup(void) - XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, - PropModeReplace, (unsigned char *) netatom, NetLast); - XDeleteProperty(dpy, root, netatom[NetClientList]); -+ XDeleteProperty(dpy, root, netatom[NetClientInfo]); - /* select events */ - wa.cursor = cursor[CurNormal]->cursor; - wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask -@@ -1656,11 +1680,22 @@ spawn(const Arg *arg) - } - } - -+void -+setclienttagprop(Client *c) -+{ -+ long data[] = { (long) c->tags, (long) c->mon->num }; -+ XChangeProperty(dpy, c->win, netatom[NetClientInfo], XA_CARDINAL, 32, -+ PropModeReplace, (unsigned char *) data, 2); -+} -+ - void - tag(const Arg *arg) - { -+ Client *c; - if (selmon->sel && arg->ui & TAGMASK) { -+ c = selmon->sel; - selmon->sel->tags = arg->ui & TAGMASK; -+ setclienttagprop(c); - focus(NULL); - arrange(selmon); - } -@@ -1735,6 +1770,7 @@ toggletag(const Arg *arg) - newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); - if (newtags) { - selmon->sel->tags = newtags; -+ setclienttagprop(selmon->sel); - focus(NULL); - arrange(selmon); - } --- -2.36.1 diff --git a/dwm/patches/dwm-restartsig-20180523-6.2.diff b/dwm/patches/dwm-restartsig-20180523-6.2.diff deleted file mode 100644 index f1f8680..0000000 --- a/dwm/patches/dwm-restartsig-20180523-6.2.diff +++ /dev/null @@ -1,139 +0,0 @@ -From 2991f37f0aaf44b9f9b11e7893ff0af8eb88f649 Mon Sep 17 00:00:00 2001 -From: Christopher Drelich -Date: Wed, 23 May 2018 22:50:38 -0400 -Subject: [PATCH] Modifies quit to handle restarts and adds SIGHUP and SIGTERM - handlers. - -Modified quit() to restart if it receives arg .i = 1 -MOD+CTRL+SHIFT+Q was added to confid.def.h to do just that. - -Signal handlers were handled for SIGHUP and SIGTERM. -If dwm receives these signals it calls quit() with -arg .i = to 1 or 0, respectively. - -To restart dwm: -MOD+CTRL+SHIFT+Q -or -kill -HUP dwmpid - -To quit dwm cleanly: -MOD+SHIFT+Q -or -kill -TERM dwmpid ---- - config.def.h | 1 + - dwm.1 | 10 ++++++++++ - dwm.c | 22 ++++++++++++++++++++++ - 3 files changed, 33 insertions(+) - -diff --git a/config.def.h b/config.def.h -index a9ac303..e559429 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -94,6 +94,7 @@ static Key keys[] = { - TAGKEYS( XK_8, 7) - TAGKEYS( XK_9, 8) - { MODKEY|ShiftMask, XK_q, quit, {0} }, -+ { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, - }; - - /* button definitions */ -diff --git a/dwm.1 b/dwm.1 -index 13b3729..36a331c 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -142,6 +142,9 @@ Add/remove all windows with nth tag to/from the view. - .TP - .B Mod1\-Shift\-q - Quit dwm. -+.TP -+.B Mod1\-Control\-Shift\-q -+Restart dwm. - .SS Mouse commands - .TP - .B Mod1\-Button1 -@@ -155,6 +158,13 @@ Resize focused window while dragging. Tiled windows will be toggled to the float - .SH CUSTOMIZATION - dwm is customized by creating a custom config.h and (re)compiling the source - code. This keeps it fast, secure and simple. -+.SH SIGNALS -+.TP -+.B SIGHUP - 1 -+Restart the dwm process. -+.TP -+.B SIGTERM - 15 -+Cleanly terminate the dwm process. - .SH SEE ALSO - .BR dmenu (1), - .BR st (1) -diff --git a/dwm.c b/dwm.c -index bb95e26..286eecd 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -205,6 +205,8 @@ static void setup(void); - static void seturgent(Client *c, int urg); - static void showhide(Client *c); - static void sigchld(int unused); -+static void sighup(int unused); -+static void sigterm(int unused); - static void spawn(const Arg *arg); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); -@@ -260,6 +262,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { - [UnmapNotify] = unmapnotify - }; - static Atom wmatom[WMLast], netatom[NetLast]; -+static int restart = 0; - static int running = 1; - static Cur *cursor[CurLast]; - static Clr **scheme; -@@ -1248,6 +1251,7 @@ propertynotify(XEvent *e) - void - quit(const Arg *arg) - { -+ if(arg->i) restart = 1; - running = 0; - } - -@@ -1536,6 +1540,9 @@ setup(void) - /* clean up any zombies immediately */ - sigchld(0); - -+ signal(SIGHUP, sighup); -+ signal(SIGTERM, sigterm); -+ - /* init screen */ - screen = DefaultScreen(dpy); - sw = DisplayWidth(dpy, screen); -@@ -1637,6 +1644,20 @@ sigchld(int unused) - } - - void -+sighup(int unused) -+{ -+ Arg a = {.i = 1}; -+ quit(&a); -+} -+ -+void -+sigterm(int unused) -+{ -+ Arg a = {.i = 0}; -+ quit(&a); -+} -+ -+void - spawn(const Arg *arg) - { - if (arg->v == dmenucmd) -@@ -2139,6 +2160,7 @@ main(int argc, char *argv[]) - setup(); - scan(); - run(); -+ if(restart) execvp(argv[0], argv); - cleanup(); - XCloseDisplay(dpy); - return EXIT_SUCCESS; --- -2.7.4 - diff --git a/dwm/patches/dwm-statuscmd-nosignal-20210402-67d76bd.diff b/dwm/patches/dwm-statuscmd-nosignal-20210402-67d76bd.diff deleted file mode 100644 index 1dc5c53..0000000 --- a/dwm/patches/dwm-statuscmd-nosignal-20210402-67d76bd.diff +++ /dev/null @@ -1,167 +0,0 @@ -From 02c4a28dd7f3a88eef3a4e533ace35f79cf09d57 Mon Sep 17 00:00:00 2001 -From: Daniel Bylinka -Date: Fri, 2 Apr 2021 19:34:38 +0200 -Subject: [PATCH] [statuscmd] Run shell commands based on mouse location and - button - ---- - config.def.h | 10 ++++++- - dwm.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++--- - 2 files changed, 81 insertions(+), 5 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 1c0b587..8f88366 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -59,6 +59,12 @@ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() - static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; - static const char *termcmd[] = { "st", NULL }; - -+/* commands spawned when clicking statusbar, the mouse button pressed is exported as BUTTON */ -+static const StatusCmd statuscmds[] = { -+ { "notify-send Mouse$BUTTON", 1 }, -+}; -+static const char *statuscmd[] = { "/bin/sh", "-c", NULL, NULL }; -+ - static Key keys[] = { - /* modifier key function argument */ - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, -@@ -103,7 +109,9 @@ static Button buttons[] = { - { ClkLtSymbol, 0, Button1, setlayout, {0} }, - { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, - { ClkWinTitle, 0, Button2, zoom, {0} }, -- { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, -+ { ClkStatusText, 0, Button1, spawn, {.v = statuscmd } }, -+ { ClkStatusText, 0, Button2, spawn, {.v = statuscmd } }, -+ { ClkStatusText, 0, Button3, spawn, {.v = statuscmd } }, - { ClkClientWin, MODKEY, Button1, movemouse, {0} }, - { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, - { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, -diff --git a/dwm.c b/dwm.c -index b0b3466..eb478a5 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -141,6 +141,11 @@ typedef struct { - int monitor; - } Rule; - -+typedef struct { -+ const char *cmd; -+ int id; -+} StatusCmd; -+ - /* function declarations */ - static void applyrules(Client *c); - static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); -@@ -238,6 +243,9 @@ static void zoom(const Arg *arg); - /* variables */ - static const char broken[] = "broken"; - static char stext[256]; -+static int statusw; -+static int statuscmdn; -+static char lastbutton[] = "-"; - static int screen; - static int sw, sh; /* X display screen geometry width, height */ - static int bh, blw = 0; /* bar geometry */ -@@ -440,8 +448,27 @@ buttonpress(XEvent *e) - arg.ui = 1 << i; - } else if (ev->x < x + blw) - click = ClkLtSymbol; -- else if (ev->x > selmon->ww - (int)TEXTW(stext)) -+ else if (ev->x > selmon->ww - statusw) { -+ char *text, *s, ch; -+ *lastbutton = '0' + ev->button; -+ -+ x = selmon->ww - statusw; - click = ClkStatusText; -+ -+ statuscmdn = 0; -+ for (text = s = stext; *s && x <= ev->x; s++) { -+ if ((unsigned char)(*s) < ' ') { -+ ch = *s; -+ *s = '\0'; -+ x += TEXTW(text) - lrpad; -+ *s = ch; -+ text = s + 1; -+ if (x >= ev->x) -+ break; -+ statuscmdn = ch; -+ } -+ } -+ } - else - click = ClkWinTitle; - } else if ((c = wintoclient(ev->window))) { -@@ -704,9 +731,24 @@ drawbar(Monitor *m) - - /* draw status first so it can be overdrawn by tags later */ - if (m == selmon) { /* status is only drawn on selected monitor */ -+ char *text, *s, ch; - drw_setscheme(drw, scheme[SchemeNorm]); -- tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ -- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); -+ -+ x = 0; -+ for (text = s = stext; *s; s++) { -+ if ((unsigned char)(*s) < ' ') { -+ ch = *s; -+ *s = '\0'; -+ tw = TEXTW(text) - lrpad; -+ drw_text(drw, m->ww - statusw + x, 0, tw, bh, 0, text, 0); -+ x += tw; -+ *s = ch; -+ text = s + 1; -+ } -+ } -+ tw = TEXTW(text) - lrpad + 2; -+ drw_text(drw, m->ww - statusw + x, 0, tw, bh, 0, text, 0); -+ tw = statusw; - } - - for (c = m->clients; c; c = c->next) { -@@ -1645,6 +1687,17 @@ spawn(const Arg *arg) - if (fork() == 0) { - if (dpy) - close(ConnectionNumber(dpy)); -+ if (arg->v == statuscmd) { -+ for (int i = 0; i < LENGTH(statuscmds); i++) { -+ if (statuscmdn == statuscmds[i].id) { -+ statuscmd[2] = statuscmds[i].cmd; -+ setenv("BUTTON", lastbutton, 1); -+ break; -+ } -+ } -+ if (!statuscmd[2]) -+ exit(EXIT_SUCCESS); -+ } - setsid(); - execvp(((char **)arg->v)[0], (char **)arg->v); - fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]); -@@ -1990,8 +2043,23 @@ updatesizehints(Client *c) - void - updatestatus(void) - { -- if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) -+ if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) { - strcpy(stext, "dwm-"VERSION); -+ statusw = TEXTW(stext) - lrpad + 2; -+ } else { -+ char *text, *s, ch; -+ statusw = 0; -+ for (text = s = stext; *s; s++) { -+ if ((unsigned char)(*s) < ' ') { -+ ch = *s; -+ *s = '\0'; -+ statusw += TEXTW(text) - lrpad; -+ *s = ch; -+ text = s + 1; -+ } -+ } -+ statusw += TEXTW(text) - lrpad + 2; -+ } - drawbar(selmon); - } - --- -2.31.0 - diff --git a/dwm/patches/dwm-swallow-6.3.diff b/dwm/patches/dwm-swallow-6.3.diff deleted file mode 100644 index 47586a0..0000000 --- a/dwm/patches/dwm-swallow-6.3.diff +++ /dev/null @@ -1,412 +0,0 @@ -From 0cf9a007511f7dfd7dd94171b172562ebac9b6d5 Mon Sep 17 00:00:00 2001 -From: Tom Schwindl -Date: Sat, 10 Sep 2022 12:51:09 +0200 -Subject: [PATCH] 6.3 swallow patch - ---- - config.def.h | 9 +- - config.mk | 3 +- - dwm.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++-- - 3 files changed, 237 insertions(+), 10 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 061ad662f82a..0b2b8ffd30d5 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -3,6 +3,7 @@ - /* appearance */ - static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ -+static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ - static const int showbar = 1; /* 0 means no bar */ - static const int topbar = 1; /* 0 means bottom bar */ - static const char *fonts[] = { "monospace:size=10" }; -@@ -26,9 +27,11 @@ static const Rule rules[] = { - * 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 }, -+ /* class instance title tags mask isfloating isterminal noswallow monitor */ -+ { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 }, -+ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 }, -+ { "St", NULL, NULL, 0, 0, 1, 0, -1 }, -+ { NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */ - }; - - /* layout(s) */ -diff --git a/config.mk b/config.mk -index 81c493ef4aff..52d1ebf30bec 100644 ---- a/config.mk -+++ b/config.mk -@@ -20,10 +20,11 @@ FREETYPEINC = /usr/include/freetype2 - # OpenBSD (uncomment) - #FREETYPEINC = ${X11INC}/freetype2 - #MANPREFIX = ${PREFIX}/man -+#KVMLIB = -lkvm - - # includes and libs - INCS = -I${X11INC} -I${FREETYPEINC} --LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -+LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB} - - # flags - CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -diff --git a/dwm.c b/dwm.c -index e5efb6a22806..e68294b6b679 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -40,6 +40,12 @@ - #include - #endif /* XINERAMA */ - #include -+#include -+#include -+#ifdef __OpenBSD__ -+#include -+#include -+#endif /* __OpenBSD */ - - #include "drw.h" - #include "util.h" -@@ -92,9 +98,11 @@ struct Client { - int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; - int bw, oldbw; - unsigned int tags; -- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; -+ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow; -+ pid_t pid; - Client *next; - Client *snext; -+ Client *swallowing; - Monitor *mon; - Window win; - }; -@@ -138,6 +146,8 @@ typedef struct { - const char *title; - unsigned int tags; - int isfloating; -+ int isterminal; -+ int noswallow; - int monitor; - } Rule; - -@@ -235,6 +245,12 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee); - static int xerrorstart(Display *dpy, XErrorEvent *ee); - static void zoom(const Arg *arg); - -+static pid_t getparentprocess(pid_t p); -+static int isdescprocess(pid_t p, pid_t c); -+static Client *swallowingclient(Window w); -+static Client *termforwin(const Client *c); -+static pid_t winpid(Window w); -+ - /* variables */ - static const char broken[] = "broken"; - static char stext[256]; -@@ -269,6 +285,8 @@ static Drw *drw; - static Monitor *mons, *selmon; - static Window root, wmcheckwin; - -+static xcb_connection_t *xcon; -+ - /* configuration, allows nested code to access above variables */ - #include "config.h" - -@@ -298,6 +316,8 @@ applyrules(Client *c) - && (!r->class || strstr(class, r->class)) - && (!r->instance || strstr(instance, r->instance))) - { -+ c->isterminal = r->isterminal; -+ c->noswallow = r->noswallow; - c->isfloating = r->isfloating; - c->tags |= r->tags; - for (m = mons; m && m->num != r->monitor; m = m->next); -@@ -416,6 +436,53 @@ attachstack(Client *c) - c->mon->stack = c; - } - -+void -+swallow(Client *p, Client *c) -+{ -+ -+ if (c->noswallow || c->isterminal) -+ return; -+ if (c->noswallow && !swallowfloating && c->isfloating) -+ return; -+ -+ detach(c); -+ detachstack(c); -+ -+ setclientstate(c, WithdrawnState); -+ XUnmapWindow(dpy, p->win); -+ -+ p->swallowing = c; -+ c->mon = p->mon; -+ -+ Window w = p->win; -+ p->win = c->win; -+ c->win = w; -+ updatetitle(p); -+ XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h); -+ arrange(p->mon); -+ configure(p); -+ updateclientlist(); -+} -+ -+void -+unswallow(Client *c) -+{ -+ c->win = c->swallowing->win; -+ -+ free(c->swallowing); -+ c->swallowing = NULL; -+ -+ /* unfullscreen the client */ -+ setfullscreen(c, 0); -+ updatetitle(c); -+ arrange(c->mon); -+ XMapWindow(dpy, c->win); -+ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); -+ setclientstate(c, NormalState); -+ focus(NULL); -+ arrange(c->mon); -+} -+ - void - buttonpress(XEvent *e) - { -@@ -656,6 +723,9 @@ destroynotify(XEvent *e) - - if ((c = wintoclient(ev->window))) - unmanage(c, 1); -+ -+ else if ((c = swallowingclient(ev->window))) -+ unmanage(c->swallowing, 1); - } - - void -@@ -1022,12 +1092,13 @@ killclient(const Arg *arg) - void - manage(Window w, XWindowAttributes *wa) - { -- Client *c, *t = NULL; -+ Client *c, *t = NULL, *term = NULL; - Window trans = None; - XWindowChanges wc; - - c = ecalloc(1, sizeof(Client)); - c->win = w; -+ c->pid = winpid(w); - /* geometry */ - c->x = c->oldx = wa->x; - c->y = c->oldy = wa->y; -@@ -1042,6 +1113,7 @@ manage(Window w, XWindowAttributes *wa) - } else { - c->mon = selmon; - applyrules(c); -+ term = termforwin(c); - } - - if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) -@@ -1076,6 +1148,8 @@ manage(Window w, XWindowAttributes *wa) - c->mon->sel = c; - arrange(c->mon); - XMapWindow(dpy, c->win); -+ if (term) -+ swallow(term, c); - focus(NULL); - } - -@@ -1763,6 +1837,20 @@ unmanage(Client *c, int destroyed) - Monitor *m = c->mon; - XWindowChanges wc; - -+ if (c->swallowing) { -+ unswallow(c); -+ return; -+ } -+ -+ Client *s = swallowingclient(c->win); -+ if (s) { -+ free(s->swallowing); -+ s->swallowing = NULL; -+ arrange(m); -+ focus(NULL); -+ return; -+ } -+ - detach(c); - detachstack(c); - if (!destroyed) { -@@ -1778,9 +1866,12 @@ unmanage(Client *c, int destroyed) - XUngrabServer(dpy); - } - free(c); -- focus(NULL); -- updateclientlist(); -- arrange(m); -+ -+ if (!s) { -+ arrange(m); -+ focus(NULL); -+ updateclientlist(); -+ } - } - - void -@@ -2044,6 +2135,136 @@ view(const Arg *arg) - arrange(selmon); - } - -+pid_t -+winpid(Window w) -+{ -+ -+ pid_t result = 0; -+ -+#ifdef __linux__ -+ xcb_res_client_id_spec_t spec = {0}; -+ spec.client = w; -+ spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; -+ -+ xcb_generic_error_t *e = NULL; -+ xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); -+ xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); -+ -+ if (!r) -+ return (pid_t)0; -+ -+ xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); -+ for (; i.rem; xcb_res_client_id_value_next(&i)) { -+ spec = i.data->spec; -+ if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { -+ uint32_t *t = xcb_res_client_id_value_value(i.data); -+ result = *t; -+ break; -+ } -+ } -+ -+ free(r); -+ -+ if (result == (pid_t)-1) -+ result = 0; -+ -+#endif /* __linux__ */ -+ -+#ifdef __OpenBSD__ -+ Atom type; -+ int format; -+ unsigned long len, bytes; -+ unsigned char *prop; -+ pid_t ret; -+ -+ if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 0), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop) -+ return 0; -+ -+ ret = *(pid_t*)prop; -+ XFree(prop); -+ result = ret; -+ -+#endif /* __OpenBSD__ */ -+ return result; -+} -+ -+pid_t -+getparentprocess(pid_t p) -+{ -+ unsigned int v = 0; -+ -+#ifdef __linux__ -+ FILE *f; -+ char buf[256]; -+ snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); -+ -+ if (!(f = fopen(buf, "r"))) -+ return 0; -+ -+ fscanf(f, "%*u %*s %*c %u", &v); -+ fclose(f); -+#endif /* __linux__*/ -+ -+#ifdef __OpenBSD__ -+ int n; -+ kvm_t *kd; -+ struct kinfo_proc *kp; -+ -+ kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL); -+ if (!kd) -+ return 0; -+ -+ kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n); -+ v = kp->p_ppid; -+#endif /* __OpenBSD__ */ -+ -+ return (pid_t)v; -+} -+ -+int -+isdescprocess(pid_t p, pid_t c) -+{ -+ while (p != c && c != 0) -+ c = getparentprocess(c); -+ -+ return (int)c; -+} -+ -+Client * -+termforwin(const Client *w) -+{ -+ Client *c; -+ Monitor *m; -+ -+ if (!w->pid || w->isterminal) -+ return NULL; -+ -+ for (m = mons; m; m = m->next) { -+ for (c = m->clients; c; c = c->next) { -+ if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) -+ return c; -+ } -+ } -+ -+ return NULL; -+} -+ -+Client * -+swallowingclient(Window w) -+{ -+ Client *c; -+ Monitor *m; -+ -+ for (m = mons; m; m = m->next) { -+ for (c = m->clients; c; c = c->next) { -+ if (c->swallowing && c->swallowing->win == w) -+ return c; -+ } -+ } -+ -+ return NULL; -+} -+ - Client * - wintoclient(Window w) - { -@@ -2133,10 +2354,12 @@ main(int argc, char *argv[]) - fputs("warning: no locale support\n", stderr); - if (!(dpy = XOpenDisplay(NULL))) - die("dwm: cannot open display"); -+ if (!(xcon = XGetXCBConnection(dpy))) -+ die("dwm: cannot get xcb connection\n"); - checkotherwm(); - setup(); - #ifdef __OpenBSD__ -- if (pledge("stdio rpath proc exec", NULL) == -1) -+ if (pledge("stdio rpath proc exec ps", NULL) == -1) - die("pledge"); - #endif /* __OpenBSD__ */ - scan(); --- -2.37.2 - diff --git a/sistema/etc/elogind/logind.conf.d/10-acpid.conf b/sistema/etc/elogind/logind.conf.d/10-acpid.conf deleted file mode 100644 index 6ea7964..0000000 --- a/sistema/etc/elogind/logind.conf.d/10-acpid.conf +++ /dev/null @@ -1,11 +0,0 @@ -# acpid ya se encarga de la tapa y del botón de suspender (llama a zzz) y del -# botón de encendido. Si elogind también reacciona, el portátil se suspende -# dos veces: al abrir la tapa se enciende, se vuelve a suspender y luego -# arranca. Así solo lo gestiona acpid. -[Login] -HandlePowerKey=ignore -HandleSuspendKey=ignore -HandleHibernateKey=ignore -HandleLidSwitch=ignore -HandleLidSwitchExternalPower=ignore -HandleLidSwitchDocked=ignore diff --git a/sistema/etc/zzz.d/suspend/10-slock b/sistema/etc/zzz.d/suspend/10-slock deleted file mode 100755 index e1cdc82..0000000 --- a/sistema/etc/zzz.d/suspend/10-slock +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh -# Bloquear con slock ANTES de suspender, para que al volver no se vea el -# escritorio. zzz ejecuta este hook como root; slock se lanza como el -# usuario de la sesión de dwm, con su DISPLAY y XAUTHORITY. - -pgrep -x slock >/dev/null && exit 0 - -pid=$(pgrep -xo dwm) || exit 0 -user=$(getent passwd "$(stat -c %u "/proc/$pid")" | cut -d: -f1) -env=$(tr '\0' '\n' <"/proc/$pid/environ" | grep -E '^(DISPLAY|XAUTHORITY)=') -[ -n "$user" ] && [ -n "$env" ] || exit 0 - -env $env setsid chpst -u "$user" /usr/local/bin/slock >/dev/null 2>&1 & - -# Esperar a que slock arranque y tape la pantalla (máximo 2 s) antes de -# dejar que zzz siga con la suspensión. -i=0 -while ! pgrep -x slock >/dev/null && [ "$i" -lt 20 ]; do - sleep 0.1 - i=$((i + 1)) -done -sleep 0.5 diff --git a/slock/config.def.h b/slock/config.def.h index b51b48c..9855e21 100644 --- a/slock/config.def.h +++ b/slock/config.def.h @@ -8,21 +8,5 @@ static const char *colorname[NUMCOLS] = { [FAILED] = "#CC3333", /* wrong password */ }; -/* lock screen */ -static const char *bgcolor = "black"; -static const char *fgcolor = "#eeeeee"; -static const char *dimcolor = "#888888"; - -static const char *clockfont = "monospace:bold:pixelsize=160"; -static const char *datefont = "monospace:pixelsize=34"; -static const char *textfont = "monospace:pixelsize=22"; -static const char *iconfont = "Symbols Nerd Font Mono:pixelsize=24"; - -static const int barheight = 10; /* height of the bottom bar */ -static const unsigned int maxdots = 24; /* max dots shown while typing */ - -static const char *battery = "BAT0"; /* /sys/class/power_supply/... */ -static const int batterylow = 20; /* percent shown as low */ - /* treat a cleared input like a wrong password (color) */ static const int failonclear = 1; diff --git a/slock/config.h b/slock/config.h index d2bc65a..fd5a3b0 100644 --- a/slock/config.h +++ b/slock/config.h @@ -2,28 +2,11 @@ static const char *user = "nobody"; static const char *group = "nogroup"; -/* colores de la barra inferior según el estado */ static const char *colorname[NUMCOLS] = { - [INIT] = "#475258", /* after initialization (gris Everforest) */ + [INIT] = "#2d353b", /* after initialization (fondo Everforest) */ [INPUT] = "#a7c080", /* during input (verde acento) */ [FAILED] = "#e67e80", /* wrong password (rojo Everforest) */ }; -/* pantalla de bloqueo (paleta Everforest) */ -static const char *bgcolor = "#2d353b"; /* fondo */ -static const char *fgcolor = "#d3c6aa"; /* reloj y texto */ -static const char *dimcolor = "#859289"; /* fecha y avisos */ - -static const char *clockfont = "Fira Code:style=Bold:pixelsize=160:antialias=true"; -static const char *datefont = "Fira Code:pixelsize=34:antialias=true"; -static const char *textfont = "Fira Code:pixelsize=22:antialias=true"; -static const char *iconfont = "Symbols Nerd Font Mono:pixelsize=24:antialias=true"; - -static const int barheight = 10; /* alto de la barra inferior */ -static const unsigned int maxdots = 24; /* puntos máximos al teclear */ - -static const char *battery = "BAT1"; /* /sys/class/power_supply/... */ -static const int batterylow = 20; /* % para mostrarla en rojo */ - /* treat a cleared input like a wrong password (color) */ static const int failonclear = 1; diff --git a/slock/config.mk b/slock/config.mk index 3e12e2a..9fe5bff 100644 --- a/slock/config.mk +++ b/slock/config.mk @@ -11,8 +11,8 @@ X11INC = /usr/X11R6/include X11LIB = /usr/X11R6/lib # includes and libs -INCS = -I. -I/usr/include -I${X11INC} -I/usr/include/freetype2 -LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr -lXft -lfontconfig +INCS = -I. -I/usr/include -I${X11INC} +LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr # flags CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H @@ -21,7 +21,7 @@ LDFLAGS = -s ${LIBS} COMPATSRC = explicit_bzero.c # On OpenBSD and Darwin remove -lcrypt from LIBS -#LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lXext -lXrandr -lXft -lfontconfig +#LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lXext -lXrandr # On *BSD remove -DHAVE_SHADOW_H from CPPFLAGS # On NetBSD add -D_NETBSD_SOURCE to CPPFLAGS #CPPFLAGS = -DVERSION=\"${VERSION}\" -D_BSD_SOURCE -D_NETBSD_SOURCE diff --git a/slock/slock.c b/slock/slock.c index 6aa996c..9c587e1 100644 --- a/slock/slock.c +++ b/slock/slock.c @@ -12,15 +12,12 @@ #include #include #include -#include #include -#include #include #include #include #include #include -#include #include "util.h" @@ -33,40 +30,13 @@ enum { NUMCOLS }; -enum { - COLBG, - COLFG, - COLDIM, - COLCHARGE, - COLLOW, - NUMUICOLS -}; - struct lock { int screen; Window root, win; Pixmap pmap; unsigned long colors[NUMCOLS]; - /* dibujado: doble búfer del tamaño de la pantalla */ - int w, h; - Pixmap buf; - XftDraw *draw; - XftColor bar[NUMCOLS]; - XftColor ui[NUMUICOLS]; - XftFont *fclock, *fdate, *ftext, *ficon; }; -/* estado que se muestra en la pantalla de bloqueo */ -struct state { - unsigned int len; /* caracteres tecleados */ - int color; /* INIT, INPUT o FAILED */ - int failure; /* ha habido una contraseña incorrecta */ - char clock[16], date[64], bat[16]; - int batlevel, charging; -}; - -static char username[64]; - struct xrandr { int active; int evbase; @@ -153,296 +123,23 @@ gethash(void) return hash; } -static XftFont * -loadfont(Display *dpy, int screen, const char *name) -{ - XftFont *f; - - if (!(f = XftFontOpenName(dpy, screen, name)) && - !(f = XftFontOpenName(dpy, screen, "monospace"))) - die("slock: cannot load font %s\n", name); - return f; -} - -static void -setupdraw(Display *dpy, struct lock *lock) -{ - Visual *vis = DefaultVisual(dpy, lock->screen); - Colormap cmap = DefaultColormap(dpy, lock->screen); - const char *uinames[NUMUICOLS] = { - [COLBG] = bgcolor, [COLFG] = fgcolor, [COLDIM] = dimcolor, - [COLCHARGE] = colorname[INPUT], [COLLOW] = colorname[FAILED], - }; - int i; - - for (i = 0; i < NUMCOLS; i++) - if (!XftColorAllocName(dpy, vis, cmap, colorname[i], &lock->bar[i])) - die("slock: cannot allocate color %s\n", colorname[i]); - for (i = 0; i < NUMUICOLS; i++) - if (!XftColorAllocName(dpy, vis, cmap, uinames[i], &lock->ui[i])) - die("slock: cannot allocate color %s\n", uinames[i]); - - lock->fclock = loadfont(dpy, lock->screen, clockfont); - lock->fdate = loadfont(dpy, lock->screen, datefont); - lock->ftext = loadfont(dpy, lock->screen, textfont); - lock->ficon = loadfont(dpy, lock->screen, iconfont); - - lock->w = DisplayWidth(dpy, lock->screen); - lock->h = DisplayHeight(dpy, lock->screen); - lock->buf = XCreatePixmap(dpy, lock->root, lock->w, lock->h, - DefaultDepth(dpy, lock->screen)); - lock->draw = XftDrawCreate(dpy, lock->buf, vis, cmap); -} - -static void -resizedraw(Display *dpy, struct lock *lock, int w, int h) -{ - if (w == lock->w && h == lock->h) - return; - lock->w = w; - lock->h = h; - XFreePixmap(dpy, lock->buf); - lock->buf = XCreatePixmap(dpy, lock->root, w, h, - DefaultDepth(dpy, lock->screen)); - XftDrawChange(lock->draw, lock->buf); -} - -static int -textw(Display *dpy, XftFont *f, const char *s) -{ - XGlyphInfo ext; - - XftTextExtentsUtf8(dpy, f, (const FcChar8 *)s, strlen(s), &ext); - return ext.xOff; -} - -static int -iconw(Display *dpy, XftFont *f, FcChar32 icon) -{ - XGlyphInfo ext; - - if (!icon || !XftCharExists(dpy, f, icon)) - return 0; - XftTextExtents32(dpy, f, &icon, 1, &ext); - return ext.xOff; -} - -/* icono (opcional) + separación + texto, con la línea base en y */ -static int -drawlabel(Display *dpy, struct lock *lock, XftFont *f, XftColor *c, - int x, int y, FcChar32 icon, const char *s) -{ - int iw = iconw(dpy, lock->ficon, icon), gap = iw ? f->height / 2 : 0; - - if (iw) - XftDrawString32(lock->draw, c, lock->ficon, x, y, &icon, 1); - XftDrawStringUtf8(lock->draw, c, f, x + iw + gap, y, - (const FcChar8 *)s, strlen(s)); - return iw + gap + textw(dpy, f, s); -} - -static int -labelw(Display *dpy, struct lock *lock, XftFont *f, FcChar32 icon, - const char *s) -{ - int iw = iconw(dpy, lock->ficon, icon); - - return iw + (iw ? f->height / 2 : 0) + textw(dpy, f, s); -} - -/* Actualiza hora, fecha y batería. Devuelve 1 si algo ha cambiado. */ -static int -updatestate(struct state *st) -{ - static const char *wdays[] = { "domingo", "lunes", "martes", - "miércoles", "jueves", "viernes", "sábado" }; - static const char *months[] = { "enero", "febrero", "marzo", "abril", - "mayo", "junio", "julio", "agosto", "septiembre", "octubre", - "noviembre", "diciembre" }; - char clk[sizeof(st->clock)], date[sizeof(st->date)], bat[sizeof(st->bat)]; - char path[128], status[32] = ""; - int level = -1, charging = 0, changed; - time_t t = time(NULL); - struct tm *tm = localtime(&t); - FILE *f; - - strftime(clk, sizeof(clk), "%H:%M", tm); - snprintf(date, sizeof(date), "%s, %d de %s", wdays[tm->tm_wday], - tm->tm_mday, months[tm->tm_mon]); - date[0] = toupper((unsigned char)date[0]); - - snprintf(path, sizeof(path), "/sys/class/power_supply/%s/capacity", - battery); - if ((f = fopen(path, "r"))) { - if (fscanf(f, "%d", &level) != 1) - level = -1; - fclose(f); - } - snprintf(path, sizeof(path), "/sys/class/power_supply/%s/status", - battery); - if ((f = fopen(path, "r"))) { - if (fscanf(f, "%31s", status) != 1) - status[0] = '\0'; - fclose(f); - } - charging = !strcmp(status, "Charging") || !strcmp(status, "Full"); - if (level >= 0) - snprintf(bat, sizeof(bat), "%d%%", level); - else - bat[0] = '\0'; - - changed = strcmp(clk, st->clock) || strcmp(date, st->date) || - strcmp(bat, st->bat) || charging != st->charging; - memcpy(st->clock, clk, sizeof(clk)); - memcpy(st->date, date, sizeof(date)); - memcpy(st->bat, bat, sizeof(bat)); - st->batlevel = level; - st->charging = charging; - return changed; -} - -/* Símbolos de Nerd Font (Material Design) */ -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -#define ICON_LOCK 0xF033E -#define ICON_ALERT 0xF0026 -#define ICON_USER 0xF0004 -#define ICON_CHARGING 0xF0084 -#define ICON_BAT10 0xF007A /* 10 % .. 90 % seguidos; 100 % es 0xF0079 */ -#define ICON_BAT100 0xF0079 - -static FcChar32 -baticon(const struct state *st) -{ - if (st->charging) - return ICON_CHARGING; - if (st->batlevel >= 95) - return ICON_BAT100; - if (st->batlevel < 10) - return ICON_ALERT; - return ICON_BAT10 + st->batlevel / 10 - 1; -} - -/* Dibuja la pantalla de bloqueo en el rectángulo de un monitor */ -static void -drawmon(Display *dpy, struct lock *lock, const struct state *st, - int mx, int my, int mw, int mh) -{ - XftColor *fg = &lock->ui[COLFG], *dim = &lock->ui[COLDIM], *msgc; - char msg[128]; - FcChar32 icon = 0; - int x, y, w, pad = mh / 24, low; - unsigned int i, n; - - /* reloj y fecha, algo por encima del centro */ - y = my + mh * 2 / 5; - x = mx + (mw - textw(dpy, lock->fclock, st->clock)) / 2; - XftDrawStringUtf8(lock->draw, fg, lock->fclock, x, y, - (const FcChar8 *)st->clock, strlen(st->clock)); - y += lock->fdate->height * 3 / 2; - x = mx + (mw - textw(dpy, lock->fdate, st->date)) / 2; - XftDrawStringUtf8(lock->draw, dim, lock->fdate, x, y, - (const FcChar8 *)st->date, strlen(st->date)); - - /* mensaje de estado: indicación, puntos o error */ - msgc = dim; - if (st->color == INPUT) { - n = MIN(st->len, maxdots); - for (i = 0, msg[0] = '\0'; i < n; i++) - strcat(msg, i ? " ●" : "●"); - msgc = &lock->bar[INPUT]; - } else if (st->color == FAILED && st->failure) { - icon = ICON_ALERT; - snprintf(msg, sizeof(msg), "Contraseña incorrecta"); - msgc = &lock->bar[FAILED]; - } else { - icon = ICON_LOCK; - snprintf(msg, sizeof(msg), "Escribe la contraseña"); - } - y = my + mh * 3 / 5 + lock->ftext->ascent; - x = mx + (mw - labelw(dpy, lock, lock->ftext, icon, msg)) / 2; - drawlabel(dpy, lock, lock->ftext, msgc, x, y, icon, msg); - - /* abajo: usuario a la izquierda, batería a la derecha */ - y = my + mh - barheight - pad; - drawlabel(dpy, lock, lock->ftext, dim, mx + pad, y, ICON_USER, username); - if (st->bat[0]) { - low = !st->charging && st->batlevel <= batterylow; - w = labelw(dpy, lock, lock->ftext, baticon(st), st->bat); - drawlabel(dpy, lock, lock->ftext, - low ? &lock->ui[COLLOW] : - st->charging ? &lock->ui[COLCHARGE] : fg, - mx + mw - pad - w, y, baticon(st), st->bat); - } - - /* barra con el color del estado */ - XftDrawRect(lock->draw, &lock->bar[st->color], mx, my + mh - barheight, - mw, barheight); -} - -static void -drawlock(Display *dpy, struct lock *lock, const struct state *st) -{ - XRRMonitorInfo *mons; - int i, n = 0; - - XftDrawRect(lock->draw, &lock->ui[COLBG], 0, 0, lock->w, lock->h); - mons = XRRGetMonitors(dpy, lock->root, True, &n); - for (i = 0; i < n; i++) - drawmon(dpy, lock, st, mons[i].x, mons[i].y, - mons[i].width, mons[i].height); - if (mons) - XRRFreeMonitors(mons); - if (n <= 0) - drawmon(dpy, lock, st, 0, 0, lock->w, lock->h); - XCopyArea(dpy, lock->buf, lock->win, DefaultGC(dpy, lock->screen), - 0, 0, lock->w, lock->h, 0, 0); -} - -static void -drawall(Display *dpy, struct lock **locks, int nscreens, - const struct state *st) -{ - int screen; - - for (screen = 0; screen < nscreens; screen++) - drawlock(dpy, locks[screen], st); - XFlush(dpy); -} - static void readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, const char *hash) { XRRScreenChangeNotifyEvent *rre; char buf[32], passwd[256], *inputhash; - int num, screen, running, xfd; - struct state st = { 0 }; - struct timeval tv; + int num, screen, running, failure, oldc; + unsigned int len, color; KeySym ksym; XEvent ev; - fd_set fds; + len = 0; running = 1; - st.color = INIT; - xfd = ConnectionNumber(dpy); - updatestate(&st); - drawall(dpy, locks, nscreens, &st); + failure = 0; + oldc = INIT; - while (running) { - /* sin eventos pendientes: esperar como mucho 1 s y refrescar - * reloj y batería si han cambiado (también tras suspender) */ - if (!XPending(dpy)) { - FD_ZERO(&fds); - FD_SET(xfd, &fds); - tv.tv_sec = 1; - tv.tv_usec = 0; - if (select(xfd + 1, &fds, NULL, NULL, &tv) <= 0 && - updatestate(&st)) - drawall(dpy, locks, nscreens, &st); - continue; - } - XNextEvent(dpy, &ev); + while (running && !XNextEvent(dpy, &ev)) { if (ev.type == KeyPress) { explicit_bzero(&buf, sizeof(buf)); num = XLookupString(&ev.xkey, buf, sizeof(buf), &ksym, 0); @@ -460,7 +157,7 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, continue; switch (ksym) { case XK_Return: - passwd[st.len] = '\0'; + passwd[len] = '\0'; errno = 0; if (!(inputhash = crypt(passwd, hash))) fprintf(stderr, "slock: crypt: %s\n", strerror(errno)); @@ -468,56 +165,52 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, running = !!strcmp(inputhash, hash); if (running) { XBell(dpy, 100); - st.failure = 1; + failure = 1; } explicit_bzero(&passwd, sizeof(passwd)); - st.len = 0; + len = 0; break; case XK_Escape: explicit_bzero(&passwd, sizeof(passwd)); - st.len = 0; + len = 0; break; case XK_BackSpace: - if (st.len) - passwd[--st.len] = '\0'; + if (len) + passwd[--len] = '\0'; break; default: if (num && !iscntrl((unsigned char)buf[0]) && - (st.len + num < sizeof(passwd))) { - memcpy(passwd + st.len, buf, num); - st.len += num; + (len + num < sizeof(passwd))) { + memcpy(passwd + len, buf, num); + len += num; } else if (buf[0] == '\025') { /* ctrl-u clears input */ explicit_bzero(&passwd, sizeof(passwd)); - st.len = 0; + len = 0; } break; } - st.color = st.len ? INPUT : - ((st.failure || failonclear) ? FAILED : INIT); - if (running) { - updatestate(&st); - drawall(dpy, locks, nscreens, &st); + 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 (ev.type == Expose) { - if (ev.xexpose.count == 0) - drawall(dpy, locks, nscreens, &st); } else if (rr->active && ev.type == rr->evbase + RRScreenChangeNotify) { rre = (XRRScreenChangeNotifyEvent*)&ev; for (screen = 0; screen < nscreens; screen++) { if (locks[screen]->win == rre->window) { if (rre->rotation == RR_Rotate_90 || - rre->rotation == RR_Rotate_270) { + rre->rotation == RR_Rotate_270) XResizeWindow(dpy, locks[screen]->win, rre->height, rre->width); - resizedraw(dpy, locks[screen], - rre->height, rre->width); - } else { + else XResizeWindow(dpy, locks[screen]->win, rre->width, rre->height); - resizedraw(dpy, locks[screen], - rre->width, rre->height); - } - drawlock(dpy, locks[screen], &st); + XClearWindow(dpy, locks[screen]->win); break; } } @@ -550,20 +243,16 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) lock->colors[i] = color.pixel; } - setupdraw(dpy, lock); - /* init */ wa.override_redirect = 1; - wa.background_pixel = lock->ui[COLBG].pixel; - wa.event_mask = ExposureMask; + 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 | CWEventMask, - &wa); + CWOverrideRedirect | CWBackPixel, &wa); lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8); invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, &color, &color, 0, 0); @@ -651,10 +340,6 @@ main(int argc, char **argv) { dontkillme(); #endif - /* nombre del usuario que bloquea, para mostrarlo */ - if ((pwd = getpwuid(getuid()))) - snprintf(username, sizeof(username), "%s", pwd->pw_name); - hash = gethash(); errno = 0; if (!crypt("", hash)) diff --git a/slstatus/config.h b/slstatus/config.h index 66018ae..a2ab6f3 100644 --- a/slstatus/config.h +++ b/slstatus/config.h @@ -1,7 +1,7 @@ /* See LICENSE file for copyright and license details. */ /* interval between updates (in ms) */ -const unsigned int interval = 2000; +const unsigned int interval = 1000; /* text to show if no value can be retrieved */ static const char unknown_str[] = "N/A"; @@ -21,39 +21,18 @@ static const char unknown_str[] = "N/A"; * run_command output of a shell command command * wifi_essid WiFi network name interface name (wlan0) */ -/* - * Red sin lanzar procesos: ETH si hay cable en enp3s0; si no, la red WiFi de - * wlp4s0 (se lee por netlink con el componente wifi_essid de slstatus). - */ -static const char * -red(const char *unused) -{ - const char *s; - - if ((s = cat("/sys/class/net/enp3s0/operstate")) && !strcmp(s, "up")) - return "ETH"; - if (!(s = wifi_essid("wlp4s0"))) - return "WiFi: N/A"; - return bprintf("WiFi: %s", s); -} - -/* - * Los bytes \001, \002 y \003 delimitan las zonas clicables de la barra - * (parche statuscmd de dwm): la red, el volumen y el bluetooth. Lo que hace - * cada clic está en statuscmds, en el config.h de dwm. - */ static const struct arg args[] = { - /* function format argument */ - { cpu_perc, "[ CPU: %s%% ] ", NULL }, - { ram_perc, "[ RAM: %s%% ] ", NULL }, - { red, "\001[ %s ]\001 ", NULL }, - { battery_perc, "[ BAT: %s%%", "BAT1" }, - { battery_state, " %s ] ", "BAT1" }, + /* function format argument */ + { cpu_perc, "[ CPU: %s%% ] ", NULL }, + { ram_perc, "[ RAM: %s%% ] ", NULL }, + /* ETH si hay cable en enp3s0; si no, la red WiFi de wlp4s0 */ + { run_command, "[ %s ] ", "if [ \"$(cat /sys/class/net/enp3s0/operstate)\" = up ]; then echo ETH; " + "else s=$(iw dev wlp4s0 link | sed -n 's/^[[:space:]]*SSID: //p'); echo \"WiFi: ${s:-N/A}\"; fi" }, + { battery_perc, "[ BAT: %s%%", "BAT1" }, + { battery_state, " %s ] ", "BAT1" }, /* mismo volumen que maneja wpctl (PipeWire); MIC OFF si el micro está silenciado */ - { run_command, "\002[ VOL: %s ]\002 ", "wpctl get-volume @DEFAULT_AUDIO_SINK@ | awk '{ printf \"%d%%\", $2 * 100 + 0.5 } /MUTED/ { printf \" MUT\" }'; " - "wpctl get-volume @DEFAULT_AUDIO_SOURCE@ | grep -q MUTED && printf ' MIC OFF'" }, - /* OFF si el adaptador está apagado; si no, el primer dispositivo conectado */ - { run_command, "\003[ BT: %s ]\003 ", "bluetoothctl show | grep -q 'Powered: yes' || { echo OFF; exit; }; " - "bluetoothctl devices Connected | head -1 | cut -d' ' -f3-" }, - { datetime, "[ %s ]", "%d/%m/%y %H:%M" }, + { run_command, "[ VOL: %s ] ", "wpctl get-volume @DEFAULT_AUDIO_SINK@ | awk '{ printf \"%d%%\", $2 * 100 + 0.5 } /MUTED/ { printf \" MUT\" }'; " + "wpctl get-volume @DEFAULT_AUDIO_SOURCE@ | grep -q MUTED && printf ' MIC OFF'" }, + { run_command, "[ BT: %s ] ", "bluetoothctl devices Connected | head -1 | cut -d' ' -f3-" }, + { datetime, "[ %s ]", "%d/%m/%y %H:%M:%S" }, };