77
88import android .os .SystemClock ;
99import android .util .Log ;
10- import android .view .MotionEvent ;
11- import android .view .InputDevice ;
1210import android .util .SparseArray ;
11+ import android .view .InputDevice ;
12+ import android .view .MotionEvent ;
1313
1414import org .mozilla .vrbrowser .ui .widgets .Widget ;
1515import org .mozilla .vrbrowser .utils .SystemUtils ;
1616
1717import java .util .Arrays ;
18- import java .util .List ;
1918
2019public class MotionEventGenerator {
2120 static final String LOGTAG = SystemUtils .createLogtag (MotionEventGenerator .class );
@@ -53,11 +52,11 @@ static class Device {
5352 private static SparseArray <Device > devices = new SparseArray <>();
5453
5554
56- private static void generateEvent (Widget aWidget , Device aDevice , int aAction , boolean aGeneric ) {
57- generateEvent (aWidget , aDevice , aAction , aGeneric , aDevice .mCoords );
55+ private static void generateEvent (Widget aWidget , Device aDevice , boolean aFocused , int aAction , boolean aGeneric ) {
56+ generateEvent (aWidget , aDevice , aFocused , aAction , aGeneric , aDevice .mCoords );
5857 }
5958
60- private static void generateEvent (Widget aWidget , Device aDevice , int aAction , boolean aGeneric , MotionEvent .PointerCoords [] aCoords ) {
59+ private static void generateEvent (Widget aWidget , Device aDevice , boolean aFocused , int aAction , boolean aGeneric , MotionEvent .PointerCoords [] aCoords ) {
6160 MotionEvent event = MotionEvent .obtain (
6261 /*mDownTime*/ aDevice .mDownTime ,
6362 /*eventTime*/ SystemClock .uptimeMillis (),
@@ -69,19 +68,24 @@ private static void generateEvent(Widget aWidget, Device aDevice, int aAction, b
6968 /*buttonState*/ 0 ,
7069 /*xPrecision*/ 0 ,
7170 /*yPrecision*/ 0 ,
72- /*deviceId*/ 0 , // aDevice.mDevice,
71+ /*deviceId*/ aDevice .mDevice ,
7372 /*edgeFlags*/ 0 ,
7473 /*source*/ InputDevice .SOURCE_TOUCHSCREEN ,
7574 /*flags*/ 0 );
7675 if (aGeneric ) {
77- aWidget .handleHoverEvent (event );
76+ if (aWidget .supportsMultipleInputDevices ()) {
77+ aWidget .handleHoverEvent (event );
78+
79+ } else if (aFocused ) {
80+ aWidget .handleHoverEvent (event );
81+ }
7882 } else {
7983 aWidget .handleTouchEvent (event );
8084 }
8185 event .recycle ();
8286 }
8387
84- public static void dispatch (Widget aWidget , int aDevice , boolean aPressed , float aX , float aY ) {
88+ public static void dispatch (Widget aWidget , int aDevice , boolean aFocused , boolean aPressed , float aX , float aY ) {
8589 Device device = devices .get (aDevice );
8690 if (device == null ) {
8791 device = new Device (aDevice );
@@ -99,41 +103,66 @@ public static void dispatch(Widget aWidget, int aDevice, boolean aPressed, float
99103 }
100104 if (!aPressed && (device .mPreviousWidget != null ) && (device .mPreviousWidget != aWidget )) {
101105 if (device .mWasPressed ) {
102- generateEvent (device .mPreviousWidget , device , MotionEvent .ACTION_CANCEL , false );
106+ generateEvent (device .mPreviousWidget , device , aFocused , MotionEvent .ACTION_CANCEL , false );
103107 device .mWasPressed = false ;
104108 }
105- generateEvent (device .mPreviousWidget , device , MotionEvent .ACTION_HOVER_EXIT , true , device .mMouseOutCoords );
109+ generateEvent (device .mPreviousWidget , device , aFocused , MotionEvent .ACTION_HOVER_EXIT , true , device .mMouseOutCoords );
106110 device .mPreviousWidget = null ;
107111 }
108112 if (aWidget == null ) {
109113 device .mPreviousWidget = null ;
110114 return ;
111115 }
112116 if (aWidget != device .mPreviousWidget && !aPressed ) {
113- generateEvent (aWidget , device , MotionEvent .ACTION_HOVER_ENTER , true );
117+ generateEvent (aWidget , device , aFocused , MotionEvent .ACTION_HOVER_ENTER , true );
114118 }
115119 if (aPressed && !device .mWasPressed ) {
116120 device .mDownTime = SystemClock .uptimeMillis ();
117121 device .mWasPressed = true ;
118- generateEvent (aWidget , device , MotionEvent .ACTION_HOVER_EXIT , true );
119- generateEvent (aWidget , device , MotionEvent .ACTION_DOWN , false );
122+ if (!isOtherDeviceDown (device .mDevice )) {
123+ generateEvent (aWidget , device , aFocused , MotionEvent .ACTION_HOVER_EXIT , true );
124+ generateEvent (aWidget , device , aFocused , MotionEvent .ACTION_DOWN , false );
125+ }
120126 device .mTouchStartWidget = aWidget ;
121127 } else if (!aPressed && device .mWasPressed ) {
122128 device .mWasPressed = false ;
123- generateEvent (device .mTouchStartWidget , device , MotionEvent .ACTION_UP , false );
124- generateEvent (aWidget , device , MotionEvent .ACTION_HOVER_ENTER , true );
129+ if (!isOtherDeviceDown (device .mDevice )) {
130+ generateEvent (device .mTouchStartWidget , device , aFocused , MotionEvent .ACTION_UP , false );
131+ generateEvent (aWidget , device , aFocused , MotionEvent .ACTION_HOVER_ENTER , true );
132+ }
133+ device .mTouchStartWidget = null ;
125134 } else if (moving && aPressed ) {
126- generateEvent (aWidget , device , MotionEvent .ACTION_MOVE , false );
135+ generateEvent (aWidget , device , aFocused , MotionEvent .ACTION_MOVE , false );
127136 } else if (moving ) {
128- generateEvent (aWidget , device , MotionEvent .ACTION_HOVER_MOVE , true );
137+ generateEvent (aWidget , device , aFocused , MotionEvent .ACTION_HOVER_MOVE , true );
129138 } else {
130139 Log .e ("VRB" , "Unknown touch event action" );
131140 return ;
132141 }
133142 device .mPreviousWidget = aWidget ;
134143 }
135144
136- public static void dispatchScroll (Widget aWidget , int aDevice , float aX , float aY ) {
145+ /**
146+ * Checks if any other device has an ongoing touch down event.
147+ * Android throw away all previous state when starting a new touch gesture
148+ * and this seem to make the previous touch to be sent up the view hierarchy.
149+ * To avoid this we check if any other device has a button down before sending
150+ * touch down/up event.
151+ * @param deviceId Device Id to filter
152+ * @return true if any other device has a button down, false otherwise
153+ */
154+ private static boolean isOtherDeviceDown (int deviceId ) {
155+ boolean result = false ;
156+ for (int i =0 ; i <devices .size (); i ++) {
157+ if (i != deviceId ) {
158+ result |= devices .get (i ).mTouchStartWidget != null ;
159+ }
160+ }
161+
162+ return result ;
163+ }
164+
165+ public static void dispatchScroll (Widget aWidget , int aDevice , boolean aFocused , float aX , float aY ) {
137166 Device device = devices .get (aDevice );
138167 if (device == null ) {
139168 device = new Device (aDevice );
@@ -142,7 +171,7 @@ public static void dispatchScroll(Widget aWidget, int aDevice, float aX, float a
142171 device .mPreviousWidget = aWidget ;
143172 device .mCoords [0 ].setAxisValue (MotionEvent .AXIS_VSCROLL , aY );
144173 device .mCoords [0 ].setAxisValue (MotionEvent .AXIS_HSCROLL , aX );
145- generateEvent (aWidget , device , MotionEvent .ACTION_SCROLL , true );
174+ generateEvent (aWidget , device , aFocused , MotionEvent .ACTION_SCROLL , true );
146175 device .mCoords [0 ].setAxisValue (MotionEvent .AXIS_VSCROLL , 0.0f );
147176 device .mCoords [0 ].setAxisValue (MotionEvent .AXIS_HSCROLL , 0.0f );
148177 }
0 commit comments