@@ -46,6 +46,10 @@ async fn main() -> Result<()> { |
| 46 | 46 | |
| 47 | 47 | tracing::info!("gardm-greeter starting"); |
| 48 | 48 | |
| 49 | + // Kill any running compositor that might be left over from a previous session |
| 50 | + // These would render on top of the greeter and block visibility |
| 51 | + kill_leftover_compositors(); |
| 52 | + |
| 49 | 53 | // Load configuration |
| 50 | 54 | let config = GreeterConfig::load().unwrap_or_default(); |
| 51 | 55 | tracing::debug!(?config, "Greeter configuration"); |
@@ -626,3 +630,30 @@ fn render_tooltip( |
| 626 | 630 | |
| 627 | 631 | Ok(()) |
| 628 | 632 | } |
| 633 | + |
| 634 | +/// Kill any compositors that might be left over from a previous session |
| 635 | +/// |
| 636 | +/// When a user logs out, their compositor (garchomp, picom) may not exit cleanly |
| 637 | +/// and will continue rendering on top of the greeter. We must kill these before |
| 638 | +/// the greeter can be visible. |
| 639 | +fn kill_leftover_compositors() { |
| 640 | + use std::process::Command; |
| 641 | + |
| 642 | + let compositors = ["garchomp", "picom", "compton", "xcompmgr"]; |
| 643 | + |
| 644 | + for name in compositors { |
| 645 | + match Command::new("pkill").args(["-x", name]).status() { |
| 646 | + Ok(status) if status.success() => { |
| 647 | + tracing::info!("Killed leftover compositor: {}", name); |
| 648 | + // Give it a moment to exit and release X resources |
| 649 | + std::thread::sleep(std::time::Duration::from_millis(100)); |
| 650 | + } |
| 651 | + Ok(_) => { |
| 652 | + // Process not found, which is fine |
| 653 | + } |
| 654 | + Err(e) => { |
| 655 | + tracing::warn!("Failed to kill {}: {}", name, e); |
| 656 | + } |
| 657 | + } |
| 658 | + } |
| 659 | +} |