Make forward-focus in a PopupWindow work

This commit is contained in:
Olivier Goffart 2025-02-04 12:31:06 +01:00 committed by GitHub
parent 1d42e78c22
commit 88cc96ba73
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 57 additions and 61 deletions

View file

@ -40,35 +40,14 @@ pub fn replace_forward_focus_bindings_with_focus_functions(
local_forwards.remove_uncallable_forwards();
// Phase 3: For `focus-forward` in the root element, create `focus()` and `clear-focus()` functions that are callable from the outside
if let Some((root_focus_forward, focus_forward_location)) =
local_forwards.focus_forward_for_element(&component.root_element)
{
for function in FocusFunctionType::iter() {
if let Some(set_or_clear_focus_code) = call_set_focus_function(
&root_focus_forward,
Some(&focus_forward_location),
function,
) {
component.root_element.borrow_mut().property_declarations.insert(
function.name().into(),
PropertyDeclaration {
property_type: Type::Function(Rc::new(Function {
return_type: Type::Void.into(),
args: vec![],
arg_names: vec![],
})),
visibility: PropertyVisibility::Public,
pure: Some(false),
..Default::default()
},
);
component.root_element.borrow_mut().bindings.insert(
function.name().into(),
RefCell::new(set_or_clear_focus_code.into()),
);
}
local_forwards.gen_focus_functions(&component.root_element);
// Phase 3b: also for PopupWindow
recurse_elem_including_sub_components(component, &(), &mut |elem, _| {
if elem.borrow().builtin_type().is_some_and(|b| b.name == "PopupWindow") {
local_forwards.gen_focus_functions(elem);
}
}
});
// Phase 4: All calls to `.focus()` may need to be changed with `focus-forward` resolved or changed from the built-in
// SetFocusItem() call to a regular function call to the component's focus() function.
@ -222,6 +201,38 @@ impl<'a> LocalFocusForwards<'a> {
}
}
}
fn gen_focus_functions(&mut self, elem: &ElementRc) {
if let Some((root_focus_forward, focus_forward_location)) =
self.focus_forward_for_element(&elem)
{
for function in FocusFunctionType::iter() {
if let Some(set_or_clear_focus_code) = call_set_focus_function(
&root_focus_forward,
Some(&focus_forward_location),
function,
) {
elem.borrow_mut().property_declarations.insert(
function.name().into(),
PropertyDeclaration {
property_type: Type::Function(Rc::new(Function {
return_type: Type::Void.into(),
args: vec![],
arg_names: vec![],
})),
visibility: PropertyVisibility::Public,
pure: Some(false),
..Default::default()
},
);
elem.borrow_mut().bindings.insert(
function.name().into(),
RefCell::new(set_or_clear_focus_code.into()),
);
}
}
}
}
}
#[derive(Copy, Clone, strum::EnumIter)]

View file

@ -221,6 +221,8 @@ fn lower_popup_window(
});
});
super::focus_handling::call_focus_on_init(&popup_comp);
parent_component.popup_windows.borrow_mut().push(PopupWindow {
component: popup_comp,
x: coord_x,

View file

@ -97,13 +97,10 @@ export component ComboBox {
y: root.height + 4px;
width: root.width;
height: root.visible-items * CosmicSizeSettings.item-height + 2 * root.popup-padding;
forward-focus: inner-fs;
FocusScope {
init => {
self.focus();
base.popup-has-focus = true;
}
changed has-focus => {
inner-fs := FocusScope {
focus-changed-event => {
base.popup-has-focus = self.has-focus;
}
key-pressed(event) => {

View file

@ -167,13 +167,10 @@ export component ComboBox {
y: parent.height + 6px;
width: root.width;
height: root.visible-items * CupertinoSizeSettings.item-height + 2 * root.popup-padding;
forward-focus: inner-fs;
FocusScope {
init => {
self.focus();
base.popup-has-focus = true;
}
changed has-focus => {
inner-fs := FocusScope {
focus-changed-event => {
base.popup-has-focus = self.has-focus;
}
key-pressed(event) => {

View file

@ -107,13 +107,10 @@ export component ComboBox {
y: -4px;
width: root.width;
height: root.visible-items * FluentSizeSettings.item-height + 2 * root.popup-padding;
forward-focus: inner-fs;
FocusScope {
init => {
self.focus();
base.popup-has-focus = true;
}
changed has-focus => {
inner-fs := FocusScope {
focus-changed-event => {
base.popup-has-focus = self.has-focus;
}
key-pressed(event) => {

View file

@ -95,6 +95,7 @@ export component ComboBox {
y: root.height;
width: root.width;
height: root.visible-items * MaterialSizeSettings.item-height;
forward-focus: inner-fs;
popup-container := Rectangle {
background: MaterialPalette.alternate-background;
@ -104,12 +105,8 @@ export component ComboBox {
border-radius: 4px;
}
FocusScope {
init => {
self.focus();
base.popup-has-focus = true;
}
changed has-focus => {
inner-fs := FocusScope {
focus-changed-event => {
base.popup-has-focus = self.has-focus;
}
key-pressed(event) => {

View file

@ -53,18 +53,15 @@ export component ComboBox {
width: root.width;
// Try to hardcode about the size of 6 items
height: 6 * 2rem;
forward-focus: inner-fs;
NativeComboBoxPopup {
width: 100%;
height: 100%;
}
FocusScope {
init => {
self.focus();
base.popup-has-focus = true;
}
changed has-focus => {
inner-fs := FocusScope {
focus-changed-event => {
base.popup-has-focus = self.has-focus;
}
key-pressed(event) => {