test(linux): verify the KWin script against the live Plasma session
The KWin JavaScript had never been executed. It is now.
A probe script was loaded into the running Plasma 6.6.6 compositor, which
reported:
js: PROBE: activated resourceClass=org.kde.konsole resourceName=konsole
caption=... internalId={6866aecf-...} pid=4147
js: PROBE: activated resourceClass=Spotify resourceName=spotify
caption=... internalId={c99b88b4-...} pid=74378
The probe was unloaded immediately afterwards and `isScriptLoaded` confirmed
`false`.
**This proved one thing I had wrong.** The file asserted that "KWin does not
expose the PID to scripts, so resolution happens on the Rust side from
resource_class." It does expose it — `pid=4147` for Konsole, `pid=74378` for
Spotify. The payload now carries it, and the daemon can resolve
`/proc/<pid>/exe` directly instead of inferring an application from its
resource class. Inferring from `resourceClass` would have been a guess, and a
wrong guess blocks the wrong application.
Also confirmed: `workspace.windowActivated` exists and fires on real window
changes, and `resourceClass`, `resourceName`, `caption` and `internalId` are all
readable from a script.
**Still unverified, and stated as such in the module:** the D-Bus leg — whether
`callDBus` from inside the script reaches an exported daemon interface. That half
is ordinary Rust and needs no compositor, so it is exercised by an integration
test rather than by touching a live session again.
Also records ADR-6 as accepted: the owner chose **egui** for the block screen,
so the UI toolkit is no longer a blocker. Reasoning is in the ADR, including the
licence entanglement — Slint is GPL-3.0, which is why ADR-17 sits upstream of
this decision.
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -47,11 +47,24 @@
|
||||
//! .isScriptLoaded method s b
|
||||
//! ```
|
||||
//!
|
||||
//! The KWin *JavaScript* API — `workspace.windowActivated`, `client.resourceClass`
|
||||
//! — is written against the documented Plasma 6 scripting surface and has **not**
|
||||
//! been executed against a live KWin yet, because doing so would load a script
|
||||
//! into the user's running compositor. That is the honest status, and
|
||||
//! `LIMITATIONS.md` records it.
|
||||
//! The KWin *JavaScript* API has been **executed against the live session**. A
|
||||
//! probe script was loaded into the running Plasma 6.6.6, which printed:
|
||||
//!
|
||||
//! ```text
|
||||
//! js: PROBE: activated resourceClass=org.kde.konsole resourceName=konsole
|
||||
//! caption=... internalId={6866aecf-...} pid=4147
|
||||
//! js: PROBE: activated resourceClass=Spotify resourceName=spotify
|
||||
//! caption=... internalId={c99b88b4-...} pid=74378
|
||||
//! ```
|
||||
//!
|
||||
//! That confirmed `workspace.windowActivated` exists and fires, and that
|
||||
//! `resourceClass`, `resourceName`, `caption`, `internalId` and — contrary to an
|
||||
//! earlier assumption in this file — **`pid`** are all readable from a script.
|
||||
//! The probe was unloaded immediately afterwards and verified gone.
|
||||
//!
|
||||
//! What remains unverified is the D-Bus leg: whether `callDBus` from inside the
|
||||
//! script reaches the daemon's exported interface. That half is ordinary Rust
|
||||
//! and is exercised by the integration test in M2.
|
||||
|
||||
use std::sync::mpsc::Sender;
|
||||
|
||||
@@ -92,12 +105,19 @@ function reportFocus(client) {
|
||||
"Focused", "", function(err) {}, 0);
|
||||
return;
|
||||
}
|
||||
// resourceClass is the most stable identifier KWin offers; caption changes
|
||||
// constantly and internalId is not stable across restarts.
|
||||
// resourceClass is the stable identifier; caption changes constantly and
|
||||
// internalId is not stable across restarts.
|
||||
//
|
||||
// pid is included because it is EXPOSED — verified on Plasma 6.6.6, where a
|
||||
// probe script printed `pid=4147` for Konsole and `pid=74378` for Spotify.
|
||||
// An earlier version of this file asserted that KWin hid the pid from
|
||||
// scripts, and that was wrong; with a real pid the daemon can resolve
|
||||
// /proc/<pid>/exe instead of inferring an app from its resource class.
|
||||
var payload = (client.resourceClass || "") + "\t" +
|
||||
(client.resourceName || "") + "\t" +
|
||||
(client.caption || "") + "\t" +
|
||||
String(client.internalId || "");
|
||||
String(client.internalId || "") + "\t" +
|
||||
String(client.pid || "");
|
||||
callDBus("vu.valiq.blocker", "/Watcher", "vu.valiq.blocker.Watcher",
|
||||
"Focused", payload, function(err) {}, 0);
|
||||
}
|
||||
@@ -261,12 +281,12 @@ pub fn parse_payload(payload: &str) -> Option<ForegroundWindow> {
|
||||
let resource_name = parts.next().unwrap_or_default();
|
||||
let caption = parts.next().unwrap_or_default();
|
||||
let internal_id = parts.next().unwrap_or_default();
|
||||
let pid = parts.next().and_then(|p| p.trim().parse::<u32>().ok());
|
||||
|
||||
Some(ForegroundWindow {
|
||||
handle: internal_id.to_owned(),
|
||||
// KWin does not expose the PID to scripts, so resolution happens on the
|
||||
// Rust side from resource_class. Left `None` rather than guessed.
|
||||
pid: None,
|
||||
// Present on Plasma 6 — see the note in SCRIPT_JS.
|
||||
pid,
|
||||
exe_path: None,
|
||||
title: (!caption.is_empty()).then(|| caption.to_owned()),
|
||||
desktop_id: (!resource_class.is_empty())
|
||||
|
||||
Reference in New Issue
Block a user