Už docela dlouho k téměř úplné spokojenosti používám XMonad jako správce oken. Sice má své mouchy, ale přednosti to dostatečně vyvažují. Navíc se i ty mouchy dají odstranit.
Poslední věc, na kterou jsem narazil a která mě donutila upravit xmonad.hs
bylo ne zrovna přátelské chování k oknům, která si nastavují nějakou
požadovanou velikost. XMonad tyto rady totiž totálně ignoruje. Ve většině
případů je to docela žádoucí chování, jediná výjimka jsou okna, u kterých nemá
moc smysl měnit velikost. V mém případě šlo hlavně o Frozen
Bubble a dosbox.
Jedna možnost řešení by bylo vyjmenovat dotyčné aplikace a přímo oknům nastavit režim floating. To se mi ale nelíbilo, protože by to nebylo ani pohodlné, ani spolehlivé, a často bych musel měnit konfiguraci.
Společným znakem oken, která mají fixní velikost, je nastavení minimální a
maximální velikosti okna na stejnou hodnotu. Toto nastavení je
v WM_NORMAL_HINTS
a dá se zjistit třeba přes xprop
. Toto pole má typ
XSizeHints
a nejpřesnější popis, který jsem našel, vypadá takto:
typedef struct {
; /* marks which fields in this
long flags structure are defined */
, y; /* Obsolete */
int x, height; /* Obsolete */
int width, min_height;
int min_width, max_height;
int max_width, height_inc;
int width_inc{
struct int x; /* numerator */
int y; /* denominator */
} min_aspect, max_aspect;
, base_height;
int base_width;
int win_gravity/* this structure may be extended in the future */
} XSizeHints;
To jistě není žádný zázrak, ale už se s tím dá něco dělat. Zajímavé hodnoty
jsou ty s prefixem min_
a max_
. Pokud jsou nastavené na jinou hodnotu než 0
a zároveň se rovnají odpovídající si hodnoty, okno má zřejmě nastavenou fixní
velikost.
isFixed :: [CLong] -> Bool
= minWidth h == maxWidth h
isFixed h && minHeight h == maxHeight h
&& all (>0) [minWidth h, maxWidth h, minHeight h, maxHeight h]
V modulu XMonad.Util.WindowProperties
je k dispozici funkce
getProp32s :: String -> Window -> X (Maybe [CLong])
, s jejíž pomocí už se dá
napsat potřebná funkce pro manage hook. Definice typu CLong
je v modulu
Foreign.C.Types
.
isNonResizable :: Query Bool
= ask >>= \w -> liftX $ do
isNonResizable <- getProp32s "WM_NORMAL_HINTS" w
atom return $ case atom of
Just hints -> hasFixedSize hints
Nothing -> False
Poslední chybějící kus jsou funkce na vrácení požadovaných rozměrů. Vlastně jde jenom o čitelnější zápisy vytažení příslušné hodnoty ze seznamu:
= (!! 5) :: [CLong] -> CLong
minWidth = (!! 6) :: [CLong] -> CLong
minHeight = (!! 7) :: [CLong] -> CLong
maxWidth = (!! 8) :: [CLong] -> CLong maxHeight
A to je asi tak všechno. Zatím mám pocit, že to funguje, žádné chyby jsem
nepozoroval. Kompletní soubor stačí nakopírovat do ~/.xmonad/lib/
,
naimportovat do konfiguračního souboru a použít.