dotfiles

My PC Dotfiles & Website

modules/desktop/hyprland/_settings/keybinds.nix (12872B)


  1## Compositor Binds
  2_: {lib, ...}: let
  3  lua = import ./_lib.nix lib;
  4  inherit (lua) combo bind bindOpts exec;
  5
  6  mod = "SUPER";
  7
  8  # Bind flags
  9  mouse = {mouse = true;};
 10  locked = {locked = true;};
 11  repeat = {repeating = true;};
 12  lockedRepeat = {
 13    locked = true;
 14    repeating = true;
 15  };
 16
 17  # Directions
 18  dir = d:
 19    {
 20      l = "left";
 21      r = "right";
 22      u = "up";
 23      d = "down";
 24    }.${
 25      d
 26    };
 27
 28  # Dispatchers
 29  focusDir = d: ''hl.dsp.focus({ direction = "${dir d}" })'';
 30  swapDir = d: ''hl.dsp.window.swap({ direction = "${dir d}" })'';
 31  intoGroup = d: ''hl.dsp.window.move({ into_group = "${dir d}" })'';
 32  moveOrGroup = d: ''hl.dsp.window.move({ direction = "${dir d}", group_aware = true })'';
 33  moveActive = x: y: ''hl.dsp.window.move({ x = ${toString x}, y = ${toString y}, relative = true })'';
 34  resizeActive = x: y: ''hl.dsp.window.resize({ x = ${toString x}, y = ${toString y}, relative = true })'';
 35  multi = disps: "function() " + lib.concatStringsSep " " (map (d: "hl.dispatch(${d});") disps) + " end";
 36  call = d: "hl.dispatch(${d})";
 37
 38  # Overview
 39  seq = stmts: "function() " + lib.concatStringsSep " " (map (s: "${s};") stmts) + " end";
 40  overview = action: ''hl.plugin.scrolloverview.overview("${action}")'';
 41  soNav = d: ''hl.plugin.scrolloverview.navigate("${dir d}")'';
 42  soWindow = action: ''hl.plugin.scrolloverview.window("${action}")'';
 43
 44  # Layout-specific binds
 45  layout = msg: ''hl.dsp.layout("${msg}")'';
 46  layoutAware = scroll: fallback: ''function() if hl.get_config("general.layout") == "scrolling" then hl.dispatch(${scroll}) else hl.dispatch(${fallback}) end end'';
 47  toggleLayout = ''function() if hl.get_config("general.layout") == "scrolling" then hl.config({ general = { layout = "dwindle" } }); hl.dispatch(hl.dsp.event("layout:dwindle")) else hl.config({ general = { layout = "scrolling" } }); hl.dispatch(hl.dsp.event("layout:scrolling")) end end'';
 48in {
 49  wayland.windowManager.hyprland = {
 50    ## Keybindings
 51    settings.bind =
 52      [
 53        # Compositor Commands
 54        (bind (combo ["ALT"] "F4") "hl.dsp.window.close()")
 55        (bind (combo [mod] "Q") "hl.dsp.window.close()")
 56        (bind (combo [mod "SHIFT"] "Q") "hl.dsp.window.kill()")
 57        (bind (combo [mod "SHIFT"] "E") "hl.dsp.window.fullscreen()")
 58        (bind (combo [mod] "C") (multi [
 59          "hl.dsp.window.center()"
 60          "hl.dsp.cursor.move_to_corner({ corner = 2 })"
 61        ]))
 62        (bind (combo [mod] "E") ''hl.dsp.window.fullscreen({ mode = "maximized" })'')
 63        (bind (combo [mod] "P") "hl.dsp.window.pin()")
 64        (bind (combo [mod] "Space") (layoutAware (layout "consume_or_expel next") ''hl.dsp.layout("togglesplit")''))
 65        (bind (combo [mod] "BackSpace") toggleLayout)
 66        (bind (combo [mod "SHIFT"] "S") "hl.dsp.window.toggle_swallow()")
 67
 68        # Window Focus
 69        (bind (combo [mod] "left") (focusDir "l"))
 70        (bind (combo [mod] "right") (focusDir "r"))
 71        (bind (combo [mod] "up") (focusDir "u"))
 72        (bind (combo [mod] "down") (focusDir "d"))
 73        (bind (combo ["ALT"] "Tab") "hl.dsp.window.cycle_next({ next = true })")
 74        (bind (combo ["ALT" "SHIFT"] "Tab") "hl.dsp.window.cycle_next({ next = false })")
 75        (bind (combo ["ALT"] "A") (multi [
 76          "hl.dsp.focus({ urgent_or_last = true })"
 77          ''hl.dsp.window.alter_zorder({ mode = "top" })''
 78        ]))
 79
 80        # Window Movement
 81        (bind (combo [mod "SHIFT"] "left") (layoutAware (layout "swapcol l") (swapDir "l")))
 82        (bind (combo [mod "SHIFT"] "right") (layoutAware (layout "swapcol r") (swapDir "r")))
 83        (bind (combo [mod "SHIFT"] "up") (layoutAware (layout "consume") (swapDir "u")))
 84        (bind (combo [mod "SHIFT"] "down") (layoutAware (layout "expel") (swapDir "d")))
 85
 86        # Scrolling
 87        (bind (combo [mod] "bracketright") (layout "colresize +conf"))
 88        (bind (combo [mod] "bracketleft") (layout "colresize -conf"))
 89        (bind (combo [mod "SHIFT"] "bracketright") (layout "fit all"))
 90        (bind (combo [mod "SHIFT"] "bracketleft") (layout "center"))
 91
 92        # Window Groups
 93        (bind (combo [mod "SHIFT"] "space") "hl.dsp.group.toggle()")
 94        (bind (combo ["ALT"] "grave") "hl.dsp.group.next()")
 95        (bind (combo ["ALT" "SHIFT"] "grave") "hl.dsp.group.prev()")
 96        (bind (combo [mod "CTRL"] "left") (intoGroup "l"))
 97        (bind (combo [mod "CTRL"] "right") (intoGroup "r"))
 98        (bind (combo [mod "CTRL"] "up") (intoGroup "u"))
 99        (bind (combo [mod "CTRL"] "down") (intoGroup "d"))
100
101        # Floating Mode
102        (bind (combo [mod] "semicolon") ''hl.dsp.window.float({ action = "toggle" })'')
103        (bind (combo [mod] "apostrophe") (exec "hyprutils toggle float"))
104
105        # Cycle Workspaces
106        (bind (combo [mod] "comma") ''hs.dsp.focus({ workspace = "m-1" })'')
107        (bind (combo [mod] "period") ''hs.dsp.focus({ workspace = "m+1" })'')
108        (bind (combo [mod "CTRL"] "comma") ''hs.dsp.focus({ workspace = "r-1" })'')
109        (bind (combo [mod "CTRL"] "period") ''hs.dsp.focus({ workspace = "r+1" })'')
110        (bind (combo [mod] "mouse_down") ''hs.dsp.focus({ workspace = "r-1" })'')
111        (bind (combo [mod] "mouse_up") ''hs.dsp.focus({ workspace = "r+1" })'')
112
113        # Special Workspace
114        (bind (combo [mod] "0") ''hl.dsp.workspace.toggle_special("Stash")'')
115        (bind (combo [mod "SHIFT"] "0") (exec "pypr toggle_special Stash"))
116
117        # Move Window to Workspace
118        (bind (combo [mod "SHIFT"] "comma") ''hs.dsp.window.move({ workspace = "-1", follow = false })'')
119        (bind (combo [mod "SHIFT"] "period") ''hs.dsp.window.move({ workspace = "+1", follow = false })'')
120
121        # Cycle Monitors
122        (bind (combo [mod "ALT"] "comma") ''hl.dsp.focus({ monitor = "l" })'')
123        (bind (combo [mod "ALT"] "period") ''hl.dsp.focus({ monitor = "r" })'')
124
125        # Move Window to Monitor
126        (bind (combo [mod "SHIFT" "ALT"] "comma") ''hl.dsp.window.move({ monitor = "-1" })'')
127        (bind (combo [mod "SHIFT" "ALT"] "period") ''hl.dsp.window.move({ monitor = "+1" })'')
128
129        # Screen Lock
130        (bind (combo [mod] "L") (exec "noctalia msg session lock"))
131
132        # Window Minimization
133        (bind (combo ["ALT"] "Q") ''hl.dsp.window.move({ workspace = "special:minimized", follow = false })'')
134        (bind (combo ["ALT" "SHIFT"] "Q") (exec "hyprutils toggle minimized"))
135
136        # Screenshot
137        (bind (combo [] "Print") (exec "noctalia msg screenshot-region"))
138        (bind (combo ["SHIFT"] "Print") (exec "noctalia msg screenshot-fullscreen pick"))
139
140        # Overview
141        (bind (combo [mod] "grave") (seq [
142          (overview "toggle")
143          (call ''hl.dsp.submap("scrolloverview")'')
144        ]))
145
146        # Submaps
147        (bind (combo [mod "SHIFT"] "Escape") ''hl.dsp.submap("inhibit")'')
148        (bind (combo [mod] "R") ''hl.dsp.submap("resize")'')
149        (bind (combo [mod] "M") ''hl.dsp.submap("move")'')
150      ]
151      ++
152      # Workspaces
153      (builtins.concatLists (
154        builtins.genList (
155          n: let
156            i = toString (n + 1);
157          in [
158            (bind (combo [mod] i) "hs.dsp.focus({ workspace = ${i} })")
159            (bind (combo [mod "SHIFT"] i) "hs.dsp.window.move({ workspace = ${i}, follow = false })")
160          ]
161        )
162        9
163      ))
164      ++ [
165        # Mouse
166        (bindOpts (combo [mod] "mouse:272") "hl.dsp.window.drag()" mouse)
167        (bindOpts (combo [mod] "mouse:273") "hl.dsp.window.resize()" mouse)
168
169        # Media Controls
170        (bindOpts (combo [] "XF86AudioPlay") (exec "noctalia msg media toggle") locked)
171        (bindOpts (combo [] "XF86AudioPrev") (exec "noctalia msg media previous") locked)
172        (bindOpts (combo [] "XF86AudioNext") (exec "noctalia msg media next") locked)
173
174        # Volume
175        (bindOpts (combo [] "XF86AudioMute") (exec "noctalia msg volume-mute") locked)
176
177        # Keyboard Backlight
178        (bindOpts (combo [] "XF86KbdBrightnessUp") (exec "noctalia msg keyboard-backlight-up") locked)
179        (bindOpts (combo [] "XF86KbdBrightnessDown") (exec "noctalia msg keyboard-backlight-down") locked)
180
181        # Touchpad
182        (bindOpts (combo [] "XF86TouchpadToggle") (exec "hyprutils toggle touchpad") locked)
183
184        # Laptop Lid
185        (bindOpts (combo [] "switch:on:Lid Switch") (exec "noctalia msg session lock") locked)
186
187        # Volume
188        (bindOpts (combo [] "XF86AudioRaiseVolume") (exec "noctalia msg volume-up") lockedRepeat)
189        (bindOpts (combo [] "XF86AudioLowerVolume") (exec "noctalia msg volume-down") lockedRepeat)
190
191        # Backlight
192        (bindOpts (combo [] "XF86MonBrightnessUp") (exec "noctalia msg brightness-up") lockedRepeat)
193        (bindOpts (combo [] "XF86MonBrightnessDown") (exec "noctalia msg brightness-down") lockedRepeat)
194
195        # Magnifier
196        (bindOpts (combo [mod] "equal") (exec "hyprutils magnify ++0.5") lockedRepeat)
197        (bindOpts (combo [mod] "minus") (exec "hyprutils magnify --0.5") lockedRepeat)
198        (bindOpts (combo [mod "SHIFT"] "minus") (exec "hyprutils magnify") lockedRepeat)
199      ];
200
201    ## Submaps
202    submaps = {
203      # Inhibit Keybinds
204      inhibit.settings.bind = [(bind (combo [mod "SHIFT"] "Escape") ''hl.dsp.submap("reset")'')];
205
206      # Workspace Overview
207      scrolloverview.settings.bind =
208        [
209          (bind (combo [] "left") (seq [(soNav "l")]))
210          (bind (combo [] "right") (seq [(soNav "r")]))
211          (bind (combo [] "up") (seq [(soNav "u")]))
212          (bind (combo [] "down") (seq [(soNav "d")]))
213          (bind (combo [] "Return") (seq [
214            (overview "select")
215            (call ''hl.dsp.submap("reset")'')
216          ]))
217          (bind (combo [] "escape") (seq [
218            (overview "off")
219            (call ''hl.dsp.submap("reset")'')
220          ]))
221          (bind (combo [mod] "grave") (seq [
222            (overview "off")
223            (call ''hl.dsp.submap("reset")'')
224          ]))
225          (bindOpts (combo [] "mouse:272") (seq [
226              (overview "select")
227              (soWindow "select")
228              (overview "off")
229              (call ''hl.dsp.submap("reset")'')
230            ])
231            mouse)
232          (bindOpts (combo [] "mouse:274") (seq [(soWindow "close")]) mouse)
233        ]
234        ++ builtins.genList (
235          n: let
236            i = toString (n + 1);
237          in
238            bind (combo [] i) (seq [
239              (call "hs.dsp.focus({ workspace = ${i} })")
240              (overview "off")
241              (call ''hl.dsp.submap("reset")'')
242            ])
243        )
244        9;
245
246      # Window Resize
247      resize.settings.bind = [
248        (bindOpts (combo [] "right") (resizeActive 10 0) repeat)
249        (bindOpts (combo [] "left") (resizeActive (-10) 0) repeat)
250        (bindOpts (combo [] "up") (resizeActive 0 (-10)) repeat)
251        (bindOpts (combo [] "down") (resizeActive 0 10) repeat)
252        (bindOpts (combo [] "mouse:272") "hl.dsp.window.resize()" mouse)
253        (bind (combo [] "escape") ''hl.dsp.submap("reset")'')
254        (bind (combo [mod] "R") ''hl.dsp.submap("reset")'')
255      ];
256
257      # Window Movement
258      move.settings.bind = [
259        (bind (combo [] "C") "hl.dsp.window.center()")
260        (bind (combo [] "P") "hl.dsp.window.pin()")
261        (bind (combo [] "left") (moveOrGroup "l"))
262        (bind (combo [] "right") (moveOrGroup "r"))
263        (bind (combo [] "up") (moveOrGroup "u"))
264        (bind (combo [] "down") (moveOrGroup "d"))
265        (bind (combo ["SHIFT"] "left") (moveActive (-30) 0))
266        (bind (combo ["SHIFT"] "right") (moveActive 30 0))
267        (bind (combo ["SHIFT"] "up") (moveActive 0 (-30)))
268        (bind (combo ["SHIFT"] "down") (moveActive 0 30))
269        (bind (combo [] "comma") ''hs.dsp.window.move({ workspace = "-1", follow = false })'')
270        (bind (combo [] "period") ''hs.dsp.window.move({ workspace = "+1", follow = false })'')
271        (bindOpts (combo [] "mouse:272") "hl.dsp.window.drag()" mouse)
272        (bind (combo [] "escape") ''hl.dsp.submap("reset")'')
273        (bind (combo [mod] "M") ''hl.dsp.submap("reset")'')
274      ];
275
276      # Window Minimization
277      minimized.settings.bind = [
278        (bind (combo [] "left") (focusDir "l"))
279        (bind (combo [] "right") (focusDir "r"))
280        (bind (combo [] "up") (focusDir "u"))
281        (bind (combo [] "down") (focusDir "d"))
282        (bind (combo [] "Q") "hl.dsp.window.close()")
283        (bind (combo [] "Return") (multi [
284          ''hl.dsp.window.move({ workspace = "+0" })''
285          ''hl.dsp.submap("reset")''
286        ]))
287        (bind (combo [] "mouse:272") (multi [
288          ''hl.dsp.window.move({ workspace = "+0" })''
289          ''hl.dsp.submap("reset")''
290        ]))
291        (bind (combo [] "escape") (multi [
292          ''hl.dsp.workspace.toggle_special("minimized")''
293          ''hl.dsp.submap("reset")''
294        ]))
295      ];
296    };
297  };
298}