Search code examples
haskellxmonad

How to override XMonad.Hooks.FadeInactive for some tiles?


I'm trying to implement this code into my xmonad.hs, so i get selective fadeout for inactive tiles but dont know any haskell, so this has been all trial and error...

import XMonad
import XMonad.Hooks.FadeInactive
import Control.Monad (filterM,liftM, join)
import Data.IORef
import Data.List
import qualified Data.Set as S
import qualified XMonad.StackSet as W
import XMonad.Util.EZConfig(additionalKeys,removeKeys)

myFadeHook toggleFadeSet = fadeOutLogHook $ fadeIf (testCondition toggleFadeSet) 0.7
doNotFadeOutWindows = title =? "Call with " <||> className =? "QupZilla" <||> className =? "qpdfview"

testCondition :: IORef (S.Set Window) -> Query Bool
testCondition floats =
    liftM not doNotFadeOutWindows <&&> isUnfocused
    <&&> (join . asks $ \w -> liftX . io $ S.notMember w `fmap` readIORef floats)

toggleFadeOut :: Window -> S.Set Window -> S.Set Window
toggleFadeOut w s | w `S.member` s = S.delete w s
                  | otherwise = S.insert w s


main = do
  toggleFadeSet <- newIORef S.empty
  xmonad $ defaultConfig
  {
  logHook = myFadeHook toggleFadeSet
  , modMask = mod4Mask
  } `additionalKeys`
  [
  ((mod4Mask, xK_f), withFocused $ io . modifyIORef toggleFadeSet . toggleFadeOut
  ]

Which looks like this now:

import           XMonad                          hiding ((|||))
import           XMonad.Hooks.FadeInactive
import           XMonad.Hooks.DynamicLog
import           XMonad.Hooks.ManageDocks
import           XMonad.Hooks.UrgencyHook
import           XMonad.Layout.Accordion
import           XMonad.Layout.DecorationMadness
import           XMonad.Layout.Fullscreen
import           XMonad.Layout.Grid
import           XMonad.Layout.LayoutCombinators
import           XMonad.Layout.NoBorders
import           XMonad.Layout.PerWorkspace
import           XMonad.Layout.Renamed
import           XMonad.Layout.Tabbed
import           XMonad.Layout.Spacing
import           XMonad.Prompt
import           XMonad.Prompt.Input
import qualified XMonad.StackSet                 as W
import           XMonad.Util.EZConfig(additionalKeys,removeKeys)
import           XMonad.Util.Scratchpad
import           XMonad.Util.Run(spawnPipe)
import           System.IO
import           Control.Monad (filterM,liftM, join)
import           Data.IORef
import           Data.List
import qualified Data.Set as S
import qualified XMonad.StackSet as W
import           Data.Ratio                      ((%))

myFadeHook toggleFadeSet = fadeOutLogHook $ fadeIf (testCondition toggleFadeSet) 0.7
doNotFadeOutWindows = title =? "Call with " <||> className =? "QupZilla" <||> className =? "qpdfview"

testCondition :: IORef (S.Set Window) -> Query Bool
testCondition floats =
    liftM not doNotFadeOutWindows <&&> isUnfocused
    <&&> (join . asks $ \w -> liftX . io $ S.notMember w `fmap` readIORef floats)

toggleFadeOut :: Window -> S.Set Window -> S.Set Window
toggleFadeOut w s | w `S.member` s = S.delete w s
                  | otherwise = S.insert w s

main :: IO ()

main = do
  xmproc <- spawnPipe "xmobar"
  toggleFadeSet <- newIORef S.empty
  xmonad $ defaultConfig
    { terminal = "xfce4-terminal"
    , modMask = mod4Mask
    , borderWidth = 0
    , focusedBorderColor = "#56F48B"
    , layoutHook = myLayoutHook
    , manageHook = manageHook defaultConfig <+> myManageHook
    , handleEventHook = mconcat
                  [ docksEventHook
                  , handleEventHook defaultConfig ]
    , logHook = myFadeHook toggleFadeSet
          <+> dynamicLogWithPP xmobarPP
                        { ppOutput = hPutStrLn xmproc
                        , ppTitle = xmobarColor "#56F48B" "" . shorten 50
                        }
    } `additionalKeys` myKeys
  where
      -- keybindings
      myKeys = [ ((mod4Mask,                 xK_b           ), spawn "qupzilla")
               , ((mod4Mask,                 xK_r           ), spawn "emacs")
               , ((mod4Mask,                 xK_u           ), scratchpad)
               , ((mod4Mask,                 xK_y           ), focusUrgent)
               , ((mod4Mask .|. controlMask, xK_space       ), myLayoutPrompt)
               , ((mod4Mask, xK_f), withFocused $ io . modifyIORef toggleFadeSet . toggleFadeOut)
               ]
      scratchpad = scratchpadSpawnActionTerminal "xfce4-terminal"

      -- layouts
      myLayoutHook = avoidStrutsOn [U] $
                     smartBorders $
                     smartSpacingWithEdge 2 $
                     tall ||| wide ||| full ||| circle ||| sTabbed ||| acc
      tall   = renamed [Replace "tall"] $ Tall 1 0.03 0.5
      wide   = renamed [Replace "wide"] $ Mirror tall
      full   = renamed [Replace "full"] $ Full
      circle = renamed [Replace "circle"] $ circleSimpleDefaultResizable
      sTabbed = renamed [Replace "tabbed"] $ simpleTabbed
      acc = renamed [Replace "accordion"] $ Accordion

      -- layout prompt (w/ auto-completion and all layouts)
      myLayoutPrompt = inputPromptWithCompl myXPConfig "Layout"
                       (mkComplFunFromList' allLayouts)
                       ?+ (sendMessage . JumpToLayout)
      myXPConfig = defaultXPConfig { autoComplete = Just 1000 }
      allLayouts = ["tall", "wide", "circle", "full", "tabbed", "accordion"]

      -- manageHook
      myManageHook =     manageDocks
                     <+> floatHook
                     <+> fullscreenManageHook
                     <+> scratchpadManageHookDefault
  -- Inspect with xprop: appName is the first element in WM_CLASS, while
  -- className is the second.
  floatHook = composeAll [ appName =? "gimp-2.8"    --> doFloat
                         , className =? "qupzilla" --> doF (W.shift "1")
                         ]

Now when i compile i just get this error, any idea how i can fix this is much appreciated :)

Error detected while loading xmonad configuration file: /home/n3p/.xmonad/xmonad.hs

xmonad.hs:70:68: error:
  * Variable not in scope: toggleFadeSet :: IORef (S.Set Window)
  * Perhaps you meant 'toggleFadeOut' (line 39)

Please check the file for errors.

Solution

  • You are binding toggleFadeSet in the main do-block:

    toggleFadeSet <- newIORef S.empty
    

    toggleFadeSet, however, is only in scope in the body of the do-block, and not in the where block beneath it; so when you try to use it (in what I presume is the line 70 mentioned by the error message)...

    myKeys = [ ((mod4Mask,                 xK_b           ), spawn "qupzilla")
             -- etc.
             , ((mod4Mask, xK_f), withFocused $ io . modifyIORef toggleFadeSet . toggleFadeOut)
    

    ... you get a "variable not in scope" error. To fix it, you can either move the definition of myKeys to a let within the do-block. Another option is leaving myKeys where it is, but turning it into a function, to which you pass the IORef:

    main = do
      xmproc <- spawnPipe "xmobar"
      toggleFadeSet <- newIORef S.empty
      xmonad $ defaultConfig
        { terminal = "xfce4-terminal"
        -- etc.
        } `additionalKeys` myKeys toggleFadeSet
      where
          -- keybindings
          myKeys toggleFadeSet = 
              [ ((mod4Mask,                 xK_b           ), spawn "qupzilla")
              , ((mod4Mask,                 xK_r           ), spawn "emacs")
              , ((mod4Mask,                 xK_u           ), scratchpad)
              , ((mod4Mask,                 xK_y           ), focusUrgent)
              , ((mod4Mask .|. controlMask, xK_space       ), myLayoutPrompt)
              , ((mod4Mask, xK_f), withFocused $ io . modifyIORef toggleFadeSet . toggleFadeOut)
              ]
          -- etc.