mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Merge branch 'noctalia-dev:main' into pr/networking-refactor-pt2
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user