1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
local mainMod = "SUPER"
-- Quit Keys
hl.bind(mainMod .. " + Q", hl.dsp.window.close())
hl.bind(mainMod .. " + CTRL + Q", hl.dsp.exit())
-- Program keys
hl.bind(mainMod .. " + T", hl.dsp.exec_cmd(TERMINAL))
hl.bind(mainMod .. " + R", hl.dsp.exec_cmd(MENU))
hl.bind(mainMod .. " + B", hl.dsp.exec_cmd(BROWSER))
hl.bind(mainMod .. " + O", hl.dsp.exec_cmd(HYPRLOCK))
hl.bind(mainMod .. " + G", hl.dsp.exec_cmd(STEAM))
hl.bind(mainMod .. " + S",
hl.dsp.exec_cmd("grim -o" .. MAIN_DISPLAY .. " \"${HOME}/screenshots/screenshot-$(date +%F-%T).png\""))
hl.bind(mainMod .. " + SHIFT + S", hl.dsp.exec_cmd("grim -g \"$(slurp)\" - | wl-copy"))
local function focus_hyprland(direction)
hl.dispatch(hl.dsp.focus({ direction = direction }))
end
local function is_direct_nvim(title)
title = (title or ""):lower()
return title:find("^nvim")
or title:find(" - nvim", 1, true)
or title:find("^vim")
or title:find(" - vim", 1, true)
end
local function ask_direct_nvim(win, direction)
local runtime_dir = os.getenv("XDG_RUNTIME_DIR") or "/tmp"
local socket_path = string.format(
"%s/nvim-hypr-nav-%x.sock",
runtime_dir,
tostring(win.stable_id)
)
local handle = io.popen(string.format(
"printf 'nav:%s\\n' | socat -T 0.25 -,ignoreeof UNIX-CONNECT:%s 2>/dev/null",
direction,
socket_path
))
if not handle then
return false
end
local response = handle:read("*a")
handle:close()
return response:find("success", 1, true) ~= nil
end
local function smart_nav(direction)
return function()
local win = hl.get_active_window()
if not win then
return
end
if win.class ~= "com.mitchellh.ghostty" then
focus_hyprland(direction)
return
end
local title = (win.title or ""):lower()
if title == "herdr" then
local helper = (os.getenv("HOME") or "")
.. "/.config/hypr/scripts/herdr-smart-nav"
local handle = io.popen(helper .. " " .. direction)
if not handle then
focus_hyprland(direction)
return
end
local result = handle:read("*a")
handle:close()
if result:find("hyprland", 1, true) then
focus_hyprland(direction)
end
return
end
if is_direct_nvim(title) and ask_direct_nvim(win, direction) then
return
end
focus_hyprland(direction)
end
end
local movement_keys = {
H = "left",
L = "right",
J = "down",
K = "up"
}
for key, dir in pairs(movement_keys) do
hl.bind(mainMod .. " + " .. key, smart_nav(dir))
end
hl.bind(mainMod .. " + SHIFT + H", hl.dsp.window.move({ direction = "left" }))
hl.bind(mainMod .. " + SHIFT + L", hl.dsp.window.move({ direction = "right" }))
hl.bind(mainMod .. " + SHIFT + J", hl.dsp.window.move({ direction = "down" }))
hl.bind(mainMod .. " + SHIFT + K", hl.dsp.window.move({ direction = "up" }))
hl.bind(mainMod .. " + CTRL + H", hl.dsp.window.resize({ x = -10, y = 0, relative = true }), { repeating = true })
hl.bind(mainMod .. " + CTRL + L", hl.dsp.window.resize({ x = 10, y = 0, relative = true }), { repeating = true })
hl.bind(mainMod .. " + CTRL + J", hl.dsp.window.resize({ x = 0, y = -10, relative = true }), { repeating = true })
hl.bind(mainMod .. " + CTRL + K", hl.dsp.window.resize({ x = 0, y = 10, relative = true }), { repeating = true })
for i = 1, 10 do
local key = i % 10
hl.bind(mainMod .. " + " .. key, hl.dsp.focus({ workspace = i }))
hl.bind(mainMod .. " + SHIFT + " .. key, hl.dsp.window.move({ workspace = i }))
end
-- Resize Keys
hl.bind(mainMod .. " + F", hl.dsp.window.fullscreen({ action = "toggle" }))
hl.bind(mainMod .. " + v", hl.dsp.window.float())
hl.bind(mainMod .. " + mouse:272", hl.dsp.window.drag(), { mouse = true })
hl.bind(mainMod .. " + mouse:273", hl.dsp.window.resize(), { mouse = true })
-- Multimedia Keys
hl.bind("XF86AudioRaiseVolume", hl.dsp.exec_cmd("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+"),
{ locked = true, repeating = true })
hl.bind("XF86AudioLowerVolume", hl.dsp.exec_cmd("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"),
{ locked = true, repeating = true })
hl.bind("XF86AudioMute", hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"))
hl.bind("XF86AudioPlay", hl.dsp.exec_cmd("playerctl play-pause"), { locked = true })
hl.bind("XF86AudioNext", hl.dsp.exec_cmd("playerctl next"), { locked = true })
hl.bind("XF86AudioPrev", hl.dsp.exec_cmd("playerctl previous"), { locked = true })
-- hl.bind("code:51", hl.dsp.pass({ window = "class:^([Dd]iscord)$" }), { non_consuming = true })
|