From eb6028f8fc788e198be4dcac85e870add095925a Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Fri, 4 Mar 2022 12:00:54 +0100 Subject: [PATCH] fix: Show context for graphics only if switchable graphics found --- Cargo.lock | 17 ++++++++++ plugins/Cargo.toml | 2 ++ plugins/src/desktop_entries/graphics.rs | 43 +++++++++++++++++++++++++ plugins/src/desktop_entries/mod.rs | 35 +++++++++++--------- 4 files changed, 81 insertions(+), 16 deletions(-) create mode 100644 plugins/src/desktop_entries/graphics.rs diff --git a/Cargo.lock b/Cargo.lock index 4f5a278..2b78b3b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1184,6 +1184,12 @@ dependencies = [ "libc", ] +[[package]] +name = "numtoa" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aa2c4e539b869820a2b82e1aef6ff40aa85e65decdd5185e83fb4b1249cd00f" + [[package]] name = "objc" version = "0.2.7" @@ -1398,6 +1404,7 @@ dependencies = [ name = "pop-launcher-plugins" version = "1.1.0" dependencies = [ + "anyhow", "async-pidfd", "fork", "freedesktop-desktop-entry", @@ -1416,6 +1423,7 @@ dependencies = [ "slab", "smol", "strsim", + "sysfs-class", "tracing", "tracing-subscriber", "url", @@ -1846,6 +1854,15 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "sysfs-class" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1bbcf869732c45a77898f7f61ed6d411dfc37613517e444842f58d428856d1" +dependencies = [ + "numtoa", +] + [[package]] name = "system-deps" version = "6.0.2" diff --git a/plugins/Cargo.toml b/plugins/Cargo.toml index cfa6ffb..db89f17 100644 --- a/plugins/Cargo.toml +++ b/plugins/Cargo.toml @@ -32,3 +32,5 @@ zvariant = "3.1.2" ward = "2.1.0" isahc = "1.6.0" url = "2.2.2" +sysfs-class = "0.1.3" +anyhow = "1.0.55" diff --git a/plugins/src/desktop_entries/graphics.rs b/plugins/src/desktop_entries/graphics.rs new file mode 100644 index 0000000..ff0ec54 --- /dev/null +++ b/plugins/src/desktop_entries/graphics.rs @@ -0,0 +1,43 @@ +// Copyright 2022 System76 +// SPDX-License-Identifier: GPL-3.0-only + +use anyhow::Context; +use sysfs_class::{PciDevice, SysClass}; + +/// Checks if the system has switchable graphics. +/// +/// A system is considered switchable if multiple graphics card devices are found. +pub fn is_switchable() -> bool { + let main = || -> anyhow::Result { + let devices = PciDevice::all().context("cannot get PCI devices")?; + + let mut amd_graphics = 0; + let mut intel_graphics = 0; + let mut nvidia_graphics = 0; + + for dev in devices { + let c = dev.class().context("cannot get class of device")?; + if let 0x03 = (c >> 16) & 0xFF { + match dev.vendor().context("cannot get vendor of device")? { + 0x1002 => amd_graphics += 1, + 0x10DE => nvidia_graphics += 1, + 0x8086 => intel_graphics += 1, + _ => (), + } + } + } + + let switchable = (nvidia_graphics > 0 && (intel_graphics > 0 || amd_graphics > 0)) + || (intel_graphics > 0 && amd_graphics > 0); + + Ok(switchable) + }; + + match main() { + Ok(value) => value, + Err(why) => { + tracing::error!("{}", why); + false + } + } +} diff --git a/plugins/src/desktop_entries/mod.rs b/plugins/src/desktop_entries/mod.rs index 11d64c9..6f334c1 100644 --- a/plugins/src/desktop_entries/mod.rs +++ b/plugins/src/desktop_entries/mod.rs @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only // Copyright © 2021 System76 +mod graphics; + use crate::*; use freedesktop_desktop_entry::{default_paths, DesktopEntry, Iter as DesktopIter, PathSource}; use futures_lite::{AsyncWrite, StreamExt}; @@ -20,7 +22,6 @@ struct Item { path: PathBuf, prefers_non_default_gpu: bool, src: PathSource, - terminal_command: bool, } impl Hash for Item { @@ -162,7 +163,6 @@ impl App { icon: entry.icon().map(|x| x.to_owned()), exec: exec.to_owned(), path: path.clone(), - terminal_command: entry.terminal(), prefers_non_default_gpu: entry.prefers_non_default_gpu(), src, }; @@ -212,22 +212,25 @@ impl App { async fn context(&mut self, id: u32) { if let Some(entry) = self.entries.get(id as usize) { - let option = ContextOption { - id: 0, - name: (if entry.prefers_non_default_gpu { - "Launch Using Integrated Graphics Card" - } else { - "Launch Using Discrete Graphics Card" - }) - .to_owned(), - }; + let mut options = Vec::new(); - let response = PluginResponse::Context { - id, - options: vec![option], - }; + if graphics::is_switchable() { + options.push(ContextOption { + id: 0, + name: (if entry.prefers_non_default_gpu { + "Launch Using Integrated Graphics Card" + } else { + "Launch Using Discrete Graphics Card" + }) + .to_owned(), + }); + } - send(&mut self.tx, response).await; + if !options.is_empty() { + let response = PluginResponse::Context { id, options }; + + send(&mut self.tx, response).await; + } } }