gardesk/gar / 0c71d2c

Browse files

Clear root window on window close to fix visual artifacts

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
0c71d2c44a352c24881246fa92f3e1effea17cd8
Parents
80bba0d
Tree
e660517

2 changed files

StatusFile+-
M gar/src/x11/connection.rs 29 6
M gar/src/x11/events.rs 11 0
gar/src/x11/connection.rsmodified
@@ -118,18 +118,35 @@ impl Connection {
118118
     }
119119
 
120120
     pub fn become_wm(&self) -> Result<(), Error> {
121
-        let change = ChangeWindowAttributesAux::new().event_mask(
122
-            EventMask::SUBSTRUCTURE_REDIRECT
123
-                | EventMask::SUBSTRUCTURE_NOTIFY
124
-                | EventMask::STRUCTURE_NOTIFY
125
-                | EventMask::PROPERTY_CHANGE,
126
-        );
121
+        // Set root window background to black and subscribe to events
122
+        // The background ensures old window pixels are cleared when windows close
123
+        let change = ChangeWindowAttributesAux::new()
124
+            .event_mask(
125
+                EventMask::SUBSTRUCTURE_REDIRECT
126
+                    | EventMask::SUBSTRUCTURE_NOTIFY
127
+                    | EventMask::STRUCTURE_NOTIFY
128
+                    | EventMask::PROPERTY_CHANGE,
129
+            )
130
+            .background_pixel(self.screen().black_pixel);
127131
 
128132
         let result = self
129133
             .conn
130134
             .change_window_attributes(self.root, &change)?
131135
             .check();
132136
 
137
+        // Clear the root window to apply the background
138
+        if result.is_ok() {
139
+            self.conn.clear_area(
140
+                false,
141
+                self.root,
142
+                0,
143
+                0,
144
+                self.screen_width,
145
+                self.screen_height,
146
+            )?;
147
+            self.conn.flush()?;
148
+        }
149
+
133150
         match result {
134151
             Ok(_) => {
135152
                 tracing::info!("Successfully became window manager");
@@ -260,6 +277,12 @@ impl Connection {
260277
         Ok(())
261278
     }
262279
 
280
+    /// Clear an area of the root window (fills with background color).
281
+    pub fn clear_root_area(&self, x: i16, y: i16, width: u16, height: u16) -> Result<(), Error> {
282
+        self.conn.clear_area(false, self.root, x, y, width, height)?;
283
+        Ok(())
284
+    }
285
+
263286
     /// Configure a window's geometry.
264287
     pub fn configure_window(
265288
         &self,
gar/src/x11/events.rsmodified
@@ -274,6 +274,10 @@ impl WindowManager {
274274
         // are unmapped intentionally by us during workspace switching
275275
         if is_visible {
276276
             self.unmanage_window(window);
277
+
278
+            // Clear the entire root window to remove any leftover pixels
279
+            self.conn.clear_root_area(0, 0, self.conn.screen_width, self.conn.screen_height)?;
280
+
277281
             self.apply_layout()?;
278282
 
279283
             // Focus next window or warp to monitor if none left
@@ -283,6 +287,8 @@ impl WindowManager {
283287
                 // No windows left, warp to current monitor center
284288
                 self.warp_to_monitor(self.focused_monitor)?;
285289
             }
290
+
291
+            self.conn.flush()?;
286292
         }
287293
 
288294
         Ok(())
@@ -294,6 +300,10 @@ impl WindowManager {
294300
         // Remove from management
295301
         self.unmanage_window(event.window);
296302
 
303
+        // Clear the entire root window to remove any leftover pixels
304
+        // This is needed because X11 without a compositor doesn't automatically repaint
305
+        self.conn.clear_root_area(0, 0, self.conn.screen_width, self.conn.screen_height)?;
306
+
297307
         // Re-apply layout
298308
         self.apply_layout()?;
299309
 
@@ -305,6 +315,7 @@ impl WindowManager {
305315
             self.warp_to_monitor(self.focused_monitor)?;
306316
         }
307317
 
318
+        self.conn.flush()?;
308319
         Ok(())
309320
     }
310321