Utilizing dragging and gestures

This artice should describe the different possibilities of Disko to handle user input. It will focus on the abilities to process user input for dragging elements within a gui application.

Input Types

Disko disko can handle input events from mulitiple sources like X11, DirectFB or the Linux input sybsytem. It distinguishes two fundamental types of inputs: Keyboard events (like keys on a keyboard or ther dedicated hardware buttons) and pointer events (mouse clicks, mouse movement or touchscreen events). Any input event will be one of:

  • Keypress, Keyrelease
  • Buttonpress, Buttonrelease
  • Axismotion

The appropriate inputs are automatically seleceted implicitly by the desired backend system (Linux Framebuffer, X11, DirectFB).

Handling Inputs

The direct inputs from the hardware are normally handled by disko and its gui elements automatically (widget inputs, z-order changes, focus changes, etc). However if the interface needs to be a little smarter than the default beahaviour of disko there are some ways of controlling the inputs for the developer.

Intercepting window inputs

The window input handling can be interfaced using one of emmited signals, that are emitted during the input event processing:

MMSWindow::onHandleInput()
is emitted if the default processing of focused MMSWindow() was not able to process the event.

MMSWindow::onBeforeHandleInput()
is emitted before any default event handling took place. This signal can be used to collect data that can used to interpret complex user input like gestures drag events. If the user input is analyzed and processed, the callback can return true to end the processing chain. If false is returned the processing takes place in the normal way.

Guessing user input

Disko provides a very way of guessing basic gestures. The class MMSInputGesture is provided for that purpose. It can collect Axismotion events, and the can taḱe a guess if and in which direction a swipe gesture took place. A sample window callback could look like this:

bool beforeInputCB(MMSWindow *win, MMSInputEvent *event) {
    static MMSInputGesture gest;
    gest.addInfo(event);
    MMSINPUTGESTURE guess = gest.guess();
    switch(guess) {
        case MMSINPUTGESTURE_UKN: 
            break;		

        case MMSINPUTGESTURE_UP:
        case MMSINPUTGESTURE_DOWN:

            //handle vertical swipe
            handleVSwipe(guess);

            //stop processing chain
            return true;
        case MMSINPUTGESTURE_LEFT:
	    case MMSINPUTGESTURE_RIGHT:

            //handle horizontal swipe
            handleHSwipe(guess);

            //stop processing chain
            return true;
    }
    
    //proceed normally
    return false;
}

Identify dragging events

To identify a dragging event it is necessary to identify a sequence of input events: ButtonPress -> AxisMotion -> ButtonRelease.

A Simple dragging of a Window could be achieved easily:

bool beforeInputCB(MMSWindow *win, MMSInputEvent *event) {
    static bool drag=false;
    
    if(event->type == MMSINPUTEVENTTYPE_BUTTONPRESS) {
    	drag=true;
    	
        //proceed normally
        return false;
    }
    if(event->type == MMSINPUTEVENTTYPE_BUTTONRELEASE) {
        drag=false;

        //proceed normally
        return false;
    }
    if(event->type == MMSINPUTEVENTTYPE_AXISMOTION) {
    	MMSFBRectangle rect=win->getGeometry();
        win->moveTo(rect.x+event->dx, rect.y+event->dy);
        
        //end event processing
        return true;
    }
	
    //proceed normally
    return false;
}

This example will simply change the window position according to the pointer movement that to place between the >press and release envents.

In our latest version of the disko demos (LINK HIER!!!!!!!!!!) we utilize some additional mechanism to reduce spent cpu power and to create a more convenient user experience. Before an actual dragging operation is started, the axismotion dx or dy amounts must exceed a specific threshold. This ensures that slight slips in the handling (like when using an on screen keyboard) do trigger the dragging mode. Theres also a threshold that needs to be exceeded for redrawing the user interface during a draggin operation (e.g. every 10px). This leads to a much reduced cpu usage.

MMSInputEvent in Detail

The MMSinputEvent provides several different informations. It contais the event type, a keysymbol if applicabe (keypress, keyrelease) and 3 sets of coordinates for different purposes:

Attribute Description
type Type of the event
key Contains the MMSKeySymbol for the pressed or released key.
posx, posy Contains the position of the pointer relative to the window geometry.
absx, absy Contains the position of the pointer relative to the layer geometry.
dx, dy Contains the relative change of the pointer position since the last processed axismotion event.