oxwm

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

Fixed transiet dialog handling for Firefox, Brave, and Discord. Removed geomtric caching in favor of using client struct as the source of truth.

Commit
d7dbcfd89e1b8ac5827b19c6b7b51447f9c4f21c
Parent
bc6b4cb
Author
tonybtw <tonybtw@tonybtw.com>
Date
2025-12-10 22:26:43

Diff

diff --git a/src/window_manager.rs b/src/window_manager.rs
index 5f5c4a1..4b4b9d7 100644
--- a/src/window_manager.rs
+++ b/src/window_manager.rs
@@ -17,14 +17,6 @@ use x11rb::protocol::Event;
 use x11rb::protocol::xproto::*;
 use x11rb::rust_connection::RustConnection;
 
-#[derive(Debug, Clone, Copy)]
-pub struct CachedGeometry {
-    pub x_position: i16,
-    pub y_position: i16,
-    pub width: u16,
-    pub height: u16,
-    pub border_width: u16,
-}
 
 pub fn tag_mask(tag: usize) -> TagMask {
     1 << tag
@@ -43,9 +35,6 @@ struct AtomCache {
     wm_name: Atom,
     net_wm_name: Atom,
     utf8_string: Atom,
-    wm_normal_hints: Atom,
-    wm_hints: Atom,
-    wm_transient_for: Atom,
     net_active_window: Atom,
 }
 
@@ -96,9 +85,6 @@ impl AtomCache {
         let wm_name = AtomEnum::WM_NAME.into();
         let net_wm_name = connection.intern_atom(false, b"_NET_WM_NAME")?.reply()?.atom;
         let utf8_string = connection.intern_atom(false, b"UTF8_STRING")?.reply()?.atom;
-        let wm_normal_hints = AtomEnum::WM_NORMAL_HINTS.into();
-        let wm_hints = AtomEnum::WM_HINTS.into();
-        let wm_transient_for = AtomEnum::WM_TRANSIENT_FOR.into();
         let net_active_window = connection.intern_atom(false, b"_NET_ACTIVE_WINDOW")?.reply()?.atom;
 
         Ok(Self {
@@ -114,9 +100,6 @@ impl AtomCache {
             wm_name,
             net_wm_name,
             utf8_string,
-            wm_normal_hints,
-            wm_hints,
-            wm_transient_for,
             net_active_window,
         })
     }
@@ -131,7 +114,6 @@ pub struct WindowManager {
     windows: Vec<Window>,
     clients: HashMap<Window, Client>,
     layout: LayoutBox,
-    window_geometry_cache: HashMap<Window, CachedGeometry>,
     gaps_enabled: bool,
     floating_windows: HashSet<Window>,
     fullscreen_windows: HashSet<Window>,
@@ -289,7 +271,6 @@ impl WindowManager {
             windows: Vec::new(),
             clients: HashMap::new(),
             layout: Box::new(TilingLayout),
-            window_geometry_cache: HashMap::new(),
             gaps_enabled,
             floating_windows: HashSet::new(),
             fullscreen_windows: HashSet::new(),
@@ -1040,14 +1021,36 @@ impl WindowManager {
             let has_no_layout = self.layout.name() == LayoutType::Normie.as_str();
 
             if (has_no_layout || is_floating) && !is_fullscreen {
-                self.connection.configure_window(
+                let (x, y, w, h, changed) = self.apply_size_hints(
                     window,
-                    &ConfigureWindowAux::new()
-                        .x(client.x_position as i32)
-                        .y(client.y_position as i32)
-                        .width(client.width as u32)
-                        .height(client.height as u32),
-                )?;
+                    client.x_position as i32,
+                    client.y_position as i32,
+                    client.width as i32,
+                    client.height as i32,
+                );
+                if changed {
+                    if let Some(c) = self.clients.get_mut(&window) {
+                        c.old_x_position = c.x_position;
+                        c.old_y_position = c.y_position;
+                        c.old_width = c.width;
+                        c.old_height = c.height;
+                        c.x_position = x as i16;
+                        c.y_position = y as i16;
+                        c.width = w as u16;
+                        c.height = h as u16;
+                    }
+                    self.connection.configure_window(
+                        window,
+                        &ConfigureWindowAux::new()
+                            .x(x)
+                            .y(y)
+                            .width(w as u32)
+                            .height(h as u32)
+                            .border_width(self.config.border_width),
+                    )?;
+                    self.send_configure_notify(window)?;
+                    self.connection.flush()?;
+                }
             }
 
             self.showhide(client.stack_next)?;
@@ -1369,30 +1372,6 @@ impl WindowManager {
         Ok(())
     }
 
-    fn get_window_state(&self, window: Window) -> WmResult<i32> {
-        let reply = self.connection.get_property(
-            false,
-            window,
-            self.atoms.wm_state,
-            self.atoms.wm_state,
-            0,
-            2,
-        )?.reply();
-
-        match reply {
-            Ok(prop) if !prop.value.is_empty() && prop.value.len() >= 4 => {
-                let state = u32::from_ne_bytes([
-                    prop.value[0],
-                    prop.value[1],
-                    prop.value[2],
-                    prop.value[3],
-                ]);
-                Ok(state as i32)
-            }
-            _ => Ok(-1),
-        }
-    }
-
     fn get_window_atom_property(&self, window: Window, property: Atom) -> WmResult<Option<Atom>> {
         let reply = self.connection.get_property(
             false,
@@ -1417,25 +1396,6 @@ impl WindowManager {
         }
     }
 
-    fn get_window_text_property(&self, window: Window, atom: Atom) -> WmResult<Option<String>> {
-        let reply = self.connection.get_property(
-            false,
-            window,
-            atom,
-            AtomEnum::ANY,
-            0,
-            1024,
-        )?.reply();
-
-        match reply {
-            Ok(prop) if !prop.value.is_empty() => {
-                let text = String::from_utf8_lossy(&prop.value).to_string();
-                Ok(Some(text.trim_end_matches('\0').to_string()))
-            }
-            _ => Ok(None),
-        }
-    }
-
     fn fullscreen(&mut self) -> WmResult<()> {
         if self.show_bar {
             let windows: Vec<Window> = self.windows.iter()
@@ -1511,7 +1471,7 @@ impl WindowManager {
                 if let Some(&(x, y, width, height, border_width)) = self.floating_geometry_before_fullscreen.get(&window) {
                     self.connection.configure_window(
                         window,
-                        &x11rb::protocol::xproto::ConfigureWindowAux::new()
+                        &ConfigureWindowAux::new()
                             .x(x as i32)
                             .y(y as i32)
                             .width(width as u32)
@@ -1519,13 +1479,13 @@ impl WindowManager {
                             .border_width(border_width as u32),
                     )?;
 
-                    self.update_geometry_cache(window, CachedGeometry {
-                        x_position: x,
-                        y_position: y,
-                        width,
-                        height,
-                        border_width,
-                    });
+                    if let Some(c) = self.clients.get_mut(&window) {
+                        c.x_position = x;
+                        c.y_position = y;
+                        c.width = width;
+                        c.height = height;
+                        c.border_width = border_width;
+                    }
 
                     self.floating_geometry_before_fullscreen.remove(&window);
                 }
@@ -1673,79 +1633,6 @@ impl WindowManager {
             })
     }
 
-    fn has_user_set_position(&self, window: Window) -> bool {
-        const US_POSITION: u32 = 1 << 0;
-        const P_POSITION: u32 = 1 << 2;
-
-        let size_hints = self.connection
-            .get_property(
-                false,
-                window,
-                x11rb::protocol::xproto::AtomEnum::WM_NORMAL_HINTS,
-                x11rb::protocol::xproto::AtomEnum::WM_SIZE_HINTS,
-                0,
-                18,
-            )
-            .ok()
-            .and_then(|cookie| cookie.reply().ok());
-
-        if let Some(hints) = size_hints {
-            if hints.value.len() >= 4 {
-                let flags = u32::from_ne_bytes([
-                    hints.value[0],
-                    hints.value[1],
-                    hints.value[2],
-                    hints.value[3],
-                ]);
-                return (flags & US_POSITION) != 0 || (flags & P_POSITION) != 0;
-            }
-        }
-        false
-    }
-
-    fn is_dialog_window(&self, window: Window) -> bool {
-        let window_type_property = self.connection
-            .get_property(
-                false,
-                window,
-                self.atoms.net_wm_window_type,
-                AtomEnum::ATOM,
-                0,
-                32,
-            )
-            .ok()
-            .and_then(|cookie| cookie.reply().ok());
-
-        if let Some(reply) = window_type_property {
-            let atoms: Vec<Atom> = reply
-                .value
-                .chunks_exact(4)
-                .map(|chunk| u32::from_ne_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]))
-                .collect();
-
-            let is_dialog = atoms.contains(&self.atoms.net_wm_window_type_dialog);
-            is_dialog
-        } else {
-            false
-        }
-    }
-
-    fn get_window_class(&self, window: Window) -> Option<String> {
-        self.connection
-            .get_property(false, window, AtomEnum::WM_CLASS, AtomEnum::STRING, 0, 1024)
-            .ok()
-            .and_then(|cookie| cookie.reply().ok())
-            .and_then(|reply| {
-                if reply.value.is_empty() {
-                    None
-                } else {
-                    std::str::from_utf8(&reply.value).ok().map(|s| {
-                        s.split('\0').nth(1).unwrap_or(s.split('\0').next().unwrap_or("")).to_string()
-                    })
-                }
-            })
-    }
-
     fn get_window_class_instance(&self, window: Window) -> (String, String) {
         let reply = self.connection
             .get_property(false, window, AtomEnum::WM_CLASS, AtomEnum::STRING, 0, 1024)
@@ -1819,133 +1706,81 @@ impl WindowManager {
 
     fn manage_window(&mut self, window: Window) -> WmResult<()> {
         let geometry = self.connection.get_geometry(window)?.reply()?;
-        let mut window_x = geometry.x as i32;
-        let mut window_y = geometry.y as i32;
-        let mut window_width = geometry.width as u32;
-        let mut window_height = geometry.height as u32;
         let border_width = self.config.border_width;
 
-        self.update_window_title(window)?;
-
         let transient_parent = self.get_transient_parent(window);
         let is_transient = transient_parent.is_some();
 
-        let parent_geometry = if let Some(parent) = transient_parent {
-            self.connection.get_geometry(parent)
-                .ok()
-                .and_then(|cookie| cookie.reply().ok())
-        } else {
-            None
-        };
-
-        let (initial_tags, initial_monitor_index) = if let Some(parent) = transient_parent {
-            if let Some(ref parent_geom) = parent_geometry {
-                let parent_mon_idx = self.get_monitor_for_rect(
-                    parent_geom.x as i32,
-                    parent_geom.y as i32,
-                    parent_geom.width as i32,
-                    parent_geom.height as i32
-                );
-
-                let tags = if let Some(parent_client) = self.clients.get(&parent) {
-                    parent_client.tags
-                } else {
-                    self.monitors
-                        .get(parent_mon_idx)
-                        .map(|m| m.tagset[m.selected_tags_index])
-                        .unwrap_or(tag_mask(0))
-                };
-
-                (tags, parent_mon_idx)
+        let (monitor_index, tags) = if let Some(parent) = transient_parent {
+            if let Some(parent_client) = self.clients.get(&parent) {
+                (parent_client.monitor_index, parent_client.tags)
             } else {
-                let tags = self.monitors
-                    .get(self.selected_monitor)
+                let tags = self.monitors.get(self.selected_monitor)
                     .map(|m| m.tagset[m.selected_tags_index])
                     .unwrap_or(tag_mask(0));
-                (tags, self.selected_monitor)
+                (self.selected_monitor, tags)
             }
         } else {
-            let tags = self.monitors
-                .get(self.selected_monitor)
+            let tags = self.monitors.get(self.selected_monitor)
                 .map(|m| m.tagset[m.selected_tags_index])
                 .unwrap_or(tag_mask(0));
-            (tags, self.selected_monitor)
+            (self.selected_monitor, tags)
         };
 
-        let mut client = Client::new(window, initial_monitor_index, initial_tags);
-        client.old_border_width = border_width as u16;
+        let mut client = Client::new(window, monitor_index, tags);
+        client.x_position = geometry.x;
+        client.y_position = geometry.y;
+        client.width = geometry.width;
+        client.height = geometry.height;
+        client.old_x_position = geometry.x;
+        client.old_y_position = geometry.y;
+        client.old_width = geometry.width;
+        client.old_height = geometry.height;
+        client.old_border_width = geometry.border_width;
+        client.border_width = border_width as u16;
 
         self.clients.insert(window, client);
+        self.update_window_title(window)?;
 
         if !is_transient {
             self.apply_rules(window)?;
         }
 
-        let final_monitor_index = self.clients.get(&window).map(|c| c.monitor_index).unwrap_or(initial_monitor_index);
-        let final_monitor = self.monitors.get(final_monitor_index).cloned().unwrap_or_else(|| {
-            self.monitors.get(self.selected_monitor).cloned().unwrap_or_else(|| {
-                Monitor::new(0, 0, self.screen.width_in_pixels as u32, self.screen.height_in_pixels as u32)
-            })
-        });
-
-        let total_width = window_width as i32 + 2 * border_width as i32;
-        let total_height = window_height as i32 + 2 * border_width as i32;
+        let client_monitor = self.clients.get(&window).map(|c| c.monitor_index).unwrap_or(monitor_index);
+        let monitor = &self.monitors[client_monitor];
 
-        self.update_window_type(window)?;
-
-        let has_explicit_position = self.has_user_set_position(window);
-        let is_dialog = self.is_dialog_window(window);
-        let position_is_origin = window_x == 0 && window_y == 0;
-        let should_center = (is_transient || is_dialog) && (!has_explicit_position || position_is_origin);
-
-        if should_center {
-            if transient_parent.is_some() {
-                if let Some(ref parent_geom) = parent_geometry {
-                    let parent_center_x = parent_geom.x as i32 + parent_geom.width as i32 / 2;
-                    let parent_center_y = parent_geom.y as i32 + parent_geom.height as i32 / 2;
-                    window_x = parent_center_x - window_width as i32 / 2;
-                    window_y = parent_center_y - window_height as i32 / 2;
-                } else {
-                    window_x = final_monitor.window_area_x + final_monitor.window_area_width / 2 - window_width as i32 / 2;
-                    window_y = final_monitor.window_area_y + final_monitor.window_area_height / 2 - window_height as i32 / 2;
-                }
-            } else {
-                window_x = final_monitor.window_area_x + final_monitor.window_area_width / 2 - window_width as i32 / 2;
-                window_y = final_monitor.window_area_y + final_monitor.window_area_height / 2 - window_height as i32 / 2;
-            }
-        }
+        let mut x = self.clients.get(&window).map(|c| c.x_position as i32).unwrap_or(0);
+        let mut y = self.clients.get(&window).map(|c| c.y_position as i32).unwrap_or(0);
+        let w = self.clients.get(&window).map(|c| c.width as i32).unwrap_or(1);
+        let h = self.clients.get(&window).map(|c| c.height as i32).unwrap_or(1);
+        let bw = border_width as i32;
 
-        if window_x + total_width > final_monitor.window_area_x + final_monitor.window_area_width {
-            window_x = final_monitor.window_area_x + final_monitor.window_area_width - total_width;
+        if x + w + 2 * bw > monitor.window_area_x + monitor.window_area_width {
+            x = monitor.window_area_x + monitor.window_area_width - w - 2 * bw;
         }
-        if window_y + total_height > final_monitor.window_area_y + final_monitor.window_area_height {
-            window_y = final_monitor.window_area_y + final_monitor.window_area_height - total_height;
+        if y + h + 2 * bw > monitor.window_area_y + monitor.window_area_height {
+            y = monitor.window_area_y + monitor.window_area_height - h - 2 * bw;
         }
-        window_x = window_x.max(final_monitor.window_area_x);
-        window_y = window_y.max(final_monitor.window_area_y);
+        x = x.max(monitor.window_area_x);
+        y = y.max(monitor.window_area_y);
 
-        if let Some(client) = self.clients.get_mut(&window) {
-            client.x_position = window_x as i16;
-            client.y_position = window_y as i16;
-            client.width = window_width as u16;
-            client.height = window_height as u16;
-            client.old_x_position = window_x as i16;
-            client.old_y_position = window_y as i16;
-            client.old_width = window_width as u16;
-            client.old_height = window_height as u16;
-            client.border_width = border_width as u16;
+        if let Some(c) = self.clients.get_mut(&window) {
+            c.x_position = x as i16;
+            c.y_position = y as i16;
         }
 
         self.connection.configure_window(
             window,
-            &ConfigureWindowAux::new()
-                .x(window_x)
-                .y(window_y)
-                .border_width(border_width),
+            &ConfigureWindowAux::new().border_width(border_width),
+        )?;
+        self.connection.change_window_attributes(
+            window,
+            &ChangeWindowAttributesAux::new().border_pixel(self.config.border_unfocused),
         )?;
-
         self.send_configure_notify(window)?;
+        self.update_window_type(window)?;
         self.update_size_hints(window)?;
+        self.update_window_hints(window)?;
 
         self.connection.change_window_attributes(
             window,
@@ -1955,17 +1790,14 @@ impl WindowManager {
         )?;
 
         let is_fixed = self.clients.get(&window).map(|c| c.is_fixed).unwrap_or(false);
-        let already_floating = self.clients.get(&window).map(|c| c.is_floating).unwrap_or(false);
-
-        if !already_floating {
-            if let Some(client) = self.clients.get_mut(&window) {
-                client.is_floating = is_transient || is_fixed;
-                client.old_state = client.is_floating;
+        if let Some(c) = self.clients.get_mut(&window) {
+            if !c.is_floating {
+                c.is_floating = is_transient || is_fixed;
+                c.old_state = c.is_floating;
             }
         }
 
-        let is_floating = self.clients.get(&window).map(|c| c.is_floating).unwrap_or(false);
-        if is_floating {
+        if self.clients.get(&window).map(|c| c.is_floating).unwrap_or(false) {
             self.floating_windows.insert(window);
             self.connection.configure_window(
                 window,
@@ -1973,35 +1805,33 @@ impl WindowManager {
             )?;
         }
 
-        self.attach_aside(window, final_monitor_index);
-        self.attach_stack(window, final_monitor_index);
+        self.attach_aside(window, client_monitor);
+        self.attach_stack(window, client_monitor);
         self.windows.push(window);
 
-        let off_screen_x = window_x + 2 * self.screen.width_in_pixels as i32;
+        let off_screen_x = x + 2 * self.screen.width_in_pixels as i32;
         self.connection.configure_window(
             window,
             &ConfigureWindowAux::new()
                 .x(off_screen_x)
-                .y(window_y)
-                .width(window_width)
-                .height(window_height),
+                .y(y)
+                .width(w as u32)
+                .height(h as u32),
         )?;
 
         self.set_wm_state(window, 1)?;
 
-        let final_tags = self.clients.get(&window).map(|c| c.tags).unwrap_or(initial_tags);
-        if let Err(error) = self.save_client_tag(window, final_tags) {
-            eprintln!("Failed to save client tag for new window: {:?}", error);
-        }
+        let final_tags = self.clients.get(&window).map(|c| c.tags).unwrap_or(tags);
+        let _ = self.save_client_tag(window, final_tags);
 
-        if final_monitor_index == self.selected_monitor {
-            if let Some(old_selected) = self.monitors.get(self.selected_monitor).and_then(|m| m.selected_client) {
-                self.unfocus(old_selected)?;
+        if client_monitor == self.selected_monitor {
+            if let Some(old_sel) = self.monitors.get(self.selected_monitor).and_then(|m| m.selected_client) {
+                self.unfocus(old_sel)?;
             }
         }
 
-        if let Some(monitor) = self.monitors.get_mut(final_monitor_index) {
-            monitor.selected_client = Some(window);
+        if let Some(m) = self.monitors.get_mut(client_monitor) {
+            m.selected_client = Some(window);
         }
 
         self.apply_layout()?;
@@ -2647,9 +2477,11 @@ impl WindowManager {
                         .unwrap_or(false);
 
                     if should_resize {
-                        if let Some(client) = self.clients.get(&window) {
-                            let (hint_width, hint_height) = self.apply_size_hints(
-                                client,
+                        if let Some(client) = self.clients.get(&window).cloned() {
+                            let (_, _, hint_width, hint_height, _) = self.apply_size_hints(
+                                window,
+                                client.x_position as i32,
+                                client.y_position as i32,
                                 new_width as i32,
                                 new_height as i32,
                             );
@@ -2787,7 +2619,7 @@ impl WindowManager {
                 }
             }
             Event::PropertyNotify(event) => {
-                if event.state == x11rb::protocol::xproto::Property::DELETE {
+                if event.state == Property::DELETE {
                     return Ok(None);
                 }
 
@@ -2796,16 +2628,12 @@ impl WindowManager {
                 }
 
                 if event.atom == AtomEnum::WM_TRANSIENT_FOR.into() {
-                    let is_floating = self.clients
-                        .get(&event.window)
-                        .map(|c| c.is_floating)
-                        .unwrap_or(false);
-
+                    let is_floating = self.clients.get(&event.window).map(|c| c.is_floating).unwrap_or(false);
                     if !is_floating {
-                        if let Some(transient_parent) = self.get_transient_parent(event.window) {
-                            if self.clients.contains_key(&transient_parent) {
-                                if let Some(client) = self.clients.get_mut(&event.window) {
-                                    client.is_floating = true;
+                        if let Some(parent) = self.get_transient_parent(event.window) {
+                            if self.clients.contains_key(&parent) {
+                                if let Some(c) = self.clients.get_mut(&event.window) {
+                                    c.is_floating = true;
                                 }
                                 self.floating_windows.insert(event.window);
                                 self.apply_layout()?;
@@ -2813,8 +2641,8 @@ impl WindowManager {
                         }
                     }
                 } else if event.atom == AtomEnum::WM_NORMAL_HINTS.into() {
-                    if let Some(client) = self.clients.get_mut(&event.window) {
-                        client.hints_valid = false;
+                    if let Some(c) = self.clients.get_mut(&event.window) {
+                        c.hints_valid = false;
                     }
                 } else if event.atom == AtomEnum::WM_HINTS.into() {
                     self.update_window_hints(event.window)?;
@@ -2830,77 +2658,6 @@ impl WindowManager {
 
                 if event.atom == self.atoms.net_wm_window_type {
                     self.update_window_type(event.window)?;
-
-                    if self.is_dialog_window(event.window) {
-
-                        let client_info = self.clients.get(&event.window).map(|c| {
-                            (c.width, c.height, c.border_width, c.monitor_index, c.is_floating)
-                        });
-
-                        if let Some((width, height, border_width, current_monitor_index, is_floating)) = client_info {
-                            if !is_floating {
-                                if let Some(client) = self.clients.get_mut(&event.window) {
-                                    client.is_floating = true;
-                                }
-                                self.floating_windows.insert(event.window);
-                            }
-
-                            let transient_parent = self.get_transient_parent(event.window);
-                            let target_monitor_index = if let Some(parent) = transient_parent {
-                                if let Ok(parent_geom_reply) = self.connection.get_geometry(parent) {
-                                    if let Ok(parent_geom) = parent_geom_reply.reply() {
-                                        self.get_monitor_for_rect(
-                                            parent_geom.x as i32,
-                                            parent_geom.y as i32,
-                                            parent_geom.width as i32,
-                                            parent_geom.height as i32,
-                                        )
-                                    } else {
-                                        current_monitor_index
-                                    }
-                                } else {
-                                    current_monitor_index
-                                }
-                            } else {
-                                current_monitor_index
-                            };
-
-                            let monitor = &self.monitors[target_monitor_index];
-                            let window_width = width as i32;
-                            let window_height = height as i32;
-
-                            let mut window_x = monitor.window_area_x + monitor.window_area_width / 2 - window_width / 2;
-                            let mut window_y = monitor.window_area_y + monitor.window_area_height / 2 - window_height / 2;
-
-                            let total_width = window_width + 2 * border_width as i32;
-                            let total_height = window_height + 2 * border_width as i32;
-
-                            if window_x + total_width > monitor.window_area_x + monitor.window_area_width {
-                                window_x = monitor.window_area_x + monitor.window_area_width - total_width;
-                            }
-                            if window_y + total_height > monitor.window_area_y + monitor.window_area_height {
-                                window_y = monitor.window_area_y + monitor.window_area_height - total_height;
-                            }
-                            window_x = window_x.max(monitor.window_area_x);
-                            window_y = window_y.max(monitor.window_area_y);
-
-                            if let Some(client) = self.clients.get_mut(&event.window) {
-                                client.x_position = window_x as i16;
-                                client.y_position = window_y as i16;
-                                client.monitor_index = target_monitor_index;
-                            }
-
-                            self.connection.configure_window(
-                                event.window,
-                                &ConfigureWindowAux::new()
-                                    .x(window_x)
-                                    .y(window_y)
-                            )?.check()?;
-
-                            self.connection.flush()?;
-                            self.apply_layout()?;
-                        }
-                    }
                 }
             }
             Event::EnterNotify(event) => {
@@ -3115,117 +2872,109 @@ impl WindowManager {
                 }
             }
             Event::ConfigureRequest(event) => {
-                if self.windows.contains(&event.window) {
-                    let monitor_index = self.clients.get(&event.window)
-                        .map(|c| c.monitor_index)
-                        .unwrap_or(self.selected_monitor);
-                    let monitor = &self.monitors[monitor_index];
-                    let is_floating = self.floating_windows.contains(&event.window);
-                    let is_tiling_layout = self.layout.name() != "normie";
-
-                    if is_floating || !is_tiling_layout {
-                        let cached_geom = self.window_geometry_cache.get(&event.window);
-                        let border_width = self.config.border_width as u16;
-                        let value_mask = event.value_mask;
-
-                        let final_x = if value_mask.contains(ConfigWindow::X) {
-                            let mut x = event.x as i32;
-                            x = x.max(monitor.screen_x);
-                            if x + event.width as i32 + 2 * border_width as i32 > monitor.screen_x + monitor.screen_width as i32 {
-                                x = monitor.screen_x + monitor.screen_width as i32 - event.width as i32 - 2 * border_width as i32;
+                if let Some(client) = self.clients.get(&event.window) {
+                    let monitor = &self.monitors[client.monitor_index];
+                    let is_floating = client.is_floating;
+                    let has_layout = self.layout.name() != "normie";
+
+                    if event.value_mask.contains(ConfigWindow::BORDER_WIDTH) {
+                        if let Some(c) = self.clients.get_mut(&event.window) {
+                            c.border_width = event.border_width;
+                        }
+                    } else if is_floating || !has_layout {
+                        let mut x = client.x_position as i32;
+                        let mut y = client.y_position as i32;
+                        let mut w = client.width as i32;
+                        let mut h = client.height as i32;
+
+                        if event.value_mask.contains(ConfigWindow::X) {
+                            if let Some(c) = self.clients.get_mut(&event.window) {
+                                c.old_x_position = c.x_position;
                             }
-                            x as i16
-                        } else {
-                            cached_geom.map(|g| g.x_position).unwrap_or(0)
-                        };
-
-                        let final_y = if value_mask.contains(ConfigWindow::Y) {
-                            let mut y = event.y as i32;
-                            y = y.max(monitor.screen_y);
-                            if y + event.height as i32 + 2 * border_width as i32 > monitor.screen_y + monitor.screen_height as i32 {
-                                y = monitor.screen_y + monitor.screen_height as i32 - event.height as i32 - 2 * border_width as i32;
+                            x = monitor.screen_x + event.x as i32;
+                        }
+                        if event.value_mask.contains(ConfigWindow::Y) {
+                            if let Some(c) = self.clients.get_mut(&event.window) {
+                                c.old_y_position = c.y_position;
                             }
-                            y as i16
-                        } else {
-                            cached_geom.map(|g| g.y_position).unwrap_or(0)
-                        };
-
-                        let mut final_width = if value_mask.contains(ConfigWindow::WIDTH) { event.width } else { cached_geom.map(|g| g.width).unwrap_or(1) };
-                        let mut final_height = if value_mask.contains(ConfigWindow::HEIGHT) { event.height } else { cached_geom.map(|g| g.height).unwrap_or(1) };
-
-                        if let Some(client) = self.clients.get(&event.window) {
-                            let (w, h) = self.apply_size_hints(client, final_width as i32, final_height as i32);
-                            final_width = w as u16;
-                            final_height = h as u16;
+                            y = monitor.screen_y + event.y as i32;
+                        }
+                        if event.value_mask.contains(ConfigWindow::WIDTH) {
+                            if let Some(c) = self.clients.get_mut(&event.window) {
+                                c.old_width = c.width;
+                            }
+                            w = event.width as i32;
+                        }
+                        if event.value_mask.contains(ConfigWindow::HEIGHT) {
+                            if let Some(c) = self.clients.get_mut(&event.window) {
+                                c.old_height = c.height;
+                            }
+                            h = event.height as i32;
                         }
 
-                        let mut config = ConfigureWindowAux::new()
-                            .x(final_x as i32)
-                            .y(final_y as i32)
-                            .width(final_width as u32)
-                            .height(final_height as u32);
+                        let bw = self.config.border_width as i32;
+                        let width_with_border = w + 2 * bw;
+                        let height_with_border = h + 2 * bw;
 
-                        if value_mask.contains(ConfigWindow::BORDER_WIDTH) {
-                            config = config.border_width(event.border_width as u32);
+                        if (x + w) > monitor.screen_x + monitor.screen_width as i32 && is_floating {
+                            x = monitor.screen_x + (monitor.screen_width as i32 / 2 - width_with_border / 2);
                         }
-
-                        if value_mask.contains(ConfigWindow::SIBLING) {
-                            config = config.sibling(event.sibling);
+                        if (y + h) > monitor.screen_y + monitor.screen_height as i32 && is_floating {
+                            y = monitor.screen_y + (monitor.screen_height as i32 / 2 - height_with_border / 2);
                         }
 
-                        if value_mask.contains(ConfigWindow::STACK_MODE) {
-                            config = config.stack_mode(event.stack_mode);
+                        if let Some(c) = self.clients.get_mut(&event.window) {
+                            c.x_position = x as i16;
+                            c.y_position = y as i16;
+                            c.width = w as u16;
+                            c.height = h as u16;
                         }
 
-                        self.connection.configure_window(event.window, &config)?;
-
-                        if let Some(client) = self.clients.get_mut(&event.window) {
-                            client.old_x_position = client.x_position;
-                            client.old_y_position = client.y_position;
-                            client.old_width = client.width;
-                            client.old_height = client.height;
-                            client.x_position = final_x;
-                            client.y_position = final_y;
-                            client.width = final_width;
-                            client.height = final_height;
+                        let only_position_change = event.value_mask.contains(ConfigWindow::X) || event.value_mask.contains(ConfigWindow::Y);
+                        let no_size_change = !event.value_mask.contains(ConfigWindow::WIDTH) && !event.value_mask.contains(ConfigWindow::HEIGHT);
+                        if only_position_change && no_size_change {
+                            self.send_configure_notify(event.window)?;
                         }
 
-                        self.update_geometry_cache(event.window, CachedGeometry {
-                            x_position: final_x,
-                            y_position: final_y,
-                            width: final_width,
-                            height: final_height,
-                            border_width: if value_mask.contains(ConfigWindow::BORDER_WIDTH) { event.border_width } else { border_width },
-                        });
-
-                        if is_floating {
-                            let new_monitor = self.get_monitor_for_rect(final_x as i32, final_y as i32, final_width as i32, final_height as i32);
-
-                            if new_monitor != monitor_index {
-                                self.move_window_to_monitor(event.window, new_monitor)?;
-                            }
+                        if self.is_visible(event.window) {
+                            self.connection.configure_window(
+                                event.window,
+                                &ConfigureWindowAux::new()
+                                    .x(x)
+                                    .y(y)
+                                    .width(w as u32)
+                                    .height(h as u32),
+                            )?;
                         }
                     } else {
                         self.send_configure_notify(event.window)?;
                     }
                 } else {
-                    let mut config = ConfigureWindowAux::new()
-                        .x(event.x as i32)
-                        .y(event.y as i32)
-                        .width(event.width as u32)
-                        .height(event.height as u32)
-                        .border_width(event.border_width as u32);
-
+                    let mut aux = ConfigureWindowAux::new();
+                    if event.value_mask.contains(ConfigWindow::X) {
+                        aux = aux.x(event.x as i32);
+                    }
+                    if event.value_mask.contains(ConfigWindow::Y) {
+                        aux = aux.y(event.y as i32);
+                    }
+                    if event.value_mask.contains(ConfigWindow::WIDTH) {
+                        aux = aux.width(event.width as u32);
+                    }
+                    if event.value_mask.contains(ConfigWindow::HEIGHT) {
+                        aux = aux.height(event.height as u32);
+                    }
+                    if event.value_mask.contains(ConfigWindow::BORDER_WIDTH) {
+                        aux = aux.border_width(event.border_width as u32);
+                    }
                     if event.value_mask.contains(ConfigWindow::SIBLING) {
-                        config = config.sibling(event.sibling);
+                        aux = aux.sibling(event.sibling);
                     }
-
                     if event.value_mask.contains(ConfigWindow::STACK_MODE) {
-                        config = config.stack_mode(event.stack_mode);
+                        aux = aux.stack_mode(event.stack_mode);
                     }
-
-                    self.connection.configure_window(event.window, &config)?;
+                    self.connection.configure_window(event.window, &aux)?;
                 }
+                self.connection.flush()?;
             }
             Event::ClientMessage(event) => {
                 if !self.clients.contains_key(&event.window) {
@@ -3293,6 +3042,11 @@ impl WindowManager {
     }
 
     fn apply_layout(&mut self) -> WmResult<()> {
+        for monitor_index in 0..self.monitors.len() {
+            let stack_head = self.monitors.get(monitor_index).and_then(|m| m.stack_head);
+            self.showhide(stack_head)?;
+        }
+
         let is_normie = self.layout.name() == LayoutType::Normie.as_str();
 
         if !is_normie {
@@ -3360,10 +3114,12 @@ impl WindowManager {
                 let mut adjusted_width = geometry.width.saturating_sub(2 * border_width);
                 let mut adjusted_height = geometry.height.saturating_sub(2 * border_width);
 
-                if let Some(client) = self.clients.get(window) {
+                if let Some(client) = self.clients.get(window).cloned() {
                     if !client.is_floating {
-                        let (hint_width, hint_height) = self.apply_size_hints(
-                            client,
+                        let (_, _, hint_width, hint_height, _) = self.apply_size_hints(
+                            *window,
+                            geometry.x_coordinate as i32,
+                            geometry.y_coordinate as i32,
                             adjusted_width as i32,
                             adjusted_height as i32,
                         );
@@ -3392,13 +3148,13 @@ impl WindowManager {
                         .border_width(border_width),
                 )?;
 
-                self.update_geometry_cache(*window, CachedGeometry {
-                    x_position: adjusted_x as i16,
-                    y_position: adjusted_y as i16,
-                    width: adjusted_width as u16,
-                    height: adjusted_height as u16,
-                    border_width: border_width as u16,
-                });
+                if let Some(c) = self.clients.get_mut(window) {
+                    c.x_position = adjusted_x as i16;
+                    c.y_position = adjusted_y as i16;
+                    c.width = adjusted_width as u16;
+                    c.height = adjusted_height as u16;
+                    c.border_width = border_width as u16;
+                }
             }
             }
         }
@@ -3494,52 +3250,33 @@ impl WindowManager {
         Ok(())
     }
 
-    fn update_geometry_cache(&mut self, window: Window, geometry: CachedGeometry) {
-        self.window_geometry_cache.insert(window, geometry);
-    }
-
-    fn get_cached_geometry(&self, window: Window) -> Option<CachedGeometry> {
-        self.window_geometry_cache.get(&window).copied()
-    }
-
-    fn get_or_query_geometry(&mut self, window: Window) -> WmResult<CachedGeometry> {
-        if let Some(cached) = self.get_cached_geometry(window) {
-            return Ok(cached);
-        }
-
-        let geometry = self.connection.get_geometry(window)?.reply()?;
-        let cached = CachedGeometry {
-            x_position: geometry.x,
-            y_position: geometry.y,
-            width: geometry.width,
-            height: geometry.height,
-            border_width: geometry.border_width as u16,
+    fn send_configure_notify(&self, window: Window) -> WmResult<()> {
+        let client = self.clients.get(&window);
+        let (x, y, w, h, bw) = if let Some(c) = client {
+            (c.x_position, c.y_position, c.width, c.height, c.border_width)
+        } else {
+            let geom = self.connection.get_geometry(window)?.reply()?;
+            (geom.x, geom.y, geom.width, geom.height, geom.border_width)
         };
-        self.update_geometry_cache(window, cached);
-        Ok(cached)
-    }
-
-    fn send_configure_notify(&mut self, window: Window) -> WmResult<()> {
-        let geometry = self.get_or_query_geometry(window)?;
 
-        let event = x11rb::protocol::xproto::ConfigureNotifyEvent {
-            response_type: x11rb::protocol::xproto::CONFIGURE_NOTIFY_EVENT,
+        let event = ConfigureNotifyEvent {
+            response_type: CONFIGURE_NOTIFY_EVENT,
             sequence: 0,
             event: window,
             window,
             above_sibling: x11rb::NONE,
-            x: geometry.x_position,
-            y: geometry.y_position,
-            width: geometry.width,
-            height: geometry.height,
-            border_width: geometry.border_width,
+            x,
+            y,
+            width: w,
+            height: h,
+            border_width: bw,
             override_redirect: false,
         };
 
         self.connection.send_event(
             false,
             window,
-            x11rb::protocol::xproto::EventMask::STRUCTURE_NOTIFY,
+            EventMask::STRUCTURE_NOTIFY,
             event,
         )?;
 
@@ -3579,7 +3316,6 @@ impl WindowManager {
 
         let flags = read_u32(0);
 
-        const P_SIZE: u32 = 1 << 3;
         const P_MIN_SIZE: u32 = 1 << 4;
         const P_MAX_SIZE: u32 = 1 << 5;
         const P_RESIZE_INC: u32 = 1 << 6;
@@ -3588,8 +3324,8 @@ impl WindowManager {
 
         if let Some(client) = self.clients.get_mut(&window) {
             if flags & P_BASE_SIZE != 0 {
-                client.base_width = read_u32(8) as i32;
-                client.base_height = read_u32(9) as i32;
+                client.base_width = read_u32(15) as i32;
+                client.base_height = read_u32(16) as i32;
             } else if flags & P_MIN_SIZE != 0 {
                 client.base_width = read_u32(5) as i32;
                 client.base_height = read_u32(6) as i32;
@@ -3599,8 +3335,8 @@ impl WindowManager {
             }
 
             if flags & P_RESIZE_INC != 0 {
-                client.increment_width = read_u32(10) as i32;
-                client.increment_height = read_u32(11) as i32;
+                client.increment_width = read_u32(9) as i32;
+                client.increment_height = read_u32(10) as i32;
             } else {
                 client.increment_width = 0;
                 client.increment_height = 0;
@@ -3617,17 +3353,17 @@ impl WindowManager {
             if flags & P_MIN_SIZE != 0 {
                 client.min_width = read_u32(5) as i32;
                 client.min_height = read_u32(6) as i32;
-            } else if flags & P_SIZE != 0 {
-                client.min_width = read_u32(3) as i32;
-                client.min_height = read_u32(4) as i32;
+            } else if flags & P_BASE_SIZE != 0 {
+                client.min_width = read_u32(15) as i32;
+                client.min_height = read_u32(16) as i32;
             } else {
                 client.min_width = 0;
                 client.min_height = 0;
             }
 
             if flags & P_ASPECT != 0 {
-                client.min_aspect = (read_u32(12) as f32) / (read_u32(13) as f32).max(1.0);
-                client.max_aspect = (read_u32(14) as f32) / (read_u32(15) as f32).max(1.0);
+                client.min_aspect = (read_u32(12) as f32) / (read_u32(11) as f32).max(1.0);
+                client.max_aspect = (read_u32(13) as f32) / (read_u32(14) as f32).max(1.0);
             } else {
                 client.min_aspect = 0.0;
                 client.max_aspect = 0.0;
@@ -3773,51 +3509,101 @@ impl WindowManager {
         Ok(())
     }
 
-    fn apply_size_hints(&self, client: &Client, mut width: i32, mut height: i32) -> (i32, i32) {
-        let min_size = 20;
-        width = width.max(min_size);
-        height = height.max(min_size);
+    fn apply_size_hints(&mut self, window: Window, mut x: i32, mut y: i32, mut w: i32, mut h: i32) -> (i32, i32, i32, i32, bool) {
+        let bh = 20;
 
-        if !client.hints_valid {
-            return (width, height);
-        }
+        let (client_x, client_y, client_w, client_h, bw, monitor_index, is_floating, mut hints_valid) = {
+            let client = match self.clients.get(&window) {
+                Some(c) => c,
+                None => return (x, y, w, h, false),
+            };
+            (client.x_position as i32, client.y_position as i32, client.width as i32, client.height as i32,
+             client.border_width as i32, client.monitor_index, client.is_floating, client.hints_valid)
+        };
+
+        let monitor = &self.monitors[monitor_index];
+        let client_width = client_w + 2 * bw;
+        let client_height = client_h + 2 * bw;
 
-        if client.min_width > 0 {
-            width = width.max(client.min_width);
+        w = w.max(1);
+        h = h.max(1);
+
+        if x >= monitor.window_area_x + monitor.window_area_width {
+            x = monitor.window_area_x + monitor.window_area_width - client_width;
         }
-        if client.min_height > 0 {
-            height = height.max(client.min_height);
+        if y >= monitor.window_area_y + monitor.window_area_height {
+            y = monitor.window_area_y + monitor.window_area_height - client_height;
         }
-
-        if client.max_width > 0 {
-            width = width.min(client.max_width);
+        if x + w + 2 * bw <= monitor.window_area_x {
+            x = monitor.window_area_x;
         }
-        if client.max_height > 0 {
-            height = height.min(client.max_height);
+        if y + h + 2 * bw <= monitor.window_area_y {
+            y = monitor.window_area_y;
         }
 
-        if client.increment_width > 0 {
-            width -= client.base_width;
-            width -= width % client.increment_width;
-            width += client.base_width;
+        if h < bh {
+            h = bh;
         }
-        if client.increment_height > 0 {
-            height -= client.base_height;
-            height -= height % client.increment_height;
-            height += client.base_height;
+        if w < bh {
+            w = bh;
         }
 
-        if client.min_aspect > 0.0 || client.max_aspect > 0.0 {
-            let actual_aspect = width as f32 / height as f32;
+        if is_floating || self.layout.name() == "normie" {
+            if !hints_valid {
+                let _ = self.update_size_hints(window);
+                hints_valid = self.clients.get(&window).map(|c| c.hints_valid).unwrap_or(false);
+            }
+
+            if hints_valid {
+                let (base_width, base_height, min_width, min_height, max_width, max_height,
+                     inc_width, inc_height, min_aspect, max_aspect) = {
+                    let client = self.clients.get(&window).unwrap();
+                    (client.base_width, client.base_height, client.min_width, client.min_height,
+                     client.max_width, client.max_height, client.increment_width, client.increment_height,
+                     client.min_aspect, client.max_aspect)
+                };
 
-            if client.max_aspect > 0.0 && actual_aspect > client.max_aspect {
-                width = (height as f32 * client.max_aspect) as i32;
-            } else if client.min_aspect > 0.0 && actual_aspect < client.min_aspect {
-                height = (width as f32 / client.min_aspect) as i32;
+                let base_is_min = base_width == min_width && base_height == min_height;
+
+                if !base_is_min {
+                    w -= base_width;
+                    h -= base_height;
+                }
+
+                if min_aspect > 0.0 && max_aspect > 0.0 {
+                    if max_aspect < (w as f32 / h as f32) {
+                        w = (h as f32 * max_aspect + 0.5) as i32;
+                    } else if min_aspect < (h as f32 / w as f32) {
+                        h = (w as f32 * min_aspect + 0.5) as i32;
+                    }
+                }
+
+                if base_is_min {
+                    w -= base_width;
+                    h -= base_height;
+                }
+
+                if inc_width > 0 {
+                    w -= w % inc_width;
+                }
+                if inc_height > 0 {
+                    h -= h % inc_height;
+                }
+
+                w = (w + base_width).max(min_width);
+                h = (h + base_height).max(min_height);
+
+                if max_width > 0 {
+                    w = w.min(max_width);
+                }
+                if max_height > 0 {
+                    h = h.min(max_height);
+                }
             }
         }
 
-        (width.max(1), height.max(1))
+        let changed = x != client_x || y != client_y || w != client_w || h != client_h;
+        (x, y, w, h, changed)
     }
 
     fn next_tiled(&self, start: Option<Window>, monitor: &Monitor) -> Option<Window> {
@@ -3991,7 +3777,6 @@ impl WindowManager {
         }
 
         self.windows.retain(|&w| w != window);
-        self.window_geometry_cache.remove(&window);
         self.floating_windows.remove(&window);
 
         if self.windows.len() < initial_count {