This tutorial provides step-by-step instructions and sample code to help you write applications using advanced pointers.
Variant: ScreenPlay. Target audience: Application developers.
This topic builds on the material in the following topics:
This topic covers the following:
RWindow provides
a handle to a standard window. Call RWindow
to create
an instance of a window.
RWindow window(ws); User::LeaveIfError(window.Construct(wg, reinterpret_cast<TUint32>(&wg) + 1));
Call RWindow::EnableAdvancedPointers()
to enable advanced pointers.
Then call RWindowBase::Activate()
to display the
window and enable the window to receive events. RWindow
inherits from RWindowBase
, so you can call the Activate()
function on RWindow
.
window.EnableAdvancedPointers(); window.Activate();
When an application needs to receive advanced pointer
events in a window, it must call RWindowBase::EnableAdvancedPointers()
for the window before it is activated.
If advanced
pointers are not enabled for a window, it receives only standard TPointerEvent
information from a single pointer with no
pressure and proximity data. The single pointer environment rules
describe the way in which pointer events coming from many pointers
in the multiple pointer model are transformed into events of one pointer.
They are necessary to ensure that old single-pointer applications
work in a multiple pointer environment intuitively and
as expected by the user.
However, the new TPointerEvent
types, EEnterCloseProximity, EExitCloseProximity, EEnterHighPressure and EExitHighPressure, are delivered to all windows, even to those that do not enable
advanced pointers.
Call TPointerEvent::AdvancedPointerEvent()
on a TPointerEvent
to return a pointer to a TAdvancedPointerEvent
.
TZType aZType; TPointerEvent& aPointerEvent; TInt* aZ; TInt* aPoint3D; TAdvancedPointerEvent *advancedP = aPointerEvent.AdvancedPointerEvent();
TPointerEvent
is a struct that contains
details of a pointer event. TZType
is a struct provided
by the programmer containing members to hold proximity, pressure,
and "proximity and pressure" data.
Now we need to test whether the pointer event contains advanced pointer data. If it is not an advanced pointer, the code leaves.
If it is an advanced pointer, we call functions to detect proximity, pressure, "proximity and pressure" data and coordinates.
if(!advancedP) { // The TPointerEvent isn't an instance of TAdvancedPointerEvent User::Leave(KErrArgument); } switch(aZType) { case EZTypeProximity: aZ = advancedP->Proximity(); aPoint3D = advancedP->Proximity3D(); break; case EZTypePressure: aZ = advancedP->Pressure(); aPoint3D = advancedP->Pressure3D(); break; case EZTypeProximityAndPressure: aZ = advancedP->ProximityAndPressure(); aPoint3D = advancedP->ProximityAndPressure3D(); break; default: User::Leave(KErrArgument); break; }
TAdvancedPointerEvent::Proximity()
returns the proximity.
TAdvancedPointerEvent::Pressure()
returns the pressure.
TAdvancedPointerEvent::ProximityAndPressure()
returns the proximity and pressure combined.
TAdvancedPointerEvent::
Position3D()
returns the proximity and the X, Y and Z coordinates.
TAdvancedPointerEvent::Pressure3D()
returns the pressure and the X and Y coordinates.
Proximity is always negative and pressure is always positive. Internally they are combined together as a Z coordinate.
When Z > 0, the proximity is 0 and the Z value represents the pressure.
When Z < 0, the pressure is 0 and the Z value represents the proximity.
Some APIs use only a Z coordinate (such as the threshold getters and
setters and TAdvancedPointerEvent::ProximityAndPressure()
). In these, the Z coordinate is interpreted in terms of pressure
and proximity.
Figure: Relationships between the pointer proximity, pressure and Z coordinate
This example shows an easy way to pinch zoom an
image when the screen receives pointer events from two pointers. There
are two functions in this code that must be implemented by the programmer: BitmapCoordinates()
and MoveBitmap()
. They
are not included in the example because they involve complex calculations
that are not related to advanced pointers.
The high-level steps to perform pinch zooming are:
Define the coordinates,
equivalent to the given on-screen coordinates. In the code example,
this is done using the function BitmapCoordinates()
.
Define the ID
of the pointer by using TAdvancedPointerEvent::PointerNumber()
. If the device can handle two pointers (two fingers) at the same
time, their numbers are 0 and 1. The pointer number enables you to
distinguish a given pointer from other pointers.
For each pointer assign its coordinates to a local variable. We assume there are only two pointers handled by the system here.
Use the MoveBitmap()
function to achieve the zoom effect.
/** Receives pointer events from two pointers to perform Pinch Zoom of the image. Function will finish when EButton1Up is received for any of the pointers. @param aPointer1 Coordinates of pointer number 1 when zoom is started @param aPointer2 Coordinates of pointer number 2 when zoom is started */ void PinchZoom(TPoint aPointer1, TPoint aPointer2) { TPoint actualP1 = aPointer1; TPoint actualP2 = aPointer2; // translate on-screen pointer coordinates to coordinates of displayed bitmap TPoint bitmapCatching1 = BitmapCoordinates(aPointer1); TPoint bitmapCatching2 = BitmapCoordinates(aPointer2); TBool repaint = EFalse; while (ETrue) { TAdvancedPointerEvent event = GetNextPointerEvent(); if (event.iType == TPointerEvent::EDrag) { if (event.PointerNumber() == 1) { actualP1 = event.iPosition; repaint = ETrue; } else if (event.PointerNumber() == 2) { actualP2 = event.iPosition; repaint = ETrue; } } else if (event.iType == TPointerEvent::EButton1Up) { break; } if (repaint) { // move bitmap on the screen in the way that // bitmapCatching1 point of the bitmap will be displayed at actualP1 screen coordinate, // bitmapCatching2 point of the bitmap will be displayed at actualP2 screen coordinate. MoveBitmap(bitmapCatching1, actualP1, bitmapCatching2, actualP2); repaint = EFalse; } } }