Setting a waveform sample position in a timerCallback causes flickering

Please?

We 100% know what’s going on.

We’ve gone to a lot of effort to explain it in detail, again and again, in this thread.

It has nothing at all to do with double-buffering.

So why are you asking about the double-buffering? Do you not think I know what I’m talking about?

I have NEVER seen missing objects on a back buffer swap or splat, OK you may get the odd ‘tearing’ or ‘shearing’ due to the scan line but never anything missing, it’s impossible because the object will always be there.

That’s right.
Like I said, double-buffering has nothing whatsoever to do with this problem.

Yes, a problem. Oh well, never mind.

For me at 60 Hz the needle becomes entirely invisible, apart from a few brief flashes. I think it has to do with the screen refresh rate (which would explain why switching the screen resolution affected the issue. Probably the refresh rate changed from 30 Hz to 60 Hz).

Random weird observation #1: When I take a screenshot with Alt + Print Screen the needle will show up in my screenshot every time.

Random weird observation #2: If I drag the window, the problem goes away as long as I’m actually moving.

I’ve seen a similar thing in our app. Mouse drag events come in at exactly the refresh rate which triggers this bug, so animations triggered by mouse drags are affected very badly. This issue can be reproduced by dragging the “Drag me” box in the Animation pane in the JuceDemo, if you drag it the yellow edge of the box will disappear.

But bottom line, this appears to be weird behaviour of the Win32 API, and it appears we just have to accept it and work around it by repainting slightly larger areas.

Yes, I’m afraid so.

We can be a bit more precise about what’s going on - what I suspect is happening is that if there’s already a WM_PAINT message waiting to be delivered on the event queue, and then the Timer callback happens, which moves the component along and invalidates its new position, this newly invalidated area doesn’t get added to the dirty region which the already-pending WM_PAINT will draw. Instead it just gets sent as another WM_PAINT message that will come later. So if things stay still for long enough, everything will always end up correctly painted. But in these cases where something is moving at the same rate as the repaint, you can get out of sync so that WM_PAINT is “chasing” you, but where it’s always just painting the last region.

I’ve written dirty rectangle invalidation systems for openGL and other platforms like Android and Linux, and have made sure they don’t suffer from the same problem, but on Windows it’s best to use the native win32 invalidation system so that the app interoperates better with the system.

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CocoaDrawingGuide/GraphicsContexts/GraphicsContexts.html
“Important: Because most OS X windows are already double-buffered, do not use offscreen windows or bitmaps simply to update the contents of a window. Doing so wastes memory (by adding a third buffer) and requires an extra copy operation to transfer the bits from the offscreen window to the window buffer.”

@DaveH Your posts have been getting increasingly tangential… Apart from the fact that “duh, yes, we know”, this is so far removed from being relevant to anything on this thread that it’s almost like you posted a random quote.

I think it’s time for me to lock this topic for your own good. Make your repaint area bigger like I suggested in my first reply, go get some rest, and work on something more important in your app.

If you’re still bewildered by what’s going on, Ed and I have explained in great detail exactly what’s going on, and you can re-read our posts. I’m sorry if for some reason you still can’t understand it, but we tried our best. There’s nothing else we could add here that we haven’t already said about 10 times.