From 2fdc6f0573539beff4d73a265e4cd61c3e49a282 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Tue, 16 Jun 2026 01:24:56 -0400 Subject: [PATCH] Move stock Hyprland bindings into defaults --- bin/omarchy-finalize-user | 18 +- bin/omarchy-refresh-hyprland | 17 -- bin/omarchy-remove-preinstalls | 4 +- bin/omarchy-upgrade-to-4 | 29 ++-- config/hypr/bindings.lua | 55 +++--- config/hypr/hyprland.lua | 13 +- config/hypr/input.lua | 92 +++++----- config/hypr/monitors.lua | 7 +- default/hypr/bindings/applications.lua | 39 +++++ default/hypr/helpers.lua | 18 ++ default/hypr/input.lua | 38 ++++- default/hypr/omarchy.lua | 11 +- default/hypr/plain-bindings.lua | 13 -- docs/file-layout.md | 4 +- migrations/1781485962.sh | 109 ++++++++++++ test/shell.d/hyprland-default-config-test.sh | 168 +++++++++++++++++++ 16 files changed, 477 insertions(+), 158 deletions(-) create mode 100644 default/hypr/bindings/applications.lua delete mode 100644 default/hypr/plain-bindings.lua create mode 100644 migrations/1781485962.sh create mode 100644 test/shell.d/hyprland-default-config-test.sh diff --git a/bin/omarchy-finalize-user b/bin/omarchy-finalize-user index 2dc32c3d..df856d84 100755 --- a/bin/omarchy-finalize-user +++ b/bin/omarchy-finalize-user @@ -12,7 +12,7 @@ Usage: omarchy finalize user [--force] [--first-install] Runs the per-user setup steps that /etc/skel can't seed: dev-aware skill symlinks, xdg-user-dirs + gtk bookmarks (need \$HOME), -vconsole→hypr keyboard sync, default browser/mailto, and install/user/all.sh. +default browser/mailto, and install/user/all.sh. For shipped configs see /etc/skel (new users) and omarchy-reinstall-configs (existing users explicitly resyncing). @@ -100,22 +100,6 @@ for dir in Downloads Projects Pictures Videos; do grep -qxF "$bookmark" ~/.config/gtk-3.0/bookmarks || echo "$bookmark" >>~/.config/gtk-3.0/bookmarks done -conf=/etc/vconsole.conf -hyprlua="$HOME/.config/hypr/input.lua" -if [[ -f $conf && -f $hyprlua ]]; then - sed -i '/^[[:space:]]*kb_layout[[:space:]]*=/d' "$hyprlua" - sed -i '/^[[:space:]]*kb_variant[[:space:]]*=/d' "$hyprlua" - - if grep -q '^XKBLAYOUT=' "$conf"; then - layout=$(grep '^XKBLAYOUT=' "$conf" | cut -d= -f2 | tr -d '"') - sed -i "/^[[:space:]]*kb_options *=/i\ kb_layout = \"$layout\"," "$hyprlua" - fi - if grep -q '^XKBVARIANT=' "$conf"; then - variant=$(grep '^XKBVARIANT=' "$conf" | cut -d= -f2 | tr -d '"') - sed -i "/^[[:space:]]*kb_options *=/i\ kb_variant = \"$variant\"," "$hyprlua" - fi -fi - source "$OMARCHY_INSTALL/user/all.sh" omarchy-refresh-applications diff --git a/bin/omarchy-refresh-hyprland b/bin/omarchy-refresh-hyprland index d9f751d3..6549c693 100755 --- a/bin/omarchy-refresh-hyprland +++ b/bin/omarchy-refresh-hyprland @@ -12,20 +12,3 @@ omarchy-refresh-config hypr/monitors.lua mkdir -p ~/.local/state/omarchy/toggles/hypr cp "$OMARCHY_PATH/default/hypr/toggles/flags.lua" ~/.local/state/omarchy/toggles/hypr/ - -conf=/etc/vconsole.conf -hyprlua="$HOME/.config/hypr/input.lua" -if [[ -f $conf && -f $hyprlua ]]; then - sed -i '/^[[:space:]]*kb_layout[[:space:]]*=/d' "$hyprlua" - sed -i '/^[[:space:]]*kb_variant[[:space:]]*=/d' "$hyprlua" - - if grep -q '^XKBLAYOUT=' "$conf"; then - layout=$(grep '^XKBLAYOUT=' "$conf" | cut -d= -f2 | tr -d '"') - sed -i "/^[[:space:]]*kb_options *=/i\ kb_layout = \"$layout\"," "$hyprlua" - fi - - if grep -q '^XKBVARIANT=' "$conf"; then - variant=$(grep '^XKBVARIANT=' "$conf" | cut -d= -f2 | tr -d '"') - sed -i "/^[[:space:]]*kb_options *=/i\ kb_variant = \"$variant\"," "$hyprlua" - fi -fi diff --git a/bin/omarchy-remove-preinstalls b/bin/omarchy-remove-preinstalls index b74458b9..262b1560 100755 --- a/bin/omarchy-remove-preinstalls +++ b/bin/omarchy-remove-preinstalls @@ -8,8 +8,8 @@ if gum confirm "Are you sure you want to remove all preinstalled web apps, TUI w omarchy-webapp-remove-all omarchy-tui-remove-all - [[ -f ~/.config/hypr/bindings.lua ]] && cp ~/.config/hypr/bindings.lua ~/.config/hypr/bindings.lua.bak - cp "$OMARCHY_PATH/default/hypr/plain-bindings.lua" ~/.config/hypr/bindings.lua + mkdir -p ~/.local/state/omarchy + touch ~/.local/state/omarchy/preinstalls-removed hyprctl reload # Remove mise stubs diff --git a/bin/omarchy-upgrade-to-4 b/bin/omarchy-upgrade-to-4 index 11750a3d..a74c493e 100755 --- a/bin/omarchy-upgrade-to-4 +++ b/bin/omarchy-upgrade-to-4 @@ -1613,6 +1613,17 @@ refresh_known_config_defaults() { done < <(default_hash_paths refresh) } +mark_removed_preinstalls_from_legacy_bindings() { + local bindings_file="$HOME/.config/hypr/bindings.lua" + local plain_bindings_sha="5d92d4008b04848256445da3cf5c10422a8d537baad499a4e63f60daecaefc6f" + + [[ -f $bindings_file ]] || return 0 + [[ $(file_sha256 "$bindings_file") == "$plain_bindings_sha" ]] || return 0 + + mkdir -p "$state_dir" + touch "$state_dir/preinstalls-removed" +} + copy_always_config_defaults() { local rel for rel in "${always_copy_config_files[@]}"; do @@ -1754,6 +1765,7 @@ done # and always write the v4-only entry points that older installs cannot have. refresh_known_config_defaults copy_missing_config_defaults "$root/config" "$HOME/.config" +mark_removed_preinstalls_from_legacy_bindings copy_always_config_defaults repair_chromium_copy_url_extension_flags @@ -1821,7 +1833,7 @@ repair_sleep_lock_unit_override install_bash_startup unset rel file backup retired_config_files always_copy_config_files uwsm_env known_config_default_hashes_by_key -unset -f file_sha256 known_config_default_hashes default_hash_paths is_known_default_hash backup_config_file migrate_uwsm_env_customizations is_retired_config_file copy_config_default copy_missing_config_defaults refresh_known_config_defaults copy_always_config_defaults repair_chromium_copy_url_extension_flags repair_sleep_lock_unit_override is_known_bashrc_default install_bash_startup +unset -f file_sha256 known_config_default_hashes default_hash_paths is_known_default_hash backup_config_file migrate_uwsm_env_customizations is_retired_config_file copy_config_default copy_missing_config_defaults refresh_known_config_defaults mark_removed_preinstalls_from_legacy_bindings copy_always_config_defaults repair_chromium_copy_url_extension_flags repair_sleep_lock_unit_override is_known_bashrc_default install_bash_startup mkdir -p "$HOME/.agents/skills" "$HOME/.claude/skills" "$HOME/.codex/skills" "$HOME/.pi/agent/skills" if [[ -d $root/default/omarchy-skill ]]; then @@ -1865,21 +1877,6 @@ for dir in Downloads Projects Pictures Videos; do grep -qxF "$bookmark" "$HOME/.config/gtk-3.0/bookmarks" || echo "$bookmark" >>"$HOME/.config/gtk-3.0/bookmarks" done -conf=/etc/vconsole.conf -hyprlua="$HOME/.config/hypr/input.lua" -if [[ -f $conf && -f $hyprlua ]]; then - sed -i '/^[[:space:]]*kb_layout[[:space:]]*=/d' "$hyprlua" - sed -i '/^[[:space:]]*kb_variant[[:space:]]*=/d' "$hyprlua" - if grep -q '^XKBLAYOUT=' "$conf"; then - layout=$(grep '^XKBLAYOUT=' "$conf" | cut -d= -f2 | tr -d '"') - sed -i "/^[[:space:]]*kb_options *=/i\ kb_layout = \"$layout\"," "$hyprlua" - fi - if grep -q '^XKBVARIANT=' "$conf"; then - variant=$(grep '^XKBVARIANT=' "$conf" | cut -d= -f2 | tr -d '"') - sed -i "/^[[:space:]]*kb_options *=/i\ kb_variant = \"$variant\"," "$hyprlua" - fi -fi - if [[ -n ${OMARCHY_USER_NAME//[[:space:]]/} ]]; then git config --global user.name "$OMARCHY_USER_NAME" || true fi diff --git a/config/hypr/bindings.lua b/config/hypr/bindings.lua index e006e199..d8eb55a9 100644 --- a/config/hypr/bindings.lua +++ b/config/hypr/bindings.lua @@ -1,44 +1,27 @@ --- Application bindings. -o.bind("SUPER + RETURN", "Terminal", { omarchy = "terminal" }) -o.bind("SUPER + ALT + RETURN", "Tmux", { omarchy = "terminal-tmux" }) -o.bind("SUPER + SHIFT + RETURN", "Browser", { omarchy = "browser" }) -o.bind("SUPER + SHIFT + F", "File manager", { omarchy = "nautilus" }) -o.bind("SUPER + ALT + SHIFT + F", "File manager (cwd)", { omarchy = "nautilus-cwd" }) -o.bind("SUPER + SHIFT + B", "Browser", { omarchy = "browser" }) -o.bind("SUPER + SHIFT + ALT + B", "Browser (private)", { omarchy = "browser --private" }) -o.bind("SUPER + SHIFT + M", "Music", { omarchy = "spotify" }) -o.bind("SUPER + SHIFT + ALT + M", "Music TUI", { tui = "cliamp", focus = true }) -o.bind("SUPER + SHIFT + N", "Editor", { omarchy = "editor" }) -o.bind("SUPER + SHIFT + D", "Docker", { tui = "lazydocker" }) -o.bind("SUPER + SHIFT + G", "Signal", { omarchy = "signal" }) -o.bind("SUPER + SHIFT + O", "Obsidian", { launch = "obsidian", focus = "^obsidian$" }) -o.bind("SUPER + SHIFT + W", "Typora", { launch = "typora --enable-wayland-ime" }) -o.bind("SUPER + SHIFT + SLASH", "Passwords", { launch = "1password" }) +-- Keep only your personal keybinding overrides here. Add new bindings or +-- unbind defaults before replacing them. --- Web app bindings. -o.bind("SUPER + SHIFT + A", "ChatGPT", { webapp = "https://chatgpt.com" }) -o.bind("SUPER + SHIFT + ALT + A", "Grok", { webapp = "https://grok.com" }) -o.bind("SUPER + SHIFT + C", "Calendar", { webapp = "https://app.hey.com/calendar/weeks/" }) -o.bind("SUPER + SHIFT + E", "Email", { webapp = "https://app.hey.com" }) -o.bind("SUPER + SHIFT + ALT + E", "New email", { webapp = "https://app.hey.com/messages/new?display=standalone&new_window=true" }) -o.bind("SUPER + SHIFT + Y", "YouTube", { webapp = "https://youtube.com/" }) -o.bind("SUPER + SHIFT + ALT + G", "WhatsApp", { webapp = "https://web.whatsapp.com/", focus = true }) -o.bind( - "SUPER + SHIFT + CTRL + G", - "Google Messages", - { webapp = "https://messages.google.com/web/conversations", focus = true } -) -o.bind("SUPER + SHIFT + P", "Google Photos", { webapp = "https://photos.google.com/", focus = true }) -o.bind("SUPER + SHIFT + S", "Google Maps", { webapp = "https://maps.google.com/", focus = true }) -o.bind("SUPER + SHIFT + X", "X", { webapp = "https://x.com/" }) -o.bind("SUPER + SHIFT + ALT + X", "X Post", { webapp = "https://x.com/compose/post" }) +-- See current bindings and descriptions: +-- omarchy menu keybindings --print --- Add extra bindings below. +-- To disable every Omarchy default binding, set this in +-- ~/.config/hypr/hyprland.lua before require("default.hypr.omarchy"), then add +-- only the bindings you want below: +-- omarchy_default_bindings = false + +-- To disable all preinstalled app/webapp bindings, set: +-- omarchy_preinstalled_bindings = false + +-- Add a new binding. -- o.bind("SUPER + SHIFT + R", "SSH", "alacritty -e ssh your-server") --- Overwrite existing bindings with hl.unbind() first if needed. +-- Change an existing binding by unbinding it first, then binding the key again. +-- This example changes SUPER+SPACE from the launcher to the Omarchy root menu. -- hl.unbind("SUPER + SPACE") --- o.bind("SUPER + SPACE", "Omarchy menu", "omarchy-menu") +-- o.bind("SUPER + SPACE", "Omarchy menu", "omarchy-menu toggle root") + +-- Disable a default binding without replacing it. +-- hl.unbind("SUPER + SHIFT + B") -- Logitech MX Keys examples: -- o.bind("SUPER + SHIFT + S", nil, "omarchy-capture-screenshot") diff --git a/config/hypr/hyprland.lua b/config/hypr/hyprland.lua index 473aed37..45c9b664 100644 --- a/config/hypr/hyprland.lua +++ b/config/hypr/hyprland.lua @@ -3,10 +3,19 @@ -- Omarchy's bootstrap keeps path setup out of this user config. dofile((os.getenv("OMARCHY_PATH") or "/usr/share/omarchy") .. "/default/hypr/bootstrap.lua") --- All Omarchy default setups +-- Disable all Omarchy default bindings. Add your own in hypr/bindings.lua. +-- omarchy_default_bindings = false +-- +-- Or disable only bindings for Omarchy's preinstalled apps/web apps while +-- keeping core window-manager bindings: +-- omarchy_preinstalled_bindings = false + +-- Load Omarchy defaults. require("default.hypr.omarchy") --- Change your own setup in these files and override defaults. +-- Put your personal overrides in these files. They're loaded after Omarchy's +-- defaults so package updates can improve the defaults without rewriting your +-- ~/.config/hypr files. require("hypr.monitors") require("hypr.input") require("hypr.bindings") diff --git a/config/hypr/input.lua b/config/hypr/input.lua index 03e32bde..301aa0cb 100644 --- a/config/hypr/input.lua +++ b/config/hypr/input.lua @@ -1,50 +1,52 @@ --- Control your input devices. +-- Keep only your personal input overrides here. Uncommented settings below +-- replace Omarchy's defaults. + +-- Keyboard layout and options. -- See https://wiki.hypr.land/Configuring/Basics/Variables/#input -hl.config({ - input = { - -- Use multiple keyboard layouts and switch between them with Left Alt + Right Alt. - -- kb_layout = "us,dk,eu", +-- hl.config({ +-- input = { +-- -- Use multiple keyboard layouts and switch between them with Left Alt + Right Alt. +-- kb_layout = "us,dk,eu", +-- kb_options = "compose:caps,grp:alts_toggle", +-- +-- -- Use a specific keyboard variant if needed (e.g. intl for international keyboards). +-- kb_variant = "intl", +-- +-- -- Change speed of keyboard repeat. +-- repeat_rate = 40, +-- repeat_delay = 250, +-- +-- -- Start with numlock on by default. +-- numlock_by_default = true, +-- +-- -- Increase sensitivity for mouse/trackpad (default: 0). +-- sensitivity = 0.35, +-- +-- -- Turn off mouse acceleration (default: adaptive). +-- accel_profile = "flat", +-- +-- touchpad = { +-- -- Use natural (inverse) scrolling. +-- natural_scroll = true, +-- +-- -- Use two-finger clicks for right-click instead of lower-right corner. +-- clickfinger_behavior = true, +-- +-- -- Control the speed of your scrolling. +-- scroll_factor = 0.4, +-- +-- -- Enable the touchpad while typing. +-- disable_while_typing = false, +-- +-- -- Left-click-and-drag with three fingers. +-- drag_3fg = 1, +-- }, +-- }, +-- }) - -- Use a specific keyboard variant if needed (e.g. intl for international keyboards). - -- kb_variant = "intl", - - kb_options = "compose:caps", -- ,grp:alts_toggle - - -- Change speed of keyboard repeat. - repeat_rate = 40, - repeat_delay = 250, - - -- Start with numlock on by default. - numlock_by_default = true, - - -- Increase sensitivity for mouse/trackpad (default: 0). - -- sensitivity = 0.35, - - -- Turn off mouse acceleration (default: adaptive). - -- accel_profile = "flat", - - touchpad = { - -- Use natural (inverse) scrolling. - -- natural_scroll = true, - - -- Use two-finger clicks for right-click instead of lower-right corner. - clickfinger_behavior = true, - - -- Control the speed of your scrolling. - scroll_factor = 0.4, - - -- Enable the touchpad while typing. - -- disable_while_typing = false, - - -- Left-click-and-drag with three fingers. - -- drag_3fg = 1, - }, - }, -}) - --- Scroll nicely in the terminal. -o.window("(Alacritty|kitty|foot)", { scroll_touchpad = 1.5 }) -o.window("com.mitchellh.ghostty", { scroll_touchpad = 0.2 }) +-- App-specific touchpad scroll speeds. +-- o.window("(Alacritty|kitty|foot)", { scroll_touchpad = 1.5 }) +-- o.window("com.mitchellh.ghostty", { scroll_touchpad = 0.2 }) -- Enable touchpad gestures for changing workspaces. -- See https://wiki.hypr.land/Configuring/Advanced-and-Cool/Gestures/ diff --git a/config/hypr/monitors.lua b/config/hypr/monitors.lua index dbca4b5c..189f13c2 100644 --- a/config/hypr/monitors.lua +++ b/config/hypr/monitors.lua @@ -1,5 +1,5 @@ -- See https://wiki.hypr.land/Configuring/Basics/Monitors/ --- List current monitors and resolutions possible: hyprctl monitors all +-- List current monitors and supported resolutions with: hyprctl monitors all local omarchy_gdk_scale = 2 local omarchy_monitor_scale = "auto" @@ -7,5 +7,8 @@ local omarchy_monitor_scale = "auto" hl.env("GDK_SCALE", tostring(omarchy_gdk_scale)) hl.monitor({ output = "", mode = "preferred", position = "auto", scale = omarchy_monitor_scale }) --- Portrait/rotated secondary monitor (transform: 1 = 90°, 3 = 270°) +-- Configure a specific monitor. +-- hl.monitor({ output = "DP-2", mode = "2560x1440@144", position = "0x0", scale = 1 }) + +-- Portrait/rotated secondary monitor (transform: 1 = 90°, 3 = 270°). -- hl.monitor({ output = "DP-2", mode = "preferred", position = "auto", scale = 1, transform = 1 }) diff --git a/default/hypr/bindings/applications.lua b/default/hypr/bindings/applications.lua new file mode 100644 index 00000000..b6d9ed4d --- /dev/null +++ b/default/hypr/bindings/applications.lua @@ -0,0 +1,39 @@ +-- Essential application bindings. +o.bind("SUPER + RETURN", "Terminal", { omarchy = "terminal" }) +o.bind("SUPER + SHIFT + RETURN", "Browser", { omarchy = "browser" }) +o.bind("SUPER + SHIFT + F", "File manager", { omarchy = "nautilus" }) +o.bind("SUPER + ALT + SHIFT + F", "File manager (cwd)", { omarchy = "nautilus-cwd" }) +o.bind("SUPER + SHIFT + B", "Browser", { omarchy = "browser" }) +o.bind("SUPER + SHIFT + ALT + B", "Browser (private)", { omarchy = "browser --private" }) +o.bind("SUPER + SHIFT + N", "Editor", { omarchy = "editor" }) + +if not o.preinstalled_bindings_enabled() then + return +end + +-- Bindings for preinstalled Omarchy applications, TUIs, and web apps. +o.bind("SUPER + ALT + RETURN", "Tmux", { omarchy = "terminal-tmux" }) +o.bind("SUPER + SHIFT + M", "Music", { omarchy = "spotify" }) +o.bind("SUPER + SHIFT + ALT + M", "Music TUI", { tui = "cliamp", focus = true }) +o.bind("SUPER + SHIFT + D", "Docker", { tui = "lazydocker" }) +o.bind("SUPER + SHIFT + G", "Signal", { omarchy = "signal" }) +o.bind("SUPER + SHIFT + O", "Obsidian", { launch = "obsidian", focus = "^obsidian$" }) +o.bind("SUPER + SHIFT + W", "Typora", { launch = "typora --enable-wayland-ime" }) +o.bind("SUPER + SHIFT + SLASH", "Passwords", { launch = "1password" }) + +o.bind("SUPER + SHIFT + A", "ChatGPT", { webapp = "https://chatgpt.com" }) +o.bind("SUPER + SHIFT + ALT + A", "Grok", { webapp = "https://grok.com" }) +o.bind("SUPER + SHIFT + C", "Calendar", { webapp = "https://app.hey.com/calendar/weeks/" }) +o.bind("SUPER + SHIFT + E", "Email", { webapp = "https://app.hey.com" }) +o.bind("SUPER + SHIFT + ALT + E", "New email", { webapp = "https://app.hey.com/messages/new?display=standalone&new_window=true" }) +o.bind("SUPER + SHIFT + Y", "YouTube", { webapp = "https://youtube.com/" }) +o.bind("SUPER + SHIFT + ALT + G", "WhatsApp", { webapp = "https://web.whatsapp.com/", focus = true }) +o.bind( + "SUPER + SHIFT + CTRL + G", + "Google Messages", + { webapp = "https://messages.google.com/web/conversations", focus = true } +) +o.bind("SUPER + SHIFT + P", "Google Photos", { webapp = "https://photos.google.com/", focus = true }) +o.bind("SUPER + SHIFT + S", "Google Maps", { webapp = "https://maps.google.com/", focus = true }) +o.bind("SUPER + SHIFT + X", "X", { webapp = "https://x.com/" }) +o.bind("SUPER + SHIFT + ALT + X", "X Post", { webapp = "https://x.com/compose/post" }) diff --git a/default/hypr/helpers.lua b/default/hypr/helpers.lua index 80aa5747..e744c87c 100644 --- a/default/hypr/helpers.lua +++ b/default/hypr/helpers.lua @@ -49,6 +49,24 @@ local function command_from(value, description) return value end +local function file_exists(path) + local file = io.open(path, "r") + if file then + file:close() + return true + end + + return false +end + +function o.preinstalled_bindings_enabled() + if _G.omarchy_preinstalled_bindings ~= nil then + return _G.omarchy_preinstalled_bindings == true + end + + return not file_exists((os.getenv("HOME") or "") .. "/.local/state/omarchy/preinstalls-removed") +end + function o.bind(keys, description, dispatcher, options) local opts = options or {} diff --git a/default/hypr/input.lua b/default/hypr/input.lua index 1f003936..d7232736 100644 --- a/default/hypr/input.lua +++ b/default/hypr/input.lua @@ -1,16 +1,46 @@ -- https://wiki.hypr.land/Configuring/Basics/Variables/#input + +local function read_vconsole() + local values = {} + local file = io.open("/etc/vconsole.conf", "r") + if not file then + return values + end + + for line in file:lines() do + local key, value = line:match("^%s*([%w_]+)%s*=%s*(.-)%s*$") + if key and value then + value = value:gsub("%s+#.*$", "") + value = value:gsub('^"(.*)"$', "%1") + value = value:gsub("^'(.*)'$", "%1") + values[key] = value + end + end + + file:close() + return values +end + +local vconsole = read_vconsole() + hl.config({ input = { - kb_layout = "us", - kb_variant = "", + kb_layout = vconsole.XKBLAYOUT or "us", + kb_variant = vconsole.XKBVARIANT or "", kb_model = "", kb_options = "compose:caps", kb_rules = "", follow_mouse = 1, sensitivity = 0, + repeat_rate = 40, + repeat_delay = 250, + numlock_by_default = true, + touchpad = { natural_scroll = false, + clickfinger_behavior = true, + scroll_factor = 0.4, }, }, @@ -19,3 +49,7 @@ hl.config({ mouse_move_enables_dpms = true, }, }) + +-- Scroll nicely in the terminal. +o.window("(Alacritty|kitty|foot)", { scroll_touchpad = 1.5 }) +o.window("com.mitchellh.ghostty", { scroll_touchpad = 0.2 }) diff --git a/default/hypr/omarchy.lua b/default/hypr/omarchy.lua index 657ac887..1d62f827 100644 --- a/default/hypr/omarchy.lua +++ b/default/hypr/omarchy.lua @@ -4,10 +4,13 @@ require("default.hypr.helpers") -- Use Omarchy defaults, but don't edit these directly. require("default.hypr.autostart") -require("default.hypr.bindings.media") -require("default.hypr.bindings.clipboard") -require("default.hypr.bindings.tiling-v2") -require("default.hypr.bindings.utilities") +if _G.omarchy_default_bindings ~= false then + require("default.hypr.bindings.media") + require("default.hypr.bindings.clipboard") + require("default.hypr.bindings.tiling-v2") + require("default.hypr.bindings.utilities") + require("default.hypr.bindings.applications") +end require("default.hypr.envs") require("default.hypr.looknfeel") require("default.hypr.input") diff --git a/default/hypr/plain-bindings.lua b/default/hypr/plain-bindings.lua deleted file mode 100644 index 5f132a84..00000000 --- a/default/hypr/plain-bindings.lua +++ /dev/null @@ -1,13 +0,0 @@ -require("default.hypr.bindings.media") -require("default.hypr.bindings.clipboard") -require("default.hypr.bindings.tiling-v2") -require("default.hypr.bindings.utilities") - --- Application bindings without Omarchy's preinstalled web apps, TUIs, or desktop apps. -o.bind("SUPER + RETURN", "Terminal", { omarchy = "terminal" }) -o.bind("SUPER + SHIFT + RETURN", "Browser", { omarchy = "browser" }) -o.bind("SUPER + SHIFT + F", "File manager", { omarchy = "nautilus" }) -o.bind("SUPER + ALT + SHIFT + F", "File manager (cwd)", { omarchy = "nautilus-cwd" }) -o.bind("SUPER + SHIFT + B", "Browser", { omarchy = "browser" }) -o.bind("SUPER + SHIFT + ALT + B", "Browser (private)", { omarchy = "browser --private" }) -o.bind("SUPER + SHIFT + N", "Editor", { omarchy = "editor" }) diff --git a/docs/file-layout.md b/docs/file-layout.md index 6bdc674b..d886d55a 100644 --- a/docs/file-layout.md +++ b/docs/file-layout.md @@ -163,8 +163,8 @@ It only does the things `/etc/skel` can't: `omarchy dev link` against a dev checkout repoints them correctly. - `xdg-user-dirs-update` (Templates/Public/Desktop folded back into `$HOME`) and `~/.config/gtk-3.0/bookmarks` (needs `$HOME` expansion). -- Sync `XKBLAYOUT` / `XKBVARIANT` from `/etc/vconsole.conf` into - `~/.config/hypr/input.lua`. +- Hyprland's package-owned default input reads `XKBLAYOUT` / `XKBVARIANT` + from `/etc/vconsole.conf`; no per-user Hyprland config rewrite is needed. - `xdg-settings set default-web-browser chromium.desktop` and `xdg-mime default HEY.desktop x-scheme-handler/mailto` (XDG-aware paths). - `omarchy-refresh-applications` (composes generated `.desktop` launchers). diff --git a/migrations/1781485962.sh b/migrations/1781485962.sh new file mode 100644 index 00000000..a0bc799d --- /dev/null +++ b/migrations/1781485962.sh @@ -0,0 +1,109 @@ +echo "Move stock Hyprland user overrides into package defaults" + +stock_input_sha="bf7602d679a31da028528d9b7dac64463217a9df42b254d3baefb7ce35674be5" +stock_bindings_sha="932d647b07d24907d46c0b7752bb81ad87276ccd057670be6c3a5c5e950c19aa" +plain_bindings_sha="5d92d4008b04848256445da3cf5c10422a8d537baad499a4e63f60daecaefc6f" + +file_sha() { + sha256sum "$1" | awk '{ print $1 }' +} + +packaged_hypr_config() { + local omarchy_config="$OMARCHY_PATH/config/hypr/$1" + + if [[ -f $omarchy_config ]]; then + printf '%s\n' "$omarchy_config" + else + printf '/etc/skel/.config/hypr/%s\n' "$1" + fi +} + +replace_with_packaged_config() { + local name="$1" + local user_file="$HOME/.config/hypr/$name" + local packaged_file + + packaged_file=$(packaged_hypr_config "$name") + [[ -f $user_file && -f $packaged_file ]] || return 0 + + cp "$packaged_file" "$user_file" +} + +vconsole_value() { + local key="$1" + + [[ -f /etc/vconsole.conf ]] || return 0 + + awk -F= -v key="$key" ' + $1 == key { + value = $2 + sub(/^[[:space:]]*/, "", value) + sub(/[[:space:]]*$/, "", value) + gsub(/^"/, "", value) + gsub(/"$/, "", value) + print value + exit + } + ' /etc/vconsole.conf +} + +active_lua_string_value() { + local key="$1" + local file="$2" + + awk -F= -v key="$key" ' + $0 ~ "^[[:space:]]*" key "[[:space:]]*=" { + value = $2 + sub(/^[[:space:]]*/, "", value) + sub(/[[:space:]]*,?[[:space:]]*$/, "", value) + gsub(/^"/, "", value) + gsub(/"$/, "", value) + print value + exit + } + ' "$file" +} + +normalized_input_sha() { + sed \ + -e '/^[[:space:]]*kb_layout[[:space:]]*=/d' \ + -e '/^[[:space:]]*kb_variant[[:space:]]*=/d' \ + "$1" | sha256sum | awk '{ print $1 }' +} + +input_is_stock_or_installer_synced() { + local input_file="$1" + local layout variant vconsole_layout vconsole_variant + + [[ $(normalized_input_sha "$input_file") == $stock_input_sha ]] || return 1 + + layout=$(active_lua_string_value kb_layout "$input_file") + variant=$(active_lua_string_value kb_variant "$input_file") + vconsole_layout=$(vconsole_value XKBLAYOUT) + vconsole_variant=$(vconsole_value XKBVARIANT) + + [[ -n $layout && $layout != $vconsole_layout ]] && return 1 + [[ -n $variant && $variant != $vconsole_variant ]] && return 1 + + return 0 +} + +input_file="$HOME/.config/hypr/input.lua" +if [[ -f $input_file ]] && input_is_stock_or_installer_synced "$input_file"; then + replace_with_packaged_config input.lua +fi + +bindings_file="$HOME/.config/hypr/bindings.lua" +if [[ -f $bindings_file ]]; then + case "$(file_sha "$bindings_file")" in + "$stock_bindings_sha") + replace_with_packaged_config bindings.lua + ;; + "$plain_bindings_sha") + mkdir -p "$HOME/.local/state/omarchy" + touch "$HOME/.local/state/omarchy/preinstalls-removed" + replace_with_packaged_config bindings.lua + ;; + esac +fi + diff --git a/test/shell.d/hyprland-default-config-test.sh b/test/shell.d/hyprland-default-config-test.sh new file mode 100644 index 00000000..7fa10f24 --- /dev/null +++ b/test/shell.d/hyprland-default-config-test.sh @@ -0,0 +1,168 @@ +#!/bin/bash + +source "$(dirname "${BASH_SOURCE[0]}")/base-test.sh" + +require_command lua + +run_application_bindings() { + local home="$1" + local prelude="${2:-}" + + HOME="$home" XDG_CONFIG_HOME="$home/.config" XDG_STATE_HOME="$home/.local/state" OMARCHY_PATH="$ROOT" OMARCHY_BINDING_PRELUDE="$prelude" lua <<'LUA' +package.path = os.getenv("HOME") .. "/.config/?.lua;" .. os.getenv("OMARCHY_PATH") .. "/?.lua;" .. package.path + +local prelude = os.getenv("OMARCHY_BINDING_PRELUDE") or "" +if prelude ~= "" then + assert(load(prelude))() +end + +hl = { + dsp = { + exec_cmd = function(command) + return { kind = "exec", arg = command } + end, + }, + bind = function(keys, dispatcher, opts) + opts = opts or {} + if opts.description then + print(keys .. "\t" .. opts.description) + end + end, +} + +require("default.hypr.helpers") +require("default.hypr.bindings.applications") +LUA +} + +run_omarchy_bindings() { + local home="$1" + local prelude="${2:-}" + + HOME="$home" XDG_CONFIG_HOME="$home/.config" XDG_STATE_HOME="$home/.local/state" OMARCHY_PATH="$ROOT" OMARCHY_BINDING_PRELUDE="$prelude" lua <<'LUA' +package.path = os.getenv("HOME") .. "/.config/?.lua;" .. os.getenv("OMARCHY_PATH") .. "/?.lua;" .. package.path + +local function proxy() + return setmetatable({}, { + __index = function(self, key) + local value = proxy() + rawset(self, key, value) + return value + end, + __call = function() + return {} + end, + }) +end + +local prelude = os.getenv("OMARCHY_BINDING_PRELUDE") or "" +if prelude ~= "" then + assert(load(prelude))() +end + +hl = setmetatable({ + dsp = proxy(), + bind = function(keys, dispatcher, opts) + opts = opts or {} + if opts.description then + print(keys .. "\t" .. opts.description) + end + end, + config = function() end, + env = function() end, + monitor = function() end, + window_rule = function() end, + workspace_rule = function() end, + layer_rule = function() end, + gesture = function() end, + animation = function() end, + curve = function() end, + exec_cmd = function() end, + dispatch = function() end, + on = function() end, + timer = function() end, + get_config = function() return nil end, + get_active_window = function() return nil end, +}, { + __index = function() + return function() + return {} + end + end, +}) + +require("default.hypr.omarchy") +LUA +} + +tmpdir=$(mktemp -d) +trap 'rm -rf "$tmpdir"' EXIT + +fresh_home="$tmpdir/fresh-home" +mkdir -p "$fresh_home" +fresh_output=$(run_application_bindings "$fresh_home") +grep -Fq $'SUPER + RETURN Terminal' <<<"$fresh_output" || fail "default application bindings include essentials" +grep -Fq $'SUPER + SHIFT + A ChatGPT' <<<"$fresh_output" || fail "default application bindings include preinstalled web apps" +pass "default application bindings load from package defaults" + +removed_home="$tmpdir/removed-home" +mkdir -p "$removed_home/.local/state/omarchy" +touch "$removed_home/.local/state/omarchy/preinstalls-removed" +removed_output=$(run_application_bindings "$removed_home") +grep -Fq $'SUPER + RETURN Terminal' <<<"$removed_output" || fail "preinstall removal keeps essential bindings" +if grep -Fq $'SUPER + SHIFT + A ChatGPT' <<<"$removed_output"; then + fail "preinstall removal skips preinstalled web app bindings" +fi +pass "preinstall removal flag skips optional application bindings" + +variable_home="$tmpdir/variable-home" +mkdir -p "$variable_home" +variable_output=$(run_application_bindings "$variable_home" 'omarchy_preinstalled_bindings = false') +grep -Fq $'SUPER + RETURN Terminal' <<<"$variable_output" || fail "preinstalled binding variable keeps essential bindings" +if grep -Fq $'SUPER + SHIFT + A ChatGPT' <<<"$variable_output"; then + fail "preinstalled binding variable skips optional application bindings" +fi +pass "preinstalled binding variable skips optional application bindings" + +no_bindings_home="$tmpdir/no-bindings-home" +mkdir -p "$no_bindings_home" +no_bindings_output=$(run_omarchy_bindings "$no_bindings_home" 'omarchy_default_bindings = false') +[[ -z $no_bindings_output ]] || fail "default binding variable disables all Omarchy bindings" "$no_bindings_output" +pass "default binding variable disables all Omarchy bindings" + +migration=$(grep -rl 'Move stock Hyprland user overrides into package defaults' "$ROOT/migrations" | head -n 1 || true) +[[ -n $migration ]] || fail "Hyprland default config migration exists" + +migration_home="$tmpdir/migration-home" +mkdir -p "$migration_home/.config/hypr" +cat >"$migration_home/.config/hypr/bindings.lua" <<'LUA' +require("default.hypr.bindings.media") +require("default.hypr.bindings.clipboard") +require("default.hypr.bindings.tiling-v2") +require("default.hypr.bindings.utilities") + +-- Application bindings without Omarchy's preinstalled web apps, TUIs, or desktop apps. +o.bind("SUPER + RETURN", "Terminal", { omarchy = "terminal" }) +o.bind("SUPER + SHIFT + RETURN", "Browser", { omarchy = "browser" }) +o.bind("SUPER + SHIFT + F", "File manager", { omarchy = "nautilus" }) +o.bind("SUPER + ALT + SHIFT + F", "File manager (cwd)", { omarchy = "nautilus-cwd" }) +o.bind("SUPER + SHIFT + B", "Browser", { omarchy = "browser" }) +o.bind("SUPER + SHIFT + ALT + B", "Browser (private)", { omarchy = "browser --private" }) +o.bind("SUPER + SHIFT + N", "Editor", { omarchy = "editor" }) +LUA +HOME="$migration_home" OMARCHY_PATH="$ROOT" bash -euo pipefail "$migration" >/dev/null +cmp -s "$ROOT/config/hypr/bindings.lua" "$migration_home/.config/hypr/bindings.lua" || + fail "plain legacy bindings migrate to the user override stub" +[[ -f $migration_home/.local/state/omarchy/preinstalls-removed ]] || + fail "plain legacy bindings preserve preinstall removal state" +pass "migration converts plain legacy bindings to package-owned defaults" + +upgrade_script="$ROOT/bin/omarchy-upgrade-to-4" +grep -Fq 'touch "$state_dir/preinstalls-removed"' "$upgrade_script" || + fail "upgrade-to-4 preserves preinstall removal state" + +mark_line=$(awk '/^mark_removed_preinstalls_from_legacy_bindings$/ { print NR; exit }' "$upgrade_script") +copy_line=$(awk '/^copy_always_config_defaults$/ { print NR; exit }' "$upgrade_script") +[[ -n $mark_line && -n $copy_line ]] || fail "upgrade-to-4 preinstall marker and config refresh calls exist" +(( mark_line < copy_line )) || fail "upgrade-to-4 detects plain legacy bindings before overwriting Hyprland bindings" +pass "upgrade-to-4 preserves preinstall removal before refreshing Hyprland bindings"