plasma-optimus/000775 001750 001750 00000000000 15212040642 014255 5ustar00ericherich000000 000000 plasma-optimus/README.md000664 001750 001750 00000003503 15212036110 015530 0ustar00ericherich000000 000000 # Plasma Optimus A fork from [Prime Render Switch and Status](https://store.kde.org/p/1425330/) for [optimus-manager](https://github.com/Askannz/optimus-manager) This is a simple widget for KDE Plasma 6 to display the active Nvidia GPU mode, switch between GPU modes using prime-select, and view processes running on the GPU. #### Prerequisites - prime-select (nvidia-prime) - python3 - python3-pyqt6 #### Usage/Install ```bash On an Ubuntu system: sudo apt install plasma-optimus ``` Widget will be automatically added to Plasma notification area on next login. #### Changelog - 26.04.4 — Fix GPU detection under Wayland (glxinfo reports wrong GPU via XWayland); use nvidia-smi/sysfs instead - Fix system tray popup not opening on click - 26.04.3 — Fix fullRepresentation to use PlasmaExtras.Representation for popup menu - 26.04.2 — Fix metadata.json for system tray integration - 26.04.1 — Consolidate plasma-prime-select into switch.py with token-based security; remove obsolete scripts - 26.04.0 — Ported to KDE Plasma 6 / Qt 6 - Replaced `metadata.desktop` with `metadata.json` - Updated QML imports for Plasma 6 (`PlasmoidItem`, `Kirigami`, `plasma5support`) - Replaced kdialog/zenity with native PyQt6 dialogs - 22.04.2 — Reboots instead of logout due to changes in the Nvidia driver - 22.04.0 - Sets false variables for modes not in use - Power-saving changes - Only sniffs the gpu in use upon load - `prime-select query` now runs only once every 10 seconds - 21.10.0 — Initial Release #### Author ###### Erich Eickmeyer [LinkedIn](https://www.linkedin.com/in/erich-eickmeyer-a8954623/) #### Original Author ###### Rui Guilherme [GitHub](https://github.com/RuiGuilherme/)
[Linkedin](https://www.linkedin.com/in/rui-guilherme/) #### Contributing Contributions, issues and feature requests are welcome! plasma-optimus/LICENSE000664 001750 001750 00000002132 15212036110 015253 0ustar00ericherich000000 000000 MIT License Copyright (c) 2020 Rui Guilherme da Cunha Copyright (c) 2021 Erich Eickmeyer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. plasma-optimus/usr/000775 001750 001750 00000000000 15212036110 015061 5ustar00ericherich000000 000000 plasma-optimus/usr/share/000775 001750 001750 00000000000 15212037754 016202 5ustar00ericherich000000 000000 plasma-optimus/usr/share/polkit-1/000775 001750 001750 00000000000 15212036110 017623 5ustar00ericherich000000 000000 plasma-optimus/usr/share/polkit-1/actions/000775 001750 001750 00000000000 15212036110 021263 5ustar00ericherich000000 000000 plasma-optimus/usr/share/polkit-1/actions/org.kubuntu.plasma-prime.policy000664 001750 001750 00000001326 15212036110 027357 0ustar00ericherich000000 000000 Authentication is required to change GPU mode yes yes yes /usr/share/plasma/plasmoids/org.kde.plasma.plasma-optimus/contents/ui/switch.py true plasma-optimus/usr/share/plasma/000775 001750 001750 00000000000 15212036110 017440 5ustar00ericherich000000 000000 plasma-optimus/usr/share/plasma/plasmoids/000775 001750 001750 00000000000 15212036110 021433 5ustar00ericherich000000 000000 plasma-optimus/usr/share/plasma/plasmoids/org.kde.plasma.plasma-optimus/000775 001750 001750 00000000000 15212036110 027212 5ustar00ericherich000000 000000 plasma-optimus/usr/share/plasma/plasmoids/org.kde.plasma.plasma-optimus/contents/000775 001750 001750 00000000000 15212036110 031047 5ustar00ericherich000000 000000 plasma-optimus/usr/share/plasma/plasmoids/org.kde.plasma.plasma-optimus/contents/config/000775 001750 001750 00000000000 15212036110 032314 5ustar00ericherich000000 000000 plasma-optimus/usr/share/plasma/plasmoids/org.kde.plasma.plasma-optimus/contents/config/config.qml000664 001750 001750 00000000323 15212036110 034272 0ustar00ericherich000000 000000 import QtQuick import org.kde.plasma.configuration ConfigModel { ConfigCategory { name: i18n("General") icon: "preferences-system-windows" source: "config/configGeneral.qml" } } plasma-optimus/usr/share/plasma/plasmoids/org.kde.plasma.plasma-optimus/contents/config/main.xml000664 001750 001750 00000000670 15212036110 033765 0ustar00ericherich000000 000000 3 plasma-optimus/usr/share/plasma/plasmoids/org.kde.plasma.plasma-optimus/contents/ui/000775 001750 001750 00000000000 15212036110 031464 5ustar00ericherich000000 000000 plasma-optimus/usr/share/plasma/plasmoids/org.kde.plasma.plasma-optimus/contents/ui/nvidia-on.svg000664 001750 001750 00000005040 15212036110 034070 0ustar00ericherich000000 000000 plasma-optimus/usr/share/plasma/plasmoids/org.kde.plasma.plasma-optimus/contents/ui/intel.png000664 001750 001750 00000005145 15212036110 033312 0ustar00ericherich000000 000000 PNG  IHDR@@iq pHYs'tEXtSoftwarewww.inkscape.org< IDATx{pTw&**PXu&Dꈏ:3*ɦ6![ѱm"c۰Ԫ02**UdHdI~n IH:fvf^;߹ (P@ "ڀތ[R T :ՠk.Xk٥6*>Ǜڱ0zML3CLUe0 7.BuFx7-b~s@4IRf@%P6P} _R3@3^YQDezl#R%;ޞ AhcUt(UigcP5Q+BX]ªO9nY] ՋE8<(7޵n𪓽^$Q"“)yq[5րxj~BTk@.5jͥmVg.+@b口%~ޏkoDv`TFCDZ?la; =եF>xH\,W[aO"u+r} 6jq?ؿҘhzkV";Wi&ֺ3`kC!_x#6Ok25M> %큺F"R0a ],CXtՅRHpEs*r0k((Fu59.HJbmO5*`~5+}ٓm";Nϖ 2MFY9vw"u'sk7?:>IW3}##N(HNiuZu$/2/#~kf5Fcx (zv߹PL /5{T{zWLo;kse_ r U#HV!d? ?VԼ4! VryDow-OBE$Gn3Kkc};yrV!ޣghwF$4~jYG>~%z,8ʻd9'OAz9ؖ9vA\.&@:Y)8ol${ 9]$;ZER_eLIhn7eYA}Y/ّh&7RA-S1}.ڡ% y˝n"NFխ́c1K%[iE9N+7"kկIJ.Saz6VxbcF )[blDF^$s6/jϭgH#=X<\;-ʋݖ2KQ9:3AA LO+COh`Ȕ-cټhv{B%mGn 'm g>-p'E+}U_**h/VHuY|f'3*g Q ڠ+Z0I)LCܟM.½]G/+/IEj`^_EL8l Eހr{kD)3O}|.?ݼ5EֳT% g| u6{2 Nّǩz p8CwJ;CkKv滉!$ʽO9qxuv.΢U@ (P@~ѤIENDB`plasma-optimus/usr/share/plasma/plasmoids/org.kde.plasma.plasma-optimus/contents/ui/nvidia-on.png000664 001750 001750 00000004542 15212036110 034063 0ustar00ericherich000000 000000 PNG  IHDR@@iq pHYs\rtEXtSoftwarewww.inkscape.org<IDATxkT;3,HEմFh&T;3 B[ 5Ħ5Ud4 5hD*RDڸΙaEF+I[Tb5^#Z%ʲyawʲ&??缗=PC 5PC 5|Q! l[M kF;V#ԌvpN1hFN`Q#`kD[]wQ9hDk=IOjмxNQǜ'ٌpD6BAj4DE_9xzlk3|3xO?9K=; |,Asݶӌ)(%v)YC^?y.c7AQ\X׃Ż0I'c^ G2Ń[:Tx{pm-3`:#.yswQHDv۷, bAa$9'+A(J`mIFо;\c?b{sKJGcUƞ&mA꘧z<FU!Vm6TZ0]YEN+s!z8H v*]I3іϯEtai+ξEGEenCzDReS0 ǜpu0^aŐfyITb~Z$ʺm-*FZe ѿ7bW|z)fuZ[ZR{*Z=+0s_ 2>8q|.p"pp=ͰmY } ˲ź!zTFt58s6Tvf|ߩJ%~ *fvfPKŦD?(gT EOuY~9^5(hi?%^~cUf; 1-[zxoSsr֮ECP*6Q>e'`G<(ƹװҤH0M-ntTl}ee^r,舟0N՘e[󢷢^?2ƑLG^a$Is@ۧQ:bM@pprIs1 KeT.A0*Zuj^凈^P։??8AEg": Y\`hQ F;*_5: `*cGeю3vTu5PC 5P!l<~+IENDB`plasma-optimus/usr/share/plasma/plasmoids/org.kde.plasma.plasma-optimus/contents/ui/switch.py000775 001750 001750 00000012776 15212036110 033357 0ustar00ericherich000000 000000 #!/usr/bin/env python3 # # switch.py # Brings up a GUI for switching between # Nvidia (discrete) and Intel (integrated) GPUs # # Copyright (c) 2026 Erich Eickmeyer # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import os import sys import uuid import subprocess import tempfile from pathlib import Path VALID_OPTIONS = ("nvidia", "intel", "on-demand") SWITCH_PY = "/usr/share/plasma/plasmoids/org.kde.plasma.plasma-optimus/contents/ui/switch.py" def run_prime_select(option, token): """Elevated mode: validate token, run prime-select. Called via pkexec.""" if option not in VALID_OPTIONS: sys.exit(1) token_path = Path(tempfile.gettempdir()) / f"plasma-optimus-{token}" if not token_path.is_file(): print("This cannot be executed outside of Plasma Optimus", file=sys.stderr) sys.exit(1) token_path.unlink() os.execvp("prime-select", ["prime-select", option]) GPU_MAP = { "nvidia": ("Nvidia GPU (Performance Mode)", "nvidia"), "intel": ("Intel GPU (Power Save Mode)", "intel"), "on-demand": ("Hybrid GPU (On-Demand Mode)

Not Recommended if Using
External Monitors", "hybrid"), } def switch_graphics(option, icon_name): """Run pkexec switch.py --prime-select with a progress dialog, then reboot.""" token = str(uuid.uuid4()) token_path = Path(tempfile.gettempdir()) / f"plasma-optimus-{token}" token_path.touch() icon_path = f"/usr/share/pixmaps/plasma-optimus-{icon_name}.png" # Import Qt only in GUI mode from PyQt6.QtWidgets import QApplication, QProgressDialog from PyQt6.QtGui import QIcon from PyQt6.QtCore import Qt, QProcess, QEventLoop progress = QProgressDialog( "Please wait while your graphics system is configured.\n" "This may take a while (updating initramfs)...", None, # no cancel button 0, 0, # indeterminate ) progress.setWindowTitle("Plasma Optimus") progress.setWindowIcon(QIcon(icon_path)) progress.setCancelButton(None) progress.setWindowModality(Qt.WindowModality.ApplicationModal) progress.setMinimumDuration(0) progress.show() QApplication.processEvents() # Use QProcess so the event loop keeps running and the throbber animates loop = QEventLoop() proc = QProcess() proc.finished.connect(loop.quit) proc.start("pkexec", [SWITCH_PY, "--prime-select", option, token]) if not proc.waitForStarted(30000): progress.close() sys.exit(1) loop.exec() progress.close() if proc.exitCode() != 0: sys.exit(1) # Show Plasma reboot dialog via D-Bus subprocess.run([ "qdbus6", "org.kde.LogoutPrompt", "/LogoutPrompt", "promptReboot", ]) def logout_dialog(option, gpu_str, icon_name): """Show confirmation dialog, then switch if accepted.""" icon_path = f"/usr/share/pixmaps/plasma-optimus-{icon_name}.png" from PyQt6.QtWidgets import QMessageBox from PyQt6.QtGui import QIcon from PyQt6.QtCore import Qt text = f"""

Switching To

{gpu_str}

You must reboot to apply the new GPU settings.
Make sure to save all work before continuing.

Do you wish to reboot now?

""" msg = QMessageBox() msg.setWindowTitle("Plasma Optimus") msg.setWindowIcon(QIcon(icon_path)) msg.setTextFormat(Qt.TextFormat.RichText) msg.setText(text) msg.setStandardButtons( QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No ) msg.setDefaultButton(QMessageBox.StandardButton.No) if msg.exec() == QMessageBox.StandardButton.Yes: switch_graphics(option, icon_name) def main(): if len(sys.argv) < 2: sys.exit(1) # Elevated mode: pkexec switch.py --prime-select