wineshelllink: Use FreeDesktop standard to create Wine menu structure.

Jeremy White jwhite at winehq.org
Fri Nov 24 15:32:59 CST 2006


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
> 
> 
> 
> ------------------------------------------------------------------------
> 
> 




More information about the wine-devel mailing list