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