diff --git a/modules/nixos/desktop/desktop-niri.ulu.nix b/modules/nixos/desktop/desktop-niri.ulu.nix index 209c886..db4c083 100644 --- a/modules/nixos/desktop/desktop-niri.ulu.nix +++ b/modules/nixos/desktop/desktop-niri.ulu.nix @@ -6,15 +6,12 @@ programs.niri.enable = true; nixpkgs.overlays = [ (final: prev: { - xwayland-satellite = - if prev.lib.versionOlder prev.xwayland-satellite.version "0.8.3" then - prev.xwayland-satellite.overrideAttrs (old: { - patches = (old.patches or [ ]) ++ [ - ./xwayland-satellite-no-focus-override-redirect.patch - ]; - }) - else - prev.xwayland-satellite; + xwayland-satellite = prev.xwayland-satellite.overrideAttrs (old: { + patches = + (old.patches or [ ]) + ++ prev.lib.optional (prev.lib.versionOlder old.version "0.8.3") ./xwayland-satellite-no-focus-override-redirect.patch + ++ prev.lib.optional (prev.lib.versionOlder old.version "0.8.4") ./xwayland-satellite-resizable-dialog-toplevel.patch; + }); }) ]; diff --git a/modules/nixos/desktop/xwayland-satellite-resizable-dialog-toplevel.patch b/modules/nixos/desktop/xwayland-satellite-resizable-dialog-toplevel.patch new file mode 100644 index 0000000..c7e028d --- /dev/null +++ b/modules/nixos/desktop/xwayland-satellite-resizable-dialog-toplevel.patch @@ -0,0 +1,49 @@ +--- a/src/xstate/mod.rs 2026-10-10 02:55:59.663368893 +0300 ++++ b/src/xstate/mod.rs 2026-10-10 02:55:59.699369500 +0300 +@@ -1189,7 +1189,9 @@ + match ty { + x if x == window_atoms.normal => return WindowRole::Toplevel, + x if x == window_atoms.dialog => { +- return WindowRole::new_basic(self.has_transient_for && motif_no_decor); ++ return WindowRole::new_basic( ++ self.has_transient_for && motif_no_decor && forced_size, ++ ); + } + x if x == window_atoms.utility => { + return WindowRole::new_basic(motif_no_decor && forced_size); +--- a/src/xstate/tests.rs 2026-10-10 02:55:59.665368927 +0300 ++++ b/src/xstate/tests.rs 2026-10-10 02:56:08.382515889 +0300 +@@ -473,6 +473,33 @@ + assert_eq!(win.guess_window_role(&win_types), WindowRole::Popup); + } + ++ // https://github.com/Supreeeme/xwayland-satellite/issues/470 ++ // A DIALOG with TRANSIENT_FOR and no Motif decorations which is resizable ++ // (min_size != max_size) should be a top-level, mirroring the UTILITY fix in #383. ++ // Otherwise the popup parent resolves to a hidden WM_CLIENT_LEADER and the ++ // window never appears (e.g. DaVinci Resolve's Project Manager). ++ // Window attributes are taken from the full xprop posted in #470 (DIALOG + ++ // NORMAL window types, _MOTIF_WM_HINTS decorations=0, resizable normal hints). ++ #[test] ++ fn davinci_resolve_project_manager() { ++ let win_types = WindowTypes::new(); ++ let wm_normal_hints = WmNormalHints::new() ++ .user_pos(978, 270) ++ .user_size(1884, 1620) ++ .min_size(910, 640) ++ .max_size(2880, 1620) ++ .win_gravity(Gravity::Static); ++ let win = WindowRoleHeuristics { ++ has_transient_for: true, ++ motif_wm_hints: Some(motif::Hints::from([0x2_u32, 0x1, 0, 0, 0].as_slice())), ++ window_types: vec![win_types.dialog, win_types.normal], ++ wm_normal_hints: Some(wm_normal_hints.into()), ++ wm_class: Some("resolve".into()), ++ ..Default::default() ++ }; ++ assert_eq!(win.guess_window_role(&win_types), WindowRole::Toplevel); ++ } ++ + // https://github.com/Supreeeme/xwayland-satellite/pull/390 + // With Motif decorations, even a dialog with TRANSIENT_FOR is better treated as a top-level + #[test]