]> Git — Sourcephile - julm/julm-nix.git/blob - home-manager/profiles/xmonad/xmonad.hs
xmonad: add more key bindings
[julm/julm-nix.git] / home-manager / profiles / xmonad / xmonad.hs
1 {-# LANGUAGE NamedFieldPuns #-}
2 {-# OPTIONS_GHC -Wall #-}
3 {-# OPTIONS_GHC -fno-warn-missing-signatures #-}
4 import Data.Default
5 import qualified Data.Char as Char
6 import Data.List as List
7 import Data.Ratio
8 import System.Exit
9 import qualified Data.Map as Map
10 import Control.Arrow (first)
11
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.Fullscreen
36 import XMonad.Layout.Grid
37 import XMonad.Layout.LayoutCombinators
38 import XMonad.Layout.Magnifier
39 import XMonad.Layout.MultiToggle
40 import XMonad.Layout.MultiToggle.Instances
41 import XMonad.Layout.NoBorders
42 import XMonad.Layout.ResizableTile
43 import XMonad.Layout.Spiral
44 import XMonad.Layout.Tabbed
45 import XMonad.Layout.ThreeColumns
46 import XMonad.Prompt
47 import XMonad.Prompt.FuzzyMatch
48 import XMonad.Prompt.Pass
49 --import XMonad.Operations (unGrab) -- TODO: needs xmonad 0.18
50 import XMonad.Util.SpawnOnce
51 import qualified XMonad.StackSet as W
52
53 main = xmonad $
54 withUrgencyHook NoUrgencyHook $
55 -- dzenUrgencyHook { args = ["-bg", "darkgreen", "-xs", "1"] } $
56 --addAfterRescreenHook myAfterRescreenHook $
57 addRandrChangeHook (spawnExec "autorandr --change") $
58 dynamicSBs barSpawner $
59 docks $
60 setEwmhActivateHook doAskUrgent $
61 ewmhFullscreen $
62 ewmh $
63 azertyConfig
64 { borderWidth = 1
65 , focusFollowsMouse = True
66 , focusedBorderColor = "#00b10b"
67 , handleEventHook = handleEventHook def
68 , keys = \conf@XConfig{XMonad.modMask} ->
69 Map.fromList $
70 let xK_XF86Backward = 0x1008ff26
71 xK_XF86Forward = 0x1008ff27 in
72 [
73 -- Start a terminal
74 ((modMask, xK_Return), spawnExec $ XMonad.terminal conf)
75 -- Launch a program
76 , ((modMask, xK_Menu), spawnCommand)
77 , ((modMask, xK_a), spawnCommand)
78 -- Browse the filesystem
79 , ((modMask, xK_BackSpace), spawnExec "systemd-run --user --unit=app-org.rofi.caja@$RANDOM -p CollectMode=inactive-or-failed caja")
80
81 -- Lock the screen
82 , ((0, xK_Pause), {-unGrab >>-} spawnExec "loginctl lock-session \"$XDG_SESSION_ID\"")
83 , ((modMask, xK_Delete), {-unGrab >>-} spawnExec "loginctl lock-session \"$XDG_SESSION_ID\"")
84
85 -- Take a full screenshot
86 , ((0, xK_Print), spawn "mkdir -p ~/Images/screenshots && scrot --quality 42 ~/Images/screenshots/'%Y-%m-%d_%H-%M-%S.png' && caja ~/Images/screenshots")
87 -- Take a selective screenshot
88 , ((modMask, xK_Print), spawn "select-screenshot")
89
90 -- Volume control
91 , ((0, 0x1008FF12), spawnExec "pactl -- set-sink-mute @DEFAULT_SINK@ toggle") -- XF88AudioMute
92 , ((0, 0x1008FF11), spawnExec "pactl -- set-sink-volume @DEFAULT_SINK@ -5%") -- XF86AudioLowerVolume
93 , ((0, 0x1008FF13), spawnExec "pactl -- set-sink-volume @DEFAULT_SINK@ +5%") -- XF86AudioRaiseVolume
94 -- Audio previous
95 -- , ((0, 0x1008FF16), spawnExec "")
96 -- Play/pause
97 -- , ((0, 0x1008FF14), spawnExec "")
98 -- Audio next
99 -- , ((0, 0x1008FF17), spawnExec "")
100 -- Eject CD tray
101 -- , ((0, 0x1008FF2C), spawnExec "eject -T")
102
103 -- Close focused window.
104 , ((modMask, xK_Escape), kill)
105 , ((modMask, xK_q), kill)
106
107 -- Clipboard
108 , ((modMask, xK_c), spawnExec "clipster --select --primary")
109
110 -- Temporarily maximize a window
111 , ((modMask, xK_f), sendMessage $ XMonad.Layout.MultiToggle.Toggle FULL)
112 -- , ((modMask, xK_f), withFocused (sendMessage . maximizeRestore))
113
114 -- Cycle through the available layout algorithms
115 , ((modMask, 0x13bd), sendMessage NextLayout) -- oe (²)
116 , ((modMask, xK_ampersand), sendMessage $ JumpToLayout "ResizableTall") -- & (1)
117 , ((modMask, xK_eacute), sendMessage $ JumpToLayout "Mirror ResizableTall") -- é (2)
118 , ((modMask, xK_quotedbl), sendMessage $ JumpToLayout "Tabbed Simplest") -- ' (3)
119 , ((modMask, xK_apostrophe), sendMessage $ JumpToLayout "Magnifier Grid") -- " (4)
120 , ((modMask, xK_parenleft), sendMessage $ JumpToLayout "Spiral") -- ( (5)
121 , ((modMask, xK_minus), sendMessage $ JumpToLayout "Full") -- - (6)
122 , ((modMask, xK_egrave), sendMessage $ JumpToLayout "ThreeCol") -- è (7)
123
124 -- Reset the layouts on the current workspace to default
125 -- , ((modMask .|. shiftMask, xK_space), setLayout $ XMonad.layoutHook conf)
126
127 -- Resize viewed windows to the correct size.
128 , ((modMask, xK_n), refresh)
129
130 -- Move focus between windows
131 , ((modMask, xK_Tab), windows W.focusDown)
132 , ((modMask .|. shiftMask, xK_Tab), windows W.focusUp)
133 , ((modMask, xK_i), windows W.focusUp)
134 , ((modMask, xK_k), windows W.focusDown)
135
136 -- Move focus to the master window
137 , ((modMask, xK_m), windows W.focusMaster)
138 -- Swap the focused window and the master window
139 , ((modMask, xK_space), windows W.swapMaster)
140
141 -- Swap the focused window with the next window.
142 --, ((modMask, xK_o), windows W.swapDown >> windows W.focusMaster)
143 -- Swap the focused window with the previous window.
144 , ((modMask, xK_m), windows W.swapUp >> windows W.focusMaster)
145
146 -- Push window back into tiling.
147 , ((modMask, xK_t), withFocused $ windows . W.sink)
148
149 -- Change the number of windows in the master area
150 , ((modMask, xK_Up), sendMessage $ IncMasterN 1)
151 , ((modMask, xK_Down), sendMessage $ IncMasterN (-1))
152
153 -- Toggle the status bar gap.
154 , ((modMask, xK_b), sendMessage ToggleStruts)
155
156 -- Quit xmonad
157 , ((modMask .|. shiftMask, xK_End), io exitSuccess)
158 -- Restart xmonad
159 , ((modMask, xK_End), restart "xmonad" True)
160
161 , ((modMask, xK_p), passPrompt dtXPConfig)
162 , ((modMask .|. controlMask, xK_p), passGeneratePrompt dtXPConfig)
163 , ((modMask .|. controlMask .|. shiftMask, xK_p), passRemovePrompt dtXPConfig)
164
165 -- Workspace management
166 -- XF86Back: Switch to previous workspace
167 , ((0, xK_XF86Backward), prevWS)
168 , ((modMask, xK_j), prevWS)
169 -- Switch to next workspace
170 , ((0, xK_XF86Forward), nextWS)
171 , ((modMask, xK_l), nextWS)
172 -- XF86Back: Move the current client to the previous workspace and go there
173 , ((modMask, xK_XF86Backward), shiftToPrev >> prevWS)
174 , ((modMask .|. shiftMask, xK_j), shiftToPrev >> prevWS)
175 -- Move the current client to the next workspace and go there
176 , ((modMask, xK_XF86Forward), shiftToNext >> nextWS)
177 , ((modMask .|. shiftMask, xK_l), shiftToNext >> nextWS)
178 -- Switch to previous workspace
179 -- Switch to next workspace
180 {-
181 -- Move the current client to the previous workspace
182 , ((0 .|. shiftMask , xK_XF86Backward), shiftToPrev )
183 -- Move the current client to the next workspace
184 , ((0 .|. shiftMask , xK_XF86Forward), shiftToNext )
185 -}
186
187 -- Toggle copying window on all workspaces (sticky window)
188 , ((modMask, xK_s), do
189 copies <- wsContainingCopies -- NOTE: consider only hidden workspaces
190 case copies of
191 [] -> windows copyToAll
192 _ -> killAllOtherCopies
193 )
194
195 -- Resize the master area
196 , ((modMask, xK_Left), sendMessage Shrink)
197 , ((modMask, xK_Right), sendMessage Expand)
198 -- Resize windows in ResizableTall mode
199 , ((modMask .|. shiftMask, xK_Left), sendMessage MirrorShrink)
200 , ((modMask .|. shiftMask, xK_Right), sendMessage MirrorExpand)
201 ] ++
202
203 -- mod-[F1..F9], Switch to workspace N
204 -- mod-shift-[F1..F9], Move client to workspace N
205 [ ((m .|. modMask, k), windows $ f i)
206 | (i, k) <- zip (workspaces conf) [xK_F1 ..] ++
207 zip (workspaces conf) [xK_1 ..]
208 , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]
209 ] ++
210 {- NOTE: with Xinerama
211 [((m .|. modMask, k), windows $ onCurrentScreen f i)
212 | (i, k) <- zip (workspaces' conf) [xK_F1 ..]
213 , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)] ]
214 -}
215
216 -- mod-{w,e,r}, Switch to physical/Xinerama screens 1, 2, or 3
217 -- mod-shift-{w,e,r}, Move client to screen 1, 2, or 3
218 [ ((m .|. modMask, key), screenWorkspace sc >>= flip whenJust (windows . f))
219 | (key, sc) <- zip [xK_w, xK_e, xK_r] [0 ..]
220 , (f, m) <- [(W.view, 0), (W.shift, shiftMask)]
221 ] ++
222
223 -- mod-shift-[F1..F9], Swap workspace with workspace N
224 -- mod-shift-[1..9], Swap workspace with workspace N
225 [ ((modMask .|. controlMask, k), windows $ swapWithCurrent i)
226 | (i, k) <- zip (workspaces conf) [xK_F1 ..] ++
227 zip (workspaces conf) [xK_1 ..]
228 ]
229 {- NOTE: with Xinerama
230 [((modMask .|. controlMask, k), windows $ onCurrentScreen swapWithCurrent i)
231 | (i, k) <- zip (workspaces' conf) [xK_F1 ..] ]
232 -}
233 , layoutHook = smartBorders $
234 mkToggle (NOBORDERS ?? FULL ?? EOT) $ -- enable temporarily maximizing a window
235 avoidStruts $ -- prevents windows from overlapping dock windows
236 let tall = ResizableTall 1 (1%200) (8%13) [] in
237 tabbed shrinkText tabConfig
238 ||| tall
239 ||| Mirror tall
240 ||| magnifiercz (13%10) Grid
241 ||| spiral (6%7)
242 ||| noBorders (fullscreenFull Full)
243 ||| ThreeColMid 1 (1%200) (1%2)
244 -- ||| Tall 1 (3/100) (1/2)
245 , manageHook = composeAll
246 -- [ , isFullscreen --> (doF W.focusDown <+> doFullFloat)
247 [ isFullscreen --> doFullFloat
248 , manageHook def
249 , manageDocks -- NOTE: do not tile dock windows
250 , resource =? "desktop_window" --> doIgnore
251 , className =? "Gimp" --> doFloat
252 , resource =? "gpicview" --> doSink
253 , className =? "mpv" --> doFloat
254 --, className =? "MPlayer" --> doShift "3:media" -- <+> doFloat
255 --, className =? "vlc" --> doShift "3:media"
256 , className =? "trayer" --> doIgnore
257 ]
258 , modMask = mod4Mask
259 , mouseBindings = \XConfig{XMonad.modMask} ->
260 Map.fromList
261 [
262 -- mod-button1, Set the window to floating mode and move by dragging
263 ((modMask, button1), \w -> focus w >> mouseMoveWindow w)
264
265 -- mod-button2, Raise the window to the top of the stack
266 , ((modMask, button2), \w -> focus w >> windows W.swapMaster)
267
268 -- mod-button3, Set the window to floating mode and resize by dragging
269 , ((modMask, button3), \w -> focus w >> mouseResizeWindow w)
270
271 , ((modMask, button4), \_ -> windows W.focusUp)
272 , ((modMask, button5), \_ -> windows W.focusDown)
273
274 -- Cycle through workspaces
275 , ((controlMask .|. modMask, button5), nextNonEmptyWS)
276 , ((controlMask .|. modMask, button4), prevNonEmptyWS)
277 ]
278 , normalBorderColor = "#7C7C7C"
279 , startupHook = setWMName "XMonad"
280 <+> spawnExec "wmname XMonad"
281 <+> spawnExec "xrdb -all .Xresources"
282 <+> spawn "sleep 1 && xmodmap .Xmodmap"
283 <+> spawnExec "xset r rate 250 25"
284 <+> spawnExec "xset b off"
285 <+> spawnExec "xhost local:root"
286 <+> spawnExec "setxkbmap -option keypad:pointerkeys"
287 -- Useful for programs launched by rofi
288 <+> spawnExec "systemctl --user import-environment GNUPGHOME PASSWORD_STORE_DIR PATH"
289 -- <+> spawnOnce "exec arbtt-capture -r 60"
290 -- <+> spawnOnce "exec parcellite"
291 -- <+> spawnOnce "exec xautolock"
292 -- <+> spawnOnce "exec redshift-gtk -l -45.7800:1.9700 -t 6500:3700"
293 <+> spawnOnce "exec nm-applet"
294 , terminal = "urxvtc"
295 , workspaces = {- withScreens nScreens $ -}
296 {-["1:work","2:web","3:media"] ++-}
297 map show [1::Int .. 9]
298 , logHook = updatePointer (0.5, 0.5) (0, 0)
299 -- >> updatePointer (Relative 0.5 0.5)
300 }
301 where
302 tabConfig = def
303 { activeBorderColor = "#7C7C7C"
304 , activeColor = "#000000"
305 , activeTextColor = "#00FF00"
306 , inactiveBorderColor = "#7C7C7C"
307 , inactiveColor = "#000000"
308 , inactiveTextColor = "#EEEEEE"
309 , fontName = "Hack 7"
310 }
311
312 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}'\""
313
314 barSpawner :: ScreenId -> IO StatusBarConfig
315 barSpawner 0 = pure $ topXmobar <> traySB
316 --barSpawner 1 = pure $ xmobar1
317 barSpawner _ = pure $ topXmobar -- nothing on the rest of the screens
318
319 -- Display properties of the root window:
320 -- xprop -display $DISPLAY -root
321 topXmobar = statusBarPropTo "_XMONAD_XMOBAR0" "xmobar -x 0 ~/.config/xmonad/xmobar0.hs" (pure topPP)
322 where
323 topPP =
324 xmobarPP
325 { ppCurrent = xmobarColor "black" "#CCCCCC"
326 , ppHidden = xmobarColor "#CCCCCC" "black"
327 , ppHiddenNoWindows = xmobarColor "#606060" "black"
328 , ppLayout = \s -> xmobarColor "black" "#606060" $
329 case s of
330 "ResizableTall" -> " | "
331 "Mirror ResizableTall" -> " - "
332 "Tabbed Simplest" -> " + "
333 "Magnifier Grid" -> " ~ "
334 "Spiral" -> " @ "
335 "Full" -> " O "
336 "ThreeCol" -> " # "
337 _ -> s
338 , ppSep = " "
339 , ppTitle = xmobarColor "white" "black" . shorten 50
340 , ppUrgent = xmobarColor "yellow" "black"
341 , ppWsSep = " "
342 }
343
344 traySB :: StatusBarConfig
345 traySB =
346 statusBarGeneric
347 ( List.unwords
348 [ "trayer"
349 , "--align right"
350 , "--distance 0,0"
351 , "--distancefrom top,right"
352 , "--edge top"
353 , "--expand true"
354 , "--height 16"
355 , "--monitor primary"
356 , "--tint 0x000000"
357 , "--iconspacing 0"
358 , "--transparent true"
359 , "--widthtype request"
360 , "-l"
361 ]
362 )
363 mempty
364
365 nextNonEmptyWS _ = moveTo Next (WSIs ((not .) <$> isWindowSpaceVisible))
366 prevNonEmptyWS _ = moveTo Prev (WSIs ((not .) <$> isWindowSpaceVisible))
367
368 isWindowSpaceVisible :: X (WindowSpace -> Bool)
369 isWindowSpaceVisible = do
370 vs <- gets (map (W.tag . W.workspace) . W.visible . windowset)
371 return (\w -> W.tag w `elem` vs)
372
373 spawnExec s = spawn $ List.unwords $ [ "exec" ] <> systemdCat <> [ s ]
374 systemdCat = [ "systemd-cat" , "--priority=info", "--stderr-priority=warning", "--level-prefix=false" , "--" ]
375
376 dtXPConfig :: XPConfig
377 dtXPConfig = def
378 { font = "Hack 7"
379 , bgColor = "#282c34"
380 , fgColor = "#bbc2cf"
381 , bgHLight = "#c792ea"
382 , fgHLight = "#000000"
383 , borderColor = "#535974"
384 , promptBorderWidth = 0
385 , promptKeymap = dtXPKeymap
386 , position = Top
387 -- , position = CenteredAt { xpCenterY = 0.3, xpWidth = 0.3 }
388 , height = 23
389 , historySize = 256
390 , historyFilter = id
391 , defaultText = []
392 , autoComplete = Just 100000 -- set Just 100000 for .1 sec
393 , showCompletionOnTab = False
394 -- , searchPredicate = isPrefixOf
395 , searchPredicate = fuzzyMatch
396 , defaultPrompter = id $ List.map Char.toUpper -- change prompt to UPPER
397 -- , defaultPrompter = unwords . map reverse . words -- reverse the prompt
398 -- , defaultPrompter = drop 5 .id (++ "XXXX: ") -- drop first 5 chars of prompt and add XXXX:
399 , alwaysHighlight = True
400 , maxComplRows = Nothing -- set to 'Just 5' for 5 rows
401 }
402
403 dtXPKeymap :: Map.Map (KeyMask,KeySym) (XP ())
404 dtXPKeymap = Map.fromList $
405 List.map (first $ (,) controlMask) -- control + <key>
406 [ (xK_z, killBefore) -- kill line backwards
407 , (xK_k, killAfter) -- kill line forwards
408 , (xK_a, startOfLine) -- move to the beginning of the line
409 , (xK_e, endOfLine) -- move to the end of the line
410 , (xK_m, deleteString Next) -- delete a character foward
411 , (xK_b, moveCursor Prev) -- move cursor forward
412 , (xK_f, moveCursor Next) -- move cursor backward
413 , (xK_BackSpace, killWord Prev) -- kill the previous word
414 , (xK_y, pasteString) -- paste a string
415 , (xK_g, quit) -- quit out of prompt
416 , (xK_bracketleft, quit)
417 ]
418 ++
419 List.map (first $ (,) altMask) -- meta key + <key>
420 [ (xK_BackSpace, killWord Prev) -- kill the prev word
421 , (xK_f, moveWord Next) -- move a word forward
422 , (xK_b, moveWord Prev) -- move a word backward
423 , (xK_d, killWord Next) -- kill the next word
424 , (xK_n, moveHistory W.focusUp') -- move up thru history
425 , (xK_p, moveHistory W.focusDown') -- move down thru history
426 ]
427 ++
428 List.map (first $ (,) 0) -- <key>
429 [ (xK_Return, setSuccess True >> setDone True)
430 , (xK_KP_Enter, setSuccess True >> setDone True)
431 , (xK_BackSpace, deleteString Prev)
432 , (xK_Delete, deleteString Next)
433 , (xK_Left, moveCursor Prev)
434 , (xK_Right, moveCursor Next)
435 , (xK_Home, startOfLine)
436 , (xK_End, endOfLine)
437 , (xK_Down, moveHistory W.focusUp')
438 , (xK_Up, moveHistory W.focusDown')
439 , (xK_Escape, quit)
440 ]
441
442 altMask :: KeyMask
443 altMask = mod1Mask