Processing pen events

This topic describes various events processed by Pen or Mouse.

Simple drag events

In order for the FEP control to receive drag events occurring in its window, all that is needed is to call EnableDragEvents() in the control’s construction routine. Having done that, the control will receive drag events as calls to its HandlePointerEventL() virtual function. The iType member of HandlePointerEventL() ’s aPointerEvent parameter is set to TPointerEvent::EDrag for drag events.

This method makes heavy use of IPC (inter-process communication) as the user drags the mouse/pen around the FEP control’s window, which means that the FEP does not get drag events at optimum frequency. This may be problematic for something like handwriting recognition software. If there is a requirement to follow the path traced by the mouse/pen as closely as possible, another method can be used, namely buffered drag events.

Buffered drag events

The advantage of buffered drag events over simple drag events is that the window server client can receive multiple mouse/pen positions in a single event, which reduces the IPC overhead. To enable this, the following code needs to be called in the FEP control’s construction routine:

User::LeaveIfError(DrawableWindow()->AllocPointerMoveBuffer(ENumberOfPointsInBuffer, 0));

This assumes that ENumberOfPointsInBuffer has been defined elsewhere; TFEP2Plugin sets this constant to 32. The control then receives drag events as calls to its HandlePointerBufferReadyL() virtual function, rather than as calls to HandlePointerEventL(). To retrieve these drag events, include the following code at the start of the FEP control’s HandlePointerBufferReadyL() function:

TPoint arrayOfPoints[ENumberOfPointsInBuffer];
TPtr8 bufferOfPoints(REINTERPRET_CAST(TUint8*, arrayOfPoints), 0, ENumberOfPointsInBuffer*sizeof(TPoint));
const TInt numberOfPointsInBuffer=bufferOfPoints.Length()/sizeof(TPoint);

Having done that, numberOfPointsInBuffer of arrayOfPoints can be used for whatever purpose the FEP requires, for example handwriting recognition. Note that AllocPointerMoveBuffer() ’s counterpart FreePointerMoveBuffer() does not need to be called in the FEP control’s destructor as this happens automatically when the control’s window is destroyed.

Intercepting pen events anywhere on the screen

In order to intercept mouse/pen events anywhere on the screen it is necessary to write a plugin into the window server (WSERV). This is in addition to the FEP plugin which plugs into the FEP architecture. TFEP2plugin provides a working example of this (TFEP2be). The details of how to write a window server plugin DLL are beyond the scope of this document because the APIs involved belong to the window server. See CAnim and CAnimDll in the SDK for information on this. The way mouse/pen events can be intercepted is by returning ETrue from the function overriding MEventHandler::OfferRawEvent() (CAnim derives from MEventHandler). Events which are handled in this way will not be sent to the relevant window server client, in other words, the client who would otherwise have received this event.

The sprite feature of the window server (RWsSprite, defined in epoc32\include\W32STD.H) can be used to display to the user the path on the screen being traced out by their mouse/pen movements. However, care should be taken when using sprites for this purpose. Sprites use bitmaps, which in this context would need to be the size of the screen. Because each running application has its own FEP, which would have its own sprite, which in turn would have its own screen-sized bitmap, it becomes apparent that some optimization must be done to avoid huge amounts of memory being consumed. TFEP2Plugin solves this problem by using a single bitmap shared between each sprite. It uses the 4 byte thread-local storage of the window server plugin DLL to store the identifier of this bitmap. The code which constructs the sprite is protected by a mutex (RMutex, defined in epoc32\include\E32STD.H) as it tests to see if the bitmap to be used by the sprite has already been created by a FEP running the same code in another thread. If it has then it merely calls CFbsBitmap::Duplicate() which simply increments the existing bitmap’s reference count, thus only one large bitmap is created rather than one per running application.

Intercepting mouse/pen events anywhere on the screen is likely to be most useful to handwriting-interpreting FEPs. Given that using this feature involves two polymorphic DLLs (plugging into different frameworks) running in two separate threads in separate processes, there is a choice regarding where the bulk of the FEP’s processing is done. The advantage of the processing being done outside of the window server process (in other words, in the FEP architecture plugin) is that bugs in the processing code (for instance crashing or hanging) do not affect the whole machine. The advantage of the processing being done inside the window server process (in other words, in the window server plugin) is that the long lists of screen positions (tracing out the path of where the user has dragged the mouse/pen) do not need to be communicated between processes.