@@ -700,11 +700,22 @@ impl WindowManager { |
| 700 | 700 | |
| 701 | 701 | // Warp pointer to center of focused window (mouse follows focus) |
| 702 | 702 | if warp_pointer { |
| 703 | + // Use stored geometry instead of querying X11 (avoids race with ConfigureWindow) |
| 704 | + if let Some(win) = self.windows.get(&window) { |
| 705 | + let g = &win.current_geometry; |
| 706 | + let center_x = g.x + (g.width as i16 / 2); |
| 707 | + let center_y = g.y + (g.height as i16 / 2); |
| 708 | + if let Err(e) = self.conn.warp_pointer(center_x, center_y) { |
| 709 | + tracing::warn!("Failed to warp pointer: {}", e); |
| 710 | + } |
| 711 | + } else { |
| 712 | + // Fallback to querying X11 if window not in our map |
| 703 | 713 | if let Err(e) = self.conn.warp_pointer_to_window(window) { |
| 704 | 714 | tracing::warn!("Failed to warp pointer: {}", e); |
| 705 | 715 | } |
| 706 | | - // Record warp time to suppress EnterNotify feedback loop |
| 716 | + } |
| 707 | 717 | self.last_warp = std::time::Instant::now(); |
| 718 | + self.conn.flush()?; |
| 708 | 719 | } |
| 709 | 720 | |
| 710 | 721 | Ok(()) |
@@ -981,6 +992,11 @@ impl WindowManager { |
| 981 | 992 | border_width, |
| 982 | 993 | )?; |
| 983 | 994 | } |
| 995 | + |
| 996 | + // Store the actual geometry for pointer warping |
| 997 | + if let Some(win) = self.windows.get_mut(window) { |
| 998 | + win.current_geometry = Rect::new(gapped_x, gapped_y, final_width.max(1), final_height.max(1)); |
| 999 | + } |
| 984 | 1000 | } |
| 985 | 1001 | |
| 986 | 1002 | // 2. Configure floating windows and stack them above tiled |
@@ -988,13 +1004,17 @@ impl WindowManager { |
| 988 | 1004 | |
| 989 | 1005 | for window_id in floating_ids { |
| 990 | 1006 | // Get the window's floating geometry from our state |
| 991 | | - if let Some(win) = self.windows.get(&window_id) { |
| 992 | | - let geom = win.floating_geometry; |
| 1007 | + let (geom, has_frame) = match self.windows.get(&window_id) { |
| 1008 | + Some(win) => (win.floating_geometry, win.frame.is_some()), |
| 1009 | + None => { |
| 1010 | + tracing::warn!("apply_layout: floating window {} not in windows map!", window_id); |
| 1011 | + continue; |
| 1012 | + } |
| 1013 | + }; |
| 1014 | + |
| 993 | 1015 | let adjusted_width = geom.width.saturating_sub(2 * border_width as u16); |
| 994 | 1016 | let adjusted_height = geom.height.saturating_sub(2 * border_width as u16); |
| 995 | 1017 | |
| 996 | | - let has_frame = win.frame.is_some(); |
| 997 | | - |
| 998 | 1018 | if has_frame && titlebar_enabled { |
| 999 | 1019 | // Configure frame for floating window |
| 1000 | 1020 | let client_height = adjusted_height.saturating_sub(titlebar_height); |
@@ -1039,8 +1059,10 @@ impl WindowManager { |
| 1039 | 1059 | let aux = ConfigureWindowAux::new().stack_mode(StackMode::ABOVE); |
| 1040 | 1060 | self.conn.conn.configure_window(window_id, &aux)?; |
| 1041 | 1061 | } |
| 1042 | | - } else { |
| 1043 | | - tracing::warn!("apply_layout: floating window {} not in windows map!", window_id); |
| 1062 | + |
| 1063 | + // Store the actual geometry for pointer warping |
| 1064 | + if let Some(win) = self.windows.get_mut(&window_id) { |
| 1065 | + win.current_geometry = Rect::new(geom.x, geom.y, adjusted_width.max(1), adjusted_height.max(1)); |
| 1044 | 1066 | } |
| 1045 | 1067 | } |
| 1046 | 1068 | } |