gardesk/gardisplay / df76f20

Browse files

fix scaling: validate profile monitors and always reset scale transform

- Don't apply profile positions when monitor set doesn't match current
- Add sanity check for clearly invalid positions (negative or >10000)
- Watchdog now always includes --scale NxN to reset transforms
- Fixes issue where stale multi-monitor profile caused wrong positions
Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
df76f209e963646faf5481d7f739b90786a3ae02
Parents
74bf29b
Tree
94e1396

2 changed files

StatusFile+-
M gardisplay/src/app.rs 39 7
M gardisplay/src/watchdog.rs 8 6
gardisplay/src/app.rsmodified
@@ -244,16 +244,48 @@ impl App {
244
             .map(|m| (m.name.as_str(), m))
244
             .map(|m| (m.name.as_str(), m))
245
             .collect();
245
             .collect();
246
 
246
 
247
+        // Check if the profile's monitor set matches the current monitors
248
+        let current_monitors: Vec<&str> = view.monitors().iter().map(|s| s.info.name.as_str()).collect();
249
+        let profile_monitors: Vec<&str> = profile.monitors.iter().map(|m| m.name.as_str()).collect();
250
+
251
+        let monitors_match = current_monitors.len() == profile_monitors.len()
252
+            && current_monitors.iter().all(|m| profile_monitors.contains(m));
253
+
254
+        if !monitors_match {
255
+            tracing::warn!(
256
+                "profile monitors {:?} don't match current monitors {:?}, skipping position loading",
257
+                profile_monitors,
258
+                current_monitors
259
+            );
260
+            // Still set primary if specified
261
+            if let Some(ref primary) = profile.primary {
262
+                view.set_primary(primary);
263
+            }
264
+            view.recalculate_layout();
265
+            return;
266
+        }
267
+
247
         // Update monitor positions from profile
268
         // Update monitor positions from profile
248
         for state in view.monitors_mut() {
269
         for state in view.monitors_mut() {
249
             if let Some(config) = config_map.get(state.info.name.as_str()) {
270
             if let Some(config) = config_map.get(state.info.name.as_str()) {
250
-                state.real_position = gartk_core::Point::new(config.x, config.y);
271
+                // Sanity check: don't apply positions that are clearly wrong
251
-                tracing::debug!(
272
+                // (negative positions or positions way outside screen bounds)
252
-                    "loaded {} at ({}, {})",
273
+                if config.x >= 0 && config.y >= 0 && config.x < 10000 && config.y < 10000 {
253
-                    state.info.name,
274
+                    state.real_position = gartk_core::Point::new(config.x, config.y);
254
-                    config.x,
275
+                    tracing::debug!(
255
-                    config.y
276
+                        "loaded {} at ({}, {})",
256
-                );
277
+                        state.info.name,
278
+                        config.x,
279
+                        config.y
280
+                    );
281
+                } else {
282
+                    tracing::warn!(
283
+                        "ignoring invalid position ({}, {}) for {}",
284
+                        config.x,
285
+                        config.y,
286
+                        state.info.name
287
+                    );
288
+                }
257
             }
289
             }
258
         }
290
         }
259
 
291
 
gardisplay/src/watchdog.rsmodified
@@ -111,22 +111,24 @@ fn generate_xrandr_commands(configs: &[MonitorConfig]) -> String {
111
             _ => "normal",
111
             _ => "normal",
112
         };
112
         };
113
 
113
 
114
-        // Include scale if not 1.0
114
+        // Always include scale to reset any transforms
115
-        let scale_arg = if (config.scale - 1.0).abs() > 0.001 {
115
+        // scale 1x1 resets to identity transform
116
-            format!(" --scale {}x{}", config.scale, config.scale)
116
+        let scale = if (config.scale - 1.0).abs() > 0.001 {
117
+            config.scale
117
         } else {
118
         } else {
118
-            String::new()
119
+            1.0
119
         };
120
         };
120
 
121
 
121
         commands.push(format!(
122
         commands.push(format!(
122
-            "xrandr --output {} --mode {}x{} --pos {}x{} --rotate {}{}",
123
+            "xrandr --output {} --mode {}x{} --pos {}x{} --rotate {} --scale {}x{}",
123
             config.name,
124
             config.name,
124
             config.width,
125
             config.width,
125
             config.height,
126
             config.height,
126
             config.x,
127
             config.x,
127
             config.y,
128
             config.y,
128
             rotation,
129
             rotation,
129
-            scale_arg
130
+            scale,
131
+            scale
130
         ));
132
         ));
131
     }
133
     }
132
 
134