Haskell
xmonad
関数型プログラミング

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力が少し上がった気がした。