CAD: type a sketch dimension without clicking the field first

On a Wayland session the in-canvas value field never took the keyboard focus, so
after drawing a rectangle the first keystrokes went nowhere and the field had to
be clicked before a number could be typed. open() already did Show, Raise,
SetFocus on both frame and control, SelectAll, and re-asserted all of it in a
CallAfter — none of it works here, and no amount of re-asserting would: under
Wayland a client cannot focus itself, and mutter ignores gtk_window_present()
without an activation token as focus-stealing prevention. The earlier fix
recorded in this file (dropping wxFRAME_FLOAT_ON_PARENT, whose GTK _UTILITY_
hint made an xrdp session refuse focus) addressed a different compositor.

Stop needing WM focus. The canvas keeps the focus and feeds the field:
SketchInlineEditor::feed_key() types into the control directly — Enter commits,
Esc cancels, Backspace/Delete edit, digits and '-' '.' ',' are accepted, and
anything else is handed back so a stray letter cannot vanish into a numeric
field. A m_fresh flag reproduces the SelectAll semantics the field already had,
so the first digit replaces the prefill. It returns false when the control
genuinely holds the focus, so X11 keeps wx's normal routing and no character is
typed twice.

The CHAR_HOOK gates on the editor's own is_open(), NOT on inline_busy().
inline_busy is a freeze flag for the sketch tool: cleared on commit, re-set only
when the next queued field opens, with a CallAfter between them. Gating on it
left a window where the field was on screen and the flag was false — typing
worked for a rectangle's Width and not its Height.

VERIFIED at the machine on behemoth: typing the first dimension directly, with
no click, works. NOT yet confirmed: the Width -> Height handover; the is_open()
gate is diagnosed from the handover code, not observed. The hook's
SNAPORCA_KEYTRACE=1 switch logs each key with the focused widget if it needs
chasing further.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tommaso Bianchi
2026-08-14 17:53:41 +02:00
co-authored by Claude Opus 5
parent 614824ce89
commit ab15f386e4
5 changed files with 61 additions and 1 deletions
+12
View File
@@ -3796,6 +3796,18 @@ DesignPanel::DesignPanel(wxWindow* parent)
// Delete/Ctrl+Z there must edit the text, not the model.
const bool in_text = (dynamic_cast<wxTextCtrl*>(wxWindow::FindFocus()) != nullptr)
|| (m_viewport && m_viewport->inline_busy());
// The in-canvas value field cannot take the keyboard focus on a Wayland session (mutter
// refuses a self-focus request without an activation token), so typing went nowhere and
// the value had to be clicked into first. Feed it from here instead: the canvas keeps
// focus, we hand it the keys, and the behaviour is identical on every compositor. Does
// nothing when the field genuinely does hold focus, so X11 keeps its normal routing.
// Gate on the EDITOR being open, not on inline_busy(). inline_busy is a freeze flag for
// the sketch tool: it is cleared on commit and only re-set when the next queued field
// opens, so across a rectangle's Width -> Height handover there is a window where the
// field is on screen and the flag is false. Typing worked for the first dimension and
// not the second, which is exactly that gap. feed_inline_key() already checks is_open().
if (m_viewport && m_viewport->feed_inline_key(e))
return;
if (getenv("SNAPORCA_KEYTRACE")) {
wxWindow* fw = wxWindow::FindFocus();