Merge branch 'noctalia-dev:main' into pr/networking-refactor-pt2

This commit is contained in:
Turann_
2026-03-14 00:56:16 +03:00
committed by GitHub
44 changed files with 165 additions and 100 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ Item {
property string icon: ""
property string text: ""
property string suffix: ""
property var tooltipText: ""
property var tooltipText
property bool autoHide: false
property bool forceOpen: false
property bool forceClose: false
+1 -1
View File
@@ -13,7 +13,7 @@ Item {
property string icon: ""
property string text: ""
property string suffix: ""
property var tooltipText: ""
property var tooltipText
property bool autoHide: false
property bool forceOpen: false
property bool forceClose: false
+1 -1
View File
@@ -13,7 +13,7 @@ Item {
property string icon: ""
property string text: ""
property string suffix: ""
property var tooltipText: ""
property var tooltipText
property bool autoHide: false
property bool forceOpen: false
property bool forceClose: false
+27 -2
View File
@@ -73,8 +73,33 @@ Item {
id: loader
anchors.fill: parent
asynchronous: false
// Include reloadCounter in the binding to force re-evaluation
active: root.checkWidgetExists() && (root.reloadCounter >= 0)
// Deferred activation to prevent re-entrant incubation crash:
// When ListModel.append() creates this delegate, the Repeater is mid-incubation.
// If this Loader activates synchronously (asynchronous: false) during delegate
// finalization, it triggers nested QQmlIncubatorPrivate::incubate which corrupts
// the V4 heap (SIGSEGV in QV4::Object::insertMember).
// Deferring to the next event loop iteration breaks the nesting.
property bool _ready: false
active: _ready && root.checkWidgetExists() && (root.reloadCounter >= 0)
Timer {
id: activateTimer
interval: 0
onTriggered: loader._ready = true
}
Component.onCompleted: activateTimer.start()
// Reset _ready when reloadCounter changes to force a deferred re-activation
Connections {
target: root
function onReloadCounterChanged() {
loader._ready = false;
activateTimer.restart();
}
}
sourceComponent: {
// Depend on reloadCounter to force re-fetch of component
var _ = root.reloadCounter;
+2 -2
View File
@@ -37,8 +37,8 @@ NIconButton {
baseSize: Style.getCapsuleHeightForScreen(screen?.name)
applyUiScale: false
customRadius: Style.radiusL
colorBg: Settings.data.nightLight.forced ? Color.mPrimary : Style.capsuleColor
colorFg: Settings.data.nightLight.forced ? Color.mOnPrimary : Color.resolveColorKey(iconColorKey)
colorBg: Settings.data.nightLight.enabled ? Color.mPrimary : Style.capsuleColor
colorFg: Settings.data.nightLight.enabled ? Color.mOnPrimary : Color.resolveColorKey(iconColorKey)
border.color: Style.capsuleBorderColor
border.width: Style.capsuleBorderWidth
+9 -9
View File
@@ -76,7 +76,7 @@ Loader {
readonly property string displayMode: Settings.data.dock.displayMode
readonly property bool autoHide: displayMode === "auto_hide"
readonly property bool exclusive: displayMode === "exclusive"
readonly property bool isStaticMode: Settings.data.dock.dockType === "static"
readonly property bool isAttachedMode: Settings.data.dock.dockType === "attached"
readonly property int hideDelay: 500
readonly property int showDelay: 100
readonly property int hideAnimationDuration: Math.max(0, Math.round(Style.animationFast / (Settings.data.dock.animationSpeed || 1.0)))
@@ -104,7 +104,7 @@ Loader {
readonly property real barMarginV: Settings.data.bar.floating ? Math.ceil(Settings.data.bar.marginVertical) : 0
readonly property int barHeight: Style.getBarHeightForScreen(modelData?.name)
readonly property bool staticPanelOpen: {
if (!isStaticMode)
if (!isAttachedMode)
return false;
var panel = getStaticDockPanel();
if (panel && panel.isPanelOpen !== undefined)
@@ -151,7 +151,7 @@ Loader {
return Math.max(0, Math.round((edgeSize - peekEdgeLength) / 2));
}
readonly property bool showDockIndicator: {
if (!Settings.data.dock.showDockIndicator || (!autoHide && !isStaticMode) || !hidden)
if (!Settings.data.dock.showDockIndicator || (!autoHide && !isAttachedMode) || !hidden)
return false;
return !staticPanelOpen;
}
@@ -639,13 +639,13 @@ Loader {
menuHovered = false;
}
if (autoHide && !dockHovered && !anyAppHovered && !peekHovered && !menuHovered) {
if (isStaticMode) {
if (isAttachedMode) {
const panel = getStaticDockPanel();
if (panel && (panel.menuHovered || (panel.currentContextMenu && panel.currentContextMenu.visible))) {
restart();
return;
}
if (panel && panel.isDockHovered) {
if (panel && (panel.isDockHovered || panel.dockHovered || panel.anyAppHovered)) {
restart();
return;
}
@@ -669,7 +669,7 @@ Loader {
interval: showDelay
onTriggered: {
if (autoHide) {
if (!isStaticMode) {
if (!isAttachedMode) {
dockLoaded = true; // Load dock immediately
}
hidden = false; // Then trigger show animation
@@ -725,7 +725,7 @@ Loader {
onEntered: {
peekHovered = true;
if (isStaticMode) {
if (isAttachedMode) {
if (dockItemCount <= 0)
return;
const panel = getStaticDockPanel();
@@ -741,7 +741,7 @@ Loader {
onExited: {
peekHovered = false;
showTimer.stop();
if (isStaticMode) {
if (isAttachedMode) {
// Start hideTimer which checks panel.isDockHovered before closing
if (!dockHovered && !anyAppHovered && !menuHovered) {
hideTimer.restart();
@@ -820,7 +820,7 @@ Loader {
Loader {
id: dockWindowLoader
active: Settings.data.dock.enabled && !isStaticMode && (barIsReady || !hasBar) && modelData && (Settings.data.dock.monitors.length === 0 || Settings.data.dock.monitors.includes(modelData.name)) && dockLoaded && ToplevelManager && (dockApps.length > 0)
active: Settings.data.dock.enabled && !isAttachedMode && (barIsReady || !hasBar) && modelData && (Settings.data.dock.monitors.length === 0 || Settings.data.dock.monitors.includes(modelData.name)) && dockLoaded && ToplevelManager && (dockApps.length > 0)
sourceComponent: PanelWindow {
id: dockWindow
+3 -3
View File
@@ -18,7 +18,7 @@ Item {
required property int extraLeft
required property int extraRight
property alias dockContainer: dockContainer
readonly property bool isStaticMode: Settings.data.dock.dockType === "static"
readonly property bool isAttachedMode: Settings.data.dock.dockType === "attached"
readonly property string tooltipDirection: dockRoot.dockPosition === "left" ? "right" : (dockRoot.dockPosition === "right" ? "left" : (dockRoot.dockPosition === "top" ? "bottom" : "top"))
Rectangle {
@@ -26,7 +26,7 @@ Item {
// For vertical dock, swap width and height logic
width: dockRoot.isVertical ? Math.round(dockRoot.iconSize * 1.5) : Math.min(dockLayout.implicitWidth + Style.marginXL, dockRoot.maxWidth)
height: dockRoot.isVertical ? Math.min(dockLayout.implicitHeight + Style.marginXL, dockRoot.maxHeight) : Math.round(dockRoot.iconSize * 1.5)
color: Qt.alpha(Color.mSurface, (isStaticMode ? 0 : Settings.data.dock.backgroundOpacity))
color: Qt.alpha(Color.mSurface, (isAttachedMode ? 0 : Settings.data.dock.backgroundOpacity))
// Anchor based on padding to achieve centering shift
anchors.horizontalCenter: extraLeft > 0 || extraRight > 0 ? undefined : parent.horizontalCenter
@@ -39,7 +39,7 @@ Item {
radius: Style.radiusL
border.width: Style.borderS
border.color: Qt.alpha(Color.mOutline, (isStaticMode ? 0 : Settings.data.dock.backgroundOpacity))
border.color: Qt.alpha(Color.mOutline, (isAttachedMode ? 0 : Settings.data.dock.backgroundOpacity))
MouseArea {
id: dockMouseArea
+1 -1
View File
@@ -265,7 +265,7 @@ PopupWindow {
} else if (action.execute) {
action.execute();
}
if (Settings.data.dock.dockType === "static") {
if (Settings.data.dock.dockType === "attached") {
const panel = PanelService.getPanel("staticDockPanel", root.screen, false);
if (panel)
panel.close();
+7 -2
View File
@@ -25,6 +25,8 @@ PanelWindow {
Component.onCompleted: {
Logger.d("BarContentWindow", "Bar content window created for screen:", barWindow.screen?.name);
if (!isHidden)
contentLoaded = true;
}
// Wayland layer configuration
@@ -144,8 +146,11 @@ PanelWindow {
right: barPosition === "right" || !barIsVertical
}
// Track if content should be loaded (stays true during fade-out animation)
property bool contentLoaded: !isHidden
// Track if content should be loaded (stays true during fade-out animation).
// Must NOT be a binding to isHidden — on the first hide cycle the binding
// would flip contentLoaded false synchronously (before onIsHiddenChanged can
// start the unload timer), unmapping the Wayland surface mid-animation.
property bool contentLoaded: false
// Timer to delay unload until after fade animation
Timer {
@@ -11,7 +11,7 @@ NIconButtonHot {
enabled: ProgramCheckerService.wlsunsetAvailable
icon: Settings.data.nightLight.enabled ? (Settings.data.nightLight.forced ? "nightlight-forced" : "nightlight-on") : "nightlight-off"
hot: !Settings.data.nightLight.enabled || Settings.data.nightLight.forced
hot: Settings.data.nightLight.enabled
tooltipText: I18n.tr("common.night-light")
onClicked: {
@@ -6,7 +6,9 @@ import Quickshell.Services.Notifications
import Quickshell.Wayland
import qs.Commons
import qs.Modules.MainScreen
import qs.Modules.Panels.Settings
import qs.Services.System
import qs.Services.UI
import qs.Widgets
// Notification History panel
@@ -421,6 +423,16 @@ SmartPanel {
}
}
NIconButton {
icon: "settings"
tooltipText: I18n.tr("common.settings")
baseSize: Style.baseWidgetSize * 0.8
onClicked: {
SettingsPanelService.openToTab(SettingsPanel.Tab.Notifications, 0, screen);
root.close();
}
}
NIconButton {
icon: "close"
tooltipText: I18n.tr("common.close")
@@ -59,8 +59,8 @@ ColumnLayout {
"name": I18n.tr("panels.dock.appearance-type-floating")
},
{
"key": "static",
"name": I18n.tr("panels.dock.appearance-type-static")
"key": "attached",
"name": I18n.tr("panels.dock.appearance-type-attached")
}
]
currentKey: Settings.data.dock.dockType
@@ -96,7 +96,7 @@ ColumnLayout {
NToggle {
Layout.fillWidth: true
visible: Settings.data.dock.dockType === "static" && Settings.data.bar.barType === "framed"
visible: Settings.data.dock.dockType === "attached" && Settings.data.bar.barType === "framed"
label: I18n.tr("panels.dock.appearance-sit-on-frame-label")
description: I18n.tr("panels.dock.appearance-sit-on-frame-description")
checked: Settings.data.dock.sitOnFrame