#!/bin/bash
# gnome-session-start - Start GNOME session components for sysvinit systems
# Usage: gnome-session-start <session_type> <session_name>
#   session_type: wayland
#   session_name: gnome, gnome-login, gnome-initial-setup

SESSION_TYPE="${1:-wayland}"
SESSION_NAME="${2:-gnome}"

# Source system profile scripts, exactly as GDM's old wayland-session script did.
# Dot-sourcing preserves all GDM-passed variables (XDG_SESSION_ID, XDG_SEAT, etc.)
# and adds the profile vars (LANG, HOSTNAME, XKB_DEFAULT_*, etc.) on top.
case $SHELL in
    */bash)
        [ -z "$BASH" ] && exec "$SHELL" "$0" "$@"
        set +o posix
        [ -f /etc/profile ] && . /etc/profile
        if [ -f "$HOME/.bash_profile" ]; then
            . "$HOME/.bash_profile"
        elif [ -f "$HOME/.bash_login" ]; then
            . "$HOME/.bash_login"
        elif [ -f "$HOME/.profile" ]; then
            . "$HOME/.profile"
        fi
        ;;
    */zsh)
        [ -z "$ZSH_NAME" ] && exec "$SHELL" "$0" "$@"
        [ -d /etc/zsh ] && zdir=/etc/zsh || zdir=/etc
        zhome=${ZDOTDIR:-$HOME}
        [ -f $zdir/zprofile ] && . $zdir/zprofile
        [ -f $zhome/.zprofile ] && . $zhome/.zprofile
        [ -f $zdir/zlogin ] && . $zdir/zlogin
        [ -f $zhome/.zlogin ] && . $zhome/.zlogin
        emulate -R sh
        ;;
    */csh|*/tcsh)
        # [t]cshrc is always sourced automatically.
        # Note that sourcing csh.login after .cshrc is non-standard.
        wlsess_tmp=`mktemp /tmp/wlsess-env-XXXXXX`
        $SHELL -c "if (-f /etc/csh.login) source /etc/csh.login; if (-f ~/.login) source ~/.login; /bin/sh -c 'export -p' >! $wlsess_tmp"
        . $wlsess_tmp
        rm -f $wlsess_tmp
        ;;
    */fish)
        xsess_tmp=`mktemp /tmp/xsess-env-XXXXXX`
        $SHELL --login -c "/bin/sh -c 'export -p' > $xsess_tmp"
        . $xsess_tmp
        rm -f $xsess_tmp
        ;;
    *) # Plain sh, ksh, and anything we do not know.
        [ -f /etc/profile ] && . /etc/profile
        [ -f "$HOME/.profile" ] && . "$HOME/.profile"
        ;;
esac

# Apply the user's locale region from GNOME Settings (mirrors old /usr/bin/gnome-session).
REGION=$(G_MESSAGES_DEBUG='' gsettings get org.gnome.system.locale region 2>/dev/null)
REGION=${REGION#\'}
REGION=${REGION%\'}
if [ -n "$REGION" ] && [ "$LANG" != "$REGION" ]; then
    export LC_NUMERIC=$REGION LC_TIME=$REGION LC_MONETARY=$REGION
    export LC_PAPER=$REGION LC_ADDRESS=$REGION LC_TELEPHONE=$REGION
    export LC_MEASUREMENT=$REGION
fi

# Use session-specific rundir created by the leader, so that stop scripts
# from concurrent sessions do not interfere with each other.
PIDDIR="${GNOME_SESSION_RUNDIR:-$XDG_RUNTIME_DIR}"

export XDG_CURRENT_DESKTOP=GNOME
export XDG_SESSION_TYPE="$SESSION_TYPE"

# Ensure the session D-Bus address is set
if [ -z "$DBUS_SESSION_BUS_ADDRESS" ]; then
    if [ -S "$XDG_RUNTIME_DIR/bus" ]; then
        export DBUS_SESSION_BUS_ADDRESS="unix:path=$XDG_RUNTIME_DIR/bus"
    fi
fi

# Add flatpak export paths if available
for d in "$HOME/.local/share/flatpak/exports/share" "/var/lib/flatpak/exports/share"; do
    if [ -d "$d" ]; then
        XDG_DATA_DIRS="${XDG_DATA_DIRS:+$XDG_DATA_DIRS:}$d"
    fi
done
export XDG_DATA_DIRS

write_pid() {
    echo "$2" > "$PIDDIR/$1.pid"
}

# Start session D-Bus service
/usr/libexec/gnome-session-service --session="$SESSION_NAME" &
SERVICE_PID=$!
write_pid gnome-session-service $SERVICE_PID

# Start session monitor (reads the leader FIFO)
/usr/libexec/gnome-session-ctl --monitor &
write_pid gnome-session-monitor $!

# Wait for the gnome-session-monitor to claim its bus name
gdbus wait --session org.gnome.SessionManager

# Start gnome-shell
SHELL_ARGS="--wayland"
if [ "$SESSION_NAME" = "gnome-login" ]; then
	SHELL_ARGS="--wayland --mode=gdm"
fi

/usr/bin/gnome-shell $SHELL_ARGS &
SHELL_PID=$!
write_pid gnome-shell $SHELL_PID

# Wait for the gnome-shell to register its interface
gdbus wait --session org.gnome.Shell

# gnome-shell registers on D-Bus slightly before creating the Wayland socket,
# so retry for up to 5 seconds to close the race window.
_wayland_retries=50
while [ -z "$WAYLAND_DISPLAY" ] && [ "$_wayland_retries" -gt 0 ]; do
    sleep 0.1
    for _f in "$XDG_RUNTIME_DIR"/wayland-[0-9]; do
        [ -S "$_f" ] && export WAYLAND_DISPLAY="${_f##*/}" && break
    done
    unset _f
    _wayland_retries=$((_wayland_retries - 1))
done
unset _wayland_retries

# Xwayland is started eagerly by mutter; retry with the same window.
_display_retries=50
while [ -z "$DISPLAY" ] && [ "$_display_retries" -gt 0 ]; do
    sleep 0.1
    for _f in /tmp/.X11-unix/X[0-9]; do
        [ -S "$_f" ] && export DISPLAY=":${_f##*/X}" && break
    done
    unset _f
    _display_retries=$((_display_retries - 1))
done
unset _display_retries

if [ -z "$XAUTHORITY" ]; then
    for _f in "$XDG_RUNTIME_DIR"/.mutter-Xwaylandauth.*; do
        [ -f "$_f" ] && export XAUTHORITY="$_f" && break
    done
    unset _f
fi

# Push the full session environment (locale, display, profile vars) to the
# dbus activation environment. All display vars are now set above, so --all
# is safe and avoids having to maintain an explicit list.
dbus-update-activation-environment --all

# Start GNOME Settings Daemon components
for _gsd in /usr/libexec/gsd-*; do
    [ -x "$_gsd" ] || continue
    daemon="${_gsd##*/}"
    "$_gsd" &
    write_pid "$daemon" $!
done
unset _gsd daemon

# Signal session initialization complete
/usr/libexec/gnome-session-ctl --signal-init

# Wait for gnome-shell or gnome-session-service to exit.
wait -n $SHELL_PID $SERVICE_PID 2>/dev/null
exit $?
