mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-28 03:11:47 +00:00
Sketch value fields: content-based key arbiter + the gate that can judge it
The reported defect: sketch dimension labels are "not editable" — you draw a
rectangle, its Width field opens, you type, and the as-drawn number is committed
instead. It affects every sketch tool, not just the rounded rectangle.
WHAT THIS ADDS
1. The arbiter (DesignPanel CHAR_HOOK -> DesignCanvas::inline_type_char ->
SketchInlineEditor::type_char). Routes a key by what it IS, not by who the
window manager focused: digits, sign, decimal separator and Backspace/Delete
go to the open value field, Enter/Tab commit, letters stay tool shortcuts.
This is FreeCAD Sketcher's rule (DrawSketchKeyboardManager::
detectKeyboardEventHandlingMode), and the reason its sketcher behaves the same
on every desktop: it never asks who has focus.
2. The [UX] trace (SNAPORCA_UXTRACE) in SketchInlineEditor: open/commit/refused/
cancel, with the prefill and what the control actually held at Enter. It did
not exist — the ladder below was written against a surface no build emitted,
so it could only ever report "nothing opened". typed == prefill on a commit is
the defect's signature and nothing else makes it visible.
3. A draw-then-edit trace in DesignSketchTool: four early returns can swallow the
value-field chain and from outside they are indistinguishable.
4. scripts/CAD/check-gui-click-edit.py — types WITHOUT clicking the field, as a
person does, across Line/Rectangle/Circle/Slot/Polygon/Ellipse/Arc plus label
click-to-edit, and asserts committed == typed != prefill.
5. scripts/CAD/focus-loop.sh — sync/build/assert on behemoth. NOT the orcacad-gui
rig: its image pins deps 216 non-CAD files behind cad-mainline, so today's CAD
sources cannot build there without a deps rebuild.
WHAT IS PROVEN, AND WHAT IS NOT
Green under openbox: 28 checks, every tool, committed == typed != prefill.
But openbox CANNOT adjudicate this bug and the ladder says so in place. There the
field always wins the keyboard, so the same ladder also passes against a binary
with the arbiter compiled out — measured twice. Two ways of removing the keyboard
were tried and both are recorded as dead ends: XSetInputFocus loses to the field's
own re-focus CallAfter, and XSendEvent (xdotool --window) is dropped by GTK, which
made every run red regardless of the code.
Under metacity — same focus-stealing-prevention lineage as the user's mutter — the
mechanism appears in the WM's own log:
Buggy client sent a _NET_ACTIVE_WINDOW message with a timestamp of 0
That is the activation being refused, which is exactly the reported symptom.
present_toplevel() already asks for a server timestamp, so a path is still falling
through to frame->Raise(), which sends time 0. That is the next thing to fix, and
it is tracked; the arbiter alone does not close it. metacity also aborts on this
window (frames.c:1239), so the gate needs a WM that survives before it can return
a verdict.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011FbJKJAJxxkhDTs9XdZzKA
This commit is contained in:
co-authored by
Claude Opus 5
parent
af4bbe0217
commit
9134299233
@@ -0,0 +1,86 @@
|
||||
# DELEGATION SPECIFICATION: HARNESS-DRIVEN VALIDATION LOOP
|
||||
slug: sketch-focus-arbiter · repo: /home/tommaso/projects/apps/orca_cad · branch: cad-mainline
|
||||
|
||||
## 1. TARGET GOAL
|
||||
|
||||
**Functional Objective.** Keyboard input in the Design tab is routed by WHAT THE KEY IS, not by
|
||||
which widget the window manager decided to focus. Adopted from FreeCAD's
|
||||
`DrawSketchKeyboardManager::detectKeyboardEventHandlingMode`
|
||||
(src/Mod/Sketcher/Gui/DrawSketchKeyboardManager.cpp), which never queries focus at all:
|
||||
|
||||
- digit, `-`, `.`, `,` -> the open value field
|
||||
- Backspace / Delete -> the open value field (when one is open)
|
||||
- Enter / Return / Tab -> commit the field, control returns to the view
|
||||
- a letter -> the sketch-tool shortcut map, as today
|
||||
- Esc -> the existing CadLevel LIFO (DesignInteraction.hpp), unchanged
|
||||
- anything else -> sticky: whoever had it keeps it
|
||||
|
||||
Observable postcondition: for EVERY sketch tool that opens a value field, a value typed
|
||||
immediately after the field appears — with NO click into the field — is the value committed.
|
||||
Today the prefill is committed instead whenever the WM withholds focus.
|
||||
|
||||
**Target Files / Scope (writable).**
|
||||
src/slic3r/GUI/CAD/DesignPanel.cpp (the arbiter lives in the existing wxEVT_CHAR_HOOK)
|
||||
src/slic3r/GUI/CAD/DesignCanvas.cpp/.hpp (forwarding entry points only)
|
||||
src/slic3r/GUI/CAD/SketchInlineEditor.cpp/.hpp (accept a programmatically delivered character)
|
||||
scripts/CAD/check-gui-click-edit.py (F2P oracle — authoring exception, see §4)
|
||||
Everything else read-only. No dependency additions, no reformatting.
|
||||
|
||||
**Open Bindings.**
|
||||
- The in-canvas ImGui field on wip/in-canvas-value-field is NOT in scope. Default: the arbiter
|
||||
is implemented against the CURRENT wxFrame field on cad-mainline, because content-based
|
||||
routing makes the window's focus irrelevant either way. If it later moves in-canvas the
|
||||
arbiter is unchanged.
|
||||
- Tools whose field is opened by a toolbar button rather than a gesture (Constrain path) are
|
||||
covered by the same arbiter but are not in the F2P tool list. Default: assert them in P2P only.
|
||||
|
||||
## 2. HARNESS ENVIRONMENT & GROUND TRUTH
|
||||
|
||||
The rig container `orcacad-gui` on nativedev IS the harness. Xvfb `:11` + openbox, the app under
|
||||
test, `xdotool` for synthetic input, and an MCP socket at `/tmp/mcp.sock` that reports sketch
|
||||
state as JSON. It is a closed loop: drive input, read geometry back, assert. No window manager
|
||||
politics, no human.
|
||||
|
||||
Harness interface (ordered; each slot one invocation, one exit code):
|
||||
S1 sync docker cp <file> orcacad-gui:/OrcaSlicer/<path>
|
||||
S2 build docker exec orcacad-gui ninja -C /OrcaSlicer/build orca-slicer
|
||||
S3 restart docker exec orcacad-gui /OrcaSlicer/scripts/CAD/start-headless-gui.sh
|
||||
S4 F2P docker exec -e DISPLAY=:11 orcacad-gui python3 /tmp/check-gui-click-edit.py --attach
|
||||
S5 P2P docker exec -e DISPLAY=:11 orcacad-gui python3 /tmp/check-gui-sketching.py
|
||||
|
||||
**F2P.** `scripts/CAD/check-gui-click-edit.py`. For each of Line, Rectangle, Circle, Slot,
|
||||
Polygon, Ellipse and Rounded rectangle: arm the tool, draw it, and type a value that differs
|
||||
from the prefill WITHOUT clicking the field. Assert the committed value equals the typed value.
|
||||
The ladder must FAIL against unmodified cad-mainline — that is what proves it asserts something.
|
||||
|
||||
**P2P.** `scripts/CAD/check-gui-sketching.py`, the existing gesture ladder, minus anything red at
|
||||
baseline. NOTE: it calls `focus_field()` — one click into the field before typing — which is the
|
||||
workaround this whole task removes. It stays green as a regression guard; it is NOT evidence.
|
||||
|
||||
**Test Integrity Constraint.** `focus_field()` in check-gui-sketching.py must NOT be deleted to
|
||||
make things pass, and check-gui-click-edit.py must NOT be weakened. Either invalidates the run.
|
||||
|
||||
## 3. VERIFICATION COMMANDS
|
||||
1. Static: `docker exec orcacad-gui ninja -C /OrcaSlicer/build orca-slicer` (warnings delta only;
|
||||
this repo configures no linter — the compiler is the static gate. Absolute-zero is NOT the gate.)
|
||||
2. Harness: `docker exec -e DISPLAY=:11 orcacad-gui python3 /tmp/check-gui-click-edit.py --attach`
|
||||
3. Regression: `docker exec -e DISPLAY=:11 orcacad-gui python3 /tmp/check-gui-sketching.py`
|
||||
|
||||
## 4. CONVERGENCE LOOP — ceiling 8 iterations
|
||||
EDIT (scoped) -> EXECUTE S1..S5 -> PARSE the ladder's per-tool assertions and the [UX]/[KEYTRACE]
|
||||
lines -> PATCH from the parsed cause. On ceiling without convergence: stop, report the last diff
|
||||
and the unresolved failure set. Do not report success.
|
||||
|
||||
F2P authoring exception: check-gui-click-edit.py is writable, and must be shown RED against
|
||||
unmodified source before any source edit counts.
|
||||
|
||||
## 5. TERMINATION CRITERIA
|
||||
- [ ] S2 exits 0, and introduces no compiler warning absent from the baseline.
|
||||
- [ ] S4 ALL_PASSED — every tool commits the typed value, no click into the field.
|
||||
- [ ] S5 shows zero regressions against its recorded baseline pass count.
|
||||
- [ ] F2P proven red without the fix (source stashed, ladder re-run, must FAIL).
|
||||
|
||||
## 6. GUARDRAILS
|
||||
Zero-assumption: no completion claim without captured stdout and exit codes. Oracle supremacy:
|
||||
the ladder's verdict overrides my judgement. Blast radius: §1 files only. Baseline obligation:
|
||||
run §3 once before the first edit and record it.
|
||||
Reference in New Issue
Block a user