1 {-# LANGUAGE NamedFieldPuns #-}
2 {-# OPTIONS_GHC -Wall #-}
3 {-# OPTIONS_GHC -fno-warn-missing-signatures #-}
5 import qualified Data.Char as Char
6 import Data.List as List
9 import qualified Data.Map as Map
10 import Control.Arrow (first)
12 -- import XMonad.Actions.DwmPromote
13 -- import XMonad.Actions.Warp
14 -- import XMonad.Layout.Maximize
15 -- import XMonad.Layout.Monitor
16 -- import XMonad.Layout.ResizableTile
17 -- import XMonad.Layout.TabBarDecoration
18 -- import XMonad.Util.EZConfig
19 -- import XMonad.Util.EZConfig(additionalKeys)
20 -- import XMonad.Util.WorkspaceCompare
21 import XMonad hiding ((|||))
22 import XMonad.Actions.CopyWindow
23 import XMonad.Actions.CycleWS
24 import XMonad.Actions.SwapWorkspaces
25 import XMonad.Actions.UpdatePointer
26 import XMonad.Config.Azerty
27 import XMonad.Hooks.DynamicLog
28 import XMonad.Hooks.EwmhDesktops
29 import XMonad.Hooks.ManageDocks
30 import XMonad.Hooks.ManageHelpers
31 import XMonad.Hooks.Rescreen
32 import XMonad.Hooks.SetWMName
33 import XMonad.Hooks.StatusBar
34 import XMonad.Hooks.UrgencyHook
35 import XMonad.Layout.Columns
36 import XMonad.Layout.Fullscreen
37 import XMonad.Layout.Grid
38 import XMonad.Layout.LayoutCombinators
39 import XMonad.Layout.Magnifier
40 import XMonad.Layout.MultiToggle
41 import XMonad.Layout.MultiToggle.Instances
42 import XMonad.Layout.NoBorders
43 import XMonad.Layout.ResizableTile
44 import XMonad.Layout.Spiral
45 import XMonad.Layout.Tabbed
46 import XMonad.Layout.ThreeColumns
47 import XMonad.Layout.WindowNavigation
48 import XMonad.Operations (unGrab)
50 import XMonad.Prompt.FuzzyMatch
51 import XMonad.Prompt.Pass
52 import XMonad.Prompt.Window
53 import XMonad.Util.SpawnOnce
54 import qualified XMonad.StackSet as W
57 withUrgencyHook NoUrgencyHook $
58 -- dzenUrgencyHook { args = ["-bg", "darkgreen", "-xs", "1"] } $
59 --addAfterRescreenHook myAfterRescreenHook $
60 addRandrChangeHook (spawnExec "autorandr --change") $
61 dynamicSBs barSpawner $
63 setEwmhActivateHook doAskUrgent $
68 , focusFollowsMouse = True
69 , focusedBorderColor = "#00b10b"
70 , handleEventHook = handleEventHook def
71 , keys = \conf@XConfig{XMonad.modMask} ->
73 let xK_XF86Backward = 0x1008ff26
74 xK_XF86Forward = 0x1008ff27 in
77 ((modMask, xK_Return), spawnExec $ XMonad.terminal conf)
79 , ((modMask, xK_Menu), spawnCommand)
80 , ((modMask, xK_space), spawnCommand)
81 -- Browse the filesystem
82 , ((modMask, xK_BackSpace), spawnExec "systemd-run --user --unit=app-org.rofi.caja@$RANDOM -p CollectMode=inactive-or-failed caja")
85 , ((0, xK_Pause), unGrab >> spawnExec "loginctl lock-session \"$XDG_SESSION_ID\"")
86 , ((modMask, xK_Delete), unGrab >> spawnExec "loginctl lock-session \"$XDG_SESSION_ID\"")
88 -- Take a full screenshot
89 , ((0, xK_Print), spawn "mkdir -p ~/Images/screenshots && scrot --quality 42 ~/Images/screenshots/'%Y-%m-%d_%H-%M-%S.png' && caja ~/Images/screenshots")
90 -- Take a selective screenshot
91 , ((modMask, xK_Print), spawn "select-screenshot")
94 , ((0, 0x1008FF12), spawnExec "pactl -- set-sink-mute @DEFAULT_SINK@ toggle") -- XF88AudioMute
95 , ((0, 0x1008FF11), spawnExec "pactl -- set-sink-volume @DEFAULT_SINK@ -5%") -- XF86AudioLowerVolume
96 , ((0, 0x1008FF13), spawnExec "pactl -- set-sink-volume @DEFAULT_SINK@ +5%") -- XF86AudioRaiseVolume
98 -- , ((0, 0x1008FF16), spawnExec "")
100 -- , ((0, 0x1008FF14), spawnExec "")
102 -- , ((0, 0x1008FF17), spawnExec "")
104 -- , ((0, 0x1008FF2C), spawnExec "eject -T")
106 -- Close focused window.
107 , ((modMask, xK_Escape), kill)
110 , ((modMask, xK_c), spawnExec "clipster --select --primary")
112 -- Temporarily maximize a window
113 , ((modMask, xK_f), sendMessage $ XMonad.Layout.MultiToggle.Toggle FULL)
114 -- , ((modMask, xK_f), withFocused (sendMessage . maximizeRestore))
116 -- Cycle through the available layout algorithms
117 , ((modMask, 0x13bd), sendMessage NextLayout) -- oe (²)
118 , ((modMask, xK_ampersand), sendMessage $ JumpToLayout "ResizableTall") -- & (1)
119 , ((modMask, xK_eacute), sendMessage $ JumpToLayout "Mirror ResizableTall") -- é (2)
120 , ((modMask, xK_quotedbl), sendMessage $ JumpToLayout "Tabbed Simplest") -- ' (3)
121 , ((modMask, xK_apostrophe), sendMessage $ JumpToLayout "Magnifier Grid") -- " (4)
122 , ((modMask, xK_parenleft), sendMessage $ JumpToLayout "Spiral") -- ( (5)
123 , ((modMask, xK_minus), sendMessage $ JumpToLayout "Full") -- - (6)
124 , ((modMask, xK_egrave), sendMessage $ JumpToLayout "ThreeCol") -- è (7)
125 , ((modMask, xK_underscore), sendMessage $ JumpToLayout "Columns") -- _ (8)
127 -- Reset the layouts on the current workspace to default
128 -- , ((modMask .|. shiftMask, xK_space), setLayout $ XMonad.layoutHook conf)
130 -- Resize viewed windows to the correct size.
131 , ((modMask, xK_n), refresh)
133 -- Move focus to the master window
134 , ((modMask .|. shiftMask, xK_exclam), windows W.focusMaster)
135 -- Swap the focused window and the master window
136 , ((modMask, xK_exclam), windows W.swapMaster)
138 -- Swap the focused window with the next window.
139 --, ((modMask, xK_o), windows W.swapDown >> windows W.focusMaster)
140 -- Swap the focused window with the previous window.
141 , ((modMask, xK_m), windows W.swapUp >> windows W.focusMaster)
144 , ((modMask, xK_h), sendMessage $ Go L)
145 , ((modMask, xK_m), sendMessage $ Go R)
146 --, ((modMask, xK_i), sendMessage $ Go U)
147 --, ((modMask, xK_k), sendMessage $ Go D)
148 , ((modMask, xK_i), windows W.focusUp)
149 , ((modMask, xK_k), windows W.focusDown)
150 , ((modMask, xK_j), prevWS)
151 , ((modMask, xK_l), nextWS)
152 , ((modMask, xK_Left), windows W.focusUp)
153 , ((modMask, xK_Right), windows W.focusDown)
154 --, ((modMask, xK_Left), onGroup W.focusUp')
155 --, ((modMask, xK_Right), onGroup W.focusDown')
156 , ((modMask, xK_Up), sendMessage $ Go U)
157 , ((modMask, xK_Down), sendMessage $ Go D)
160 , ((modMask .|. shiftMask, xK_h), sendMessage MoveLeft)
161 , ((modMask .|. shiftMask, xK_m), sendMessage MoveRight)
162 , ((modMask .|. controlMask, xK_h), sendMessage MoveLeft)
163 , ((modMask .|. controlMask, xK_m), sendMessage MoveRight)
164 , ((modMask .|. controlMask, xK_i), sendMessage MoveUp)
165 , ((modMask .|. controlMask, xK_k), sendMessage MoveDown)
166 , ((modMask .|. controlMask, xK_j), shiftToPrev >> prevWS)
167 , ((modMask .|. controlMask, xK_l), shiftToNext >> nextWS)
170 , ((modMask .|. shiftMask, xK_l), sendMessage HorizontalExpand)
171 , ((modMask .|. shiftMask, xK_j), sendMessage HorizontalShrink)
172 , ((modMask .|. shiftMask, xK_i), sendMessage VerticalExpand)
173 , ((modMask .|. shiftMask, xK_k), sendMessage VerticalShrink)
175 -- Push window back into tiling.
176 , ((modMask, xK_t), withFocused $ windows . W.sink)
178 -- Change the number of windows in the master area
179 , ((modMask, xK_Up), sendMessage $ IncMasterN 1)
180 , ((modMask, xK_Down), sendMessage $ IncMasterN (-1))
182 -- Toggle the status bar gap.
183 , ((modMask, xK_b), sendMessage ToggleStruts)
186 , ((modMask .|. shiftMask, xK_End), io exitSuccess)
188 , ((modMask, xK_End), restart "xmonad" True)
190 , ((modMask, xK_p), passPrompt promptConfig)
191 , ((modMask .|. controlMask, xK_p), passGeneratePrompt promptConfig)
192 , ((modMask .|. controlMask .|. shiftMask, xK_p), passRemovePrompt promptConfig)
193 , ((modMask, xK_Tab), windowMultiPrompt promptConfig [(Goto, allWindows), (Goto, wsWindows)])
195 -- Workspace management
196 -- XF86Back: Switch to previous workspace
197 , ((0, xK_XF86Backward), prevWS)
198 , ((modMask, xK_Page_Up), prevWS)
199 -- Switch to next workspace
200 , ((0, xK_XF86Forward), nextWS)
201 , ((modMask, xK_Page_Down), nextWS)
202 -- XF86Back: Move the current client to the previous workspace and go there
203 , ((modMask, xK_XF86Backward), shiftToPrev >> prevWS)
204 -- Move the current client to the next workspace and go there
205 , ((modMask, xK_XF86Forward), shiftToNext >> nextWS)
206 -- Switch to previous workspace
207 -- Switch to next workspace
209 -- Move the current client to the previous workspace
210 , ((0 .|. shiftMask , xK_XF86Backward), shiftToPrev )
211 -- Move the current client to the next workspace
212 , ((0 .|. shiftMask , xK_XF86Forward), shiftToNext )
215 -- Toggle copying window on all workspaces (sticky window)
216 , ((modMask, xK_s), do
217 copies <- wsContainingCopies -- NOTE: consider only hidden workspaces
219 [] -> windows copyToAll
220 _ -> killAllOtherCopies
223 -- Resize the master area
224 --, ((modMask, xK_Left), sendMessage Shrink)
225 --, ((modMask, xK_Right), sendMessage Expand)
226 -- Resize windows in ResizableTall mode
227 --, ((modMask .|. shiftMask, xK_Left), sendMessage MirrorShrink)
228 --, ((modMask .|. shiftMask, xK_Right), sendMessage MirrorExpand)
231 -- mod-[F1..F9], Switch to workspace N
232 -- mod-shift-[F1..F9], Move client to workspace N
233 [ ((m .|. modMask, k), windows $ f i)
234 | (i, k) <- zip (workspaces conf) [xK_F1 ..] ++
235 zip (workspaces conf) [xK_1 ..]
236 , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]
238 {- NOTE: with Xinerama
239 [((m .|. modMask, k), windows $ onCurrentScreen f i)
240 | (i, k) <- zip (workspaces' conf) [xK_F1 ..]
241 , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)] ]
244 -- mod-{w,e,r}, Switch to physical/Xinerama screens 1, 2, or 3
245 -- mod-shift-{w,e,r}, Move client to screen 1, 2, or 3
246 [ ((m .|. modMask, key), screenWorkspace sc >>= flip whenJust (windows . f))
247 | (key, sc) <- zip [xK_w, xK_e, xK_r] [0 ..]
248 , (f, m) <- [(W.view, 0), (W.shift, shiftMask)]
251 -- mod-shift-[F1..F9], Swap workspace with workspace N
252 -- mod-shift-[1..9], Swap workspace with workspace N
253 [ ((modMask .|. controlMask, k), windows $ swapWithCurrent i)
254 | (i, k) <- zip (workspaces conf) [xK_F1 ..] ++
255 zip (workspaces conf) [xK_1 ..]
257 {- NOTE: with Xinerama
258 [((modMask .|. controlMask, k), windows $ onCurrentScreen swapWithCurrent i)
259 | (i, k) <- zip (workspaces' conf) [xK_F1 ..] ]
261 , layoutHook = smartBorders $
262 mkToggle (NOBORDERS ?? FULL ?? EOT) $ -- enable temporarily maximizing a window
263 avoidStruts $ -- prevents windows from overlapping dock windows
264 let tall = ResizableTall 1 (1%200) (8%13) [] in
266 -- addTabs shrinkText tabBar (subLayout [] Simplest (Columns 1 []))
268 ||| tabbed shrinkText tabConfig
271 ||| magnifiercz (13%10) Grid
273 ||| noBorders (fullscreenFull Full)
274 ||| ThreeColMid 1 (1%200) (1%2)
275 -- ||| Tall 1 (3/100) (1/2)
276 , manageHook = composeAll
277 -- [ , isFullscreen --> (doF W.focusDown <+> doFullFloat)
278 [ isFullscreen --> doFullFloat
280 , manageDocks -- NOTE: do not tile dock windows
281 , resource =? "desktop_window" --> doIgnore
282 , className =? "Gimp" --> doFloat
283 , resource =? "gpicview" --> doSink
284 , className =? "mpv" --> doFloat
285 , className =? "ultrastardx" --> doSink
286 --, className =? "MPlayer" --> doShift "3:media" -- <+> doFloat
287 --, className =? "vlc" --> doShift "3:media"
288 , className =? "trayer" --> doIgnore
291 , mouseBindings = \XConfig{XMonad.modMask} ->
294 -- mod-button1, Set the window to floating mode and move by dragging
295 ((modMask, button1), \w -> focus w >> mouseMoveWindow w)
297 -- mod-button2, Raise the window to the top of the stack
298 , ((modMask, button2), \w -> focus w >> windows W.swapMaster)
300 -- mod-button3, Set the window to floating mode and resize by dragging
301 , ((modMask, button3), \w -> focus w >> mouseResizeWindow w)
303 , ((modMask, button4), \_ -> windows W.focusUp)
304 , ((modMask, button5), \_ -> windows W.focusDown)
306 -- Cycle through workspaces
307 , ((controlMask .|. modMask, button5), nextNonEmptyWS)
308 , ((controlMask .|. modMask, button4), prevNonEmptyWS)
310 , normalBorderColor = "#7C7C7C"
311 , startupHook = setWMName "XMonad"
312 <+> spawnExec "wmname XMonad"
313 <+> spawnExec "xrdb -all .Xresources"
314 <+> spawn "sleep 1 && xmodmap .Xmodmap"
315 <+> spawnExec "xset r rate 250 25"
316 <+> spawnExec "xinput --set-button-map 'Logitech USB Receiver Mouse' 1 2 3 4 5 6 7 2"
317 <+> spawnExec "xset b off"
318 <+> spawnExec "xhost local:root"
319 <+> spawnExec "setxkbmap -option keypad:pointerkeys"
320 -- Useful for programs launched by rofi
321 <+> spawnExec (unwords [ "systemctl --user import-environment"
322 , "DBUS_SESSION_BUS_ADDRESS"
323 , "GDK_PIXBUF_MODULE_FILE"
324 , "GIO_EXTRA_MODULES"
332 , "LD_LIBRARY_PATH" -- For sane and pipewire
334 , "NIX_PROFILES" -- fcitx5 does not work without it…
335 , "PASSWORD_STORE_DIR"
337 , "QTWEBKIT_PLUGIN_PATH"
345 -- <+> spawnOnce "exec arbtt-capture -r 60"
346 -- <+> spawnOnce "exec parcellite"
347 -- <+> spawnOnce "exec xautolock"
348 -- <+> spawnOnce "exec redshift-gtk -l -45.7800:1.9700 -t 6500:3700"
349 <+> spawnOnce "exec nm-applet"
350 , terminal = "urxvtc"
351 , workspaces = {- withScreens nScreens $ -}
352 {-["1:work","2:web","3:media"] ++-}
353 map show [1::Int .. 9]
354 , logHook = updatePointer (0.5, 0.5) (0, 0)
355 -- >> updatePointer (Relative 0.5 0.5)
359 { activeBorderColor = "#7C7C7C"
360 , activeColor = "#000000"
361 , activeTextColor = "#00FF00"
362 , inactiveBorderColor = "#7C7C7C"
363 , inactiveColor = "#000000"
364 , inactiveTextColor = "#EEEEEE"
365 , fontName = "Hack 7"
368 spawnCommand = 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}'\""
370 barSpawner :: ScreenId -> X StatusBarConfig
371 barSpawner 0 = pure $ topXmobar <> traySB
372 --barSpawner 1 = pure $ xmobar1
373 barSpawner _ = pure $ topXmobar -- nothing on the rest of the screens
375 -- Display properties of the root window:
376 -- xprop -display $DISPLAY -root
377 topXmobar = statusBarPropTo "_XMONAD_XMOBAR0" "xmobar -x 0 ~/.config/xmonad/xmobar0.hs" (pure topPP)
381 { ppCurrent = xmobarColor "black" "#CCCCCC"
382 , ppHidden = xmobarColor "#CCCCCC" "black"
383 , ppHiddenNoWindows = xmobarColor "#606060" "black"
384 , ppLayout = \s -> xmobarColor "black" "#606060" $
387 "ResizableTall" -> " | "
388 "Mirror ResizableTall" -> " - "
389 "Tabbed Simplest" -> " + "
390 "Magnifier Grid" -> " ~ "
396 , ppTitle = xmobarColor "white" "black" . shorten 50
397 , ppUrgent = xmobarColor "yellow" "black"
401 traySB :: StatusBarConfig
408 , "--distancefrom top,right"
412 , "--monitor primary"
415 , "--transparent true"
416 , "--widthtype request"
422 nextNonEmptyWS _ = moveTo Next (WSIs ((not .) <$> isWindowSpaceVisible))
423 prevNonEmptyWS _ = moveTo Prev (WSIs ((not .) <$> isWindowSpaceVisible))
425 isWindowSpaceVisible :: X (WindowSpace -> Bool)
426 isWindowSpaceVisible = do
427 vs <- gets (map (W.tag . W.workspace) . W.visible . windowset)
428 return (\w -> W.tag w `elem` vs)
430 spawnExec s = spawn $ List.unwords $ [ "exec" ] <> systemdCat <> [ s ]
431 systemdCat = [ "systemd-cat" , "--priority=info", "--stderr-priority=warning", "--level-prefix=false" , "--" ]
433 promptConfig :: XPConfig
435 { font = "xft:monospace-"<>show fontSize
439 , fgHLight = "#000000"
440 , borderColor = "darkgreen"
441 , promptBorderWidth = 1
442 , promptKeymap = promptKeyMap
443 , position = CenteredAt { xpCenterY = 0.3, xpWidth = 0.5 }
444 , height = fontSize + 11
448 , autoComplete = Nothing -- Just 500000 -- nanoseconds
449 , showCompletionOnTab = False
450 , completionKey = (0, xK_Down)
451 , prevCompletionKey = (0, xK_Up)
452 , searchPredicate = fuzzyMatch -- isPrefixOf
454 , defaultPrompter = const ""
455 , alwaysHighlight = True
456 , maxComplRows = Just 10
457 , maxComplColumns = Just 1
458 , changeModeKey = xK_twosuperior
463 promptKeyMap :: Map.Map (KeyMask,KeySym) (XP ())
464 promptKeyMap = Map.fromList $
465 List.map (first $ (,) controlMask) -- control + <key>
466 [ (xK_z, killBefore) -- kill line backwards
467 , (xK_k, killAfter) -- kill line forwards
468 , (xK_u, killBefore) -- kill line backwards
469 , (xK_a, startOfLine) -- move to the beginning of the line
470 , (xK_e, endOfLine) -- move to the end of the line
471 , (xK_m, deleteString Next) -- delete a character foward
472 , (xK_b, moveCursor Prev) -- move cursor forward
473 , (xK_f, moveCursor Next) -- move cursor backward
474 , (xK_BackSpace, killWord Prev) -- kill the previous word
475 , (xK_y, pasteString) -- paste a string
476 , (xK_g, quit) -- quit out of prompt
477 , (xK_bracketleft, quit)
480 List.map (first $ (,) altMask) -- meta key + <key>
481 [ (xK_BackSpace, killWord Prev) -- kill the prev word
482 , (xK_f, moveWord Next) -- move a word forward
483 , (xK_b, moveWord Prev) -- move a word backward
484 , (xK_d, killWord Next) -- kill the next word
485 , (xK_n, moveHistory W.focusUp') -- move up through history
486 , (xK_p, moveHistory W.focusDown') -- move down through history
489 List.map (first $ (,) 0) -- <key>
490 [ (xK_Return, setSuccess True >> setDone True)
491 , (xK_KP_Enter, setSuccess True >> setDone True)
492 , (xK_BackSpace, deleteString Prev)
493 , (xK_Delete, deleteString Next)
494 , (xK_Left, moveCursor Prev)
495 , (xK_Right, moveCursor Next)
496 , (xK_Home, startOfLine)
497 , (xK_End, endOfLine)
498 , (xK_Down, moveHistory W.focusUp')
499 , (xK_Up, moveHistory W.focusDown')