slint-ui / slint

Slint is a declarative GUI toolkit to build native user interfaces for Rust, C++, or JavaScript apps.
https://slint.dev
Other
17.55k stars 601 forks source link

FocusScope auto-repeat #3065

Closed 0x6e closed 11 months ago

0x6e commented 1 year ago

I have the opposite problem to #3051 in FocusScope: I would like to be able to filter out the auto-repeated events.

I wonder if adding KeyEventType::KeyPressedAutoRepeat and KeyEventType::KeyReleaseAutoRepeat would work. Then the FocusScope could have an pub auto_repeat: Property<bool> to toggle whether the auto-repeat events get passed to the callback.

ogoffart commented 1 year ago

I think a KeyEventType::KeyPressedAutoRepeat makes sense. But KeyEventType::KeyReleaseAutoRepeat doesn't (because auto-repeat only generate presses). Instead of a property in the FocusScope, i'd add a bool in the KeyEvent that says it is auto repeat.

0x6e commented 1 year ago

Hi Olivier,

I'm getting both press and release as auto-repeats.

Here is my code:

use slint::private_unstable_api::re_exports::EventResult;

slint::include_modules!();

fn main() -> Result<(), slint::PlatformError> {
    let ui = AppWindow::new()?;

    ui.on_key_pressed(|event| {
        println!("Pressed: {event:?}");
        EventResult::Accept
    });
    ui.on_key_released(|event| {
        println!("Released: {event:?}");
        EventResult::Accept
    });

    ui.run()
}

slint::slint! {
    import { VerticalBox } from "std-widgets.slint";

export component AppWindow inherits Window {
    callback key-pressed  <=> keyboard.key-pressed;
    callback key-released <=> keyboard.key-released;
    callback pointer-event <=> touch.pointer-event;
    forward-focus: keyboard;
    keyboard := FocusScope {
        VerticalBox {
            Text {
                text: "Hello keyboard";
            }
            Text {
                text:keyboard.has-focus ? "Focused" : "Unfocused";
            }
        }
    }
    touch := TouchArea {}
}
}

And here is the output I see when I press and hold the s key:

Pressed: KeyEvent { modifiers: KeyboardModifiers { alt: false, control: false, meta: false, shift: false }, text: "s", event_type: KeyPressed, preedit_selection_start: 0, preedit_selection_end: 0 }
Released: KeyEvent { modifiers: KeyboardModifiers { alt: false, control: false, meta: false, shift: false }, text: "s", event_type: KeyReleased, preedit_selection_start: 0, preedit_selection_end: 0 }
Pressed: KeyEvent { modifiers: KeyboardModifiers { alt: false, control: false, meta: false, shift: false }, text: "s", event_type: KeyPressed, preedit_selection_start: 0, preedit_selection_end: 0 }
Released: KeyEvent { modifiers: KeyboardModifiers { alt: false, control: false, meta: false, shift: false }, text: "s", event_type: KeyReleased, preedit_selection_start: 0, preedit_selection_end: 0 }
Pressed: KeyEvent { modifiers: KeyboardModifiers { alt: false, control: false, meta: false, shift: false }, text: "s", event_type: KeyPressed, preedit_selection_start: 0, preedit_selection_end: 0 }
Released: KeyEvent { modifiers: KeyboardModifiers { alt: false, control: false, meta: false, shift: false }, text: "s", event_type: KeyReleased, preedit_selection_start: 0, preedit_selection_end: 0 }
0x6e commented 1 year ago

winit 0.29.0-beta.0 introduces breaking changes to the keyboard input handling. In versions prior to this, winit is unable to tell us whether the input we receive is a repeat or not. The new API introduces the KeyEvent struct with a repeat property.

There are currently 16 breaking changes for 0.28.6 to 0.29.0-beta0, plus one unreleased. Do you have a policy for this kind of update? At a guess updating to a beta release is not attractive. I am interesting in investigating further.

For Qt we have QKeyEvent::isAutoRepeat, so that is not a problem.

ogoffart commented 1 year ago

Do you have a policy for this kind of update?

We'll upgrade as soon as winit release the actual 0.29 I'm aware of some wip to upgrade winit in this branch: https://github.com/hunger/slint/tree/winit_update

0x6e commented 1 year ago

Thanks, I've rebased that branch onto master and fixed the remaining build issues: https://github.com/0x6e/slint/tree/winit_update

Next steps for me will be to go and look at what @hunger has commented out and investigate how to fix it.