diff --git a/nfpm.yaml b/nfpm.yaml index 7e993ed6..68c9c34c 100644 --- a/nfpm.yaml +++ b/nfpm.yaml @@ -54,6 +54,7 @@ overrides: - libxext6 - libxfixes3 - libxkbcommon0 + - libxkbcommon-x11-0 - libxrandr2 - xdg-utils - xwayland diff --git a/package-lock.json b/package-lock.json index b892e77f..74d73210 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "querymt-desktop", - "version": "0.1.9", + "version": "0.1.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "querymt-desktop", - "version": "0.1.9", + "version": "0.1.10", "dependencies": { "@fontsource-variable/ibm-plex-sans": "^5.3.0", "@fontsource/ibm-plex-mono": "^5.3.0", diff --git a/package.json b/package.json index 8e1ab63b..99342104 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "querymt-desktop", - "version": "0.1.9", + "version": "0.1.10", "private": true, "type": "module", "scripts": { diff --git a/scripts/cef/package.sh b/scripts/cef/package.sh index e5ea0ee1..286f4035 100644 --- a/scripts/cef/package.sh +++ b/scripts/cef/package.sh @@ -58,15 +58,23 @@ bash scripts/cef/stage-runtime.sh release "$PROFILE_DIR" WORK="$TARGET_ROOT/cef-package-$ARCH" OUT="$TARGET_ROOT/release/bundle" RUNTIME="$WORK/runtime" +XKB_FALLBACK="$WORK/xkb-fallback" rm -rf "$WORK" -mkdir -p "$RUNTIME" +mkdir -p "$RUNTIME" "$XKB_FALLBACK" rm -rf "$OUT/appimage" "$OUT/deb" "$OUT/tar" mkdir -p "$OUT/appimage" "$OUT/deb" "$OUT/tar" cp -a "$PROFILE_DIR"/*.so* "$RUNTIME/" 2>/dev/null || true cp -a "$PROFILE_DIR"/*.pak "$PROFILE_DIR"/*.dat "$PROFILE_DIR"/*.bin "$PROFILE_DIR"/*.json "$RUNTIME/" 2>/dev/null || true -stage_library_family libxkbcommon-x11.so.0 "$RUNTIME" -stage_library_family libxcb-xkb.so.1 "$RUNTIME" +# winit dlopens libxkbcommon-x11 for the CEF runtime's X11 event loop. +# libxkbcommon-x11 builds keymaps using libxkbcommon's private struct layouts, +# so it must come from the same release as libxkbcommon. Never put it next to +# the binary (RUNPATH=$ORIGIN would pair it with a different host libxkbcommon +# and segfault in xkb_state_update_mask). Keep a matched set in a separate +# directory that the AppImage only uses when the host lacks libxkbcommon-x11. +stage_library_family libxkbcommon.so.0 "$XKB_FALLBACK" +stage_library_family libxkbcommon-x11.so.0 "$XKB_FALLBACK" +stage_library_family libxcb-xkb.so.1 "$XKB_FALLBACK" cp -a "$PROFILE_DIR"/chrome_crashpad_handler "$RUNTIME/" 2>/dev/null || true cp -a "$PROFILE_DIR"/CEF-LICENSE.txt "$RUNTIME/" mkdir -p "$RUNTIME/locales" @@ -88,6 +96,8 @@ fi APPDIR="$WORK/QueryMT.AppDir" mkdir -p "$APPDIR/usr/bin" cp -a "$RUNTIME/." "$APPDIR/usr/bin/" +mkdir -p "$APPDIR/usr/lib/xkb-fallback" +cp -a "$XKB_FALLBACK/." "$APPDIR/usr/lib/xkb-fallback/" cp "$BINARY" "$APPDIR/usr/bin/querymt-desktop" cp packaging/querymt-desktop.desktop "$APPDIR/querymt-desktop.desktop" cp src-tauri/icons/icon.png "$APPDIR/querymt-desktop.png" @@ -96,6 +106,42 @@ cat > "$APPDIR/AppRun" <<'APPRUN' HERE="$(dirname "$(readlink -f "$0")")" export LD_LIBRARY_PATH="$HERE/usr/bin${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" +# Only libraries loadable by this AppImage's architecture count; a 32-bit-only +# host copy must not suppress the bundled fallback. +case "$(uname -m)" in + x86_64) LDCONFIG_ARCH=x86-64; MULTIARCH=x86_64-linux-gnu; ELF_MACHINE=3e ;; + aarch64 | arm64) LDCONFIG_ARCH=AArch64; MULTIARCH=aarch64-linux-gnu; ELF_MACHINE=b7 ;; + *) LDCONFIG_ARCH=; MULTIARCH=; ELF_MACHINE= ;; +esac + +elf_matches_arch() { + command -v od >/dev/null 2>&1 || return 0 + [ "$(od -An -tx1 -j4 -N1 "$1" 2>/dev/null | tr -d ' \n')" = 02 ] || return 1 + [ -z "$ELF_MACHINE" ] || [ "$(od -An -tx1 -j18 -N1 "$1" 2>/dev/null | tr -d ' \n')" = "$ELF_MACHINE" ] +} + +host_has_library() { + for ldconfig in ldconfig /sbin/ldconfig /usr/sbin/ldconfig; do + if command -v "$ldconfig" >/dev/null 2>&1; then + if [ -n "$LDCONFIG_ARCH" ]; then + "$ldconfig" -p 2>/dev/null | grep -q "[[:space:]]$1 (libc6,$LDCONFIG_ARCH" && return 0 + fi + break + fi + done + for dir in ${MULTIARCH:+/usr/lib/$MULTIARCH /lib/$MULTIARCH} /usr/lib64 /lib64 /usr/lib /lib; do + [ -e "$dir/$1" ] && elf_matches_arch "$dir/$1" && return 0 + done + return 1 +} + +# libxkbcommon-x11 must match the libxkbcommon it is paired with. Prefer the +# host's pair; only fall back to the bundled, matched pair when the host has no +# libxkbcommon-x11 at all. +if ! host_has_library libxkbcommon-x11.so.0; then + export LD_LIBRARY_PATH="$HERE/usr/lib/xkb-fallback:$LD_LIBRARY_PATH" +fi + # AppImages cannot install a path-based AppArmor userns profile. Fall back only # when the host blocks the user namespaces required by Chromium's sandbox. if ! command -v unshare >/dev/null 2>&1 || ! unshare --user --map-root-user true >/dev/null 2>&1; then diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 270ebf2b..ff2621b8 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3662,7 +3662,7 @@ dependencies = [ [[package]] name = "querymt-desktop" -version = "0.1.9" +version = "0.1.10" dependencies = [ "cef", "dirs 7.0.0", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 4113b6e8..e80bbfcf 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "querymt-desktop" -version = "0.1.9" +version = "0.1.10" description = "QueryMT Desktop" authors = ["QueryMT"] edition = "2021" diff --git a/src-tauri/icons/128x128.png b/src-tauri/icons/128x128.png index 87ee11d6..83470d8c 100644 Binary files a/src-tauri/icons/128x128.png and b/src-tauri/icons/128x128.png differ diff --git a/src-tauri/icons/128x128@2x.png b/src-tauri/icons/128x128@2x.png index f26f6cf8..2baee9d5 100644 Binary files a/src-tauri/icons/128x128@2x.png and b/src-tauri/icons/128x128@2x.png differ diff --git a/src-tauri/icons/32x32.png b/src-tauri/icons/32x32.png index be5a27bd..17c35500 100644 Binary files a/src-tauri/icons/32x32.png and b/src-tauri/icons/32x32.png differ diff --git a/src-tauri/icons/64x64.png b/src-tauri/icons/64x64.png index a68b2b48..92eb219b 100644 Binary files a/src-tauri/icons/64x64.png and b/src-tauri/icons/64x64.png differ diff --git a/src-tauri/icons/icon.icns b/src-tauri/icons/icon.icns index 94eb5a18..2eb6a868 100644 Binary files a/src-tauri/icons/icon.icns and b/src-tauri/icons/icon.icns differ diff --git a/src-tauri/icons/icon.ico b/src-tauri/icons/icon.ico index b9d71cae..236c6a9d 100644 Binary files a/src-tauri/icons/icon.ico and b/src-tauri/icons/icon.ico differ diff --git a/src-tauri/icons/icon.png b/src-tauri/icons/icon.png index 015082b6..9f84c8ec 100644 Binary files a/src-tauri/icons/icon.png and b/src-tauri/icons/icon.png differ diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 1209d448..353e8a53 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "QueryMT Desktop", - "version": "0.1.9", + "version": "0.1.10", "identifier": "com.querymt.desktop", "build": { "beforeDevCommand": "npm run dev",