使用 xmonad 使每个 window 透明

Making every window transparent with xmonad

我希望每个 window 都是透明的,我正在使用 xmonad 和 X11。我对 Haskell、xmonad 或 X11 中的任何一个都不是很熟悉。

我如何为此配置 xmonad?我什至不知道如何开始。

为此,您需要一个事件挂钩,用于在创建新 windows 时设置不透明度 属性。这就是我正在使用的(需要 xprop 在路径上):

import XMonad
import Graphics.X11.Xlib
import Graphics.X11.Xlib.Extras
import Data.Monoid
import Data.Word

setTransparentHook :: Event -> X All
setTransparentHook ConfigureEvent{ev_event_type = createNotify, ev_window = id} = do
  setOpacity id opacity
  return (All True) where
    opacityFloat = 0.9
    opacity = floor $ fromIntegral (maxBound :: Word32) * opacityFloat
    setOpacity id op = spawn $ "xprop -id " ++ show id ++ " -f _NET_WM_WINDOW_OPACITY 32c -set _NET_WM_WINDOW_OPACITY " ++ show op
setTransparentHook _ = return (All True)

main = xmonad $ def
  { handleEventHook = setTransparentHook <+> handleEventHook def }

进程

Give a man a fish and you feed him for a day; teach a man to fish and you feed him for a lifetime.

本着这句话的精神,我正在描述我想出这个的过程。请注意,我对 Haskell、xmonad 和 X11 的所有经验都非常有限。

最初的想法是我需要一个脚本来设置所有 windows 的不透明度(事实证明这并不是我所需要的)。我知道 linux 上的复合管理器会做这种事情(视觉效果),所以我通过 man compton.

查看了 compton(我正在使用的)的手册页

搜索“不透明度”时,我看到 --opacity-rule 标志,其中提到建议使用 compton-trans,所以我查看了 its source。在命令行中尝试脚本,发现我需要 window ID 来设置其不透明度,所以我查看了如何执行此操作。

一个解决方案是使用 xwininfo。您可以使用 xwininfo -tree -root 列出所有 windows。我想我需要解析它的输出并且已经在查找 awk 教程。

然后我明白了:“等等,如果我只是在 window 创建时设置不透明度怎么办?Xmonad 是一个 window 管理器,它绝对应该有 window ID !”。所以我查看了 xmonad's config options,在那里我找到了 handleEventHook 属性。通过单击 EventAll 类型,我找出了我需要哪些导入(Graphics.X11.Xlib.ExtrasData.Monoid)。

通过应对 default:

为我的事件挂钩创建框架
import XMonad
import Graphics.X11.Xlib.Extras
import Data.Monoid

myEventHook :: Event -> X All
myEventHook _ = return (All True)

现在需要一些Haskell知识,我想在Event是window创建事件时做点什么。通过 Event docs 和一些探测,我发现我需要 ConfigureEvent 其中 ev_event_typecreateNotifyev_window 是创建的 window ID。要使用 createNotify 我还导入 Graphics.X11.Xlib:

import XMonad
import Graphics.X11.Xlib
import Graphics.X11.Xlib.Extras
import Data.Monoid

myEventHook :: Event -> X All
myEventHook ConfigureEvent{ ev_event_type = createNotify, ev_window = id } = do
  return (All True)
myEventHook _ = return (All True)

现在我们到底想做什么?我们想用 compton-trans 命令生成一个 shell 进程。整个 xmonad 中使用的简单函数 spawn

myEventHook :: Event -> X All
myEventHook ConfigureEvent{ ev_event_type = createNotify, ev_window = id } = do
  spawn $ "compton-trans -w " ++ show id ++ " 50"
  return (All True)
myEventHook _ = return (All True)

成功了!这很好,但我注意到它有点慢,而且它仍然具有并不真正需要的康普顿依赖性。所以我再次查看 compton-trans 源代码,发现 the last line that actually does the work 只使用了 xprop!现在这很棒,因为我不需要 compton-trans 的所有内容,它们会进行一些检查并为方便用户进行了优化。使用一些数字转换,我得出了如上所示的最终版本。使用可执行文件的直接路径甚至可能更快。

我有时也使用 ghci ~/.xmonad/xmonad.hs 来检查一些类型和 man xprop/man whatever 来检查文档。

我希望这可以帮助 xmonad 的朋友们入门!如果有人有一些改进,请告诉我。