The frames now keep coming; the characters still do not

Third measured step, and the last one I will take without a second pair of eyes.

set_as_dirty() BEFORE Refresh(): GLCanvas3D's paint handler returns without rendering when the
canvas is not marked dirty, so the previous commit's bare Refresh() posted paint events that drew
nothing and the frames stopped anyway. With both halves the pump sustains, and the trace shows the
field holding the keyboard frame after frame:

  [UX] frame want_text=1 want_kb=1 active=1 buf=158.74
  [UX] frame want_text=1 want_kb=1 active=1 buf=158.74   (repeating)

STILL OPEN, and now narrowed to one question: buf never changes. ImGui owns the keyboard and our
InputText is the active item, so what is missing is upstream of ImGui — the characters are not
reaching io.AddInputCharacter at all. The next thing to MEASURE (not to change) is whether
wxEVT_CHAR arrives at the GL canvas in the Design tab: DesignPanel's wxEVT_CHAR_HOOK Skips digits
while inline_busy(), but Skip only helps if the focused widget is the canvas, and nothing has yet
proved that it is at the moment the keys are sent.

Three attempts have now gone into this one point. Per the standing rule that is where solo
iteration stops.

Deployed binary restored to 00d6c191dc (md5 0eeb9a58cef5) — nothing from this branch is installed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011FbJKJAJxxkhDTs9XdZzKA
This commit is contained in:
Tommaso Bianchi
2026-09-06 10:58:05 +02:00
co-authored by Claude Opus 5
parent d82c8b59c2
commit b45d675488
+15 -1
View File
@@ -87,7 +87,21 @@ DesignCanvas::DesignCanvas(wxWindow* parent)
// The tool draws it: it owns the frame's ImGui pass and the render scale. Handing it a raw
// pointer rather than the unique_ptr keeps the ownership where it was.
m_sketch_tool.inline_editor = m_inline_editor.get();
m_inline_editor->request_frame = [this] { request_repaint(); };
// SCHEDULE a paint, do not render one. request_repaint() renders SYNCHRONOUSLY on software
// GL, and this callback runs from inside DesignSketchTool::render() — so using it here asks
// for a render from within a render. The frames stopped after nine, which is what a
// re-entrancy guard giving up looks like. Refresh() posts a paint event instead: the current
// frame finishes, the event loop runs (which is where ImGui's queued characters are consumed),
// and the next frame starts clean.
m_inline_editor->request_frame = [this] {
// BOTH halves, and the dirty flag first: GLCanvas3D's paint handler returns without
// rendering when the canvas is not marked dirty, so a bare Refresh() posts an event that
// draws nothing and the frames still stop. request_repaint() does exactly this pair on
// the hardware path; what it must NOT do here is its software path, which renders
// synchronously — and this callback runs from inside render().
if (m_canvas) m_canvas->set_as_dirty();
if (m_canvas_widget) m_canvas_widget->Refresh(false);
};
m_sketch_tool.on_inline_edit = [this](wxPoint screen_px, double current,
const std::string& title,
std::function<void(double)> commit,