Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert pen input flow and map pen to touch on mobile platforms #6523

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
4 changes: 2 additions & 2 deletions osu.Framework.Tests/Visual/Input/TestSceneTouchInput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ public void TestMouseInputAppliedFromLatestTouch()

AddStep("retrieve receptors", () =>
{
firstReceptor = receptors[(int)TouchSource.Touch1];
lastReceptor = receptors[(int)TouchSource.Touch10];
firstReceptor = receptors.First();
lastReceptor = receptors.Last();
});

AddStep("activate first", () =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public TestSceneTouchVisualiser()

public partial class TouchVisualiser : CompositeDrawable
{
private readonly Drawable[] drawableTouches = new Drawable[10];
private readonly Drawable[] drawableTouches = new Drawable[TouchState.MAX_TOUCH_COUNT];

public TouchVisualiser()
{
Expand Down
24 changes: 13 additions & 11 deletions osu.Framework/Input/Handlers/Pen/PenHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,24 @@ public override bool Initialize(GameHost host)
return true;
}

// iPadOS doesn't support external tablets, so we are sure it's direct Apple Pencil input.
// Other platforms support both direct and indirect tablet input, but SDL doesn't provide any information on the current device type.
private static readonly TabletPenDeviceType device_type = RuntimeInfo.OS == RuntimeInfo.Platform.iOS ? TabletPenDeviceType.Direct : TabletPenDeviceType.Unknown;
// Pen input is not necessarily direct on mobile platforms (specifically Android, where external tablets are supported),
// but until users experience issues with this, consider it "direct" for now.
private static readonly TabletPenDeviceType device_type = RuntimeInfo.IsMobile ? TabletPenDeviceType.Direct : TabletPenDeviceType.Unknown;

private void handlePenMove(Vector2 position)
private void handlePenMove(Vector2 position, bool pressed)
{
enqueueInput(new MousePositionAbsoluteInputFromPen
{
Position = position,
DeviceType = device_type
});
if (pressed && device_type == TabletPenDeviceType.Direct)
enqueueInput(new TouchInput(new Input.Touch(TouchSource.PenTouch, position), true));
else
enqueueInput(new MousePositionAbsoluteInputFromPen { DeviceType = device_type, Position = position });
}

private void handlePenTouch(bool pressed)
private void handlePenTouch(bool pressed, Vector2 position)
{
enqueueInput(new MouseButtonInputFromPen(pressed) { DeviceType = device_type });
if (device_type == TabletPenDeviceType.Direct)
enqueueInput(new TouchInput(new Input.Touch(TouchSource.PenTouch, position), pressed));
else
enqueueInput(new MouseButtonInputFromPen(pressed) { DeviceType = device_type });
}

private void handlePenButton(TabletPenButton button, bool pressed)
Expand Down
3 changes: 2 additions & 1 deletion osu.Framework/Input/StateChanges/ISourcedFromPen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ namespace osu.Framework.Input.StateChanges
/// <summary>
/// Denotes a simulated mouse input that was made by a tablet/pen device.
/// </summary>
public interface ISourcedFromPen : IInput
// todo: this is not ready to be used externally for distinguishing input, therefore it's internal for now.
internal interface ISourcedFromPen : IInput
{
/// <summary>
/// The type of the tablet or pen device that made this input.
Expand Down
7 changes: 6 additions & 1 deletion osu.Framework/Input/States/TouchState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ namespace osu.Framework.Input.States
public class TouchState
{
/// <summary>
/// The maximum amount of touches this can handle.
/// The maximum number of touches this can handle.
/// </summary>
public static readonly int MAX_TOUCH_COUNT = Enum.GetValues<TouchSource>().Length;

/// <summary>
/// The maximum number of touches this can handle excluding the synthetic source <see cref="TouchSource.PenTouch"/>.
/// </summary>
internal static readonly int MAX_NATIVE_TOUCH_COUNT = 10;

/// <summary>
/// The list of currently active touch sources.
/// </summary>
Expand Down
5 changes: 5 additions & 0 deletions osu.Framework/Input/TouchSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,10 @@ public enum TouchSource
/// The tenth and last available touch source.
/// </summary>
Touch10,

/// <summary>
/// A touch source that represents a pen/stylus.
/// </summary>
PenTouch,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The eleventh finger on a touchscreen would report as a PenTouch. assignNextAvailableTouchSource() / activeTouches (both SDL2 and SDL3) needs to be updated to only consider the first ten.

I'd say add internal const int MAX_NATIVE_TOUCH_COUNT = 10 in TouchState.

}
}
4 changes: 2 additions & 2 deletions osu.Framework/Platform/SDL2/SDL2Window_Input.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ private void handleDropEvent(SDL_DropEvent evtDrop)
}
}

private readonly long?[] activeTouches = new long?[TouchState.MAX_TOUCH_COUNT];
private readonly long?[] activeTouches = new long?[TouchState.MAX_NATIVE_TOUCH_COUNT];

private TouchSource? getTouchSource(long fingerId)
{
Expand All @@ -230,7 +230,7 @@ private void handleDropEvent(SDL_DropEvent evtDrop)
return (TouchSource)i;
}

// we only handle up to TouchState.MAX_TOUCH_COUNT. Ignore any further touches for now.
// we only handle up to TouchState.MAX_NATIVE_TOUCH_COUNT. Ignore any further touches for now.
return null;
}

Expand Down
15 changes: 8 additions & 7 deletions osu.Framework/Platform/SDL3/SDL3Window_Input.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ private void handleDropEvent(SDL_DropEvent evtDrop)
}
}

private readonly SDL_FingerID?[] activeTouches = new SDL_FingerID?[TouchState.MAX_TOUCH_COUNT];
private readonly SDL_FingerID?[] activeTouches = new SDL_FingerID?[TouchState.MAX_NATIVE_TOUCH_COUNT];

private TouchSource? getTouchSource(SDL_FingerID fingerId)
{
Expand All @@ -270,7 +270,7 @@ private void handleDropEvent(SDL_DropEvent evtDrop)
return (TouchSource)i;
}

// we only handle up to TouchState.MAX_TOUCH_COUNT. Ignore any further touches for now.
// we only handle up to TouchState.MAX_NATIVE_TOUCH_COUNT. Ignore any further touches for now.
return null;
}

Expand Down Expand Up @@ -532,12 +532,12 @@ private void handleKeyboardEvent(SDL_KeyboardEvent evtKey)

private void handlePenMotionEvent(SDL_PenMotionEvent evtPenMotion)
{
PenMove?.Invoke(new Vector2(evtPenMotion.x, evtPenMotion.y) * Scale);
PenMove?.Invoke(new Vector2(evtPenMotion.x, evtPenMotion.y) * Scale, evtPenMotion.pen_state.HasFlagFast(SDL_PenInputFlags.SDL_PEN_INPUT_DOWN));
}

private void handlePenTouchEvent(SDL_PenTouchEvent evtPenTouch)
{
PenTouch?.Invoke(evtPenTouch.down);
PenTouch?.Invoke(evtPenTouch.down, new Vector2(evtPenTouch.x, evtPenTouch.y) * Scale);
}

/// <summary>
Expand Down Expand Up @@ -743,14 +743,15 @@ private void updateConfineMode()
public event Action<Touch>? TouchUp;

/// <summary>
/// Invoked when a pen moves.
/// Invoked when a pen moves. Passes pen position and whether the pen is touching the tablet surface.
/// </summary>
public event Action<Vector2>? PenMove;
public event Action<Vector2, bool>? PenMove;

/// <summary>
/// Invoked when a pen touches (<c>true</c>) or lifts (<c>false</c>) from the tablet surface.
/// Also passes the current position of the pen.
/// </summary>
public event Action<bool>? PenTouch;
public event Action<bool, Vector2>? PenTouch;

/// <summary>
/// Invoked when a <see cref="TabletPenButton">pen button</see> is pressed (<c>true</c>) or released (<c>false</c>).
Expand Down
Loading