use anyhow::Result;
use std::env::temp_dir;
use std::path::Path;
use zbus::{block_on, Connection};
pub struct AdhocScriptHandler {}
impl AdhocScriptHandler {
pub fn new() -> Self {
Self {}
}
pub fn run_script(&self, script: &str) -> Result<()> {
let conn = block_on(Connection::session())?;
let path = temp_dir().join("xremap-oneoff-script.js");
std::fs::write(&path, script)?;
let script_id = self.dbus_load_script(&conn, &path)?;
self.dbus_run_script(&conn, script_id)?;
std::fs::remove_file(&path)?;
self.dbus_unload_script(&conn, script_id)
}
fn get_dbus_script_path(&self, script_id: i32) -> Result<String> {
if std::env::var("KDE_SESSION_VERSION")? == "5" {
Ok(format!("/{script_id}"))
} else {
Ok(format!("/Scripting/Script{script_id}"))
}
}
fn dbus_load_script(&self, conn: &Connection, path: &Path) -> Result<i32> {
let result = block_on(conn.call_method(
Some("org.kde.KWin"),
"/Scripting",
Some("org.kde.kwin.Scripting"),
"loadScript",
&path,
));
Ok(result?.body().deserialize::<i32>()?)
}
fn dbus_run_script(&self, conn: &Connection, script_id: i32) -> Result<()> {
block_on(conn.call_method(
Some("org.kde.KWin"),
self.get_dbus_script_path(script_id)?,
Some("org.kde.kwin.Script"),
"run",
&(),
))?;
Ok(())
}
fn dbus_unload_script(&self, conn: &Connection, script_id: i32) -> Result<()> {
block_on(conn.call_method(
Some("org.kde.KWin"),
self.get_dbus_script_path(script_id)?,
Some("org.kde.kwin.Script"),
"stop",
&(),
))?;
Ok(())
}
}