Skip to content
Snippets Groups Projects
appimage-desktopintegration 6.77 KiB
Newer Older
  • Learn to ignore specific revisions
  • probonopd's avatar
    probonopd committed
    #!/bin/bash
    
    # The purpose of this script is to provide lightweight desktop integration
    # into the host system without special help from the host system.
    # If you want to have fuller and automatic desktop integration, you might
    # consider to use the optional appimaged daemon instead.
    
    # Exit on errors
    set -e
    
    # Be verbose if $DEBUG=1 is set
    if [ ! -z "$DEBUG" ] ; then
      env
      set -x
    fi
    
    THIS="$0"
    args=("$@") # http://stackoverflow.com/questions/3190818/
    NUMBER_OF_ARGS="$#"
    
    # Please do not change $VENDORPREFIX as it will allow for desktop files
    # belonging to AppImages to be recognized by future AppImageKit components
    # such as desktop integration daemons
    VENDORPREFIX=appimagekit
    
    APPDIR="$(dirname "$(readlink -f "${THIS}")")"
    
    BIN="${APPDIR}/xdgurl"
    
    probonopd's avatar
    probonopd committed
    export PATH="${APPDIR}/usr/bin:$PATH"
    
    probonopd's avatar
    probonopd committed
    
    trap atexit EXIT
    
    # Note that the following handles 0, 1 or more arguments (file paths)
    # which can include blanks but uses a bashism; can the same be achieved
    # in POSIX-shell? (FIXME)
    # http://stackoverflow.com/questions/3190818
    atexit()
    {
    if [ $NUMBER_OF_ARGS -eq 0 ] ; then
      exec "${BIN}"
    else
      exec "${BIN}" "${args[@]}"
    fi
    }
    
    error()
    {
      if [ -x /usr/bin/zenity ] ; then
        LD_LIBRARY_PATH="" zenity --error --text "${1}" 2>/dev/null
      elif [ -x /usr/bin/kdialog ] ; then
        LD_LIBRARY_PATH="" kdialog --msgbox "${1}" 2>/dev/null
      elif [ -x /usr/bin/Xdialog ] ; then
        LD_LIBRARY_PATH="" Xdialog --msgbox "${1}" 2>/dev/null
      else
        echo "${1}"
      fi
      exit 1
    }
    
    yesno()
    {
      TITLE=$1
      TEXT=$2
      if [ -x /usr/bin/zenity ] ; then
        LD_LIBRARY_PATH="" zenity --question --title="$TITLE" --text="$TEXT" 2>/dev/null || exit 0
      elif [ -x /usr/bin/kdialog ] ; then
        LD_LIBRARY_PATH="" kdialog --caption "" --title "$TITLE" -yesno "$TEXT" || exit 0
      elif [ -x /usr/bin/Xdialog ] ; then
        LD_LIBRARY_PATH="" Xdialog --title "$TITLE" --clear --yesno "$TEXT" 10 80 || exit 0
      else
        echo "zenity, kdialog, Xdialog missing. Skipping ${THIS}."
        exit 0
      fi
    }
    
    check_prevent()
    {
      FILE=$1
      if [ -e "$FILE" ] ; then
        exit 0
      fi
    }
    
    # Exit immediately of one of these files is present
    # (e.g., because the desktop environment wants to handle desktop integration itself)
    check_prevent "$HOME/.local/share/$VENDORPREFIX/no_desktopintegration"
    check_prevent "/usr/share/$VENDORPREFIX/no_desktopintegration"
    check_prevent "/etc/$VENDORPREFIX/no_desktopintegration"
    
    # Exit immediately if appimaged is running
    pidof appimaged 2>/dev/null && exit 0
    
    # Exit immediately if $DESKTOPINTEGRATION is not empty
    if [ ! -z "$DESKTOPINTEGRATION" ] ; then
      exit 0
    fi
    
    check_dep()
    {
      DEP=$1
      if [ -z $(which $DEP) ] ; then
        echo "$DEP is missing. Skipping ${THIS}."
        exit 0
      fi
    }
    
    
    probonopd's avatar
    probonopd committed
    DIRNAME="$APPDIR"
    
    probonopd's avatar
    probonopd committed
    
    # Check whether dependencies are present in base system (we do not bundle these)
    # http://cgit.freedesktop.org/xdg/desktop-file-utils/
    check_dep desktop-file-validate
    check_dep update-desktop-database
    check_dep desktop-file-install
    check_dep xdg-icon-resource
    check_dep xdg-mime
    check_dep xdg-desktop-menu
    
    DESKTOPFILE=$(find "$APPDIR" -maxdepth 1 -name "*.desktop" | head -n 1)
    # echo "$DESKTOPFILE"
    DESKTOPFILE_NAME=$(basename "${DESKTOPFILE}")
    
    if [ ! -f "$DESKTOPFILE" ] ; then
      echo "Desktop file is missing. Please run ${THIS} from within an AppImage."
      exit 0
    fi
    
    if [ -z "$APPIMAGE" ] ; then
      APPIMAGE="$APPDIR/AppRun"
      # Not running from within an AppImage; hence using the AppRun for Exec=
    fi
    
    ABS_APPIMAGE=$(readlink -e "$APPIMAGE")
    
    probonopd's avatar
    probonopd committed
    ICONFILE="$APPDIR/.DirIcon"
    
    probonopd's avatar
    probonopd committed
    
    # $XDG_DATA_DIRS contains the default paths /usr/local/share:/usr/share
    # desktop file has to be installed in an applications subdirectory
    # of one of the $XDG_DATA_DIRS components
    if [ -z "$XDG_DATA_DIRS" ] ; then
      XDG_DATA_DIRS=/usr/local/share:/usr/share
    fi
    
    # Determine where the desktop file should be installed
    if [[ $EUID -ne 0 ]]; then
       DESTINATION_DIR_DESKTOP="$HOME/.local/share/applications"
       SYSTEM_WIDE=""
    else
       # TODO: Check $XDG_DATA_DIRS
       DESTINATION_DIR_DESKTOP="/usr/local/share/applications"
       SYSTEM_WIDE="--mode system" # for xdg-mime and xdg-icon-resource
    fi
    
    # Check if the desktop file is already there
    # and if so, whether it points to the same AppImage
    if [ -e "$DESTINATION_DIR_DESKTOP/$VENDORPREFIX-$DESKTOPFILE_NAME" ] ; then
      # echo "$DESTINATION_DIR_DESKTOP/$VENDORPREFIX-$DESKTOPFILE_NAME already there"
      EXEC=$(grep "^Exec=" "$DESTINATION_DIR_DESKTOP/$VENDORPREFIX-$DESKTOPFILE_NAME" | head -n 1 | cut -d " " -f 1)
      # echo $EXEC
      if [ "Exec=\"$APPIMAGE\"" == "$EXEC" ] ; then
        exit 0
      fi
    fi
    
    # We ask the user only if we have found no reason to skip until here
    if [ -z "$SKIP" ] ; then
      yesno "Install" "Would you like to integrate $APPIMAGE with your system?\n\nThis will add it to your applications menu and install icons.\nIf you don't do this you can still launch the application by double-clicking on the AppImage."
    fi
    
    APP=$(echo "$DESKTOPFILE_NAME" | sed -e 's/.desktop//g')
    
    # If the user has agreed, rewrite and install the desktop file, and the MIME information
    if [ -z "$SKIP" ] ; then
      # desktop-file-install is supposed to install .desktop files to the user's
      # applications directory when run as a non-root user,
      # and to /usr/share/applications if run as root
      # but that does not really work for me...
      #
      # For Exec we must use quotes
      # For TryExec quotes is not supported, so, space must be replaced to \s
      # https://askubuntu.com/questions/175404/how-to-add-space-to-exec-path-in-a-thumbnailer-descrption/175567
      desktop-file-install --rebuild-mime-info-cache \
    
        --vendor=$VENDORPREFIX --set-key=Exec --set-value="\"${APPIMAGE}\" %u" \
    
    probonopd's avatar
    probonopd committed
        --set-key=X-AppImage-Comment --set-value="Generated by ${THIS}" \
        --set-icon="$ICONFILE" --set-key=TryExec --set-value=${APPIMAGE// /\\s} "$DESKTOPFILE" \
        --dir "$DESTINATION_DIR_DESKTOP"
      chmod a+x "$DESTINATION_DIR_DESKTOP/"*
      RESOURCE_NAME=$(echo "$VENDORPREFIX-$DESKTOPFILE_NAME" | sed -e 's/.desktop//g')
      # echo $RESOURCE_NAME
    
      # Install the icon files for the application; TODO: scalable
      ICONS=$(find "${APPDIR}/usr/share/icons/" -wholename "*/apps/${APP}.png" 2>/dev/null || true)
      for ICON in $ICONS ; do
        ICON_SIZE=$(echo "${ICON}" | rev | cut -d "/" -f 3 | rev | cut -d "x" -f 1)
        xdg-icon-resource install --context apps --size ${ICON_SIZE} "${ICON}" "${RESOURCE_NAME}"
      done
    
      # Install mime type
      find "${APPDIR}/usr/share/mime/" -type f -name *xml -exec xdg-mime install $SYSTEM_WIDE --novendor {} \; 2>/dev/null || true
    
      # Install the icon files for the mime type; TODO: scalable
      ICONS=$(find "${APPDIR}/usr/share/icons/" -wholename "*/mimetypes/*.png" 2>/dev/null || true)
      for ICON in $ICONS ; do
        ICON_SIZE=$(echo "${ICON}" | rev | cut -d "/" -f 3 | rev | cut -d "x" -f 1)
        xdg-icon-resource install --context mimetypes --size ${ICON_SIZE} "${ICON}" $(basename $ICON | sed -e 's/.png//g')
      done
    
      xdg-desktop-menu forceupdate
      gtk-update-icon-cache # for MIME
    fi