Make BOS a complete, bootable, themed desktop OS
Some checks failed
Mirror to GitHub / mirror (push) Failing after 7s

Install/boot reliability:
- Use native Calamares initcpiocfg/initcpio + explicit grub-install (nvram +
  --removable) in post-install; drop the flaky native bootloader/grubcfg modules.
- mount.conf: bind /proc /sys /dev (devtmpfs) /run + efivars into the chroot.
- bos-copy-kernel: stage kernel + write a stock mkinitcpio preset (replace the
  archiso preset). Per-service systemctl enable (fixes NetworkManager et al.
  silently not enabling due to the all-or-nothing grub-btrfs.path name).

System completeness:
- greetd + tuigreet graphical login; installed pacman.conf + working mirrorlist;
  base CLI tools (nano, micro, vim, htop, …); amd/intel-ucode; tlp + hypridle
  power management; systemd-timesyncd, fstrim.timer; wpa_supplicant wifi; Zen
  browser (republished to the [Breadway] repo).

Desktop + theming:
- Native Lua Hyprland config (hyprland.lua) with curated standard binds; kitty
  (blur) replaces foot; awww wallpaper + pywal palette (tamed to a black base
  with warm accents); GTK dark mode.
- Plymouth boot splash (bos theme: logo + spinner + status) via plymouthcfg.
- Varela Round font; Calamares bread-palette sidebar (logo/black-region polish
  still pending).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Breadway 2026-06-16 09:09:34 +08:00
parent 2a866144f4
commit 9ea57d87c0
35 changed files with 787 additions and 180 deletions

View file

@ -0,0 +1,37 @@
# Idle management (hypridle). Conservative, mainstream-OS-like defaults:
# dim -> screen off -> lock -> suspend, all respecting idle inhibitors (so media
# playback, etc. won't dim or suspend the machine). Vendor-neutral: nothing here
# is Intel/AMD specific.
general {
lock_cmd = pidof hyprlock || hyprlock
before_sleep_cmd = loginctl lock-session
after_sleep_cmd = hyprctl dispatch dpms on
ignore_dbus_inhibit = false
}
# Dim the backlight after 5 minutes (restored on activity). No-op on hardware
# without a backlight (desktops / VMs).
listener {
timeout = 300
on-timeout = brightnessctl -s set 10%
on-resume = brightnessctl -r
}
# Turn the display off after 8 minutes.
listener {
timeout = 480
on-timeout = hyprctl dispatch dpms off
on-resume = hyprctl dispatch dpms on
}
# Lock shortly after the screen turns off.
listener {
timeout = 510
on-timeout = loginctl lock-session
}
# Suspend after 20 minutes of inactivity (skipped while something inhibits idle).
listener {
timeout = 1200
on-timeout = systemctl suspend
}

View file

@ -1,55 +0,0 @@
monitor=,preferred,auto,1
exec-once = breadd
exec-once = breadbar
exec-once = breadbox-sync
source = ~/.config/hypr/keybinds.conf
general {
gaps_in = 5
gaps_out = 10
border_size = 2
col.active_border = rgba(88c0d0ff)
col.inactive_border = rgba(4c566aff)
layout = dwindle
}
decoration {
rounding = 8
blur {
enabled = true
size = 6
passes = 2
}
shadow {
enabled = true
range = 12
render_power = 3
}
}
animations {
enabled = true
bezier = ease, 0.25, 0.1, 0.25, 1.0
animation = windows, 1, 4, ease
animation = fade, 1, 4, ease
animation = workspaces, 1, 5, ease
}
input {
kb_layout = us
follow_mouse = 1
touchpad {
natural_scroll = true
}
}
dwindle {
preserve_split = true
}
misc {
disable_hyprland_logo = true
disable_splash_rendering = true
}

View file

@ -0,0 +1,168 @@
-- BOS Hyprland configuration — native Lua config (Hyprland 0.55+).
-- hyprlang (.conf) is deprecated; this uses the built-in `hl` API.
-- Single-file and non-modular by design. Reference: https://wiki.hypr.land/
local mod = "SUPER"
-- ---------------------------------------------------------------------------
-- Monitors — generic default that works on any hardware.
-- ---------------------------------------------------------------------------
hl.monitor({ output = "", mode = "preferred", position = "auto", scale = "auto" })
-- ---------------------------------------------------------------------------
-- Core settings.
-- ---------------------------------------------------------------------------
hl.config({
general = {
gaps_in = 5,
gaps_out = 10,
border_size = 2,
col = {
active_border = "rgba(88c0d0ff)",
inactive_border = "rgba(4c566aff)",
},
layout = "dwindle",
resize_on_border = true,
},
decoration = {
rounding = 8,
active_opacity = 1.0,
inactive_opacity = 1.0,
blur = {
enabled = true,
size = 6,
passes = 2,
new_optimizations = true,
},
shadow = {
enabled = true,
range = 12,
render_power = 3,
},
},
input = {
kb_layout = "us",
follow_mouse = 1,
touchpad = { natural_scroll = true },
},
dwindle = {
preserve_split = true,
},
animations = {
enabled = true,
},
misc = {
disable_hyprland_logo = true,
disable_splash_rendering = true,
},
})
-- ---------------------------------------------------------------------------
-- Environment (vendor-neutral; no GPU-specific vars so it works on Intel/AMD).
-- ---------------------------------------------------------------------------
hl.env("XCURSOR_SIZE", "24")
hl.env("HYPRCURSOR_SIZE", "24")
hl.env("MOZ_ENABLE_WAYLAND", "1")
hl.env("QT_QPA_PLATFORM", "wayland;xcb")
hl.env("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1")
hl.env("SDL_VIDEODRIVER", "wayland")
hl.env("ELECTRON_OZONE_PLATFORM_HINT", "auto")
hl.env("_JAVA_AWT_WM_NONREPARENTING", "1")
-- kitty sets its own background_opacity (see kitty.conf), so the global blur
-- above blurs behind the terminal while keeping text fully opaque.
-- ---------------------------------------------------------------------------
-- Standard BOS keybinds (SUPER = mod).
-- ---------------------------------------------------------------------------
-- Apps / window management
hl.bind(mod .. " + RETURN", hl.dsp.exec_cmd("kitty"))
hl.bind(mod .. " + BACKSPACE", hl.dsp.window.close())
hl.bind(mod .. " + SPACE", hl.dsp.exec_cmd("breadbox"))
hl.bind(mod .. " + E", hl.dsp.exec_cmd("nautilus"))
hl.bind(mod .. " + B", hl.dsp.exec_cmd("zen-browser"))
hl.bind(mod .. " + U", hl.dsp.exec_cmd("breadpad"))
hl.bind(mod .. " + M", hl.dsp.exec_cmd("breadman"))
hl.bind(mod .. " + L", hl.dsp.exec_cmd("loginctl lock-session"))
hl.bind(mod .. " + F", hl.dsp.window.fullscreen({ action = "toggle" }))
hl.bind(mod .. " + V", hl.dsp.window.float({ action = "toggle" }))
hl.bind(mod .. " + T", hl.dsp.layout("togglesplit"))
hl.bind(mod .. " + Tab", hl.dsp.focus({ urgent_or_last = true }))
hl.bind(mod .. " + N", hl.dsp.exit())
-- Screenshots (grim + slurp + wl-clipboard)
hl.bind(mod .. " + SHIFT + S", hl.dsp.exec_cmd([[bash -c 'mkdir -p ~/Pictures/Screenshots && grim -g "$(slurp)" ~/Pictures/Screenshots/$(date +%Y%m%d-%H%M%S).png']]))
hl.bind(mod .. " + SHIFT + C", hl.dsp.exec_cmd([[bash -c 'grim -g "$(slurp)" - | wl-copy']]))
hl.bind(mod .. " + SHIFT + P", hl.dsp.exec_cmd([[bash -c 'mkdir -p ~/Pictures/Screenshots && grim ~/Pictures/Screenshots/$(date +%Y%m%d-%H%M%S).png']]))
-- Focus (directional)
hl.bind(mod .. " + left", hl.dsp.focus({ direction = "left" }))
hl.bind(mod .. " + right", hl.dsp.focus({ direction = "right" }))
hl.bind(mod .. " + up", hl.dsp.focus({ direction = "up" }))
hl.bind(mod .. " + down", hl.dsp.focus({ direction = "down" }))
-- Move window (directional, vim keys)
hl.bind(mod .. " + SHIFT + h", hl.dsp.window.move({ direction = "left" }))
hl.bind(mod .. " + SHIFT + j", hl.dsp.window.move({ direction = "down" }))
hl.bind(mod .. " + SHIFT + k", hl.dsp.window.move({ direction = "up" }))
hl.bind(mod .. " + SHIFT + l", hl.dsp.window.move({ direction = "right" }))
-- Resize active window (arrows)
hl.bind(mod .. " + SHIFT + right", hl.dsp.window.resize({ x = 30, y = 0, relative = true }), { repeating = true })
hl.bind(mod .. " + SHIFT + left", hl.dsp.window.resize({ x = -30, y = 0, relative = true }), { repeating = true })
hl.bind(mod .. " + SHIFT + up", hl.dsp.window.resize({ x = 0, y = -30, relative = true }), { repeating = true })
hl.bind(mod .. " + SHIFT + down", hl.dsp.window.resize({ x = 0, y = 30, relative = true }), { repeating = true })
-- Workspaces 110 (0 = workspace 10)
for i = 1, 10 do
local key = tostring(i % 10)
hl.bind(mod .. " + " .. key, hl.dsp.focus({ workspace = i }))
hl.bind(mod .. " + SHIFT + " .. key, hl.dsp.window.move({ workspace = i }))
end
-- Workspace cycling
hl.bind(mod .. " + bracketright", hl.dsp.focus({ workspace = "e+1" }))
hl.bind(mod .. " + bracketleft", hl.dsp.focus({ workspace = "e-1" }))
hl.bind(mod .. " + SHIFT + bracketright", hl.dsp.window.move({ workspace = "e+1" }))
hl.bind(mod .. " + SHIFT + bracketleft", hl.dsp.window.move({ workspace = "e-1" }))
-- Mouse
hl.bind(mod .. " + mouse_down", hl.dsp.focus({ workspace = "e+1" }))
hl.bind(mod .. " + mouse_up", hl.dsp.focus({ workspace = "e-1" }))
hl.bind(mod .. " + mouse:272", hl.dsp.window.drag(), { mouse = true })
hl.bind(mod .. " + mouse:273", hl.dsp.window.resize(), { mouse = true })
-- Media / hardware keys (work locked, i.e. on the lock screen too)
hl.bind("XF86AudioRaiseVolume", hl.dsp.exec_cmd("wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+"), { locked = true, repeating = true })
hl.bind("XF86AudioLowerVolume", hl.dsp.exec_cmd("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"), { locked = true, repeating = true })
hl.bind("XF86AudioMute", hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"), { locked = true })
hl.bind("XF86AudioMicMute", hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"), { locked = true })
hl.bind("XF86MonBrightnessUp", hl.dsp.exec_cmd("brightnessctl -e4 -n2 set 5%+"), { locked = true, repeating = true })
hl.bind("XF86MonBrightnessDown", hl.dsp.exec_cmd("brightnessctl -e4 -n2 set 5%-"), { locked = true, repeating = true })
hl.bind("XF86AudioNext", hl.dsp.exec_cmd("playerctl next"), { locked = true })
hl.bind("XF86AudioPrev", hl.dsp.exec_cmd("playerctl previous"), { locked = true })
hl.bind("XF86AudioPlay", hl.dsp.exec_cmd("playerctl play-pause"), { locked = true })
-- ---------------------------------------------------------------------------
-- Autostart. polkit agent + the bread ecosystem + idle daemon + wallpaper.
-- (bos-live-setup appends the live-installer launch below this on the ISO.)
-- ---------------------------------------------------------------------------
hl.on("hyprland.start", function()
local startup = {
-- Prefer dark for GTK4/libadwaita apps (GTK3 uses settings.ini); without
-- this nautilus/breadbox render in light mode.
"gsettings set org.gnome.desktop.interface color-scheme prefer-dark",
"gsettings set org.gnome.desktop.interface gtk-theme Adwaita-dark",
"/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1",
"awww-daemon",
-- set the default wallpaper once the daemon is up (retry until ready)
[[bash -c 'until awww img /usr/share/backgrounds/bos/bread-background.png 2>/dev/null; do sleep 0.3; done']],
"breadd",
"breadbar",
"breadbox-sync",
"hypridle",
}
for _, cmd in ipairs(startup) do
hl.dispatch(hl.dsp.exec_cmd(cmd))
end
end)

View file

@ -0,0 +1,28 @@
# Lock screen (hyprlock). Solid dark background (no runtime-generated wallpaper
# dependency), accent matched to the Hyprland border colour.
general {
hide_cursor = true
}
background {
monitor =
color = rgba(46, 52, 64, 1.0)
blur_passes = 0
}
input-field {
monitor =
size = 20%, 5%
outline_thickness = 3
inner_color = rgba(0, 0, 0, 0.2)
outer_color = rgba(136, 192, 208, 0.8)
check_color = rgba(120, 220, 140, 0.95)
fail_color = rgba(255, 90, 90, 0.95)
font_color = rgba(255, 255, 255, 0.95)
fade_on_empty = false
rounding = 12
placeholder_text = <i>Password…</i>
position = 0, -20
halign = center
valign = center
}

View file

@ -1,58 +0,0 @@
$mod = SUPER
# App launchers
bind = $mod, Space, exec, breadbox
bind = $mod, N, exec, breadpad
bind = $mod, M, exec, breadman
bind = $mod, S, exec, bos-settings
# Core
bind = $mod, Return, exec, foot
bind = $mod, Q, killactive
bind = $mod SHIFT, E, exit
bind = $mod, F, fullscreen
# Focus
bind = $mod, H, movefocus, l
bind = $mod, L, movefocus, r
bind = $mod, K, movefocus, u
bind = $mod, J, movefocus, d
# Move windows
bind = $mod SHIFT, H, movewindow, l
bind = $mod SHIFT, L, movewindow, r
bind = $mod SHIFT, K, movewindow, u
bind = $mod SHIFT, J, movewindow, d
# Workspaces
bind = $mod, 1, workspace, 1
bind = $mod, 2, workspace, 2
bind = $mod, 3, workspace, 3
bind = $mod, 4, workspace, 4
bind = $mod, 5, workspace, 5
bind = $mod SHIFT, 1, movetoworkspace, 1
bind = $mod SHIFT, 2, movetoworkspace, 2
bind = $mod SHIFT, 3, movetoworkspace, 3
bind = $mod SHIFT, 4, movetoworkspace, 4
bind = $mod SHIFT, 5, movetoworkspace, 5
# Scroll through workspaces
bind = $mod, mouse_down, workspace, e+1
bind = $mod, mouse_up, workspace, e-1
# Mouse binds
bindm = $mod, mouse:272, movewindow
bindm = $mod, mouse:273, resizewindow
# Volume
bind = , XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
bind = , XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
bind = , XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
# Brightness
bind = , XF86MonBrightnessUp, exec, brightnessctl set 5%+
bind = , XF86MonBrightnessDown, exec, brightnessctl set 5%-
# Screenshot
bind = , Print, exec, grimblast copy area