A game framework written with osu! in mind.
at master 62 lines 2.9 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2// See the LICENCE file in the repository root for full licence text. 3 4using System; 5using osu.Framework.Platform.MacOS.Native; 6using osuTK; 7 8namespace osu.Framework.Platform.MacOS 9{ 10 /// <summary> 11 /// macOS-specific subclass of <see cref="SDL2DesktopWindow"/>. 12 /// </summary> 13 public class MacOSWindow : SDL2DesktopWindow 14 { 15 private static readonly IntPtr sel_hasprecisescrollingdeltas = Selector.Get("hasPreciseScrollingDeltas"); 16 private static readonly IntPtr sel_scrollingdeltax = Selector.Get("scrollingDeltaX"); 17 private static readonly IntPtr sel_scrollingdeltay = Selector.Get("scrollingDeltaY"); 18 private static readonly IntPtr sel_respondstoselector_ = Selector.Get("respondsToSelector:"); 19 20 private delegate void ScrollWheelDelegate(IntPtr handle, IntPtr selector, IntPtr theEvent); // v@:@ 21 22 private IntPtr originalScrollWheel; 23 private ScrollWheelDelegate scrollWheelHandler; 24 25 public override void Create() 26 { 27 base.Create(); 28 29 // replace [SDLView scrollWheel:(NSEvent *)] with our own version 30 var viewClass = Class.Get("SDLView"); 31 scrollWheelHandler = scrollWheel; 32 originalScrollWheel = Class.SwizzleMethod(viewClass, "scrollWheel:", "v@:@", scrollWheelHandler); 33 } 34 35 /// <summary> 36 /// Swizzled replacement of [SDLView scrollWheel:(NSEvent *)] that checks for precise scrolling deltas. 37 /// </summary> 38 private void scrollWheel(IntPtr receiver, IntPtr selector, IntPtr theEvent) 39 { 40 var hasPrecise = Cocoa.SendBool(theEvent, sel_respondstoselector_, sel_hasprecisescrollingdeltas) && 41 Cocoa.SendBool(theEvent, sel_hasprecisescrollingdeltas); 42 43 if (!hasPrecise) 44 { 45 // calls the unswizzled [SDLView scrollWheel:(NSEvent *)] method if this is a regular scroll wheel event 46 // the receiver may sometimes not be SDLView, ensure it has a scroll wheel selector implemented before attempting to call. 47 if (Cocoa.SendBool(receiver, sel_respondstoselector_, originalScrollWheel)) 48 Cocoa.SendVoid(receiver, originalScrollWheel, theEvent); 49 50 return; 51 } 52 53 // according to osuTK, 0.1f is the scaling factor expected to be returned by CGEventSourceGetPixelsPerLine 54 const float scale_factor = 0.1f; 55 56 float scrollingDeltaX = Cocoa.SendFloat(theEvent, sel_scrollingdeltax); 57 float scrollingDeltaY = Cocoa.SendFloat(theEvent, sel_scrollingdeltay); 58 59 ScheduleEvent(() => TriggerMouseWheel(new Vector2(scrollingDeltaX * scale_factor, scrollingDeltaY * scale_factor), true)); 60 } 61 } 62}