forked from AppImage/AppImageKit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
desktopintegration
267 lines (230 loc) · 8.7 KB
/
desktopintegration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
#!/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 use it, then place this in usr/bin/$APPNAME.wrapper
# and set it as the Exec= line of the .desktop file in the AppImage.
#
# For example, to install the appropriate icons for Scribus,
# put them into the AppDir at the following locations:
#
# ./usr/share/icons/default/128x128/apps/scribus.png
# ./usr/share/icons/default/128x128/mimetypes/application-vnd.scribus.png
#
# Note that the filename application-vnd.scribus.png is derived from
# and must be match MimeType=application/vnd.scribus; in scribus.desktop
# (with "/" characters replaced by "-").
#
# Then, change Exec=scribus to Exec=scribus.wrapper and place the script
# below in usr/bin/scribus.wrapper and make it executable.
# When you run AppRun, then AppRun runs the wrapper script below
# which in turn will run the main application.
#
# TODO:
# Handle multiple versions of the same AppImage?
# Handle removed AppImages? Currently we are just setting TryExec=
# See http://specifications.freedesktop.org/thumbnail-spec/thumbnail-spec-latest.html#DELETE
# Possibly move this to the C runtime that is part of every AppImage?
# 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
find-up () {
path="$(dirname "$(readlink -f "${THIS}")")"
while [[ "$path" != "" && ! -e "$path/$1" ]]; do
path=${path%/*}
done
# echo "$path"
}
if [ -z $APPDIR ] ; then
# Find the AppDir. It is the directory that contains AppRun.
# This assumes that this script resides inside the AppDir or a subdirectory.
# If this script is run inside an AppImage, then the AppImage runtime
# likely has already set $APPDIR
APPDIR=$(find-up "AppRun")
fi
# echo "$APPDIR"
FILENAME="$(readlink -f "${THIS}")"
# echo "$FILENAME"
if [[ "$FILENAME" != *.wrapper ]] ; then
echo "${THIS} is not named correctly. It should be named \$Exec.wrapper"
exit 0
fi
BIN=$(echo "$FILENAME" | sed -e 's|.wrapper||g')
if [[ ! -f "$BIN" ]] ; then
echo "$BIN not found"
exit 0
fi
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 "Disk auswerfen?" --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
}
DIRNAME=$(dirname $FILENAME)
# 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
# Construct path to the icon according to
# http://specifications.freedesktop.org/thumbnail-spec/thumbnail-spec-latest.html
ABS_APPIMAGE=$(readlink -e "$APPIMAGE")
ICONURL="file://$ABS_APPIMAGE"
MD5=$(echo -n $ICONURL | md5sum | cut -c -32)
ICONFILE="$HOME/.cache/thumbnails/normal/$MD5.png"
if [ ! -f "$ICONFILE" ] ; then
echo "$ICONFILE is missing. Probably not running ${THIS} from within an AppImage."
echo "Hence falling back to using .DirIcon"
ICONFILE="$APPDIR/.DirIcon"
fi
# $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
echo "\$XDG_DATA_DIRS is missing. Please run ${THIS} from within an AppImage."
exit 0
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" "Should a desktop file for $APPIMAGE be installed?"
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" \
--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