oxwm

https://git.tonybtw.com/oxwm.git git://git.tonybtw.com/oxwm.git

Added proper error handling for when a user logs in to a deprecated config.

Commit
2d0ce7825c6353a42f12e3dccd6f032122174bb8
Parent
115e1de
Author
tonybtw <tonybtw@tonybtw.com>
Date
2025-11-13 05:44:07

Diff

diff --git a/Cargo.lock b/Cargo.lock
index d90c691..e029d9b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -297,7 +297,7 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
 
 [[package]]
 name = "oxwm"
-version = "0.6.0"
+version = "0.7.0"
 dependencies = [
  "anyhow",
  "chrono",
diff --git a/src/bin/main.rs b/src/bin/main.rs
index 484fa22..1fb28d6 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -30,9 +30,14 @@ fn main() -> Result<()> {
         _ => {}
     }
 
-    let config = load_config(custom_config_path)?;
+    let (config, had_broken_config) = load_config(custom_config_path)?;
 
     let mut wm = oxwm::window_manager::WindowManager::new(config)?;
+
+    if had_broken_config {
+        wm.show_migration_overlay();
+    }
+
     let should_restart = wm.run()?;
 
     drop(wm);
@@ -46,7 +51,7 @@ fn main() -> Result<()> {
     Ok(())
 }
 
-fn load_config(custom_path: Option<PathBuf>) -> Result<oxwm::Config> {
+fn load_config(custom_path: Option<PathBuf>) -> Result<(oxwm::Config, bool)> {
     let config_path = if let Some(path) = custom_path {
         path
     } else {
@@ -77,8 +82,16 @@ fn load_config(custom_path: Option<PathBuf>) -> Result<oxwm::Config> {
         std::fs::read_to_string(&config_path).with_context(|| "Failed to read config file")?;
 
     let config_dir = config_path.parent();
-    oxwm::config::parse_lua_config(&config_str, config_dir)
-        .with_context(|| "Failed to parse Lua config")
+
+    match oxwm::config::parse_lua_config(&config_str, config_dir) {
+        Ok(config) => Ok((config, false)),
+        Err(_) => {
+            let template = include_str!("../../templates/config.lua");
+            let config = oxwm::config::parse_lua_config(template, None)
+                .with_context(|| "Failed to parse default template config")?;
+            Ok((config, true))
+        }
+    }
 }
 
 fn init_config() -> Result<()> {
diff --git a/src/overlay/error.rs b/src/overlay/error.rs
index 256c584..2d1f98e 100644
--- a/src/overlay/error.rs
+++ b/src/overlay/error.rs
@@ -1,7 +1,6 @@
 use super::{Overlay, OverlayBase};
 use crate::bar::font::Font;
 use crate::errors::X11Error;
-use std::time::Instant;
 use x11rb::connection::Connection;
 use x11rb::protocol::xproto::*;
 use x11rb::rust_connection::RustConnection;
@@ -10,11 +9,9 @@ const PADDING: i16 = 20;
 const LINE_SPACING: i16 = 5;
 const BORDER_WIDTH: u16 = 2;
 const BORDER_COLOR: u32 = 0xff5555;
-const AUTO_DISMISS_SECONDS: u64 = 10;
 
 pub struct ErrorOverlay {
     base: OverlayBase,
-    created_at: Option<Instant>,
     lines: Vec<String>,
 }
 
@@ -42,7 +39,6 @@ impl ErrorOverlay {
 
         Ok(ErrorOverlay {
             base,
-            created_at: None,
             lines: Vec::new(),
         })
     }
@@ -76,19 +72,10 @@ impl ErrorOverlay {
 
         self.base.configure(connection, x, y, width, height)?;
         self.base.show(connection)?;
-        self.created_at = Some(Instant::now());
         self.draw(connection, font)?;
         Ok(())
     }
 
-    pub fn should_auto_dismiss(&self) -> bool {
-        if let Some(created_at) = self.created_at {
-            created_at.elapsed().as_secs() >= AUTO_DISMISS_SECONDS
-        } else {
-            false
-        }
-    }
-
     fn wrap_text(&self, text: &str, font: &Font, max_width: u16) -> Vec<String> {
         let mut lines = Vec::new();
         for paragraph in text.lines() {
@@ -134,7 +121,6 @@ impl Overlay for ErrorOverlay {
 
     fn hide(&mut self, connection: &RustConnection) -> Result<(), X11Error> {
         self.base.hide(connection)?;
-        self.created_at = None;
         self.lines.clear();
         Ok(())
     }
diff --git a/src/window_manager.rs b/src/window_manager.rs
index ed717b1..b823e2b 100644
--- a/src/window_manager.rs
+++ b/src/window_manager.rs
@@ -244,6 +244,26 @@ impl WindowManager {
         Ok(tag_mask(0))
     }
 
+    pub fn show_migration_overlay(&mut self) {
+        let message = "Your config.lua uses legacy syntax or has errors.\n\n\
+                       You are now running with default configuration.\n\n\
+                       Press Mod+Shift+/ to see default keybinds\n\
+                       Press Mod+Shift+R to reload after fixing your config";
+
+        let screen_width = self.screen.width_in_pixels;
+        let screen_height = self.screen.height_in_pixels;
+
+        if let Err(e) = self.overlay.show_error(
+            &self.connection,
+            &self.font,
+            message,
+            screen_width,
+            screen_height,
+        ) {
+            eprintln!("Failed to show migration overlay: {:?}", e);
+        }
+    }
+
     fn try_reload_config(&mut self) -> Result<(), String> {
         let config_dir = if let Some(xdg_config) = std::env::var_os("XDG_CONFIG_HOME") {
             std::path::PathBuf::from(xdg_config).join("oxwm")
@@ -427,10 +447,6 @@ impl WindowManager {
                 self.update_bar()?;
             }
 
-            if self.overlay.is_visible() && self.overlay.should_auto_dismiss() {
-                let _ = self.overlay.hide(&self.connection);
-            }
-
             std::thread::sleep(std::time::Duration::from_millis(100));
         }
     }