Fix command palette over focused scratchpad
The stdin loop's scratchpad-input branch ran before the palette branch and silently dropped every byte except a handful of app-level chords, so palette typing and Esc never reached the palette while a pad was focused. Skip the pad-input branch whenever st.palette != nil. closePalette also called repaintFocused() on cancel / no-op action paths, which paints the empty focused-child slot (focusedID == "" while a pad is focused) and leaves the palette's top border drawn over the pad. Route those branches through a restoreView helper that picks repaintFocusedPad when a pad is focused. Switching from a pad to a child via the palette now clears the pad focus and wipes the viewport, matching focusProcess's pad-exit path. Adds a harness scenario (palette_over_scratchpad) that opens a pad, opens the palette, types a query, and verifies that Esc leaves the pad correctly repainted with no palette chrome lingering.
This commit is contained in:
@@ -1178,7 +1178,11 @@ func (st *uiState) processStdin(chunk []byte) {
|
||||
// palette, Ctrl-WASD focus, Ctrl-B scrollback) fall through to
|
||||
// the handlers below; everything else is swallowed silently so
|
||||
// typing into a pad view can't leak to a child PTY.
|
||||
if st.focusedPad != "" {
|
||||
//
|
||||
// When the palette is open we skip this block entirely so the
|
||||
// palette handler below receives every byte. Otherwise typing
|
||||
// (and Esc) get swallowed here and the palette appears wedged.
|
||||
if st.focusedPad != "" && st.palette == nil {
|
||||
if b == 0x1b { // ESC or CSI
|
||||
if n := csiLen(chunk, i); n > 0 {
|
||||
final := chunk[i+n-1]
|
||||
@@ -1553,16 +1557,32 @@ func (st *uiState) closePalette(action paletteAction) {
|
||||
st.outMu.Unlock()
|
||||
st.clearScreen()
|
||||
|
||||
// When a scratchpad is focused, the "main viewport" is showing the
|
||||
// pad's rendered body, not a child PTY. repaintFocused() would draw
|
||||
// an empty state (focusedID == "") and leave the previous palette's
|
||||
// top border visible in the pad area. Use the pad-aware helper for
|
||||
// any branch below that wants to restore the prior view.
|
||||
restoreView := func() {
|
||||
st.mu.Lock()
|
||||
padFocused := st.focusedPad != ""
|
||||
st.mu.Unlock()
|
||||
if padFocused {
|
||||
st.repaintFocusedPad()
|
||||
return
|
||||
}
|
||||
st.repaintFocused()
|
||||
}
|
||||
|
||||
switch action.kind {
|
||||
case "", "cancel":
|
||||
st.repaintFocused()
|
||||
restoreView()
|
||||
st.drawTabBar()
|
||||
st.drawSidebar()
|
||||
st.drawStatusLine()
|
||||
|
||||
case "spawn-agent":
|
||||
if action.preset == nil {
|
||||
st.repaintFocused()
|
||||
restoreView()
|
||||
return
|
||||
}
|
||||
l := st.layoutSnapshot()
|
||||
@@ -1575,7 +1595,7 @@ func (st *uiState) closePalette(action paletteAction) {
|
||||
|
||||
case "spawn-process":
|
||||
if action.preset == nil {
|
||||
st.repaintFocused()
|
||||
restoreView()
|
||||
return
|
||||
}
|
||||
l := st.layoutSnapshot()
|
||||
@@ -1586,7 +1606,7 @@ func (st *uiState) closePalette(action paletteAction) {
|
||||
|
||||
case "spawn-process-submit":
|
||||
if action.command == "" {
|
||||
st.repaintFocused()
|
||||
restoreView()
|
||||
return
|
||||
}
|
||||
l := st.layoutSnapshot()
|
||||
@@ -1617,16 +1637,24 @@ func (st *uiState) closePalette(action paletteAction) {
|
||||
case "switch":
|
||||
c := st.sess.FindChild(action.childID)
|
||||
if c == nil || (c.Kind == KindAgent && c.Status() != StatusRunning) {
|
||||
st.repaintFocused()
|
||||
restoreView()
|
||||
return
|
||||
}
|
||||
layout := st.layoutSnapshot()
|
||||
st.mu.Lock()
|
||||
leavingPad := st.focusedPad != ""
|
||||
st.focusedPad = ""
|
||||
st.focusedID = action.childID
|
||||
st.focusedName = c.DisplayName()
|
||||
st.updateActiveAgentLocked(c)
|
||||
st.renderer = newViewportRenderer(layout)
|
||||
st.mu.Unlock()
|
||||
// Switching from a pad to a child: wipe the pad body so the
|
||||
// child's snapshot paints onto a clean canvas, mirroring
|
||||
// focusProcess.
|
||||
if leavingPad {
|
||||
st.clearViewportArea()
|
||||
}
|
||||
st.repaintFocused()
|
||||
st.drawTabBar()
|
||||
st.drawSidebar()
|
||||
|
||||
Reference in New Issue
Block a user