Files
RedBear-OS/local/recipes/system/redbear-greeter/source/redbear-kde-session
T
vasilito 845ae99f9d fix graphical boot: DRM scheme detection, ConsoleKit bypass, boot chain deps
Three fixes for the KWin DRM device discovery failure:

1. drm_scheme_ready(): replace head -c 1 with exec 3< open test.
   Reading from a DRM scheme fd blocks because the scheme expects
   ioctl-style request/response, not streaming reads. Use open()
   success as the scheme availability probe instead.

2. ConsoleKitSession::create(): return nullptr immediately.
   The D-Bus isServiceRegistered() call can block indefinitely when
   the bus daemon doesn't fully implement org.freedesktop.DBus.
   With both LogindSession and ConsoleKitSession returning nullptr,
   Session::create() falls through to NoopSession which uses plain
   open() for DRM device access.

3. Boot chain deps: redox-drm depends on driver-manager,
   greeter depends on evdevd (keyboard/mouse ready before login).

Also includes: KF6 CMake build fixes, Qt6 platform patches,
libdrm Redox ioctl shim, and wayland.toml scheme check fix.
2026-05-28 23:19:49 +03:00

290 lines
8.7 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
VALIDATION_REQUEST="/run/redbear-kde-session.validation-request"
VALIDATION_SUCCESS="/run/redbear-kde-session.validation-success"
kwin_pid=""
optional_pids=()
export DESKTOP_SESSION="${DESKTOP_SESSION:-plasmawayland}"
export DISPLAY=""
export KDE_FULL_SESSION="${KDE_FULL_SESSION:-true}"
export KDE_SESSION_VERSION="${KDE_SESSION_VERSION:-6}"
export LIBSEAT_BACKEND="${LIBSEAT_BACKEND:-seatd}"
export LOGNAME="${LOGNAME:-${USER:-root}}"
export PATH="${PATH:-/usr/bin:/bin}"
export QML2_IMPORT_PATH="${QML2_IMPORT_PATH:-/usr/qml}"
export QT_PLUGIN_PATH="${QT_PLUGIN_PATH:-/usr/plugins}"
export QT_QPA_PLATFORM="${QT_QPA_PLATFORM:-wayland}"
export QT_QPA_PLATFORM_PLUGIN_PATH="${QT_QPA_PLATFORM_PLUGIN_PATH:-/usr/plugins/platforms}"
export SEATD_SOCK="${SEATD_SOCK:-/run/seatd.sock}"
export USER="${USER:-root}"
export WAYLAND_DISPLAY="${WAYLAND_DISPLAY:-wayland-0}"
export XCURSOR_THEME="${XCURSOR_THEME:-Pop}"
export XDG_CURRENT_DESKTOP="${XDG_CURRENT_DESKTOP:-KDE}"
export XDG_SESSION_DESKTOP="${XDG_SESSION_DESKTOP:-KDE}"
export XDG_SESSION_ID="${XDG_SESSION_ID:-c1}"
export XDG_SESSION_TYPE="${XDG_SESSION_TYPE:-wayland}"
export XKB_CONFIG_ROOT="${XKB_CONFIG_ROOT:-/usr/share/X11/xkb}"
export KWIN_COMPOSE="${KWIN_COMPOSE:-Q}"
if [ -z "${XDG_RUNTIME_DIR:-}" ]; then
export XDG_RUNTIME_DIR="/tmp/run/user/$(id -u)"
fi
mkdir -p "$XDG_RUNTIME_DIR"
chmod 700 "$XDG_RUNTIME_DIR" 2>/dev/null || true
choose_state_dir() {
local requested="${REDBEAR_KDE_SESSION_STATE_DIR:-}"
if [ -n "$requested" ]; then
mkdir -p "$requested" 2>/dev/null || true
if [ -d "$requested" ] && [ -w "$requested" ]; then
printf '%s\n' "$requested"
return 0
fi
fi
if [ -d /run ] && [ -w /run ]; then
printf '%s\n' "/run"
return 0
fi
printf '%s\n' "$XDG_RUNTIME_DIR"
}
session_state_dir="$(choose_state_dir)"
mkdir -p "$session_state_dir"
chmod 700 "$session_state_dir" 2>/dev/null || true
session_env_file="$session_state_dir/redbear-kde-session.env"
session_ready_file="$session_state_dir/redbear-kde-session.ready"
panel_ready_file="$session_state_dir/redbear-kde-session.panel-ready"
rm -f "$session_ready_file" "$panel_ready_file"
cleanup() {
local status=$?
trap - EXIT INT TERM
for pid in "${optional_pids[@]}"; do
if kill -0 "$pid" 2>/dev/null; then
kill "$pid" 2>/dev/null || true
wait "$pid" 2>/dev/null || true
fi
done
if [ -n "$kwin_pid" ] && kill -0 "$kwin_pid" 2>/dev/null; then
kill "$kwin_pid" 2>/dev/null || true
wait "$kwin_pid" 2>/dev/null || true
fi
exit "$status"
}
trap cleanup EXIT INT TERM
kwin_mode="virtual"
# Redox scheme paths do not respond to stat()/test -e, but opening and
# reading a byte works. Use the same probe the compositor wrapper uses.
drm_scheme_ready() {
( exec 3<"/scheme/drm/card0" && exec 3>&- ) >/dev/null 2>&1
}
set_kwin_mode() {
local requested="${REDBEAR_KDE_SESSION_BACKEND:-auto}"
case "$requested" in
drm)
if [ -z "${KWIN_DRM_DEVICES:-}" ] && drm_scheme_ready; then
export KWIN_DRM_DEVICES=/scheme/drm/card0
fi
if [ -n "${KWIN_DRM_DEVICES:-}" ]; then
kwin_mode="drm"
else
kwin_mode="virtual"
fi
;;
virtual)
kwin_mode="virtual"
;;
auto|"")
if [ -n "${KWIN_DRM_DEVICES:-}" ]; then
kwin_mode="drm"
elif drm_scheme_ready; then
export KWIN_DRM_DEVICES=/scheme/drm/card0
kwin_mode="drm"
else
kwin_mode="virtual"
fi
;;
*)
kwin_mode="virtual"
;;
esac
}
set_kwin_mode
if [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ] && command -v dbus-launch >/dev/null 2>&1; then
eval "$(dbus-launch --sh-syntax)"
fi
write_session_environment() {
{
printf 'DBUS_SESSION_BUS_ADDRESS=%s\n' "${DBUS_SESSION_BUS_ADDRESS:-}"
printf 'DESKTOP_SESSION=%s\n' "$DESKTOP_SESSION"
printf 'KDE_FULL_SESSION=%s\n' "$KDE_FULL_SESSION"
printf 'KDE_SESSION_VERSION=%s\n' "$KDE_SESSION_VERSION"
printf 'KWIN_DRM_DEVICES=%s\n' "${KWIN_DRM_DEVICES:-}"
printf 'KWIN_MODE=%s\n' "$kwin_mode"
printf 'QML2_IMPORT_PATH=%s\n' "$QML2_IMPORT_PATH"
printf 'QT_PLUGIN_PATH=%s\n' "$QT_PLUGIN_PATH"
printf 'QT_QPA_PLATFORM=%s\n' "$QT_QPA_PLATFORM"
printf 'QT_QPA_PLATFORM_PLUGIN_PATH=%s\n' "$QT_QPA_PLATFORM_PLUGIN_PATH"
printf 'SEATD_SOCK=%s\n' "$SEATD_SOCK"
printf 'SESSION_STATE_DIR=%s\n' "$session_state_dir"
printf 'WAYLAND_DISPLAY=%s\n' "$WAYLAND_DISPLAY"
printf 'XDG_CURRENT_DESKTOP=%s\n' "$XDG_CURRENT_DESKTOP"
printf 'XDG_RUNTIME_DIR=%s\n' "$XDG_RUNTIME_DIR"
printf 'XDG_SESSION_DESKTOP=%s\n' "$XDG_SESSION_DESKTOP"
printf 'XDG_SESSION_ID=%s\n' "$XDG_SESSION_ID"
printf 'XDG_SESSION_TYPE=%s\n' "$XDG_SESSION_TYPE"
printf 'XKB_CONFIG_ROOT=%s\n' "$XKB_CONFIG_ROOT"
} > "$session_env_file"
chmod 600 "$session_env_file" 2>/dev/null || true
}
write_session_environment
if command -v dbus-update-activation-environment >/dev/null 2>&1; then
dbus-update-activation-environment \
DBUS_SESSION_BUS_ADDRESS \
DBUS_SESSION_BUS_PID \
DESKTOP_SESSION \
KDE_FULL_SESSION \
KDE_SESSION_VERSION \
KWIN_DRM_DEVICES \
QML2_IMPORT_PATH \
QT_PLUGIN_PATH \
QT_QPA_PLATFORM \
QT_QPA_PLATFORM_PLUGIN_PATH \
WAYLAND_DISPLAY \
XDG_CURRENT_DESKTOP \
XDG_RUNTIME_DIR \
XDG_SESSION_DESKTOP \
XDG_SESSION_ID \
XDG_SESSION_TYPE \
XKB_CONFIG_ROOT \
XCURSOR_THEME
fi
wait_for_wayland_socket() {
local socket_path="$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY"
local attempts=0
while [ "$attempts" -lt 40 ]; do
if [ -S "$socket_path" ] || [ -e "$socket_path" ]; then
return 0
fi
if [ -n "$kwin_pid" ] && ! kill -0 "$kwin_pid" 2>/dev/null; then
return 1
fi
attempts=$((attempts + 1))
sleep 1
done
return 1
}
mark_validation_success() {
if [ -e "$VALIDATION_REQUEST" ]; then
: > "$VALIDATION_SUCCESS" 2>/dev/null || true
fi
}
validation_requested() {
[ -e "$VALIDATION_REQUEST" ]
}
launch_optional_component() {
local program="$1"
local ready_marker="$2"
if ! command -v "$program" >/dev/null 2>&1; then
return 0
fi
# kded6 is a D-Bus daemon with no GUI requirement.
# Force offscreen QPA to avoid the Qt6 Wayland page-fault crash at null+8.
if [ "$program" = "kded6" ]; then
QT_QPA_PLATFORM=offscreen "$program" &
else
"$program" &
fi
local pid=$!
optional_pids+=("$pid")
if [ -n "$ready_marker" ]; then
sleep 1
if kill -0 "$pid" 2>/dev/null; then
: > "$ready_marker"
fi
fi
}
# Prefer kwin_wayland (real KWin compositor). Fall back to redbear-compositor.
COMPOSITOR=""
if command -v kwin_wayland >/dev/null 2>&1; then
COMPOSITOR="kwin_wayland"
elif command -v /usr/bin/kwin_wayland >/dev/null 2>&1; then
COMPOSITOR="/usr/bin/kwin_wayland"
elif command -v redbear-compositor >/dev/null 2>&1; then
COMPOSITOR="redbear-compositor"
echo "redbear-kde-session: kwin_wayland not found, falling back to redbear-compositor" >&2
else
echo "redbear-kde-session: no compositor found (need kwin_wayland or redbear-compositor)" >&2
exit 1
fi
kwin_args=()
if [ "$kwin_mode" = "drm" ]; then
kwin_args+=(--drm)
else
kwin_args+=(--virtual)
fi
"$COMPOSITOR" "${kwin_args[@]}" &
kwin_pid=$!
if ! wait_for_wayland_socket; then
printf '%s\n' "redbear-kde-session: $COMPOSITOR failed to expose $XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" >&2
printf '%s\n' "redbear-kde-session: kwin_pid=$kwin_pid, kwin_alive=$(kill -0 $kwin_pid 2>/dev/null && echo yes || echo no)" >&2
printf '%s\n' "redbear-kde-session: XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR" >&2
printf '%s\n' "redbear-kde-session: WAYLAND_DISPLAY=$WAYLAND_DISPLAY" >&2
printf '%s\n' "redbear-kde-session: contents of $XDG_RUNTIME_DIR:" >&2
ls -la "$XDG_RUNTIME_DIR" 2>/dev/null >&2 || echo "(dir not found)" >&2
exit 1
fi
: > "$session_ready_file"
mark_validation_success
if validation_requested; then
# Bounded validation mode: once the compositor exposed a real Wayland socket and
# the session marker was written, keep the session alive briefly so the checker can
# observe startup, then exit cleanly to let greeterd return to greeter_ready.
sleep 2
exit 0
fi
launch_optional_component kded6 ""
launch_optional_component plasmashell "$panel_ready_file"
wait "$kwin_pid"