Tactile feedback implementation example

This is an implementation example of a simple tactile feedback enabled control. This example can help give you an overall understanding of what methods to implement and what are the typical actions in each function.

The example control uses area registry for producing basic feedback on pointer down events, and instant feedback for producing sensitive feedback on drag events when the control’s state changes.

The header file of the example control is presented below.

#include <coecntrl.h>

class CMyTactileEnabledControl: public CCoeControl
    {
public:
    CMyTactileEnabledControl();
    virtual ~CMyTactileEnabledControl();

public: // from CCoeControl
    void HandlePointerEventL( const TPointerEvent& aPointerEvent );
    void SizeChanged();
    void PositionChanged();
    };

Note that you do not necessarily need to implement any new functions for supporting tactile feedback. But for non-window-owning controls that use area registry, you have to override PositionChanged, because otherwise you may end up with a situation where the control has been moved, but the feedback area still remains in its original place.

The first part of the source file is presented below.

#include <touchfeedback.h>
#include "mytactileenabledcontrol.h"

CMyTactileEnabledControl::CMyTactileEnabledControl()
    {
    // No Tactile Feedback related actions needed 
    // when the control is created.
    }

CMyTactileEnabledControl::~CMyTactileEnabledControl()
    {
    // Before destroying the control, you need to call 
    // RemoveFeedbackForControl, first, for removing all remaining
    // feedback areas, and, second, for clearing this control's   
    // state information stored by the Tactile Feedback Client API.
    MTouchFeedback* feedback = MTouchFeedback::Instance();
    if ( feedback )
        {
        feedback->RemoveFeedbackForControl( this );
        } 
    }

The code above illustrates that usually nothing needs to be done (from the tactile feedback point of view) when a control is constructed, but you must always call RemoveFeedbackForControl at the destructor if you have added any feedback areas with the SetFeedbackArea function, or disabled or enabled feedback with the EnableFeedbackForControl function.

Also notice that you must use MTouchFeedback::Instance in the destructor (and not any stored pointer), because in some rare cases the feedback system may already have been destroyed before the last controls are deleted.

The remaining part of the source file is displayed below.

void CMyTactileEnabledControl::HandlePointerEventL(
    const TPointerEvent& aPointerEvent )
    {
    TBool stateChanged;

    // (your code here)

    if(aPointerEvent.iType == TPointerEvent::EDrag && stateChanged)
        {
        // Producing sensitive feedback when dragging causes a state
        // change (this kind of feedback triggering is not possible  
        // by using area registry).
        MTouchFeedback* feedback = MTouchFeedback::Instance();
        if ( feedback )
            {
            feedback->InstantFeedback( ETouchFeedbackSensitive );
            }
        }
    }

void CMyTactileEnabledControl::SizeChanged()
    {
    // (your code here)
    
    // We have to update all feedback areas when control is resized.
    // This is also enough for adding the feedback area in the first
    // place, because SizeChanged is always called after control has
    // been created and positioned on screen.
    MTouchFeedback* feedback = MTouchFeedback::Instance();
    if ( feedback )
        {
        feedback->SetFeedbackArea( 
            this,
            0, // Area index, use 0 when only one area in this control
            Rect(), 
            ETouchFeedbackBasic,
            ETouchEventStylusDown );
        }    
    }

void CMyTactileEnabledControl::PositionChanged()
    {
    // We have to update our feedback area when this control 
    // is moved. One way to do this is to call SizeChanged here.
    SizeChanged();    
    }

You are recommended to put feedback area updates into a new UpdateFeedbackAreas function, and then to call this from both the SizeChanged and PositionChanged functions.