From 7dc391d20574e864e3aee06679912aea76647877 Mon Sep 17 00:00:00 2001 From: Nikita Gladkikh <57749142+BrenOne@users.noreply.github.com> Date: Mon, 2 Nov 2026 23:21:49 +1000 Subject: [PATCH 1/2] Windows: switch the strip off when shutdown is queried Windows sends WM_QUERYENDSESSION and then WM_ENDSESSION. tao's own window calls exit(0) on WM_ENDSESSION at once, so our hidden window's Shutdown request (a USB write) often never finished and the strip stayed lit. The strip now goes dark on the query, which tao ignores, and lights up again if the shutdown is cancelled. Co-Authored-By: Claude Sonnet 5.5 --- src-tauri/src/engine.rs | 11 +++++++++++ src-tauri/src/lifecycle.rs | 22 ++++++++++++++++++++++ src-tauri/src/lifecycle_windows.rs | 10 +++++++++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/engine.rs b/src-tauri/src/engine.rs index 6fa5f9d..6bd2435 100644 --- a/src-tauri/src/engine.rs +++ b/src-tauri/src/engine.rs @@ -555,6 +555,7 @@ impl Engine { | SystemEvent::Locked(true) | SystemEvent::DisplayOff(true) | SystemEvent::Away(Away::OtherUser | Away::Remote) + | SystemEvent::Ending(true) ) { self.extension = None; self.external_cue = None; @@ -597,6 +598,16 @@ impl Engine { .close(self.life.pause_reason(&self.state.settings)); } } + SystemEvent::Ending(ending) => { + if ending == self.life.ending { + return; + } + self.life.ending = ending; + if ending && self.state.settings.off_on_quit { + self.black(); + self.controller.close("Computer shutting down"); + } + } SystemEvent::SourcesChanged => { if self.state.capturing && self.state.settings.mode == "blend" { self.lose_blend_source(true); diff --git a/src-tauri/src/lifecycle.rs b/src-tauri/src/lifecycle.rs index 60d85ca..55b3dec 100644 --- a/src-tauri/src/lifecycle.rs +++ b/src-tauri/src/lifecycle.rs @@ -12,6 +12,10 @@ pub enum SystemEvent { /// Only Windows reports it. #[cfg_attr(not(target_os = "windows"), allow(dead_code))] Away(Away), + /// Windows is about to end the session (shutdown, restart, sign-out); `false` + /// when something cancelled it. Only Windows reports it. + #[cfg_attr(not(target_os = "windows"), allow(dead_code))] + Ending(bool), SourcesChanged, #[cfg(target_os = "linux")] AudioChanged, @@ -41,6 +45,7 @@ pub struct Lifecycle { pub display_off: bool, pub locked: bool, pub away: Away, + pub ending: bool, } impl Lifecycle { pub fn pause_reason(&self, s: &Settings) -> &'static str { @@ -52,6 +57,8 @@ impl Lifecycle { "Remote desktop session" } else if self.away == Away::OtherUser { "Another Windows user is active" + } else if self.ending && s.off_on_quit { + "Computer shutting down" } else if self.locked && s.off_on_lock { "Computer locked" } else if self.display_off && s.off_on_display_sleep { @@ -154,4 +161,19 @@ mod tests { std::fs::write(&path, b"invalid").unwrap(); assert!(SavedIntent::load(&path).is_err()); } + + #[test] + fn ending_session_pauses_only_when_the_strip_goes_off_on_quit() { + let mut life = Lifecycle { + requested: true, + ..Default::default() + }; + let mut s = Settings::default(); + assert!(life.active(&s)); + life.ending = true; + s.off_on_quit = true; + assert_eq!(life.pause_reason(&s), "Computer shutting down"); + s.off_on_quit = false; + assert!(life.active(&s)); + } } diff --git a/src-tauri/src/lifecycle_windows.rs b/src-tauri/src/lifecycle_windows.rs index 71c711d..a211797 100644 --- a/src-tauri/src/lifecycle_windows.rs +++ b/src-tauri/src/lifecycle_windows.rs @@ -95,10 +95,18 @@ unsafe extern "system" fn window_proc( WM_DISPLAYCHANGE => handle.system_event(SystemEvent::SourcesChanged, false), // Windows shutdown/restart/sign-out: turn the strip off before the process is // killed, otherwise USB power keeps the last frame lit. - WM_QUERYENDSESSION => return LRESULT(1), + // The strip goes dark already on the query: when the session really ends, + // tao's window calls exit(0) on its own WM_ENDSESSION at once, which would + // kill this process before the USB frame below is written. + WM_QUERYENDSESSION => { + handle.system_event(SystemEvent::Ending(true), true); + return LRESULT(1); + } WM_ENDSESSION if wparam.0 != 0 => { let _ = handle.request(crate::engine::Action::Shutdown); } + // Something cancelled the shutdown: light up again. + WM_ENDSESSION => handle.system_event(SystemEvent::Ending(false), false), _ => {} } } From 8989d0268cb0a77188c9982ea175f04b0827c891 Mon Sep 17 00:00:00 2001 From: Nikita Gladkikh <57749142+BrenOne@users.noreply.github.com> Date: Mon, 2 Nov 2026 23:40:14 +1000 Subject: [PATCH 2/2] Release 1.0.4 Co-Authored-By: Claude Sonnet 5.5 --- control/Cargo.lock | 2 +- control/Cargo.toml | 2 +- package.json | 2 +- src-tauri/Cargo.lock | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/control/Cargo.lock b/control/Cargo.lock index faa7788..a63f9e1 100644 --- a/control/Cargo.lock +++ b/control/Cargo.lock @@ -37,7 +37,7 @@ dependencies = [ [[package]] name = "dynamiclight-control" -version = "1.0.3" +version = "1.0.4" dependencies = [ "dirs", "getrandom 0.3.4", diff --git a/control/Cargo.toml b/control/Cargo.toml index 3d547f2..4e37b80 100644 --- a/control/Cargo.toml +++ b/control/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dynamiclight-control" -version = "1.0.3" +version = "1.0.4" edition = "2021" license = "MIT" rust-version = "1.99" diff --git a/package.json b/package.json index 6a31037..57fe07a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dynamiclight", - "version": "1.0.3", + "version": "1.0.4", "private": true, "license": "MIT", "author": "mskutin", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index b3d05f5..2014172 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1227,7 +1227,7 @@ checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "dynamiclight" -version = "1.0.3" +version = "1.0.4" dependencies = [ "cc", "chrono", @@ -1256,7 +1256,7 @@ dependencies = [ [[package]] name = "dynamiclight-control" -version = "1.0.3" +version = "1.0.4" dependencies = [ "dirs 6.0.0", "getrandom 0.3.4", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 5a4d2fa..27d946b 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dynamiclight" -version = "1.0.3" +version = "1.0.4" description = "Local USB monitor backlight controller" authors = ["mskutin"] license = "MIT" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index dbd9423..24e33ca 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "DynamicLight", - "version": "1.0.3", + "version": "1.0.4", "identifier": "com.dynamiclight.desktop", "build": { "frontendDist": "../src/ui"