Files
xmonad-contrib/DynamicLog.hs
Christian Thiemann 2c600dbc7c Two new dynamic log functions that display the title of the currently focused window
I liked the window-title-in-statusbar feature of dwm very much and wanted to
have that in XMonad as well.  Somewhere on the net I found some code to put
into Config.hs (and sorry, that was last week and I already forgot where I got
it from) which I modified and put into the DynamicLog extension.  One can now
set the logHook in Config.hs either to dynamicLogWithTitle to get the usual
layout description and workspace list plus window title enclosed in angle
brackets, or dynamicLogWithTitleColored "white" (or "red" etc.) to have xmonad
print out some ^fg() markers for dzen to display the window title in the given
color.

Some windows (like terminals or browsers) change their window title from time
to time but xmonad does not recognize this.  So I started learning Haskell to
provide patches for X11-extras and xmonad so that PropertyNotify events are
captured and, if the event notifies about a WM_NAME property change, call the
logHook to update the status bar.

Hope you find this useful,
  Christian
2007-10-06 17:31:13 +00:00

133 lines
4.4 KiB
Haskell

-----------------------------------------------------------------------------
-- |
-- Module : XMonadContrib.DynamicLog
-- Copyright : (c) Don Stewart <dons@cse.unsw.edu.au>
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Don Stewart <dons@cse.unsw.edu.au>
-- Stability : unstable
-- Portability : unportable
--
-- DynamicLog
--
-- Log events in:
--
-- > 1 2 [3] 4 8
--
-- format. Suitable to pipe into dzen.
--
-----------------------------------------------------------------------------
module XMonadContrib.DynamicLog (
-- * Usage
-- $usage
dynamicLog, dynamicLogWithTitle, dynamicLogWithTitleColored, dynamicLogXinerama, pprWindowSet, pprWindowSetXinerama
) where
--
-- Useful imports
--
import XMonad
import {-# SOURCE #-} Config (workspaces)
import Operations () -- for ReadableSomeLayout instance
import Data.Maybe ( isJust )
import Data.List
import Data.Ord ( comparing )
import qualified StackSet as S
import Data.Monoid
import XMonadContrib.NamedWindows
-- $usage
--
-- To use, set:
--
-- > import XMonadContrib.DynamicLog
-- > logHook = dynamicLog
--
-- To get the title of the currently focused window after the workspace list:
--
-- > import XMonadContrib.DynamicLog
-- > logHook = dynamicLogWithTitle
--
-- To have the window title highlighted in any color recognized by dzen:
--
-- > import XMonadContrib.DynamicLog
-- > logHook = dynamicLogWithTitleColored "white"
--
-- %import XMonadContrib.DynamicLog
-- %def -- comment out default logHook definition above if you uncomment any of these:
-- %def logHook = dynamicLog
-- %def logHook = dynamicLogWithTitle
-- %def logHook = dynamicLogWithTitleColored "white"
-- |
-- Perform an arbitrary action on each state change.
-- Examples include:
-- * do nothing
-- * log the state to stdout
--
-- An example logger, print a status bar output to dzen, in the form:
--
-- > 1 2 [3] 4 7
--
dynamicLog :: X ()
dynamicLog = withWindowSet $ \ws -> do
let desc = description . S.layout . S.workspace . S.current $ ws
io . putStrLn $ "(" ++ desc ++ ") " ++ pprWindowSet ws
-- Appends title of currently focused window to log output
-- Arguments are: pre-title text and post-title text
dynamicLogWithTitle_ :: String -> String -> X ()
dynamicLogWithTitle_ pre post= do ld <- withWindowSet $ return . description . S.layout . S.workspace . S.current -- layout description
ws <- withWindowSet $ return . pprWindowSet -- workspace list
wt <- withWindowSet $ maybe (return "") (fmap show . getName) . S.peek -- window title
io . putStrLn $ "(" ++ ld ++ ") " ++ ws ++ " " ++ pre ++ wt ++ post
dynamicLogWithTitle :: X ()
dynamicLogWithTitle = dynamicLogWithTitle_ "<" ">"
-- As dynamicLogWithTitle but with colored window title instead of angle brackets (works with dzen only)
dynamicLogWithTitleColored :: String -> X ()
dynamicLogWithTitleColored color = dynamicLogWithTitle_ ("^fg(" ++ color ++ ")") "^fg()"
pprWindowSet :: WindowSet -> String
pprWindowSet s = concatMap fmt $ sortBy cmp
(map S.workspace (S.current s : S.visible s) ++ S.hidden s)
where f Nothing Nothing = EQ
f (Just _) Nothing = LT
f Nothing (Just _) = GT
f (Just x) (Just y) = compare x y
wsIndex = flip elemIndex workspaces . S.tag
cmp a b = f (wsIndex a) (wsIndex b) `mappend` compare (S.tag a) (S.tag b)
this = S.tag (S.workspace (S.current s))
visibles = map (S.tag . S.workspace) (S.visible s)
fmt w | S.tag w == this = "[" ++ S.tag w ++ "]"
| S.tag w `elem` visibles = "<" ++ S.tag w ++ ">"
| isJust (S.stack w) = " " ++ S.tag w ++ " "
| otherwise = ""
-- |
-- Workspace logger with a format designed for Xinerama:
--
-- > [1 9 3] 2 7
--
-- where 1, 9, and 3 are the workspaces on screens 1, 2 and 3, respectively,
-- and 2 and 7 are non-visible, non-empty workspaces
--
dynamicLogXinerama :: X ()
dynamicLogXinerama = withWindowSet $ io . putStrLn . pprWindowSetXinerama
pprWindowSetXinerama :: WindowSet -> String
pprWindowSetXinerama ws = "[" ++ unwords onscreen ++ "] " ++ unwords offscreen
where onscreen = map (S.tag . S.workspace)
. sortBy (comparing S.screen) $ S.current ws : S.visible ws
offscreen = map S.tag . filter (isJust . S.stack)
. sortBy (comparing S.tag) $ S.hidden ws