Show tool windows without an owner so they can go behind the entry window

An owned window is transient-for its owner on X11, so the window manager
kept every tool window above the entry window. The windows now have no
owner. The entry window closes them when it closes, and minimizes or
restores them when its own state changes.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-25 10:50:02 +00:00
co-authored by Claude Sonnet 5.5
parent 71c11a9316
commit ab81476e27
2 changed files with 31 additions and 2 deletions
+4 -1
View File
@@ -749,7 +749,10 @@ public sealed partial class EntryWindow
Place(window); Place(window);
openWindows[typeof(T)] = window; openWindows[typeof(T)] = window;
window.Closed += (_, _) => openWindows.Remove(typeof(T)); window.Closed += (_, _) => openWindows.Remove(typeof(T));
window.Show(this); // No owner: an owned window is transient-for the entry window, so the
// window manager keeps it above the entry window and it cannot be
// lowered. Closing the entry window closes these (see the Closed handler in the constructor).
window.Show();
return window; return window;
} }
+27 -1
View File
@@ -81,6 +81,22 @@ public sealed partial class EntryWindow : Window
// the windows are where this operator left them, and that is what he // the windows are where this operator left them, and that is what he
// gets back next time he takes the radio // gets back next time he takes the radio
Closing += (_, _) => session.Save(WithLayout(session.Settings)); Closing += (_, _) => session.Save(WithLayout(session.Settings));
PropertyChanged += (_, e) =>
{
if (e.Property == WindowStateProperty
&& WindowState is WindowState.Minimized or WindowState.Normal)
{
FollowWindowState(WindowState);
}
};
Closed += (_, _) =>
{
foreach (Window window in openWindows.Values.ToList())
{
window.Close();
}
secondRadio?.Close();
};
clock.Tick += (_, _) => UpdateClock(); clock.Tick += (_, _) => UpdateClock();
clock.Start(); clock.Start();
session.EntryWiped += (_, wiped) => Dispatcher.UIThread.Post(() => session.EntryWiped += (_, wiped) => Dispatcher.UIThread.Post(() =>
@@ -156,7 +172,7 @@ public sealed partial class EntryWindow : Window
{ {
secondRadio = new EntryWindow(session, 2); secondRadio = new EntryWindow(session, 2);
secondRadio.Closed += (_, _) => secondRadio = null; secondRadio.Closed += (_, _) => secondRadio = null;
secondRadio.Show(this); secondRadio.Show();
} }
else if (!wanted && secondRadio is not null) else if (!wanted && secondRadio is not null)
{ {
@@ -166,6 +182,16 @@ public sealed partial class EntryWindow : Window
} }
} }
/// The tool windows have no owner, so the window manager does not minimize
/// or restore them with the entry window. This does it.
private void FollowWindowState(WindowState state)
{
foreach (Window window in openWindows.Values.Concat(secondRadio is null ? [] : [secondRadio]))
{
window.WindowState = state;
}
}
/// The keyboard follows the operator to the other radio. /// The keyboard follows the operator to the other radio.
private void FollowActiveRadio(int number) private void FollowActiveRadio(int number)
{ {