Symbian3/SDK/Source/GUID-C60DC070-572B-5960-B394-550426FDB909.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Fri, 11 Jun 2010 12:39:03 +0100
changeset 8 ae94777fff8f
parent 7 51a74ef9ed63
child 11 5072524fcc79
permissions -rw-r--r--
Week 23 contribution of SDK documentation content. See release notes for details. Fixes bugs Bug 2714, Bug 462.

<?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><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><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 multi-touch for 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 multi-touch
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 multi-pointer model are transformed into events of one pointer.
They are necessary to ensure that old single-pointer applications work in
a multi-touch 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_d0e193926_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>