Skip to content

FocusScope: add consume-focus-click property#12045

Open
Eyalm321 wants to merge 2 commits into
slint-ui:masterfrom
Eyalm321:focus-scope-press-passthrough
Open

FocusScope: add consume-focus-click property#12045
Eyalm321 wants to merge 2 commits into
slint-ui:masterfrom
Eyalm321:focus-scope-press-passthrough

Conversation

@Eyalm321

@Eyalm321 Eyalm321 commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Fixes #12044

When a FocusScope does not yet have focus, the pointer press that gives it focus via focus-on-click is consumed (EventAccepted), so it never reaches other pointer handlers under the cursor — the classic "click once to focus, click again to act" behavior. Once the scope has focus, the same press propagates (EventIgnored), so only the focus-delivering press is special.

This adds an opt-in boolean property consume-focus-click (default true, preserving the current behavior) following the two existing booleans focus-on-click / focus-on-tab-navigation (per the API-review preference for booleans over a policy enum in #9263). When set to false, FocusScope::input_event still transfers the focus on press but returns EventIgnored, letting the press continue to elements behind the scope (e.g. a sibling TouchArea).

The default stays consuming so the nested-scope behavior from #2530 (tests/cases/focus/event_propagation_3.slint) is unchanged; the docs note that opting in allows an enclosing default FocusScope to take the focus instead.

Two points I'd welcome guidance on:

  • Naming: consume-focus-click doesn't follow the focus-on-* prefix of its siblings; happy to rename (e.g. if you'd rather frame it positively).
  • Depth: a per-scope boolean can't make pass-through safe under nested scopes (an enclosing default FocusScope will take the focus from the propagated press — documented). A deeper alternative would be dispatcher-level tracking of "focus already claimed during this press" (or a dedicated InputEventResult variant) so ancestors skip their grab without consuming; that would even make pass-through safe by default, but it's a bigger change to internal/core/input.rs. Happy to rework in that direction if preferred.

Includes:

  • new property in internal/core/items/input_items.rs and internal/compiler/builtins.slint (docs inline)
  • test tests/cases/focus/consume_focus_click.slint (rust/cpp/js) covering both default and opt-in behavior
  • CHANGELOG entry

🤖 Generated with Claude Code

When a FocusScope does not yet have focus, the pointer press that gives
it focus via focus-on-click is consumed, so it never reaches other
pointer handlers under the cursor ("click once to focus, click again to
act"). Once the scope has focus, the same press propagates, so only the
focus-delivering press is special.

Add an opt-in boolean property consume-focus-click (default true,
preserving the current behavior). When false, the press still transfers
the focus but returns EventIgnored so it continues to elements behind
the scope, e.g. a sibling TouchArea.

The default stays consuming so the nested-scope behavior from slint-ui#2530 is
unchanged.

Fixes slint-ui#12044

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FocusScope consumes the pointer press that gives it focus - first click into an unfocused scope never reaches other handlers

1 participant