import QtQuick import Quickshell import qs.Commons import qs.Services.UI /** * PanelPlaceholder - Lightweight positioning logic for panel backgrounds * * This component stays in MainScreen and provides geometry for PanelBackground rendering. * It contains only positioning calculations and animations, no visual content. * The actual panel content lives in a separate SmartPanelWindow. */ Item { id: root // Required properties required property ShellScreen screen required property string panelName // Unique identifier // Panel size properties property real preferredWidth: 700 property real preferredHeight: 900 property real preferredWidthRatio property real preferredHeightRatio property var buttonItem: null property bool forceAttachToBar: false // Anchoring properties property bool panelAnchorHorizontalCenter: false property bool panelAnchorVerticalCenter: false property bool panelAnchorTop: false property bool panelAnchorBottom: false property bool panelAnchorLeft: false property bool panelAnchorRight: false // Button position properties property bool useButtonPosition: false property point buttonPosition: Qt.point(0, 0) property int buttonWidth: 0 property int buttonHeight: 0 // Edge snapping distance property real edgeSnapDistance: 50 // State tracking (controlled by SmartPanelWindow) property bool isPanelVisible: false property bool isClosing: false property bool opacityFadeComplete: false // Content size (set by SmartPanelWindow when content size changes) property real contentPreferredWidth: 0 property real contentPreferredHeight: 0 // Expose panelBackground as panelItem for AllBackgrounds readonly property var panelItem: panelBackground // Bar configuration readonly property string barPosition: Settings.data.bar.position readonly property bool barIsVertical: barPosition === "left" || barPosition === "right" readonly property bool barFloating: Settings.data.bar.floating readonly property real barMarginH: barFloating ? Settings.data.bar.marginHorizontal * Style.marginXL : 0 readonly property real barMarginV: barFloating ? Settings.data.bar.marginVertical * Style.marginXL : 0 // Helper to detect if any anchor is explicitly set readonly property bool hasExplicitHorizontalAnchor: panelAnchorHorizontalCenter || panelAnchorLeft || panelAnchorRight readonly property bool hasExplicitVerticalAnchor: panelAnchorVerticalCenter || panelAnchorTop || panelAnchorBottom // Attachment properties readonly property bool allowAttach: Settings.data.ui.panelsAttachedToBar || root.forceAttachToBar readonly property bool allowAttachToBar: { if (!(Settings.data.ui.panelsAttachedToBar || root.forceAttachToBar) || Settings.data.bar.backgroundOpacity < 1.0) { return false } // A panel can only be attached to a bar if there is a bar on that screen var monitors = Settings.data.bar.monitors || [] var result = monitors.length === 0 || monitors.includes(root.screen?.name || "") return result } // Effective anchor properties (depend on allowAttach) readonly property bool effectivePanelAnchorTop: panelAnchorTop || (useButtonPosition && barPosition === "top") || (allowAttach && !hasExplicitVerticalAnchor && barPosition === "top" && !barIsVertical) readonly property bool effectivePanelAnchorBottom: panelAnchorBottom || (useButtonPosition && barPosition === "bottom") || (allowAttach && !hasExplicitVerticalAnchor && barPosition === "bottom" && !barIsVertical) readonly property bool effectivePanelAnchorLeft: panelAnchorLeft || (useButtonPosition && barPosition === "left") || (allowAttach && !hasExplicitHorizontalAnchor && barPosition === "left" && barIsVertical) readonly property bool effectivePanelAnchorRight: panelAnchorRight || (useButtonPosition && barPosition === "right") || (allowAttach && !hasExplicitHorizontalAnchor && barPosition === "right" && barIsVertical) // Panel dimensions and visibility visible: isPanelVisible width: parent ? parent.width : 0 height: parent ? parent.height : 0 // Update position when UI scale changes Connections { target: Style function onUiScaleRatioChanged() { if (root.isPanelVisible) { root.setPosition() } } } // Public function to update content size from SmartPanelWindow function updateContentSize(w, h) { contentPreferredWidth = w contentPreferredHeight = h if (isPanelVisible) { setPosition() } } // Main positioning calculation function function setPosition() { // Don't calculate position if parent dimensions aren't available yet if (!root.width || !root.height) { Logger.d("PanelPlaceholder", "Skipping setPosition - dimensions not ready:", root.width, "x", root.height, panelName) Qt.callLater(setPosition) return } // Calculate panel dimensions first (needed for positioning) var w // Priority 1: Content-driven size (dynamic) if (contentPreferredWidth > 0) { w = contentPreferredWidth } // Priority 2: Ratio-based size else if (root.preferredWidthRatio !== undefined) { w = Math.round(Math.max(root.width * root.preferredWidthRatio, root.preferredWidth)) } // Priority 3: Static preferred width else { w = root.preferredWidth } var panelWidth = Math.min(w, root.width - Style.marginL * 2) var h // Priority 1: Content-driven size (dynamic) if (contentPreferredHeight > 0) { h = contentPreferredHeight } // Priority 2: Ratio-based size else if (root.preferredHeightRatio !== undefined) { h = Math.round(Math.max(root.height * root.preferredHeightRatio, root.preferredHeight)) } // Priority 3: Static preferred height else { h = root.preferredHeight } var panelHeight = Math.min(h, root.height - Style.barHeight - Style.marginL * 2) // Update panelBackground target size (will be animated) panelBackground.targetWidth = panelWidth panelBackground.targetHeight = panelHeight // Calculate position var calculatedX var calculatedY // ===== X POSITIONING ===== if (root.useButtonPosition && root.width > 0 && panelWidth > 0) { if (root.barIsVertical) { // For vertical bars if (allowAttach) { // Attached panels: align with bar edge (left or right side) if (root.barPosition === "left") { var leftBarEdge = root.barMarginH + Style.barHeight calculatedX = leftBarEdge } else { // right var rightBarEdge = root.width - root.barMarginH - Style.barHeight calculatedX = rightBarEdge - panelWidth } } else { // Detached panels: center on button X position var panelX = root.buttonPosition.x + root.buttonWidth / 2 - panelWidth / 2 var minX = Style.marginL var maxX = root.width - panelWidth - Style.marginL // Account for vertical bar taking up space if (root.barPosition === "left") { minX = root.barMarginH + Style.barHeight + Style.marginL } else if (root.barPosition === "right") { maxX = root.width - root.barMarginH - Style.barHeight - panelWidth - Style.marginL } panelX = Math.max(minX, Math.min(panelX, maxX)) calculatedX = panelX } } else { // For horizontal bars, center panel on button X position var panelX = root.buttonPosition.x + root.buttonWidth / 2 - panelWidth / 2 if (allowAttach) { var cornerInset = root.barFloating ? Style.radiusL * 2 : 0 var barLeftEdge = root.barMarginH + cornerInset var barRightEdge = root.width - root.barMarginH - cornerInset panelX = Math.max(barLeftEdge, Math.min(panelX, barRightEdge - panelWidth)) } else { panelX = Math.max(Style.marginL, Math.min(panelX, root.width - panelWidth - Style.marginL)) } calculatedX = panelX } } else { // Standard anchor positioning if (root.panelAnchorHorizontalCenter) { if (root.barIsVertical) { if (root.barPosition === "left") { var availableStart = root.barMarginH + Style.barHeight var availableWidth = root.width - availableStart calculatedX = availableStart + (availableWidth - panelWidth) / 2 } else if (root.barPosition === "right") { var availableWidth = root.width - root.barMarginH - Style.barHeight calculatedX = (availableWidth - panelWidth) / 2 } else { calculatedX = (root.width - panelWidth) / 2 } } else { calculatedX = (root.width - panelWidth) / 2 } } else if (root.effectivePanelAnchorRight) { if (allowAttach && root.barIsVertical && root.barPosition === "right") { var rightBarEdge = root.width - root.barMarginH - Style.barHeight calculatedX = rightBarEdge - panelWidth } else if (allowAttach) { // Account for corner inset when bar is floating, horizontal, AND panel is on same edge as bar var panelOnSameEdgeAsBar = (root.barPosition === "top" && root.effectivePanelAnchorTop) || (root.barPosition === "bottom" && root.effectivePanelAnchorBottom) if (!root.barIsVertical && root.barFloating && panelOnSameEdgeAsBar) { var rightCornerInset = Style.radiusL * 2 calculatedX = root.width - root.barMarginH - rightCornerInset - panelWidth } else { calculatedX = root.width - panelWidth } } else { calculatedX = root.width - panelWidth - Style.marginL } } else if (root.effectivePanelAnchorLeft) { if (allowAttach && root.barIsVertical && root.barPosition === "left") { var leftBarEdge = root.barMarginH + Style.barHeight calculatedX = leftBarEdge } else if (allowAttach) { // Account for corner inset when bar is floating, horizontal, AND panel is on same edge as bar var panelOnSameEdgeAsBar = (root.barPosition === "top" && root.effectivePanelAnchorTop) || (root.barPosition === "bottom" && root.effectivePanelAnchorBottom) if (!root.barIsVertical && root.barFloating && panelOnSameEdgeAsBar) { var leftCornerInset = Style.radiusL * 2 calculatedX = root.barMarginH + leftCornerInset } else { calculatedX = 0 } } else { calculatedX = Style.marginL } } else { // No explicit anchor: default to centering on bar if (root.barIsVertical) { if (root.barPosition === "left") { var availableStart = root.barMarginH + Style.barHeight var availableWidth = root.width - availableStart - Style.marginL calculatedX = availableStart + (availableWidth - panelWidth) / 2 } else { var availableWidth = root.width - root.barMarginH - Style.barHeight - Style.marginL calculatedX = Style.marginL + (availableWidth - panelWidth) / 2 } } else { if (allowAttach) { var cornerInset = Style.radiusL + (root.barFloating ? Style.radiusL : 0) var barLeftEdge = root.barMarginH + cornerInset var barRightEdge = root.width - root.barMarginH - cornerInset var centeredX = (root.width - panelWidth) / 2 calculatedX = Math.max(barLeftEdge, Math.min(centeredX, barRightEdge - panelWidth)) } else { calculatedX = (root.width - panelWidth) / 2 } } } } // Edge snapping for X if (allowAttach && !root.barFloating && root.width > 0 && panelWidth > 0) { var leftEdgePos = root.barMarginH if (root.barPosition === "left") { leftEdgePos = root.barMarginH + Style.barHeight } var rightEdgePos = root.width - root.barMarginH - panelWidth if (root.barPosition === "right") { rightEdgePos = root.width - root.barMarginH - Style.barHeight - panelWidth } // Only snap to left edge if panel is actually meant to be at left var shouldSnapToLeft = root.effectivePanelAnchorLeft || (!root.hasExplicitHorizontalAnchor && root.barPosition === "left") // Only snap to right edge if panel is actually meant to be at right var shouldSnapToRight = root.effectivePanelAnchorRight || (!root.hasExplicitHorizontalAnchor && root.barPosition === "right") if (shouldSnapToLeft && Math.abs(calculatedX - leftEdgePos) <= root.edgeSnapDistance) { calculatedX = leftEdgePos } else if (shouldSnapToRight && Math.abs(calculatedX - rightEdgePos) <= root.edgeSnapDistance) { calculatedX = rightEdgePos } } // ===== Y POSITIONING ===== if (root.useButtonPosition && root.height > 0 && panelHeight > 0) { if (root.barPosition === "top") { var topBarEdge = root.barMarginV + Style.barHeight if (allowAttach) { calculatedY = topBarEdge } else { calculatedY = topBarEdge + Style.marginM } } else if (root.barPosition === "bottom") { var bottomBarEdge = root.height - root.barMarginV - Style.barHeight if (allowAttach) { calculatedY = bottomBarEdge - panelHeight } else { calculatedY = bottomBarEdge - panelHeight - Style.marginM } } else if (root.barIsVertical) { var panelY = root.buttonPosition.y + root.buttonHeight / 2 - panelHeight / 2 var extraPadding = (allowAttach && root.barFloating) ? Style.radiusL : 0 if (allowAttach) { var cornerInset = extraPadding + (root.barFloating ? Style.radiusL : 0) var barTopEdge = root.barMarginV + cornerInset var barBottomEdge = root.height - root.barMarginV - cornerInset panelY = Math.max(barTopEdge, Math.min(panelY, barBottomEdge - panelHeight)) } else { panelY = Math.max(Style.marginL + extraPadding, Math.min(panelY, root.height - panelHeight - Style.marginL - extraPadding)) } calculatedY = panelY } } else { // Standard anchor positioning var barOffset = 0 if (!allowAttach) { if (root.barPosition === "top") { barOffset = root.barMarginV + Style.barHeight + Style.marginM } else if (root.barPosition === "bottom") { barOffset = root.barMarginV + Style.barHeight + Style.marginM } } else { if (root.effectivePanelAnchorTop && root.barPosition === "top") { calculatedY = root.barMarginV + Style.barHeight } else if (root.effectivePanelAnchorBottom && root.barPosition === "bottom") { calculatedY = root.height - root.barMarginV - Style.barHeight - panelHeight } else if (!root.hasExplicitVerticalAnchor) { if (root.barPosition === "top") { calculatedY = root.barMarginV + Style.barHeight } else if (root.barPosition === "bottom") { calculatedY = root.height - root.barMarginV - Style.barHeight - panelHeight } } } if (calculatedY === undefined) { if (root.panelAnchorVerticalCenter) { if (!root.barIsVertical) { if (root.barPosition === "top") { var availableStart = root.barMarginV + Style.barHeight var availableHeight = root.height - availableStart calculatedY = availableStart + (availableHeight - panelHeight) / 2 } else if (root.barPosition === "bottom") { var availableHeight = root.height - root.barMarginV - Style.barHeight calculatedY = (availableHeight - panelHeight) / 2 } else { calculatedY = (root.height - panelHeight) / 2 } } else { calculatedY = (root.height - panelHeight) / 2 } } else if (root.effectivePanelAnchorTop) { if (allowAttach) { calculatedY = 0 } else { var topBarOffset = (root.barPosition === "top") ? barOffset : 0 calculatedY = topBarOffset + Style.marginL } } else if (root.effectivePanelAnchorBottom) { if (allowAttach) { calculatedY = root.height - panelHeight } else { var bottomBarOffset = (root.barPosition === "bottom") ? barOffset : 0 calculatedY = root.height - panelHeight - bottomBarOffset - Style.marginL } } else { if (root.barIsVertical) { if (allowAttach) { var cornerInset = root.barFloating ? Style.radiusL * 2 : 0 var barTopEdge = root.barMarginV + cornerInset var barBottomEdge = root.height - root.barMarginV - cornerInset var centeredY = (root.height - panelHeight) / 2 calculatedY = Math.max(barTopEdge, Math.min(centeredY, barBottomEdge - panelHeight)) } else { calculatedY = (root.height - panelHeight) / 2 } } else { if (allowAttach && !root.barIsVertical) { if (root.barPosition === "top") { calculatedY = root.barMarginV + Style.barHeight } else if (root.barPosition === "bottom") { calculatedY = root.height - root.barMarginV - Style.barHeight - panelHeight } } else { if (root.barPosition === "top") { calculatedY = barOffset + Style.marginL } else if (root.barPosition === "bottom") { calculatedY = Style.marginL } else { calculatedY = Style.marginL } } } } } } // Edge snapping for Y if (allowAttach && !root.barFloating && root.height > 0 && panelHeight > 0) { var topEdgePos = root.barMarginV if (root.barPosition === "top") { topEdgePos = root.barMarginV + Style.barHeight } var bottomEdgePos = root.height - root.barMarginV - panelHeight if (root.barPosition === "bottom") { bottomEdgePos = root.height - root.barMarginV - Style.barHeight - panelHeight } // Only snap to top edge if panel is actually meant to be at top var shouldSnapToTop = root.effectivePanelAnchorTop || (!root.hasExplicitVerticalAnchor && root.barPosition === "top") // Only snap to bottom edge if panel is actually meant to be at bottom var shouldSnapToBottom = root.effectivePanelAnchorBottom || (!root.hasExplicitVerticalAnchor && root.barPosition === "bottom") if (shouldSnapToTop && Math.abs(calculatedY - topEdgePos) <= root.edgeSnapDistance) { calculatedY = topEdgePos } else if (shouldSnapToBottom && Math.abs(calculatedY - bottomEdgePos) <= root.edgeSnapDistance) { calculatedY = bottomEdgePos } } // Apply calculated positions (set targets for animation) panelBackground.targetX = calculatedX panelBackground.targetY = calculatedY Logger.d("PanelPlaceholder", "Position calculated:", calculatedX, calculatedY, panelName) Logger.d("PanelPlaceholder", " Panel size:", panelWidth, "x", panelHeight) } // The panel background geometry item Item { id: panelBackground // Store target dimensions (set by setPosition()) property real targetWidth: root.preferredWidth property real targetHeight: root.preferredHeight property real targetX: 0 property real targetY: 0 property var bezierCurve: [0.05, 0, 0.133, 0.06, 0.166, 0.4, 0.208, 0.82, 0.25, 1, 1, 1] // Edge detection readonly property bool touchingLeftEdge: allowAttach && panelBackground.x <= 1 readonly property bool touchingRightEdge: allowAttach && (panelBackground.x + panelBackground.width) >= (root.width - 1) readonly property bool touchingTopEdge: allowAttach && panelBackground.y <= 1 readonly property bool touchingBottomEdge: allowAttach && (panelBackground.y + panelBackground.height) >= (root.height - 1) // Bar edge detection readonly property bool touchingTopBar: allowAttachToBar && root.barPosition === "top" && !root.barIsVertical && Math.abs(panelBackground.y - (root.barMarginV + Style.barHeight)) <= 1 readonly property bool touchingBottomBar: allowAttachToBar && root.barPosition === "bottom" && !root.barIsVertical && Math.abs((panelBackground.y + panelBackground.height) - (root.height - root.barMarginV - Style.barHeight)) <= 1 readonly property bool touchingLeftBar: allowAttachToBar && root.barPosition === "left" && root.barIsVertical && Math.abs(panelBackground.x - (root.barMarginH + Style.barHeight)) <= 1 readonly property bool touchingRightBar: allowAttachToBar && root.barPosition === "right" && root.barIsVertical && Math.abs((panelBackground.x + panelBackground.width) - (root.width - root.barMarginH - Style.barHeight)) <= 1 // Animation direction determination (using target position to avoid binding loops) readonly property bool willTouchTopBar: { if (!isPanelVisible) return false if (!allowAttachToBar || root.barPosition !== "top" || root.barIsVertical) return false var targetTopBarY = root.barMarginV + Style.barHeight return Math.abs(panelBackground.targetY - targetTopBarY) <= 1 } readonly property bool willTouchBottomBar: { if (!isPanelVisible) return false if (!allowAttachToBar || root.barPosition !== "bottom" || root.barIsVertical) return false var targetBottomBarY = root.height - root.barMarginV - Style.barHeight - panelBackground.targetHeight return Math.abs(panelBackground.targetY - targetBottomBarY) <= 1 } readonly property bool willTouchLeftBar: { if (!isPanelVisible) return false if (!allowAttachToBar || root.barPosition !== "left" || !root.barIsVertical) return false var targetLeftBarX = root.barMarginH + Style.barHeight return Math.abs(panelBackground.targetX - targetLeftBarX) <= 1 } readonly property bool willTouchRightBar: { if (!isPanelVisible) return false if (!allowAttachToBar || root.barPosition !== "right" || !root.barIsVertical) return false var targetRightBarX = root.width - root.barMarginH - Style.barHeight - panelBackground.targetWidth return Math.abs(panelBackground.targetX - targetRightBarX) <= 1 } readonly property bool willTouchTopEdge: isPanelVisible && allowAttach && panelBackground.targetY <= 1 readonly property bool willTouchBottomEdge: isPanelVisible && allowAttach && (panelBackground.targetY + panelBackground.targetHeight) >= (root.height - 1) readonly property bool willTouchLeftEdge: isPanelVisible && allowAttach && panelBackground.targetX <= 1 readonly property bool willTouchRightEdge: isPanelVisible && allowAttach && (panelBackground.targetX + panelBackground.targetWidth) >= (root.width - 1) readonly property bool isActuallyAttachedToAnyEdge: { if (!isPanelVisible) return false return willTouchTopBar || willTouchBottomBar || willTouchLeftBar || willTouchRightBar || willTouchTopEdge || willTouchBottomEdge || willTouchLeftEdge || willTouchRightEdge } readonly property bool animateFromTop: { if (!isPanelVisible) return true if (willTouchTopBar) return true if (willTouchTopEdge && !willTouchTopBar && !willTouchBottomBar && !willTouchLeftBar && !willTouchRightBar) return true if (!isActuallyAttachedToAnyEdge) return true return false } readonly property bool animateFromBottom: { if (!isPanelVisible) return false if (willTouchBottomBar) return true if (willTouchBottomEdge && !willTouchTopBar && !willTouchBottomBar && !willTouchLeftBar && !willTouchRightBar) return true return false } readonly property bool animateFromLeft: { if (!isPanelVisible) return false if (willTouchTopBar || willTouchBottomBar) return false if (willTouchLeftBar) return true var touchingTopEdge = isPanelVisible && allowAttach && panelBackground.targetY <= 1 var touchingBottomEdge = isPanelVisible && allowAttach && (panelBackground.targetY + panelBackground.targetHeight) >= (root.height - 1) if (touchingTopEdge || touchingBottomEdge) return false if (willTouchLeftEdge && !willTouchLeftBar && !willTouchTopBar && !willTouchBottomBar && !willTouchRightBar) return true return false } readonly property bool animateFromRight: { if (!isPanelVisible) return false if (willTouchTopBar || willTouchBottomBar) return false if (willTouchRightBar) return true var touchingTopEdge = isPanelVisible && allowAttach && panelBackground.targetY <= 1 var touchingBottomEdge = isPanelVisible && allowAttach && (panelBackground.targetY + panelBackground.targetHeight) >= (root.height - 1) if (touchingTopEdge || touchingBottomEdge) return false if (willTouchRightEdge && !willTouchLeftBar && !willTouchTopBar && !willTouchBottomBar && !willTouchRightBar) return true return false } readonly property bool shouldAnimateWidth: !shouldAnimateHeight && (animateFromLeft || animateFromRight) readonly property bool shouldAnimateHeight: animateFromTop || animateFromBottom // Current animated width/height readonly property real currentWidth: { if (isClosing && opacityFadeComplete && shouldAnimateWidth) return 0 if (isClosing || isPanelVisible) return targetWidth return 0 } readonly property real currentHeight: { if (isClosing && opacityFadeComplete && shouldAnimateHeight) return 0 if (isClosing || isPanelVisible) return targetHeight return 0 } width: currentWidth height: currentHeight x: { if (animateFromRight) { if (isPanelVisible || isClosing) { var targetRightEdge = targetX + targetWidth return targetRightEdge - width } } return targetX } y: { if (animateFromBottom) { if (isPanelVisible || isClosing) { var targetBottomEdge = targetY + targetHeight return targetBottomEdge - height } } return targetY } Behavior on width { NumberAnimation { duration: { if (!panelBackground.shouldAnimateWidth) return 0 return root.isClosing ? Style.animationFast : Style.animationNormal } easing.type: Easing.BezierSpline easing.bezierCurve: panelBackground.bezierCurve } } Behavior on height { NumberAnimation { duration: { if (!panelBackground.shouldAnimateHeight) return 0 return root.isClosing ? Style.animationFast : Style.animationNormal } easing.type: Easing.BezierSpline easing.bezierCurve: panelBackground.bezierCurve } } // Corner states for PanelBackground to read property int topLeftCornerState: { var barInverted = allowAttachToBar && ((root.barPosition === "top" && !root.barIsVertical && root.effectivePanelAnchorTop) || (root.barPosition === "left" && root.barIsVertical && root.effectivePanelAnchorLeft)) var barTouchInverted = touchingTopBar || touchingLeftBar var edgeInverted = allowAttach && (touchingLeftEdge || touchingTopEdge) var oppositeEdgeInverted = allowAttach && (touchingTopEdge && !root.barIsVertical && root.barPosition !== "top") if (barInverted || barTouchInverted || edgeInverted || oppositeEdgeInverted) { if (touchingLeftEdge && touchingTopEdge) return 0 if (touchingLeftEdge) return 2 if (touchingTopEdge) return 1 return root.barIsVertical ? 2 : 1 } return 0 } property int topRightCornerState: { var barInverted = allowAttachToBar && ((root.barPosition === "top" && !root.barIsVertical && root.effectivePanelAnchorTop) || (root.barPosition === "right" && root.barIsVertical && root.effectivePanelAnchorRight)) var barTouchInverted = touchingTopBar || touchingRightBar var edgeInverted = allowAttach && (touchingRightEdge || touchingTopEdge) var oppositeEdgeInverted = allowAttach && (touchingTopEdge && !root.barIsVertical && root.barPosition !== "top") if (barInverted || barTouchInverted || edgeInverted || oppositeEdgeInverted) { if (touchingRightEdge && touchingTopEdge) return 0 if (touchingRightEdge) return 2 if (touchingTopEdge) return 1 return root.barIsVertical ? 2 : 1 } return 0 } property int bottomLeftCornerState: { var barInverted = allowAttachToBar && ((root.barPosition === "bottom" && !root.barIsVertical && root.effectivePanelAnchorBottom) || (root.barPosition === "left" && root.barIsVertical && root.effectivePanelAnchorLeft)) var barTouchInverted = touchingBottomBar || touchingLeftBar var edgeInverted = allowAttach && (touchingLeftEdge || touchingBottomEdge) var oppositeEdgeInverted = allowAttach && (touchingBottomEdge && !root.barIsVertical && root.barPosition !== "bottom") if (barInverted || barTouchInverted || edgeInverted || oppositeEdgeInverted) { if (touchingLeftEdge && touchingBottomEdge) return 0 if (touchingLeftEdge) return 2 if (touchingBottomEdge) return 1 return root.barIsVertical ? 2 : 1 } return 0 } property int bottomRightCornerState: { var barInverted = allowAttachToBar && ((root.barPosition === "bottom" && !root.barIsVertical && root.effectivePanelAnchorBottom) || (root.barPosition === "right" && root.barIsVertical && root.effectivePanelAnchorRight)) var barTouchInverted = touchingBottomBar || touchingRightBar var edgeInverted = allowAttach && (touchingRightEdge || touchingBottomEdge) var oppositeEdgeInverted = allowAttach && (touchingBottomEdge && !root.barIsVertical && root.barPosition !== "bottom") if (barInverted || barTouchInverted || edgeInverted || oppositeEdgeInverted) { if (touchingRightEdge && touchingBottomEdge) return 0 if (touchingRightEdge) return 2 if (touchingBottomEdge) return 1 return root.barIsVertical ? 2 : 1 } return 0 } } }