diff --git a/README.md b/README.md index 20d3394..5aa2170 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ command -v lemonbar ~/.bin/lemonbar.sh | lemonbar ``` -After all these programs have been started, firestarter executes `~/.firestarterrc` if it exists. +After all these programs have been started, firestarter starts XDG autostart applications and executes `~/.firestarterrc` if it exists. ## Logging @@ -68,6 +68,10 @@ Firestarter, in addition to spawning the programs in the default configs, also i | 53 | Failed to create logging directory (and logging is enabled) | | 54 | `HOME` does not exist or is unreadable | +## Idiosyncracies + +* The `wm` config file is special; if it exists and a default can be found for it, firestarter will watch the `_NET_WM_NAME` atom on the root window, waiting for it to initialize before starting XDG autostarts. This prevents applications from being started before the WM is ready to manage them. You can disable this by setting `FS_NOWAITWM`. + ## Contribution Firestarter by no means contains an exhaustive list of all possible programs. If you know of or have created a program that should be added, *please* open an issue about it. The script should be light but its choices massive. diff --git a/firestarter b/firestarter index a614fb2..f33c1d0 100755 --- a/firestarter +++ b/firestarter @@ -13,6 +13,8 @@ _configdir="${XDG_CONFIG_HOME:-$HOME/.config}/$_name" _logdir="${XDG_DATA_HOME:-$HOME/.local/share}/$_name/logs" _firestarterrc="$HOME/.firestarterrc" _sessionid="$(< /proc/self/sessionid)" +# Dummy fd for read sleeping +exec 1023<> <(:) # Basic functions print() { @@ -41,6 +43,10 @@ err() { exit "$2" fi } +has() { + [ -z "$1" ] && return 1 + command -v "$1" > /dev/null 2>&1 +} gettarget() { # Parse a defaults file to get the target program [ -z "$1" ] && return 1 @@ -278,6 +284,7 @@ Start or generate a desktop environment configuration Additionally, firestarter responds to the following environment variables: FS_NOLOG If nonempty, create no log files + FS_NOWAITWM If nonempty, skip waiting on the WM to initialize Copyright (c) 2019 rehashedsalt@cock.li Licensed under the MIT License @@ -303,7 +310,7 @@ step_check() { } step_preexecute() { # Special things that can't use simple configuration files - [ "$_dryrun" = "1" ] && return 0 + [ -n "$_dryrun" ] && return 0 # Exports export XDG_CURRENT_DESKTOP="${XDG_CURRENT_DESKTOP:-firestarter}" @@ -319,7 +326,7 @@ step_preexecute() { hasdbus=1 elif \ [ -z "$DBUS_SESSION_BUS_ADDRESS" ] && \ - command -v dbus-launch > /dev/null 2>&1; then + has dbus-launch; then # We have dbus but haven't started up a bus yet eval "$(dbus-launch --exit-with-session --sh-syntax)" hasdbus=1 @@ -327,18 +334,18 @@ step_preexecute() { log "Did not start dbus; some applications may misbehave" fi if [ -n "$hasdbus" ]; then - if command -v dbus-update-activation-environment > /dev/null 2>&1; then + if has dbus-update-activation-environment; then dbus-update-activation-environment --verbose --systemd --all > /dev/null 2>&1 fi fi unset hasdbus # kcminit/Qt settings - if command -v kcminit > /dev/null 2>&1; then + if has kcminit; then log "Initializing KDE Control Module settings" kcminit > /dev/null 2>&1 export XDG_CURRENT_DESKTOP="KDE" - elif command -v qt5ct > /dev/null 2>&1; then + elif has qt5ct; then log "Integrating qt5ct" if [ -z "$QT_QPA_PLATFORMTHEME" ]; then export QT_QPA_PLATFORMTHEME="qt5ct" @@ -355,7 +362,7 @@ step_preexecute() { fi # xhost - if command -v xhost > /dev/null 2>&1; then + if has xhost; then if xhost +si:localuser:"$(id -un)" > /dev/null 2>&1; then log "Session can be accessed in other sessions by this user" else @@ -364,7 +371,7 @@ step_preexecute() { fi # xresources - if [ -n "$DISPLAY" ] && command -v xrdb && [ -r "$HOME/.Xresources" ]; then + if [ -n "$DISPLAY" ] && has xrdb && [ -r "$HOME/.Xresources" ]; then if xrdb "$HOME/.Xresources" > /dev/null 2>&1; then log "Loaded in .Xresources" else @@ -373,7 +380,7 @@ step_preexecute() { fi # xset - if command -v xset > /dev/null 2>&1; then + if has xset; then log "Disabling bell" xset -b fi @@ -407,7 +414,7 @@ step_execute() { if gettarget "$file"; then target="$_return" log "Found target for \"$filename\": \"$target\"" - if ! [ "$_dryrun" = "1" ]; then + if [ -z "$_dryrun" ]; then if [ -f "$logfile" ]; then [ -f "$logfile.old" ] && rm "$logfile.old" mv "$logfile" "$logfile.old" @@ -418,7 +425,30 @@ step_execute() { done } step_postexecute() { - # Wait for the WM to initialize, if one was found + # Wait for the WM to initialize, if one was found and we have the tools + if [ -z "$FS_NOWAITWM" ] && gettarget "$_configdir/wm" && has xprop && has grep; then + log "Waiting for WM to initialize: \"$_return\"" + for (( i=0; i<10; i++ )); do + line="$(xprop -root | grep ^_NET_WM_NAME | grep -o '"\S*"$')" + if [ -n "$line" ]; then + log "WM has intiailized, _NET_WM_NAME atom reads: $line" + break + fi + read -t 1 -u 1023 + done + fi + # Start XDG autostarters, if they exist + if [ -z "$_dryrun" ]; then + if has dex; then + dex -a > /dev/null 2>&1 + elif has fbautostart; then + fbautostart > /dev/null 2>&1 + elif has xdg-autostart; then + xdg-autostart ${XDG_CURRENT_DESKTOP:-firestarter} + else + log "Could not find an XDG autostarter" + fi + fi # Source in a user script if it exists if [ -r "$_firestarterrc" ] && [ -z "$_dryrun" ]; then log "Sourcing .firestarterrc" @@ -426,7 +456,7 @@ step_postexecute() { fi } step_wait() { - [ "$_dryrun" = "1" ] && exit 0 + [ -n "$_dryrun" ] && exit 0 log "Waiting for programs to exit" log "Send any termination signal to firestarter to log out" trap step_logout EXIT @@ -435,7 +465,7 @@ step_wait() { } step_logout() { log "Logging out" - if command -v loginctl > /dev/null 2>&1; then + if has loginctl; then # Use loginctl if possible if [ -n "$_sessionid" ]; then loginctl terminate-session "$_sessionid" @@ -452,7 +482,7 @@ main() { while getopts ":dgh" opt; do case $opt in d) - if ! [ "$_dryrun" = "1" ]; then + if [ -z "$_dryrun" ]; then log "Performing a dry run" _dryrun=1 fi