Skip to content

Commit 12f00a4

Browse files
committed
Mouse fake pointer now is created right when ALT+PRESS happens and not the next frame after ALT+RELEASE. The former method was triggering unnecessary taps and was interfering with other gestures.
Now when ALT+PRESS happens, mouse pointer and fake pointer are moving together until ALT+RELEASE, after which fake pointer remains stationary.
1 parent 64a34b5 commit 12f00a4

1 file changed

Lines changed: 189 additions & 95 deletions

File tree

  • Source/Assets/TouchScript/Scripts/InputSources/InputHandlers

Source/Assets/TouchScript/Scripts/InputSources/InputHandlers/MouseHandler.cs

Lines changed: 189 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,33 @@ namespace TouchScript.InputSources.InputHandlers
1414
/// </summary>
1515
public class MouseHandler : IInputSource, IDisposable
1616
{
17+
#region Consts
18+
19+
private enum State
20+
{
21+
/// <summary>
22+
/// Only mouse pointer is active
23+
/// </summary>
24+
Mouse,
25+
26+
/// <summary>
27+
/// ALT is pressed but mouse isn't
28+
/// </summary>
29+
WaitingForFake,
30+
31+
/// <summary>
32+
/// Mouse and fake pointers are moving together after ALT+PRESS
33+
/// </summary>
34+
MouseAndFake,
35+
36+
/// <summary>
37+
/// After ALT+RELEASE fake pointer is stationary while mouse can move freely
38+
/// </summary>
39+
StationaryFake
40+
}
41+
42+
#endregion
43+
1744
#region Public properties
1845

1946
/// <inheritdoc />
@@ -48,10 +75,10 @@ public bool EmulateSecondMousePointer
4875
private PointerDelegate removePointer;
4976
private PointerDelegate cancelPointer;
5077

78+
private State state;
5179
private ObjectPool<MousePointer> mousePool;
5280
private MousePointer mousePointer, fakeMousePointer;
5381
private Vector3 mousePointPos = Vector3.zero;
54-
private DelayedFakePointer addFakePointer;
5582

5683
#endregion
5784

@@ -75,85 +102,97 @@ public MouseHandler(PointerDelegate addPointer, PointerDelegate updatePointer, P
75102

76103
mousePool = new ObjectPool<MousePointer>(4, () => new MousePointer(this), null, (t) => t.INTERNAL_Reset());
77104

78-
addFakePointer.ShouldAdd = false;
79105
mousePointPos = Input.mousePosition;
80-
mousePointer = internalAddPointer(mousePointPos);
106+
mousePointer = internalAddPointer(remapCoordinates(mousePointPos));
107+
108+
stateMouse();
81109
}
82110

83111
#region Public methods
84112

85113
/// <inheritdoc />
86114
public void UpdateInput()
87115
{
88-
if (addFakePointer.ShouldAdd)
89-
{
90-
addFakePointer.ShouldAdd = false;
91-
fakeMousePointer = internalAddPointer(addFakePointer.Position, addFakePointer.Buttons, addFakePointer.Flags);
92-
pressPointer(fakeMousePointer);
93-
}
94-
95-
if (fakeMousePointer != null
96-
&& !(Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt)))
97-
{
98-
releasePointer(fakeMousePointer);
99-
removePointer(fakeMousePointer);
100-
fakeMousePointer = null;
101-
}
102-
103-
var pos = Input.mousePosition;
104-
if (mousePointPos != pos)
105-
{
106-
mousePointPos = pos;
107-
mousePointer.Position = remapCoordinates(new Vector2(pos.x, pos.y));
108-
updatePointer(mousePointer);
109-
}
110-
111-
var scroll = Input.mouseScrollDelta;
112-
mousePointer.ScrollDelta = scroll;
113-
if (!Mathf.Approximately(scroll.sqrMagnitude, 0.0f))
114-
{
115-
updatePointer(mousePointer);
116-
}
117-
118-
var buttons = mousePointer.Buttons;
119-
var newButtons = getMouseButtons();
120-
121-
if (buttons == newButtons) return; // nothing new happened
122-
123-
// pressed something
124-
if (buttons == Pointer.PointerButtonState.Nothing)
125-
{
126-
// pressed and released this frame
127-
if ((newButtons & Pointer.PointerButtonState.AnyButtonPressed) == 0)
128-
{
129-
// Add pressed buttons for processing
130-
mousePointer.Buttons = newButtons | (Pointer.PointerButtonState) ((uint) (newButtons & Pointer.PointerButtonState.AnyButtonDown) >> 1);
131-
pressPointer(mousePointer);
132-
internalReleaseMousePointer(newButtons);
133-
}
134-
// pressed this frame
135-
else
136-
{
137-
mousePointer.Buttons = newButtons;
138-
pressPointer(mousePointer);
139-
}
140-
}
141-
// released or button state changed
142-
else
116+
var buttons = state == State.MouseAndFake ? fakeMousePointer.Buttons : mousePointer.Buttons;
117+
var newButtons = getMouseButtons();
118+
var pos = Input.mousePosition;
119+
Vector2 remappedPos = new Vector2(0, 0);
120+
121+
if (mousePointPos != pos)
122+
{
123+
remappedPos = remapCoordinates(new Vector2(pos.x, pos.y));
124+
mousePointer.Position = remappedPos;
125+
updatePointer(mousePointer);
126+
}
127+
128+
var scroll = Input.mouseScrollDelta;
129+
if (!Mathf.Approximately(scroll.sqrMagnitude, 0.0f))
130+
{
131+
mousePointer.ScrollDelta = scroll;
132+
updatePointer(mousePointer);
133+
}
134+
135+
if (emulateSecondMousePointer)
143136
{
144-
// released this frame
145-
if ((newButtons & Pointer.PointerButtonState.AnyButtonPressed) == 0)
146-
{
147-
mousePointer.Buttons = newButtons;
148-
internalReleaseMousePointer(newButtons);
149-
}
150-
// button state changed this frame
151-
else
152-
{
153-
mousePointer.Buttons = newButtons;
154-
updatePointer(mousePointer);
155-
}
156-
}
137+
switch (state)
138+
{
139+
case State.Mouse:
140+
if (Input.GetKeyDown(KeyCode.LeftAlt) && !Input.GetKeyUp(KeyCode.LeftAlt)
141+
&& ((newButtons & Pointer.PointerButtonState.AnyButtonPressed) == 0))
142+
{
143+
stateWaitingForFake();
144+
} else {
145+
if (buttons != newButtons) updateButtons(buttons, newButtons);
146+
}
147+
break;
148+
case State.WaitingForFake:
149+
if (Input.GetKey(KeyCode.LeftAlt))
150+
{
151+
if ((newButtons & Pointer.PointerButtonState.AnyButtonDown) != 0)
152+
{
153+
// A button is down while holding Alt
154+
fakeMousePointer = internalAddPointer(pos, newButtons, mousePointer.Flags | Pointer.FLAG_ARTIFICIAL);
155+
pressPointer(fakeMousePointer);
156+
stateMouseAndFake();
157+
}
158+
} else {
159+
stateMouse();
160+
}
161+
break;
162+
case State.MouseAndFake:
163+
if (fakeTouchReleased())
164+
{
165+
stateMouse();
166+
} else {
167+
if (mousePointPos != pos)
168+
{
169+
fakeMousePointer.Position = remappedPos;
170+
updatePointer(fakeMousePointer);
171+
}
172+
if ((newButtons & Pointer.PointerButtonState.AnyButtonPressed) == 0)
173+
{
174+
// All buttons are released, Alt is still holding
175+
stateStationaryFake();
176+
} else if (buttons != newButtons)
177+
{
178+
fakeMousePointer.Buttons = newButtons;
179+
updatePointer(fakeMousePointer);
180+
}
181+
}
182+
break;
183+
case State.StationaryFake:
184+
if (buttons != newButtons) updateButtons(buttons, newButtons);
185+
if (fakeTouchReleased())
186+
{
187+
stateMouse();
188+
}
189+
break;
190+
}
191+
} else {
192+
if (buttons != newButtons) updateButtons(buttons, newButtons);
193+
}
194+
195+
mousePointPos = pos;
157196
}
158197

159198
/// <inheritdoc />
@@ -163,7 +202,7 @@ public bool CancelPointer(Pointer pointer, bool shouldReturn)
163202
{
164203
cancelPointer(mousePointer);
165204
if (shouldReturn) mousePointer = internalReturnPointer(mousePointer);
166-
else mousePointer = internalAddPointer(mousePointPos); // can't totally cancell mouse pointer
205+
else mousePointer = internalAddPointer(mousePointer.Position); // can't totally cancel mouse pointer
167206
return true;
168207
}
169208
if (pointer.Equals(fakeMousePointer))
@@ -227,27 +266,62 @@ private Pointer.PointerButtonState getMouseButtons()
227266
return buttons;
228267
}
229268

230-
private void tryAddFakePointer(Pointer.PointerButtonState newButtons)
231-
{
232-
if (emulateSecondMousePointer
233-
&& (Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt))
234-
&& fakeMousePointer == null)
269+
private void updateButtons(Pointer.PointerButtonState oldButtons, Pointer.PointerButtonState newButtons)
270+
{
271+
// pressed something
272+
if (oldButtons == Pointer.PointerButtonState.Nothing)
235273
{
236-
var up = (uint)(newButtons & Pointer.PointerButtonState.AnyButtonUp);
237-
addFakePointer.ShouldAdd = true;
238-
addFakePointer.Flags = mousePointer.Flags | Pointer.FLAG_ARTIFICIAL;
239-
addFakePointer.Buttons = newButtons
240-
& ~Pointer.PointerButtonState.AnyButtonUp // remove up state from fake pointer
241-
| (Pointer.PointerButtonState)(up >> 1) // Add down state from pressed buttons
242-
| (Pointer.PointerButtonState)(up >> 2); // Add pressed state from pressed buttons
243-
addFakePointer.Position = mousePointPos;
274+
// pressed and released this frame
275+
if ((newButtons & Pointer.PointerButtonState.AnyButtonPressed) == 0)
276+
{
277+
// Add pressed buttons for processing
278+
mousePointer.Buttons = newButtons | (Pointer.PointerButtonState) ((uint) (newButtons & Pointer.PointerButtonState.AnyButtonDown) >> 1);
279+
pressPointer(mousePointer);
280+
internalReleaseMousePointer(newButtons);
281+
}
282+
// pressed this frame
283+
else
284+
{
285+
mousePointer.Buttons = newButtons;
286+
pressPointer(mousePointer);
287+
}
244288
}
245-
}
289+
// released or button state changed
290+
else
291+
{
292+
// released this frame
293+
if ((newButtons & Pointer.PointerButtonState.AnyButtonPressed) == 0)
294+
{
295+
mousePointer.Buttons = newButtons;
296+
internalReleaseMousePointer(newButtons);
297+
}
298+
// button state changed this frame
299+
else
300+
{
301+
mousePointer.Buttons = newButtons;
302+
updatePointer(mousePointer);
303+
}
304+
}
305+
}
306+
307+
private bool fakeTouchReleased()
308+
{
309+
if (!Input.GetKey(KeyCode.LeftAlt))
310+
{
311+
// Alt is released, need to kill the fake touch
312+
fakeMousePointer.Buttons = (Pointer.PointerButtonState)((uint)fakeMousePointer.Buttons << 2); // Convert current pressed buttons to UP
313+
releasePointer(fakeMousePointer);
314+
removePointer(fakeMousePointer);
315+
fakeMousePointer = null; // Will be returned to the pool by INTERNAL_DiscardPointer
316+
return true;
317+
}
318+
return false;
319+
}
246320

247321
private MousePointer internalAddPointer(Vector2 position, Pointer.PointerButtonState buttons = Pointer.PointerButtonState.Nothing, uint flags = 0)
248322
{
249323
var pointer = mousePool.Get();
250-
pointer.Position = remapCoordinates(position);
324+
pointer.Position = position;
251325
pointer.Buttons |= buttons;
252326
pointer.Flags |= flags;
253327
addPointer(pointer);
@@ -258,7 +332,6 @@ private void internalReleaseMousePointer(Pointer.PointerButtonState buttons)
258332
{
259333
mousePointer.Flags &= ~Pointer.FLAG_RETURNED;
260334
releasePointer(mousePointer);
261-
tryAddFakePointer(buttons);
262335
}
263336

264337
private MousePointer internalReturnPointer(MousePointer pointer)
@@ -284,13 +357,34 @@ private Vector2 remapCoordinates(Vector2 position)
284357

285358
#endregion
286359

287-
private struct DelayedFakePointer
288-
{
289-
public bool ShouldAdd;
290-
public uint Flags;
291-
public Pointer.PointerButtonState Buttons;
292-
public Vector2 Position;
293-
}
360+
#region State logic
361+
362+
private void stateMouse()
363+
{
364+
setState(State.Mouse);
365+
}
366+
367+
private void stateWaitingForFake()
368+
{
369+
setState(State.WaitingForFake);
370+
}
371+
372+
private void stateMouseAndFake()
373+
{
374+
setState(State.MouseAndFake);
375+
}
376+
377+
private void stateStationaryFake()
378+
{
379+
setState(State.StationaryFake);
380+
}
381+
382+
private void setState(State newState)
383+
{
384+
state = newState;
385+
}
386+
387+
#endregion
294388

295389
}
296390
}

0 commit comments

Comments
 (0)