Compare commits

..

3 commits

Author SHA1 Message Date
20cb3ae4a6
bluetooth: conectar los conocidos aunque no estén emparejados
El menú solo enseñaba los dispositivos con Paired: yes, así que un
auricular de confianza que había perdido el emparejamiento no salía, y
volver a emparejarlo fallaba porque bluetoothctl no tenía agente. Ahora
salen los emparejados y los de confianza; al elegir uno se empareja si hace
falta (agente NoInputNoOutput), se busca unos segundos si no está a la
vista, y si falla lo dice (también si wireplumber no está en marcha).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C5v1qWDwgkaVM5kjVHGGh8
2026-09-28 15:48:16 +02:00
3864c31ba1
slstatus: VOL y BT cada 10 s o al recibir SIGUSR1
Componente lento: run_command con caché. slstatus.c cuenta las SIGUSR1
para que se refresque en cuanto un script o un clic lo pide. Así ya no se
lanzan wpctl y bluetoothctl cada 2 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C5v1qWDwgkaVM5kjVHGGh8
2026-09-28 15:38:41 +02:00
73d005dd30
Fuera avahi, xss-lock, chrony y nemo; .bashrc más limpio
- inactivo: slock cuando salta el salvapantallas de X (xssstate), en vez
  de xss-lock (glib, D-Bus y logind).
- openntpd en vez de chrony.
- Fuera avahi y nss-mdns (la impresora va por IP fija); quitar limpia
  nsswitch.conf.
- Fuera nemo y upower (y con ellos gvfs y udisks2): las carpetas se abren
  en yazi dentro de st.
- .bashrc: PATH sin repetidos y ex con bsdtar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C5v1qWDwgkaVM5kjVHGGh8
2026-09-28 15:36:16 +02:00
11 changed files with 209 additions and 85 deletions

View file

@ -54,21 +54,24 @@ for example) and repeated safely:
6. `sistema` (system): copies `sistema/` into `/`, sets up 6. `sistema` (system): copies `sistema/` into `/`, sets up
`wpa_supplicant.conf` so wheel users can use `wpa_cli` without root and `wpa_supplicant.conf` so wheel users can use `wpa_cli` without root and
save networks, enables the runit services (dbus, turnstiled, save networks, enables the runit services (dbus, turnstiled,
wpa_supplicant, dhcpcd, bluetoothd, acpid, chronyd, tlp, automontaje, wpa_supplicant, dhcpcd, bluetoothd, acpid, openntpd, tlp, automontaje,
cupsd), removes NetworkManager, elogind and polkitd (if something asks for cupsd), removes NetworkManager, elogind, chronyd, avahi-daemon (the printer
polkit, like udisks2 or libvirt, D-Bus starts it on its own) and adds the has a fixed IP) and polkitd (if something asks for polkit, like libvirt,
user to the audio, video, input, network, bluetooth, lpadmin (printer D-Bus starts it on its own) and adds the user to the audio, video, input,
management) and `_pipewire` (realtime priority for audio without rtkit) network, bluetooth, lpadmin (printer management) and `_pipewire` (realtime
groups. `doas.conf` is checked with `doas -C` before it is installed with priority for audio without rtkit) groups. `doas.conf` is checked with `doas
mode 400. -C` before it is installed with mode 400.
7. `quitar` (remove): uninstalls what the repo no longer uses because 7. `quitar` (remove): uninstalls what the repo no longer uses because
something else replaces it: sudo (doas), feh (xwallpaper and nsxiv), something else replaces it: sudo (doas), feh (xwallpaper and nsxiv),
gammastep (sct), autorandr (`pantallas`), blueman and pavucontrol (the gammastep (sct), autorandr (`pantallas`), blueman and pavucontrol (the
`bluetooth` and `volumen` scripts), pinentry-gtk (pinentry-dmenu), vlc `bluetooth` and `volumen` scripts), pinentry-gtk (pinentry-dmenu), vlc
(mpv), btop, NetworkManager and tlp-rdw (wpa_supplicant, dhcpcd and the (mpv), btop, NetworkManager and tlp-rdw (wpa_supplicant, dhcpcd and the
`wifi` script), rtkit and elogind (turnstile). sudo can be removed thanks `wifi` script), rtkit, elogind (turnstile), xss-lock (`inactivo`, with
to `sistema/etc/xbps.d/sin-sudo.conf` (base-system depends on it), and it xssstate), chrony (openntpd), avahi and nss-mdns (also removed from
is only removed once `/etc/doas.conf` is installed. `/etc/nsswitch.conf`) and nemo with upower (yazi; gvfs and udisks2 go with
nemo). sudo can be removed thanks to `sistema/etc/xbps.d/sin-sudo.conf`
(base-system depends on it), and it is only removed once `/etc/doas.conf`
is installed.
Afterwards, log out and back in (for the groups) and run `startx`. Afterwards, log out and back in (for the groups) and run `startx`.
@ -88,9 +91,9 @@ elogind is systemd's logind on its own, and it is not needed here:
- Devices (sound, video, input, bluetooth) are reached through the user's - Devices (sound, video, input, bluetooth) are reached through the user's
groups, not through the ACLs elogind gave the active session. groups, not through the ACLs elogind gave the active session.
What stops working: mounting disks from a file manager (udisks2 asks polkit What stops working: mounting disks from a graphical file manager (udisks2
for an active session, and there is none). USB sticks are mounted by asked polkit for an active session; now there is neither a file manager nor
`automontaje`. udisks2). USB sticks are mounted by `automontaje`.
## Rebuilding after changing the config ## Rebuilding after changing the config
@ -165,6 +168,11 @@ and which area is which is marked by the `\001`...`\004` bytes in
| BT | `OFF`, or the connected device and its battery if it reports it (`VJ 901 100%`) | `bluetooth` menu: connect, disconnect, scan and pair, power off | | Power on or off | | | BT | `OFF`, or the connected device and its battery if it reports it (`VJ 901 100%`) | `bluetooth` menu: connect, disconnect, scan and pair, power off | | Power on or off | |
| Date | Day and time | This month's calendar (`calendario`) | | | | | Date | Day and time | This month's calendar (`calendario`) | | | |
VOL and BT are not read every 2 s like the rest, but every 10 s or as soon as
`SIGUSR1` arrives (`lento` component in slstatus's `config.h`): `volumen`,
`bluetooth`, `wifi` and the clicks send it, so your own changes show up at
once and wpctl and bluetoothctl are not spawned every 2 s.
After changing dwm's `config.h`, reinstall and restart it for new clicks to After changing dwm's `config.h`, reinstall and restart it for new clicks to
work: `pkill -HUP dwm` restarts it without closing windows (restartsig and work: `pkill -HUP dwm` restarts it without closing windows (restartsig and
preserveonrestart patches). preserveonrestart patches).
@ -201,8 +209,9 @@ preserveonrestart patches).
when the SSH key is already unlocked (so pinentry never pops up) and when the SSH key is already unlocked (so pinentry never pops up) and
retries every hour. `marcadores ya` uploads it right away. To restore: retries every hour. `marcadores ya` uploads it right away. To restore:
Firefox > Bookmarks > Manage bookmarks > Import and Backup > Restore. Firefox > Bookmarks > Manage bookmarks > Import and Backup > Restore.
- After 30 minutes idle the screen locks with slock (`xss-lock`) and one - After 30 minutes idle the screen locks with slock (`inactivo`, which
minute later it turns off. watches the X screensaver with `xssstate`) and one minute later it turns
off. Videos that ask to keep the screen on (mpv, Firefox) prevent it.
- USB sticks and SD cards: the `automontaje` service (runit, as root) mounts - USB sticks and SD cards: the `automontaje` service (runit, as root) mounts
them in `/mnt/LABEL`, or `/mnt/sdXY` if they have no label, and unmounts them in `/mnt/LABEL`, or `/mnt/sdXY` if they have no label, and unmounts
them when removed, with a notification. FAT, exFAT and NTFS are owned by them when removed, with a notification. FAT, exFAT and NTFS are owned by
@ -210,6 +219,10 @@ preserveonrestart patches).
wrote to, run `sync` (or `doas umount /mnt/...`). wrote to, run `sync` (or `doas umount /mnt/...`).
- User folders in English and without accents (`user-dirs.dirs`): - User folders in English and without accents (`user-dirs.dirs`):
Documents, Downloads and Images. Documents, Downloads and Images.
- Folders ("Open folder" in Firefox, `xdg-open`) open in yazi inside st
(`home/.local/share/applications/yazi-st.desktop`).
- `ex file...` extracts almost anything with `bsdtar` (a `.bashrc`
function).
## Notes ## Notes
@ -228,5 +241,7 @@ preserveonrestart patches).
- In st, Ctrl+Shift+right click on an image opens it in `nsxiv`. - In st, Ctrl+Shift+right click on an image opens it in `nsxiv`.
- st shows images with the kitty graphics protocol; yazi detects it on its - st shows images with the kitty graphics protocol; yazi detects it on its
own and shows previews without ueberzugpp. own and shows previews without ueberzugpp.
- slstatus.c has a hand-made change (not a patch): it counts `SIGUSR1`
signals so `lento` knows when to refresh.
- slock is modified by hand (not a patch): clock, date, battery and a bottom - slock is modified by hand (not a patch): clock, date, battery and a bottom
bar with the state colour. bar with the state colour.

View file

@ -51,20 +51,22 @@ Hace siete pasos, que también se pueden lanzar por separado
6. `sistema`: copia `sistema/` en `/`, prepara `wpa_supplicant.conf` para que 6. `sistema`: copia `sistema/` en `/`, prepara `wpa_supplicant.conf` para que
los de wheel usen `wpa_cli` sin root y guarden redes, activa los servicios los de wheel usen `wpa_cli` sin root y guarden redes, activa los servicios
de runit (dbus, turnstiled, wpa_supplicant, dhcpcd, bluetoothd, acpid, de runit (dbus, turnstiled, wpa_supplicant, dhcpcd, bluetoothd, acpid,
chronyd, tlp, automontaje, cupsd), quita NetworkManager, elogind y polkitd openntpd, tlp, automontaje, cupsd), quita NetworkManager, elogind, chronyd,
(si algo pide polkit, como udisks2 o libvirt, D-Bus lo arranca solo) y avahi-daemon (la impresora va por IP fija) y polkitd (si algo pide polkit,
añade el usuario a los grupos audio, video, input, network, bluetooth, como libvirt, D-Bus lo arranca solo) y añade el usuario a los grupos audio,
lpadmin (para gestionar impresoras) y `_pipewire` (prioridad de tiempo real video, input, network, bluetooth, lpadmin (para gestionar impresoras) y
para el audio sin rtkit). `doas.conf` se valida con `doas -C` antes de `_pipewire` (prioridad de tiempo real para el audio sin rtkit). `doas.conf`
instalarlo con modo 400. se valida con `doas -C` antes de instalarlo con modo 400.
7. `quitar`: desinstala lo que el repo ya no usa porque lo sustituye otra 7. `quitar`: desinstala lo que el repo ya no usa porque lo sustituye otra
cosa: sudo (doas), feh (xwallpaper y nsxiv), gammastep (sct), autorandr cosa: sudo (doas), feh (xwallpaper y nsxiv), gammastep (sct), autorandr
(`pantallas`), blueman y pavucontrol (scripts `bluetooth` y `volumen`), (`pantallas`), blueman y pavucontrol (scripts `bluetooth` y `volumen`),
pinentry-gtk (pinentry-dmenu), vlc (mpv), btop, NetworkManager y tlp-rdw pinentry-gtk (pinentry-dmenu), vlc (mpv), btop, NetworkManager y tlp-rdw
(wpa_supplicant, dhcpcd y el script `wifi`), rtkit y elogind (turnstile). (wpa_supplicant, dhcpcd y el script `wifi`), rtkit, elogind (turnstile),
sudo se puede quitar gracias a `sistema/etc/xbps.d/sin-sudo.conf` xss-lock (`inactivo`, con xssstate), chrony (openntpd), avahi y nss-mdns
(base-system depende de él), y solo se quita si `/etc/doas.conf` ya está (también los quita de `/etc/nsswitch.conf`) y nemo con upower (yazi; con
instalado. nemo se van gvfs y udisks2). sudo se puede quitar gracias a
`sistema/etc/xbps.d/sin-sudo.conf` (base-system depende de él), y solo se
quita si `/etc/doas.conf` ya está instalado.
Después hay que cerrar sesión y volver a entrar (por los grupos) y lanzar Después hay que cerrar sesión y volver a entrar (por los grupos) y lanzar
`startx`. `startx`.
@ -85,9 +87,9 @@ elogind es el logind de systemd por separado, y aquí sobra:
- Los dispositivos (sonido, vídeo, entrada, bluetooth) van por los grupos del - Los dispositivos (sonido, vídeo, entrada, bluetooth) van por los grupos del
usuario, no por las ACL que ponía elogind a la sesión activa. usuario, no por las ACL que ponía elogind a la sesión activa.
Lo que deja de ir: montar discos desde un gestor de archivos (udisks2 pide a Lo que deja de ir: montar discos desde un gestor de archivos gráfico (udisks2
polkit una sesión activa, que ya no hay). Las memorias USB las monta pedía a polkit una sesión activa; ya no hay ni gestor ni udisks2). Las
`automontaje`. memorias USB las monta `automontaje`.
## Recompilar tras cambiar la configuración ## Recompilar tras cambiar la configuración
@ -163,6 +165,11 @@ y qué zona es cada una lo marcan los bytes `\001`...`\004` de
| BT | `OFF`, o el dispositivo conectado y su batería si la da (`VJ 901 100%`) | Menú `bluetooth`: conectar, desconectar, buscar y emparejar, apagar | | Encender o apagar | | | BT | `OFF`, o el dispositivo conectado y su batería si la da (`VJ 901 100%`) | Menú `bluetooth`: conectar, desconectar, buscar y emparejar, apagar | | Encender o apagar | |
| Fecha | Día y hora | Calendario del mes (`calendario`) | | | | | Fecha | Día y hora | Calendario del mes (`calendario`) | | | |
VOL y BT no se miran cada 2 s como el resto, sino cada 10 s o en cuanto
llega `SIGUSR1` (componente `lento` del `config.h` de slstatus): lo mandan
`volumen`, `bluetooth`, `wifi` y los clics, así que lo que cambias tú se ve al
momento y wpctl y bluetoothctl no se lanzan cada 2 s.
Si se cambia el `config.h` de dwm, hay que reinstalarlo y reiniciarlo para Si se cambia el `config.h` de dwm, hay que reinstalarlo y reiniciarlo para
que los clics nuevos funcionen: `pkill -HUP dwm` lo relanza sin cerrar las que los clics nuevos funcionen: `pkill -HUP dwm` lo relanza sin cerrar las
ventanas (parches restartsig y preserveonrestart). ventanas (parches restartsig y preserveonrestart).
@ -198,8 +205,9 @@ ventanas (parches restartsig y preserveonrestart).
con la clave SSH desbloqueada (para no sacar pinentry) y lo reintenta cada con la clave SSH desbloqueada (para no sacar pinentry) y lo reintenta cada
hora. `marcadores ya` la sube en el momento. Para restaurar: Firefox > hora. `marcadores ya` la sube en el momento. Para restaurar: Firefox >
Marcadores > Administrar marcadores > Importar y respaldar > Restaurar. Marcadores > Administrar marcadores > Importar y respaldar > Restaurar.
- Tras 30 minutos sin tocar nada se bloquea con slock (`xss-lock`) y un - Tras 30 minutos sin tocar nada se bloquea con slock (`inactivo`, que mira
minuto después se apaga la pantalla. el salvapantallas de X con `xssstate`) y un minuto después se apaga la
pantalla. Los vídeos que piden no apagarla (mpv, Firefox) lo evitan.
- Memorias USB y tarjetas SD: el servicio `automontaje` (runit, como root) - Memorias USB y tarjetas SD: el servicio `automontaje` (runit, como root)
las monta en `/mnt/ETIQUETA`, o en `/mnt/sdXY` si no tienen etiqueta, y las monta en `/mnt/ETIQUETA`, o en `/mnt/sdXY` si no tienen etiqueta, y
las desmonta al sacarlas, con una notificación. FAT, exFAT y NTFS quedan a las desmonta al sacarlas, con una notificación. FAT, exFAT y NTFS quedan a
@ -207,6 +215,10 @@ ventanas (parches restartsig y preserveonrestart).
memoria en la que se ha escrito, `sync` (o `doas umount /mnt/...`). memoria en la que se ha escrito, `sync` (o `doas umount /mnt/...`).
- Carpetas del usuario en inglés y sin tildes (`user-dirs.dirs`): - Carpetas del usuario en inglés y sin tildes (`user-dirs.dirs`):
Documents, Downloads e Images. Documents, Downloads e Images.
- Las carpetas ("Abrir carpeta" en Firefox, `xdg-open`) se abren en yazi
dentro de st (`home/.local/share/applications/yazi-st.desktop`).
- `ex archivo...` descomprime casi cualquier cosa con `bsdtar` (función de
`.bashrc`).
## Notas ## Notas
@ -224,5 +236,7 @@ ventanas (parches restartsig y preserveonrestart).
- En st, Ctrl+Shift+clic derecho sobre una imagen la abre en `nsxiv`. - En st, Ctrl+Shift+clic derecho sobre una imagen la abre en `nsxiv`.
- st muestra imágenes con el protocolo de gráficos de kitty; yazi lo detecta - st muestra imágenes con el protocolo de gráficos de kitty; yazi lo detecta
solo y enseña las vistas previas sin ueberzugpp. solo y enseña las vistas previas sin ueberzugpp.
- slstatus.c tiene un cambio a mano (no es un parche): cuenta las señales
`SIGUSR1` para que `lento` sepa cuándo refrescar.
- slock está modificado a mano (no es un parche): reloj, fecha, batería y - slock está modificado a mano (no es un parche): reloj, fecha, batería y
una barra inferior con el color del estado. una barra inferior con el color del estado.

View file

@ -3,8 +3,15 @@
# ===================================================================== # =====================================================================
# --- 1. Entorno y Rutas --- # --- 1. Entorno y Rutas ---
# Priorizar binarios locales y scripts de usuario # Priorizar binarios locales y scripts de usuario. Si ya estaban (un bash
export PATH="$HOME/.local/bin:/usr/local/bin:$PATH" # dentro de otro), se quitan antes para no repetirlos.
for d in /usr/local/bin "$HOME/.local/bin"; do
PATH=":$PATH:"
PATH=${PATH//:$d:/:}
PATH=${PATH#:}
PATH="$d:${PATH%:}"
done
export PATH
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket) export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
export GPG_TTY=$(tty) export GPG_TTY=$(tty)
gpg-connect-agent updatestartuptty /bye >/dev/null 2>&1 gpg-connect-agent updatestartuptty /bye >/dev/null 2>&1
@ -71,27 +78,20 @@ alias esp32='doas chmod a+rw /dev/ttyUSB0'
# --- 5. Funciones Útiles --- # --- 5. Funciones Útiles ---
# Comando 'ex': Descomprime LITERALMENTE CUALQUIER COSA # ex: descomprime lo que sea. bsdtar se entiende con tar (gz, bz2, xz, zst),
# Uso: ex archivo.zip | ex archivo.tar.gz # zip, 7z, rar e iso; los comprimidos sueltos, con su herramienta.
# Uso: ex archivo.zip [otro.tar.gz ...]
ex() { ex() {
if [ -f "$1" ]; then for f; do
case $1 in case $f in
*.tar.bz2) tar xjf "$1" ;; *.tar|*.tar.*|*.t?z|*.tbz2|*.zip|*.7z|*.rar|*.iso) bsdtar -xf "$f" ;;
*.tar.gz) tar xzf "$1" ;; *.gz) gunzip -k "$f" ;;
*.bz2) bunzip2 "$1" ;; *.bz2) bunzip2 -k "$f" ;;
*.rar) unrar x "$1" ;; *.xz) unxz -k "$f" ;;
*.gz) gunzip "$1" ;; *.zst) unzstd "$f" ;;
*.tar) tar xf "$1" ;; *) echo "ex: no sé descomprimir '$f'" >&2 ;;
*.tbz2) tar xjf "$1" ;;
*.tgz) tar xzf "$1" ;;
*.zip) unzip "$1" ;;
*.Z) uncompress "$1";;
*.7z) 7z x "$1" ;;
*) echo "'$1' formato no reconocido por la función ex()" ;;
esac esac
else done
echo "'$1' no es un archivo válido"
fi
} }
# Forzar IPv4 en Nix (IPv6 del sistema está roto) # Forzar IPv4 en Nix (IPv6 del sistema está roto)

View file

@ -1,4 +1,5 @@
[Default Applications] [Default Applications]
inode/directory=yazi-st.desktop
x-scheme-handler/http=firefox.desktop x-scheme-handler/http=firefox.desktop
x-scheme-handler/https=firefox.desktop x-scheme-handler/https=firefox.desktop
x-scheme-handler/chrome=firefox.desktop x-scheme-handler/chrome=firefox.desktop
@ -11,6 +12,7 @@ application/x-extension-xhtml=firefox.desktop
application/x-extension-xht=firefox.desktop application/x-extension-xht=firefox.desktop
[Added Associations] [Added Associations]
inode/directory=yazi-st.desktop;
x-scheme-handler/http=firefox.desktop; x-scheme-handler/http=firefox.desktop;
x-scheme-handler/https=firefox.desktop; x-scheme-handler/https=firefox.desktop;
x-scheme-handler/chrome=firefox.desktop; x-scheme-handler/chrome=firefox.desktop;

View file

@ -1,8 +1,9 @@
#!/bin/sh #!/bin/sh
# Menú de bluetooth con dmenu (clic izquierdo en BT de la barra): conectar o # Menú de bluetooth con dmenu (clic izquierdo en BT de la barra). Arriba, los
# desconectar los dispositivos emparejados (󰂱 = conectado), buscar y # dispositivos conocidos (emparejados o de confianza; 󰂱 = conectado): elegir
# emparejar uno nuevo y apagar el adaptador. Si está apagado, ofrece # uno lo desconecta si está conectado y, si no, lo busca y se conecta (y lo
# encenderlo. # vuelve a emparejar si hace falta). Debajo, buscar y emparejar uno nuevo y
# apagar el adaptador. Si está apagado, ofrece encenderlo.
avisar() { avisar() {
notify-send -h string:x-dunst-stack-tag:bluetooth -i bluetooth "Bluetooth" "$1" notify-send -h string:x-dunst-stack-tag:bluetooth -i bluetooth "Bluetooth" "$1"
@ -11,6 +12,36 @@ avisar() {
# "Device AA:BB:CC:DD:EE:FF Nombre" -> "Nombre (AA:BB:CC:DD:EE:FF)" # "Device AA:BB:CC:DD:EE:FF Nombre" -> "Nombre (AA:BB:CC:DD:EE:FF)"
lista() { sed -n 's/^Device \([^ ]*\) \(.*\)/\2 (\1)/p'; } lista() { sed -n 's/^Device \([^ ]*\) \(.*\)/\2 (\1)/p'; }
mac() { printf '%s\n' "$1" | sed 's/.*(\([^)]*\))$/\1/'; } mac() { printf '%s\n' "$1" | sed 's/.*(\([^)]*\))$/\1/'; }
buscar() { bluetoothctl --timeout "$1" scan on >/dev/null; }
# Sin agente, bluetoothctl no puede emparejar; los auriculares no piden PIN.
emparejar() {
bluetoothctl --agent NoInputNoOutput pair "$1" >/dev/null &&
bluetoothctl trust "$1" >/dev/null
}
# conectar MAC: si no está emparejado lo empareja; si no está a la vista, lo
# busca unos segundos y lo vuelve a intentar.
conectar() {
if ! bluetoothctl info "$1" | grep -q 'Paired: yes'; then
emparejar "$1" || { buscar 8 && emparejar "$1"; } || return 1
fi
bluetoothctl connect "$1" >/dev/null ||
{ buscar 8 && bluetoothctl connect "$1" >/dev/null; }
}
# conectar_y_avisar "Nombre (MAC)"
conectar_y_avisar() {
nombre=${1% (*}
avisar "Conectando: $nombre..."
if conectar "$(mac "$1")"; then
avisar "Conectado: $nombre"
elif ! pgrep -x wireplumber >/dev/null; then
avisar "No se pudo conectar $nombre: wireplumber no está en marcha (sin él no hay audio)"
else
avisar "No se pudo conectar $nombre: ¿está encendido y cerca?"
fi
}
if ! bluetoothctl show | grep -q 'Powered: yes'; then if ! bluetoothctl show | grep -q 'Powered: yes'; then
[ "$(echo Encender | menu -p Bluetooth:)" = Encender ] || exit 0 [ "$(echo Encender | menu -p Bluetooth:)" = Encender ] || exit 0
@ -19,10 +50,10 @@ if ! bluetoothctl show | grep -q 'Powered: yes'; then
fi fi
conectados=$(bluetoothctl devices Connected | lista) conectados=$(bluetoothctl devices Connected | lista)
emparejados=$(bluetoothctl devices Paired | lista) conocidos=$({ bluetoothctl devices Paired; bluetoothctl devices Trusted; } | lista | sort -u)
opcion=$( opcion=$(
printf '%s\n' "$emparejados" | while IFS= read -r d; do printf '%s\n' "$conocidos" | while IFS= read -r d; do
[ -n "$d" ] || continue [ -n "$d" ] || continue
if printf '%s\n' "$conectados" | grep -qxF "$d"; then if printf '%s\n' "$conectados" | grep -qxF "$d"; then
echo "󰂱 $d" echo "󰂱 $d"
@ -42,29 +73,19 @@ case $opcion in
;; ;;
*" Buscar dispositivos") *" Buscar dispositivos")
avisar "Buscando dispositivos durante 10 s..." avisar "Buscando dispositivos durante 10 s..."
bluetoothctl --timeout 10 scan on >/dev/null buscar 10
nuevo=$(bluetoothctl devices | lista | awk -v e="$emparejados" ' nuevo=$(bluetoothctl devices | lista | awk -v e="$conocidos" '
BEGIN { n = split(e, a, "\n"); for (i = 1; i <= n; i++) visto[a[i]] } BEGIN { n = split(e, a, "\n"); for (i = 1; i <= n; i++) visto[a[i]] }
!($0 in visto)' | menu -p Emparejar:) !($0 in visto)' | menu -p Emparejar:)
[ -n "$nuevo" ] || exit 0 [ -n "$nuevo" ] || exit 0
m=$(mac "$nuevo") conectar_y_avisar "$nuevo"
if bluetoothctl pair "$m" >/dev/null && bluetoothctl trust "$m" >/dev/null &&
bluetoothctl connect "$m" >/dev/null; then
avisar "Conectado: $nuevo"
else
avisar "No se pudo emparejar: $nuevo"
fi
;; ;;
"󰂱 "*) "󰂱 "*)
bluetoothctl disconnect "$(mac "$opcion")" >/dev/null && bluetoothctl disconnect "$(mac "$opcion")" >/dev/null &&
avisar "Desconectado: ${opcion#"󰂱 "}" avisar "Desconectado: ${opcion#"󰂱 "}"
;; ;;
*) *)
if bluetoothctl connect "$(mac "$opcion")" >/dev/null; then conectar_y_avisar "${opcion#" "}"
avisar "Conectado: ${opcion#" "}"
else
avisar "No se pudo conectar: ${opcion#" "}"
fi
;; ;;
esac esac
pkill -USR1 -x slstatus pkill -USR1 -x slstatus

12
home/.local/bin/inactivo Executable file
View file

@ -0,0 +1,12 @@
#!/bin/sh
# Bloquea con slock cuando salta el salvapantallas de X (xset s en .xinitrc:
# 30 minutos sin tocar nada). Mira el estado con xssstate cada 5 s. Los
# vídeos que piden no apagar la pantalla (mpv, Firefox) paran el salvapantallas
# y así tampoco bloquea. Al suspender ya bloquea el hook de zzz.
while :; do
if [ "$(xssstate -s)" = on ] && ! pgrep -x slock >/dev/null; then
slock
fi
sleep 5
done

View file

@ -0,0 +1,8 @@
[Desktop Entry]
Type=Application
Name=yazi
Comment=Carpetas con yazi en st (para xdg-open y Firefox)
Exec=st -e yazi %f
Terminal=false
MimeType=inode/directory;
NoDisplay=true

View file

@ -35,10 +35,10 @@ luz &
bateria & bateria &
marcadores & marcadores &
# Bloquear con slock tras 30 minutos sin tocar nada, y apagar la pantalla un # Bloquear con slock tras 30 minutos sin tocar nada (salvapantallas de X,
# minuto después. Al suspender ya bloquea el hook de zzz (--ignore-sleep). # lo vigila inactivo) y apagar la pantalla un minuto después.
xset s 1800 1800 xset s 1800 1800
xset dpms 0 0 1860 xset dpms 0 0 1860
xss-lock --ignore-sleep -- slock & inactivo &
exec dwm exec dwm

View file

@ -18,27 +18,28 @@ PAQUETES="
libXrender-devel xorgproto imlib2-devel zlib-devel libxcrypt-devel libXrender-devel xorgproto imlib2-devel zlib-devel libxcrypt-devel
xorg xinit setxkbmap xrandr dbus turnstile xorg xinit setxkbmap xrandr dbus turnstile
picom dunst libnotify xwallpaper nsxiv maim xclip sct xss-lock picom dunst libnotify xwallpaper nsxiv maim xclip sct xssstate
pipewire wireplumber libspa-bluetooth alsa-pipewire pipewire wireplumber libspa-bluetooth alsa-pipewire
wpa_supplicant dhcpcd bluez acpid chrony tlp wpa_supplicant dhcpcd bluez acpid openntpd tlp
cups cups-filters hplip cups cups-filters hplip
font-firacode nerd-fonts-symbols-ttf papirus-icon-theme papirus-folders font-firacode nerd-fonts-symbols-ttf papirus-icon-theme papirus-folders
sassc gnome-themes-extra qt5ct qt6ct sassc gnome-themes-extra qt5ct qt6ct
opendoas gnupg pinentry-dmenu opendoas gnupg pinentry-dmenu
firefox thunderbird mpv neovim git fuse-sshfs unzip firefox thunderbird mpv neovim git fuse-sshfs unzip
yazi file ffmpeg 7zip jq poppler fd ripgrep fzf zoxide resvg ImageMagick yazi file bsdtar ffmpeg 7zip jq poppler fd ripgrep fzf zoxide resvg ImageMagick
" "
SUCKLESS="dwm st dmenu slstatus slock scroll clipmenu" SUCKLESS="dwm st dmenu slstatus slock scroll clipmenu"
# Tema GTK Everforest, en una versión fija para que siempre salga igual # Tema GTK Everforest, en una versión fija para que siempre salga igual
GTK_TEMA_REPO=https://github.com/Fausto-Korpsvart/Everforest-GTK-Theme GTK_TEMA_REPO=https://github.com/Fausto-Korpsvart/Everforest-GTK-Theme
GTK_TEMA_COMMIT=9b8be4d6648ae9eaae3dd550105081f8c9054825 GTK_TEMA_COMMIT=9b8be4d6648ae9eaae3dd550105081f8c9054825
SERVICIOS="dbus turnstiled wpa_supplicant dhcpcd bluetoothd acpid chronyd tlp automontaje cupsd" SERVICIOS="dbus turnstiled wpa_supplicant dhcpcd bluetoothd acpid openntpd tlp automontaje cupsd"
# La red la llevan wpa_supplicant y dhcpcd. polkitd no hace falta como # La red la llevan wpa_supplicant y dhcpcd. polkitd no hace falta como
# servicio: si algo lo pide (udisks2, libvirt), D-Bus lo arranca. turnstiled # servicio: si algo lo pide (libvirt), D-Bus lo arranca. turnstiled sustituye
# sustituye a elogind. # a elogind y openntpd a chronyd. avahi-daemon (mDNS) no hace falta: la
SERVICIOS_FUERA="NetworkManager polkitd elogind" # impresora va por IP fija.
SERVICIOS_FUERA="NetworkManager polkitd elogind chronyd avahi-daemon"
# _pipewire da prioridad de tiempo real al audio sin rtkit # _pipewire da prioridad de tiempo real al audio sin rtkit
# (/etc/security/limits.d/25-pw-rlimits.conf, de pipewire). # (/etc/security/limits.d/25-pw-rlimits.conf, de pipewire).
GRUPOS="audio video input network bluetooth lpadmin _pipewire" GRUPOS="audio video input network bluetooth lpadmin _pipewire"
@ -46,11 +47,14 @@ GRUPOS="audio video input network bluetooth lpadmin _pipewire"
# nsxiv), gammastep (sct), autorandr (pantallas), blueman y pavucontrol # nsxiv), gammastep (sct), autorandr (pantallas), blueman y pavucontrol
# (scripts bluetooth y volumen), pinentry-gtk (pinentry-dmenu), vlc (mpv), # (scripts bluetooth y volumen), pinentry-gtk (pinentry-dmenu), vlc (mpv),
# NetworkManager (wpa_supplicant, dhcpcd y el script wifi), rtkit (el grupo # NetworkManager (wpa_supplicant, dhcpcd y el script wifi), rtkit (el grupo
# _pipewire) y elogind (turnstile; Xorg arranca como root con Xorg.wrap y la # _pipewire), elogind (turnstile; Xorg arranca como root con Xorg.wrap y la
# tapa y los botones ya los lleva acpid). # tapa y los botones ya los lleva acpid), xss-lock (inactivo, con xssstate),
# chrony (openntpd), avahi y nss-mdns (nada los usa) y nemo con upower (yazi;
# con nemo se van gvfs y udisks2).
QUITAR=" QUITAR="
sudo feh gammastep autorandr blueman pavucontrol pinentry-gtk sudo feh gammastep autorandr blueman pavucontrol pinentry-gtk
gtk-engine-murrine vlc btop NetworkManager tlp-rdw rtkit elogind gtk-engine-murrine vlc btop NetworkManager tlp-rdw rtkit elogind
xss-lock chrony avahi nss-mdns nemo upower
" "
msg() { printf '\033[1;32m==>\033[0m %s\n' "$*"; } msg() { printf '\033[1;32m==>\033[0m %s\n' "$*"; }
@ -260,6 +264,12 @@ quitar() {
# shellcheck disable=SC2086 # shellcheck disable=SC2086
root xbps-remove -Ry $fuera root xbps-remove -Ry $fuera
# Sin nss-mdns, "mdns" sobra en la línea hosts de nsswitch.conf
if grep -q '^hosts:.*mdns' /etc/nsswitch.conf; then
root sed -i '/^hosts:/s/ mdns[a-z0-9_]*\( \[NOTFOUND=return\]\)\{0,1\}//g' \
/etc/nsswitch.conf
fi
# Lo que puso aquí una versión anterior de sistema/ para elogind # Lo que puso aquí una versión anterior de sistema/ para elogind
if [ -e /etc/elogind/logind.conf.d/10-acpid.conf ]; then if [ -e /etc/elogind/logind.conf.d/10-acpid.conf ]; then
root rm /etc/elogind/logind.conf.d/10-acpid.conf root rm /etc/elogind/logind.conf.d/10-acpid.conf

View file

@ -37,6 +37,45 @@ red(const char *unused)
return bprintf("WiFi: %s", s); return bprintf("WiFi: %s", s);
} }
/*
* run_command, pero solo cada LENTO segundos o en cuanto llega SIGUSR1 (lo
* mandan los scripts volumen, bluetooth y wifi y los clics en la barra). Así
* VOL y BT no lanzan wpctl y bluetoothctl cada 2 s; lo que cambie por otro
* lado tarda como mucho LENTO segundos en verse. La cuenta de SIGUSR1 (usr1)
* la lleva slstatus.c.
*/
#define LENTO 10
static const char *
lento(const char *cmd)
{
static struct {
const char *cmd;
char out[256];
int ok;
sig_atomic_t usr1;
time_t t;
} c[4];
struct timespec ahora;
const char *res;
size_t i;
clock_gettime(CLOCK_MONOTONIC, &ahora);
for (i = 0; i < LEN(c) && c[i].cmd && c[i].cmd != cmd; i++)
;
if (i == LEN(c))
return run_command(cmd);
if (c[i].cmd && c[i].usr1 == usr1 && ahora.tv_sec - c[i].t < LENTO)
return c[i].ok ? c[i].out : NULL;
c[i].cmd = cmd;
c[i].usr1 = usr1;
c[i].t = ahora.tv_sec;
if ((c[i].ok = (res = run_command(cmd)) != NULL))
snprintf(c[i].out, sizeof(c[i].out), "%s", res);
return c[i].ok ? c[i].out : NULL;
}
/* /*
* Los bytes \001 a \004 delimitan las zonas clicables de la barra * Los bytes \001 a \004 delimitan las zonas clicables de la barra
* (parche statuscmd de dwm): la red, el volumen, el bluetooth y la fecha. Lo que hace * (parche statuscmd de dwm): la red, el volumen, el bluetooth y la fecha. Lo que hace
@ -50,11 +89,11 @@ static const struct arg args[] = {
{ battery_perc, "[ BAT: %s%%", "BAT1" }, { battery_perc, "[ BAT: %s%%", "BAT1" },
{ battery_state, " %s ] ", "BAT1" }, { battery_state, " %s ] ", "BAT1" },
/* mismo volumen que maneja wpctl (PipeWire); MIC OFF si el micro está silenciado */ /* mismo volumen que maneja wpctl (PipeWire); MIC OFF si el micro está silenciado */
{ run_command, "\002[ VOL: %s ]\002 ", "wpctl get-volume @DEFAULT_AUDIO_SINK@ | awk '{ printf \"%d%%\", $2 * 100 + 0.5 } /MUTED/ { printf \" MUT\" }'; " { lento, "\002[ VOL: %s ]\002 ", "wpctl get-volume @DEFAULT_AUDIO_SINK@ | awk '{ printf \"%d%%\", $2 * 100 + 0.5 } /MUTED/ { printf \" MUT\" }'; "
"wpctl get-volume @DEFAULT_AUDIO_SOURCE@ | grep -q MUTED && printf ' MIC OFF'" }, "wpctl get-volume @DEFAULT_AUDIO_SOURCE@ | grep -q MUTED && printf ' MIC OFF'" },
/* OFF si el adaptador está apagado; si no, el primer dispositivo conectado /* OFF si el adaptador está apagado; si no, el primer dispositivo conectado
* y su batería, si la da ("Battery Percentage: 0x64 (100)" -> " 100%") */ * y su batería, si la da ("Battery Percentage: 0x64 (100)" -> " 100%") */
{ run_command, "\003[ BT: %s ]\003 ", "bluetoothctl show | grep -q 'Powered: yes' || { echo OFF; exit; }; " { lento, "\003[ BT: %s ]\003 ", "bluetoothctl show | grep -q 'Powered: yes' || { echo OFF; exit; }; "
"set -- $(bluetoothctl devices Connected | head -1); [ $# -gt 0 ] || exit; " "set -- $(bluetoothctl devices Connected | head -1); [ $# -gt 0 ] || exit; "
"m=$2; shift 2; printf %s \"$*\"; " "m=$2; shift 2; printf %s \"$*\"; "
"bluetoothctl info \"$m\" | awk -F'[()]' '/Battery Percentage/ { printf \" %s%%\", $2 }'" }, "bluetoothctl info \"$m\" | awk -F'[()]' '/Battery Percentage/ { printf \" %s%%\", $2 }'" },

View file

@ -19,6 +19,7 @@ struct arg {
char buf[1024]; char buf[1024];
static volatile sig_atomic_t done; static volatile sig_atomic_t done;
static volatile sig_atomic_t usr1; /* SIGUSR1 recibidas, para lento() en config.h */
static Display *dpy; static Display *dpy;
#include "config.h" #include "config.h"
@ -28,6 +29,8 @@ terminate(const int signo)
{ {
if (signo != SIGUSR1) if (signo != SIGUSR1)
done = 1; done = 1;
else
usr1++;
} }
static void static void