diff --git a/tools/create-macos-app.sh b/tools/create-macos-app.sh new file mode 100755 index 00000000..8f4a70ef --- /dev/null +++ b/tools/create-macos-app.sh @@ -0,0 +1,95 @@ +#!/usr/bin/env bash +# Helper to build a minimal macOS .app wrapper for Solaar. +set -euo pipefail + +APP_ROOT=${1:-/Applications/Solaar.app} +SOLAR_PATH=${SOLAR_PATH:-/opt/homebrew/bin/solaar} +ICON_SOURCE=${ICON_SOURCE:-share/solaar/icons/solaar-light_100.png} + +if [[ ! -x "${SOLAR_PATH}" ]]; then + echo "Error: Unable to execute ${SOLAR_PATH}. Set SOLAR_PATH to the solaar binary." >&2 + exit 1 +fi + +case "${APP_ROOT}" in + ""|"/"|".") + echo "Error: Refusing to create app bundle at unsafe location: \"${APP_ROOT}\"" >&2 + exit 1 + ;; +esac + +echo "Creating Solaar app bundle at ${APP_ROOT}" +rm -rf "${APP_ROOT}" + +APP_CONTENTS="${APP_ROOT}/Contents" +MACOS_DIR="${APP_CONTENTS}/MacOS" +RESOURCES_DIR="${APP_CONTENTS}/Resources" + +mkdir -p "${MACOS_DIR}" "${RESOURCES_DIR}" + +WRAPPER="${MACOS_DIR}/solaar-wrapper" +cat > "${WRAPPER}" </dev/null 2>&1 && command -v iconutil >/dev/null 2>&1 && [[ -f "${ICON_SOURCE}" ]]; then + TMP_ICONSET=$(mktemp -d /tmp/solaar-iconset.XXXXXX) + trap 'rm -rf "${TMP_ICONSET}"' EXIT + for SIZE in 16 32 64 128 256 512; do + sips -s format png -z "${SIZE}" "${SIZE}" "${ICON_SOURCE}" --out "${TMP_ICONSET}/icon_${SIZE}x${SIZE}.png" >/dev/null + DOUBLE=$((SIZE * 2)) + sips -s format png -z "${DOUBLE}" "${DOUBLE}" "${ICON_SOURCE}" --out "${TMP_ICONSET}/icon_${SIZE}x${SIZE}@2x.png" >/dev/null + done + if iconutil -c icns "${TMP_ICONSET}" -o "${RESOURCES_DIR}/solaar.icns" >/dev/null 2>&1; then + HAVE_ICON=1 + echo "Added icon from ${ICON_SOURCE}" + else + echo "Warning: Failed to create solaar.icns – continuing without custom icon" >&2 + fi + rm -rf "${TMP_ICONSET}" + trap - EXIT +else + echo "Skipping icon generation (requires sips, iconutil, and ${ICON_SOURCE})" +fi + +{ +cat < + + + + CFBundleExecutable + solaar-wrapper + CFBundleIdentifier + io.github.pwr-solaar.solaar + CFBundleName + Solaar + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + LSMinimumSystemVersion + 11.0 + NSInputMonitoringUsageDescription + Solaar needs to access input devices to configure and monitor your Logitech keyboards, mice, and other peripherals. +EOF +if [[ ${HAVE_ICON} -eq 1 ]]; then +cat <<'EOF' + CFBundleIconFile + solaar.icns +EOF +fi +cat <<'EOF' + + +EOF +} > "${APP_CONTENTS}/Info.plist" + +echo "Solaar app bundle created at ${APP_ROOT}" +echo "" +echo "To install the LaunchAgent for automatic startup and keep-alive execute:" +echo " bash tools/create-macos-launchagent.sh" diff --git a/tools/create-macos-launchagent.sh b/tools/create-macos-launchagent.sh new file mode 100755 index 00000000..4af93d89 --- /dev/null +++ b/tools/create-macos-launchagent.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# Helper to install a LaunchAgent for Solaar to keep it running in the background. +set -euo pipefail + +SOLAR_PATH=${SOLAR_PATH:-/opt/homebrew/bin/solaar} + +if [[ ! -x "${SOLAR_PATH}" ]]; then + echo "Error: Unable to execute ${SOLAR_PATH}. Set SOLAR_PATH to the solaar binary." >&2 + exit 1 +fi + +LAUNCH_AGENT_DIR="${HOME}/Library/LaunchAgents" +LAUNCH_AGENT_PLIST="${LAUNCH_AGENT_DIR}/io.github.pwr-solaar.solaar.plist" + +mkdir -p "${LAUNCH_AGENT_DIR}" + +echo "Creating LaunchAgent to keep Solaar running..." + +# Unload if already loaded (suppress errors) +launchctl unload "${LAUNCH_AGENT_PLIST}" 2>/dev/null || true + +cat > "${LAUNCH_AGENT_PLIST}" < + + + + Label + io.github.pwr-solaar.solaar + ProgramArguments + + ${SOLAR_PATH} + --window=hide + + RunAtLoad + + KeepAlive + + StandardOutPath + ${HOME}/Library/Logs/solaar.log + StandardErrorPath + ${HOME}/Library/Logs/solaar.error.log + ProcessType + Background + + +EOF + +launchctl load "${LAUNCH_AGENT_PLIST}" + +echo "LaunchAgent created at ${LAUNCH_AGENT_PLIST}" +echo "" +echo "To disable automatic startup:" +echo " launchctl unload \"${LAUNCH_AGENT_PLIST}\"" +echo "" +echo "To re-enable automatic startup:" +echo " launchctl load \"${LAUNCH_AGENT_PLIST}\"" +echo "" +echo "To start Solaar:" +echo " launchctl start io.github.pwr-solaar.solaar" +echo "" +echo "To stop Solaar:" +echo " launchctl stop io.github.pwr-solaar.solaar" +echo "" +echo "Logs will be written to:" +echo " ${HOME}/Library/Logs/solaar.log" +echo " ${HOME}/Library/Logs/solaar.error.log"