![Community banner](https://infosec.pub/pictrs/image/0f4f5323-05ed-4561-b0ff-3ae1b5883d1c.png)
-
Help Wanted: wlroots bindings (the first step toward Waymonad!)
github.com GitHub - bradrn/wlhs: Haskell bindings to wlroots (and libwayland)Haskell bindings to wlroots (and libwayland). Contribute to bradrn/wlhs development by creating an account on GitHub.
-
Glassy and Classy Neovim
cross-posted from: https://lemmy.ml/post/3446539
> Dots: https://github.com/siph/nix-dotfiles > Neovim: https://github.com/siph/nixvim-flake > > This neovim config is build with nixvim.
-
Switching to Kanagawa
cross-posted from: https://discuss.online/post/632392
> * GitHub Repository: Snowflake (Nix Flake) > * Distribution: NixOS > * Keyboard Manager: KMonad > * Window Manager: XMonad > * Status-Bar: Taffybar > * Display Manager: LightDM-mini-greeter > * GTK Theme: Kanagawa GTK > * Icon Theme: Kanagawa Icons > * Cursor Theme: Bibata-Cursor (Modern-Classic) > * Font: Victor Mono Nerd Font > * Terminal: Alacritty \+ Tmux > * Editor: Emacs \- Irkalla (Emacs Conf) > * Wallpaper: Ismail Inceoglu - Chaos Invoked > * Browser: Firefox > > Everything else not listed in this comment can be found in the repository linked above.
-
I love inflicting pain on myself, so here's my self-made taskbar.
cross-posted from: https://sopuli.xyz/post/1271853
> Yep, this is me with my own taskbar. I only thought about if I could, never stopping to ever consider whether I should.
-
High Density
cross-posted from: https://lemmy.world/post/628249
> Simple additions to the default theme of XMonad. > > I have taken inspiration from liskin's dotfiles here (https://github.com/liskin/dotfiles/tree/home/.xmonad) because he does the high density thing very well, I am trying to replicate the looks of his setup in my config, his one still looks way better in my opinion. > > Dotfiles: https://codeberg.org/yusz/dotfiles-public
-
Old Pywal Setup
cross-posted from: https://pawb.social/post/108705
> I made This old setup a couple of years ago that was (nearly) fully automated with Pywal. I don't think I have the source for most of it anymore, but here is what I remember using: > > WM: xmonad > Terminal: Alacritty + fish + starship > Bar: Polybar > App launcher: Rofi, based on adi1090x's themes > Clock widget: Conky, using a custom background made in Inkscape > Text editor: Micro / VSCode > Firefox theme: blurredfox > Spotify theme: spicetify
-
Riceberry-pi
cross-posted from: https://lemmy.ml/post/1262399
> Some of my nixos config running on a raspberry-pi. > Dots: https://github.com/siph/nix-dotfiles
-
kanagawa guix
cross-posted from: https://lemmy.ml/post/1153165
> hello! i previously posted my setup on the subreddit however due to some egregious decisions i am trying to move largely to lemmy and other federated social media platforms. this is my first post yet so hello again! > > Operating System: GNU Guix > > Desktop Environment: Xfce > > Window Manager: xmonad > > Text Editor: GNU Emacs with native-comp from flatwhatson channel > > Terminal: Kitty > > Font: Iosevka Term > > Theme: Kanagawa > > you can access my dotfiles on my codeberg!
-
DistroTube - Getting Started With XMonad (42:46)
YouTube Video
Click to view this content.
> In this rather lengthy video, I go over the basics of getting started with XMonad. I install XMonad on Ubuntu 20.04 and show some of the basics as far as configuration. I also show you how to use the Haskell documentation. And I briefly show you how to install and configure XMobar.
-
My Current NixOS XMonad Config
https://github.com/harryprayiv/nix-config/blob/intelTower/home/programs/xmonad/config.hs
``` import Control.Monad ( replicateM_ , filterM , liftM , join , unless ) import Data.IORef import Data.Char import Data.List import Data.Foldable ( traverse_ ) import Data.Monoid import Graphics.X11.ExtraTypes.XF86 import System.Exit import System.Directory ( doesFileExist ) import System.IO ( hPutStr , hClose , writeFile ) import XMonad import XMonad.Actions.CycleWS ( Direction1D(..) , WSType(..) , anyWS , findWorkspace ) import XMonad.Actions.DynamicProjects ( Project(..) , dynamicProjects , switchProjectPrompt ) import XMonad.Actions.DynamicWorkspaces ( removeWorkspace ) import XMonad.Actions.FloatKeys ( keysAbsResizeWindow , keysResizeWindow ) import XMonad.Actions.RotSlaves ( rotSlavesUp ) import XMonad.Actions.SpawnOn ( manageSpawn , spawnOn ) import XMonad.Actions.WithAll ( killAll ) import XMonad.Actions.CopyWindow ( killAllOtherCopies , copy , copyToAll , kill1 ) import XMonad.Hooks.EwmhDesktops ( ewmh , ewmhFullscreen ) import XMonad.Hooks.FadeInactive import XMonad.Hooks.InsertPosition ( Focus(..) , Position(..) --, Position(Above) , insertPosition ) import XMonad.Hooks.ManageDocks ( Direction2D(..) , ToggleStruts(..) , avoidStruts , docks ) import XMonad.Hooks.ManageHelpers ( (-?>) , composeOne , doCenterFloat , doFullFloat , isDialog , isFullscreen , isInProperty ) import XMonad.Hooks.UrgencyHook ( UrgencyHook(..) , withUrgencyHook ) import XMonad.Layout.Gaps ( GapSpec(..) , GapMessage (IncGap, DecGap) , weakModifyGaps , gaps , setGaps ) import XMonad.Layout.MultiToggle ( Toggle(..) , mkToggle , single ) import XMonad.Layout.MultiToggle.Instances ( StdTransformers(NBFULL) ) import XMonad.Layout.NoBorders ( smartBorders ) import XMonad.Layout.PerWorkspace ( onWorkspace ) import XMonad.Layout.Spacing ( SpacingModifier(..) , spacing , incScreenWindowSpacing , decScreenWindowSpacing ) import XMonad.Layout.HintedGrid import XMonad.Layout.ThreeColumns ( ThreeCol(..) ) import XMonad.Layout.Spiral import XMonad.Layout.Fullscreen import XMonad.Layout.OneBig import XMonad.Layout.Tabbed import XMonad.Layout.Reflect ( reflectHoriz ) import XMonad.Layout.ResizableTile import XMonad.Prompt ( XPConfig(..) , amberXPConfig , XPPosition(CenteredAt) ) import XMonad.Util.EZConfig ( mkNamedKeymap , additionalKeys , removeKeys ) import XMonad.Util.NamedActions ( (++) , NamedAction (..) , addDescrKeys' , addName , showKm , subtitle ) import XMonad.Util.NamedScratchpad ( NamedScratchpad(..) , customFloating , defaultFloating , namedScratchpadAction , namedScratchpadManageHook ) import XMonad.Util.Run ( safeSpawn , spawnPipe ) import XMonad.Util.SpawnOnce ( spawnOnce ) import XMonad.Util.WorkspaceCompare ( getSortByIndex ) import XMonad.Util.XSelection ( safePromptSelection )
import qualified Control.Exception as E import qualified Data.Map as M import qualified XMonad.StackSet as W import qualified XMonad.Util.NamedWindows as W import qualified XMonad.Util.ExtensibleState as XS -- Custom State
-- Imports for Polybar -- import qualified Codec.Binary.UTF8.String as UTF8 import qualified Data.Set as S import qualified DBus as D import qualified DBus.Client as D import XMonad.Hooks.DynamicLog import HueLighting
main :: IO () main = mkDbusClient >>= main'
main' :: D.Client -> IO () main' dbus = xmonad . docks . ewmh . ewmhFullscreen . dynProjects . keybindings . urgencyHook $ def { terminal = myTerminal , focusFollowsMouse = False , clickJustFocuses = False , borderWidth = 2 , modMask = myModMask , workspaces = myWS , normalBorderColor = "#32343d" -- #neutral gray , focusedBorderColor = "#6C99B8" -- nice blue , mouseBindings = myMouseBindings , layoutHook = myLayout , manageHook = myManageHook , logHook = myPolybarLogHook dbus , startupHook = myStartupHook } where myModMask = mod4Mask -- super as the mod key dynProjects = dynamicProjects projects keybindings = addDescrKeys' ((myModMask, xK_F1), showKeybindings) myKeys urgencyHook = withUrgencyHook LibNotifyUrgencyHook
-- Perform an arbitrary action each time xmonad starts or is restarted -- with mod-q. Used by, e.g., XMonad.Layout.PerWorkspace to initialize -- per-workspace layout choices. myStartupHook = startupHook def
-- original idea: https://pbrisbin.com/posts/using_notify_osd_for_xmonad_notifications/ data LibNotifyUrgencyHook = LibNotifyUrgencyHook deriving (Read, Show)
instance UrgencyHook LibNotifyUrgencyHook where urgencyHook LibNotifyUrgencyHook w = do name <- W.getName w maybeIdx <- W.findTag w <$> gets windowset traverse_ (\i -> safeSpawn "notify-send" [show name, "workspace " ++ i]) maybeIdx
------------------------------------------------------------------------ -- Polybar settings (needs DBus client). -- mkDbusClient :: IO D.Client mkDbusClient = do dbus <- D.connectSession D.requestName dbus (D.busName_ "org.xmonad.log") opts return dbus where opts = [D.nameAllowReplacement, D.nameReplaceExisting, D.nameDoNotQueue]
-- Emit a DBus signal on log updates dbusOutput :: D.Client -> String -> IO () dbusOutput dbus str = let opath = D.objectPath_ "/org/xmonad/Log" iname = D.interfaceName_ "org.xmonad.Log" mname = D.memberName_ "Update" signal = D.signal opath iname mname body = [D.toVariant $ UTF8.decodeString str] in D.emit dbus $ signal { D.signalBody = body }
polybarHook :: D.Client -> PP polybarHook dbus = let wrapper c s | s /= "NSP" = wrap ("%{F" <> c <> "} ") " %{F-}" s | otherwise = mempty blue = "#619DEC" gray = "#8D868F" white = "#FFFFFF" orange = "#CF6A4C" yellow = "#F9F4CD" green = "#8F9D6A" darkgray = "#5F5A60" in def { ppOutput = dbusOutput dbus , ppCurrent = wrapper blue , ppVisible = wrapper white , ppUrgent = wrapper orange , ppHidden = wrapper gray , ppHiddenNoWindows = wrapper darkgray , ppTitle = wrapper yellow . shorten 120 }
myPolybarLogHook dbus = myLogHook <+> dynamicLogWithPP (polybarHook dbus)
--- Dynamic Gaps implementation
-- Gaps between windows gapSize = 10
newtype GapState = GapIndex Int deriving Show instance ExtensionClass GapState where initialValue = GapIndex 0
myGaps :: [GapSpec] myGaps = [ [(R,10),(L,10),(U,10),(D,10)] -- you do have to specify all directions , [(R,5),(L,5),(U,5),(D,5)] , [(R,2),(L,2),(U,2),(D,2)] , [(R,20),(L,20),(U,20),(D,20)] , [(R,25),(L,25),(U,25),(D,25)] , [(R,30),(L,30),(U,30),(D,30)] , [(R,40),(L,40),(U,40),(D,40)] , [(R,0),(L,0),(U,100),(D,100)] , [(R,500),(L,0),(U,0),(D,0)] , [(R,0),(L,500),(U,0),(D,0)] , [(R,0),(L,0),(U,400),(D,0)] , [(R,0),(L,0),(U,0),(D,400)] , [(R,0),(L,0),(U,0),(D,0)] ]
cycleGaps :: X() cycleGaps = do (GapIndex idx) <- XS.gets $ \(GapIndex i) -> let n = if i >= length myGaps - 1 then 0 else i+1 in GapIndex n sendMessage (setGaps $ myGaps !! idx) XS.put $ GapIndex idx
myTerminal = "alacritty"
terminalWithCommand :: String -> String terminalWithCommand cmd = "alacritty -o shell.program=fish -o shell.args=['-C " <> cmd <> "']"
myBashTerminal = "alacritty --hold -e bash" myZshTerminal = "alacritty --hold -e zsh"
delayTerminal = "sleep 2s && alacritty" myGuildView = "alacritty --hold -e ./guild-operators/scripts/cnode-helper-scripts/gLiveView.sh" cnodeStatus = "alacritty --hold -o font.size=5 -e systemctl status cardano-node" myCardanoCli = "sleep 20m && alacritty --hold -e node_check" appLauncher = "rofi -modi drun,ssh,window -show drun -show-icons" playerctl c = "playerctl --player=spotify,%any " <> c
calcLauncher = "rofi -show calc -modi calc -no-show-match -no-sort" emojiPicker = "rofi -modi emoji -show emoji -emoji-mode copy" --spotlight = "rofi -modi spotlight -show spotlight -spotlight-mode copy"
-- Screen Lock screenLocker = "betterlockscreen -l dim"
------------------------------------------------------------------------ -- Key bindings. Add, modify or remove key bindings here. showKeybindings :: [((KeyMask, KeySym), NamedAction)] -> NamedAction showKeybindings xs = let filename = "/home/bismuth/.xmonad/keybindings" command f = "alacritty -e dialog --title 'XMonad Key Bindings' --colors --hline \"$(date)\" --textbox " ++ f ++ " 50 100" in addName "Show Keybindings" $ do b <- liftIO $ doesFileExist filename unless b $ liftIO (writeFile filename (unlines $ showKm xs)) spawnOn webWs $ command filename -- show dialog on webWs windows $ W.greedyView webWs -- switch to webWs
-- use "xev" to figure out exactly what key you are pressing myKeys conf@XConfig {XMonad.modMask = modm} = keySet "Applications" [ key "Mastodon" (modm .|. controlMask, xK_t ) $ spawnOn comWs "brave --app=https://mastodon.social/" , key "Youtube" (modm .|. controlMask, xK_y ) $ spawnOn webWs "brave --app=https://youtube.com/" , key "Private Browser" (modm .|. controlMask, xK_p ) $ spawnOn webWs "brave --incognito" -- , key "Home Page w/App" (modm .|. controlMask, xK_a ) $ spawnOn webWs "brave --app=https://prettycoffee.github.io/fluidity/" ] ++ keySet "Lighting Cues" [ key "DarkWarm" (0, xF86XK_MonBrightnessDown ) (runLightCue 0) , key "BrighterWarm" (0, xF86XK_MonBrightnessUp ) (runLightCue 2) , key "FullWarm" (controlMask, xF86XK_MonBrightnessUp ) (runLightCue 3) , key "Prev Lighting Cue" (modm, xF86XK_MonBrightnessDown ) prevLightCue , key "Next Lighting Cue" (modm, xF86XK_MonBrightnessUp ) nextLightCue , key "FullCold" (modm .|. controlMask, xF86XK_MonBrightnessUp ) (runLightCue 6) ] ++ keySet "Audio" [ key "Mute" (0, xF86XK_AudioMute ) $ spawn "amixer -q set Master toggle" , key "Lower volume" (0, xF86XK_AudioLowerVolume ) $ spawn "amixer -q set Master 3%-" , key "Raise volume" (0, xF86XK_AudioRaiseVolume ) $ spawn "amixer -q set Master 3%+" , key "Lower S volume" (modm, xF86XK_AudioLowerVolume ) $ spawn $ playerctl "volume 0.05-" , key "Raise S volume" (modm, xF86XK_AudioRaiseVolume ) $ spawn $ playerctl "volume 0.05+" , key "Mute S volume" (modm, xF86XK_AudioMute ) $ spawn $ playerctl "volume 0.0" , key "100% S volume" (modm .|. shiftMask , xF86XK_AudioMute ) $ spawn $ playerctl "volume 1.0" , key "Play / Pause" (0, xF86XK_AudioPlay ) $ spawn $ playerctl "play-pause" , key "Stop" (0, xF86XK_AudioStop ) $ spawn $ playerctl "stop" , key "Previous" (0, xF86XK_AudioPrev ) $ spawn $ playerctl "previous" , key "Next" (0, xF86XK_AudioNext ) $ spawn $ playerctl "next" ] ++ keySet "Launchers" [ key "Terminal" (modm .|. shiftMask , xK_Return ) $ spawn (XMonad.terminal conf) , key "Bash Terminal" (modm .|. controlMask, xK_b ) $ spawn myBashTerminal , key "Zsh Terminal" (modm .|. controlMask, xK_z ) $ spawn myZshTerminal , key "Apps (Rofi)" (0, xF86XK_LaunchA ) $ spawn appLauncher , key "Calc (Rofi)" (modm .|. shiftMask , xK_c ) $ spawn calcLauncher , key "Emojis (Rofi)" (modm .|. shiftMask , xK_m ) $ spawn emojiPicker , key "Lock screen" (modm .|. controlMask, xK_l ) $ spawn screenLocker >> runLightCue 8 ] ++ keySet "Layouts" [ key "Next" (modm , xK_space ) $ sendMessage NextLayout , key "SpaceInc" (modm , xK_g ) $ incScreenWindowSpacing 2 , key "SpaceDec" (modm .|. shiftMask , xK_g ) $ decScreenWindowSpacing 2 , key "BorderSwitch" (modm , xK_b ) cycleGaps , key "Reset" (modm .|. shiftMask , xK_space ) $ setLayout (XMonad.layoutHook conf) , key "Fullscreen" (modm , xK_f ) $ sendMessage (Toggle NBFULL) ] ++ keySet "Polybar" [ key "Toggle" (modm , xK_equal ) togglePolybar ] ++ keySet "Projects" [ key "Switch prompt" (0, xF86XK_KbdBrightnessDown ) $ switchProjectPrompt projectsTheme ] ++ keySet "Scratchpads" [ key "bottom" (0, xF86XK_LaunchB ) $ runScratchpadApp btm , key "GuildView" (modm .|. controlMask, xK_g ) $ spawnOn spoWs myGuildView , key "Files" (modm .|. controlMask, xK_f ) $ runScratchpadApp nautilus , key "Screen recorder" (modm .|. controlMask, xK_r ) $ runScratchpadApp scr -- , key "Spotify" (modm .|. controlMask, xK_s ) $ runScratchpadApp spotify , key "Mpv" (modm .|. controlMask, xK_m ) $ safePromptSelection "mpv" , key "Gimp" (modm .|. controlMask, xK_i ) $ runScratchpadApp gimp ] ++ keySet "Screens" switchScreen ++ keySet "System" [ key "Toggle status bar gap" (modm .|. shiftMask, xK_b ) toggleStruts , key "Logout (quit XMonad)" (modm .|. shiftMask, xK_q ) $ io exitSuccess , key "Restart XMonad" (modm , xK_q ) $ spawn "xmonad --recompile; xmonad --restart" , key "Capture entire screen" (modm , xK_Print ) $ spawn "flameshot full -p ~/Pictures/flameshot/" , key "Switch keyboard layout" (modm , xK_F8 ) $ spawn "kls" , key "Disable CapsLock" (modm , xK_F9 ) $ spawn "setxkbmap -option ctrl:nocaps" ] ++ keySet "Windows" [ key "Close focused" (modm , xK_BackSpace ) kill1 , key "Close all in ws" (modm .|. shiftMask, xK_BackSpace ) killAll , key "Refresh size" (modm , xK_n ) refresh , key "Focus next" (modm , xK_j ) $ windows W.focusDown , key "Focus previous" (modm , xK_k ) $ windows W.focusUp , key "Focus master" (modm , xK_m ) $ windows W.focusMaster , key "Swap master" (modm , xK_Return ) $ windows W.swapMaster , key "Swap next" (modm .|. shiftMask, xK_j ) $ windows W.swapDown , key "Swap previous" (modm .|. shiftMask, xK_k ) $ windows W.swapUp , key "Shrink master" (modm , xK_h ) $ sendMessage Shrink , key "Expand master" (modm , xK_l ) $ sendMessage Expand , key "Mirror shrink" (modm , xK_a ) $ sendMessage MirrorShrink , key "Mirror grow" (modm , xK_z ) $ sendMessage MirrorExpand , key "Switch to tile" (modm , xK_t ) $ withFocused (windows . W.sink) , key "Rotate slaves" (modm .|. shiftMask, xK_Tab ) rotSlavesUp , key "Decrease size" (modm , xK_d ) $ withFocused (keysResizeWindow (-10,-10) (1,1)) , key "Increase size" (modm , xK_s ) $ withFocused (keysResizeWindow (10,10) (1,1)) , key "Decr abs size" (modm .|. shiftMask, xK_d ) $ withFocused (keysAbsResizeWindow (-10,-10) (1024,752)) , key "Incr abs size" (modm .|. shiftMask, xK_s ) $ withFocused (keysAbsResizeWindow (10,10) (1024,752)) , key "Always Visible" (modm , xK_v ) $ windows copyToAll , key "Kill Copies" (modm .|. shiftMask, xK_v ) $ killAllOtherCopies ] ++ keySet "Workspaces" [ key "Next" (modm , xK_period ) nextWS' , key "Previous" (modm , xK_comma ) prevWS' , key "Remove" (modm , xF86XK_Eject ) removeWorkspace ] ++ switchWsById where togglePolybar = spawn "polybar-msg cmd toggle &" toggleStruts = togglePolybar >> sendMessage ToggleStruts keySet s ks = subtitle s : ks key n k a = (k, addName n a) action m = if m == shiftMask then "Move to " else "Switch to " -- mod-[1..9]: Switch to workspace N | -- mod-shift-[1..9]: Move client to workspace N switchWsById = [ key (action m <> show i) (m .|. modm, k) (windows $ f i) | (i, k) <- zip (XMonad.workspaces conf) [xK_1 .. xK_9] , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask), (copy, shiftMask .|. controlMask)]] -- 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 switchScreen = [ key (action m <> show sc) (m .|. modm, k) (screenWorkspace sc >>= flip whenJust (windows . f)) | (k, sc) <- zip [xK_w, xK_e, xK_r] [0..] , (f, m) <- [(W.view, 0), (W.shift, shiftMask)]]
----------- Cycle through workspaces one by one but filtering out NSP (scratchpads) -----------
nextWS' = switchWS Next prevWS' = switchWS Prev
switchWS dir = findWorkspace filterOutNSP dir anyWS 1 >>= windows . W.view
filterOutNSP = let g f xs = filter (\(W.Workspace t _ _) -> t /= "NSP") (f xs) in g <$> getSortByIndex
------------------------------------------------------------------------ -- Mouse bindings: default actions bound to mouse events---------------- myMouseBindings XConfig {XMonad.modMask = modm} = M.fromList
-- mod-button1, Set the window to floating mode and move by dragging [ ((modm, button1), \w -> focus w >> mouseMoveWindow w >> windows W.shiftMaster)
-- mod-button2, Raise the window to the top of the stack , ((modm, button2), \w -> focus w >> windows W.shiftMaster)
-- mod-button3, Set the window to floating mode and resize by dragging , ((modm, button3), \w -> focus w >> mouseResizeWindow w >> windows W.shiftMaster)
-- you may also bind events to the mouse scroll wheel (button4 and button5) ]
------------------------------------------------------------------------ -- Layouts:
-- You can specify and transform your layouts by modifying these values. -- If you change layout bindings be sure to use 'mod-shift-space' after -- restarting (with 'mod-q') to reset your layout state to the new -- defaults, as xmonad preserves your old layout settings by default. -- -- The available layouts. Note that each layout is separated by |||, -- which denotes layout choice. -- myLayout = avoidStruts . smartBorders . fullScreenToggle . comLayout . vscLayout . musLayout . webLayout . mscLayout . devLayout . scdLayout . spoLayout . vmsLayout . secLayout $ (tiled ||| Mirror tiled ||| column3 ||| full) where -- default tiling algorithm partitions the screen into two panes grid = spacing gapSize . gaps (head myGaps) $ Grid False grid_strict_portrait = spacing gapSize . gaps (head myGaps) $ GridRatio grid_portrait False grid_strict_landscape = spacing gapSize . gaps (head myGaps) $ GridRatio grid_landscape False tiled = spacing gapSize . gaps (head myGaps) $ Tall nmaster delta golden_ratio doubletiled = spacing gapSize . gaps (head myGaps) $ Tall nmasterTwo delta golden_ratio tiled_nogap = spacing 0 . gaps (myGaps !! 12) $ Tall nmaster delta golden_ratio tiled_spaced = spacing 0 . gaps (myGaps !! 3) $ Tall nmaster delta ratio column3_og = spacing gapSize . gaps (head myGaps) $ ThreeColMid 1 (3/100) (1/2) video_tile = spacing gapSize . gaps (head myGaps) $ Mirror (Tall 1 (1/50) (3/5)) full = Full fuller = spacing 0 . gaps (myGaps !! 12) $ Full column3 = spacing 2 . gaps (myGaps !! 2) $ ThreeColMid 1 (33/100) (1/2) goldenSpiral = spacing gapSize . gaps (head myGaps) $ spiral golden_ratio silverSpiral = spacing gapSize . gaps (head myGaps) $ spiralWithDir East CCW ratio dynamicGaps = spacing gapSize . gaps (head myGaps) $ spiralWithDir East CCW ratio oneBig = spacing 2 . gaps (myGaps !! 3) $ OneBig (3/4) (3/4) tabbed = spacing 2 . gaps (myGaps !! 3) $ simpleTabbed resizeTall = spacing gapSize . gaps (head myGaps) $ ResizableTall nmaster (delta) ratio [] resize2Master = spacing gapSize . gaps (head myGaps) $ ResizableTall nmasterTwo (delta) ratio []
-- The default number of windows in the master pane nmaster = 1 nmasterTwo = 2
-- Default proportions of screen occupied by master pane ratio = 1/2 golden_ratio = 1/1.618033988749894e0 grid_portrait = 3/4 grid_landscape = 4/3
-- Percent of screen to increment by when resizing panes delta = 2/100
-- Per workspace layout webLayout = onWorkspace webWs (resizeTall ||| tiled_nogap ||| oneBig ||| reflectHoriz tiled_nogap ||| fuller ||| goldenSpiral ||| reflectHoriz goldenSpiral ||| tiled_spaced ||| reflectHoriz tiled_spaced ||| full ||| grid ||| grid_strict_landscape) mscLayout = onWorkspace mscWs (resize2Master ||| resizeTall ||| tabbed ||| resize2Master ||| dynamicGaps ||| doubletiled ||| Mirror grid_strict_landscape ||| grid_strict_landscape ||| Mirror grid_strict_portrait ||| grid_strict_portrait ||| column3_og ||| tiled_spaced ||| grid ||| fuller ||| Mirror tiled_nogap ||| Mirror tiled ||| tiled_nogap ||| tiled ||| video_tile ||| full ||| column3 ||| goldenSpiral ||| silverSpiral) musLayout = onWorkspace musWs (fuller ||| oneBig ||| tiled ||| tiled_spaced ||| reflectHoriz tiled_spaced) vscLayout = onWorkspace vscWs (resize2Master ||| oneBig ||| Mirror tiled_nogap ||| reflectHoriz tiled ||| fuller ||| tiled_nogap ||| goldenSpiral ||| full ||| Mirror tiled ||| column3_og ) comLayout = onWorkspace comWs (tiled ||| full ||| column3 ||| goldenSpiral) spoLayout = onWorkspace spoWs (tabbed ||| oneBig ||| goldenSpiral ||| column3 ||| Mirror tiled_nogap ||| fuller ||| full ||| tiled) scdLayout = onWorkspace scdWs (oneBig ||| dynamicGaps ||| doubletiled ||| Mirror grid_strict_landscape ||| grid_strict_landscape ||| Mirror grid_strict_portrait ||| grid_strict_portrait ||| column3_og ||| tiled_spaced ||| grid ||| fuller ||| Mirror tiled_nogap ||| Mirror tiled ||| tiled_nogap ||| tiled ||| video_tile ||| full ||| column3 ||| goldenSpiral ||| silverSpiral) devLayout = onWorkspace devWs (oneBig ||| reflectHoriz tiled ||| goldenSpiral ||| full ||| tiled ||| Mirror tiled ||| column3) secLayout = onWorkspace secWs (tiled ||| fuller ||| column3) vmsLayout = onWorkspace vmsWs (full ||| tiled ||| fuller ||| column3)
-- Fullscreen fullScreenToggle = mkToggle (single NBFULL)
-- Defining Rectangles using absolute points (https://gist.github.com/tkf/1343015) doFloatAbsRect :: Rational -> Rational -> Rational -> Rational -> ManageHook doFloatAbsRect x y width height = do win <- ask -- get Window q <- liftX (floatLocation win) -- get (ScreenId, W.RationalRect) let sid = fst q :: ScreenId oirgRect = snd q :: W.RationalRect ss2ss ss = -- :: StackSet ... -> StackSet ... W.float win newRect ss where mapping = map (\s -> (W.screen s, W.screenDetail s)) (c:v) where c = W.current ss v = W.visible ss maybeSD = lookup sid mapping scRect = fmap screenRect maybeSD newRect = case scRect of Nothing -> oirgRect Just (Rectangle x0 y0 w0 h0) -> W.RationalRect x' y' w' h' where W.RationalRect x1 y1 w1 h1 = oirgRect x' = if x0 == 0 then x1 else x / (fromIntegral x0) y' = if y0 == 0 then y1 else y / (fromIntegral y0) w' = if w0 == 0 then w1 else width / (fromIntegral w0) h' = if h0 == 0 then h1 else height / (fromIntegral h0) doF ss2ss
type AppName = String type AppTitle = String type AppClassName = String type AppCommand = String
data App = ClassApp AppClassName AppCommand | TitleApp AppTitle AppCommand | NameApp AppName AppCommand deriving Show
audacious = ClassApp "Audacious" "audacious" btm = TitleApp "btm" "alacritty -t btm -e btm --color gruvbox --default_widget_type proc" virtbox = ClassApp "VirtualBox Machine" "VBoxManage startvm 'plutusVM_bismuth'" calendar = ClassApp "Orage" "orage" cmatrix = TitleApp "cmatrix" "alacritty cmatrix" eog = NameApp "eog" "eog" evince = ClassApp "Evince" "evince" gimp = ClassApp "Gimp" "gimp" keepass = ClassApp "KeePassXC" "keepassxc" -- mastodon = TitleApp "Mastodon" "tokodon" nautilus = ClassApp "Org.Gnome.Nautilus" "nautilus" office = ClassApp "libreoffice-draw" "libreoffice-draw" pavuctrl = ClassApp "Pavucontrol" "pavucontrol" scr = ClassApp "SimpleScreenRecorder" "simplescreenrecorder" -- spotify = ClassApp "Spotify" "spotify" vlc = ClassApp "Vlc" "vlc --qt-minimal-view" mpv = ClassApp "Mpv" "mpv" kodi = ClassApp "Kodi" "kodi" vscodium = ClassApp "VSCodium" "vscodium" yad = ClassApp "Yad" "yad --text-info --text 'XMonad'"
myManageHook = manageApps <+> manageSpawn <+> manageScratchpads where isBrowserDialog = isDialog <&&> className =? "Brave-browser" isFileChooserDialog = isRole =? "GtkFileChooserDialog" isPopup = isRole =? "pop-up" isSplash = isInProperty "_NET_WM_WINDOW_TYPE" "_NET_WM_WINDOW_TYPE_SPLASH" isRole = stringProperty "WM_WINDOW_ROLE" tileBelow = insertPosition Below Newer tileAbove = insertPosition Above Newer doVideoFloat = doFloatAbsRect 240 720 600 300 doCalendarFloat = customFloating (W.RationalRect (11 / 15) (1 / 48) (1 / 4) (1 / 8)) manageScratchpads = namedScratchpadManageHook scratchpads anyOf :: [Query Bool] -> Query Bool anyOf = foldl (<||>) (pure False) match :: [App] -> Query Bool match = anyOf . fmap isInstance manageApps = composeOne [ isInstance calendar -?> doCalendarFloat , match [ virtbox ] -?> tileAbove , match [ keepass , mpv ] -?> tileAbove , match [ audacious , eog , nautilus , office , pavuctrl , scr ] -?> doCenterFloat , match [ btm , evince , gimp ] -?> doFullFloat , resource =? "desktop_window" -?> doIgnore , resource =? "kdesktop" -?> doIgnore , anyOf [ isPopup ] -?> tileBelow , anyOf [ isFileChooserDialog , isDialog , isSplash , isBrowserDialog ] -?> doCenterFloat , isFullscreen -?> doFullFloat , pure True -?> tileBelow ]
isInstance (ClassApp c _) = className =? c isInstance (TitleApp t _) = title =? t isInstance (NameApp n _) = appName =? n
getNameCommand (ClassApp n c) = (n, c) getNameCommand (TitleApp n c) = (n, c) getNameCommand (NameApp n c) = (n, c)
getAppName = fst . getNameCommand getAppCommand = snd . getNameCommand
scratchpadApp :: App -> NamedScratchpad scratchpadApp app = NS (getAppName app) (getAppCommand app) (isInstance app) defaultFloating
runScratchpadApp = namedScratchpadAction scratchpads . getAppName
scratchpads = scratchpadApp <$> [ audacious, btm, nautilus, scr, gimp, mpv, virtbox ]
------------------------------------------------------------------------ -- Workspaces -- webWs = "web" mscWs = "msc" musWs = "mus" vscWs = "vsc" comWs = "com" spoWs = "spo" scdWs = "scd" devWs = "dev" secWs = "sec" vmsWs = "vms"
myWS :: [WorkspaceId] myWS = [webWs, mscWs, musWs, vscWs, comWs, spoWs, devWs, scdWs, secWs, vmsWs]
------------------------------------------------------------------------ -- Dynamic Projects -- projects :: [Project] projects = [ Project { projectName = webWs , projectDirectory = "~/plutus/workspace/webWs/" , projectStartHook = Just $ do spawn "brave" spawn "brave --app=https://youtube.com/" } , Project { projectName = mscWs , projectDirectory = "~/plutus/workspace/mscWs/" , projectStartHook = Just $ do spawn (terminalWithCommand "cowsay 'how are you today?'") } , Project { projectName = musWs , projectDirectory = "~/plutus/workspace/musWs/" , projectStartHook = Just $ do spawn "brave --app=https://music.youtube.com/" } , Project { projectName = vscWs , projectDirectory = "~/plutus/workspace/vscWs/nix-config.git/intelTower/" , projectStartHook = Just $ do spawn "codium -n ." spawn delayTerminal } , Project { projectName = comWs , projectDirectory = "~/plutus/workspace/comWs/" , projectStartHook = Just $ do spawn "brave --app=https://mastodon.social/" spawn "discord" spawn "telegram-desktop" spawn "signal-desktop" -- spawn "element-desktop" -- spawn "slack" } , Project { projectName = spoWs , projectDirectory = "~/plutus/workspace/spoWs/" , projectStartHook = Just $ do spawn (terminalWithCommand "systemctl status cardano-node") } , Project { projectName = devWs , projectDirectory = "~/plutus/workspace/devWs/" , projectStartHook = Just $ do spawn "codium -n ." spawn delayTerminal } , Project { projectName = scdWs , projectDirectory = "~/Cardano/git/" , projectStartHook = Just $ do spawn "codium -n ." spawn delayTerminal } , Project { projectName = secWs , projectDirectory = "~/plutus/workspace/secWs/" , projectStartHook = Just $ do spawn "keepassxc" } , Project { projectName = vmsWs , projectDirectory = "~/plutus/workspace/vmsWs/" , projectStartHook = Just $ runScratchpadApp virtbox } ]
projectsTheme :: XPConfig projectsTheme = amberXPConfig { bgHLight = "#002b36" , font = "xft:Bitstream Vera Sans Mono:size=8:antialias=true" , height = 60 , position = CenteredAt 0.5 0.5 }
------------------------------------------------------------------------ -- Event handling
-- * EwmhDesktops users should change this to ewmhDesktopsEventHook -- -- Defines a custom handler function for X Events. The function should -- return (All True) if the default handler is to be run afterwards. To -- combine event hooks use mappend or mconcat from Data.Monoid. -- -- NOTE: the (docks . ewmh . ewmhFullscreen) defined in main already overrides handleEventHook -- -- myEventHook = docksEventHook <+> ewmhDesktopsEventHook <+> fullscreenEventHook
------------------------------------------------------------------------ -- Status bars and logging
-- Perform an arbitrary action on each internal state change or X event. -- See the 'XMonad.Hooks.DynamicLog' extension for examples. --TODO: Add transparency on a per app basis --TODO: Add figure out how to make one window persistent using a keystroke myLogHook = fadeInactiveLogHook 1.0
and the custom Hue stuff:
module HueLighting ( nextLightCue , prevLightCue , cycleLightCue , runLightCue ) whereimport XMonad import XMonad.Util.Run import qualified XMonad.Util.ExtensibleState as XS
type LightCommand = String data HueCommand = HueCommand { lights :: [Int], commands :: [LightCommand] }
type LightZone = [Int]
{- Smart Lighting Hotkeys
Lights: 1. Window 1 (rest area) 2. Corner (rest area) 3. Closet (work area) 5. TV candle 2 (rest area) 6. Bed China Ball (rest area) 7. Chandelier 1 (Su) 8. Dresser Candle 1 (boundary) 9. Shelf Box 1 (rest area) 10. Chandelier 2 (Su) 12. Desk Light (Su) 14. Overhead Computers (work area) 16. Overhead Middle (boundary) 17. Guitars (work area) 18. Overhead Bed (rest area) 19. TV Candle 1 (rest area) 20. Window 2 (rest area) 21. TV Candle 3 (rest area) -}
-- A function to generate hue strings buildLightCommand :: HueCommand -> String buildLightCommand (HueCommand ls cmds) = concatMap buildCommands cmds where buildCommands cmd = unwords $ concatMap (\light -> ["hue light", show light, cmd, ";"]) ls
-- Chain multiple HueCommands chainCommands :: [HueCommand] -> String chainCommands = unwords . map buildLightCommand
-- Zones wholeRoom, restArea, boundary, workArea, suRoom:: LightZone wholeRoom = [1, 2, 3, 5, 6, 8, 9, 14, 16, 17, 18, 19, 20, 21] restArea = [1, 2, 5, 6, 9, 18, 19, 20, 21] boundary = [8, 16] workArea = [3, 14, 17] suRoom = [7, 10, 12]
-- Hue Lighting Cues blackOut :: String blackOut = chainCommands [ HueCommand wholeRoom ["off"]]
darkWarm = chainCommands [ HueCommand restArea ["off"] , HueCommand boundary ["off"] , HueCommand [17] [ "on", "brightness 28%", "color 2141" ] , HueCommand [3] [ "on", "color 2000", "brightness 100%" ] , HueCommand [14] [ "on", "color 2141", "brightness 10%" ] ] brightWarm = chainCommands [ HueCommand restArea ["relax", "brightness 50%" ] , HueCommand boundary [ "relax", "brightness 22%" ] , HueCommand [17] [ "on", "color 2141", "brightness 69%" ] , HueCommand [3] [ "on", "color 2141", "brightness 100%" ] , HueCommand [14] [ "on", "color 2141", "brightness 80%" ] ] basque = chainCommands [ HueCommand [1] [ "on", "brightness 155", "color 0.4247, 0.3421" ] , HueCommand [2] [ "on", "brightness 132", "color 0.4834, 0.3606" ] , HueCommand [3] [ "on", "brightness 155", "color 0.4129, 0.3416" ] , HueCommand [6] [ "on", "brightness 134", "color 0.414, 0.3905" ] , HueCommand [8] [ "on", "brightness 125", "color 0.4129, 0.3416" ] , HueCommand [5, 9, 14, 16, 18, 19] [ "on", "brightness 125", "color 0.5106, 0.3739" ] , HueCommand [17] [ "on", "brightness 156", "color 0.4834, 0.3606" ] , HueCommand [20] [ "on", "brightness 155", "color 0.413, 0.3415" ] , HueCommand [21] [ "on", "brightness 156", "color 0.4831, 0.3606" ] ]
fullWarm = chainCommands [ HueCommand wholeRoom ["relax"]]
darkCold = chainCommands [ HueCommand restArea ["off"] , HueCommand boundary ["off"] , HueCommand [17] ["on", "color 6200", "brightness 28%"] , HueCommand [3] ["on", "blue", "brightness 100%"] , HueCommand [14] ["on", "blue", "brightness 10%"] ] brightCold = chainCommands [ HueCommand restArea [ "on", "color 6500", "brightness 50%" ] , HueCommand boundary [ "on", "color 6500", "brightness 22%" ] , HueCommand [17] [ "on", "color 6500", "brightness 69%" ] , HueCommand [3] ["concentrate"] , HueCommand [14] [ "on", "color 6500", "brightness 80%" ] ] fullCold = chainCommands [ HueCommand wholeRoom ["concentrate"]] freakOut = chainCommands [ HueCommand restArea ["on", "blue", "brightness 80%" ] , HueCommand workArea ["on", "red", "brightness 80%" ] , HueCommand boundary ["on", "green", "brightness 80%", "blink" ] , HueCommand [2, 17] [ "on", "brightness 28%" ] , HueCommand [3] [ "on", "brightness 100%", "blink" ] , HueCommand [14] [ "on", "brightness 45%" ] ] deskOff = chainCommands [ HueCommand [17] ["off"]]
data LightingCue = DarkWarm | BrightWarm | Basque | FullWarm | DarkCold | BrightCold | FullCold | FreakOut | DeskOff | BlackOut deriving (Enum, Bounded, Show)
lightingCues :: [X ()] lightingCues = [ spawn darkWarm , spawn brightWarm , spawn basque , spawn fullWarm , spawn darkCold , spawn brightCold , spawn fullCold , spawn freakOut , spawn deskOff , spawn blackOut ]
nextLightCue, prevLightCue :: X () nextLightCue = cycleLightCue 1 prevLightCue = cycleLightCue (-1)
cycleLightCue :: Int -> X () cycleLightCue d = do LightCueIndex idx <- XS.get let n = length lightingCues newIndex = (idx + d)
mod
n (lightingCues !! newIndex) XS.put $ LightCueIndex newIndexrunLightCue :: Int -> X () runLightCue idx = do let n = length lightingCues newIndex = idx
mod
n (lightingCues !! newIndex) XS.put $ LightCueIndex newIndexnewtype LightCueState = LightCueIndex Int deriving Show instance ExtensionClass LightCueState where initialValue = LightCueIndex 0 ```