You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让XMonad的manageHook在窗口属性动态变更时重新执行?

XMonad窗口动态属性变更后重新应用manageHook规则的解决方法

XMonad自带的manageHook只会在窗口创建时执行一次,要是窗口后续动态修改了WM_NAME或WM_CLASS属性,之前设置的规则就没法触发了。要解决这个问题,我们可以监听这些属性的变更事件,一旦检测到变化就重新对目标窗口执行manageHook规则。

实现步骤

1. 导入必要模块

先把需要的模块导进来,这些模块负责处理X11事件、重新管理窗口等核心功能:

import XMonad
import XMonad.Hooks.EwmhDesktops (ewmh)
import XMonad.Query (runQuery)
import qualified XMonad.StackSet as W
import Data.Monoid (Endo)

2. 编写属性变更监听钩子

写一个事件处理函数,专门监听PropertyNotify事件——当窗口的WM_NAME或WM_CLASS属性变更时,重新执行myManageHook规则:

myPropertyHook :: Event -> X ()
myPropertyHook (PropertyNotifyEvent { ev_window = w, ev_atom = a }) = do
    -- 获取WM_NAME和WM_CLASS对应的X11 Atom
    wmName <- getAtom "WM_NAME"
    wmClass <- getAtom "WM_CLASS"
    -- 检测变更的属性是否是我们关心的
    if a == wmName || a == wmClass
        then do
            -- 对当前窗口执行manageHook规则
            ruleActions <- runQuery myManageHook w
            windows $ appEndo ruleActions
            -- 强制刷新窗口状态,确保变更生效
            refresh
        else return ()
-- 忽略其他类型的事件
myPropertyHook _ = return ()

3. 整合到XMonad主配置

把上面写的钩子加到主配置的handleEventHook里,同时记得启用ewmh(它是处理X11属性事件的基础):

main :: IO ()
main = xmonad $ ewmh $ def
    { manageHook = myManageHook
    -- 组合默认事件钩子和我们自定义的属性监听钩子
    , handleEventHook = myPropertyHook <+> handleEventHook def
    -- 这里可以加你的其他配置,比如修饰键、工作区设置等
    , modMask = mod4Mask  -- 示例:用Win键作为修饰键
    }

4. 注意事项

  • 确保myManageHook里的规则是幂等的:比如多次执行doFloat不会出问题(XMonad本身已经处理了重复浮动的情况,但自定义动作要注意)。
  • 不要直接覆盖handleEventHook,要用<+>和默认钩子组合,避免丢失其他默认事件处理逻辑。
  • 测试的时候可以用xprop工具手动修改窗口的WM_NAME或WM_CLASS,看看规则会不会触发。

完整配置片段

import XMonad
import XMonad.Hooks.EwmhDesktops (ewmh)
import XMonad.Query (runQuery)
import qualified XMonad.StackSet as W
import Data.Monoid (Endo)

-- 你的原有manageHook规则
myManageHook :: X (Endo WindowSet)
myManageHook = composeAll
    [ className =? "confirm" --> doFloat
    , title =? "My App" --> doFloat
    -- 其他自定义规则...
    ]

-- 自定义属性变更监听钩子
myPropertyHook :: Event -> X ()
myPropertyHook (PropertyNotifyEvent { ev_window = w, ev_atom = a }) = do
    wmName <- getAtom "WM_NAME"
    wmClass <- getAtom "WM_CLASS"
    when (a == wmName || a == wmClass) $ do
        ruleActions <- runQuery myManageHook w
        windows $ appEndo ruleActions
        refresh
myPropertyHook _ = return ()

main :: IO ()
main = xmonad $ ewmh $ def
    { manageHook = myManageHook
    , handleEventHook = myPropertyHook <+> handleEventHook def
    , modMask = mod4Mask
    -- 其他配置项...
    }

内容的提问来源于stack exchange,提问作者Oh Fiveight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 21:18:13