mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Compare commits
7 Commits
argh
...
5ea14be3fa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ea14be3fa | ||
|
|
64c2e55db4 | ||
|
|
5303bfc1ad | ||
|
|
635f1dc9b9 | ||
|
|
33a4dba8fe | ||
|
|
e4680c9543 | ||
|
|
e9c5315bda |
@@ -90,7 +90,7 @@ pages:
|
|||||||
- rm -rf public
|
- rm -rf public
|
||||||
- mkdir public
|
- mkdir public
|
||||||
- cp -R ci-target/doc/* public
|
- cp -R ci-target/doc/* public
|
||||||
- cp extra/index.html public
|
- if [ -f extra/index.html ]; then cp extra/index.html public; else echo "no extra/index.html to copy"; fi
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- public
|
- public
|
||||||
|
|||||||
@@ -2,11 +2,16 @@
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
## [6.3.0]
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Added support for TUF keyboard powerstate control
|
- Added support for TUF keyboard powerstate control
|
||||||
- Improved AniMe Matrix support thanks to @Seom1177 !
|
- Improved AniMe Matrix support thanks to @Seom1177 !
|
||||||
- Fixed a bug with one-shot battery change, thanks @bitr8 !
|
- Fixed a bug with one-shot battery change, thanks @bitr8 !
|
||||||
- Changed the CLI interface of asusctl to be less confusing
|
- Changed the CLI interface of asusctl to be less confusing
|
||||||
|
- Added support for G835L, thanks to @shevchenko0013 !
|
||||||
|
|
||||||
## [6.2.0]
|
## [6.2.0]
|
||||||
|
|
||||||
|
|||||||
28
Cargo.lock
generated
28
Cargo.lock
generated
@@ -212,7 +212,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "asusctl"
|
name = "asusctl"
|
||||||
version = "6.2.0"
|
version = "6.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"argh",
|
"argh",
|
||||||
"dmi_id",
|
"dmi_id",
|
||||||
@@ -232,7 +232,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "asusd"
|
name = "asusd"
|
||||||
version = "6.2.0"
|
version = "6.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cargo-husky",
|
"cargo-husky",
|
||||||
"concat-idents",
|
"concat-idents",
|
||||||
@@ -259,7 +259,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "asusd-user"
|
name = "asusd-user"
|
||||||
version = "6.2.0"
|
version = "6.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"config-traits",
|
"config-traits",
|
||||||
"dirs",
|
"dirs",
|
||||||
@@ -938,7 +938,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "config-traits"
|
name = "config-traits"
|
||||||
version = "6.2.0"
|
version = "6.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"ron",
|
"ron",
|
||||||
@@ -1274,7 +1274,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dmi_id"
|
name = "dmi_id"
|
||||||
version = "6.2.0"
|
version = "6.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"udev 0.8.0",
|
"udev 0.8.0",
|
||||||
@@ -4482,7 +4482,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rog-control-center"
|
name = "rog-control-center"
|
||||||
version = "6.2.0"
|
version = "6.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"asusd",
|
"asusd",
|
||||||
"concat-idents",
|
"concat-idents",
|
||||||
@@ -4513,7 +4513,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rog_anime"
|
name = "rog_anime"
|
||||||
version = "6.2.0"
|
version = "6.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dmi_id",
|
"dmi_id",
|
||||||
"gif 0.12.0",
|
"gif 0.12.0",
|
||||||
@@ -4527,7 +4527,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rog_aura"
|
name = "rog_aura"
|
||||||
version = "6.2.0"
|
version = "6.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dmi_id",
|
"dmi_id",
|
||||||
"log",
|
"log",
|
||||||
@@ -4538,7 +4538,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rog_dbus"
|
name = "rog_dbus"
|
||||||
version = "6.2.0"
|
version = "6.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"asusd",
|
"asusd",
|
||||||
"rog_anime",
|
"rog_anime",
|
||||||
@@ -4552,7 +4552,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rog_platform"
|
name = "rog_platform"
|
||||||
version = "6.2.0"
|
version = "6.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"concat-idents",
|
"concat-idents",
|
||||||
"inotify",
|
"inotify",
|
||||||
@@ -4565,7 +4565,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rog_profiles"
|
name = "rog_profiles"
|
||||||
version = "6.2.0"
|
version = "6.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"rog_platform",
|
"rog_platform",
|
||||||
@@ -4576,7 +4576,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rog_scsi"
|
name = "rog_scsi"
|
||||||
version = "6.2.0"
|
version = "6.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ron",
|
"ron",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -4586,7 +4586,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rog_simulators"
|
name = "rog_simulators"
|
||||||
version = "6.2.0"
|
version = "6.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"rog_anime",
|
"rog_anime",
|
||||||
@@ -4596,7 +4596,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rog_slash"
|
name = "rog_slash"
|
||||||
version = "6.2.0"
|
version = "6.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dmi_id",
|
"dmi_id",
|
||||||
"serde",
|
"serde",
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "6.2.0"
|
version = "6.3.0"
|
||||||
rust-version = "1.82"
|
rust-version = "1.82"
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = ["Luke <luke@ljones.dev>"]
|
authors = [
|
||||||
|
"Luke <luke@ljones.dev>",
|
||||||
|
"Denis Benato <benato.denis96@gmail.com>"
|
||||||
|
]
|
||||||
repository = "https://gitlab.com/asus-linux/asusctl"
|
repository = "https://gitlab.com/asus-linux/asusctl"
|
||||||
homepage = "https://gitlab.com/asus-linux/asusctl"
|
homepage = "https://gitlab.com/asus-linux/asusctl"
|
||||||
description = "Laptop feature control for ASUS ROG laptops and others"
|
description = "Laptop feature control for ASUS ROG laptops and others"
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
%global debug_package %{nil}
|
%global debug_package %{nil}
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
%define version 6.2.0
|
%define version 6.3.0
|
||||||
%define specrelease %{?dist}
|
%define specrelease %{?dist}
|
||||||
%define pkg_release 1%{specrelease}
|
%define pkg_release 1%{specrelease}
|
||||||
|
|
||||||
|
|||||||
23
extra/index.html
Normal file
23
extra/index.html
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
|
<title>asusctl docs</title>
|
||||||
|
<!-- Redirect to the generated crate docs -->
|
||||||
|
<meta http-equiv="refresh" content="0;url=asusctl/index.html">
|
||||||
|
<link rel="canonical" href="asusctl/index.html">
|
||||||
|
<style>
|
||||||
|
body { font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial; color:#222; display:flex; align-items:center; justify-content:center; height:100vh; margin:0 }
|
||||||
|
.box { text-align:center }
|
||||||
|
a { color: #0366d6 }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="box">
|
||||||
|
<h1>asusctl documentation</h1>
|
||||||
|
<p>Redirecting to the generated docs — if your browser doesn't redirect automatically, <a href="asusctl/index.html">click here</a>.</p>
|
||||||
|
<p>If you expected a different landing page, update <code>extra/index.html</code> accordingly.</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -566,6 +566,15 @@
|
|||||||
advanced_type: PerKey,
|
advanced_type: PerKey,
|
||||||
power_zones: [Keyboard, Lightbar, Logo, RearGlow],
|
power_zones: [Keyboard, Lightbar, Logo, RearGlow],
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
device_name: "G835L",
|
||||||
|
product_id: "",
|
||||||
|
layout_name: "g814ji-per-key",
|
||||||
|
basic_modes: [Static, Breathe, RainbowCycle, RainbowWave, Star, Rain, Highlight, Laser, Ripple, Pulse, Comet, Flash],
|
||||||
|
basic_zones: [],
|
||||||
|
advanced_type: PerKey,
|
||||||
|
power_zones: [Keyboard, Lightbar, Logo],
|
||||||
|
),
|
||||||
(
|
(
|
||||||
device_name: "GA401I",
|
device_name: "GA401I",
|
||||||
product_id: "",
|
product_id: "",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ mocking = []
|
|||||||
x11 = ["slint/backend-winit-x11"]
|
x11 = ["slint/backend-winit-x11"]
|
||||||
# Optional tokio debug feature does not require nightly; remove RUSTFLAGS note.
|
# Optional tokio debug feature does not require nightly; remove RUSTFLAGS note.
|
||||||
tokio-debug = ["console-subscriber"]
|
tokio-debug = ["console-subscriber"]
|
||||||
|
rog_ally = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
console-subscriber = { version = "^0.4", optional = true }
|
console-subscriber = { version = "^0.4", optional = true }
|
||||||
|
|||||||
@@ -107,7 +107,6 @@ async fn main() -> Result<()> {
|
|||||||
let board_name = dmi.board_name;
|
let board_name = dmi.board_name;
|
||||||
let prod_family = dmi.product_family;
|
let prod_family = dmi.product_family;
|
||||||
info!("Running on {board_name}, product: {prod_family}");
|
info!("Running on {board_name}, product: {prod_family}");
|
||||||
let is_rog_ally = board_name == "RC71L" || board_name == "RC72L" || prod_family == "ROG Ally";
|
|
||||||
|
|
||||||
let args: Vec<String> = args().skip(1).collect();
|
let args: Vec<String> = args().skip(1).collect();
|
||||||
|
|
||||||
@@ -138,6 +137,18 @@ async fn main() -> Result<()> {
|
|||||||
config.start_fullscreen = false;
|
config.start_fullscreen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let is_rog_ally = {
|
||||||
|
#[cfg(feature = "rog_ally")]
|
||||||
|
{
|
||||||
|
board_name == "RC71L" || board_name == "RC72L" || prod_family == "ROG Ally"
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "rog_ally"))]
|
||||||
|
{
|
||||||
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "rog_ally")]
|
||||||
if is_rog_ally {
|
if is_rog_ally {
|
||||||
config.notifications.enabled = false;
|
config.notifications.enabled = false;
|
||||||
config.enable_tray_icon = false;
|
config.enable_tray_icon = false;
|
||||||
@@ -145,6 +156,7 @@ async fn main() -> Result<()> {
|
|||||||
config.startup_in_background = false;
|
config.startup_in_background = false;
|
||||||
config.start_fullscreen = true;
|
config.start_fullscreen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
config.write();
|
config.write();
|
||||||
|
|
||||||
let enable_tray_icon = config.enable_tray_icon;
|
let enable_tray_icon = config.enable_tray_icon;
|
||||||
@@ -203,76 +215,77 @@ async fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
} else {
|
|
||||||
// save as a var, don't hold the lock the entire time or deadlocks happen
|
continue;
|
||||||
if let Ok(app_state) = app_state.lock() {
|
}
|
||||||
state = *app_state;
|
|
||||||
|
// save as a var, don't hold the lock the entire time or deadlocks happen
|
||||||
|
if let Ok(app_state) = app_state.lock() {
|
||||||
|
state = *app_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This sleep is required to give the event loop time to react
|
||||||
|
sleep(Duration::from_millis(300));
|
||||||
|
if state == AppState::MainWindowShouldOpen {
|
||||||
|
if let Ok(mut app_state) = app_state.lock() {
|
||||||
|
*app_state = AppState::MainWindowOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This sleep is required to give the event loop time to react
|
let config_copy = config.clone();
|
||||||
sleep(Duration::from_millis(300));
|
let app_state_copy = app_state.clone();
|
||||||
if state == AppState::MainWindowShouldOpen {
|
slint::invoke_from_event_loop(move || {
|
||||||
if let Ok(mut app_state) = app_state.lock() {
|
UI.with(|ui| {
|
||||||
*app_state = AppState::MainWindowOpen;
|
let app_state_copy = app_state_copy.clone();
|
||||||
}
|
let mut ui = ui.borrow_mut();
|
||||||
|
if let Some(ui) = ui.as_mut() {
|
||||||
|
ui.window().show().unwrap();
|
||||||
|
ui.window().on_close_requested(move || {
|
||||||
|
if let Ok(mut app_state) = app_state_copy.lock() {
|
||||||
|
*app_state = AppState::MainWindowClosed;
|
||||||
|
}
|
||||||
|
slint::CloseRequestResponse::HideWindow
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
let config_copy_2 = config_copy.clone();
|
||||||
|
let newui = setup_window(config_copy);
|
||||||
|
newui.window().on_close_requested(move || {
|
||||||
|
if let Ok(mut app_state) = app_state_copy.lock() {
|
||||||
|
*app_state = AppState::MainWindowClosed;
|
||||||
|
}
|
||||||
|
slint::CloseRequestResponse::HideWindow
|
||||||
|
});
|
||||||
|
|
||||||
let config_copy = config.clone();
|
let ui_copy = newui.as_weak();
|
||||||
let app_state_copy = app_state.clone();
|
newui
|
||||||
slint::invoke_from_event_loop(move || {
|
.window()
|
||||||
UI.with(|ui| {
|
.set_rendering_notifier(move |s, _| {
|
||||||
let app_state_copy = app_state_copy.clone();
|
if let slint::RenderingState::RenderingSetup = s {
|
||||||
let mut ui = ui.borrow_mut();
|
let config = config_copy_2.clone();
|
||||||
if let Some(ui) = ui.as_mut() {
|
ui_copy
|
||||||
ui.window().show().unwrap();
|
.upgrade_in_event_loop(move |w| {
|
||||||
ui.window().on_close_requested(move || {
|
let fullscreen =
|
||||||
if let Ok(mut app_state) = app_state_copy.lock() {
|
config.lock().is_ok_and(|c| c.start_fullscreen);
|
||||||
*app_state = AppState::MainWindowClosed;
|
if fullscreen && !w.window().is_fullscreen() {
|
||||||
|
w.window().set_fullscreen(fullscreen);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
}
|
}
|
||||||
slint::CloseRequestResponse::HideWindow
|
})
|
||||||
});
|
.ok();
|
||||||
} else {
|
ui.replace(newui);
|
||||||
let config_copy_2 = config_copy.clone();
|
|
||||||
let newui = setup_window(config_copy);
|
|
||||||
newui.window().on_close_requested(move || {
|
|
||||||
if let Ok(mut app_state) = app_state_copy.lock() {
|
|
||||||
*app_state = AppState::MainWindowClosed;
|
|
||||||
}
|
|
||||||
slint::CloseRequestResponse::HideWindow
|
|
||||||
});
|
|
||||||
|
|
||||||
let ui_copy = newui.as_weak();
|
|
||||||
newui
|
|
||||||
.window()
|
|
||||||
.set_rendering_notifier(move |s, _| {
|
|
||||||
if let slint::RenderingState::RenderingSetup = s {
|
|
||||||
let config = config_copy_2.clone();
|
|
||||||
ui_copy
|
|
||||||
.upgrade_in_event_loop(move |w| {
|
|
||||||
let fullscreen = config
|
|
||||||
.lock()
|
|
||||||
.is_ok_and(|c| c.start_fullscreen);
|
|
||||||
if fullscreen && !w.window().is_fullscreen() {
|
|
||||||
w.window().set_fullscreen(fullscreen);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
ui.replace(newui);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
} else if state == AppState::QuitApp {
|
|
||||||
slint::quit_event_loop().unwrap();
|
|
||||||
exit(0);
|
|
||||||
} else if state != AppState::MainWindowOpen {
|
|
||||||
if let Ok(config) = config.lock() {
|
|
||||||
if !config.run_in_background {
|
|
||||||
slint::quit_event_loop().unwrap();
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
} else if state == AppState::QuitApp {
|
||||||
|
slint::quit_event_loop().unwrap();
|
||||||
|
exit(0);
|
||||||
|
} else if state != AppState::MainWindowOpen {
|
||||||
|
if let Ok(config) = config.lock() {
|
||||||
|
if !config.run_in_background {
|
||||||
|
slint::quit_event_loop().unwrap();
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,15 +9,11 @@ use std::process::Command;
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use futures_util::StreamExt;
|
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
use notify_rust::{Hint, Notification, Timeout, Urgency};
|
use notify_rust::{Hint, Notification, Timeout};
|
||||||
use rog_platform::platform::GpuMode;
|
|
||||||
use rog_platform::power::AsusPower;
|
use rog_platform::power::AsusPower;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use supergfxctl::actions::UserActionRequired as GfxUserAction;
|
use supergfxctl::pci_device::GfxPower;
|
||||||
use supergfxctl::pci_device::{GfxMode, GfxPower};
|
|
||||||
use supergfxctl::zbus_proxy::DaemonProxy as SuperProxy;
|
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
|
|
||||||
@@ -145,12 +141,8 @@ pub fn start_notifications(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let enabled_notifications_copy = config.clone();
|
info!("Attempting to start plain dgpu status monitor");
|
||||||
let no_supergfx = move |e: &zbus::Error| {
|
start_dpu_status_mon(config.clone());
|
||||||
error!("zbus signal: receive_notify_gfx_status: {e}");
|
|
||||||
warn!("Attempting to start plain dgpu status monitor");
|
|
||||||
start_dpu_status_mon(enabled_notifications_copy.clone());
|
|
||||||
};
|
|
||||||
|
|
||||||
// GPU MUX Mode notif
|
// GPU MUX Mode notif
|
||||||
// TODO: need to get armoury attrs and iter to find
|
// TODO: need to get armoury attrs and iter to find
|
||||||
@@ -189,95 +181,9 @@ pub fn start_notifications(
|
|||||||
// Ok::<(), zbus::Error>(())
|
// Ok::<(), zbus::Error>(())
|
||||||
// });
|
// });
|
||||||
|
|
||||||
let enabled_notifications_copy = config.clone();
|
|
||||||
// GPU Mode change/action notif
|
|
||||||
tokio::spawn(async move {
|
|
||||||
let conn = zbus::Connection::system().await.inspect_err(|e| {
|
|
||||||
no_supergfx(e);
|
|
||||||
})?;
|
|
||||||
let proxy = SuperProxy::builder(&conn).build().await.inspect_err(|e| {
|
|
||||||
no_supergfx(e);
|
|
||||||
})?;
|
|
||||||
let _ = proxy.mode().await.inspect_err(|e| {
|
|
||||||
no_supergfx(e);
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let proxy_copy = proxy.clone();
|
|
||||||
let enabled_notifications_copy_action = enabled_notifications_copy.clone();
|
|
||||||
let mut p = proxy.receive_notify_action().await?;
|
|
||||||
tokio::spawn(async move {
|
|
||||||
info!("Started zbus signal thread: receive_notify_action");
|
|
||||||
while let Some(e) = p.next().await {
|
|
||||||
if let Ok(out) = e.args() {
|
|
||||||
// Respect user notification settings for gpu actions
|
|
||||||
if let Ok(cfg) = enabled_notifications_copy_action.lock() {
|
|
||||||
if !cfg.notifications.enabled || !cfg.notifications.receive_notify_gfx {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let action = out.action();
|
|
||||||
let mode = convert_gfx_mode(proxy.mode().await.unwrap_or_default());
|
|
||||||
match action {
|
|
||||||
supergfxctl::actions::UserActionRequired::Reboot => {
|
|
||||||
do_mux_notification("Graphics mode change requires reboot", &mode)
|
|
||||||
}
|
|
||||||
_ => do_gfx_action_notif(<&str>::from(action), *action, mode),
|
|
||||||
}
|
|
||||||
.map_err(|e| {
|
|
||||||
error!("zbus signal: do_gfx_action_notif: {e}");
|
|
||||||
e
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut p = proxy_copy.receive_notify_gfx_status().await?;
|
|
||||||
tokio::spawn(async move {
|
|
||||||
info!("Started zbus signal thread: receive_notify_gfx_status");
|
|
||||||
let mut last_status = GfxPower::Unknown;
|
|
||||||
while let Some(e) = p.next().await {
|
|
||||||
if let Ok(out) = e.args() {
|
|
||||||
let status = out.status;
|
|
||||||
if status != GfxPower::Unknown && status != last_status {
|
|
||||||
if let Ok(config) = enabled_notifications_copy.lock() {
|
|
||||||
if !config.notifications.receive_notify_gfx_status
|
|
||||||
|| !config.notifications.enabled
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Required check because status cycles through
|
|
||||||
// active/unknown/suspended
|
|
||||||
do_gpu_status_notif("dGPU status changed:", &status)
|
|
||||||
.show_async()
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.on_close(|_| ());
|
|
||||||
}
|
|
||||||
last_status = status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Ok::<(), zbus::Error>(())
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(vec![blocking])
|
Ok(vec![blocking])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_gfx_mode(gfx: GfxMode) -> GpuMode {
|
|
||||||
match gfx {
|
|
||||||
GfxMode::Hybrid => GpuMode::Optimus,
|
|
||||||
GfxMode::Integrated => GpuMode::Integrated,
|
|
||||||
GfxMode::NvidiaNoModeset => GpuMode::Optimus,
|
|
||||||
GfxMode::Vfio => GpuMode::Vfio,
|
|
||||||
GfxMode::AsusEgpu => GpuMode::Egpu,
|
|
||||||
GfxMode::AsusMuxDgpu => GpuMode::Ultimate,
|
|
||||||
GfxMode::None => GpuMode::Error,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn base_notification<T>(message: &str, data: &T) -> Notification
|
fn base_notification<T>(message: &str, data: &T) -> Notification
|
||||||
where
|
where
|
||||||
T: Display,
|
T: Display,
|
||||||
@@ -303,97 +209,3 @@ fn do_gpu_status_notif(message: &str, data: &GfxPower) -> Notification {
|
|||||||
notif.icon(icon);
|
notif.icon(icon);
|
||||||
notif
|
notif
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_gfx_action_notif(message: &str, action: GfxUserAction, mode: GpuMode) -> Result<()> {
|
|
||||||
if matches!(action, GfxUserAction::Reboot) {
|
|
||||||
do_mux_notification("Graphics mode change requires reboot", &mode).ok();
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut notif = Notification::new();
|
|
||||||
notif
|
|
||||||
.appname(NOTIF_HEADER)
|
|
||||||
.summary(&format!("Changing to {mode}. {message}"))
|
|
||||||
//.hint(Hint::Resident(true))
|
|
||||||
.hint(Hint::Category("device".into()))
|
|
||||||
.urgency(Urgency::Critical)
|
|
||||||
// For user-action notifications keep them visible if they require interaction
|
|
||||||
// but for non-interactive actions we prefer they auto-hide like other notifs.
|
|
||||||
.timeout(Timeout::Milliseconds(6000))
|
|
||||||
.icon("dialog-warning")
|
|
||||||
.hint(Hint::Transient(true));
|
|
||||||
|
|
||||||
if matches!(action, GfxUserAction::Logout) {
|
|
||||||
notif.action("gfx-mode-session-action", "Logout");
|
|
||||||
let handle = notif.show()?;
|
|
||||||
if let Ok(desktop) = std::env::var("XDG_CURRENT_DESKTOP") {
|
|
||||||
if desktop.to_lowercase() == "gnome" {
|
|
||||||
handle.wait_for_action(|id| {
|
|
||||||
if id == "gfx-mode-session-action" {
|
|
||||||
let mut cmd = Command::new("gnome-session-quit");
|
|
||||||
cmd.spawn().ok();
|
|
||||||
} else if id == "__closed" {
|
|
||||||
// TODO: cancel the switching
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if desktop.to_lowercase() == "kde" {
|
|
||||||
handle.wait_for_action(|id| {
|
|
||||||
if id == "gfx-mode-session-action" {
|
|
||||||
let mut cmd = Command::new("qdbus");
|
|
||||||
cmd.args([
|
|
||||||
"org.kde.ksmserver", "/KSMServer", "logout", "1", "0", "0",
|
|
||||||
]);
|
|
||||||
cmd.spawn().ok();
|
|
||||||
} else if id == "__closed" {
|
|
||||||
// TODO: cancel the switching
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// todo: handle alternatives
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
notif.show()?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Actual `GpuMode` unused as data is never correct until switched by reboot
|
|
||||||
fn do_mux_notification(message: &str, m: &GpuMode) -> Result<()> {
|
|
||||||
let mut notif = base_notification(message, &m.to_string());
|
|
||||||
notif
|
|
||||||
.action("gfx-mode-session-action", "Reboot")
|
|
||||||
.urgency(Urgency::Critical)
|
|
||||||
.icon("system-reboot-symbolic")
|
|
||||||
.hint(Hint::Transient(true));
|
|
||||||
let handle = notif.show()?;
|
|
||||||
|
|
||||||
std::thread::spawn(|| {
|
|
||||||
if let Ok(desktop) = std::env::var("XDG_CURRENT_DESKTOP") {
|
|
||||||
if desktop.to_lowercase() == "gnome" {
|
|
||||||
handle.wait_for_action(|id| {
|
|
||||||
if id == "gfx-mode-session-action" {
|
|
||||||
let mut cmd = Command::new("gnome-session-quit");
|
|
||||||
cmd.arg("--reboot");
|
|
||||||
cmd.spawn().ok();
|
|
||||||
} else if id == "__closed" {
|
|
||||||
// TODO: cancel the switching
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if desktop.to_lowercase() == "kde" {
|
|
||||||
handle.wait_for_action(|id| {
|
|
||||||
if id == "gfx-mode-session-action" {
|
|
||||||
let mut cmd = Command::new("qdbus");
|
|
||||||
cmd.args([
|
|
||||||
"org.kde.ksmserver", "/KSMServer", "logout", "1", "1", "0",
|
|
||||||
]);
|
|
||||||
cmd.spawn().ok();
|
|
||||||
} else if id == "__closed" {
|
|
||||||
// TODO: cancel the switching
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user