Index: gnome-shell-extensions-47.2/extensions/apps-menu/extension.js =================================================================== --- gnome-shell-extensions-47.2.orig/extensions/apps-menu/extension.js +++ gnome-shell-extensions-47.2/extensions/apps-menu/extension.js @@ -23,6 +23,8 @@ import * as DND from 'resource:///org/gn import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; +import * as AppFavorites from 'resource:///org/gnome/shell/ui/appFavorites.js'; +import * as BoxPointer from 'resource:///org/gnome/shell/ui/boxpointer.js'; const appSys = Shell.AppSystem.get_default(); @@ -60,6 +62,9 @@ class ApplicationMenuItem extends PopupM () => this._updateIcon(), this); this._updateIcon(); + this._menu = null; + this._menuManager = new PopupMenu.PopupMenuManager(this); + this._delegate = this; let draggable = DND.makeDraggable(this); @@ -72,6 +77,24 @@ class ApplicationMenuItem extends PopupM } activate(event) { + // close any opened menu to avoid input focus grab + if (this._menu && this._menu.isOpen) { + this._menu.close(); + return; + } + + let button = event.get_button(); + if (button == 3) { + this.popupMenu(); + return; + } + + let symbol = event.get_key_symbol(); + if (symbol === Clutter.KEY_space) { + this.popupMenu(); + return; + } + this._app.open_new_window(-1); this._button.selectCategory(null); this._button.menu.toggle(); @@ -80,6 +103,87 @@ class ApplicationMenuItem extends PopupM Main.overview.hide(); } + 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_child(this._menu.actor); + + this._menuManager.addMenu(this._menu); + } + + this._menu.open(BoxPointer.PopupAnimation.NONE); + this._menuManager.ignoreRelease(); + + return false; + } + setActive(active, params) { if (active) this._button.scrollToButton(this);