Smearing on os x


#1

I have a component that is setAlwaysOnTop(true) and fairly regularly it moves itself.

If I get the cpu usage high (just moving the mouse over other components really fast so they need to repait a lot is enough) then the moving component fails to erase itself as it moves. (Or more likely, the components underneath are not getting their repaint message)

This only happens on Mac OS, not windows.


#2

Nasty. I expect that it’s not the cpu that’s the factor, but rather that there are lots of separate areas being told to repaint at the same time.

One quick idea, looking at the mac code, is that it might be a floating point rounding error. The HIView repainting is all done in floating point co-ords, and a quick way to test it would be to increase the area in juce_mac_Windowing.cpp, line 710, just by adding a pixel, e.g.

r.origin.x = x - 1; r.origin.y = y - 1; r.size.width = w + 2; r.size.height = h + 2;

If that sorts it out, then we can try some more elegant rounding on the numbers.


#3

I’m compiling for 10.3, so I changed it just above the line you mentioned. No difference.

I have a work around, after the Component moves, get repaint the parent about 5 pixels around the Component. Seems to work for now.

I have a deadline coming up, so I’m pretty busy, so that’ll have to do for now. I’ll look into it more in the future.


#4

It’s not a rounding error, it seems as if every once and a while a repaint message gets completely lost.

I’m using the JUCE_ENABLE_REPAINT_DEBUGGING and I’m not seeing any coloured rectangles appear when an artifact is left behind.


#5

Hmm. That’s bad news because it’s Apple code that manages the paint region. They might have a bug, or maybe some limit on the number of rectangles before it starts ignoring them? I guess the only way to find out would be to make it reproducable, but that’s not easy.


#6

Ok, so I think the problem is calling repaint from inside paint, which in this thread (http://www.rawmaterialsoftware.com/juceforum/viewtopic.php?t=875&highlight=paint+repaint), you determined was bad.

So I added a assertion to test for it and it’s getting hit from within juce code.

void TreeViewContentComponent::paint (Graphics& g) { if (owner->rootItem != 0) { owner->handleAsyncUpdate();

causes repaints and components to be resized. I assume resizing in a paint is also bad news. [/url]


#7

Hmm. Yes, resizing a component from within a paint() would call repaint() indirectly. Seems like the mac must be clearing the dirty region list at the end of the paint callback, and losing any new regions that were added.

I think it might actually be better to say that repaint() is ok in a paint() callback, and to fix the mac implementation so that it works. I’m not on my mac at the moment, but how about this little change to the order in the mac ComponentPeer:

[code] if (context.reduceClipRegion (regionsNeedingRepaint))
{
regionsNeedingRepaint.clear();

                if (! peer->getComponent()->isOpaque())
                {
                    for (RectangleList::Iterator i (*context.getRawClipRegion()); i.next();)
                    {
                        const Rectangle& r = i.getRectangle();
                        image->clear (r.getX(), r.getY(), r.getWidth(), r.getHeight());
                    }
                }

                regionsNeedingRepaint.clear();
                peer->clearMaskedRegion();
                peer->handlePaint (context);
            }
            else
            {
                regionsNeedingRepaint.clear();
            }

[/code]


#8

that seems to have fixed it, thanks

i’ll need to do more testing to say for sure if it is fixed


#9

Cool. Fingers crossed…


#10

didn’t fix it, I’m just going to avoid calling repaint in the paint


#11