From 3b03a5c32496a17d1fa947cf7418d1c329e8cb98 Mon Sep 17 00:00:00 2001 From: Leon Kowarschick Date: Sat, 9 May 2020 15:24:23 +0200 Subject: [PATCH] Add multimonitor support in a good way --- files/.Xresources | 3 + .../configstore/update-notifier-npm.json | 2 +- files/.config/picom.conf | 2 +- files/.config/polybar/config.ini | 4 +- .../polybar/polybar-scripts/xmonad-status.sh | 17 ++ files/.xmonad/.stack-work/stack.sqlite3 | Bin 561152 -> 561152 bytes files/.xmonad/lib/Config.hs | 190 ++++++++++-------- files/scripts/gpuinfo.sh | 2 + 8 files changed, 128 insertions(+), 92 deletions(-) create mode 100755 files/.config/polybar/polybar-scripts/xmonad-status.sh create mode 100755 files/scripts/gpuinfo.sh diff --git a/files/.Xresources b/files/.Xresources index bae1e55..b814af6 100644 --- a/files/.Xresources +++ b/files/.Xresources @@ -1,5 +1,8 @@ *.background: #282828 +Xcursor.size: 16 +Xcursor.theme: capitaine-cursors-light + rofi.lines: 5 rofi.eh: 2 rofi.padding: 200 diff --git a/files/.config/configstore/update-notifier-npm.json b/files/.config/configstore/update-notifier-npm.json index 1441d06..8126ef7 100644 --- a/files/.config/configstore/update-notifier-npm.json +++ b/files/.config/configstore/update-notifier-npm.json @@ -1,4 +1,4 @@ { "optOut": false, - "lastUpdateCheck": 1588770448547 + "lastUpdateCheck": 1588866305414 } \ No newline at end of file diff --git a/files/.config/picom.conf b/files/.config/picom.conf index 335c284..59952a3 100644 --- a/files/.config/picom.conf +++ b/files/.config/picom.conf @@ -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 = false; -blur-method = "dual_kawase"; +#blur-method = "dual_kawase"; #blur-method = "kernel"; blur-strength = 10; # max 20 blur-size = 20; diff --git a/files/.config/polybar/config.ini b/files/.config/polybar/config.ini index 21c2aea..09828f8 100644 --- a/files/.config/polybar/config.ini +++ b/files/.config/polybar/config.ini @@ -170,8 +170,10 @@ label = "%{F#444} %{F-}%{B#444} %time% | %date% %{B-}%{F#444} %{ [module/xmonad] type = custom/script -exec = xmonad-log +;exec = "xmonad-log" +exec = '/home/leon/.config/polybar/polybar-scripts/xmonad-status.sh' tail = true +;interval = 1 [module/timerDisplay] diff --git a/files/.config/polybar/polybar-scripts/xmonad-status.sh b/files/.config/polybar/polybar-scripts/xmonad-status.sh new file mode 100755 index 0000000..6c88b07 --- /dev/null +++ b/files/.config/polybar/polybar-scripts/xmonad-status.sh @@ -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 qHr6#@5D!)&$1Z1g6#m=B)`VRRK(lOD8KT7`F2UvH&qF5VHX> L`*z+yj?Z=gQ1B8; delta 60 zcmZozpwzHHX@WFk^+XwG#_Gm|)&$1Z1g6#m=B)`VRRNO?6y%v0+uDBzumCYD5VHX> L`}W@f9IW;Lg!2{1 diff --git a/files/.xmonad/lib/Config.hs b/files/.xmonad/lib/Config.hs index 289c8c9..0bff93c 100644 --- a/files/.xmonad/lib/Config.hs +++ b/files/.xmonad/lib/Config.hs @@ -4,21 +4,23 @@ module Config (main) where +import Control.Concurrent +import Control.Exception ( catch + , SomeException + ) import Data.Char (isDigit) -import Data.List (isSuffixOf, isPrefixOf) +import Data.List ( isSuffixOf , isPrefixOf) import System.Exit (exitSuccess) 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.Monoid +import Data.Foldable ( for_ ) import qualified System.IO as SysIO import XMonad.Layout.HintedGrid -import XMonad.Layout.TwoPanePersistent import XMonad hiding ((|||)) import XMonad.Actions.Commands @@ -26,7 +28,6 @@ import XMonad.Actions.CopyWindow import XMonad.Actions.Submap import XMonad.Config.Desktop import XMonad.Hooks.DynamicLog -import XMonad.Hooks.FadeInactive import XMonad.Hooks.ManageDocks import XMonad.Hooks.SetWMName (setWMName) import XMonad.Layout.BinarySpacePartition @@ -39,10 +40,9 @@ import XMonad.Layout.NoBorders import XMonad.Layout.Renamed (renamed, Rename(Replace)) import XMonad.Layout.ResizableTile import XMonad.Layout.Spacing (spacingRaw, Border(..), toggleWindowSpacingEnabled) -import XMonad.Layout.Spiral (spiral) import XMonad.Layout.ToggleLayouts import XMonad.Layout.ZoomRow -import XMonad.Util.EZConfig (additionalKeysP, removeKeysP, checkKeymap) +import XMonad.Util.EZConfig (additionalKeysP, removeKeysP) import XMonad.Util.NamedScratchpad import XMonad.Util.Run 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.ManageHelpers as ManageHelpers import qualified XMonad.Layout.BoringWindows as BoringWindows +import XMonad.Layout.IndependentScreens import qualified XMonad.StackSet as W import qualified XMonad.Util.XSelection as XSel @@ -133,13 +134,6 @@ myLayout = avoidStruts . BoringWindows.boringWindows . smartBorders . toggleLayo in spacingRaw True spacingBorder True gapBorder True --- }}} - --- Loghook -------------------------------------- {{{ - -myLogHook :: X () -myLogHook = return () -- fadeInactiveLogHook 0.95 -- opacity of unfocused windows - -- }}} -- Startuphook ----------------------------- {{{ @@ -153,8 +147,9 @@ myStartupHook = do spawnOnce "mailspring --background" spawnOnce "redshift -P -O 5000" 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/.screenlayout/dualscreen.sh" spawn "feh --bg-fill /home/leon/Bilder/wallpapers/mountains_with_clounds.jpg" setWMName "LG3D" -- Java stuff hack @@ -164,60 +159,65 @@ myStartupHook = do -- Default mappings that need to be removed 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 operation n = do monitor <- screenWorkspace n - case monitor of + case monitor of Just mon -> windows $ operation mon Nothing -> return () -myKeys :: [(String, X ())] -myKeys = [ ("M-+", sendMessage zoomIn) - , ("M--", sendMessage zoomOut) - , ("M-#", sendMessage zoomReset) +myKeys :: XConfig a -> XConfig a +myKeys c = additionalKeysP c $ + [ ("M-+", sendMessage zoomIn) + , ("M--", sendMessage zoomOut) + , ("M-#", sendMessage zoomReset) - , ("M-f", toggleFullscreen) + , ("M-f", toggleFullscreen) - , ("M-S-C-c", kill1) - , ("M-S-C-q", io exitSuccess) + , ("M-S-C-c", kill1) + , ("M-S-C-q", io exitSuccess) - -- Binary space partitioning - , ("M-", sendMessage Swap) - , ("M-M1-", sendMessage Rotate) + -- Binary space partitioning + , ("M-", sendMessage Swap) + , ("M-M1-", sendMessage Rotate) - -- Media - , ("", spawn "amixer sset Master 5%+") - , ("", spawn "amixer sset Master 5%-") + -- Media + , ("", spawn "amixer sset Master 5%+") + , ("", spawn "amixer sset Master 5%-") - -- Multi monitor - , ("M-s", multiMonitorOperation W.view 0) - , ("M-d", multiMonitorOperation W.view 1) - , ("M-S-s", (multiMonitorOperation W.shift 0) >> multiMonitorOperation W.view 0) - , ("M-S-d", (multiMonitorOperation W.shift 1) >> multiMonitorOperation W.view 1) + -- Multi monitor + , ("M-s", multiMonitorOperation W.view 1) + , ("M-d", multiMonitorOperation W.view 0) + , ("M-S-s", (multiMonitorOperation W.shift 1) >> multiMonitorOperation W.view 1) + , ("M-S-d", (multiMonitorOperation W.shift 0) >> multiMonitorOperation W.view 0) - -- programs - , ("M-p", spawn myLauncher) - , ("M-b", spawn myBrowser) - , ("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-e", Rofi.showNormal (def { Rofi.theme = Rofi.bigTheme }) "emoji" ) - --, ("M-s", spawn $ scriptFile "rofi-search.sh") - , ("M-S-o", spawn $ scriptFile "rofi-open.sh") - , ("M-n", scratchpadSubmap ) - , ("M-m", mediaSubmap ) - , ("M-e", Rofi.promptRunCommand def specialCommands) - , ("M-C-e", Rofi.promptRunCommand def =<< defaultCommands ) - , ("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 - ] ++ generatedMappings + -- programs + , ("M-p", spawn myLauncher) + , ("M-b", spawn myBrowser) + , ("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-e", Rofi.showNormal (def { Rofi.theme = Rofi.bigTheme }) "emoji" ) + --, ("M-s", spawn $ scriptFile "rofi-search.sh") + , ("M-S-o", spawn $ scriptFile "rofi-open.sh") + , ("M-n", scratchpadSubmap ) + , ("M-m", mediaSubmap ) + , ("M-e", Rofi.promptRunCommand def specialCommands) + , ("M-C-e", Rofi.promptRunCommand def =<< defaultCommands ) + , ("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 + ] ++ generatedMappings where generatedMappings :: [(String, X ())] - generatedMappings = copyToWorkspaceMappings ++ windowGoMappings ++ windowSwapMappings ++ resizeMappings + generatedMappings = windowGoMappings ++ windowSwapMappings ++ resizeMappings ++ workspaceMappings 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)] @@ -230,6 +230,9 @@ myKeys = [ ("M-+", sendMessage zoomIn) , ("M-C-l", ifLayoutIs "BSP" (sendMessage $ ExpandTowards R) (ifLayoutIs "Horizon" (sendMessage ExpandSlave) (sendMessage Expand))) ] + + + toggleFullscreen :: X () toggleFullscreen = do sendMessage ToggleLayout -- toggle fullscreen layout @@ -307,29 +310,35 @@ myManageHook = composeAll -- Main ------------------------------------ {{{ main :: IO () main = do - dbus <- D.connectSession - -- Request access to the DBus name - _ <- D.requestName dbus (D.busName_ "org.xmonad.Log") - [D.nameAllowReplacement, D.nameReplaceExisting, D.nameDoNotQueue] + currentScreenCount :: Int <- countScreens + let monitorIndices = [0..currentScreenCount - 1] + + -- 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 $ Ewmh.ewmh $ Nav2d.withNavigation2DConfig def { Nav2d.defaultTiledNavigation = Nav2d.sideNavigation } - $ myConfig dbus - -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 + $ myConfig @@ -337,11 +346,19 @@ myConfig dbus = desktopConfig -- 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 - { ppOutput = dbusOutput dbus - , ppCurrent = withBG bg2 + +-- swapping namedScratchpadFilterOutWorkspacePP and marshallPP will throw "Prelude.read no Parse" errors..... wtf +-- | create a polybar Pretty printer, marshalled for given monitor. +polybarPP :: Int -> PP +polybarPP monitor = namedScratchpadFilterOutWorkspacePP $ marshallPP (fromIntegral monitor) $ def + { ppCurrent = withBG bg2 , ppVisible = withBG bg2 , ppUrgent = withFG red , ppLayout = removeWord "Minimize" . removeWord "Hinted" . removeWord "Spacing" . withFG purple @@ -349,7 +366,7 @@ polybarPP dbus = namedScratchpadFilterOutWorkspacePP $ def , ppWsSep = "" , ppSep = " | " , ppExtras = [] - , ppTitle = const "" -- withFG aqua . (shorten 40) + , ppTitle = withFG aqua . (shorten 40) } where removeWord substr = unwords . filter (/= substr) . words @@ -360,21 +377,16 @@ polybarPP dbus = namedScratchpadFilterOutWorkspacePP $ def | otherwise = wsp 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 --------------------------------------------------- {{{ + + + +catchAndNotifyAny :: IO () -> IO () +catchAndNotifyAny ioAction = catch ioAction (\(e :: SomeException) -> safeSpawn "notify-send" ["Xmonad exception", show e]) + + promptDzenWhileRunning :: String -> [String] -> X () -> X () promptDzenWhileRunning promptTitle options action = do handle <- spawnPipe $ "sleep 1 && dzen2 -e onstart=uncollapse -l " ++ lineCount ++ " -fn '" ++ font ++ "'" diff --git a/files/scripts/gpuinfo.sh b/files/scripts/gpuinfo.sh new file mode 100755 index 0000000..8ccfffa --- /dev/null +++ b/files/scripts/gpuinfo.sh @@ -0,0 +1,2 @@ +#!/bin/dash +sudo cat /sys/kernel/debug/dri/0/amdgpu_pm_info