xmonad: Check if a window is present in a workspace

122 Views Asked by At

In this certain section of my xmonad.hs config:

changeWorkspaces f i z = do
                windows $ f i
                when (z == True && windowsPresent /= "0") $ notifyWS i
                    where notifyWS i = spawn ("notify-send \"hello, workspace: " ++ i ++ "\"") 

                          windowsPresent :: XState -> String
                          windowsPresent = show . length . W.index . windowset 

And specifically in..

    when (z == True && windowsPresent /= "0") $ notifyWS i
                       ^^^^^^^^^^^^^^^^^^^^^

..I'm trying to check to see if a window or any number of windows (windowsPresent) is present in a workspace. If there are, as well as if z is equal to True, then run notifyWS.

The code above is one of my many experiements to solve this problem, and I'm aware that it's just a shot in the dark.

I've read through XMonad.StackSet and XMonad.Operations, and I have a hard time understanding their usage. I've tried the functions peek, index, and member, even looking through their source code, but getting them into boolean or arithmetic comparison is out of my limited knowledge for Haskell.


Provided error:
xmonad.hs:223:54: error:
    • Couldn't match type: [Char]
                     with: XState -> String
      Expected: XState -> String
        Actual: String
    • In the second argument of ‘(/=)’, namely ‘"0"’
      In the second argument of ‘(&&)’, namely ‘windowsPresent /= "0"’
      In the first argument of ‘when’, namely
        ‘(z == True && windowsPresent /= "0")’
    |
223 |                 when (z == True && windowsPresent /= "0") $ notifyWS i
    |

Code snippet:

    -- // workspace navigation
    -- mod-[1..9]         = Switch to workspace 
    -- mod-shift-[1..9]   = Move window to workspace
    -- mod-control-[1..9] = Move window to workspace and switch to that workspace
    [ ((modm .|. m, k), changeWorkspaces f i z)
        | (i, k) <- zip (myWorkspaces) [xK_1 .. xK_9]
        , (f, m, z) <- [ (W.greedyView, 0, False), 
                         (W.shift, shiftMask, True), 
                         (\i -> W.greedyView i . W.shift i, controlMask, True) ]
    ] 
        where 
            changeWorkspaces f i z = do
                windows $ f i
                when (z == True && windowsPresent /= "0") $ notifyWS i
                    where notifyWS i = spawn ("notify-send \"hello, workspace: " ++ i ++ "\"") 
 
                          windowsPresent :: XState -> String
                          windowsPresent = read . show . length . W.index . windowset
1

There are 1 best solutions below

3
lsmor On BEST ANSWER

Ok, I think I understood what you want. I haven't tested the solution (no Xmonad available now). Let me know if it works

-- You may need to import things

    [ ((modm .|. m, k), changeWorkspaces f i z)
        | (i, k) <- zip (myWorkspaces) [xK_1 .. xK_9]
        , (f, m, z) <- [ (W.greedyView, 0, False), 
                         (W.shift, shiftMask, True), 
                         (\i -> W.greedyView i . W.shift i, controlMask, True) ]
    ] 
        where 
            changeWorkspaces f i z = do
                windows $ f i
                stackset <- gets windowset  -- you need import Control.Monad.State.Class IIRC
                --   Just check for z and windowsPresent.
                when (z && windowsPresent stackset) $ notifyWS i
                    where notifyWS i = spawn ("notify-send \"hello, workspace: " ++ i ++ "\"") 
                          -- This should return True if workspace i has a windows
                          -- If workspace i doesn't exist; then checks if current
                          -- focused workspace has a window open
                          windowsPresent :: WindowSet -> Bool
                          windowsPresent = null . W.index . W.view i

EDIT: For the checking if the current workspace has a window, you can define the function currentWorkSpaceHasWindow = isJust . peek.

For example

-- You may need to import things

    [ ((modm .|. m, k), changeWorkspaces f i z)
        | (i, k) <- zip (myWorkspaces) [xK_1 .. xK_9]
        , (f, m, z) <- [ (W.greedyView, 0, False), 
                         (W.shift, shiftMask, True), 
                         (\i -> W.greedyView i . W.shift i, controlMask, True) ]
    ] 
        where 
            changeWorkspaces f i z = do
                windows $ f i
                stackset <- gets windowset  -- you need import Control.Monad.State.Class IIRC
                -- just move condition to its own line for clarity
                let cond = z && not (windowsPresent stackset) && currentWorkSpaceHasWindow stackset  
                when cond $ notifyWS i
                    where notifyWS i = spawn ("notify-send \"hello, workspace: " ++ i ++ "\"") 
                          -- This should return True if workspace i has a windows
                          -- If workspace i doesn't exist; then checks if current
                          -- focused workspace has a window open
                          windowsPresent :: WindowSet -> Bool
                          windowsPresent = null . W.index . W.view i
                          -- import Data.Maybe for isJust function.
                          -- True if the current ws has a window
                          currentWorkSpaceHasWindow :: WindowSet -> Bool
                          currentWorkSpaceHasWindow = isJust . peek