RFC: gestures

Hey everyone,

In the past days I've been hacking again on the gestures branch, and
it's reaching an state where I feel it's getting quite solid, so I would
like to get discussion started, tentatively aiming to get this included
early in 3.13.


The two object types this relies on are GtkEventController and
GtkGesture. GtkEventController is a very lowlevel abstraction for
something that just "handles events". GtkGesture is a subclass very
centered around handling single or multiple sequences of
press/update.../release events, by default it's restricted to handling
touch events, although can be made to listen to mouse events, either
though API or through the GTK_TEST_TOUCHSCREEN envvar (a NULL
GdkEventSequence is used in those cases).

Multiple GtkGesture implementations are offered in the branch:

      * Drag: keeps track of drags, reporting the offset from the drag
        start point.
      * Swipe: reports x/y velocity at the end of a begin/update/end
      * LongPress: reports long presses, or those being canceled after
        threshold/timeout excess.
      * MultiPress: reports multiple presses, as long as they're within
        double click threshold/timeout
      * Rotate: reports angle changes from two touch sequences
      * Zoom: reports distance changes from to touch sequences as a
        factor of the initial distance.

Integration with GtkWidget

This is all mostly exposed through gtk_widget_add_controller() to the
upper layers. This function lets a widget manage the controller, so the
controllers will be hooked to the bubble/capture propagation phase as
specified by the enum argument in that function.

But GtkGestures remain useful as separate entities, callers are free to
feed those events manually, generally non-containers could get away with
just that, although should only remain preferable for not-so-GtkWidget

Gestures over the widget hierarchy

And here's the gory details. First of all, the way captured events has
changed so it's not capped from the top by the grab widget, running
invariably now from the toplevel even with ongoing GTK+ grabs. This
allows for more or less sane integration of gestures with the classic
event handling/grabbing approach.

Users of GtkGesture can set sequences on those in 3 states:

      * None: the gesture handles events to construct possibly useful
        output, but event delivery is not blocked.
      * Claimed: the gesture handles the event and blocks delivery.
      * Denied: The gesture ignores the sequence to every external

State can't be changed freely though, it's constrained to the following
life cycles:
      * None
      * None->Claimed
      * None->Denied
      * None->Claimed->Denied

If the widget helper functions are used, this results in
GtkWidget::sequence-state-changed emitted, first on the caller widget,
and then sequentially from the event widget to the toplevel. The default
implementation does enforce the state policy over the hierarchy:

      * On the caller widget, it sets the sequence to the same state on
        all attached gestures. 
      * If the sequence was claimed on the caller widget, all widgets
        underneath get the sequence canceled. 
      * If a sequence that was previously claimed is suddenly denied,
        all widgets beneath the caller widget towards the event widget
        will be able to receive events again. If the button/touch press
        was consumed, that event will be emulated to keep these widgets
        coherent event-wise.

So far in the branch this is exercised in a "gestures" demo in gtk3-demo
that should react to most of the added gestures, and GtkScrolledWindow
has been wired up to make kinetic scrolling event handling consist of 3
GtkGestureDrag/Swipe/LongPress gestures, if it works as always, that's
good news :).

So, comments are appreciated. Concerns or observable flaws?


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]