M6: autohide/dodge, hot corners/edges, Wayfire-eventström, urgency
Some checks failed
check / check (push) Failing after 13s

Autohide med Revealer-animation + sensorremsa vid kanten; dodge räknar
fönsteröverlapp via Wayfire-IPC-geometri, helt händelsestyrt via
window-rules/events/watch (ingen polling). Hotspot-ytor för hörn/kanter
med dwell + exec/ipc-actions. Urgency-puls via view-hints-changed.
IPC-socketen hittas även när pluginen aktiverats efter sessionsstart.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-29 23:34:32 +02:00
parent bc2fa65558
commit 95d342ae9e
5 changed files with 596 additions and 34 deletions

View File

@@ -3,6 +3,7 @@
mod config;
mod dock;
mod hotspots;
mod icons;
mod menu;
mod settings;
@@ -110,7 +111,7 @@ fn layout_signature(cfg: &config::Config) -> String {
cfg.appearance.shadow.enabled,
cfg.appearance.shadow.blur,
cfg.outputs.keys().collect::<Vec<_>>(),
)
) + &format!("|{:?}", cfg.autohide)
}
fn main() -> glib::ExitCode {
@@ -149,6 +150,8 @@ fn activate(app: &gtk::Application, cfg_path: PathBuf) {
app: app.clone(),
on_config_changed: RefCell::new(None),
save_generation: Cell::new(0),
urgent: RefCell::new(Default::default()),
hotspot_windows: RefCell::new(Vec::new()),
});
// CSS + rebuild/refresh-logik
@@ -170,6 +173,7 @@ fn activate(app: &gtk::Application, cfg_path: PathBuf) {
} else {
dock::refresh_items(&ctx2);
}
hotspots::rebuild(&ctx2);
});
*ctx.on_config_changed.borrow_mut() = Some(apply);
}
@@ -186,8 +190,10 @@ fn activate(app: &gtk::Application, cfg_path: PathBuf) {
}
}
if !wayfire_ipc::available() {
warn!("WAYFIRE_SOCKET saknas — översikt/flytta-till-skärm/dodge avstängda (aktivera ipc-pluginen i wayfire.ini)");
if wayfire_ipc::available() {
subscribe_wayfire_events(&ctx);
} else {
warn!("Wayfire-IPC saknas — översikt/flytta-till-skärm/dodge avstängda (aktivera ipc-pluginen i wayfire.ini)");
}
// första uppritningen
@@ -230,3 +236,66 @@ fn activate(app: &gtk::Application, cfg_path: PathBuf) {
});
}
}
/// Händelsestyrd dodge + urgency via Wayfires eventström.
fn subscribe_wayfire_events(ctx: &Rc<dock::Ctx>) {
let ctx2 = ctx.clone();
let pending = Rc::new(Cell::new(0u64));
let result = wayfire_ipc::subscribe(Rc::new(move |ev| {
let name = ev["event"].as_str().unwrap_or("");
match name {
"view-hints-changed" => {
let view = &ev["view"];
let app_id = view["app-id"].as_str().unwrap_or("");
if app_id.is_empty() {
return;
}
let key = icons::lookup(app_id).key;
let wants = ev["hints"]["demands-attention"].as_bool()
.or_else(|| view["demands-attention"].as_bool())
.unwrap_or(false);
let changed = if wants {
ctx2.urgent.borrow_mut().insert(key)
} else {
ctx2.urgent.borrow_mut().remove(&key)
};
if changed {
dock::refresh_items(&ctx2);
}
}
"view-focused" => {
let app_id = ev["view"]["app-id"].as_str().unwrap_or("");
if !app_id.is_empty() {
let key = icons::lookup(app_id).key;
if ctx2.urgent.borrow_mut().remove(&key) {
dock::refresh_items(&ctx2);
}
}
schedule_dodge(&ctx2, &pending);
}
n if n.starts_with("view-") || n.starts_with("output-") => {
schedule_dodge(&ctx2, &pending);
}
_ => {}
}
}));
if let Err(e) = result {
warn!("kunde inte prenumerera på wayfire-events: {e}");
}
}
/// Debounca dodge-omräkningen (events kommer i skurar).
fn schedule_dodge(ctx: &Rc<dock::Ctx>, pending: &Rc<Cell<u64>>) {
if !ctx.cfg.borrow().autohide.enabled {
return;
}
let generation = pending.get() + 1;
pending.set(generation);
let ctx = ctx.clone();
let pending = pending.clone();
glib::timeout_add_local_once(Duration::from_millis(120), move || {
if pending.get() == generation {
dock::recompute_dodge(&ctx);
}
});
}