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 {
long flags; /* marks which fields in this
structure are defined */
int x, y; /* Obsolete */
int width, height; /* Obsolete */
int min_width, min_height;
int max_width, max_height;
int width_inc, height_inc;
struct {
int x; /* numerator */
int y; /* denominator */
} min_aspect, max_aspect;
int base_width, base_height;
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
isFixed h = minWidth h == maxWidth 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
isNonResizable = ask >>= \w -> liftX $ do
atom <- getProp32s "WM_NORMAL_HINTS" w
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:
minWidth = (!! 5) :: [CLong] -> CLong
minHeight = (!! 6) :: [CLong] -> CLong
maxWidth = (!! 7) :: [CLong] -> CLong
maxHeight = (!! 8) :: [CLong] -> CLong
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.