Add multimonitor support in a good way

This commit is contained in:
Leon Kowarschick 2020-05-09 15:24:23 +02:00
parent f92fc0173c
commit 3b03a5c324
8 changed files with 128 additions and 92 deletions

View file

@ -1,5 +1,8 @@
*.background: #282828 *.background: #282828
Xcursor.size: 16
Xcursor.theme: capitaine-cursors-light
rofi.lines: 5 rofi.lines: 5
rofi.eh: 2 rofi.eh: 2
rofi.padding: 200 rofi.padding: 200

View file

@ -1,4 +1,4 @@
{ {
"optOut": false, "optOut": false,
"lastUpdateCheck": 1588770448547 "lastUpdateCheck": 1588866305414
} }

View file

@ -65,7 +65,7 @@ inactive-opacity-override = false;
# Blur background of transparent windows. Bad performance with X Render backend. GLX backend is preferred. # Blur background of transparent windows. Bad performance with X Render backend. GLX backend is preferred.
blur-background = false; blur-background = false;
blur-method = "dual_kawase"; #blur-method = "dual_kawase";
#blur-method = "kernel"; #blur-method = "kernel";
blur-strength = 10; # max 20 blur-strength = 10; # max 20
blur-size = 20; blur-size = 20;

View file

@ -170,8 +170,10 @@ label = "%{F#444} %{F-}%{B#444} %time% | %date% %{B-}%{F#444} %{
[module/xmonad] [module/xmonad]
type = custom/script type = custom/script
exec = xmonad-log ;exec = "xmonad-log"
exec = '/home/leon/.config/polybar/polybar-scripts/xmonad-status.sh'
tail = true tail = true
;interval = 1
[module/timerDisplay] [module/timerDisplay]

View file

@ -0,0 +1,17 @@
#!/bin/bash
if [ "$MONITOR" = "HDMI-A-0" ]; then
while true; do
tail -F /tmp/xmonad-state-bar0
done
else
while true; do
tail -F /tmp/xmonad-state-bar1
done
fi
#while true; do
#if read -r line </tmp/.xmonad-state-bar0; then
#echo "$line"
#fi
#done

View file

@ -4,21 +4,23 @@
module Config (main) where module Config (main) where
import Control.Concurrent
import Control.Exception ( catch
, SomeException
)
import Data.Char (isDigit) import Data.Char (isDigit)
import Data.List (isSuffixOf, isPrefixOf) import Data.List ( isSuffixOf , isPrefixOf)
import System.Exit (exitSuccess) import System.Exit (exitSuccess)
import qualified Rofi import qualified Rofi
import qualified Codec.Binary.UTF8.String as UTF8
import qualified DBus as D
import qualified DBus.Client as D
import qualified Data.Map as M import qualified Data.Map as M
import qualified Data.Monoid import qualified Data.Monoid
import Data.Foldable ( for_ )
import qualified System.IO as SysIO import qualified System.IO as SysIO
import XMonad.Layout.HintedGrid import XMonad.Layout.HintedGrid
import XMonad.Layout.TwoPanePersistent
import XMonad hiding ((|||)) import XMonad hiding ((|||))
import XMonad.Actions.Commands import XMonad.Actions.Commands
@ -26,7 +28,6 @@ import XMonad.Actions.CopyWindow
import XMonad.Actions.Submap import XMonad.Actions.Submap
import XMonad.Config.Desktop import XMonad.Config.Desktop
import XMonad.Hooks.DynamicLog import XMonad.Hooks.DynamicLog
import XMonad.Hooks.FadeInactive
import XMonad.Hooks.ManageDocks import XMonad.Hooks.ManageDocks
import XMonad.Hooks.SetWMName (setWMName) import XMonad.Hooks.SetWMName (setWMName)
import XMonad.Layout.BinarySpacePartition import XMonad.Layout.BinarySpacePartition
@ -39,10 +40,9 @@ import XMonad.Layout.NoBorders
import XMonad.Layout.Renamed (renamed, Rename(Replace)) import XMonad.Layout.Renamed (renamed, Rename(Replace))
import XMonad.Layout.ResizableTile import XMonad.Layout.ResizableTile
import XMonad.Layout.Spacing (spacingRaw, Border(..), toggleWindowSpacingEnabled) import XMonad.Layout.Spacing (spacingRaw, Border(..), toggleWindowSpacingEnabled)
import XMonad.Layout.Spiral (spiral)
import XMonad.Layout.ToggleLayouts import XMonad.Layout.ToggleLayouts
import XMonad.Layout.ZoomRow import XMonad.Layout.ZoomRow
import XMonad.Util.EZConfig (additionalKeysP, removeKeysP, checkKeymap) import XMonad.Util.EZConfig (additionalKeysP, removeKeysP)
import XMonad.Util.NamedScratchpad import XMonad.Util.NamedScratchpad
import XMonad.Util.Run import XMonad.Util.Run
import XMonad.Util.SpawnOnce (spawnOnce) import XMonad.Util.SpawnOnce (spawnOnce)
@ -50,6 +50,7 @@ import qualified XMonad.Actions.Navigation2D as Nav2d
import qualified XMonad.Hooks.EwmhDesktops as Ewmh import qualified XMonad.Hooks.EwmhDesktops as Ewmh
import qualified XMonad.Hooks.ManageHelpers as ManageHelpers import qualified XMonad.Hooks.ManageHelpers as ManageHelpers
import qualified XMonad.Layout.BoringWindows as BoringWindows import qualified XMonad.Layout.BoringWindows as BoringWindows
import XMonad.Layout.IndependentScreens
import qualified XMonad.StackSet as W import qualified XMonad.StackSet as W
import qualified XMonad.Util.XSelection as XSel import qualified XMonad.Util.XSelection as XSel
@ -133,13 +134,6 @@ myLayout = avoidStruts . BoringWindows.boringWindows . smartBorders . toggleLayo
in spacingRaw True spacingBorder True gapBorder True in spacingRaw True spacingBorder True gapBorder True
-- }}}
-- Loghook -------------------------------------- {{{
myLogHook :: X ()
myLogHook = return () -- fadeInactiveLogHook 0.95 -- opacity of unfocused windows
-- }}} -- }}}
-- Startuphook ----------------------------- {{{ -- Startuphook ----------------------------- {{{
@ -153,8 +147,9 @@ myStartupHook = do
spawnOnce "mailspring --background" spawnOnce "mailspring --background"
spawnOnce "redshift -P -O 5000" spawnOnce "redshift -P -O 5000"
spawn "xset r rate 300 50" -- make key repeat quicker spawn "xset r rate 300 50" -- make key repeat quicker
spawn "/home/leon/.screenlayout/dualscreen-landscape.sh"
_ <- liftIO $ Control.Concurrent.threadDelay (1000 * 10)
spawn "/home/leon/.config/polybar/launch.sh" spawn "/home/leon/.config/polybar/launch.sh"
spawn "/home/leon/.screenlayout/dualscreen.sh"
spawn "feh --bg-fill /home/leon/Bilder/wallpapers/mountains_with_clounds.jpg" spawn "feh --bg-fill /home/leon/Bilder/wallpapers/mountains_with_clounds.jpg"
setWMName "LG3D" -- Java stuff hack setWMName "LG3D" -- Java stuff hack
@ -164,60 +159,65 @@ myStartupHook = do
-- Default mappings that need to be removed -- Default mappings that need to be removed
removedKeys :: [String] removedKeys :: [String]
removedKeys = ["M-S-c", "M-S-q", "M-h", "M-l"] removedKeys = ["M-S-c", "M-S-q", "M-h", "M-l"] ++ ["M-" ++ show n | n <- [1..9 :: Int]]
multiMonitorOperation :: (WorkspaceId -> WindowSet -> WindowSet) -> ScreenId -> X () multiMonitorOperation :: (WorkspaceId -> WindowSet -> WindowSet) -> ScreenId -> X ()
multiMonitorOperation operation n = do multiMonitorOperation operation n = do
monitor <- screenWorkspace n monitor <- screenWorkspace n
case monitor of case monitor of
Just mon -> windows $ operation mon Just mon -> windows $ operation mon
Nothing -> return () Nothing -> return ()
myKeys :: [(String, X ())] myKeys :: XConfig a -> XConfig a
myKeys = [ ("M-+", sendMessage zoomIn) myKeys c = additionalKeysP c $
, ("M--", sendMessage zoomOut) [ ("M-+", sendMessage zoomIn)
, ("M-#", sendMessage zoomReset) , ("M--", sendMessage zoomOut)
, ("M-#", sendMessage zoomReset)
, ("M-f", toggleFullscreen) , ("M-f", toggleFullscreen)
, ("M-S-C-c", kill1) , ("M-S-C-c", kill1)
, ("M-S-C-q", io exitSuccess) , ("M-S-C-q", io exitSuccess)
-- Binary space partitioning -- Binary space partitioning
, ("M-<Backspace>", sendMessage Swap) , ("M-<Backspace>", sendMessage Swap)
, ("M-M1-<Backspace>", sendMessage Rotate) , ("M-M1-<Backspace>", sendMessage Rotate)
-- Media -- Media
, ("<XF86AudioRaiseVolume>", spawn "amixer sset Master 5%+") , ("<XF86AudioRaiseVolume>", spawn "amixer sset Master 5%+")
, ("<XF86AudioLowerVolume>", spawn "amixer sset Master 5%-") , ("<XF86AudioLowerVolume>", spawn "amixer sset Master 5%-")
-- Multi monitor -- Multi monitor
, ("M-s", multiMonitorOperation W.view 0) , ("M-s", multiMonitorOperation W.view 1)
, ("M-d", multiMonitorOperation W.view 1) , ("M-d", multiMonitorOperation W.view 0)
, ("M-S-s", (multiMonitorOperation W.shift 0) >> multiMonitorOperation W.view 0) , ("M-S-s", (multiMonitorOperation W.shift 1) >> multiMonitorOperation W.view 1)
, ("M-S-d", (multiMonitorOperation W.shift 1) >> multiMonitorOperation W.view 1) , ("M-S-d", (multiMonitorOperation W.shift 0) >> multiMonitorOperation W.view 0)
-- programs -- programs
, ("M-p", spawn myLauncher) , ("M-p", spawn myLauncher)
, ("M-b", spawn myBrowser) , ("M-b", spawn myBrowser)
, ("M-C-p", spawn (myTerminal ++ " --class termite_floating -e fff")) , ("M-C-p", spawn (myTerminal ++ " --class termite_floating -e fff"))
, ("M-S-p", Rofi.showCombi (def { Rofi.theme = Rofi.bigTheme }) [ "drun", "window", "ssh" ]) , ("M-S-p", Rofi.showCombi (def { Rofi.theme = Rofi.bigTheme }) [ "drun", "window", "ssh" ])
, ("M-S-e", Rofi.showNormal (def { Rofi.theme = Rofi.bigTheme }) "emoji" ) , ("M-S-e", Rofi.showNormal (def { Rofi.theme = Rofi.bigTheme }) "emoji" )
--, ("M-s", spawn $ scriptFile "rofi-search.sh") --, ("M-s", spawn $ scriptFile "rofi-search.sh")
, ("M-S-o", spawn $ scriptFile "rofi-open.sh") , ("M-S-o", spawn $ scriptFile "rofi-open.sh")
, ("M-n", scratchpadSubmap ) , ("M-n", scratchpadSubmap )
, ("M-m", mediaSubmap ) , ("M-m", mediaSubmap )
, ("M-e", Rofi.promptRunCommand def specialCommands) , ("M-e", Rofi.promptRunCommand def specialCommands)
, ("M-C-e", Rofi.promptRunCommand def =<< defaultCommands ) , ("M-C-e", Rofi.promptRunCommand def =<< defaultCommands )
, ("M-o", Rofi.promptRunCommand def withSelectionCommands) , ("M-o", Rofi.promptRunCommand def withSelectionCommands)
, ("M-S-C-g", spawn "killall -INT -g giph" >> spawn "notify-send gif 'saved gif in ~/Bilder/gifs'") -- stop gif recording , ("M-S-C-g", spawn "killall -INT -g giph" >> spawn "notify-send gif 'saved gif in ~/Bilder/gifs'") -- stop gif recording
] ++ generatedMappings ] ++ generatedMappings
where where
generatedMappings :: [(String, X ())] generatedMappings :: [(String, X ())]
generatedMappings = copyToWorkspaceMappings ++ windowGoMappings ++ windowSwapMappings ++ resizeMappings generatedMappings = windowGoMappings ++ windowSwapMappings ++ resizeMappings ++ workspaceMappings
where where
copyToWorkspaceMappings = [ ("M-C-" ++ wsp, windows $ copy wsp) | wsp <- map show [1..9 :: Int] ] workspaceMappings =
[ (mappingPrefix ++ show wspNum, windows $ onCurrentScreen action wsp)
| (wsp, wspNum) <- zip (workspaces' c) [1..9 :: Int]
, (mappingPrefix, action) <- [("M-", W.greedyView), ("M-S-", W.shift), ("M-C-", copy)]
]
keyDirPairs = [("h", L), ("j", D), ("k", U), ("l", R)] keyDirPairs = [("h", L), ("j", D), ("k", U), ("l", R)]
@ -230,6 +230,9 @@ myKeys = [ ("M-+", sendMessage zoomIn)
, ("M-C-l", ifLayoutIs "BSP" (sendMessage $ ExpandTowards R) (ifLayoutIs "Horizon" (sendMessage ExpandSlave) (sendMessage Expand))) , ("M-C-l", ifLayoutIs "BSP" (sendMessage $ ExpandTowards R) (ifLayoutIs "Horizon" (sendMessage ExpandSlave) (sendMessage Expand)))
] ]
toggleFullscreen :: X () toggleFullscreen :: X ()
toggleFullscreen = do toggleFullscreen = do
sendMessage ToggleLayout -- toggle fullscreen layout sendMessage ToggleLayout -- toggle fullscreen layout
@ -307,29 +310,35 @@ myManageHook = composeAll
-- Main ------------------------------------ {{{ -- Main ------------------------------------ {{{
main :: IO () main :: IO ()
main = do main = do
dbus <- D.connectSession currentScreenCount :: Int <- countScreens
-- Request access to the DBus name let monitorIndices = [0..currentScreenCount - 1]
_ <- D.requestName dbus (D.busName_ "org.xmonad.Log")
[D.nameAllowReplacement, D.nameReplaceExisting, D.nameDoNotQueue] -- create a fifo named pipe for every monitor (called /tmp/xmonad-state-bar0, etc)
for_ monitorIndices (\idx -> safeSpawn "mkfifo" ["/tmp/xmonad-state-bar" ++ show idx])
-- create polybarLogHooks for every monitor and combine them using the <+> monoid instance
let polybarLogHooks = foldMap (polybarLogHook . fromIntegral) monitorIndices
let myConfig = myKeys (desktopConfig
{ terminal = myTerminal
, workspaces = withScreens (fromIntegral currentScreenCount) (map show [1..9 :: Int])
, modMask = myModMask
, borderWidth = 2
, layoutHook = myLayout
, logHook = polybarLogHook 0 <+> polybarLogHook 1 <+> logHook def
, startupHook = myStartupHook <+> startupHook def -- <+> return () >> checkKeymap myConfig (myKeys myConfig)
, manageHook = myManageHook <+> manageHook def
, focusedBorderColor = aqua
, normalBorderColor = "#282828"
--, handleEventHook = minimizeEventHook <+> handleEventHook def <+> hintsEventHook -- <+> Ewmh.fullscreenEventHook
} `removeKeysP` removedKeys)
-- $ ewmh (kills IntelliJ)
xmonad xmonad
$ Ewmh.ewmh $ Ewmh.ewmh
$ Nav2d.withNavigation2DConfig def { Nav2d.defaultTiledNavigation = Nav2d.sideNavigation } $ Nav2d.withNavigation2DConfig def { Nav2d.defaultTiledNavigation = Nav2d.sideNavigation }
$ myConfig dbus $ myConfig
myConfig dbus = desktopConfig
{ terminal = myTerminal
, modMask = myModMask
, borderWidth = 2
, layoutHook = myLayout
, logHook = myLogHook <+> dynamicLogWithPP (polybarPP dbus) <+> logHook def
, startupHook = myStartupHook <+> startupHook def <+> return () >> checkKeymap (myConfig dbus ) myKeys
, manageHook = myManageHook <+> manageHook def
, focusedBorderColor = aqua
, normalBorderColor = "#282828"
--, handleEventHook = minimizeEventHook <+> handleEventHook def <+> hintsEventHook -- <+> Ewmh.fullscreenEventHook
} `removeKeysP` removedKeys `additionalKeysP` myKeys
@ -337,11 +346,19 @@ myConfig dbus = desktopConfig
-- POLYBAR Kram -------------------------------------- {{{ -- POLYBAR Kram -------------------------------------- {{{
-- | Loghook for polybar on a given monitor.
-- Will write the polybar formatted string to /tmp/xmonad-state-bar${monitor}
polybarLogHook :: Int -> X ()
polybarLogHook monitor = do
barOut <- dynamicLogString $ polybarPP monitor
io $ SysIO.appendFile ("/tmp/xmonad-state-bar" ++ show monitor) (barOut ++ "\n")
polybarPP :: D.Client -> PP
polybarPP dbus = namedScratchpadFilterOutWorkspacePP $ def -- swapping namedScratchpadFilterOutWorkspacePP and marshallPP will throw "Prelude.read no Parse" errors..... wtf
{ ppOutput = dbusOutput dbus -- | create a polybar Pretty printer, marshalled for given monitor.
, ppCurrent = withBG bg2 polybarPP :: Int -> PP
polybarPP monitor = namedScratchpadFilterOutWorkspacePP $ marshallPP (fromIntegral monitor) $ def
{ ppCurrent = withBG bg2
, ppVisible = withBG bg2 , ppVisible = withBG bg2
, ppUrgent = withFG red , ppUrgent = withFG red
, ppLayout = removeWord "Minimize" . removeWord "Hinted" . removeWord "Spacing" . withFG purple , ppLayout = removeWord "Minimize" . removeWord "Hinted" . removeWord "Spacing" . withFG purple
@ -349,7 +366,7 @@ polybarPP dbus = namedScratchpadFilterOutWorkspacePP $ def
, ppWsSep = "" , ppWsSep = ""
, ppSep = " | " , ppSep = " | "
, ppExtras = [] , ppExtras = []
, ppTitle = const "" -- withFG aqua . (shorten 40) , ppTitle = withFG aqua . (shorten 40)
} }
where where
removeWord substr = unwords . filter (/= substr) . words removeWord substr = unwords . filter (/= substr) . words
@ -360,21 +377,16 @@ polybarPP dbus = namedScratchpadFilterOutWorkspacePP $ def
| otherwise = wsp | otherwise = wsp
wrapOnClickCmd command = wrap ("%{A1:" ++ command ++ ":}") "%{A}" wrapOnClickCmd command = wrap ("%{A1:" ++ command ++ ":}") "%{A}"
-- Emit a DBus signal on log updates
dbusOutput :: D.Client -> String -> IO ()
dbusOutput dbus str = do
let signal = (D.signal objectPath interfaceName memberName) {
D.signalBody = [D.toVariant $ UTF8.decodeString str]
}
D.emit dbus signal
where
objectPath = D.objectPath_ "/org/xmonad/Log"
interfaceName = D.interfaceName_ "org.xmonad.Log"
memberName = D.memberName_ "Update"
-- }}} -- }}}
-- Utilities --------------------------------------------------- {{{ -- Utilities --------------------------------------------------- {{{
catchAndNotifyAny :: IO () -> IO ()
catchAndNotifyAny ioAction = catch ioAction (\(e :: SomeException) -> safeSpawn "notify-send" ["Xmonad exception", show e])
promptDzenWhileRunning :: String -> [String] -> X () -> X () promptDzenWhileRunning :: String -> [String] -> X () -> X ()
promptDzenWhileRunning promptTitle options action = do promptDzenWhileRunning promptTitle options action = do
handle <- spawnPipe $ "sleep 1 && dzen2 -e onstart=uncollapse -l " ++ lineCount ++ " -fn '" ++ font ++ "'" handle <- spawnPipe $ "sleep 1 && dzen2 -e onstart=uncollapse -l " ++ lineCount ++ " -fn '" ++ font ++ "'"

2
files/scripts/gpuinfo.sh Executable file
View file

@ -0,0 +1,2 @@
#!/bin/dash
sudo cat /sys/kernel/debug/dri/0/amdgpu_pm_info