From a819d570ebdc5ab2e910d1db85efa9382d0d6dd0 Mon Sep 17 00:00:00 2001 From: Michael Webster Date: Sat, 9 May 2020 12:08:32 -0400 Subject: [PATCH] Support nvidia on-demand app launching. Requires linuxmint/xapps@dcb600595dcc6a5 to function correctly. --- .../mintMenu/plugins/applications.py | 21 +++++++++++++++- .../linuxmint/mintMenu/plugins/easybuttons.py | 15 ++++++++---- usr/lib/linuxmint/mintMenu/plugins/execute.py | 24 +++++++++++++++---- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/usr/lib/linuxmint/mintMenu/plugins/applications.py b/usr/lib/linuxmint/mintMenu/plugins/applications.py index a9f2515..22b8321 100755 --- a/usr/lib/linuxmint/mintMenu/plugins/applications.py +++ b/usr/lib/linuxmint/mintMenu/plugins/applications.py @@ -12,7 +12,7 @@ import urllib.request, urllib.parse, urllib.error import gi gi.require_version("Gtk", "3.0") gi.require_version("MateMenu", "2.0") -from gi.repository import Gtk, Gdk, GdkPixbuf, Gio, GLib, MateMenu +from gi.repository import Gtk, Gdk, GdkPixbuf, Gio, GLib, MateMenu, XApp import plugins.recentHelper as RecentHelper from plugins.easybuttons import (ApplicationLauncher, CategoryButton, @@ -188,6 +188,13 @@ class pluginclass(object): self.menuFiles = [] self.de = de + self.canOffload = False + + try: + self.canOffload = XApp.util_gpu_offload_supported() + except AttributeError: + print("Could not check for gpu offload support - maybe xapps isn't up to date."); + # Detect the locale (this is used for the Wikipedia search) self.lang = "en" lang = os.getenv('LANG') @@ -835,6 +842,7 @@ class pluginclass(object): startupMenuItem = Gtk.CheckMenuItem(_("Launch when I log in")) separator3 = Gtk.SeparatorMenuItem() launchMenuItem = Gtk.MenuItem(_("Launch")) + launchOffloadedMenuItem = Gtk.MenuItem(_("Run with NVIDIA GPU")) removeFromFavMenuItem = Gtk.MenuItem(_("Remove from favorites")) separator4 = Gtk.SeparatorMenuItem() propsMenuItem = Gtk.MenuItem(_("Edit properties")) @@ -850,6 +858,7 @@ class pluginclass(object): startupMenuItem.set_active(False) startupMenuItem.connect("toggled", self.onAddToStartup, widget) launchMenuItem.connect("activate", self.onLaunchApp, widget) + launchOffloadedMenuItem.connect("activate", self.onLaunchOffloadedApp, widget) removeFromFavMenuItem.connect("activate", self.onFavoritesRemove, widget) propsMenuItem.connect("activate", self.onPropsApp, widget) @@ -863,6 +872,8 @@ class pluginclass(object): mTree.append(startupMenuItem) mTree.append(separator3) mTree.append(launchMenuItem) + if self.canOffload: + mTree.append(launchOffloadedMenuItem) mTree.append(removeFromFavMenuItem) mTree.append(separator4) mTree.append(propsMenuItem) @@ -904,6 +915,7 @@ class pluginclass(object): startupMenuItem = Gtk.CheckMenuItem(_("Launch when I log in")) separator2 = Gtk.SeparatorMenuItem() launchMenuItem = Gtk.MenuItem(_("Launch")) + launchOffloadedMenuItem = Gtk.MenuItem(_("Run with NVIDIA GPU")) uninstallMenuItem = Gtk.MenuItem(_("Uninstall")) deleteMenuItem = Gtk.MenuItem(_("Delete from menu")) separator3 = Gtk.SeparatorMenuItem() @@ -918,6 +930,8 @@ class pluginclass(object): mTree.append(startupMenuItem) mTree.append(separator2) mTree.append(launchMenuItem) + if self.canOffload: + mTree.append(launchOffloadedMenuItem) mTree.append(uninstallMenuItem) if home in widget.desktopFile: mTree.append(deleteMenuItem) @@ -929,6 +943,7 @@ class pluginclass(object): desktopMenuItem.connect("activate", self.add_to_desktop, widget) panelMenuItem.connect("activate", self.add_to_panel, widget) launchMenuItem.connect("activate", self.onLaunchApp, widget) + launchOffloadedMenuItem.connect("activate", self.onLaunchOffloadedApp, widget) propsMenuItem.connect("activate", self.onPropsApp, widget) uninstallMenuItem.connect("activate", self.onUninstallApp, widget) @@ -1070,6 +1085,10 @@ class pluginclass(object): widget.execute() self.mintMenuWin.hide() + def onLaunchOffloadedApp(self, menu, widget): + widget.execute(offload=True) + self.mintMenuWin.hide() + def onPropsApp(self, menu, widget): newFileFlag = False sysPaths = get_system_item_paths() diff --git a/usr/lib/linuxmint/mintMenu/plugins/easybuttons.py b/usr/lib/linuxmint/mintMenu/plugins/easybuttons.py index bef3bdb..17a08e0 100755 --- a/usr/lib/linuxmint/mintMenu/plugins/easybuttons.py +++ b/usr/lib/linuxmint/mintMenu/plugins/easybuttons.py @@ -344,7 +344,7 @@ class ApplicationLauncher(easyButton): else: selection.set_uris(["file://" + self.desktopFile]) - def execute(self, *args): + def execute(self, *args, **kwargs): if self.appExec: if self.useTerminal: cmd = "x-terminal-emulator -e \"" + self.appExec + "\"" @@ -352,7 +352,14 @@ class ApplicationLauncher(easyButton): cmd = "mate-terminal -e \"" + self.appExec + "\"" Execute(cmd, self.appPath) else: - Execute(None, desktopFile=self.desktopFile) + offload = False + + try: + offload = kwargs["offload"] + except KeyError: + pass + + Execute(None, desktopFile=self.desktopFile, offload=offload) def uninstall(self, *args): Execute("mint-remove-application " + self.desktopFile) @@ -464,12 +471,12 @@ class MenuApplicationLauncher(ApplicationLauncher): else: self.addLabel(appName) - def execute(self, *args): + def execute(self, *args, **kwargs): self.highlight = False for child in self.labelBox: child.destroy() self.setupLabels() - return super(MenuApplicationLauncher, self).execute(*args) + return super(MenuApplicationLauncher, self).execute(*args, **kwargs) def setShowComment(self, showComment): self.showComment = showComment diff --git a/usr/lib/linuxmint/mintMenu/plugins/execute.py b/usr/lib/linuxmint/mintMenu/plugins/execute.py index d016a17..64de85e 100755 --- a/usr/lib/linuxmint/mintMenu/plugins/execute.py +++ b/usr/lib/linuxmint/mintMenu/plugins/execute.py @@ -1,7 +1,7 @@ #!/usr/bin/python3 import os -from gi.repository import Gio, GLib +from gi.repository import Gio, GLib, Gdk def RemoveArgs(Execline): @@ -25,12 +25,26 @@ def gather_pid_callback(appinfo, pid, data): GLib.child_watch_add(pid, dummy_child_watch, None) # Actually execute the command -def Execute(cmd , commandCwd=None, desktopFile=None): +def Execute(cmd , commandCwd=None, desktopFile=None, offload=False): if desktopFile: launcher = Gio.DesktopAppInfo.new_from_filename(desktopFile) - retval = launcher.launch_uris_as_manager(uris=[], launch_context=None, spawn_flags=GLib.SpawnFlags.SEARCH_PATH|GLib.SpawnFlags.DO_NOT_REAP_CHILD, \ - user_setup=None, user_setup_data=None, pid_callback=gather_pid_callback, pid_callback_data=None) - return retval + context = Gdk.Display.get_default().get_app_launch_context() + if offload: + print("Offloading '%s' to discrete gpu." % launcher.get_name()); + + context.setenv("__NV_PRIME_RENDER_OFFLOAD", "1") + context.setenv("__GLX_VENDOR_LIBRARY_NAME", "nvidia"); + + try: + retval = launcher.launch_uris_as_manager(uris=[], + launch_context=context, + spawn_flags=GLib.SpawnFlags.SEARCH_PATH|GLib.SpawnFlags.DO_NOT_REAP_CHILD, + user_setup=None, user_setup_data=None, + pid_callback=gather_pid_callback, pid_callback_data=None) + return retval + except GLib.Error as e: + print("Error launching %s: %s" % (launcher.get_name(), e.message)) + return False cwd = os.path.expanduser("~")