1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-13 01:02:18 -04:00
Files
DankMaterialShell/quickshell/Modules/DankBar/DankBarContent.qml
Thomas Kroll 049266271a fix(system-update): popout first-click and AUR package listing (#2183)
* fix(system-update): open popout on first click

The SystemUpdate widget required two clicks to open its popout.

On the first click, the LazyLoader was activated but popoutTarget
(bound to the loader's item) was still null in the MouseArea handler,
so setTriggerPosition was never called. The popout's open() then
returned early because screen was unset.

Restructure the onClicked handler to call setTriggerPosition directly
on the loaded item (matching the pattern used by Clock, Clipboard, and
other bar widgets) and use PopoutManager.requestPopout() instead of
toggle() for consistent popout management.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(system-update): include AUR packages in update list

When paru or yay is the package manager, the update list only showed
official repo packages (via checkupdates or -Qu) while the upgrade
command (paru/yay -Syu) also processes AUR packages. This mismatch
meant AUR updates appeared as a surprise during the upgrade.

Combine the repo update listing with the AUR helper's -Qua flag so
both official and AUR packages are shown in the popout before the
user triggers the upgrade. The output format is identical for both
sources, so the existing parser works unchanged.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 10:49:15 -04:00

1460 lines
65 KiB
QML

import QtQuick
import Quickshell.Hyprland
import Quickshell.I3
import Quickshell.Services.SystemTray
import Quickshell.Wayland
import qs.Common
import qs.Modules.DankBar.Widgets
import qs.Services
Item {
id: topBarContent
required property var barWindow
required property var rootWindow
required property var barConfig
readonly property var blurBarWindow: barWindow
property var leftWidgetsModel
property var centerWidgetsModel
property var rightWidgetsModel
readonly property real innerPadding: barConfig?.innerPadding ?? 4
readonly property real outlineThickness: (barConfig?.widgetOutlineEnabled ?? false) ? (barConfig?.widgetOutlineThickness ?? 1) : 0
property alias hLeftSection: hLeftSection
property alias hCenterSection: hCenterSection
property alias hRightSection: hRightSection
property alias vLeftSection: vLeftSection
property alias vCenterSection: vCenterSection
property alias vRightSection: vRightSection
anchors.fill: parent
anchors.leftMargin: Math.max(Theme.spacingXS, innerPadding * 0.8)
anchors.rightMargin: Math.max(Theme.spacingXS, innerPadding * 0.8)
anchors.topMargin: barWindow.isVertical ? (barWindow.hasAdjacentTopBar ? outlineThickness : Theme.spacingXS) : 0
anchors.bottomMargin: barWindow.isVertical ? (barWindow.hasAdjacentBottomBar ? outlineThickness : Theme.spacingXS) : 0
clip: false
property int componentMapRevision: 0
function updateComponentMap() {
componentMapRevision++;
}
readonly property var sortedToplevels: {
return CompositorService.filterCurrentWorkspace(CompositorService.sortedToplevels, barWindow.screenName);
}
function getRealWorkspaces() {
if (CompositorService.isNiri) {
const fallbackWorkspaces = [
{
"id": 1,
"idx": 0,
"name": ""
},
{
"id": 2,
"idx": 1,
"name": ""
}
];
if (!barWindow.screenName || SettingsData.workspaceFollowFocus) {
const currentWorkspaces = NiriService.getCurrentOutputWorkspaces();
return currentWorkspaces.length > 0 ? currentWorkspaces : fallbackWorkspaces;
}
const workspaces = NiriService.allWorkspaces.filter(ws => ws.output === barWindow.screenName);
return workspaces.length > 0 ? workspaces : fallbackWorkspaces;
} else if (CompositorService.isHyprland) {
const workspaces = Hyprland.workspaces?.values || [];
if (!barWindow.screenName || SettingsData.workspaceFollowFocus) {
const sorted = workspaces.slice().sort((a, b) => a.id - b.id);
const filtered = sorted.filter(ws => ws.id > -1);
return filtered.length > 0 ? filtered : [
{
"id": 1,
"name": "1"
}
];
}
const monitorWorkspaces = workspaces.filter(ws => {
return ws.lastIpcObject && ws.lastIpcObject.monitor === barWindow.screenName && ws.id > -1;
});
if (monitorWorkspaces.length === 0) {
return [
{
"id": 1,
"name": "1"
}
];
}
return monitorWorkspaces.sort((a, b) => a.id - b.id);
} else if (CompositorService.isDwl) {
if (!DwlService.dwlAvailable) {
return [0];
}
if (SettingsData.dwlShowAllTags) {
return Array.from({
length: DwlService.tagCount
}, (_, i) => i);
}
return DwlService.getVisibleTags(barWindow.screenName);
} else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) {
const workspaces = I3.workspaces?.values || [];
if (workspaces.length === 0)
return [
{
"num": 1
}
];
if (!barWindow.screenName || SettingsData.workspaceFollowFocus) {
return workspaces.slice().sort((a, b) => a.num - b.num);
}
const monitorWorkspaces = workspaces.filter(ws => ws.monitor?.name === barWindow.screenName);
return monitorWorkspaces.length > 0 ? monitorWorkspaces.sort((a, b) => a.num - b.num) : [
{
"num": 1
}
];
}
return [1];
}
function getCurrentWorkspace() {
if (CompositorService.isNiri) {
if (!barWindow.screenName || SettingsData.workspaceFollowFocus) {
return NiriService.getCurrentWorkspaceNumber();
}
const activeWs = NiriService.allWorkspaces.find(ws => ws.output === barWindow.screenName && ws.is_active);
return activeWs ? activeWs.idx : 1;
} else if (CompositorService.isHyprland) {
const monitors = Hyprland.monitors?.values || [];
const currentMonitor = monitors.find(monitor => monitor.name === barWindow.screenName);
return currentMonitor?.activeWorkspace?.id ?? 1;
} else if (CompositorService.isDwl) {
if (!DwlService.dwlAvailable)
return 0;
const outputState = DwlService.getOutputState(barWindow.screenName);
if (!outputState || !outputState.tags)
return 0;
const activeTags = DwlService.getActiveTags(barWindow.screenName);
return activeTags.length > 0 ? activeTags[0] : 0;
} else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) {
if (!barWindow.screenName || SettingsData.workspaceFollowFocus) {
const focusedWs = I3.workspaces?.values?.find(ws => ws.focused === true);
return focusedWs ? focusedWs.num : 1;
}
const focusedWs = I3.workspaces?.values?.find(ws => ws.monitor?.name === barWindow.screenName && ws.focused === true);
return focusedWs ? focusedWs.num : 1;
}
return 1;
}
function switchWorkspace(direction) {
const realWorkspaces = getRealWorkspaces();
if (realWorkspaces.length < 2) {
return;
}
if (CompositorService.isNiri) {
const currentWs = getCurrentWorkspace();
const currentIndex = realWorkspaces.findIndex(ws => ws && ws.idx === currentWs);
const validIndex = currentIndex === -1 ? 0 : currentIndex;
const nextIndex = direction > 0 ? Math.min(validIndex + 1, realWorkspaces.length - 1) : Math.max(validIndex - 1, 0);
if (nextIndex !== validIndex) {
const nextWorkspace = realWorkspaces[nextIndex];
if (!nextWorkspace || nextWorkspace.idx === undefined) {
return;
}
NiriService.switchToWorkspace(nextWorkspace.idx);
}
} else if (CompositorService.isHyprland) {
const currentWs = getCurrentWorkspace();
const currentIndex = realWorkspaces.findIndex(ws => ws.id === currentWs);
const validIndex = currentIndex === -1 ? 0 : currentIndex;
const nextIndex = direction > 0 ? Math.min(validIndex + 1, realWorkspaces.length - 1) : Math.max(validIndex - 1, 0);
if (nextIndex !== validIndex) {
Hyprland.dispatch(`workspace ${realWorkspaces[nextIndex].id}`);
}
} else if (CompositorService.isDwl) {
const currentTag = getCurrentWorkspace();
const currentIndex = realWorkspaces.findIndex(tag => tag === currentTag);
const validIndex = currentIndex === -1 ? 0 : currentIndex;
const nextIndex = direction > 0 ? Math.min(validIndex + 1, realWorkspaces.length - 1) : Math.max(validIndex - 1, 0);
if (nextIndex !== validIndex) {
DwlService.switchToTag(barWindow.screenName, realWorkspaces[nextIndex]);
}
} else if (CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) {
const currentWs = getCurrentWorkspace();
const currentIndex = realWorkspaces.findIndex(ws => ws.num === currentWs);
const validIndex = currentIndex === -1 ? 0 : currentIndex;
const nextIndex = direction > 0 ? Math.min(validIndex + 1, realWorkspaces.length - 1) : Math.max(validIndex - 1, 0);
if (nextIndex !== validIndex) {
try {
I3.dispatch(`workspace number ${realWorkspaces[nextIndex].num}`);
} catch (_) {}
}
}
}
function switchApp(deltaY) {
const windows = sortedToplevels;
if (windows.length < 2) {
return;
}
let currentIndex = -1;
for (let i = 0; i < windows.length; i++) {
if (windows[i].activated) {
currentIndex = i;
break;
}
}
let nextIndex;
if (deltaY < 0) {
if (currentIndex === -1) {
nextIndex = 0;
} else {
nextIndex = currentIndex + 1;
}
} else {
if (currentIndex === -1) {
nextIndex = windows.length - 1;
} else {
nextIndex = currentIndex - 1;
}
}
const nextWindow = windows[nextIndex];
if (nextWindow) {
nextWindow.activate();
}
}
readonly property int availableWidth: width
readonly property int launcherButtonWidth: 40
readonly property int workspaceSwitcherWidth: 120
readonly property int focusedAppMaxWidth: 456
readonly property int estimatedLeftSectionWidth: launcherButtonWidth + workspaceSwitcherWidth + focusedAppMaxWidth + (Theme.spacingXS * 2)
readonly property int rightSectionWidth: 200
readonly property int clockWidth: 120
readonly property int mediaMaxWidth: 280
readonly property int weatherWidth: 80
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: !barWindow.isVertical && validLayout && (leftToMediaGap < 150 || clockToRightGap < 100)
readonly property bool overlapping: !barWindow.isVertical && validLayout && (leftToMediaGap < 100 || clockToRightGap < 50)
function getWidgetEnabled(enabled) {
return enabled !== false;
}
function getWidgetSection(parentItem) {
let current = parentItem;
while (current) {
if (current.objectName === "leftSection") {
return "left";
}
if (current.objectName === "centerSection") {
return "center";
}
if (current.objectName === "rightSection") {
return "right";
}
current = current.parent;
}
return "left";
}
readonly property var widgetVisibility: ({
"cpuUsage": DgopService.dgopAvailable,
"memUsage": DgopService.dgopAvailable,
"cpuTemp": DgopService.dgopAvailable,
"gpuTemp": DgopService.dgopAvailable,
"network_speed_monitor": DgopService.dgopAvailable
})
function getWidgetVisible(widgetId) {
return widgetVisibility[widgetId] ?? true;
}
readonly property var componentMap: {
componentMapRevision;
let baseMap = {
"launcherButton": launcherButtonComponent,
"workspaceSwitcher": workspaceSwitcherComponent,
"focusedWindow": focusedWindowComponent,
"runningApps": runningAppsComponent,
"appsDock": appsDockComponent,
"clock": clockComponent,
"music": mediaComponent,
"weather": weatherComponent,
"systemTray": systemTrayComponent,
"privacyIndicator": privacyIndicatorComponent,
"clipboard": clipboardComponent,
"cpuUsage": cpuUsageComponent,
"memUsage": memUsageComponent,
"diskUsage": diskUsageComponent,
"cpuTemp": cpuTempComponent,
"gpuTemp": gpuTempComponent,
"notificationButton": notificationButtonComponent,
"battery": batteryComponent,
"layout": layoutComponent,
"controlCenterButton": controlCenterButtonComponent,
"capsLockIndicator": capsLockIndicatorComponent,
"idleInhibitor": idleInhibitorComponent,
"spacer": spacerComponent,
"separator": separatorComponent,
"network_speed_monitor": networkComponent,
"keyboard_layout_name": keyboardLayoutNameComponent,
"vpn": vpnComponent,
"notepadButton": notepadButtonComponent,
"colorPicker": colorPickerComponent,
"systemUpdate": systemUpdateComponent,
"powerMenuButton": powerMenuButtonComponent
};
let pluginMap = PluginService.getWidgetComponents();
return Object.assign(baseMap, pluginMap);
}
function getWidgetComponent(widgetId) {
return componentMap[widgetId] || null;
}
readonly property var allComponents: ({
"launcherButtonComponent": launcherButtonComponent,
"workspaceSwitcherComponent": workspaceSwitcherComponent,
"focusedWindowComponent": focusedWindowComponent,
"runningAppsComponent": runningAppsComponent,
"appsDockComponent": appsDockComponent,
"clockComponent": clockComponent,
"mediaComponent": mediaComponent,
"weatherComponent": weatherComponent,
"systemTrayComponent": systemTrayComponent,
"privacyIndicatorComponent": privacyIndicatorComponent,
"clipboardComponent": clipboardComponent,
"cpuUsageComponent": cpuUsageComponent,
"memUsageComponent": memUsageComponent,
"diskUsageComponent": diskUsageComponent,
"cpuTempComponent": cpuTempComponent,
"gpuTempComponent": gpuTempComponent,
"notificationButtonComponent": notificationButtonComponent,
"batteryComponent": batteryComponent,
"layoutComponent": layoutComponent,
"controlCenterButtonComponent": controlCenterButtonComponent,
"capsLockIndicatorComponent": capsLockIndicatorComponent,
"idleInhibitorComponent": idleInhibitorComponent,
"spacerComponent": spacerComponent,
"separatorComponent": separatorComponent,
"networkComponent": networkComponent,
"keyboardLayoutNameComponent": keyboardLayoutNameComponent,
"vpnComponent": vpnComponent,
"notepadButtonComponent": notepadButtonComponent,
"colorPickerComponent": colorPickerComponent,
"systemUpdateComponent": systemUpdateComponent,
"powerMenuButtonComponent": powerMenuButtonComponent
})
Item {
id: stackContainer
anchors.fill: parent
Item {
id: horizontalStack
anchors.fill: parent
visible: !barWindow.axis.isVertical
LeftSection {
id: hLeftSection
objectName: "leftSection"
overrideAxisLayout: true
forceVerticalLayout: false
anchors {
left: parent.left
verticalCenter: parent.verticalCenter
}
axis: barWindow.axis
widgetsModel: topBarContent.leftWidgetsModel
components: topBarContent.allComponents
noBackground: barConfig?.noBackground ?? false
parentScreen: barWindow.screen
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
barSpacing: barConfig?.spacing ?? 4
}
Binding {
target: hLeftSection
property: "barConfig"
value: topBarContent.barConfig
restoreMode: Binding.RestoreNone
}
Binding {
target: hLeftSection
property: "blurBarWindow"
value: topBarContent.blurBarWindow
restoreMode: Binding.RestoreNone
}
RightSection {
id: hRightSection
objectName: "rightSection"
overrideAxisLayout: true
forceVerticalLayout: false
anchors {
right: parent.right
verticalCenter: parent.verticalCenter
}
axis: barWindow.axis
widgetsModel: topBarContent.rightWidgetsModel
components: topBarContent.allComponents
noBackground: barConfig?.noBackground ?? false
parentScreen: barWindow.screen
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
barSpacing: barConfig?.spacing ?? 4
}
Binding {
target: hRightSection
property: "barConfig"
value: topBarContent.barConfig
restoreMode: Binding.RestoreNone
}
Binding {
target: hRightSection
property: "blurBarWindow"
value: topBarContent.blurBarWindow
restoreMode: Binding.RestoreNone
}
CenterSection {
id: hCenterSection
objectName: "centerSection"
overrideAxisLayout: true
forceVerticalLayout: false
anchors {
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
axis: barWindow.axis
widgetsModel: topBarContent.centerWidgetsModel
components: topBarContent.allComponents
noBackground: barConfig?.noBackground ?? false
parentScreen: barWindow.screen
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
barSpacing: barConfig?.spacing ?? 4
}
Binding {
target: hCenterSection
property: "barConfig"
value: topBarContent.barConfig
restoreMode: Binding.RestoreNone
}
Binding {
target: hCenterSection
property: "blurBarWindow"
value: topBarContent.blurBarWindow
restoreMode: Binding.RestoreNone
}
}
Item {
id: verticalStack
anchors.fill: parent
visible: barWindow.axis.isVertical
LeftSection {
id: vLeftSection
objectName: "leftSection"
overrideAxisLayout: true
forceVerticalLayout: true
width: parent.width
anchors {
top: parent.top
horizontalCenter: parent.horizontalCenter
}
axis: barWindow.axis
widgetsModel: topBarContent.leftWidgetsModel
components: topBarContent.allComponents
noBackground: barConfig?.noBackground ?? false
parentScreen: barWindow.screen
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
barSpacing: barConfig?.spacing ?? 4
}
Binding {
target: vLeftSection
property: "barConfig"
value: topBarContent.barConfig
restoreMode: Binding.RestoreNone
}
Binding {
target: vLeftSection
property: "blurBarWindow"
value: topBarContent.blurBarWindow
restoreMode: Binding.RestoreNone
}
CenterSection {
id: vCenterSection
objectName: "centerSection"
overrideAxisLayout: true
forceVerticalLayout: true
width: parent.width
anchors {
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
axis: barWindow.axis
widgetsModel: topBarContent.centerWidgetsModel
components: topBarContent.allComponents
noBackground: barConfig?.noBackground ?? false
parentScreen: barWindow.screen
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
barSpacing: barConfig?.spacing ?? 4
}
Binding {
target: vCenterSection
property: "barConfig"
value: topBarContent.barConfig
restoreMode: Binding.RestoreNone
}
Binding {
target: vCenterSection
property: "blurBarWindow"
value: topBarContent.blurBarWindow
restoreMode: Binding.RestoreNone
}
RightSection {
id: vRightSection
objectName: "rightSection"
overrideAxisLayout: true
forceVerticalLayout: true
width: parent.width
height: implicitHeight
anchors {
bottom: parent.bottom
horizontalCenter: parent.horizontalCenter
}
axis: barWindow.axis
widgetsModel: topBarContent.rightWidgetsModel
components: topBarContent.allComponents
noBackground: barConfig?.noBackground ?? false
parentScreen: barWindow.screen
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
barSpacing: barConfig?.spacing ?? 4
}
Binding {
target: vRightSection
property: "barConfig"
value: topBarContent.barConfig
restoreMode: Binding.RestoreNone
}
Binding {
target: vRightSection
property: "blurBarWindow"
value: topBarContent.blurBarWindow
restoreMode: Binding.RestoreNone
}
}
}
Component {
id: clipboardComponent
ClipboardButton {
id: clipboardWidget
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
axis: barWindow.axis
section: topBarContent.getWidgetSection(parent)
parentScreen: barWindow.screen
popoutTarget: clipboardHistoryPopoutLoader.item ?? null
function openClipboardPopout(initialTab) {
clipboardHistoryPopoutLoader.active = true;
if (!clipboardHistoryPopoutLoader.item) {
return;
}
const popout = clipboardHistoryPopoutLoader.item;
const effectiveBarConfig = topBarContent.barConfig;
const barPosition = barWindow.axis?.edge === "left" ? 2 : (barWindow.axis?.edge === "right" ? 3 : (barWindow.axis?.edge === "top" ? 0 : 1));
if (popout.setBarContext) {
popout.setBarContext(barPosition, effectiveBarConfig?.bottomGap ?? 0);
}
if (popout.setTriggerPosition) {
const globalPos = clipboardWidget.mapToItem(null, 0, 0);
const pos = SettingsData.getPopupTriggerPosition(globalPos, barWindow.screen, barWindow.effectiveBarThickness, clipboardWidget.width, effectiveBarConfig?.spacing ?? 4, barPosition, effectiveBarConfig);
const widgetSection = topBarContent.getWidgetSection(parent) || "right";
popout.setTriggerPosition(pos.x, pos.y, pos.width, widgetSection, barWindow.screen, barPosition, barWindow.effectiveBarThickness, effectiveBarConfig?.spacing ?? 4, effectiveBarConfig);
}
if (initialTab) {
popout.activeTab = initialTab;
}
PopoutManager.requestPopout(popout, undefined, "clipboard");
}
onClipboardClicked: openClipboardPopout("recents")
onShowSavedItemsRequested: openClipboardPopout("saved")
onClearAllRequested: {
clipboardHistoryPopoutLoader.active = true;
const popout = clipboardHistoryPopoutLoader.item;
if (!popout?.confirmDialog) {
return;
}
const hasPinned = popout.pinnedCount > 0;
const message = hasPinned ? I18n.tr("This will delete all unpinned entries. %1 pinned entries will be kept.").arg(popout.pinnedCount) : I18n.tr("This will permanently delete all clipboard history.");
popout.confirmDialog.show(I18n.tr("Clear History?"), message, function () {
if (popout && typeof popout.clearAll === "function") {
popout.clearAll();
}
}, function () {});
}
}
}
Component {
id: powerMenuButtonComponent
PowerMenuButton {
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
axis: barWindow.axis
section: topBarContent.getWidgetSection(parent)
parentScreen: barWindow.screen
onClicked: {
if (powerMenuModalLoader) {
powerMenuModalLoader.active = true;
if (powerMenuModalLoader.item) {
powerMenuModalLoader.item.openCentered();
}
}
}
}
}
Component {
id: launcherButtonComponent
LauncherButton {
id: launcherButton
isActive: false
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
section: topBarContent.getWidgetSection(parent)
popoutTarget: appDrawerLoader.item
parentScreen: barWindow.screen
hyprlandOverviewLoader: barWindow ? barWindow.hyprlandOverviewLoader : null
function _preparePopout() {
appDrawerLoader.active = true;
if (!appDrawerLoader.item)
return false;
const effectiveBarConfig = topBarContent.barConfig;
const barPosition = barWindow.axis?.edge === "left" ? 2 : (barWindow.axis?.edge === "right" ? 3 : (barWindow.axis?.edge === "top" ? 0 : 1));
if (appDrawerLoader.item.setBarContext)
appDrawerLoader.item.setBarContext(barPosition, effectiveBarConfig?.bottomGap ?? 0);
if (appDrawerLoader.item.setTriggerPosition) {
const globalPos = launcherButton.visualContent.mapToItem(null, 0, 0);
const currentScreen = barWindow.screen;
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barWindow.effectiveBarThickness, launcherButton.visualWidth, effectiveBarConfig?.spacing ?? 4, barPosition, effectiveBarConfig);
appDrawerLoader.item.setTriggerPosition(pos.x, pos.y, pos.width, launcherButton.section, currentScreen, barPosition, barWindow.effectiveBarThickness, effectiveBarConfig?.spacing ?? 4, effectiveBarConfig);
}
return true;
}
function openWithMode(mode) {
if (!_preparePopout())
return;
appDrawerLoader.item.openWithMode(mode);
}
function toggleWithMode(mode) {
if (!_preparePopout())
return;
appDrawerLoader.item.toggleWithMode(mode);
}
function openWithQuery(query) {
if (!_preparePopout())
return;
appDrawerLoader.item.openWithQuery(query);
}
function toggleWithQuery(query) {
if (!_preparePopout())
return;
appDrawerLoader.item.toggleWithQuery(query);
}
onClicked: {
if (!_preparePopout())
return;
PopoutManager.requestPopout(appDrawerLoader.item, undefined, "appDrawer");
}
}
}
Component {
id: workspaceSwitcherComponent
WorkspaceSwitcher {
axis: barWindow.axis
screenName: barWindow.screenName
widgetHeight: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
parentScreen: barWindow.screen
hyprlandOverviewLoader: barWindow ? barWindow.hyprlandOverviewLoader : null
}
}
Component {
id: focusedWindowComponent
FocusedApp {
axis: barWindow.axis
availableWidth: topBarContent.leftToMediaGap
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
barSpacing: barConfig?.spacing ?? 4
barConfig: topBarContent.barConfig
isAutoHideBar: topBarContent.barConfig?.autoHide ?? false
parentScreen: barWindow.screen
}
}
Component {
id: runningAppsComponent
RunningApps {
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
barSpacing: barConfig?.spacing ?? 4
section: topBarContent.getWidgetSection(parent)
parentScreen: barWindow.screen
topBar: topBarContent
barConfig: topBarContent.barConfig
isAutoHideBar: topBarContent.barConfig?.autoHide ?? false
}
}
Component {
id: appsDockComponent
AppsDock {
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
barSpacing: barConfig?.spacing ?? 4
section: topBarContent.getWidgetSection(parent)
parentScreen: barWindow.screen
topBar: topBarContent
barConfig: topBarContent.barConfig
isAutoHideBar: topBarContent.barConfig?.autoHide ?? false
}
}
Component {
id: clockComponent
Clock {
axis: barWindow.axis
compactMode: topBarContent.overlapping
barThickness: barWindow.effectiveBarThickness
widgetThickness: barWindow.widgetThickness
section: topBarContent.getWidgetSection(parent) || "center"
popoutTarget: dankDashPopoutLoader.item ?? null
parentScreen: barWindow.screen
Component.onCompleted: {
barWindow.clockButtonRef = this;
}
Component.onDestruction: {
if (barWindow.clockButtonRef === this) {
barWindow.clockButtonRef = null;
}
}
onClockClicked: {
dankDashPopoutLoader.active = true;
if (dankDashPopoutLoader.item) {
const effectiveBarConfig = topBarContent.barConfig;
const barPosition = barWindow.axis?.edge === "left" ? 2 : (barWindow.axis?.edge === "right" ? 3 : (barWindow.axis?.edge === "top" ? 0 : 1));
if (dankDashPopoutLoader.item.setBarContext) {
dankDashPopoutLoader.item.setBarContext(barPosition, effectiveBarConfig?.bottomGap ?? 0);
}
if (dankDashPopoutLoader.item.setTriggerPosition) {
let triggerPos, triggerWidth;
if (section === "center") {
const centerSection = barWindow.isVertical ? (barWindow.axis?.edge === "left" ? vCenterSection : vCenterSection) : hCenterSection;
if (centerSection) {
if (barWindow.isVertical) {
const centerY = centerSection.height / 2;
const centerGlobalPos = centerSection.mapToItem(null, 0, centerY);
triggerPos = centerGlobalPos;
triggerWidth = centerSection.height;
} else {
const centerGlobalPos = centerSection.mapToItem(null, 0, 0);
triggerPos = centerGlobalPos;
triggerWidth = centerSection.width;
}
} else {
triggerPos = visualContent.mapToItem(null, 0, 0);
triggerWidth = visualWidth;
}
} else {
triggerPos = visualContent.mapToItem(null, 0, 0);
triggerWidth = visualWidth;
}
const pos = SettingsData.getPopupTriggerPosition(triggerPos, barWindow.screen, barWindow.effectiveBarThickness, triggerWidth, effectiveBarConfig?.spacing ?? 4, barPosition, effectiveBarConfig);
dankDashPopoutLoader.item.setTriggerPosition(pos.x, pos.y, pos.width, section, barWindow.screen, barPosition, barWindow.effectiveBarThickness, effectiveBarConfig?.spacing ?? 4, effectiveBarConfig);
} else {
dankDashPopoutLoader.item.triggerScreen = barWindow.screen;
}
PopoutManager.requestPopout(dankDashPopoutLoader.item, 0, (effectiveBarConfig?.id ?? "default") + "-" + section + "-0");
}
}
}
}
Component {
id: mediaComponent
Media {
axis: barWindow.axis
compactMode: topBarContent.spacingTight || topBarContent.overlapping
barThickness: barWindow.effectiveBarThickness
widgetThickness: barWindow.widgetThickness
section: topBarContent.getWidgetSection(parent) || "center"
popoutTarget: dankDashPopoutLoader.item ?? null
parentScreen: barWindow.screen
onClicked: {
dankDashPopoutLoader.active = true;
if (dankDashPopoutLoader.item) {
const effectiveBarConfig = topBarContent.barConfig;
const barPosition = barWindow.axis?.edge === "left" ? 2 : (barWindow.axis?.edge === "right" ? 3 : (barWindow.axis?.edge === "top" ? 0 : 1));
if (dankDashPopoutLoader.item.setBarContext) {
dankDashPopoutLoader.item.setBarContext(barPosition, effectiveBarConfig?.bottomGap ?? 0);
}
if (dankDashPopoutLoader.item.setTriggerPosition) {
let triggerPos, triggerWidth;
if (section === "center") {
const centerSection = barWindow.isVertical ? (barWindow.axis?.edge === "left" ? vCenterSection : vCenterSection) : hCenterSection;
if (centerSection) {
if (barWindow.isVertical) {
const centerY = centerSection.height / 2;
const centerGlobalPos = centerSection.mapToItem(null, 0, centerY);
triggerPos = centerGlobalPos;
triggerWidth = centerSection.height;
} else {
const centerGlobalPos = centerSection.mapToItem(null, 0, 0);
triggerPos = centerGlobalPos;
triggerWidth = centerSection.width;
}
} else {
triggerPos = visualContent.mapToItem(null, 0, 0);
triggerWidth = visualWidth;
}
} else {
triggerPos = visualContent.mapToItem(null, 0, 0);
triggerWidth = visualWidth;
}
const pos = SettingsData.getPopupTriggerPosition(triggerPos, barWindow.screen, barWindow.effectiveBarThickness, triggerWidth, effectiveBarConfig?.spacing ?? 4, barPosition, effectiveBarConfig);
dankDashPopoutLoader.item.setTriggerPosition(pos.x, pos.y, pos.width, section, barWindow.screen, barPosition, barWindow.effectiveBarThickness, effectiveBarConfig?.spacing ?? 4, effectiveBarConfig);
} else {
dankDashPopoutLoader.item.triggerScreen = barWindow.screen;
}
PopoutManager.requestPopout(dankDashPopoutLoader.item, 1, (effectiveBarConfig?.id ?? "default") + "-" + section + "-1");
}
}
}
}
Component {
id: weatherComponent
Weather {
axis: barWindow.axis
barThickness: barWindow.effectiveBarThickness
widgetThickness: barWindow.widgetThickness
section: topBarContent.getWidgetSection(parent) || "center"
popoutTarget: dankDashPopoutLoader.item ?? null
parentScreen: barWindow.screen
onClicked: {
dankDashPopoutLoader.active = true;
if (dankDashPopoutLoader.item) {
const effectiveBarConfig = topBarContent.barConfig;
// Calculate barPosition from axis.edge
const barPosition = barWindow.axis?.edge === "left" ? 2 : (barWindow.axis?.edge === "right" ? 3 : (barWindow.axis?.edge === "top" ? 0 : 1));
if (dankDashPopoutLoader.item.setBarContext) {
dankDashPopoutLoader.item.setBarContext(barPosition, effectiveBarConfig?.bottomGap ?? 0);
}
if (dankDashPopoutLoader.item.setTriggerPosition) {
// For center section widgets, use center section bounds for DankDash centering
let triggerPos, triggerWidth;
if (section === "center") {
const centerSection = barWindow.isVertical ? (barWindow.axis?.edge === "left" ? vCenterSection : vCenterSection) : hCenterSection;
if (centerSection) {
// For vertical bars, use center Y of section; for horizontal, use left edge
if (barWindow.isVertical) {
const centerY = centerSection.height / 2;
const centerGlobalPos = centerSection.mapToItem(null, 0, centerY);
triggerPos = centerGlobalPos;
triggerWidth = centerSection.height;
} else {
// For horizontal bars, use left edge (DankPopout will center it)
const centerGlobalPos = centerSection.mapToItem(null, 0, 0);
triggerPos = centerGlobalPos;
triggerWidth = centerSection.width;
}
} else {
triggerPos = visualContent.mapToItem(null, 0, 0);
triggerWidth = visualWidth;
}
} else {
triggerPos = visualContent.mapToItem(null, 0, 0);
triggerWidth = visualWidth;
}
const pos = SettingsData.getPopupTriggerPosition(triggerPos, barWindow.screen, barWindow.effectiveBarThickness, triggerWidth, effectiveBarConfig?.spacing ?? 4, barPosition, effectiveBarConfig);
dankDashPopoutLoader.item.setTriggerPosition(pos.x, pos.y, pos.width, section, barWindow.screen, barPosition, barWindow.effectiveBarThickness, effectiveBarConfig?.spacing ?? 4, effectiveBarConfig);
} else {
dankDashPopoutLoader.item.triggerScreen = barWindow.screen;
}
PopoutManager.requestPopout(dankDashPopoutLoader.item, 3, (effectiveBarConfig?.id ?? "default") + "-" + section + "-3");
}
}
}
}
Component {
id: systemTrayComponent
SystemTrayBar {
parentWindow: barWindow
parentScreen: barWindow.screen
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
axis: barWindow.axis
barSpacing: barConfig?.spacing ?? 4
barConfig: topBarContent.barConfig
widgetData: parent.widgetData
isAutoHideBar: topBarContent.barConfig?.autoHide ?? false
isAtBottom: barWindow.axis?.edge === "bottom"
visible: SettingsData.getFilteredScreens("systemTray").includes(barWindow.screen) && SystemTray.items.values.length > 0
}
}
Component {
id: privacyIndicatorComponent
PrivacyIndicator {
widgetThickness: barWindow.widgetThickness
section: topBarContent.getWidgetSection(parent) || "right"
parentScreen: barWindow.screen
}
}
Component {
id: cpuUsageComponent
CpuMonitor {
id: cpuWidget
barThickness: barWindow.effectiveBarThickness
widgetThickness: barWindow.widgetThickness
axis: barWindow.axis
section: topBarContent.getWidgetSection(parent) || "right"
popoutTarget: processListPopoutLoader.item ?? null
parentScreen: barWindow.screen
widgetData: parent.widgetData
onCpuClicked: {
processListPopoutLoader.active = true;
if (!processListPopoutLoader.item) {
return;
}
const effectiveBarConfig = topBarContent.barConfig;
const barPosition = barWindow.axis?.edge === "left" ? 2 : (barWindow.axis?.edge === "right" ? 3 : (barWindow.axis?.edge === "top" ? 0 : 1));
if (processListPopoutLoader.item.setBarContext) {
processListPopoutLoader.item.setBarContext(barPosition, effectiveBarConfig?.bottomGap ?? 0);
}
if (processListPopoutLoader.item.setTriggerPosition) {
const globalPos = cpuWidget.mapToItem(null, 0, 0);
const pos = SettingsData.getPopupTriggerPosition(globalPos, barWindow.screen, barWindow.effectiveBarThickness, cpuWidget.width, effectiveBarConfig?.spacing ?? 4, barPosition, effectiveBarConfig);
const widgetSection = topBarContent.getWidgetSection(parent) || "right";
processListPopoutLoader.item.setTriggerPosition(pos.x, pos.y, pos.width, widgetSection, barWindow.screen, barPosition, barWindow.effectiveBarThickness, effectiveBarConfig?.spacing ?? 4, effectiveBarConfig);
}
PopoutManager.requestPopout(processListPopoutLoader.item, undefined, "cpu");
}
}
}
Component {
id: memUsageComponent
RamMonitor {
id: ramWidget
barThickness: barWindow.effectiveBarThickness
widgetThickness: barWindow.widgetThickness
axis: barWindow.axis
section: topBarContent.getWidgetSection(parent) || "right"
popoutTarget: processListPopoutLoader.item ?? null
parentScreen: barWindow.screen
widgetData: parent.widgetData
onRamClicked: {
processListPopoutLoader.active = true;
if (!processListPopoutLoader.item) {
return;
}
const effectiveBarConfig = topBarContent.barConfig;
const barPosition = barWindow.axis?.edge === "left" ? 2 : (barWindow.axis?.edge === "right" ? 3 : (barWindow.axis?.edge === "top" ? 0 : 1));
if (processListPopoutLoader.item.setBarContext) {
processListPopoutLoader.item.setBarContext(barPosition, effectiveBarConfig?.bottomGap ?? 0);
}
if (processListPopoutLoader.item.setTriggerPosition) {
const globalPos = ramWidget.mapToItem(null, 0, 0);
const pos = SettingsData.getPopupTriggerPosition(globalPos, barWindow.screen, barWindow.effectiveBarThickness, ramWidget.width, effectiveBarConfig?.spacing ?? 4, barPosition, effectiveBarConfig);
const widgetSection = topBarContent.getWidgetSection(parent) || "right";
processListPopoutLoader.item.setTriggerPosition(pos.x, pos.y, pos.width, widgetSection, barWindow.screen, barPosition, barWindow.effectiveBarThickness, effectiveBarConfig?.spacing ?? 4, effectiveBarConfig);
}
PopoutManager.requestPopout(processListPopoutLoader.item, undefined, "memory");
}
}
}
Component {
id: diskUsageComponent
DiskUsage {
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
axis: barWindow.axis
widgetData: parent.widgetData
parentScreen: barWindow.screen
barConfig: topBarContent.barConfig
isAutoHideBar: topBarContent.barConfig?.autoHide ?? false
}
}
Component {
id: cpuTempComponent
CpuTemperature {
id: cpuTempWidget
barThickness: barWindow.effectiveBarThickness
widgetThickness: barWindow.widgetThickness
axis: barWindow.axis
section: topBarContent.getWidgetSection(parent) || "right"
popoutTarget: processListPopoutLoader.item ?? null
parentScreen: barWindow.screen
widgetData: parent.widgetData
onCpuTempClicked: {
processListPopoutLoader.active = true;
if (!processListPopoutLoader.item) {
return;
}
const effectiveBarConfig = topBarContent.barConfig;
const barPosition = barWindow.axis?.edge === "left" ? 2 : (barWindow.axis?.edge === "right" ? 3 : (barWindow.axis?.edge === "top" ? 0 : 1));
if (processListPopoutLoader.item.setBarContext) {
processListPopoutLoader.item.setBarContext(barPosition, effectiveBarConfig?.bottomGap ?? 0);
}
if (processListPopoutLoader.item.setTriggerPosition) {
const globalPos = cpuTempWidget.mapToItem(null, 0, 0);
const pos = SettingsData.getPopupTriggerPosition(globalPos, barWindow.screen, barWindow.effectiveBarThickness, cpuTempWidget.width, effectiveBarConfig?.spacing ?? 4, barPosition, effectiveBarConfig);
const widgetSection = topBarContent.getWidgetSection(parent) || "right";
processListPopoutLoader.item.setTriggerPosition(pos.x, pos.y, pos.width, widgetSection, barWindow.screen, barPosition, barWindow.effectiveBarThickness, effectiveBarConfig?.spacing ?? 4, effectiveBarConfig);
}
PopoutManager.requestPopout(processListPopoutLoader.item, undefined, "cpu_temp");
}
}
}
Component {
id: gpuTempComponent
GpuTemperature {
id: gpuTempWidget
barThickness: barWindow.effectiveBarThickness
widgetThickness: barWindow.widgetThickness
axis: barWindow.axis
section: topBarContent.getWidgetSection(parent) || "right"
popoutTarget: processListPopoutLoader.item ?? null
parentScreen: barWindow.screen
widgetData: parent.widgetData
onGpuTempClicked: {
processListPopoutLoader.active = true;
if (!processListPopoutLoader.item) {
return;
}
const effectiveBarConfig = topBarContent.barConfig;
const barPosition = barWindow.axis?.edge === "left" ? 2 : (barWindow.axis?.edge === "right" ? 3 : (barWindow.axis?.edge === "top" ? 0 : 1));
if (processListPopoutLoader.item.setBarContext) {
processListPopoutLoader.item.setBarContext(barPosition, effectiveBarConfig?.bottomGap ?? 0);
}
if (processListPopoutLoader.item.setTriggerPosition) {
const globalPos = gpuTempWidget.mapToItem(null, 0, 0);
const pos = SettingsData.getPopupTriggerPosition(globalPos, barWindow.screen, barWindow.effectiveBarThickness, gpuTempWidget.width, effectiveBarConfig?.spacing ?? 4, barPosition, effectiveBarConfig);
const widgetSection = topBarContent.getWidgetSection(parent) || "right";
processListPopoutLoader.item.setTriggerPosition(pos.x, pos.y, pos.width, widgetSection, barWindow.screen, barPosition, barWindow.effectiveBarThickness, effectiveBarConfig?.spacing ?? 4, effectiveBarConfig);
}
PopoutManager.requestPopout(processListPopoutLoader.item, undefined, "gpu_temp");
}
}
}
Component {
id: networkComponent
NetworkMonitor {}
}
Component {
id: notificationButtonComponent
NotificationCenterButton {
id: notificationButton
hasUnread: barWindow.notificationCount > 0
isActive: notificationCenterLoader.item ? notificationCenterLoader.item.shouldBeVisible : false
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
axis: barWindow.axis
section: topBarContent.getWidgetSection(parent) || "right"
popoutTarget: notificationCenterLoader.item ?? null
parentScreen: barWindow.screen
onClicked: {
notificationCenterLoader.active = true;
if (!notificationCenterLoader.item) {
return;
}
const effectiveBarConfig = topBarContent.barConfig;
const barPosition = barWindow.axis?.edge === "left" ? 2 : (barWindow.axis?.edge === "right" ? 3 : (barWindow.axis?.edge === "top" ? 0 : 1));
if (notificationCenterLoader.item.setBarContext) {
notificationCenterLoader.item.setBarContext(barPosition, effectiveBarConfig?.bottomGap ?? 0);
}
if (notificationCenterLoader.item.setTriggerPosition) {
const globalPos = notificationButton.mapToItem(null, 0, 0);
const pos = SettingsData.getPopupTriggerPosition(globalPos, barWindow.screen, barWindow.effectiveBarThickness, notificationButton.width, effectiveBarConfig?.spacing ?? 4, barPosition, effectiveBarConfig);
const widgetSection = topBarContent.getWidgetSection(parent) || "right";
notificationCenterLoader.item.setTriggerPosition(pos.x, pos.y, pos.width, widgetSection, barWindow.screen, barPosition, barWindow.effectiveBarThickness, effectiveBarConfig?.spacing ?? 4, effectiveBarConfig);
}
PopoutManager.requestPopout(notificationCenterLoader.item, undefined, "notifications");
}
}
}
Component {
id: batteryComponent
Battery {
id: batteryWidget
batteryPopupVisible: batteryPopoutLoader.item ? batteryPopoutLoader.item.shouldBeVisible : false
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
axis: barWindow.axis
section: topBarContent.getWidgetSection(parent) || "right"
barSpacing: barConfig?.spacing ?? 4
barConfig: topBarContent.barConfig
popoutTarget: batteryPopoutLoader.item ?? null
parentScreen: barWindow.screen
onToggleBatteryPopup: {
batteryPopoutLoader.active = true;
if (!batteryPopoutLoader.item) {
return;
}
const effectiveBarConfig = topBarContent.barConfig;
const barPosition = barWindow.axis?.edge === "left" ? 2 : (barWindow.axis?.edge === "right" ? 3 : (barWindow.axis?.edge === "top" ? 0 : 1));
if (batteryPopoutLoader.item.setBarContext) {
batteryPopoutLoader.item.setBarContext(barPosition, effectiveBarConfig?.bottomGap ?? 0);
}
if (batteryPopoutLoader.item.setTriggerPosition) {
const globalPos = batteryWidget.mapToItem(null, 0, 0);
const pos = SettingsData.getPopupTriggerPosition(globalPos, barWindow.screen, barWindow.effectiveBarThickness, batteryWidget.width, effectiveBarConfig?.spacing ?? 4, barPosition, effectiveBarConfig);
const widgetSection = topBarContent.getWidgetSection(parent) || "right";
batteryPopoutLoader.item.setTriggerPosition(pos.x, pos.y, pos.width, widgetSection, barWindow.screen, barPosition, barWindow.effectiveBarThickness, effectiveBarConfig?.spacing ?? 4, effectiveBarConfig);
}
PopoutManager.requestPopout(batteryPopoutLoader.item, undefined, "battery");
}
}
}
Component {
id: layoutComponent
DWLLayout {
id: layoutWidget
layoutPopupVisible: layoutPopoutLoader.item ? layoutPopoutLoader.item.shouldBeVisible : false
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
axis: barWindow.axis
section: topBarContent.getWidgetSection(parent) || "center"
popoutTarget: layoutPopoutLoader.item ?? null
parentScreen: barWindow.screen
onToggleLayoutPopup: {
layoutPopoutLoader.active = true;
if (!layoutPopoutLoader.item)
return;
const effectiveBarConfig = topBarContent.barConfig;
const barPosition = barWindow.axis?.edge === "left" ? 2 : (barWindow.axis?.edge === "right" ? 3 : (barWindow.axis?.edge === "top" ? 0 : 1));
if (layoutPopoutLoader.item.setTriggerPosition) {
const globalPos = layoutWidget.mapToItem(null, 0, 0);
const pos = SettingsData.getPopupTriggerPosition(globalPos, barWindow.screen, barWindow.effectiveBarThickness, layoutWidget.width, effectiveBarConfig?.spacing ?? 4, barPosition, effectiveBarConfig);
const widgetSection = topBarContent.getWidgetSection(parent) || "center";
layoutPopoutLoader.item.setTriggerPosition(pos.x, pos.y, pos.width, widgetSection, barWindow.screen, barPosition, barWindow.effectiveBarThickness, effectiveBarConfig?.spacing ?? 4, effectiveBarConfig);
}
PopoutManager.requestPopout(layoutPopoutLoader.item, undefined, "layout");
}
}
}
Component {
id: vpnComponent
Vpn {
id: vpnWidget
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
axis: barWindow.axis
section: topBarContent.getWidgetSection(parent) || "right"
barSpacing: barConfig?.spacing ?? 4
barConfig: topBarContent.barConfig
isAutoHideBar: topBarContent.barConfig?.autoHide ?? false
popoutTarget: vpnPopoutLoader.item ?? null
parentScreen: barWindow.screen
onToggleVpnPopup: {
vpnPopoutLoader.active = true;
if (!vpnPopoutLoader.item)
return;
const effectiveBarConfig = topBarContent.barConfig;
const barPosition = barWindow.axis?.edge === "left" ? 2 : (barWindow.axis?.edge === "right" ? 3 : (barWindow.axis?.edge === "top" ? 0 : 1));
if (vpnPopoutLoader.item.setBarContext) {
vpnPopoutLoader.item.setBarContext(barPosition, effectiveBarConfig?.bottomGap ?? 0);
}
if (vpnPopoutLoader.item.setTriggerPosition) {
const globalPos = vpnWidget.mapToItem(null, 0, 0);
const pos = SettingsData.getPopupTriggerPosition(globalPos, barWindow.screen, barWindow.effectiveBarThickness, vpnWidget.width, effectiveBarConfig?.spacing ?? 4, barPosition, effectiveBarConfig);
const widgetSection = topBarContent.getWidgetSection(parent) || "right";
vpnPopoutLoader.item.setTriggerPosition(pos.x, pos.y, pos.width, widgetSection, barWindow.screen, barPosition, barWindow.effectiveBarThickness, effectiveBarConfig?.spacing ?? 4, effectiveBarConfig);
}
PopoutManager.requestPopout(vpnPopoutLoader.item, undefined, "vpn");
}
}
}
Component {
id: controlCenterButtonComponent
ControlCenterButton {
isActive: controlCenterLoader.item ? controlCenterLoader.item.shouldBeVisible : false
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
axis: barWindow.axis
section: topBarContent.getWidgetSection(parent) || "right"
popoutTarget: controlCenterLoader.item ?? null
parentScreen: barWindow.screen
screenName: barWindow.screen?.name || ""
screenModel: barWindow.screen?.model || ""
widgetData: parent.widgetData
Component.onCompleted: {
barWindow.controlCenterButtonRef = this;
}
Component.onDestruction: {
if (barWindow.controlCenterButtonRef === this) {
barWindow.controlCenterButtonRef = null;
}
}
onClicked: {
controlCenterLoader.active = true;
if (!controlCenterLoader.item) {
return;
}
controlCenterLoader.item.triggerScreen = barWindow.screen;
if (controlCenterLoader.item.setTriggerPosition) {
const globalPos = mapToItem(null, 0, 0);
// Use topBarContent.barConfig directly
const effectiveBarConfig = topBarContent.barConfig;
// Calculate barPosition from axis.edge like Battery widget does
const barPosition = barWindow.axis?.edge === "left" ? 2 : (barWindow.axis?.edge === "right" ? 3 : (barWindow.axis?.edge === "top" ? 0 : 1));
const pos = SettingsData.getPopupTriggerPosition(globalPos, barWindow.screen, barWindow.effectiveBarThickness, width, effectiveBarConfig?.spacing ?? 4, barPosition, effectiveBarConfig);
const section = topBarContent.getWidgetSection(parent) || "right";
controlCenterLoader.item.setTriggerPosition(pos.x, pos.y, pos.width, section, barWindow.screen, barPosition, barWindow.effectiveBarThickness, effectiveBarConfig?.spacing ?? 4, effectiveBarConfig);
}
PopoutManager.requestPopout(controlCenterLoader.item, undefined, "controlCenter");
if (controlCenterLoader.item.shouldBeVisible && NetworkService.wifiEnabled) {
NetworkService.scanWifi();
}
}
}
}
Component {
id: capsLockIndicatorComponent
CapsLockIndicator {
widgetThickness: barWindow.widgetThickness
section: topBarContent.getWidgetSection(parent) || "right"
parentScreen: barWindow.screen
}
}
Component {
id: idleInhibitorComponent
IdleInhibitor {
widgetThickness: barWindow.widgetThickness
section: topBarContent.getWidgetSection(parent) || "right"
parentScreen: barWindow.screen
}
}
Component {
id: spacerComponent
Item {
width: barWindow.isVertical ? barWindow.widgetThickness : (parent.spacerSize || 20)
height: barWindow.isVertical ? (parent.spacerSize || 20) : barWindow.widgetThickness
implicitWidth: width
implicitHeight: height
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
acceptedButtons: Qt.NoButton
propagateComposedEvents: true
cursorShape: Qt.ArrowCursor
onEntered: parent.visible = true
onExited: parent.visible = false
}
}
}
}
Component {
id: separatorComponent
Item {
width: barWindow.isVertical ? parent.barThickness : 1
height: barWindow.isVertical ? 1 : parent.barThickness
implicitWidth: width
implicitHeight: height
Rectangle {
width: barWindow.isVertical ? parent.width * 0.6 : 1
height: barWindow.isVertical ? 1 : parent.height * 0.6
anchors.centerIn: parent
color: Theme.outline
opacity: 0.3
}
}
}
Component {
id: keyboardLayoutNameComponent
KeyboardLayoutName {}
}
Component {
id: notepadButtonComponent
NotepadButton {
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
axis: barWindow.axis
section: topBarContent.getWidgetSection(parent) || "right"
parentScreen: barWindow.screen
}
}
Component {
id: colorPickerComponent
ColorPicker {
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
section: topBarContent.getWidgetSection(parent) || "right"
parentScreen: barWindow.screen
onColorPickerRequested: {
barWindow.colorPickerRequested();
}
}
}
Component {
id: systemUpdateComponent
SystemUpdate {
isActive: systemUpdateLoader.item ? systemUpdateLoader.item.shouldBeVisible : false
widgetThickness: barWindow.widgetThickness
barThickness: barWindow.effectiveBarThickness
axis: barWindow.axis
section: topBarContent.getWidgetSection(parent) || "right"
popoutTarget: systemUpdateLoader.item ?? null
parentScreen: barWindow.screen
onClicked: {
systemUpdateLoader.active = true;
if (!systemUpdateLoader.item)
return;
const popout = systemUpdateLoader.item;
const effectiveBarConfig = topBarContent.barConfig;
const barPosition = barWindow.axis?.edge === "left" ? 2 : (barWindow.axis?.edge === "right" ? 3 : (barWindow.axis?.edge === "top" ? 0 : 1));
if (popout.setBarContext) {
popout.setBarContext(barPosition, effectiveBarConfig?.bottomGap ?? 0);
}
if (popout.setTriggerPosition) {
const globalPos = visualContent.mapToItem(null, 0, 0);
const currentScreen = parentScreen || Screen;
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barWindow.effectiveBarThickness, visualWidth, effectiveBarConfig?.spacing ?? 4, barPosition, effectiveBarConfig);
popout.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen, barPosition, barWindow.effectiveBarThickness, effectiveBarConfig?.spacing ?? 4, effectiveBarConfig);
}
PopoutManager.requestPopout(popout, undefined, "systemUpdate");
}
}
}
}