CombBox: Don't change on scroll unless we have focus / not at all on cupertino

* ComboBox: Don't change on scroll uless we have focus

This is what native Windows combobox does.
Otherwise this causes problem when combobox are in scrollable

Fixes #5929

* ComboBox: Don't scroll at all with the wheel on Mac.

This is also Qt's behavior
https://doc.qt.io/qt-6/qstyle.html#:~:text=SH_ComboBox_AllowWheelScrolling
This commit is contained in:
Olivier Goffart 2025-02-07 13:52:14 +01:00 committed by GitHub
parent c0b72cad2f
commit 9853384f56
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 47 additions and 4 deletions

View file

@ -73,7 +73,8 @@ export component ComboBoxBase {
root.update-current-value();
}
private property <length> scroll-delta: 2px;
/// Minimum scroll delta so that the scroll wheel changes the value.
in property <length> scroll-delta: 2px;
forward-focus: i-focus-scope;
@ -109,6 +110,9 @@ export component ComboBoxBase {
}
scroll-event(event) => {
if (!root.has-focus) {
return reject;
}
if (event.delta-y < -root.scroll-delta) {
root.move-selection-down();
return accept;

View file

@ -47,6 +47,9 @@ export component ComboBox {
width: 100%;
height: 100%;
// Mac doesn't react on mouse wheel on the ComboBox.
scroll-delta: 1000000px;
show-popup => {
popup.show();
}

View file

@ -21,6 +21,10 @@ export component TestCase inherits Window {
}
}
public function unfocus() {
box.clear-focus();
}
in-out property current-index <=> box.current-index;
in-out property current-value <=> box.current-value;
in-out property model <=> box.model;
@ -32,9 +36,7 @@ export component TestCase inherits Window {
```rust
use std::rc::Rc;
use slint::platform::Key;
use slint::SharedString;
use slint::VecModel;
use slint::{platform::WindowEvent, platform::Key, VecModel, SharedString, LogicalPosition};
use i_slint_backend_testing::mock_elapsed_time;
let instance = TestCase::new().unwrap();
@ -167,6 +169,40 @@ assert_eq!(instance.get_output(), "");
assert_eq!(instance.get_has_focus(), true);
assert_eq!(combobox.accessible_expanded(), Some(false));
// Scroll with the wheel
let wheel_change_value = !module_path!().contains("cupertino");
instance.set_output(Default::default());
instance.window().dispatch_event(WindowEvent::PointerScrolled { position: LogicalPosition::new(100.0, 100.0), delta_x: 0.0, delta_y: 20.0 });
if wheel_change_value {
assert_eq!(instance.get_current_value(), "Aaa");
assert_eq!(instance.get_current_index(), 0);
assert_eq!(instance.get_output(), "selected(Aaa,0)\n");
} else {
assert_eq!(instance.get_current_value(), "Bbb");
assert_eq!(instance.get_current_index(), 1);
assert_eq!(instance.get_output(), "");
}
instance.window().dispatch_event(WindowEvent::PointerScrolled { position: LogicalPosition::new(100.0, 100.0), delta_x: 0.0, delta_y: -5.0 });
assert_eq!(instance.get_has_focus(), true);
assert_eq!(instance.get_current_value(), "Bbb");
assert_eq!(instance.get_current_index(), 1);
if wheel_change_value {
assert_eq!(instance.get_output(), "selected(Aaa,0)\nselected(Bbb,1)\n");
}
// When not having focus, do nothing
instance.invoke_unfocus();
instance.set_output(Default::default());
assert_eq!(instance.get_has_focus(), false);
instance.window().dispatch_event(WindowEvent::PointerScrolled { position: LogicalPosition::new(100.0, 100.0), delta_x: 0.0, delta_y: 20.0 });
assert_eq!(instance.get_current_value(), "Bbb");
assert_eq!(instance.get_current_index(), 1);
instance.window().dispatch_event(WindowEvent::PointerScrolled { position: LogicalPosition::new(100.0, 100.0), delta_x: 0.0, delta_y: -5.0 });
assert_eq!(instance.get_has_focus(), false);
assert_eq!(instance.get_current_value(), "Bbb");
assert_eq!(instance.get_current_index(), 1);
assert_eq!(instance.get_output(), "");
slint_testing::send_keyboard_string_sequence(&instance, "\t");
assert_eq!(instance.get_has_focus(), true);
// Set current-index to -1
instance.set_current_index(-1);