From 809274a2947094bd4d8285bbb4c5e86b5312a2f4 Mon Sep 17 00:00:00 2001 From: bbedward Date: Tue, 2 Sep 2025 15:58:34 -0400 Subject: [PATCH] top bar improvements --- Modules/ControlCenter/ControlCenterPopout.qml | 45 +- Modules/TopBar/TopBar.qml | 1975 +++++++++-------- Widgets/DankPopout.qml | 46 +- 3 files changed, 1058 insertions(+), 1008 deletions(-) diff --git a/Modules/ControlCenter/ControlCenterPopout.qml b/Modules/ControlCenter/ControlCenterPopout.qml index 65173c7a..e829f48f 100644 --- a/Modules/ControlCenter/ControlCenterPopout.qml +++ b/Modules/ControlCenter/ControlCenterPopout.qml @@ -80,43 +80,18 @@ DankPopout { property alias bluetoothCodecSelector: bluetoothCodecSelector Rectangle { - id: controlContent + id: controlContent - anchors.fill: parent - implicitHeight: mainColumn.implicitHeight + Theme.spacingM + anchors.fill: parent + implicitHeight: mainColumn.implicitHeight + Theme.spacingM - color: Theme.popupBackground() - radius: Theme.cornerRadius - border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, - Theme.outline.b, 0.08) - border.width: 1 - antialiasing: true - smooth: true - focus: true - - Component.onCompleted: { - if (root.shouldBeVisible) - forceActiveFocus() - } - - Keys.onPressed: function (event) { - if (event.key === Qt.Key_Escape) { - root.close() - event.accepted = true - } else { - event.accepted = false - } - } - - Connections { - function onShouldBeVisibleChanged() { - if (root.shouldBeVisible) - Qt.callLater(function () { - controlContent.forceActiveFocus() - }) - } - target: root - } + color: Theme.popupBackground() + radius: Theme.cornerRadius + border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, + Theme.outline.b, 0.08) + border.width: 1 + antialiasing: true + smooth: true Column { id: mainColumn diff --git a/Modules/TopBar/TopBar.qml b/Modules/TopBar/TopBar.qml index 2939cfcc..e39029b6 100644 --- a/Modules/TopBar/TopBar.qml +++ b/Modules/TopBar/TopBar.qml @@ -19,12 +19,15 @@ PanelWindow { property var modelData property string screenName: modelData.name - property real backgroundTransparency: SettingsData.topBarTransparency readonly property int notificationCount: NotificationService.notifications.length - property bool autoHide: SettingsData.topBarAutoHide - property bool reveal: SettingsData.topBarVisible && (!autoHide || topBarMouseArea.containsMouse) - readonly property real effectiveBarHeight: Math.max(root.widgetHeight + SettingsData.topBarInnerPadding + 4, Theme.barHeight - 4 - (8 - SettingsData.topBarInnerPadding)) - readonly property real widgetHeight: Math.max(20, 26 + SettingsData.topBarInnerPadding * 0.6) + readonly property real effectiveBarHeight: Math.max( + root.widgetHeight + + SettingsData.topBarInnerPadding + 4, + Theme.barHeight - 4 + - (8 - SettingsData.topBarInnerPadding)) + readonly property real widgetHeight: Math.max( + 20, + 26 + SettingsData.topBarInnerPadding * 0.6) screen: modelData implicitHeight: effectiveBarHeight + SettingsData.topBarSpacing @@ -102,10 +105,6 @@ PanelWindow { } Connections { - function onTopBarTransparencyChanged() { - root.backgroundTransparency = SettingsData.topBarTransparency - } - function onTopBarLeftWidgetsChanged() { root.updateGpuTempConfig() } @@ -155,1033 +154,1113 @@ PanelWindow { right: true } - exclusiveZone: !SettingsData.topBarVisible || autoHide ? -1 : root.effectiveBarHeight + SettingsData.topBarSpacing - 2 + SettingsData.topBarBottomGap + exclusiveZone: topBarCore.autoHide ? -1 : root.effectiveBarHeight + SettingsData.topBarSpacing + - 2 + SettingsData.topBarBottomGap mask: Region { item: topBarMouseArea } - MouseArea { - id: topBarMouseArea - height: root.reveal ? effectiveBarHeight + SettingsData.topBarSpacing : 4 - anchors { - top: parent.top - left: parent.left - right: parent.right - } - hoverEnabled: true + Item { + id: topBarCore + anchors.fill: parent - Behavior on height { - NumberAnimation { - duration: 200 - easing.type: Easing.OutCubic + property real backgroundTransparency: SettingsData.topBarTransparency + property bool autoHide: SettingsData.topBarAutoHide + property bool reveal: SettingsData.topBarVisible + && (!autoHide || topBarMouseArea.containsMouse || hasActivePopout) + + readonly property bool hasActivePopout: { + var result = false + if (typeof appDrawerLoader !== "undefined" && appDrawerLoader.item) + result = result || appDrawerLoader.item.shouldBeVisible + if (typeof centcomPopoutLoader !== "undefined" && centcomPopoutLoader.item) + result = result || centcomPopoutLoader.item.shouldBeVisible + if (typeof processListPopoutLoader !== "undefined" && processListPopoutLoader.item) + result = result || processListPopoutLoader.item.shouldBeVisible + if (typeof notificationCenterLoader !== "undefined" && notificationCenterLoader.item) + result = result || notificationCenterLoader.item.shouldBeVisible + if (typeof batteryPopoutLoader !== "undefined" && batteryPopoutLoader.item) + result = result || batteryPopoutLoader.item.shouldBeVisible + if (typeof vpnPopoutLoader !== "undefined" && vpnPopoutLoader.item) + result = result || vpnPopoutLoader.item.shouldBeVisible + if (typeof controlCenterLoader !== "undefined" && controlCenterLoader.item) + result = result || controlCenterLoader.item.shouldBeVisible + if (typeof notepadModalLoader !== "undefined" && notepadModalLoader.item) + result = result || notepadModalLoader.item.visible + if (typeof clipboardHistoryModalPopup !== "undefined" && clipboardHistoryModalPopup.item) + result = result || clipboardHistoryModalPopup.item.visible + return result + } + + Connections { + function onTopBarTransparencyChanged() { + topBarCore.backgroundTransparency = SettingsData.topBarTransparency } + + target: SettingsData } - Item { - id: topBarContainer - anchors.fill: parent + MouseArea { + id: topBarMouseArea + height: parent.reveal ? root.effectiveBarHeight + SettingsData.topBarSpacing : 4 + anchors { + top: parent.top + left: parent.left + right: parent.right + } + hoverEnabled: true - transform: Translate { - id: topBarSlide - y: root.reveal ? 0 : -(effectiveBarHeight - 4) - - Behavior on y { - NumberAnimation { - duration: 200 - easing.type: Easing.OutCubic - } + Behavior on height { + NumberAnimation { + duration: 200 + easing.type: Easing.OutCubic } } Item { + id: topBarContainer anchors.fill: parent - anchors.topMargin: SettingsData.topBarSpacing - anchors.bottomMargin: 0 - anchors.leftMargin: SettingsData.topBarSpacing - anchors.rightMargin: SettingsData.topBarSpacing - Rectangle { - anchors.fill: parent - radius: SettingsData.topBarSquareCorners ? 0 : Theme.cornerRadius - color: Qt.rgba(Theme.surfaceContainer.r, - Theme.surfaceContainer.g, - Theme.surfaceContainer.b, - root.backgroundTransparency) - layer.enabled: true + transform: Translate { + id: topBarSlide + y: topBarCore.reveal ? 0 : -(root.effectiveBarHeight - 4) - Rectangle { - anchors.fill: parent - color: "transparent" - border.color: Theme.outlineMedium - border.width: 1 - radius: parent.radius - } - - Rectangle { - anchors.fill: parent - color: Qt.rgba(Theme.surfaceTint.r, - Theme.surfaceTint.g, - Theme.surfaceTint.b, 0.04) - radius: parent.radius - - SequentialAnimation on opacity { - running: false - loops: Animation.Infinite - - NumberAnimation { - to: 0.08 - duration: Theme.extraLongDuration - easing.type: Theme.standardEasing - } - - NumberAnimation { - to: 0.02 - duration: Theme.extraLongDuration - easing.type: Theme.standardEasing - } + Behavior on y { + NumberAnimation { + duration: 200 + easing.type: Easing.OutCubic } } - - layer.effect: MultiEffect { - shadowEnabled: true - shadowHorizontalOffset: 0 - shadowVerticalOffset: 4 - shadowBlur: 0.5 // radius/32, adjusted for visual match - shadowColor: Qt.rgba(0, 0, 0, 0.15) - shadowOpacity: 0.15 - } } Item { - id: topBarContent - - readonly property int availableWidth: width - readonly property int launcherButtonWidth: 40 - readonly property int workspaceSwitcherWidth: 120 // Approximate - readonly property int focusedAppMaxWidth: 456 // Fixed width since we don't have focusedApp reference - readonly property int estimatedLeftSectionWidth: launcherButtonWidth + workspaceSwitcherWidth + focusedAppMaxWidth + (Theme.spacingXS * 2) - readonly property int rightSectionWidth: rightSection.width - readonly property int clockWidth: 120 // Approximate clock width - readonly property int mediaMaxWidth: 280 // Normal max width - readonly property int weatherWidth: 80 // Approximate weather width - readonly property bool validLayout: availableWidth > 100 - && estimatedLeftSectionWidth > 0 - && rightSectionWidth > 0 - readonly property int clockLeftEdge: (availableWidth - clockWidth) / 2 - readonly property int clockRightEdge: clockLeftEdge + clockWidth - readonly property int leftSectionRightEdge: estimatedLeftSectionWidth - readonly property int mediaLeftEdge: clockLeftEdge - mediaMaxWidth - - Theme.spacingS - readonly property int rightSectionLeftEdge: availableWidth - rightSectionWidth - readonly property int leftToClockGap: Math.max( - 0, - clockLeftEdge - leftSectionRightEdge) - readonly property int leftToMediaGap: mediaMaxWidth > 0 ? Math.max(0, mediaLeftEdge - leftSectionRightEdge) : leftToClockGap - readonly property int mediaToClockGap: mediaMaxWidth > 0 ? Theme.spacingS : 0 - readonly property int clockToRightGap: validLayout ? Math.max( - 0, - rightSectionLeftEdge - clockRightEdge) : 1000 - readonly property bool spacingTight: validLayout - && (leftToMediaGap < 150 - || clockToRightGap < 100) - readonly property bool overlapping: validLayout - && (leftToMediaGap < 100 - || clockToRightGap < 50) - - function getWidgetEnabled(enabled) { - return enabled !== undefined ? enabled : true - } - - function getWidgetVisible(widgetId) { - switch (widgetId) { - case "launcherButton": - return true - case "workspaceSwitcher": - return true - case "focusedWindow": - return true - case "runningApps": - return true - case "clock": - return true - case "music": - return true - case "weather": - return true - case "systemTray": - return true - case "privacyIndicator": - return true - case "clipboard": - return true - case "cpuUsage": - return DgopService.dgopAvailable - case "memUsage": - return DgopService.dgopAvailable - case "cpuTemp": - return DgopService.dgopAvailable - case "gpuTemp": - return DgopService.dgopAvailable - case "notificationButton": - return true - case "battery": - return true - case "controlCenterButton": - return true - case "idleInhibitor": - return true - case "spacer": - return true - case "separator": - return true - case "network_speed_monitor": - return DgopService.dgopAvailable - case "keyboard_layout_name": - return true - case "vpn": - return true - case "notepadButton": - return true - default: - return false - } - } - - function getWidgetComponent(widgetId) { - switch (widgetId) { - case "launcherButton": - return launcherButtonComponent - case "workspaceSwitcher": - return workspaceSwitcherComponent - case "focusedWindow": - return focusedWindowComponent - case "runningApps": - return runningAppsComponent - case "clock": - return clockComponent - case "music": - return mediaComponent - case "weather": - return weatherComponent - case "systemTray": - return systemTrayComponent - case "privacyIndicator": - return privacyIndicatorComponent - case "clipboard": - return clipboardComponent - case "cpuUsage": - return cpuUsageComponent - case "memUsage": - return memUsageComponent - case "cpuTemp": - return cpuTempComponent - case "gpuTemp": - return gpuTempComponent - case "notificationButton": - return notificationButtonComponent - case "battery": - return batteryComponent - case "controlCenterButton": - return controlCenterButtonComponent - case "idleInhibitor": - return idleInhibitorComponent - case "spacer": - return spacerComponent - case "separator": - return separatorComponent - case "network_speed_monitor": - return networkComponent - case "keyboard_layout_name": - return keyboardLayoutNameComponent - case "vpn": - return vpnComponent - case "notepadButton": - return notepadButtonComponent - default: - return null - } - } - anchors.fill: parent - anchors.leftMargin: Math.max(Theme.spacingXS, SettingsData.topBarInnerPadding * 0.8) - anchors.rightMargin: Math.max(Theme.spacingXS, SettingsData.topBarInnerPadding * 0.8) - anchors.topMargin: SettingsData.topBarInnerPadding / 2 - anchors.bottomMargin: SettingsData.topBarInnerPadding / 2 - clip: true + anchors.topMargin: SettingsData.topBarSpacing + anchors.bottomMargin: 0 + anchors.leftMargin: SettingsData.topBarSpacing + anchors.rightMargin: SettingsData.topBarSpacing - Row { - id: leftSection - - height: parent.height - spacing: SettingsData.topBarNoBackground ? 2 : Theme.spacingXS - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - - Repeater { - model: SettingsData.topBarLeftWidgetsModel - - Loader { - property string widgetId: model.widgetId - property var widgetData: model - property int spacerSize: model.size || 20 - - anchors.verticalCenter: parent ? parent.verticalCenter : undefined - active: topBarContent.getWidgetVisible( - model.widgetId) - sourceComponent: topBarContent.getWidgetComponent( - model.widgetId) - opacity: topBarContent.getWidgetEnabled( - model.enabled) ? 1 : 0 - asynchronous: false - - } - } - } - - Item { - id: centerSection - - property var centerWidgets: [] - property int totalWidgets: 0 - property real totalWidth: 0 - property real spacing: SettingsData.topBarNoBackground ? 2 : Theme.spacingS - - function updateLayout() { - // Defer layout if dimensions are invalid - if (width <= 0 || height <= 0 || !visible) { - Qt.callLater(updateLayout) - return - } - - centerWidgets = [] - totalWidgets = 0 - totalWidth = 0 - for (var i = 0; i < centerRepeater.count; i++) { - let item = centerRepeater.itemAt(i) - if (item && item.active && item.item) { - centerWidgets.push(item.item) - totalWidgets++ - totalWidth += item.item.width - } - } - if (totalWidgets > 1) - totalWidth += spacing * (totalWidgets - 1) - - positionWidgets() - } - - function positionWidgets() { - if (totalWidgets === 0 || width <= 0) - return - - let parentCenterX = width / 2 - if (totalWidgets % 2 === 1) { - let middleIndex = Math.floor(totalWidgets / 2) - let currentX = parentCenterX - - (centerWidgets[middleIndex].width / 2) - centerWidgets[middleIndex].x = currentX - centerWidgets[middleIndex].anchors.horizontalCenter = undefined - currentX = centerWidgets[middleIndex].x - for (var i = middleIndex - 1; i >= 0; i--) { - currentX -= (spacing + centerWidgets[i].width) - centerWidgets[i].x = currentX - centerWidgets[i].anchors.horizontalCenter = undefined - } - currentX = centerWidgets[middleIndex].x - + centerWidgets[middleIndex].width - for (var i = middleIndex + 1; i < totalWidgets; i++) { - currentX += spacing - centerWidgets[i].x = currentX - centerWidgets[i].anchors.horizontalCenter = undefined - currentX += centerWidgets[i].width - } - } else { - let leftMiddleIndex = (totalWidgets / 2) - 1 - let rightMiddleIndex = totalWidgets / 2 - let gapCenter = parentCenterX - let halfSpacing = spacing / 2 - centerWidgets[leftMiddleIndex].x = gapCenter - halfSpacing - - centerWidgets[leftMiddleIndex].width - centerWidgets[leftMiddleIndex].anchors.horizontalCenter = undefined - centerWidgets[rightMiddleIndex].x = gapCenter + halfSpacing - centerWidgets[rightMiddleIndex].anchors.horizontalCenter = undefined - let currentX = centerWidgets[leftMiddleIndex].x - for (var i = leftMiddleIndex - 1; i >= 0; i--) { - currentX -= (spacing + centerWidgets[i].width) - centerWidgets[i].x = currentX - centerWidgets[i].anchors.horizontalCenter = undefined - } - currentX = centerWidgets[rightMiddleIndex].x - + centerWidgets[rightMiddleIndex].width - for (var i = rightMiddleIndex + 1; i < totalWidgets; i++) { - currentX += spacing - centerWidgets[i].x = currentX - centerWidgets[i].anchors.horizontalCenter = undefined - currentX += centerWidgets[i].width - } - } - } - - height: parent.height - width: parent.width - anchors.centerIn: parent - Component.onCompleted: { - Qt.callLater(() => { - Qt.callLater(updateLayout) - }) - } - - onWidthChanged: { - if (width > 0) { - Qt.callLater(updateLayout) - } - } - - onVisibleChanged: { - if (visible && width > 0) { - Qt.callLater(updateLayout) - } - } - - Repeater { - id: centerRepeater - - model: SettingsData.topBarCenterWidgetsModel - - Loader { - property string widgetId: model.widgetId - property var widgetData: model - property int spacerSize: model.size || 20 - - anchors.verticalCenter: parent ? parent.verticalCenter : undefined - active: topBarContent.getWidgetVisible( - model.widgetId) - sourceComponent: topBarContent.getWidgetComponent( - model.widgetId) - opacity: topBarContent.getWidgetEnabled( - model.enabled) ? 1 : 0 - asynchronous: false - - onLoaded: { - if (item) { - item.onWidthChanged.connect( - centerSection.updateLayout) - if (model.widgetId === "spacer") - item.spacerSize = Qt.binding(() => { - return model.size - || 20 - }) - Qt.callLater(centerSection.updateLayout) - } - } - onActiveChanged: { - Qt.callLater(centerSection.updateLayout) - } - } - } - - Connections { - function onCountChanged() { - Qt.callLater(centerSection.updateLayout) - } - - target: SettingsData.topBarCenterWidgetsModel - } - } - - Row { - id: rightSection - - height: parent.height - spacing: SettingsData.topBarNoBackground ? 2 : Theme.spacingXS - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - - Repeater { - model: SettingsData.topBarRightWidgetsModel - - Loader { - property string widgetId: model.widgetId - property var widgetData: model - property int spacerSize: model.size || 20 - - anchors.verticalCenter: parent ? parent.verticalCenter : undefined - active: topBarContent.getWidgetVisible( - model.widgetId) - sourceComponent: topBarContent.getWidgetComponent( - model.widgetId) - opacity: topBarContent.getWidgetEnabled( - model.enabled) ? 1 : 0 - asynchronous: false - - } - } - } - - Component { - id: clipboardComponent + Rectangle { + anchors.fill: parent + radius: SettingsData.topBarSquareCorners ? 0 : Theme.cornerRadius + color: Qt.rgba(Theme.surfaceContainer.r, + Theme.surfaceContainer.g, + Theme.surfaceContainer.b, + topBarCore.backgroundTransparency) + layer.enabled: true Rectangle { - readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (root.widgetHeight / 30)) - width: clipboardIcon.width + horizontalPadding * 2 - height: root.widgetHeight - radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius - color: { - if (SettingsData.topBarNoBackground) return "transparent" - const baseColor = clipboardArea.containsMouse ? Theme.primaryHover : Theme.secondaryHover - return Qt.rgba( - baseColor.r, baseColor.g, - baseColor.b, - baseColor.a * Theme.widgetTransparency) - } + anchors.fill: parent + color: "transparent" + border.color: Theme.outlineMedium + border.width: 1 + radius: parent.radius + } - DankIcon { - id: clipboardIcon - anchors.centerIn: parent - name: "content_paste" - size: Theme.iconSize - 6 - color: Theme.surfaceText - } + Rectangle { + anchors.fill: parent + color: Qt.rgba(Theme.surfaceTint.r, + Theme.surfaceTint.g, + Theme.surfaceTint.b, 0.04) + radius: parent.radius - MouseArea { - id: clipboardArea + SequentialAnimation on opacity { + running: false + loops: Animation.Infinite - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onClicked: { - clipboardHistoryModalPopup.toggle() + NumberAnimation { + to: 0.08 + duration: Theme.extraLongDuration + easing.type: Theme.standardEasing } - } - Behavior on color { - ColorAnimation { - duration: Theme.shortDuration + NumberAnimation { + to: 0.02 + duration: Theme.extraLongDuration easing.type: Theme.standardEasing } } } - } - Component { - id: launcherButtonComponent - - LauncherButton { - isActive: false - widgetHeight: root.widgetHeight - barHeight: root.effectiveBarHeight - section: { - if (parent && parent.parent) { - if (parent.parent === leftSection) - return "left" - if (parent.parent === rightSection) - return "right" - if (parent.parent === centerSection) - return "center" - } - return "left" - } - popupTarget: appDrawerLoader.item - parentScreen: root.screen - onClicked: { - appDrawerLoader.active = true - if (appDrawerLoader.item) - appDrawerLoader.item.toggle() - } + layer.effect: MultiEffect { + shadowEnabled: true + shadowHorizontalOffset: 0 + shadowVerticalOffset: 4 + shadowBlur: 0.5 // radius/32, adjusted for visual match + shadowColor: Qt.rgba(0, 0, 0, 0.15) + shadowOpacity: 0.15 } } - Component { - id: workspaceSwitcherComponent + Item { + id: topBarContent - WorkspaceSwitcher { - screenName: root.screenName - widgetHeight: root.widgetHeight + readonly property int availableWidth: width + readonly property int launcherButtonWidth: 40 + readonly property int workspaceSwitcherWidth: 120 // Approximate + readonly property int focusedAppMaxWidth: 456 // Fixed width since we don't have focusedApp reference + readonly property int estimatedLeftSectionWidth: launcherButtonWidth + workspaceSwitcherWidth + focusedAppMaxWidth + (Theme.spacingXS * 2) + readonly property int rightSectionWidth: rightSection.width + readonly property int clockWidth: 120 // Approximate clock width + readonly property int mediaMaxWidth: 280 // Normal max width + readonly property int weatherWidth: 80 // Approximate weather width + readonly property bool validLayout: availableWidth > 100 + && estimatedLeftSectionWidth > 0 + && rightSectionWidth > 0 + readonly property int clockLeftEdge: (availableWidth - clockWidth) / 2 + readonly property int clockRightEdge: clockLeftEdge + clockWidth + readonly property int leftSectionRightEdge: estimatedLeftSectionWidth + readonly property int mediaLeftEdge: clockLeftEdge - mediaMaxWidth + - Theme.spacingS + readonly property int rightSectionLeftEdge: availableWidth + - rightSectionWidth + readonly property int leftToClockGap: Math.max( + 0, + clockLeftEdge + - leftSectionRightEdge) + readonly property int leftToMediaGap: mediaMaxWidth > 0 ? Math.max(0, mediaLeftEdge - leftSectionRightEdge) : leftToClockGap + readonly property int mediaToClockGap: mediaMaxWidth + > 0 ? Theme.spacingS : 0 + readonly property int clockToRightGap: validLayout ? Math.max(0, rightSectionLeftEdge - clockRightEdge) : 1000 + readonly property bool spacingTight: validLayout + && (leftToMediaGap < 150 + || clockToRightGap < 100) + readonly property bool overlapping: validLayout + && (leftToMediaGap < 100 + || clockToRightGap < 50) + + function getWidgetEnabled(enabled) { + return enabled !== undefined ? enabled : true } - } - Component { - id: focusedWindowComponent - - FocusedApp { - availableWidth: topBarContent.leftToMediaGap - widgetHeight: root.widgetHeight + function getWidgetVisible(widgetId) { + switch (widgetId) { + case "launcherButton": + return true + case "workspaceSwitcher": + return true + case "focusedWindow": + return true + case "runningApps": + return true + case "clock": + return true + case "music": + return true + case "weather": + return true + case "systemTray": + return true + case "privacyIndicator": + return true + case "clipboard": + return true + case "cpuUsage": + return DgopService.dgopAvailable + case "memUsage": + return DgopService.dgopAvailable + case "cpuTemp": + return DgopService.dgopAvailable + case "gpuTemp": + return DgopService.dgopAvailable + case "notificationButton": + return true + case "battery": + return true + case "controlCenterButton": + return true + case "idleInhibitor": + return true + case "spacer": + return true + case "separator": + return true + case "network_speed_monitor": + return DgopService.dgopAvailable + case "keyboard_layout_name": + return true + case "vpn": + return true + case "notepadButton": + return true + default: + return false + } } - } - Component { - id: runningAppsComponent - - RunningApps { - widgetHeight: root.widgetHeight - section: { - if (parent && parent.parent === leftSection) - return "left" - if (parent && parent.parent === rightSection) - return "right" - if (parent && parent.parent === centerSection) - return "center" - return "left" + function getWidgetComponent(widgetId) { + switch (widgetId) { + case "launcherButton": + return launcherButtonComponent + case "workspaceSwitcher": + return workspaceSwitcherComponent + case "focusedWindow": + return focusedWindowComponent + case "runningApps": + return runningAppsComponent + case "clock": + return clockComponent + case "music": + return mediaComponent + case "weather": + return weatherComponent + case "systemTray": + return systemTrayComponent + case "privacyIndicator": + return privacyIndicatorComponent + case "clipboard": + return clipboardComponent + case "cpuUsage": + return cpuUsageComponent + case "memUsage": + return memUsageComponent + case "cpuTemp": + return cpuTempComponent + case "gpuTemp": + return gpuTempComponent + case "notificationButton": + return notificationButtonComponent + case "battery": + return batteryComponent + case "controlCenterButton": + return controlCenterButtonComponent + case "idleInhibitor": + return idleInhibitorComponent + case "spacer": + return spacerComponent + case "separator": + return separatorComponent + case "network_speed_monitor": + return networkComponent + case "keyboard_layout_name": + return keyboardLayoutNameComponent + case "vpn": + return vpnComponent + case "notepadButton": + return notepadButtonComponent + default: + return null } - parentScreen: root.screen - topBar: topBarContent } - } - Component { - id: clockComponent + anchors.fill: parent + anchors.leftMargin: Math.max( + Theme.spacingXS, + SettingsData.topBarInnerPadding * 0.8) + anchors.rightMargin: Math.max( + Theme.spacingXS, + SettingsData.topBarInnerPadding * 0.8) + anchors.topMargin: SettingsData.topBarInnerPadding / 2 + anchors.bottomMargin: SettingsData.topBarInnerPadding / 2 + clip: true - Clock { - compactMode: topBarContent.overlapping - barHeight: root.effectiveBarHeight - widgetHeight: root.widgetHeight - section: { - if (parent && parent.parent === leftSection) - return "left" - if (parent && parent.parent === rightSection) - return "right" - if (parent && parent.parent === centerSection) - return "center" - return "center" - } - popupTarget: { - centcomPopoutLoader.active = true - return centcomPopoutLoader.item - } - parentScreen: root.screen - onClockClicked: { - centcomPopoutLoader.active = true - if (centcomPopoutLoader.item) { - centcomPopoutLoader.item.calendarVisible - = !centcomPopoutLoader.item.calendarVisible + Row { + id: leftSection + + height: parent.height + spacing: SettingsData.topBarNoBackground ? 2 : Theme.spacingXS + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + + Repeater { + model: SettingsData.topBarLeftWidgetsModel + + Loader { + property string widgetId: model.widgetId + property var widgetData: model + property int spacerSize: model.size || 20 + + anchors.verticalCenter: parent ? parent.verticalCenter : undefined + active: topBarContent.getWidgetVisible( + model.widgetId) + sourceComponent: topBarContent.getWidgetComponent( + model.widgetId) + opacity: topBarContent.getWidgetEnabled( + model.enabled) ? 1 : 0 + asynchronous: false } } } - } - Component { - id: mediaComponent + Item { + id: centerSection - Media { - compactMode: topBarContent.spacingTight - || topBarContent.overlapping - barHeight: root.effectiveBarHeight - widgetHeight: root.widgetHeight - section: { - if (parent && parent.parent === leftSection) - return "left" - if (parent && parent.parent === rightSection) - return "right" - if (parent && parent.parent === centerSection) - return "center" - return "center" + property var centerWidgets: [] + property int totalWidgets: 0 + property real totalWidth: 0 + property real spacing: SettingsData.topBarNoBackground ? 2 : Theme.spacingS + + function updateLayout() { + // Defer layout if dimensions are invalid + if (width <= 0 || height <= 0 || !visible) { + Qt.callLater(updateLayout) + return + } + + centerWidgets = [] + totalWidgets = 0 + totalWidth = 0 + for (var i = 0; i < centerRepeater.count; i++) { + let item = centerRepeater.itemAt(i) + if (item && item.active && item.item) { + centerWidgets.push(item.item) + totalWidgets++ + totalWidth += item.item.width + } + } + if (totalWidgets > 1) + totalWidth += spacing * (totalWidgets - 1) + + positionWidgets() } - popupTarget: { - centcomPopoutLoader.active = true - return centcomPopoutLoader.item + + function positionWidgets() { + if (totalWidgets === 0 || width <= 0) + return + + let parentCenterX = width / 2 + if (totalWidgets % 2 === 1) { + let middleIndex = Math.floor( + totalWidgets / 2) + let currentX = parentCenterX + - (centerWidgets[middleIndex].width / 2) + centerWidgets[middleIndex].x = currentX + centerWidgets[middleIndex].anchors.horizontalCenter = undefined + currentX = centerWidgets[middleIndex].x + for (var i = middleIndex - 1; i >= 0; i--) { + currentX -= (spacing + centerWidgets[i].width) + centerWidgets[i].x = currentX + centerWidgets[i].anchors.horizontalCenter = undefined + } + currentX = centerWidgets[middleIndex].x + + centerWidgets[middleIndex].width + for (var i = middleIndex + 1; i < totalWidgets; i++) { + currentX += spacing + centerWidgets[i].x = currentX + centerWidgets[i].anchors.horizontalCenter = undefined + currentX += centerWidgets[i].width + } + } else { + let leftMiddleIndex = (totalWidgets / 2) - 1 + let rightMiddleIndex = totalWidgets / 2 + let gapCenter = parentCenterX + let halfSpacing = spacing / 2 + centerWidgets[leftMiddleIndex].x = gapCenter + - halfSpacing - centerWidgets[leftMiddleIndex].width + centerWidgets[leftMiddleIndex].anchors.horizontalCenter + = undefined + centerWidgets[rightMiddleIndex].x = gapCenter + halfSpacing + centerWidgets[rightMiddleIndex].anchors.horizontalCenter + = undefined + let currentX = centerWidgets[leftMiddleIndex].x + for (var i = leftMiddleIndex - 1; i >= 0; i--) { + currentX -= (spacing + centerWidgets[i].width) + centerWidgets[i].x = currentX + centerWidgets[i].anchors.horizontalCenter = undefined + } + currentX = centerWidgets[rightMiddleIndex].x + + centerWidgets[rightMiddleIndex].width + for (var i = rightMiddleIndex + 1; i < totalWidgets; i++) { + currentX += spacing + centerWidgets[i].x = currentX + centerWidgets[i].anchors.horizontalCenter = undefined + currentX += centerWidgets[i].width + } + } } - parentScreen: root.screen - onClicked: { - centcomPopoutLoader.active = true - if (centcomPopoutLoader.item) { - centcomPopoutLoader.item.calendarVisible - = !centcomPopoutLoader.item.calendarVisible + + height: parent.height + width: parent.width + anchors.centerIn: parent + Component.onCompleted: { + Qt.callLater(() => { + Qt.callLater(updateLayout) + }) + } + + onWidthChanged: { + if (width > 0) { + Qt.callLater(updateLayout) + } + } + + onVisibleChanged: { + if (visible && width > 0) { + Qt.callLater(updateLayout) + } + } + + Repeater { + id: centerRepeater + + model: SettingsData.topBarCenterWidgetsModel + + Loader { + property string widgetId: model.widgetId + property var widgetData: model + property int spacerSize: model.size || 20 + + anchors.verticalCenter: parent ? parent.verticalCenter : undefined + active: topBarContent.getWidgetVisible( + model.widgetId) + sourceComponent: topBarContent.getWidgetComponent( + model.widgetId) + opacity: topBarContent.getWidgetEnabled( + model.enabled) ? 1 : 0 + asynchronous: false + + onLoaded: { + if (item) { + item.onWidthChanged.connect( + centerSection.updateLayout) + if (model.widgetId === "spacer") + item.spacerSize = Qt.binding( + () => { + return model.size + || 20 + }) + Qt.callLater(centerSection.updateLayout) + } + } + onActiveChanged: { + Qt.callLater(centerSection.updateLayout) + } + } + } + + Connections { + function onCountChanged() { + Qt.callLater(centerSection.updateLayout) + } + + target: SettingsData.topBarCenterWidgetsModel + } + } + + Row { + id: rightSection + + height: parent.height + spacing: SettingsData.topBarNoBackground ? 2 : Theme.spacingXS + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + + Repeater { + model: SettingsData.topBarRightWidgetsModel + + Loader { + property string widgetId: model.widgetId + property var widgetData: model + property int spacerSize: model.size || 20 + + anchors.verticalCenter: parent ? parent.verticalCenter : undefined + active: topBarContent.getWidgetVisible( + model.widgetId) + sourceComponent: topBarContent.getWidgetComponent( + model.widgetId) + opacity: topBarContent.getWidgetEnabled( + model.enabled) ? 1 : 0 + asynchronous: false } } } - } - Component { - id: weatherComponent + Component { + id: clipboardComponent - Weather { - barHeight: root.effectiveBarHeight - widgetHeight: root.widgetHeight - section: { - if (parent && parent.parent === leftSection) - return "left" - if (parent && parent.parent === rightSection) - return "right" - if (parent && parent.parent === centerSection) - return "center" - return "center" - } - popupTarget: { - centcomPopoutLoader.active = true - return centcomPopoutLoader.item - } - parentScreen: root.screen - onClicked: { - centcomPopoutLoader.active = true - if (centcomPopoutLoader.item) { - centcomPopoutLoader.item.calendarVisible - = !centcomPopoutLoader.item.calendarVisible + Rectangle { + readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (root.widgetHeight / 30)) + width: clipboardIcon.width + horizontalPadding * 2 + height: root.widgetHeight + radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius + color: { + if (SettingsData.topBarNoBackground) + return "transparent" + const baseColor = clipboardArea.containsMouse ? Theme.primaryHover : Theme.secondaryHover + return Qt.rgba( + baseColor.r, baseColor.g, + baseColor.b, + baseColor.a * Theme.widgetTransparency) } - } - } - } - Component { - id: systemTrayComponent - - SystemTrayBar { - parentWindow: root - parentScreen: root.screen - widgetHeight: root.widgetHeight - } - } - - Component { - id: privacyIndicatorComponent - - PrivacyIndicator { - widgetHeight: root.widgetHeight - section: { - if (parent && parent.parent === leftSection) - return "left" - if (parent && parent.parent === rightSection) - return "right" - if (parent && parent.parent === centerSection) - return "center" - return "right" - } - parentScreen: root.screen - } - } - - Component { - id: cpuUsageComponent - - CpuMonitor { - barHeight: root.effectiveBarHeight - widgetHeight: root.widgetHeight - section: { - if (parent && parent.parent === leftSection) - return "left" - if (parent && parent.parent === rightSection) - return "right" - if (parent && parent.parent === centerSection) - return "center" - return "right" - } - popupTarget: { - processListPopoutLoader.active = true - return processListPopoutLoader.item - } - parentScreen: root.screen - toggleProcessList: () => { - processListPopoutLoader.active = true - if (processListPopoutLoader.item) - return processListPopoutLoader.item.toggle() - } - } - } - - Component { - id: memUsageComponent - - RamMonitor { - barHeight: root.effectiveBarHeight - widgetHeight: root.widgetHeight - section: { - if (parent && parent.parent === leftSection) - return "left" - if (parent && parent.parent === rightSection) - return "right" - if (parent && parent.parent === centerSection) - return "center" - return "right" - } - popupTarget: { - processListPopoutLoader.active = true - return processListPopoutLoader.item - } - parentScreen: root.screen - toggleProcessList: () => { - processListPopoutLoader.active = true - if (processListPopoutLoader.item) - return processListPopoutLoader.item.toggle() - } - } - } - - Component { - id: cpuTempComponent - - CpuTemperature { - barHeight: root.effectiveBarHeight - widgetHeight: root.widgetHeight - section: { - if (parent && parent.parent === leftSection) - return "left" - if (parent && parent.parent === rightSection) - return "right" - if (parent && parent.parent === centerSection) - return "center" - return "right" - } - popupTarget: { - processListPopoutLoader.active = true - return processListPopoutLoader.item - } - parentScreen: root.screen - toggleProcessList: () => { - processListPopoutLoader.active = true - if (processListPopoutLoader.item) - return processListPopoutLoader.item.toggle() - } - } - } - - Component { - id: gpuTempComponent - - GpuTemperature { - barHeight: root.effectiveBarHeight - widgetHeight: root.widgetHeight - section: { - if (parent && parent.parent === leftSection) - return "left" - if (parent && parent.parent === rightSection) - return "right" - if (parent && parent.parent === centerSection) - return "center" - return "right" - } - popupTarget: { - processListPopoutLoader.active = true - return processListPopoutLoader.item - } - parentScreen: root.screen - widgetData: parent.widgetData - toggleProcessList: () => { - processListPopoutLoader.active = true - if (processListPopoutLoader.item) - return processListPopoutLoader.item.toggle() - } - } - } - - Component { - id: networkComponent - - NetworkMonitor {} - } - - Component { - id: notificationButtonComponent - - NotificationCenterButton { - hasUnread: root.notificationCount > 0 - isActive: notificationCenterLoader.item ? notificationCenterLoader.item.shouldBeVisible : false - widgetHeight: root.widgetHeight - barHeight: root.effectiveBarHeight - section: { - if (parent && parent.parent === leftSection) - return "left" - if (parent && parent.parent === rightSection) - return "right" - if (parent && parent.parent === centerSection) - return "center" - return "right" - } - popupTarget: { - notificationCenterLoader.active = true - return notificationCenterLoader.item - } - parentScreen: root.screen - onClicked: { - notificationCenterLoader.active = true - if (notificationCenterLoader.item) { - notificationCenterLoader.item.toggle() + DankIcon { + id: clipboardIcon + anchors.centerIn: parent + name: "content_paste" + size: Theme.iconSize - 6 + color: Theme.surfaceText } - } - } - } - Component { - id: batteryComponent + MouseArea { + id: clipboardArea - Battery { - batteryPopupVisible: batteryPopoutLoader.item ? batteryPopoutLoader.item.shouldBeVisible : false - widgetHeight: root.widgetHeight - barHeight: root.effectiveBarHeight - section: { - if (parent && parent.parent === leftSection) - return "left" - if (parent && parent.parent === rightSection) - return "right" - if (parent && parent.parent === centerSection) - return "center" - return "right" - } - popupTarget: { - batteryPopoutLoader.active = true - return batteryPopoutLoader.item - } - parentScreen: root.screen - onToggleBatteryPopup: { - batteryPopoutLoader.active = true - if (batteryPopoutLoader.item) { - batteryPopoutLoader.item.toggle() + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + clipboardHistoryModalPopup.toggle() + } } - } - } - } - Component { - id: vpnComponent - - Vpn { - widgetHeight: root.widgetHeight - barHeight: root.effectiveBarHeight - section: { - if (parent && parent.parent === leftSection) - return "left" - if (parent && parent.parent === rightSection) - return "right" - if (parent && parent.parent === centerSection) - return "center" - return "right" - } - popupTarget: { - vpnPopoutLoader.active = true - return vpnPopoutLoader.item - } - parentScreen: root.screen - onToggleVpnPopup: { - vpnPopoutLoader.active = true - if (vpnPopoutLoader.item) { - vpnPopoutLoader.item.toggle() - } - } - } - } - - Component { - id: controlCenterButtonComponent - - ControlCenterButton { - isActive: controlCenterLoader.item ? controlCenterLoader.item.shouldBeVisible : false - widgetHeight: root.widgetHeight - barHeight: root.effectiveBarHeight - section: { - if (parent && parent.parent === leftSection) - return "left" - if (parent && parent.parent === rightSection) - return "right" - if (parent && parent.parent === centerSection) - return "center" - return "right" - } - popupTarget: { - controlCenterLoader.active = true - return controlCenterLoader.item - } - parentScreen: root.screen - widgetData: parent.widgetData - onClicked: { - controlCenterLoader.active = true - if (controlCenterLoader.item) { - controlCenterLoader.item.triggerScreen = root.screen - controlCenterLoader.item.toggle() - if (controlCenterLoader.item.shouldBeVisible) { - if (NetworkService.wifiEnabled) - NetworkService.scanWifi() + Behavior on color { + ColorAnimation { + duration: Theme.shortDuration + easing.type: Theme.standardEasing } } } } - } - Component { - id: idleInhibitorComponent + Component { + id: launcherButtonComponent - IdleInhibitor { - widgetHeight: root.widgetHeight - section: { - if (parent && parent.parent === leftSection) + LauncherButton { + isActive: false + widgetHeight: root.widgetHeight + barHeight: root.effectiveBarHeight + section: { + if (parent && parent.parent) { + if (parent.parent === leftSection) + return "left" + if (parent.parent === rightSection) + return "right" + if (parent.parent === centerSection) + return "center" + } return "left" - if (parent && parent.parent === rightSection) - return "right" - if (parent && parent.parent === centerSection) - return "center" - return "right" - } - parentScreen: root.screen - } - } - - Component { - id: spacerComponent - - Item { - width: parent.spacerSize || 20 - height: root.widgetHeight - - Rectangle { - anchors.fill: parent - color: "transparent" - border.color: Qt.rgba(Theme.outline.r, - Theme.outline.g, - Theme.outline.b, 0.1) - border.width: 1 - radius: 2 - visible: false - - MouseArea { - anchors.fill: parent - hoverEnabled: true - onEntered: parent.visible = true - onExited: parent.visible = false + } + popupTarget: appDrawerLoader.item + parentScreen: root.screen + onClicked: { + appDrawerLoader.active = true + if (appDrawerLoader.item) + appDrawerLoader.item.toggle() } } } - } - Component { - id: separatorComponent + Component { + id: workspaceSwitcherComponent - Rectangle { - width: 1 - height: root.widgetHeight * 0.67 - color: Theme.outline - opacity: 0.3 + WorkspaceSwitcher { + screenName: root.screenName + widgetHeight: root.widgetHeight + } } - } - Component { - id: keyboardLayoutNameComponent + Component { + id: focusedWindowComponent - KeyboardLayoutName {} - } + FocusedApp { + availableWidth: topBarContent.leftToMediaGap + widgetHeight: root.widgetHeight + } + } - Component { - id: notepadButtonComponent + Component { + id: runningAppsComponent - NotepadButton { - isActive: notepadModalLoader.item ? notepadModalLoader.item.visible : false - widgetHeight: root.widgetHeight - barHeight: root.effectiveBarHeight - section: { - if (parent && parent.parent === leftSection) + RunningApps { + widgetHeight: root.widgetHeight + section: { + if (parent && parent.parent === leftSection) + return "left" + if (parent + && parent.parent === rightSection) + return "right" + if (parent + && parent.parent === centerSection) + return "center" return "left" - if (parent && parent.parent === rightSection) - return "right" - if (parent && parent.parent === centerSection) + } + parentScreen: root.screen + topBar: topBarContent + } + } + + Component { + id: clockComponent + + Clock { + compactMode: topBarContent.overlapping + barHeight: root.effectiveBarHeight + widgetHeight: root.widgetHeight + section: { + if (parent && parent.parent === leftSection) + return "left" + if (parent + && parent.parent === rightSection) + return "right" + if (parent + && parent.parent === centerSection) + return "center" return "center" - return "right" + } + popupTarget: { + centcomPopoutLoader.active = true + return centcomPopoutLoader.item + } + parentScreen: root.screen + onClockClicked: { + centcomPopoutLoader.active = true + if (centcomPopoutLoader.item) { + centcomPopoutLoader.item.calendarVisible + = !centcomPopoutLoader.item.calendarVisible + } + } } - popupTarget: { - notepadModalLoader.active = true - return notepadModalLoader.item + } + + Component { + id: mediaComponent + + Media { + compactMode: topBarContent.spacingTight + || topBarContent.overlapping + barHeight: root.effectiveBarHeight + widgetHeight: root.widgetHeight + section: { + if (parent && parent.parent === leftSection) + return "left" + if (parent + && parent.parent === rightSection) + return "right" + if (parent + && parent.parent === centerSection) + return "center" + return "center" + } + popupTarget: { + centcomPopoutLoader.active = true + return centcomPopoutLoader.item + } + parentScreen: root.screen + onClicked: { + centcomPopoutLoader.active = true + if (centcomPopoutLoader.item) { + centcomPopoutLoader.item.calendarVisible + = !centcomPopoutLoader.item.calendarVisible + } + } } - parentScreen: root.screen - onClicked: { - notepadModalLoader.active = true - if (notepadModalLoader.item) { - notepadModalLoader.item.toggle() + } + + Component { + id: weatherComponent + + Weather { + barHeight: root.effectiveBarHeight + widgetHeight: root.widgetHeight + section: { + if (parent && parent.parent === leftSection) + return "left" + if (parent + && parent.parent === rightSection) + return "right" + if (parent + && parent.parent === centerSection) + return "center" + return "center" + } + popupTarget: { + centcomPopoutLoader.active = true + return centcomPopoutLoader.item + } + parentScreen: root.screen + onClicked: { + centcomPopoutLoader.active = true + if (centcomPopoutLoader.item) { + centcomPopoutLoader.item.calendarVisible + = !centcomPopoutLoader.item.calendarVisible + } + } + } + } + + Component { + id: systemTrayComponent + + SystemTrayBar { + parentWindow: root + parentScreen: root.screen + widgetHeight: root.widgetHeight + } + } + + Component { + id: privacyIndicatorComponent + + PrivacyIndicator { + widgetHeight: root.widgetHeight + section: { + if (parent && parent.parent === leftSection) + return "left" + if (parent + && parent.parent === rightSection) + return "right" + if (parent + && parent.parent === centerSection) + return "center" + return "right" + } + parentScreen: root.screen + } + } + + Component { + id: cpuUsageComponent + + CpuMonitor { + barHeight: root.effectiveBarHeight + widgetHeight: root.widgetHeight + section: { + if (parent && parent.parent === leftSection) + return "left" + if (parent + && parent.parent === rightSection) + return "right" + if (parent + && parent.parent === centerSection) + return "center" + return "right" + } + popupTarget: { + processListPopoutLoader.active = true + return processListPopoutLoader.item + } + parentScreen: root.screen + toggleProcessList: () => { + processListPopoutLoader.active = true + if (processListPopoutLoader.item) + return processListPopoutLoader.item.toggle() + } + } + } + + Component { + id: memUsageComponent + + RamMonitor { + barHeight: root.effectiveBarHeight + widgetHeight: root.widgetHeight + section: { + if (parent && parent.parent === leftSection) + return "left" + if (parent + && parent.parent === rightSection) + return "right" + if (parent + && parent.parent === centerSection) + return "center" + return "right" + } + popupTarget: { + processListPopoutLoader.active = true + return processListPopoutLoader.item + } + parentScreen: root.screen + toggleProcessList: () => { + processListPopoutLoader.active = true + if (processListPopoutLoader.item) + return processListPopoutLoader.item.toggle() + } + } + } + + Component { + id: cpuTempComponent + + CpuTemperature { + barHeight: root.effectiveBarHeight + widgetHeight: root.widgetHeight + section: { + if (parent && parent.parent === leftSection) + return "left" + if (parent + && parent.parent === rightSection) + return "right" + if (parent + && parent.parent === centerSection) + return "center" + return "right" + } + popupTarget: { + processListPopoutLoader.active = true + return processListPopoutLoader.item + } + parentScreen: root.screen + toggleProcessList: () => { + processListPopoutLoader.active = true + if (processListPopoutLoader.item) + return processListPopoutLoader.item.toggle() + } + } + } + + Component { + id: gpuTempComponent + + GpuTemperature { + barHeight: root.effectiveBarHeight + widgetHeight: root.widgetHeight + section: { + if (parent && parent.parent === leftSection) + return "left" + if (parent + && parent.parent === rightSection) + return "right" + if (parent + && parent.parent === centerSection) + return "center" + return "right" + } + popupTarget: { + processListPopoutLoader.active = true + return processListPopoutLoader.item + } + parentScreen: root.screen + widgetData: parent.widgetData + toggleProcessList: () => { + processListPopoutLoader.active = true + if (processListPopoutLoader.item) + return processListPopoutLoader.item.toggle() + } + } + } + + Component { + id: networkComponent + + NetworkMonitor {} + } + + Component { + id: notificationButtonComponent + + NotificationCenterButton { + hasUnread: root.notificationCount > 0 + isActive: notificationCenterLoader.item ? notificationCenterLoader.item.shouldBeVisible : false + widgetHeight: root.widgetHeight + barHeight: root.effectiveBarHeight + section: { + if (parent && parent.parent === leftSection) + return "left" + if (parent + && parent.parent === rightSection) + return "right" + if (parent + && parent.parent === centerSection) + return "center" + return "right" + } + popupTarget: { + notificationCenterLoader.active = true + return notificationCenterLoader.item + } + parentScreen: root.screen + onClicked: { + notificationCenterLoader.active = true + if (notificationCenterLoader.item) { + notificationCenterLoader.item.toggle() + } + } + } + } + + Component { + id: batteryComponent + + Battery { + batteryPopupVisible: batteryPopoutLoader.item ? batteryPopoutLoader.item.shouldBeVisible : false + widgetHeight: root.widgetHeight + barHeight: root.effectiveBarHeight + section: { + if (parent && parent.parent === leftSection) + return "left" + if (parent + && parent.parent === rightSection) + return "right" + if (parent + && parent.parent === centerSection) + return "center" + return "right" + } + popupTarget: { + batteryPopoutLoader.active = true + return batteryPopoutLoader.item + } + parentScreen: root.screen + onToggleBatteryPopup: { + batteryPopoutLoader.active = true + if (batteryPopoutLoader.item) { + batteryPopoutLoader.item.toggle() + } + } + } + } + + Component { + id: vpnComponent + + Vpn { + widgetHeight: root.widgetHeight + barHeight: root.effectiveBarHeight + section: { + if (parent && parent.parent === leftSection) + return "left" + if (parent + && parent.parent === rightSection) + return "right" + if (parent + && parent.parent === centerSection) + return "center" + return "right" + } + popupTarget: { + vpnPopoutLoader.active = true + return vpnPopoutLoader.item + } + parentScreen: root.screen + onToggleVpnPopup: { + vpnPopoutLoader.active = true + if (vpnPopoutLoader.item) { + vpnPopoutLoader.item.toggle() + } + } + } + } + + Component { + id: controlCenterButtonComponent + + ControlCenterButton { + isActive: controlCenterLoader.item ? controlCenterLoader.item.shouldBeVisible : false + widgetHeight: root.widgetHeight + barHeight: root.effectiveBarHeight + section: { + if (parent && parent.parent === leftSection) + return "left" + if (parent + && parent.parent === rightSection) + return "right" + if (parent + && parent.parent === centerSection) + return "center" + return "right" + } + popupTarget: { + controlCenterLoader.active = true + return controlCenterLoader.item + } + parentScreen: root.screen + widgetData: parent.widgetData + onClicked: { + controlCenterLoader.active = true + if (controlCenterLoader.item) { + controlCenterLoader.item.triggerScreen = root.screen + controlCenterLoader.item.toggle() + if (controlCenterLoader.item.shouldBeVisible) { + if (NetworkService.wifiEnabled) + NetworkService.scanWifi() + } + } + } + } + } + + Component { + id: idleInhibitorComponent + + IdleInhibitor { + widgetHeight: root.widgetHeight + section: { + if (parent && parent.parent === leftSection) + return "left" + if (parent + && parent.parent === rightSection) + return "right" + if (parent + && parent.parent === centerSection) + return "center" + return "right" + } + parentScreen: root.screen + } + } + + Component { + id: spacerComponent + + Item { + width: parent.spacerSize || 20 + height: root.widgetHeight + + Rectangle { + anchors.fill: parent + color: "transparent" + border.color: Qt.rgba(Theme.outline.r, + Theme.outline.g, + Theme.outline.b, 0.1) + border.width: 1 + radius: 2 + visible: false + + MouseArea { + anchors.fill: parent + hoverEnabled: true + onEntered: parent.visible = true + onExited: parent.visible = false + } + } + } + } + + Component { + id: separatorComponent + + Rectangle { + width: 1 + height: root.widgetHeight * 0.67 + color: Theme.outline + opacity: 0.3 + } + } + + Component { + id: keyboardLayoutNameComponent + + KeyboardLayoutName {} + } + + Component { + id: notepadButtonComponent + + NotepadButton { + isActive: notepadModalLoader.item ? notepadModalLoader.item.visible : false + widgetHeight: root.widgetHeight + barHeight: root.effectiveBarHeight + section: { + if (parent && parent.parent === leftSection) + return "left" + if (parent + && parent.parent === rightSection) + return "right" + if (parent + && parent.parent === centerSection) + return "center" + return "right" + } + popupTarget: { + notepadModalLoader.active = true + return notepadModalLoader.item + } + parentScreen: root.screen + onClicked: { + notepadModalLoader.active = true + if (notepadModalLoader.item) { + notepadModalLoader.item.toggle() + } } } } diff --git a/Widgets/DankPopout.qml b/Widgets/DankPopout.qml index 7f7ce132..4b9a085e 100644 --- a/Widgets/DankPopout.qml +++ b/Widgets/DankPopout.qml @@ -137,32 +137,28 @@ PanelWindow { active: root.visible asynchronous: false } - } - FocusScope { - anchors.fill: parent - visible: shouldBeVisible - focus: shouldBeVisible - - Keys.onPressed: event => { - if (event.key === Qt.Key_Escape) { - close() - event.accepted = true - } else { - // Forward all non-escape keys to content - event.accepted = false - } - } - - onVisibleChanged: { - if (visible) { - Qt.callLater(function () { - if (contentLoader.item) { - contentLoader.item.forceActiveFocus() - } else { - forceActiveFocus() - } - }) + Item { + anchors.fill: parent + focus: true + + Keys.onPressed: event => { + if (event.key === Qt.Key_Escape) { + close() + event.accepted = true + } else { + event.accepted = false + } + } + + Component.onCompleted: { + forceActiveFocus() + } + + onVisibleChanged: { + if (visible) { + forceActiveFocus() + } } } }