From 472c575946c7366f6dc5e2dcaaa2e59ca813c2e0 Mon Sep 17 00:00:00 2001 From: Julien Moutinho Date: Sat, 4 May 2024 09:00:34 +0200 Subject: [PATCH] xmonad: fix multiscreen support --- home-manager/profiles/xmonad.nix | 11 +- .../profiles/xmonad/{xmobar.hs => xmobar0.hs} | 4 +- home-manager/profiles/xmonad/xmonad.hs | 591 +++++++++--------- 3 files changed, 315 insertions(+), 291 deletions(-) rename home-manager/profiles/xmonad/{xmobar.hs => xmobar0.hs} (93%) diff --git a/home-manager/profiles/xmonad.nix b/home-manager/profiles/xmonad.nix index 6f1c594..a29653a 100644 --- a/home-manager/profiles/xmonad.nix +++ b/home-manager/profiles/xmonad.nix @@ -5,7 +5,7 @@ ./screen-locker.nix ./urxvt.nix ]; - home.file.".xmonad/xmobar.hs".source = xmonad/xmobar.hs; + xdg.configFile."xmonad/xmobar0.hs".source = xmonad/xmobar0.hs; xsession = { enable = true; scriptPath = ".hm-xsession"; @@ -21,11 +21,16 @@ haskellPackages.data-default ]; enableContribAndExtras = true; + # Develop with: + # nix shell --impure --expr 'with import {}; haskellPackages.ghcWithPackages (hs: with hs; [ xmonad-contrib data-default ])' + # ln -fns $PWD/home-manager/profiles/xmonad/xmonad.hs ~/.xmonad/xmonad.hs + # ~/.xmonad/xmonad-x86_64-linux --recompile config = xmonad/xmonad.hs; }; }; home.packages = [ pkgs.acpilight + pkgs.autorandr pkgs.ffmpegthumbnailer pkgs.gmrun pkgs.light @@ -35,7 +40,8 @@ #(pkgs.writeShellScriptBin "mate-terminal" ''exec ${pkgs.rxvt-unicode}/bin/urxvtc -hold "$@"'') pkgs.rofi pkgs.scrot - pkgs.stalonetray + pkgs.trayer + #pkgs.stalonetray pkgs.wmname pkgs.xmobar pkgs.xorg.appres @@ -43,6 +49,7 @@ pkgs.xorg.xhost pkgs.xorg.xmodmap pkgs.xorg.xset + #pkgs.xdotool ]; xresources.properties = { "Xft.antialias" = true; diff --git a/home-manager/profiles/xmonad/xmobar.hs b/home-manager/profiles/xmonad/xmobar0.hs similarity index 93% rename from home-manager/profiles/xmonad/xmobar.hs rename to home-manager/profiles/xmonad/xmobar0.hs index f068da7..335d0e1 100644 --- a/home-manager/profiles/xmonad/xmobar.hs +++ b/home-manager/profiles/xmonad/xmobar0.hs @@ -10,7 +10,7 @@ Config { -- , borderColor = "#646464" , sepChar = "%" -- delineator between plugin names and straight text , alignSep = "}{" -- separator between left-right alignment - , template = "%StdinReader% }{ %multicpu% %thermal0% %memory% %dynnetwork% %battery% %kbd% %parisTime% " + , template = "%_XMONAD_XMOBAR0% }{ %multicpu% %thermal0% %memory% %dynnetwork% %battery% %kbd% %parisTime% " , lowerOnStart = True -- send to bottom of window stack on start , hideOnStart = False -- start with window unmapped (hidden) , allDesktops = True -- show on all desktops @@ -18,7 +18,7 @@ Config { , pickBroadest = False -- choose widest display (multi-monitor) , persistent = True -- enable/disable hiding (True = disabled) , commands = - [ Run StdinReader + [ Run XPropertyLog "_XMONAD_XMOBAR0" , Run MultiCpu [ "--template", "CPU:%" , "--Low", "50" -- units: % diff --git a/home-manager/profiles/xmonad/xmonad.hs b/home-manager/profiles/xmonad/xmonad.hs index 8075a02..0e7925d 100644 --- a/home-manager/profiles/xmonad/xmonad.hs +++ b/home-manager/profiles/xmonad/xmonad.hs @@ -27,7 +27,9 @@ import XMonad.Hooks.DynamicLog import XMonad.Hooks.EwmhDesktops import XMonad.Hooks.ManageDocks import XMonad.Hooks.ManageHelpers +import XMonad.Hooks.Rescreen import XMonad.Hooks.SetWMName +import XMonad.Hooks.StatusBar import XMonad.Hooks.UrgencyHook import XMonad.Layout.Fullscreen import XMonad.Layout.Grid @@ -41,288 +43,251 @@ import XMonad.Layout.ResizableTile import XMonad.Layout.Spiral import XMonad.Layout.Tabbed import XMonad.Layout.ThreeColumns -import XMonad.Util.Run(spawnPipe) +import XMonad.Util.Ungrab (unGrab) +--import XMonad.Operations (unGrab) -- TODO: needs xmonad 0.18 import XMonad.Util.SpawnOnce import qualified XMonad.StackSet as W -myKeys - conf@XConfig{XMonad.modMask} = - Map.fromList $ - let xK_XF86Backward = 0x1008ff26 - xK_XF86Forward = 0x1008ff27 in - [ - -- Start a terminal - ((modMask, xK_Return), spawn $ XMonad.terminal conf) - -- Launch a program - , ((modMask, xK_Menu), spawn "exec rofi -show run -no-disable-history -run-command \"bash -c 'systemd-run --user --unit=app-org.rofi.\\$(systemd-escape \\\"{cmd}\\\")@\\$RANDOM -p CollectMode=inactive-or-failed {cmd}'\"") - -- Browse the filesystem - , ((modMask, xK_BackSpace), spawn "systemd-run --user --unit=app-org.rofi.caja@$RANDOM -p CollectMode=inactive-or-failed caja") - - -- Lock the screen - , ((0, xK_Pause), spawn "systemctl --user start xss-lock.service; xset s activate dpms force off") - - -- Take a full screenshot - , ((0, xK_Print), spawn "cd ~/img/cap && scrot --quality 42 '%Y-%m-%d_%H-%M-%S.png' && caja ~/img/cap") - -- Take a selective screenshot - , ((modMask, xK_Print), spawn "select-screenshot") - - -- Volume control - , ((0, 0x1008FF12), spawn "pactl -- set-sink-mute @DEFAULT_SINK@ toggle") -- XF88AudioMute - , ((0, 0x1008FF11), spawn "pactl -- set-sink-volume @DEFAULT_SINK@ -5%") -- XF86AudioLowerVolume - , ((0, 0x1008FF13), spawn "pactl -- set-sink-volume @DEFAULT_SINK@ +5%") -- XF86AudioRaiseVolume - -- Audio previous - -- , ((0, 0x1008FF16), spawn "") - -- Play/pause - -- , ((0, 0x1008FF14), spawn "") - -- Audio next - -- , ((0, 0x1008FF17), spawn "") - -- Eject CD tray - -- , ((0, 0x1008FF2C), spawn "eject -T") - - -- Close focused window. - , ((modMask, xK_Escape), kill) - , ((modMask, xK_q), kill) - - -- Clipboard - , ((modMask, xK_c), spawn "clipster --select --primary") - - -- Temporarily maximize a window - , ((modMask, xK_f), sendMessage $ XMonad.Layout.MultiToggle.Toggle FULL) - -- , ((modMask, xK_f), withFocused (sendMessage . maximizeRestore)) - - -- Cycle through the available layout algorithms - , ((modMask, 0x13bd), sendMessage NextLayout) -- oe (²) - , ((modMask, xK_ampersand), sendMessage $ JumpToLayout "ResizableTall") -- & (1) - , ((modMask, xK_eacute), sendMessage $ JumpToLayout "Mirror ResizableTall") -- é (2) - , ((modMask, xK_quotedbl), sendMessage $ JumpToLayout "Tabbed Simplest") -- ' (3) - , ((modMask, xK_apostrophe), sendMessage $ JumpToLayout "Magnifier Grid") -- " (4) - , ((modMask, xK_parenleft), sendMessage $ JumpToLayout "Spiral") -- ( (5) - , ((modMask, xK_minus), sendMessage $ JumpToLayout "Full") -- - (6) - , ((modMask, xK_egrave), sendMessage $ JumpToLayout "ThreeCol") -- è (7) - - -- Reset the layouts on the current workspace to default - -- , ((modMask .|. shiftMask, xK_space), setLayout $ XMonad.layoutHook conf) - - -- Resize viewed windows to the correct size. - , ((modMask, xK_n), refresh) - - -- Move focus between windows - , ((modMask, xK_Tab), windows W.focusDown) - , ((modMask .|. shiftMask, xK_Tab), windows W.focusUp) - , ((modMask, xK_i), windows W.focusUp) - , ((modMask, xK_k), windows W.focusDown) - - -- Move focus to the master window - , ((modMask, xK_m), windows W.focusMaster) - -- Swap the focused window and the master window - , ((modMask, xK_space), windows W.swapMaster) - - -- Swap the focused window with the next window. - --, ((modMask, xK_o), windows W.swapDown >> windows W.focusMaster) - -- Swap the focused window with the previous window. - , ((modMask, xK_m), windows W.swapUp >> windows W.focusMaster) - - -- Push window back into tiling. - , ((modMask, xK_t), withFocused $ windows . W.sink) - - -- Change the number of windows in the master area - , ((modMask, xK_Up), sendMessage $ IncMasterN 1) - , ((modMask, xK_Down), sendMessage $ IncMasterN (-1)) - - -- Toggle the status bar gap. - , ((modMask, xK_b), sendMessage ToggleStruts) - - -- Quit xmonad - , ((modMask .|. shiftMask, xK_End), io exitSuccess) - -- Restart xmonad - , ((modMask, xK_End), restart "xmonad" True) - - -- Workspace management - -- XF86Back: Switch to previous workspace - , ((0, xK_XF86Backward), prevWS) - , ((modMask, xK_j), prevWS) - -- Switch to next workspace - , ((0, xK_XF86Forward), nextWS) - , ((modMask, xK_l), nextWS) - -- XF86Back: Move the current client to the previous workspace and go there - , ((modMask, xK_XF86Backward), shiftToPrev >> prevWS) - , ((modMask .|. shiftMask, xK_j), shiftToPrev >> prevWS) - -- Move the current client to the next workspace and go there - , ((modMask, xK_XF86Forward), shiftToNext >> nextWS) - , ((modMask .|. shiftMask, xK_l), shiftToNext >> nextWS) - -- Switch to previous workspace - -- Switch to next workspace - {- - -- Move the current client to the previous workspace - , ((0 .|. shiftMask , xK_XF86Backward), shiftToPrev ) - -- Move the current client to the next workspace - , ((0 .|. shiftMask , xK_XF86Forward), shiftToNext ) - -} - - -- Toggle copying window on all workspaces (sticky window) - , ((modMask, xK_s), do - copies <- wsContainingCopies -- NOTE: consider only hidden workspaces - case copies of - [] -> windows copyToAll - _ -> killAllOtherCopies - ) - - -- Resize the master area - , ((modMask, xK_Left), sendMessage Shrink) - , ((modMask, xK_Right), sendMessage Expand) - -- Resize windows in ResizableTall mode - , ((modMask .|. shiftMask, xK_Left), sendMessage MirrorShrink) - , ((modMask .|. shiftMask, xK_Right), sendMessage MirrorExpand) - ] ++ - - -- mod-[F1..F9], Switch to workspace N - -- mod-shift-[F1..F9], Move client to workspace N - [ ((m .|. modMask, k), windows $ f i) - | (i, k) <- zip (workspaces conf) [xK_F1 ..] ++ - zip (workspaces conf) [xK_1 ..] - , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)] - ] ++ - {- NOTE: with Xinerama - [((m .|. modMask, k), windows $ onCurrentScreen f i) - | (i, k) <- zip (workspaces' conf) [xK_F1 ..] - , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)] ] - -} - - -- mod-{w,e,r}, Switch to physical/Xinerama screens 1, 2, or 3 - -- mod-shift-{w,e,r}, Move client to screen 1, 2, or 3 - [ ((m .|. modMask, key), screenWorkspace sc >>= flip whenJust (windows . f)) - | (key, sc) <- zip [xK_w, xK_e, xK_r] [0 ..] - , (f, m) <- [(W.view, 0), (W.shift, shiftMask)] - ] ++ - - -- mod-shift-[F1..F9], Swap workspace with workspace N - -- mod-shift-[1..9], Swap workspace with workspace N - [ ((modMask .|. controlMask, k), windows $ swapWithCurrent i) - | (i, k) <- zip (workspaces conf) [xK_F1 ..] ++ - zip (workspaces conf) [xK_1 ..] - ] - {- NOTE: with Xinerama - [((modMask .|. controlMask, k), windows $ onCurrentScreen swapWithCurrent i) - | (i, k) <- zip (workspaces' conf) [xK_F1 ..] ] - -} - - -myMouseBindings - XConfig{XMonad.modMask} = - Map.fromList - [ - -- mod-button1, Set the window to floating mode and move by dragging - ((modMask, button1), \w -> focus w >> mouseMoveWindow w) - - -- mod-button2, Raise the window to the top of the stack - , ((modMask, button2), \w -> focus w >> windows W.swapMaster) - - -- mod-button3, Set the window to floating mode and resize by dragging - , ((modMask, button3), \w -> focus w >> mouseResizeWindow w) - - , ((modMask, button4), \_ -> windows W.focusUp) - , ((modMask, button5), \_ -> windows W.focusDown) - - -- Cycle through workspaces - , ((controlMask .|. modMask, button5), nextNonEmptyWS) - , ((controlMask .|. modMask, button4), prevNonEmptyWS) - ] - where - nextNonEmptyWS _ = moveTo Next (WSIs ((not .) <$> isWindowSpaceVisible)) - prevNonEmptyWS _ = moveTo Prev (WSIs ((not .) <$> isWindowSpaceVisible)) - -isWindowSpaceVisible :: X (WindowSpace -> Bool) -isWindowSpaceVisible = do - vs <- gets (map (W.tag . W.workspace) . W.visible . windowset) - return (\w -> W.tag w `elem` vs) - -defaults xmproc _nScreens = docks $ ewmhFullscreen $ ewmh $ - azertyConfig - { borderWidth = 1 - , focusFollowsMouse = True +main = xmonad $ + withUrgencyHook NoUrgencyHook $ + -- dzenUrgencyHook { args = ["-bg", "darkgreen", "-xs", "1"] } $ + --addAfterRescreenHook myAfterRescreenHook $ + addRandrChangeHook (spawnExec "autorandr --change") $ + dynamicSBs barSpawner $ + docks $ + setEwmhActivateHook doAskUrgent $ + ewmhFullscreen $ + ewmh $ + azertyConfig + { borderWidth = 1 + , focusFollowsMouse = True , focusedBorderColor = "#00b10b" - , handleEventHook = handleEventHook def - , keys = myKeys - , layoutHook = smartBorders $ - mkToggle (NOBORDERS ?? FULL ?? EOT) $ -- enable temporarily maximizing a window - avoidStruts $ -- prevents windows from overlapping dock windows - let tall = ResizableTall 1 (1%200) (8%13) [] in - tabbed shrinkText tabConfig - ||| tall - ||| Mirror tall - ||| magnifiercz (13%10) Grid - ||| spiral (6%7) - ||| noBorders (fullscreenFull Full) - ||| ThreeColMid 1 (1%200) (1%2) - -- ||| Tall 1 (3/100) (1/2) - , manageHook = composeAll - -- [ , isFullscreen --> (doF W.focusDown <+> doFullFloat) - [ isFullscreen --> doFullFloat - , manageHook def - , manageDocks -- NOTE: do not tile dock windows - , resource =? "desktop_window" --> doIgnore - , className =? "Gimp" --> doFloat - , resource =? "gpicview" --> doSink - , className =? "mpv" --> doFloat - --, className =? "MPlayer" --> doShift "3:media" -- <+> doFloat - --, className =? "vlc" --> doShift "3:media" - , className =? "stalonetray" --> doIgnore - ] - , modMask = mod4Mask - , mouseBindings = myMouseBindings - , normalBorderColor = "#7C7C7C" - , startupHook = setWMName "XMonad" - <+> spawn "wmname XMonad" - <+> spawn "xrdb -all .Xresources" - <+> spawn "sleep 1 && xmodmap .Xmodmap" - <+> spawn "xset r rate 250 25" - <+> spawn "xset b off" - <+> spawn "xhost local:root" - <+> spawn "setxkbmap -option keypad:pointerkeys" - -- Useful for programs launched by rofi - <+> spawnOnce "exec systemctl --user import-environment GNUPGHOME PASSWORD_STORE_DIR PATH" - -- <+> spawnOnce "exec arbtt-capture -r 60" - -- <+> spawnOnce "exec parcellite" - -- <+> spawnOnce "exec xautolock" - -- <+> spawnOnce "exec redshift-gtk -l -45.7800:1.9700 -t 6500:3700" - <+> spawnOnce "exec nm-applet" - <+> spawnOnce (List.unwords - [ "exec stalonetray" - , "--background '#000000'" - , "--geometry 5x1-0+0" - , "--icon-gravity E" - , "--icon-size 16" - , "--kludges force_icons_size" - , "--max-geometry 0x1+0+0" - , "--skip-taskbar" - , "--window-strut none" - ]) - , terminal = "urxvtc" - , workspaces = {- withScreens nScreens $ -} - {-["1:work","2:web","3:media"] ++-} - map show [1::Int .. 9] - , logHook = - dynamicLogWithPP xmobarPP - { ppCurrent = xmobarColor "black" "#CCCCCC" - , ppHidden = xmobarColor "#CCCCCC" "black" - , ppHiddenNoWindows = xmobarColor "#606060" "black" - , ppLayout = \s -> xmobarColor "black" "#606060" $ - case s of - "ResizableTall" -> " | " - "Mirror ResizableTall" -> " - " - "Tabbed Simplest" -> " + " - "Magnifier Grid" -> " ~ " - "Spiral" -> " @ " - "Full" -> " O " - "ThreeCol" -> " # " - _ -> s - , ppOutput = hPutStrLn xmproc - , ppSep = " " - , ppTitle = xmobarColor "white" "black" . shorten 50 - , ppUrgent = xmobarColor "yellow" "black" - , ppWsSep = " " - } - >> updatePointer (0.5, 0.5) (0, 0) + , handleEventHook = handleEventHook def + , keys = \conf@XConfig{XMonad.modMask} -> + Map.fromList $ + let xK_XF86Backward = 0x1008ff26 + xK_XF86Forward = 0x1008ff27 in + [ + -- Start a terminal + ((modMask, xK_Return), spawnExec $ XMonad.terminal conf) + -- Launch a program + , ((modMask, xK_Menu), spawnExec "rofi -show run -no-disable-history -run-command \"bash -c 'systemd-run --user --unit=app-org.rofi.\\$(systemd-escape \\\"{cmd}\\\")@\\$RANDOM -p CollectMode=inactive-or-failed {cmd}'\"") + -- Browse the filesystem + , ((modMask, xK_BackSpace), spawnExec "systemd-run --user --unit=app-org.rofi.caja@$RANDOM -p CollectMode=inactive-or-failed caja") + + -- Lock the screen + , ((0, xK_Pause), unGrab >> spawnExec "loginctl lock-session \"$XDG_SESSION_ID\"") + + -- Take a full screenshot + , ((0, xK_Print), spawn "cd ~/img/cap && scrot --quality 42 '%Y-%m-%d_%H-%M-%S.png' && caja ~/img/cap") + -- Take a selective screenshot + , ((modMask, xK_Print), spawn "select-screenshot") + + -- Volume control + , ((0, 0x1008FF12), spawnExec "pactl -- set-sink-mute @DEFAULT_SINK@ toggle") -- XF88AudioMute + , ((0, 0x1008FF11), spawnExec "pactl -- set-sink-volume @DEFAULT_SINK@ -5%") -- XF86AudioLowerVolume + , ((0, 0x1008FF13), spawnExec "pactl -- set-sink-volume @DEFAULT_SINK@ +5%") -- XF86AudioRaiseVolume + -- Audio previous + -- , ((0, 0x1008FF16), spawnExec "") + -- Play/pause + -- , ((0, 0x1008FF14), spawnExec "") + -- Audio next + -- , ((0, 0x1008FF17), spawnExec "") + -- Eject CD tray + -- , ((0, 0x1008FF2C), spawnExec "eject -T") + + -- Close focused window. + , ((modMask, xK_Escape), kill) + , ((modMask, xK_q), kill) + + -- Clipboard + , ((modMask, xK_c), spawnExec "clipster --select --primary") + + -- Temporarily maximize a window + , ((modMask, xK_f), sendMessage $ XMonad.Layout.MultiToggle.Toggle FULL) + -- , ((modMask, xK_f), withFocused (sendMessage . maximizeRestore)) + + -- Cycle through the available layout algorithms + , ((modMask, 0x13bd), sendMessage NextLayout) -- oe (²) + , ((modMask, xK_ampersand), sendMessage $ JumpToLayout "ResizableTall") -- & (1) + , ((modMask, xK_eacute), sendMessage $ JumpToLayout "Mirror ResizableTall") -- é (2) + , ((modMask, xK_quotedbl), sendMessage $ JumpToLayout "Tabbed Simplest") -- ' (3) + , ((modMask, xK_apostrophe), sendMessage $ JumpToLayout "Magnifier Grid") -- " (4) + , ((modMask, xK_parenleft), sendMessage $ JumpToLayout "Spiral") -- ( (5) + , ((modMask, xK_minus), sendMessage $ JumpToLayout "Full") -- - (6) + , ((modMask, xK_egrave), sendMessage $ JumpToLayout "ThreeCol") -- è (7) + + -- Reset the layouts on the current workspace to default + -- , ((modMask .|. shiftMask, xK_space), setLayout $ XMonad.layoutHook conf) + + -- Resize viewed windows to the correct size. + , ((modMask, xK_n), refresh) + + -- Move focus between windows + , ((modMask, xK_Tab), windows W.focusDown) + , ((modMask .|. shiftMask, xK_Tab), windows W.focusUp) + , ((modMask, xK_i), windows W.focusUp) + , ((modMask, xK_k), windows W.focusDown) + + -- Move focus to the master window + , ((modMask, xK_m), windows W.focusMaster) + -- Swap the focused window and the master window + , ((modMask, xK_space), windows W.swapMaster) + + -- Swap the focused window with the next window. + --, ((modMask, xK_o), windows W.swapDown >> windows W.focusMaster) + -- Swap the focused window with the previous window. + , ((modMask, xK_m), windows W.swapUp >> windows W.focusMaster) + + -- Push window back into tiling. + , ((modMask, xK_t), withFocused $ windows . W.sink) + + -- Change the number of windows in the master area + , ((modMask, xK_Up), sendMessage $ IncMasterN 1) + , ((modMask, xK_Down), sendMessage $ IncMasterN (-1)) + + -- Toggle the status bar gap. + , ((modMask, xK_b), sendMessage ToggleStruts) + + -- Quit xmonad + , ((modMask .|. shiftMask, xK_End), io exitSuccess) + -- Restart xmonad + , ((modMask, xK_End), restart "xmonad" True) + + -- Workspace management + -- XF86Back: Switch to previous workspace + , ((0, xK_XF86Backward), prevWS) + , ((modMask, xK_j), prevWS) + -- Switch to next workspace + , ((0, xK_XF86Forward), nextWS) + , ((modMask, xK_l), nextWS) + -- XF86Back: Move the current client to the previous workspace and go there + , ((modMask, xK_XF86Backward), shiftToPrev >> prevWS) + , ((modMask .|. shiftMask, xK_j), shiftToPrev >> prevWS) + -- Move the current client to the next workspace and go there + , ((modMask, xK_XF86Forward), shiftToNext >> nextWS) + , ((modMask .|. shiftMask, xK_l), shiftToNext >> nextWS) + -- Switch to previous workspace + -- Switch to next workspace + {- + -- Move the current client to the previous workspace + , ((0 .|. shiftMask , xK_XF86Backward), shiftToPrev ) + -- Move the current client to the next workspace + , ((0 .|. shiftMask , xK_XF86Forward), shiftToNext ) + -} + + -- Toggle copying window on all workspaces (sticky window) + , ((modMask, xK_s), do + copies <- wsContainingCopies -- NOTE: consider only hidden workspaces + case copies of + [] -> windows copyToAll + _ -> killAllOtherCopies + ) + + -- Resize the master area + , ((modMask, xK_Left), sendMessage Shrink) + , ((modMask, xK_Right), sendMessage Expand) + -- Resize windows in ResizableTall mode + , ((modMask .|. shiftMask, xK_Left), sendMessage MirrorShrink) + , ((modMask .|. shiftMask, xK_Right), sendMessage MirrorExpand) + ] ++ + + -- mod-[F1..F9], Switch to workspace N + -- mod-shift-[F1..F9], Move client to workspace N + [ ((m .|. modMask, k), windows $ f i) + | (i, k) <- zip (workspaces conf) [xK_F1 ..] ++ + zip (workspaces conf) [xK_1 ..] + , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)] + ] ++ + {- NOTE: with Xinerama + [((m .|. modMask, k), windows $ onCurrentScreen f i) + | (i, k) <- zip (workspaces' conf) [xK_F1 ..] + , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)] ] + -} + + -- mod-{w,e,r}, Switch to physical/Xinerama screens 1, 2, or 3 + -- mod-shift-{w,e,r}, Move client to screen 1, 2, or 3 + [ ((m .|. modMask, key), screenWorkspace sc >>= flip whenJust (windows . f)) + | (key, sc) <- zip [xK_w, xK_e, xK_r] [0 ..] + , (f, m) <- [(W.view, 0), (W.shift, shiftMask)] + ] ++ + + -- mod-shift-[F1..F9], Swap workspace with workspace N + -- mod-shift-[1..9], Swap workspace with workspace N + [ ((modMask .|. controlMask, k), windows $ swapWithCurrent i) + | (i, k) <- zip (workspaces conf) [xK_F1 ..] ++ + zip (workspaces conf) [xK_1 ..] + ] + {- NOTE: with Xinerama + [((modMask .|. controlMask, k), windows $ onCurrentScreen swapWithCurrent i) + | (i, k) <- zip (workspaces' conf) [xK_F1 ..] ] + -} + , layoutHook = smartBorders $ + mkToggle (NOBORDERS ?? FULL ?? EOT) $ -- enable temporarily maximizing a window + avoidStruts $ -- prevents windows from overlapping dock windows + let tall = ResizableTall 1 (1%200) (8%13) [] in + tabbed shrinkText tabConfig + ||| tall + ||| Mirror tall + ||| magnifiercz (13%10) Grid + ||| spiral (6%7) + ||| noBorders (fullscreenFull Full) + ||| ThreeColMid 1 (1%200) (1%2) + -- ||| Tall 1 (3/100) (1/2) + , manageHook = composeAll + -- [ , isFullscreen --> (doF W.focusDown <+> doFullFloat) + [ isFullscreen --> doFullFloat + , manageHook def + , manageDocks -- NOTE: do not tile dock windows + , resource =? "desktop_window" --> doIgnore + , className =? "Gimp" --> doFloat + , resource =? "gpicview" --> doSink + , className =? "mpv" --> doFloat + --, className =? "MPlayer" --> doShift "3:media" -- <+> doFloat + --, className =? "vlc" --> doShift "3:media" + , className =? "trayer" --> doIgnore + ] + , modMask = mod4Mask + , mouseBindings = \XConfig{XMonad.modMask} -> + Map.fromList + [ + -- mod-button1, Set the window to floating mode and move by dragging + ((modMask, button1), \w -> focus w >> mouseMoveWindow w) + + -- mod-button2, Raise the window to the top of the stack + , ((modMask, button2), \w -> focus w >> windows W.swapMaster) + + -- mod-button3, Set the window to floating mode and resize by dragging + , ((modMask, button3), \w -> focus w >> mouseResizeWindow w) + + , ((modMask, button4), \_ -> windows W.focusUp) + , ((modMask, button5), \_ -> windows W.focusDown) + + -- Cycle through workspaces + , ((controlMask .|. modMask, button5), nextNonEmptyWS) + , ((controlMask .|. modMask, button4), prevNonEmptyWS) + ] + , normalBorderColor = "#7C7C7C" + , startupHook = setWMName "XMonad" + <+> spawnExec "wmname XMonad" + <+> spawnExec "xrdb -all .Xresources" + <+> spawn "sleep 1 && xmodmap .Xmodmap" + <+> spawnExec "xset r rate 250 25" + <+> spawnExec "xset b off" + <+> spawnExec "xhost local:root" + <+> spawnExec "setxkbmap -option keypad:pointerkeys" + -- Useful for programs launched by rofi + <+> spawnExec "systemctl --user import-environment GNUPGHOME PASSWORD_STORE_DIR PATH" + -- <+> spawnOnce "exec arbtt-capture -r 60" + -- <+> spawnOnce "exec parcellite" + -- <+> spawnOnce "exec xautolock" + -- <+> spawnOnce "exec redshift-gtk -l -45.7800:1.9700 -t 6500:3700" + <+> spawnOnce "exec nm-applet" + , terminal = "urxvtc" + , workspaces = {- withScreens nScreens $ -} + {-["1:work","2:web","3:media"] ++-} + map show [1::Int .. 9] + , logHook = updatePointer (0.5, 0.5) (0, 0) -- >> updatePointer (Relative 0.5 0.5) } where @@ -336,12 +301,64 @@ defaults xmproc _nScreens = docks $ ewmhFullscreen $ ewmh $ , fontName = "Hack 7" } --- --- Run xmonad --- -main = do - nScreens <- countScreens - xmproc <- spawnPipe "exec xmobar ~/.xmonad/xmobar.hs" - xmonad $ - withUrgencyHook NoUrgencyHook $ -- dzenUrgencyHook { args = ["-bg", "darkgreen", "-xs", "1"] } - defaults xmproc (nScreens::Integer) +barSpawner :: ScreenId -> IO StatusBarConfig +barSpawner 0 = pure $ topXmobar <> traySB +--barSpawner 1 = pure $ xmobar1 +barSpawner _ = pure $ topXmobar -- nothing on the rest of the screens + +-- Display properties of the root window: +-- xprop -display $DISPLAY -root +topXmobar = statusBarPropTo "_XMONAD_XMOBAR0" "xmobar -x 0 ~/.config/xmonad/xmobar0.hs" (pure topPP) + where + topPP = + xmobarPP + { ppCurrent = xmobarColor "black" "#CCCCCC" + , ppHidden = xmobarColor "#CCCCCC" "black" + , ppHiddenNoWindows = xmobarColor "#606060" "black" + , ppLayout = \s -> xmobarColor "black" "#606060" $ + case s of + "ResizableTall" -> " | " + "Mirror ResizableTall" -> " - " + "Tabbed Simplest" -> " + " + "Magnifier Grid" -> " ~ " + "Spiral" -> " @ " + "Full" -> " O " + "ThreeCol" -> " # " + _ -> s + , ppSep = " " + , ppTitle = xmobarColor "white" "black" . shorten 50 + , ppUrgent = xmobarColor "yellow" "black" + , ppWsSep = " " + } + +traySB :: StatusBarConfig +traySB = + statusBarGeneric + ( List.unwords + [ "trayer" + , "--align right" + , "--distance 0,0" + , "--distancefrom top,right" + , "--edge top" + , "--expand true" + , "--height 16" + , "--monitor primary" + , "--tint 0x000000" + , "--iconspacing 0" + , "--transparent true" + , "--widthtype request" + , "-l" + ] + ) + mempty + +nextNonEmptyWS _ = moveTo Next (WSIs ((not .) <$> isWindowSpaceVisible)) +prevNonEmptyWS _ = moveTo Prev (WSIs ((not .) <$> isWindowSpaceVisible)) + +isWindowSpaceVisible :: X (WindowSpace -> Bool) +isWindowSpaceVisible = do + vs <- gets (map (W.tag . W.workspace) . W.visible . windowset) + return (\w -> W.tag w `elem` vs) + +spawnExec s = spawn $ List.unwords $ [ "exec" ] <> systemdCat <> [ s ] +systemdCat = [ "systemd-cat" , "--priority=info", "--stderr-priority=warning", "--level-prefix=false" , "--" ] -- 2.42.0