haskell 仅限XMonad中的内部间距

qyyhg6bp  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(172)

在XMonad中是否可以只在图块之间留有间距,即在图块周围没有间距?最左边的图块到左边没有间距,最上面的图块到顶部没有间距,等等。

我还没有能够找到一个合适的选项删除外部间距阅读文档。
https://hackage.haskell.org/package/xmonad-contrib-0.17.1/docs/XMonad-Layout-Spacing.html
https://hackage.haskell.org/package/xmonad-contrib-0.17.1/docs/XMonad-Layout-Gaps.html
这是我在xmonad.hs中的当前间距配置。

myConfig = def
    ...
    -- , layoutHook = smartSpacingWithEdge 10 $ myLayout
    , layoutHook = smartSpacing 10 $ myLayout
    ...

编辑:测试Ismore的解决方案。
这种方法看起来很有前途,但是屏幕边框、窗口边框和间隙看起来是完全独立的。例如,你不能通过将屏幕边框设置为0来否定最外面的窗口边框。我不完全确定间隙和屏幕边框之间的区别,它们似乎在完全相同的地方(外部环绕边框)添加了间距。
使用此代码,

testSpace = spacingRaw True (Border 30 30 30 30) True (Border 40 40 40 40) True
testGaps = gaps [(U,20), (D,20), (L,20), (R,20)]
expandedL = testGaps . testSpace $ myLayout

我把缝隙涂成绿色,屏幕边框涂成蓝色,窗口边框涂成红色。我不知道缝隙或屏幕边框是最外面的,这里我把缝隙(绿色)涂成最靠近边缘的:

再做一些实验,看起来间隙、屏幕边框和窗口边框并不相互作用。

--                                           `False` produces the same outcome as `True` with the parameter to the left set to all 0's.
--                                           |
testSpace = spacingRaw True (Border 0 0 0 0) True (Border 40 40 40 40) True
testGaps = gaps [(U,0), (D,0), (L,0), (R,0)]
expandedL = testGaps . testSpace $ myLayout

移除间隙和屏幕边框(绿色和蓝色矩形),但窗口边框(红色矩形)仍然存在,从而创建外部间距。

nqwrtyyt

nqwrtyyt1#

免责声明:我还没有测试过这个解决方案,也没有Xmonad env来测试它,但是这不适合放在评论部分。
对于这种“扩展布局”,我不知道你是否必须使用gapsspacingRaw或两者都用。无论如何,下面有一些片段,我认为你应该配置每一种方式。
gaps应该使用关联列表[(screen border, num of pixels)]进行配置。在文档之前,这应该足够了。

import XMonad.Layout.Gaps

-- Set up, down, left and right screen gaps to 0
expandedL = gaps [(U,0), (D,0), (L,0), (R,0) ]

myConfig = def
    ...
    , layoutHook = expandedL $ myLayout
    ...

另一个可能性是使用细粒度的窗口间距函数spacingRaw。它有很多参数,我想你应该禁用屏幕边框。注意你可以设置边框为一些像素,然后禁用它。这有助于发送消息toggleScreenSpacingEnabled,如果你愿意

import XMonad.Layout.Spacing

--           |- fine grained constructor for spacing
--           |         |- Enable Smart border
--           |         |     |- Set screen border to 10 pixel except for the top one
--           |         |     |                  |- Disable screen borders
--           |         |     |                  |      |- Add a 10 pixel border to windows
--           |         |     |      T  B  R  L  |      |       T  B  R  L  |- Enable window borders
expandedL = spacingRaw True (Border 0 10 10 10) False (Border 10 10 10 10) True

myConfig = def
    ...
    , layoutHook = expandedL $ myLayout
    ...

也许你需要同时修改这两个修饰符。我想你可以简单地把它们连在一起

import XMonad.Layout.Spacing
import XMonad.Layout.Gaps

noGaps = gaps [(U,0), (D,0), (L,0), (R,0)]
noSpace = spacingRaw True (Border 0 10 10 10) False (Border 10 10 10 10) True

-- chain both mods
expandedL = noSpace  . noGaps 

myConfig = def
    ...
    , layoutHook = expandedL $ myLayout
    ...

在OP版本之后编辑

我发现您遇到了间距无法检测边缘是“内部”还是“外部”(在窗口内或窗口与屏幕之间)的问题。请注意,检测这样的问题可能很困难,例如,如果您有收缩的可用窗口或浮动窗口。
尽管如此,我认为您可以编写自己的LayoutModifier,只实现pureModifier。我不太喜欢xmonad库,所以下面的代码只是一个草图(我只从文档中构建它,并查看Spacing源代码,我手边甚至没有编译器,所以不要期待任何工作代码)

import qualified XMonad.Util.Rectangle as R
import           XMonad.Layout.LayoutModifier
import           Data.Function (on)
import           Data.List (minimumBy)

-- Probably you need to enable some compiler extension.
-- It will warn you with the right one
data Expanded a = Expanded

-- expand is defined as "add 10 pixel space to each window; then expand outer borders"
-- Notice you can define expand = ModifiedLayout Expanded but this way you ensure expand is applied to spaced windows.
expand :: l a -> ModifiedLayout Expanded (ModifiedLayout Spacing l) a
expand = ModifiedLayout Expanded . spacing 10

instance Eq a => LayoutModifier Expanded a where
  -- the last parameter of this function is the window list and rectangles
  -- returned by the underlying layout (the spacing layout in your case)
  pureModifier Expanded screen_rectangle window_stack window_list = 
     let rectangle_coords = fmap (pixelsToCoordinates . snd) window_list
         -- Notice that this may fail on runtime if no windows are on the stack...
         minimum_x = minimumBy (compare `on` point_x1) rectangle_coords 
         minimum_y = minimumBy (compare `on` point_y1) rectangle_coords 
         maximum_x = maximumBy (compare `on` point_x2) rectangle_coords 
         maximum_y = maximumBy (compare `on` point_y2) rectangle_coords
         -- this function takes a rectangle and change the borders to match the screen borders if the rectangle border is outer
         extend_border rect = 
            case pixelsToCoordinates rect of
              PointRectangle x1 y1 x2 y2 = 
                 let new_x1 = if x1 == minimum_x then point_x1 (pixelsToCoordinates screen_rectangle) else x1
                     new_y1 = if y1 == minimum_y then point_y1 (pixelsToCoordinates screen_rectangle) else y1
                     new_x2 = if x2 == maximum_x then point_x2 (pixelsToCoordinates screen_rectangle) else x2 
                     new_y2 = if y2 == maximum_y then point_y2 (pixelsToCoordinates screen_rectangle) else y2 
                 in coordinatesToRectangle (PointRectangle new_x1 new_y2 new_x2 new_y2)
         extended_rectangles = fmap (\(w, r) -> (w, extend_border r)) window_list 
      in if null window_list
          then ([], Nothing)
          else (extended_rectangles, Nothing)

-- then you can expand your layouts with this
myConfig = def
    ...
    , layoutHook = expand $ myLayout
    ...

相关问题