Symbian3/SDK/Source/GUID-C60DC070-572B-5960-B394-550426FDB909.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Tue, 20 Jul 2010 12:00:49 +0100
changeset 13 48780e181b38
parent 11 5072524fcc79
permissions -rw-r--r--
Week 28 contribution of SDK documentation content. See release notes for details. Fixes bugs Bug 1897 and Bug 1522.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-C60DC070-572B-5960-B394-550426FDB909" xml:lang="en"><title> Advanced Pointer Tutorial</title><shortdesc>This tutorial provides step-by-step instructions and sample
code to help you write applications using advanced pointers. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
<p> <b>Variant</b>: <xref href="GUID-D93978BE-11A3-5CE3-B110-1DEAA5AD566C.dita">ScreenPlay</xref>. <b>Target audience</b>: Application developers. </p>
<section id="GUID-372AE50A-22BF-488F-BCFB-9B9A734C1D79"><title>Required background </title> <p>This topic builds
on the material in the following topics: </p> <ul>
<li id="GUID-C4209FBD-3860-5F4B-8458-87D22D483953"><p><xref href="GUID-9C269F45-F160-5A4B-ABF8-896D2A538E3B.dita">Advanced Pointer
Overview</xref>  </p> </li>
<li id="GUID-9D3C3B31-F43A-5201-A1EC-A1F2848CFF43"><p><xref href="GUID-9AD75103-CD56-5279-B639-5CA2BBF979B5.dita">Advanced Pointer
States and Event Communication</xref>  </p> </li>
</ul> </section>
<section id="GUID-1C0E6832-C5BA-49EE-85E7-02801488CE8A"><title>Using advanced pointers</title> <p>This topic covers
the following: </p> <ul>
<li id="GUID-C3AD43AA-09C0-5BA2-8496-5B87D40C89F5"><p><xref href="GUID-C60DC070-572B-5960-B394-550426FDB909.dita#GUID-C60DC070-572B-5960-B394-550426FDB909/GUID-8CBE862B-0C1D-5088-89B7-9B3EC898E4FC">Enabling multiple pointers in a window</xref>  </p> </li>
<li id="GUID-177323F2-55C6-56D9-B3D2-A8DDACF69E10"><p><xref href="GUID-C60DC070-572B-5960-B394-550426FDB909.dita#GUID-C60DC070-572B-5960-B394-550426FDB909/GUID-C026DAB9-C11C-5D29-A1EA-6730E914250F">Getting Z coordinates from TPointerEvent</xref>  </p> </li>
<li id="GUID-91CEA92C-A692-5853-96F0-625A76B7DC8D"><p><xref href="GUID-C60DC070-572B-5960-B394-550426FDB909.dita#GUID-C60DC070-572B-5960-B394-550426FDB909/GUID-B7057F69-191F-5AA4-8C61-EBECE66D92F6"> Pinch zooming</xref>  </p> </li>
</ul> </section>
<section id="GUID-8CBE862B-0C1D-5088-89B7-9B3EC898E4FC"><title>Enabling
multiple pointers in a window</title> <ol id="GUID-210D17A8-4869-5F9B-B71C-672101AC591C">
<li id="GUID-81A2AC5C-7837-5216-8F47-FC5959C27522"><p> <xref href="GUID-637F82AF-0CF9-3C85-834D-7C1A0866DF87.dita"><apiname>RWindow</apiname></xref> provides
a handle to a standard window. Call <codeph>RWindow</codeph> to create
an instance of a window. </p> <codeblock id="GUID-0E31C3F6-3719-5F16-9F74-C405850604B8" xml:space="preserve">
RWindow window(ws);

User::LeaveIfError(window.Construct(wg, reinterpret_cast&lt;TUint32&gt;(&amp;wg) + 1));
</codeblock> </li>
<li id="GUID-B67D3702-1A8F-5C6A-AB0F-FEA7C4D04A07"><p>Call <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita#GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79/GUID-05293539-F1B0-3C7D-BB14-3FD42F23D5C8"><apiname>RWindow::EnableAdvancedPointers()</apiname></xref> to enable advanced pointers.
Then call <xref href="GUID-1460DD8F-9AA1-3B99-8FFD-F309959CCA34.dita#GUID-1460DD8F-9AA1-3B99-8FFD-F309959CCA34/GUID-4E02165A-DFCC-3D18-BB18-18726B28E90A"><apiname>RWindowBase::Activate()</apiname></xref> to display the
window and enable the window to receive events. <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita"><apiname>RWindow</apiname></xref> inherits from <xref href="GUID-1460DD8F-9AA1-3B99-8FFD-F309959CCA34.dita"><apiname>RWindowBase</apiname></xref>, so you can call the <codeph>Activate()</codeph> function on <codeph>RWindow</codeph>. </p> <codeblock id="GUID-DB2FB570-2BB0-5C5F-9E4F-076D6A0E469E" xml:space="preserve">
window.EnableAdvancedPointers();
window.Activate();
</codeblock> <p>When an application needs to receive advanced pointer
events in a window, it must call <codeph>RWindowBase::EnableAdvancedPointers()</codeph> for the window <i>before</i> it is activated. </p> <p>If advanced
pointers are not enabled for a window, it receives only standard <xref href="GUID-1FFA0073-3D83-388E-A824-08C31F90CC54.dita"><apiname>TPointerEvent</apiname></xref> 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. </p> <p>However, the new <codeph>TPointerEvent</codeph> types, <xref href="GUID-239D0A8B-2759-321D-AD48-976E80192239.dita"><apiname>EEnterCloseProximity</apiname></xref>, <xref href="GUID-8C6264B4-5E19-33A7-92B0-BB79C871BEC7.dita"><apiname>EExitCloseProximity</apiname></xref>, <xref href="GUID-F02DB96E-1541-3223-9B7B-79D45840DB7B.dita"><apiname>EEnterHighPressure</apiname></xref> and <xref href="GUID-15B5991C-B075-3110-B0A4-540EC282AA56.dita"><apiname>EExitHighPressure</apiname></xref>, are delivered to all windows, even to those that do not enable
advanced pointers. </p> </li>
</ol> </section>
<section id="GUID-C026DAB9-C11C-5D29-A1EA-6730E914250F"><title>Getting
Z coordinates from TPointerEvent</title> <ol id="GUID-4CC2271D-1798-51B3-9A9D-E7E0B9A33DAE">
<li id="GUID-184B5B63-4EFC-55CD-8D1F-E015EEBACBE2"><p>Call <xref href="GUID-1FFA0073-3D83-388E-A824-08C31F90CC54.dita#GUID-1FFA0073-3D83-388E-A824-08C31F90CC54/GUID-E961DA4D-AD38-31F0-88DD-A07D36346DCB"><apiname>TPointerEvent::AdvancedPointerEvent()</apiname></xref> on a <codeph>TPointerEvent</codeph> to return a pointer to a <xref href="GUID-FADA3278-FF8B-308F-90AD-3DCF8911A023.dita"><apiname>TAdvancedPointerEvent</apiname></xref>. </p> <codeblock id="GUID-6E81680A-3070-546B-B575-49EA9E34FAF9" xml:space="preserve">
TZType aZType;
TPointerEvent&amp; aPointerEvent;
TInt* aZ; 
TInt* aPoint3D;

TAdvancedPointerEvent *advancedP = aPointerEvent.AdvancedPointerEvent();
</codeblock> <p> <codeph>TPointerEvent</codeph> is a struct that contains
details of a pointer event. <codeph>TZType</codeph> is a struct provided
by the programmer containing members to hold proximity, pressure,
and "proximity and pressure" data. </p> </li>
<li id="GUID-ABA8FA09-5F57-51BC-8CAE-43649B5ED6D3"><p>Now we need
to test whether the pointer event contains advanced pointer data.
If it is not an advanced pointer, the code leaves. </p> <p>If it is
an advanced pointer, we call functions to detect proximity, pressure,
"proximity and pressure" data and coordinates. </p> <codeblock id="GUID-DF109643-2564-51A0-B0F6-33BF4DA1F6E3" xml:space="preserve">
if(!advancedP)
    {
    // The TPointerEvent isn't an instance of TAdvancedPointerEvent
    User::Leave(KErrArgument);
    }

switch(aZType)
    {
    case EZTypeProximity:
        aZ = advancedP-&gt;Proximity();
        aPoint3D = advancedP-&gt;Proximity3D(); 
        break;
    case EZTypePressure:
        aZ = advancedP-&gt;Pressure();
        aPoint3D = advancedP-&gt;Pressure3D();
        break;
    case EZTypeProximityAndPressure:
        aZ = advancedP-&gt;ProximityAndPressure();
        aPoint3D = advancedP-&gt;ProximityAndPressure3D();
        break;
    default: 
        User::Leave(KErrArgument);
        break;
    }
</codeblock> <ul>
<li id="GUID-40C01884-AC86-5882-935D-2EC2E27C9004"><p> <xref href="GUID-FADA3278-FF8B-308F-90AD-3DCF8911A023.dita#GUID-FADA3278-FF8B-308F-90AD-3DCF8911A023/GUID-0ED4B1CC-0655-3246-8645-AAC9E0C27298"><apiname>TAdvancedPointerEvent::Proximity()</apiname></xref> returns the proximity. </p> </li>
<li id="GUID-16A9A86B-A837-5E43-BB3A-F5A04A7F4552"><p> <xref href="GUID-FADA3278-FF8B-308F-90AD-3DCF8911A023.dita#GUID-FADA3278-FF8B-308F-90AD-3DCF8911A023/GUID-15DEBFBF-7B7D-3FCF-9929-C973824A5FD3"><apiname>TAdvancedPointerEvent::Pressure()</apiname></xref> returns the pressure. </p> </li>
<li id="GUID-3E614890-C317-596E-A5B9-FD76426DBD12"><p> <xref href="GUID-FADA3278-FF8B-308F-90AD-3DCF8911A023.dita#GUID-FADA3278-FF8B-308F-90AD-3DCF8911A023/GUID-114AE77E-D0BD-321E-BFCB-1388B35582EC"><apiname>TAdvancedPointerEvent::ProximityAndPressure()</apiname></xref> returns the proximity and pressure combined. </p> </li>
<li id="GUID-6F62C0D1-FAE4-5F8F-B451-68ABA404A369"><p> <xref href="GUID-FADA3278-FF8B-308F-90AD-3DCF8911A023.dita#GUID-FADA3278-FF8B-308F-90AD-3DCF8911A023/GUID-E5AA7737-D217-3FDE-9E4D-AAA7F5D2C300"><apiname>TAdvancedPointerEvent::
Position3D()</apiname></xref> returns the proximity and the X, Y and Z coordinates. </p> </li>
<li id="GUID-5AD1811D-BCBF-5A44-B6E7-EB71BF254BCA"><p> <xref href="GUID-FADA3278-FF8B-308F-90AD-3DCF8911A023.dita#GUID-FADA3278-FF8B-308F-90AD-3DCF8911A023/GUID-2F30A8F5-75BA-3FE3-84B7-3C772ED75857"><apiname>TAdvancedPointerEvent::Pressure3D()</apiname></xref> returns the pressure and the X and Y coordinates. </p> </li>
</ul> <p>Proximity is <i>always</i> negative and pressure is <i>always</i> positive. Internally they are combined together as a Z coordinate.
When Z &gt; 0, the proximity is 0 and the Z value represents the pressure.
When Z &lt; 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 <xref href="GUID-FADA3278-FF8B-308F-90AD-3DCF8911A023.dita#GUID-FADA3278-FF8B-308F-90AD-3DCF8911A023/GUID-114AE77E-D0BD-321E-BFCB-1388B35582EC"><apiname>TAdvancedPointerEvent::ProximityAndPressure()</apiname></xref>). In these, the Z coordinate is interpreted in terms of pressure
and proximity. </p> </li>
</ol> <fig id="GUID-7A49B143-5458-5916-B937-55D98B77BB2C">
<title> Relationships between the pointer proximity, pressure and
Z              coordinate            </title>
<image href="GUID-1A0FB98B-8DB3-5067-9B71-FF838F6AE402_d0e198935_href.png" placement="inline"/>
</fig> </section>
<section id="GUID-B7057F69-191F-5AA4-8C61-EBECE66D92F6"><title>Pinch
zooming</title> <p>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: <codeph>BitmapCoordinates()</codeph> and <codeph>MoveBitmap()</codeph>. They
are not included in the example because they involve complex calculations
that are not related to advanced pointers. </p> <p>The high-level
steps to perform pinch zooming are: </p> <ol id="GUID-AEF3917C-AAFE-5C25-9609-396D08478AC0">
<li id="GUID-7839E665-C4E1-59C8-BA89-22A62615EFA3"><p>Define the coordinates,
equivalent to the given on-screen coordinates. In the code example,
this is done using the function <codeph>BitmapCoordinates()</codeph>. </p> </li>
<li id="GUID-FC4B1BDA-8120-53C9-9C88-BEFEF1AD54B4"><p>Define the ID
of the pointer by using <xref href="GUID-FADA3278-FF8B-308F-90AD-3DCF8911A023.dita#GUID-FADA3278-FF8B-308F-90AD-3DCF8911A023/GUID-67593D7E-CE40-303F-B847-81D6FC0578B1"><apiname>TAdvancedPointerEvent::PointerNumber()</apiname></xref>. 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. </p> </li>
<li id="GUID-1E8F7D23-EEAD-5EA5-8863-276076D6B54E"><p>For each pointer
assign its coordinates to a local variable. We assume there are only
two pointers handled by the system here. </p> </li>
<li id="GUID-E44B3D9B-560A-5959-996D-A63CBD4C3786"><p>Use the <codeph>MoveBitmap()</codeph> function to achieve the zoom effect. </p> <codeblock id="GUID-D85CCFDD-8F65-530A-ACD7-93DD1D435FC6" xml:space="preserve">
/**
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;
            }
        }
    }
</codeblock> </li>
</ol> </section>
</conbody><related-links>
<link href="GUID-9C269F45-F160-5A4B-ABF8-896D2A538E3B.dita"><linktext>Advanced
Pointer                 Overview</linktext></link>
<link href="GUID-9AD75103-CD56-5279-B639-5CA2BBF979B5.dita"><linktext>Advanced
Pointer States and                 Event Communication</linktext></link>
</related-links></concept>