vcl/inc/quartz/salgdi.h | 28 +++++-- vcl/inc/skia/osx/gdiimpl.hxx | 4 + vcl/osx/salnativewidgets.cxx | 170 ++++++++++++++++++++++++------------------- vcl/skia/osx/gdiimpl.cxx | 50 ++++++++++++ 4 files changed, 173 insertions(+), 79 deletions(-)
New commits: commit e3a8826709430f414411d22d98c1fd5e647e1417 Author: Luboš Luňák <l.lu...@collabora.com> AuthorDate: Fri Aug 13 16:18:43 2021 +0200 Commit: Luboš Luňák <l.lu...@collabora.com> CommitDate: Mon Aug 23 15:00:15 2021 +0200 implement mac native widget drawing also for Skia Change-Id: Ie91e48cb315d8e11508f064a6dcd9fafebb39abd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120809 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lu...@collabora.com> 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; commit c8055fd19613a7c5cc5e39156714c781302b7841 Author: Luboš Luňák <l.lu...@collabora.com> AuthorDate: Fri Aug 13 07:38:03 2021 +0200 Commit: Luboš Luňák <l.lu...@collabora.com> CommitDate: Mon Aug 23 14:59:57 2021 +0200 explicitly force skia raster on mac for now Change-Id: I29b09b63a7d18d2e32f6310f2851aa6cd5cd7a8e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120808 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lu...@collabora.com> diff --git a/vcl/skia/osx/gdiimpl.cxx b/vcl/skia/osx/gdiimpl.cxx index c815fc1ebe9d..5396cde921da 100644 --- a/vcl/skia/osx/gdiimpl.cxx +++ b/vcl/skia/osx/gdiimpl.cxx @@ -52,6 +52,7 @@ void AquaSkiaSalGraphicsImpl::createWindowContext(bool forceRaster) SkiaZone zone; sk_app::DisplayParams displayParams; displayParams.fColorType = kN32_SkColorType; + forceRaster = true; // TODO RenderMethod renderMethod = forceRaster ? RenderRaster : renderMethodToUse(); switch (renderMethod) {