Как удалить границы всех плавающих окон в XMonad

Есть несколько похожих вопросов, но ни один из них не решает их для меня, например этот вопрос объясняет, как удалить границы полноэкранных плавающих окон.

Использование XMonad.Layout.NoBorders вы можете делать много интересных вещей, таких как удаление границ из определенных окон или если это единственное окно или только полноэкранные плавающие окна.

Я не смог найти ничего для всех плавающих окон, однако, если бы кто-нибудь мог просто указать мне какой-нибудь инструмент, который я мог бы использовать, чтобы проверить, является ли окно плавающим или нет, я уверен, что мог бы попытаться взломать решение.

Любые предложения приветствуются


person Dylan    schedule 07.03.2019    source источник


Ответы (1)


Я буду использовать исходный код XMonad.Layout.NoBorders в качестве ссылки, поскольку я не могу найти ничего более подходящего из уже существующего. Мы хотим увидеть, как он реализует «удаление границ в полноэкранных плавающих окнах», чтобы увидеть, можно ли легко смягчить его, чтобы «удалить границы в плавающих окнах» (без полноэкранного ограничения).

Согласно ответу на вопрос, который вы связали:

layoutHook = lessBorders OnlyFloat $ avoidStruts $ myLayout

OnlyFloat кажется спецификатором для «удаления границ в полноэкранных плавающих окнах», поэтому давайте проверим определение этого:

data Ambiguity = Combine With Ambiguity Ambiguity
               | OnlyFloat
               | Never
               | EmptyScreen
               | OtherIndicated
               | Screen
    deriving (Read, Show)

Не слишком полезно само по себе. Мы должны посмотреть в другом месте, чтобы увидеть, как код обрабатывает эти значения.


Можно с уверенностью сказать, что первой нужно проверить функцию lessBorders:

lessBorders :: (SetsAmbiguous p, Read p, Show p, LayoutClass l a) =>
        p -> l a -> ModifiedLayout (ConfigurableBorder p) l a
lessBorders amb = ModifiedLayout (ConfigurableBorder amb [])

Из сигнатуры типа lessBorders мы видим, что:

OnlyFloat :: (SetsAmbiguous p, Read p, Show p) => p

Это хороший знак, так как это означает, что lessBorders явно не ожидает Ambiguity: здесь мы можем расширить функциональность, реализовав собственный SetsAmbiguous и передав его существующему lessBorders. Давайте теперь посмотрим на SetsAmbiguous и его реализацию Ambiguity:

class SetsAmbiguous p where
    hiddens :: p -> WindowSet -> Maybe (W.Stack Window) -> [(Window, Rectangle)] -> [Window]

instance SetsAmbiguous Ambiguity where
    hiddens amb wset mst wrs
      | Combine Union a b <- amb = on union next a b
      | Combine Difference a b <- amb = on (\\) next a b
      | Combine Intersection a b <- amb = on intersect next a b
      | otherwise = tiled ms ++ floating
      where next p = hiddens p wset mst wrs
            nonzerorect (Rectangle _ _ 0 0) = False
            nonzerorect _ = True
            screens =
              [ scr | scr <- W.screens wset,
                      case amb of
                            Never -> True
                            _ -> not $ null $ integrate scr,
                      nonzerorect . screenRect $ W.screenDetail scr]
            floating = [ w |
                        (w, W.RationalRect px py wx wy) <- M.toList . W.floating $ wset,
                        px <= 0, py <= 0,
                        wx + px >= 1, wy + py >= 1]
            ms = filter (`elem` W.integrate' mst) $ map fst wrs
            tiled [w]
              | Screen <- amb = [w]
              | OnlyFloat <- amb = []
              | OtherIndicated <- amb
              , let nonF = map integrate $ W.current wset : W.visible wset
              , length (concat nonF) > length wrs
              , singleton $ filter (1==) $ map length nonF = [w]
              | singleton screens = [w]
            tiled _ = []
            integrate y = W.integrate' . W.stack $ W.workspace y

hiddens — единственный метод, который нам нужно реализовать. Его аргументами являются наше значение SetsAmbiguous, WindowSet и некоторые другие вещи, и он возвращает список окон, у которых не должно быть границ. Существует много логики для операций объединения и других значений Ambiguity, но сейчас это не имеет для нас значения. Нас интересует вот этот фрагмент:

            floating = [ w |
                        (w, W.RationalRect px py wx wy) <- M.toList . W.floating $ wset,
                        px <= 0, py <= 0,
                        wx + px >= 1, wy + py >= 1]

Это очень многообещающе. Он определяет набор плавающих окон, извлекая все окна из раздела floating WindowSet, преобразовывая его в список (изначально это Data.Map) и отфильтровывая все окна, которые не покрывают весь экран. Все, что нам нужно сделать, это удалить фильтр.


После внесения этого изменения и удаления всего ненужного кода, относящегося к мозаичным окнам и операциям набора (что составляет большую часть реализации), мы просто получаем:

import XMonad.Layout.NoBorders
import qualified XMonad.StackSet as W
import qualified Data.Map as M

data AllFloats = AllFloats deriving (Read, Show)

instance SetsAmbiguous AllFloats where
    hiddens _ wset _ _ = M.keys $ W.floating wset

Тогда мы можем сказать:

layoutHook = lessBorders AllFloats $ myLayout...
person DarthFennec    schedule 31.07.2019
comment
Вау, спасибо за ваш подробный ответ. Я тот, кто почти не знает Haskell, только настоящие основы, и вы объяснили это так хорошо, что я мог понять. Честно говоря, это один из лучших ответов, которые я когда-либо видел на вопрос. Ваше здоровье. - person Dylan; 01.08.2019
comment
У меня есть один вопрос. Я заметил, что в haskell, когда вы что-то импортируете, по той или иной причине иногда вам приходится делать что-то вроде import qualified XMonad.StackSet as W. Я предполагаю, что это то, что вы сделали здесь для буквы М. Просто интересно, что такое М? - person Dylan; 01.08.2019
comment
Поскольку вы используете ключи слова, и это М, я предполагаю, что это Data.Map? - person Dylan; 01.08.2019
comment
Я не могу заставить его работать. Я получаю следующую ошибку Типа Не удалось сопоставить ожидаемый тип [(Окно, Прямоугольник)] -> [Окно] с фактическим типом [Окно] В выражении: M.keys $ W.floating wset - person Dylan; 01.08.2019
comment
@Dylan Да, поскольку я изменил этот код из XMonad.Layout.NoBorders, я использовал тот же импорт, который использует. Я отредактировал свой ответ и добавил импорт для ясности. Вам действительно не нужно квалифицировать импорт, но это хорошая идея, потому что становится очевидным, откуда берутся функции, которые вы вызываете. Это особенно важно, если несколько импортируемых библиотек определяют функции с одинаковыми именами. - person DarthFennec; 01.08.2019
comment
@Dylan Вы уверены, что у вашего hiddens правильное количество аргументов? Итак, hiddens _ wset _ _ = ..., а не hiddens _ wset _ = ...? - person DarthFennec; 01.08.2019
comment
Мне удалось заставить его работать. Пришлось написать hiddens _ wset _ _ _ вместо hiddens _ wset _ _. - person Dylan; 02.08.2019
comment
Не относящийся к этому вопросу вообще, но так как вы, кажется, знаете много. Есть ли лучший способ определить размеры окна в XMonad с типом лучше, чем RationalRect? Может быть что-то определяющее размер по расстоянию от края экрана в пикселях? - person Dylan; 02.08.2019
comment
@Dylan О, это странно, не нужно так много аргументов. Я имею в виду, что если это работает, то работает, но в этом случае я должен что-то упустить ... Я думаю, что большинство вещей принимает только RationalRect, но с некоторой математикой вы можете написать функцию, которая выполняет преобразование в RationalRect, и передает ваши пиксельные координаты и общий размер экрана в этом. - person DarthFennec; 02.08.2019