Stop raising from restoring the entry window and focus the callsign box

The window manager activates another window when the entry window
minimizes, and raising the windows then restored the entry window.
Raising is now skipped while the entry window is minimized and for a
second after its state changes. Restoring the entry window puts focus
in the callsign box.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-25 11:27:46 +00:00
co-authored by Claude Sonnet 5.5
parent 8c80a46e5e
commit 845a629e37
6 changed files with 57 additions and 14 deletions
@@ -27,6 +27,8 @@ public sealed partial class CheckWindow : RefreshableWindow
}
public override void RefreshForEntry() => Refresh();
public override void Refresh()
{
Columns.Children.Clear();
+40 -9
View File
@@ -83,8 +83,16 @@ public sealed partial class EntryWindow : Window
Closing += (_, _) => session.Save(WithLayout(session.Settings));
PropertyChanged += (_, e) =>
{
if (e.Property == WindowStateProperty
&& session.Settings.MinimizeWindowsTogether
if (e.Property != WindowStateProperty)
{
return;
}
lastStateChange = Environment.TickCount64;
if (WindowState == WindowState.Normal)
{
Dispatcher.UIThread.Post(() => boxes.ElementAtOrDefault(0)?.Focus(), DispatcherPriority.Background);
}
if (session.Settings.MinimizeWindowsTogether
&& WindowState is WindowState.Minimized or WindowState.Normal)
{
FollowWindowState(WindowState);
@@ -195,13 +203,19 @@ public sealed partial class EntryWindow : Window
}
private long lastRaise;
private long lastStateChange;
/// Brings the other windows that are not minimized above whatever else is
/// on screen, then puts `front` back on top. Activating them fires their
/// own Activated events, so raises within half a second are ignored.
private void RaiseTogether(Window front)
{
if (!session.Settings.RaiseWindowsTogether || Environment.TickCount64 - lastRaise < 500)
// The window manager activates another window when the entry window
// minimizes. Raising then would restore the entry window.
if (!session.Settings.RaiseWindowsTogether
|| Environment.TickCount64 - lastRaise < 500
|| Environment.TickCount64 - lastStateChange < 1000
|| WindowState == WindowState.Minimized)
{
return;
}
@@ -380,7 +394,8 @@ public sealed partial class EntryWindow : Window
private bool typingRefreshPosted;
/// Refresh redraws this window and every open tool window, which is too
/// slow to run between two key presses. It runs once the key presses
/// slow to run between two key presses. Typing refreshes this window and
/// the tool windows that show the call, and it runs once the key presses
/// waiting in the queue have been handled, so fast typing costs one
/// refresh instead of one per letter.
private void RefreshAfterTyping()
@@ -394,7 +409,7 @@ public sealed partial class EntryWindow : Window
() =>
{
typingRefreshPosted = false;
Refresh();
RefreshForTyping();
},
DispatcherPriority.Background);
}
@@ -919,6 +934,26 @@ public sealed partial class EntryWindow : Window
}
internal void Refresh()
{
RefreshSelf();
foreach (Window window in openWindows.Values)
{
(window as RefreshableWindow)?.Refresh();
}
}
/// What a typed letter changes: this window, and the tool windows that
/// show something about the call being typed.
private void RefreshForTyping()
{
RefreshSelf();
foreach (Window window in openWindows.Values)
{
(window as RefreshableWindow)?.RefreshForEntry();
}
}
private void RefreshSelf()
{
ShowFunctionKeys();
ShowBandButtons();
@@ -967,10 +1002,6 @@ public sealed partial class EntryWindow : Window
VerdictBorder.Background = Verdicts.Background(verdict);
VerdictText.Text = VerdictLine(verdict);
VerdictText.Foreground = Themes.Brush(Themes.Current.FormForeground);
foreach (Window window in openWindows.Values)
{
(window as RefreshableWindow)?.Refresh();
}
}
/// N1MM colours the callsign itself rather than the box: blue for a station
@@ -36,6 +36,8 @@ public sealed partial class GraylineWindow : RefreshableWindow
private OperatingPosition? Radio => session.Position;
public override void RefreshForEntry() => Refresh();
public override void Refresh()
{
Map.Moment = DateTime.UtcNow;
@@ -204,6 +204,8 @@ public sealed partial class LogWindow : RefreshableWindow
return new ContextMenu { ItemsSource = new List<MenuItem> { edit, operators, delete } };
}
public override void RefreshForEntry() => ShowEarlier();
public override void Refresh()
{
if (session.Logging is null)
@@ -6,4 +6,10 @@ namespace Nonemm.App.Windows;
public abstract class RefreshableWindow : Window
{
public abstract void Refresh();
/// Called instead of `Refresh` when the entry window's call or exchange
/// changes. A window that shows nothing about them does nothing.
public virtual void RefreshForEntry()
{
}
}