diff --git a/snap/gui/heroic.desktop b/snap/gui/heroic.desktop new file mode 100644 index 0000000000..c874ce97f1 --- /dev/null +++ b/snap/gui/heroic.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Name=Heroic Games Launcher +Exec=heroic %u +Terminal=false +Type=Application +Icon=${SNAP}/meta/gui/heroic.png +StartupWMClass=Heroic +Comment=An Open Source GOG and Epic Games launcher +Comment[de]=Ein Open Source Spielelauncher for GOG und Epic Games +MimeType=x-scheme-handler/heroic; +Categories=Game; diff --git a/snap/hooks/configure b/snap/hooks/configure new file mode 100644 index 0000000000..5fbd8681ec --- /dev/null +++ b/snap/hooks/configure @@ -0,0 +1,45 @@ +#!/bin/sh + +# https://github.com/canonical/steam-snap/issues/19#issuecomment-1171984524 +# https://gist.github.com/jhenstridge/425c769949d034033f3d5d90acc2f181 + +set -e + +mkdir -p $SNAP_DATA/etc + +snap_ld_so_conf=$SNAP_DATA/etc/snap-ld.so.conf +snap_ld_so_cache=$SNAP_DATA/etc/snap-ld.so.cache +real_ld_so_cache=$SNAP_DATA/etc/ld.so.cache + +RUNTIME=$SNAP/gnome-platform + +cat > "$snap_ld_so_conf" < $real_ld_so_cache diff --git a/snap/local/src/desktop-launch b/snap/local/src/desktop-launch new file mode 100755 index 0000000000..204d239e45 --- /dev/null +++ b/snap/local/src/desktop-launch @@ -0,0 +1,356 @@ +#!/bin/bash +################# +# Launcher init # +################# + +# shellcheck disable=SC2034 +START=$(date +%s.%N) + +if ! snapctl is-connected "gaming-mesa"; then + echo "ERROR: not connected to the gaming-mesa content interface." + echo "To connect:" + echo "sudo snap connect heroic:gaming-mesa gaming-graphics-core22" + exit 1 +fi + +# ensure_dir_exists calls `mkdir -p` if the given path is not a directory. +# This speeds up execution time by avoiding unnecessary calls to mkdir. +# +# Usage: ensure_dir_exists []... +# +function ensure_dir_exists() { + [ -d "$1" ] || mkdir -p "$@" +} + +declare -A PIDS +function async_exec() { + "$@" & + PIDS[$!]=$* +} +function wait_for_async_execs() { + for pid in "${!PIDS[@]}" + do + wait "$pid" && continue || echo "ERROR: ${PIDS[$pid]} exited abnormally with status $?" + done +} + +# shellcheck source=/dev/null +source "$SNAP_USER_DATA/.last_revision" 2>/dev/null || true +if [ "$SNAP_DESKTOP_LAST_REVISION" = "$SNAP_REVISION" ]; then + needs_update=false +else + needs_update=true +fi + +# Set $REALHOME to the users real home directory +REALHOME=$(getent passwd $UID | cut -d ':' -f 6) + +export SNAP_DESKTOP_RUNTIME=$SNAP + +# Set config folder to local path +export XDG_CONFIG_HOME="$SNAP_USER_COMMON/.config" +ensure_dir_exists "$XDG_CONFIG_HOME" +chmod 700 "$XDG_CONFIG_HOME" + +# If the user has modified their user-dirs settings, force an update +if [[ -f "$XDG_CONFIG_HOME/user-dirs.dirs.md5sum" ]]; then + if [[ "$(md5sum < "$REALHOME/.config/user-dirs.dirs")" != "$(cat "$XDG_CONFIG_HOME/user-dirs.dirs.md5sum")" || + ( -f "$XDG_CONFIG_HOME/user-dirs.locale.md5sum" && + "$(md5sum < "$REALHOME/.config/user-dirs.locale")" != "$(cat "$XDG_CONFIG_HOME/user-dirs.locale.md5sum")" ) ]]; then + needs_update=true + fi +else + # shellcheck disable=SC2034 + needs_update=true +fi + +# If the user has saves in the old $SNAP_USER_DATA/.config, move them +# to $SNAP_USER_COMMON/.config +if [[ -d $SNAP_USER_DATA/.config ]]; then + mv -n $SNAP_USER_DATA/.config/* $XDG_CONFIG_HOME + rm -r $SNAP_USER_DATA/.config +fi + +if [ "$SNAP_ARCH" = "amd64" ]; then + ARCH="x86_64-linux-gnu" +elif [ "$SNAP_ARCH" = "armhf" ]; then + ARCH="arm-linux-gnueabihf" +elif [ "$SNAP_ARCH" = "arm64" ]; then + ARCH="aarch64-linux-gnu" +elif [ "$SNAP_ARCH" = "ppc64el" ]; then + ARCH="powerpc64le-linux-gnu" +else + ARCH="$SNAP_ARCH-linux-gnu" +fi + +# Force i386 +export ARCH="i386-linux-gnu" +export SNAP_LAUNCHER_ARCH_TRIPLET="$ARCH" + +############################################### +# Launcher common exports for any desktop app # +############################################### + +# Note: We avoid using `eval` because we don't want to expand variable names +# in paths. For example: LD_LIBRARY_PATH paths might contain `$LIB`. +function prepend_dir() { + local -n var="$1" + local dir="$2" + # We can't check if the dir exists when the dir contains variables + if [[ "$dir" == *"\$"* || -d "$dir" ]]; then + export "${!var}=${dir}${var:+:$var}" + fi +} + +function append_dir() { + local -n var="$1" + local dir="$2" + # We can't check if the dir exists when the dir contains variables + if [[ "$dir" == *"\$"* || -d "$dir" ]]; then + export "${!var}=${var:+$var:}${dir}" + fi +} + + +function strip_unreachable_dirs() { + local -n var=$1 + local dirs="${var}" + + tmp="" + local IFS=: + for d in $dirs; do + # Just checking existence and the `x` bit isn't enough + # we need to see if we can actually `ls` it because of apparmor + # quirks + ls $d > /dev/null 2>&1 + if [[ $? -eq 0 ]]; then + append_dir tmp "$d" + else + echo "INFO: filtering $d out of ${!var} because it is unreachable" + fi + + done + + export "${!var}=${tmp}" + unset tmp +} + +function is_subpath() { + dir="$(realpath "$1")" + parent="$(realpath "$2")" + [ "${dir##$parent/}" != "$dir" ] && return 0 || return 1 +} + +append_dir PATH "$SNAP_DESKTOP_RUNTIME/usr/bin" + +# XKB config +export XKB_CONFIG_ROOT="$SNAP_DESKTOP_RUNTIME/usr/share/X11/xkb" + +# Give XOpenIM a chance to locate locale data. +# This is required for text input to work in SDL2 games. +export XLOCALEDIR="$SNAP_DESKTOP_RUNTIME/usr/share/X11/locale" + +# Set XCursors path +export XCURSOR_PATH="$SNAP_DESKTOP_RUNTIME/usr/share/icons" +prepend_dir XCURSOR_PATH "$SNAP/share/icons" + +# Mesa Libs for OpenGL support +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/mesa" +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/mesa-egl" +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/x86_64-linux-gnu/mesa" +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/x86_64-linux-gnu/mesa-egl" +# append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/$ARCH/mesa" +# append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/$ARCH/mesa-egl" +# append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/x86_64-linux-gnu/mesa" +# append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/x86_64-linux-gnu/mesa-egl" + +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/$ARCH" +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/x86_64-linux-gnu" + +# Tell libGL and libva where to find the drivers +export LIBGL_DRIVERS_PATH="$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/dri" +append_dir LIBGL_DRIVERS_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/x86_64-linux-gnu/dri" +append_dir LIBGL_DRIVERS_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/$ARCH/dri" +append_dir LIBGL_DRIVERS_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/x86_64-linux-gnu/dri" +append_dir LIBGL_DRIVERS_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/i386-linux-gnu/dri" +append_dir LD_LIBRARY_PATH "$LIBGL_DRIVERS_PATH" + +append_dir LIBVA_DRIVERS_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/dri" +append_dir LIBVA_DRIVERS_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/x86_64-linux-gnu/dri" +append_dir LIBVA_DRIVERS_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/$ARCH/dri" +append_dir LIBVA_DRIVERS_PATH "$SNAP_DESKTOP_RUNTIME/graphics/usr/lib/x86_64-linux-gnu/dri" + +# Set where the VDPAU drivers are located +export VDPAU_DRIVER_PATH="/usr/lib/$ARCH/vdpau/" +if [ -e "/var/lib/snapd/lib/gl/vdpau/libvdpau_nvidia.so" ]; then + export VDPAU_DRIVER_PATH="/var/lib/snapd/lib/gl/vdpau" + # Prevent picking VA-API (Intel/AMD) over NVIDIA VDPAU; on PRIME systems for example + unset LIBVA_DRIVERS_PATH +fi + +# Export Vulkan ICD filename paths +export VK_ICD_FILENAMES="/var/lib/snapd/lib/vulkan/icd.d/nvidia_icd.json:$SNAP/graphics/usr/share/vulkan/icd.d/radeon_icd.x86_64.json:$SNAP/graphics/usr/share/vulkan/icd.d/radeon_icd.i686.json:$SNAP/graphics/usr/share/vulkan/icd.d/intel_icd.x86_64.json:$SNAP/graphics/usr/share/vulkan/icd.d/intel_icd.i686.json" + +# Workaround in snapd for proprietary nVidia drivers mounts the drivers in +# /var/lib/snapd/lib/gl that needs to be in LD_LIBRARY_PATH +# Without that OpenGL using apps do not work with the nVidia drivers. +# Ref.: https://bugs.launchpad.net/snappy/+bug/1588192 +append_dir LD_LIBRARY_PATH "/var/lib/snapd/lib/gl" +append_dir LD_LIBRARY_PATH "/var/lib/snapd/lib/gl/vdpau" + +# By sheer luck, this was working in the past, but we need this explicitly +append_dir LD_LIBRARY_PATH "/var/lib/snapd/lib/gl32" +append_dir LD_LIBRARY_PATH "/var/lib/snapd/lib/gl32/vdpau" + +# Unity7 export (workaround for https://launchpad.net/bugs/1638405) +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/libunity" + +# Pulseaudio export +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/pulseaudio" + +# EGL vendor files on glvnd enabled systems +prepend_dir __EGL_VENDOR_LIBRARY_DIRS "/var/lib/snapd/lib/glvnd/egl_vendor.d" +append_dir __EGL_VENDOR_LIBRARY_DIRS "$SNAP_DESKTOP_RUNTIME/usr/share/glvnd/egl_vendor.d" + +# Tell GStreamer where to find its plugins +export GST_PLUGIN_PATH="$SNAP/usr/lib/$ARCH/gstreamer-1.0" +export GST_PLUGIN_SYSTEM_PATH="$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/gstreamer-1.0" +# gst plugin scanner doesn't install in the correct path: https://github.com/ubuntu/snapcraft-desktop-helpers/issues/43 +export GST_PLUGIN_SCANNER="$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner" + +# XDG Config +prepend_dir XDG_CONFIG_DIRS "$SNAP_DESKTOP_RUNTIME/etc/xdg" +prepend_dir XDG_CONFIG_DIRS "$SNAP/etc/xdg" + +# Define snaps' own data dir +prepend_dir XDG_DATA_DIRS "$SNAP_DESKTOP_RUNTIME/usr/share" +prepend_dir XDG_DATA_DIRS "$SNAP/usr/share" +prepend_dir XDG_DATA_DIRS "$SNAP/share" +prepend_dir XDG_DATA_DIRS "$SNAP/data-dir" +prepend_dir XDG_DATA_DIRS "$SNAP_USER_DATA" +append_dir XDG_DATA_DIRS "$SNAP/graphics/usr/share" + +# Set XDG_DATA_HOME to local path +# heroic snap +export XDG_DATA_HOME="$SNAP_USER_COMMON/.local/share" +ensure_dir_exists "$XDG_DATA_HOME" + +# Workaround for GLib < 2.53.2 not searching for schemas in $XDG_DATA_HOME: +# https://bugzilla.gnome.org/show_bug.cgi?id=741335 +prepend_dir XDG_DATA_DIRS "$XDG_DATA_HOME" + +# Set cache folder to local path +export XDG_CACHE_HOME="$SNAP_USER_COMMON/.cache" +if [[ -d "$SNAP_USER_DATA/.cache" && ! -e "$XDG_CACHE_HOME" ]]; then + # the .cache directory used to be stored under $SNAP_USER_DATA, migrate it + mv "$SNAP_USER_DATA/.cache" "$SNAP_USER_COMMON/" +fi +ensure_dir_exists "$XDG_CACHE_HOME" + +# Create $XDG_RUNTIME_DIR if not exists (to be removed when LP: #1656340 is fixed) +# shellcheck disable=SC2174 +ensure_dir_exists "$XDG_RUNTIME_DIR" -m 700 + +# Ensure the app finds locale definitions (requires locales-all to be installed) +append_dir LOCPATH "$SNAP_DESKTOP_RUNTIME/usr/lib/locale" + +# If detect wayland server socket, then set environment so applications prefer +# wayland, and setup compat symlink (until we use user mounts. Remember, +# XDG_RUNTIME_DIR is /run/user//snap.$SNAP so look in the parent directory +# for the socket. For details: +# https://forum.snapcraft.io/t/wayland-dconf-and-xdg-runtime-dir/186/10 +# Applications that don't support wayland natively may define DISABLE_WAYLAND +# (to any non-empty value) to skip that logic entirely. +wayland_available=false +if [[ -n "$XDG_RUNTIME_DIR" && -z "$DISABLE_WAYLAND" ]]; then + wdisplay="wayland-0" + if [ -n "$WAYLAND_DISPLAY" ]; then + wdisplay="$WAYLAND_DISPLAY" + fi + wayland_sockpath="$XDG_RUNTIME_DIR/../$wdisplay" + wayland_snappath="$XDG_RUNTIME_DIR/$wdisplay" + if [ -S "$wayland_sockpath" ]; then + # if running under wayland, use it + #export WAYLAND_DEBUG=1 + # shellcheck disable=SC2034 + wayland_available=true + # create the compat symlink for now + if [ ! -e "$wayland_snappath" ]; then + ln -s "$wayland_sockpath" "$wayland_snappath" + fi + fi +fi + +# Make PulseAudio socket available inside the snap-specific $XDG_RUNTIME_DIR +if [ -n "$XDG_RUNTIME_DIR" ]; then + pulsenative="pulse/native" + pulseaudio_sockpath="$XDG_RUNTIME_DIR/../$pulsenative" + if [ -S "$pulseaudio_sockpath" ]; then + export PULSE_SERVER="unix:${pulseaudio_sockpath}" + fi +fi + +# Keep an array of data dirs, for looping through them +IFS=':' read -r -a data_dirs_array <<< "$XDG_DATA_DIRS" + +if [ "$needs_update" = true ]; then + rm -rf "$XDG_DATA_HOME"/{themes,.themes} +fi + +############################## +# GTK launcher specific part # +############################## + +# shellcheck disable=SC2154 +if [ "$wayland_available" = true ]; then + export GDK_BACKEND="wayland" + export CLUTTER_BACKEND="wayland" + # Does not hurt to specify this as well, just in case + export QT_QPA_PLATFORM=wayland-egl +fi +append_dir GTK_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/gtk-3.0" + +############################### +# Mark update and exec binary # +############################### + +# shellcheck disable=SC2154 +[ "$needs_update" = true ] && echo "SNAP_DESKTOP_LAST_REVISION=$SNAP_REVISION" > "$SNAP_USER_DATA/.last_revision" + +wait_for_async_execs + +if [ -n "$SNAP_DESKTOP_DEBUG" ]; then + echo "desktop-launch elapsed time: $(date +%s.%N --date="$START seconds ago")" + echo "Now running: exec $*" +fi + +# Fix default run command +# The default works on a system with only the Snap installed, but if they also +# have the deb then the default command will run the deb instead of the Snap. +find "$SNAP_USER_COMMON/.local/share/applications" -type f | while read -r file; do + sed -i "s/Exec=heroic/Exec=snap run heroic/" "$file" +done + +# Links game icons to host +find "$SNAP_USER_COMMON/.local/share/icons/hicolor" -type f -name "heroic_icon_*.png" | while read -r file; do + dest="${file/$SNAP_USER_COMMON/$REALHOME}" + ensure_dir_exists "$(dirname $dest)" + ln -sf "$file" "$dest" +done + +# Link .desktop files to host +ln -sf $SNAP_USER_COMMON/.local/share/applications/* $REALHOME/.local/share/applications/ + +strip_unreachable_dirs XDG_DATA_DIRS +strip_unreachable_dirs XDG_CONFIG_DIRS +strip_unreachable_dirs XDG_SPECIAL_DIRS + +# Even with libfuse, appimages need to be extracted to run. +# This is a workaround until we figure out something better, because it makes +# launching AppImage games way slower +# +# That said, they're really rare so it's not a big deal +export APPIMAGE_EXTRACT_AND_RUN=1 + +$SNAP/bin/nvidia32 & +"$@" diff --git a/snap/local/src/nvidia32 b/snap/local/src/nvidia32 new file mode 100755 index 0000000000..6f8b55145a --- /dev/null +++ b/snap/local/src/nvidia32 @@ -0,0 +1,171 @@ +#!/usr/bin/python3 + +import gi +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk, Gdk +import os +import argparse + +TITLE = "NVIDIA 32-bit Not Found" +TEXT = """32-bit NVIDIA driver files were not found on your host system. +It is recommended that you install them for the best experience. + +See https://github.com/canonical/steam-snap/wiki/FAQ#32-bit-driver for more information.""" +COMMAND = """sudo dpkg --add-architecture i386 +sudo apt update +sudo apt install libnvidia-gl-{}:i386""" + +DO_NOT_SHOW_PATH = os.path.expandvars("$SNAP_USER_COMMON/.nvidia32") + +def do_not_show_file(do_not_show: bool): + """Ok button press. + + `do_not_show`: whether the Do not show again checkbox is checked or not + """ + if do_not_show: + open(DO_NOT_SHOW_PATH, "a").close() + elif os.path.exists(DO_NOT_SHOW_PATH): + os.remove(DO_NOT_SHOW_PATH) + + +def nvidia_version(): + """Try to find NVIDIA driver version from modinfo. + + Returns a tuple of the full NVIDIA version triplet and NVIDIA major version. + """ + modinfo = os.popen( + "modinfo /usr/lib/modules/$(uname -r)/updates/dkms/nvidia.ko* 2> /dev/null" + " | grep -m 1 '^version:'" + " | sed 's/version:\s*//'" + ).read().splitlines() + modinfo = modinfo or os.popen( + "modinfo /usr/lib/modules/$(uname -r)/kernel/nvidia*/nvidia.ko* 2> /dev/null" + " | grep -m 1 '^version:'" + " | sed 's/version:\s*//'" + ).read().splitlines() + + if not modinfo: + return () + nvidia_version = modinfo[0].strip() + nvidia_version_major = nvidia_version.split(".")[0] + return (nvidia_version, nvidia_version_major) + + +def nvidia_missing(): + """Returns whether NVIDIA 32 is missing or not. + """ + version = nvidia_version() + if not version: + return False + + print(f"Found NVIDIA version: {version[0]}") + needs_32 = os.path.exists(f"/var/lib/snapd/hostfs/usr/lib/x86_64-linux-gnu/libnvidia-glcore.so.{version[0]}")\ + and not os.path.exists(f"/var/lib/snapd/hostfs/usr/lib/i386-linux-gnu/libnvidia-glcore.so.{version[0]}") + print(f"Need NVIDIA 32-bit: {needs_32}") + return needs_32 + + +class NvidiaWindow(Gtk.Window): + def __init__(self): + super().__init__() + self.set_resizable(False) + self.set_border_width(10) + self.set_position(Gtk.WindowPosition.CENTER) + self.set_keep_above(True) + + header = Gtk.HeaderBar(title=TITLE) + self.set_titlebar(header) + + self.grid = Gtk.Grid( + row_spacing=10, + column_spacing=10 + ) + self.add(self.grid) + + # main text + self.label = Gtk.Label() + self.label.set_markup(TEXT) + self.grid.attach(self.label, 0, 0, 2, 1) + + # run prompt + self.run_label = Gtk.Label( + margin_top=20, + halign=Gtk.Align.START + ) + self.run_label.set_markup("To install, run:") + self.grid.attach_next_to(self.run_label, self.label, Gtk.PositionType.BOTTOM, 1, 1) + + # copy button + self.copy_btn = Gtk.Button.new_from_icon_name("edit-copy-symbolic", Gtk.IconSize.MENU) + self.copy_btn.set_margin_top(20) + self.copy_btn.set_tooltip_text("Copy") + self.copy_btn.connect("clicked", lambda x: self.button_copy()) + self.copy_btn.set_halign(Gtk.Align.END) + self.grid.attach_next_to(self.copy_btn, self.run_label, Gtk.PositionType.RIGHT, 1, 1) + + # command text + self.nvidia_version = nvidia_version() + self.textview = Gtk.TextView( + editable=False, + monospace=True, + top_margin=5, + bottom_margin=5, + right_margin=10, + left_margin=10 + ) + command_text = COMMAND.format("") + if self.nvidia_version: command_text = COMMAND.format(self.nvidia_version[1]) + self.textview.get_buffer().set_text(command_text) + self.grid.attach_next_to(self.textview, self.run_label, Gtk.PositionType.BOTTOM, 2, 1) + + # Do not show again button + self.checkbox = Gtk.CheckButton( + label="Do not show again", + halign=Gtk.Align.END, + tooltip_markup="This window can always be shown again by running " + "$SNAP/bin/nvidia32 --reset in the Steam Snap shell." + ) + self.grid.attach_next_to(self.checkbox, self.textview, Gtk.PositionType.BOTTOM, 1, 1) + + # Ok button + self.btn = Gtk.Button(label="Ok") + self.btn.connect("clicked", lambda x: self.button_ok(self.checkbox.get_active())) + self.grid.attach_next_to(self.btn, self.checkbox, Gtk.PositionType.RIGHT, 1, 1) + + + def button_ok(self, toggled: bool): + do_not_show_file(toggled) + self.close() + + + def button_copy(self): + clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) + clipboard.set_text(COMMAND.format(self.nvidia_version[1]), -1) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--reset", + help="Show the dialog again if you selected 'Do not show again'", + action="store_true" + ) + parser.add_argument( + "--show", + help="Show the dialog regardless of conditions met", + action="store_true" + ) + args = parser.parse_args() + + if args.reset: + do_not_show_file(False) + + if args.show or (nvidia_missing() and not os.path.exists(DO_NOT_SHOW_PATH)): + win = NvidiaWindow() + win.connect("destroy", Gtk.main_quit) + win.show_all() + Gtk.main() + + +if __name__ == "__main__": + main() diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml new file mode 100644 index 0000000000..b4625e2bc4 --- /dev/null +++ b/snap/snapcraft.yaml @@ -0,0 +1,452 @@ +name: heroic +summary: An Open Source Launcher for GOG Amazon and Epic Games +description: | + Heroic is an Open Source Games Launcher. Right now it supports launching games from the Epic Games + Store using Legendary Amazon Games using Nile and GOG Games using our custom implementations Nile and gogdl. +adopt-info: heroic +icon: src/frontend/assets/heroic-icon.svg +grade: stable +confinement: strict +architectures: + - build-on: amd64 +base: core22 +compression: lzo +assumes: + - snapd2.62 + +lint: + # Snapcraft's `ldd` lint can't handle 32-bit things, + # So just make it quiet and also make builds a surprising amount faster + ignore: + - library: + - lib/i386-linux-gnu/** + - usr/lib/i386-linux-gnu/** + - lib32/** + - usr/lib32/** + +package-repositories: + - type: apt + components: [main] + suites: [jammy] + architectures: [amd64, i386] + key-id: 9FD3B784BC1C6FC31A8A0A1C1655A0AB68576280 + url: https://deb.nodesource.com/node_20.x + +layout: + /usr/share/zenity: + bind: $SNAP/usr/share/zenity + # https://discourse.ubuntu.com/t/the-graphics-core20-snap-interface/23000 + /usr/share/drirc.d: + bind: $SNAP/graphics/usr/share/drirc.d + /usr/share/glvnd/egl_vendor.d: + bind: $SNAP/graphics/usr/share/glvnd/egl_vendor.d + /usr/lib/x86_64-linux-gnu/alsa-lib: + bind: $SNAP/usr/lib/x86_64-linux-gnu/alsa-lib + /usr/share/alsa: + bind: $SNAP/usr/share/alsa + /usr/share/X11/xkb: + bind: $SNAP/usr/share/X11/xkb + /etc/ld.so.cache: + bind-file: $SNAP_DATA/etc/ld.so.cache + /etc/fonts: + bind: $SNAP/etc/fonts + +plugs: + gaming-mesa: + interface: content + target: $SNAP/graphics + default-provider: gaming-graphics-core22 + gtk-3-themes: + interface: content + target: $SNAP/share/themes + default-provider: gtk-common-themes + icon-themes: + interface: content + target: $SNAP/share/icons + default-provider: gtk-common-themes + sound-themes: + interface: content + target: $SNAP/share/sounds + default-provider: gtk-common-themes + dot-local-share-steam: + interface: personal-files + write: + - $HOME/.local/share/Steam + - $HOME/Steam + - $HOME/snap/steam/common/.steam + dot-local-share-applications: + interface: personal-files + write: + - $HOME/.local/share/applications + dot-local-share-icons: + interface: personal-files + write: + - $HOME/.local/share/icons + desktop: + mount-host-font-cache: false + shmem: + interface: shared-memory + private: true + +hooks: + configure: + plugs: + - opengl + +parts: + launcher: + after: [heroic] + plugin: nil + source: $CRAFT_PROJECT_DIR/snap/local/src + override-build: | + mkdir -p $CRAFT_PART_INSTALL/usr/bin + cp * $CRAFT_PART_INSTALL/usr/bin/ + stage-packages: + - python3-gi + - gir1.2-gtk-3.0 + stage: + - bin/* + - usr/lib/python3/dist-packages/* + - usr/share/mime/* + - usr/share/icons/* + - usr/lib/**/gtk-3.0* + - etc/gtk-3.0* + - usr/share/*/gir1.2-gtk-3.0* + - usr/**/libfontconfig* + - usr/**/cairo-1* + - usr/**/libatspi* + - usr/**/libavahi-client* + - usr/**/libavahi-common* + - usr/**/libcairo-gobject* + - usr/**/libcairo* + - usr/**/libcolord* + - usr/**/libcups* + - usr/**/libdatrie* + - usr/**/libdconf* + - usr/**/libdeflate* + - usr/**/libepoxy* + - usr/**/libfribidi* + - usr/**/*girepository* + - usr/**/libgraphite2* + - usr/**/libgtk-3* + - usr/**/libharfbuzz* + - usr/**/libjbig* + - usr/**/libjpeg* + - usr/**/liblcms2* + - usr/**/libpango-1* + - usr/**/libpangocairo-1* + - usr/**/libpangoft2-1* + - usr/**/libpangoxft-1* + - usr/**/libpixman-1* + - usr/**/libthai* + - usr/**/libtiff* + - usr/**/libwayland-cursor* + - usr/**/libwebp* + - usr/**/libxcb-render* + - usr/**/libxkbcommon* + prime: + - -etc/dconf + - -etc/gtk* + - -etc/init* + - -etc/ld* + - -etc/vulkan + - -etc/X11 + - -etc/xdg + + ninja: + after: [heroic] + plugin: nil + source: https://github.com/ninja-build/ninja.git + source-tag: 'v1.12.1' + override-build: | + rm -rf build + rm -f ninja + rm -f ninja_bootstrap + sed -i 's_^#!/usr/bin/env python$_#!/usr/bin/env python3_g' configure.py + ./configure.py --bootstrap + mv ninja ninja_bootstrap + rm -rf build + ./ninja_bootstrap + rm -f ninja_bootstrap + mkdir -p $CRAFT_PART_INSTALL/usr/bin + mv ninja $CRAFT_PART_INSTALL/usr/bin/ + build-packages: + - python3 + prime: + - -* + + meson-deps: + after: [ninja] + plugin: nil + source: https://github.com/mesonbuild/meson.git + source-tag: '1.4.1' + source-depth: 1 + override-build: | + python3 -m pip install . + mkdir -p $CRAFT_PART_INSTALL/usr/lib/python3/dist-packages + rm -rf $CRAFT_PART_INSTALL/usr/lib/python3/dist-packages/meson* + python3 -m pip install --target=$CRAFT_PART_INSTALL/usr . + mv $CRAFT_PART_INSTALL/usr/meson* $CRAFT_PART_INSTALL/usr/lib/python3/dist-packages/ + sed -i "s%^#!/usr/bin/python3$%#!/usr/bin/env python3%g" /usr/local/bin/meson + sed -i "s%^#!/usr/bin/python3$%#!/usr/bin/env python3%g" $CRAFT_PART_INSTALL/usr/bin/meson + build-packages: + - python3-pip + prime: + - -* + + mangohud: + after: [meson-deps] + source: https://github.com/flightlessmango/MangoHud.git + source-tag: 'v0.7.2' + source-depth: 1 + plugin: meson + organize: + snap/heroic/current/usr: usr + build-environment: + - PKG_CONFIG_PATH: /usr/lib/i386-linux-gnu/pkgconfig:/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/lib/pkgconfig + meson-parameters: + - --prefix=/usr + - --libdir=lib/i386-linux-gnu + - -Dappend_libdir_mangohud=false + build-packages: + - gcc + - gcc-multilib + - g++ + - g++-multilib + - glslang-dev + - glslang-tools + - libdbus-1-dev + - libgl-dev + - libglvnd-dev + - libx11-dev + - libxnvctrl-dev + - mesa-common-dev + - python3-mako + - libwayland-dev + - libxkbcommon-dev + # Fixes the $LIB being escaped for some reason + override-build: | + craftctl default + sed -i 's/\/usr\/\\\$LIB/\$SNAP\/usr\/lib\/x86_64-linux-gnu/' $CRAFT_PART_INSTALL/usr/bin/mangohud + + mangohud64: + after: [meson-deps, mangohud] + source: https://github.com/flightlessmango/MangoHud.git + source-tag: 'v0.7.2' + source-depth: 1 + plugin: meson + organize: + snap/heroic/current/usr: usr + meson-parameters: + - --prefix=/usr + - --libdir=lib/x86_64-linux-gnu + - -Dappend_libdir_mangohud=false + stage: + - -usr/bin/mangohud + - -usr/share/vulkan/implicit_layer.d/MangoHud.json + - -usr/share/vulkan/implicit_layer.d/MangoHud.x86_64.json + - -usr/share/vulkan/implicit_layer.d/libMangoApp.json + - -usr/share/doc/mangohud/MangoHud.conf.example + - -usr/share/man/man1/mangohud.1 + + gamemode: + after: [meson-deps] + source: https://github.com/FeralInteractive/gamemode.git + source-tag: '1.8.2' + source-depth: 1 + plugin: meson + organize: + snap/heroic/current/usr: usr + meson-parameters: + - --prefix=/usr + build-packages: + - libsystemd-dev + - pkg-config + - libdbus-1-dev + prime: + - usr/bin/gamemoderun + - usr/lib/*/libgamemode*.so.* + + heroic: + source: https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher.git + source-tag: 'v2.15.2' + source-depth: 1 + plugin: dump + build-packages: + - dpkg-dev + - nodejs + prime: + - -chrome-* + - -chrome_crashpad_handler + - -usr/share/doc + - -usr/share/man + - -usr/share/bug + - -usr/share/gdb + - -usr/share/emacs* + - -usr/share/lintian + - -usr/share/drirc.d + - -usr/share/vulkan + - -usr/share/Xsession.d + - -usr/lib/*/dri + - -usr/lib/*/vdpau + - -usr/lib/*/libvkd3d* + - -usr/lib/*/libvulkan* + - -usr/lib/*/libVk* + - -usr/lib/*/libLLVM* + override-build: | + set -eux + if [[ -n "${http_proxy:-}" ]]; then + export HTTP_PROXY="${http_proxy:-}" + export HTTPS_PROXY="${http_proxy:-}" + export ELECTRON_GET_USE_PROXY=1 + export GLOBAL_AGENT_HTTP_PROXY="${http_proxy:-}" + export GLOBAL_AGENT_HTTPS_PROXY="${http_proxy:-}" + fi + npm config set -g registry https://registry.npmjs.org/ + npm config set -g proxy "${http_proxy:-}" + npm config set -g https-proxy "${http_proxy:-}" + npm install -g pnpm + pnpm config set -g registry https://github.com/ + pnpm config set -g proxy "${http_proxy:-}" + pnpm config set -g https-proxy "${http_proxy:-}" + pnpm config set -g registry https://registry.npmjs.org/ + pnpm config set -g proxy "${http_proxy:-}" + pnpm config set -g https-proxy "${http_proxy:-}" + pnpm install + pnpm run download-helper-binaries + pnpm dist:linux --dir + cp -a dist/linux-unpacked/* $CRAFT_PART_INSTALL/ + + debs: + plugin: nil + stage-packages: + - libappindicator3-1 + - libgtk-3-0 + - libpangoxft-1.0-0 + - libsasl2-2 + - libasound2 + - libnspr4 + - libnss3 + - libcurl4 + - libxcb-dri3-0:amd64 + - libxcb-dri3-0:i386 + - libpci3 + - libvulkan1:i386 + - libvulkan1:amd64 + - libxml2:i386 + - libxml2:amd64 + - libicu70:i386 + - libicu70:amd64 + - zlib1g:i386 + - zlib1g:amd64 + - xdg-utils + - xdg-user-dirs + - xz-utils + - fontconfig-config + - fontconfig:i386 + - fontconfig:amd64 + - pciutils + - lsof + - usbutils # Allows finding controllers etc + - psmisc + - libfuse2:amd64 + - libfuse2:i386 + - libxss1:amd64 + - libxss1:i386 + - x11-xserver-utils + prime: + - -etc/dconf + - -etc/gtk* + - -etc/init* + - -etc/ld* + - -etc/vulkan + - -etc/X11 + - -etc/xdg + - -usr/bin/cpp* + - -usr/bin/X11 + - -usr/bin/browse + - -usr/bin/x86* + - -usr/bin/iceauth + - -usr/include + - -usr/lib/gcc + - -usr/lib/systemd + - -usr/lib/X11 + - -usr/sbin + - -usr/share/doc* + - -usr/share/man + - -usr/share/bug + - -usr/share/apport + - -usr/share/gcc + - -usr/share/lintian + - -usr/share/libthai + - -usr/share/pkgconfig + - -usr/share/themes + - -usr/libexec + + conditioning: + after: [heroic, debs] + plugin: nil + build-packages: + - shared-mime-info + - gtk-update-icon-cache + override-prime: | + set -eux + craftctl default + for dir in usr/share/icons/*; do + if [ -f "$dir/index.theme" ]; then + gtk-update-icon-cache --force "$dir" + fi + done + + cleanup: + after: [heroic, conditioning] + plugin: nil + build-snaps: + - gaming-graphics-core22/kisak-fresh/candidate + override-prime: | + set -eux + cd /snap/gaming-graphics-core22/current/usr/lib + find . -type f,l -exec rm -rf $CRAFT_PRIME/usr/lib/{} \; + cd /snap/gaming-graphics-core22/current/usr/share + find . -type f,l -exec rm -rf $CRAFT_PRIME/usr/share/{} \; + for snap in "core22"; do + cd "/snap/$snap/current" && find . -type f,l -exec rm -rf "$CRAFT_PRIME/{}" \; + done + +apps: + heroic: + command-chain: [bin/desktop-launch] + command: heroic --no-sandbox + environment: + HOME: $SNAP_USER_COMMON + #LIBGL_DEBUG: verbose + TMPDIR: $XDG_RUNTIME_DIR + ALWAYS_USE_PULSEAUDIO: 1 + PYTHONPATH: $SNAP/usr/lib/python3/dist-packages + GI_TYPELIB_PATH: $SNAP/usr/lib/x86_64-linux-gnu/girepository-1.0 + plugs: + - shmem + - desktop + - desktop-legacy + - wayland + - home + - x11 + - gsettings + - hardware-observe + - mount-observe + - system-observe + - joystick + - network + - network-bind + - opengl + - audio-playback + - audio-record + - screen-inhibit-control + - process-control + - bluez + - network-control + - fuse-support + - steam-support + - removable-media + - upower-observe + - uinput diff --git a/src/backend/utils/systeminfo/osInfo/linux.ts b/src/backend/utils/systeminfo/osInfo/linux.ts index fbc2ffaec3..231e4f3556 100644 --- a/src/backend/utils/systeminfo/osInfo/linux.ts +++ b/src/backend/utils/systeminfo/osInfo/linux.ts @@ -14,7 +14,11 @@ function stripQuotes(stringMaybeWithQuotes: string): string { async function osInfo_linux(): Promise<{ name: string; version?: string }> { let os_release_path: string | null = null - for (const potPath of ['/run/host/os-release', '/etc/os-release']) { + for (const potPath of [ + '/run/host/os-release', + '/var/lib/snapd/hostfs/etc/os-release', + '/etc/os-release' + ]) { try { await stat(potPath) os_release_path = potPath