Listed below are ways to interface xmobar with your window manager of choice.
- Aliases to XMonadLog
- Displays information from xmonad’s
_XMONAD_LOG
. You can use this by using functions from the XMonad.Hooks.DynamicLog module. By using thexmonadPropLog
function in your logHook, you can write the the above property. The following shows a minimal xmonad configuration that spawns xmobar and then writes to the_XMONAD_LOG
property.main = do spawn "xmobar" xmonad $ def { logHook = dynamicLogString defaultPP >>= xmonadPropLog }
This plugin can be used as a sometimes more convenient alternative to
StdinReader
. For instance, it allows you to (re)start xmobar outside xmonad.
- Aliases to UnsafeXMonadLog
- Displays any text received by xmobar on the
_XMONAD_LOG
atom. - Will not do anything to the text received. This means you can pass
xmobar dynamic actions. Be careful to escape (using
<raw=…>
) or remove tags from dynamic text that you pipe through to xmobar in this way. - Sample usage: Send the list of your workspaces, enclosed by actions
tags, to xmobar. This enables you to switch to a workspace when you
click on it in xmobar!
<action=`xdotool key alt+1`>ws1</action> <action=`xdotool key alt+1`>ws2</action>
- If you use xmonad, It is advised that you still use
xmobarStrip
for theppTitle
in your logHook:myPP = defaultPP { ppTitle = xmobarStrip } main = xmonad $ def { logHook = dynamicLogString myPP >>= xmonadPropLog }
- Aliases to
PropName
- Reads the X property named by
PropName
(a string) and displays its value. The examples/xmonadpropwrite.hs script in xmobar’s distribution can be used to set the given property from the output of any other program or script.
- Aliases to
PropName
- Same as
XPropertyLog
but the input is not filtered to avoid injection of actions (cf.UnsafeXMonadLog
). The program writing the value of the read property is responsible of performing any needed cleanups.
- Aliases to
Alias
- Same as
XPropertyLog
but a custom alias can be specified.
- Aliases to
Alias
- Same as
UnsafeXPropertyLog
, but a custom alias can be specified.
- Aliases to StdinReader
- Displays any text received by xmobar on its standard input.
- Strips actions from the text received. This means you can’t pass
dynamic actions via stdin. This is safer than
UnsafeStdinReader
because there is no need to escape the content before passing it to xmobar’s standard input.
- Aliases to UnsafeStdinReader
- Displays any text received by xmobar on its standard input.
- Similar to UnsafeXMonadLog, in the sense that it does not strip any
actions from the received text, only using
stdin
and not a property atom of the root window. Please be equally carefully when using this as when usingUnsafeXMonadLog
!
- Reads its displayed output from the given pipe.
- Prefix an optional default text separated by a colon
- Expands environment variables in the first argument of syntax
${VAR}
or$VAR
- Generally equivalent to PipeReader
- Text is displayed as marquee with the specified length, rate in 10th
seconds and separator when it wraps around
Run MarqueePipeReader "/tmp/testpipe" (10, 7, "+") "mpipe"
- Expands environment variables in the first argument
- Display data from multiple pipes.
- Timeout (in tenth of seconds) is the value after which the previous content is restored i.e. if there was already something from a previous pipe it will be put on display again, overwriting the current status.
- A pipe with Timeout of 0 will be displayed permanently, just
like
PipeReader
- The boolean option indicates whether new data for this pipe should make xmobar appear (unhide, reveal). In this case, the Timeout additionally specifies when the window should be hidden again. The output is restored in any case.
- Use it for OSD-like status bars e.g. for setting the volume or
brightness:
Run BufferedPipeReader "bpr" [ ( 0, False, "/tmp/xmobar_window" ) , ( 15, True, "/tmp/xmobar_status" ) ]
Have your window manager send window titles to
/tmp/xmobar_window
. They will always be shown and not reveal your xmobar. Sending some status information to/tmp/xmobar_status
will reveal xmonad for 1.5 seconds and temporarily overwrite the window titles. - Take a look at examples/status.sh
- Expands environment variables for the pipe path
- Display data from a Haskell
Handle
- This plugin is only useful if you are running xmobar from another Haskell program like XMonad.
- You can use
System.Process.createPipe
to create a pair ofread
&write
Handles. Pass theread
Handle to HandleReader and write your output to thewrite
Handle:(readHandle, writeHandle) <- createPipe xmobarProcess <- forkProcess $ xmobar myConfig { commands = Run (HandleReader readHandle "handle") : commands myConfig } hPutStr writeHandle "Hello World"
When invoking xmobar from other Haskell code it can be easier and
more performant to use shared memory. The following plugins
leverage Control.Concurrent.STM
to realize these gains for xmobar.
- Display data from a Haskell
TQueue a
. - This plugin is only useful if you are running xmobar from another haskell program like xmonad.
- You should make an
IO
safeTQueue a
withControl.Concurrent.STM.newTQueueIO
. Write to it from the user code withwriteTQueue
, and read withreadTQueue
. A common use is to overwiteppOutput
fromXMonad.Hooks.DynamicLog
as shown below.main :: IO () main = do initThreads q <- STM.newTQueueIO @String bar <- forkOS $ xmobar myConf { commands = Run (QueueReader q id "XMonadLog") : commands myConf } xmonad $ def { logHook = logWorkspacesToQueue q } logWorkspacesToQueue :: STM.TQueue String -> X () logWorkspacesToQueue q = dynamicLogWithPP def { ppOutput = STM.atomically . STM.writeTQueue q }
Note that xmonad uses blocking Xlib calls in its event loop and isn’t normally compiled with the threaded RTS so an xmobar thread running inside xmonad will suffer from delayed updates. It is thus necessary to enable
-threaded
when compiling xmonad configuration (xmonad.hs
), e.g. by using a custom~/.xmonad/build
script.
Bind the key which should {,un}map xmobar to a dummy value. This is necessary for {,un}grabKey in xmonad.
((0, xK_Alt_L), pure ())
Also, install avoidStruts
layout modifier from
XMonad.Hooks.ManageDocks
Finally, install these two event hooks (handleEventHook
in XConfig
)
myDocksEventHook
is a replacement for docksEventHook
which reacts
on unmap events as well (which docksEventHook
doesn’t).
import qualified XMonad.Util.ExtensibleState as XS
data DockToggleTime = DTT { lastTime :: Time } deriving (Eq, Show, Typeable)
instance ExtensionClass DockToggleTime where
initialValue = DTT 0
toggleDocksHook :: Int -> KeySym -> Event -> X All
toggleDocksHook to ks ( KeyEvent { ev_event_display = d
, ev_event_type = et
, ev_keycode = ekc
, ev_time = etime
} ) =
io (keysymToKeycode d ks) >>= toggleDocks >> return (All True)
where
toggleDocks kc
| ekc == kc && et == keyPress = do
safeSendSignal ["Reveal 0", "TogglePersistent"]
XS.put ( DTT etime )
| ekc == kc && et == keyRelease = do
gap <- XS.gets ( (-) etime . lastTime )
safeSendSignal [ "TogglePersistent"
, "Hide " ++ show (if gap < 400 then to else 0)
]
| otherwise = return ()
safeSendSignal s = catchX (io $ sendSignal s) (return ())
sendSignal = withSession . callSignal
withSession mc = connectSession >>= \c -> callNoReply c mc >> disconnect c
callSignal :: [String] -> MethodCall
callSignal s = ( methodCall
( objectPath_ "/org/Xmobar/Control" )
( interfaceName_ "org.Xmobar.Control" )
( memberName_ "SendSignal" )
) { methodCallDestination = Just $ busName_ "org.Xmobar.Control"
, methodCallBody = map toVariant s
}
toggleDocksHook _ _ _ = return (All True)
myDocksEventHook :: Event -> X All
myDocksEventHook e = do
when (et == mapNotify || et == unmapNotify) $
whenX ((not `fmap` (isClient w)) <&&> runQuery checkDock w) refresh
return (All True)
where w = ev_window e
et = ev_event_type e