问题描述
我使用 Xmonad 作为窗口管理器。为了自动处理全屏窗口,我使用 XMonad.Hooks.EwmhDesktops.fullscreenEventHook。并将其放入我的配置中:
,handleEventHook = handleEventHook def <+> docksEventHook <+> XMonad.Hooks.EwmhDesktops.fullscreenEventHook
我希望能够通过键绑定来切换它。因此,默认情况下,全屏窗口会占据整个屏幕,但是当我关闭 EwmhDesktops.fullscreenEventHook 时,它仅在窗口占据的“平铺”空间中是全屏的。
完整配置为 here
解决方法
将状态添加到 XMonad 本身是非常困难的,因此我们必须使用 IORef
作为外部状态。首先,我们将创建一个全屏事件挂钩,它检查来自 IORef 的布尔值,并且仅在为真时才运行实际的事件挂钩:
toggleableFullscreen :: IORef Bool -> Event -> X All
toggleableFullscreen ref evt =
io (readIORef ref) >>= \isOn ->
if isOn
then XMonad.Hooks.EwmhDesktops.fullscreenEventHook evt
else return (All True)
这使用 io :: IO a -> X a
将 IO
monad 提升为 X
monad。现在,在我们的主函数中,我们想用 newIORef
构造 IORef
:
main = do
fullscreenRef <- newIORef True -- default to being on
-- rest of main goes here
现在,我们还将编辑 main 的 handleEventHook
行,以将 toggleableFullscreen
与传入的 fullscreenRef
一起使用:
,handleEventHook = handleEventHook def <+> docksEventHook <+> toggleableFullscreen fullscreenRef
到此,事件挂钩部分就完成了。现在我们需要一种方法来切换它。 myKeys
函数也需要将 fullscreenRef
作为参数接收,因此您必须将其添加到:
myKeys fullscreenRef conf@(XConfig {XMonad.modMask = modm}) = M.fromList $
-- rest of myKeys
(这是您配置的第 125 行)
然后,您必须添加一个使用 modifyIORef
切换 IORef 的新键绑定(假设为 mod+shift+f):
,((modm .|. shiftMask,xK_f),io (modifyIORef fullscreenRef not))
然后,在您的主函数中,将 fullscreenRef
传递到 myKeys
:
,keys = myKeys fullscreenRef
(第 400 行)
并删除整个块,因为您不使用它(并且它不会进行类型检查):
defaults = def {
-- simple stuff
terminal = myTerminal,focusFollowsMouse = myFocusFollowsMouse,clickJustFocuses = myClickJustFocuses,borderWidth = myBorderWidth,modMask = myModMask,workspaces = myWorkspaces,normalBorderColor = myNormalBorderColor,focusedBorderColor = myFocusedBorderColor,-- key bindings
keys = myKeys,mouseBindings = myMouseBindings,-- hooks,layouts
layoutHook = myLayout,manageHook = myManageHook,handleEventHook = myEventHook,logHook = myLogHook,startupHook = myStartupHook
}
(第 446-467 行)
然后,重新启动 xmonad,您应该可以使用 mod+shift+f 切换全屏事件挂钩。