vstgui
vstgui copied to clipboard
CSplashScreen not showing when embedded into CLayeredViewContainer
CSplashScreens that are embedded into CLayeredViewContainers don't show on splash() when running on Mac Cocoa.
So, here's am minimal code example that implements an eyedropper that shows the pixel color under the mouse cursor. The code works fine unless we embed that view in a CLayeredViewContainer on Mac, pa->getColor(color); always returns black in that case. On Windows it works either way which implies that it has something to do with the CALayer based implementation.
I'm aware that the backround graphic could be accessed directly, but imagine the CEyedropperView ::drawRect() implementation could draw anything.
class CEyedropperView : public CView
{
public:
CEyedropperView(const CRect &size, CFrame *parent, CBitmap *hBackround) : CView(size)
{
setBackground(hBackround);
oc = COffscreenContext::create(parent, getWidth(), getHeight());
}
virtual void drawRect(CDrawContext *pContext, const CRect& updateRect) override
{
// Draw contents to COffscreenContext.
if(oc)
{
oc->beginDraw();
CView::drawRect(oc, updateRect);
oc->endDraw();
}
// NOTE: We could simply use oc->copyFrom() here so stuff doesn't need
// to be drawn twice, but that would also require oc to be oversampled
// for HighDPI / Retina displays. That doesn't have anything to do with
// the issue itself though
CView::drawRect(pContext, updateRect);
// Draw eyedropper: The oc's bitmap is used to retrieve the pixel values
// under the mouse cursor
if(oc && eyedropperActive)
{
auto pa = VSTGUI::owned(CBitmapPixelAccess::create(oc->getBitmap()));
if(pa)
{
CColor color;
pa->setPosition(uint32_t(lastMousePoint.x), uint32_t(lastMousePoint.y));
pa->getColor(color);
CRect rect(-15.0, -15.0, +15.0, +15.0);
rect.offset(lastMousePoint);
pContext->setDrawMode(kAntiAliasing);
pContext->setLineWidth(2.0);
pContext->setFrameColor(kWhiteCColor);
pContext->setFillColor(color);
pContext->drawEllipse(rect, kDrawFilledAndStroked);
}
}
}
// Keep track of mouse cursor position
virtual CMouseEventResult onMouseMoved(CPoint& where, const CButtonState& buttons) override
{
if(where != lastMousePoint)
{
lastMousePoint = where;
invalid();
}
return CView::onMouseMoved(where, buttons);
}
virtual CMouseEventResult onMouseEntered(CPoint& where, const CButtonState& buttons) override
{
if(getFrame())
getFrame()->setCursor(kCursorHand);
eyedropperActive = true;
invalid();
return kMouseEventHandled;
}
virtual CMouseEventResult onMouseExited(CPoint& where, const CButtonState& buttons) override
{
if(getFrame())
getFrame()->setCursor(kCursorDefault);
eyedropperActive = false;
invalid();
return kMouseEventHandled;
}
CLASS_METHODS(CEyedropperView, CView);
protected:
SharedPointer<COffscreenContext> oc;
CPoint lastMousePoint;
bool eyedropperActive{false};
};
OK, now I understand the issue. The problem is, that CLayeredViewContainers are an optimization and are not redrawn in a normal way. So you cannot call draw(..) or drawRect(..) on it. That are no-ops. A possible workaround is, to find all instances in your view hierarchy and after you've drawn the normal views, you call drawViewLayer() on that instances (you have to cast to IPlatformViewLayerDelegate before, otherwise the method is protected). You may have to offset the draw context by the top-left position of the view relative to the frame.