C2/C3: restore rotation keybinds (REPLY/LS-cycle) + focus contract routing on the focused chat surface
This commit is contained in:
@@ -13,7 +13,7 @@ namespace HellionChat.Ui.Windows;
|
||||
// via ctor — see plan §B.2. The ###id carries the slot index so all N
|
||||
// instances are unique for WindowSystem.AddWindow and ImGui state is stable
|
||||
// per slot (not per bound tab).
|
||||
internal sealed class ChannelPopoutWindow : Window
|
||||
internal sealed class ChannelPopoutWindow : Window, IFocusableChatWindow
|
||||
{
|
||||
private readonly int _slotIndex;
|
||||
private readonly MessageList _messages;
|
||||
@@ -75,6 +75,18 @@ internal sealed class ChannelPopoutWindow : Window
|
||||
IsOpen = false;
|
||||
}
|
||||
|
||||
// IFocusableChatWindow — this pop-out's own InputBar carries the focus state
|
||||
// the keybind tail checks when deciding whether to route at this surface (C3).
|
||||
public bool HasFocusedInput => _input.IsFocused;
|
||||
|
||||
// Arm-and-hold the one-frame Activate flag; the pop-out's Draw applies the
|
||||
// ImGui focus next frame. Framework-thread safe (field write only).
|
||||
public void RequestInputFocus()
|
||||
{
|
||||
BringToFront();
|
||||
_input.Activate = true;
|
||||
}
|
||||
|
||||
public override void PreDraw()
|
||||
{
|
||||
// Gate the native title bar on the user toggle (1.5.6 parity). DrawHeader
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace HellionChat.Ui.Windows;
|
||||
|
||||
// Focus contract shared by the main window and each pop-out so the keybind tail
|
||||
// can route channel-set / REPLY / prefill to whichever surface currently owns the
|
||||
// input focus, without the KeybindManager reaching into either window's privates.
|
||||
// HasFocusedInput reads the bound InputBar's per-frame focus state; RequestInputFocus
|
||||
// only arms the one-frame Activate flag (ImGui focus is frame-bound — never call
|
||||
// SetKeyboardFocusHere from the framework thread).
|
||||
internal interface IFocusableChatWindow
|
||||
{
|
||||
bool HasFocusedInput { get; }
|
||||
|
||||
void RequestInputFocus();
|
||||
}
|
||||
@@ -16,7 +16,7 @@ namespace HellionChat.Ui.Windows;
|
||||
// Components are fully qualified through the Ui.Components prefix so the
|
||||
// old Ui.StatusBar type (still alive until the cleanup block removes it)
|
||||
// cannot shadow the new layer through parent-namespace resolution.
|
||||
internal sealed class MainWindow : Window
|
||||
internal sealed class MainWindow : Window, IFocusableChatWindow
|
||||
{
|
||||
private const float DefaultWidth = 620f;
|
||||
private const float DefaultHeight = 340f;
|
||||
@@ -205,6 +205,18 @@ internal sealed class MainWindow : Window
|
||||
_input.Activate = true;
|
||||
}
|
||||
|
||||
// IFocusableChatWindow — the keybind tail resolves which surface owns the
|
||||
// input focus before routing a channel-set/REPLY/prefill at it (C3).
|
||||
public bool HasFocusedInput => _input.IsFocused;
|
||||
|
||||
// Arm-and-hold: field writes only, safe from the framework thread; the draw
|
||||
// path applies the actual ImGui focus next frame (same path as ActivateChat).
|
||||
public void RequestInputFocus()
|
||||
{
|
||||
BringToFront();
|
||||
_input.Activate = true;
|
||||
}
|
||||
|
||||
// new-shadow on Window.Toggle so the open path also writes Config. A user-hide
|
||||
// counts as "not visible", so /hellion is a reliable one-press recovery even when
|
||||
// the Enter keybind can't fire (DirectChat / a focused game text field).
|
||||
|
||||
Reference in New Issue
Block a user