From 141e071d0d523a521e0e790efbb57a95854aaaed Mon Sep 17 00:00:00 2001 From: jao Date: Sun, 24 Jul 2022 16:12:39 +0100 Subject: documentation: header levels re-adjusted --- doc/window-managers.org | 482 ++++++++++++++++++++++++------------------------ 1 file changed, 241 insertions(+), 241 deletions(-) (limited to 'doc/window-managers.org') diff --git a/doc/window-managers.org b/doc/window-managers.org index ea3aeea..db8207c 100644 --- a/doc/window-managers.org +++ b/doc/window-managers.org @@ -3,284 +3,284 @@ Listed below are ways to interface xmobar with your window manager of choice. -*** Property-based Logging -***** =XMonadLog= - - - Aliases to XMonadLog - - - Displays information from xmonad's =_XMONAD_LOG=. You can use - this by using functions from the [[https://hackage.haskell.org/package/xmonad-contrib-0.16/docs/XMonad-Hooks-DynamicLog.html][XMonad.Hooks.DynamicLog]] - module. By using the =xmonadPropLog= 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. +* Property-based Logging +** =XMonadLog= + + - Aliases to XMonadLog + + - Displays information from xmonad's =_XMONAD_LOG=. You can use + this by using functions from the [[https://hackage.haskell.org/package/xmonad-contrib-0.16/docs/XMonad-Hooks-DynamicLog.html][XMonad.Hooks.DynamicLog]] + module. By using the =xmonadPropLog= 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. - #+begin_src haskell - main = do - spawn "xmobar" - xmonad $ def - { logHook = dynamicLogString defaultPP >>= xmonadPropLog - } - #+end_src + #+begin_src haskell + main = do + spawn "xmobar" + xmonad $ def + { logHook = dynamicLogString defaultPP >>= xmonadPropLog + } + #+end_src - This plugin can be used as a sometimes more convenient - alternative to =StdinReader=. For instance, it allows you to - (re)start xmobar outside xmonad. + This plugin can be used as a sometimes more convenient + alternative to =StdinReader=. For instance, it allows you to + (re)start xmobar outside xmonad. -***** =UnsafeXMonadLog= +** =UnsafeXMonadLog= - - 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 ==) or - remove tags from dynamic text that you pipe through to xmobar in this - way. + - 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 ==) 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! + - 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! - #+begin_src shell - ws1 ws2 - #+end_src + #+begin_src shell + ws1 ws2 + #+end_src - - If you use xmonad, It is advised that you still use =xmobarStrip= for - the =ppTitle= in your logHook: + - If you use xmonad, It is advised that you still use =xmobarStrip= for + the =ppTitle= in your logHook: - #+begin_src haskell - myPP = defaultPP { ppTitle = xmobarStrip } - main = xmonad $ def - { logHook = dynamicLogString myPP >>= xmonadPropLog - } - #+end_src + #+begin_src haskell + myPP = defaultPP { ppTitle = xmobarStrip } + main = xmonad $ def + { logHook = dynamicLogString myPP >>= xmonadPropLog + } + #+end_src -***** =XPropertyLog PropName= +** =XPropertyLog PropName= - - Aliases to =PropName= - - Reads the X property named by =PropName= (a string) and displays its - value. The [[../examples/xmonadpropwrite.hs][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= + - Reads the X property named by =PropName= (a string) and displays its + value. The [[../examples/xmonadpropwrite.hs][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. -***** =UnsafeXPropertyLog PropName= +** =UnsafeXPropertyLog PropName= - - 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 =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. -***** =NamedXPropertyLog PropName Alias= +** =NamedXPropertyLog PropName Alias= - - Aliases to =Alias= - - Same as =XPropertyLog= but a custom alias can be specified. + - Aliases to =Alias= + - Same as =XPropertyLog= but a custom alias can be specified. -***** =UnsafeNamedXPropertyLog PropName Alias= +** =UnsafeNamedXPropertyLog PropName Alias= - - Aliases to =Alias= - - Same as =UnsafeXPropertyLog=, but a custom alias can be specified. + - Aliases to =Alias= + - Same as =UnsafeXPropertyLog=, but a custom alias can be specified. -*** Logging via Stdin -***** =StdinReader= +* Logging via Stdin +** =StdinReader= - - 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 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. -***** =UnsafeStdinReader= +** =UnsafeStdinReader= - - Aliases to UnsafeStdinReader - - Displays any text received by xmobar on its standard input. - - Similar to [[=UnsafeXMonadLog=][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 using =UnsafeXMonadLog=! + - Aliases to UnsafeStdinReader + - Displays any text received by xmobar on its standard input. + - Similar to [[=UnsafeXMonadLog=][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 using =UnsafeXMonadLog=! -*** Pipe-based Logging -***** =PipeReader "default text:/path/to/pipe" Alias= +* Pipe-based Logging +** =PipeReader "default text:/path/to/pipe" Alias= - - 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= + - 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= -***** =MarqueePipeReader "default text:/path/to/pipe" (length, rate, sep) Alias= +** =MarqueePipeReader "default text:/path/to/pipe" (length, rate, sep) Alias= - - Generally equivalent to PipeReader + - Generally equivalent to PipeReader - - Text is displayed as marquee with the specified length, rate in 10th - seconds and separator when it wraps around + - Text is displayed as marquee with the specified length, rate in 10th + seconds and separator when it wraps around - #+begin_src haskell - Run MarqueePipeReader "/tmp/testpipe" (10, 7, "+") "mpipe" - #+end_src + #+begin_src haskell + Run MarqueePipeReader "/tmp/testpipe" (10, 7, "+") "mpipe" + #+end_src - - Expands environment variables in the first argument + - Expands environment variables in the first argument -***** =BufferedPipeReader Alias [(Timeout, Bool, "/path/to/pipe1"), ..]= +** =BufferedPipeReader Alias [(Timeout, Bool, "/path/to/pipe1"), ..]= - - Display data from multiple pipes. + - 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. + - 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= + - 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. + - 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: + - Use it for OSD-like status bars e.g. for setting the volume or + brightness: - #+begin_src haskell - Run BufferedPipeReader "bpr" - [ ( 0, False, "/tmp/xmobar_window" ) - , ( 15, True, "/tmp/xmobar_status" ) - ] - #+end_src + #+begin_src haskell + Run BufferedPipeReader "bpr" + [ ( 0, False, "/tmp/xmobar_window" ) + , ( 15, True, "/tmp/xmobar_status" ) + ] + #+end_src - 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. + 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][examples/status.sh]] + - Take a look at [[../examples/status.sh][examples/status.sh]] - - Expands environment variables for the pipe path + - Expands environment variables for the pipe path -*** Handle-based Logging -***** =HandleReader Handle Alias= +* Handle-based Logging +** =HandleReader Handle Alias= - - Display data from a Haskell =Handle= + - 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 of =read= & - =write= Handles. Pass the =read= Handle to HandleReader and write your - output to the =write= Handle: - - #+begin_src haskell - (readHandle, writeHandle) <- createPipe - xmobarProcess <- forkProcess $ xmobar myConfig - { commands = - Run (HandleReader readHandle "handle") : commands myConfig - } - hPutStr writeHandle "Hello World" - #+end_src - -*** Software Transactional Memory - - 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. - -***** =QueueReader (TQueue a) (a -> String) String= - - - 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= safe =TQueue a= with - =Control.Concurrent.STM.newTQueueIO=. Write to it from the user - code with =writeTQueue=, and read with =readTQueue=. A common use - is to overwite =ppOutput= from =XMonad.Hooks.DynamicLog= as shown - below. - - #+begin_src haskell - 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 } - #+end_src - - Note that xmonad uses blocking Xlib calls in its event loop and isn't - normally compiled with - [[https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/using-concurrent.html][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. - -*** Example of using the DBus IPC interface with XMonad - - Bind the key which should {,un}map xmobar to a dummy value. This is - necessary for {,un}grabKey in xmonad. - - #+begin_src haskell - ((0, xK_Alt_L), pure ()) - #+end_src - - 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). - - #+begin_src haskell - 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 - #+end_src + - 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 of =read= & + =write= Handles. Pass the =read= Handle to HandleReader and write your + output to the =write= Handle: + + #+begin_src haskell + (readHandle, writeHandle) <- createPipe + xmobarProcess <- forkProcess $ xmobar myConfig + { commands = + Run (HandleReader readHandle "handle") : commands myConfig + } + hPutStr writeHandle "Hello World" + #+end_src + +* Software Transactional Memory + + 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. + +** =QueueReader (TQueue a) (a -> String) String= + + - 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= safe =TQueue a= with + =Control.Concurrent.STM.newTQueueIO=. Write to it from the user + code with =writeTQueue=, and read with =readTQueue=. A common use + is to overwite =ppOutput= from =XMonad.Hooks.DynamicLog= as shown + below. + + #+begin_src haskell + 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 } + #+end_src + + Note that xmonad uses blocking Xlib calls in its event loop and isn't + normally compiled with + [[https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/using-concurrent.html][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. + +* Example of using the DBus IPC interface with XMonad + + Bind the key which should {,un}map xmobar to a dummy value. This is + necessary for {,un}grabKey in xmonad. + + #+begin_src haskell + ((0, xK_Alt_L), pure ()) + #+end_src + + 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). + + #+begin_src haskell + 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 + #+end_src -- cgit v1.2.3