I would strongly recommend that this be done instead with xdg-utils: http://portland.freedesktop.org/wiki/XdgUtils
That will allow us to avoid the pain of maintaining our own implementation, and allow distro vendors to make their distro work with Wine just by supplying a working version of xdg-utils. The trick is whether or not we can persuade Alexandre and/or all of the Wine packagers to include xdg-utils by default in distributions. Cheers, Jeremy Vitaliy Margolen wrote: > Change Log: > wineshelllink: Use FreeDesktop standard to create Wine menu structure. > > The major changes include: > - Use WM independent paths for all generated files. > - Dynamically build .menu and .directory files to create menu structure. > - Store icons in local icon store using their "cryptic" names to avoid > conflicts. > - Number of other changes required for compatibility. > Note: .desktop links are still stored in a directory structure representing > Start Menu. This is done for possible future expansion. > > This new approach should work with KDE, Gnome and other XDG compliant > managers. > I have verified this with recent versions of KDE and Gnome on several distros. > > However there are might be some problems with some custom changes some distros > might have. As an example SuSE has special feature that doesn't work right: > https://bugzilla.novell.com/show_bug.cgi?id=188110 > > The question of removing these links after programs have been uninstalled > still open. > There are number of possible ways to solve it. The simplest would be > symlinking > directories containing .desktop files. However that might brake whole menu > structure. > --- > tools/wineshelllink | 258 ++++++++++++++++++++++---------------------------- > 1 files changed, 114 insertions(+), 144 deletions(-) > > > ------------------------------------------------------------------------ > > diff --git a/tools/wineshelllink b/tools/wineshelllink > index db65efa..5d91afc 100755 > --- a/tools/wineshelllink > +++ b/tools/wineshelllink > @@ -4,6 +4,7 @@ > # This is used by the IShellLink interface > # > # Copyright 2000 Alexandre Julliard > +# Copyright 2006 Vitaliy Margolen > # > # This library is free software; you can redistribute it and/or > # modify it under the terms of the GNU Lesser General Public > @@ -22,8 +23,7 @@ > > # Note that the link is a relative unix-style path name. Since the / > character > # is not valid in Windows filenames it is an adequate separator to show the > -# menu structure. (This program may need to split the menu structure out for > -# implementing xdg-style menus) > +# menu structure. > > mode="" > args="" > @@ -82,176 +82,146 @@ if [ -z "$link" ] ; then > usage > fi > > -kde_entry() > +desktop_entry() > { > - xname=`basename "$link"` > - cat <<EOF > -# KDE Config File > -[KDE Desktop Entry] > -Name=$xname > -Exec=wine '$path' $args > -Type=Application > -Comment=$descr > -EOF > - [ -z "$workdir" ] || echo "Path=\"$workdir\"" > - [ -z "$xpmicon" ] || echo "Icon=$xpmicon" > -} > - > -gnome_entry() > -{ > - xname=`basename "$link"` > cat <<EOF > [Desktop Entry] > -Name=$xname > +Name=$linkname > Exec=wine "$path" $args > Type=Application > -Comment=$descr > EOF > + [ -z "$descr" ] || echo "Comment=$descr" > [ -z "$workdir" ] || echo "Path=$workdir" > [ -z "$xpmicon" ] || echo "Icon=$xpmicon" > } > > -mdk_entry() > +directory_entry() > { > - base=`basename "$link"` > - section=`dirname "$link"` > - [ -z "$icon" ] || xicon="icon=\"$xpmicon\"" > - pathmenu=`echo "$path" | sed 's+\\\\+\\\\\\\\+g'` > - echo "?package(local.Wine):needs=x11 section=\"/Wine/$section\" > title=\"$base\" longtitle=\"$descr\" command=\"wine '$pathmenu' $args\" > $xicon" > + cat <<EOF > +[Desktop Entry] > +Type=Directory > +EOF > + if [ "$1" == "wine" ] ; then > + echo "Name=Wine" > + echo "Icon=wine" > + else > + echo "Name=$1" > + echo "Icon=folder" > + fi > } > > # copy the icon file to a specified dir and set xpmicon to the resulting path > copy_icon() > { > - dir="$1" > - mkdir -p "$dir" > - mkdir -p "$dir/""`dirname "$link"`" || true > - if [ -f "$icon" ] > - then > - cp "$icon" "$dir/$link.xpm" > - xpmicon="$dir/$link.xpm" > - else > - xpmicon="" > - fi > + if [ -f "$icon" ] > + then > + xpmicon=`basename "$icon" .xpm` > + > + mkdir -p "$1" > + cp "$icon" "$1/$xpmicon.xpm" > + else > + xpmicon="" > + fi > } > > -# Debian/Mandrake > - > -type update-menus > /dev/null 2>&1 > -if [ $? = 0 -a $mode = "menu" ] > -then > - iconname="`basename "$link"`.xpm" > - dir="$HOME/.menu/icons" > - if [ -f "$icon" ] > - then > - mkdir -p "$dir" > - cp "$icon" "$dir/$iconname" > - xpmicon="$dir/$iconname" > - else > - xpmicon="" > - fi > - mdk_entry >> "$HOME/.menu/wine" > - if [ -d "/usr/lib/menu" ] && [ -w "/usr/lib/menu" ] > - then > - mdk_entry >> "/usr/lib/menu/wine" > - fi > - update-menus > /dev/null 2>&1 > -fi > +# XDG > > -# KDE > +xdg_config_dir="$XDG_CONFIG_HOME" > +[ -n "$xdg_user_dir" ] || xdg_config_dir="$HOME/.config" > +xdg_config_dir="$xdg_config_dir/menus/applications-merged" > > -if [ -d "$HOME/.kde" ] > -then > - kdeversion=0 > - if type kde-config >/dev/null 2>&1 > - then > - kdeversion=`kde-config -v | grep KDE: | sed -n "s/^KDE: > \([^.]*\)\..*$/\1/p"` > - fi > +xdg_data_dir="$XDG_DATA_HOME" > +[ -n "$xdg_data_dir" ] || xdg_data_dir="$HOME/.local/share" > > - if [ $kdeversion -ge 2 ] > - then > - copy_icon "$HOME/.kde/share/applnk/Wine" > - if [ $mode = "menu" ] > - then > - gnome_entry > "$HOME/.kde/share/applnk/Wine/$link.desktop" > - elif [ -d "$HOME/Desktop" ] > - then > - gnome_entry > "$HOME/Desktop/$link.desktop" > +# Create common directories > +mkdir -p "$xdg_config_dir" > +mkdir -p "$xdg_data_dir/desktop-directories" > + > +get_menu_entries() > +{ > + tmp="$xdg_config_dir/$1.menu" > + > + if [ -r "$tmp" ] ; then > + awk ' > +BEGIN { RS="<" } > +/^Filename/ { > + if (match($0,/>/)) { > + print substr($0,RSTART+1) > + } > +}' $tmp > fi > - else > - copy_icon "$HOME/.kde/share/applnk/Wine" > - if [ $mode = "menu" ] > - then > - kde_entry > "$HOME/.kde/share/applnk/Wine/$link.kdelnk" > +} > > - # KDE 1.x kludge. Wake up KDE, if we can find kpanel running > - type kwmcom >/dev/null 2>/dev/null && \ > - ps u -C kpanel >/dev/null 2>/dev/null && \ > - kwmcom kpanel:restart > +# Input > +# menu file name > +# new item > +write_menu_file() > +{ > + tmpfile=`mktemp` > + ( > + echo '<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"' > + echo '"http://www.freedesktop.org/standards/menu-spec/menu-1.0.dtd">' > + echo '<Menu>' > + echo ' <Name>Applications</Name>' > + > + IFS="-" > + > + fullname='wine' > + for i in $1; do > + echo " <Menu>" > + echo " <Name>$fullname-$i</Name>" > + echo " <Directory>$fullname-$i.directory</Directory>" > + > + > dir_file_name="$xdg_data_dir/desktop-directories/$fullname-$i.directory" > + if [ ! -f "$dir_file_name" ] ; then > + directory_entry "$i" > "$dir_file_name" > + fi > + test "$i" = "wine" || fullname="$fullname-$i" > + done > + > + echo " <Include>" > + > + IFS=" > +" > + for i in $(get_menu_entries "$1"); do > + test "$i" = "$2" && continue > + echo " <Filename>$i</Filename>" > + done > + > + # New record > + echo " <Filename>$2</Filename>" > + echo " </Include>" > + > + IFS='-' > + for i in $1; do > + echo " </Menu>" > + done > + echo '</Menu>' > + ) > $tmpfile > + chmod 0600 $tmpfile > + > + mv -f $tmpfile "$xdg_config_dir/$1.menu" > +} > > - elif [ -d "$HOME/Desktop" ] > - then > - kde_entry > "$HOME/Desktop/$link.kdelnk" > - # KDE 1.x kludge: wake up KDE, if we can find kfm running... > - type kfmclient >/dev/null 2>/dev/null && \ > - ps u -C kfm >/dev/null 2>/dev/null && \ > - kfmclient refreshDesktop > - fi > - fi > -fi > > -if [ -d "$HOME/.kde2" ] > -then > - copy_icon "$HOME/.kde2/share/applnk/Wine" > - if [ $mode = "menu" ] > - then > - gnome_entry > "$HOME/.kde2/share/applnk/Wine/$link.desktop" > - else > - if [ -d "$HOME/Desktop2" ] > - then > - gnome_entry > "$HOME/Desktop2/$link.desktop" > - fi > - if [ -d "$HOME/Desktop" ] > - then > - gnome_entry > "$HOME/Desktop/$link.desktop" > - fi > - fi > -fi > +copy_icon "$xdg_data_dir/icons" > > -if [ -d "$HOME/.kde3/share/applnk" ] > -then > - copy_icon "$HOME/.kde3/share/applnk/Wine" > - if [ $mode = "menu" ] > - then > - gnome_entry > "$HOME/.kde3/share/applnk/Wine/$link.desktop" > - else > - if [ -d "$HOME/Desktop3" ] > - then > - gnome_entry > "$HOME/Desktop3/$link.desktop" > - fi > - if [ -d "$HOME/Desktop2" ] > - then > - gnome_entry > "$HOME/Desktop2/$link.desktop" > - fi > - if [ -d "$HOME/Desktop" ] > - then > - gnome_entry > "$HOME/Desktop/$link.desktop" > +linkname=`basename "$link"` > + > +if [ $mode = "menu" ] ; then > + mkdir -p "$xdg_data_dir/applications/wine/`dirname "$link"`" > + > + linkpath=`dirname "$link" | sed 's!/!-!g'` > + if [ "$linkpath" == "." ] ; then > + linkpath="" > + else > + linkpath="-$linkpath" > fi > - fi > -fi > > -# Gnome > - > -if [ -d "$HOME/.gnome" ] > -then > - copy_icon "$HOME/.gnome/apps/Wine" > - if [ $mode = "menu" ] > - then > - gnome_entry > "$HOME/.gnome/apps/Wine/$link.desktop" > - elif [ -d "$HOME/.gnome-desktop" ] > - then > - gnome_entry > "$HOME/.gnome-desktop/$link.desktop" > - fi > + desktop_entry > "$xdg_data_dir/applications/wine/$link.desktop" > + write_menu_file "wine$linkpath" "wine$linkpath-$linkname.desktop" > +else > + desktop_entry > "$HOME/Desktop/$linkname.desktop" > fi > > exit 0 > > > > ------------------------------------------------------------------------ > >