XMonad

O XMonadu

XMonad je jedním z mnoha window managerů (jako KDE, Gnome a spousty dalších). Tím, čím se vymyká je, že je to tillingový window manager a těch už až tak moc není. A co že to přesně znamená? Zatímco ostatní WM si kolem každého okna vykreslí rámeček a nějak ho prsknou do prostoru (a umožní s nim hýbat), tillingový wm okna poctivě rozskládá do plochy. Tedy okna jsou rozestavěna tak, aby využily celou plochu a jsou umisťována podle nějakých pravidel (layoutu) a typické rozestavění také zajišťuje, že se okna nepřekrývají (ne vždy...). Pokud si na to člověk zvykne, dokáže to celkem zvýšit efektivitu práce (člověk netráví hromadu času neustálým přehazováním oken, aby viděl co potřebuje). Pokud se to již teď někomu nelíbí, nechť přestane číst a šoupá si dál svýma okýnkama :-)

Co všechno to umí

Jednou z dalších věcí, kterou XMonad oproti ostatním vyniká, je, že je napsán v Haskellu. A v Haskellu je také napsán jeho konfigurační soubor. Díky tomu pro někoho, kdo nikdy neviděl funkcionální jazyk, bude připadat konfigurák obzvláště nečitelný, na druhou stranu možnosti konfigurace jsou téměř neomezené. To co zde budu popisovat je moje nastavení a tedy to, co mně vyhovuje - při patřičném nastavení se to ale také může chovat úplně jinak (anebo jde nastavit spousta jiných věcí, o kterých ani nevím...)

Věci, o kterých si myslím, že se stojí za to zmínit:

  • Možnost použití libovolných dostupných layoutů (viz dále), jejich přepínání pro každou plochu zvlášť a možné předdefinování pro každou plochu.
  • Použití modifikátorů layoutů.
  • Možnost integrace s jiným desktopovým prostředím - XMonad je pouze window manager, lze ho tak třeba nahradit v Gnome místo Metacity/Compiz, ve KDE místo KWin apod.
  • Spoustu věcí lze dělat pouze pomocí klávesnice (včetně přepínání fokusu oken)
  • Tagování jednotlivých oken a hromadné provádění operací podle tagů.
  • Virtuální plochy nezávislé na monitoru - plochy jsou pevně definovány a každý monitor zobrazuje právě jednu plochu - není tak problém najednou vyměnit plochy mezi dvouma monitorama, když se odpojí sekundární monitor, tak nezůstanou žádné okna skryty a navíc díky chytrému dláždění oken nevznikají žádné divné efekty u přehazování ploch na větší/menší obrazovky.
  • Nastavování různých vlastností podle aplikace, jména okna apod.
  • XMonad je malý, rychlý a systémově nenáročný.

Popis layoutů

Layout tedy popisuje, jak se okna budou po ploše rozmisťovat. Veškerá uvedená konfigurace předpokládá nainstalovaný i balík xmonad-contrib, kde jsou další doplňkové moduly a dostupných layoutů je poměrně dost. Dále je k dispozici řada modifikátorů, které dané layouty nějakým způsobem upraví (ty také popíšu). V mé konfiguraci jsou použity tyto layouty:

  • Tall - základní layout (používá se v defaultním nastavení) - uspořádává okna do dvou sloupců, ve výchozím nastavení je v levém pouze jedno (master) okno a zbytek se skládá do pravého sloupce (ale počty oken ve sloupcích se dají za běhu měnit klávesami).
  • Full - plné zobrazení - aktivní okno je roztaženo přes celou plochu, ostatní jsou pod ním.
  • Grid - tabulka - uspořádává všechny okna do tabulky.
  • OneBig - hlavní master okno je v levém horním rohu a má nastavené rozměry. Ostatní okna se skládají do toho prostoru, co zbyde.

Modifikátory layoutů

Kromě samotných layoutů je použito i několik modifikátorů, které chování daného layoutu změní. V konfiguraci je pár modifikátorů, které moc zajímavé nejsou (například desktopLayoutModifier je použit kvůli tomu, že já mám XMonad integrovaný v Gnome, tak aby to fungovalo). Ty které něco dělají a jsou zajímavé jsou tyto:

  • IM Layout - zobrazení pro instant messaging - veme nějaký standardní layout a doplní ho efektivní zobrazení okna s kontakt listem - v mém případě okno s rosterem psi je po celé výšce vlevo a zbytek oken (jako jednotlivé user chaty apod.) se skládají do mřížky.
  • Magnifier - okno s aktivním fokusem je zvětšeno (a tedy i o něco překrývá ostatní okna). Používám na jedné ploše s terminálama v kombinaci s grid - když je oken více, terminály jsou už poměrně malé a tímto modifikátorem se dá aktivní terminál zvětšit.

SubLayout

V XMonadu lze použít i sublayouty - tedy pokud už na ploše je aktivní nějaký layout, tak v místě, kde normálně bývá už nějaké okno, je zase nějaká složenina z nějakého jiného layoutu. Implementace sublayoutů momentálně není úplně nejšťastnější a i ovládání je poměrně obskurní. Osobně používám pouze jako sublayout tabbed, který se ještě dá celkem rozumě používat. SubTabbed vytváří tabbovaná okna, tedy okna která spojím do jednoho sublayoutu, mají krom aktivního vidět pouze titulkový pruh s tabama. Lze tím získat nějaké místo, pokud člověk to okno nechce zavřít, ale zároveň ho nemusí zrovna nutně vidět...

Konfigurace

Nyní tedy k samotné konfiguraci. Na začátek asi uvedu celý konfigurační soubor (který se nachází v ~/.xmonad/xmonad.hs) a pak se jej pokusím alespoň z části vysvětlit a popsat, co to dělá.

  1. import System.Exit
  2. import System.IO
  3. import XMonad
  4. import XMonad.Actions.TagWindows
  5. import XMonad.Config.Desktop
  6. import XMonad.Config.Gnome
  7. import XMonad.Hooks.DynamicLog
  8. import XMonad.Hooks.EwmhDesktops
  9. import XMonad.Hooks.ManageDocks
  10. import XMonad.Hooks.ManageHelpers
  11. import XMonad.Hooks.SetWMName
  12. import XMonad.Layout.BoringWindows
  13. import XMonad.Layout.Grid
  14. import XMonad.Layout.IM
  15. import XMonad.Layout.Magnifier
  16. import XMonad.Layout.NoBorders
  17. import XMonad.Layout.OneBig
  18. import XMonad.Layout.PerWorkspace
  19. import XMonad.Layout.SubLayouts
  20. import XMonad.Layout.Tabbed
  21. import XMonad.Layout.WindowNavigation
  22. import XMonad.Prompt
  23. import XMonad.Prompt.Window
  24. import qualified XMonad.StackSet as W
  25. import qualified Data.Map        as M
  26. import XMonad.Util.EZConfig
  27. import XMonad.Util.Run (spawnPipe)
  28.  
  29. altMask         = mod1Mask
  30. myModMask       = mod4Mask
  31. myWorkspaces    = ["im","web","mail","term","files","devel","7","8","9","10","11","12"]
  32.  
  33. myKeys conf@(XConfig {XMonad.modMask = modm}) = M.fromList $
  34.     [
  35.       ((modm,                               xK_a)        , tagPrompt defaultXPConfig (\s -> withFocused (addTag s)))
  36.     , ((modm .|. shiftMask,                 xK_a)        , tagPrompt defaultXPConfig (\s -> withTaggedGlobalP s shiftHere))
  37.     , ((modm .|. shiftMask,                 xK_c)        , kill)
  38.     , ((modm .|. controlMask .|. shiftMask, xK_c)        , tagPrompt defaultXPConfig (\s -> withTaggedGlobalP s W.delete))
  39.     , ((modm,                               xK_h)        , sendMessage $ Go L)
  40.     , ((modm .|. shiftMask,                 xK_h)        , sendMessage $ Swap L)
  41.     , ((modm .|. altMask,                   xK_h)        , sendMessage Shrink)
  42.     , ((modm .|. controlMask,               xK_h)        , sendMessage $ pullGroup L)
  43.     , ((modm,                               xK_j)        , sendMessage $ Go D)
  44.     , ((modm .|. shiftMask,                 xK_j)        , sendMessage $ Swap D)
  45.     , ((modm .|. controlMask,               xK_j)        , sendMessage $ pullGroup D)
  46.     , ((modm,                               xK_k)        , sendMessage $ Go U)
  47.     , ((modm .|. shiftMask,                 xK_k)        , sendMessage $ Swap U)
  48.     , ((modm .|. controlMask,               xK_k)        , sendMessage $ pullGroup U)
  49.     , ((modm,                               xK_l)        , sendMessage $ Go R)
  50.     , ((modm .|. shiftMask,                 xK_l)        , sendMessage $ Swap R)
  51.     , ((modm .|. altMask,                   xK_l)        , sendMessage Expand)
  52.     , ((modm .|. controlMask,               xK_l)        , sendMessage $ pullGroup R)
  53.     , ((modm .|. controlMask,               xK_m)        , withFocused (sendMessage . MergeAll))
  54.     , ((modm,                               xK_n)        , refresh)
  55.     , ((modm,                               xK_p)        , spawn "exe=`dmenu_path | dmenu` && eval \"exec $exe\"")
  56.     , ((modm,                               xK_q)        , restart "xmonad" True)
  57.     , ((modm .|. shiftMask,                 xK_q)        , io (exitWith ExitSuccess))
  58.     , ((modm,                               xK_s)        , withFocused (unTag))
  59.     , ((modm,                               xK_t)        , withFocused $ windows . W.sink)
  60.     , ((modm .|. controlMask,               xK_u)        , withFocused (sendMessage . UnMerge))
  61.     , ((modm,                               xK_comma)    , sendMessage (IncMasterN 1))
  62.     , ((modm .|. controlMask,               xK_comma)    , onGroup W.focusUp')
  63.     , ((modm,                               xK_period)   , sendMessage (IncMasterN (-1)))
  64.     , ((modm .|. controlMask,               xK_period)   , onGroup W.focusDown')
  65.     , ((modm,                               xK_Return)   , windows W.swapMaster)
  66.     , ((modm .|. shiftMask,                 xK_Return)   , spawn $ XMonad.terminal conf)
  67.     , ((modm,                               xK_space)    , sendMessage NextLayout)
  68.     , ((modm .|. shiftMask,                 xK_space)    , setLayout $ XMonad.layoutHook conf)
  69.     , ((modm,                               xK_Tab)      , windows W.focusDown)
  70.     , ((modm .|. shiftMask,                 xK_Tab)      , windowPromptGoto defaultXPConfig)
  71.     , ((modm .|. controlMask,               xK_Tab)      , windowPromptBring defaultXPConfig)
  72.     , ((modm,                               xK_BackSpace), spawn "gnome-screensaver-command --lock & sudo pm-suspend")
  73.     , ((modm .|. shiftMask,                 xK_BackSpace), spawn "gnome-screensaver-command --lock & sudo pm-hibernate")
  74.     , ((0, 0x1008FF32)                                   , spawn "gnome-screensaver-command --lock")
  75.     ]
  76.     ++
  77.     [ ((altMask, k), windows $ W.greedyView i)
  78.         | (i, k) <- zip myWorkspaces workspaceKeys
  79.     ] ++
  80.     [ ((myModMask, k), (windows $ W.shift i) >> (windows $ W.greedyView i))
  81.         | (i, k) <- zip myWorkspaces workspaceKeys
  82.     ] ++
  83.     [((m .|. modm, key), screenWorkspace sc >>= flip whenJust (windows . f))
  84.     | (key, sc) <- zip [xK_e, xK_w, xK_r] [0..]
  85.     , (f, m) <- [(W.view, 0), (W.shift, shiftMask)]]
  86.     where workspaceKeys = [xK_F1 .. xK_F12]
  87.  
  88. myManageHook = composeAll
  89.     [ manageHook gnomeConfig
  90.     , className =? "Gimp"           --> doFloat
  91.     , className =? "VirtualBox"     --> doFloat
  92.     , title =? "VLC (XVideo output)"        --> doFloat
  93.     , resource  =? "desktop_window" --> doIgnore
  94.     , resource  =? "kdesktop"       --> doIgnore
  95.     ]
  96.  
  97. myTheme = defaultTheme { decoHeight = 16
  98.                         , activeColor = "#a6c292"
  99.                         , activeBorderColor = "#a6c292"
  100.                         , activeTextColor = "#000000"
  101.                         , inactiveBorderColor = "#000000"
  102.                         }
  103.  
  104. myLayout = avoidStruts
  105.          $ configurableNavigation (navigateColor "#00aa00")
  106.          $ boringWindows
  107.          $ subTabbed
  108.          $ onWorkspace "im" imLayout
  109.          $ onWorkspace "web" weblayout
  110.          $ onWorkspace "term" terms
  111.          $ desktopLayoutModifiers(Tall 1 0.03 0.5 |||  Full ||| Grid)
  112.   where
  113.     imLayout = withIM (2/13) ( (ClassName "psi") `And` (Resource "main") ) Grid
  114.     terms = desktopLayoutModifiers (Grid ||| magnifier Grid ||| Full)
  115.     weblayout = desktopLayoutModifiers (OneBig (3/4) (3/4) ||| Full ||| Tall 1 0.03 0.5)
  116.  
  117. myDynamicLog xmproc = dynamicLogWithPP xmobarPP { ppOutput = hPutStrLn xmproc
  118.                                                   , ppTitle = xmobarColor "green" "" . shorten 50
  119.                                                   , ppVisible = wrap "<fc=black,yellow> " " </fc>"
  120.                                                   , ppCurrent = wrap "<fc=blue,yellow> " " </fc>"
  121.                                                   , ppLayout = \x -> "<fc=aquamarine2,black>"
  122.                                                                ++ case x of
  123.                                                                   "Tabbed Magnifier Grid"       -> "Mag Grid"
  124.                                                                   "Tabbed Full"                 -> "Full"
  125.                                                                   "Tabbed Grid"                 -> "Grid"
  126.                                                                   "Tabbed OneBig 0.75 0.75"     -> "OneBig"
  127.                                                                   "Tabbed Tall"                 -> "Tall"
  128.                                                                   "Tabbed IM Grid"              -> "IM"
  129.                                                                 ++ "</fc> "
  130.                                                         }
  131.                                        >> ewmhDesktopsLogHook
  132.                                        >> setWMName "LG3D"
  133.  
  134. main = do
  135.           xmproc <- spawnPipe "/usr/bin/xmobar /home/spm/.xmobarrc"
  136.           xmonad $ gnomeConfig
  137.                { terminal = "urxvt"
  138.                  , modMask = myModMask -- set the mod key to the windows key
  139.                  , keys = myKeys
  140.                  , workspaces = myWorkspaces
  141.                  , manageHook = myManageHook
  142.                  , layoutHook = myLayout
  143.                  , borderWidth = 2
  144.                  , normalBorderColor = "#dddddd"
  145.                  , focusedBorderColor = "#0033FF"
  146.                  , logHook = myDynamicLog xmproc
  147.                 }
  148.  

Kromě integrace s Gnome je v konfiguraci vidět použití xmobaru - xmobar je takový malý panel, který může zobrazovat různé informace a mimo jiné mu některé cenné informace může předávat sám XMonad (jako aktuální layout, plochy, apod.) - pro tuhle integraci snad už i existuje nějaký plugin do Gnome panelu, ale osobně jsem jej nezkoušel. Konfigurace samotného xmobaru (zde uložená v ~/.xmobarrc) vypadá takto:

  1. Config { font = "-misc-fixed-*-*-*-*-13-*-*-*-*-*-*-*"
  2.        , bgColor = "black"
  3.        , fgColor = "grey"
  4.        , position = BottomW L 100
  5.        , lowerOnStart = False
  6.        , commands = [ Run Cpu ["-L","15","-H","50","--normal","green","--high","red"] 10
  7.                     , Run Memory [] 10
  8.                     , Run Swap [] 10
  9.                     , Run StdinReader
  10.                     ]
  11.        , sepChar = "%"
  12.        , alignSep = "}{"
  13.        , template = "%StdinReader% %cpu% | %memory% * %swap%}{"
  14.        }
  15.  

Vysvětlení konfigurace

  • Po importu všech modulů se napřed definují modifikátory kláves - téměř všechny klávesové zkratky se používají v kombinaci s myModMask - ten je v tomhle případě nastaven na win tlačítko (které je jinak na té klávesnici úplně k ničemu).
  • V myWorskpaces jsou definovány všechny virtuální plochy - v tomto případě jich je 12.
  • za myKeys následuje nastavení vlastních klávesových zkratek pro téměř vše. Každý záznam je pak tvořen jednak definováním dané klávesové zkratky a k ní akce, která se má provést. Klávesová zkratka se pak skládá z modifikátoru (téměř všude modm reprezentující win tlačítko, kombinace modm .|. controlMask znamená win tlačítko + control a podobně) a samotné klávesy. xK_a reprezentuje například klávesu a.
  • K definici klávesových zkratek patří i ten podivný konec - ten říká, že klávesy alt+F1-F12 přepínají na plochu 1 - 12, win+F1-F12 přesune okno na plochu 1-12 a win+W, E, R přepíná na 1., 2., 3. monitor.
  • myManageHook definuje nějaké zvláštní podmínky. Konfigurace říká, že okna Gimpu, VirtualBoxu a fullscreen okno VLC se nebudou tillingovat, ale budou jako plovoucí okna.
  • myLayout konečně definuje jednotlivé používané layouty, i se všemi modifikátory a s tabbovým sublayoutem. Navíc kouzelné slůvko onWorkspace zajišťuje to, že na zadané ploše bude pouze tento daný layout.
  • myDynamicLog převážně určuje to, co se všechno posílá do xmobaru (a to i v jakém formátu, s jakými barvami apod.) - dá se s tím pohrát. Poslední dva řádky z něj pak alespoň částečně eliminují java bug... aplikace se dá sice už spustit a používat, ale žádná sláva... snad se to časem opraví :-)
  • Na konec se předá všechno to, co se definovalo. V tom posledním odstavci už je jen jedno zajímavé nastavení a to je terminal - v této konfiguraci nastavuje jako používaný terminál urxvt.

Používání (podle zmíněné konfigurace)

Tak, jak to tedy používat:

  • Stiskem Win+Shift+Enter se spustí terminál
  • Mezi oknama se dá pohybovat pomocí Win+h, j, k, l (h posouvá doleva, j dolu, k nahoru, l doprava). Navíc aktivní okno má modrý rámeček a okna okolo něj obarvená zelenou barvou určují, kam se fokus posune.
  • Stejnými zkratkami, ale ještě s přidrženým kontrolem dojde k přesunutí okna do tabbovaného sublayoutu. Tedy třeba stisk Win+Ctrl+h přidá aktivní okno do toho nalevo jako nový tab.
  • Kombinace Win+Shift+h, j, k, l opět podle stejné logiky prohazují okna. Tedy Win+Shift+h přehodí aktivní okno s tím nalevo. Pro přehazování oken slouží také kombinace Win+enter - ta přehodí aktivní okno s master oknem. Nicméně ne všechny layouty master okno mají (třeba grid ho nemá).
  • Stiskem Win+Alt+h, l dojde ke zmenšování/zvětšování okna. Opět - funguje to pouze na některých layoutech (třeba na gridu to zase nejde).
  • Win+Ctrl+m ztabuje všechny okna, tedy ve výsledku na celé ploše zůstane pouze to jedno okno se sublayoutem a všechny okna budou jako taby. Win+Ctrl+u aktivní okno vyhodí ven ze sublayoutu.
  • Win+, a Win+. snižuje/zvyšuje počet master oken. Výsledný efekt je třeba hezky vidět na Till layoutu.
  • Win+Ctrl+, + Win+Ctrl+. přepínají okna v rámci sublayoutu (tedy vlastně přehazjí ty taby.
  • Podržením Win + klikem levým tlačítkem myši na okno ho lze vyjmout z tilling vrstvy a nechat ho na ploše jako plovoucí. Se stisknutým Win ho pak lze přemisťovat nebo pravým tlačítkem měnit velikost. Win+t okno opět vrátí do tilling vrstvy.
  • Win+q reloaduje XMonad - to mj. zajistí načtení nové konfigurace.
  • Stiskem Win+Shift+c lze okno zavřít.
  • Win+mezerník přepíná jednotlivé dostupné layouty.
  • Win+p spouští program dmenu (musí být nainstalován) - ten slouží k celkem pohodlnému spouštění aplikací.
  • Win+tab přepíná na další okno (bez ohledu na to, zda je v sublayoutu nebo ne). Win+Shift+tab se zeptá na jméno okna (doplňuje) a po jeho vybrání na něj přejde (vidí okna ze všech ploch, v případě potřeby přepne plochu). Win+Ctrl+tab funguje obdobně, jen místo přepnutí na okno dané okno přesune do aktuální plochy.
  • Win+a se zeptá na tag a ten přiřadí oknu s fokusem. Win+s oknu s fokusem odebere všechny tagy.
  • Win+Ctrl+Shift c se zeptá na tag a pak všechny okna s tímto tagem zavře.
  • Win+Shift+a se zeptá na tag a okna s vybraným tagem přesune do aktuální plochy.
  • Na konci už je jen už pár notebookuvhodných zkratek - Win+Backspace zamkne plochu a uspí počítač do RAMky, stejná varianta se shiftem místo uspání do RAM uspí na disk a to hrůzné číslo ukazuje na nějakou multimediální klávesu, kterou se zamkne obrazovka.

Screenshoty

Na závěr tedy ještě pár screenshotů z toho, jak to ve výsledku vypadá.

IM rozložení s mřížkou Grid + Magnifier (zvětšené okno s fokusem)
Layout OneBig - hlavní okno zabírá 3/4 v obou směrech celé plochy

Komentáře

<a href="http://nexium.us.org/">buy nexium 20mg</a> <a href="http://hydroxychlorothiazide.com/">amlodipine hydrochlorothiazide</a> <a href="http://prazosin.us.com/">buy prazosin</a> <a href="http://hydroxychloroquine.us.com/">hydroxychloroquine sulfate tabs 200mg</a> <a href="http://motrin.us.com/">motrin 400 mg</a> <a href="http://hydroxychloroquinecv.com/">buy hydroxychloroquine</a> <a href="http://amitriptyline24.com/">buy amitriptyline</a> <a href="http://proscar.us.com/">proscar 5mg</a> <a href="http://malegra.us.org/">buy malegra fxt</a> <a href="http://zovirax.us.com/">buy zovirax canada</a>