diff --git a/Modules/AppDrawer/AppDrawerPopout.qml b/Modules/AppDrawer/AppDrawerPopout.qml index 73782de4..947ade1b 100644 --- a/Modules/AppDrawer/AppDrawerPopout.qml +++ b/Modules/AppDrawer/AppDrawerPopout.qml @@ -14,6 +14,10 @@ PanelWindow { id: appDrawerPopout property bool isVisible: false + property real triggerX: Theme.spacingL + property real triggerY: Theme.barHeight + Theme.spacingXS + property real triggerWidth: 40 + property string triggerSection: "left" // "left", "center", "right" function show() { appDrawerPopout.isVisible = true; @@ -31,6 +35,13 @@ PanelWindow { show(); } + function setTriggerPosition(x, y, width, section) { + triggerX = x; + triggerY = y; + triggerWidth = width; + triggerSection = section; + } + WlrLayershell.layer: WlrLayershell.Overlay WlrLayershell.exclusiveZone: -1 WlrLayershell.keyboardFocus: isVisible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None @@ -70,12 +81,36 @@ PanelWindow { Loader { id: launcherLoader + readonly property real popupWidth: 520 + readonly property real popupHeight: 600 + readonly property real screenWidth: Screen.width + readonly property real screenHeight: Screen.height + readonly property real calculatedX: { + var centerX = appDrawerPopout.triggerX + (appDrawerPopout.triggerWidth / 2) - (popupWidth / 2); + + if (centerX >= Theme.spacingM && centerX + popupWidth <= screenWidth - Theme.spacingM) { + return centerX; + } + + if (centerX < Theme.spacingM) { + return Theme.spacingM; + } + + if (centerX + popupWidth > screenWidth - Theme.spacingM) { + return screenWidth - popupWidth - Theme.spacingM; + } + + return centerX; + } + readonly property real calculatedY: appDrawerPopout.triggerY + asynchronous: true active: appDrawerPopout.isVisible - width: 520 - height: 600 - x: Theme.spacingL - y: Theme.barHeight + Theme.spacingXS + width: popupWidth + height: popupHeight + x: calculatedX + y: calculatedY + opacity: appDrawerPopout.isVisible ? 1 : 0 scale: appDrawerPopout.isVisible ? 1 : 0.9 diff --git a/Modules/CentcomCenter/CentcomPopout.qml b/Modules/CentcomCenter/CentcomPopout.qml index d4c9d2d3..e35090f9 100644 --- a/Modules/CentcomCenter/CentcomPopout.qml +++ b/Modules/CentcomCenter/CentcomPopout.qml @@ -15,6 +15,17 @@ PanelWindow { readonly property bool hasActiveMedia: MprisController.activePlayer !== null property bool calendarVisible: false property bool internalVisible: false + property real triggerX: (Screen.width - 480) / 2 + property real triggerY: Theme.barHeight + 4 + property real triggerWidth: 80 + property string triggerSection: "center" + + function setTriggerPosition(x, y, width, section) { + triggerX = x; + triggerY = y; + triggerWidth = width; + triggerSection = section; + } visible: internalVisible onCalendarVisibleChanged: { @@ -77,6 +88,24 @@ PanelWindow { return Math.min(contentHeight, parent.height * 0.9); } + readonly property real calculatedX: { + var centerX = root.triggerX + (root.triggerWidth / 2) - (targetWidth / 2); + + if (centerX >= Theme.spacingM && centerX + targetWidth <= Screen.width - Theme.spacingM) { + return centerX; + } + + if (centerX < Theme.spacingM) { + return Theme.spacingM; + } + + if (centerX + targetWidth > Screen.width - Theme.spacingM) { + return Screen.width - targetWidth - Theme.spacingM; + } + + return centerX; + } + width: targetWidth height: calculateHeight() color: Theme.surfaceContainer @@ -86,8 +115,8 @@ PanelWindow { layer.enabled: true opacity: calendarVisible ? 1 : 0 scale: calendarVisible ? 1 : 0.9 - x: (Screen.width - targetWidth) / 2 - y: Theme.barHeight + 4 + x: calculatedX + y: root.triggerY onOpacityChanged: { if (opacity === 1) Qt.callLater(() => { diff --git a/Modules/Notifications/Center/NotificationCenterPopout.qml b/Modules/Notifications/Center/NotificationCenterPopout.qml index b740a3af..20f1f8ee 100644 --- a/Modules/Notifications/Center/NotificationCenterPopout.qml +++ b/Modules/Notifications/Center/NotificationCenterPopout.qml @@ -12,6 +12,17 @@ PanelWindow { id: root property bool notificationHistoryVisible: false + property real triggerX: Screen.width - 400 - Theme.spacingL + property real triggerY: Theme.barHeight + Theme.spacingXS + property real triggerWidth: 40 + property string triggerSection: "right" + + function setTriggerPosition(x, y, width, section) { + triggerX = x; + triggerY = y; + triggerWidth = width; + triggerSection = section; + } visible: notificationHistoryVisible onNotificationHistoryVisibleChanged: { @@ -53,10 +64,29 @@ PanelWindow { return Math.max(300, baseHeight); } - width: 400 + readonly property real popupWidth: 400 + readonly property real calculatedX: { + var centerX = root.triggerX + (root.triggerWidth / 2) - (popupWidth / 2); + + if (centerX >= Theme.spacingM && centerX + popupWidth <= Screen.width - Theme.spacingM) { + return centerX; + } + + if (centerX < Theme.spacingM) { + return Theme.spacingM; + } + + if (centerX + popupWidth > Screen.width - Theme.spacingM) { + return Screen.width - popupWidth - Theme.spacingM; + } + + return centerX; + } + + width: popupWidth height: calculateHeight() - x: Screen.width - width - Theme.spacingL - y: Theme.barHeight + Theme.spacingXS + x: calculatedX + y: root.triggerY color: Theme.popupBackground() radius: Theme.cornerRadiusLarge border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) diff --git a/Modules/ProcessList/ProcessListPopout.qml b/Modules/ProcessList/ProcessListPopout.qml index db818a92..eddae653 100644 --- a/Modules/ProcessList/ProcessListPopout.qml +++ b/Modules/ProcessList/ProcessListPopout.qml @@ -16,6 +16,17 @@ PanelWindow { property bool isVisible: false property var parentWidget: null + property real triggerX: Screen.width - 600 - Theme.spacingL + property real triggerY: Theme.barHeight + Theme.spacingXS + property real triggerWidth: 55 + property string triggerSection: "right" + + function setTriggerPosition(x, y, width, section) { + triggerX = x; + triggerY = y; + triggerWidth = width; + triggerSection = section; + } function hide() { isVisible = false; @@ -69,13 +80,30 @@ PanelWindow { readonly property real targetWidth: Math.min(600, Screen.width - Theme.spacingL * 2) readonly property real targetHeight: Math.min(600, Screen.height - Theme.barHeight - Theme.spacingS * 2) + readonly property real calculatedX: { + var centerX = processListPopout.triggerX + (processListPopout.triggerWidth / 2) - (targetWidth / 2); + + if (centerX >= Theme.spacingM && centerX + targetWidth <= Screen.width - Theme.spacingM) { + return centerX; + } + + if (centerX < Theme.spacingM) { + return Theme.spacingM; + } + + if (centerX + targetWidth > Screen.width - Theme.spacingM) { + return Screen.width - targetWidth - Theme.spacingM; + } + + return centerX; + } asynchronous: true active: processListPopout.isVisible width: targetWidth height: targetHeight - y: Theme.barHeight + Theme.spacingXS - x: Math.max(Theme.spacingL, Screen.width - targetWidth - Theme.spacingL) + y: processListPopout.triggerY + x: calculatedX opacity: processListPopout.isVisible ? 1 : 0 scale: processListPopout.isVisible ? 1 : 0.9 diff --git a/Modules/TopBar/Battery.qml b/Modules/TopBar/Battery.qml index 05ab8eb6..551680f8 100644 --- a/Modules/TopBar/Battery.qml +++ b/Modules/TopBar/Battery.qml @@ -8,6 +8,8 @@ Rectangle { id: battery property bool batteryPopupVisible: false + property string section: "right" + property var popupTarget: null signal toggleBatteryPopup() @@ -92,6 +94,11 @@ Rectangle { hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: { + if (popupTarget && popupTarget.setTriggerPosition) { + var globalPos = mapToGlobal(0, 0); + var screenRelativeX = globalPos.x >= Screen.width ? globalPos.x % Screen.width : globalPos.x; + popupTarget.setTriggerPosition(screenRelativeX, Theme.barHeight + Theme.spacingXS, width, section); + } toggleBatteryPopup(); } } diff --git a/Modules/TopBar/BatteryPopout.qml b/Modules/TopBar/BatteryPopout.qml index 66a81f1d..840a26fa 100644 --- a/Modules/TopBar/BatteryPopout.qml +++ b/Modules/TopBar/BatteryPopout.qml @@ -12,6 +12,17 @@ PanelWindow { id: root property bool batteryPopupVisible: false + property real triggerX: Screen.width - 380 - Theme.spacingL + property real triggerY: Theme.barHeight + Theme.spacingS + property real triggerWidth: 70 + property string triggerSection: "right" + + function setTriggerPosition(x, y, width, section) { + triggerX = x; + triggerY = y; + triggerWidth = width; + triggerSection = section; + } function isActiveProfile(profile) { if (typeof PowerProfiles === "undefined") @@ -61,13 +72,30 @@ PanelWindow { readonly property real targetWidth: Math.min(380, Screen.width - Theme.spacingL * 2) readonly property real targetHeight: Math.min(450, Screen.height - Theme.barHeight - Theme.spacingS * 2) + readonly property real calculatedX: { + var centerX = root.triggerX + (root.triggerWidth / 2) - (targetWidth / 2); + + if (centerX >= Theme.spacingM && centerX + targetWidth <= Screen.width - Theme.spacingM) { + return centerX; + } + + if (centerX < Theme.spacingM) { + return Theme.spacingM; + } + + if (centerX + targetWidth > Screen.width - Theme.spacingM) { + return Screen.width - targetWidth - Theme.spacingM; + } + + return centerX; + } asynchronous: true active: batteryPopupVisible width: targetWidth height: targetHeight - x: Math.max(Theme.spacingL, Screen.width - targetWidth - Theme.spacingL) - y: Theme.barHeight + Theme.spacingS + x: calculatedX + y: root.triggerY opacity: batteryPopupVisible ? 1 : 0 scale: batteryPopupVisible ? 1 : 0.9 diff --git a/Modules/TopBar/Clock.qml b/Modules/TopBar/Clock.qml index 80ade06c..bd86c5e3 100644 --- a/Modules/TopBar/Clock.qml +++ b/Modules/TopBar/Clock.qml @@ -8,6 +8,8 @@ Rectangle { property date currentDate: new Date() property bool compactMode: false + property string section: "center" + property var popupTarget: null signal clockClicked() @@ -67,6 +69,11 @@ Rectangle { hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: { + if (popupTarget && popupTarget.setTriggerPosition) { + var globalPos = mapToGlobal(0, 0); + var screenRelativeX = globalPos.x >= Screen.width ? globalPos.x % Screen.width : globalPos.x; + popupTarget.setTriggerPosition(screenRelativeX, Theme.barHeight + Theme.spacingXS, width, section); + } root.clockClicked(); } } diff --git a/Modules/TopBar/CpuMonitor.qml b/Modules/TopBar/CpuMonitor.qml index e5c2a706..55fa3a23 100644 --- a/Modules/TopBar/CpuMonitor.qml +++ b/Modules/TopBar/CpuMonitor.qml @@ -10,6 +10,8 @@ Rectangle { property bool showPercentage: true property bool showIcon: true property var toggleProcessList + property string section: "right" + property var popupTarget: null width: 55 height: 30 @@ -32,10 +34,14 @@ Rectangle { hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: { + if (popupTarget && popupTarget.setTriggerPosition) { + var globalPos = mapToGlobal(0, 0); + var screenRelativeX = globalPos.x >= Screen.width ? globalPos.x % Screen.width : globalPos.x; + popupTarget.setTriggerPosition(screenRelativeX, Theme.barHeight + Theme.spacingXS, width, section); + } SysMonitorService.setSortBy("cpu"); if (root.toggleProcessList) root.toggleProcessList(); - } } diff --git a/Modules/TopBar/LauncherButton.qml b/Modules/TopBar/LauncherButton.qml index 40c5032f..e1f03fe5 100644 --- a/Modules/TopBar/LauncherButton.qml +++ b/Modules/TopBar/LauncherButton.qml @@ -7,6 +7,8 @@ Rectangle { id: root property bool isActive: false + property string section: "left" // Which section this button is in + property var popupTarget: null // Reference to the popup to position signal clicked() @@ -42,7 +44,14 @@ Rectangle { anchors.fill: parent hoverEnabled: true cursorShape: Qt.PointingHandCursor - onClicked: root.clicked() + onClicked: { + if (popupTarget && popupTarget.setTriggerPosition) { + var globalPos = mapToGlobal(0, 0); + var screenRelativeX = globalPos.x >= Screen.width ? globalPos.x % Screen.width : globalPos.x; + popupTarget.setTriggerPosition(screenRelativeX, Theme.barHeight + Theme.spacingXS, width, section); + } + root.clicked(); + } } Behavior on color { diff --git a/Modules/TopBar/Media.qml b/Modules/TopBar/Media.qml index cc955e21..13788e87 100644 --- a/Modules/TopBar/Media.qml +++ b/Modules/TopBar/Media.qml @@ -13,6 +13,8 @@ Rectangle { readonly property int baseContentWidth: mediaRow.implicitWidth + Theme.spacingS * 2 readonly property int normalContentWidth: Math.min(280, baseContentWidth) readonly property int compactContentWidth: Math.min(120, baseContentWidth) + property string section: "center" + property var popupTarget: null signal clicked() @@ -127,7 +129,14 @@ Rectangle { anchors.fill: parent hoverEnabled: true cursorShape: Qt.PointingHandCursor - onClicked: root.clicked() + onClicked: { + if (root.popupTarget && root.popupTarget.setTriggerPosition) { + var globalPos = mapToGlobal(0, 0); + var screenRelativeX = globalPos.x >= Screen.width ? globalPos.x % Screen.width : globalPos.x; + root.popupTarget.setTriggerPosition(screenRelativeX, Theme.barHeight + Theme.spacingXS, root.width, root.section); + } + root.clicked(); + } } } diff --git a/Modules/TopBar/NotificationCenterButton.qml b/Modules/TopBar/NotificationCenterButton.qml index f2d19f13..d71e7a02 100644 --- a/Modules/TopBar/NotificationCenterButton.qml +++ b/Modules/TopBar/NotificationCenterButton.qml @@ -7,6 +7,8 @@ Rectangle { property bool hasUnread: false property bool isActive: false + property string section: "right" + property var popupTarget: null signal clicked() @@ -44,6 +46,11 @@ Rectangle { hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: { + if (popupTarget && popupTarget.setTriggerPosition) { + var globalPos = mapToGlobal(0, 0); + var screenRelativeX = globalPos.x >= Screen.width ? globalPos.x % Screen.width : globalPos.x; + popupTarget.setTriggerPosition(screenRelativeX, Theme.barHeight + Theme.spacingXS, width, section); + } root.clicked(); } } diff --git a/Modules/TopBar/RamMonitor.qml b/Modules/TopBar/RamMonitor.qml index 56895e7e..045d0230 100644 --- a/Modules/TopBar/RamMonitor.qml +++ b/Modules/TopBar/RamMonitor.qml @@ -10,6 +10,8 @@ Rectangle { property bool showPercentage: true property bool showIcon: true property var toggleProcessList + property string section: "right" + property var popupTarget: null width: 55 height: 30 @@ -32,10 +34,14 @@ Rectangle { hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: { + if (popupTarget && popupTarget.setTriggerPosition) { + var globalPos = mapToGlobal(0, 0); + var screenRelativeX = globalPos.x >= Screen.width ? globalPos.x % Screen.width : globalPos.x; + popupTarget.setTriggerPosition(screenRelativeX, Theme.barHeight + Theme.spacingXS, width, section); + } SysMonitorService.setSortBy("memory"); if (root.toggleProcessList) root.toggleProcessList(); - } } diff --git a/Modules/TopBar/TopBar.qml b/Modules/TopBar/TopBar.qml index b3207471..a04d79b3 100644 --- a/Modules/TopBar/TopBar.qml +++ b/Modules/TopBar/TopBar.qml @@ -437,10 +437,19 @@ PanelWindow { LauncherButton { isActive: appDrawerPopout ? appDrawerPopout.isVisible : false + section: { + // Determine which section this loader is in by checking parent + if (parent && parent.parent) { + if (parent.parent === leftSection) return "left"; + if (parent.parent === rightSection) return "right"; + if (parent.parent === centerSection) return "center"; + } + return "left"; // default fallback + } + popupTarget: appDrawerPopout onClicked: { if (appDrawerPopout) appDrawerPopout.toggle(); - } } @@ -470,6 +479,13 @@ PanelWindow { Clock { compactMode: topBarContent.overlapping + 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: centcomPopout onClockClicked: { centcomPopout.calendarVisible = !centcomPopout.calendarVisible; } @@ -482,6 +498,13 @@ PanelWindow { Media { compactMode: topBarContent.spacingTight || topBarContent.overlapping + 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: centcomPopout onClicked: { centcomPopout.calendarVisible = !centcomPopout.calendarVisible; } @@ -493,6 +516,13 @@ PanelWindow { id: weatherComponent Weather { + 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: centcomPopout onClicked: { centcomPopout.calendarVisible = !centcomPopout.calendarVisible; } @@ -565,12 +595,26 @@ PanelWindow { spacing: Theme.spacingXS CpuMonitor { + section: { + if (parent && parent.parent && parent.parent.parent === leftSection) return "left"; + if (parent && parent.parent && parent.parent.parent === rightSection) return "right"; + if (parent && parent.parent && parent.parent.parent === centerSection) return "center"; + return "right"; + } + popupTarget: processListPopout toggleProcessList: () => { return processListPopout.toggle(); } } RamMonitor { + section: { + if (parent && parent.parent && parent.parent.parent === leftSection) return "left"; + if (parent && parent.parent && parent.parent.parent === rightSection) return "right"; + if (parent && parent.parent && parent.parent.parent === centerSection) return "center"; + return "right"; + } + popupTarget: processListPopout toggleProcessList: () => { return processListPopout.toggle(); } @@ -586,6 +630,13 @@ PanelWindow { NotificationCenterButton { hasUnread: root.notificationCount > 0 isActive: notificationCenter.notificationHistoryVisible + 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: notificationCenter onClicked: { notificationCenter.notificationHistoryVisible = !notificationCenter.notificationHistoryVisible; } @@ -598,6 +649,13 @@ PanelWindow { Battery { batteryPopupVisible: batteryPopout.batteryPopupVisible + 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: batteryPopout onToggleBatteryPopup: { batteryPopout.batteryPopupVisible = !batteryPopout.batteryPopupVisible; } diff --git a/Modules/TopBar/Weather.qml b/Modules/TopBar/Weather.qml index a4b89d2d..d9698498 100644 --- a/Modules/TopBar/Weather.qml +++ b/Modules/TopBar/Weather.qml @@ -6,6 +6,9 @@ import qs.Widgets Rectangle { id: root + property string section: "center" + property var popupTarget: null + signal clicked() width: visible ? Math.min(100, weatherRow.implicitWidth + Theme.spacingS * 2) : 0 @@ -48,7 +51,14 @@ Rectangle { anchors.fill: parent hoverEnabled: true cursorShape: Qt.PointingHandCursor - onClicked: root.clicked() + onClicked: { + if (popupTarget && popupTarget.setTriggerPosition) { + var globalPos = mapToGlobal(0, 0); + var screenRelativeX = globalPos.x >= Screen.width ? globalPos.x % Screen.width : globalPos.x; + popupTarget.setTriggerPosition(screenRelativeX, Theme.barHeight + Theme.spacingXS, width, section); + } + root.clicked(); + } } Behavior on color {