Productividad en el escritorio Linux: Xmonad

Públicado el sáb 26 noviembre 2011

xmonad es un Gestor de ventanas de mosaico, 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 tiling window manager es muy difícil que echarse atrás, volver a un gestor de ventanas flotantes tradicional es casi impensable. Probaré uno más, awesome, que promete mucho y solo si este logra convencerme del cambio, abandonaré Xmonad.

¿Pero que tiene de especial un twm como Xmonad 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.

¿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.

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.

Xmonad 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 OpenBox. En el vídeo se puede apreciar que lo estoy empleando conjuntamente con Unity, en concreto Unity 2D. 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 forma de arreglar esto, 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 metacity por xmonad.

Xmonad con Unity 2D

Aquí contaré como tengo configurado actualmente Xmonad con Ubuntu 11.10 (Oneiric Ocelot) y con Gnome 3 y el panel de Unity 2D (unity-2p-panel). Si alguien continua con Gnome 2D o alguna versión anterior de Ubuntu puede revisar este enlace, la base es muy parecida, y luego solo habría que aplicar mi configuración (u otra).

Lo primero que se necesita es instalar xmonad, que en Ubuntu viene siendo así:

$ sudo apt-get install xmonad

A continuación crearíamos un fichero ~/.xmonad/xmonad.hs de configuración básica

$ mkdir ~/.xmonad           # El carácter ~ se obtiene pulsando Alt Gr + 4
$ vi ~/.xmonad/xmonad.hs    # Puedes emplear gedit en vez de vi si lo prefieres

e incluiríamos lo siguiente dentro de él:

import XMonad
import XMonad.Config.Gnome

myManageHook = composeAll (
    [ manageHook gnomeConfig
    , className =? "Unity-2d-panel" --> doIgnore
    , className =? "Unity-2d-launcher" --> doFloat
    ])

main = xmonad gnomeConfig { manageHook = myManageHook }

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):

$ xmonad --recompile

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:

$ sudo vi /usr/share/gnome-session/sessions/xmonad.session

y dentro añadimos esto:

[GNOME Session]
Name=Xmonad Unity 2D
RequiredComponents=gnome-settings-daemon;
RequiredProviders=windowmanager;panel;
DefaultProvider-windowmanager=xmonad
DefaultProvider-panel=unity-2d-panel

a continuación creamos el fichero que inicia esta sesión:

$ sudo vi /usr/share/xsessions/xmonad-unity-session.desktop

con este contenido:

[Desktop Entry]
Name=XMonad Unity 2D
Comment=Tiling window manager
TryExec=/usr/bin/gnome-session
Exec=gnome-session --session=xmonad
Type=XSession

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 Xmonad Unity 2D.

Advertencia: 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 Win + Mayús + Q, porque será una sesión donde solo tendrás Xmonad, y es la única forma de cerrar la sesión.

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 mapa del teclado de referencia que será muy útil.

Mi configuración

Para poder emplear la configuración que se puede ver en el vídeo simplemente habría que editar el fichero ~/.xmonad/xmonad.hs 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.

Atajos de teclado

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.

Lanzar aplicaciones

-- Win  +  Enter                   Terminal
-- Win  +  F1                      Nautilus
-- Win  +  F2                      Firefox                  (single instance)
-- Win  +  F3                      Thunderbird              (single instance)
-- Win  +  F4                      RSSOwl                   (single instance)
-- Win  +  F5                      Hotot                    (single instance)
-- Win  +  F6                      ncmpcpp  - MPD player
-- Win  +  F7                      taskwarrior
-- Win  +  F8                      PAC                      (single instance)
-- Win  +  F9                      Aptana                   (single instance)
-- Win  +  F10                     Xmind                    (single instance)
-- Win  +  F11                     Dbeaver                  (single instance)
-- Win  +  F12                     VirtualBox               (single instance)

Lo primero que se puede ver es una serie de atajos para lanzar aplicaciones empleando la tecla Win más las teclas de función. La tecla Win (también llamada Super) es la tecla maestra por defecto de Xmonad (mod4Mask) 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.

Algunas aparecen con la frase single instance 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.

Adicionalmente la combinación Alt + Enter nos permite abrir una ventana del terminal. En este caso lo tengo predeterminado para que abra una venta de terminator

Consola emergente

-- Win  +  Space                   Run or Raise Shell Prompt
-- Win  +  Shift   +  Space        Run Shell Prompt
-- Win  +  Control +  Space        Window Prompt

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.

  • Win + Espacio 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.

  • Win + Mayús + Espacio ejecuta el comando que escribamos. Similar a la ventana de ejecutar comando de Gnome (Alt + F2 en Gnome)

  • Win + Control + Espacio 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.

Reiniciar Xmonad

Con la combinación Win + q 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 xmonad --recompile en un terminal, pulsamos esta combinación y los cambios se reflejaran de forma inmediata.

Transparencias

Una de las carencias de Xmonad es que no incorpora un gestor de composición por lo que si queremos manejar transparencias en nuestros terminales, notificaciones, ventanas, etc, debemos emplear uno externo. Para esto empleo xcompmgr 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 Xmonad Unity 2D es emplear este script bash:

#!/bin/bash

if [ $DESKTOP_SESSION = "xmonad-unity-session" ]; then
    xcompmgr -I1 -O1 -Ff;
fi

Luego añado el script a las aplicaciones que se ejecutan al inicio de la sesión y listo.

Bandeja del sistema

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 indicadores. Se supone que debería añadirlos de forma automática al panel, incluso hay una configuración a través de dconf para habilitar esto, pero no funciona para todas las aplicaciones. Para añadir un systray empleo un script parecido al anterior para lanzar la aplicación trayer en esta sesión.

#!/bin/bash

MYARGS="--edge top --widthtype request --transparent true --alpha 0 --distancefrom right --distance 1100 --height 24 --tint 0x4c4a44 --align right"

if [ $DESKTOP_SESSION = "xmonad-unity-session" ]; then
    sleep 24 && trayer $MYARGS;
fi

Como personalizar Xmonad: Haskell

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: Haskell. 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.

Afortunadamente hay varios recursos disponibles que nos hacen el trabajo más fácil, porque Xmonad está aceptablemente bien documentado (en Inglés).

  • Pantallazos
  • Ficheros de configuración
  • Wiki
  • API Docs
  • API Extensiones Docs

Xmonad.hs

Este es mi mi fichero de configuración de Xmonad:

-- joe di castro's xmonad.hs
-- Based on rupa's xmonad.hs, https://github.com/rupa/xmonad

-- ===============================================================  KEY BINDINGS

------------------------------------------------- Launch (or Raise) Applications
-- Win  +  Enter                   Terminal
-- Win  +  F1                      Nautilus
-- Win  +  F2                      Firefox                  (single instance)
-- Win  +  F3                      Thunderbird              (single instance)
-- Win  +  F4                      RSSOwl                   (single instance)
-- Win  +  F5                      Hotot                    (single instance)
-- Win  +  F6                      ncmpcpp  - MPD player
-- Win  +  F7                      taskwarrior
-- Win  +  F8                      PAC                      (single instance)
-- Win  +  F9                      Aptana                   (single instance)
-- Win  +  F10                     Xmind                    (single instance)
-- Win  +  F11                     Dbeaver                  (single instance)
-- Win  +  F12                     VirtualBox               (single instance)
----------------------------------------------------------- Shell/Window prompts
-- Win  +  Space                   Run or Raise Shell Prompt
-- Win  +  Shift   +  Space        Run Shell Prompt
-- Win  +  Control +  Space        Window Prompt
--------------------------------------------------------------------- Navigation
-- Win  +  [1..9]                  Switch to workspace N
-- Win  +  Shift   +  [1..9]       Move client to workspace N
-- Ctrl +  Alt     +  Left/Right   Previous/Next workspace
-- Alt  +  Tab                     Focus next window
-- Alt  +  Shift   +  Tab          Focus previous window
-------------------------------------------------------------- Window management
-- Win  +  Shift   +  Left         Move window to previous workspace
-- Win  +  Shift   +  Right        Move window to next workspace
-- Win  +  Control +  Left         Move window to previous empty workspace
-- Win  +  Control +  Right        Move window to next empty workspace
-- Ctrl +  Up/Down                 Move focused window up/down
-- Win  +  m                       Toggle focused window Full Screen
-- Win  +  n                       Refresh
-- Win  +  -                       Move focused windows to master area
-- Win  +  w  (or Alt + F4)        Close focused window
-- Win  +  t                       Back to tiling (unfloat floating window)
-- Win  +  Shift   +  t            Back All to tiling (unfloat ALL windows)
-------------------------------------------------------------  Layout management
-- Win  +  Tab                     Rotate layouts
-- Win  +  Left/Right              Shrink/Expand the master area
-- Win  +  Up/Down                 Mirror Shrink/expand
-- Win  +  ,/.                     Increment/Deincrement 1 window in master area
-- Win  +  f                       Hide/Unhide the gnome-panel/status bar
-- Win  +  Shift   +  n            Reset current workspace to main layout
------------------------------------------------------------------ Mosaic Layout
-- Win  +  a/z                     Taller/Wider
-- Win  +  Control +  n            Reset
------------------------------------------------------------------------- Others
-- Print Screen                    Capture screen
-- Win  +  q                       Restart XMonad
-- Win  +  Shift   +  q            Close gnome session dialog

-- ============================================================== MOUSE BINDINGS

-- Win  +  Button 1                Float Window and Move by dragging
-- Win  +  Button 2                Raise Window to the top
-- Win  +  Button 3                Float Window and Resize by dragging

import XMonad
import qualified XMonad.StackSet as W
import qualified Data.Map        as M
import Data.Monoid

import XMonad.Actions.CycleWS
import XMonad.Actions.FlexibleResize as Flex
import XMonad.Actions.SinkAll
import XMonad.Actions.UpdatePointer
import XMonad.Actions.WindowGo

import XMonad.Hooks.DynamicLog
import XMonad.Hooks.EwmhDesktops
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.ManageHelpers

import XMonad.Layout.LayoutHints
import XMonad.Layout.NoBorders
import XMonad.Layout.ResizableTile
import XMonad.Layout.Tabbed
import XMonad.Layout.ToggleLayouts
import XMonad.Layout.WindowArranger
import XMonad.Layout.Mosaic

import XMonad.Prompt
import XMonad.Prompt.Input
import XMonad.Prompt.RunOrRaise
import XMonad.Prompt.Shell
import XMonad.Prompt.Window

import XMonad.Util.Run
import XMonad.Util.Scratchpad
import XMonad.Util.WorkspaceCompare
import XMonad.Util.XSelection

import XMonad.Config.Gnome

-- Mod4 is the Super / Windows key
winMask = mod4Mask
altMask = mod1Mask

-- key bindings
myKeys conf@(XConfig {XMonad.modMask = modMask}) = M.fromList $
    [ ((winMask,                    xK_Return   ), spawn $ XMonad.terminal conf)
    , ((winMask,                    xK_F1       ), spawn "nautilus ~")
    , ((winMask,                    xK_F2       ), runOrRaise "firefox" (className =? "Firefox"))
    , ((winMask,                    xK_F3       ), runOrRaise "thunderbird" (className =? "Thunderbird"))
    , ((winMask,                    xK_F4       ), runOrRaise "./rssowl/RSSOwl" (className =? "RSSOwl"))
    , ((winMask,                    xK_F5       ), runOrRaise "hotot" (className =? "Hotot"))
    , ((winMask,                    xK_F6       ), spawn "terminator -e ncmpcpp")
    , ((winMask,                    xK_F7       ), spawn "terminator -e 'task shell' -p task")
    , ((winMask,                    xK_F8       ), runOrRaise "pac" (className =? "Pac"))
    , ((winMask,                    xK_F9       ), runOrRaise "./Aptana Studio 3/AptanaStudio3" (className =? "Aptana Studio 3"))
    , ((winMask,                    xK_F10      ), runOrRaise "/usr/local/xmind/xmind" (className =? "XMind"))
    , ((winMask,                    xK_F11      ), runOrRaise "./dbeaver/dbeaver" (className =? "DBeaver"))
    , ((winMask,                    xK_F12      ), runOrRaise "VirtualBox" (className =? "VirtualBox"))
    , ((winMask,                    xK_space    ), runOrRaisePrompt mySP)
    , ((winMask .|. shiftMask,      xK_space    ), shellPrompt mySP)
    , ((winMask .|. controlMask,    xK_space    ), windowPromptGoto mySP)
    , ((0,                          xK_Print    ), unsafeSpawn "gnome-screenshot")
    , ((altMask .|. controlMask,    xK_Right    ), moveTo Next (WSIs (return $ not . (=="NSP") . W.tag)))
    , ((altMask .|. controlMask,    xK_Left     ), moveTo Prev (WSIs (return $ not . (=="NSP") . W.tag)))
    , ((winMask .|. shiftMask,      xK_Right    ), shiftTo Next (WSIs (return $ not . (=="NSP") . W.tag)))
    , ((winMask .|. shiftMask,      xK_Left     ), shiftTo Prev (WSIs (return $ not . (=="NSP") . W.tag)))
    , ((winMask .|. controlMask,    xK_Right    ), shiftTo Next EmptyWS)
    , ((winMask .|. controlMask,    xK_Left     ), shiftTo Prev EmptyWS)
    , ((winMask,                    xK_Tab      ), sendMessage NextLayout >> (dynamicLogString myPP >>= \d->safeSpawn "gnome-osd-client" [d]))
    , ((altMask,                    xK_Tab      ), windows W.focusDown)
    , ((altMask .|. shiftMask,      xK_Tab      ), windows W.focusUp)
    , ((controlMask,                xK_Down     ), windows W.swapDown)
    , ((controlMask,                xK_Up       ), windows W.swapUp)
    , ((winMask,                    xK_Left     ), sendMessage Shrink)
    , ((winMask,                    xK_Right    ), sendMessage Expand)
    , ((winMask,                    xK_Down     ), sendMessage MirrorShrink)
    , ((winMask,                    xK_Up       ), sendMessage MirrorExpand)
    , ((winMask,                    xK_minus    ), windows W.shiftMaster)
    , ((winMask,                    xK_comma    ), sendMessage (IncMasterN 1))
    , ((winMask,                    xK_period   ), sendMessage (IncMasterN (-1)))
    , ((winMask,                    xK_n        ), refresh)
    , ((winMask .|. shiftMask,      xK_n        ), setLayout $ XMonad.layoutHook conf)
    , ((winMask ,                   xK_a        ), sendMessage Taller)
    , ((winMask ,                   xK_z        ), sendMessage Wider)
    , ((winMask .|. controlMask,    xK_n        ), sendMessage Reset)
    , ((winMask,                    xK_m        ), sendMessage (Toggle "Full") >> (dynamicLogString myPP >>= \d->safeSpawn "gnome-osd-client" [d]))
    , ((winMask,                    xK_t        ), withFocused $ windows . W.sink)
    , ((winMask .|. shiftMask,      xK_t        ), sinkAll)
    , ((winMask,                    xK_f        ), sendMessage ToggleStruts)
    , ((winMask,                    xK_w        ), kill)
    , ((altMask,                    xK_F4       ), kill)
    , ((winMask,                    xK_q        ), broadcastMessage ReleaseResources >> restart "xmonad" True)
    , ((winMask .|. shiftMask,      xK_q        ), spawn "gnome-session-quit")
    ]

    ++
    -- mod-[1..9], Switch to workspace N
    -- mod-shift-[1..9], Move client to workspace N
    [ ((m .|. winMask, k), windows $ f i)
        | (i, k) <- zip (XMonad.workspaces conf) [xK_1 .. xK_9]
        , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)] ]

-- mouse bindings
myMouseBindings (XConfig {XMonad.modMask = modMask}) = M.fromList $
    [ ((winMask, button1), (\w -> focus w >> mouseMoveWindow w))
    , ((winMask, button2), (\w -> focus w >> windows W.shiftMaster))
    , ((winMask, button3), (\w -> focus w >> Flex.mouseResizeWindow w)) ]

-- decoration theme
myDeco = defaultTheme
    { activeColor           = "orange"
    , inactiveColor         = "#222222"
    , urgentColor           = "yellow"
    , activeBorderColor     = "orange"
    , inactiveBorderColor   = "#222222"
    , urgentBorderColor     = "yellow"
    , activeTextColor       = "orange"
    , inactiveTextColor     = "#222222"
    , urgentTextColor       = "yellow"
    , decoHeight            = 10 }

-- tab theme
myTab = defaultTheme
    { activeColor           = "black"
    , inactiveColor         = "black"
    , urgentColor           = "yellow"
    , activeBorderColor     = "orange"
    , inactiveBorderColor   = "#222222"
    , urgentBorderColor     = "black"
    , activeTextColor       = "orange"
    , inactiveTextColor     = "#222222"
    , urgentTextColor       = "yellow" }

-- shell prompt theme
mySP = defaultXPConfig
    { bgColor               = "black"
    , fgColor               = "white"
    , bgHLight              = "gray"
    , fgHLight              = "black"
    , borderColor           = "orange"
    , promptBorderWidth     = 2
    , position              = Bottom
    , height                = 40
    --, autoComplete        = Just 1000
    , historySize           = 1000 }

-- dynamicLog theme (suppress everything but layout)
myPP = defaultPP
    { ppLayout  = (\ x -> case x of
      "Hinted ResizableTall"        -> "[|]"
      "Mirror Hinted ResizableTall" -> "[-]"
      "Hinted Tabbed Simplest"      -> "[T]"
      "Mosaic"                      -> "[M]"
      "Full"                 -> "[ ]"
      _                      -> x )
    , ppCurrent             = const ""
    , ppVisible             = const ""
    , ppHidden              = const ""
    , ppHiddenNoWindows     = const ""
    , ppUrgent              = const ""
    , ppTitle               = const ""
    , ppWsSep               = ""
    , ppSep                 = "" }

-- layouts
myLayout = avoidStruts $ toggleLayouts (noBorders Full)
    (smartBorders (tiled ||| mosaic 2 [3,2] ||| Mirror tiled ||| layoutHints (tabbed shrinkText myTab)))
    where
        tiled   = layoutHints $ ResizableTall nmaster delta ratio []
        nmaster = 1
        delta   = 2/100
        ratio   = 1/2

-- special windows
myManageHook = composeAll
    [ className =? "MPlayer"                --> doFloat
    , className =? "Gimp-2.6"               --> doFloat
    , className =? "Gnome-panel"            --> doIgnore
    , className =? "XVkbd"                  --> doIgnore
    , className =? "Cellwriter"             --> doIgnore
    , className =? "Gtkdialog"              --> doFloat
    , resource  =? "desktop_window"         --> doIgnore
    , className  =? "Xmessage"              --> doCenterFloat
    , className =? "Unity-2d-panel"         --> doIgnore
    , isFullscreen                          --> doFullFloat
    , isDialog                              --> doCenterFloat
    , title =? "RSSOwl"                     --> doIgnore
    , title =? "Dbeaver"                    --> doIgnore
    , title =? "Xmind-bin"                  --> doIgnore
    , title =? "AptanaStudio3"              --> doIgnore
    , resource =? "sun-awt-X11-XDialogPeer" --> doCenterFloat
    , title =? "screenkey"                  --> doIgnore
    , className =? "Gloobus-preview"        --> doCenterFloat
    --                                      x y w h
    , scratchpadManageHook $ W.RationalRect 0 0 1 0.42
    , manageDocks ] <+> manageHook defaultConfig

-- let Gnome know about Xmonad actions
myLogHook = ewmhDesktopsLogHookCustom scratchpadFilterOutWorkspace >> updatePointer (Relative 0.5 0.5)

myConfig = ewmh defaultConfig
    { terminal           = "terminator"
    , borderWidth        = 2
    , normalBorderColor  = "black"
    , focusedBorderColor = "orange"
    , focusFollowsMouse  = True
    , modMask            = mod4Mask
    , keys               = myKeys
    , mouseBindings      = myMouseBindings
    , layoutHook         = myLayout
    , manageHook         = myManageHook
    , startupHook        = gnomeRegister
    }

-- need to override ewmh's logHook cause I'm using Scratchpad
main = xmonad $ myConfig
    { logHook            = myLogHook }

Etiquetado como: linux, ubuntu, unity, tiling, twm, productividad, xmonad, gnome, haskell.