# Android Multi Touch

**URL:** <https://forum.juce.com/t/android-multi-touch/9547>\
**Category:** Android\
**Created:** [November 13, 2012, 1:01pm UTC](https://forum.juce.com/t/android-multi-touch/9547 "2012-11-13T13:01:41Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![hugh](https://avatars.discourse-cdn.com/v4/letter/h/c5a1d2/32.png) [@hugh](https://forum.juce.com/u/hugh)\
**Post date:** [November 13, 2012, 1:01pm UTC](https://forum.juce.com/t/android-multi-touch/9547/1 "2012-11-13T13:01:41Z")

</div>

So, my multi-touch control is looking good… until i discover multi-touch is missing from JUCE Android !!

so here you go,

JuceAppActivity.java

[code] private native void handleMouseDown (int id, float x, float y, long time);  
private native void handleMouseDrag (int id, float x, float y, long time);  
private native void handleMouseUp (int id, float x, float y, long time);

```
    @Override
    public boolean onTouchEvent (MotionEvent event)
    {
        int action = event.getAction();
        switch (action & MotionEvent.ACTION_MASK)
        {
            case MotionEvent.ACTION_DOWN:
            {
                int id = event.getPointerId(0);
                handleMouseDown (id, event.getX(), event.getY(), event.getEventTime());
                return true;
            }
            case MotionEvent.ACTION_MOVE:
            { 
                int n = event.getPointerCount();
                for (int i = 0; i < n; ++i)
                {
                    int id = event.getPointerId(i);
                    handleMouseDrag (id, event.getX(i), event.getY(i), event.getEventTime());
                }
                return true;
            }
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
            {
                int id = event.getPointerId(0);
                handleMouseUp (id, event.getX(), event.getY(), event.getEventTime());
                return true;
            }
            case MotionEvent.ACTION_POINTER_UP:
            {
                int i = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) 
                    >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
                
                int id = event.getPointerId(i);
                handleMouseUp (id, event.getX(i), event.getY(i), event.getEventTime());
                return true;

            }
            case MotionEvent.ACTION_POINTER_DOWN:
            {
               int i = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) 
                    >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
                
                int id = event.getPointerId(i);
                handleMouseDown (id, event.getX(i), event.getY(i), event.getEventTime());
                return true;
            }
            default: break;
        }

        return false;
    }[/code]

```

modules\juce\_gui\_basics\native\juce\_android\_Windowing.cpp

[code] static const int maxTouch = 4;  
void handleMouseDownCallback (int id, float x, float y, int64 time)  
{  
lastMousePos.setXY ((int) x, (int) y);  
currentModifiers = currentModifiers.withoutMouseButtons();  
handleMouseEvent (id, lastMousePos, currentModifiers, time);  
currentModifiers = currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier);  
handleMouseEvent (id, lastMousePos, currentModifiers, time);  
}

```
void handleMouseDragCallback (int id, float x, float y, int64 time)
{
    lastMousePos.setXY ((int) x, (int) y);
    handleMouseEvent (id, lastMousePos, currentModifiers, time);
}

void handleMouseUpCallback (int id, float x, float y, int64 time)
{
    lastMousePos.setXY ((int) x, (int) y);
    currentModifiers = currentModifiers.withoutMouseButtons();
    handleMouseEvent (id, lastMousePos, currentModifiers, time);
}

```

…

JUCE\_VIEW\_CALLBACK (void, handleMouseDown, (JNIEnv\* env, jobject view, jint id, jfloat x, jfloat y, jlong time), handleMouseDownCallback (id, (float) x, (float) y, (int64) time))  
JUCE\_VIEW\_CALLBACK (void, handleMouseDrag, (JNIEnv\* env, jobject view, jint id, jfloat x, jfloat y, jlong time), handleMouseDragCallback (id, (float) x, (float) y, (int64) time))  
JUCE\_VIEW\_CALLBACK (void, handleMouseUp, (JNIEnv\* env, jobject view, jint id, jfloat x, jfloat y, jlong time), handleMouseUpCallback (id, (float) x, (float) y, (int64) time))

[/code]

– hugh.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://forum.juce.com/u/jules)\
**Post date:** [November 13, 2012, 5:14pm UTC](https://forum.juce.com/t/android-multi-touch/9547/2 "2012-11-13T17:14:45Z")

</div>

I definitely owe you a beer 🙂

---

<div class="post-metadata">

**Author:** ![jpo](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/jpo/32/503_2.png) [@jpo](https://forum.juce.com/u/jpo)\
**Post date:** [November 14, 2012, 11:56pm UTC](https://forum.juce.com/t/android-multi-touch/9547/3 "2012-11-14T23:56:52Z")

</div>

Jules, what do you think of adding a multitouch demo to the JuceDemo app ? It would be also very useful for testing multitouch. Here is a very small one that I wrote when I was also looking at android multitouch support and trying to get it to work (and failed) :

[code]class MultitouchDemo : public Component {  
Array\<Point \> mtouch;

Point &touch(int id) {  
while (id \>= mtouch.size()) mtouch.add(Point(-1,-1));  
return mtouch.getReference(id);  
}

void mouseDown(const MouseEvent &e) {  
int id = e.source.getIndex();  
DBG(“mouseDown " \<\< id);  
touch(id) = Point(e.x, e.y);  
repaint();  
}  
void mouseUp(const MouseEvent &e) {  
int id = e.source.getIndex();  
DBG(“mouseUp " \<\< id);  
touch(id) = Point(-1, -1);  
repaint();  
}  
void mouseDrag(const MouseEvent &e) {  
int id = e.source.getIndex();  
//DBG(“mouseDrag: source=” \<\< id \<\< " x=” \<\< e.x \<\< " y=” \<\< e.y);  
touch(id) = Point(e.x, e.y);  
repaint();  
}  
void paint(Graphics &g) {  
for (int i=0; i \< mtouch.size(); ++i) {  
if (i == 0) g.setColour(Colours::red);  
if (i == 1) g.setColour(Colours::blue);  
if (i == 2) g.setColour(Colours::green);  
if (i \>= 3) g.setColour(Colours::yellow);  
int x = mtouch[i].getX(), y = mtouch[i].getY();  
if (x != -1 || y != -1)  
g.fillEllipse(x-60, y-60, 120, 120);  
}  
}

};  
[/code]

I think it shows there is an issue in the code you have commited , for example if you press two fingers, and then raise one of the fingers, JUCE considers that both fingers have been raised

---

<div class="post-metadata">

**Author:** ![hugh](https://avatars.discourse-cdn.com/v4/letter/h/c5a1d2/32.png) [@hugh](https://forum.juce.com/u/hugh)\
**Post date:** [November 20, 2012, 11:28pm UTC](https://forum.juce.com/t/android-multi-touch/9547/4 "2012-11-20T23:28:01Z")

</div>

if you press two fingers, and then raise one of the fingers, JUCE considers that both fingers have been raised[quote][/quote]

That could be a problem with the code i posted. i couldnt figure out why this was. basically, if you lift one finger, nothing worked until the other finger is lifted, after which it worked as expected.

– hugh.

---

<div class="post-metadata">

**Author:** ![shini](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/shini/32/186_2.png) [@shini](https://forum.juce.com/u/shini)\
**Post date:** [October 16, 2013, 3:54pm UTC](https://forum.juce.com/t/android-multi-touch/9547/5 "2013-10-16T15:54:01Z")

</div>

I'm indeed experiencing this in my Juce android app.

Was it updated in Juce since ?

&nbsp;

---

<div class="post-metadata">

**Author:** ![hugh](https://avatars.discourse-cdn.com/v4/letter/h/c5a1d2/32.png) [@hugh](https://forum.juce.com/u/hugh)\
**Post date:** [October 17, 2013, 10:45am UTC](https://forum.juce.com/t/android-multi-touch/9547/6 "2013-10-17T10:45:36Z")

</div>

&nbsp;

hmm. maybe it's time i fixed this one. I'll add it to my list....

---

<div class="post-metadata">

**Author:** ![shini](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/shini/32/186_2.png) [@shini](https://forum.juce.com/u/shini)\
**Post date:** [October 21, 2013, 1:31pm UTC](https://forum.juce.com/t/android-multi-touch/9547/7 "2013-10-21T13:31:00Z")

</div>

Btw, I've put 16 as the maximum number of touches but obviously a higher value is more future-proof.

&nbsp;

&nbsp;

&nbsp;

&nbsp;

---

<div class="post-metadata">

**Author:** ![shini](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/shini/32/186_2.png) [@shini](https://forum.juce.com/u/shini)\
**Post date:** [October 22, 2013, 4:51pm UTC](https://forum.juce.com/t/android-multi-touch/9547/8 "2013-10-22T16:51:00Z")

</div>

I think I've fixed the android multitouch bug :

&nbsp;

In the handleMouseDownCallback and handleMouseUpCallback, you use a single ModifierKeys member, while you should have one for each touch index.

So I added in juce\_Android\_Windowing.cpp:

> ModifierKeys currentModifiersList[16];

to the private members of AndroidComponentPeer, then initialize this list in the constructor:

> for(int i=0;i\<16;i++)  
> &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;currentModifiersList[i] = 0;

And then I reimplemented the callbacks like this:

> void handleMouseDownCallback (int index, float x, float y, int64 time)  
> &nbsp;&nbsp;&nbsp; {  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastMousePos.setXY ((int) x, (int) y);  
> &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;  
> &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; currentModifiersList[index] = currentModifiersList[index].withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier);  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handleMouseEvent (index, lastMousePos, currentModifiersList[index], time);  
> &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;  
> &nbsp;&nbsp;&nbsp; }
> 
> &nbsp;&nbsp;&nbsp; void handleMouseDragCallback (int index, float x, float y, int64 time)  
> &nbsp;&nbsp;&nbsp; {  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastMousePos.setXY ((int) x, (int) y);  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handleMouseEvent (index, lastMousePos, currentModifiersList[index], time);  
> &nbsp;&nbsp;&nbsp; }
> 
> &nbsp;&nbsp;&nbsp; void handleMouseUpCallback (int index, float x, float y, int64 time)  
> &nbsp;&nbsp;&nbsp; {  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastMousePos.setXY ((int) x, (int) y);  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentModifiersList[index] = currentModifiersList[index].withoutMouseButtons();  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handleMouseEvent (index, lastMousePos, currentModifiersList[index], time);  
> &nbsp;&nbsp;&nbsp; }

&nbsp;

This fixes it for me.

&nbsp;

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://forum.juce.com/u/jules)\
**Post date:** [October 23, 2013, 12:33pm UTC](https://forum.juce.com/t/android-multi-touch/9547/9 "2013-10-23T12:33:56Z")

</div>

Hmm..&nbsp;I don't think that's the right approach to fixing it - the library has always assumed that&nbsp;there's a single set of modifier keys, but each mouse-source behaves independently. That works for multi-touch on windows and iOS, not sure why it's not working here...

---

<div class="post-metadata">

**Author:** ![shini](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/shini/32/186_2.png) [@shini](https://forum.juce.com/u/shini)\
**Post date:** [October 24, 2013, 10:57am UTC](https://forum.juce.com/t/android-multi-touch/9547/10 "2013-10-24T10:57:00Z")

</div>

This is indeed causing some problems with combobox's popups for instance, so I modified the methods like this:

&nbsp;

> void handleMouseDownCallback (int index, float x, float y, int64 time)  
> &nbsp;&nbsp;&nbsp; {  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastMousePos.setXY ((int) x, (int) y);  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentModifiersList[index] = currentModifiersList[index].withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier);  
> &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;currentModifiers = currentModifiersList[index];  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handleMouseEvent (index, lastMousePos, currentModifiersList[index], time);&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;  
> &nbsp;&nbsp;&nbsp; }
> 
> &nbsp;&nbsp;&nbsp; void handleMouseDragCallback (int index, float x, float y, int64 time)  
> &nbsp;&nbsp;&nbsp; {  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastMousePos.setXY ((int) x, (int) y);  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handleMouseEvent (index, lastMousePos, currentModifiersList[index], time);  
> &nbsp;&nbsp;&nbsp; }
> 
> &nbsp;&nbsp;&nbsp; void handleMouseUpCallback (int index, float x, float y, int64 time)  
> &nbsp;&nbsp;&nbsp; {  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastMousePos.setXY ((int) x, (int) y);  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentModifiersList[index] = currentModifiersList[index].withoutMouseButtons();  
> &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; currentModifiers = currentModifiersList[index];  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handleMouseEvent (index, lastMousePos, currentModifiersList[index], time);  
> &nbsp;&nbsp;&nbsp; }

And now everything seems to work as intended.

&nbsp;

I know this is not the most elegant fix ever made, but at least it should give you some indications on what's wrong with the current code ?

&nbsp;

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://forum.juce.com/u/jules)\
**Post date:** [October 28, 2013, 10:27am UTC](https://forum.juce.com/t/android-multi-touch/9547/11 "2013-10-28T10:27:50Z")

</div>

Ok, I've just had a bit of a tinker-around with this. My system's in a bit of a mess and I can't test android builds at the moment, but I've changed the code&nbsp;so it should work more like the iOS and Windows versions.
