mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-05-08 07:08:05 +03:00
Ship Lan Mouse on macOS as an accessory app (no Dock icon, no main window on launch) with a status-bar item for show/quit. Closing the window hides it instead of quitting so the menu bar stays the primary surface. - build-aux/macos-lsui-element.plist: LSUIElement=true plus NSInputMonitoringUsageDescription and NSAppleEventsUsageDescription (merged into Info.plist via cargo-bundle's osx_info_plist_exts). - lan-mouse-gtk/src/macos_status_item.rs: NSStatusItem setup via raw objc_msgSend FFI. Loads a bundled 22pt PNG as a template image so it auto-tints for light/dark menu bars. - scripts/makeicns.sh: emit Contents/Resources/menubar-template.png from the existing SVG. - scripts/copy-macos-dylib.sh: flatten cargo-bundle's preserved target/ subdir under Resources so NSBundle pathForResource: finds the template image. - lan-mouse-gtk/src/lib.rs: register the new modules, set up a Cmd+Q-wired quit action, configure bundle env vars (schemas, XDG_DATA_DIRS, GTK_DATA_PREFIX) when running from inside the .app, and filter the known upstream Gtk theme-parser warning spam. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
137 lines
4.4 KiB
Bash
Executable File
137 lines
4.4 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
homebrew_path=""
|
|
exec_path="target/debug/bundle/osx/Lan Mouse.app/Contents/MacOS/lan-mouse"
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
$0: Copy all Homebrew libraries into the macOS app bundle.
|
|
USAGE: $0 [-h] [-b homebrew_path] [exec_path]
|
|
|
|
OPTIONS:
|
|
-h, --help Show this help message and exit
|
|
-b Path to Homebrew installation (default: $homebrew_path)
|
|
exec_path Path to the main executable in the app bundle
|
|
(default: get from `brew --prefix`)
|
|
|
|
When macOS apps are linked to dynamic libraries (.dylib files),
|
|
the fully qualified path to the library is embedded in the binary.
|
|
If the libraries come from Homebrew, that means that Homebrew must be present
|
|
and the libraries must be installed in the same location on the user's machine.
|
|
|
|
This script copies all of the Homebrew libraries that an executable links to into the app bundle
|
|
and tells all the binaries in the bundle to look for them there.
|
|
EOF
|
|
}
|
|
|
|
# Gather command-line arguments
|
|
while test $# -gt 0; do
|
|
case "$1" in
|
|
-h | --help ) usage; exit 0;;
|
|
-b | --homebrew ) homebrew_path="$1"; shift 2;;
|
|
* ) exec_path="$1"; shift;;
|
|
esac
|
|
done
|
|
|
|
if [ -z "$homebrew_path" ]; then
|
|
homebrew_path="$(brew --prefix)"
|
|
fi
|
|
|
|
# Path to the .app bundle
|
|
bundle_path=$(dirname "$(dirname "$(dirname "$exec_path")")")
|
|
# Path to the Frameworks directory
|
|
fwks_path="$bundle_path/Contents/Frameworks"
|
|
mkdir -p "$fwks_path"
|
|
# Path to bundled GTK/GSettings data
|
|
resources_path="$bundle_path/Contents/Resources"
|
|
share_path="$resources_path/share"
|
|
|
|
# Copy and fix references for a binary (executable or dylib)
|
|
#
|
|
# This function will:
|
|
# - Copy any referenced dylibs from /opt/homebrew to the Frameworks directory
|
|
# - Update the binary to reference the local copy instead
|
|
# - Add the Frameworks directory to the binary's RPATH
|
|
# - Recursively process the copied dylibs
|
|
fix_references() {
|
|
local bin="$1"
|
|
|
|
# Get all Homebrew libraries referenced by the binary
|
|
libs=$(otool -L "$bin" | awk -v homebrew="$homebrew_path" '$0 ~ homebrew {print $1}')
|
|
|
|
echo "$libs" | while IFS= read -r old_path; do
|
|
if [ -z "$old_path" ]; then
|
|
continue
|
|
fi
|
|
|
|
local base_name="$(basename "$old_path")"
|
|
local dest="$fwks_path/$base_name"
|
|
|
|
if [ ! -e "$dest" ]; then
|
|
echo "Copying $old_path -> $dest"
|
|
cp -f "$old_path" "$dest"
|
|
# Ensure the copied dylib is writable so that xattr -rd /path/to/Lan\ Mouse.app works.
|
|
chmod 644 "$dest"
|
|
|
|
echo "Updating $dest to have install_name of @rpath/$base_name..."
|
|
install_name_tool -id "@rpath/$base_name" "$dest"
|
|
|
|
# Recursively process this dylib
|
|
fix_references "$dest"
|
|
fi
|
|
|
|
echo "Updating $bin to reference @rpath/$base_name..."
|
|
install_name_tool -change "$old_path" "@rpath/$base_name" "$bin"
|
|
done
|
|
}
|
|
|
|
fix_references "$exec_path"
|
|
|
|
copy_runtime_data() {
|
|
mkdir -p "$share_path"
|
|
|
|
if [ -d "$homebrew_path/share/glib-2.0/schemas" ]; then
|
|
mkdir -p "$share_path/glib-2.0"
|
|
rm -rf "$share_path/glib-2.0/schemas"
|
|
cp -RL "$homebrew_path/share/glib-2.0/schemas" "$share_path/glib-2.0/schemas"
|
|
if command -v glib-compile-schemas >/dev/null 2>&1; then
|
|
glib-compile-schemas "$share_path/glib-2.0/schemas"
|
|
elif [ -x "$homebrew_path/bin/glib-compile-schemas" ]; then
|
|
"$homebrew_path/bin/glib-compile-schemas" "$share_path/glib-2.0/schemas"
|
|
fi
|
|
fi
|
|
|
|
if [ -d "$homebrew_path/share/gtk-4.0" ]; then
|
|
rm -rf "$share_path/gtk-4.0"
|
|
cp -RL "$homebrew_path/share/gtk-4.0" "$share_path/gtk-4.0"
|
|
fi
|
|
|
|
if [ -d "$homebrew_path/share/icons/Adwaita" ]; then
|
|
mkdir -p "$share_path/icons"
|
|
rm -rf "$share_path/icons/Adwaita"
|
|
cp -RL "$homebrew_path/share/icons/Adwaita" "$share_path/icons/Adwaita"
|
|
fi
|
|
}
|
|
|
|
copy_runtime_data
|
|
|
|
# cargo-bundle preserves the source path under Contents/Resources (so
|
|
# `target/menubar-template.png` lands at `Resources/target/...`). Flatten it
|
|
# so NSBundle pathForResource: finds the file at the Resources root.
|
|
if [ -f "$resources_path/target/menubar-template.png" ]; then
|
|
mv "$resources_path/target/menubar-template.png" "$resources_path/menubar-template.png"
|
|
rmdir "$resources_path/target" 2>/dev/null || true
|
|
fi
|
|
|
|
# Ensure the main executable has our Frameworks path in its RPATH
|
|
if ! otool -l "$exec_path" | grep -q "@executable_path/../Frameworks"; then
|
|
echo "Adding RPATH to $exec_path"
|
|
install_name_tool -add_rpath "@executable_path/../Frameworks" "$exec_path"
|
|
fi
|
|
|
|
# Se-sign the .app
|
|
codesign --force --deep --sign - "$bundle_path"
|
|
|
|
echo "Done!"
|