在Xmonad中为特定窗口配置无边框



目标

为Xmonad中的特定窗口设置无边框。

具体的例子:我希望firefoxfeh总是没有边界。我想设置这个不仅为特定的布局(例如,单窗口)或特定的窗口模式,如浮动。

尝试

我最直接的想法是在manageHook中添加一行,该行假定用于处理窗口创建。因此,我在自定义的ManageHook中添加了一行:

className =? "firefox" --> ask >>= w -> liftX $ withDisplay $ d -> io $ setWindowBorderWidth d w 0 >> idHook

它可以编译,但不幸的是,当我启动firefox时什么也没有发生。

然后我试着调试它:

  1. 测试了下面的工作(新的firefox窗口是浮动的),这表明我的自定义ManageHook工作,我的逻辑(修改窗口之后的idHook)应该是OK的。
className =? "firefox" --> ask >>= liftX . float >> idHook
  1. 通过在XMonad.Actions.NoBorders中尝试toggleBorder来测试setWindowBorderWidth功能。toggleBorder调用setWindowBorderWidth做类似的事情。我使用一个键绑定来调用toggleBorder,它工作。因此,setWindowBorderWidth在创建窗口后的Xmonad会话期间工作得很好。

  2. 测试了以下内容(在这里找到),但它不起作用,与我的代码(尝试A)相同。

className =? "firefox" --> ask >>= liftX . toggleBorder >> idHook

尝试B

我在XMonad.Layout.NoBorders和这个答案中找到了hasBorder函数,但我没有成功。

如果我只把className =? "firefox" --> hasBorder False放在ManageHook而不使用layoutHook,什么也不会发生。我检查了hasBorder的源代码,发现它只广播消息而不设置边界。我想我可能需要从XMonad.Layout.NoBorders调用layoutHook来真正设置边界,但我不确定我应该使用哪一个。我也不确定我是否需要指定任何布局使用XMonad.Layout.NoBorders

  1. Xmonad设置边界后ManageHook,所以我的代码在尝试A无效?

  2. 如果Q1为真,是否意味着当窗口绘制在屏幕上时,我只能在LayoutHook(可能使用XMonad.Layout.NoBorders)设置无边界?

  3. 如果Q2为真,我需要指定一个布局和哪个layoutHook我可以使用?

我选择尝试B:

从xmonad-contrib:

导入NoBorders模块
import XMonad.Layout.NoBorders

在manageHook中定义约束:

className =? "feh"     --> hasBorder False
className =? "firefox" --> hasBorder False

并应用模块的布局修饰符之一,例如smartBorders所有查看你的布局:

layoutHook = smartBorders $ Full ||| ResizableTall 1 (3/100) (1/2) [] ||| ...
注意:这只会影响在之后创建的的windows重新编译并重新启动XMonad。已经存在的firefox和feh实例在关闭并重新启动之前仍然会有它们的边框。

我想我找到了问题的答案。

Xmonad是否在ManageHook之后设置边界,因此我在尝试A中的代码无效?

是的。

看起来像xmonad窗口初始化逻辑在xmonad/Operations.hs。创建窗口时,调用manage()函数。函数的最后三行:

  1. loadManageHook
  2. 应用ManageHookrunQuery()
  3. 运行windows()函数,从配置中加载边界信息,并应用setInitialProperties()函数根据边界配置设置边界。

最后一步setInitialProperties()调用setWindowBorderWidth()的边界宽度从配置加载,这使我的setWindowBorderWidth()作为ManageHook步骤无效。

如果我不改变这个逻辑在XMonad/操作。是的,看起来我只能尝试b。然而,我真的发现窗口跳跃问题很烦人。这不仅发生在Full布局中,我使用Tall与单个窗口。当我在两个工作区之间切换时,这两个工作区都有一个没有边框的窗口,我看到这个跳跃。视觉效果会影响屏幕上的所有像素,因为它需要缩放整个窗口。

如果Q1是真的,这是否意味着当窗口绘制在屏幕上时,我只能在LayoutHook(可能使用XMonad.Layout.NoBorders)设置没有边界?

。除了LayoutHook,还有一个可能是logHook

如果Q2为真,我是否需要指定一个布局和哪个layoutHook我可以使用?

是的。但是,如果使用logHook,则不需要覆盖默认布局。

解决方案

让我们建立一个新的XMonad扩展来实现这个人们在12年前就要求的功能。