joe di castrohttp://joedicastro.com2012-06-07T00:00:00+02:00Productividad en el escritorio Linux: Awesome2012-06-07T00:00:00+02:00joe di castrohttp://joedicastro.com/productividad-en-el-escritorio-linux-awesome.html<p>Como había comentando en el anterior articulo sobre <a href="http://joedicastro.com/productividad-en-el-escritorio-linux-xmonad.html">Xmonad</a>, tenía la
intención de probar un <a href="http://joedicastro.com/productividad-en-el-escritorio-linux-tiling.html">Gestor de ventanas de mosaico</a> más, antes de tomar
la decisión final de cual emplear a diario. Y si, <em>y solo si</em>, resultaba ser una
mejor alternativa, abandonaría <strong>Xmonad</strong>. Este <strong>tiling window manager</strong> era
<a href="http://awesome.naquadah.org/">Awesome</a> y ha conseguido con creces que abandone a Xmonad.</p>
<p><strong>Awesome</strong> carece de algunas funcionalidades que me ofrecía Xmonad, pero después
de trabajar con él durante seis meses y conseguir tener una configuración a mi
medida, solamente hecho en falta una característica que comentare después. Además
Awesome me ofrece algunas características que no me ofrecía Xmonad y que valoro lo
suficiente como para realizar el cambio sin mirar atrás.</p>
<h2 id="awesome_vs_xmonad">Awesome vs Xmonad</h2>
<p>En esta tabla podemos ver una comparativa rápida de algunas de las
características de ambos gestores de ventanas.</p>
<table>
<thead>
<tr>
<th>Característica</th>
<th>Awesome</th>
<th>Xmonad</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Lenguaje</strong></td>
<td>C</td>
<td>Haskell</td>
</tr>
<tr>
<td><strong>Extensible</strong></td>
<td>Lua</td>
<td>Haskell</td>
</tr>
<tr>
<td><strong>Gestión ventanas</strong></td>
<td>Automático</td>
<td>Automático</td>
</tr>
<tr>
<td><strong>Soporte ratón</strong></td>
<td>Muy bueno</td>
<td>Básico</td>
</tr>
<tr>
<td><strong>Bandeja sistema (systray)</strong></td>
<td>Integrada</td>
<td>No</td>
</tr>
<tr>
<td><strong>Paneles</strong></td>
<td>Integrado</td>
<td>No</td>
</tr>
<tr>
<td><strong>Reinicio en caliente</strong></td>
<td>Si</td>
<td>Si</td>
</tr>
<tr>
<td><strong>Librería</strong></td>
<td>XCB</td>
<td>Xlib</td>
</tr>
<tr>
<td><strong>Soporte varios monitores</strong></td>
<td>Muy bueno</td>
<td>Bueno</td>
</tr>
<tr>
<td><strong>Transparencias</strong></td>
<td>Gestor externo</td>
<td>Gestor externo</td>
</tr>
<tr>
<td><strong>Integración escritorios</strong></td>
<td>Buena</td>
<td>Muy buena (Gnome, KDE)</td>
</tr>
<tr>
<td><strong>Desarrollo</strong></td>
<td>Muy activo</td>
<td>Muy activo</td>
</tr>
<tr>
<td><strong>Estabilidad</strong></td>
<td>Estable</td>
<td>Estable</td>
</tr>
<tr>
<td><strong>Documentación</strong></td>
<td>Buena</td>
<td>Buena</td>
</tr>
</tbody>
</table>
<h3 id="ventajas">Ventajas</h3>
<p>Una de las principales ventajas de Awesome sobre Xmonad es la velocidad de
respuesta que ofrece el entorno, que en Awesome es bastante superior a la de
Xmonad. Alguna que otra vez, al intentar realizar muchas operaciones
consecutivas entre ventanas y escritorios en Xmonad, se me ha quedado colgado y
he tenido que reiniciarlo (que se hace en caliente y en segundos, pero no deja
de ser algo molesto). En este sentido Awesome solo se me ha colgado un par de
veces.</p>
<p>Otra de las grandes ventajas es que al configurarse en <a href="https://es.wikipedia.org/wiki/Lua">Lua</a> es
bastante más sencillo hacerse con él, ya que es un lenguaje relativamente
asequible y carece de la complejidad inicial de <a href="https://es.wikipedia.org/wiki/Haskell">Haskell</a> para aquellos
que no conocen la programación funcional. Esto aumenta las posibilidades de
personalizarlo para un usuario con conocimientos muy básicos de programación.</p>
<p>La configuración por defecto de Awesome también es más completa y amigable que
la de Xmonad, partiendo de un esquema tradicional de ventanas flotantes y con
menús que nos permiten dar los primeros pasos y poder abandonar la sesión sin
llegar a conocer las combinaciones de teclado por defecto. Algo que agradecerán
aquellos que se hayan tenido que enfrentar a una configuración por defecto de
Xmonad por primera vez. Esto invita a conocer el sistema y no abandonarlo
"asustado" por su complejidad. En la imagen se puede ver el aspecto que presenta
una sesión de Awesome con la configuración por defecto.</p>
<p style="text-align:center;"><img src="pictures/awesome_default.png" width="700"
height="525" alt="configuración por defecto de Awesome" /></p>
<blockquote>
<p>Para acceder al menú podemos bien hacer click sobre el icono de
Awesome en la parte superior izquierda o bien con el botón derecho en
cualquier parte de la pantalla. También se puede acceder a él con la
combinación de teclas <strong><code>Win</code></strong> + <strong><code>w</code></strong></p>
</blockquote>
<p>Finalmente, el que Awesome tenga integrados aspectos como los paneles, una
bandeja del sistema (systray), lanzador de aplicaciones y un soporte muy bueno del
ratón facilita el poder emplearlo en solitario, sin un sistema de escritorio
tradicional detrás. Y a través de librerías es fácil implementar un sistema de
notificaciones, un localizador de ventanas, temas, menús emergentes, ...</p>
<h3 id="desventajas">Desventajas</h3>
<p>Quizás para mí la mayor desventaja frente a Xmonad y lo único que hecho
realmente en falta, es la imposibilidad, a diferencia de Xmonad, de poder
regular el tamaño vertical de las ventanas. Es particularmente útil en algunas
situaciones y en Xmonad está integrado de manera natural. Pero después de varios
meses he aprendido a vivir sin ello.</p>
<p>La otra gran desventaja es que el desarrollo aún no ha alcanzado el estadio de
madurez de Xmonad, esta sujeto a demasiados cambios y no cuidan demasiado la
retrocompatibilidad. Las nuevas versiones frecuentemente obligan a realizar
cambios en la configuración para que todo vuelva a funcionar con normalidad.</p>
<p>Por otro lado, la instalación en algunas distribuciones puede no ser tan
sencilla como la de Xmonad por la falta de soporte a la librería XCB o por
necesitar versiones especificas de cairo.</p>
<h3 id="diferentes_filosof+as">Diferentes filosofías</h3>
<p>Siendo como son ambos, gestores de ventanas de mosaico, difieren particularmente
en la manera de entender principalmente dos conceptos:</p>
<h4 id="__m+ltiples_escritorios__"><strong>Múltiples escritorios</strong></h4>
<p>Aquí Xmonad sigue el concepto tradicional de múltiples escritorios en Linux,
soportando por defecto 9 por monitor y asignándoles un número del 1 al 0. Luego
una aplicación puede estar, por ejemplo, en el escritorio 4 del monitor 2 y
podemos movernos entre escritorios y monitores y mover a su vez las aplicaciones
entre ellos.</p>
<p>En cambio, Awesome, aunque aparentemente sigue el mismo sistema, y para
cualquiera que no quiera profundizar en ello no habrá diferencia alguna, se
basa en un concepto diferente. En Awesome cada escritorio es en realidad una
<strong>etiqueta</strong> y puede ser tanto un número como un texto. En principio también
son 9 por monitor, aunque esto puede ampliarse o reducirse en la configuración.
La diferencia principal es que una aplicación puede ser asignada a varias
etiquetas simultáneamente y puede por lo tanto ser mostrada en varios
<em>escritorios</em> a la vez. Esto permite asignar de forma muy sencilla etiquetas
destinadas a una tarea y predefinir ciertas aplicaciones para que sean mostradas
en una o más etiquetas. Por ejemplo podemos tener una etiqueta para
<code>redes sociales</code> y mostrar allí un navegador, pero al mismo tiempo podemos tener
una etiqueta <code>desarrollo</code> en la que también queremos que se muestre el navegador.
Por otro lado, también es posible mostrar varias etiquetas al mismo tiempo, lo
que nos permite trabajar en dos tareas distintas y bien definidas, cada una en su
etiqueta, y en un momento dado, visualizarlas juntas sin perder la asignación de
etiquetas original. En este sentido Awesome es mucho más flexible y potente que
Xmonad.</p>
<h4 id="__m+ltiples_monitores__"><strong>Múltiples monitores</strong></h4>
<p>En este caso Xmonad comparte el mismo escritorio en distintos monitores. Por lo
tanto si estamos en el escritorio 1 en el monitor 1 y nos movemos al escritorio
2, lo hará en todos los monitores a la vez, lo que también es el comportamiento
clásico. Con lo que podemos decir que aunque tenemos 9 escritorios por monitor,
se comporta como si tuviéramos 9 para todos los monitores.</p>
<p>Awesome, al contrario, emplea 9 etiquetas por monitor independientes entre
si. Lo que significa que en este casi si tenemos 9 <em>escritorios</em> reales por cada
monitor. Si nos encontramos en el monitor 1 y la etiqueta 1, al cambiar a la
etiqueta 2, el resto de monitores permanecerán inalterados en la etiqueta en la
que estuvieran previamente. En este sentido Awesome también sigue siendo bastante
más flexible y potente que Xmonad. Este comportamiento puede ser alterado mediante
la configuración. Hay quienes prefieren un método de trabajo y quienes
prefieren el otro, yo soy de los que prefieren el comportamiento de Awesome.</p>
<h2 id="awesome_con_gnome">Awesome con Gnome</h2>
<p>Actualmente estoy empleando Awesome en solitario, si un escritorio detrás, lo que
me obliga a configurar por mi cuenta todos los servicios que estos proporcionan,
pero me compensa con la ligereza que me reporta el no emplear un pesado
escritorio por debajo. Sin embargo, los primeros meses lo empleé conjuntamente
con Gnome en Ubuntu, utilizando solo los componentes básicos del mismo. La forma
de configurar una sesión de Awesome con Gnome en Ubuntu (11.10 y 12.04) y en
<a href="http://www.archlinux.org">Arch Linux</a>, la distribución que estoy empleando ahora, es a través
de los siguientes ficheros:</p>
<p><code>/usr/share/applications/awesome.desktop</code></p>
<div class="codehilite"><pre><span class="k">[Desktop Entry]</span>
<span class="na">Version</span><span class="o">=</span><span class="s">1.0</span>
<span class="na">Type</span><span class="o">=</span><span class="s">Application</span>
<span class="na">Name</span><span class="o">=</span><span class="s">Awesome</span>
<span class="na">Comment</span><span class="o">=</span><span class="s">The awesome launcher!</span>
<span class="na">TryExec</span><span class="o">=</span><span class="s">awesome</span>
<span class="na">Exec</span><span class="o">=</span><span class="s">awesome</span>
</pre></div>
<p><code>/usr/share/gnome-session/sessions/awesome.session</code></p>
<div class="codehilite"><pre><span class="k">[GNOME Session]</span>
<span class="na">Name</span><span class="o">=</span><span class="s">Awesome session</span>
<span class="na">RequiredComponents</span><span class="o">=</span><span class="s">gnome-settings-daemon;</span>
<span class="na">RequiredProviders</span><span class="o">=</span><span class="s">windowmanager;</span>
<span class="na">DefaultProvider-windowmanager</span><span class="o">=</span><span class="s">awesome</span>
<span class="na">DesktopName</span><span class="o">=</span><span class="s">GNOME</span>
</pre></div>
<p><code>/usr/share/xsessions/awesome-gnome-session.desktop</code></p>
<div class="codehilite"><pre><span class="k">[Desktop Entry]</span>
<span class="na">Name</span><span class="o">=</span><span class="s">Awesome GNOME</span>
<span class="na">Comment</span><span class="o">=</span><span class="s">Dynamic window manager</span>
<span class="na">TryExec</span><span class="o">=</span><span class="s">/usr/bin/gnome-session</span>
<span class="na">Exec</span><span class="o">=</span><span class="s">gnome-session --session=awesome</span>
<span class="na">Type</span><span class="o">=</span><span class="s">XSession</span>
</pre></div>
<p>Evidentemente para esto es necesario instalar los paquetes necesarios para
ejecutar Awesome que en el caso de Ubuntu son <code>awesome</code> y <code>awesome-extra</code>:</p>
<div class="codehilite"><pre><span class="gp">$</span> sudo apt-get install awesome awesome-extra
</pre></div>
<p>En Arch, bastaría con instalar el paquete <code>awesome</code>:</p>
<div class="codehilite"><pre><span class="gp">$</span> sudo pacman -S awesome
</pre></div>
<h2 id="mi_configuraci+n">Mi configuración</h2>
<p>A diferencia de Xmonad, mi configuración de Awesome no está contenida en un solo
fichero, ya que el tema y los diversos plugins están alojados dentro de sus
propios directorios. Además el fichero de configuración <code>rc.lua</code> es demasiado
extenso (cerca de 1200 lineas) para volcarlo aquí. Así que me limitare a
mencionar los aspectos más destacados, la configuración completa queda
disponible a través de mi repositorio en <a href="http://github.com/joedicastro/dotfiles">GitHub</a>.</p>
<p>Destacar que al principio del fichero incluyo una <em>Cheat Sheet</em> ("chuleta") con
todas las combinaciones de teclado y ratón que tengo habilitadas en mi
configuración.</p>
<h2 id="panel_y_widgets">Panel y Widgets</h2>
<p>Awesome permite la creación de varios paneles, generalmente se suelen crear en
la parte superior y/o inferior de la pantalla. A mi me gusta disponer del máximo
espacio posible para las aplicaciones, así que solo he creado uno superior que
además puedo ocultar a conveniencia. De hecho, para determinadas tareas, lo
mantengo oculto la mayor parte del tiempo y solo lo muestro cuando me interesa
consultar la información que allí se muestra.</p>
<p>Aquí se puede ver la apariencia del panel superior y una ampliación del mismo:</p>
<p style="text-align:center;"><img src="pictures/wibox_full.png" width="700"
height="8" alt="wibox" /></p>
<p style="text-align:center;"><img src="pictures/wibox.png" width="600"
height="63" alt="Zoom sobre la barra de estado" /></p>
<p>En el que se pueden apreciar (de izquierda a derecha y de arriba a abajo) los
siguientes widgets:</p>
<ul>
<li>Icono de Awesome. Proporciona acceso al menú de Awesome</li>
<li>Etiquetas. Aquí se puede ver que hay dos activas y que nos encontramos en la
segunda, <code>β</code></li>
<li>Icono de esquema. Vemos que está seleccionado el esquema <code>tile</code></li>
<li>Icono y titulo de la ventana activa. En este caso tenemos una ventana de <em>Gvim</em>
y además el icono del final nos indica que es una ventana flotante</li>
<li>Pomodoro. Es un widget que me permite seguir el método <a href="http://www.pomodorotechnique.com/">Pomodoro</a> y que
indica que quedan 4 minutos y 14 segundos para tomarme un pequeño descanso.</li>
<li>MPD. Indica el estado del servidor de música <em>mpd</em>, y en este caso nos indica el
autor y el titulo de la canción que se está reproduciendo</li>
<li>Velocidad de los ventiladores del sistema</li>
<li>Temperaturas de CPU y GPU</li>
<li>Uso de las CPUs del microprocesador</li>
<li>Porcentaje y cantidad de memoria RAM en uso</li>
<li>Velocidad (en Kbs) de bajada y subida de la red.</li>
<li>Porcentaje de ocupación en disco de <code>/</code> y <code>/home</code></li>
<li>Estado de la batería y tiempo estimado de carga/descarga</li>
<li>Uptime. Indica el tiempo que lleva el equipo encendido desde el último
reinicio</li>
<li>Versión del Kernel Linux en ejecución</li>
<li>Volumen del sonido del sistema</li>
<li>Fecha y hora</li>
</ul>
<p>Muchos prefieren añadir iconos o encabezados a todos los widgets para facilitar
su identificación, pero yo ya conozco para que es cada uno y prefiero un entorno
minimalista que me distraiga lo menos posible. Muchos de estos widgets ejecutan
una acción al ser pulsados con un botón del ratón o al pasar por encima de
ellos. Por ejemplo al pasar el ratón por encima de la fecha y hora se muestra un
calendario y al pulsar con el botón izquierdo sobre el uso de las CPUs, se lanza
una ventana con el programa <code>htop</code></p>
<h2 id="localizar_aplicaciones">Localizar aplicaciones</h2>
<p>Una de las funcionalidades geniales que tenía implementada en Xmonad me permitía
conocer todas las ventanas que estaban abiertas y elegir la deseada con una
rápida combinación de teclas. Awesome no tiene esto implementado, pero gracias a
una librería externa, <strong><a href="https://github.com/bioe007/awesome-revelation">Revelation</a></strong>, podemos emplear un método similar al
famoso Exposé del Mac OS y también presente en Compiz. Lo que hace es mostrarnos
en la etiqueta que estemos actualmente todas las ventanas abiertas en forma de
mosaico y podemos elegir una de ellas para saltar automáticamente a ella (y la
etiqueta en la que se encuentre). Aquí podemos ver un screencast de su
funcionamiento:</p>
<p style="text-align:center;"><img src="pictures/revelation.gif" width="640"
height="400" alt="Revelation en funcionamiento" /></p>
<p>Es también un método muy rápido y muy visual, al final he acabado prefiriendo
este método al que empleaba en Xmonad, ya que en este último, el titulo de las
ventanas podía ser muy ambiguo y no ser fácil dar con la ventana adecuada.</p>
<h2 id="gesti+n_din+mica_de_etiquetas">Gestión dinámica de etiquetas</h2>
<p>Aunque por defecto Awesome define 10 etiquetas por monitor, podemos definir a
nuestro antojo el número de ellas que queramos en el fichero de configuración.
Podemos optar por un número clásico en los escritorios Linux, cuatro, o
podemos crear una para cada tarea concreta más una libre. Por defecto tengo
definidas diez, empleando para identificarlas los números en griego:</p>
<div class="codehilite"><pre><span class="c1">-- definición de las etiquetas en el fichero de configuración rc.lua</span>
<span class="n">tags</span><span class="p">[</span><span class="n">s</span><span class="p">]</span> <span class="o">=</span> <span class="n">awful</span><span class="p">.</span><span class="n">tag</span><span class="p">({</span> <span class="s2">"</span><span class="s">α"</span><span class="p">,</span> <span class="s2">"</span><span class="s">β"</span><span class="p">,</span> <span class="s2">"</span><span class="s">γ"</span><span class="p">,</span> <span class="s2">"</span><span class="s">δ"</span><span class="p">,</span> <span class="s2">"</span><span class="s">ε"</span><span class="p">,</span> <span class="s2">"</span><span class="s">ς"</span><span class="p">,</span> <span class="s2">"</span><span class="s">ζ"</span><span class="p">,</span> <span class="s2">"</span><span class="s">η"</span><span class="p">,</span> <span class="s2">"</span><span class="s">θ"</span><span class="p">},</span> <span class="n">s</span><span class="p">,</span> <span class="n">layouts</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
</pre></div>
<p>Sin embargo, en mi configuración empleo una librería externa, <a href="http://git.glacicle.org/eminent">Eminent</a>,
que gestiona estas etiquetas de forma dinámica, creándolas y destruyéndolas
según sea necesario. Así de entrada solo tenemos una etiqueta, <code>α</code> y solo se
creara una segunda etiqueta, <code>β</code> si nos desplazamos a ella. Del mismo modo,
cuando eliminamos la última ventana de una etiqueta y la abandonamos, se
destruye. La ventaja de esto es que por un lado nos facilita localizar donde
estamos más fácilmente y por otro, que en caso de ser necesario, si necesitamos
más etiquetas (de las creadas por defecto), las creara de forma automática. De
este modo cuando llegamos a la etiqueta <code>θ</code>, si necesitamos otra, creara la <code>10</code>
y así en lo sucesivo.</p>
<h2 id="lanzar_aplicaciones">Lanzar aplicaciones</h2>
<p>Existen dos métodos para realizar esta tarea:</p>
<ul>
<li>Empleando un prompt que emerge en el panel superior y nos permite escribir el
comando que queremos ejecutar y que posee autocompletado. La combinación de
teclas por defecto que activa esto es <strong><code>Win</code></strong> + <strong><code>r</code></strong></li>
</ul>
<p style="text-align:center;"><img src="pictures/awesome_prompt.png" width="585"
height="30" alt="prompt en Awesome" /></p>
<ul>
<li>Empleando <a href="http://awesome.naquadah.org/wiki/Menubar">menubar</a>. Menubar es una librería externa, que será incluida
en la próxima versión de Awesome por defecto, que al igual que muchos
otros lanzadores de aplicaciones (<em>Gnome Do</em>, <em>Kupfer</em>, <em>Synapse</em>, etc) nos va
mostrando las aplicaciones disponibles en función de lo que vayamos tecleando.
Se lanza con la combinación de teclas <strong><code>Win</code></strong> + <strong><code>p</code></strong> y en mi caso, esta
aparece inmediatamente debajo del panel superior.
Aquí se puede ver la menubar en funcionamiento (la tecla <strong><code>Win</code></strong> también es
llamada <strong><code>Super</code></strong> ):</li>
</ul>
<p style="text-align:center;"><img src="pictures/menubar.gif" width="640"
height="400" alt="Lanzar aplicaciones con menubar en Awesome wm" /></p>
<p>Yo además empleo un tercer método que heredo de Xmonad, y es emplear
<a href="http://tools.suckless.org/dmenu/">dmenu</a> para lanzar aplicaciones. <code>dmenu</code> es muy parecido al prompt de
Awesome, pero busca para el autocompletado en todo el nombre del comando y no
solo al principio. Además muestra todas las coincidencias disponibles y que se
pueden seleccionar con las teclas de dirección.</p>
<p style="text-align:center;"><img src="pictures/dmenu.gif" width="640"
height="400" alt="dmenu en acción" /></p>
<h3 id="grabar_v+deos_y_screencasts_del_escritorio">Grabar vídeos y screencasts del escritorio</h3>
<p>Adicionalmente, tengo definidas ciertas combinaciones de teclas para lanzar
determinadas aplicaciones o procesos con las teclas de función. Dentro de estos
atajos de teclado cabe destacar cinco que en lugar lanzar una aplicación,
comienzan o terminan un determinado proceso. Estas combinaciones, que van de
<strong><code>F8</code></strong> a <strong><code>F12</code></strong>, las utilizo para grabar vídeos y screencasts con gifs
animados y son las que he empleado para ilustrar este articulo.</p>
<div class="codehilite"><pre><span class="c1">-- Win + F8 Start gif screencast recording LowRes</span>
<span class="c1">-- Win + F9 Start gif screencast recording HighRes</span>
<span class="c1">-- Win + F10 Stop gif screencast recording</span>
<span class="c1">-- Win + F11 Start mkv screencast recording</span>
<span class="c1">-- Win + F12 Stop mkv screencast recording</span>
<span class="n">awful</span><span class="p">.</span><span class="n">key</span><span class="p">({</span> <span class="n">modkey</span> <span class="p">},</span> <span class="s2">"</span><span class="s">F8"</span><span class="p">,</span>
<span class="k">function</span> <span class="p">()</span>
<span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn_with_shell</span><span class="p">(</span><span class="s2">"</span><span class="s">rm "</span> <span class="o">..</span> <span class="n">home_dir</span> <span class="o">..</span> <span class="s2">"</span><span class="s">/screencast.gif"</span><span class="p">)</span>
<span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn</span><span class="p">(</span><span class="s2">"</span><span class="s">ffmpeg -f x11grab -s "</span> <span class="o">..</span> <span class="n">scr_res</span> <span class="o">..</span>
<span class="s2">"</span><span class="s"> -r 2 -i :0.0 -b:v 500k -pix_fmt rgb24 -y"</span> <span class="o">..</span>
<span class="s2">"</span><span class="s"> -loop 0 -s 640x400 "</span> <span class="o">..</span> <span class="n">home_dir</span> <span class="o">..</span>
<span class="s2">"</span><span class="s">/animated.gif"</span><span class="p">)</span>
<span class="k">end</span><span class="p">),</span>
<span class="n">awful</span><span class="p">.</span><span class="n">key</span><span class="p">({</span> <span class="n">modkey</span> <span class="p">},</span> <span class="s2">"</span><span class="s">F9"</span><span class="p">,</span>
<span class="k">function</span> <span class="p">()</span>
<span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn_with_shell</span><span class="p">(</span><span class="s2">"</span><span class="s">rm "</span> <span class="o">..</span> <span class="n">home_dir</span> <span class="o">..</span> <span class="s2">"</span><span class="s">/screencast.gif"</span><span class="p">)</span>
<span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn</span><span class="p">(</span><span class="s2">"</span><span class="s">ffmpeg -f x11grab -s "</span> <span class="o">..</span> <span class="n">scr_res</span> <span class="o">..</span>
<span class="s2">"</span><span class="s"> -r 2 -i :0.0 -b:v 500k -pix_fmt rgb24 -y"</span> <span class="o">..</span>
<span class="s2">"</span><span class="s"> -loop 0 -s 1440x900 "</span> <span class="o">..</span> <span class="n">home_dir</span> <span class="o">..</span>
<span class="s2">"</span><span class="s">/animated.gif"</span><span class="p">)</span>
<span class="k">end</span><span class="p">),</span>
<span class="n">awful</span><span class="p">.</span><span class="n">key</span><span class="p">({</span> <span class="n">modkey</span> <span class="p">},</span> <span class="s2">"</span><span class="s">F10"</span><span class="p">,</span>
<span class="k">function</span> <span class="p">()</span>
<span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn</span><span class="p">(</span><span class="s2">"</span><span class="s">killall ffmpeg"</span><span class="p">)</span>
<span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn</span><span class="p">(</span><span class="s2">"</span><span class="s">convert ephemeral:"</span> <span class="o">..</span> <span class="n">home_dir</span> <span class="o">..</span>
<span class="s2">"</span><span class="s">/animated.gif -fuzz 7% -layers Optimize "</span> <span class="o">..</span>
<span class="n">home_dir</span> <span class="o">..</span> <span class="s2">"</span><span class="s">/screencast.gif"</span><span class="p">)</span>
<span class="k">end</span><span class="p">),</span>
<span class="n">awful</span><span class="p">.</span><span class="n">key</span><span class="p">({</span> <span class="n">modkey</span> <span class="p">},</span> <span class="s2">"</span><span class="s">F11"</span><span class="p">,</span>
<span class="k">function</span> <span class="p">()</span>
<span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn_with_shell</span><span class="p">(</span><span class="s2">"</span><span class="s">rm "</span> <span class="o">..</span> <span class="n">home_dir</span> <span class="o">..</span> <span class="s2">"</span><span class="s">/screencast.mkv"</span><span class="p">)</span>
<span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn</span><span class="p">(</span><span class="s2">"</span><span class="s">ffmpeg -f x11grab -s "</span> <span class="o">..</span> <span class="n">scr_res</span> <span class="o">..</span>
<span class="s2">"</span><span class="s"> -r 25 -i :0.0 -sameq "</span> <span class="o">..</span> <span class="n">home_dir</span> <span class="o">..</span>
<span class="s2">"</span><span class="s">/screencast.mkv"</span><span class="p">)</span>
<span class="k">end</span><span class="p">),</span>
<span class="n">awful</span><span class="p">.</span><span class="n">key</span><span class="p">({</span> <span class="n">modkey</span> <span class="p">},</span> <span class="s2">"</span><span class="s">F12"</span><span class="p">,</span>
<span class="k">function</span> <span class="p">()</span>
<span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn</span><span class="p">(</span><span class="s2">"</span><span class="s">killall ffmpeg"</span><span class="p">)</span>
<span class="k">end</span><span class="p">)</span>
</pre></div>
<h2 id="gesti+n_tiempo_con_pomodoro">Gestión tiempo con pomodoro</h2>
<p>La <a href="https://es.wikipedia.org/wiki/T%C3%A9cnica_Pomodoro">técnica Pomodoro</a> puede ser muy provechosa en ciertas tareas si se
emplea con sentido común y se sigue más o menos a rajatabla. Yo la empleo muy a
menudo cuando tengo una tarea concreta en la que quiero centrarme sin
distracciones para sacarla adelante y no caer en el error de procrastinar
demasiado. Es una combinación ideal entre concentración puntual y alternar
distracciones, que impiden a uno "quemarse" por no saber echar el freno a
tiempo. Es una técnica muy útil a la hora de programar o de crear un articulo
como este, pero que es difícilmente aplicable en tareas que requieren cierta
multitarea como son las de administración de sistemas.</p>
<p>Existen múltiples aplicaciones, applets, indicadores, etc para aplicar esta
técnica, que se basaba originalmente en un simple reloj de cocina. Pero alguien,
en su momento pensó, que no era mala idea crear un widget para Awesome que nos
permitiera medir los tiempos para aplicarla y creo una librería externa para
ello. Yo empleo esta <a href="https://github.com/nikolavp/awesome-pomodoro">librería</a> ligeramente modificada para controlar
el tiempo transcurrido.</p>
<p>El funcionamiento es muy básico, pulsamos sobre el icono y se activa la cuenta
atrás de 25 minutos. Al acabar, una alarma sonora y una notificación emergente,
nos avisan de que se ha terminado el tiempo de trabajo y nos merecemos un
descanso. Volvemos a pulsar sobre el widget y comienza la cuenta atrás de cinco
minutos y se repite el proceso. Si pulsamos con el botón derecho se reinicia el
widget.</p>
<p style="text-align:center;"><img src="pictures/pomodoro.png" width="613"
height="105" alt="notificaciones de pomodoro" /></p>
<h2 id="debug_con_xephyr">Debug con Xephyr</h2>
<p>Esta es una de las posibilidades que nos permite Awesome, que más nos ayudará a
la hora de "trastear" con él, sin temor a "romper" nada. Podemos depurar los
errores y realizar pruebas con Awesome con una configuración distinta a la
nuestra y en una sesión X distinta a la actual. Esto lo conseguimos ejecutando
Awesome dentro de un servidor X, <a href="http://www.freedesktop.org/wiki/Software/Xephyr">Xephyr</a>, que aparecerá dentro de
nuestra sesión como una ventana más.</p>
<p>Yo he integrado esta posibilidad dentro del menú de Awesome para que sea mucho
más sencillo e inmediato el poder probar cambios en un entorno de pruebas.</p>
<p style="text-align:center;"><img src="pictures/awesome_menu.png" width="603"
height="275" alt="Mi menu de Awesome" /></p>
<p>En este vídeo se puede ver el funcionamiento básico de este sistema. Normalmente
inicio el entorno de pruebas a pantalla completa, pero que se pueda apreciar
mejor la diferencia, he grabado la mayoría del vídeo con una sesión de Xephyr a
menor resolución. Lo que se puede ver es como primero inicio una sesión de
Awesome dentro de Xephyr con la configuración por defecto. Después la cierro y
compruebo la sintaxis Lua de la configuración de test. La notificación me alerta
de que el fichero no existe, luego procedo a crearlo (es una copia de la
configuración real actual) y vuelvo a comprobar la sintaxis. Una vez que veo que
esta es correcta, lanzo Awesome con la configuración de test. Cierro la sesión y
procedo a realizar cambios en la configuración de pruebas. Ahora lanzo de nuevo
Awesome con esta configuración y compruebo que efectivamente se han realizado
los cambios. Dentro de esta sesión vuelvo a editar la configuración de test para
deshacer los cambios y después reinicio este Awesome de pruebas. Se puede ver
como efectivamente todo vuelve a el estado anterior. Cierro la sesión y
compruebo el log de la sesión para ver los mensajes de error. Finalmente abro
varias sesiones de Awesome a la vez y una a pantalla completa.</p>
<div style="text-align:center">
<iframe src="http://player.vimeo.com/video/43562306" width="700" height="438">
</iframe>
<p>Muestra de las posibilidades que ofrecen Xephyr y el script
<strong>awdt.py</strong> para poder depurar la configuración de Awesome.
Recomiendo ver en alta resolución y a pantalla completa.</p>
</div>
<p>Para realizar estas acciones programé un script en Python, <code>awdt.py</code>, que incluyo
al final del articulo.</p>
<p>Una de las ventajas de Awesome con respecto a Xmonad, es que no necesitamos
recompilar cada vez que realizamos un cambio en la configuración, basta con
editar el fichero, salvar y reiniciarlo. Reiniciar Awesome es algo que lleva
menos de un segundo.</p>
<h2 id="reinicio_apagado_y_suspensi+n">Reinicio, apagado y suspensión</h2>
<p>Dado que no empleo ningún escritorio, arrancando directamente la sesión en
Awesome, debo gestionar directamente cierto tipo de situaciones que vienen
resueltas de manera predefinida en estos. Uno de estos casos es la gestión de
energía del equipo, esto es: apagarlo, reiniciarlo, suspenderlo e hibernarlo.
Dado que nunca lo hiberno, he implementado únicamente las tres primeras
acciones. Lo que hago es emplear directamente los comandos de consola, que
ejecuto a través de un dialogo gráfico que me pide la contraseña para <code>sudo</code> con
<code>gksudo</code> (podría haber empleado <em>Zenity</em>, <em>Xdialog</em> o cualquier otro similar)
que es activado a través de una combinación de teclas. Por ejemplo, para
suspender el equipo lo activo a través de la combinación <strong><code>Win</code></strong> + <strong><code>s</code></strong> :</p>
<div class="codehilite"><pre><span class="n">awful</span><span class="p">.</span><span class="n">key</span><span class="p">({</span> <span class="n">modkey</span> <span class="p">},</span> <span class="s2">"</span><span class="s">s"</span><span class="p">,</span>
<span class="k">function</span> <span class="p">()</span>
<span class="n">awful</span><span class="p">.</span><span class="n">util</span><span class="p">.</span><span class="n">spawn</span><span class="p">(</span><span class="s2">"</span><span class="s">gksudo pm-suspend -m "</span> <span class="o">..</span>
<span class="s2">"</span><span class="s">'Se va a suspender el equipo, ¿estás seguro?'"</span><span class="p">)</span>
<span class="k">end</span><span class="p">),</span>
</pre></div>
<p>con el siguiente resultado:</p>
<p style="text-align:center;"><img src="pictures/suspend.png" width="381"
height="191" alt="Dialogo para suspensión" /></p>
<p>Sé que la mayoría no está acostumbrado a tener que introducir la contraseña para
realizar cualquiera de estas acciones y posiblemente detestarían hacerlo, pero
yo lo prefiero así.</p>
<h2 id="bloqueo_de_la_pantalla">Bloqueo de la pantalla</h2>
<p>Empleo un método similar para bloquear la pantalla, ya que no empleo un
salvapantallas (simplemente apago la pantalla pasado un cierto tiempo) empleo el
programa <a href="http://joelburget.com/slimlock/"><code>slimlock</code></a> para realizar esta tarea y lo activo de forma manual
con otra combinación de teclas. El resultado es una pantalla como esta:</p>
<p style="text-align:center;"><img src="pictures/slimlock.png" width="642"
height="401" alt="slimlock" /></p>
<h2 id="documentaci+n_y_enlaces_de_inter+s">Documentación y enlaces de interés.</h2>
<p>La documentación del código fuente y de la API de Awesome son bastante buenas,
con lo que si tienes los conocimientos suficientes no te será muy dificil
hacerte con él. Si necesitas algo más general, tanto el propio Wiki de Awesome
como los recursos disponibles gracias a su comunidad (lista de correo e IRC) son
bastante útiles para ayudarte a conseguir la configuración que más se ajuste a
tus necesidades. Es una comunidad muy dinámica y bastante colaboradora. También
en el Wiki de Arch Linux hay información interesante sobre Awesome.</p>
<ul>
<li><a href="http://awesome.naquadah.org/">Pagina principal</a></li>
<li><a href="http://awesome.naquadah.org/wiki/Main_Page">Wiki</a></li>
<li><a href="http://awesome.naquadah.org/wiki/Screenshots">Pantallazos</a></li>
<li><a href="http://awesome.naquadah.org/wiki/User_Configuration_Files">Ficheros de configuración</a></li>
<li><a href="http://awesome.naquadah.org/doc/api/">API Docs</a></li>
<li><a href="https://wiki.archlinux.org/index.php/Awesome">Arch Linux Wiki</a></li>
<li><a href="http://www.lua.org/pil/">Programming in Lua</a></li>
</ul>
<h2 id="awdtpy">awdt.py</h2>
<p>Este es el contenido del script <code>awdt.py</code> que empleo para depurar la
configuración de Awesome en un entorno de pruebas. Se encuentra dentro del mismo
repositorio que el resto de la configuración.</p>
<div class="codehilite"><pre><span class="c">#!/usr/bin/env python</span>
<span class="c"># encoding: utf-8</span>
<span class="sd">"""</span>
<span class="sd"> awdt.py: a script to debug awesome wm configs in nested Xephyr sessions</span>
<span class="sd"> This script is a tool intended to help to debug Awesome wm configurations</span>
<span class="sd"> in a safe manner. To this purpose uses the Xephyr X server to nest a X</span>
<span class="sd"> session inside the current Awesome X session.</span>
<span class="sd"> The original idea come from the mikar's bash awmtt script (Thanks mikar):</span>
<span class="sd"> https://github.com/mikar/awmtt</span>
<span class="sd"> Needs logger.py and check_execs.py from my Python Recipes repository at</span>
<span class="sd"> https://github.com/joedicastro/python-recipes</span>
<span class="sd">"""</span>
<span class="c">#==============================================================================</span>
<span class="c"># Copyright 2012 joe di castro <joe@joedicastro.com></span>
<span class="c">#</span>
<span class="c"># This program is free software: you can redistribute it and/or modify</span>
<span class="c"># it under the terms of the GNU General Public License as published by</span>
<span class="c"># the Free Software Foundation, either version 3 of the License, or</span>
<span class="c"># (at your option) any later version.</span>
<span class="c">#</span>
<span class="c"># This program is distributed in the hope that it will be useful,</span>
<span class="c"># but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
<span class="c"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span>
<span class="c"># GNU General Public License for more details.</span>
<span class="c">#</span>
<span class="c"># You should have received a copy of the GNU General Public License</span>
<span class="c"># along with this program. If not, see <http://www.gnu.org/licenses/>.</span>
<span class="c">#==============================================================================</span>
<span class="n">__author__</span> <span class="o">=</span> <span class="s">"joe di castro <joe@joedicastro.com>"</span>
<span class="n">__license__</span> <span class="o">=</span> <span class="s">"GNU General Public License version 3"</span>
<span class="n">__date__</span> <span class="o">=</span> <span class="s">"05/06/2012"</span>
<span class="n">__version__</span> <span class="o">=</span> <span class="s">"0.5"</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">argparse</span> <span class="kn">import</span> <span class="n">ArgumentParser</span><span class="p">,</span> <span class="n">RawDescriptionHelpFormatter</span>
<span class="kn">from</span> <span class="nn">re</span> <span class="kn">import</span> <span class="n">findall</span>
<span class="kn">from</span> <span class="nn">shutil</span> <span class="kn">import</span> <span class="n">copy</span>
<span class="kn">from</span> <span class="nn">subprocess</span> <span class="kn">import</span> <span class="n">Popen</span><span class="p">,</span> <span class="n">PIPE</span><span class="p">,</span> <span class="n">STDOUT</span>
<span class="kn">from</span> <span class="nn">tempfile</span> <span class="kn">import</span> <span class="n">gettempdir</span>
<span class="kn">from</span> <span class="nn">time</span> <span class="kn">import</span> <span class="n">sleep</span>
<span class="kn">from</span> <span class="nn">logger</span> <span class="kn">import</span> <span class="n">Logger</span>
<span class="kn">from</span> <span class="nn">check_execs</span> <span class="kn">import</span> <span class="n">check_execs</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
<span class="c"># Checks the installation of the necessary python modules</span>
<span class="k">print</span><span class="p">((</span><span class="n">os</span><span class="o">.</span><span class="n">linesep</span> <span class="o">*</span> <span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="s">"An error found importing one module:"</span><span class="p">,</span>
<span class="nb">str</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">1</span><span class="p">]),</span> <span class="s">"You need to install it"</span><span class="p">,</span> <span class="s">"Stopping..."</span><span class="p">]))</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">arguments</span><span class="p">():</span>
<span class="sd">"""Defines the command line arguments for the script."""</span>
<span class="n">main_desc</span> <span class="o">=</span> <span class="s">"""Debug awesome wm configurations in Xephyr sessions.</span>
<span class="s"> Use `new` to create a new test config file cloned from your rc.lua</span>
<span class="s"> Use `check` to test the Lua syntax on this file</span>
<span class="s"> Use `start` to start a new awesome debug session</span>
<span class="s"> Use `restart` to restart all awesome debug sessions</span>
<span class="s"> Use `stop` to stop all awesome debug sessions</span>
<span class="s"> """</span>
<span class="n">parser</span> <span class="o">=</span> <span class="n">ArgumentParser</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="n">main_desc</span><span class="p">,</span>
<span class="n">formatter_class</span><span class="o">=</span><span class="n">RawDescriptionHelpFormatter</span><span class="p">)</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">"action"</span><span class="p">,</span> <span class="n">choices</span><span class="o">=</span><span class="p">[</span><span class="s">"new"</span><span class="p">,</span> <span class="s">"check"</span><span class="p">,</span> <span class="s">"start"</span><span class="p">,</span> <span class="s">"restart"</span><span class="p">,</span>
<span class="s">"stop"</span><span class="p">],</span> <span class="n">help</span><span class="o">=</span><span class="s">"the action to perform"</span><span class="p">)</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">"-t"</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="s">"test"</span><span class="p">,</span> <span class="n">action</span><span class="o">=</span><span class="s">"store_true"</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span>
<span class="n">help</span><span class="o">=</span><span class="s">"use created test configuration file"</span><span class="p">)</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">"-s"</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="s">"screen"</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">"the screen resolution"</span><span class="p">)</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">"-d"</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="s">"display"</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">"the DISPLAY to use"</span><span class="p">)</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">"-v"</span><span class="p">,</span> <span class="s">"--version"</span><span class="p">,</span> <span class="n">action</span><span class="o">=</span><span class="s">"version"</span><span class="p">,</span>
<span class="n">version</span><span class="o">=</span><span class="s">"</span><span class="si">%(prog)s</span><span class="s"> {0}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">__version__</span><span class="p">),</span>
<span class="n">help</span><span class="o">=</span><span class="s">"show program's version number and exit"</span><span class="p">)</span>
<span class="k">return</span> <span class="n">parser</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="sd">"""The script core."""</span>
<span class="c"># the files needed</span>
<span class="n">cfg_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="s">"~/.config/awesome"</span><span class="p">)</span>
<span class="n">rc_real</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">cfg_dir</span><span class="p">,</span> <span class="s">"rc.lua"</span><span class="p">)</span>
<span class="n">rc_test</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">cfg_dir</span><span class="p">,</span> <span class="s">"rc_test.lua"</span><span class="p">)</span>
<span class="n">rc_original</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">cfg_dir</span><span class="p">,</span> <span class="s">"rc_original.lua"</span><span class="p">)</span>
<span class="n">xpids_tmp</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">gettempdir</span><span class="p">(),</span> <span class="s">"xpids"</span><span class="p">)</span>
<span class="n">apids_tmp</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">gettempdir</span><span class="p">(),</span> <span class="s">"apids"</span><span class="p">)</span>
<span class="n">log_file</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">cfg_dir</span><span class="p">,</span> <span class="s">"awdt.log"</span><span class="p">)</span>
<span class="n">args</span> <span class="o">=</span> <span class="n">arguments</span><span class="p">()</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span>
<span class="c"># get the current screen resolution</span>
<span class="n">xdpyinfo</span> <span class="o">=</span> <span class="n">Popen</span><span class="p">(</span><span class="s">"xdpyinfo"</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">PIPE</span><span class="p">)</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
<span class="n">currres</span> <span class="o">=</span> <span class="n">findall</span><span class="p">(</span><span class="s">"dimensions:\s*(\d+x\d+)\spixels"</span><span class="p">,</span> <span class="n">xdpyinfo</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="c"># set defaults</span>
<span class="n">args</span><span class="o">.</span><span class="n">screen</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">screen</span> <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">screen</span> <span class="k">else</span> <span class="n">currres</span>
<span class="n">args</span><span class="o">.</span><span class="n">test</span> <span class="o">=</span> <span class="n">rc_test</span> <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">test</span> <span class="k">else</span> <span class="n">rc_original</span>
<span class="n">args</span><span class="o">.</span><span class="n">display</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">display</span> <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">display</span> <span class="k">else</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">action</span> <span class="o">==</span> <span class="s">"new"</span><span class="p">:</span>
<span class="n">copy</span><span class="p">(</span><span class="n">rc_real</span><span class="p">,</span> <span class="n">rc_test</span><span class="p">)</span>
<span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">action</span> <span class="o">==</span> <span class="s">"check"</span><span class="p">:</span>
<span class="n">check</span> <span class="o">=</span> <span class="n">Popen</span><span class="p">(</span><span class="s">"awesome -c {0} -k"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">rc_test</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(),</span> <span class="n">stdout</span><span class="o">=</span><span class="n">PIPE</span><span class="p">,</span>
<span class="n">stderr</span><span class="o">=</span><span class="n">STDOUT</span><span class="p">)</span>
<span class="n">check_out</span> <span class="o">=</span> <span class="n">check</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">readlines</span><span class="p">()</span>
<span class="n">Popen</span><span class="p">([</span><span class="s">"notify-send"</span><span class="p">,</span> <span class="s">"Lua sintax chek:"</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">linesep</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">check_out</span><span class="p">)])</span>
<span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">action</span> <span class="o">==</span> <span class="s">"start"</span><span class="p">:</span>
<span class="c"># clean log in each debug session</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">apids_tmp</span><span class="p">):</span>
<span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">log_file</span><span class="p">):</span>
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">log_file</span><span class="p">)</span>
<span class="n">log</span> <span class="o">=</span> <span class="n">Logger</span><span class="p">()</span>
<span class="n">log</span><span class="o">.</span><span class="n">filename</span> <span class="o">=</span> <span class="n">log_file</span>
<span class="n">log</span><span class="o">.</span><span class="n">header</span><span class="p">(</span><span class="s">"https://github.com/joedicastro/dotfiles"</span><span class="p">,</span>
<span class="s">"This is a log from an Awesome wm's debug session"</span><span class="p">)</span>
<span class="n">log</span><span class="o">.</span><span class="n">time</span><span class="p">(</span><span class="s">"Start time"</span><span class="p">)</span>
<span class="n">x_cmd</span> <span class="o">=</span> <span class="s">"Xephyr -ac -br -noreset -screen {0} :{1}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">screen</span><span class="p">,</span>
<span class="n">args</span><span class="o">.</span><span class="n">display</span><span class="p">)</span>
<span class="n">aw_cmd</span> <span class="o">=</span> <span class="s">"awesome -c {0}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">test</span><span class="p">)</span>
<span class="n">xserver</span> <span class="o">=</span> <span class="n">Popen</span><span class="p">(</span><span class="n">x_cmd</span><span class="o">.</span><span class="n">split</span><span class="p">(),</span> <span class="n">stdout</span><span class="o">=</span><span class="n">PIPE</span><span class="p">,</span> <span class="n">stderr</span><span class="o">=</span><span class="n">STDOUT</span><span class="p">)</span>
<span class="n">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">os</span><span class="o">.</span><span class="n">putenv</span><span class="p">(</span><span class="s">"DISPLAY"</span><span class="p">,</span> <span class="s">":{0}.0"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">display</span><span class="p">))</span>
<span class="n">awesome</span> <span class="o">=</span> <span class="n">Popen</span><span class="p">(</span><span class="n">aw_cmd</span><span class="o">.</span><span class="n">split</span><span class="p">(),</span> <span class="n">stdout</span><span class="o">=</span><span class="n">PIPE</span><span class="p">,</span> <span class="n">stderr</span><span class="o">=</span><span class="n">STDOUT</span><span class="p">)</span>
<span class="c"># save the process PIDs for kill them properly later. This way, no</span>
<span class="c"># matter how many awesome sessions do you start, all of them will be</span>
<span class="c"># reported to the log file. Also, awesome PIDs are used to restart each</span>
<span class="c"># one when is required</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">xpids_tmp</span><span class="p">,</span> <span class="s">'a+'</span><span class="p">)</span> <span class="k">as</span> <span class="n">xpids</span><span class="p">:</span>
<span class="n">xpids</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">xserver</span><span class="o">.</span><span class="n">pid</span><span class="p">)</span> <span class="o">+</span> <span class="n">os</span><span class="o">.</span><span class="n">linesep</span><span class="p">)</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">apids_tmp</span><span class="p">,</span> <span class="s">'a+'</span><span class="p">)</span> <span class="k">as</span> <span class="n">apids</span><span class="p">:</span>
<span class="n">apids</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">awesome</span><span class="o">.</span><span class="n">pid</span><span class="p">)</span> <span class="o">+</span> <span class="n">os</span><span class="o">.</span><span class="n">linesep</span><span class="p">)</span>
<span class="n">log</span><span class="o">.</span><span class="n">list</span><span class="p">(</span><span class="s">"Parameters"</span><span class="p">,</span> <span class="p">[</span><span class="s">"Screen resolution: {0}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">screen</span><span class="p">),</span>
<span class="s">"Display: {0}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">display</span><span class="p">),</span>
<span class="s">"Configuration file: {0}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">test</span><span class="p">)])</span>
<span class="n">log</span><span class="o">.</span><span class="n">list</span><span class="p">(</span><span class="s">"Xephyr output"</span><span class="p">,</span> <span class="n">xserver</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">readlines</span><span class="p">())</span>
<span class="n">log</span><span class="o">.</span><span class="n">list</span><span class="p">(</span><span class="s">"Awesome output"</span><span class="p">,</span> <span class="n">awesome</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">readlines</span><span class="p">())</span>
<span class="n">log</span><span class="o">.</span><span class="n">time</span><span class="p">(</span><span class="s">"End time"</span><span class="p">)</span>
<span class="n">log</span><span class="o">.</span><span class="n">free</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">linesep</span> <span class="o">*</span> <span class="mi">4</span><span class="p">)</span>
<span class="n">log</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
<span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">action</span> <span class="o">==</span> <span class="s">"restart"</span><span class="p">:</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">apids_tmp</span><span class="p">,</span> <span class="s">'r'</span><span class="p">)</span> <span class="k">as</span> <span class="n">apids</span><span class="p">:</span>
<span class="k">for</span> <span class="n">pid</span> <span class="ow">in</span> <span class="n">apids</span><span class="o">.</span><span class="n">readlines</span><span class="p">():</span>
<span class="n">os</span><span class="o">.</span><span class="n">kill</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">pid</span><span class="p">),</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">action</span> <span class="o">==</span> <span class="s">"stop"</span><span class="p">:</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">xpids_tmp</span><span class="p">,</span> <span class="s">'r'</span><span class="p">)</span> <span class="k">as</span> <span class="n">xpids</span><span class="p">:</span>
<span class="k">for</span> <span class="n">pid</span> <span class="ow">in</span> <span class="n">xpids</span><span class="o">.</span><span class="n">readlines</span><span class="p">():</span>
<span class="n">os</span><span class="o">.</span><span class="n">kill</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">pid</span><span class="p">),</span> <span class="mi">9</span><span class="p">)</span>
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">xpids_tmp</span><span class="p">)</span>
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">apids_tmp</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">check_execs</span><span class="p">(</span><span class="s">"Xephyr"</span><span class="p">,</span> <span class="s">"awesome"</span><span class="p">)</span>
<span class="n">main</span><span class="p">()</span>
<span class="c">#==============================================================================</span>
<span class="c"># Changelog:</span>
<span class="c">#==============================================================================</span>
<span class="c">#</span>
<span class="c"># 0.5:</span>
<span class="c">#</span>
<span class="c"># * New log file per debug session</span>
<span class="c"># * Improve argparse help</span>
<span class="c"># * Better comments</span>
<span class="c">#</span>
<span class="c"># 0.4:</span>
<span class="c">#</span>
<span class="c"># * remove debug prints</span>
<span class="c"># * clean code</span>
<span class="c">#</span>
<span class="c"># 0.3:</span>
<span class="c">#</span>
<span class="c"># * implement logging functions</span>
<span class="c"># * check for executables</span>
<span class="c">#</span>
<span class="c"># 0.2:</span>
<span class="c">#</span>
<span class="c"># * argparse instead of sys.argv</span>
<span class="c"># * create a new rc_test.lua file from original</span>
<span class="c"># * restart the awesome session</span>
<span class="c">#</span>
<span class="c"># 0.1:</span>
<span class="c">#</span>
<span class="c"># * First attempt</span>
<span class="c">#</span>
<span class="c">#==============================================================================</span>
</pre></div>Productividad en el escritorio Linux: Xmonad2011-11-26T00:00:00+01:00joe di castrohttp://joedicastro.com/productividad-en-el-escritorio-linux-xmonad.html<p><a href="http://xmonad.org">xmonad</a> es un <a href="http://joedicastro.com/productividad-en-el-escritorio-linux-tiling.html">Gestor de ventanas de mosaico</a>, uno de los más
empleados y de los más potentes. Después de haber probado varios (dwm, bluetile,
wmii y el plugin Compiz Grid) llevo ya unos cuantos meses trabajando con él y
posiblemente siga conmigo mucho, mucho tiempo. Una vez que trabajas con un
<strong>tiling window manager</strong> es muy difícil que echarse atrás, volver a un gestor de
ventanas flotantes tradicional es casi impensable. Probaré uno más,
<a href="http://awesome.naquadah.org">awesome</a>, que promete mucho y solo si este logra convencerme del cambio,
abandonaré Xmonad.</p>
<p>¿Pero que tiene de especial un <strong>twm</strong> como <strong>Xmonad</strong> para haber decidido
abandonar la gestión de ventanas por defecto de Compiz, Gnome Shell, Unity, Kwin,
etc y apostar por él? Cuando uno está cansado de perder el tiempo con maniobras y
decisiones triviales -ajustar las ventanas en la pantalla, que si el navegador por
aquí, que si este terminal por allá, etc y cambiando continuamente la mano del
teclado al ratón y viceversa- pues entonces decides que hay que darle una
oportunidad a un twm, que sea el gestor de ventanas quien haga el trabajo sucio
por ti.</p>
<p>¿Y hasta que punto resuelve bien este problema un twm como Xmonad? En este vídeo
de xmonad trabajando con mi configuración, uno se puede hacer una idea de lo que
es capaz.</p>
<div style="text-align:center">
<iframe src="http://player.vimeo.com/video/33164152?title=0&byline=0&portrait=0"
width="700" height="438">
</iframe>
<p>Esbozo de las posibilidades de un Tiling Window Manager como Xmonad
trabajando conjuntamente con Gnome 3 y Unity 2D sobre un Ubuntu 11.10.
Recomiendo ver en alta resolución y a pantalla completa.</p>
</div>
<p><strong>Xmonad</strong> no necesita de un entorno de escritorio para trabajar, se puede iniciar
una sesión directamente en él, al igual que la mayoría de gestores de ventanas
de mosaico y otros gestores de ventanas como <a href="http://es.wikipedia.org/wiki/Openbox">OpenBox</a>. En el vídeo se puede
apreciar que lo estoy empleando conjuntamente con Unity, en concreto <strong>Unity 2D</strong>.
Esto es así porque emplear Xmonad (u otro twm) de forma autónoma te obliga a
montar una serie de servicios que vienen montados por defecto normalmente en un
escritorio, como salvapantallas, fondo de pantalla, bandeja de sistema, gestor
de red, notificaciones, control de volumen, soporte impresoras, etc. Como estoy
contento con el funcionamiento en general de Gnome, lo mejor es no reinventar la
rueda y aprovechar lo mejor de los dos mundos empleando ambos a la vez.
Anteriormente con Gnome 2, lo tenia funcionando sin Unity, pero con Gnome 3 me
encuentro con la desagradable situación de que Gnome classic (el fallback mode)
tiene un panel que es un autentico desastre y que además no es redimensionable
en altura (tiene 30px y yo lo quiero con 21px). Actualmente hay una
<a href="http://askubuntu.com/questions/69576/how-to-customize-the-gnome-classic-panel/76884#76884">forma de arreglar esto</a>, pero de momento lo tengo montado todo con Unity
2D y no hecho nada en falta. Eso si, de Unity solo empleo el panel, el Global Menu
y la base de Gnome 3, lo demás lo descarto. Resumiendo, que básicamente sustituyo
<code>metacity</code> por <code>xmonad</code>.</p>
<h2 id="xmonad_con_unity_2d">Xmonad con Unity 2D</h2>
<p>Aquí contaré como tengo configurado actualmente <strong>Xmonad</strong> con <strong>Ubuntu 11.10</strong>
(Oneiric Ocelot) y con <strong>Gnome 3</strong> y el panel de <strong>Unity 2D</strong> (<code>unity-2p-panel</code>).
Si alguien continua con Gnome 2D o alguna versión anterior de Ubuntu puede revisar
<a href="http://markhansen.co.nz/xmonad-ubuntu-lucid/">este enlace</a>, la base es muy parecida, y luego solo habría que aplicar mi
configuración (u otra).</p>
<p>Lo primero que se necesita es instalar xmonad, que en Ubuntu viene siendo así:</p>
<div class="codehilite"><pre><span class="nv">$ </span>sudo apt-get install xmonad
</pre></div>
<p>A continuación crearíamos un fichero <code>~/.xmonad/xmonad.hs</code> de configuración
básica</p>
<div class="codehilite"><pre><span class="nv">$ </span>mkdir ~/.xmonad <span class="c"># El carácter ~ se obtiene pulsando Alt Gr + 4</span>
<span class="nv">$ </span>vi ~/.xmonad/xmonad.hs <span class="c"># Puedes emplear gedit en vez de vi si lo prefieres</span>
</pre></div>
<p>e incluiríamos lo siguiente dentro de él:</p>
<div class="codehilite"><pre><span class="kr">import</span> <span class="nn">XMonad</span>
<span class="kr">import</span> <span class="nn">XMonad.Config.Gnome</span>
<span class="nf">myManageHook</span> <span class="ow">=</span> <span class="n">composeAll</span> <span class="p">(</span>
<span class="p">[</span> <span class="n">manageHook</span> <span class="n">gnomeConfig</span>
<span class="p">,</span> <span class="n">className</span> <span class="o">=?</span> <span class="s">"Unity-2d-panel"</span> <span class="o">--></span> <span class="n">doIgnore</span>
<span class="p">,</span> <span class="n">className</span> <span class="o">=?</span> <span class="s">"Unity-2d-launcher"</span> <span class="o">--></span> <span class="n">doFloat</span>
<span class="p">])</span>
<span class="nf">main</span> <span class="ow">=</span> <span class="n">xmonad</span> <span class="n">gnomeConfig</span> <span class="p">{</span> <span class="n">manageHook</span> <span class="ow">=</span> <span class="n">myManageHook</span> <span class="p">}</span>
</pre></div>
<p>Ahora tendríamos que recompilar Xmonad, es algo necesario cada vez que realizamos
algún cambio en la configuración, pero es un proceso que no suele llevar más de
5 segundos (y Xmonad se puede reiniciar sin tener que cerrar la sesión):</p>
<div class="codehilite"><pre><span class="nv">$ </span>xmonad --recompile
</pre></div>
<p>Lo siguiente es crear los ficheros necesarios para crear una nueva sesión de
Gnome. Creamos primero el fichero que define nuestra nueva sesión:</p>
<div class="codehilite"><pre><span class="nv">$ </span>sudo vi /usr/share/gnome-session/sessions/xmonad.session
</pre></div>
<p>y dentro añadimos esto:</p>
<div class="codehilite"><pre><span class="k">[GNOME Session]</span>
<span class="na">Name</span><span class="o">=</span><span class="s">Xmonad Unity 2D</span>
<span class="na">RequiredComponents</span><span class="o">=</span><span class="s">gnome-settings-daemon;</span>
<span class="na">RequiredProviders</span><span class="o">=</span><span class="s">windowmanager;panel;</span>
<span class="na">DefaultProvider-windowmanager</span><span class="o">=</span><span class="s">xmonad</span>
<span class="na">DefaultProvider-panel</span><span class="o">=</span><span class="s">unity-2d-panel</span>
</pre></div>
<p>a continuación creamos el fichero que inicia esta sesión:</p>
<div class="codehilite"><pre><span class="nv">$ </span>sudo vi /usr/share/xsessions/xmonad-unity-session.desktop
</pre></div>
<p>con este contenido:</p>
<div class="codehilite"><pre><span class="k">[Desktop Entry]</span>
<span class="na">Name</span><span class="o">=</span><span class="s">XMonad Unity 2D</span>
<span class="na">Comment</span><span class="o">=</span><span class="s">Tiling window manager</span>
<span class="na">TryExec</span><span class="o">=</span><span class="s">/usr/bin/gnome-session</span>
<span class="na">Exec</span><span class="o">=</span><span class="s">gnome-session --session=xmonad</span>
<span class="na">Type</span><span class="o">=</span><span class="s">XSession</span>
</pre></div>
<p>Con esto estaría ya montada una sesión con la configuración por defecto de
Xmonad funcionado sobre Gnome y empleando el panel de Unity 2D. Ahora solo
tendrías que cerrar la sesión e iniciar la sesión con <em>Xmonad Unity 2D</em>.</p>
<blockquote>
<p><strong>Advertencia:</strong> Por defecto verás que se ha creado automáticamente una sesión
llamada Xmonad al instalar este. Bien, si vas iniciar esa sesión, será mejor
que sepas que para salir tienes que pulsar <strong>Win + Mayús + Q</strong>, porque será una
sesión donde solo tendrás Xmonad, y es la única forma de cerrar la sesión.</p>
</blockquote>
<p>Si queréis hacer alguna prueba con esta configuración básica por defecto, es
mejor tener a mano una referencia con las combinaciones de teclas disponibles,
aquí hay un <a href="http://haskell.org/wikiupload/b/b8/Xmbindings.png">mapa del teclado</a> de referencia que será muy útil.</p>
<h2 id="mi_configuraci+n">Mi configuración</h2>
<p>Para poder emplear la configuración que se puede ver en el vídeo simplemente
habría que editar el fichero <code>~/.xmonad/xmonad.hs</code> y sustituir su contenido por
el de mi fichero de configuración. El contenido del fichero lo incluyo al final
del articulo para no entorpecer la lectura del mismo.</p>
<h3 id="atajos_de_teclado">Atajos de teclado</h3>
<p>Al comienzo del fichero enumero las combinaciones de teclas empleadas en mi
configuración, que difieren de las combinaciones por defecto y se asemejan de
algún modo a las que estaba habituado en Gnome y son más intuitivas para los que
estamos acostumbrados a él. Aunque las que se emplean por defecto también me son
muy familiares al estar basadas en parte en Vim. Voy a detallar algunas de estas
combinaciones.</p>
<h4 id="lanzar_aplicaciones">Lanzar aplicaciones</h4>
<div class="codehilite"><pre><span class="c1">-- Win + Enter Terminal</span>
<span class="c1">-- Win + F1 Nautilus</span>
<span class="c1">-- Win + F2 Firefox (single instance)</span>
<span class="c1">-- Win + F3 Thunderbird (single instance)</span>
<span class="c1">-- Win + F4 RSSOwl (single instance)</span>
<span class="c1">-- Win + F5 Hotot (single instance)</span>
<span class="c1">-- Win + F6 ncmpcpp - MPD player</span>
<span class="c1">-- Win + F7 taskwarrior</span>
<span class="c1">-- Win + F8 PAC (single instance)</span>
<span class="c1">-- Win + F9 Aptana (single instance)</span>
<span class="c1">-- Win + F10 Xmind (single instance)</span>
<span class="c1">-- Win + F11 Dbeaver (single instance)</span>
<span class="c1">-- Win + F12 VirtualBox (single instance)</span>
</pre></div>
<p>Lo primero que se puede ver es una serie de atajos para lanzar aplicaciones
empleando la tecla <strong>Win</strong> más las teclas de función. La tecla <strong>Win</strong> (también
llamada <strong>Super</strong>) es la tecla maestra por defecto de Xmonad (<code>mod4Mask</code>) y es la
que se emplea en combinación con otras para realizar todo tipo de acciones. Estas
combinaciones me permiten lanzar las aplicaciones que uso con más frecuencia con
un par de teclas.</p>
<p>Algunas aparecen con la frase <em>single instance</em> entre paréntesis, esto quiere
decir que de estas aplicaciones solamente se abrirá una ventana. De hecho, lo que
ocurre si volvemos a pulsar la combinación de teclas que abre la aplicación (una
vez que esta ya está abierta) es que en lugar de abrir una nueva, nos movemos a
la ventana ya abierta, esté en el escritorio que esté. Lo que es muy útil para
localizar la ventana de una de estas aplicaciones de forma inmediata.</p>
<p>Adicionalmente la combinación <strong>Alt + Enter</strong> nos permite abrir una ventana del
terminal. En este caso lo tengo predeterminado para que abra una venta de
<code>terminator</code></p>
<h4 id="consola_emergente">Consola emergente</h4>
<div class="codehilite"><pre><span class="c1">-- Win + Space Run or Raise Shell Prompt</span>
<span class="c1">-- Win + Shift + Space Run Shell Prompt</span>
<span class="c1">-- Win + Control + Space Window Prompt</span>
</pre></div>
<p>A continuación podemos ver las teclas dedicadas a la consola emergente inferior
(al estilo de Guake, Yakuake o Tilda) y que según la combinación pulsada
realizara una acción u otra. La consola cuenta con auto-completado de texto, con
lo cual escribiendo las primeras letras se nos muestran todas las coincidencias
disponibles, a través de las que podemos desplazarnos con el tabulador.</p>
<ul>
<li>
<p><strong>Win + Espacio</strong> nos despliega una consola que nos permite lanzar una
aplicación de igual modo que los lanzadores gráficos. Si la aplicación ya se
encuentra abierta, nos dirige a la ventana de la misma.</p>
</li>
<li>
<p><strong>Win + Mayús + Espacio</strong> ejecuta el comando que escribamos. Similar a la
ventana de ejecutar comando de Gnome (<em>Alt + F2</em> en Gnome)</p>
</li>
<li>
<p><strong>Win + Control + Espacio</strong> nos muestra las ventanas que están abiertas en ese
momento. Seleccionando una nos envía directamente a ella. Gracias a esto,
localizar una ventana abierta entre los múltiples escritorios es cuestión de
segundos. Si conocemos el nombre de la ventana podemos filtrarla escribiendo las
primeras letras con el teclado. Imagina una sesión en la que tenemos abiertas más
de 10 aplicaciones en varios escritorios distintos, esto nos permite localizar
una ventana en segundos, es muy útil.</p>
</li>
</ul>
<h4 id="reiniciar_xmonad">Reiniciar Xmonad</h4>
<p>Con la combinación <strong>Win + q</strong> lo que hacemos es reiniciar Xmonad sin necesidad
de reiniciar la sesión. Esto es muy útil cuando introducimos cambios en la
configuración, después de guardar el fichero y ejecutar <code>xmonad --recompile</code> en
un terminal, pulsamos esta combinación y los cambios se reflejaran de forma
inmediata.</p>
<h2 id="transparencias">Transparencias</h2>
<p>Una de las carencias de Xmonad es que no incorpora un <a href="http://es.wikipedia.org/wiki/Gestor_de_composici%C3%B3n_de_ventanas">gestor de composición</a>
por lo que si queremos manejar transparencias en nuestros terminales,
notificaciones, ventanas, etc, debemos emplear uno externo. Para esto empleo
<code>xcompmgr</code> que funciona perfectamente y es muy ligero. Como aún conservo las
otras sesiones de Ubuntu (Unity, Unity 2 D, Gnome Shell, etc) lo que hago para
que solo se ejecute en la sesión de <em>Xmonad Unity 2D</em> es emplear este script bash:</p>
<div class="codehilite"><pre><span class="c">#!/bin/bash</span>
<span class="k">if</span> <span class="o">[</span> <span class="nv">$DESKTOP_SESSION</span> <span class="o">=</span> <span class="s2">"xmonad-unity-session"</span> <span class="o">]</span>; <span class="k">then</span>
<span class="k"> </span>xcompmgr -I1 -O1 -Ff;
<span class="k">fi</span>
</pre></div>
<p>Luego añado el script a las aplicaciones que se ejecutan al inicio de la sesión
y listo.</p>
<h2 id="bandeja_del_sistema">Bandeja del sistema</h2>
<p>Una de las carencias de Unity en la versión 11.10 es que no han incorporado una
bandeja del sistema donde alojar los iconos de aplicaciones que aún no tienen
soporte para los <em>indicadores</em>. Se supone que debería añadirlos de forma
automática al panel, incluso hay una configuración a través de <code>dconf</code> para
habilitar esto, pero no funciona para todas las aplicaciones. Para añadir un
<em>systray</em> empleo un script parecido al anterior para lanzar la aplicación
<code>trayer</code> en esta sesión.</p>
<div class="codehilite"><pre><span class="c">#!/bin/bash</span>
<span class="nv">MYARGS</span><span class="o">=</span><span class="s2">"--edge top --widthtype request --transparent true --alpha 0 --distancefrom right --distance 1100 --height 24 --tint 0x4c4a44 --align right"</span>
<span class="k">if</span> <span class="o">[</span> <span class="nv">$DESKTOP_SESSION</span> <span class="o">=</span> <span class="s2">"xmonad-unity-session"</span> <span class="o">]</span>; <span class="k">then</span>
<span class="k"> </span>sleep 24 <span class="o">&&</span> trayer <span class="nv">$MYARGS</span>;
<span class="k">fi</span>
</pre></div>
<br />
<h2 id="como_personalizar_xmonad_haskell">Como personalizar Xmonad: Haskell</h2>
<p>El mayor inconveniente de Xmonad (y a la vez una de sus ventajas) es que la
configuración es necesario hacerla a través del mismo lenguaje de programación
en el que está creado: <a href="http://haskell.org/haskellwiki/Haskell">Haskell</a>. Esto es una importante barrera de
entrada para los que no conocen el lenguaje, yo incluido, pero a base de ir
probando algunas de las configuraciones aportadas y el prueba y error, puedes
salir del paso muy satisfactoriamente. Con un poco de práctica y estudiando un
poco el lenguaje (que de entrada no es de los más fáciles de leer) y gracias a
la documentación disponible, puedes conseguir exactamente lo que quieres. Y esa es
precisamente también su mayor ventaja, que puedes llegar a un gran nivel de
personalización si conoces Haskell. Además Haskell le proporciona una gran
estabilidad y extensibilidad.</p>
<p>Afortunadamente hay varios recursos disponibles que nos hacen el trabajo más
fácil, porque Xmonad está aceptablemente bien documentado (en Inglés).</p>
<ul>
<li><a href="http://haskell.org/haskellwiki/Xmonad/Screenshots">Pantallazos</a></li>
<li><a href="http://haskell.org/haskellwiki/Xmonad/Config_archive">Ficheros de configuración</a></li>
<li><a href="http://haskell.org/haskellwiki/Xmonad">Wiki</a></li>
<li><a href="http://xmonad.org/xmonad-docs/xmonad/index.html">API Docs</a></li>
<li><a href="http://xmonad.org/xmonad-docs/xmonad-contrib/index.html">API Extensiones Docs</a></li>
</ul>
<h2 id="xmonadhs">Xmonad.hs</h2>
<p>Este es mi mi fichero de configuración de Xmonad:</p>
<div class="codehilite"><pre><span class="c1">-- joe di castro's xmonad.hs</span>
<span class="c1">-- Based on rupa's xmonad.hs, https://github.com/rupa/xmonad</span>
<span class="c1">-- =============================================================== KEY BINDINGS</span>
<span class="c1">------------------------------------------------- Launch (or Raise) Applications</span>
<span class="c1">-- Win + Enter Terminal</span>
<span class="c1">-- Win + F1 Nautilus</span>
<span class="c1">-- Win + F2 Firefox (single instance)</span>
<span class="c1">-- Win + F3 Thunderbird (single instance)</span>
<span class="c1">-- Win + F4 RSSOwl (single instance)</span>
<span class="c1">-- Win + F5 Hotot (single instance)</span>
<span class="c1">-- Win + F6 ncmpcpp - MPD player</span>
<span class="c1">-- Win + F7 taskwarrior</span>
<span class="c1">-- Win + F8 PAC (single instance)</span>
<span class="c1">-- Win + F9 Aptana (single instance)</span>
<span class="c1">-- Win + F10 Xmind (single instance)</span>
<span class="c1">-- Win + F11 Dbeaver (single instance)</span>
<span class="c1">-- Win + F12 VirtualBox (single instance)</span>
<span class="c1">----------------------------------------------------------- Shell/Window prompts</span>
<span class="c1">-- Win + Space Run or Raise Shell Prompt</span>
<span class="c1">-- Win + Shift + Space Run Shell Prompt</span>
<span class="c1">-- Win + Control + Space Window Prompt</span>
<span class="c1">--------------------------------------------------------------------- Navigation</span>
<span class="c1">-- Win + [1..9] Switch to workspace N</span>
<span class="c1">-- Win + Shift + [1..9] Move client to workspace N</span>
<span class="c1">-- Ctrl + Alt + Left/Right Previous/Next workspace</span>
<span class="c1">-- Alt + Tab Focus next window</span>
<span class="c1">-- Alt + Shift + Tab Focus previous window</span>
<span class="c1">-------------------------------------------------------------- Window management</span>
<span class="c1">-- Win + Shift + Left Move window to previous workspace</span>
<span class="c1">-- Win + Shift + Right Move window to next workspace</span>
<span class="c1">-- Win + Control + Left Move window to previous empty workspace</span>
<span class="c1">-- Win + Control + Right Move window to next empty workspace</span>
<span class="c1">-- Ctrl + Up/Down Move focused window up/down</span>
<span class="c1">-- Win + m Toggle focused window Full Screen</span>
<span class="c1">-- Win + n Refresh</span>
<span class="c1">-- Win + - Move focused windows to master area</span>
<span class="c1">-- Win + w (or Alt + F4) Close focused window</span>
<span class="c1">-- Win + t Back to tiling (unfloat floating window)</span>
<span class="c1">-- Win + Shift + t Back All to tiling (unfloat ALL windows)</span>
<span class="c1">------------------------------------------------------------- Layout management</span>
<span class="c1">-- Win + Tab Rotate layouts</span>
<span class="c1">-- Win + Left/Right Shrink/Expand the master area</span>
<span class="c1">-- Win + Up/Down Mirror Shrink/expand</span>
<span class="c1">-- Win + ,/. Increment/Deincrement 1 window in master area</span>
<span class="c1">-- Win + f Hide/Unhide the gnome-panel/status bar</span>
<span class="c1">-- Win + Shift + n Reset current workspace to main layout</span>
<span class="c1">------------------------------------------------------------------ Mosaic Layout</span>
<span class="c1">-- Win + a/z Taller/Wider</span>
<span class="c1">-- Win + Control + n Reset</span>
<span class="c1">------------------------------------------------------------------------- Others</span>
<span class="c1">-- Print Screen Capture screen</span>
<span class="c1">-- Win + q Restart XMonad</span>
<span class="c1">-- Win + Shift + q Close gnome session dialog</span>
<span class="c1">-- ============================================================== MOUSE BINDINGS</span>
<span class="c1">-- Win + Button 1 Float Window and Move by dragging</span>
<span class="c1">-- Win + Button 2 Raise Window to the top</span>
<span class="c1">-- Win + Button 3 Float Window and Resize by dragging</span>
<span class="kr">import</span> <span class="nn">XMonad</span>
<span class="kr">import</span> <span class="k">qualified</span> <span class="nn">XMonad.StackSet</span> <span class="k">as</span> <span class="n">W</span>
<span class="kr">import</span> <span class="k">qualified</span> <span class="nn">Data.Map</span> <span class="k">as</span> <span class="n">M</span>
<span class="kr">import</span> <span class="nn">Data.Monoid</span>
<span class="kr">import</span> <span class="nn">XMonad.Actions.CycleWS</span>
<span class="kr">import</span> <span class="nn">XMonad.Actions.FlexibleResize</span> <span class="k">as</span> <span class="n">Flex</span>
<span class="kr">import</span> <span class="nn">XMonad.Actions.SinkAll</span>
<span class="kr">import</span> <span class="nn">XMonad.Actions.UpdatePointer</span>
<span class="kr">import</span> <span class="nn">XMonad.Actions.WindowGo</span>
<span class="kr">import</span> <span class="nn">XMonad.Hooks.DynamicLog</span>
<span class="kr">import</span> <span class="nn">XMonad.Hooks.EwmhDesktops</span>
<span class="kr">import</span> <span class="nn">XMonad.Hooks.ManageDocks</span>
<span class="kr">import</span> <span class="nn">XMonad.Hooks.ManageHelpers</span>
<span class="kr">import</span> <span class="nn">XMonad.Layout.LayoutHints</span>
<span class="kr">import</span> <span class="nn">XMonad.Layout.NoBorders</span>
<span class="kr">import</span> <span class="nn">XMonad.Layout.ResizableTile</span>
<span class="kr">import</span> <span class="nn">XMonad.Layout.Tabbed</span>
<span class="kr">import</span> <span class="nn">XMonad.Layout.ToggleLayouts</span>
<span class="kr">import</span> <span class="nn">XMonad.Layout.WindowArranger</span>
<span class="kr">import</span> <span class="nn">XMonad.Layout.Mosaic</span>
<span class="kr">import</span> <span class="nn">XMonad.Prompt</span>
<span class="kr">import</span> <span class="nn">XMonad.Prompt.Input</span>
<span class="kr">import</span> <span class="nn">XMonad.Prompt.RunOrRaise</span>
<span class="kr">import</span> <span class="nn">XMonad.Prompt.Shell</span>
<span class="kr">import</span> <span class="nn">XMonad.Prompt.Window</span>
<span class="kr">import</span> <span class="nn">XMonad.Util.Run</span>
<span class="kr">import</span> <span class="nn">XMonad.Util.Scratchpad</span>
<span class="kr">import</span> <span class="nn">XMonad.Util.WorkspaceCompare</span>
<span class="kr">import</span> <span class="nn">XMonad.Util.XSelection</span>
<span class="kr">import</span> <span class="nn">XMonad.Config.Gnome</span>
<span class="c1">-- Mod4 is the Super / Windows key</span>
<span class="nf">winMask</span> <span class="ow">=</span> <span class="n">mod4Mask</span>
<span class="nf">altMask</span> <span class="ow">=</span> <span class="n">mod1Mask</span>
<span class="c1">-- key bindings</span>
<span class="nf">myKeys</span> <span class="n">conf</span><span class="o">@</span><span class="p">(</span><span class="kt">XConfig</span> <span class="p">{</span><span class="kt">XMonad</span><span class="o">.</span><span class="n">modMask</span> <span class="ow">=</span> <span class="n">modMask</span><span class="p">})</span> <span class="ow">=</span> <span class="kt">M</span><span class="o">.</span><span class="n">fromList</span> <span class="o">$</span>
<span class="p">[</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_Return</span> <span class="p">),</span> <span class="n">spawn</span> <span class="o">$</span> <span class="kt">XMonad</span><span class="o">.</span><span class="n">terminal</span> <span class="n">conf</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_F1</span> <span class="p">),</span> <span class="n">spawn</span> <span class="s">"nautilus ~"</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_F2</span> <span class="p">),</span> <span class="n">runOrRaise</span> <span class="s">"firefox"</span> <span class="p">(</span><span class="n">className</span> <span class="o">=?</span> <span class="s">"Firefox"</span><span class="p">))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_F3</span> <span class="p">),</span> <span class="n">runOrRaise</span> <span class="s">"thunderbird"</span> <span class="p">(</span><span class="n">className</span> <span class="o">=?</span> <span class="s">"Thunderbird"</span><span class="p">))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_F4</span> <span class="p">),</span> <span class="n">runOrRaise</span> <span class="s">"./rssowl/RSSOwl"</span> <span class="p">(</span><span class="n">className</span> <span class="o">=?</span> <span class="s">"RSSOwl"</span><span class="p">))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_F5</span> <span class="p">),</span> <span class="n">runOrRaise</span> <span class="s">"hotot"</span> <span class="p">(</span><span class="n">className</span> <span class="o">=?</span> <span class="s">"Hotot"</span><span class="p">))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_F6</span> <span class="p">),</span> <span class="n">spawn</span> <span class="s">"terminator -e ncmpcpp"</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_F7</span> <span class="p">),</span> <span class="n">spawn</span> <span class="s">"terminator -e 'task shell' -p task"</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_F8</span> <span class="p">),</span> <span class="n">runOrRaise</span> <span class="s">"pac"</span> <span class="p">(</span><span class="n">className</span> <span class="o">=?</span> <span class="s">"Pac"</span><span class="p">))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_F9</span> <span class="p">),</span> <span class="n">runOrRaise</span> <span class="s">"./Aptana Studio 3/AptanaStudio3"</span> <span class="p">(</span><span class="n">className</span> <span class="o">=?</span> <span class="s">"Aptana Studio 3"</span><span class="p">))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_F10</span> <span class="p">),</span> <span class="n">runOrRaise</span> <span class="s">"/usr/local/xmind/xmind"</span> <span class="p">(</span><span class="n">className</span> <span class="o">=?</span> <span class="s">"XMind"</span><span class="p">))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_F11</span> <span class="p">),</span> <span class="n">runOrRaise</span> <span class="s">"./dbeaver/dbeaver"</span> <span class="p">(</span><span class="n">className</span> <span class="o">=?</span> <span class="s">"DBeaver"</span><span class="p">))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_F12</span> <span class="p">),</span> <span class="n">runOrRaise</span> <span class="s">"VirtualBox"</span> <span class="p">(</span><span class="n">className</span> <span class="o">=?</span> <span class="s">"VirtualBox"</span><span class="p">))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_space</span> <span class="p">),</span> <span class="n">runOrRaisePrompt</span> <span class="n">mySP</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span> <span class="o">.|.</span> <span class="n">shiftMask</span><span class="p">,</span> <span class="n">xK_space</span> <span class="p">),</span> <span class="n">shellPrompt</span> <span class="n">mySP</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span> <span class="o">.|.</span> <span class="n">controlMask</span><span class="p">,</span> <span class="n">xK_space</span> <span class="p">),</span> <span class="n">windowPromptGoto</span> <span class="n">mySP</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="mi">0</span><span class="p">,</span> <span class="n">xK_Print</span> <span class="p">),</span> <span class="n">unsafeSpawn</span> <span class="s">"gnome-screenshot"</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">altMask</span> <span class="o">.|.</span> <span class="n">controlMask</span><span class="p">,</span> <span class="n">xK_Right</span> <span class="p">),</span> <span class="n">moveTo</span> <span class="kt">Next</span> <span class="p">(</span><span class="kt">WSIs</span> <span class="p">(</span><span class="n">return</span> <span class="o">$</span> <span class="n">not</span> <span class="o">.</span> <span class="p">(</span><span class="o">==</span><span class="s">"NSP"</span><span class="p">)</span> <span class="o">.</span> <span class="kt">W</span><span class="o">.</span><span class="n">tag</span><span class="p">)))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">altMask</span> <span class="o">.|.</span> <span class="n">controlMask</span><span class="p">,</span> <span class="n">xK_Left</span> <span class="p">),</span> <span class="n">moveTo</span> <span class="kt">Prev</span> <span class="p">(</span><span class="kt">WSIs</span> <span class="p">(</span><span class="n">return</span> <span class="o">$</span> <span class="n">not</span> <span class="o">.</span> <span class="p">(</span><span class="o">==</span><span class="s">"NSP"</span><span class="p">)</span> <span class="o">.</span> <span class="kt">W</span><span class="o">.</span><span class="n">tag</span><span class="p">)))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span> <span class="o">.|.</span> <span class="n">shiftMask</span><span class="p">,</span> <span class="n">xK_Right</span> <span class="p">),</span> <span class="n">shiftTo</span> <span class="kt">Next</span> <span class="p">(</span><span class="kt">WSIs</span> <span class="p">(</span><span class="n">return</span> <span class="o">$</span> <span class="n">not</span> <span class="o">.</span> <span class="p">(</span><span class="o">==</span><span class="s">"NSP"</span><span class="p">)</span> <span class="o">.</span> <span class="kt">W</span><span class="o">.</span><span class="n">tag</span><span class="p">)))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span> <span class="o">.|.</span> <span class="n">shiftMask</span><span class="p">,</span> <span class="n">xK_Left</span> <span class="p">),</span> <span class="n">shiftTo</span> <span class="kt">Prev</span> <span class="p">(</span><span class="kt">WSIs</span> <span class="p">(</span><span class="n">return</span> <span class="o">$</span> <span class="n">not</span> <span class="o">.</span> <span class="p">(</span><span class="o">==</span><span class="s">"NSP"</span><span class="p">)</span> <span class="o">.</span> <span class="kt">W</span><span class="o">.</span><span class="n">tag</span><span class="p">)))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span> <span class="o">.|.</span> <span class="n">controlMask</span><span class="p">,</span> <span class="n">xK_Right</span> <span class="p">),</span> <span class="n">shiftTo</span> <span class="kt">Next</span> <span class="kt">EmptyWS</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span> <span class="o">.|.</span> <span class="n">controlMask</span><span class="p">,</span> <span class="n">xK_Left</span> <span class="p">),</span> <span class="n">shiftTo</span> <span class="kt">Prev</span> <span class="kt">EmptyWS</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_Tab</span> <span class="p">),</span> <span class="n">sendMessage</span> <span class="kt">NextLayout</span> <span class="o">>></span> <span class="p">(</span><span class="n">dynamicLogString</span> <span class="n">myPP</span> <span class="o">>>=</span> <span class="nf">\</span><span class="n">d</span><span class="ow">-></span><span class="n">safeSpawn</span> <span class="s">"gnome-osd-client"</span> <span class="p">[</span><span class="n">d</span><span class="p">]))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">altMask</span><span class="p">,</span> <span class="n">xK_Tab</span> <span class="p">),</span> <span class="n">windows</span> <span class="kt">W</span><span class="o">.</span><span class="n">focusDown</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">altMask</span> <span class="o">.|.</span> <span class="n">shiftMask</span><span class="p">,</span> <span class="n">xK_Tab</span> <span class="p">),</span> <span class="n">windows</span> <span class="kt">W</span><span class="o">.</span><span class="n">focusUp</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">controlMask</span><span class="p">,</span> <span class="n">xK_Down</span> <span class="p">),</span> <span class="n">windows</span> <span class="kt">W</span><span class="o">.</span><span class="n">swapDown</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">controlMask</span><span class="p">,</span> <span class="n">xK_Up</span> <span class="p">),</span> <span class="n">windows</span> <span class="kt">W</span><span class="o">.</span><span class="n">swapUp</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_Left</span> <span class="p">),</span> <span class="n">sendMessage</span> <span class="kt">Shrink</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_Right</span> <span class="p">),</span> <span class="n">sendMessage</span> <span class="kt">Expand</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_Down</span> <span class="p">),</span> <span class="n">sendMessage</span> <span class="kt">MirrorShrink</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_Up</span> <span class="p">),</span> <span class="n">sendMessage</span> <span class="kt">MirrorExpand</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_minus</span> <span class="p">),</span> <span class="n">windows</span> <span class="kt">W</span><span class="o">.</span><span class="n">shiftMaster</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_comma</span> <span class="p">),</span> <span class="n">sendMessage</span> <span class="p">(</span><span class="kt">IncMasterN</span> <span class="mi">1</span><span class="p">))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_period</span> <span class="p">),</span> <span class="n">sendMessage</span> <span class="p">(</span><span class="kt">IncMasterN</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_n</span> <span class="p">),</span> <span class="n">refresh</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span> <span class="o">.|.</span> <span class="n">shiftMask</span><span class="p">,</span> <span class="n">xK_n</span> <span class="p">),</span> <span class="n">setLayout</span> <span class="o">$</span> <span class="kt">XMonad</span><span class="o">.</span><span class="n">layoutHook</span> <span class="n">conf</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span> <span class="p">,</span> <span class="n">xK_a</span> <span class="p">),</span> <span class="n">sendMessage</span> <span class="kt">Taller</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span> <span class="p">,</span> <span class="n">xK_z</span> <span class="p">),</span> <span class="n">sendMessage</span> <span class="kt">Wider</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span> <span class="o">.|.</span> <span class="n">controlMask</span><span class="p">,</span> <span class="n">xK_n</span> <span class="p">),</span> <span class="n">sendMessage</span> <span class="kt">Reset</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_m</span> <span class="p">),</span> <span class="n">sendMessage</span> <span class="p">(</span><span class="kt">Toggle</span> <span class="s">"Full"</span><span class="p">)</span> <span class="o">>></span> <span class="p">(</span><span class="n">dynamicLogString</span> <span class="n">myPP</span> <span class="o">>>=</span> <span class="nf">\</span><span class="n">d</span><span class="ow">-></span><span class="n">safeSpawn</span> <span class="s">"gnome-osd-client"</span> <span class="p">[</span><span class="n">d</span><span class="p">]))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_t</span> <span class="p">),</span> <span class="n">withFocused</span> <span class="o">$</span> <span class="n">windows</span> <span class="o">.</span> <span class="kt">W</span><span class="o">.</span><span class="n">sink</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span> <span class="o">.|.</span> <span class="n">shiftMask</span><span class="p">,</span> <span class="n">xK_t</span> <span class="p">),</span> <span class="n">sinkAll</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_f</span> <span class="p">),</span> <span class="n">sendMessage</span> <span class="kt">ToggleStruts</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_w</span> <span class="p">),</span> <span class="n">kill</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">altMask</span><span class="p">,</span> <span class="n">xK_F4</span> <span class="p">),</span> <span class="n">kill</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">xK_q</span> <span class="p">),</span> <span class="n">broadcastMessage</span> <span class="kt">ReleaseResources</span> <span class="o">>></span> <span class="n">restart</span> <span class="s">"xmonad"</span> <span class="kt">True</span><span class="p">)</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span> <span class="o">.|.</span> <span class="n">shiftMask</span><span class="p">,</span> <span class="n">xK_q</span> <span class="p">),</span> <span class="n">spawn</span> <span class="s">"gnome-session-quit"</span><span class="p">)</span>
<span class="p">]</span>
<span class="o">++</span>
<span class="c1">-- mod-[1..9], Switch to workspace N</span>
<span class="c1">-- mod-shift-[1..9], Move client to workspace N</span>
<span class="p">[</span> <span class="p">((</span><span class="n">m</span> <span class="o">.|.</span> <span class="n">winMask</span><span class="p">,</span> <span class="n">k</span><span class="p">),</span> <span class="n">windows</span> <span class="o">$</span> <span class="n">f</span> <span class="n">i</span><span class="p">)</span>
<span class="o">|</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">k</span><span class="p">)</span> <span class="ow"><-</span> <span class="n">zip</span> <span class="p">(</span><span class="kt">XMonad</span><span class="o">.</span><span class="n">workspaces</span> <span class="n">conf</span><span class="p">)</span> <span class="p">[</span><span class="n">xK_1</span> <span class="o">..</span> <span class="n">xK_9</span><span class="p">]</span>
<span class="p">,</span> <span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">m</span><span class="p">)</span> <span class="ow"><-</span> <span class="p">[(</span><span class="kt">W</span><span class="o">.</span><span class="n">greedyView</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="kt">W</span><span class="o">.</span><span class="n">shift</span><span class="p">,</span> <span class="n">shiftMask</span><span class="p">)]</span> <span class="p">]</span>
<span class="c1">-- mouse bindings</span>
<span class="nf">myMouseBindings</span> <span class="p">(</span><span class="kt">XConfig</span> <span class="p">{</span><span class="kt">XMonad</span><span class="o">.</span><span class="n">modMask</span> <span class="ow">=</span> <span class="n">modMask</span><span class="p">})</span> <span class="ow">=</span> <span class="kt">M</span><span class="o">.</span><span class="n">fromList</span> <span class="o">$</span>
<span class="p">[</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">button1</span><span class="p">),</span> <span class="p">(</span><span class="nf">\</span><span class="n">w</span> <span class="ow">-></span> <span class="n">focus</span> <span class="n">w</span> <span class="o">>></span> <span class="n">mouseMoveWindow</span> <span class="n">w</span><span class="p">))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">button2</span><span class="p">),</span> <span class="p">(</span><span class="nf">\</span><span class="n">w</span> <span class="ow">-></span> <span class="n">focus</span> <span class="n">w</span> <span class="o">>></span> <span class="n">windows</span> <span class="kt">W</span><span class="o">.</span><span class="n">shiftMaster</span><span class="p">))</span>
<span class="p">,</span> <span class="p">((</span><span class="n">winMask</span><span class="p">,</span> <span class="n">button3</span><span class="p">),</span> <span class="p">(</span><span class="nf">\</span><span class="n">w</span> <span class="ow">-></span> <span class="n">focus</span> <span class="n">w</span> <span class="o">>></span> <span class="kt">Flex</span><span class="o">.</span><span class="n">mouseResizeWindow</span> <span class="n">w</span><span class="p">))</span> <span class="p">]</span>
<span class="c1">-- decoration theme</span>
<span class="nf">myDeco</span> <span class="ow">=</span> <span class="n">defaultTheme</span>
<span class="p">{</span> <span class="n">activeColor</span> <span class="ow">=</span> <span class="s">"orange"</span>
<span class="p">,</span> <span class="n">inactiveColor</span> <span class="ow">=</span> <span class="s">"#222222"</span>
<span class="p">,</span> <span class="n">urgentColor</span> <span class="ow">=</span> <span class="s">"yellow"</span>
<span class="p">,</span> <span class="n">activeBorderColor</span> <span class="ow">=</span> <span class="s">"orange"</span>
<span class="p">,</span> <span class="n">inactiveBorderColor</span> <span class="ow">=</span> <span class="s">"#222222"</span>
<span class="p">,</span> <span class="n">urgentBorderColor</span> <span class="ow">=</span> <span class="s">"yellow"</span>
<span class="p">,</span> <span class="n">activeTextColor</span> <span class="ow">=</span> <span class="s">"orange"</span>
<span class="p">,</span> <span class="n">inactiveTextColor</span> <span class="ow">=</span> <span class="s">"#222222"</span>
<span class="p">,</span> <span class="n">urgentTextColor</span> <span class="ow">=</span> <span class="s">"yellow"</span>
<span class="p">,</span> <span class="n">decoHeight</span> <span class="ow">=</span> <span class="mi">10</span> <span class="p">}</span>
<span class="c1">-- tab theme</span>
<span class="nf">myTab</span> <span class="ow">=</span> <span class="n">defaultTheme</span>
<span class="p">{</span> <span class="n">activeColor</span> <span class="ow">=</span> <span class="s">"black"</span>
<span class="p">,</span> <span class="n">inactiveColor</span> <span class="ow">=</span> <span class="s">"black"</span>
<span class="p">,</span> <span class="n">urgentColor</span> <span class="ow">=</span> <span class="s">"yellow"</span>
<span class="p">,</span> <span class="n">activeBorderColor</span> <span class="ow">=</span> <span class="s">"orange"</span>
<span class="p">,</span> <span class="n">inactiveBorderColor</span> <span class="ow">=</span> <span class="s">"#222222"</span>
<span class="p">,</span> <span class="n">urgentBorderColor</span> <span class="ow">=</span> <span class="s">"black"</span>
<span class="p">,</span> <span class="n">activeTextColor</span> <span class="ow">=</span> <span class="s">"orange"</span>
<span class="p">,</span> <span class="n">inactiveTextColor</span> <span class="ow">=</span> <span class="s">"#222222"</span>
<span class="p">,</span> <span class="n">urgentTextColor</span> <span class="ow">=</span> <span class="s">"yellow"</span> <span class="p">}</span>
<span class="c1">-- shell prompt theme</span>
<span class="nf">mySP</span> <span class="ow">=</span> <span class="n">defaultXPConfig</span>
<span class="p">{</span> <span class="n">bgColor</span> <span class="ow">=</span> <span class="s">"black"</span>
<span class="p">,</span> <span class="n">fgColor</span> <span class="ow">=</span> <span class="s">"white"</span>
<span class="p">,</span> <span class="n">bgHLight</span> <span class="ow">=</span> <span class="s">"gray"</span>
<span class="p">,</span> <span class="n">fgHLight</span> <span class="ow">=</span> <span class="s">"black"</span>
<span class="p">,</span> <span class="n">borderColor</span> <span class="ow">=</span> <span class="s">"orange"</span>
<span class="p">,</span> <span class="n">promptBorderWidth</span> <span class="ow">=</span> <span class="mi">2</span>
<span class="p">,</span> <span class="n">position</span> <span class="ow">=</span> <span class="kt">Bottom</span>
<span class="p">,</span> <span class="n">height</span> <span class="ow">=</span> <span class="mi">40</span>
<span class="c1">--, autoComplete = Just 1000</span>
<span class="p">,</span> <span class="n">historySize</span> <span class="ow">=</span> <span class="mi">1000</span> <span class="p">}</span>
<span class="c1">-- dynamicLog theme (suppress everything but layout)</span>
<span class="nf">myPP</span> <span class="ow">=</span> <span class="n">defaultPP</span>
<span class="p">{</span> <span class="n">ppLayout</span> <span class="ow">=</span> <span class="p">(</span><span class="nf">\</span> <span class="n">x</span> <span class="ow">-></span> <span class="kr">case</span> <span class="n">x</span> <span class="kr">of</span>
<span class="s">"Hinted ResizableTall"</span> <span class="ow">-></span> <span class="s">"[|]"</span>
<span class="s">"Mirror Hinted ResizableTall"</span> <span class="ow">-></span> <span class="s">"[-]"</span>
<span class="s">"Hinted Tabbed Simplest"</span> <span class="ow">-></span> <span class="s">"[T]"</span>
<span class="s">"Mosaic"</span> <span class="ow">-></span> <span class="s">"[M]"</span>
<span class="s">"Full"</span> <span class="ow">-></span> <span class="s">"[ ]"</span>
<span class="kr">_</span> <span class="ow">-></span> <span class="n">x</span> <span class="p">)</span>
<span class="p">,</span> <span class="n">ppCurrent</span> <span class="ow">=</span> <span class="n">const</span> <span class="s">""</span>
<span class="p">,</span> <span class="n">ppVisible</span> <span class="ow">=</span> <span class="n">const</span> <span class="s">""</span>
<span class="p">,</span> <span class="n">ppHidden</span> <span class="ow">=</span> <span class="n">const</span> <span class="s">""</span>
<span class="p">,</span> <span class="n">ppHiddenNoWindows</span> <span class="ow">=</span> <span class="n">const</span> <span class="s">""</span>
<span class="p">,</span> <span class="n">ppUrgent</span> <span class="ow">=</span> <span class="n">const</span> <span class="s">""</span>
<span class="p">,</span> <span class="n">ppTitle</span> <span class="ow">=</span> <span class="n">const</span> <span class="s">""</span>
<span class="p">,</span> <span class="n">ppWsSep</span> <span class="ow">=</span> <span class="s">""</span>
<span class="p">,</span> <span class="n">ppSep</span> <span class="ow">=</span> <span class="s">""</span> <span class="p">}</span>
<span class="c1">-- layouts</span>
<span class="nf">myLayout</span> <span class="ow">=</span> <span class="n">avoidStruts</span> <span class="o">$</span> <span class="n">toggleLayouts</span> <span class="p">(</span><span class="n">noBorders</span> <span class="kt">Full</span><span class="p">)</span>
<span class="p">(</span><span class="n">smartBorders</span> <span class="p">(</span><span class="n">tiled</span> <span class="o">|||</span> <span class="n">mosaic</span> <span class="mi">2</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">|||</span> <span class="kt">Mirror</span> <span class="n">tiled</span> <span class="o">|||</span> <span class="n">layoutHints</span> <span class="p">(</span><span class="n">tabbed</span> <span class="n">shrinkText</span> <span class="n">myTab</span><span class="p">)))</span>
<span class="kr">where</span>
<span class="n">tiled</span> <span class="ow">=</span> <span class="n">layoutHints</span> <span class="o">$</span> <span class="kt">ResizableTall</span> <span class="n">nmaster</span> <span class="n">delta</span> <span class="n">ratio</span> <span class="kt">[]</span>
<span class="n">nmaster</span> <span class="ow">=</span> <span class="mi">1</span>
<span class="n">delta</span> <span class="ow">=</span> <span class="mi">2</span><span class="o">/</span><span class="mi">100</span>
<span class="n">ratio</span> <span class="ow">=</span> <span class="mi">1</span><span class="o">/</span><span class="mi">2</span>
<span class="c1">-- special windows</span>
<span class="nf">myManageHook</span> <span class="ow">=</span> <span class="n">composeAll</span>
<span class="p">[</span> <span class="n">className</span> <span class="o">=?</span> <span class="s">"MPlayer"</span> <span class="o">--></span> <span class="n">doFloat</span>
<span class="p">,</span> <span class="n">className</span> <span class="o">=?</span> <span class="s">"Gimp-2.6"</span> <span class="o">--></span> <span class="n">doFloat</span>
<span class="p">,</span> <span class="n">className</span> <span class="o">=?</span> <span class="s">"Gnome-panel"</span> <span class="o">--></span> <span class="n">doIgnore</span>
<span class="p">,</span> <span class="n">className</span> <span class="o">=?</span> <span class="s">"XVkbd"</span> <span class="o">--></span> <span class="n">doIgnore</span>
<span class="p">,</span> <span class="n">className</span> <span class="o">=?</span> <span class="s">"Cellwriter"</span> <span class="o">--></span> <span class="n">doIgnore</span>
<span class="p">,</span> <span class="n">className</span> <span class="o">=?</span> <span class="s">"Gtkdialog"</span> <span class="o">--></span> <span class="n">doFloat</span>
<span class="p">,</span> <span class="n">resource</span> <span class="o">=?</span> <span class="s">"desktop_window"</span> <span class="o">--></span> <span class="n">doIgnore</span>
<span class="p">,</span> <span class="n">className</span> <span class="o">=?</span> <span class="s">"Xmessage"</span> <span class="o">--></span> <span class="n">doCenterFloat</span>
<span class="p">,</span> <span class="n">className</span> <span class="o">=?</span> <span class="s">"Unity-2d-panel"</span> <span class="o">--></span> <span class="n">doIgnore</span>
<span class="p">,</span> <span class="n">isFullscreen</span> <span class="o">--></span> <span class="n">doFullFloat</span>
<span class="p">,</span> <span class="n">isDialog</span> <span class="o">--></span> <span class="n">doCenterFloat</span>
<span class="p">,</span> <span class="n">title</span> <span class="o">=?</span> <span class="s">"RSSOwl"</span> <span class="o">--></span> <span class="n">doIgnore</span>
<span class="p">,</span> <span class="n">title</span> <span class="o">=?</span> <span class="s">"Dbeaver"</span> <span class="o">--></span> <span class="n">doIgnore</span>
<span class="p">,</span> <span class="n">title</span> <span class="o">=?</span> <span class="s">"Xmind-bin"</span> <span class="o">--></span> <span class="n">doIgnore</span>
<span class="p">,</span> <span class="n">title</span> <span class="o">=?</span> <span class="s">"AptanaStudio3"</span> <span class="o">--></span> <span class="n">doIgnore</span>
<span class="p">,</span> <span class="n">resource</span> <span class="o">=?</span> <span class="s">"sun-awt-X11-XDialogPeer"</span> <span class="o">--></span> <span class="n">doCenterFloat</span>
<span class="p">,</span> <span class="n">title</span> <span class="o">=?</span> <span class="s">"screenkey"</span> <span class="o">--></span> <span class="n">doIgnore</span>
<span class="p">,</span> <span class="n">className</span> <span class="o">=?</span> <span class="s">"Gloobus-preview"</span> <span class="o">--></span> <span class="n">doCenterFloat</span>
<span class="c1">-- x y w h</span>
<span class="p">,</span> <span class="n">scratchpadManageHook</span> <span class="o">$</span> <span class="kt">W</span><span class="o">.</span><span class="kt">RationalRect</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">1</span> <span class="mf">0.42</span>
<span class="p">,</span> <span class="n">manageDocks</span> <span class="p">]</span> <span class="o"><+></span> <span class="n">manageHook</span> <span class="n">defaultConfig</span>
<span class="c1">-- let Gnome know about Xmonad actions</span>
<span class="nf">myLogHook</span> <span class="ow">=</span> <span class="n">ewmhDesktopsLogHookCustom</span> <span class="n">scratchpadFilterOutWorkspace</span> <span class="o">>></span> <span class="n">updatePointer</span> <span class="p">(</span><span class="kt">Relative</span> <span class="mf">0.5</span> <span class="mf">0.5</span><span class="p">)</span>
<span class="nf">myConfig</span> <span class="ow">=</span> <span class="n">ewmh</span> <span class="n">defaultConfig</span>
<span class="p">{</span> <span class="n">terminal</span> <span class="ow">=</span> <span class="s">"terminator"</span>
<span class="p">,</span> <span class="n">borderWidth</span> <span class="ow">=</span> <span class="mi">2</span>
<span class="p">,</span> <span class="n">normalBorderColor</span> <span class="ow">=</span> <span class="s">"black"</span>
<span class="p">,</span> <span class="n">focusedBorderColor</span> <span class="ow">=</span> <span class="s">"orange"</span>
<span class="p">,</span> <span class="n">focusFollowsMouse</span> <span class="ow">=</span> <span class="kt">True</span>
<span class="p">,</span> <span class="n">modMask</span> <span class="ow">=</span> <span class="n">mod4Mask</span>
<span class="p">,</span> <span class="n">keys</span> <span class="ow">=</span> <span class="n">myKeys</span>
<span class="p">,</span> <span class="n">mouseBindings</span> <span class="ow">=</span> <span class="n">myMouseBindings</span>
<span class="p">,</span> <span class="n">layoutHook</span> <span class="ow">=</span> <span class="n">myLayout</span>
<span class="p">,</span> <span class="n">manageHook</span> <span class="ow">=</span> <span class="n">myManageHook</span>
<span class="p">,</span> <span class="n">startupHook</span> <span class="ow">=</span> <span class="n">gnomeRegister</span>
<span class="p">}</span>
<span class="c1">-- need to override ewmh's logHook cause I'm using Scratchpad</span>
<span class="nf">main</span> <span class="ow">=</span> <span class="n">xmonad</span> <span class="o">$</span> <span class="n">myConfig</span>
<span class="p">{</span> <span class="n">logHook</span> <span class="ow">=</span> <span class="n">myLogHook</span> <span class="p">}</span>
</pre></div>Productividad en el escritorio Linux: Tiling2011-11-25T00:00:00+01:00joe di castrohttp://joedicastro.com/productividad-en-el-escritorio-linux-tiling.html<p>Los <strong>Gestores de Ventanas de Mosaico</strong> (<a href="http://en.wikipedia.org/wiki/Tiling_window_manager">Tiling Windows Manager</a>) son el
gran desconocido entre la mayoría de usuarios de Linux. Y sin embargo, a mi
juicio, suponen el salto más importante en productividad en el escritorio linux
que se haya producido en mucho tiempo. Permiten manejar todo el escritorio sin
apenas despegar las manos del teclado y sin verse relegado a emplear únicamente
la consola. Las ventanas se distribuyen ellas solas de forma automática por la
pantalla y no es necesario emplear el ratón para moverlas y redimensionarlas
(aunque puede seguir empleándose, naturalmente).</p>
<p>A diferencia de un gestor de ventanas tradicional, a los que estamos normalmente
acostumbrados, las ventanas no se apilan y flotan unas encima de otras, si no
que se redistribuyen por toda la pantalla de acorde a un esquema previo (variable)
sin solaparse entre ellas, quedando todas a la vista de forma simultanea. De ahí
el símil del mosaico, donde el mismo seria el escritorio y donde las ventanas
serian las teselas que lo componen. Puede no ser fácil visualizar de entrada en
que consiste exactamente esto y como funciona, luego los vídeos nos ayudarán a
entender mejor de lo que estoy hablando. Aunque uno no aprecia realmente las
ventajas que aportan hasta que prueba uno. </p>
<h2 id="+que_ventajas_tienen">¿Que ventajas tienen?</h2>
<p>Primero mencionar que esto no es una idea nueva, ni mucho menos, esto ya lo
inventó en 1981 <strong>Xerox</strong> (el inventor a su vez de los entornos de ventanas) e
incluso MS Windows 1.0 lo empleaba. La razón de que algo desarrollado desde hace
dos décadas aún no haya llamado demasiado la atención hasta ahora, es bien
sencilla, el triunfo de un dispositivo de entrada más amigable e intuitivo que
el teclado: el ratón. La metáfora de el entorno de ventanas con el escritorio
junto con la del ratón como la extensión de nuestro brazo, propiciaba que fuera
lo más natural emplearlo para mover las ventanas y redimensionarlas. Pero que
sea más fácil o intuitivo no quiere decir que sea más eficiente, nadie en su sano
juicio escribiría un documento empleando el ratón sobre un teclado virtual ni
realizaría retoque fotográfico empleando únicamente el teclado. ¿Pero cuantos
dirían que el teclado es el medio más eficiente para manejar las ventanas?</p>
<p>En una pantalla de grandes dimensiones y elevada resolución (e.g. un
monitor de 24" y 1920x1200) es muy frecuente andar redimensionando continuamente
las ventanas para acomodarlas y redistribuirlas dentro del escritorio. Nos sobra
espacio por todos los lados y la mayoría de las aplicaciones que en monitores y
resoluciones menores empleábamos maximizadas, ahora son incomodas de usar a
pantalla completa (e.g. navegador web). ¿No sería útil que las ventanas se
recolocaran y redimensionaran automáticamente por si solas? Más o menos esto es
lo que viene a hacer un gestor de ventanas de mosaico. </p>
<p>Pero cuales son las ventajas reales de este sistema:</p>
<ul>
<li>
<p><strong>Las ventanas se organizan solas</strong>, muchas veces no necesitas mover o
redimensionar una ventana, simplemente aparece en un lugar adecuado y con las
dimensiones adecuadas. Una vez le que coges el truco te organizas de manera que
esto ocurre con cierta naturalidad.</p>
</li>
<li>
<p><strong>Se aprovecha todo el espacio de la pantalla</strong>. Las ventanas se ajustan a todo
el espacio libre disponible del escritorio. Aún así pueden emplearse paneles,
docks, ...</p>
</li>
<li>
<p>Las ventanas normalmente apenas tienen marco y carecen de barra de titulo y
decoraciones, por lo tanto se ahorra espacio. Combinado con un menú integrado
como el <em>Global Menu</em> de Unity, <strong>se ahorra mucho espacio</strong>.</p>
</li>
<li>
<p><strong>No es un método excluyente</strong>, aún se pueden emplear con toda normalidad las
ventanas flotantes como habitualmente. Incluso pueden convivir entre ellas sin
problema alguno.</p>
</li>
<li>
<p><strong>En un sistema de múltiples monitores se facilita mucho el manejo de las
múltiples ventanas</strong> y el tener simultáneamente abiertas un número elevado de
ellas es algo realmente sencillo. </p>
</li>
<li>
<p><strong>Es posible automatizar el tamaño, posición y escritorio virtual en donde se
situara la ventana(s) de una aplicación al iniciarse</strong>, lo que abre un mundo de
posibilidades. </p>
</li>
<li>
<p><strong>Es posible tener múltiples escritorios virtuales (usualmente 9 por monitor)
con características distintas en cada uno</strong>. Puede ser un esquema distinto
(desde una simple rejilla a un escritorio normal) o un escritorio para cada tarea
(e.g. 1 - navegar, 2 - correo y redes sociales, 3 - trabajo, 4 - terminales, ...)</p>
</li>
<li>
<p><strong>Mover las ventanas, redimensionarlas, lanzar aplicaciones, cerrarlas, ... y
manejar los escritorios virtuales desde el teclado</strong> es mucho más eficiente que
emplear el ratón para lo mismo.</p>
</li>
<li>
<p><strong>Te olvidas de buscar una ventana entre la pila de ventanas flotantes</strong> sobre
el escritorio, es sencillo incluso encontrar una ventana dentro de otro
escritorio virtual (con unos gestores más que otros). Los escritorios modernos
permiten mostrar un mosaico con todas las aplicaciones abiertas (Exposé, Scale,
...), ¿pero que ocurre cuando tienes abiertas cerca de 30? con un twm la localizas enseguida si lo configuras adecuadamente, en mi caso menos de 2 segundos.</p>
</li>
<li>
<p><strong>Te permite organizar las ventanas en función de múltiples patrones distintos:</strong>
rejillas, columnas, filas, espirales, por pestañas, etc... de forma automática,
acomodándose a múltiples situaciones distintas.</p>
</li>
<li>
<p><strong>Se pueden emplear de forma autónoma, sin un escritorio detrás</strong> (gnome, kde,
...) lo que permite tener un sistema muy ligero ideal para equipos poco potentes. </p>
</li>
<li>
<p><strong>Puede ser una manera de mejorar la accesibilidad del escritorio</strong> para
aquellos que encuentren dificultades para manejar un ratón pero puedan defenderse
con un teclado.</p>
</li>
</ul>
<h2 id="inconvenientes">Inconvenientes</h2>
<p>No son para todo el mundo. Soy plenamente consciente de ello, una buena mayoría
de los usuarios son reticentes a aprenderse los atajos de teclado de una
aplicación (hay quien no sabe cortar y pegar desde él), así que entiendo
perfectamente que siquiera lleguen a plantearse el emplearlos. De hecho los
tímidos avances que están realizando los escritorios en este sentido implican el
uso del ratón para implantar un sucedáneo de este sistema. También es una
cuestión de gustos, habrá a quien simplemente la desagradará el como funciona
este sistema.</p>
<p>Por otro lado los profesionales multimedia que requieren un uso elevado del ratón
probablemente prefieran seguir empleando un gestor de ventanas tradicional,
aunque los gestores de mosaico pueden moverse con soltura en este entorno. </p>
<p>También es cierto que la mayoría de ellos requieren un esfuerzo por nuestra
parte para configurarlos a nuestro gusto. Aunque es precisamente esto lo que nos
permite configurarlos exactamente a nuestro gusto, con muchas posibilidades de
configuración. Pero es una barrera de entrada importante para los gestores más
potentes y completos. Alguno hasta requiere conocimientos en algún lenguaje de
programación (C, Lua, Haskell)</p>
<p>Aunque por un lado pueden suponer una ventaja en la accesibilidad a determinados
discapacitados, pueden suponer un escollo para otros, pues no están tan adaptados
como puedan estarlo los escritorios tradicionales para determinadas
discapacidades.</p>
<h2 id="tipos_de_gestores">Tipos de gestores</h2>
<p>Básicamente existen dos tipos de gestores de ventanas de mosaico, en función de
el modo de organización de las ventanas. </p>
<ul>
<li>
<p><strong><em>Manuales</em></strong>, requieren que el usuario sea quien decida la posición (a veces
el tamaño) de las ventanas, con el inconveniente de la perdida de tiempo a costa
de lograr un control más preciso.</p>
</li>
<li>
<p><strong><em>Automáticos</em></strong>, ajustan automáticamente la posición y el tamaño de las
ventanas en función del esquema por defecto. Posteriormente podemos variar tanto
el esquema como la posición y tamaño de las ventanas individuales.</p>
</li>
</ul>
<h2 id="adaptaci+n_de_la_idea_en_los_escritorios_m+s_comunes">Adaptación de la idea en los escritorios más comunes</h2>
<p>Tal y como ocurre con los lanzadores de aplicaciones, los escritorios más
tradiciones de linux comienzan a incorporar esta idea a sus desarrollos, en
mayor o menor medida. Unity, Compiz, Gnome y KDE se han atrevido a dar un paso
en esta dirección en sus últimas versiones:</p>
<ul>
<li>
<p><strong>Compiz Grid</strong>, es un plugin de Compiz que permite realizar un tiling
primitivo, empleando el ratón o el teclado. Divide la pantalla en una rejilla de
3 x 3 y permite que las ventanas se ajusten al tamaño de una cuadricula o varias.
Manejarlo desde el teclado es muy sencillo, simplemente pulsamos Ctrl + Alt + una
tecla del teclado numérico del 1 al 9 según la cuadricula a la que la queramos
ajustar la ventana. Para cambiar el tamaño de la ventana mantenemos pulsadas las
teclas Ctrl + Alt y volvemos a pulsar la tecla numérica las veces que sea
necesario hasta tener el tamaño que deseemos. Es decir, si pulsamos Ctrl+Alt+7
nos sitúa la ventana en la parte superior izquierda de la pantalla ocupando 1/9
de la misma. </p>
</li>
<li>
<p><strong>Unity</strong>, emplea el plugin Grid de compiz anterior, pero modificado desde la
versión 11.10 para que se comporte como ellos desean. En este vídeo se puede ver
como se comporta este plugin manejándolo desde el teclado. Personalmente opino
que mejor lo hubieran dejado como estaba.</p>
</li>
</ul>
<div style="text-align:center">
<iframe src="http://player.vimeo.com/video/32746967?title=0&byline=0&portrait=0"
width="700" height="438">
</iframe>
<p>Demostración del tiling básico del plugin
de Compiz, Grid, en Ubuntu 11.10 con Unity</p>
</div>
<ul>
<li>
<p><strong>Gnome Shell</strong>, tiene un tiling muy básico parecido al que emplea Unity. Te
permite maximizar una ventana o ajustarla a la mitad derecha/izquierda de la
pantalla simplemente arrastrándola al borde correspondiente.</p>
</li>
<li>
<p><strong>KDE</strong> a partir de la versión 4.4 tiene un tiling bastante conseguido, aunque
no tan avanzado como los gestores dedicados. Desde luego es el escritorio que ha
apostado más fuerte por este sistema y el que mejores resultados obtiene. Aunque
no viene activarlo por defecto, es necesario activarlo a mano. De momento solo
permite elegir entre dos esquemas predeterminados: columnas y espiral (fibonacci).</p>
</li>
</ul>
<h3 id="aplicaciones_que_funcionan_como_un_gestor">Aplicaciones que funcionan como un gestor</h3>
<p>Para aquellos que no quieran instalar un gestor o no empleen uno de los entornos
de escritorio anteriores, siempre existe la posibilidad de emplear alguna de
estas aplicaciones que emulan el comportamiento básico de un gestor de ventanas
de mosaico. Ambos son del tipo manual.</p>
<ul>
<li>
<p><a href="http://ssokolow.github.com/quicktile/">QuickTile</a>, es un script en python que ofrece las mismas funcionalidades
que el plugin Grid de Compiz. </p>
</li>
<li>
<p><a href="http://www.giuspen.com/x-tile/">x tile</a>, es una aplicación instalable (viene en los repositorios de
algunas distros) que ofrece más opciones que la anterior. </p>
</li>
</ul>
<h2 id="gestores_m+s_populares">Gestores más populares</h2>
<p>Hay muchos y para todos los gustos. Incluso los hay disponibles para otros SOs
como Mac OS X o Windows (es muy famoso el WinSplit-Revolution para Windows, en
el que se basa el plugin Grid, aunque los primeros gestores para linux son del
2000 y WinSplit aparece en el 2007). Me centrare aquí solo en los más populares.</p>
<h3 id="awesomeaw"><a href="http://awesome.naquadah.org/">awesome</a></h3>
<p>Automático. Escrito en <em>C</em> y <em>Lua</em>, es configurable y extensible en <em>Lua</em>. Basado
en <strong>dwm</strong></p>
<p>Uno de los dos grandes, junto con <strong>Xmonad</strong>. Es quizá el que más opciones
presenta hoy en día. Está basado en XCB en vez de Xlib, lo que le proporciona
mayor agilidad. Aporta su propia barra de información, bandeja del sistema
(systray) y lanzador de aplicaciones integrado. Tiene un soporte de ratón
superior a la competencia. Pero su desarrollo no es aún solido, varía demasiado a
lo largo de las distintas versiones y te obliga a reconfigurarlo cada vez que
sale una nueva. Le he dedicado un <a href="http://joedicastro.com/productividad-en-el-escritorio-linux-awesome.html">articulo completo</a> </p>
<br />
<h3 id="bluetilebt"><a href="http://bluetile.org/">bluetile</a></h3>
<p>Automático. Escrito en <em>Haskell</em>. Basado en <strong>Xmonad</strong></p>
<p>Es uno de los más sencillos de utilizar y de los más sencillos de probar. Es el
más adecuado para probar por primera vez para los que se inician en esto. Está
pensado para emplear conjuntamente con Gnome y pensando para que los están
acostumbrados al ratón lo usen indistintamente con el teclado. En el siguiente
vídeo realizado por su autor, Jan Vornberger, se puede ver como funciona:</p>
<div style="text-align:center">
<iframe src="http://player.vimeo.com/video/6661713?title=0&byline=0&portrait=0" width="667" height="500"></iframe>
</div>
<br />
<h3 id="dwmdwm"><a href="http://dwm.suckless.org/">dwm</a></h3>
<p>Automático. Escrito, configurable y extensible en <em>C</em>. </p>
<p>Uno de los más ligeros, rápidos y simples. Su configuración se hace modificando
su código fuente en <em>C</em> y luego hay que recompilarlo y reiniciarlo. Esto lo
limita a usuarios avanzados con conocimientos de programación. Su diseño
minimalista ha sido la inspiración para los dos más grandes: Awesome y Xmonad. </p>
<p>Para lanzar las aplicaciones se desarrolló <strong>dmenu</strong> un lanzador basado en texto,
que es muy empleado en otros gestores. Funciona al igual que los lanzadores
gráficos como Gnome Do. </p>
<br />
<h3 id="i3i3"><a href="http://i3wm.org/">i3</a></h3>
<p>Manual. Escrito en <em>C</em> y configurable con ficheros de texto. Basado en <strong>wmii</strong></p>
<p>Muy sencillo y que presume de estar bien documentado. Fácil de usar y configurar.
Es manual, lo que le permite crear esquemas muy flexibles y personalizados, pero
que por otro lado le resta comodidad. </p>
<br />
<h3 id="wmiiwmii"><a href="http://wmii.suckless.org/">wmii</a></h3>
<p>Manual. Escrito en <em>C</em> y configurable en <em>bash</em>, <em>rc</em>, <em>ruby</em> o <em>python</em></p>
<p>Escrito por el mismo desarrollador que <strong>dwm</strong>. Digamos que es el gestor
equivalente a <strong>dwm</strong> pero manual. </p>
<br />
<h3 id="xmonadxmnd"><a href="http://xmonad.org/">xmonad</a></h3>
<p>Automático. Escrito, extensible y configurable en <em>Haskell</em>. Inspirado en <strong>dwm</strong></p>
<p>Muy potente, estable y con muchas opciones. Es altamente personalizable, con
muchas extensiones disponibles. Se integra muy bien con Gnome y KDE. Tiene un
desarrollo muy activo y una gran comunidad de usuarios detrás. Es el que empleo
desde hace meses y le he dedicado un <a href="http://joedicastro.com/productividad-en-el-escritorio-linux-xmonad.html">articulo completo</a>.</p>
<br />
<p>Todos estos gestores están incluidos en los repositorios de Ubuntu, Debian,
Gentoo y Arch Linux, y la mayoría están disponibles también en otras
distribuciones. </p>
<p>Como curiosidad, mencionar otros dos, que aunque no son muy populares, están desarrollados en Python: <a href="http://sourceforge.net/projects/tritium/">tritium</a> y <a href="http://qtile.org/">qtile</a></p>