Feature Description
FocusScope::input_event consumes the pointer press that gives the scope focus: when the scope is enabled, focus-on-click is true (the default), and it does not already have focus, a Pressed event grabs focus and returns EventAccepted (internal/core/items/input_items.rs, FocusScope::input_event).
The press therefore never reaches other pointer handlers under the cursor, producing the classic "click once to focus, click again to act" behavior: the first click into an unfocused widget does nothing visible. Note the asymmetry — once the scope has focus, the same press returns EventIgnored and propagates normally, so only the focus-delivering press is special.
I'd like an opt-in way for a FocusScope to take focus on press and let the press propagate.
Minimal repro
export component Demo inherits Window {
width: 200px;
height: 200px;
ta := TouchArea {
pointer-event(ev) => {
if ev.kind == PointerEventKind.down {
debug("press"); // does NOT fire on the first click
}
}
clicked => { debug("clicked"); } // does NOT fire on the first click either
}
// Later sibling, drawn above `ta`, hit-tested first — the common
// "widget with both pointer handling and keyboard handling" shape.
fs := FocusScope { }
}
First click: fs grabs focus and swallows the press, so ta never sees the button-down (clicked also stays silent because the press never armed the TouchArea). Every subsequent click works. The same applies when the FocusScope wraps the TouchArea and the inner TouchArea doesn't cover the press position, or generally whenever an unfocused FocusScope wins the hit-test.
Real-world impact
In a terminal-emulator widget (FocusScope for keyboard input + TouchArea for the pointer), this single root cause produced two user-visible bugs:
- right-click-paste into an unfocused pane silently no-opped (paste was triggered on button-down, which vanished);
- a drag-selection's anchor press was lost when the pane wasn't focused, so the drag selected nothing — and with copy-on-select enabled, the release re-copied a stale selection, clobbering the clipboard.
Workaround today
focus-on-click: false; on the scope plus calling fs.focus() from the TouchArea's pointer-event on every button-down. Works, but it's boilerplate every "focusable pointer widget" must rediscover, and the failure mode (silently lost first press) is hard to diagnose.
Prior art
Proposed API
A third boolean alongside focus-on-click / focus-on-tab-navigation (per the API-review preference for bools in #9263), e.g.:
/// When false, the pointer press that gives this FocusScope the focus via
/// `focus-on-click` is not consumed: after focus is transferred, the press
/// continues to be processed by elements behind the FocusScope.
/// Note: with `false`, an enclosing FocusScope with default settings may then
/// take the focus instead (see #2530); opt in on outer scopes accordingly.
in property <bool> consume-focus-click: true;
(An enum on focus-on-click, e.g. pass-through, would express the same thing but would be a breaking type change to an existing bool property.)
Implementation is a small change in FocusScope::input_event: return EventIgnored instead of EventAccepted after set_focus_item(...) when the property is false. I'm happy to submit a PR with the property, tests, docs, and CHANGELOG entry.
Product Impact
Any widget that combines a FocusScope with sibling/overlapping pointer handlers (terminal emulators, canvases, custom list items) currently loses the first pointer press into an unfocused instance, or must carry the manual-focus workaround.
Feature Description
FocusScope::input_eventconsumes the pointer press that gives the scope focus: when the scope is enabled,focus-on-clickis true (the default), and it does not already have focus, aPressedevent grabs focus and returnsEventAccepted(internal/core/items/input_items.rs,FocusScope::input_event).The press therefore never reaches other pointer handlers under the cursor, producing the classic "click once to focus, click again to act" behavior: the first click into an unfocused widget does nothing visible. Note the asymmetry — once the scope has focus, the same press returns
EventIgnoredand propagates normally, so only the focus-delivering press is special.I'd like an opt-in way for a
FocusScopeto take focus on press and let the press propagate.Minimal repro
First click:
fsgrabs focus and swallows the press, sotanever sees the button-down (clickedalso stays silent because the press never armed the TouchArea). Every subsequent click works. The same applies when theFocusScopewraps theTouchAreaand the inner TouchArea doesn't cover the press position, or generally whenever an unfocusedFocusScopewins the hit-test.Real-world impact
In a terminal-emulator widget (FocusScope for keyboard input + TouchArea for the pointer), this single root cause produced two user-visible bugs:
Workaround today
focus-on-click: false;on the scope plus callingfs.focus()from the TouchArea'spointer-eventon every button-down. Works, but it's boilerplate every "focusable pointer widget" must rediscover, and the failure mode (silently lost first press) is hard to diagnose.Prior art
focus-on-click(Addfocus-policyproperty to FocusScope #8940, reworked in FocusScope: Remove FocusPolicy and adds two bool state instead #9263). That only lets you turn click-to-focus off; it can't keep click-to-focus and propagate the press.FocusScopeclick-to-focus behavior #2530 deliberately made the focus-grabbing press consumed, to stop a parentFocusScopefrom stealing focus from a nested child scope on the same click (tests/cases/focus/event_propagation_3.slint). So the default must stay as-is; this request is for an opt-in.Proposed API
A third boolean alongside
focus-on-click/focus-on-tab-navigation(per the API-review preference for bools in #9263), e.g.:(An enum on
focus-on-click, e.g.pass-through, would express the same thing but would be a breaking type change to an existing bool property.)Implementation is a small change in
FocusScope::input_event: returnEventIgnoredinstead ofEventAcceptedafterset_focus_item(...)when the property is false. I'm happy to submit a PR with the property, tests, docs, and CHANGELOG entry.Product Impact
Any widget that combines a
FocusScopewith sibling/overlapping pointer handlers (terminal emulators, canvases, custom list items) currently loses the first pointer press into an unfocused instance, or must carry the manual-focus workaround.