Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions quickshell/Modals/ProcessListModal.qml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ FloatingWindow {

property bool disablePopupTransparency: true
property int currentTab: 0
// Number of tabs in the tab bar — derived from the tab model array.
// Using array literal length (4) as a constant property; matches the
// inline Repeater model so the bound stays correct if tabs are added.
readonly property int tabCount: 4
readonly property int maxTabIndex: tabCount - 1
property string searchText: ""
property string expandedPid: ""
property string processFilter: "all"
Expand All @@ -21,11 +26,25 @@ FloatingWindow {

signal closingModal

function show() {
function clampTab(tabIndex) {
if (tabIndex === undefined || tabIndex === null)
return currentTab;
return Math.max(0, Math.min(maxTabIndex, tabIndex));
}

function show(tabIndex) {
if (!DgopService.dgopAvailable) {
log.warn("dgop is not available");
return;
}
currentTab = clampTab(tabIndex);
// Restore sort state when navigating to Performance tab (tab 1).
// CpuMonitor and RamMonitor call setSortBy themselves; routing here
// from a thermal widget should also set the sort so the data is
// pre-sorted for the tab being opened.
if (currentTab === 1) {
DgopService.setSortBy("cpu");
}
visible = true;
}

Expand All @@ -35,12 +54,18 @@ FloatingWindow {
processContextMenu.close();
}

function toggle() {
function toggle(tabIndex) {
if (!DgopService.dgopAvailable) {
log.warn("dgop is not available");
return;
}
visible = !visible;
// If already visible on the target tab, just hide.
// Otherwise delegate to show() which handles clampTab, sort state, and visibility.
if (visible && currentTab === clampTab(tabIndex)) {
hide();
return;
}
show(tabIndex);
}

function focusOrToggle() {
Expand Down Expand Up @@ -75,11 +100,11 @@ FloatingWindow {
}

function nextTab() {
currentTab = (currentTab + 1) % 4;
currentTab = (currentTab + 1) % tabCount;
}

function previousTab() {
currentTab = (currentTab - 1 + 4) % 4;
currentTab = (currentTab - 1 + tabCount) % tabCount;
}

objectName: "processListModal"
Expand Down
34 changes: 2 additions & 32 deletions quickshell/Modules/DankBar/DankBarContent.qml
Original file line number Diff line number Diff line change
Expand Up @@ -1180,22 +1180,7 @@ Item {
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");
PopoutService.toggleProcessListModal(1);
}
}
}
Expand All @@ -1213,22 +1198,7 @@ Item {
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");
PopoutService.toggleProcessListModal(3);
}
}
}
Expand Down
1 change: 0 additions & 1 deletion quickshell/Modules/DankBar/Widgets/CpuTemperature.qml
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ BasePill {
acceptedButtons: Qt.LeftButton
onPressed: mouse => {
root.triggerRipple(this, mouse.x, mouse.y);
DgopService.setSortBy("cpu");
cpuTempClicked();
}
}
Expand Down
1 change: 0 additions & 1 deletion quickshell/Modules/DankBar/Widgets/GpuTemperature.qml
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@ BasePill {
acceptedButtons: Qt.LeftButton
onPressed: mouse => {
root.triggerRipple(this, mouse.x, mouse.y);
DgopService.setSortBy("cpu");
gpuTempClicked();
}
}
Expand Down
28 changes: 22 additions & 6 deletions quickshell/Services/PopoutService.qml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ Singleton {
property var powerMenuModal: null
property var processListModal: null
property var processListModalLoader: null
// Pending tab index for async Loader path — consumed by Connections when modal loads
property int pendingProcessTab: -1
property var colorPickerModal: null
property var notificationModal: null
property var wifiPasswordModal: null
Expand Down Expand Up @@ -708,12 +710,12 @@ Singleton {
}
}

function showProcessListModal() {
function showProcessListModal(tabIndex) {
if (processListModal) {
processListModal.show();
processListModal.show(tabIndex);
} else if (processListModalLoader) {
pendingProcessTab = (tabIndex !== undefined && tabIndex !== null) ? tabIndex : -1;
processListModalLoader.active = true;
Qt.callLater(() => processListModal?.show());
}
}

Expand All @@ -728,12 +730,26 @@ Singleton {
}
}

function toggleProcessListModal() {
function toggleProcessListModal(tabIndex) {
if (processListModal) {
processListModal.toggle();
processListModal.toggle(tabIndex);
} else if (processListModalLoader) {
pendingProcessTab = (tabIndex !== undefined && tabIndex !== null) ? tabIndex : -1;
processListModalLoader.active = true;
Qt.callLater(() => processListModal?.show());
}
}

// Reactive async path: when Loader finishes loading, show modal at pending tab.
// Avoids Qt.callLater race condition where the lambda fires before modal is ready.
Connections {
target: processListModalLoader
function onStatusChanged() {
if (!processListModalLoader)
return;
if (processListModalLoader.status === Loader.Ready && pendingProcessTab !== -1) {
processListModal?.show(pendingProcessTab);
pendingProcessTab = -1;
}
}
}

Expand Down
Loading