Skip to content

Commit afd0a6f

Browse files
YNataniel295peppy
andauthored
Fix hovering with tablet causing mouse buttons to be immediately released (#6701)
* Fix LMB hold when hovering with tablet pen Fixes an issue where LMB would be released immediately when the pen is in hover range. Added pen pressure hysteresis, may be needed. * Fix LMB hold when hovering with tablet pen Fixes an issue where LMB would be released immediately when the pen is in hover range. Added pen pressure hysteresis, may be needed. * Fix LMB hold when hovering with tablet pen Stop continuously propagating pen LMB state; use edge-only press/release with a small internal hysteresis and release on tablet disconnect. * Fix LMB hold when hovering with tablet pen * Fix LMB hold when hovering with tablet pen * Rewrite for simplicity --------- Co-authored-by: Dean Herbert <pe@ppy.sh>
1 parent ec800bc commit afd0a6f

File tree

1 file changed

+45
-2
lines changed

1 file changed

+45
-2
lines changed

osu.Framework/Input/Handlers/Tablet/OpenTabletDriverHandler.cs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
22
// See the LICENCE file in the repository root for full licence text.
33

4+
using System;
45
using System.Collections.Generic;
56
using System.Linq;
67
using System.Threading.Tasks;
@@ -44,7 +45,7 @@ public class OpenTabletDriverHandler : InputHandler, IAbsolutePointer, IRelative
4445

4546
public Bindable<float> Rotation { get; } = new Bindable<float>();
4647

47-
public BindableFloat PressureThreshold { get; } = new BindableFloat(0.0f)
48+
public BindableFloat PressureThreshold { get; } = new BindableFloat
4849
{
4950
MinValue = 0f,
5051
MaxValue = 1f,
@@ -119,7 +120,34 @@ void IRelativePointer.SetPosition(System.Numerics.Vector2 delta)
119120
enqueueInput(new MousePositionRelativeInputFromPen { Delta = new Vector2(delta.X, delta.Y), DeviceType = lastTabletDeviceType });
120121
}
121122

122-
void IPressureHandler.SetPressure(float percentage) => enqueueInput(new MouseButtonInputFromPen(percentage > PressureThreshold.Value) { DeviceType = lastTabletDeviceType });
123+
private bool penPressed;
124+
125+
void IPressureHandler.SetPressure(float pressure)
126+
{
127+
// Most important for edge cases where users have pressure set to 0 or 1 and tablets can report fuzzy data.
128+
const float hysteresis_half = 0.02f;
129+
130+
pressure = Math.Clamp(pressure, 0f, 1f);
131+
132+
float releaseThreshold = PressureThreshold.Value - hysteresis_half;
133+
float pressThreshold = PressureThreshold.Value + hysteresis_half;
134+
135+
// keep press..release threshold range constant for edge cases.
136+
if (releaseThreshold < 0f)
137+
{
138+
pressThreshold = hysteresis_half * 2;
139+
releaseThreshold = 0f;
140+
}
141+
else if (pressThreshold > 1f)
142+
{
143+
releaseThreshold = 1 - (hysteresis_half * 2);
144+
pressThreshold = 1f;
145+
}
146+
147+
setPressed(penPressed
148+
? pressure > releaseThreshold
149+
: pressure > pressThreshold);
150+
}
123151

124152
private void handleTabletsChanged(object? sender, IEnumerable<TabletReference> tablets)
125153
{
@@ -135,7 +163,22 @@ private void handleTabletsChanged(object? sender, IEnumerable<TabletReference> t
135163
updateOutputArea(host.Window);
136164
}
137165
else
166+
{
167+
// Ensure we don't leave the simulated mouse button pressed if the tablet disappears.
168+
setPressed(false);
138169
tablet.Value = null;
170+
}
171+
}
172+
173+
private void setPressed(bool pressed)
174+
{
175+
// Importantly, only fire input when the state changes.
176+
// If we fire more often, this may intefere with users that click with mouse but use tablet for positional input (hovering).
177+
if (pressed == penPressed)
178+
return;
179+
180+
enqueueInput(new MouseButtonInputFromPen(pressed) { DeviceType = lastTabletDeviceType });
181+
penPressed = pressed;
139182
}
140183

141184
private void handleDeviceReported(object? sender, IDeviceReport report)

0 commit comments

Comments
 (0)