changeset 5513:c81922444345

[RT-32802] Lens: touch events are not handled corectly - step 5 Summary: make sure all touch events go to the same window, mark primary touch point for mouse event emulationThis patch resolved: RT-32548 Lens: Long press on Touch keyboard not working well on the Beagle RT-33687 Lens:some touch events are been dropepd in native causing exceptions to be thrown RT-33731 Lens:DND is not working with touch screen RT-32580 Lens: release event is not posted to the Java/Lens layer on the Beagleboard The main points of this patch are: 1) make sure that all touch events going to the same window until released 2) make sure that the same index point is used for coordinates calculation Tested by: Tested with: HelloSanity, HelloDragAndDrop, LinuxInputTests and other toys. Touch and mouse a like Reviewed-by: David Hill (david.hill@oracle.com), Lisa Selle (lisa.selle@oracle.com), Rafi Tayar (rafi.tayar@oracle.com) and Daniel Blaukopf (Daniel.Blaukopf@Oracle.com) Contributed-by:
author Assaf Yavani
date Thu, 24 Oct 2013 14:37:26 +0300
parents 70401ef2c3cd
children 6151a4b1b4ef
files modules/graphics/src/main/java/com/sun/glass/ui/lens/LensApplication.java modules/graphics/src/main/native-glass/lens/LensApplication.c modules/graphics/src/main/native-glass/lens/input/android/androidLens.c modules/graphics/src/main/native-glass/lens/input/udev/udevInput.c modules/graphics/src/main/native-glass/lens/wm/LensWindowManager.c modules/graphics/src/main/native-glass/lens/wm/LensWindowManager.h
diffstat 6 files changed, 302 insertions(+), 170 deletions(-) [+]
line wrap: on
line diff
--- a/modules/graphics/src/main/java/com/sun/glass/ui/lens/LensApplication.java	Thu Oct 24 09:15:02 2013 +0100
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/lens/LensApplication.java	Thu Oct 24 14:37:26 2013 +0300
@@ -53,6 +53,7 @@
 import com.sun.glass.ui.Window;
 import sun.util.logging.PlatformLogger.Level;
 import java.util.Arrays;
+import java.util.Iterator;
 
 final class LensApplication extends Application {
 
@@ -501,12 +502,6 @@
         @Override
         void dispatch() {
             LensTouchInputSupport.postTouchEvent(view, state, id, x, y, absX, absY);
-            if (state == TouchEvent.TOUCH_MOVED) {
-                view._notifyMouse(MouseEvent.DRAG, MouseEvent.BUTTON_NONE,
-                                  x, y, absX, absY, KeyEvent.MODIFIER_BUTTON_PRIMARY,
-                                  false, true);
-            } 
-	    // else do nothing; other events are synthesized in native code
         }
 
         @Override
@@ -547,12 +542,6 @@
         void dispatch() {
             LensTouchInputSupport.postMultiTouchEvent(
                     view, states, ids, xs, ys, dx, dy);
-            if (states.length > 0 && states[0] == TouchEvent.TOUCH_MOVED) {
-                view._notifyMouse(MouseEvent.DRAG, MouseEvent.BUTTON_NONE,
-                    xs[0] + dx, ys[0] + dy, xs[0], ys[0],
-                    KeyEvent.MODIFIER_BUTTON_PRIMARY, false, true);
-            }
-	    // else do nothing; other events are synthesized in native code
         }
 
         @Override
@@ -746,22 +735,25 @@
         synchronized (eventList) {
             if (!eventList.isEmpty() && (eventType == MouseEvent.DRAG
                     || eventType == MouseEvent.MOVE)) {
-                Event lastEvent = eventList.getLast();
-                if (lastEvent instanceof LensMouseEvent) {
-                    LensMouseEvent e = (LensMouseEvent) lastEvent;
-                    if (e.target == view
-                            && e.action == eventType
-                            && e.button == button
-                            && e.modifiers == modifiers
-                            && e.isPopupTrigger == isPopupTrigger
-                            && e.isSynthesized == isSynthesized) {
-                        // rewrite the coordinates of the scheduled event with
-                        // the coordinates of this event.
-                        e.x = x;
-                        e.y = y;
-                        e.absx = absx;
-                        e.absy = absy;
-                        return;
+                Iterator <Event>events = eventList.descendingIterator();
+                while (events.hasNext()) {
+                    Event lastEvent = events.next();
+                    if (lastEvent instanceof LensMouseEvent) {
+                        LensMouseEvent e = (LensMouseEvent) lastEvent;
+                        if (e.target == view
+                                && e.action == eventType
+                                && e.button == button
+                                && e.modifiers == modifiers
+                                && e.isPopupTrigger == isPopupTrigger
+                                && e.isSynthesized == isSynthesized) {
+                            // rewrite the coordinates of the scheduled event with
+                            // the coordinates of this event.
+                            e.x = x;
+                            e.y = y;
+                            e.absx = absx;
+                            e.absy = absy;
+                            return;
+                        }
                     }
                 }
             }
@@ -1173,7 +1165,7 @@
             }
 
             //continue process events only if not already consumed
-            if (!handleDragEvents(view, eventType, x, y, absx, absy, button, modifiers)) {
+            if (!handleDragEvents(view, eventType, x, y, absx, absy, button, modifiers)) {                
                 postMouseEvent(view, eventType, x, y, absx, absy,
                                button, modifiers,
                                isPopupTrigger, isSynthesized);
@@ -1413,25 +1405,37 @@
      */
     private void postTouchMoveEvent(LensView view, long id, int x, int y, int absX, int absY) {
         synchronized (eventList) {
+            boolean isEventCompacted = false;
             if (!eventList.isEmpty()) {
-                Event lastEvent = eventList.getLast();
-                if (lastEvent instanceof LensTouchEvent) {
-                    LensTouchEvent e = (LensTouchEvent) lastEvent;
-                    if (e.view == view &&
-                        e.id == id && 
-                        (e.state == TouchEvent.TOUCH_MOVED || e.state == TouchEvent.TOUCH_STILL)) {
-                        // Rewrite the coordinates of the scheduled event
-                        // with the coordinates of this event.
-                        e.x = x;
-                        e.y = y;
-                        e.absX = absX;
-                        e.absY = absY;
-                        return;
+                Iterator <Event>events = eventList.descendingIterator();
+                while (events.hasNext()) {
+                    Event lastEvent = events.next();
+                    if (lastEvent instanceof LensTouchEvent) {
+                        LensTouchEvent e = (LensTouchEvent) lastEvent;
+                        if (e.view == view &&
+                            e.id == id && 
+                            (e.state == TouchEvent.TOUCH_MOVED || e.state == TouchEvent.TOUCH_STILL)) {
+                            // Rewrite the coordinates of the scheduled event
+                            // with the coordinates of this event.
+                            e.x = x;
+                            e.y = y;
+                            e.absX = absX;
+                            e.absY = absY;
+                            isEventCompacted = true;
+                        }
+                        //we have found the last touch event on the queue, break
+                        break;
+                    } else if (lastEvent instanceof LensMultiTouchEvent) {
+                        //another touch event type was posted, can't update event
+                        break;
                     }
                 }
-            } else {
+            }
+             
+            if (!isEventCompacted) {
                 postEvent(new LensTouchEvent(view, TouchEvent.TOUCH_MOVED, id, x, y, absX, absY));
             }
+            
         }
     }
 
@@ -1488,37 +1492,50 @@
                                             + " on " + view);
             }
             synchronized (eventList) {
-                // Try to match this multitouch event against a pending event
-                //This code assume that the order of touch points doesn't 
+                // Try to match this multitouch event against a the last multi touch 
+                // pending event on the queue, if they match and event type is move,
+                // update the existing event with the new values instead of posting a new event
+                // This code assume that the order of touch points doesn't 
                 //change between events
                 boolean match = false;
                 if (!eventList.isEmpty()) {
-                    Event lastEvent = eventList.getLast();
-                    if (lastEvent instanceof LensMultiTouchEvent) {
-                        LensMultiTouchEvent e = (LensMultiTouchEvent) lastEvent;
-                        if (e.view == view
-                                && e.states.length == states.length) {
-                            assert(states.length == ids.length);
-                            assert(e.states.length == e.ids.length);
-                            match = true;
-                            for (int i = 0; i < states.length && match; i++) {
-                                //check if event is motion related
-                                if ((e.states[i] != TouchEvent.TOUCH_MOVED &&
-                                     e.states[i] != TouchEvent.TOUCH_STILL) ||
-                                    (states[i] != TouchEvent.TOUCH_MOVED && 
-                                     states[i] != TouchEvent.TOUCH_STILL)) {
-                                    match = false;
+                    Iterator <Event>events = eventList.descendingIterator();
+                    while (events.hasNext()) {
+                        Event lastEvent = events.next();
+                        if (lastEvent instanceof LensMultiTouchEvent) {
+                            LensMultiTouchEvent e = (LensMultiTouchEvent) lastEvent;
+                            if (e.view == view
+                                    && e.states.length == states.length) {
+                                assert(states.length == ids.length);
+                                assert(e.states.length == e.ids.length);
+                                match = true;
+                                for (int i = 0; i < states.length && match; i++) {
+                                    //check if event is motion related
+                                    if ((e.states[i] != TouchEvent.TOUCH_MOVED &&
+                                         e.states[i] != TouchEvent.TOUCH_STILL) ||
+                                        (states[i] != TouchEvent.TOUCH_MOVED && 
+                                         states[i] != TouchEvent.TOUCH_STILL)) {
+                                        match = false;
+                                    }
+                                    if (e.ids[i] != ids[i]) {
+                                        match = false;
+                                    }
                                 }
-                                if (e.ids[i] != ids[i]) {
-                                    match = false;
+                                if (match) {
+                                    // rewrite the coordinates of the scheduled event
+                                    // with the coordinates of this event.
+                                    e.xs = xs;
+                                    e.ys = ys;
+                                    e.states = states;
+                                    e.dx = dx;
+                                    e.dy = dy;
                                 }
                             }
-                            if (match) {
-                                // rewrite the coordinates of the scheduled event
-                                // with the coordinates of this event.
-                                e.xs = xs;
-                                e.ys = ys;
-                            }
+                            //we have found the last touch event on the queue, break
+                            break;
+                        } else if (lastEvent instanceof LensTouchEvent) {
+                            //another touch event type was posted, can't update event
+                            break;
                         }
                     }
                 }
--- a/modules/graphics/src/main/native-glass/lens/LensApplication.c	Thu Oct 24 09:15:02 2013 +0100
+++ b/modules/graphics/src/main/native-glass/lens/LensApplication.c	Thu Oct 24 14:37:26 2013 +0300
@@ -478,6 +478,8 @@
                                isPopupTrigger, JNI_FALSE);
         if (glass_application_checkReportException(env)) {
             //an exception happened, bail now.
+            //because the stack trace doesn't include native function, print a message
+            GLASS_LOG_SEVERE("Exception detected, bailing out");
             return;
         }
 
--- a/modules/graphics/src/main/native-glass/lens/input/android/androidLens.c	Thu Oct 24 09:15:02 2013 +0100
+++ b/modules/graphics/src/main/native-glass/lens/input/android/androidLens.c	Thu Oct 24 14:37:26 2013 +0300
@@ -93,7 +93,8 @@
            &state,
            &jlid,
            &xabs,
-           &yabs);
+           &yabs,
+           0 /*primary point index*/);
                    
    if (sendAlsoButtonEvent) {
         lens_wm_notifyButtonEvent(env,
@@ -121,7 +122,8 @@
            states,
            jids,
            xs,
-           ys);
+           ys,
+           0 /*primary point index */);
     DETACH_JNI_THREAD();
 }
 
--- a/modules/graphics/src/main/native-glass/lens/input/udev/udevInput.c	Thu Oct 24 09:15:02 2013 +0100
+++ b/modules/graphics/src/main/native-glass/lens/input/udev/udevInput.c	Thu Oct 24 14:37:26 2013 +0300
@@ -106,6 +106,8 @@
 
     /* multitouch points */
     int                     nextTouchID; // ID used for the next new touch point
+    // the ID of the point that mouse events will be synthesize from
+    int                     touchPrimaryPointID; 
     /* existing touch points that have already been sent up to Glass */
     int                     touchPointCount;
     int                     touchIDs[LENS_MAX_TOUCH_POINTS];
@@ -126,7 +128,6 @@
     int pressedX;
     int pressedY;
 
-    jboolean isTouchDragging; //true when touch is dragging
 } LensInputMouseState;
 
 typedef struct {
@@ -698,7 +699,7 @@
 
     state->pressedX = 0;
     state->pressedY = 0;
-    state->isTouchDragging = JNI_FALSE;
+    state->touchPrimaryPointID = -1; //not set
 
     return LENS_OK;
 }
@@ -1756,19 +1757,78 @@
             }
         }
         if (needToNotify) {
+
+
+            int primaryPointIndex = -1;
+            //Find the primary point in this touch event. Mouse events will be
+            //synthesized from it
+            if (mouseState->touchPrimaryPointID == -1) {
+                //no previous primary point
+                for (i = 0; i < count; i++) {
+                    if (states[i] == com_sun_glass_events_TouchEvent_TOUCH_PRESSED) {
+                        mouseState->touchPrimaryPointID = (int)ids[i];
+                        primaryPointIndex = i;
+                        GLASS_LOG_FINEST("no previous primary touch point -"
+                                         " assigning point (index %d, id %d) as primary point",
+                                         i,
+                                         (int)ids[i]);
+                        break;
+                    }
+                }
+            } else if (mouseState->touchPrimaryPointID > 0) { //Glass id starts from 1
+                //we have a previous primary point, try to find it
+                for (i = 0; i < count; i++) {
+                    if (ids[i] == mouseState->touchPrimaryPointID &&
+                        states[i] != com_sun_glass_events_TouchEvent_TOUCH_RELEASED) {
+                        primaryPointIndex = i;
+                        GLASS_LOG_FINEST("primary point (id %d), found at index %d",
+                                     (int)ids[i],
+                                     i);
+                        break;
+                    }
+                }
+
+                if (primaryPointIndex == -1) {
+                    //previous primary point doesn't exist or released, find a new one
+                    for (i = 0; i < count; i++) {
+                        if (states[i] != com_sun_glass_events_TouchEvent_TOUCH_RELEASED) {
+                            mouseState->touchPrimaryPointID = (int)ids[i];
+                            primaryPointIndex = i;
+                            GLASS_LOG_FINEST("previous primary point doesn't exist"
+                                         " reassign to point[%d], id = %d ",
+                                         i,
+                                         (int)ids[i]);
+                            break;
+                        }
+                    }
+                }
+
+            } else {
+                GLASS_LOG_SEVERE("Illegal indexed touch point state");
+            }
+
+
+            if (primaryPointIndex == -1) {
+                 GLASS_LOG_FINEST("primary point not found - release");
+            }
+
             GLASS_IF_LOG_FINEST {
                 GLASS_LOG_FINEST("lens_wm_notifyMultiTouchEvent() with:");
                 for (i = 0; i < count; i++) {
-                    GLASS_LOG_FINEST("point %d / %d id=%d state=%d, x=%d y=%d",
+                    char *isPrimary = primaryPointIndex >=0?
+                                        "[Primary]":
+                                        "";
+                    GLASS_LOG_FINEST("point %d / %d id=%d state=%d, x=%d y=%d %s",
                                      i+1,
                                      count,
                                      (int)ids[i],
                                      states[i],
-                                     xs[i], ys[i]);
+                                     xs[i], ys[i],
+                                     isPrimary);
                 }
                 GLASS_LOG_FINEST(""); //make it easier to read the log
             }
-            lens_wm_notifyMultiTouchEvent(gJNIEnv, count, states, ids, xs, ys);
+            lens_wm_notifyMultiTouchEvent(gJNIEnv, count, states, ids, xs, ys, primaryPointIndex);
         } else {
             GLASS_LOG_FINEST("all points are STILL - skipping event");
         }
@@ -1782,27 +1842,29 @@
     GLASS_LOG_FINEST("device %p x %d y %d reportMove %d keyEventIndex: %d\n",
                      device, mousePosX, mousePosY, reportMouseMove, keyEventIndex);
 
-    if (keyEventIndex >= 0) {
-         lens_input_pointerEvents_handleKeyEvent(device,
-                                                 &mouseState->pendingInputEvents[keyEventIndex]);
+    if (!device->isTouch) {
+        if (keyEventIndex >= 0) {
+             lens_input_pointerEvents_handleKeyEvent(device,
+                                                     &mouseState->pendingInputEvents[keyEventIndex]);
+        }
+
+        if (reportMouseMove) {
+
+            //report move
+            lens_wm_notifyMotionEvent(gJNIEnv, mousePosX, mousePosY);
+
+            if (mouseState->rel[REL_WHEEL] != 0) {
+                //report wheel
+                lens_wm_notifyScrollEvent(gJNIEnv, mousePosX, mousePosY,
+                                          mouseState->rel[REL_WHEEL]);
+            }
+
+            for (i = 0; i < REL_MAX + 1; i++) {
+                mouseState->rel[i] = 0;
+            }
+        }
+
     }
-
-    if (reportMouseMove) {
-
-        //report move
-        lens_wm_notifyMotionEvent(gJNIEnv, mousePosX, mousePosY);
-
-        if (mouseState->rel[REL_WHEEL] != 0) {
-            //report wheel
-            lens_wm_notifyScrollEvent(gJNIEnv, mousePosX, mousePosY,
-                                      mouseState->rel[REL_WHEEL]);
-        }
-
-        for (i = 0; i < REL_MAX + 1; i++) {
-            mouseState->rel[i] = 0;
-        }
-    }
-
     mouseState->pendingInputEventCount = 0;
 
     // recording pending touch points as existing touch points
--- a/modules/graphics/src/main/native-glass/lens/wm/LensWindowManager.c	Thu Oct 24 09:15:02 2013 +0100
+++ b/modules/graphics/src/main/native-glass/lens/wm/LensWindowManager.c	Thu Oct 24 14:37:26 2013 +0300
@@ -44,6 +44,8 @@
 static jboolean _mousePressed = JNI_FALSE;
 static jboolean _onDraggingAction = JNI_FALSE;
 static NativeWindow _dragGrabbingWindow = NULL;
+static int _mousePressedButton = com_sun_glass_events_MouseEvent_BUTTON_NONE;
+static NativeWindow touchWindow = NULL;
 
 static jboolean isDnDStarted = JNI_FALSE;
 
@@ -942,6 +944,7 @@
     GLASS_LOG_FINER("Absolute coordinates %i,%i are not on a window",
                     absX, absY);
 
+
     return NULL;
 }
 
@@ -1004,16 +1007,34 @@
     //cache new coordinates
     _mousePosX = xabs;
     _mousePosY = yabs;
-
     window = glass_window_findWindowAtLocation(xabs, yabs,
                           &relX, &relY);
 
-    _mousePressed = pressed;
+    GLASS_LOG_FINEST("button event on window %d[%p], pressed %s, button %d, abs (%d,%d) rel (%d,%d)",
+                                      window?window->id:-1,
+                                      window,
+                                      pressed?"true":"false",
+                                      button,
+                                      xabs, yabs,
+                                      relX, relY);
+
+    if (_mousePressedButton == com_sun_glass_events_MouseEvent_BUTTON_NONE) {
+        if (_onDraggingAction) {
+             GLASS_LOG_SEVERE("bad native mouse drag state - Press event while on drag, resetting");
+             _onDraggingAction = JNI_FALSE;
+             _dragGrabbingWindow = NULL;
+        }
+        GLASS_LOG_FINEST("first press (button %d)", button);
+        _mousePressedButton = button;
+         
+    } else if (!pressed && button == _mousePressedButton) {
+        GLASS_LOG_FINEST("pressed button %d released - stopping native mouse drag", button);
+        _mousePressedButton = com_sun_glass_events_MouseEvent_BUTTON_NONE;        
+         _onDraggingAction = JNI_FALSE;
+        _dragGrabbingWindow = NULL;
+    }
 
     if (_onDraggingAction) {
-        if (pressed) {
-            GLASS_LOG_SEVERE("Press event while on drag !");
-        }
 
         if (_dragGrabbingWindow != NULL) {
 
@@ -1026,9 +1047,11 @@
                                                button);
 
         }
-
-        _onDraggingAction = JNI_FALSE;
-        _dragGrabbingWindow = NULL;
+        
+        if (button == _mousePressedButton) {
+            _onDraggingAction = JNI_FALSE;
+            _dragGrabbingWindow = NULL;
+        }
 
     } else {
         if (window != NULL) {
@@ -1051,78 +1074,90 @@
 
 }
 
-
 // check for window grab then forward event to application.
 // check for focus changes and handle them.
 void lens_wm_notifyMultiTouchEvent(JNIEnv *env,
                                    jint count,
                                    jint *states,
                                    jlong *ids,
-                                   int *xabs, int *yabs) {
+                                   int *xabs, int *yabs,
+                                   int primaryPointIndex) {
 
     int i;
-    int dx, dy;
-    NativeWindow window;
-    jboolean allReleased;
+    int dx, dy, relX, relY, absX, absY;
+    jboolean allReleased;    
 
-    //cache new coordinates
-    _mousePosX = xabs[0];
-    _mousePosY = yabs[0];
-
-    fbCursorSetPosition(_mousePosX, _mousePosY);
-
-    if (_dragGrabbingWindow == NULL) {
-        int relX, relY;
-        window = glass_window_findWindowAtLocation(xabs[0], yabs[0],
-                          &relX, &relY);
-        dx = relX - xabs[0];
-        dy = relY - yabs[0];
-        lens_wm_setMouseWindow(window);
-    } else {
-        window = _dragGrabbingWindow;
-        dx = -window->currentBounds.x;
-        dy = -window->currentBounds.y;
+    //set the touch window on first touch event
+    if (touchWindow == NULL) {
+        //find the touch window for first event
+        touchWindow = glass_window_findWindowAtLocation(xabs[primaryPointIndex],
+                                                        yabs[primaryPointIndex],
+                                                        &relX, &relY);
+        lens_wm_setMouseWindow(touchWindow);
     }
 
-    if (states[0] == com_sun_glass_events_TouchEvent_TOUCH_PRESSED && !_mousePressed) {
-        _mousePressed = JNI_TRUE;
-        if (window) {
-            // Pressed on window
-            glass_application_notifyMouseEvent(env,
-                                               window,
-                                               com_sun_glass_events_MouseEvent_ENTER,
-                                               xabs[0] + dx, yabs[0] + dy, xabs[0], yabs[0],
-                                               com_sun_glass_events_MouseEvent_BUTTON_NONE);
+    GLASS_LOG_FINER("touch window %d, indexPoint = %d",
+                    touchWindow? touchWindow->id : -1,
+                    primaryPointIndex);
+    if (touchWindow == NULL && primaryPointIndex == -1) {
+        GLASS_LOG_FINER("Touch event outside a window");
+    }
+    //sythesis mouse events.
+    // handling of grab, exit/enter events etc. is done by the mouse handlers
+    if (primaryPointIndex == -1) {
+        //all points released, release button
+        GLASS_LOG_FINEST("touch -> mouse - release");
+        //use last location
+        absX = _mousePosX; 
+        absY = _mousePosY;
+        lens_wm_notifyButtonEvent(env,
+                                  JNI_FALSE, //pressed
+                                  com_sun_glass_events_MouseEvent_BUTTON_LEFT,
+                                  absX,
+                                  absY);
+    } else {
+        //use new location
+        absX = xabs[primaryPointIndex];
+        absY = yabs[primaryPointIndex];
+        switch (states[primaryPointIndex]) {
+            case com_sun_glass_events_TouchEvent_TOUCH_PRESSED:
+                //send button pressed
+                GLASS_LOG_FINEST("touch -> mouse - pressed");
+                lens_wm_notifyButtonEvent(env,
+                                          JNI_TRUE, //preseed
+                                          com_sun_glass_events_MouseEvent_BUTTON_LEFT,
+                                          absX,
+                                          absY);
+
+                break;
+            case com_sun_glass_events_TouchEvent_TOUCH_MOVED:
+                GLASS_LOG_FINEST("touch -> mouse - move");
+                lens_wm_notifyMotionEvent(env,
+                                          absX,
+                                          absY);
+                break;
+            case com_sun_glass_events_TouchEvent_TOUCH_STILL:
+                //nothing to do
+                GLASS_LOG_FINEST("touch -> mouse - still, ignoring");
+                break;
+            case com_sun_glass_events_TouchEvent_TOUCH_RELEASED:
+                GLASS_LOG_WARNING("touch -> mouse - release, illegal state");
+                break;
         }
     }
-
-    allReleased = JNI_TRUE;
-    for (i = 0; i < count && allReleased; i++) {
-        if (states[i] != com_sun_glass_events_TouchEvent_TOUCH_RELEASED) {
-            allReleased = JNI_FALSE;
-            break;
+    
+    if (touchWindow != NULL) {
+        dx = -touchWindow->currentBounds.x;
+        dy = -touchWindow->currentBounds.y;
+        glass_application_notifyMultiTouchEvent(env, touchWindow, count,
+                                                states, ids, xabs, yabs,
+                                                dx, dy);
+        if (primaryPointIndex == -1) {
+            //all released
+            touchWindow = NULL;
         }
     }
-    if (allReleased) {
-        _mousePressed = JNI_FALSE;
-        _onDraggingAction = JNI_FALSE;
-        _dragGrabbingWindow = NULL;
-        glass_inputEvents_updateMouseButtonModifiers(
-            com_sun_glass_events_MouseEvent_BUTTON_LEFT,
-            com_sun_glass_events_MouseEvent_DOWN);
-    } else {
-        glass_inputEvents_updateMouseButtonModifiers(
-            com_sun_glass_events_MouseEvent_BUTTON_LEFT,
-            com_sun_glass_events_MouseEvent_UP);
-    }
-
-    if (window != NULL) {
-        glass_application_notifyMultiTouchEvent(env, window, count,
-                                                states, ids, xabs, yabs,
-                                                dx, dy);
-    }
-    handleClickOrTouchEvent(env, xabs[0] + dx, yabs[0] + dy);
-
+   
 }
 
 
@@ -1142,9 +1177,8 @@
         _onDraggingAction = JNI_TRUE;
         _dragGrabbingWindow = lens_wm_getMouseWindow();
     }
-    
-    NativeWindow window = glass_window_findWindowAtLocation(
-                              _mousePosX, _mousePosY, &relX, &relY);
+    NativeWindow window = glass_window_findWindowAtLocation(_mousePosX, _mousePosY,
+                                                            &relX, &relY);
 
     GLASS_LOG_FINER("Motion event on window %i[%p] absX=%i absY=%i, relX=%i, relY=%i",
                     (window)?window->id:-1,
--- a/modules/graphics/src/main/native-glass/lens/wm/LensWindowManager.h	Thu Oct 24 09:15:02 2013 +0100
+++ b/modules/graphics/src/main/native-glass/lens/wm/LensWindowManager.h	Thu Oct 24 14:37:26 2013 +0300
@@ -114,18 +114,33 @@
 
 
 /**
- * Process a touch or multitouch event and pass it on to
- * glass_application_notifyTouchEvent or
- * glass_application_notifyMultiTouchEvent, taking into account the grabbed
- * window.
- * Note: a NULL window is appropriate as that 
- * will cause the grab window to be release.
+ * Process a touch or multitouch event and simulate the required
+ * mouse events. Notification is done through 
+ * glass_application_notifyTouchEvent or 
+ * glass_application_notifyMultiTouchEvent Note: 
+ *  
+ * @param env 
+ * 
+ * @param count number of touch points
+ * 
+ * @param state array of states for each point
+ * 
+ * @param ids array of ids for each point
+ * 
+ * @param xabs array of X coordinates for each point
+ * 
+ * @param yabs array of Y coordinates for each point
+ * 
+ * @param primaryPointIndex the index of the point that mouse 
+ *                   events will be synthesis from
+ * 
  */
 void lens_wm_notifyMultiTouchEvent(JNIEnv *env,
                                    int count,
                                    jint *state,
                                    jlong *ids,
-                                   int *xabs, int *yabs);
+                                   int *xabs, int *yabs,
+                                   int primaryPointIndex);
 
 
 /**