INSTALAR Y CONFIGURAR DWM (2)

Y… Vamos a finalizar con el post anterior. Una vez hemos instalado Dwm, hemos entrado en él, y lo hemos dejado un poco a nuestro gusto, vamos con un par de cosillas que lo dejarán más “a nuestro aire”.

EXTENDER DWM CON PARCHES

Una de las cosas que hacen curioso a este WM es el tema de los parches. Pese a que DWM viene un poco pelado de inicio, podemos ampliarlo mediante parches, los cuales compilaremos como parte de la instalación.
No todos funcionan como deberían. Ni todos explican exactamente “cómo” se añaden (Sí, es un WM bastante elitista, es lo que hay) así que a la hora de probar alguno, es posible que no salga bien a la primera (El cambio de 6.0 a 6.1 también influye)..

Yo, personalmente, uso 2: Uno, para que DWM le de un valor de ventana a su panel y otro para separar las ventanas entre si mediante “gaps”, lo cual, aunque un tanto “raro” en un escritorio tiling, le quita una gran parte de claustrofobia.
¿Cómo funcionan los parches? Por un lado, necesitamos añadirlos a dwm.c para especificar las variables, y a al config.h, para determinar la configuración de estas variables.
Para añadirlos, los descargamos en nuestra carpeta de compilación dwm-6.1 y ejecutamos:

patch -p1 < parche_que_nos_hemos_bajado.diff

Aquí dejo el de compton.diff (Lo encontré buscando por foros, gracias a Darkfeline por hacerlo).

https://bbs.archlinux.org/viewtopic.php?pid=1375894#p1375894
pre-patch dwm-6.1

diff –git a/dwm.c b/dwm.c
index ff7e096..21a2684 100644
— a/dwm.c
+++ b/dwm.c
@@ -1806,6 +1806,9 @@ updatebars(void)
.background_pixmap = ParentRelative,
.event_mask = ButtonPressMask|ExposureMask
};
+ XClassHint *ch = XAllocClassHint();
+ ch->res_name = “dwmstatus”;
+ ch->res_class = “dwm”;
for (m = mons; m; m = m->next) {
if (m->barwin)
continue;
@@ -1814,7 +1817,9 @@ updatebars(void)
CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor);
XMapRaised(dpy, m->barwin);
+ XSetClassHint(dpy, m->barwin, ch);
}
+ XFree(ch);
}

void

Para este no es necesario añadir nada al config.h, este parche permite que xprop reconozca el panel como “algo” y podamos excluirlo de compton (Para evitar transparencias no deseadas) mediante el parámetro –focus-exclude ‘class_g = “dwm”‘.

El de uselessgaps.diff, está aquí. Este nos separará un poco las ventanas entre si. Es algo muy a gustos, pero le da un poco de “aire” a nuestro escritorio.

— dwm/dwm.c.orig 2015-11-22 13:26:16.664650238 -0700
+++ dwm/dwm.c 2015-11-22 13:25:57.407984351 -0700
@@ -52,8 +52,8 @@
#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
#define LENGTH(X) (sizeof X / sizeof X[0])
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
-#define WIDTH(X) ((X)->w + 2 * (X)->bw)
-#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
+#define WIDTH(X) ((X)->w + 2 * (X)->bw + gappx)
+#define HEIGHT(X) ((X)->h + 2 * (X)->bw + gappx)
#define TAGMASK ((1 << LENGTH(tags)) – 1) #define TEXTW(X) (drw_text(drw, 0, 0, 0, 0, (X), 0) + drw->fonts[0]->h)

@@ -1293,12 +1293,36 @@ void
resizeclient(Client *c, int x, int y, int w, int h)
{
XWindowChanges wc;
+ unsigned int n;
+ unsigned int gapoffset;
+ unsigned int gapincr;
+ Client *nbc;

– c->oldx = c->x; c->x = wc.x = x;
– c->oldy = c->y; c->y = wc.y = y;
– c->oldw = c->w; c->w = wc.width = w;
– c->oldh = c->h; c->h = wc.height = h;
wc.border_width = c->bw;
+
+ /* Get number of clients for the selected monitor */
+ for (n = 0, nbc = nexttiled(selmon->clients); nbc; nbc = nexttiled(nbc->next), n++);
+
+ /* Do nothing if layout is floating */
+ if (c->isfloating || selmon->lt[selmon->sellt]->arrange == NULL) {
+ gapincr = gapoffset = 0;
+ } else {
+ /* Remove border and gap if layout is monocle or only one client */
+ if (selmon->lt[selmon->sellt]->arrange == monocle || n == 1) {
+ gapoffset = 0;
+ gapincr = -2 * borderpx;
+ wc.border_width = 0;
+ } else {
+ gapoffset = gappx;
+ gapincr = 2 * gappx;
+ }
+ }
+
+ c->oldx = c->x; c->x = wc.x = x + gapoffset;
+ c->oldy = c->y; c->y = wc.y = y + gapoffset;
+ c->oldw = c->w; c->w = wc.width = w – gapincr;
+ c->oldh = c->h; c->h = wc.height = h – gapincr;
+
XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
configure(c);
XSync(dpy, False);

Para éste deberemos añadir a nuestro config.h esta línea y le asignamos el valor que más rabia nos de.

static const unsigned int gappx = 6;

Una vez aplicados ambos parches, compilamos.

AÑADIR UN SYSTRAY

Seguramente echemos de menos algo como un systray para aplicaciones como puede ser el indicador del volumen (Si no usas otros métodos). Existe un parche para aplicar el systray, pero no he conseguido hacerlo andar, por suerte hay algunas opciones. La que yo uso es trayer, un simple panel de systray, y lo puedo hacer aparecer o desaparecer con un comando. Como, a fin de cuentas, sólo lo uso para cosas como Steam y Transmission, si lo necesito, lo ejecuto/cierro mediante un script.

#!/bin/sh

if pidof trayer | grep [0-9] > /dev/null
then
exec killall trayer
else
exec trayer –transparent true –tint 0x000000 –alpha 0 –distance 25 –width 10 –SetDockType true –padding 5 –align right –height 40 –expand true

fi

Lo guardamos como systraytoggle (Por ejemplo) en /usr/bin y le damos permisos de ejecución.

sudo cp systraytoggle /usr/bin
sudo chmod +x /usr/bin/systraytoggle

Una vez hecho esto, podemos añadirle un keybind en nuestro config.h y desactivarlo o activarlo a voluntad.

AMPLIAR EL PANEL CON INFORMACIÓN EXTRA

Esto lo haremos mediante conky. Este programita es un clásico en linux, dándonos mediciones de RAM, CPU, disco, red… Casi todo lo que queramos.
Existen 2 opciones, conky, y conky-cli. Mientras que el primero nos generará una ventana en el escritorio, conky-cli nos sacará la información por consola, cosa necesaria para poder “pipearla” al panel.
Si recordamos, creamos un ejecutable en el anterior post para poder lanzar nuestro entorno de escritorio. Usaremos eso para hacer el pipe.
En cuanto al conky, necesita unas pocas opciones básicas para poder “funcionar”. Para no marear mucho, este es mi .conkyrc:

# Ejecutar sin fondo, solo el texto
background no
# Cada cuando actualiza
update_interval 2
# Cuantas veces queremos que haga la medición, en “0” es siempre
total_run_times 0
use_spacer none
cpu_avg_samples 2

TEXT
CPU ${cpubar 5,10} \
RAM ${membar 5,10} \
$kernel \
${fs_used_perc /home}% Home \
${fs_used_perc /}% Root \
${fs_used_perc /media/almacen}% Alm. \
${mixer}% Vol \
${time %d %B} \
${time %H:%M}

Lo guardamos como /home/usuario/.conkyrc, y acto seguido nos vamos al script de inicio de DWM:

sudo nano /usr/bin/dwm-start

Y añadimos esta línea:

conky | while read -r; do xsetroot -name “$REPLY”; done &

La siguiente vez que recarguemos DWM tendremos un indicador de la fecha, el consumo de RAM, etc justo en nuestro panel.

COMPTON

Aunque toqué un poco compton en este otro post (link) me he decidido a poner la línea que uso (completa) porque fue un ratito largo de pruebas,

sleep 2; compton -cCbGfF -e 0.7 -i 0.7 -I 0.7 -O 0.7 -D 6 –focus-exclude ‘class_g = “mpv”‘ –focus-exclude ‘class_g = “dwm”‘ –inactive-dim 0.3 –focus-exclude ‘_NET_WM_NAME@:s = “rofi”‘ &

Esta encíclica de comando nos dará desvanecimiento al cambiar de escritorio o abrir/cerrar aplicaciones, transparencia en las ventanas inactivas, y evitará que las tenga el panel, rofi (Lo tocaré en otro momento), los menús desplegables, y mpv, para poder ver una pelicula al tiempo que escribo esto, sin que esté semitransparente.
Al igual que conky, lo añadimos al dwm-start.

Y, con esto, creo que ya está. A continuación dejaré mi config.h, para dar ideas.

/* See LICENSE file for copyright and license details. */

/* appearance */
/* Los colores personalizados son #232323, #e1e1e1 y #4f6f94 */
static const char *fonts[] = {
“monospace:size=9”
};
static const char dmenufont[] = “monospace:size=9”;
static const char normbordercolor[] = “#000000”;
static const char normbgcolor[] = “#232323”;
static const char normfgcolor[] = “#e1e1e1”;
static const char selbordercolor[] = “#000000”;
static const char selbgcolor[] = “#e1e1e1”;
static const char selfgcolor[] = “#000000”;
static const unsigned int borderpx = 4; /* border pixel of windows */
static const unsigned int snap = 32; /* snap pixel */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 0; /* 0 means bottom bar */
static const unsigned int gappx = 6;

/* tagging */
static const char *tags[] = { “Base “, “Extra”, “Media”, “Steam”, “Gimp “, “Trans” };

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, 1 << 4, False, -1 },
{ “Steam”, NULL, NULL, 1 << 3, False },
{ “Firefox”, NULL, NULL, 0, False, -1 },
{ “trayer”, NULL, NULL, 0, False },
{ “Galculator”, NULL, NULL, 0, True },
{ “Transmission-gtk”, NULL, NULL, 1 << 5, False },
};

/* layout(s) */
static const float mfact = 0.60; /* factor of master area size [0.05..0.95] */
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 */
{ “[T]”, tile }, /* first entry is default */
{ “[F]”, NULL }, /* no layout function means floating behavior */
{ “[M]”, monocle },
};

/* key definitions */
#define MODKEY Mod4Mask
#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} },

/* 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”, “-b”, “-m”, dmenumon, “-fn”, dmenufont, “-nb”, normbgcolor, “-nf”, normfgcolor, “-sb”, selbgcolor, “-sf”, selfgcolor, NULL }; */
static const char *dmenucmd[] = { “rofi”, “-show”, “run”, NULL };
static const char *dmenu2[] = { “dmenu_extended_run”, NULL };
static const char *termcmd[] = { “lxterminal”, NULL };
static const char *firefox[] = { “firefox”, NULL };
static const char *ranger[] = { “xt”, “ranger”, NULL };
static const char *pcmanfm[] = { “pcmanfm”, NULL };
static const char *moc[] = { “xt”, “mocp”, “-m”, NULL };
static const char *calendar[] = { “zenity”, “–calendar”, NULL };
static const char *volup[] = { “amixer”, “-q”, “set”, “Master”, “5dB+”, “unmute”, NULL };
static const char *voldn[] = { “amixer”, “-q”, “set”, “Master”, “5dB-“, “unmute”, NULL };
static const char *apagar[] = { “sudo”, “/sbin/shutdown”, “-h”, “now”, NULL };
static const char *reiniciar[] = { “sudo”, “/sbin/reboot”, NULL };
static const char *scrot[] = { “scrot”, NULL };
static const char *systraytoggle[] = { “systraytoggle”, NULL }; /* systray ON/OFF */

static Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_z, spawn, {.v = dmenucmd } },
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
{ MODKEY, XK_b, togglebar, {0} },
{ MODKEY, XK_w, focusstack, {.i = +1 } },
{ MODKEY, XK_q, focusstack, {.i = -1 } },
{ MODKEY, XK_s, incnmaster, {.i = +1 } },
{ MODKEY, XK_a, incnmaster, {.i = -1 } },
{ MODKEY, XK_e, setmfact, {.f = -0.05} },
{ MODKEY, XK_r, setmfact, {.f = +0.05} },
{ MODKEY, XK_Return, zoom, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY|ShiftMask, XK_q, 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_y, focusmon, {.i = -1 } },
{ MODKEY, XK_u, focusmon, {.i = +1 } },
{ MODKEY, XK_o, tagmon, {.i = -1 } },
{ MODKEY, XK_p, tagmon, {.i = +1 } },
/* Comandos personalizados */
{ NULL, XK_Print, spawn, {.v = scrot } },
{ MODKEY, XK_x, spawn, {.v = dmenu2 } },
{ MODKEY, XK_F1, spawn, {.v = firefox } },
{ MODKEY, XK_F2, spawn, {.v = ranger } },
{ MODKEY, XK_F3, spawn, {.v = pcmanfm } },
{ MODKEY, XK_F4, spawn, {.v = moc } },
{ MODKEY, XK_F12, spawn, {.v = volup } },
{ MODKEY, XK_F11, spawn, {.v = voldn } },
{ MODKEY|ControlMask, XK_a, spawn, {.v = apagar } },
{ MODKEY|ControlMask, XK_r, spawn, {.v = reiniciar } },
{ MODKEY, XK_c, spawn, {.v = calendar } },
{ MODKEY, XK_d, spawn, {.v = systraytoggle } },
/* Fin de los comandos personalizados */
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
TAGKEYS( XK_4, 3)
TAGKEYS( XK_5, 4)
TAGKEYS( XK_6, 5)
{ MODKEY|ControlMask, XK_s, 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} },
};

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s