XMonad: как отобразить текущее видимое рабочее пространство на xmobar при использовании нескольких экранов?

#xmonad #xmobar

#xmonad #xmobar

Вопрос:

Я использую XMonad в настройке с несколькими физическими экранами.

Я бы хотел, чтобы на каждом из физических экранов был экземпляр xmobar , который
показывает, какое рабочее пространство отображается на этом конкретном экране, независимо от того, является ли
это рабочее пространство «текущим» / «активным» или нет.

Например.

  --------------    --------------                                                       
|              |  |              |                                                      
|              |  |              |                                                      
|              |  |              |                                                      
|              |  |              |                                                      
 --------------    --------------                                                       
|Workspace 3   |  |Workspace 5   |                                                      
 --------------    --------------                                                       
 

Мой текущий (свернутый для наглядности) xmonad.hs приведен ниже.

 import XMonad                                                                           
import XMonad.Layout.NoBorders                                                          
import XMonad.Hooks.ManageDocks                                                         
import XMonad.Hooks.DynamicLog                                                          
import XMonad.Util.Run                                                                  
import XMonad.Layout.IndependentScreens                                                 
                                                                                        
main = do                                                                               
    n <- countScreens                                                                   
    xmprocs <- mapM (i -> spawnPipe $ "xmobar"    " -x "    show i) [0..n-1]           
                                                                                        
    xmonad $ docks def                                                                  
        { layoutHook = avoidStruts $ smartBorders $ layoutHook defaultConfig            
        , logHook = mapM_ (xmobarPipe -> dynamicLogWithPP $ def                        
            { ppOutput = hPutStrLn xmobarPipe                                           
            , ppCurrent = s -> s                                                       
            , ppVisible = s -> ""                                                      
            , ppHidden = s -> ""                                                       
            , ppLayout = s -> ""                                                       
            , ppTitle = s -> ""                                                        
            }) xmprocs                                                                  
        }                                                                               
 

То есть мне удалось создать 2 экземпляра xmobar, по одному для каждого экрана. Однако он просто показывает текущее активное рабочее пространство (на разных экранах) на xmobar обоих экранов. Например. это показало бы:

  --------------    --------------                                                       
|              |  |              |                                                      
|              |  |              |                                                      
|              |  |              |                                                      
|              |  |              |                                                      
 --------------    --------------                                                       
|Workspace 3   |  |Workspace 3   |                                                      
 --------------    --------------                                                       
 

Теперь, как мне достичь того, чего я на самом деле хочу?

Я думаю, что конфигурация здесь
https://github.com/nwf/xconfig/blob/208e6d6ce48fba45ec30bb1df1389f9ff2263edd/xmonad/lib/XMonad/Actions/XMobars.hs#L163 может содержать подсказки к ответу, но я недостаточно хорошо разбираюсь в Haskell, чтобы
вернуться от этого примера к чему-то минимальному, что я могу использовать.

Ответ №1:

Это работает:

 import GHC.IO.Handle.Types (Handle)

import XMonad (MonadIO, WorkspaceId, Layout, Window, ScreenId, ScreenDetail, WindowSet, layoutHook, logHook, X, io, ScreenId(..), gets, windowset, xmonad)
import Graphics.X11.ExtraTypes.XF86 (xF86XK_MonBrightnessUp, xF86XK_MonBrightnessDown)
import XMonad.Layout.NoBorders (smartBorders)
import XMonad.Hooks.ManageDocks (docks, avoidStruts)
import XMonad.Hooks.DynamicLog (def)
import XMonad.Util.Run (spawnPipe, hPutStrLn)
import XMonad.Layout.IndependentScreens (countScreens)
import XMonad.StackSet (current, screen, visible, Screen, workspace, tag)

spawnXMobar :: MonadIO m => Int -> m (Int, Handle)
spawnXMobar i = (spawnPipe $ "xmobar"    " -x "    show i) >>= (handle -> return (i, handle))

spawnXMobars :: MonadIO m => Int -> m [(Int, Handle)]
spawnXMobars n = mapM spawnXMobar [0..n-1]

type ScreenFoo = Screen WorkspaceId (Layout Window) Window ScreenId ScreenDetail

visibleScreens :: WindowSet -> [ScreenFoo]
visibleScreens cws = ([current cws])    (visible cws)

joinToString :: [String] -> String
joinToString workspaceIds = foldl (  ) "" workspaceIds

myLogHookForPipe :: WindowSet -> (Int, Handle) -> X ()
myLogHookForPipe currentWindowSet (i, xmobarPipe) =
    io $ hPutStrLn xmobarPipe $ -- write to pipe and lift to XMonad
    joinToString $ map (tag . workspace) $  -- extract workspace names and join into a single string
    filter ((==) (S i) . screen) $  -- filter to this xmobar's screen only
    visibleScreens currentWindowSet  -- get list of all visible screens

myLogHook :: [(Int, Handle)] -> X ()
myLogHook xmobarPipes = do
    currentWindowSet <- gets windowset
    mapM_ (myLogHookForPipe currentWindowSet) xmobarPipes

main = do
    n <- countScreens
    xmobarPipes <- spawnXMobars n

    xmonad $ docks def
        { layoutHook = avoidStruts $ smartBorders $ layoutHook def
        , logHook = myLogHook xmobarPipes
        }