DeltaY in MouseWheel Event OSX

On OSX I am using the DeltaY argument in the MouseWheel event to move graphics in a canvas up and down. I note that the rate of movement is not the same as other OS applications such as if i go into iCal and scroll up and down, the graphics displacement for the same mouse wheel (trackpad swipe) is much greater. I have already tried moving my graphics by 2DeltaY and 3DeltaY etc but then I just get a nasty looking juddery scroll due to the 3 pixel jump for every DeltaY.

Any tips?

You could try to organize the 3 pixels jump in a loop of three times 1 pixels, instead of skipping two. The speed would be the same, but cinematics could be smoother.

I see the concept but it would be a nightmare to calculate, bare in mind that the MouseWheel event has inertia, deceleration and acceleration so to get it consistent my loop of 3 x 1 pixel would need to be timed appropriately with the current rate of mouse wheel events i.e. 3 x 1pixel movements between 2 mouse wheel events or at least 2 events with deltaY > 0

What I meant is this : jumps are jittery. Instead of a jump, do deltaY several times in a raw. In effect you get the same displacement, but in smaller increments, resulting in a smoother animation. I just tried and it seems convincing.

Function MouseWheel(X As Integer, Y As Integer, deltaX as Integer, deltaY as Integer) As Boolean for i as integer = 0 to 4 Xscroll = xscroll+deltax yscroll = yscroll+deltay me.scroll(deltax, deltay) next End Function

As far as I can tell, the inertia does not manifest with the regular deltaY value in the MouseWheel event.

See https://forum.xojo.com/3803-mousewheel-scroll-that-feels-native for an interesting discussion about that not long ago.

It definitely does. I can scroll fast, let go and my canvas decelerates.

  Dim CorrectX As Single = DeltaX
  Dim CorrectY As Single = DeltaY
  Dim UsesPixelDeltas As Boolean
  
  #if TargetCocoa
    Try
      Declare Function objc_getClass Lib "Cocoa.framework" (aClassName As CString) As Ptr
      Declare Function sel_registerName Lib "/usr/lib/libobjc.dylib" (Name As CString) As Ptr
      Declare Function GetSharedApplication Lib "Cocoa.framework" Selector "sharedApplication" (Target As Ptr) As Ptr
      Declare Function GetCurrentEvent Lib "Cocoa.framework" Selector "currentEvent" (Target As Ptr) As Ptr
      Declare Function RespondsToSelector Lib "Cocoa.framework" Selector "respondsToSelector:" (Target As Ptr, Sel As Ptr) As Boolean
      Declare Function HasPreciseScrollingDeltas Lib "Cocoa.framework" Selector "hasPreciseScrollingDeltas" (Target As Ptr) As Boolean
      Declare Function ScrollingDeltaX Lib "Cocoa.framework" Selector "scrollingDeltaX" (Target As Ptr) As Single
      Declare Function ScrollingDeltaY Lib "Cocoa.framework" Selector "scrollingDeltaY" (Target As Ptr) As Single
      
      Dim NSApplication As Ptr = objc_getClass("NSApplication")
      If NSApplication <> Nil Then
        Dim SharedApplication As Ptr = GetSharedApplication(NSApplication)
        If SharedApplication <> Nil Then
          Dim EventObject As Ptr = GetCurrentEvent(SharedApplication)
          If EventObject <> Nil Then
            If RespondsToSelector(EventObject,sel_registerName("hasPreciseScrollingDeltas")) Then
              UsesPixelDeltas = HasPreciseScrollingDeltas(EventObject)
              CorrectX = ScrollingDeltaX(EventObject) * -1
              CorrectY = ScrollingDeltaY(EventObject) * -1
            End If
          End If
        End If
      End If
    Catch Err As RuntimeException
      UsesPixelDeltas = False
      CorrectX = DeltaX * -1
      CorrectY = DeltaY * -1
    End Try
  #endif
  
  me.Value = me.Value + (CorrectY) - (CorrectX)

The example above is what you need.

I believe it’s the same that I got from Thom McGrath: https://forum.xojo.com/10413-canvas-mousewheel-and-native-feeling-delta/p1#p74418

There’s also feedback://showreport?report_id=32886

Do you guys have any ideas on how to control the bounds of this mousewheel declares? When I have tried it looks really bad (flickers and bounces unnaturally).

Thanks!

What do you mean by bounds? MouseWheel is just a delta vector.

If you mean a bounce like Safari does when content is scrolled past the very top or bottom that’s accomplished with an NSScrollView with elasticity true. A ScrollView can do this because it has a document view whose bounds are tracked so it knows where edges are that need to be elastically bounced back.

This doesn’t explain flickering though, or an unnatural bounce. Can you show some code or explain more what you’re doing?

I have nested containers and I did try NSScrollView unsuccessfully.

My code in the mousewheel (which doesn’t give me what I want naturally) is

  #Pragma DisableBackgroundTasks
  #Pragma DisableBoundsChecking
  
  Dim CorrectX As Single = DeltaX
  Dim CorrectY As Single = DeltaY
  Dim UsesPixelDeltas As Boolean
  
  Try
    Declare Function objc_getClass Lib "Cocoa.framework" (aClassName As CString) As Ptr
    Declare Function sel_registerName Lib "/usr/lib/libobjc.dylib" (Name As CString) As Ptr
    Declare Function GetSharedApplication Lib "Cocoa.framework" Selector "sharedApplication" (Target As Ptr) As Ptr
    Declare Function GetCurrentEvent Lib "Cocoa.framework" Selector "currentEvent" (Target As Ptr) As Ptr
    Declare Function RespondsToSelector Lib "Cocoa.framework" Selector "respondsToSelector:" (Target As Ptr, Sel As Ptr) As Boolean
    Declare Function HasPreciseScrollingDeltas Lib "Cocoa.framework" Selector "hasPreciseScrollingDeltas" (Target As Ptr) As Boolean
    Declare Function ScrollingDeltaX Lib "Cocoa.framework" Selector "scrollingDeltaX" (Target As Ptr) As Single
    Declare Function ScrollingDeltaY Lib "Cocoa.framework" Selector "scrollingDeltaY" (Target As Ptr) As Single
    
    Dim NSApplication As Ptr = objc_getClass("NSApplication")
    If NSApplication <> Nil Then
      Dim SharedApplication As Ptr = GetSharedApplication(NSApplication)
      If SharedApplication <> Nil Then
        Dim EventObject As Ptr = GetCurrentEvent(SharedApplication)
        If EventObject <> Nil Then
          If RespondsToSelector(EventObject,sel_registerName("hasPreciseScrollingDeltas")) Then
            UsesPixelDeltas = HasPreciseScrollingDeltas(EventObject)
            CorrectX = ScrollingDeltaX(EventObject) * -1
            CorrectY = ScrollingDeltaY(EventObject) * -1
          End If
        End If
      End If
    End If
  Catch Err As RuntimeException
    UsesPixelDeltas = False
    CorrectX = DeltaX * -1
    CorrectY = DeltaY * -1
  End Try
  
  Me.ScrollValX = CorrectX
  Me.ScrollValY = CorrectY
  
  ScrollimageTop = ScrollimageTop - ScrollValY
  ScrollimageLeft = ScrollimageLeft - ScrollValX
  
  // CONTROL SCROLLING BOUNDS TOP
  Dim thisConnectedDevice as Common_Module.ConnectedDevice_Class = Common_Module.ConnectedDeviceClassArray(AristaEAPI_Window.SelectedIndexID)
  Dim thisSelectedReport as Integer = thisConnectedDevice.FeatureContainerView_ReportCenter.SelectedReportIndexID_DeviceProfileReport
  Dim theReportContainerArray() as DeviceProfileReportContainer = Common_Module.ConnectedDeviceClassArray(AristaEAPI_Window.SelectedIndexID).FeatureContainerView_ReportCenter.DeviceProfileReportContainerArray()
  Dim totalNumPages as Integer = theReportContainerArray(thisSelectedReport).CreateReportClass.pageNumStart
  Dim thisTopLimit as Integer = (totalNumPages -2) * -1240
  
  // CONTROL SCROLL BOTTOM BOUNDS
  If ScrollimageTop <= thisTopLimit Then
    ScrollimageTop = thisTopLimit + 1
  End If
  // CONTROL SCROLL TOP BOUNDS
  If ScrollimageTop >= 10 Then
    ScrollimageTop = 9
  End If
  
  // CONTROL SCROLL LEFT BOUNDS
  If ScrollimageLeft >= 10 Then
    ScrollimageLeft = 9
  End If
  
  // CONTROL SCROLL RIGHT BOUNDS
  Dim RightBoundary as Integer = Me.Left + Me.Width
  If ScrollimageLeft <= RightBoundary  Then
    ScrollimageLeft = 9
  End If
  Me.Invalidate(False)

I didn’t study at your code, but just used a part of it, and looked what happened:

[code] Dim CorrectX As Single = DeltaX
Dim CorrectY As Single = DeltaY
Dim UsesPixelDeltas As Boolean

Try
Declare Function objc_getClass Lib “Cocoa.framework” (aClassName As CString) As Ptr
Declare Function sel_registerName Lib “/usr/lib/libobjc.dylib” (Name As CString) As Ptr
Declare Function GetSharedApplication Lib “Cocoa.framework” Selector “sharedApplication” (Target As Ptr) As Ptr
Declare Function GetCurrentEvent Lib “Cocoa.framework” Selector “currentEvent” (Target As Ptr) As Ptr
Declare Function RespondsToSelector Lib “Cocoa.framework” Selector “respondsToSelector:” (Target As Ptr, Sel As Ptr) As Boolean
Declare Function HasPreciseScrollingDeltas Lib “Cocoa.framework” Selector “hasPreciseScrollingDeltas” (Target As Ptr) As Boolean
Declare Function ScrollingDeltaX Lib “Cocoa.framework” Selector “scrollingDeltaX” (Target As Ptr) As Single
Declare Function ScrollingDeltaY Lib “Cocoa.framework” Selector “scrollingDeltaY” (Target As Ptr) As Single

Dim NSApplication As Ptr = objc_getClass("NSApplication")
If NSApplication <> Nil Then
  Dim SharedApplication As Ptr = GetSharedApplication(NSApplication)
  If SharedApplication <> Nil Then
    Dim EventObject As Ptr = GetCurrentEvent(SharedApplication)
    If EventObject <> Nil Then
      If RespondsToSelector(EventObject,sel_registerName("hasPreciseScrollingDeltas")) Then
        UsesPixelDeltas = HasPreciseScrollingDeltas(EventObject)
        CorrectX = ScrollingDeltaX(EventObject) * -1
        CorrectY = ScrollingDeltaY(EventObject) * -1
      End If
    End If
  End If
End If

Catch Err As RuntimeException
UsesPixelDeltas = False
CorrectX = DeltaX * -1
CorrectY = DeltaY * -1
End Try

Self.x = Self.x - CorrectX
Self.y = Self.y - CorrectY

Me.Invalidate()

Return True[/code]
In the Paint event of the canvas I did put this:

  g.DrawPicture(Pic, x, y)

… and in the Constructor of the windows this code:

Super.Constructor() pic = New Picture(100, 100, 32) pic.Graphics.DrawOval(0, 0, pic.Graphics.Width, pic.Graphics.Height)
The window also has to properties x and y.

Works.