slint-ui / slint

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

WheelEvents callback #1280

Closed ogoffart closed 11 months ago

ogoffart commented 2 years ago

TouchArea should support wheel event.

Options:

  1. add a new callback wheel-event(Orientation, delta) (what type should the delta be?)

  2. add things in the current pointer-event. PointerEventKind.vertical-wheel / horizontal-wheel or should it be in PointerEventButton ? PointerEvent.wheel-delta ?

ogoffart commented 1 year ago

What needs to be done is decide on the API. Then the implementation should be quite easy by calling the relevant callback in the TouchArea item

DaMilyutin commented 1 year ago

@ogoffart , I've created naive implementation of events aggregator in my pet project.

In brief. (upd: I'm describing this to tell you my user case. ) Aggregation is stored in a structure with pressed keys, mouse position and accumulated events. Accumulated events are key/mouse clicks (up to tripple), wheel movement (vertical/hoizontal) accumulations, mouse movement. I assume only one mouse button and only one keyboard button can be clicked. (Might someone want to do multiple clicks with many keys?)

When aggregated state is read (Ex. pushed to events queue) all accumulated events are reset.

Since I "reinvented the wheel" this can be quite naive and have some flaws.

Ex. windows has it's own system functions to test mouse double clicks and current verion does all this bookkeeping. But those system events still can be stored in aggregated state.

You may have a look if you want to https://github.com/DaMilyutin/system_events/blob/main/include/system_events.h

upd: It is in playground state. So there are some debugs and logging.

ogoffart commented 1 year ago

@DaMilyutin Internally, we already represent the wheel event internally: The internal MouseEvent has a Wheel event https://github.com/slint-ui/slint/blob/e557ba5eedf289ad30d6c5587cfce1dc60fe997d/internal/core/input.rs#L46

What we don't do, is forward it to the .slint code. This should happens here: https://github.com/slint-ui/slint/blob/e557ba5eedf289ad30d6c5587cfce1dc60fe997d/internal/core/items.rs#L575 For the other events, we forward to one of the TouchArea's callback (pointer-event, moved, clicked, ...) but not for the Wheel.

We could add some entries in the Slint's pointer-event enum to indicate a wheel. Or we could create a new callback only for the wheel event.

DaMilyutin commented 1 year ago

@ogoffart, thank you for clarification. Inner representation looks like what I want to have. I wish I could have full controll of all inputs if needed. Or some shortcuts. Or maybe if I just could forward all state to my C++ code.

In my plans for plotting application I'm going to have following use case. I'd like to process both mouse events with modifiers pressed. For example ctrl links axes in x, alt in y, both in xy, etc.

ogoffart commented 1 year ago

Given that we would want to know the keyboard state, i'm thinking we should extend the PointerEvent structure.

https://github.com/slint-ui/slint/blob/master/docs/langref/src/builtin_structs.md#pointerevent

(pseudo-slint-code based on https://github.com/slint-ui/slint/blob/41157b9984bb205c4703dd43e05b7656c6662015/internal/compiler/builtins.slint#L87)

 export struct PointerEvent {
    button: PointerEventButton,
    kind: PointerEventKind,
+   // When kind == wheel, this is the amount of logical pixel to scroll in the vertical or horizontal direction
+   delta-x: length,
+   delta-y: length,
+   // The modifiers currently pressed
+   modifiers: KeyboardModifiers
 }

   enum PointerEventKind {
      cancel,
      down,
      up,
+     wheel,
    }

Does that new API make sense?

ogoffart commented 1 year ago

Possible alternative:

DaMilyutin commented 1 year ago

@ogoffart, + delta-x: length, + delta-y: length, Seems better to me. Because there is less cases for kind. Actually, you can even keep kind without wheel because nonzero delta-x, delta-y will signalize wheel movement. For me wheel movement event can be seen in same fashion as mouse movement event.

I'm curiuos, is it possible to join events from keyboard and mouse in one callback? Like ex. keypressed('V') and mousemove(dx, dy) => do something

tronical commented 1 year ago

I think extending a pointer event to support wheel events feels wrong to me. Those are rather different kinds of user actions IMO. I’d prefer a separate event / callback.

Regarding the modifiers: instead of adding this to every single event I’d prefer if API wise this was a global property. In practice it is, in practice there is only one keyboard active for an application.

ogoffart commented 11 months ago

I had a small chat with @simon and we decided on this API:

struct PointerScrollEvent { delta-x: length, delta-y: length, modifiers: KeyboardModifiers }

// in TouchArea
callback scroll-event(PointerScrollEvent) -> EventResult;

(I added the EventResult return type because if we don't interpret it, we still want to let flickable scroll)