XMonadでワークスペース毎に異なる壁紙を設定する


はじめに

記事タイトルを「XMonadでfehを使わずに壁紙を設定する方法」とかにしたかったのですが、諸事情によりできませんでした。

依存パッケージ

  • feh
  • imagemagick

「諸事情」です。

ソースをみたところ、しっかりfehを呼び出していました。

目的

  • ワークスペース毎に異なる壁紙を設定する。
  • xmonad.hs内で壁紙を管理する。

デメリット

  • 壁紙の切り替えに若干のラグを挟みます。

メリット

  • ワークスペース間で壁紙を変えることができる
  • 何もかもHaskellに押し付けることで達成感を得られる

実装

設定する壁紙は

  • ~/Pictures/wallpapers/ワークスペース番号.jpg
  • ~/Pictures/wallpapers/main.jpg

です。

1.jpgはワークスペース1の壁紙、4.jpgはワークスペース4の壁紙として設定され、ワークスペースを切り替える毎に変更されます。番号のファイルがない場合はmain.jpgが設定されます。

以下が実装です。

~/.xmonad/xmonad.hs
{-# LANGUAGE LambdaCase #-}

import Control.Monad
import Data.List
import Data.Monoid
import Data.Ord
import System.Directory
import System.Posix.Files

import XMonad.Hooks.WallpaperSetter


myLogHook :: X ()
myLogHook = setWallpaper

myWallpaperDir :: IO FilePath
myWallpaperDir = (++ "/Pictures/wallpapers/") <$> getHomeDirectory

myWallpaper :: FilePath
myWallpaper = "main.jpg"

spWallpapers :: [FilePath]
spWallpapers = map (++ ".jpg") myWorkspaces

getWallpaper :: FilePath -> IO Wallpaper
getWallpaper spwPath = do
      (doesFileExist <$> (++ spwPath) =<< myWallpaperDir) >>= \case
         True  -> return $ WallpaperFix spwPath
         False -> return $ WallpaperFix myWallpaper

setWallpaper :: X ()
setWallpaper = do
      wallpapers'  <- io $ traverse getWallpaper spWallpapers
      wallpaperDir <- io $ myWallpaperDir
      let wplist = WallpaperList $ zip myWorkspaces wallpapers'
          wpconf = (WallpaperConf wallpaperDir) wplist
      wallpaperSetter wpconf

myWorkspaces :: [WorkspaceId]
myWorkspaces = map show [1 .. 9 :: Int]

getHomeDirectory関数でホームディレクトリを取得できます(末尾にスラッシュがないことに注意)。

実態としては「ワークスペース毎に設定」というよりも、「該当するワークスペースに来た時に壁紙を変更する」のほうが正しいです。

まとめ

Haskell力が少し上がった気がした。