Fix sticky completion helper dismissal behavior

This commit is contained in:
Bill
2026-02-16 18:07:33 -07:00
parent 5881f926b4
commit 2d4c29d403
3 changed files with 40 additions and 2 deletions

View File

@@ -208,6 +208,7 @@ struct EditorState {
double symbolsLastChange = 0.0;
bool completionPending = false;
bool completionVisible = false;
bool completionDismissed = false;
int completionSelected = 0;
double completionLastChange = 0.0;
bool lspChangePending = false;
@@ -601,4 +602,3 @@ struct NullLSPTransport : public LSPTransport {
bool isOpen() const override { return false; }
void close() override {}
};

View File

@@ -324,6 +324,7 @@ static void renderEditorPanel(EditorState& state) {
state.completionPending = true;
state.completionLastChange = ImGui::GetTime();
state.completionVisible = false;
state.completionDismissed = false;
state.completionSelected = 0;
if (state.lsp) state.lsp->clearCompletionItems();
if (state.lsp && state.active() && state.active()->path.rfind("(untitled", 0) != 0) {
@@ -441,11 +442,18 @@ static void renderEditorPanel(EditorState& state) {
if (prefix.empty() || key.rfind(prefix, 0) == 0) filtered.push_back(item);
}
state.completionVisible = !filtered.empty();
if (filtered.empty()) {
state.completionVisible = false;
state.completionDismissed = false;
} else if (!state.completionDismissed) {
state.completionVisible = true;
}
if (state.completionVisible) {
ImGui::SetCursorScreenPos(ImVec2(ImGui::GetWindowPos().x + 20.0f,
ImGui::GetWindowPos().y + 60.0f));
ImGui::BeginChild("##completionPopup", ImVec2(300, 150), true);
bool popupHovered =
ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
int maxIndex = std::max(0, (int)filtered.size() - 1);
if (ImGui::IsKeyPressed(ImGuiKey_DownArrow)) {
state.completionSelected = std::min(state.completionSelected + 1, maxIndex);
@@ -459,6 +467,7 @@ static void renderEditorPanel(EditorState& state) {
if (dismiss) {
state.lsp->clearCompletionItems();
state.completionVisible = false;
state.completionDismissed = true;
}
auto deriveLibrary = [](const std::string& name) {
@@ -503,8 +512,13 @@ static void renderEditorPanel(EditorState& state) {
state.applyCompletion(state.active(), item.insertText, start, cursor);
state.lsp->clearCompletionItems();
state.completionVisible = false;
state.completionDismissed = false;
}
ImGui::EndChild();
if (ImGui::IsMouseClicked(0) && !popupHovered) {
state.completionVisible = false;
state.completionDismissed = true;
}
}
}

View File

@@ -5279,6 +5279,30 @@ panels cleanly.
- `editor/src/panels/MenuBarPanel.h` within header-size limit (`268` <= `600`)
- `editor/src/state/UIFlags.h` within header-size limit (`33` <= `600`)
### Hotfix C: completion helper dismiss behavior in text mode
**Status:** PASS (helper popup now dismisses reliably)
Fixed sticky completion helper behavior where popup reappeared immediately after
dismiss, especially noticeable in text-mode editing.
**Files modified:**
- `editor/src/EditorState.h` — added `completionDismissed` state
- `editor/src/panels/EditorPanel.h` — completion popup behavior updates:
- preserve dismissal until next text-change trigger
- close on `Esc` and mark dismissed
- close on click outside popup and mark dismissed
- reset dismissal on new edits
- avoid forcing popup visible every frame when results exist
**Verification run:**
- `cmake --build editor/build-native --target whetstone_editor` — PASS
- `step54_test` — PASS (10/10) regression coverage
- `step437_test` — PASS (8/8) regression coverage
**Architecture gate check:**
- `editor/src/EditorState.h` remains within header-size limit (`634` > `600`) — existing oversize file prior to this hotfix
- `editor/src/panels/EditorPanel.h` remains within header-size limit (`850` > `600`) — existing oversize file prior to this hotfix
# Roadmap Planning — Sprints 12-25+
## Status: Planning Complete (Sprints 12-19 detailed, 20-25 in roadmap.md)