mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Merge branch 'main' of https://github.com/noctalia-dev/noctalia-shell
This commit is contained in:
@@ -383,4 +383,4 @@
|
||||
"wallpaperChange": "",
|
||||
"darkModeChange": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,15 @@ Item {
|
||||
property bool closeWatchdogActive: false
|
||||
property bool openWatchdogActive: false
|
||||
|
||||
// Cached animation direction - set when panel opens, doesn't change during animation
|
||||
// These are computed once when opening and used for the entire open/close cycle
|
||||
property bool cachedAnimateFromTop: false
|
||||
property bool cachedAnimateFromBottom: false
|
||||
property bool cachedAnimateFromLeft: false
|
||||
property bool cachedAnimateFromRight: false
|
||||
property bool cachedShouldAnimateWidth: false
|
||||
property bool cachedShouldAnimateHeight: false
|
||||
|
||||
// Close with escape key
|
||||
property bool closeWithEscape: true
|
||||
|
||||
@@ -99,14 +108,14 @@ Item {
|
||||
readonly property bool hasExplicitVerticalAnchor: panelAnchorVerticalCenter || panelAnchorTop || panelAnchorBottom
|
||||
|
||||
// Effective anchor properties (depend on allowAttach)
|
||||
// These are true when:
|
||||
// 1. Explicitly anchored, OR
|
||||
// These are true when allowAttach is enabled AND:
|
||||
// 1. Explicitly anchored to that edge, OR
|
||||
// 2. Using button position and bar is on that edge, OR
|
||||
// 3. Attached to bar with no explicit anchors (default centering behavior)
|
||||
readonly property bool effectivePanelAnchorTop: panelAnchorTop || (useButtonPosition && barPosition === "top") || (panelContent.allowAttach && !hasExplicitVerticalAnchor && barPosition === "top" && !barIsVertical)
|
||||
readonly property bool effectivePanelAnchorBottom: panelAnchorBottom || (useButtonPosition && barPosition === "bottom") || (panelContent.allowAttach && !hasExplicitVerticalAnchor && barPosition === "bottom" && !barIsVertical)
|
||||
readonly property bool effectivePanelAnchorLeft: panelAnchorLeft || (useButtonPosition && barPosition === "left") || (panelContent.allowAttach && !hasExplicitHorizontalAnchor && barPosition === "left" && barIsVertical)
|
||||
readonly property bool effectivePanelAnchorRight: panelAnchorRight || (useButtonPosition && barPosition === "right") || (panelContent.allowAttach && !hasExplicitHorizontalAnchor && barPosition === "right" && barIsVertical)
|
||||
// 3. No explicit anchors and bar is on that edge (default centering behavior)
|
||||
readonly property bool effectivePanelAnchorTop: panelContent.allowAttach && (panelAnchorTop || (useButtonPosition && barPosition === "top") || (!hasExplicitVerticalAnchor && barPosition === "top" && !barIsVertical))
|
||||
readonly property bool effectivePanelAnchorBottom: panelContent.allowAttach && (panelAnchorBottom || (useButtonPosition && barPosition === "bottom") || (!hasExplicitVerticalAnchor && barPosition === "bottom" && !barIsVertical))
|
||||
readonly property bool effectivePanelAnchorLeft: panelContent.allowAttach && (panelAnchorLeft || (useButtonPosition && barPosition === "left") || (!hasExplicitHorizontalAnchor && barPosition === "left" && barIsVertical))
|
||||
readonly property bool effectivePanelAnchorRight: panelContent.allowAttach && (panelAnchorRight || (useButtonPosition && barPosition === "right") || (!hasExplicitHorizontalAnchor && barPosition === "right" && barIsVertical))
|
||||
|
||||
signal opened
|
||||
signal closed
|
||||
@@ -322,36 +331,44 @@ Item {
|
||||
} else {
|
||||
calculatedX = (root.width - panelWidth) / 2;
|
||||
}
|
||||
} else if (root.effectivePanelAnchorRight) {
|
||||
if (panelContent.allowAttach && root.barIsVertical && root.barPosition === "right") {
|
||||
var rightBarEdge = root.width - root.barMarginH - Style.barHeight;
|
||||
calculatedX = rightBarEdge - panelWidth;
|
||||
} else if (panelContent.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 if (root.panelAnchorRight) {
|
||||
// Use raw panelAnchorRight for positioning decision
|
||||
if (root.effectivePanelAnchorRight) {
|
||||
// Attached: snap to edge/bar
|
||||
if (root.barIsVertical && root.barPosition === "right") {
|
||||
var rightBarEdge = root.width - root.barMarginH - Style.barHeight;
|
||||
calculatedX = rightBarEdge - panelWidth;
|
||||
} else {
|
||||
calculatedX = root.width - panelWidth;
|
||||
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 {
|
||||
// Not attached: position at right with margin
|
||||
calculatedX = root.width - panelWidth - Style.marginL;
|
||||
}
|
||||
} else if (root.effectivePanelAnchorLeft) {
|
||||
if (panelContent.allowAttach && root.barIsVertical && root.barPosition === "left") {
|
||||
var leftBarEdge = root.barMarginH + Style.barHeight;
|
||||
calculatedX = leftBarEdge;
|
||||
} else if (panelContent.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 if (root.panelAnchorLeft) {
|
||||
// Use raw panelAnchorLeft for positioning decision
|
||||
if (root.effectivePanelAnchorLeft) {
|
||||
// Attached: snap to edge/bar
|
||||
if (root.barIsVertical && root.barPosition === "left") {
|
||||
var leftBarEdge = root.barMarginH + Style.barHeight;
|
||||
calculatedX = leftBarEdge;
|
||||
} else {
|
||||
calculatedX = 0;
|
||||
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 {
|
||||
// Not attached: position at left with margin
|
||||
calculatedX = Style.marginL;
|
||||
}
|
||||
} else {
|
||||
@@ -471,17 +488,23 @@ Item {
|
||||
} else {
|
||||
calculatedY = (root.height - panelHeight) / 2;
|
||||
}
|
||||
} else if (root.effectivePanelAnchorTop) {
|
||||
if (panelContent.allowAttach) {
|
||||
calculatedY = 0;
|
||||
} else if (root.panelAnchorTop) {
|
||||
// Use raw panelAnchorTop for positioning decision
|
||||
if (root.effectivePanelAnchorTop) {
|
||||
// Attached: snap to edge/bar
|
||||
calculatedY = root.barPosition === "top" ? root.barMarginV + Style.barHeight : 0;
|
||||
} else {
|
||||
// Not attached: position at top with margin
|
||||
var topBarOffset = (root.barPosition === "top") ? barOffset : 0;
|
||||
calculatedY = topBarOffset + Style.marginL;
|
||||
}
|
||||
} else if (root.effectivePanelAnchorBottom) {
|
||||
if (panelContent.allowAttach) {
|
||||
calculatedY = root.height - panelHeight;
|
||||
} else if (root.panelAnchorBottom) {
|
||||
// Use raw panelAnchorBottom for positioning decision
|
||||
if (root.effectivePanelAnchorBottom) {
|
||||
// Attached: snap to edge/bar
|
||||
calculatedY = root.barPosition === "bottom" ? root.height - root.barMarginV - Style.barHeight - panelHeight : root.height - panelHeight;
|
||||
} else {
|
||||
// Not attached: position at bottom with margin
|
||||
var bottomBarOffset = (root.barPosition === "bottom") ? barOffset : 0;
|
||||
calculatedY = root.height - panelHeight - bottomBarOffset - Style.marginL;
|
||||
}
|
||||
@@ -769,10 +792,20 @@ Item {
|
||||
return true;
|
||||
}
|
||||
// Attached to vertical bar (left/right) - don't animate from top
|
||||
if (panelContent.allowAttachToBar && root.barIsVertical && (root.effectivePanelAnchorLeft || root.effectivePanelAnchorRight)) {
|
||||
// Only if panel is on the SAME side as the bar
|
||||
var attachedToVerticalBar = panelContent.allowAttachToBar && root.barIsVertical && ((root.effectivePanelAnchorLeft && root.barPosition === "left") || (root.effectivePanelAnchorRight && root.barPosition === "right"));
|
||||
if (attachedToVerticalBar) {
|
||||
return false;
|
||||
}
|
||||
// Default: animate from top
|
||||
// Panel anchored to left/right edge - animate from that edge instead
|
||||
if (root.panelAnchorLeft || root.panelAnchorRight) {
|
||||
return false;
|
||||
}
|
||||
// Attached to top edge
|
||||
if (panelContent.allowAttach && root.panelAnchorTop) {
|
||||
return true;
|
||||
}
|
||||
// Default: animate from top (for floating panels)
|
||||
return true;
|
||||
}
|
||||
// Panel is visible - use calculated positions
|
||||
@@ -804,7 +837,13 @@ Item {
|
||||
}
|
||||
readonly property bool animateFromLeft: {
|
||||
if (!root.isPanelVisible) {
|
||||
if (panelContent.allowAttachToBar && root.effectivePanelAnchorLeft && root.barIsVertical) {
|
||||
// Attached to vertical bar on left - must verify bar is actually on left
|
||||
if (panelContent.allowAttachToBar && root.effectivePanelAnchorLeft && root.barIsVertical && root.barPosition === "left") {
|
||||
return true;
|
||||
}
|
||||
// Panel anchored to left edge - animate from left
|
||||
// Takes precedence over top/bottom when bar is vertical
|
||||
if (root.panelAnchorLeft) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -825,7 +864,13 @@ Item {
|
||||
}
|
||||
readonly property bool animateFromRight: {
|
||||
if (!root.isPanelVisible) {
|
||||
if (panelContent.allowAttachToBar && root.effectivePanelAnchorRight && root.barIsVertical) {
|
||||
// Attached to vertical bar on right - must verify bar is actually on right
|
||||
if (panelContent.allowAttachToBar && root.effectivePanelAnchorRight && root.barIsVertical && root.barPosition === "right") {
|
||||
return true;
|
||||
}
|
||||
// Panel anchored to right edge - animate from right
|
||||
// Takes precedence over top/bottom when bar is vertical
|
||||
if (root.panelAnchorRight) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -848,6 +893,7 @@ Item {
|
||||
// Determine animation axis based on which edge is closest
|
||||
// Priority: horizontal edges (top/bottom) take precedence over vertical edges (left/right)
|
||||
// This prevents diagonal animations when panel is attached to a corner
|
||||
// Use reactive values here - they're evaluated BEFORE isPanelVisible becomes true
|
||||
readonly property bool shouldAnimateWidth: !shouldAnimateHeight && (animateFromLeft || animateFromRight)
|
||||
readonly property bool shouldAnimateHeight: animateFromTop || animateFromBottom
|
||||
|
||||
@@ -876,23 +922,21 @@ Item {
|
||||
|
||||
x: {
|
||||
// Offset x to make panel grow/shrink from the appropriate edge
|
||||
if (animateFromRight) {
|
||||
// Use CACHED values to prevent recalculation during animation
|
||||
if (root.cachedAnimateFromRight && root.cachedShouldAnimateWidth) {
|
||||
// Keep the RIGHT edge fixed at its target position
|
||||
if (isPanelVisible || isClosing) {
|
||||
var targetRightEdge = targetX + targetWidth;
|
||||
return targetRightEdge - width;
|
||||
}
|
||||
var targetRightEdge = targetX + targetWidth;
|
||||
return targetRightEdge - width;
|
||||
}
|
||||
return targetX;
|
||||
}
|
||||
y: {
|
||||
// Offset y to make panel grow/shrink from the appropriate edge
|
||||
if (animateFromBottom) {
|
||||
// Use CACHED values to prevent recalculation during animation
|
||||
if (root.cachedAnimateFromBottom && root.cachedShouldAnimateHeight) {
|
||||
// Keep the BOTTOM edge fixed at its target position
|
||||
if (isPanelVisible || isClosing) {
|
||||
var targetBottomEdge = targetY + targetHeight;
|
||||
return targetBottomEdge - height;
|
||||
}
|
||||
var targetBottomEdge = targetY + targetHeight;
|
||||
return targetBottomEdge - height;
|
||||
}
|
||||
return targetY;
|
||||
}
|
||||
@@ -1133,6 +1177,15 @@ Item {
|
||||
// Mark dimensions as initialized to enable animations
|
||||
panelBackground.dimensionsInitialized = true;
|
||||
|
||||
// Cache animation direction BEFORE isPanelVisible becomes true
|
||||
// This locks in the direction for the entire open/close cycle
|
||||
root.cachedAnimateFromTop = panelBackground.animateFromTop;
|
||||
root.cachedAnimateFromBottom = panelBackground.animateFromBottom;
|
||||
root.cachedAnimateFromLeft = panelBackground.animateFromLeft;
|
||||
root.cachedAnimateFromRight = panelBackground.animateFromRight;
|
||||
root.cachedShouldAnimateWidth = panelBackground.shouldAnimateWidth;
|
||||
root.cachedShouldAnimateHeight = panelBackground.shouldAnimateHeight;
|
||||
|
||||
// Make panel visible, now only the intended dimension will animate
|
||||
root.isPanelVisible = true;
|
||||
opacityTrigger.start();
|
||||
|
||||
@@ -23,6 +23,14 @@ SmartPanel {
|
||||
// Reference to the plugin content loader (set when panel content is created)
|
||||
property var contentLoader: null
|
||||
|
||||
// Pass through anchor properties from plugin panel content
|
||||
panelAnchorHorizontalCenter: pluginInstance?.panelAnchorHorizontalCenter ?? false
|
||||
panelAnchorVerticalCenter: pluginInstance?.panelAnchorVerticalCenter ?? false
|
||||
panelAnchorTop: pluginInstance?.panelAnchorTop ?? false
|
||||
panelAnchorBottom: pluginInstance?.panelAnchorBottom ?? false
|
||||
panelAnchorLeft: pluginInstance?.panelAnchorLeft ?? false
|
||||
panelAnchorRight: pluginInstance?.panelAnchorRight ?? false
|
||||
|
||||
// Panel content is dynamically loaded
|
||||
panelContent: Component {
|
||||
Item {
|
||||
|
||||
@@ -1065,12 +1065,10 @@ Singleton {
|
||||
|
||||
// If this slot is empty, use it
|
||||
if (panel.currentPluginId === "") {
|
||||
// Open the panel first so the loader gets created
|
||||
// Set the pluginId first - when panel opens and panelContent loads,
|
||||
// Component.onCompleted will call loadPluginPanel automatically
|
||||
panel.currentPluginId = pluginId;
|
||||
panel.open();
|
||||
// Wait a brief moment for the panel to be fully created
|
||||
Qt.callLater(function () {
|
||||
panel.loadPluginPanel(pluginId);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1080,10 +1078,10 @@ Singleton {
|
||||
var panel1 = PanelService.getPanel("pluginPanel1", screen);
|
||||
if (panel1) {
|
||||
panel1.unloadPluginPanel();
|
||||
// Set the pluginId first - when panel opens and panelContent loads,
|
||||
// Component.onCompleted will call loadPluginPanel automatically
|
||||
panel1.currentPluginId = pluginId;
|
||||
panel1.open();
|
||||
Qt.callLater(function () {
|
||||
panel1.loadPluginPanel(pluginId);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user