Browse Source

Added sway configs; added tmux theme

master
chodak166 3 days ago
parent
commit
6914eaeacb
  1. 19
      .config/nvim/lazy-lock.json
  2. 68
      .config/nvim/lua/plugins/colorscheme.lua
  3. 610
      .config/sway/config
  4. 11
      .config/sway/scripts/always-float
  5. 28
      .config/sway/scripts/autoapp
  6. 36
      .config/sway/scripts/backlight
  7. 101
      .config/sway/scripts/gammastep-adjust
  8. 44
      .config/sway/scripts/output-profile
  9. 46
      .config/sway/scripts/swayexit
  10. 48
      .config/sway/scripts/translate-wl
  11. 68
      .config/sway/scripts/volctl
  12. 14
      .config/waybar/config.jsonc
  13. 16
      .config/waybar/disk.py
  14. 13
      .config/waybar/network.py
  15. 4
      .config/waybar/style.css
  16. 447
      .local/bin/btswitch
  17. 1
      .tmux.d/tmux-gruvbox

19
.config/nvim/lazy-lock.json

@ -1,6 +1,6 @@
{ {
"LazyVim": { "branch": "main", "commit": "c10948c50b18fae7f256433afdef09e432410480" }, "LazyVim": { "branch": "main", "commit": "c10948c50b18fae7f256433afdef09e432410480" },
"avante.nvim": { "branch": "main", "commit": "dee2402ed0b7c1d3710c0c8eed3d26aa055e118e" }, "avante.nvim": { "branch": "main", "commit": "d9c33ebe1e7205f416796b5b383d6894abe47495" },
"blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" }, "blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" },
"bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" }, "bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" },
"catppuccin": { "branch": "main", "commit": "49a926655a2f5579e9c276470fc300baaa49e524" }, "catppuccin": { "branch": "main", "commit": "49a926655a2f5579e9c276470fc300baaa49e524" },
@ -10,8 +10,9 @@
"dressing.nvim": { "branch": "master", "commit": "2d7c2db2507fa3c4956142ee607431ddb2828639" }, "dressing.nvim": { "branch": "master", "commit": "2d7c2db2507fa3c4956142ee607431ddb2828639" },
"flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" }, "flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" },
"friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" },
"gitsigns.nvim": { "branch": "main", "commit": "25050e4ed39e628282831d4cbecb1850454ce915" }, "gitsigns.nvim": { "branch": "main", "commit": "2038c666bd9d8a0b7349a0b6ee00dc83104b9ecf" },
"grug-far.nvim": { "branch": "main", "commit": "c995bbacf8229dc096ec1c3d60f8531059c86c1b" }, "grug-far.nvim": { "branch": "main", "commit": "c995bbacf8229dc096ec1c3d60f8531059c86c1b" },
"hybrid-theme": { "branch": "main", "commit": "6ae348938376f345e02eea4e6c27c0874b05f33a" },
"indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" }, "indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" },
"just-runner.nvim": { "branch": "main", "commit": "f29d405aa828900df242600720a2b0e57261489f" }, "just-runner.nvim": { "branch": "main", "commit": "f29d405aa828900df242600720a2b0e57261489f" },
"lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" },
@ -19,20 +20,20 @@
"lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" }, "lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" },
"mason-lspconfig.nvim": { "branch": "main", "commit": "21c5b3ebeaa0412e28096bb0701434c51c1fbf76" }, "mason-lspconfig.nvim": { "branch": "main", "commit": "21c5b3ebeaa0412e28096bb0701434c51c1fbf76" },
"mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" }, "mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" },
"mini.ai": { "branch": "main", "commit": "4511b3481707c1d021485475d34f2ed2a50bf47b" }, "mini.ai": { "branch": "main", "commit": "d73c36349aa7b0bab5f77ad71701a1d42211a1df" },
"mini.files": { "branch": "main", "commit": "02874bc653fbecf2bee2c65441d0ebd09110f011" }, "mini.files": { "branch": "main", "commit": "a5689dae6b732955e33eec225b798d6815063179" },
"mini.icons": { "branch": "main", "commit": "ac38c983aed0a2bd32a65ca3e2348e12e58ca292" }, "mini.icons": { "branch": "main", "commit": "e56797f90192d81f1fda02e662fc3e8e3d775027" },
"mini.pairs": { "branch": "main", "commit": "30cf2f01c4aaa2033db67376b9924fa2442c05d6" }, "mini.pairs": { "branch": "main", "commit": "4a014143fcb4e9df26198ccb3ecff3b9e77a048c" },
"noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" }, "noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" },
"nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" },
"nvim-lint": { "branch": "master", "commit": "1ba49820a3c29ba6ab1b2dd441a63b3822c4e39b" }, "nvim-lint": { "branch": "master", "commit": "01c9842c089069ab497430159312b2c8868a4590" },
"nvim-lspconfig": { "branch": "master", "commit": "a683e0ddf0cf64c6cd689e18ffb480ade3c162b7" }, "nvim-lspconfig": { "branch": "master", "commit": "bfcc0171a43f22afa61d927ffe9fcb6cb85dc99e" },
"nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" }, "nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" },
"nvim-treesitter-textobjects": { "branch": "main", "commit": "851e865342e5a4cb1ae23d31caf6e991e1c99f1e" }, "nvim-treesitter-textobjects": { "branch": "main", "commit": "851e865342e5a4cb1ae23d31caf6e991e1c99f1e" },
"nvim-ts-autotag": { "branch": "main", "commit": "88c1453db4ba7dd24131086fe51fdf74e587d275" }, "nvim-ts-autotag": { "branch": "main", "commit": "88c1453db4ba7dd24131086fe51fdf74e587d275" },
"persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" }, "persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" },
"plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" }, "plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" },
"render-markdown.nvim": { "branch": "main", "commit": "5adf0895310c1904e5abfaad40a2baad7fe44a07" }, "render-markdown.nvim": { "branch": "main", "commit": "f422cb5c6855f150e2ddcfaf44e7157b98b34f6a" },
"snacks.nvim": { "branch": "main", "commit": "882c996cf28183f4d63640de0b4c02ec886d01f2" }, "snacks.nvim": { "branch": "main", "commit": "882c996cf28183f4d63640de0b4c02ec886d01f2" },
"todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" },
"tokyonight.nvim": { "branch": "main", "commit": "cdc07ac78467a233fd62c493de29a17e0cf2b2b6" }, "tokyonight.nvim": { "branch": "main", "commit": "cdc07ac78467a233fd62c493de29a17e0cf2b2b6" },

68
.config/nvim/lua/plugins/colorscheme.lua

@ -13,39 +13,39 @@
-- } -- }
-- Local development: -- Local development:
return {
dir = "/home/chodak/src/git/nvim-hybrid-theme",
name = "hybrid-theme",
lazy = false,
priority = 1000,
config = function()
require("hybrid-theme").setup({
theme = "dark",
transparent = false,
background_variant = "flat",
italics = {
comments = true,
keywords = false,
functions = false,
strings = false,
variables = false,
},
})
require("hybrid-theme").colorscheme()
end,
}
-- return { -- return {
-- { -- dir = "/home/chodak/src/git/nvim-hybrid-theme",
-- "chodak166/nvim-hybrid-theme", -- name = "hybrid-theme",
-- name = "hybrid-theme", -- lazy = false,
-- lazy = false, -- priority = 1000,
-- priority = 1000, -- config = function()
-- config = function() -- require("hybrid-theme").setup({
-- require("hybrid-theme").setup({ -- theme = "dark",
-- background_variant = "semi_flat", -- transparent = false,
-- }) -- background_variant = "flat",
-- require("hybrid-theme").colorscheme() -- italics = {
-- end, -- comments = true,
-- }, -- keywords = false,
-- functions = false,
-- strings = false,
-- variables = false,
-- },
-- })
-- require("hybrid-theme").colorscheme()
-- end,
-- } -- }
return {
{
"chodak166/nvim-hybrid-theme",
name = "hybrid-theme",
lazy = false,
priority = 1000,
config = function()
require("hybrid-theme").setup({
background_variant = "semi_flat",
})
require("hybrid-theme").colorscheme()
end,
},
}

610
.config/sway/config

@ -0,0 +1,610 @@
#----------------------------------------------------------------
# Sway Config — Arch + Wayland
#
# Migrated from i3/X11 config. All X11-specific tools have been
# replaced with Wayland-native equivalents (see migration notes
# throughout this file).
#
# Install script: arch-init.sh
#----------------------------------------------------------------
#################################################################
# Variables
#################################################################
# Mod key: Mod4 = Super/Windows key, Mod1 = Alt
set $mod Mod4
# Helper scripts directory (Wayland replacements for ratflow scripts)
set $scriptsDir ~/.config/sway/scripts
# Config directory
set $configDir ~/.config/sway
#################################################################
# Workspaces
#################################################################
set $workspace1 1: >_
set $workspace2 2: dev
set $workspace3 3: www
set $workspace4 4: files
set $workspace5 5: e-mail
set $workspace6 6: IM
set $workspace7 7: video
set $workspace8 8: workspace
set $workspace9 9: workspace
set $workspace10 10: Music
set $workspace11 V: VM
# Switch to workspace
bindsym $mod+1 workspace $workspace1
bindsym $mod+2 workspace $workspace2
bindsym $mod+3 workspace $workspace3
bindsym $mod+4 workspace $workspace4
bindsym $mod+5 workspace $workspace5
bindsym $mod+6 workspace $workspace6
bindsym $mod+7 workspace $workspace7
bindsym $mod+8 workspace $workspace8
bindsym $mod+9 workspace $workspace9
bindsym $mod+0 workspace $workspace10
# Move focused container to workspace
bindsym $mod+Shift+1 move container to workspace $workspace1
bindsym $mod+Shift+2 move container to workspace $workspace2
bindsym $mod+Shift+3 move container to workspace $workspace3
bindsym $mod+Shift+4 move container to workspace $workspace4
bindsym $mod+Shift+5 move container to workspace $workspace5
bindsym $mod+Shift+6 move container to workspace $workspace6
bindsym $mod+Shift+7 move container to workspace $workspace7
bindsym $mod+Shift+8 move container to workspace $workspace8
bindsym $mod+Shift+9 move container to workspace $workspace9
bindsym $mod+Shift+0 move container to workspace $workspace10
# Next/prev workspace
bindsym $mod+x workspace next
bindsym $mod+Shift+x move container to workspace next
bindsym $mod+z workspace prev
bindsym $mod+Shift+z move container to workspace prev
# Moving workspace across monitors
# MIGRATION: xrandr replaced by swaymsg output commands
bindsym $mod+Control+Left move workspace to output left
bindsym $mod+Control+Right move workspace to output right
#################################################################
# Output / Monitor Management
# MIGRATION: xrandr → swaymsg output / kanshi for auto profiles
#################################################################
# Define your outputs — run `swaymsg -t get_outputs` to get names
set $leftOutput eDP-1
set $rightOutput HDMI-A-1
# Default monitor setup
# sway handles output layout natively, no xrandr needed
output $rightOutput pos 1920 0
output $leftOutput pos 0 0
# Mode for toggling outputs (replaces i3 "outputs" mode)
mode "outputs" {
# $mod+Shift+1: turn off left monitor; $mod+1: turn it on
bindsym $mod+Shift+1 output $leftOutput disable; mode "default"
bindsym $mod+1 output $leftOutput enable; mode "default"
# $mod+Shift+2: turn off right monitor; $mod+2: turn it on
bindsym $mod+Shift+2 output $rightOutput disable; mode "default"
bindsym $mod+2 output $rightOutput enable; mode "default"
bindsym Return mode "default"
bindsym Escape mode "default"
}
bindsym $mod+m mode "outputs"
#################################################################
# Wallpaper
# MIGRATION: feh → swaybg (Wayland-native wallpaper setter)
# Omarchy also uses swaybg for this purpose.
#################################################################
set $wallpaper1 /usr/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png
set $wallpaper2 /usr/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png
# swaybg is a native Wayland wallpaper setter
output $leftOutput bg $wallpaper1 fill
output $rightOutput bg $wallpaper2 fill
#################################################################
# Input Device Configuration
# MIGRATION: synclient → sway input {} blocks
# X11 touchpad/synaptics config replaced by libinput via sway.
#################################################################
input "type:touchpad" {
tap enabled
click_method button_areas
scroll_method two_finger
dwt enabled
# natural_scroll enabled # uncomment if you prefer macOS-style scrolling
}
input "type:keyboard" {
xkb_layout pl
# xkb_variant ...
# xkb_options caps:escape # uncomment to remap Caps Lock to Escape
}
#################################################################
# Application Launchers
# MIGRATION: ulauncher works on Wayland but is GTK-based.
# Alternatives: wofi (native), rofi-wayland, tofi.
# dmenu_run replaced by wofi (or keep as dmenu_path | wofi -d).
# Omarchy uses Walker — a modern Wayland-native launcher.
#################################################################
# Terminal
bindsym $mod+Return exec kitty
# App launcher: wofi (lightweight, Wayland-native)
# Alternatives: rofi -show drun (rofi-wayland package), tofi
bindsym $mod+d exec fuzzel
bindsym Mod1+F2 exec wofi --show run
# Clipboard manager — show history (Ctrl+Alt+H)
# bindsym Control+Mod1+h exec copyq toggle
bindsym Control+Mod1+h exec cliphist list | fuzzel --width 80 --dmenu | cliphist decode | wl-copy
# Run app assigned to current workspace
bindsym $mod+Shift+a exec $scriptsDir/autoapp
#################################################################
# Window Navigation
# MIGRATION: i3-msg workspace back_and_forth → same in sway
#################################################################
bindsym $mod+Tab workspace back_and_forth
#################################################################
# Window Management
# MIGRATION: nearly identical to i3 — sway is i3-compatible
#################################################################
# Use Mouse+$mod to drag floating windows
floating_modifier $mod
# Kill focused window
bindsym $mod+Shift+q kill
# Change focus (vim keys)
bindsym $mod+j focus left
bindsym $mod+k focus down
bindsym $mod+l focus up
bindsym $mod+semicolon focus right
# Change focus (arrow keys)
bindsym $mod+Left focus left
bindsym $mod+Down focus down
bindsym $mod+Up focus up
bindsym $mod+Right focus right
# Move focused window (vim keys)
bindsym $mod+Shift+j move left
bindsym $mod+Shift+k move down
bindsym $mod+Shift+l move up
bindsym $mod+Shift+semicolon move right
# Move focused window (arrow keys)
bindsym $mod+Shift+Left move left
bindsym $mod+Shift+Down move down
bindsym $mod+Shift+Up move up
bindsym $mod+Shift+Right move right
# Split orientation
bindsym $mod+h split h
bindsym $mod+v split v
# Fullscreen
bindsym $mod+f fullscreen
# Layout modes
bindsym $mod+s layout stacking
bindsym $mod+w layout tabbed
bindsym $mod+e layout toggle split
# Toggle tiling / floating
bindsym $mod+Shift+space floating toggle
bindsym $mod+button2 floating toggle
# Focus tiling/floating toggle
bindsym $mod+space focus mode_toggle
# Focus parent container
bindsym $mod+a focus parent
# Always-float toggle (custom script)
bindsym $mod+Shift+f exec $scriptsDir/always-float
#################################################################
# Resize Mode
#################################################################
mode "resize" {
bindsym j resize shrink width 10 px or 10 ppt
bindsym k resize grow height 10 px or 10 ppt
bindsym l resize shrink height 10 px or 10 ppt
bindsym semicolon resize grow width 10 px or 10 ppt
bindsym Left resize shrink width 10 px or 10 ppt
bindsym Down resize grow height 10 px or 10 ppt
bindsym Up resize shrink height 10 px or 10 ppt
bindsym Right resize grow width 10 px or 10 ppt
bindsym Return mode "default"
bindsym Escape mode "default"
}
bindsym $mod+r mode "resize"
#################################################################
# Screenshots
# MIGRATION: screengrab (X11) → grim + slurp (Wayland-native)
# grim = screen capture (replaces scrot/import/screengrab)
# slurp = region selector (Wayland-native)
# wl-copy copies to Wayland clipboard
# Omarchy also uses grim + slurp (+ satty for annotation).
#################################################################
# Fullscreen screenshot → save to ~/Pictures and copy to clipboard
bindsym Print exec grim -t png ~/Pictures/screenshot_$(date +%Y%m%d_%H%M%S).png && grim -t png - | wl-copy -t image/png
# Region screenshot → select area with slurp
bindsym Shift+Print exec grim -t png -g "$(slurp)" ~/Pictures/screenshot_$(date +%Y%m%d_%H%M%S).png && grim -t png -g "$(slurp)" - | wl-copy -t image/png
# Active window screenshot (sway-specific: get focused window geometry)
bindsym Control+Print exec grim -t png -g "$(swaymsg -t get_tree | jq -j '.. | select(.type?) | select(.focused) | .rect | "\(.x),\(.y) \(.width)x\(.height)"')" ~/Pictures/screenshot_$(date +%Y%m%d_%H%M%S).png
#################################################################
# Calendar
# MIGRATION: osmo/gsimplecal (X11) → keep osmo if desired,
# or use waybar clock module + rofi/wofi calendar script.
# Omarchy uses waybar clock module only (no standalone calendar app).
#################################################################
bindsym $mod+c exec osmo -c
# Alternative: wofi-based calendar popup
# bindsym $mod+c exec $scriptsDir/calendar-popup
#################################################################
# Screen Color Temperature
# MIGRATION: redshift (X11) → gammastep (Wayland fork of redshift)
# or wlsunset (lighter alternative).
# Omarchy uses hyprsunset (Hyprland-specific), but for sway
# gammastep is the standard choice.
# $scriptsDir/gammastep-adjust replaces redshift-adjust.
#################################################################
bindsym $mod+Control+KP_Next exec $scriptsDir/gammastep-adjust "-500"
bindsym $mod+Control+KP_Prior exec $scriptsDir/gammastep-adjust "+500"
bindsym $mod+Control+l exec gammastep -x
#################################################################
# Translation of Selected Text
# MIGRATION: trans-xsel (X11 xsel) → translate-shell + wl-clipboard
# Uses wl-paste / wl-copy instead of xsel/xclip.
#################################################################
bindsym $mod+t exec bash -c "$scriptsDir/translate-wl en:pl &"
bindsym $mod+Shift+t exec bash -c "$scriptsDir/translate-wl pl:en &"
#################################################################
# Multimedia Keys & Audio
# MIGRATION: PulseAudio volctl → PipeWire + wpctl (or pamixer)
# Arch + Wayland standard is PipeWire with WirePlumber.
# Volume OSD: SwayOSD (Omarchy approach) or swayosd-server.
# The $scriptsDir/volctl wrapper uses wpctl/pamixer underneath.
#################################################################
# Volume controls (primary sink)
bindsym XF86AudioRaiseVolume exec --no-startup-id $scriptsDir/volctl up
bindsym XF86AudioLowerVolume exec --no-startup-id $scriptsDir/volctl down
bindsym XF86AudioMute exec --no-startup-id $scriptsDir/volctl toggle
# Volume controls (secondary sink, e.g. HDMI)
bindsym Shift+XF86AudioRaiseVolume exec --no-startup-id SINK_NUM=1 $scriptsDir/volctl up
bindsym Shift+XF86AudioLowerVolume exec --no-startup-id SINK_NUM=1 $scriptsDir/volctl down
bindsym Shift+XF86AudioMute exec --no-startup-id SINK_NUM=1 $scriptsDir/volctl toggle
# Screen brightness
# MIGRATION: xbacklight / ratflow-backlight → brightnessctl
bindsym XF86MonBrightnessUp exec --no-startup-id $scriptsDir/backlight up
bindsym XF86MonBrightnessDown exec --no-startup-id $scriptsDir/backlight down
# Media player controls
# MIGRATION: clementine-specific → playerctl (agnostic MPRIS controller)
# playerctl works with any MPRIS2-compatible player (Spotify, mpv, etc.)
bindsym XF86AudioPlay exec playerctl play-pause
bindsym XF86AudioPause exec playerctl pause
bindsym XF86AudioNext exec playerctl next
bindsym XF86AudioPrev exec playerctl previous
#################################################################
# Projector / Screen Layout
# MIGRATION: xrandr shell scripts → swaymsg output commands
# kanshi can auto-switch profiles on hotplug.
#################################################################
bindsym $mod+p exec $scriptsDir/output-profile projector
bindsym $mod+Shift+p exec $scriptsDir/output-profile edp-only
#################################################################
# Session / Power Management
# MIGRATION: i3-nagbar → swaynag, i3exit → loginctl-based script
# swayidle handles DPMS/idle (replaces xset dpms).
# swaylock replaces i3lock.
# Omarchy uses hyprlock+hypridle, sway equivalents are swaylock+swayidle.
#################################################################
# Reload sway config
bindsym $mod+Shift+c exec swaymsg reload
# Suspend
bindsym $mod+Escape exec systemctl suspend
# Restart sway
bindsym $mod+Shift+r exec swaymsg reload
# Exit sway
bindsym $mod+Shift+e exec swaynag -t warning -m 'Exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'
# Session management mode (replaces i3exit)
set $exitScript $scriptsDir/swayexit
mode "session_management" {
bindsym l exec --no-startup-id $exitScript lock, mode "default"
bindsym e exec --no-startup-id $exitScript logout, mode "default"
bindsym s exec --no-startup-id $exitScript suspend, mode "default"
bindsym h exec --no-startup-id $exitScript hibernate, mode "default"
bindsym r exec --no-startup-id $exitScript reboot, mode "default"
bindsym Shift+s exec --no-startup-id $exitScript shutdown, mode "default"
bindsym Return mode "default"
bindsym Escape mode "default"
}
bindsym $mod+Pause mode "session_management"
#################################################################
# New Workspace
# MIGRATION: yad → zenity (or rofi/wofi)
# yad has some Wayland issues; zenity is GTK and works.
# Alternatively, use wofi for a pure Wayland input dialog.
#################################################################
bindsym $mod+n exec name=$(wofi --dmenu --prompt "Workspace name") && swaymsg workspace "$name"
#################################################################
# Theme / Appearance
# MIGRATION: No i3 client colors — sway has the same syntax.
# compton → not needed (sway has built-in compositor with
# basic effects). For blur/shadows, use swayfx (fork of sway).
# Omarchy uses Hyprland which has built-in blur/animation;
# for sway, swayfx adds these features.
#################################################################
# Font
set $fontName "Source Sans 3 Semi-Bold"
set $fontSize 10
set $barFontSize 9
font pango: $fontName $fontSize
# Window colors
# border background text indicator
client.focused #252525 #252525 #D9D9D9 #101010
client.focused_inactive #101010 #101010 #606060 #101010
client.unfocused #101010 #000000 #606060 #101010
client.urgent #F05000 #F05000 #F0F0F0 #101010
# Default border style
default_border pixel 2
default_floating_border normal 2
# Gaps (optional — sway supports gaps natively, unlike stock i3)
# gaps inner 5
# gaps outer 2
# Window opacity (requires swayfx for per-window opacity, or use
# sway's built-in opacity for all windows)
# for_window [app_id="kitty"] opacity 0.95
#################################################################
# Bar — Waybar
# MIGRATION: i3bar + py3status → waybar
# waybar is the standard bar for wlroots-based compositors.
# Omarchy uses waybar with extensive modules.
# Config files: ~/.config/waybar/config.jsonc + style.css
#################################################################
bar {
swaybar_command waybar
}
#################################################################
# Window Assignments
# MIGRATION: class= → app_id= for native Wayland apps.
# XWayland apps still use class=. Use `swaymsg -t get_tree`
# to find the correct app_id for native Wayland apps.
# Note: some apps may need both rules.
#################################################################
# Development
assign [app_id="qtcreator"] $workspace2
assign [class="Qtcreator"] $workspace2
assign [app_id="eclipse"] $workspace2
assign [class="Eclipse"] $workspace2
# Browser
assign [app_id="firefox"] $workspace3
assign [class="Firefox"] $workspace3
assign [app_id="chromium"] $workspace3
assign [class="Chromium-browser"] $workspace3
assign [class="Chrome"] $workspace3
# File managers
assign [app_id="pcmanfm-qt"] $workspace4
assign [class="Pcmanfm"] $workspace4
assign [app_id="dolphin"] $workspace4
assign [class="Dolphin"] $workspace4
assign [app_id="nautilus"] $workspace4
assign [class="Nautilus"] $workspace4
assign [app_id="thunar"] $workspace4
assign [class="Thunar"] $workspace4
# E-mail
assign [app_id="thunderbird"] $workspace5
assign [class="Thunderbird"] $workspace5
# IM
assign [app_id="telegram-desktop"] $workspace6
assign [class="Telegram"] $workspace6
assign [class="Skype"] $workspace6
# Video
assign [app_id="kodi"] $workspace7
assign [class="Kodi"] $workspace7
# Music
assign [app_id="spotify"] $workspace10
assign [class="Spotify"] $workspace10
assign [class="Clementine"] $workspace10
# VM
assign [class="VirtualBox"] $workspace11
assign [app_id="virt-manager"] $workspace11
#################################################################
# Floating Windows
#################################################################
for_window [app_id="screengrab"] floating enable
for_window [app_id="osmo"] floating enable
for_window [app_id="gsimplecal"] floating enable
for_window [class="Osmo"] floating enable
for_window [class="Skype"] floating enable
for_window [app_id="yad"] floating enable
for_window [class="Yad"] floating enable
for_window [app_id="wofi"] floating enable
for_window [app_id="swaync"] floating enable
#################################################################
# Idle Management
# MIGRATION: xset dpms → swayidle
# Locks screen after timeout, turns off display.
# Omarchy uses hypridle; sway equivalent is swayidle.
#################################################################
set $lockCommand swaylock -f -c 000000
exec swayidle -w \
timeout 600 '$lockCommand' \
timeout 900 'swaymsg "output * dpms off"' \
resume 'swaymsg "output * dpms on"' \
before-sleep '$lockCommand'
#################################################################
# Autostart
# MIGRATION NOTES:
# dunst → mako (Wayland-native notifier, used by Omarchy)
# or swaync (Sway Notification Center, more feature-rich)
# compton → NOT NEEDED (sway has built-in compositor)
# For blur/rounded corners, use swayfx
# synclient → sway input {} block (see above)
# redshift → gammastep or wlsunset
# nm-applet → nm-applet still works on Wayland, or use
# waybar network module + impala TUI (Omarchy approach)
# parcellite → cliphist + wl-clipboard (Wayland clipboard manager)
# cliphist stores history, wl-copy/wl-paste for access
# xset dpms → swayidle (see above)
#################################################################
# Notification daemon — mako (Omarchy uses mako)
exec --no-startup-id mako
# Alternative: swaync (Sway Notification Center) — more feature-rich
# exec --no-startup-id swaync
# Screen color temperature
exec --no-startup-id gammastep -l 52.43:15.15 -m wayland
# Network manager applet (still works on Wayland)
exec --no-startup-id nm-applet --indicator
# Clipboard manager
# Use Ctrl+Alt+H to toggle the clipboard history window
# exec --no-startup-id wl-paste --watch --type image cliphist store
exec --no-startup-id wl-paste --type text --watch cliphist store
exec --no-startup-id wl-paste --type image --watch cliphist store
# Bluetooth manager (waybar module can handle this, or use blueman-applet)
# exec --no-startup-id blueman-applet
# Polkit authentication agent (needed for GUI apps that need root)
exec --no-startup-id /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1
# Background services for XDG desktop portals (screen sharing, file picker)
exec --no-startup-id dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=sway
#################################################################
# Key repeat rate
#################################################################
# input "type:keyboard" {
# xkb_layout pl
# # xkb_variant "programmer"
# xkb_options "grp:alt_shift_toggle, compose:ralt"
# repeat_delay 300
# repeat_rate 40
# }
# input type:keyboard { xkb_layout pl xkb_options grp:win_space_toggle }
# input type:keyboard {
# xkb_layout pl
# xkb_options level3:ralt_switch
# }
# input type:keyboard {
# xkb_layout pl
# xkb_options grp:alt_shift_toggle
# }
input type:keyboard {
xkb_layout pl,us
# lv3:ralt_switch keeps Right Alt working for Polish chars
# grp:alt_shift_toggle allows Alt+Shift to switch layouts
xkb_options lv3:ralt_switch,grp:alt_shift_toggle
}

11
.config/sway/scripts/always-float

@ -0,0 +1,11 @@
#!/bin/bash
#----------------------------------------------------------------
# always-float — Toggle floating on the currently focused window
#
# Adapted from the ratflow always-float script.
# Uses swaymsg instead of i3-msg.
#
# Dependencies: sway
#----------------------------------------------------------------
swaymsg floating toggle

28
.config/sway/scripts/autoapp

@ -0,0 +1,28 @@
#!/bin/bash
#----------------------------------------------------------------
# autoapp — Launch the application assigned to current workspace
#
# Adapted from the ratflow autoapp script.
# Reads workspace assignments and launches the matching app.
# Uses swaymsg instead of i3-msg.
#
# Dependencies: sway, jq
#----------------------------------------------------------------
# Get current workspace name
WORKSPACE=$(swaymsg -t get_workspaces | jq -r '.[] | select(.focused) | .name')
# Map workspace names to applications
# Customize these to match your workflow
case "$WORKSPACE" in
*">_"*) kitty ;;
*"dev"*) kitty ;;
*"www"*) firefox ;;
*"files"*) thunar ;;
*"e-mail"*) thunderbird ;;
*"IM"*) telegram-desktop ;;
*"video"*) mpv ;;
*"Music"*) spotify ;;
*"VM"*) virt-manager ;;
*) echo "No app assigned to workspace: $WORKSPACE" ;;
esac

36
.config/sway/scripts/backlight

@ -0,0 +1,36 @@
#!/bin/bash
#----------------------------------------------------------------
# backlight — Screen brightness control using brightnessctl
#
# Replaces the old ratflow backlight script (xbacklight-based).
# brightnessctl works on Wayland without X11 dependencies.
#
# Usage:
# backlight up — increase brightness by 5%
# backlight down — decrease brightness by 5%
# backlight set N — set brightness to N percent
# backlight get — print current brightness percentage
#
# Dependencies: brightnessctl
#----------------------------------------------------------------
STEP=5
case "$1" in
up)
brightnessctl set "${STEP}%+" -q
;;
down)
brightnessctl set "${STEP}%-" -q
;;
set)
brightnessctl set "${2}%" -q
;;
get)
brightnessctl info | grep -oP '\d+%' | head -1 | tr -d '%'
;;
*)
echo "Usage: backlight {up|down|set N|get}"
exit 1
;;
esac

101
.config/sway/scripts/gammastep-adjust

@ -0,0 +1,101 @@
#!/bin/bash
#----------------------------------------------------------------
# gammastep-adjust — Adjust gammastep color temperature
#
# Replaces the old ratflow redshift-adjust script.
# gammastep is the Wayland fork of redshift; it uses the same
# temperature range (1000K–25000K, default 6500K = daylight).
#
# Usage:
# gammastep-adjust -100 — make screen warmer (lower temperature by 100K)
# gammastep-adjust +100 — make screen cooler (raise temperature by 100K)
#
# How it works:
# gammastep doesn't support runtime temperature changes directly.
# This script writes the current temperature to a state file,
# kills any running gammastep, and launches a new one in one-shot
# mode (-O) with the new temperature.
#
# State file: /tmp/gammastep-current-temp
# PID file: /tmp/gammastep-pid
# Default: 6500 (neutral/daylight)
#
# Dependencies: gammastep
#----------------------------------------------------------------
set -x
STATE_FILE="/tmp/gammastep-current-temp"
PID_FILE="/tmp/gammastep-pid"
DEFAULT_TEMP=6500
MIN_TEMP=1000
MAX_TEMP=25000
# Read current temperature or use default
if [ -f "$STATE_FILE" ]; then
CURRENT=$(cat "$STATE_FILE")
else
CURRENT=$DEFAULT_TEMP
fi
# Parse argument
DELTA="${1:-0}"
# Strip the sign to get the absolute value
ABS_DELTA="${DELTA#+}"
ABS_DELTA="${ABS_DELTA#-}"
if [ -z "$ABS_DELTA" ]; then
echo "Usage: gammastep-adjust <+/-N>"
echo " Example: gammastep-adjust -100 (warmer)"
echo " Example: gammastep-adjust +100 (cooler)"
exit 1
fi
# Calculate new temperature
NEW_TEMP=$((CURRENT + DELTA))
# Clamp to valid range
if [ "$NEW_TEMP" -lt "$MIN_TEMP" ]; then
NEW_TEMP=$MIN_TEMP
fi
if [ "$NEW_TEMP" -gt "$MAX_TEMP" ]; then
NEW_TEMP=$MAX_TEMP
fi
# Save new state
echo "$NEW_TEMP" >"$STATE_FILE"
# Kill existing gammastep instance(s)
# Priority 1: use PID file if available (most precise)
if [ -f "$PID_FILE" ]; then
OLD_PID=$(cat "$PID_FILE")
if kill -0 "$OLD_PID" 2>/dev/null; then
kill "$OLD_PID" 2>/dev/null
# Give gammastep a moment to release the display and exit
sleep 0.2
fi
rm -f "$PID_FILE"
fi
# Priority 2: kill any stray gammastep processes
# -x (exact match) ensures we don't kill this script (gammastep-adjust)
pkill -x gammastep 2>/dev/null
sleep 0.1
# Launch gammastep with the new temperature.
#
# IMPORTANT: We use "setsid" (create a new session) so that gammastep is
# completely detached from the shell that Sway spawns for this keybinding.
# Without setsid, Sway kills gammastep when the keybinding shell exits,
# even with "&" — because the process is still in the same process group.
# setsid makes gammastep its own session leader, immune to cleanup.
# if [ "$NEW_TEMP" -ge "$DEFAULT_TEMP" ]; then
# # At or above neutral — reset to no tint
# setsid gammastep -x 2>/dev/null &
# echo $! >"$PID_FILE"
# echo "Temperature reset to neutral ($DEFAULT_TEMP K)"
# else
# Below neutral — apply one-shot manual temperature
setsid gammastep -O "$NEW_TEMP" 2>/dev/null &
echo $! >"$PID_FILE"
echo "Temperature set to $NEW_TEMP K"
# fi

44
.config/sway/scripts/output-profile

@ -0,0 +1,44 @@
#!/bin/bash
#----------------------------------------------------------------
# output-profile — Switch sway output profiles
#
# Replaces xrandr shell scripts used in the old i3 config.
# Uses swaymsg output commands to configure displays.
#
# Usage:
# output-profile projector — enable HDMI output (mirror or extend)
# output-profile edp-only — disable all external outputs
# output-profile dual — dual monitor setup
#
# Dependencies: sway
#
# NOTE: Edit the output names to match your hardware.
# Run `swaymsg -t get_outputs` to list connected outputs.
#----------------------------------------------------------------
# Output names — adjust to match your hardware
LAPTOP="eDP-1"
EXTERNAL="HDMI-A-1"
case "$1" in
projector)
# Enable external output, mirror the laptop display
swaymsg output "$EXTERNAL" enable pos 0 0
swaymsg output "$LAPTOP" pos 0 0
;;
edp-only)
# Disable external output, laptop only
swaymsg output "$EXTERNAL" disable
;;
dual)
# Dual monitor: laptop left, external right
swaymsg output "$LAPTOP" pos 0 0
swaymsg output "$EXTERNAL" pos 1920 0
;;
*)
echo "Usage: output-profile {projector|edp-only|dual}"
echo " Edit this script to match your output names."
echo " Run 'swaymsg -t get_outputs' to list connected outputs."
exit 1
;;
esac

46
.config/sway/scripts/swayexit

@ -0,0 +1,46 @@
#!/bin/bash
#----------------------------------------------------------------
# swayexit — Session management for sway on Wayland
#
# Replaces the old i3exit script (i3/X11-based).
# Uses loginctl for session management (systemd-logind).
#
# Usage:
# swayexit lock — lock the screen (swaylock)
# swayexit logout — exit sway
# swayexit suspend — suspend to RAM
# swayexit hibernate — suspend to disk
# swayexit reboot — reboot the system
# swayexit shutdown — power off the system
#
# Dependencies: swaylock, systemd (loginctl)
#----------------------------------------------------------------
case "$1" in
lock)
swaylock -f -c 000000
;;
logout)
swaymsg exit
;;
suspend)
swaylock -f -c 000000 &
sleep 0.5
systemctl suspend
;;
hibernate)
swaylock -f -c 000000 &
sleep 0.5
systemctl hibernate
;;
reboot)
systemctl reboot
;;
shutdown)
systemctl poweroff
;;
*)
echo "Usage: swayexit {lock|logout|suspend|hibernate|reboot|shutdown}"
exit 1
;;
esac

48
.config/sway/scripts/translate-wl

@ -0,0 +1,48 @@
#!/bin/bash
#----------------------------------------------------------------
# translate-wl — Translate selected text using translate-shell
# with Wayland clipboard (wl-clipboard)
#
# Replaces the old ratflow trans-xsel script (X11 xsel-based).
# Uses wl-paste to get clipboard content and wl-copy to write
# the translation back, plus a notification via notify-send
# (which works with mako/swaync on Wayland).
#
# Usage:
# translate-wl en:pl — translate English to Polish
# translate-wl pl:en — translate Polish to English
# translate-wl de:en — translate German to English, etc.
#
# Workflow:
# 1. Select text (it goes to Wayland primary/clipboard)
# 2. Press the bound key (e.g. $mod+t)
# 3. Script reads selection via wl-paste, translates,
# shows notification, and copies result to clipboard
#
# Dependencies: translate-shell (trans), wl-clipboard, libnotify
#----------------------------------------------------------------
LANG_PAIR="${1:-en:pl}"
# Get clipboard content (user should select text first)
# wl-paste gets the clipboard content; for primary selection use wl-paste -p
TEXT=$(wl-paste -p 2>/dev/null || wl-paste 2>/dev/null)
if [ -z "$TEXT" ]; then
notify-send -t 3000 "Translation" "No text in clipboard/selection"
exit 1
fi
# Translate using translate-shell
RESULT=$(trans -b "$LANG_PAIR" "$TEXT" 2>/dev/null)
if [ -z "$RESULT" ]; then
notify-send -t 3000 "Translation" "Translation failed"
exit 1
fi
# Copy result to clipboard
echo -n "$RESULT" | wl-copy
# Show notification
notify-send -t 5000 "Translation ($LANG_PAIR)" "$RESULT"

68
.config/sway/scripts/volctl

@ -0,0 +1,68 @@
#!/bin/bash
#----------------------------------------------------------------
# volctl — Volume control wrapper for PipeWire + WirePlumber
#
# Replaces the old ratflow volctl (PulseAudio-based).
# Uses wpctl (WirePlumber CLI) for volume management.
#
# Usage:
# volctl up — increase volume by 5%
# volctl down — decrease volume by 5%
# volctl toggle — toggle mute on default sink
# volctl mute — mute default sink
# volctl unmute — unmute default sink
#
# Environment:
# SINK_NUM — if set, selects Nth sink (0=default, 1=next, etc.)
# mirrors the old VOLCTL_SINK_NUM behavior
#
# Dependencies: wireplumber, wpctl, pipewire, pipewire-pulse
#----------------------------------------------------------------
STEP=5
# Resolve which sink to use based on SINK_NUM (like old VOLCTL_SINK_NUM)
# SINK_NUM=0 or unset → default sink, SINK_NUM=1 → second sink, etc.
get_sink_id() {
local num="${SINK_NUM:-0}"
if [ "$num" = "0" ]; then
echo "@DEFAULT_AUDIO_SINK@"
else
# List sinks and pick the Nth one (1-indexed in SINK_NUM)
local sinks
sinks=$(wpctl status | grep -A 100 'Audio' | grep -A 100 'Sinks:' | grep -oP '\d+\.' | head -n $((num + 1)) | tail -1 | tr -d '.')
if [ -z "$sinks" ]; then
echo "@DEFAULT_AUDIO_SINK@"
else
echo "$sinks"
fi
fi
}
SINK=$(get_sink_id)
case "$1" in
up)
wpctl set-volume -l 1.5 "$SINK" "${STEP}%+"
;;
down)
wpctl set-volume "$SINK" "${STEP}%-"
;;
toggle)
wpctl set-mute "$SINK" toggle
;;
mute)
wpctl set-mute "$SINK" 1
;;
unmute)
wpctl set-mute "$SINK" 0
;;
*)
echo "Usage: volctl {up|down|toggle|mute|unmute}"
echo " Set SINK_NUM env var to select sink (0=default, 1=second, etc.)"
exit 1
;;
esac
# Optional: send signal to waybar to update volume display
# pkill -SIGRTMIN+1 waybar

14
.config/waybar/config.jsonc

@ -31,20 +31,20 @@
}, },
"custom/network": { "custom/network": {
"exec": "/home/chodak/.config/waybar/network.py", "exec": "/home/chodak/.config/waybar/network.py --icon-size 12pt",
"interval": 10, "interval": 10,
"return-type": "json", "return-type": "json",
"tooltip": true "tooltip": true
}, },
"clock#0": { "clock#0": {
"format": "{:%H:%M %d/%m/%y}", "format": "{:%d/%m/%y %H:%M}",
"tooltip": false "tooltip": false
}, },
"pulseaudio": { "pulseaudio": {
"format": "<span size='x-large' rise='-1500'>{icon}</span> {volume:2}%", "format": "<span size='10pt' rise='-1500'>{icon}</span> {volume:2}%",
"format-bluetooth": "<span size='x-large' rise='-1500'>{icon}</span> {volume}%", "format-bluetooth": "<span size='10pt' rise='-1500'>{icon}</span> {volume}%",
"format-muted": "MUTE", "format-muted": "MUTE",
"format-icons": { "format-icons": {
"headphones": "", "headphones": "",
@ -59,7 +59,7 @@
}, },
"memory": { "memory": {
"interval": 5, "interval": 5,
"format": "<span size='x-large' rise='-1500'></span> {}%" "format": "<span size='10pt' rise='-1500'></span> {}%"
}, },
"custom/top": { "custom/top": {
"exec": "~/.config/waybar/top.sh", "exec": "~/.config/waybar/top.sh",
@ -73,7 +73,7 @@
"warning": 30, "warning": 30,
"critical": 15 "critical": 15
}, },
"format": "<span size='x-large' rise='-1500'>{icon}</span> {capacity}%", "format": "<span size='12pt' rise='-1500'>{icon}</span> {capacity}%",
"format-icons": [ "format-icons": [
"", "",
"", "",
@ -83,7 +83,7 @@
] ]
}, },
"custom/disk": { "custom/disk": {
"exec": "/home/chodak/.config/waybar/disk.py", "exec": "/home/chodak/.config/waybar/disk.py --icon-size 10pt",
"interval": 30, "interval": 30,
"return-type": "json", "return-type": "json",
"tooltip": true, "tooltip": true,

16
.config/waybar/disk.py

@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""Waybar disk module: shows disk usage across all mounted partitions.""" """Waybar disk module: shows disk usage across all mounted partitions."""
import argparse
import json import json
import os import os
@ -17,6 +18,15 @@ COLOR_LOW = "#a6e3a1" # green — < 70%
COLOR_MID = "#f9e2af" # yellow — 70–89% COLOR_MID = "#f9e2af" # yellow — 70–89%
COLOR_HIGH = "#f38ba8" # red — ≥ 90% COLOR_HIGH = "#f38ba8" # red — ≥ 90%
DEFAULT_ICON_SIZE = "24pt"
def parse_args():
p = argparse.ArgumentParser()
p.add_argument("--icon-size", default=DEFAULT_ICON_SIZE,
help="Icon size (Pango size, e.g. 24pt)")
return p.parse_args()
def _pct_color(pct: float) -> str: def _pct_color(pct: float) -> str:
"""Return a Pango color string for the given usage percentage.""" """Return a Pango color string for the given usage percentage."""
@ -87,6 +97,8 @@ def fmt_size(bytes_val):
def main(): def main():
args = parse_args()
isize = args.icon_size
partitions = get_partitions() partitions = get_partitions()
if not partitions: if not partitions:
@ -137,11 +149,11 @@ def main():
bar_icon = "" if root_pct >= 90 else "" bar_icon = "" if root_pct >= 90 else ""
bar_color = _pct_color(root_pct) bar_color = _pct_color(root_pct)
bar_text = ( bar_text = (
f"<span size='x-large' rise='-1500'>{bar_icon}</span>" f"<span size='{isize}' rise='-1500'>{bar_icon}</span>"
f" {_span(bar_color, f'{root_pct:.0f}%')}" f" {_span(bar_color, f'{root_pct:.0f}%')}"
) )
elif tooltip_lines: elif tooltip_lines:
bar_text = f"<span size='x-large' rise='-1500'></span> —" bar_text = f"<span size='{isize}' rise='-1500'></span> —"
else: else:
bar_text = "" bar_text = ""

13
.config/waybar/network.py

@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""Waybar network module: shows interface, IP, and up/down transfer rate.""" """Waybar network module: shows interface, IP, and up/down transfer rate."""
import argparse
import json import json
import os import os
import re import re
@ -10,6 +11,7 @@ import time
STATE_FILE_TMPL = "/tmp/waybar-network-stats-{}" STATE_FILE_TMPL = "/tmp/waybar-network-stats-{}"
ICON = "󰲝" # nerd font network icon ICON = "󰲝" # nerd font network icon
NO_NET_ICON = "󰖪" NO_NET_ICON = "󰖪"
DEFAULT_ICON_SIZE = "24pt"
def run(cmd: list[str]) -> str: def run(cmd: list[str]) -> str:
@ -62,7 +64,16 @@ def format_rate(bps: float) -> str:
return f"{bps:.1f}B" return f"{bps:.1f}B"
def parse_args():
p = argparse.ArgumentParser()
p.add_argument("--icon-size", default=DEFAULT_ICON_SIZE,
help="Icon size (Pango size, e.g. 24pt)")
return p.parse_args()
def main() -> None: def main() -> None:
args = parse_args()
isize = args.icon_size
iface = get_default_interface() iface = get_default_interface()
if iface is None: if iface is None:
print(json.dumps( print(json.dumps(
@ -127,7 +138,7 @@ def main() -> None:
tooltip_rate = "↓ ?/s ↑ ?/s" tooltip_rate = "↓ ?/s ↑ ?/s"
text = ( text = (
f"<span size='x-large' rise='-1500'>{ICON}</span>" f"<span size='{isize}' rise='-1500'>{ICON}</span>"
f" {iface} {ip}{rate_str}" f" {iface} {ip}{rate_str}"
) )
tooltip = f"{itype}: {iface}{ip} | {tooltip_rate}" tooltip = f"{itype}: {iface}{ip} | {tooltip_rate}"

4
.config/waybar/style.css

@ -30,6 +30,10 @@ window#waybar {
padding: 0 6px; padding: 0 6px;
} }
#pulseaudio.bluetooth {
color: #89b4fa;
}
/* Workspaces: dimmed inactive, bold yellow active */ /* Workspaces: dimmed inactive, bold yellow active */
#workspaces button { #workspaces button {
padding: 0 6px; padding: 0 6px;

447
.local/bin/btswitch

@ -0,0 +1,447 @@
#!/usr/bin/env bash
set -u
# -------------------------------------------------
# CONFIGURATION
# -------------------------------------------------
WIFI_5G="cintra-5g"
WIFI_24G="cintra-5g"
declare -A BT_DEVICES
BT_DEVICES[TAH8506]="00:1E:7C:CA:77:00"
BT_DEVICES[SHB7150]="00:1E:7C:30:F3:69"
BT_DEVICES[HD450BT]="00:16:94:33:91:51"
BT_DEVICES[XTREME]="41:42:5D:FA:26:0A" # BT Speaker
BT_DEVICES[EM03]="F1:5A:D5:16:57:9D" # BT Speaker/powerbank
BT_DEVICES[X5]="47:0D:FF:C9:62:E1" # Bone Headphones thinkplus-X5
BT_AUTO_DEVICES=("TAH8506" "SHB7150")
BT_SERVICE="bluetooth"
BT_RETRIES=6
BT_DELAY=3
# Polkit rule that lets the current user start/stop bluetooth.service
# without a password, so this script runs sudo-free. Installed on first
# run via ensure_polkit_rule().
BT_POLKIT_RULE_FILE="/etc/polkit-1/rules.d/49-btswitch.rules"
# Sentinel file to track that the rule was installed, since the user
# may not have read/execute access to the polkit rules directory.
BT_POLKIT_SENTINEL="$HOME/.config/btswitch/.polkit_rule_installed"
# -------------------------------------------------
# HELPERS
# -------------------------------------------------
wifi_switch_needed() {
[[ -n "$1" && -n "$2" && "$1" != "$2" ]]
}
ensure_polkit_rule() {
if [[ -f "$BT_POLKIT_SENTINEL" ]]; then
return 0
fi
cat >&2 << EOF
NOTE: This script needs to start/stop the bluetooth service, which normally
requires root. A one-time polkit rule can be installed so "$USER" can do this
without sudo. You will be prompted for your password once to write:
$BT_POLKIT_RULE_FILE
EOF
read -r -p "Install the polkit rule now? [y/N] " answer
case "$answer" in
y | Y | yes | YES) ;;
*)
echo "Skipping. The script cannot control bluetooth.service without it." >&2
return 1
;;
esac
local tmpfile
tmpfile=$(mktemp) || return 1
cat > "$tmpfile" << POLKIT
// Allow user "$USER" to start/stop bluetooth.service without a password.
// Generated by btswitch on $(date -Is).
polkit.addRule(function(action, subject) {
if (action.id === "org.freedesktop.systemd1.manage-units" &&
subject.user === "$USER") {
try {
var unit = action.lookup("unit");
if (unit === "$BT_SERVICE.service") {
return polkit.Result.YES;
}
} catch (e) {}
}
});
POLKIT
sudo cp "$tmpfile" "$BT_POLKIT_RULE_FILE" || {
echo "ERROR: Failed to write $BT_POLKIT_RULE_FILE." >&2
rm -f "$tmpfile"
return 1
}
rm -f "$tmpfile"
sudo chown root:polkitd "$BT_POLKIT_RULE_FILE" 2>/dev/null \
|| sudo chown root:root "$BT_POLKIT_RULE_FILE"
sudo chmod 644 "$BT_POLKIT_RULE_FILE"
mkdir -p "$(dirname "$BT_POLKIT_SENTINEL")"
touch "$BT_POLKIT_SENTINEL"
echo "✔ Installed polkit rule: $BT_POLKIT_RULE_FILE" >&2
echo " (polkitd picks it up automatically; no restart needed.)" >&2
return 0
}
systemctl_bt() {
ensure_polkit_rule || {
echo "ERROR: Cannot control bluetooth.service without the polkit rule." >&2
echo "Run 'sudo systemctl $* $BT_SERVICE' manually, or re-run this script and install the rule." >&2
exit 1
}
if ! systemctl "$@" "$BT_SERVICE"; then
echo "ERROR: systemctl $* $BT_SERVICE failed." >&2
echo "If polkit prompted for a password, the rule file may be missing." >&2
echo "Remove $BT_POLKIT_SENTINEL and re-run to reinstall it." >&2
exit 1
fi
}
bt_info() {
bluetoothctl info "$1" 2> /dev/null
}
bt_is_paired() {
bt_info "$1" | grep -q "Paired: yes"
}
bt_is_trusted() {
bt_info "$1" | grep -q "Trusted: yes"
}
bt_is_connected() {
bt_info "$1" | grep -q "Connected: yes"
}
bt_is_mac_address() {
[[ "$1" =~ ^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$ ]]
}
bt_resolve_device() {
local device="$1"
if bt_is_mac_address "$device"; then
echo "$device"
else
echo "${BT_DEVICES[$device]:-}"
fi
}
bt_get_all_macs() {
local devices=("${!1}")
for dev in "${devices[@]}"; do
local mac
mac=$(bt_resolve_device "$dev")
[[ -n "$mac" ]] && echo "$mac"
done
}
# -------------------------------------------------
# BLUETOOTH CONTROL
# -------------------------------------------------
start_bluetooth() {
echo "Starting Bluetooth service..."
systemctl_bt start
echo "Waiting for bluetoothd to become ready..."
for i in {1..10}; do
if bluetoothctl show | grep -q "Powered: yes"; then
bluetoothctl pairable on > /dev/null 2>&1
return 0
fi
bluetoothctl power on > /dev/null 2>&1
sleep 1
done
echo "ERROR: Bluetooth adapter not found or could not be powered on."
return 1
}
bt_pair_device() {
local mac="$1"
if bt_is_paired "$mac"; then
return 0
fi
echo "✖ Device $mac is not paired. Automatic pairing is not supported."
echo " Please pair it manually, then re-run this command:"
echo ""
echo " bluetoothctl"
echo " [bluetoothctl]# pair $mac"
echo " [bluetoothctl]# trust $mac"
echo " [bluetoothctl]# connect $mac"
echo " [bluetoothctl]# quit"
echo ""
echo " (Put the device in pairing mode first, if needed.)"
return 1
}
bt_ensure_connected() {
local mac="$1"
echo "----------------------------------------"
echo "Checking device: $mac"
if ! bt_is_trusted "$mac"; then
echo "→ Trusting $mac"
bluetoothctl trust "$mac" > /dev/null
fi
for ((i = 1; i <= BT_RETRIES; i++)); do
if bt_is_connected "$mac"; then
echo "✔ Connected: $mac"
return 0
fi
echo "→ Attempt $i/$BT_RETRIES: Connecting to $mac..."
if ! bt_is_paired "$mac"; then
bt_pair_device "$mac" || return 1
fi
bluetoothctl connect "$mac" > /dev/null 2>&1
sleep "$BT_DELAY"
if bt_is_connected "$mac"; then
echo "✔ Success!"
return 0
fi
done
echo "✖ Failed to connect $mac after $BT_RETRIES attempts"
return 1
}
bt_safe_disconnect() {
local mac="$1"
if bt_is_connected "$mac"; then
echo "Disconnecting $mac..."
bluetoothctl disconnect "$mac" > /dev/null 2>&1
else
echo "$mac is already offline."
fi
}
bt_stop_all() {
local devices=("${!1}")
for dev in "${devices[@]}"; do
local mac
mac=$(bt_resolve_device "$dev")
[[ -n "$mac" ]] && bt_safe_disconnect "$mac"
done
}
bt_start_all() {
local devices=("${!1}")
for dev in "${devices[@]}"; do
local mac
mac=$(bt_resolve_device "$dev")
[[ -n "$mac" ]] && bt_ensure_connected "$mac"
done
}
bt_status_all() {
local devices=("${!1}")
for dev in "${devices[@]}"; do
local mac
mac=$(bt_resolve_device "$dev")
if [[ -n "$mac" ]]; then
echo "--- $dev ($mac) ---"
if bt_is_connected "$mac"; then
echo "Status: CONNECTED"
elif bt_is_paired "$mac"; then
echo "Status: Paired (Offline)"
else
echo "Status: Not Paired / Unknown"
fi
fi
done
}
bt_scan() {
local scan_duration=30
declare -A seen_devices
local device_count=0
echo "Scanning for Bluetooth devices for $scan_duration seconds..."
echo "Press Ctrl+C to stop early"
echo "----------------------------------------"
trap 'echo ""; echo "Scan stopped"; exit 0' INT TERM
local start_time=$(date +%s)
local end_time=$((start_time + scan_duration))
while true; do
local current_time=$(date +%s)
if ((current_time >= end_time)); then
break
fi
while IFS= read -r line; do
if [[ $line =~ ^[[:space:]]*([0-9A-F:]{17})[[:space:]]+(.+)$ ]]; then
local mac="${BASH_REMATCH[1]}"
local name="${BASH_REMATCH[2]}"
if [[ -z "${seen_devices[$mac]:-}" ]]; then
seen_devices[$mac]="$name"
((device_count++))
echo "[$device_count] $mac - $name"
fi
fi
done < <(hcitool scan 2> /dev/null | tail -n +2)
sleep 1
done
echo "----------------------------------------"
echo "Scan complete. Found $device_count unique device(s):"
for mac in "${!seen_devices[@]}"; do
echo " $mac - ${seen_devices[$mac]}"
done
trap - INT TERM
}
bt_list() {
echo "=== BT_DEVICES ==="
for name in "${!BT_DEVICES[@]}"; do
echo " $name: ${BT_DEVICES[$name]}"
done
echo ""
echo "=== BT_AUTO_DEVICES ==="
for name in "${BT_AUTO_DEVICES[@]}"; do
echo " $name: ${BT_DEVICES[$name]}"
done
}
# -------------------------------------------------
# MAIN
# -------------------------------------------------
DEVICES=()
TIMED_MINUTES=0
parse_args() {
while [[ $# -gt 0 ]]; do
case "$1" in
-d | --device)
DEVICES+=("$2")
shift 2
;;
-t | --timed)
TIMED_MINUTES="$2"
shift 2
;;
start | stop | status | scan | list)
COMMAND="$1"
shift
;;
*)
echo "Unknown option: $1"
echo "Usage: $0 [-d|--device DEVICE] [-t|--timed MINUTES] {start|stop|status|scan|list}"
exit 1
;;
esac
done
}
parse_args "$@"
if [[ -z "${COMMAND:-}" ]]; then
echo "Usage: $0 [-d|--device DEVICE] [-t|--timed MINUTES] {start|stop|status|scan|list}"
exit 1
fi
if [[ ${#DEVICES[@]} -gt 0 ]]; then
for dev in "${DEVICES[@]}"; do
mac=$(bt_resolve_device "$dev")
if [[ -z "$mac" ]]; then
echo "ERROR: Unknown device '$dev'. Valid aliases: ${!BT_DEVICES[@]}"
exit 1
fi
done
fi
case "$COMMAND" in
start)
if wifi_switch_needed "$WIFI_5G" "$WIFI_24G"; then
nmcli connection up "$WIFI_5G"
fi
start_bluetooth || exit 1
if [[ ${#DEVICES[@]} -gt 0 ]]; then
bt_start_all DEVICES[@]
else
bt_start_all BT_AUTO_DEVICES[@]
fi
if [[ "$TIMED_MINUTES" -gt 0 ]]; then
echo "Will disconnect after $TIMED_MINUTES minute(s)..."
sleep $((TIMED_MINUTES * 60))
echo "Time elapsed. Disconnecting..."
if [[ ${#DEVICES[@]} -gt 0 ]]; then
bt_stop_all DEVICES[@]
else
bt_stop_all BT_AUTO_DEVICES[@]
fi
echo "Stopping Bluetooth service..."
systemctl_bt stop
if wifi_switch_needed "$WIFI_5G" "$WIFI_24G"; then
nmcli connection up "$WIFI_24G"
fi
fi
;;
stop)
if [[ ${#DEVICES[@]} -gt 0 ]]; then
bt_stop_all DEVICES[@]
else
bt_stop_all BT_AUTO_DEVICES[@]
fi
echo "Stopping Bluetooth service..."
systemctl_bt stop
if wifi_switch_needed "$WIFI_5G" "$WIFI_24G"; then
nmcli connection up "$WIFI_24G"
fi
;;
status)
bluetoothctl show | grep -E "Name|Powered|Discoverable"
if [[ ${#DEVICES[@]} -gt 0 ]]; then
bt_status_all DEVICES[@]
else
bt_status_all BT_AUTO_DEVICES[@]
fi
;;
scan)
bt_scan
;;
list)
bt_list
;;
esac

1
.tmux.d/tmux-gruvbox

@ -0,0 +1 @@
Subproject commit aeb30c7172a8ed8663409207814cf47d9df10d15
Loading…
Cancel
Save