File gnome-shell-add-app-to-desktop.patch of Package gnome-shell-extensions

Index: gnome-shell-extensions-3.34.2/extensions/apps-menu/extension.js
===================================================================
--- gnome-shell-extensions-3.34.2.orig/extensions/apps-menu/extension.js
+++ gnome-shell-extensions-3.34.2/extensions/apps-menu/extension.js
@@ -5,6 +5,8 @@ const {
     Atk, Clutter, Gio, GLib, GMenu, GObject, Gtk, Meta, Shell, St,
 } = imports.gi;
 const Signals = imports.signals;
+const BoxPointer = imports.ui.boxpointer;
+const AppFavorites = imports.ui.appFavorites;
 
 const DND = imports.ui.dnd;
 const ExtensionUtils = imports.misc.extensionUtils;
@@ -46,8 +48,19 @@ class ApplicationMenuItem extends PopupM
         let textureCache = St.TextureCache.get_default();
         let iconThemeChangedId = textureCache.connect('icon-theme-changed',
             this._updateIcon.bind(this));
+
+        this.actor.connect('button-press-event', this._onButtonPress.bind(this));
+        this.actor.connect('popup-menu', this._onKeyboardPopupMenu.bind(this));
+        this._menu = null;
+        this._menuManager = new PopupMenu.PopupMenuManager(this);
+
         this.connect('destroy', () => {
             textureCache.disconnect(iconThemeChangedId);
+            if (this._menu) {
+                this._menu.destroy();
+                this._menu = null;
+                this._menuManager = null;
+            }
         });
         this._updateIcon();
 
@@ -62,6 +75,107 @@ class ApplicationMenuItem extends PopupM
         };
     }
 
+    _onKeyboardPopupMenu() {
+        this.popupMenu();
+        this._menu.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
+    }
+
+    _onButtonPress(actor, event) {
+        // close any opened menu to avoid input focus grab
+        if (this._menu && this._menu.isOpen) {
+            this._menu.close();
+            return Clutter.EVENT_STOP;
+        }
+
+        let button = event.get_button();
+        if (button == 3) {
+            this.popupMenu();
+            return Clutter.EVENT_STOP;
+        }
+        return Clutter.EVENT_PROPAGATE
+    }
+
+    popupMenu() {
+        if (!this._menu) {
+            this._menu = new PopupMenu.PopupMenu(this.actor, 0.0, St.Side.TOP, 0);
+            let openItem = new PopupMenu.PopupMenuItem(_("Open"));
+            this._menu.addMenuItem(openItem);
+            openItem.connect('activate', () => {
+                this._menu.destroy();
+                this._menu = null;
+                this._app.open_new_window(-1);
+                this._button.selectCategory(null, null);
+                this._button.menu.toggle();
+            });
+
+            let sepItem = new PopupMenu.PopupSeparatorMenuItem();
+            this._menu.addMenuItem(sepItem);
+
+            let isFavorite = AppFavorites.getAppFavorites().isFavorite(this._app.get_id());
+            let favText = null;
+            if (isFavorite)
+                favText = _("Remove from Favorites");
+            else
+                favText = _("Add to Favorites");
+
+            let favItem = new PopupMenu.PopupMenuItem(favText);
+            this._menu.addMenuItem(favItem);
+            favItem.connect('activate', () => {
+                let favs = AppFavorites.getAppFavorites();
+                let isFavorite = favs.isFavorite(this._app.get_id());
+                if (isFavorite)
+                    favs.removeFavorite(this._app.get_id());
+                else
+                    favs.addFavorite(this._app.get_id());
+
+                /*As the item text changes, we need to re-generate the menu */
+                this._menu.destroy();
+                this._menu = null;
+
+                this._button.selectCategory(null, null);
+                this._button.menu.toggle();
+            });
+
+            let desktopItem = new PopupMenu.PopupMenuItem(_("Add to Desktop"));
+            this._menu.addMenuItem(desktopItem);
+            desktopItem.connect('activate', () => {
+                let desktopApp = this._app.get_app_info();
+                let sourcePath = desktopApp.get_filename();
+                let sourceFile = Gio.File.new_for_path(sourcePath);
+                let destDirPath = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP);
+                let destDir = Gio.File.new_for_path(destDirPath);
+
+                if (!destDir.query_exists(null)) {
+                    destDirPath = Glib.build_filenamev([GLib.get_home_dir(), "Desktop"]);
+                }
+                let destFile = Gio.File.new_for_path(destDirPath + '/' + sourceFile.get_basename());
+                if (sourceFile.copy(destFile, Gio.FileCopyFlags.OVERWRITE, null, null)) {
+                    // In order to make the general monitor recognize the setting of metadata,
+                    // this function call should  before the setting of unix mode.
+                    let info = new Gio.FileInfo();
+                    info.set_attribute_string('metadata::trusted', 'true');
+                    destFile.set_attributes_from_info(info,
+                                                      Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
+                    destFile.set_attribute_uint32( Gio.FILE_ATTRIBUTE_UNIX_MODE, parseInt("0755", 8),
+                                                   Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
+                }
+                this._menu.destroy();
+                this._menu = null;
+                this._button.selectCategory(null, null);
+                this._button.menu.toggle();
+            });
+
+            Main.uiGroup.add_actor(this._menu.actor);
+
+            this._menuManager.addMenu(this._menu);
+        }
+
+        this._menu.open(BoxPointer.PopupAnimation.NONE);
+        this._menuManager.ignoreRelease();
+
+        return false;
+    }
+
     activate(event) {
         this._app.open_new_window(-1);
         this._button.selectCategory(null);
openSUSE Build Service is sponsored by