summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vcl/inc/quartz/salgdi.h28
-rw-r--r--vcl/inc/skia/osx/gdiimpl.hxx4
-rw-r--r--vcl/osx/salnativewidgets.cxx170
-rw-r--r--vcl/skia/osx/gdiimpl.cxx49
4 files changed, 172 insertions, 79 deletions
diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h
index 8ec68cddcc09..6cedf6f09b29 100644
--- a/vcl/inc/quartz/salgdi.h
+++ b/vcl/inc/quartz/salgdi.h
@@ -269,10 +269,6 @@ struct AquaSharedAttributes
class AquaGraphicsBackendBase
{
-private:
- SalGraphicsImpl* mpImpl = nullptr;
-protected:
- AquaSharedAttributes& mrShared;
public:
AquaGraphicsBackendBase(AquaSharedAttributes& rShared)
: mrShared( rShared )
@@ -286,6 +282,22 @@ public:
return mpImpl;
}
virtual void UpdateGeometryProvider(SalGeometryProvider*) {};
+ virtual bool drawNativeControl(ControlType nType,
+ ControlPart nPart,
+ const tools::Rectangle &rControlRegion,
+ ControlState nState,
+ const ImplControlValue &aValue) = 0;
+protected:
+ static bool performDrawNativeControl(ControlType nType,
+ ControlPart nPart,
+ const tools::Rectangle &rControlRegion,
+ ControlState nState,
+ const ImplControlValue &aValue,
+ CGContextRef context,
+ AquaSalFrame* mpFrame);
+ AquaSharedAttributes& mrShared;
+private:
+ SalGraphicsImpl* mpImpl = nullptr;
};
inline AquaGraphicsBackendBase::~AquaGraphicsBackendBase() {}
@@ -415,6 +427,12 @@ public:
bool implDrawGradient(basegfx::B2DPolyPolygon const& rPolyPolygon,
SalGradient const& rGradient) override;
+ virtual bool drawNativeControl(ControlType nType,
+ ControlPart nPart,
+ const tools::Rectangle &rControlRegion,
+ ControlState nState,
+ const ImplControlValue &aValue) override;
+
bool supportsOperation(OutDevSupportType eType) const override;
};
@@ -549,8 +567,6 @@ public:
GetGraphicsData() const override;
private:
- UInt32 getState( ControlState nState );
- UInt32 getTrackState( ControlState nState );
static bool GetRawFontData( const PhysicalFontFace* pFontData,
std::vector<unsigned char>& rBuffer,
bool* pJustCFF );
diff --git a/vcl/inc/skia/osx/gdiimpl.hxx b/vcl/inc/skia/osx/gdiimpl.hxx
index 2850b92110e6..e42126cfae46 100644
--- a/vcl/inc/skia/osx/gdiimpl.hxx
+++ b/vcl/inc/skia/osx/gdiimpl.hxx
@@ -34,6 +34,10 @@ public:
}
static void prepareSkia();
+ virtual bool drawNativeControl(ControlType nType, ControlPart nPart,
+ const tools::Rectangle& rControlRegion, ControlState nState,
+ const ImplControlValue& aValue) override;
+
private:
virtual void createWindowContext(bool forceRaster = false) override;
virtual void performFlush() override;
diff --git a/vcl/osx/salnativewidgets.cxx b/vcl/osx/salnativewidgets.cxx
index b1d2893aba6c..5988cfe6a9d0 100644
--- a/vcl/osx/salnativewidgets.cxx
+++ b/vcl/osx/salnativewidgets.cxx
@@ -226,14 +226,14 @@ bool AquaSalGraphics::hitTestNativeControl(ControlType nType, ControlPart nPart,
return false;
}
-UInt32 AquaSalGraphics::getState(ControlState nState)
+static UInt32 getState(ControlState nState, AquaSalFrame* mpFrame)
{
// there are non key windows which are children of key windows, e.g. autofilter configuration dialog or sidebar dropdown dialogs.
// To handle these windows correctly, parent frame's key window state is considered here additionally.
- const bool bDrawActive = maShared.mpFrame == nullptr || [maShared.mpFrame->getNSWindow() isKeyWindow]
- || maShared.mpFrame->mpParent == nullptr || [maShared.mpFrame->mpParent->getNSWindow() isKeyWindow];
+ const bool bDrawActive = mpFrame == nullptr || [mpFrame->getNSWindow() isKeyWindow]
+ || mpFrame->mpParent == nullptr || [mpFrame->mpParent->getNSWindow() isKeyWindow];
if (!(nState & ControlState::ENABLED) || !bDrawActive)
{
return kThemeStateInactive;
@@ -243,9 +243,9 @@ UInt32 AquaSalGraphics::getState(ControlState nState)
return kThemeStateActive;
}
-UInt32 AquaSalGraphics::getTrackState(ControlState nState)
+static UInt32 getTrackState(ControlState nState, AquaSalFrame* mpFrame)
{
- const bool bDrawActive = maShared.mpFrame == nullptr || [maShared.mpFrame->getNSWindow() isKeyWindow];
+ const bool bDrawActive = mpFrame == nullptr || [mpFrame->getNSWindow() isKeyWindow];
if (!(nState & ControlState::ENABLED) || !bDrawActive)
return kThemeTrackInactive;
return kThemeTrackActive;
@@ -259,12 +259,54 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
const OUString &,
const Color&)
{
- bool bOK = false;
- if (!maShared.checkContext())
+ return mpBackend->drawNativeControl(nType, nPart, rControlRegion, nState, aValue);
+}
+
+bool AquaGraphicsBackend::drawNativeControl(ControlType nType,
+ ControlPart nPart,
+ const tools::Rectangle &rControlRegion,
+ ControlState nState,
+ const ImplControlValue &aValue)
+{
+ if (!mrShared.checkContext())
return false;
- maShared.maContextHolder.saveState();
+ mrShared.maContextHolder.saveState();
+ bool bOK = performDrawNativeControl( nType, nPart, rControlRegion, nState, aValue,
+ mrShared.maContextHolder.get(), mrShared.mpFrame );
+ mrShared.maContextHolder.restoreState();
+
tools::Rectangle buttonRect = rControlRegion;
- HIRect rc = ImplGetHIRectFromRectangle(buttonRect);
+
+ // in most cases invalidating the whole control region instead of just the unclipped part of it is sufficient (and probably
+ // faster). However for the window background we should not unnecessarily enlarge the really changed rectangle since the
+ // difference is usually quite high. Background is always drawn as a whole since we don't know anything about its possible
+ // contents (see issue i90291).
+
+ if (nType == ControlType::WindowBackground)
+ {
+ CGRect aRect = {{0, 0}, {0, 0}};
+ if (mrShared.mxClipPath)
+ aRect = CGPathGetBoundingBox(mrShared.mxClipPath);
+ if (aRect.size.width != 0 && aRect.size.height != 0)
+ buttonRect.Intersection(tools::Rectangle(Point(static_cast<tools::Long>(aRect.origin.x),
+ static_cast<tools::Long>(aRect.origin.y)),
+ Size(static_cast<tools::Long>(aRect.size.width),
+ static_cast<tools::Long>(aRect.size.height))));
+ }
+ mrShared.refreshRect(buttonRect.Left(), buttonRect.Top(), buttonRect.GetWidth(), buttonRect.GetHeight());
+ return bOK;
+}
+
+bool AquaGraphicsBackendBase::performDrawNativeControl(ControlType nType,
+ ControlPart nPart,
+ const tools::Rectangle &rControlRegion,
+ ControlState nState,
+ const ImplControlValue &aValue,
+ CGContextRef context,
+ AquaSalFrame* mpFrame)
+{
+ bool bOK = false;
+ HIRect rc = ImplGetHIRectFromRectangle(rControlRegion);
switch (nType)
{
case ControlType::Toolbar:
@@ -274,15 +316,15 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
aMenuItemDrawInfo.version = 0;
aMenuItemDrawInfo.state = kThemeMenuActive;
aMenuItemDrawInfo.itemType = kThemeMenuItemHierBackground;
- HIThemeDrawMenuItem(&rc, &rc, &aMenuItemDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawMenuItem(&rc, &rc, &aMenuItemDrawInfo, context, kHIThemeOrientationNormal, nullptr);
#else
if (rControlRegion.Top() == 0 && nPart == ControlPart::DrawBackgroundHorz)
{
- const bool bDrawActive = maShared.mpFrame == nullptr || [maShared.mpFrame->getNSWindow() isKeyWindow];
+ const bool bDrawActive = mpFrame == nullptr || [mpFrame->getNSWindow() isKeyWindow];
CGFloat unifiedHeight = rControlRegion.GetHeight();
CGRect drawRect = CGRectMake(rControlRegion.Left(), rControlRegion.Top(),
rControlRegion.GetWidth(), rControlRegion.GetHeight());
- CUIDraw([NSWindow coreUIRenderer], drawRect, maShared.maContextHolder.get(),
+ CUIDraw([NSWindow coreUIRenderer], drawRect, context,
reinterpret_cast<CFDictionaryRef>([NSDictionary dictionaryWithObjectsAndKeys:
@"kCUIWidgetWindowFrame",
@"widget",
@@ -305,7 +347,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
aMenuItemDrawInfo.version = 0;
aMenuItemDrawInfo.state = kThemeMenuActive;
aMenuItemDrawInfo.itemType = kThemeMenuItemHierBackground;
- HIThemeDrawMenuItem(&rc, &rc, &aMenuItemDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawMenuItem(&rc, &rc, &aMenuItemDrawInfo, context, kHIThemeOrientationNormal, nullptr);
}
#endif
bOK = true;
@@ -315,15 +357,15 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
{
HIThemeBackgroundDrawInfo aThemeBackgroundInfo;
aThemeBackgroundInfo.version = 0;
- aThemeBackgroundInfo.state = getState(nState);
+ aThemeBackgroundInfo.state = getState(nState, mpFrame);
aThemeBackgroundInfo.kind = kThemeBrushDialogBackgroundActive;
// FIXME: without this magical offset there is a 2 pixel black border on the right and bottom
rc.size.width += 2;
rc.size.height += 2;
- HIThemeApplyBackground( &rc, &aThemeBackgroundInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
- CGContextFillRect(maShared.maContextHolder.get(), rc);
+ HIThemeApplyBackground( &rc, &aThemeBackgroundInfo, context, kHIThemeOrientationNormal);
+ CGContextFillRect(context, rc);
bOK = true;
}
break;
@@ -331,12 +373,12 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
{
HIThemeBackgroundDrawInfo aThemeBackgroundInfo;
aThemeBackgroundInfo.version = 0;
- aThemeBackgroundInfo.state = getState(nState);
+ aThemeBackgroundInfo.state = getState(nState, mpFrame);
aThemeBackgroundInfo.kind = kThemeBrushAlertBackgroundActive;
rc.size.width += 2;
rc.size.height += 2;
- HIThemeApplyBackground(&rc, &aThemeBackgroundInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
- CGContextFillRect(maShared.maContextHolder.get(), rc);
+ HIThemeApplyBackground(&rc, &aThemeBackgroundInfo, context, kHIThemeOrientationNormal);
+ CGContextFillRect(context, rc);
bOK = true;
}
break;
@@ -369,11 +411,11 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
// repaints the background of the pull down menu
- HIThemeDrawMenuBackground(&rc, &aMenuInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawMenuBackground(&rc, &aMenuInfo, context, kHIThemeOrientationNormal);
// repaints the item either blue (selected) and/or grey (active only)
- HIThemeDrawMenuItem(&rc, &rc, &aMenuItemDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, &rc);
+ HIThemeDrawMenuItem(&rc, &rc, &aMenuItemDrawInfo, context, kHIThemeOrientationNormal, &rc);
bOK = true;
}
else if (nPart == ControlPart::MenuItemCheckMark || nPart == ControlPart::MenuItemRadioMark)
@@ -397,7 +439,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
if (nState & ControlState::SELECTED) aTextInfo.state = kThemeStatePressed;
UniChar mark=(nPart == ControlPart::MenuItemCheckMark) ? kCheckUnicode: kBulletUnicode;
CFStringRef cfString = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, &mark, 1, kCFAllocatorNull);
- HIThemeDrawTextBox(cfString, &rc, &aTextInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawTextBox(cfString, &rc, &aTextInfo, context, kHIThemeOrientationNormal);
if (cfString)
CFRelease(cfString);
bOK = true;
@@ -444,12 +486,12 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
// translate the origin for controls with fixed paint height so content ends up somewhere sensible
rc.origin.y += (rc.size.height - nPaintHeight) / 2;
- aPushInfo.state = getState(nState);
+ aPushInfo.state = getState(nState, mpFrame);
aPushInfo.value = ImplGetButtonValue(aValue.getTristateVal());
aPushInfo.adornment = (nState & ControlState::DEFAULT) ? kThemeAdornmentDefault : kThemeAdornmentNone;
if (nState & ControlState::FOCUSED)
aPushInfo.adornment |= kThemeAdornmentFocus;
- HIThemeDrawButton(&rc, &aPushInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawButton(&rc, &aPushInfo, context, kHIThemeOrientationNormal, nullptr);
bOK = true;
}
break;
@@ -475,7 +517,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
default:
break;
}
- aInfo.state = getState(nState);
+ aInfo.state = getState(nState, mpFrame);
ButtonValue aButtonValue = aValue.getTristateVal();
aInfo.value = ImplGetButtonValue(aButtonValue);
aInfo.adornment = (nState & ControlState::DEFAULT) ? kThemeAdornmentDefault : kThemeAdornmentNone;
@@ -485,7 +527,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
rc.size.height = RADIO_BUTTON_SMALL_SIZE;
rc.origin.x += FOCUS_RING_WIDTH;
rc.origin.y += FOCUS_RING_WIDTH;
- HIThemeDrawButton(&rc, &aInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawButton(&rc, &aInfo, context, kHIThemeOrientationNormal, nullptr);
bOK = true;
}
break;
@@ -496,7 +538,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
aInfo.version = 0;
aInfo.kind = kThemeDisclosureTriangle;
aInfo.value = kThemeDisclosureRight;
- aInfo.state = getState(nState);
+ aInfo.state = getState(nState, mpFrame);
aInfo.adornment = kThemeAdornmentNone;
switch (aButtonValue)
{
@@ -511,7 +553,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
default:
break;
}
- HIThemeDrawButton(&rc, &aInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawButton(&rc, &aInfo, context, kHIThemeOrientationNormal, nullptr);
bOK = true;
}
break;
@@ -530,7 +572,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
aTrackInfo.attributes = kThemeTrackHorizontal;
if (AllSettings::GetLayoutRTL())
aTrackInfo.attributes |= kThemeTrackRightToLeft;
- aTrackInfo.enableState = getTrackState(nState);
+ aTrackInfo.enableState = getTrackState(nState, mpFrame);
// the intro bitmap never gets key anyway; we want to draw that enabled
@@ -538,7 +580,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
aTrackInfo.enableState = kThemeTrackActive;
aTrackInfo.filler1 = 0;
aTrackInfo.trackInfo.progress.phase = static_cast<long long>(CFAbsoluteTimeGetCurrent() * 10.0);
- HIThemeDrawTrack(&aTrackInfo, nullptr, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawTrack(&aTrackInfo, nullptr, context, kHIThemeOrientationNormal);
bOK = true;
}
break;
@@ -562,7 +604,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
aSlideInfo.thumbDir = kThemeThumbUpward;
aSlideInfo.pressState = 0;
aTrackDraw.trackInfo.slider = aSlideInfo;
- HIThemeDrawTrack(&aTrackDraw, nullptr, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawTrack(&aTrackDraw, nullptr, context, kHIThemeOrientationNormal);
bOK = true;
}
}
@@ -583,7 +625,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
aTrackDraw.attributes = kThemeTrackShowThumb;
if (nPart == ControlPart::DrawBackgroundHorz)
aTrackDraw.attributes |= kThemeTrackHorizontal;
- aTrackDraw.enableState = getTrackState(nState);
+ aTrackDraw.enableState = getTrackState(nState, mpFrame);
ScrollBarTrackInfo aScrollInfo;
aScrollInfo.viewsize = pScrollbarVal->mnVisibleSize;
aScrollInfo.pressState = 0;
@@ -597,7 +639,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
if (pScrollbarVal->mnThumbState & ControlState::PRESSED)
aScrollInfo.pressState = kThemeThumbPressed;
aTrackDraw.trackInfo.scrollbar = aScrollInfo;
- HIThemeDrawTrack(&aTrackDraw, nullptr, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawTrack(&aTrackDraw, nullptr, context, kHIThemeOrientationNormal);
bOK = true;
}
}
@@ -617,7 +659,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
rc.origin.y -= TAB_HEIGHT / 2;
rc.size.height += TAB_HEIGHT / 2;
rc.size.width -= 2;
- HIThemeDrawTabPane(&rc, &aTabPaneDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawTabPane(&rc, &aTabPaneDrawInfo, context, kHIThemeOrientationNormal);
bOK = true;
}
break;
@@ -661,7 +703,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
else if (aTabItemDrawInfo.position == kHIThemeTabPositionLast)
aTabItemDrawInfo.position = kHIThemeTabPositionFirst;
}
- HIThemeDrawTab(&rc, &aTabItemDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawTab(&rc, &aTabItemDrawInfo, context, kHIThemeOrientationNormal, nullptr);
bOK=true;
}
break;
@@ -671,7 +713,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
HIThemeFrameDrawInfo aTextDrawInfo;
aTextDrawInfo.version = 0;
aTextDrawInfo.kind = kHIThemeFrameTextFieldSquare;
- aTextDrawInfo.state = getState(nState);
+ aTextDrawInfo.state = getState(nState, mpFrame);
aTextDrawInfo.isFocused = false;
rc.size.width += 2 * EDITBOX_INSET_MARGIN;
if (nType == ControlType::Editbox)
@@ -683,10 +725,10 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
// fill a white background, because HIThemeDrawFrame only draws the border
- CGContextFillRect(maShared.maContextHolder.get(), CGRectMake(rc.origin.x, rc.origin.y, rc.size.width, rc.size.height));
- HIThemeDrawFrame(&rc, &aTextDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
+ CGContextFillRect(context, CGRectMake(rc.origin.x, rc.origin.y, rc.size.width, rc.size.height));
+ HIThemeDrawFrame(&rc, &aTextDrawInfo, context, kHIThemeOrientationNormal);
if (nState & ControlState::FOCUSED)
- HIThemeDrawFocusRect(&rc, true, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawFocusRect(&rc, true, context, kHIThemeOrientationNormal);
bOK = true;
}
break;
@@ -696,7 +738,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
HIThemeButtonDrawInfo aComboInfo;
aComboInfo.version = 0;
aComboInfo.kind = kThemeComboBox;
- aComboInfo.state = getState(nState);
+ aComboInfo.state = getState(nState, mpFrame);
aComboInfo.value = kThemeButtonOn;
aComboInfo.adornment = kThemeAdornmentNone;
if (nState & ControlState::FOCUSED)
@@ -705,7 +747,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
rc.size.height = COMBOBOX_HEIGHT;
rc.origin.x += FOCUS_RING_WIDTH;
rc.origin.y += FOCUS_RING_WIDTH;
- HIThemeDrawButton(&rc, &aComboInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawButton(&rc, &aComboInfo, context, kHIThemeOrientationNormal, nullptr);
bOK = true;
}
break;
@@ -717,7 +759,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
HIThemeButtonDrawInfo aListInfo;
aListInfo.version = 0;
aListInfo.kind = kThemePopupButton;
- aListInfo.state = getState(nState);
+ aListInfo.state = getState(nState, mpFrame);
aListInfo.value = kThemeButtonOn;
aListInfo.adornment = kThemeAdornmentDefault;
if (nState & ControlState::FOCUSED)
@@ -726,7 +768,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
rc.size.height = LISTBOX_HEIGHT;
rc.origin.x += FOCUS_RING_WIDTH;
rc.origin.y += FOCUS_RING_WIDTH;
- HIThemeDrawButton(&rc, &aListInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawButton(&rc, &aListInfo, context, kHIThemeOrientationNormal, nullptr);
bOK = true;
break;
case ControlPart::ListboxWindow:
@@ -735,7 +777,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
aTextDrawInfo.kind = kHIThemeFrameListBox;
aTextDrawInfo.state = kThemeStateActive;
aTextDrawInfo.isFocused = false;
- HIThemeDrawFrame(&rc, &aTextDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawFrame(&rc, &aTextDrawInfo, context, kHIThemeOrientationNormal);
bOK = true;
break;
default:
@@ -751,7 +793,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
HIThemeFrameDrawInfo aTextDrawInfo;
aTextDrawInfo.version = 0;
aTextDrawInfo.kind = kHIThemeFrameTextFieldSquare;
- aTextDrawInfo.state = getState(nState);
+ aTextDrawInfo.state = getState(nState, mpFrame);
aTextDrawInfo.isFocused = false;
rc.size.width -= SPIN_BUTTON_WIDTH + 4 * FOCUS_RING_WIDTH;
rc.size.height = EDITBOX_HEIGHT;
@@ -760,10 +802,10 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
// fill a white background, because HIThemeDrawFrame only draws the border
- CGContextFillRect(maShared.maContextHolder.get(), CGRectMake(rc.origin.x, rc.origin.y, rc.size.width, rc.size.height));
- HIThemeDrawFrame(&rc, &aTextDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
+ CGContextFillRect(context, CGRectMake(rc.origin.x, rc.origin.y, rc.size.width, rc.size.height));
+ HIThemeDrawFrame(&rc, &aTextDrawInfo, context, kHIThemeOrientationNormal);
if (nState & ControlState::FOCUSED)
- HIThemeDrawFocusRect(&rc, true, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawFocusRect(&rc, true, context, kHIThemeOrientationNormal);
// buttons
@@ -808,7 +850,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
rc.origin.y -= 1;
rc.size.width = SPIN_BUTTON_WIDTH;
rc.size.height = SPIN_LOWER_BUTTON_HEIGHT + SPIN_LOWER_BUTTON_HEIGHT;
- HIThemeDrawButton(&rc, &aSpinInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal, nullptr);
+ HIThemeDrawButton(&rc, &aSpinInfo, context, kHIThemeOrientationNormal, nullptr);
}
bOK = true;
}
@@ -824,14 +866,14 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
// strange effects start to happen when HIThemeDrawFrame meets the border of the window.
// These can be avoided by clipping to the boundary of the frame (see issue 84756)
- if (rc.origin.y + rc.size.height >= maShared.mpFrame->maGeometry.nHeight - 3)
+ if (rc.origin.y + rc.size.height >= mpFrame->maGeometry.nHeight - 3)
{
CGMutablePathRef rPath = CGPathCreateMutable();
CGPathAddRect(rPath, nullptr,
- CGRectMake(0, 0, maShared.mpFrame->maGeometry.nWidth - 1, maShared.mpFrame->maGeometry.nHeight - 1));
- CGContextBeginPath(maShared.maContextHolder.get());
- CGContextAddPath(maShared.maContextHolder.get(), rPath);
- CGContextClip(maShared.maContextHolder.get());
+ CGRectMake(0, 0, mpFrame->maGeometry.nWidth - 1, mpFrame->maGeometry.nHeight - 1));
+ CGContextBeginPath(context);
+ CGContextAddPath(context, rPath);
+ CGContextClip(context);
CGPathRelease(rPath);
}
HIThemeFrameDrawInfo aTextDrawInfo;
@@ -839,7 +881,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
aTextDrawInfo.kind = kHIThemeFrameListBox;
aTextDrawInfo.state = kThemeStateActive;
aTextDrawInfo.isFocused = false;
- HIThemeDrawFrame(&rc, &aTextDrawInfo, maShared.maContextHolder.get(), kHIThemeOrientationNormal);
+ HIThemeDrawFrame(&rc, &aTextDrawInfo, context, kHIThemeOrientationNormal);
bOK = true;
}
}
@@ -854,25 +896,7 @@ bool AquaSalGraphics::drawNativeControl(ControlType nType,
default:
break;
}
- maShared.maContextHolder.restoreState();
-
- // in most cases invalidating the whole control region instead of just the unclipped part of it is sufficient (and probably
- // faster). However for the window background we should not unnecessarily enlarge the really changed rectangle since the
- // difference is usually quite high. Background is always drawn as a whole since we don't know anything about its possible
- // contents (see issue i90291).
- if (nType == ControlType::WindowBackground)
- {
- CGRect aRect = {{0, 0}, {0, 0}};
- if (maShared.mxClipPath)
- aRect = CGPathGetBoundingBox(maShared.mxClipPath);
- if (aRect.size.width != 0 && aRect.size.height != 0)
- buttonRect.Intersection(tools::Rectangle(Point(static_cast<tools::Long>(aRect.origin.x),
- static_cast<tools::Long>(aRect.origin.y)),
- Size(static_cast<tools::Long>(aRect.size.width),
- static_cast<tools::Long>(aRect.size.height))));
- }
- maShared.refreshRect(buttonRect.Left(), buttonRect.Top(), buttonRect.GetWidth(), buttonRect.GetHeight());
return bOK;
}
diff --git a/vcl/skia/osx/gdiimpl.cxx b/vcl/skia/osx/gdiimpl.cxx
index 5396cde921da..c5e8911d339e 100644
--- a/vcl/skia/osx/gdiimpl.cxx
+++ b/vcl/skia/osx/gdiimpl.cxx
@@ -23,6 +23,8 @@
#include <skia/osx/rastercontext.hxx>
+#include <SkCanvas.h>
+
using namespace SkiaHelper;
AquaSkiaSalGraphicsImpl::AquaSkiaSalGraphicsImpl(AquaSalGraphics& rParent,
@@ -124,6 +126,53 @@ void AquaSkiaSalGraphicsImpl::flushToScreen(const SkIRect& rect)
mrShared.refreshRect(rect.left(), rect.top(), rect.width(), rect.height());
}
+bool AquaSkiaSalGraphicsImpl::drawNativeControl(ControlType nType, ControlPart nPart,
+ const tools::Rectangle& rControlRegion,
+ ControlState nState, const ImplControlValue& aValue)
+{
+ const tools::Long width = rControlRegion.GetWidth();
+ const tools::Long height = rControlRegion.GetHeight();
+ const size_t bytes = width * height * 4;
+ std::unique_ptr<sal_uInt8[]> data(new sal_uInt8[bytes]);
+ memset(data.get(), 0, bytes);
+ CGContextRef context
+ = CGBitmapContextCreate(data.get(), width, height, 8, width * 4, // TODO
+ GetSalData()->mxRGBSpace, kCGImageAlphaPremultipliedLast); // TODO
+ assert(context); // TODO
+ // Flip upside down.
+ CGContextTranslateCTM(context, 0, height);
+ CGContextScaleCTM(context, 1, -1);
+ // Adjust for our drawn-to coordinates in the bitmap.
+ tools::Rectangle movedRegion = rControlRegion;
+ movedRegion.SetPos(Point(0, 0));
+ bool bOK = performDrawNativeControl(nType, nPart, movedRegion, nState, aValue, context,
+ mrShared.mpFrame);
+ CGContextRelease(context);
+ if (bOK)
+ {
+ SkBitmap bitmap;
+ if (!bitmap.installPixels(
+ SkImageInfo::Make(width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType),
+ data.get(), width * 4))
+ abort();
+
+ preDraw();
+ SAL_INFO("vcl.skia.trace", "drawnativecontrol(" << this << "): " << rControlRegion << ":"
+ << int(nType) << "/" << int(nPart));
+ tools::Rectangle updateRect = rControlRegion;
+ // For background update only part that is not clipped, the same
+ // as in AquaGraphicsBackend::drawNativeControl().
+ if (nType == ControlType::WindowBackground)
+ updateRect.Intersection(mClipRegion.GetBoundRect());
+ addUpdateRegion(SkRect::MakeXYWH(updateRect.Left(), updateRect.Top(), updateRect.GetWidth(),
+ updateRect.GetHeight()));
+ getDrawCanvas()->drawImage(bitmap.asImage(), rControlRegion.Left(), rControlRegion.Top());
+ ++mPendingOperationsToFlush; // tdf#136369
+ postDraw();
+ }
+ return bOK;
+}
+
std::unique_ptr<sk_app::WindowContext> createVulkanWindowContext(bool /*temporary*/)
{
return nullptr;