I think I've figured it out for you, Dave.  :)  Bear with me.

Let's look at the constants in MotionEvent:

ACTION_MASK = 0x000000ff
ACTION_POINTER_ID_MASK = 0x0000ff00
ACTION_POINTER_ID_SHIFT = 8

This confirms that the lowest order byte represents the action and the
next byte represents the pointer ID.

Now, the inconsistency that you observed (0 vs. 5, 1 vs. 6) can be
explained by the fact that the action values for the primary pointer
are different from the action values for non-primary pointers:

For primary pointers:
ACTION_DOWN = 0
ACTION_UP = 1

For non-primary pointers:
ACTION_POINTER_DOWN = 5
ACTION_POINTER_UP = 6

So, hopefully that explains why you experienced those
"inconsistencies".

Now, notice that there are some "convenience constants" that we can
use to prevent doing all of this dirty work ourselves.  Let's see if
they jive:

ACTION_POINTER_2_DOWN = 261 = 0x0100 | 0x0005
ACTION_POINTER_2_UP = 262 = 0x0100 | 0x0006
ACTION_POINTER_3_DOWN = 517 = 0x0200 | 0x0005
ACTION_POINTER_3_UP = 518 = 0x0200 | 0x0006

Important: Notice that the numbers "2" and "3" in the constant names
are 1-based and not 0-based.  However, PointerID's 0-based.  So, for
example, "POINTER_2" means PointerID = 0x01.

So, "POINTER_1" should mean PointerID = 0x00.  And note that the
documentation says "Pointer IDs start at 0, with 0 being the primary
(first) pointer in the motion."

Now, let's look at the following values:
ACTION_POINTER_1_DOWN = 5
ACTION_POINTER_1_UP = 6

POINTER_1 represents PointerID=0.  So, here we might have an apparent
contradiction in documentation.  Why would PointerID=0, a primary
pointer, generate non-primary actions?

However, one possibility is that PointerID=0 ceases to become a
"primary pointer" when 2+ fingers are touching the device.  I don't
see that documented anywhere, but that's the only explanation I can
think of for your Motorola Droid's behavior.

Based on the scenario you described above, my best guess is that your
Droid is following these interpretations/rules:
* If there is only one finger touching the device, it is treated as
PointerID=0 and as a primary, and so only ACTION_DOWN (0) and
ACTION_UP (1) events are generated.
* If there are 2+ fingers touching the device, then the first finger
is still treated as PointerID=0, but NOT as a "primary" (e.g. it
generates ACTION_POINTER_UP=6, not ACTION_UP=1).
* Whenever there are 2 fingers touching the device and one finger is
lifted, the sole remaining finger becomes PointerID=0 and "primary",
even if it was originally a "2nd" or higher finger.

If you apply these rules, it would explain your Droid's behavior:

> Press finger 1 to the screen (action value of 0)
Correct: 0x0000 | 0x0000 (finger 1 is a primary)

> Press finger 2 to the screen (action value of 261)
Correct: 0x0100 | 0x0005 (neither finger is a primary)

> Lift finger 1 from the screen (action value of 6)
Correct: 0x0000 | 0x0006 (finger 1 is no longer a primary; finger 2 is
the only finger so it becomes PointerID=0 and primary)

> Lift finger 2 from the screen (action value of 1)
Correct: 0x0000 | 0x0001 (finger 2 is primary)

So, that should explain your Droid's behavior.

Now, I'm not saying that those extra interpretations/rules are correct
and will/should be adopted by all devices.  But I think it's a decent
interpretation.  I'm not terribly surprised that your Droid is acting
like that.

What do you think?
-- PJ



On Nov 15, 3:41 pm, davemac <davemac...@gmail.com> wrote:
> I think I've got this figured out. Almost. With multi-touch support,
> getAction() can return a compound value representing the pointerID in
> the second byte and the action value in the first byte. For example,
> if two fingers are down, and pointerID 1 is lifted (i.e., finger 2),
> getAction() returns a value of 262 (0x100 or 256 to represent
> pointerID 1, and 6 to represent up for a compound value of 0x106 or
> 262). I'm curious why it was done this way instead of using 0 for down
> and 1 for up, even when pointers are involved. Things get a little
> weird because of the differences. Here's an example (note I'm using a
> Motorola Droid phone here so this may behave differently on other
> devices):
>
> Press finger 1 to the screen (action value of 0)
>     finger 1 gets pointerID 0, no problem, pointerID is 0, down is 0
> Press finger 2 to the screen (action value of 261)
>     finger 2 gets pointerID 1, a little weird, could have been 256
> instead?
> Lift finger 1 from the screen (action value of 6)
>     finger 2 is still pointerID 1, action could still have been 1?
> Lift finger 2 from the screen (action value of 1)
>     finger 2 is still pointerID 1, but the action value is not 262 or
> 257 it's 1
>
> It would seem I can't use the bitmasks reliably in all cases. If I
> always inspect the action value for the pointerID and the action
> value, I get messed up at the end because pointerID has vanished. And
> 0 seems to be equivalent to 5, and 1 to 6.
>
> Is this something you'd consider a bug or is this how it's supposed to
> work? Should we expect it to continue to work this way?
>
> Thanks for your help.
>
> - dave
>
> On Oct 27, 4:28 pm, Dianne Hackborn <hack...@android.com> wrote:
>
>
>
> > On Tue, Oct 27, 2009 at 2:02 PM, MrChaz <mrchazmob...@googlemail.com> wrote:
>
> > > Thanks for the info,
>
> > > Wouldn't this
> > > Finger 1 up: MotionEvent ACTION_POINTER_1_UP with one pointer, whose
> > > ID is
> > > 1.
> > > need to be ID of 0?  Or am I mis-understanding the purpose of the UP
> > > action?
>
> > Good point.  Actually my example was not very good because at the places
> > where there is an up transition, the last position of the pointer going up
> > is included in the event stream -- so in all of these, you would receive
> > both 0 and 1.  It is in the following move event that you will only get the
> > information for the pointers that are currently down.
>
> > --
> > Dianne Hackborn
> > Android framework engineer
> > hack...@android.com
>
> > Note: please don't send private questions to me, as I don't have time to
> > provide private support, and so won't reply to such e-mails.  All such
> > questions should be posted on public forums, where I and others can see and
> > answer them.

-- 
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Reply via email to