battery: Align primary gpu detection with cosmic-comp
This commit is contained in:
parent
94646f0124
commit
e5c89939a7
1 changed files with 53 additions and 20 deletions
|
|
@ -15,7 +15,10 @@ use cosmic::{
|
||||||
iced::{self, Subscription},
|
iced::{self, Subscription},
|
||||||
iced_futures::stream,
|
iced_futures::stream,
|
||||||
};
|
};
|
||||||
use drm::control::Device as ControlDevice;
|
use drm::control::{
|
||||||
|
Device as ControlDevice,
|
||||||
|
connector::{Info as ConnectorInfo, Interface},
|
||||||
|
};
|
||||||
use futures::{FutureExt, SinkExt};
|
use futures::{FutureExt, SinkExt};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
io::unix::AsyncFd,
|
io::unix::AsyncFd,
|
||||||
|
|
@ -57,6 +60,7 @@ impl Debug for GpuMonitor {
|
||||||
struct Gpu {
|
struct Gpu {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
name: String,
|
name: String,
|
||||||
|
boot_vga: bool,
|
||||||
primary: bool,
|
primary: bool,
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
driver: Option<OsString>,
|
driver: Option<OsString>,
|
||||||
|
|
@ -147,26 +151,32 @@ pub struct RunningApp {
|
||||||
executable_name: String,
|
executable_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn connectors(path: &impl AsRef<Path>) -> Option<impl Iterator<Item = ConnectorInfo>> {
|
||||||
|
struct Device(std::fs::File);
|
||||||
|
impl AsFd for Device {
|
||||||
|
fn as_fd(&self) -> std::os::unix::prelude::BorrowedFd<'_> {
|
||||||
|
self.0.as_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl drm::Device for Device {}
|
||||||
|
impl ControlDevice for Device {}
|
||||||
|
|
||||||
|
let device = Device(std::fs::File::open(path).ok()?);
|
||||||
|
let resources = device.resource_handles().ok()?;
|
||||||
|
|
||||||
|
Some(
|
||||||
|
resources
|
||||||
|
.connectors
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(move |conn| device.get_connector(conn, false).ok()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
impl Gpu {
|
impl Gpu {
|
||||||
async fn connected_outputs(&self) -> Option<Vec<Entry>> {
|
async fn connected_outputs(&self) -> Option<Vec<Entry>> {
|
||||||
let path = self.path.clone();
|
let path = self.path.clone();
|
||||||
spawn_blocking(move || {
|
spawn_blocking(move || {
|
||||||
struct Device(std::fs::File);
|
let outputs = connectors(&path)?
|
||||||
impl AsFd for Device {
|
|
||||||
fn as_fd(&self) -> std::os::unix::prelude::BorrowedFd<'_> {
|
|
||||||
self.0.as_fd()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl drm::Device for Device {}
|
|
||||||
impl ControlDevice for Device {}
|
|
||||||
|
|
||||||
let device = Device(std::fs::File::open(path).ok()?);
|
|
||||||
let resources = device.resource_handles().ok()?;
|
|
||||||
|
|
||||||
let outputs = resources
|
|
||||||
.connectors
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|conn| device.get_connector(conn, false).ok())
|
|
||||||
.filter(|info| info.state() == drm::control::connector::State::Connected)
|
.filter(|info| info.state() == drm::control::connector::State::Connected)
|
||||||
.map(|info| Entry {
|
.map(|info| Entry {
|
||||||
name: format!(
|
name: format!(
|
||||||
|
|
@ -178,6 +188,7 @@ impl Gpu {
|
||||||
secondary: String::new(),
|
secondary: String::new(),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// TODO read and parse edid with libdisplay-info and display output manufacture/model
|
// TODO read and parse edid with libdisplay-info and display output manufacture/model
|
||||||
|
|
||||||
Some(outputs)
|
Some(outputs)
|
||||||
|
|
@ -309,7 +320,7 @@ fn all_gpus<S: AsRef<str>>(seat: S) -> io::Result<Vec<Gpu>> {
|
||||||
let mut enumerator = udev::Enumerator::new()?;
|
let mut enumerator = udev::Enumerator::new()?;
|
||||||
enumerator.match_subsystem("drm")?;
|
enumerator.match_subsystem("drm")?;
|
||||||
enumerator.match_sysname("card[0-9]*")?;
|
enumerator.match_sysname("card[0-9]*")?;
|
||||||
Ok(enumerator
|
let mut gpus = enumerator
|
||||||
.scan_devices()?
|
.scan_devices()?
|
||||||
.filter(|device| {
|
.filter(|device| {
|
||||||
device
|
device
|
||||||
|
|
@ -370,13 +381,34 @@ fn all_gpus<S: AsRef<str>>(seat: S) -> io::Result<Vec<Gpu>> {
|
||||||
Some(Gpu {
|
Some(Gpu {
|
||||||
path,
|
path,
|
||||||
name,
|
name,
|
||||||
primary: boot_vga,
|
boot_vga,
|
||||||
|
primary: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
driver,
|
driver,
|
||||||
interval,
|
interval,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect())
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if let Some(primary_idx) = gpus
|
||||||
|
.iter()
|
||||||
|
.position(|gpu| {
|
||||||
|
connectors(&gpu.path).is_some_and(|mut conns| {
|
||||||
|
conns.any(|info| {
|
||||||
|
let i = info.interface();
|
||||||
|
i == Interface::EmbeddedDisplayPort
|
||||||
|
|| i == Interface::LVDS
|
||||||
|
|| i == Interface::DSI
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.or_else(|| gpus.iter().position(|gpu| gpu.boot_vga))
|
||||||
|
.or_else(|| (gpus.len() == 1).then_some(0))
|
||||||
|
{
|
||||||
|
gpus[primary_idx].primary = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(gpus)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dgpu_subscription<I: 'static + Hash + Copy + Send + Sync + Debug>(
|
pub fn dgpu_subscription<I: 'static + Hash + Copy + Send + Sync + Debug>(
|
||||||
|
|
@ -481,6 +513,7 @@ async fn start_listening(
|
||||||
monitor.gpus.push(Gpu {
|
monitor.gpus.push(Gpu {
|
||||||
path: path.to_path_buf(),
|
path: path.to_path_buf(),
|
||||||
name,
|
name,
|
||||||
|
boot_vga: false,
|
||||||
primary: false,
|
primary: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
driver,
|
driver,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue