nix-configs/haskell/xmonad/xmonad.hs
2023-12-06 02:30:39 +01:00

223 lines
8.8 KiB
Haskell

import Control.Monad (when)
import Data.Map qualified as M
import Data.Monoid
import Data.Ratio
import Graphics.X11.ExtraTypes.XF86
import System.Exit
import XMonad
import XMonad.Actions.KeyRemap
import XMonad.Hooks.EwmhDesktops
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.StatusBar
import XMonad.Hooks.StatusBar.PP
import XMonad.Layout.Circle
import XMonad.Layout.DraggingVisualizer
import XMonad.Layout.Grid
import XMonad.Layout.IfMax
import XMonad.Layout.Magnifier
import XMonad.Layout.Spacing
import XMonad.Layout.Tabbed
import XMonad.Layout.ThreeColumns
import XMonad.Layout.VoidBorders
import XMonad.Layout.WindowSwitcherDecoration
import XMonad.Prompt
import XMonad.Prompt.Layout
import XMonad.StackSet qualified as W
import XMonad.Actions.NoBorders
myKeys conf@(XConfig {XMonad.modMask = modm}) =
M.fromList $
[ ((modm, xK_Return), spawn $ XMonad.terminal conf),
((modm .|. shiftMask, xK_q), kill),
-- -- Rotate through the available layout algorithms
((modm, xK_space), sendMessage NextLayout),
-- rofiing
((modm, xK_d), spawn "rofi -show drun"),
((modm .|. shiftMask, xK_e), spawn "rofi -show desktopctl -modes desktopctl:desktopctl -show-icons"),
((modm, xK_m), spawn "menu-qalc -- -theme gruvbox-dark"),
((modm, xK_i), spawn "rofimoji --selector-args '-theme gruvbox-dark' -f alchemical_symbols anatolian_hieroglyphs emojis braille_patterns box_drawing chess_symbols emoticons geometric_shapes gothic greek_extended math mathematical_alphanumeric_symbols mathematical_operators miscellaneous_symbols miscellaneous_mathematical_symbols-a miscellaneous_mathematical_symbols-b miscellaneous_symbols_and_arrows miscellaneous_symbols_and_pictographs miscellaneous_technical modi modifier_tone_letters musical_symbols nerd_font number_forms shorthand_format_controls specials variation_selectors vertical_forms -a copy"),
-- screenshotting
-- TODO: Fix/rewrite window-screenshot
((modm, xK_w), spawn "window-screenshot.nu"),
((modm, xK_s), spawn "flameshot gui -c -p $HOME/Pictures/screenshots"),
((modm, xK_a), spawn "flameshot screen -c -p $HOME/Pictures/screenshots"),
((modm, xK_t), spawn "ocr-screenshot.sh"),
((modm .|. shiftMask, xK_t), spawn "DEVICE=\"MELF0410:00 1FD2:7007\"; if [ $(xinput list-props \"$DEVICE\" | awk '/^\\tDevice Enabled \\([0-9]+\\):\\t[01]/ {print $NF}') = \"1\" ]; then xinput disable \"$DEVICE\"; else xinput enable \"$DEVICE\"; fi"),
-- Push window back into tiling
((modm .|. shiftMask, xK_space), withFocused $ windows . W.sink),
-- Resize viewed windows to the correct size
((modm, xK_n), refresh),
-- Move focus to the next window
((modm, xK_Tab), layoutPrompt def),
-- Move focus
((modm, xK_j), windows W.focusDown),
((modm, xK_k), windows W.focusUp),
-- Swap the focused window with the next window
((modm .|. shiftMask, xK_j), windows W.swapDown),
((modm .|. shiftMask, xK_k), windows W.swapUp),
-- Shrink the master area
((modm, xK_h), sendMessage Shrink),
((modm, xK_l), sendMessage Expand),
-- Increment the number of windows in the master area
((modm, xK_comma), sendMessage (IncMasterN 1)),
((modm, xK_period), sendMessage (IncMasterN (-1))),
((modm, xK_b), sendMessage ToggleStruts >> withFocused toggleBorder),
-- volume keys
-- TODO: other media keys
((0, xF86XK_AudioRaiseVolume), spawn "amixer -D pulse sset Master 10%+"),
((0, xF86XK_AudioLowerVolume), spawn "amixer -D pulse sset Master 10%-"),
((0, xF86XK_AudioMute), spawn "amixer -D pulse sset Master toggle")
]
++ [ ((m .|. modm, k), windows $ f i)
| (i, k) <- zip (XMonad.workspaces conf) [xK_1 .. xK_9],
(f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]
]
-- TODO: figure out multi screen stuff, including xinerama
-- 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 -> do
focus w
mouseMoveWindow w
windows W.shiftMaster
),
-- mod-button2, Raise the window to the top of the stack
( (modm, button3),
\w -> do
focus w
mouseResizeWindow w
windows W.shiftMaster
)
]
------------------------------------------------------------------------
-- 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.
tabCfg =
def
{ activeColor = "#282828",
inactiveColor = "#1d2021",
urgentColor = "#9d0006",
activeBorderColor = "#504945",
inactiveBorderColor = "#3c3836",
urgentBorderColor = "#cc241d",
activeTextColor = "#ebdbb2",
inactiveTextColor = "#bdae93",
urgentTextColor = "#ebdbb2"
}
myLayout = avoidStruts $ autoChoose ||| threeCol ||| tiled ||| tabbed shrinkText tabCfg ||| Mirror tiled
where
-- default tiling algorithm partitions the screen into two panes
autoChoose = IfMax 2 tiled $ IfMax 3 tiled_mag $ IfMax 4 Grid threeCol
tiled = Tall nmaster delta ratio
tiled_mag = magnifiercz' 1.4 tiled
threeCol = magnifiercz' 1.6 $ ThreeColMid nmaster delta ratio
-- The default number of windows in the master pane
nmaster = 1
-- Default proportion of screen occupied by master pane
ratio = 1 / 2
-- Percent of screen to increment by when resizing panes
delta = 3 / 100
myManageHook =
composeAll
[ className =? "MPlayer" --> doFloat,
className =? "Gimp" --> doFloat,
className =? "firefox" --> doShift "browser",
className =? "Evolution" --> doShift "comms",
className =? "Signal" --> doShift "comms",
className =? "SchildiChat" --> doShift "comms",
resource =? "desktop_window" --> doIgnore,
resource =? "kdesktop" --> doIgnore
]
------------------------------------------------------------------------
-- 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.
--
myEventHook = mempty
focusChangeHook (FocusChangeEvent {ev_event_type = t, ev_window = window}) = do
when (t == focusIn) $ spawn "notify-send 'focusIn'"
when (t == focusOut) $ spawn "notify-send 'focusOut'"
return $ All True
------------------------------------------------------------------------
-- Status bars and logging
-- Perform an arbitrary action on each internal state change or X event.
-- See the 'XMonad.Hooks.DynamicLog' extension for examples.
--
myLogHook = return ()
------------------------------------------------------------------------
-- Startup hook
-- 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.
--
-- By default, do nothing.
myStartupHook = do
spawn "pgrep oneko || oneko -tofocus -tora -position +-1+5 -fg palevioletred3 -bg pink -name 'Rose the desktop kitty'"
spawn "pgrep volumeicon || volumeicon"
spawn "pgrep nm-applet || nm-applet"
spawn "pgrep mullvad-gui || mullvad-vpn"
spawn "feh --bg-fill ~/Pictures/wallpaper.jpg"
------------------------------------------------------------------------
-- Now run xmonad with all the defaults we set up.
-- Run xmonad with the settings you specify. No need to modify this.
--
mySB = statusBarProp "polybar" (pure xmobarPP)
main = xmonad $ docks $ withSB mySB (ewmh defaults)
-- A structure containing your configuration settings, overriding
-- fields in the default config. Any you don't override, will
-- use the defaults defined in xmonad/XMonad/Config.hs
--
-- No need to modify this.
--
defaults =
def
{ -- simple stuff
terminal = "kitty",
focusFollowsMouse = False,
clickJustFocuses = False,
borderWidth = 2,
modMask = mod4Mask,
workspaces = ["comms", "browser"] ++ map show [3 .. 9],
normalBorderColor = "#3c3836",
focusedBorderColor = "#504945",
-- , clientMask = focusChangeMask .|. XMonad.clientMask
-- key bindings
keys = myKeys,
mouseBindings = myMouseBindings,
-- hooks, layouts
layoutHook = spacingRaw True (Border 0 0 0 0) True (Border 7 7 7 7) True myLayout,
manageHook = myManageHook,
handleEventHook = myEventHook,
logHook = myLogHook,
startupHook = myStartupHook
}