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 by idHook) should be OK.
className =? "firefox" --> ask >>= liftX . float >> idHook
Tested setWindowBorderWidth function by trying toggleBorder in XMonad.Actions.NoBorders. toggleBorder does something similarly calling setWindowBorderWidth. I used a key binding to invoke toggleBorder and it works. So setWindowBorderWidth 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 using XMonad.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?
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.
I think I find the answers to my questions.
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 with runQuery(),
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.
If Q1 is true, does it mean I can only set no border at LayoutHook (likely using XMonad.Layout.NoBorders) when the window is drawn on the screen?
No. Another possibility besides LayoutHook is logHook.
If Q2 is true, do I need to specify a layout and which layoutHook I can use?
Yes. However, if logHook is used, there is no need to overwrite the default layouts.
Solution
Let's put up a new XMonad extension to achieve this functionality that people asked 12 years ago.
Related
When I remove xmobar I want the top gap to be incremented to make it equal to the bottom gap. On the other hand when I add the bar I want the top gap to be reduced to make it as it was on start.
I have a key binding set to toggle xmobar:
, ("M-w" , spawn "exec $HOME/.config/xmobar/bartoggle.sh")
What i'm trying to achieve is something like this:
, ("M-w" , sequence_ (spawn "exec $HOME/.config/xmobar/bartoggle.sh", toggleGap))
where toggleGap is a function that should toggle 2 commands such as:
sendMessage $ DecGap 20 U and sendMessage $ IncGap 20 U
I thought about using global variables, and I tried with ExtensibleState and IORef modules. However I wasn't able to make them work.
If you have any idea or alternatives on how to do this please let me know.
I have a fresh install of arch linux and am currently trying to theme the terminal (alacritty) and the transparency when I set it in ~/.config/picom/picom.conf never applies when I sudo pkill picom then sudo picom --experimental-backends -b any help in the right direction would be greatly appreciated.
Method 1:
In your picom config file (by default ~/.config/picom/picom.conf) there should a list at the end of Trasparency/Opacity section. There should be some examples on how to set opacity effects. But nevertheless here is the syntax:
opacity-rule = [
"OPACITY_VALUE:class_g ='CLASS_NAME'"
]
OPACITY_VALUE is a number from 1-100 where 0 is fully invisible and 100 is fully opaque. And you can get the CLASS_NAME of any window by executing the following command and clicking on a window.
xprop | grep "CLASS"
Note: The CLASS_NAME value is actually the second one.
So if you want to have the alacritty window transparent, paste the following snippet right in the middle of the opacity-rule list.
"85:class_g ='Alacritty'",
Method 2:
Me personally, I don't use the first method. Because it causes the text to be transparent as well. So if you only want to make your background transparent, go to your alacritty config file (By default, it should be on ~/.config/alacritty/alacritty.yml.
If it is not there, copy everything from the example config located in /usr/share/doc/alacritty/example/alacritty.yml and paste to ~/.config/alacritty/alacritty.yml
There, find the window: section. Under that, paste the line as shown below. The code should look somewhat similar.
window:
opacity: 0.80 #From 0.00 to 1.00
Hope this helps.
I'm using XMonad on a dual screen set up, and would like to be able to cycle focus through every window visible on either screen (say, with alt+tab). The behavior would be similar to XMonad.Actions.WindowNavigation, except it wouldn't be bound to a direction, and just cycle through them in some order that makes sense (left to right, top to bottom for instance).
I've found some code here that claims to manipulate the StackSet to solve this problem, and I got it to compile but it wouldn't do what I wanted. Unfortunately my understanding of Haskell is pretty limited, so I've been unable to either write my own or fix whatever is wrong with the code above.
You can use the CycleWS module in xmonad-contrib
It has bindings that you can use to cycle through non-empty workspaces:
import XMonad.Actions.CycleWS
myKeys homeDir conf#(XConfig {XMonad.modMask = modm}) = M.fromList $
[ -- (your own bindings here)
-- Cycle non-empty workspaces with mod+tab or mod+shift+tab
, ((modm , xK_Tab ), moveTo Next NonEmptyWS)
, ((modm .|. shiftMask, xK_Tab ), moveTo Prev NonEmptyWS)
]
My full config is here if you want a complete example.
This functionality has since been added to xmonad-contrib by this pull request.
Example usage:
import XMonad.Actions.GroupNavigation
within the keys section
-- use Alt+Tab and Alt+Shift+Tab to change focus to different windows across workspaces
((alt, xK_Tab ), nextMatch Forward isOnAnyVisibleWS),
((alt .|. shift, xK_Tab ), nextMatch Backward isOnAnyVisibleWS),
I'm writing a Haskell program with click-and-drag functionality, so with each mouse movement event an update gets painted to the window. At the moment I'm using
renderWithDrawable myCanvas update
However this is flickering a lot. My understanding is that I need to create a separate drawable (a "surface"?), render to that, and then blit it onto the screen window in a single operation. However I'm confused as to the right way to do this.
I've found drawWindowBeginPaintRegion, which talks about eliminating flicker.
However it is removed in Gtk3 according to the Haddock docs. So I'm not sure if I should use this, as it seems to be deprecated.
I've also found renderWithSimilarSurface in Cairo, which seems to do something similar.
I'm also not sure how these functions relate to renderWithDrawable: do I have to use them inside that function, or what?
What is the right way to do this?
Edit
This seems to be a known thing in Cairo. I'm trying to figure out how to handle this in Haskell.
Explanation and solution in Python
Description of how to handle this issue in raw C
The right way to do this is to make sure all your drawing comes from within expose events, and operates on the draw window provided by the event. You can mark a region as "dirty" and trigger a synthetic expose event using drawWindowInvalidateRect, drawWindowInvalidateRegion, or widgetQueueDraw.
A quick worked example of setting up the drawing pipeline follows. It is excerpted from a custom Viewport type, which does Google-maps style panning with smooth motions on drag-and-release operations, that I built for a side-project some time ago. To support that, it has to redraw on mouse motion events, so it addresses a similar use case to your described problem. I've elided irrelevant stuff with ... to highlight the important bits. I've uploaded the complete project to github just now, so you can browse the repo to see the full details of Viewport. (It's been years though, so there's probably a fair bit of bitrot -- don't expect the project to just build and run with modern GHCs/packages.)
viewportNew :: Viewport -> IO DrawingArea
viewportNew v = do
da <- drawingAreaNew
-- ...
on da exposeEvent $ exposeViewport posRef (draw v)
-- ...
exposeViewport :: IORef Position -> RegionRenderer -> EventM EExpose Bool
exposeViewport posRef draw = do
dw <- eventWindow
region <- eventRegion >>= liftIO . regionGetRectangles
-- ...
liftIO . renderWithDrawable dw $ do
-- Cairo () action goes here
-- can reference region to decide which things to draw
draw region
return True -- see documentation of exposeEvent for what this means
This template should take advantage of gtk's built-in double-buffering and work with both the gtk and gtk3 packages.
Currently I use
import XMonad.Layout.NoBorders
...
xmonad $ defaultConfig { layoutHook = noBorders $ layoutHook defaultConfig }
but this makes noBorder all the layouts, not just "Full".
I know, that I can simply copy layoutHook definition from default config and add noBorder before "Full", but I want the beautiful way, hope Haskell provides some means for it.
Instead of using noBorders, you could use smartBorders, which hides the border when there's only one window (or a floated window covers the entire screen). That isn't quite the same thing as only hiding it with the Full layout, but it might be close enough for your purposes.
Failing that, the best option is probably to copy the default layoutHook. It's not very big, and you're quite likely to want to customise it in the future, anyway. You might be able to write a typeclass with instances for all the standard LayoutClasses that applies noBorders to Full, but it'd be uglier than simply copying the default layoutHook.