gardesk/tarmac / 882a288

Browse files

Auto-float windows with AXModal=true regardless of subrole

Lots of app-defined modals (save dialogs, confirmation prompts,
inline preference panels) ship with subrole=AXStandardWindow and
relied on the human reading 'looks modal' to know not to tile them.
Tarmac was tiling them alongside the parent window. Detect AXModal
explicitly, and add AXSystemDialog to the subrole allowlist for the
ones that do declare it correctly.
Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
882a2889caf01eaa31646b0401b7b6cb3848017d
Parents
e9eabd1
Tree
8327d80

1 changed file

StatusFile+-
M tarmac/src/core/state.rs 24 5
tarmac/src/core/state.rsmodified
@@ -2915,7 +2915,7 @@ impl WmState {
2915
             }
2915
             }
2916
         }
2916
         }
2917
 
2917
 
2918
-        let should_float = rule_float.unwrap_or_else(|| should_auto_float(subrole, width, height));
2918
+        let should_float = rule_float.unwrap_or_else(|| should_auto_float(subrole, &ax_ref));
2919
 
2919
 
2920
         self.registry.add(WindowState {
2920
         self.registry.add(WindowState {
2921
             id: *id,
2921
             id: *id,
@@ -3225,11 +3225,30 @@ impl WmState {
3225
 }
3225
 }
3226
 
3226
 
3227
 /// Check if a window should automatically float based on its subrole and size.
3227
 /// Check if a window should automatically float based on its subrole and size.
3228
-fn should_auto_float(subrole: &str, _width: f64, _height: f64) -> bool {
3228
+fn should_auto_float(subrole: &str, ax_ref: &AXUIElement) -> bool {
3229
-    matches!(
3229
+    use crate::platform::accessibility::ax_get_bool;
3230
+    use objc2_core_foundation::CFString;
3231
+
3232
+    if matches!(
3230
         subrole,
3233
         subrole,
3231
-        "AXDialog" | "AXSheet" | "AXFloatingWindow" | "AXSystemFloatingWindow"
3234
+        "AXDialog"
3232
-    )
3235
+            | "AXSystemDialog"
3236
+            | "AXSheet"
3237
+            | "AXFloatingWindow"
3238
+            | "AXSystemFloatingWindow"
3239
+    ) {
3240
+        return true;
3241
+    }
3242
+
3243
+    // Many "modal-feeling" NSWindows ship with subrole=AXStandardWindow but
3244
+    // mark AXModal=true. Treat those as floats so save/confirm dialogs and
3245
+    // app-defined modals don't get tiled alongside their parent window.
3246
+    let modal_attr = CFString::from_static_str("AXModal");
3247
+    if ax_get_bool(ax_ref, &modal_attr).unwrap_or(false) {
3248
+        return true;
3249
+    }
3250
+
3251
+    false
3233
 }
3252
 }
3234
 
3253
 
3235
 /// Warp the mouse cursor to the center of a rect.
3254
 /// Warp the mouse cursor to the center of a rect.