How to change modMask in Xmonad when specific window is focused, or on specific workspace

x11xmonad

I am using left Alt as my primary modkey, but for certain application I would like to use Alt+keys as my bindings, and for that specific application I want left winkey to be my modkey.

It seems that logHook is the right place to plug this logic in, but I have troubles understanding, how to do it.

Greatly simplified, my configuration looks like

import qualified XMonad.StackSet as W
import XMonad
import XMonad.Hooks.DynamicLog

main = do
  -- some stuff
  xmonad $ defaultConfig {
      modMask = mod1Mask  -- left winkey = mod4Mask, left alt = mod1Mask
    , logHook = do
          dynamicLogWithPP pp
  }

where

pp = dzenPP {
    -- more stuff
}

I could getName of current window in my logHook

winset <- gets windowset
let wname = fmap getName (W.peek winset) -- here I have some window identificator in Maybe

but I do not understand how to replace modMask in my main function, in defaultConfig, on the fly.

I would also be happy if on one workspace modkey will be different. Say, on workspaces 1 to 8 it is an Alt key, and on 9th it's left Winkey. This would do fine too, and I bet such solution can be easily modified to be based on currently focused window.

Best Answer

This failed. XMonad works as expected, but applications do not receive pressed keys. I mean, I use winkey as modKey on 5th workspace, and altkey on other workspaces. I used to switch workspaces with modKey+number. When I press Alt+2 on 5th workspace, XMonad does nothing (which is correct), and application does nothing (which is wrong). Chrome does not switch to 2nd tab, and so on.


Okay, so I managed to do it, using XMonad.Actions.PerWorkspaceKeys.

Related configuration:

import XMonad.Actions.PerWorkspaceKeys

workspaceModkeys = [ (mod1Mask, map show ([1..4] ++ [6..9])) -- use Alt as modkey on all workspaces
                   , (mod4Mask, ["5"])                       -- save 5th (use Win there)
                   ]

modifiedKeysList conf =
  [ ((0,         xK_Return), spawn $ XMonad.terminal conf)  -- launch a terminal
  , ((shiftMask, xK_c     ), kill)  -- close focused window
  ]

unmodifiedKeys conf =
  [ ((0, xF86XK_AudioPlay ), spawn "mpc toggle")
  , ((0, xF86XK_AudioStop ), spawn "mpc stop")
  ]

keysList conf = concat (map modifyKey (modifiedKeysList conf)) ++ (unmodifiedKeys conf)

modifyKey :: ((KeyMask, KeySym), X()) -> [((KeyMask, KeySym), X())]
modifyKey k = map (f k) workspaceModkeys
  where
    f ((mask, key), action) (mod, workspaces) = ((mask .|. mod, key), bindOn (map (\w -> (w, action)) workspaces))

myKeys conf = M.fromList $ keysList conf

main = xmonad $ defaultConfig {
  keys = myKeys
}

List modifiedKeys will use modifier (in this example — Winkey on 5th workspace, and left Alt on all others), list unmodifiedKeys is used as is.

Still might look into window-specific keys later, but I'm done for now.

Related Question