特定のウィンドウにフォーカスがあるとき、または特定のワークスペースにあるときに、Xmonad で modMask を変更するにはどうすればよいですか?

特定のウィンドウにフォーカスがあるとき、または特定のワークスペースにあるときに、Xmonad で modMask を変更するにはどうすればよいですか?

私は左 Alt を主な modkey として使用していますが、特定のアプリケーションでは Alt + キーをバインディングとして使用し、その特定のアプリケーションでは左 Winkey を modkey として使用したいと考えています。

logHook がこのロジックをプラグインする適切な場所のようですが、それをどのように行うのか理解するのに苦労しています。

大幅に簡略化すると、私の構成は次のようになります

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
  }

どこ

pp = dzenPP {
    -- more stuff
}

logHookで現在のウィンドウの名前を取得できました

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

しかし、メイン関数の defaultConfig で modMask をその場で置き換える方法がわかりません。

ワークスペースごとに modkey が異なると嬉しいです。たとえば、ワークスペース 1 から 8 では Alt キー、9 では左 Win キーなどです。これも問題なく、このようなソリューションは、現在フォーカスされているウィンドウに基づいて簡単に変更できると思います。

答え1

これは失敗しました。XMonad は期待どおりに動作しますが、アプリケーションは押されたキーを受け取りません。つまり、5 番目のワークスペースでは winkey を modKey として使用し、他のワークスペースでは altkey を使用します。以前は modKey+数字でワークスペースを切り替えていました。5 番目のワークスペースで Alt+2 を押すと、XMonad は何もせず (これは正しい)、アプリケーションも何もしません (これは間違っています)。Chrome は 2 番目のタブに切り替わりません。


さて、私はなんとかそれを実現しました。XMonad.Actions.PerWorkspaceKeys

関連する構成:

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
}

リスト modifiedKeys は修飾子 (この例では、5 番目のワークスペースでは Winkey、その他すべてでは左 Alt) を使用し、リスト unmodifiedKeys はそのまま使用されます。

後でウィンドウ固有のキーを調べるかもしれませんが、今のところは完了です。

関連情報