git.lucas.co / cce-display-manager
login greeter
git clone https://git.lucas.co/cce-display-manager.git

commitdab36d706113954891320f8efa03a5017e131380
parent9740a28a87
authorLucas Galante <[email protected]>
date2026-05-28 21:06
feat: add ctrl+c keybinding to close display manager and return to TTY

 src/main.rs | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/main.rs b/src/main.rs
index 28f40be..844c355 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1116,6 +1116,13 @@ impl PointerHandler for AppState {
 impl AppState {
     fn handle_key(&mut self, event: smithay_client_toolkit::seat::keyboard::KeyEvent, state: ElementState) {
         let keysym = event.keysym;
+
+        // Check for Ctrl+C to abort/exit back to TTY
+        if self.ctrl_pressed && (keysym == xkeysym::Keysym::c || keysym == xkeysym::Keysym::C) {
+            eprintln!("[clear-display-manager] Ctrl+C pressed. Aborting greeter.");
+            std::process::exit(130);
+        }
+
         let logical_key = match keysym {
             xkeysym::Keysym::BackSpace => Key::Named(NamedKey::Backspace),
             xkeysym::Keysym::Tab => Key::Named(NamedKey::Tab),
@@ -1485,6 +1492,11 @@ fn run_daemon() {
         let status = child.wait().expect("failed to wait on child process");
         println!("[clear-display-manager] Greeter session exited with status: {}", status);
 
+        if status.code() == Some(130) {
+            println!("[clear-display-manager] Abort requested via Ctrl+C. Exiting display manager daemon.");
+            std::process::exit(0);
+        }
+
         if let Some((username, exec, is_wayland)) = auth_success {
             println!("[clear-display-manager] Launching user session Exec: '{}' (Wayland: {}) for user: '{}'", exec, is_wayland, username);