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 {
29152915
             }
29162916
         }
29172917
 
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));
29192919
 
29202920
         self.registry.add(WindowState {
29212921
             id: *id,
@@ -3225,11 +3225,30 @@ impl WmState {
32253225
 }
32263226
 
32273227
 /// 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 {
3229
-    matches!(
3228
+fn should_auto_float(subrole: &str, ax_ref: &AXUIElement) -> bool {
3229
+    use crate::platform::accessibility::ax_get_bool;
3230
+    use objc2_core_foundation::CFString;
3231
+
3232
+    if matches!(
32303233
         subrole,
3231
-        "AXDialog" | "AXSheet" | "AXFloatingWindow" | "AXSystemFloatingWindow"
3232
-    )
3234
+        "AXDialog"
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
32333252
 }
32343253
 
32353254
 /// Warp the mouse cursor to the center of a rect.