mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-12 08:42:13 -04:00
frame(ConnectedMode): Wire up Notifications
This commit is contained in:
@@ -14,27 +14,22 @@ Item {
|
||||
required property real cutoutLeftInset
|
||||
required property real cutoutRightInset
|
||||
required property real cutoutRadius
|
||||
property color borderColor: Qt.rgba(SettingsData.effectiveFrameColor.r, SettingsData.effectiveFrameColor.g, SettingsData.effectiveFrameColor.b, SettingsData.frameOpacity)
|
||||
|
||||
Rectangle {
|
||||
id: borderRect
|
||||
|
||||
anchors.fill: parent
|
||||
// Bake frameOpacity into the color alpha rather than using the `opacity` property.
|
||||
// Qt Quick can skip layer.effect processing on items with opacity < 1 as an
|
||||
// optimization, causing the MultiEffect inverted mask to stop working and the
|
||||
// Rectangle to render as a plain square at low opacity values.
|
||||
color: Qt.rgba(SettingsData.effectiveFrameColor.r,
|
||||
SettingsData.effectiveFrameColor.g,
|
||||
SettingsData.effectiveFrameColor.b,
|
||||
SettingsData.frameOpacity)
|
||||
// Bake frameOpacity into the color alpha rather than using the `opacity` property
|
||||
color: root.borderColor
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: MultiEffect {
|
||||
maskSource: cutoutMask
|
||||
maskEnabled: true
|
||||
maskInverted: true
|
||||
maskThresholdMin: 0.5
|
||||
maskSpreadAtMin: 1
|
||||
maskSource: cutoutMask
|
||||
maskEnabled: true
|
||||
maskInverted: true
|
||||
maskThresholdMin: 0.5
|
||||
maskSpreadAtMin: 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,11 +42,11 @@ Item {
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
fill: parent
|
||||
topMargin: root.cutoutTopInset
|
||||
fill: parent
|
||||
topMargin: root.cutoutTopInset
|
||||
bottomMargin: root.cutoutBottomInset
|
||||
leftMargin: root.cutoutLeftInset
|
||||
rightMargin: root.cutoutRightInset
|
||||
leftMargin: root.cutoutLeftInset
|
||||
rightMargin: root.cutoutRightInset
|
||||
}
|
||||
radius: root.cutoutRadius
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ PanelWindow {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
})
|
||||
readonly property var _notifState: ConnectedModeState.notificationStates[win._screenName] || ConnectedModeState.emptyNotificationState
|
||||
|
||||
// ─── Connected chrome convenience properties ──────────────────────────────
|
||||
readonly property bool _connectedActive: win._frameActive && SettingsData.connectedFrameModeActive
|
||||
@@ -218,6 +219,18 @@ PanelWindow {
|
||||
height: _active ? win._dockConnectorRadius() * 2 : 0
|
||||
}
|
||||
|
||||
Item {
|
||||
id: _notifBodyBlurAnchor
|
||||
visible: false
|
||||
|
||||
readonly property bool _active: win._frameActive && win._notifState.visible && win._notifState.bodyW > 0 && win._notifState.bodyH > 0
|
||||
|
||||
x: _active ? Theme.snap(win._notifState.bodyX, win._dpr) : 0
|
||||
y: _active ? Theme.snap(win._notifState.bodyY, win._dpr) : 0
|
||||
width: _active ? Theme.snap(win._notifState.bodyW, win._dpr) : 0
|
||||
height: _active ? Theme.snap(win._notifState.bodyH, win._dpr) : 0
|
||||
}
|
||||
|
||||
Region {
|
||||
id: _staticBlurRegion
|
||||
x: 0
|
||||
@@ -267,6 +280,11 @@ PanelWindow {
|
||||
radius: win._dockConnectorRadius()
|
||||
}
|
||||
}
|
||||
|
||||
Region {
|
||||
item: _notifBodyBlurAnchor
|
||||
radius: win._surfaceRadius
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Connector position helpers (dock) ─────────────────────────────────
|
||||
@@ -528,7 +546,7 @@ PanelWindow {
|
||||
|
||||
FrameBorder {
|
||||
anchors.fill: parent
|
||||
visible: win._frameActive
|
||||
visible: win._frameActive && !win._connectedActive
|
||||
cutoutTopInset: win.cutoutTopInset
|
||||
cutoutBottomInset: win.cutoutBottomInset
|
||||
cutoutLeftInset: win.cutoutLeftInset
|
||||
@@ -539,98 +557,141 @@ PanelWindow {
|
||||
// ─── Connected chrome fills ───────────────────────────────────────────────
|
||||
|
||||
Item {
|
||||
id: _connectedChrome
|
||||
id: _connectedSurfaceLayer
|
||||
anchors.fill: parent
|
||||
visible: win._connectedActive
|
||||
opacity: win._surfaceOpacity
|
||||
layer.enabled: opacity < 1
|
||||
layer.smooth: false
|
||||
|
||||
FrameBorder {
|
||||
anchors.fill: parent
|
||||
borderColor: win._opaqueSurfaceColor
|
||||
cutoutTopInset: win.cutoutTopInset
|
||||
cutoutBottomInset: win.cutoutBottomInset
|
||||
cutoutLeftInset: win.cutoutLeftInset
|
||||
cutoutRightInset: win.cutoutRightInset
|
||||
cutoutRadius: win.cutoutRadius
|
||||
}
|
||||
|
||||
Item {
|
||||
id: _popoutChrome
|
||||
visible: ConnectedModeState.popoutVisible && ConnectedModeState.popoutScreen === win._screenName
|
||||
x: win._popoutChromeX()
|
||||
y: win._popoutChromeY()
|
||||
width: win._popoutChromeWidth()
|
||||
height: win._popoutChromeHeight()
|
||||
opacity: win._surfaceOpacity
|
||||
layer.enabled: opacity < 1
|
||||
layer.smooth: false
|
||||
id: _connectedChrome
|
||||
anchors.fill: parent
|
||||
visible: true
|
||||
|
||||
Item {
|
||||
id: _popoutClip
|
||||
readonly property bool _barHoriz: ConnectedModeState.popoutBarSide === "top" || ConnectedModeState.popoutBarSide === "bottom"
|
||||
// Expand clip by ccr on bar axis to include arc columns
|
||||
x: win._popoutClipX() - (_barHoriz ? win._effectivePopoutCcr : 0)
|
||||
y: win._popoutClipY() - (_barHoriz ? 0 : win._effectivePopoutCcr)
|
||||
width: win._popoutClipWidth() + (_barHoriz ? win._effectivePopoutCcr * 2 : 0)
|
||||
height: win._popoutClipHeight() + (_barHoriz ? 0 : win._effectivePopoutCcr * 2)
|
||||
clip: true
|
||||
id: _popoutChrome
|
||||
visible: ConnectedModeState.popoutVisible && ConnectedModeState.popoutScreen === win._screenName
|
||||
x: win._popoutChromeX()
|
||||
y: win._popoutChromeY()
|
||||
width: win._popoutChromeWidth()
|
||||
height: win._popoutChromeHeight()
|
||||
|
||||
ConnectedShape {
|
||||
id: _popoutShape
|
||||
visible: _popoutBodyBlurAnchor._active && _popoutBodyBlurAnchor.width > 0 && _popoutBodyBlurAnchor.height > 0
|
||||
barSide: ConnectedModeState.popoutBarSide
|
||||
bodyWidth: win._popoutClipWidth()
|
||||
bodyHeight: win._popoutClipHeight()
|
||||
connectorRadius: win._effectivePopoutCcr
|
||||
surfaceRadius: win._surfaceRadius
|
||||
fillColor: win._opaqueSurfaceColor
|
||||
x: 0
|
||||
y: 0
|
||||
Item {
|
||||
id: _popoutClip
|
||||
readonly property bool _barHoriz: ConnectedModeState.popoutBarSide === "top" || ConnectedModeState.popoutBarSide === "bottom"
|
||||
// Expand clip by ccr on bar axis to include arc columns
|
||||
x: win._popoutClipX() - (_barHoriz ? win._effectivePopoutCcr : 0)
|
||||
y: win._popoutClipY() - (_barHoriz ? 0 : win._effectivePopoutCcr)
|
||||
width: win._popoutClipWidth() + (_barHoriz ? win._effectivePopoutCcr * 2 : 0)
|
||||
height: win._popoutClipHeight() + (_barHoriz ? 0 : win._effectivePopoutCcr * 2)
|
||||
clip: true
|
||||
|
||||
ConnectedShape {
|
||||
id: _popoutShape
|
||||
visible: _popoutBodyBlurAnchor._active && _popoutBodyBlurAnchor.width > 0 && _popoutBodyBlurAnchor.height > 0
|
||||
barSide: ConnectedModeState.popoutBarSide
|
||||
bodyWidth: win._popoutClipWidth()
|
||||
bodyHeight: win._popoutClipHeight()
|
||||
connectorRadius: win._effectivePopoutCcr
|
||||
surfaceRadius: win._surfaceRadius
|
||||
fillColor: win._opaqueSurfaceColor
|
||||
x: 0
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: _dockChrome
|
||||
visible: _dockBodyBlurAnchor._active
|
||||
x: win._dockChromeX()
|
||||
y: win._dockChromeY()
|
||||
width: win._dockChromeWidth()
|
||||
height: win._dockChromeHeight()
|
||||
|
||||
Rectangle {
|
||||
id: _dockFill
|
||||
x: win._dockBodyXInChrome()
|
||||
y: win._dockBodyYInChrome()
|
||||
width: _dockBodyBlurAnchor.width + win._dockFillOverlapX() * 2
|
||||
height: _dockBodyBlurAnchor.height + win._dockFillOverlapY() * 2
|
||||
color: win._opaqueSurfaceColor
|
||||
z: 1
|
||||
|
||||
readonly property string _dockSide: win._dockState.barSide
|
||||
readonly property real _dockRadius: win._dockBodyBlurRadius()
|
||||
topLeftRadius: (_dockSide === "top" || _dockSide === "left") ? 0 : _dockRadius
|
||||
topRightRadius: (_dockSide === "top" || _dockSide === "right") ? 0 : _dockRadius
|
||||
bottomLeftRadius: (_dockSide === "bottom" || _dockSide === "left") ? 0 : _dockRadius
|
||||
bottomRightRadius: (_dockSide === "bottom" || _dockSide === "right") ? 0 : _dockRadius
|
||||
}
|
||||
|
||||
ConnectedCorner {
|
||||
id: _connDockLeft
|
||||
visible: _dockBodyBlurAnchor._active
|
||||
barSide: win._dockState.barSide
|
||||
placement: "left"
|
||||
spacing: 0
|
||||
connectorRadius: win._dockConnectorRadius()
|
||||
color: win._opaqueSurfaceColor
|
||||
dpr: win._dpr
|
||||
x: Theme.snap(win._dockConnectorX(_dockBodyBlurAnchor.x, _dockBodyBlurAnchor.width, "left", 0) - _dockChrome.x, win._dpr)
|
||||
y: Theme.snap(win._dockConnectorY(_dockBodyBlurAnchor.y, _dockBodyBlurAnchor.height, "left", 0) - _dockChrome.y, win._dpr)
|
||||
}
|
||||
|
||||
ConnectedCorner {
|
||||
id: _connDockRight
|
||||
visible: _dockBodyBlurAnchor._active
|
||||
barSide: win._dockState.barSide
|
||||
placement: "right"
|
||||
spacing: 0
|
||||
connectorRadius: win._dockConnectorRadius()
|
||||
color: win._opaqueSurfaceColor
|
||||
dpr: win._dpr
|
||||
x: Theme.snap(win._dockConnectorX(_dockBodyBlurAnchor.x, _dockBodyBlurAnchor.width, "right", 0) - _dockChrome.x, win._dpr)
|
||||
y: Theme.snap(win._dockConnectorY(_dockBodyBlurAnchor.y, _dockBodyBlurAnchor.height, "right", 0) - _dockChrome.y, win._dpr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: _dockChrome
|
||||
visible: _dockBodyBlurAnchor._active
|
||||
x: win._dockChromeX()
|
||||
y: win._dockChromeY()
|
||||
width: win._dockChromeWidth()
|
||||
height: win._dockChromeHeight()
|
||||
opacity: win._surfaceOpacity
|
||||
layer.enabled: opacity < 1
|
||||
layer.smooth: false
|
||||
id: _notifChrome
|
||||
visible: _notifBodyBlurAnchor._active
|
||||
|
||||
Rectangle {
|
||||
id: _dockFill
|
||||
x: win._dockBodyXInChrome()
|
||||
y: win._dockBodyYInChrome()
|
||||
width: _dockBodyBlurAnchor.width + win._dockFillOverlapX() * 2
|
||||
height: _dockBodyBlurAnchor.height + win._dockFillOverlapY() * 2
|
||||
color: win._opaqueSurfaceColor
|
||||
z: 1
|
||||
readonly property string _notifSide: win._notifState.barSide
|
||||
readonly property bool _isHoriz: _notifSide === "top" || _notifSide === "bottom"
|
||||
readonly property real _notifCcr: Theme.snap(Math.max(0, Math.min(win._ccr, win._surfaceRadius, (_isHoriz ? _notifBodyBlurAnchor.width : _notifBodyBlurAnchor.height) / 2)), win._dpr)
|
||||
readonly property real _sideUnderlap: _isHoriz ? 0 : win._seamOverlap
|
||||
readonly property real _bodyW: Theme.snap(_notifBodyBlurAnchor.width + _sideUnderlap, win._dpr)
|
||||
readonly property real _bodyH: Theme.snap(_notifBodyBlurAnchor.height, win._dpr)
|
||||
|
||||
readonly property string _dockSide: win._dockState.barSide
|
||||
readonly property real _dockRadius: win._dockBodyBlurRadius()
|
||||
topLeftRadius: (_dockSide === "top" || _dockSide === "left") ? 0 : _dockRadius
|
||||
topRightRadius: (_dockSide === "top" || _dockSide === "right") ? 0 : _dockRadius
|
||||
bottomLeftRadius: (_dockSide === "bottom" || _dockSide === "left") ? 0 : _dockRadius
|
||||
bottomRightRadius: (_dockSide === "bottom" || _dockSide === "right") ? 0 : _dockRadius
|
||||
}
|
||||
z: _isHoriz ? 0 : -1
|
||||
x: Theme.snap(_notifBodyBlurAnchor.x - (_isHoriz ? _notifCcr : (_notifSide === "left" ? _sideUnderlap : 0)), win._dpr)
|
||||
y: Theme.snap(_notifBodyBlurAnchor.y - (_isHoriz ? 0 : _notifCcr), win._dpr)
|
||||
width: _isHoriz ? Theme.snap(_bodyW + _notifCcr * 2, win._dpr) : _bodyW
|
||||
height: Theme.snap(_bodyH + (_isHoriz ? 0 : _notifCcr * 2), win._dpr)
|
||||
|
||||
ConnectedCorner {
|
||||
id: _connDockLeft
|
||||
visible: _dockBodyBlurAnchor._active
|
||||
barSide: win._dockState.barSide
|
||||
placement: "left"
|
||||
spacing: 0
|
||||
connectorRadius: win._dockConnectorRadius()
|
||||
color: win._opaqueSurfaceColor
|
||||
dpr: win._dpr
|
||||
x: Theme.snap(win._dockConnectorX(_dockBodyBlurAnchor.x, _dockBodyBlurAnchor.width, "left", 0) - _dockChrome.x, win._dpr)
|
||||
y: Theme.snap(win._dockConnectorY(_dockBodyBlurAnchor.y, _dockBodyBlurAnchor.height, "left", 0) - _dockChrome.y, win._dpr)
|
||||
}
|
||||
|
||||
ConnectedCorner {
|
||||
id: _connDockRight
|
||||
visible: _dockBodyBlurAnchor._active
|
||||
barSide: win._dockState.barSide
|
||||
placement: "right"
|
||||
spacing: 0
|
||||
connectorRadius: win._dockConnectorRadius()
|
||||
color: win._opaqueSurfaceColor
|
||||
dpr: win._dpr
|
||||
x: Theme.snap(win._dockConnectorX(_dockBodyBlurAnchor.x, _dockBodyBlurAnchor.width, "right", 0) - _dockChrome.x, win._dpr)
|
||||
y: Theme.snap(win._dockConnectorY(_dockBodyBlurAnchor.y, _dockBodyBlurAnchor.height, "right", 0) - _dockChrome.y, win._dpr)
|
||||
ConnectedShape {
|
||||
visible: _notifBodyBlurAnchor._active && _notifBodyBlurAnchor.width > 0 && _notifBodyBlurAnchor.height > 0
|
||||
barSide: _notifChrome._notifSide
|
||||
bodyWidth: _notifChrome._bodyW
|
||||
bodyHeight: _notifChrome._bodyH
|
||||
connectorRadius: _notifChrome._notifCcr
|
||||
surfaceRadius: win._surfaceRadius
|
||||
fillColor: win._opaqueSurfaceColor
|
||||
x: 0
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,29 @@ import qs.Widgets
|
||||
PanelWindow {
|
||||
id: win
|
||||
|
||||
readonly property bool connectedFrameMode: SettingsData.frameEnabled
|
||||
&& Theme.isConnectedEffect
|
||||
&& SettingsData.isScreenInPreferences(win.screen, SettingsData.frameScreenPreferences)
|
||||
readonly property string notifBarSide: {
|
||||
const pos = SettingsData.notificationPopupPosition;
|
||||
if (pos === -1) return "top";
|
||||
switch (pos) {
|
||||
case SettingsData.Position.Top: return "right";
|
||||
case SettingsData.Position.Left: return "left";
|
||||
case SettingsData.Position.BottomCenter: return "bottom";
|
||||
case SettingsData.Position.Right: return "right";
|
||||
case SettingsData.Position.Bottom: return "left";
|
||||
default: return "top";
|
||||
}
|
||||
}
|
||||
|
||||
WindowBlur {
|
||||
targetWindow: win
|
||||
blurX: content.x + content.cardInset + swipeTx.x + tx.x
|
||||
blurY: content.y + content.cardInset + swipeTx.y + tx.y
|
||||
blurWidth: !win._finalized ? Math.max(0, content.width - content.cardInset * 2) : 0
|
||||
blurHeight: !win._finalized ? Math.max(0, content.height - content.cardInset * 2) : 0
|
||||
blurRadius: SettingsData.connectedFrameModeActive ? Theme.connectedSurfaceRadius : Theme.cornerRadius
|
||||
blurWidth: !win._finalized && !win.connectedFrameMode ? Math.max(0, content.width - content.cardInset * 2) : 0
|
||||
blurHeight: !win._finalized && !win.connectedFrameMode ? Math.max(0, content.height - content.cardInset * 2) : 0
|
||||
blurRadius: win.connectedFrameMode ? Theme.connectedSurfaceRadius : Theme.cornerRadius
|
||||
}
|
||||
|
||||
WlrLayershell.namespace: "dms:notification-popup"
|
||||
@@ -84,6 +100,7 @@ PanelWindow {
|
||||
signal exitStarted
|
||||
signal exitFinished
|
||||
signal popupHeightChanged
|
||||
signal popupChromeGeometryChanged
|
||||
|
||||
function startExit() {
|
||||
if (exiting || _isDestroying) {
|
||||
@@ -91,6 +108,7 @@ PanelWindow {
|
||||
}
|
||||
exiting = true;
|
||||
exitStarted();
|
||||
popupChromeGeometryChanged();
|
||||
exitAnim.restart();
|
||||
exitWatchdog.restart();
|
||||
if (NotificationService.removeFromVisibleNotifications)
|
||||
@@ -171,6 +189,7 @@ PanelWindow {
|
||||
duration: Theme.variantDuration(descriptionExpanded ? Theme.notificationExpandDuration : Theme.notificationCollapseDuration, descriptionExpanded)
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: descriptionExpanded ? Theme.variantPopoutEnterCurve : Theme.variantPopoutExitCurve
|
||||
onFinished: win.popupHeightChanged()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,12 +282,24 @@ PanelWindow {
|
||||
});
|
||||
}
|
||||
|
||||
function _frameEdgeInset(side) {
|
||||
if (!screen)
|
||||
return 0;
|
||||
const edges = SettingsData.getActiveBarEdgesForScreen(screen);
|
||||
const raw = edges.includes(side) ? SettingsData.frameBarSize : SettingsData.frameThickness;
|
||||
return Math.max(0, Math.round(Theme.px(raw, dpr)));
|
||||
}
|
||||
|
||||
function getTopMargin() {
|
||||
const popupPos = SettingsData.notificationPopupPosition;
|
||||
const isTop = isTopCenter || popupPos === SettingsData.Position.Top || popupPos === SettingsData.Position.Left;
|
||||
if (!isTop)
|
||||
return 0;
|
||||
|
||||
if (connectedFrameMode) {
|
||||
const cornerClear = isCenterPosition ? 0 : (Theme.px(SettingsData.frameRounding, dpr) + Theme.px(Theme.connectedCornerRadius, dpr));
|
||||
return _frameEdgeInset("top") + cornerClear + screenY;
|
||||
}
|
||||
const barInfo = getBarInfo();
|
||||
const base = barInfo.topBar > 0 ? barInfo.topBar : Theme.popupDistance;
|
||||
return base + screenY;
|
||||
@@ -280,6 +311,10 @@ PanelWindow {
|
||||
if (!isBottom)
|
||||
return 0;
|
||||
|
||||
if (connectedFrameMode) {
|
||||
const cornerClear = isCenterPosition ? 0 : (Theme.px(SettingsData.frameRounding, dpr) + Theme.px(Theme.connectedCornerRadius, dpr));
|
||||
return _frameEdgeInset("bottom") + cornerClear + screenY;
|
||||
}
|
||||
const barInfo = getBarInfo();
|
||||
const base = barInfo.bottomBar > 0 ? barInfo.bottomBar : Theme.popupDistance;
|
||||
return base + screenY;
|
||||
@@ -294,6 +329,8 @@ PanelWindow {
|
||||
if (!isLeft)
|
||||
return 0;
|
||||
|
||||
if (connectedFrameMode)
|
||||
return _frameEdgeInset("left");
|
||||
const barInfo = getBarInfo();
|
||||
return barInfo.leftBar > 0 ? barInfo.leftBar : Theme.popupDistance;
|
||||
}
|
||||
@@ -307,6 +344,8 @@ PanelWindow {
|
||||
if (!isRight)
|
||||
return 0;
|
||||
|
||||
if (connectedFrameMode)
|
||||
return _frameEdgeInset("right");
|
||||
const barInfo = getBarInfo();
|
||||
return barInfo.rightBar > 0 ? barInfo.rightBar : Theme.popupDistance;
|
||||
}
|
||||
@@ -351,10 +390,64 @@ PanelWindow {
|
||||
return Theme.snap(getContentY() - windowShadowPad, dpr);
|
||||
}
|
||||
|
||||
function _swipeDismissTarget() {
|
||||
return (content.swipeDismissDirection < 0 ? -1 : 1) * content.width;
|
||||
}
|
||||
|
||||
function _frameEdgeSwipeDirection() {
|
||||
const popupPos = SettingsData.notificationPopupPosition;
|
||||
return (popupPos === SettingsData.Position.Left || popupPos === SettingsData.Position.Bottom) ? -1 : 1;
|
||||
}
|
||||
|
||||
function _swipeDismissesTowardFrameEdge() {
|
||||
return content.swipeDismissDirection === _frameEdgeSwipeDirection();
|
||||
}
|
||||
|
||||
function popupChromeMotionActive() {
|
||||
return exiting || content.swipeActive || content.swipeDismissing || Math.abs(content.swipeOffset) > 0.5;
|
||||
}
|
||||
|
||||
function popupLayoutReservesSlot() {
|
||||
return !content.swipeDismissing;
|
||||
}
|
||||
|
||||
function popupChromeReservesSlot() {
|
||||
return !content.swipeDismissing;
|
||||
}
|
||||
|
||||
function popupChromeReleaseProgress() {
|
||||
if (content.swipeDismissing)
|
||||
return Math.max(0, Math.min(1, Math.abs(content.swipeOffset) / Math.max(1, content.swipeTravelDistance)));
|
||||
if (!exiting)
|
||||
return 0;
|
||||
const exitOffset = isCenterPosition ? tx.y : tx.x;
|
||||
return Math.max(0, Math.min(1, Math.abs(exitOffset) / Math.max(1, exitTravel)));
|
||||
}
|
||||
|
||||
function popupChromeMotionX() {
|
||||
if (!popupChromeMotionActive() || isCenterPosition)
|
||||
return 0;
|
||||
const motion = content.swipeOffset + tx.x;
|
||||
if (content.swipeDismissing && !_swipeDismissesTowardFrameEdge())
|
||||
return exiting ? Theme.snap(tx.x, dpr) : 0;
|
||||
if (content.swipeActive && motion * _frameEdgeSwipeDirection() < 0)
|
||||
return 0;
|
||||
return Theme.snap(motion, dpr);
|
||||
}
|
||||
|
||||
function popupChromeMotionY() {
|
||||
return popupChromeMotionActive() ? Theme.snap(tx.y, dpr) : 0;
|
||||
}
|
||||
|
||||
readonly property bool screenValid: win.screen && !_isDestroying
|
||||
readonly property real dpr: screenValid ? CompositorService.getScreenScale(win.screen) : 1
|
||||
readonly property real alignedWidth: Theme.px(Math.max(0, implicitWidth - (windowShadowPad * 2)), dpr)
|
||||
readonly property real alignedHeight: Theme.px(Math.max(0, implicitHeight - (windowShadowPad * 2)), dpr)
|
||||
onScreenYChanged: popupChromeGeometryChanged()
|
||||
onScreenChanged: popupChromeGeometryChanged()
|
||||
onConnectedFrameModeChanged: popupChromeGeometryChanged()
|
||||
onAlignedWidthChanged: popupChromeGeometryChanged()
|
||||
onAlignedHeightChanged: popupChromeGeometryChanged()
|
||||
|
||||
Item {
|
||||
id: content
|
||||
@@ -363,7 +456,7 @@ PanelWindow {
|
||||
y: Theme.snap(windowShadowPad, dpr)
|
||||
width: alignedWidth
|
||||
height: alignedHeight
|
||||
visible: !win._finalized
|
||||
visible: !win._finalized && !chromeOnlyExit
|
||||
scale: cardHoverHandler.hovered ? 1.01 : 1.0
|
||||
transformOrigin: Item.Center
|
||||
|
||||
@@ -375,13 +468,25 @@ PanelWindow {
|
||||
}
|
||||
|
||||
property real swipeOffset: 0
|
||||
readonly property real dismissThreshold: isCenterPosition ? height * 0.4 : width * 0.35
|
||||
property real swipeDismissDirection: 1
|
||||
property bool chromeOnlyExit: false
|
||||
readonly property real dismissThreshold: width * 0.35
|
||||
readonly property real swipeFadeStartRatio: 0.75
|
||||
readonly property real swipeTravelDistance: isCenterPosition ? height : width
|
||||
readonly property real swipeTravelDistance: width
|
||||
readonly property real swipeFadeStartOffset: swipeTravelDistance * swipeFadeStartRatio
|
||||
readonly property real swipeFadeDistance: Math.max(1, swipeTravelDistance - swipeFadeStartOffset)
|
||||
readonly property bool swipeActive: swipeDragHandler.active
|
||||
property bool swipeDismissing: false
|
||||
onSwipeDismissingChanged: {
|
||||
if (!win.connectedFrameMode)
|
||||
return;
|
||||
win.popupHeightChanged();
|
||||
win.popupChromeGeometryChanged();
|
||||
}
|
||||
onSwipeOffsetChanged: {
|
||||
if (win.connectedFrameMode)
|
||||
win.popupChromeGeometryChanged();
|
||||
}
|
||||
|
||||
readonly property bool shadowsAllowed: Theme.elevationEnabled && SettingsData.notificationPopupShadowEnabled
|
||||
readonly property var elevLevel: cardHoverHandler.hovered ? Theme.elevationLevel4 : Theme.elevationLevel3
|
||||
@@ -422,7 +527,7 @@ PanelWindow {
|
||||
shadowOffsetX: content.shadowOffsetX
|
||||
shadowOffsetY: content.shadowOffsetY
|
||||
shadowColor: content.shadowsAllowed && content.elevLevel ? Theme.elevationShadowColor(content.elevLevel) : "transparent"
|
||||
shadowEnabled: !win._isDestroying && win.screenValid && content.shadowsAllowed
|
||||
shadowEnabled: !win._isDestroying && win.screenValid && content.shadowsAllowed && !win.connectedFrameMode
|
||||
layer.textureSize: Qt.size(Math.round(width * win.dpr), Math.round(height * win.dpr))
|
||||
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
||||
|
||||
@@ -431,8 +536,12 @@ PanelWindow {
|
||||
sourceRect.y: content.shadowRenderPadding + content.cardInset
|
||||
sourceRect.width: Math.max(0, content.width - (content.cardInset * 2))
|
||||
sourceRect.height: Math.max(0, content.height - (content.cardInset * 2))
|
||||
sourceRect.radius: Theme.cornerRadius
|
||||
sourceRect.color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||
sourceRect.radius: win.connectedFrameMode ? Theme.connectedSurfaceRadius : Theme.cornerRadius
|
||||
sourceRect.color: win.connectedFrameMode ? Theme.popupLayerColor(Theme.surfaceContainer) : Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||
sourceRect.antialiasing: true
|
||||
sourceRect.layer.enabled: win.connectedFrameMode
|
||||
sourceRect.layer.smooth: true
|
||||
sourceRect.layer.textureSize: win.connectedFrameMode && win.dpr > 1 ? Qt.size(Math.ceil(sourceRect.width * win.dpr), Math.ceil(sourceRect.height * win.dpr)) : Qt.size(0, 0)
|
||||
sourceRect.border.color: notificationData && notificationData.urgency === NotificationUrgency.Critical ? Theme.withAlpha(Theme.primary, 0.3) : Theme.withAlpha(Theme.outline, 0.08)
|
||||
sourceRect.border.width: notificationData && notificationData.urgency === NotificationUrgency.Critical ? 2 : 0
|
||||
|
||||
@@ -470,10 +579,10 @@ PanelWindow {
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: content.cardInset
|
||||
radius: Theme.cornerRadius
|
||||
radius: win.connectedFrameMode ? Theme.connectedSurfaceRadius : Theme.cornerRadius
|
||||
color: "transparent"
|
||||
border.color: BlurService.borderColor
|
||||
border.width: BlurService.borderWidth
|
||||
border.color: win.connectedFrameMode ? "transparent" : BlurService.borderColor
|
||||
border.width: win.connectedFrameMode ? 0 : BlurService.borderWidth
|
||||
z: 100
|
||||
}
|
||||
|
||||
@@ -873,14 +982,15 @@ PanelWindow {
|
||||
DragHandler {
|
||||
id: swipeDragHandler
|
||||
target: null
|
||||
xAxis.enabled: !isCenterPosition
|
||||
yAxis.enabled: isCenterPosition
|
||||
xAxis.enabled: true
|
||||
yAxis.enabled: false
|
||||
|
||||
onActiveChanged: {
|
||||
if (active || win.exiting || content.swipeDismissing)
|
||||
return;
|
||||
|
||||
if (Math.abs(content.swipeOffset) > content.dismissThreshold) {
|
||||
content.swipeDismissDirection = content.swipeOffset < 0 ? -1 : 1;
|
||||
content.swipeDismissing = true;
|
||||
swipeDismissAnim.start();
|
||||
} else {
|
||||
@@ -892,15 +1002,7 @@ PanelWindow {
|
||||
if (win.exiting)
|
||||
return;
|
||||
|
||||
const raw = isCenterPosition ? translation.y : translation.x;
|
||||
if (isTopCenter) {
|
||||
content.swipeOffset = Math.min(0, raw);
|
||||
} else if (isBottomCenter) {
|
||||
content.swipeOffset = Math.max(0, raw);
|
||||
} else {
|
||||
const isLeft = SettingsData.notificationPopupPosition === SettingsData.Position.Left || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom;
|
||||
content.swipeOffset = isLeft ? Math.min(0, raw) : Math.max(0, raw);
|
||||
}
|
||||
content.swipeOffset = translation.x;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -931,20 +1033,28 @@ PanelWindow {
|
||||
id: swipeDismissAnim
|
||||
target: content
|
||||
property: "swipeOffset"
|
||||
to: isTopCenter ? -content.height : isBottomCenter ? content.height : (SettingsData.notificationPopupPosition === SettingsData.Position.Left || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom ? -content.width : content.width)
|
||||
to: win._swipeDismissTarget()
|
||||
duration: Theme.notificationExitDuration
|
||||
easing.type: Easing.OutCubic
|
||||
onStopped: {
|
||||
NotificationService.dismissNotification(notificationData);
|
||||
win.forceExit();
|
||||
const inwardConnectedExit = win.connectedFrameMode && !win.isCenterPosition && !win._swipeDismissesTowardFrameEdge();
|
||||
if (inwardConnectedExit)
|
||||
content.chromeOnlyExit = true;
|
||||
if (win.connectedFrameMode && (win.isCenterPosition || inwardConnectedExit)) {
|
||||
win.startExit();
|
||||
NotificationService.dismissNotification(notificationData);
|
||||
} else {
|
||||
NotificationService.dismissNotification(notificationData);
|
||||
win.forceExit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
transform: [
|
||||
Translate {
|
||||
id: swipeTx
|
||||
x: isCenterPosition ? 0 : content.swipeOffset
|
||||
y: isCenterPosition ? content.swipeOffset : 0
|
||||
x: content.swipeOffset
|
||||
y: 0
|
||||
},
|
||||
Translate {
|
||||
id: tx
|
||||
@@ -955,6 +1065,14 @@ PanelWindow {
|
||||
return isLeft ? -entryTravel : entryTravel;
|
||||
}
|
||||
y: isTopCenter ? -entryTravel : isBottomCenter ? entryTravel : 0
|
||||
onXChanged: {
|
||||
if (win.connectedFrameMode)
|
||||
win.popupChromeGeometryChanged();
|
||||
}
|
||||
onYChanged: {
|
||||
if (win.connectedFrameMode)
|
||||
win.popupChromeGeometryChanged();
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -8,24 +8,40 @@ QtObject {
|
||||
property var modelData
|
||||
property int topMargin: 0
|
||||
readonly property bool compactMode: SettingsData.notificationCompactMode
|
||||
readonly property bool connectedFrameMode: SettingsData.connectedFrameModeActive
|
||||
readonly property bool notificationConnectedMode: SettingsData.frameEnabled
|
||||
&& Theme.isConnectedEffect
|
||||
&& SettingsData.isScreenInPreferences(manager.modelData, SettingsData.frameScreenPreferences)
|
||||
readonly property string notifBarSide: {
|
||||
const pos = SettingsData.notificationPopupPosition;
|
||||
if (pos === -1) return "top";
|
||||
switch (pos) {
|
||||
case SettingsData.Position.Top: return "right";
|
||||
case SettingsData.Position.Left: return "left";
|
||||
case SettingsData.Position.BottomCenter: return "bottom";
|
||||
case SettingsData.Position.Right: return "right";
|
||||
case SettingsData.Position.Bottom: return "left";
|
||||
default: return "top";
|
||||
}
|
||||
}
|
||||
readonly property real cardPadding: compactMode ? Theme.notificationCardPaddingCompact : Theme.notificationCardPadding
|
||||
readonly property real popupIconSize: compactMode ? Theme.notificationIconSizeCompact : Theme.notificationIconSizeNormal
|
||||
readonly property real actionButtonHeight: compactMode ? 20 : 24
|
||||
readonly property real contentSpacing: compactMode ? Theme.spacingXS : Theme.spacingS
|
||||
readonly property real popupSpacing: connectedFrameMode ? 0 : (compactMode ? 0 : Theme.spacingXS)
|
||||
readonly property real popupSpacing: notificationConnectedMode ? 0 : (compactMode ? 0 : Theme.spacingXS)
|
||||
readonly property real collapsedContentHeight: Math.max(popupIconSize, Theme.fontSizeSmall * 1.2 + Theme.fontSizeMedium * 1.2 + Theme.fontSizeSmall * 1.2 * (compactMode ? 1 : 2))
|
||||
readonly property int baseNotificationHeight: cardPadding * 2 + collapsedContentHeight + actionButtonHeight + contentSpacing + popupSpacing
|
||||
property var popupWindows: []
|
||||
property var destroyingWindows: new Set()
|
||||
property var pendingDestroys: []
|
||||
property int destroyDelayMs: 100
|
||||
property bool _chromeSyncPending: false
|
||||
property Component popupComponent
|
||||
|
||||
popupComponent: Component {
|
||||
NotificationPopup {
|
||||
onExitFinished: manager._onPopupExitFinished(this)
|
||||
onPopupHeightChanged: manager._onPopupHeightChanged(this)
|
||||
onPopupChromeGeometryChanged: manager._onPopupChromeGeometryChanged(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +125,14 @@ QtObject {
|
||||
return p && p.status !== Component.Null && !p._isDestroying && p.hasValidData;
|
||||
}
|
||||
|
||||
function _layoutWindows() {
|
||||
return popupWindows.filter(p => _isValidWindow(p) && p.notificationData?.popup && !p.exiting && (!p.popupLayoutReservesSlot || p.popupLayoutReservesSlot()));
|
||||
}
|
||||
|
||||
function _chromeWindows() {
|
||||
return popupWindows.filter(p => p && p.status !== Component.Null && p.visible && !p._finalized && p.hasValidData && (p.notificationData?.popup || p.exiting));
|
||||
}
|
||||
|
||||
function _isFocusedScreen() {
|
||||
if (!SettingsData.notificationFocusedMonitor)
|
||||
return true;
|
||||
@@ -117,18 +141,24 @@ QtObject {
|
||||
}
|
||||
|
||||
function _sync(newWrappers) {
|
||||
let needsReposition = false;
|
||||
for (const p of popupWindows.slice()) {
|
||||
if (!_isValidWindow(p) || p.exiting)
|
||||
continue;
|
||||
if (p.notificationData && newWrappers.indexOf(p.notificationData) === -1) {
|
||||
p.notificationData.removedByLimit = true;
|
||||
p.notificationData.popup = false;
|
||||
needsReposition = true;
|
||||
}
|
||||
}
|
||||
for (const w of newWrappers) {
|
||||
if (w && !_hasWindowFor(w) && _isFocusedScreen())
|
||||
if (w && !_hasWindowFor(w) && _isFocusedScreen()) {
|
||||
_insertAtTop(w);
|
||||
needsReposition = false;
|
||||
}
|
||||
}
|
||||
if (needsReposition)
|
||||
_repositionAll();
|
||||
}
|
||||
|
||||
function _popupHeight(p) {
|
||||
@@ -158,7 +188,7 @@ QtObject {
|
||||
}
|
||||
|
||||
function _repositionAll() {
|
||||
const active = popupWindows.filter(p => _isValidWindow(p) && p.notificationData?.popup && !p.exiting);
|
||||
const active = _layoutWindows();
|
||||
|
||||
const pinnedSlots = [];
|
||||
for (const p of active) {
|
||||
@@ -182,6 +212,168 @@ QtObject {
|
||||
win.screenY = currentY;
|
||||
currentY += _popupHeight(win);
|
||||
}
|
||||
_scheduleNotificationChromeSync();
|
||||
}
|
||||
|
||||
function _scheduleNotificationChromeSync() {
|
||||
if (_chromeSyncPending)
|
||||
return;
|
||||
_chromeSyncPending = true;
|
||||
Qt.callLater(() => {
|
||||
_chromeSyncPending = false;
|
||||
_syncNotificationChromeState();
|
||||
});
|
||||
}
|
||||
|
||||
function _popupChromeRect(p, useMotionOffset) {
|
||||
if (!p || !p.screen)
|
||||
return null;
|
||||
const motionX = useMotionOffset && p.popupChromeMotionX ? p.popupChromeMotionX() : 0;
|
||||
const motionY = useMotionOffset && p.popupChromeMotionY ? p.popupChromeMotionY() : 0;
|
||||
const x = (p.getContentX ? p.getContentX() : 0) + motionX;
|
||||
const y = (p.getContentY ? p.getContentY() : 0) + motionY;
|
||||
const w = p.alignedWidth || 0;
|
||||
const h = Math.max(p.alignedHeight || 0, baseNotificationHeight);
|
||||
if (w <= 0 || h <= 0)
|
||||
return null;
|
||||
return {
|
||||
x: x,
|
||||
y: y,
|
||||
right: x + w,
|
||||
bottom: y + h
|
||||
};
|
||||
}
|
||||
|
||||
function _popupChromeBoundsRect(p, trailing, useMotionOffset) {
|
||||
const rect = _popupChromeRect(p, useMotionOffset);
|
||||
if (!rect || p !== trailing || !p.popupChromeReleaseProgress)
|
||||
return rect;
|
||||
|
||||
const progress = Math.max(0, Math.min(1, p.popupChromeReleaseProgress()));
|
||||
if (progress <= 0)
|
||||
return rect;
|
||||
|
||||
const anchorsTop = _stackAnchorsTop();
|
||||
const h = Math.max(0, rect.bottom - rect.y);
|
||||
const shrink = h * progress;
|
||||
if (anchorsTop)
|
||||
rect.bottom = Math.max(rect.y, rect.bottom - shrink);
|
||||
else
|
||||
rect.y = Math.min(rect.bottom, rect.y + shrink);
|
||||
return rect;
|
||||
}
|
||||
|
||||
function _stackAnchorsTop() {
|
||||
const pos = SettingsData.notificationPopupPosition;
|
||||
return pos === -1 || pos === SettingsData.Position.Top || pos === SettingsData.Position.Left;
|
||||
}
|
||||
|
||||
function _trailingChromeWindow(candidates) {
|
||||
const anchorsTop = _stackAnchorsTop();
|
||||
let trailing = null;
|
||||
let edge = anchorsTop ? -Infinity : Infinity;
|
||||
for (const p of candidates) {
|
||||
const rect = _popupChromeRect(p, false);
|
||||
if (!rect)
|
||||
continue;
|
||||
const candidateEdge = anchorsTop ? rect.bottom : rect.y;
|
||||
if ((anchorsTop && candidateEdge > edge) || (!anchorsTop && candidateEdge < edge)) {
|
||||
edge = candidateEdge;
|
||||
trailing = p;
|
||||
}
|
||||
}
|
||||
return trailing;
|
||||
}
|
||||
|
||||
function _chromeWindowReservesSlot(p, trailing) {
|
||||
if (p === trailing)
|
||||
return true;
|
||||
return !p.popupChromeReservesSlot || p.popupChromeReservesSlot();
|
||||
}
|
||||
|
||||
function _stackAnchoredChromeEdge(candidates) {
|
||||
const anchorsTop = _stackAnchorsTop();
|
||||
let edge = anchorsTop ? Infinity : -Infinity;
|
||||
for (const p of candidates) {
|
||||
const rect = _popupChromeRect(p, false);
|
||||
if (!rect)
|
||||
continue;
|
||||
if (anchorsTop && rect.y < edge)
|
||||
edge = rect.y;
|
||||
if (!anchorsTop && rect.bottom > edge)
|
||||
edge = rect.bottom;
|
||||
}
|
||||
if (edge === Infinity || edge === -Infinity)
|
||||
return null;
|
||||
return {
|
||||
anchorsTop: anchorsTop,
|
||||
edge: edge
|
||||
};
|
||||
}
|
||||
|
||||
function _syncNotificationChromeState() {
|
||||
const screenName = manager.modelData?.name || "";
|
||||
if (!screenName)
|
||||
return;
|
||||
if (!notificationConnectedMode) {
|
||||
ConnectedModeState.clearNotificationState(screenName);
|
||||
return;
|
||||
}
|
||||
const chromeCandidates = _chromeWindows();
|
||||
if (chromeCandidates.length === 0) {
|
||||
ConnectedModeState.clearNotificationState(screenName);
|
||||
return;
|
||||
}
|
||||
const trailing = chromeCandidates.length > 1 ? _trailingChromeWindow(chromeCandidates) : null;
|
||||
let active = chromeCandidates;
|
||||
if (chromeCandidates.length > 1) {
|
||||
const reserving = chromeCandidates.filter(p => _chromeWindowReservesSlot(p, trailing));
|
||||
if (reserving.length > 0)
|
||||
active = reserving;
|
||||
}
|
||||
let minX = Infinity;
|
||||
let minY = Infinity;
|
||||
let maxXEnd = -Infinity;
|
||||
let maxYEnd = -Infinity;
|
||||
const useMotionOffset = active.length === 1 && active[0].popupChromeMotionActive && active[0].popupChromeMotionActive();
|
||||
for (const p of active) {
|
||||
const rect = _popupChromeBoundsRect(p, trailing, useMotionOffset);
|
||||
if (!rect)
|
||||
continue;
|
||||
if (rect.x < minX)
|
||||
minX = rect.x;
|
||||
if (rect.y < minY)
|
||||
minY = rect.y;
|
||||
if (rect.right > maxXEnd)
|
||||
maxXEnd = rect.right;
|
||||
if (rect.bottom > maxYEnd)
|
||||
maxYEnd = rect.bottom;
|
||||
}
|
||||
const stackEdge = _stackAnchoredChromeEdge(chromeCandidates);
|
||||
if (stackEdge !== null) {
|
||||
if (stackEdge.anchorsTop && stackEdge.edge < minY)
|
||||
minY = stackEdge.edge;
|
||||
if (!stackEdge.anchorsTop && stackEdge.edge > maxYEnd)
|
||||
maxYEnd = stackEdge.edge;
|
||||
}
|
||||
if (minX === Infinity || minY === Infinity || maxXEnd <= minX || maxYEnd <= minY) {
|
||||
ConnectedModeState.clearNotificationState(screenName);
|
||||
return;
|
||||
}
|
||||
ConnectedModeState.setNotificationState(screenName, {
|
||||
visible: true,
|
||||
barSide: notifBarSide,
|
||||
bodyX: minX,
|
||||
bodyY: minY,
|
||||
bodyW: maxXEnd - minX,
|
||||
bodyH: maxYEnd - minY
|
||||
});
|
||||
}
|
||||
|
||||
function _onPopupChromeGeometryChanged(p) {
|
||||
if (!p || popupWindows.indexOf(p) === -1)
|
||||
return;
|
||||
_scheduleNotificationChromeSync();
|
||||
}
|
||||
|
||||
function _onPopupHeightChanged(p) {
|
||||
@@ -228,8 +420,15 @@ QtObject {
|
||||
}
|
||||
popupWindows = [];
|
||||
destroyingWindows.clear();
|
||||
_chromeSyncPending = false;
|
||||
_syncNotificationChromeState();
|
||||
}
|
||||
|
||||
onNotificationConnectedModeChanged: _scheduleNotificationChromeSync()
|
||||
onNotifBarSideChanged: _scheduleNotificationChromeSync()
|
||||
onModelDataChanged: _scheduleNotificationChromeSync()
|
||||
onTopMarginChanged: _repositionAll()
|
||||
|
||||
onPopupWindowsChanged: {
|
||||
if (popupWindows.length > 0 && !sweeper.running) {
|
||||
sweeper.start();
|
||||
|
||||
@@ -114,7 +114,7 @@ Item {
|
||||
}
|
||||
radiusX: root._cr
|
||||
radiusY: root._cr
|
||||
direction: PathArc.Counterclockwise
|
||||
direction: root.barSide === "bottom" ? PathArc.Clockwise : PathArc.Counterclockwise
|
||||
}
|
||||
|
||||
// Body edge to first convex corner
|
||||
@@ -169,7 +169,7 @@ Item {
|
||||
}
|
||||
radiusX: root._sr
|
||||
radiusY: root._sr
|
||||
direction: PathArc.Clockwise
|
||||
direction: root.barSide === "bottom" ? PathArc.Counterclockwise : PathArc.Clockwise
|
||||
}
|
||||
|
||||
// Far edge
|
||||
@@ -224,7 +224,7 @@ Item {
|
||||
}
|
||||
radiusX: root._sr
|
||||
radiusY: root._sr
|
||||
direction: PathArc.Clockwise
|
||||
direction: root.barSide === "bottom" ? PathArc.Counterclockwise : PathArc.Clockwise
|
||||
}
|
||||
|
||||
// Body edge to second concave arc
|
||||
@@ -279,7 +279,7 @@ Item {
|
||||
}
|
||||
radiusX: root._cr
|
||||
radiusY: root._cr
|
||||
direction: PathArc.Counterclockwise
|
||||
direction: root.barSide === "bottom" ? PathArc.Clockwise : PathArc.Counterclockwise
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user