mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-18 14:32:36 +00:00
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
86 lines
4.7 KiB
Bash
Executable File
86 lines
4.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# One turn of the keyboard-focus convergence loop, start to verdict, with no human in it.
|
|
#
|
|
# scripts/CAD/focus-loop.sh # full turn: sync -> build -> restart -> assert
|
|
# SKIP_BUILD=1 scripts/CAD/focus-loop.sh # re-assert against the binary already on the host
|
|
#
|
|
# Exit 0 only when every gate holds. Any other exit is a failing gate and names which.
|
|
#
|
|
# WHY THIS EXISTS. The focus defects in the Design tab were chased for days by hand: build, launch
|
|
# the GUI, drive it with xdotool, read a screenshot, guess, repeat. That needs a person at every
|
|
# step and it is where the days went. This does not: behemoth carries an agent-owned Xvfb :10 with
|
|
# openbox, the app, xdotool and an MCP socket that reports sketch state as JSON, so a turn is
|
|
# sync -> build -> restart -> assert, and the ASSERTION is the verdict, not my reading of a picture.
|
|
#
|
|
# WHY BEHEMOTH AND NOT THE orcacad-gui RIG CONTAINER. The rig was the obvious host and it does not
|
|
# work for this: its image pins a dependency set 216 non-CAD source files behind cad-mainline
|
|
# (assimp among them), so today's CAD sources call GUI_App::is_auto_close_sketch_loops and
|
|
# MainFrame::ensure_design_panel, which that tree has never heard of. Syncing all of src/ to fix
|
|
# that needs a deps rebuild measured in hours. behemoth already builds this exact tree, already
|
|
# runs a WM on :10, and is the machine the user actually runs the product on — so the loop asserts
|
|
# against the shipping artefact rather than a stale twin. Reviving the rig means rebuilding its
|
|
# deps image first; until then it cannot adjudicate anything about this code.
|
|
set -uo pipefail
|
|
|
|
HOST="${HOST:-tommaso@100.103.234.2}"
|
|
DISP="${DISP:-:10}"
|
|
SRC="${SRC:-\$HOME/projects/orca/orcacad-native/src}"
|
|
TRACE="${TRACE:-/tmp/ux-focus-loop.log}"
|
|
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
BIN="build/src/Release/orca-slicer"
|
|
|
|
say() { printf '\n=== %s\n' "$*"; }
|
|
die() { printf 'GATE FAILED: %s\n' "$*" >&2; exit 1; }
|
|
|
|
ssh -o ConnectTimeout=10 "$HOST" true || die "cannot reach $HOST"
|
|
|
|
# ---------------------------------------------------------------- S1 sync
|
|
# Only the CAD paths and the ladders. behemoth's tree is a full cad-mainline checkout kept in step
|
|
# by its own realign; pushing unrelated files from here would make the build host disagree with
|
|
# git for reasons no later session could reconstruct.
|
|
say "S1 sync"
|
|
rsync -q "$REPO"/src/slic3r/GUI/CAD/*.{cpp,hpp} "$HOST:$SRC/src/slic3r/GUI/CAD/" || die "sync GUI/CAD"
|
|
rsync -q "$REPO"/src/libslic3r/CAD/*.{cpp,hpp} "$HOST:$SRC/src/libslic3r/CAD/" || die "sync libslic3r/CAD"
|
|
rsync -q "$REPO"/scripts/CAD/check-gui-click-edit.py "$REPO"/scripts/CAD/check-gui-sketching.py \
|
|
"$HOST:/tmp/" || die "sync ladders"
|
|
echo " sources + ladders in place"
|
|
|
|
# ---------------------------------------------------------------- S2 build
|
|
# flock: two concurrent Orca builds once OOM'd this machine for 2h28m. Every build script on the
|
|
# fleet takes this same lock.
|
|
#
|
|
# Grade the BINARY'S TIMESTAMP, never the build command's exit code. This is a Ninja Multi-Config
|
|
# tree whose default rules are Debug while the artefact under test is Release, so a wrong-config
|
|
# invocation returns success in seconds having touched nothing — it cost a wasted cycle here
|
|
# before anyone thought to look at the file.
|
|
if [ -z "${SKIP_BUILD:-}" ]; then
|
|
say "S2 build"
|
|
before=$(ssh "$HOST" "stat -c %Y $SRC/$BIN 2>/dev/null || echo 0")
|
|
ssh "$HOST" "flock /tmp/orca-rig-build.lock \$HOME/projects/orca/orcacad-native/rebuild.sh > /tmp/focus-build.log 2>&1"
|
|
rc=$?
|
|
after=$(ssh "$HOST" "stat -c %Y $SRC/$BIN 2>/dev/null || echo 0")
|
|
if [ "$rc" != 0 ] || [ "$after" = "$before" ]; then
|
|
ssh "$HOST" "grep -m5 -B2 'error:' /tmp/focus-build.log; tail -5 /tmp/focus-build.log"
|
|
die "S2 build (exit $rc, binary $( [ "$after" = "$before" ] && echo unchanged || echo rebuilt ))"
|
|
fi
|
|
echo " built"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------- S3 F2P
|
|
# The ladder launches and tears down the app itself, in its own datadir, so nothing here has to
|
|
# manage a process. It types WITHOUT clicking the field first, which is the whole contract.
|
|
say "S3 fail-to-pass: type without clicking the field"
|
|
ssh "$HOST" "cd $SRC && DISPLAY=$DISP python3 /tmp/check-gui-click-edit.py \
|
|
--display $DISP --bin $BIN --trace $TRACE"
|
|
f2p=$?
|
|
|
|
# ---------------------------------------------------------------- S4 P2P
|
|
say "S4 pass-to-pass: the existing gesture ladder"
|
|
ssh "$HOST" "cd $SRC && DISPLAY=$DISP python3 /tmp/check-gui-sketching.py 2>&1 | tail -3"
|
|
p2p=$?
|
|
|
|
say "VERDICT"
|
|
[ "$f2p" = 0 ] || die "F2P: a tool did not take the typed value (exit $f2p)"
|
|
[ "$p2p" = 0 ] || die "P2P: the gesture ladder regressed (exit $p2p)"
|
|
echo "ALL GATES HELD"
|