Skip to content

Commit e6c75dc

Browse files
authored
Merge pull request #6235 from Susko3/windows-async-input
Async mouse input on windows
2 parents 9f10027 + ecb620c commit e6c75dc

File tree

3 files changed

+40
-28
lines changed

3 files changed

+40
-28
lines changed

osu.Framework/Platform/SDL3/SDL3Window.cs

+20-17
Original file line numberDiff line numberDiff line change
@@ -287,12 +287,13 @@ protected void RunFrame()
287287
/// As per SDL's recommendation, application events should always be handled via the event filter.
288288
/// See: https://wiki.libsdl.org/SDL3/SDL_EventType#android_ios_and_winrt_events
289289
/// </remarks>
290-
protected virtual void HandleEventFromFilter(SDL_Event evt)
290+
/// <returns>A <c>bool</c> denoting whether to keep the event. <c>false</c> will drop the event.</returns>
291+
protected virtual bool HandleEventFromFilter(SDL_Event e)
291292
{
292-
switch (evt.Type)
293+
switch (e.Type)
293294
{
294295
case SDL_EventType.SDL_EVENT_TERMINATING:
295-
handleQuitEvent(evt.quit);
296+
handleQuitEvent(e.quit);
296297
break;
297298

298299
case SDL_EventType.SDL_EVENT_DID_ENTER_BACKGROUND:
@@ -306,7 +307,22 @@ protected virtual void HandleEventFromFilter(SDL_Event evt)
306307
case SDL_EventType.SDL_EVENT_LOW_MEMORY:
307308
LowOnMemory?.Invoke();
308309
break;
310+
311+
case SDL_EventType.SDL_EVENT_MOUSE_MOTION:
312+
handleMouseMotionEvent(e.motion);
313+
return false;
314+
315+
case SDL_EventType.SDL_EVENT_MOUSE_BUTTON_DOWN:
316+
case SDL_EventType.SDL_EVENT_MOUSE_BUTTON_UP:
317+
handleMouseButtonEvent(e.button);
318+
return false;
319+
320+
case SDL_EventType.SDL_EVENT_MOUSE_WHEEL:
321+
handleMouseWheelEvent(e.wheel);
322+
return false;
309323
}
324+
325+
return true;
310326
}
311327

312328
protected void HandleEventFromWatch(SDL_Event evt)
@@ -327,7 +343,7 @@ private static SDLBool eventFilter(IntPtr userdata, SDL_Event* eventPtr)
327343
{
328344
var handle = new ObjectHandle<SDL3Window>(userdata);
329345
if (handle.GetTarget(out SDL3Window window))
330-
window.HandleEventFromFilter(*eventPtr);
346+
return window.HandleEventFromFilter(*eventPtr);
331347

332348
return true;
333349
}
@@ -514,19 +530,6 @@ protected virtual void HandleEvent(SDL_Event e)
514530
handleKeymapChangedEvent();
515531
break;
516532

517-
case SDL_EventType.SDL_EVENT_MOUSE_MOTION:
518-
handleMouseMotionEvent(e.motion);
519-
break;
520-
521-
case SDL_EventType.SDL_EVENT_MOUSE_BUTTON_DOWN:
522-
case SDL_EventType.SDL_EVENT_MOUSE_BUTTON_UP:
523-
handleMouseButtonEvent(e.button);
524-
break;
525-
526-
case SDL_EventType.SDL_EVENT_MOUSE_WHEEL:
527-
handleMouseWheelEvent(e.wheel);
528-
break;
529-
530533
case SDL_EventType.SDL_EVENT_JOYSTICK_AXIS_MOTION:
531534
handleJoyAxisEvent(e.jaxis);
532535
break;

osu.Framework/Platform/SDL3/SDL3Window_Input.cs

+17-8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Diagnostics;
77
using System.Drawing;
8+
using System.Threading;
89
using osu.Framework.Bindables;
910
using osu.Framework.Configuration;
1011
using osu.Framework.Extensions.EnumExtensions;
@@ -151,11 +152,12 @@ private void enqueueJoystickButtonInput(JoystickButton button, bool isPressed)
151152

152153
private PointF previousPolledPoint = PointF.Empty;
153154

154-
private SDL_MouseButtonFlags pressedButtons;
155+
private volatile uint pressedButtons;
155156

156157
private void pollMouse()
157158
{
158159
float x, y;
160+
var pressed = (SDL_MouseButtonFlags)pressedButtons;
159161
SDL_MouseButtonFlags globalButtons = SDL_GetGlobalMouseState(&x, &y);
160162

161163
if (previousPolledPoint.X != x || previousPolledPoint.Y != y)
@@ -170,18 +172,18 @@ private void pollMouse()
170172
}
171173

172174
// a button should be released if it was pressed and its current global state differs (its bit in globalButtons is set to 0)
173-
SDL_MouseButtonFlags buttonsToRelease = pressedButtons & (globalButtons ^ pressedButtons);
175+
SDL_MouseButtonFlags buttonsToRelease = pressed & (globalButtons ^ pressed);
174176

175177
// the outer if just optimises for the common case that there are no buttons to release.
176178
if (buttonsToRelease != 0)
177179
{
180+
Interlocked.And(ref pressedButtons, (uint)~buttonsToRelease);
181+
178182
if (buttonsToRelease.HasFlagFast(SDL_MouseButtonFlags.SDL_BUTTON_LMASK)) MouseUp?.Invoke(MouseButton.Left);
179183
if (buttonsToRelease.HasFlagFast(SDL_MouseButtonFlags.SDL_BUTTON_MMASK)) MouseUp?.Invoke(MouseButton.Middle);
180184
if (buttonsToRelease.HasFlagFast(SDL_MouseButtonFlags.SDL_BUTTON_RMASK)) MouseUp?.Invoke(MouseButton.Right);
181185
if (buttonsToRelease.HasFlagFast(SDL_MouseButtonFlags.SDL_BUTTON_X1MASK)) MouseUp?.Invoke(MouseButton.Button1);
182186
if (buttonsToRelease.HasFlagFast(SDL_MouseButtonFlags.SDL_BUTTON_X2MASK)) MouseUp?.Invoke(MouseButton.Button2);
183-
184-
pressedButtons &= ~buttonsToRelease;
185187
}
186188
}
187189

@@ -440,10 +442,17 @@ private void handleMouseWheelEvent(SDL_MouseWheelEvent evtWheel)
440442
{
441443
bool isPrecise(float f) => f % 1 != 0;
442444

445+
bool precise;
446+
443447
if (isPrecise(evtWheel.x) || isPrecise(evtWheel.y))
448+
{
449+
precise = true;
444450
lastPreciseScroll = evtWheel.timestamp;
445-
446-
bool precise = evtWheel.timestamp < lastPreciseScroll + precise_scroll_debounce;
451+
}
452+
else
453+
{
454+
precise = evtWheel.timestamp < lastPreciseScroll + precise_scroll_debounce;
455+
}
447456

448457
// SDL reports horizontal scroll opposite of what framework expects (in non-"natural" mode, scrolling to the right gives positive deltas while we want negative).
449458
TriggerMouseWheel(new Vector2(-evtWheel.x, evtWheel.y), precise);
@@ -458,12 +467,12 @@ private void handleMouseButtonEvent(SDL_MouseButtonEvent evtButton)
458467
switch (evtButton.type)
459468
{
460469
case SDL_EventType.SDL_EVENT_MOUSE_BUTTON_DOWN:
461-
pressedButtons |= mask;
462470
MouseDown?.Invoke(button);
471+
Interlocked.Or(ref pressedButtons, (uint)mask);
463472
break;
464473

465474
case SDL_EventType.SDL_EVENT_MOUSE_BUTTON_UP:
466-
pressedButtons &= ~mask;
475+
Interlocked.And(ref pressedButtons, (uint)~mask);
467476
MouseUp?.Invoke(button);
468477
break;
469478
}

osu.Framework/Platform/Windows/SDL3WindowsWindow.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,16 @@ public override void Create()
6060
Native.Input.SetWindowFeedbackSetting(WindowHandle, feedbackType, false);
6161
}
6262

63-
protected override void HandleEventFromFilter(SDL_Event evt)
63+
protected override bool HandleEventFromFilter(SDL_Event e)
6464
{
65-
switch (evt.Type)
65+
switch (e.Type)
6666
{
6767
case SDL_EventType.SDL_EVENT_WINDOW_FOCUS_LOST:
6868
warpCursorFromFocusLoss();
6969
break;
7070
}
7171

72-
base.HandleEventFromFilter(evt);
72+
return base.HandleEventFromFilter(e);
7373
}
7474

7575
public Vector2? LastMousePosition { get; set; }

0 commit comments

Comments
 (0)