nixos: add hyprland plugin dev tooling
This commit is contained in:
@@ -26,6 +26,7 @@ function M.setup(ctx)
|
|||||||
bind(main_mod .. " + Q", exec("hyprctl reload"), desc("Reload Hyprland"))
|
bind(main_mod .. " + Q", exec("hyprctl reload"), desc("Reload Hyprland"))
|
||||||
bind(main_mod .. " + R", exec("hyprctl reload"), desc("Reload Hyprland"))
|
bind(main_mod .. " + R", exec("hyprctl reload"), desc("Reload Hyprland"))
|
||||||
bind(hyper .. " + SHIFT + L", exec("hyprlock"), desc("Lock screen"))
|
bind(hyper .. " + SHIFT + L", exec("hyprlock"), desc("Lock screen"))
|
||||||
|
bind(hyper .. " + SHIFT + V", toggle_visual_performance_mode, desc("Toggle Hyprland performance mode"))
|
||||||
bind(hyper .. " + slash", function()
|
bind(hyper .. " + slash", function()
|
||||||
hl.exec_cmd("toggle_taffybar")
|
hl.exec_cmd("toggle_taffybar")
|
||||||
refresh_monitor_reserved_cache(0.25)
|
refresh_monitor_reserved_cache(0.25)
|
||||||
@@ -88,11 +89,7 @@ function M.setup(ctx)
|
|||||||
local function setup_window_overview_bindings()
|
local function setup_window_overview_bindings()
|
||||||
bind(main_mod .. " + SHIFT + C", hl.dsp.window.close(), desc("Close active window"))
|
bind(main_mod .. " + SHIFT + C", hl.dsp.window.close(), desc("Close active window"))
|
||||||
bind(main_mod .. " + SHIFT + Q", hl.dsp.exit(), desc("Exit Hyprland"))
|
bind(main_mod .. " + SHIFT + Q", hl.dsp.exit(), desc("Exit Hyprland"))
|
||||||
bind(main_mod .. " + Tab", hyprwinview({
|
bind(main_mod .. " + Tab", hyprexpo("toggle"), desc("Toggle workspace expo", overview_bind_opts))
|
||||||
action = "show",
|
|
||||||
start_in_filter_mode = true,
|
|
||||||
default_action = "select",
|
|
||||||
}), desc("Show window overview", overview_bind_opts))
|
|
||||||
bind(main_mod .. " + SHIFT + Tab", hyprwinview({
|
bind(main_mod .. " + SHIFT + Tab", hyprwinview({
|
||||||
action = "show",
|
action = "show",
|
||||||
include_current_workspace = false,
|
include_current_workspace = false,
|
||||||
@@ -105,7 +102,7 @@ function M.setup(ctx)
|
|||||||
start_in_filter_mode = true,
|
start_in_filter_mode = true,
|
||||||
default_action = "select",
|
default_action = "select",
|
||||||
}), desc("Toggle alternate window overview", overview_bind_opts))
|
}), desc("Toggle alternate window overview", overview_bind_opts))
|
||||||
bind("ALT + SHIFT + Tab", hyprexpo("open"), desc("Open workspace expo", overview_bind_opts))
|
bind("ALT + SHIFT + Tab", hyprexpo("on"), desc("Open workspace expo", overview_bind_opts))
|
||||||
bind(main_mod .. " + G", hyprwinview({
|
bind(main_mod .. " + G", hyprwinview({
|
||||||
action = "show",
|
action = "show",
|
||||||
start_in_filter_mode = true,
|
start_in_filter_mode = true,
|
||||||
@@ -201,6 +198,28 @@ function M.setup(ctx)
|
|||||||
bind("Escape", hl.dsp.submap("reset"), desc("Exit window picker"))
|
bind("Escape", hl.dsp.submap("reset"), desc("Exit window picker"))
|
||||||
bind("catchall", hl.dsp.submap("reset"), desc("Exit window picker"))
|
bind("catchall", hl.dsp.submap("reset"), desc("Exit window picker"))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
hl.define_submap("hyprexpo", function()
|
||||||
|
bind("W", hyprexpo_dispatch("kb_focus", "up"), desc("Focus workspace tile above"))
|
||||||
|
bind("A", hyprexpo_dispatch("kb_focus", "left"), desc("Focus workspace tile to the left"))
|
||||||
|
bind("S", hyprexpo_dispatch("kb_focus", "down"), desc("Focus workspace tile below"))
|
||||||
|
bind("D", hyprexpo_dispatch("kb_focus", "right"), desc("Focus workspace tile to the right"))
|
||||||
|
bind("Up", hyprexpo_dispatch("kb_focus", "up"), desc("Focus workspace tile above"))
|
||||||
|
bind("Left", hyprexpo_dispatch("kb_focus", "left"), desc("Focus workspace tile to the left"))
|
||||||
|
bind("Down", hyprexpo_dispatch("kb_focus", "down"), desc("Focus workspace tile below"))
|
||||||
|
bind("Right", hyprexpo_dispatch("kb_focus", "right"), desc("Focus workspace tile to the right"))
|
||||||
|
bind("Return", hyprexpo_dispatch("kb_confirm"), desc("Select focused workspace tile"))
|
||||||
|
bind("Space", hyprexpo_dispatch("kb_confirm"), desc("Select focused workspace tile"))
|
||||||
|
|
||||||
|
for i = 1, max_workspace do
|
||||||
|
local workspace_id = i
|
||||||
|
local key = tostring(i % 10)
|
||||||
|
bind(key, hyprexpo_dispatch("kb_selectn", workspace_id), desc("Select workspace " .. workspace_id))
|
||||||
|
end
|
||||||
|
|
||||||
|
bind("Escape", hyprexpo("off"), desc("Close workspace expo"))
|
||||||
|
bind("catchall", hyprexpo("off"), desc("Close workspace expo"))
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function setup_window_resize_and_monitor_bindings()
|
local function setup_window_resize_and_monitor_bindings()
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ function M.setup(ctx)
|
|||||||
end
|
end
|
||||||
|
|
||||||
verify_config = command_line_contains("--verify-config")
|
verify_config = command_line_contains("--verify-config")
|
||||||
|
dev_session = os.getenv("IMALISON_HYPRLAND_DEV_SESSION") == "1"
|
||||||
|
|
||||||
local function exec(command)
|
local function exec(command)
|
||||||
return hl.dsp.exec_cmd(command)
|
return hl.dsp.exec_cmd(command)
|
||||||
@@ -105,12 +106,11 @@ function M.setup(ctx)
|
|||||||
return "address:" .. tostring(window.address)
|
return "address:" .. tostring(window.address)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function hyprexpo(action)
|
local function hyprexpo_call(method, arg)
|
||||||
action = action or "toggle"
|
|
||||||
return function()
|
return function()
|
||||||
overview_trace("hyprexpo " .. tostring(action))
|
overview_trace("hyprexpo:" .. method .. (arg and (" " .. tostring(arg)) or ""))
|
||||||
if hl.plugin and hl.plugin.hyprexpo and hl.plugin.hyprexpo.expo then
|
if hl.plugin and hl.plugin.hyprexpo and hl.plugin.hyprexpo[method] then
|
||||||
hl.plugin.hyprexpo.expo(action)
|
hl.plugin.hyprexpo[method](arg)
|
||||||
else
|
else
|
||||||
hl.notification.create({
|
hl.notification.create({
|
||||||
text = "hyprexpo is not loaded",
|
text = "hyprexpo is not loaded",
|
||||||
@@ -123,6 +123,14 @@ function M.setup(ctx)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function hyprexpo(action)
|
||||||
|
return hyprexpo_call("expo", action or "toggle")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function hyprexpo_dispatch(dispatcher, arg)
|
||||||
|
return hyprexpo_call(dispatcher, arg)
|
||||||
|
end
|
||||||
|
|
||||||
local function hyprwinview(action)
|
local function hyprwinview(action)
|
||||||
return function()
|
return function()
|
||||||
local label = "hyprwinview"
|
local label = "hyprwinview"
|
||||||
@@ -219,15 +227,41 @@ function M.setup(ctx)
|
|||||||
plugin = {
|
plugin = {
|
||||||
hyprexpo = {
|
hyprexpo = {
|
||||||
columns = 3,
|
columns = 3,
|
||||||
gap_size = 5,
|
gaps_in = 5,
|
||||||
bg_col = "rgba(111111ff)",
|
gaps_out = 0,
|
||||||
|
bg_col = 0xff111111,
|
||||||
workspace_method = "center current",
|
workspace_method = "center current",
|
||||||
skip_empty = false,
|
skip_empty = false,
|
||||||
max_workspace = max_workspace,
|
|
||||||
show_workspace_numbers = true,
|
|
||||||
workspace_number_color = "rgba(edb443ff)",
|
|
||||||
gesture_distance = 200,
|
gesture_distance = 200,
|
||||||
cancel_key = "escape",
|
keynav_enable = 1,
|
||||||
|
keynav_wrap_h = 1,
|
||||||
|
keynav_wrap_v = 1,
|
||||||
|
keynav_reading_order = 0,
|
||||||
|
border_width = 2,
|
||||||
|
border_color_current = "rgb(66ccff)",
|
||||||
|
border_color_focus = "rgb(edb443)",
|
||||||
|
border_color_hover = "rgb(aabbcc)",
|
||||||
|
tile_rounding = 5,
|
||||||
|
tile_rounding_power = 2.0,
|
||||||
|
label_enable = 1,
|
||||||
|
label_font_size = 28,
|
||||||
|
label_text_mode = "token",
|
||||||
|
label_token_map = "1,2,3,4,5,6,7,8,9",
|
||||||
|
label_position = "center",
|
||||||
|
label_offset_x = 6,
|
||||||
|
label_offset_y = 6,
|
||||||
|
label_show = "always",
|
||||||
|
label_color_default = 0xffffffff,
|
||||||
|
label_color_hover = 0xffeeeeee,
|
||||||
|
label_color_focus = 0xffedb443,
|
||||||
|
label_color_current = 0xff66ccff,
|
||||||
|
label_bg_enable = 1,
|
||||||
|
label_bg_color = 0xcc000000,
|
||||||
|
label_bg_shape = "rounded",
|
||||||
|
label_bg_rounding = 10,
|
||||||
|
label_padding = 12,
|
||||||
|
label_font_bold = 1,
|
||||||
|
label_pixel_snap = 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -567,6 +601,7 @@ function M.setup(ctx)
|
|||||||
ctx.overview_trace = overview_trace
|
ctx.overview_trace = overview_trace
|
||||||
ctx.window_selector = window_selector
|
ctx.window_selector = window_selector
|
||||||
ctx.hyprexpo = hyprexpo
|
ctx.hyprexpo = hyprexpo
|
||||||
|
ctx.hyprexpo_dispatch = hyprexpo_dispatch
|
||||||
ctx.hyprwinview = hyprwinview
|
ctx.hyprwinview = hyprwinview
|
||||||
ctx.workspacehistory = workspacehistory
|
ctx.workspacehistory = workspacehistory
|
||||||
ctx.hyprspace = hyprspace
|
ctx.hyprspace = hyprspace
|
||||||
|
|||||||
@@ -40,12 +40,16 @@ function M.setup(ctx)
|
|||||||
apply_nstack_config()
|
apply_nstack_config()
|
||||||
apply_hyprexpo_config()
|
apply_hyprexpo_config()
|
||||||
apply_hyprwinview_config()
|
apply_hyprwinview_config()
|
||||||
|
apply_hyprwobbly_config()
|
||||||
apply_hyprglass_config()
|
apply_hyprglass_config()
|
||||||
|
apply_visual_performance_mode()
|
||||||
apply_rules()
|
apply_rules()
|
||||||
|
if not dev_session then
|
||||||
hl.exec_cmd("sh -lc '/run/current-system/sw/bin/uwsm finalize HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP XDG_SESSION_DESKTOP XDG_SESSION_TYPE XAUTHORITY IMALISON_SESSION_TYPE=wayland IMALISON_WINDOW_MANAGER=hyprland || dbus-update-activation-environment --systemd XDG_RUNTIME_DIR WAYLAND_DISPLAY DISPLAY XAUTHORITY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP XDG_SESSION_DESKTOP XDG_SESSION_TYPE IMALISON_SESSION_TYPE IMALISON_WINDOW_MANAGER; systemctl --user start hyprland-session.target'")
|
hl.exec_cmd("sh -lc '/run/current-system/sw/bin/uwsm finalize HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP XDG_SESSION_DESKTOP XDG_SESSION_TYPE XAUTHORITY IMALISON_SESSION_TYPE=wayland IMALISON_WINDOW_MANAGER=hyprland || dbus-update-activation-environment --systemd XDG_RUNTIME_DIR WAYLAND_DISPLAY DISPLAY XAUTHORITY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP XDG_SESSION_DESKTOP XDG_SESSION_TYPE IMALISON_SESSION_TYPE IMALISON_WINDOW_MANAGER; systemctl --user start hyprland-session.target'")
|
||||||
hl.exec_cmd("hypridle")
|
hl.exec_cmd("hypridle")
|
||||||
hl.exec_cmd("wl-paste --type text --watch cliphist store")
|
hl.exec_cmd("wl-paste --type text --watch cliphist store")
|
||||||
hl.exec_cmd("wl-paste --type image --watch cliphist store")
|
hl.exec_cmd("wl-paste --type image --watch cliphist store")
|
||||||
|
end
|
||||||
write_layout_state()
|
write_layout_state()
|
||||||
schedule_nstack_count_update()
|
schedule_nstack_count_update()
|
||||||
refresh_monitor_reserved_cache(0.25)
|
refresh_monitor_reserved_cache(0.25)
|
||||||
@@ -55,7 +59,9 @@ function M.setup(ctx)
|
|||||||
hl.on("config.reloaded", apply_nstack_config)
|
hl.on("config.reloaded", apply_nstack_config)
|
||||||
hl.on("config.reloaded", apply_hyprexpo_config)
|
hl.on("config.reloaded", apply_hyprexpo_config)
|
||||||
hl.on("config.reloaded", apply_hyprwinview_config)
|
hl.on("config.reloaded", apply_hyprwinview_config)
|
||||||
|
hl.on("config.reloaded", apply_hyprwobbly_config)
|
||||||
hl.on("config.reloaded", apply_hyprglass_config)
|
hl.on("config.reloaded", apply_hyprglass_config)
|
||||||
|
hl.on("config.reloaded", apply_visual_performance_mode)
|
||||||
hl.on("config.reloaded", apply_rules)
|
hl.on("config.reloaded", apply_rules)
|
||||||
hl.on("config.reloaded", refresh_shell_workarea_and_scratchpads)
|
hl.on("config.reloaded", refresh_shell_workarea_and_scratchpads)
|
||||||
hl.on("layer.opened", refresh_shell_workarea_and_scratchpads)
|
hl.on("layer.opened", refresh_shell_workarea_and_scratchpads)
|
||||||
|
|||||||
@@ -2,6 +2,10 @@ local M = {}
|
|||||||
|
|
||||||
function M.setup(ctx)
|
function M.setup(ctx)
|
||||||
local _ENV = ctx
|
local _ENV = ctx
|
||||||
|
local function plugin_path(env_name, default)
|
||||||
|
return os.getenv(env_name) or default
|
||||||
|
end
|
||||||
|
|
||||||
if enable_nstack and not verify_config then
|
if enable_nstack and not verify_config then
|
||||||
hl.plugin.load("/run/current-system/sw/lib/libhyprNStack.so")
|
hl.plugin.load("/run/current-system/sw/lib/libhyprNStack.so")
|
||||||
end
|
end
|
||||||
@@ -9,7 +13,7 @@ function M.setup(ctx)
|
|||||||
hl.plugin.load("/run/current-system/sw/lib/libhyprexpo.so")
|
hl.plugin.load("/run/current-system/sw/lib/libhyprexpo.so")
|
||||||
end
|
end
|
||||||
if enable_hyprspace and not verify_config then
|
if enable_hyprspace and not verify_config then
|
||||||
hl.plugin.load("/run/current-system/sw/lib/libHyprspace.so")
|
hl.plugin.load(plugin_path("HYPRLAND_HYPRSPACE_PLUGIN", "/run/current-system/sw/lib/libHyprspace.so"))
|
||||||
end
|
end
|
||||||
if enable_hyprwinview and not verify_config then
|
if enable_hyprwinview and not verify_config then
|
||||||
hl.plugin.load("/run/current-system/sw/lib/libhyprwinview.so")
|
hl.plugin.load("/run/current-system/sw/lib/libhyprwinview.so")
|
||||||
@@ -17,6 +21,9 @@ function M.setup(ctx)
|
|||||||
if enable_workspace_history and not verify_config then
|
if enable_workspace_history and not verify_config then
|
||||||
hl.plugin.load("/run/current-system/sw/lib/libhypr-workspace-history.so")
|
hl.plugin.load("/run/current-system/sw/lib/libhypr-workspace-history.so")
|
||||||
end
|
end
|
||||||
|
if enable_hyprwobbly and not verify_config then
|
||||||
|
hl.plugin.load("/run/current-system/sw/lib/libhyprwobbly.so")
|
||||||
|
end
|
||||||
if enable_hyprglass and not verify_config then
|
if enable_hyprglass and not verify_config then
|
||||||
hl.plugin.load("/run/current-system/sw/lib/hyprglass.so")
|
hl.plugin.load("/run/current-system/sw/lib/hyprglass.so")
|
||||||
end
|
end
|
||||||
@@ -173,6 +180,71 @@ function M.setup(ctx)
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function apply_hyprwobbly_config()
|
||||||
|
if verify_config or not enable_hyprwobbly then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
hl.config({
|
||||||
|
plugin = {
|
||||||
|
hyprwobbly = {
|
||||||
|
enabled = hypr_visual_performance_mode and 0 or 1,
|
||||||
|
mode = "always",
|
||||||
|
grid_width = 4,
|
||||||
|
grid_height = 4,
|
||||||
|
tiles_x = 12,
|
||||||
|
tiles_y = 12,
|
||||||
|
spring_k = 18.0,
|
||||||
|
friction = 8.0,
|
||||||
|
mass = 12.0,
|
||||||
|
move_factor = 0.65,
|
||||||
|
resize_factor = 0.45,
|
||||||
|
max_warp = 140.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
local function apply_visual_performance_mode()
|
||||||
|
if verify_config then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local visual_effects_enabled = not hypr_visual_performance_mode
|
||||||
|
hl.config({
|
||||||
|
decoration = {
|
||||||
|
blur = {
|
||||||
|
enabled = visual_effects_enabled,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
animations = {
|
||||||
|
enabled = visual_effects_enabled,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if enable_hyprwobbly then
|
||||||
|
hl.config({
|
||||||
|
plugin = {
|
||||||
|
hyprwobbly = {
|
||||||
|
enabled = visual_effects_enabled and 1 or 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function toggle_visual_performance_mode()
|
||||||
|
hypr_visual_performance_mode = not hypr_visual_performance_mode
|
||||||
|
apply_visual_performance_mode()
|
||||||
|
hl.notification.create({
|
||||||
|
text = "Hyprland performance mode: " .. (hypr_visual_performance_mode and "on" or "off"),
|
||||||
|
duration = 1800,
|
||||||
|
icon = hypr_visual_performance_mode and notification_icons.warning or notification_icons.ok,
|
||||||
|
color = hypr_visual_performance_mode and "rgba(edb443ff)" or "rgba(33ccffee)",
|
||||||
|
font_size = 13,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
local function apply_rules()
|
local function apply_rules()
|
||||||
if verify_config then
|
if verify_config then
|
||||||
return
|
return
|
||||||
@@ -243,6 +315,9 @@ function M.setup(ctx)
|
|||||||
|
|
||||||
ctx.apply_rules = apply_rules
|
ctx.apply_rules = apply_rules
|
||||||
ctx.apply_hyprglass_config = apply_hyprglass_config
|
ctx.apply_hyprglass_config = apply_hyprglass_config
|
||||||
|
ctx.apply_hyprwobbly_config = apply_hyprwobbly_config
|
||||||
|
ctx.apply_visual_performance_mode = apply_visual_performance_mode
|
||||||
|
ctx.toggle_visual_performance_mode = toggle_visual_performance_mode
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
|
local function env_bool(name, default)
|
||||||
|
local value = os.getenv(name)
|
||||||
|
if value == nil or value == "" then
|
||||||
|
return default
|
||||||
|
end
|
||||||
|
|
||||||
|
value = value:lower()
|
||||||
|
if value == "1" or value == "true" or value == "yes" or value == "on" then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if value == "0" or value == "false" or value == "no" or value == "off" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return default
|
||||||
|
end
|
||||||
|
|
||||||
local shell_ui_command = "hypr_shell_ui"
|
local shell_ui_command = "hypr_shell_ui"
|
||||||
local columns_layout = "nStack"
|
local columns_layout = "nStack"
|
||||||
local large_main_layout = "master"
|
local large_main_layout = "master"
|
||||||
@@ -46,10 +63,12 @@ return {
|
|||||||
current_layout = columns_layout,
|
current_layout = columns_layout,
|
||||||
enable_nstack = true,
|
enable_nstack = true,
|
||||||
enable_hyprexpo = true,
|
enable_hyprexpo = true,
|
||||||
enable_hyprspace = false,
|
enable_hyprspace = env_bool("HYPRLAND_ENABLE_HYPRSPACE", false),
|
||||||
enable_hyprwinview = true,
|
enable_hyprwinview = true,
|
||||||
enable_workspace_history = true,
|
enable_workspace_history = true,
|
||||||
|
enable_hyprwobbly = true,
|
||||||
enable_hyprglass = false,
|
enable_hyprglass = false,
|
||||||
|
hypr_visual_performance_mode = false,
|
||||||
configure_nstack_plugin_from_lua = false,
|
configure_nstack_plugin_from_lua = false,
|
||||||
workspace_layouts = {},
|
workspace_layouts = {},
|
||||||
minimized_windows = {},
|
minimized_windows = {},
|
||||||
|
|||||||
Submodule dotfiles/config/taffybar/taffybar updated: b4b98bf8a2...368f6a40a2
87
dotfiles/lib/bin/hypr_perf_snapshot
Executable file
87
dotfiles/lib/bin/hypr_perf_snapshot
Executable file
@@ -0,0 +1,87 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -u
|
||||||
|
|
||||||
|
runtime_dir="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
|
||||||
|
timestamp="$(date +%Y%m%d-%H%M%S)"
|
||||||
|
out="${1:-$runtime_dir/hypr-perf-snapshot-$timestamp.log}"
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "$out")"
|
||||||
|
|
||||||
|
latest_hypr_instance() {
|
||||||
|
local hypr_dir="$runtime_dir/hypr"
|
||||||
|
[[ -d "$hypr_dir" ]] || return 1
|
||||||
|
find "$hypr_dir" -mindepth 2 -maxdepth 2 -name .socket.sock -printf '%T@ %h\n' 2>/dev/null |
|
||||||
|
sort -nr |
|
||||||
|
awk 'NR == 1 { n = split($2, parts, "/"); print parts[n] }'
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ -z "${HYPRLAND_INSTANCE_SIGNATURE:-}" ]]; then
|
||||||
|
signature="$(latest_hypr_instance || true)"
|
||||||
|
if [[ -n "$signature" ]]; then
|
||||||
|
export HYPRLAND_INSTANCE_SIGNATURE="$signature"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
section() {
|
||||||
|
printf '\n## %s\n' "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_optional() {
|
||||||
|
local label="$1"
|
||||||
|
shift
|
||||||
|
section "$label"
|
||||||
|
"$@" 2>&1 || true
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
section "Snapshot"
|
||||||
|
date --iso-8601=seconds
|
||||||
|
printf 'host=%s\n' "$(hostname)"
|
||||||
|
printf 'runtime_dir=%s\n' "$runtime_dir"
|
||||||
|
printf 'hyprland_instance=%s\n' "${HYPRLAND_INSTANCE_SIGNATURE:-}"
|
||||||
|
uptime
|
||||||
|
printf 'loadavg='
|
||||||
|
cat /proc/loadavg 2>/dev/null || true
|
||||||
|
|
||||||
|
if command -v hyprctl >/dev/null 2>&1; then
|
||||||
|
run_optional "Hyprland Version" hyprctl version
|
||||||
|
run_optional "Hyprland Monitors" hyprctl monitors
|
||||||
|
plugins="$(hyprctl plugin list 2>&1 || true)"
|
||||||
|
section "Hyprland Plugins"
|
||||||
|
printf '%s\n' "$plugins"
|
||||||
|
section "Hyprland Runtime Options"
|
||||||
|
for option in \
|
||||||
|
animations:enabled \
|
||||||
|
decoration:blur:enabled \
|
||||||
|
render:direct_scanout; do
|
||||||
|
printf '\n### %s\n' "$option"
|
||||||
|
hyprctl getoption "$option" 2>&1 || true
|
||||||
|
done
|
||||||
|
if printf '%s\n' "$plugins" | grep -q 'Plugin hyprwobbly'; then
|
||||||
|
printf '\n### plugin:hyprwobbly:enabled\n'
|
||||||
|
hyprctl getoption plugin:hyprwobbly:enabled 2>&1 || true
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
section "Hyprland"
|
||||||
|
printf 'hyprctl not found\n'
|
||||||
|
fi
|
||||||
|
|
||||||
|
run_optional "Top Processes By CPU" ps -eo pid,ppid,comm,pcpu,pmem,args --sort=-pcpu
|
||||||
|
run_optional "Top Threads By CPU" ps -eLo pid,tid,comm,pcpu,pmem --sort=-pcpu
|
||||||
|
|
||||||
|
if command -v nvidia-smi >/dev/null 2>&1; then
|
||||||
|
run_optional "NVIDIA GPU" nvidia-smi
|
||||||
|
fi
|
||||||
|
|
||||||
|
section "DRM GPU Busy"
|
||||||
|
for busy in /sys/class/drm/card*/device/gpu_busy_percent; do
|
||||||
|
[[ -e "$busy" ]] || continue
|
||||||
|
printf '%s=' "$busy"
|
||||||
|
cat "$busy" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
|
||||||
|
section "Recent User Unit Failures"
|
||||||
|
systemctl --user --no-pager --failed 2>&1 || true
|
||||||
|
} >"$out"
|
||||||
|
|
||||||
|
printf '%s\n' "$out"
|
||||||
416
dotfiles/lib/bin/hypr_plugin_dev_session
Executable file
416
dotfiles/lib/bin/hypr_plugin_dev_session
Executable file
@@ -0,0 +1,416 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage: hypr_plugin_dev_session [options]
|
||||||
|
|
||||||
|
Launch a disposable nested Hyprland compositor for plugin development, then
|
||||||
|
build/load a plugin only into that nested instance.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--repo DIR Plugin repo to build. Defaults to $PWD if it has a flake,
|
||||||
|
otherwise /home/imalison/Projects/hyprwobbly when present.
|
||||||
|
--attr ATTR Nix build attr. Default: .#hyprwobbly
|
||||||
|
--plugin PATH Load an already-built plugin .so instead of building.
|
||||||
|
--hyprland-bin PATH Hyprland binary to run. Defaults to the plugin repo's
|
||||||
|
Hyprland flake input when building, otherwise PATH.
|
||||||
|
--system-hyprland Force /run/current-system/PATH Hyprland instead of the
|
||||||
|
plugin repo's Hyprland flake input.
|
||||||
|
--config PATH Run Hyprland with this config instead of a generated
|
||||||
|
minimal config.
|
||||||
|
--user-config Run the normal user Lua config.
|
||||||
|
--enable-hyprspace Set HYPRLAND_ENABLE_HYPRSPACE=1 for the nested config.
|
||||||
|
--no-load Start the nested compositor but do not load a plugin.
|
||||||
|
--detach Leave the nested compositor running and exit after setup.
|
||||||
|
--keep-tmp Do not delete the generated config/log directory.
|
||||||
|
--size WxH Nested monitor size. Default: 1280x720
|
||||||
|
--terminal COMMAND Command to open in the nested compositor.
|
||||||
|
--exit-after-ready Exit the nested compositor after startup checks.
|
||||||
|
-h, --help Show this help.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
hypr_plugin_dev_session
|
||||||
|
hypr_plugin_dev_session --repo ~/Projects/hyprwobbly --attr .#hyprwobbly
|
||||||
|
hypr_plugin_dev_session --plugin "$PWD/result/lib/libhyprwobbly.so"
|
||||||
|
hypr_plugin_dev_session --user-config --enable-hyprspace --no-load
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
die() {
|
||||||
|
printf 'hypr_plugin_dev_session: %s\n' "$*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime_dir="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
|
||||||
|
repo=""
|
||||||
|
attr=".#hyprwobbly"
|
||||||
|
plugin_path=""
|
||||||
|
plugin_path_from_arg=0
|
||||||
|
hyprland_bin=""
|
||||||
|
force_system_hyprland=0
|
||||||
|
load_plugin=1
|
||||||
|
config_arg=""
|
||||||
|
enable_hyprspace=0
|
||||||
|
detach=0
|
||||||
|
keep_tmp=0
|
||||||
|
size="1280x720"
|
||||||
|
terminal_cmd=""
|
||||||
|
exit_after_ready=0
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--repo)
|
||||||
|
repo="${2:-}"
|
||||||
|
[[ -n "$repo" ]] || die "--repo requires a directory"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--attr)
|
||||||
|
attr="${2:-}"
|
||||||
|
[[ -n "$attr" ]] || die "--attr requires a Nix attr"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--plugin)
|
||||||
|
plugin_path="${2:-}"
|
||||||
|
[[ -n "$plugin_path" ]] || die "--plugin requires a path"
|
||||||
|
plugin_path_from_arg=1
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--hyprland-bin)
|
||||||
|
hyprland_bin="${2:-}"
|
||||||
|
[[ -n "$hyprland_bin" ]] || die "--hyprland-bin requires a path"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--system-hyprland)
|
||||||
|
force_system_hyprland=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--config)
|
||||||
|
config_arg="${2:-}"
|
||||||
|
[[ -n "$config_arg" ]] || die "--config requires a path"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--user-config)
|
||||||
|
config_arg="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/hyprland.lua"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--enable-hyprspace)
|
||||||
|
enable_hyprspace=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--no-load)
|
||||||
|
load_plugin=0
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--detach)
|
||||||
|
detach=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--keep-tmp)
|
||||||
|
keep_tmp=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--size)
|
||||||
|
size="${2:-}"
|
||||||
|
[[ "$size" =~ ^[0-9]+x[0-9]+$ ]] || die "--size must look like 1280x720"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--terminal)
|
||||||
|
terminal_cmd="${2:-}"
|
||||||
|
[[ -n "$terminal_cmd" ]] || die "--terminal requires a command"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--exit-after-ready)
|
||||||
|
exit_after_ready=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h | --help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
die "unknown argument: $1"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
command -v hyprctl >/dev/null 2>&1 || die "hyprctl is not on PATH"
|
||||||
|
command -v jq >/dev/null 2>&1 || die "jq is not on PATH"
|
||||||
|
|
||||||
|
parent_wayland_display() {
|
||||||
|
if [[ -n "${WAYLAND_DISPLAY:-}" && -S "$runtime_dir/$WAYLAND_DISPLAY" ]]; then
|
||||||
|
printf '%s\n' "$WAYLAND_DISPLAY"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local from_instances
|
||||||
|
from_instances="$(hyprctl instances -j 2>/dev/null | jq -r 'max_by(.time) | .wl_socket // empty' 2>/dev/null || true)"
|
||||||
|
if [[ -n "$from_instances" && -S "$runtime_dir/$from_instances" ]]; then
|
||||||
|
printf '%s\n' "$from_instances"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local lock
|
||||||
|
lock="$(find "$runtime_dir/hypr" -mindepth 2 -maxdepth 2 -name hyprland.lock -printf '%T@ %p\n' 2>/dev/null | sort -nr | awk 'NR == 1 { print $2 }')"
|
||||||
|
if [[ -n "$lock" ]]; then
|
||||||
|
local from_lock
|
||||||
|
from_lock="$(sed -n '2p' "$lock" 2>/dev/null || true)"
|
||||||
|
if [[ -n "$from_lock" && -S "$runtime_dir/$from_lock" ]]; then
|
||||||
|
printf '%s\n' "$from_lock"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ -z "$repo" ]]; then
|
||||||
|
if [[ -f "$PWD/flake.nix" ]]; then
|
||||||
|
repo="$PWD"
|
||||||
|
elif [[ -d /home/imalison/Projects/hyprwobbly ]]; then
|
||||||
|
repo="/home/imalison/Projects/hyprwobbly"
|
||||||
|
else
|
||||||
|
repo="$PWD"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
repo="$(realpath "$repo")"
|
||||||
|
|
||||||
|
if [[ -n "$plugin_path" ]]; then
|
||||||
|
plugin_path="$(realpath "$plugin_path")"
|
||||||
|
[[ -f "$plugin_path" ]] || die "plugin does not exist: $plugin_path"
|
||||||
|
fi
|
||||||
|
|
||||||
|
choose_terminal() {
|
||||||
|
if [[ -n "$terminal_cmd" ]]; then
|
||||||
|
printf '%s\n' "$terminal_cmd"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
for candidate in ghostty foot kitty alacritty wezterm xterm; do
|
||||||
|
if command -v "$candidate" >/dev/null 2>&1; then
|
||||||
|
printf '%s\n' "$candidate"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
printf '%s\n' 'sh -lc "sleep infinity"'
|
||||||
|
}
|
||||||
|
|
||||||
|
find_built_plugin() {
|
||||||
|
local result_dir="$repo/result"
|
||||||
|
[[ -e "$result_dir" ]] || die "build result missing: $result_dir"
|
||||||
|
|
||||||
|
local preferred="$result_dir/lib/libhyprwobbly.so"
|
||||||
|
if [[ -f "$preferred" ]]; then
|
||||||
|
printf '%s\n' "$(realpath "$preferred")"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local count
|
||||||
|
count="$(find -L "$result_dir" -type f -name '*.so' | wc -l)"
|
||||||
|
[[ "$count" -gt 0 ]] || die "no .so files found under $result_dir"
|
||||||
|
[[ "$count" -eq 1 ]] || die "multiple .so files found under $result_dir; pass --plugin explicitly"
|
||||||
|
find -L "$result_dir" -type f -name '*.so' -print -quit
|
||||||
|
}
|
||||||
|
|
||||||
|
repo_hyprland_bin() {
|
||||||
|
local flake_ref expr out
|
||||||
|
flake_ref="$(jq -Rn --arg s "path:$repo" '$s')"
|
||||||
|
expr="let flake = builtins.getFlake ${flake_ref}; system = builtins.currentSystem; in flake.inputs.hyprland.packages.\${system}.hyprland"
|
||||||
|
|
||||||
|
printf 'Building matching nested Hyprland from %s input\n' "$repo" >&2
|
||||||
|
mapfile -t hyprland_outputs < <(nix build --impure --no-link --print-out-paths --expr "$expr")
|
||||||
|
for out in "${hyprland_outputs[@]}"; do
|
||||||
|
if [[ -x "$out/bin/Hyprland" ]]; then
|
||||||
|
printf '%s\n' "$out/bin/Hyprland"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
pid=""
|
||||||
|
tail_pid=""
|
||||||
|
tmpdir="$(mktemp -d "$runtime_dir/hypr-plugin-dev.XXXXXX")"
|
||||||
|
config="$tmpdir/hyprland.conf"
|
||||||
|
stdout_log="$tmpdir/hyprland.stdout.log"
|
||||||
|
|
||||||
|
if [[ -n "$config_arg" ]]; then
|
||||||
|
config="$(realpath "$config_arg")"
|
||||||
|
[[ -f "$config" ]] || die "config does not exist: $config"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
local status=$?
|
||||||
|
|
||||||
|
if [[ -n "$tail_pid" ]] && kill -0 "$tail_pid" >/dev/null 2>&1; then
|
||||||
|
kill "$tail_pid" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$detach" -eq 0 && -n "$pid" ]] && kill -0 "$pid" >/dev/null 2>&1; then
|
||||||
|
if [[ -n "${nested_sig:-}" ]]; then
|
||||||
|
HYPRLAND_INSTANCE_SIGNATURE="$nested_sig" hyprctl dispatch exit >/dev/null 2>&1 || true
|
||||||
|
sleep 0.5
|
||||||
|
fi
|
||||||
|
kill -- "-$pid" >/dev/null 2>&1 || true
|
||||||
|
kill "$pid" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$keep_tmp" -eq 0 && "$detach" -eq 0 ]]; then
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit "$status"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT INT TERM
|
||||||
|
|
||||||
|
if [[ -z "$config_arg" ]]; then
|
||||||
|
term_for_config="$(choose_terminal)"
|
||||||
|
cat >"$config" <<EOF
|
||||||
|
autogenerated = 1
|
||||||
|
|
||||||
|
debug {
|
||||||
|
disable_logs = false
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor = , ${size}@60, 0x0, 1
|
||||||
|
|
||||||
|
general {
|
||||||
|
layout = dwindle
|
||||||
|
gaps_in = 4
|
||||||
|
gaps_out = 8
|
||||||
|
border_size = 2
|
||||||
|
col.active_border = rgba(33ccffee)
|
||||||
|
col.inactive_border = rgba(595959aa)
|
||||||
|
}
|
||||||
|
|
||||||
|
decoration {
|
||||||
|
rounding = 4
|
||||||
|
shadow {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
blur {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
animations {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
kb_layout = us
|
||||||
|
follow_mouse = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
misc {
|
||||||
|
disable_hyprland_logo = true
|
||||||
|
disable_splash_rendering = true
|
||||||
|
force_default_wallpaper = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
bind = SUPER, Return, exec, ${term_for_config}
|
||||||
|
bind = SUPER, Q, killactive
|
||||||
|
bind = SUPER SHIFT, Q, exit
|
||||||
|
bind = SUPER, F, fullscreen
|
||||||
|
bind = SUPER, V, togglefloating
|
||||||
|
|
||||||
|
exec-once = ${term_for_config}
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$load_plugin" -eq 1 && -z "$plugin_path" ]]; then
|
||||||
|
[[ -d "$repo" ]] || die "repo does not exist: $repo"
|
||||||
|
[[ -f "$repo/flake.nix" ]] || die "repo has no flake.nix: $repo"
|
||||||
|
printf 'Building %s in %s\n' "$attr" "$repo"
|
||||||
|
(cd "$repo" && nix build "$attr" --print-build-logs)
|
||||||
|
plugin_path="$(find_built_plugin)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$hyprland_bin" ]]; then
|
||||||
|
hyprland_bin="$(realpath "$hyprland_bin")"
|
||||||
|
elif [[ "$force_system_hyprland" -eq 0 && "$load_plugin" -eq 1 && -n "$repo" && "$plugin_path_from_arg" -eq 0 ]]; then
|
||||||
|
hyprland_bin="$(repo_hyprland_bin)" || die "could not build matching Hyprland from $repo input"
|
||||||
|
else
|
||||||
|
hyprland_bin="$(command -v Hyprland || true)"
|
||||||
|
fi
|
||||||
|
[[ -n "$hyprland_bin" && -x "$hyprland_bin" ]] || die "Hyprland binary not found or not executable"
|
||||||
|
|
||||||
|
printf 'Starting nested Hyprland with config %s\n' "$config"
|
||||||
|
parent_wayland="$(parent_wayland_display || true)"
|
||||||
|
[[ -n "$parent_wayland" ]] || die "could not find a parent Wayland socket; set WAYLAND_DISPLAY and try again"
|
||||||
|
printf 'Parent Wayland display: %s\n' "$parent_wayland"
|
||||||
|
printf 'Nested Hyprland binary: %s\n' "$hyprland_bin"
|
||||||
|
setsid env \
|
||||||
|
-u HYPRLAND_INSTANCE_SIGNATURE \
|
||||||
|
WAYLAND_DISPLAY="$parent_wayland" \
|
||||||
|
XDG_SESSION_TYPE=wayland \
|
||||||
|
IMALISON_HYPRLAND_DEV_SESSION=1 \
|
||||||
|
HYPRLAND_ENABLE_HYPRSPACE="$enable_hyprspace" \
|
||||||
|
bash -c 'trap "" HUP; exec "$1" --config "$2"' hyprland-launch "$hyprland_bin" "$config" >"$stdout_log" 2>&1 &
|
||||||
|
pid=$!
|
||||||
|
|
||||||
|
nested_sig=""
|
||||||
|
for _ in $(seq 1 100); do
|
||||||
|
if ! kill -0 "$pid" >/dev/null 2>&1; then
|
||||||
|
printf 'Nested Hyprland exited before becoming ready. Log follows:\n' >&2
|
||||||
|
sed -n '1,220p' "$stdout_log" >&2 || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
nested_sig="$(hyprctl instances -j 2>/dev/null | jq -r --argjson pid "$pid" '.[] | select(.pid == $pid) | .instance' | head -n1)"
|
||||||
|
if [[ -n "$nested_sig" && "$nested_sig" != "null" ]]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 0.1
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ -n "$nested_sig" && "$nested_sig" != "null" ]] || die "timed out waiting for nested Hyprland instance for pid $pid"
|
||||||
|
|
||||||
|
printf 'Nested Hyprland pid: %s\n' "$pid"
|
||||||
|
printf 'Nested Hyprland signature: %s\n' "$nested_sig"
|
||||||
|
printf 'Nested Hyprland log: %s\n' "$stdout_log"
|
||||||
|
printf 'Target it with:\n HYPRLAND_INSTANCE_SIGNATURE=%q hyprctl ...\n' "$nested_sig"
|
||||||
|
|
||||||
|
HYPRLAND_INSTANCE_SIGNATURE="$nested_sig" hyprctl monitors >/dev/null
|
||||||
|
HYPRLAND_INSTANCE_SIGNATURE="$nested_sig" hyprctl configerrors || true
|
||||||
|
|
||||||
|
if [[ "$load_plugin" -eq 1 ]]; then
|
||||||
|
printf 'Loading plugin into nested Hyprland: %s\n' "$plugin_path"
|
||||||
|
load_output="$(HYPRLAND_INSTANCE_SIGNATURE="$nested_sig" hyprctl plugin load "$plugin_path" 2>&1)"
|
||||||
|
load_status=$?
|
||||||
|
printf '%s\n' "$load_output"
|
||||||
|
sleep 0.5
|
||||||
|
|
||||||
|
if ! kill -0 "$pid" >/dev/null 2>&1; then
|
||||||
|
printf 'Nested Hyprland crashed while loading plugin. Log follows:\n' >&2
|
||||||
|
sed -n '1,260p' "$stdout_log" >&2 || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
plugin_list="$(HYPRLAND_INSTANCE_SIGNATURE="$nested_sig" hyprctl plugin list 2>&1)"
|
||||||
|
printf '%s\n' "$plugin_list"
|
||||||
|
if [[ "$load_status" -ne 0 || "$load_output" == *"could not be loaded"* || "$plugin_list" == *"no plugins loaded"* ]]; then
|
||||||
|
die "plugin did not load into nested Hyprland"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$exit_after_ready" -eq 1 ]]; then
|
||||||
|
printf 'Startup check complete; exiting nested Hyprland.\n'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$detach" -eq 1 ]]; then
|
||||||
|
trap - EXIT INT TERM
|
||||||
|
disown "$pid" >/dev/null 2>&1 || true
|
||||||
|
printf 'Leaving nested Hyprland running. Stop it with:\n HYPRLAND_INSTANCE_SIGNATURE=%q hyprctl dispatch exit\n' "$nested_sig"
|
||||||
|
printf 'If the Nix wrapper process remains, clean up its process group with:\n kill -- -%q\n' "$pid"
|
||||||
|
printf 'Generated files remain in %s\n' "$tmpdir"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf 'Nested session is running. Press Ctrl-C here to stop it.\n'
|
||||||
|
tail -n +1 -F "$stdout_log" &
|
||||||
|
tail_pid=$!
|
||||||
|
wait "$pid"
|
||||||
64
nixos/flake.lock
generated
64
nixos/flake.lock
generated
@@ -10,11 +10,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1778647860,
|
"lastModified": 1778761768,
|
||||||
"narHash": "sha256-WIHQcCdzY/2MYYtVZyGkctjsISTsjHLVuunJXt5g92c=",
|
"narHash": "sha256-1i9S0IRjUuz98ab9/V2+5ax5YxIDhvl7NuMlBVXJ328=",
|
||||||
"owner": "colonelpanic8",
|
"owner": "colonelpanic8",
|
||||||
"repo": "Hyprspace",
|
"repo": "Hyprspace",
|
||||||
"rev": "a9d7685ef610d5a45c7c4f9f974bdf78443c9829",
|
"rev": "2ca4f1a47cf2dc569e6e7034e53c4cd9b25e36a8",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -161,16 +161,16 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1778574539,
|
"lastModified": 1778822718,
|
||||||
"narHash": "sha256-4wOF2LWLxWCzE2B7Nud9GZuXGEAWJwvp8XrWx+3p5aY=",
|
"narHash": "sha256-2CTjJUnLhYJIu8hW/Gmdhbhvp7RbBYY1mBFNYvzBpxE=",
|
||||||
"owner": "colonelpanic8",
|
"owner": "colonelpanic8",
|
||||||
"repo": "codex-desktop-linux",
|
"repo": "codex-desktop-linux",
|
||||||
"rev": "39671f3a944cdc68d216bd3fcf1f53a5de5c39a9",
|
"rev": "31c94dd2edfd9a86df263baaec33779123a120f3",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "colonelpanic8",
|
"owner": "colonelpanic8",
|
||||||
"ref": "codex/nixos-browser-cache-fixes",
|
"ref": "reenable-computer-use-in-nix",
|
||||||
"repo": "codex-desktop-linux",
|
"repo": "codex-desktop-linux",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
@@ -817,28 +817,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"hyprexpo": {
|
"hyprexpo": {
|
||||||
"inputs": {
|
"flake": false,
|
||||||
"hyprland": [
|
|
||||||
"hyprland"
|
|
||||||
],
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"systems": [
|
|
||||||
"systems"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1778658902,
|
"lastModified": 1778816761,
|
||||||
"narHash": "sha256-k2RpS0zA76KZBMR6Uy+WSRJBR6uDsa5m0FxfVKH01PE=",
|
"narHash": "sha256-+riuSr1jdxdhfYNtt6S5a6uUUDhYb67gDRKHpk7l1pg=",
|
||||||
"owner": "colonelpanic8",
|
"owner": "colonelpanic8",
|
||||||
"repo": "hyprexpo",
|
"repo": "hyprexpo-plus",
|
||||||
"rev": "d2786e7c21f412e0f60cc27d6763e9939ef284b0",
|
"rev": "4d753224148c45153dbea95b3d6b1897bd71dfbb",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "colonelpanic8",
|
"owner": "colonelpanic8",
|
||||||
"repo": "hyprexpo",
|
"ref": "codex/lua-config-api",
|
||||||
|
"repo": "hyprexpo-plus",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1202,6 +1193,32 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"hyprwobbly": {
|
||||||
|
"inputs": {
|
||||||
|
"hyprland": [
|
||||||
|
"hyprland"
|
||||||
|
],
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"systems": [
|
||||||
|
"systems"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1778742689,
|
||||||
|
"narHash": "sha256-j0/j9/9Pd5nC3jXsLrq9GKshcSg1Ci55E1gg7Qj84Y8=",
|
||||||
|
"owner": "colonelpanic8",
|
||||||
|
"repo": "hyprwobbly",
|
||||||
|
"rev": "d531d3f0b68d6d450bf3038571043c3f39c1fd6e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "colonelpanic8",
|
||||||
|
"repo": "hyprwobbly",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"imalison-taffybar": {
|
"imalison-taffybar": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": [
|
"flake-utils": [
|
||||||
@@ -1801,6 +1818,7 @@
|
|||||||
"hyprutils"
|
"hyprutils"
|
||||||
],
|
],
|
||||||
"hyprwinview": "hyprwinview",
|
"hyprwinview": "hyprwinview",
|
||||||
|
"hyprwobbly": "hyprwobbly",
|
||||||
"imalison-taffybar": "imalison-taffybar",
|
"imalison-taffybar": "imalison-taffybar",
|
||||||
"kanshi-sni": "kanshi-sni",
|
"kanshi-sni": "kanshi-sni",
|
||||||
"keepbook": "keepbook",
|
"keepbook": "keepbook",
|
||||||
|
|||||||
@@ -116,12 +116,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
hyprexpo = {
|
hyprexpo = {
|
||||||
url = "github:colonelpanic8/hyprexpo";
|
url = "github:colonelpanic8/hyprexpo-plus/codex/lua-config-api";
|
||||||
inputs = {
|
flake = false;
|
||||||
hyprland.follows = "hyprland";
|
|
||||||
nixpkgs.follows = "nixpkgs";
|
|
||||||
systems.follows = "systems";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Hyprspace = {
|
Hyprspace = {
|
||||||
@@ -143,6 +139,15 @@
|
|||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
hyprwobbly = {
|
||||||
|
url = "github:colonelpanic8/hyprwobbly";
|
||||||
|
inputs = {
|
||||||
|
hyprland.follows = "hyprland";
|
||||||
|
nixpkgs.follows = "nixpkgs";
|
||||||
|
systems.follows = "systems";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
hyprglass = {
|
hyprglass = {
|
||||||
url = "github:colonelpanic8/hyprglass?ref=codex/hyprland-0.55-compat";
|
url = "github:colonelpanic8/hyprglass?ref=codex/hyprland-0.55-compat";
|
||||||
flake = false;
|
flake = false;
|
||||||
@@ -238,7 +243,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
codex-desktop-linux = {
|
codex-desktop-linux = {
|
||||||
url = "github:colonelpanic8/codex-desktop-linux?ref=codex/nixos-browser-cache-fixes";
|
url = "github:colonelpanic8/codex-desktop-linux?ref=reenable-computer-use-in-nix";
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.follows = "nixpkgs";
|
nixpkgs.follows = "nixpkgs";
|
||||||
flake-utils.follows = "flake-utils";
|
flake-utils.follows = "flake-utils";
|
||||||
|
|||||||
@@ -26,6 +26,15 @@
|
|||||||
hyprlang = inputs.hyprlang.packages.${system}.hyprlang;
|
hyprlang = inputs.hyprlang.packages.${system}.hyprlang;
|
||||||
hyprutils = inputs.hyprutils.packages.${system}.hyprutils;
|
hyprutils = inputs.hyprutils.packages.${system}.hyprutils;
|
||||||
};
|
};
|
||||||
|
hyprexpo = pkgs.callPackage ../packages/hyprexpo-plus {
|
||||||
|
src = inputs.hyprexpo;
|
||||||
|
hyprland = inputs.hyprland.packages.${system}.hyprland;
|
||||||
|
aquamarine = inputs.aquamarine.packages.${system}.aquamarine;
|
||||||
|
hyprcursor = inputs.hyprcursor.packages.${system}.hyprcursor;
|
||||||
|
hyprgraphics = inputs.hyprgraphics.packages.${system}.hyprgraphics;
|
||||||
|
hyprlang = inputs.hyprlang.packages.${system}.hyprlang;
|
||||||
|
hyprutils = inputs.hyprutils.packages.${system}.hyprutils;
|
||||||
|
};
|
||||||
tangledConfig = dotfilesOrgApi.org-agenda-custom-config;
|
tangledConfig = dotfilesOrgApi.org-agenda-custom-config;
|
||||||
|
|
||||||
# Import container build logic
|
# Import container build logic
|
||||||
@@ -42,7 +51,7 @@ in {
|
|||||||
}
|
}
|
||||||
// lib.optionalAttrs pkgs.stdenv.isLinux {
|
// lib.optionalAttrs pkgs.stdenv.isLinux {
|
||||||
hyprNStack = inputs.hyprNStack.packages.${system}.hyprNStack;
|
hyprNStack = inputs.hyprNStack.packages.${system}.hyprNStack;
|
||||||
hyprexpo-lua = inputs.hyprexpo.packages.${system}.hyprexpo;
|
hyprexpo-lua = hyprexpo;
|
||||||
hyprwinview = inputs.hyprwinview.packages.${system}.hyprwinview;
|
hyprwinview = inputs.hyprwinview.packages.${system}.hyprwinview;
|
||||||
hypr-workspace-history = inputs.hypr-workspace-history.packages.${system}.hypr-workspace-history;
|
hypr-workspace-history = inputs.hypr-workspace-history.packages.${system}.hypr-workspace-history;
|
||||||
inherit hyprglass;
|
inherit hyprglass;
|
||||||
@@ -60,7 +69,7 @@ in {
|
|||||||
}
|
}
|
||||||
// lib.optionalAttrs pkgs.stdenv.isLinux {
|
// lib.optionalAttrs pkgs.stdenv.isLinux {
|
||||||
hyprNStack = inputs.hyprNStack.packages.${system}.hyprNStack;
|
hyprNStack = inputs.hyprNStack.packages.${system}.hyprNStack;
|
||||||
hyprexpo-lua = inputs.hyprexpo.packages.${system}.hyprexpo;
|
hyprexpo-lua = hyprexpo;
|
||||||
hyprwinview = inputs.hyprwinview.packages.${system}.hyprwinview;
|
hyprwinview = inputs.hyprwinview.packages.${system}.hyprwinview;
|
||||||
hypr-workspace-history = inputs.hypr-workspace-history.packages.${system}.hypr-workspace-history;
|
hypr-workspace-history = inputs.hypr-workspace-history.packages.${system}.hypr-workspace-history;
|
||||||
inherit hyprglass;
|
inherit hyprglass;
|
||||||
|
|||||||
@@ -108,13 +108,30 @@
|
|||||||
hyprlang = inputs.hyprlang.packages.${system}.hyprlang;
|
hyprlang = inputs.hyprlang.packages.${system}.hyprlang;
|
||||||
hyprutils = inputs.hyprutils.packages.${system}.hyprutils;
|
hyprutils = inputs.hyprutils.packages.${system}.hyprutils;
|
||||||
};
|
};
|
||||||
|
hyprwobbly = inputs.hyprwobbly.packages.${system}.hyprwobbly.overrideAttrs (old: {
|
||||||
|
patches =
|
||||||
|
(old.patches or [])
|
||||||
|
++ [
|
||||||
|
./packages/hyprwobbly-safe-geometry-and-idle-timer.patch
|
||||||
|
];
|
||||||
|
});
|
||||||
|
hyprexpo = pkgs.callPackage ./packages/hyprexpo-plus {
|
||||||
|
src = inputs.hyprexpo;
|
||||||
|
hyprland = baseHyprlandPackage;
|
||||||
|
aquamarine = inputs.aquamarine.packages.${system}.aquamarine;
|
||||||
|
hyprcursor = inputs.hyprcursor.packages.${system}.hyprcursor;
|
||||||
|
hyprgraphics = inputs.hyprgraphics.packages.${system}.hyprgraphics;
|
||||||
|
hyprlang = inputs.hyprlang.packages.${system}.hyprlang;
|
||||||
|
hyprutils = inputs.hyprutils.packages.${system}.hyprutils;
|
||||||
|
};
|
||||||
hyprlandPluginPackages =
|
hyprlandPluginPackages =
|
||||||
[
|
[
|
||||||
inputs.hyprNStack.packages.${system}.hyprNStack
|
inputs.hyprNStack.packages.${system}.hyprNStack
|
||||||
inputs.hyprexpo.packages.${system}.hyprexpo
|
hyprexpo
|
||||||
hyprspace
|
hyprspace
|
||||||
inputs.hyprwinview.packages.${system}.hyprwinview
|
inputs.hyprwinview.packages.${system}.hyprwinview
|
||||||
inputs.hypr-workspace-history.packages.${system}.hypr-workspace-history
|
inputs.hypr-workspace-history.packages.${system}.hypr-workspace-history
|
||||||
|
hyprwobbly
|
||||||
]
|
]
|
||||||
++ lib.optionals enableHyprglass [hyprglass];
|
++ lib.optionals enableHyprglass [hyprglass];
|
||||||
hyprRofiWindow = pkgs.writeShellApplication {
|
hyprRofiWindow = pkgs.writeShellApplication {
|
||||||
|
|||||||
75
nixos/packages/hyprexpo-plus/default.nix
Normal file
75
nixos/packages/hyprexpo-plus/default.nix
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
stdenv,
|
||||||
|
lib,
|
||||||
|
cmake,
|
||||||
|
pkg-config,
|
||||||
|
aquamarine,
|
||||||
|
cairo,
|
||||||
|
glslang,
|
||||||
|
hyprland,
|
||||||
|
hyprcursor,
|
||||||
|
hyprgraphics,
|
||||||
|
hyprlang,
|
||||||
|
hyprutils,
|
||||||
|
libdrm,
|
||||||
|
libGL,
|
||||||
|
libinput,
|
||||||
|
libxcb,
|
||||||
|
libxcb-errors,
|
||||||
|
libxcb-wm,
|
||||||
|
libxkbcommon,
|
||||||
|
lua,
|
||||||
|
pango,
|
||||||
|
pixman,
|
||||||
|
systemd,
|
||||||
|
wayland,
|
||||||
|
src,
|
||||||
|
}:
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
pname = "hyprexpo-plus";
|
||||||
|
version = "unstable-${src.shortRev or "unknown"}";
|
||||||
|
inherit src;
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
cmake
|
||||||
|
pkg-config
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = [
|
||||||
|
aquamarine
|
||||||
|
cairo
|
||||||
|
glslang
|
||||||
|
hyprland
|
||||||
|
hyprcursor
|
||||||
|
hyprgraphics
|
||||||
|
hyprlang
|
||||||
|
hyprutils
|
||||||
|
libdrm
|
||||||
|
libGL
|
||||||
|
libinput
|
||||||
|
libxcb
|
||||||
|
libxcb-errors
|
||||||
|
libxcb-wm
|
||||||
|
libxkbcommon
|
||||||
|
lua
|
||||||
|
pango
|
||||||
|
pixman
|
||||||
|
systemd
|
||||||
|
wayland
|
||||||
|
];
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
install -Dm755 libhyprexpo.so "$out/lib/libhyprexpo.so"
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
description = "Enhanced Hyprland workspace overview plugin";
|
||||||
|
homepage = "https://github.com/sandwichfarm/hyprexpo-plus";
|
||||||
|
license = lib.licenses.bsd3;
|
||||||
|
platforms = lib.platforms.linux;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
diff --git a/src/main.cpp b/src/main.cpp
|
diff --git a/src/main.cpp b/src/main.cpp
|
||||||
index 9b75f8a..b69b459 100644
|
index 9dd0286..51fd8d7 100644
|
||||||
--- a/src/main.cpp
|
--- a/src/main.cpp
|
||||||
+++ b/src/main.cpp
|
+++ b/src/main.cpp
|
||||||
@@ -5,6 +5,7 @@
|
@@ -6,6 +6,7 @@
|
||||||
#include <hyprland/src/debug/log/Logger.hpp>
|
#include <hyprland/src/debug/log/Logger.hpp>
|
||||||
#include <hyprland/src/managers/SeatManager.hpp>
|
#include <hyprland/src/managers/SeatManager.hpp>
|
||||||
#include <hyprland/src/desktop/view/Window.hpp>
|
#include <hyprland/src/desktop/view/Window.hpp>
|
||||||
+#include <lua.hpp>
|
+#include <lua.hpp>
|
||||||
#include <hyprutils/memory/SharedPtr.hpp>
|
#include <hyprutils/memory/SharedPtr.hpp>
|
||||||
|
#include <any>
|
||||||
#include "Overview.hpp"
|
#include "Overview.hpp"
|
||||||
#include "Globals.hpp"
|
@@ -380,6 +381,65 @@ static SDispatchResult dispatchCloseOverview(std::string arg) {
|
||||||
@@ -377,6 +378,65 @@ static SDispatchResult dispatchCloseOverview(std::string arg) {
|
|
||||||
return SDispatchResult{};
|
return SDispatchResult{};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ index 9b75f8a..b69b459 100644
|
|||||||
void* findFunctionBySymbol(HANDLE inHandle, const std::string func, const std::string sym) {
|
void* findFunctionBySymbol(HANDLE inHandle, const std::string func, const std::string sym) {
|
||||||
// should return all functions
|
// should return all functions
|
||||||
auto funcSearch = HyprlandAPI::findFunctionsByName(inHandle, func);
|
auto funcSearch = HyprlandAPI::findFunctionsByName(inHandle, func);
|
||||||
@@ -516,6 +566,8 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE inHandle) {
|
@@ -545,6 +605,8 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE inHandle) {
|
||||||
HyprlandAPI::addDispatcherV2(pHandle, "overview:open", ::dispatchOpenOverview);
|
HyprlandAPI::addDispatcherV2(pHandle, "overview:open", ::dispatchOpenOverview);
|
||||||
HyprlandAPI::addDispatcherV2(pHandle, "overview:close", ::dispatchCloseOverview);
|
HyprlandAPI::addDispatcherV2(pHandle, "overview:close", ::dispatchCloseOverview);
|
||||||
|
|
||||||
|
|||||||
270
nixos/packages/hyprwobbly-safe-geometry-and-idle-timer.patch
Normal file
270
nixos/packages/hyprwobbly-safe-geometry-and-idle-timer.patch
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
diff --git a/Wobbly.cpp b/Wobbly.cpp
|
||||||
|
index d21594e..d8e1534 100644
|
||||||
|
--- a/Wobbly.cpp
|
||||||
|
+++ b/Wobbly.cpp
|
||||||
|
@@ -35,6 +35,18 @@ namespace {
|
||||||
|
Vector2D lerp(const Vector2D& a, const Vector2D& b, float t) {
|
||||||
|
return a + (b - a) * t;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ bool finite(double value) {
|
||||||
|
+ return std::isfinite(value) && std::abs(value) < 1000000.0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bool finite(const Vector2D& vec) {
|
||||||
|
+ return finite(vec.x) && finite(vec.y);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bool usableBox(const CBox& box) {
|
||||||
|
+ return finite(box.x) && finite(box.y) && finite(box.w) && finite(box.h) && box.w > 0.0 && box.h > 0.0;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
CWobblyTransformer::CWobblyTransformer(PHLWINDOW pWindow) : m_window(pWindow) {
|
||||||
|
@@ -50,6 +62,10 @@ bool CWobblyTransformer::belongsTo(PHLWINDOW pWindow) const {
|
||||||
|
return m_window.lock() == pWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
+bool CWobblyTransformer::active() const {
|
||||||
|
+ return m_active;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int CWobblyTransformer::gridWidth() const {
|
||||||
|
return std::clamp(cfgInt(g_pGridWidth, 4), 2, 16);
|
||||||
|
}
|
||||||
|
@@ -126,7 +142,10 @@ size_t CWobblyTransformer::index(int x, int y) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWobblyTransformer::resetModel(const Vector2D& size) {
|
||||||
|
- m_sizePx = {std::max(1.0, size.x), std::max(1.0, size.y)};
|
||||||
|
+ if (!finite(size))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ m_sizePx = {std::clamp(size.x, 1.0, 100000.0), std::clamp(size.y, 1.0, 100000.0)};
|
||||||
|
m_points.clear();
|
||||||
|
m_points.resize(sc<size_t>(gridWidth() * gridHeight()));
|
||||||
|
|
||||||
|
@@ -159,6 +178,9 @@ Vector2D CWobblyTransformer::currentPointerLocalPx(const CBox& boxLayout) const
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWobblyTransformer::applyMoveImpulse(const Vector2D& delta, const Vector2D& anchor) {
|
||||||
|
+ if (!finite(delta) || !finite(anchor))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
const auto DIAG = std::max(1.F, sc<float>(length(m_sizePx)));
|
||||||
|
|
||||||
|
for (auto& point : m_points) {
|
||||||
|
@@ -171,6 +193,9 @@ void CWobblyTransformer::applyMoveImpulse(const Vector2D& delta, const Vector2D&
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWobblyTransformer::applyResizeImpulse(const Vector2D& deltaSize) {
|
||||||
|
+ if (!finite(deltaSize))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
const auto oldSize = m_sizePx;
|
||||||
|
const auto oldPts = m_points;
|
||||||
|
|
||||||
|
@@ -216,12 +241,15 @@ void CWobblyTransformer::preWindowRender(CSurfacePassElement::SRenderData* pRend
|
||||||
|
pRenderData->h + topLeftExtents.y + bottomRightExtents.y,
|
||||||
|
};
|
||||||
|
|
||||||
|
- if (fullBox.empty())
|
||||||
|
+ if (!usableBox(fullBox) || fullBox.empty())
|
||||||
|
fullBox = {pRenderData->pos.x, pRenderData->pos.y, pRenderData->w, pRenderData->h};
|
||||||
|
|
||||||
|
+ if (!usableBox(fullBox))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
CBox fullBoxPx = fullBox.copy().translate(-PMONITOR->m_position).scale(PMONITOR->m_scale).round();
|
||||||
|
|
||||||
|
- if (fullBoxPx.w <= 1 || fullBoxPx.h <= 1)
|
||||||
|
+ if (!usableBox(fullBoxPx) || fullBoxPx.w <= 1 || fullBoxPx.h <= 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const Vector2D newSize = fullBoxPx.size();
|
||||||
|
@@ -251,10 +279,10 @@ void CWobblyTransformer::preWindowRender(CSurfacePassElement::SRenderData* pRend
|
||||||
|
|
||||||
|
damage();
|
||||||
|
|
||||||
|
- if (std::abs(deltaSize.x) > 0.5 || std::abs(deltaSize.y) > 0.5)
|
||||||
|
+ if (finite(deltaSize) && (std::abs(deltaSize.x) > 0.5 || std::abs(deltaSize.y) > 0.5))
|
||||||
|
applyResizeImpulse(deltaSize);
|
||||||
|
|
||||||
|
- if (std::abs(deltaPos.x) > 0.5 || std::abs(deltaPos.y) > 0.5) {
|
||||||
|
+ if (finite(deltaPos) && (std::abs(deltaPos.x) > 0.5 || std::abs(deltaPos.y) > 0.5)) {
|
||||||
|
Vector2D anchor = m_sizePx / 2.0;
|
||||||
|
if (m_wasDragging)
|
||||||
|
anchor = currentPointerLocalPx(fullBox);
|
||||||
|
@@ -296,6 +324,11 @@ void CWobblyTransformer::stepSimulation(float dt) {
|
||||||
|
point.force += (point.rest - point.pos) * (K * 0.18F);
|
||||||
|
point.velocity += (point.force / MASS) * STEP;
|
||||||
|
point.pos += point.velocity * STEP;
|
||||||
|
+
|
||||||
|
+ if (!finite(point.pos) || !finite(point.velocity)) {
|
||||||
|
+ point.pos = point.rest;
|
||||||
|
+ point.velocity = {};
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -313,6 +346,12 @@ void CWobblyTransformer::stepSimulation(float dt) {
|
||||||
|
void CWobblyTransformer::constrainWarp() {
|
||||||
|
const auto LIMIT = maxWarp();
|
||||||
|
for (auto& point : m_points) {
|
||||||
|
+ if (!finite(point.pos)) {
|
||||||
|
+ point.pos = point.rest;
|
||||||
|
+ point.velocity = {};
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
auto diff = point.pos - point.rest;
|
||||||
|
auto len = length(diff);
|
||||||
|
if (len > LIMIT)
|
||||||
|
@@ -356,6 +395,9 @@ CBox CWobblyTransformer::deformedBoundsLayout() const {
|
||||||
|
Vector2D max = m_points.front().pos;
|
||||||
|
|
||||||
|
for (const auto& point : m_points) {
|
||||||
|
+ if (!finite(point.pos))
|
||||||
|
+ return {};
|
||||||
|
+
|
||||||
|
min.x = std::min(min.x, point.pos.x);
|
||||||
|
min.y = std::min(min.y, point.pos.y);
|
||||||
|
max.x = std::max(max.x, point.pos.x);
|
||||||
|
@@ -363,7 +405,8 @@ CBox CWobblyTransformer::deformedBoundsLayout() const {
|
||||||
|
}
|
||||||
|
|
||||||
|
const double SCALE = std::max(0.01, m_sourceBoxPx.w / std::max(1.0, m_sourceBoxLayout.w));
|
||||||
|
- return {m_sourceBoxLayout.x + min.x / SCALE, m_sourceBoxLayout.y + min.y / SCALE, (max.x - min.x) / SCALE, (max.y - min.y) / SCALE};
|
||||||
|
+ const CBox BOX = {m_sourceBoxLayout.x + min.x / SCALE, m_sourceBoxLayout.y + min.y / SCALE, (max.x - min.x) / SCALE, (max.y - min.y) / SCALE};
|
||||||
|
+ return usableBox(BOX) ? BOX : CBox{};
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWobblyTransformer::damage() {
|
||||||
|
@@ -372,13 +415,13 @@ void CWobblyTransformer::damage() {
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto NOW = deformedBoundsLayout().expand(8);
|
||||||
|
- if (!NOW.empty())
|
||||||
|
+ if (usableBox(NOW) && !NOW.empty())
|
||||||
|
g_pHyprRenderer->damageBox(NOW);
|
||||||
|
|
||||||
|
- if (!m_lastDamage.empty())
|
||||||
|
+ if (usableBox(m_lastDamage) && !m_lastDamage.empty())
|
||||||
|
g_pHyprRenderer->damageBox(m_lastDamage);
|
||||||
|
|
||||||
|
- m_lastDamage = NOW;
|
||||||
|
+ m_lastDamage = usableBox(NOW) ? NOW : CBox{};
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWobblyTransformer::tick(float dt) {
|
||||||
|
@@ -402,6 +445,8 @@ SP<Render::IFramebuffer> CWobblyTransformer::transform(SP<Render::IFramebuffer>
|
||||||
|
return in;
|
||||||
|
|
||||||
|
const Vector2D MONSIZE = PMONITOR->m_transformedSize;
|
||||||
|
+ if (!finite(MONSIZE) || MONSIZE.x <= 1.0 || MONSIZE.y <= 1.0 || !usableBox(m_sourceBoxPx))
|
||||||
|
+ return in;
|
||||||
|
|
||||||
|
if (!m_outputFB)
|
||||||
|
m_outputFB = g_pHyprRenderer->createFB("hyprwobbly");
|
||||||
|
diff --git a/Wobbly.hpp b/Wobbly.hpp
|
||||||
|
index b627304..8ebb12f 100644
|
||||||
|
--- a/Wobbly.hpp
|
||||||
|
+++ b/Wobbly.hpp
|
||||||
|
@@ -19,6 +19,7 @@ class CWobblyTransformer : public IWindowTransformer {
|
||||||
|
void tick(float dt);
|
||||||
|
void damage();
|
||||||
|
bool belongsTo(PHLWINDOW pWindow) const;
|
||||||
|
+ bool active() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct SPoint {
|
||||||
|
diff --git a/globals.hpp b/globals.hpp
|
||||||
|
index 38ffff4..2196124 100644
|
||||||
|
--- a/globals.hpp
|
||||||
|
+++ b/globals.hpp
|
||||||
|
@@ -13,8 +13,7 @@ class CWobblyTransformer;
|
||||||
|
|
||||||
|
inline HANDLE PHANDLE = nullptr;
|
||||||
|
inline CHyprSignalListener g_openWindowListener;
|
||||||
|
-inline CFunctionHook* g_pStyleValidHook = nullptr;
|
||||||
|
-inline wl_event_source* g_pTick = nullptr;
|
||||||
|
+inline wl_event_source* g_pTick = nullptr;
|
||||||
|
inline SP<CShader> g_pWobblyShader;
|
||||||
|
inline bool g_shaderReady = false;
|
||||||
|
inline std::vector<CWobblyTransformer*> g_transformers;
|
||||||
|
diff --git a/main.cpp b/main.cpp
|
||||||
|
index f86901e..1ea5249 100644
|
||||||
|
--- a/main.cpp
|
||||||
|
+++ b/main.cpp
|
||||||
|
@@ -19,17 +19,10 @@
|
||||||
|
|
||||||
|
using Render::GL::g_pHyprOpenGL;
|
||||||
|
|
||||||
|
-typedef std::string (*origStyleValid)(CHyprAnimationManager*, const std::string&, const std::string&);
|
||||||
|
-
|
||||||
|
APICALL EXPORT std::string PLUGIN_API_VERSION() {
|
||||||
|
return HYPRLAND_API_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static bool isWobblyStyle(const std::string& config, std::string style) {
|
||||||
|
- std::ranges::transform(style, style.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||||
|
- return config == "windowsMove" && (style == "wobbly" || style.starts_with("wobbly "));
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
template <typename T>
|
||||||
|
static void addConfigValue(SP<T>& storage, SP<T> value) {
|
||||||
|
storage = std::move(value);
|
||||||
|
@@ -51,13 +44,6 @@ static void registerConfigValues() {
|
||||||
|
addConfigValue(g_pMaxWarp, makeShared<Config::Values::CFloatValue>("plugin:hyprwobbly:max_warp", "maximum warp", 140.F));
|
||||||
|
}
|
||||||
|
|
||||||
|
-static std::string hkStyleValidInConfigVar(CHyprAnimationManager* thisptr, const std::string& config, const std::string& style) {
|
||||||
|
- if (isWobblyStyle(config, style))
|
||||||
|
- return "";
|
||||||
|
-
|
||||||
|
- return (*(origStyleValid)g_pStyleValidHook->m_original)(thisptr, config, style);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static bool hasWobbly(PHLWINDOW pWindow) {
|
||||||
|
return std::ranges::any_of(g_transformers, [pWindow](const auto* wobbly) { return wobbly && wobbly->belongsTo(pWindow); });
|
||||||
|
}
|
||||||
|
@@ -79,13 +65,16 @@ static int onTick(void*) {
|
||||||
|
const float DT = std::clamp(std::chrono::duration<float>(NOW - LAST).count(), 0.001F, 0.05F);
|
||||||
|
LAST = NOW;
|
||||||
|
|
||||||
|
+ bool anyActive = false;
|
||||||
|
const auto TRANSFORMERS = g_transformers;
|
||||||
|
for (auto* const transformer : TRANSFORMERS) {
|
||||||
|
- if (transformer)
|
||||||
|
+ if (transformer) {
|
||||||
|
transformer->tick(DT);
|
||||||
|
+ anyActive = anyActive || transformer->active();
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
- const int TIMEOUT = g_pHyprRenderer->m_mostHzMonitor ? 1000.0 / g_pHyprRenderer->m_mostHzMonitor->m_refreshRate : 16;
|
||||||
|
+ const int TIMEOUT = anyActive && g_pHyprRenderer->m_mostHzMonitor ? std::max(8, static_cast<int>(1000.0 / g_pHyprRenderer->m_mostHzMonitor->m_refreshRate)) : 100;
|
||||||
|
wl_event_source_timer_update(g_pTick, TIMEOUT);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -104,20 +93,6 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
||||||
|
|
||||||
|
registerConfigValues();
|
||||||
|
|
||||||
|
- auto FNS = HyprlandAPI::findFunctionsByName(PHANDLE, "styleValidInConfigVar");
|
||||||
|
- for (auto& fn : FNS) {
|
||||||
|
- if (!fn.demangled.contains("CHyprAnimationManager"))
|
||||||
|
- continue;
|
||||||
|
-
|
||||||
|
- g_pStyleValidHook = HyprlandAPI::createFunctionHook(PHANDLE, fn.address, (void*)::hkStyleValidInConfigVar);
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (!g_pStyleValidHook || !g_pStyleValidHook->hook()) {
|
||||||
|
- HyprlandAPI::addNotification(PHANDLE, "[hyprwobbly] Failure in initialization: failed to hook animation style validator", CHyprColor{1.0, 0.2, 0.2, 1.0}, 5000);
|
||||||
|
- throw std::runtime_error("[hyprwobbly] failed to hook animation style validator");
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
g_pHyprOpenGL->makeEGLCurrent();
|
||||||
|
g_pWobblyShader = makeShared<CShader>();
|
||||||
|
g_shaderReady = g_pWobblyShader->createProgram(WOBBLY_VERTEX_SHADER, WOBBLY_FRAGMENT_SHADER);
|
||||||
@@ -7,10 +7,45 @@
|
|||||||
...
|
...
|
||||||
}: let
|
}: let
|
||||||
system = pkgs.stdenv.hostPlatform.system;
|
system = pkgs.stdenv.hostPlatform.system;
|
||||||
|
hyprlandPackage = config.programs.hyprland.package;
|
||||||
taffybarPackage = inputs.imalison-taffybar.defaultPackage.${system};
|
taffybarPackage = inputs.imalison-taffybar.defaultPackage.${system};
|
||||||
taffybarStart = pkgs.writeShellScript "taffybar-start" ''
|
taffybarStart = pkgs.writeShellScript "taffybar-start" ''
|
||||||
runtime_dir="''${XDG_RUNTIME_DIR:-/run/user/$(${pkgs.coreutils}/bin/id -u)}"
|
runtime_dir="''${XDG_RUNTIME_DIR:-/run/user/$(${pkgs.coreutils}/bin/id -u)}"
|
||||||
|
|
||||||
|
find_hyprland_instance() {
|
||||||
|
instances_json="$(${hyprlandPackage}/bin/hyprctl instances -j 2>/dev/null || true)"
|
||||||
|
[ -n "$instances_json" ] || return 1
|
||||||
|
|
||||||
|
if [ -n "''${WAYLAND_DISPLAY:-}" ]; then
|
||||||
|
inst_row="$(
|
||||||
|
printf '%s\n' "$instances_json" |
|
||||||
|
${pkgs.jq}/bin/jq -r --arg sock "$WAYLAND_DISPLAY" \
|
||||||
|
'.[] | select(.instance and .wl_socket and .wl_socket == $sock) | [.time, .instance, .wl_socket] | @tsv' 2>/dev/null |
|
||||||
|
${pkgs.coreutils}/bin/sort -n |
|
||||||
|
${pkgs.coreutils}/bin/tail -n 1
|
||||||
|
)"
|
||||||
|
else
|
||||||
|
inst_row=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "''${inst_row:-}" ]; then
|
||||||
|
inst_row="$(
|
||||||
|
printf '%s\n' "$instances_json" |
|
||||||
|
${pkgs.jq}/bin/jq -r \
|
||||||
|
'.[] | select(.instance and .wl_socket) | [.time, .instance, .wl_socket] | @tsv' 2>/dev/null |
|
||||||
|
${pkgs.coreutils}/bin/sort -n |
|
||||||
|
${pkgs.coreutils}/bin/tail -n 1
|
||||||
|
)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -n "''${inst_row:-}" ] || return 1
|
||||||
|
set -- $inst_row
|
||||||
|
signature="$2"
|
||||||
|
socket_name="$3"
|
||||||
|
[ -n "$signature" ] && [ -n "$socket_name" ] || return 1
|
||||||
|
printf '%s\t%s\n' "$signature" "$socket_name"
|
||||||
|
}
|
||||||
|
|
||||||
find_wayland_socket() {
|
find_wayland_socket() {
|
||||||
if [ -n "''${WAYLAND_DISPLAY:-}" ] && [ -S "$runtime_dir/$WAYLAND_DISPLAY" ]; then
|
if [ -n "''${WAYLAND_DISPLAY:-}" ] && [ -S "$runtime_dir/$WAYLAND_DISPLAY" ]; then
|
||||||
printf '%s\n' "$WAYLAND_DISPLAY"
|
printf '%s\n' "$WAYLAND_DISPLAY"
|
||||||
@@ -49,6 +84,22 @@
|
|||||||
export XDG_SESSION_TYPE=wayland
|
export XDG_SESSION_TYPE=wayland
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$is_hyprland" = 1 ]; then
|
||||||
|
if inst_row="$(find_hyprland_instance)"; then
|
||||||
|
set -- $inst_row
|
||||||
|
signature="$1"
|
||||||
|
socket_name="$2"
|
||||||
|
if [ "''${HYPRLAND_INSTANCE_SIGNATURE:-}" != "$signature" ]; then
|
||||||
|
echo "taffybar-start: correcting HYPRLAND_INSTANCE_SIGNATURE=''${HYPRLAND_INSTANCE_SIGNATURE:-<unset>} to $signature" >&2
|
||||||
|
export HYPRLAND_INSTANCE_SIGNATURE="$signature"
|
||||||
|
fi
|
||||||
|
if [ "''${WAYLAND_DISPLAY:-}" != "$socket_name" ]; then
|
||||||
|
echo "taffybar-start: correcting WAYLAND_DISPLAY=''${WAYLAND_DISPLAY:-<unset>} to $socket_name" >&2
|
||||||
|
export WAYLAND_DISPLAY="$socket_name"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "''${XDG_SESSION_TYPE:-}" = "wayland" ] || [ -n "''${WAYLAND_DISPLAY:-}" ] || [ "$is_hyprland" = 1 ]; then
|
if [ "''${XDG_SESSION_TYPE:-}" = "wayland" ] || [ -n "''${WAYLAND_DISPLAY:-}" ] || [ "$is_hyprland" = 1 ]; then
|
||||||
if [ -z "''${WAYLAND_DISPLAY:-}" ] || [ ! -S "$runtime_dir/$WAYLAND_DISPLAY" ]; then
|
if [ -z "''${WAYLAND_DISPLAY:-}" ] || [ ! -S "$runtime_dir/$WAYLAND_DISPLAY" ]; then
|
||||||
if socket_name="$(find_wayland_socket)"; then
|
if socket_name="$(find_wayland_socket)"; then
|
||||||
|
|||||||
Reference in New Issue
Block a user