The Goal
Set no border for specific windows in Xmonad.
Concrete example: I'd like firefox
and feh
always have no border. I want to set this not only for specific layout (e.g., single window) or specific window mode like float.
Attempt A
The most straight forward idea I have is to add a line in manageHook
, which supposes to handle window creation. So I put a line in my customized ManageHook
:
className =? "firefox" --> ask >>= \w -> liftX $ withDisplay $ \d -> io $ setWindowBorderWidth d w 0 >> idHook
It compiles, but unfortunately nothing happens when I start firefox
.
Then I try to debug it:
- Tested the following and it works (new firefox window is floated), which indicates my customized
ManageHook
works, and my logic (modify the window followed byidHook
) should be OK.
className =? "firefox" --> ask >>= liftX . float >> idHook
Tested
setWindowBorderWidth
function by tryingtoggleBorder
in XMonad.Actions.NoBorders.toggleBorder
does something similarly callingsetWindowBorderWidth
. I used a key binding to invoketoggleBorder
and it works. SosetWindowBorderWidth
works well during a Xmonad session after the window is created.Tested the following (found it here) but it doesn't work, same as my code (Attempt A).
className =? "firefox" --> ask >>= liftX . toggleBorder >> idHook
Attempt B
I find the hasBorder
function in XMonad.Layout.NoBorders and also this answer, but I did not succeed.
If I only put className =? "firefox" --> hasBorder False
in ManageHook
but does not use layoutHook
, nothing happens. I checked the source code of hasBorder
and found it only broadcast a message but not set the border. I think I may need to invoke a layoutHook
from XMonad.Layout.NoBorders
to really set the border but I am not sure which one I should use. And I am also not sure if I need to specify any layout to use XMonad.Layout.NoBorders
.
Questions
Does Xmonad set border after
ManageHook
so my code in Attempt A is nullified?If Q1 is true, does it mean I can only set no border at
LayoutHook
(likely usingXMonad.Layout.NoBorders
) when the window is drawn on the screen?If Q2 is true, do I need to specify a layout and which
layoutHook
I can use?
CodePudding user response:
I'd go with attempt B:
Import the NoBorders module from xmonad-contrib:
import XMonad.Layout.NoBorders
Define your constraints in your manageHook:
className =? "feh" --> hasBorder False
className =? "firefox" --> hasBorder False
And apply one of the module's layout modifiers, e.g. smartBorders
to all of your layouts at once:
layoutHook = smartBorders $ Full ||| ResizableTall 1 (3/100) (1/2) [] ||| ...
Note: This will only affect windows created after recompiling and restarting XMonad. Already existing instances of firefox and feh would still have their borders until closed and restarted.
CodePudding user response:
I think I find the answer to my first question.
Does Xmonad set border after ManageHook so my code in Attempt A is nullified?
Yes.
Looks like xmonad window init logic is in XMonad/Operations.hs. When a window is created, the function manage() is called. The last three lines of the function:
- load
ManageHook
, - apply
ManageHook
withrunQuery()
, - run the windows() function, which loads border information from config and applies setInitialProperties() function to set borders according to the border config.
The last step setInitialProperties()
calls setWindowBorderWidth()
with border width loaded from config, which nullifies my setWindowBorderWidth()
as a ManageHook
step.
If I do not change this logic in XMonad/Operations.hs, it looks like I can only go with Attempt B. However, I really find the windows jumping issue annoying. This does not only occur in Full
layout, I am using Tall
with a single window. When I switch between two workspaces, both of which have a single window with no border, I see this jumping. The visual effect affects all pixels on screen since it needs to scale the entire window. Need to find a solution for this.