Ruby API - Events Suspend / Resume not fired on Mac when mouse-wheeling

Just discovered that, on MAC OSX, a Sketchup::Tool does not receive the Suspend and Resume events when the user rolls the mouse wheel in the viewport (typically for zooming).

On Windows, these events fire normally.

To Mac Developers: can you please confirm.

Apparently another difference between Windows and OSX, but not sure it is documented.

I have never set them as I could never gauge any ill effect when I didn’t…

are you seeing issues without it?

I’ll test if you have a snippet…


Like John, I’ve never implemented them because I didn’t think zoom or orbit would have any effect on the action of my tools. I’ll play around a bit tomorrow and see what I experience.

Just a note that Sketchup::ViewObserver#onViewChanged should fire in for both platforms.

(I agree however that it is desirable that the Tool callbacks should act the same on both platforms.)

That’s why I signal it.

Note that Sketchup::ViewObserver#onViewChanged behaves differently, because

  • it fires AFTER the view is changed and refreshed in the display. Cancelling the zoom causes therefore a flickering.
  • It fires continuously while zooming, whereas on Windows you get one suspend event and then one resume event
  • It is based on an Observer, prone to issues, crashes and side-effects
1 Like

I always use resume to reset the statusbar text, vcb label and vcb value after being interrupted by e.g. Orbit or Pan. Both these tools replaces these values.

Since mouse wheel scrolling doesn’t really activate a tool, just moves the camera in one go, I’m not sure why it should ever fire these methods. What are you using them for?

I use it for scrolling the timeline in Animator. So, at resume(), It checks if it was a scrolling within the timeline, and if so, does the timeline scrolling and cancel the viewport zoom. Suspend() is fired BEFORE the view is refreshed.

The Observer onViewChanged() is fired AFTER the view is refreshed. Therefore, it creates a flickering effect if I cancel the viewport zoom.

1 Like

okay, I see.

I would advise against trying to hijack the mouse wheel in a way the API doesn’t intend for. While it works today (one one platform) SketchUp could very well be updated in a way that breaks this. Maybe resume and suspend will be called after moving the camera as a result of some future optimization. Maybe they wont be called at all from wheel scroll, as the tool never really gets interrupted.

Using API hooks in a way they weren’t intended to be used is always a bit dangerous. If the API docs doesn’t sanction a specific way of using the API, chances are the SketchUp team have no idea the API can be used that way, and don’t take it into account when updating SketchUp.

What I would recommend now is:

  1. Write up an API feature request for having a proper way to detect mouse scroll. For instance the Tool interface could have an onScrollWheel(x, y, direction, view) method, where the boolean return value tells SketchUp whether to zoom as usual, or abort. The return value for onKeyDown is already used this way (although ironically not mentioned in the documentation…). With this you could simply check if the mouse is within the timeline area, and let that decide whether the scroll event propagates, or whether you use it to scroll your own content.

  2. Write a comment in your code saying the current implementation is something of a hack, stating where it works and where it doesn’t, and add a reference to the feature request. This helps when you or some other developer needs to understand this code in the future.

  3. Implement a secondary way to scroll that works without hacks or undocumented API use. For instance holding down the mouse over the timeline and drag it could be used. This doesn’t mean you have to remove the mouse wheel support on Windows, just add a separate safer way to achieve the same goal that also can be used.

Hope this helps!

it actually calls the view.invalidate on each ‘notch’ of the scroll wheel…

so if you have code that’s wrapped in the draw method it runs as you scroll…

and if you use this, thinking it will only fire on click…

    # Each click on the left button invokes view.invalidate which, in turn, calls  draw.
    def onLButtonDown(flags, x, y, view)

the tools draw actions get called as you zoom…

you can see this using the SU v5 viewtooltests.rb, so it’s always done this…

or is this a ‘mac only’ thing as well?


It has to invalidate the view as it moves the camera. Otherwise things drawn to the view by the plugin wouldn’t match the new view. If I’m not mistaken this isn’t specifically connected to the mouse wheel, but the camera move itself.

There is already an alternative way covering all functions for both Mac and Windows. So scrolling with the mouse wheel is just a convenience. It won’t be supported for Mac users.

If the Api changes in future versions of SketchUp, and no alternative way is available, then, too bad, the convenience will be stopped.

I posted here in this forum to get confirmation from MAC developers and also feedback from the SketchUp team if ever they read the post.

Then it will be time to formulate a feature request. Your proposal of onMouseWheel would be perfect.

This being said, I would not count too much on an implementation, based on my experience of past FR still pending after many years (like asking to control the visibility of The Material Inspector, having bulk methods to change materials and edge properties and a few others)

That’s good!

I’ve had success getting new API functionality added. I think the extensibility team is extra keen on adding something if it would be a proper alterative to a hack or using the API in a way it wan’t intended. It’s in everyone’s interest to use more stable implementations.


The goal is to be able to CANCEL the viewport zoom before the view is refreshed when the mouse wheel is used for scrolling the timeline.

In draw(), as in onViewChanged(), this is already too late. You get a flickering effect if you cancel the zoom after refresh.

Fredo, In answer to your first question, first…

this is what is ‘said’ to happen on both platforms…

        ## JB: this is meant to happen
        # Called when I double-click middle mouse button (exits out of orbit)
        ## JB: this is what happens
        #Called when I release the middle mouse button (exits out of orbit)
        def resume(view)   
                puts "resume called >> #{view.last_refresh_time}"

        # Called when I press middle mouse button (goes into orbit)
        def suspend(view)                
                puts "suspend called >> #{view.last_refresh_time}"

‘scroll wheel’ clicks/notches behave the same as mouse clicks and do not call :suspend or :resume

other than using a bin script to ‘prevent_default’, I can’t see a way of canceling zoom in the viewport on a mac…

I’ll see ifI have one for that already…


I agree. It never hurts to ask.


:getExtents seems to trigger ‘zoom’ so…

another thought is roll your own ‘hack’…

not sure it helps you, but it does stop zooming when the tool is active…

    # revert the zoom event
    def prevent_default
       # undocumented? send_action
       Sketchup.send_action('viewUndo:') unless @left_button_down
       puts "add your call here??"
		def getExtents

    def onLButtonDown(flags, x, y, view)
      @left_button_down = true

Thanks for this idea. It seems to work fine on Windows. I’ll need to have it tested on Mac.

But if it works, that would be a super-hack of the API (by Christina‘s standards) :slight_smile:


1 Like

Only 50% hackier than resume/suspend :stuck_out_tongue: .

Hacks can to be used. However you should be aware when you use one and why. Also, the less hacks you use, the less work you need to spend updating extension when SU updates.

it stops the zoom, but also you loose the :draw content, is that an issue??



Your suggestion of super hack happens to work well on Mac. It also works on Windows.

Thinking about it, it may even be more natural, because it does not depend on the fact that, in the current implementation of Sketchup, Zoom, Orbit, Pan generate a Suspend and Resume. So, it may be a better mechanism.

Thanks so much for the idea.


PS: The implementation in Animator is different from the one you made in your test tool, so I don’t get any side effect… I had already the code which I used in Suspend / Resume. The key point was simply to put this code in the getExtents events instead.

1 Like