Compare commits
No commits in common. "8fdd9692e610d81a2c1c15004193166295356f2a" and "6748649033828071d18710ce045b8151ca801dae" have entirely different histories.
8fdd9692e6
...
6748649033
8 changed files with 73 additions and 83 deletions
|
|
@ -31,7 +31,7 @@ M.BarSection {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
target: root
|
target: root
|
||||||
property: "_blinkOpacity"
|
property: "_blinkOpacity"
|
||||||
to: 0.45
|
to: 0.2
|
||||||
duration: 400
|
duration: 400
|
||||||
easing.type: Easing.InOutQuad
|
easing.type: Easing.InOutQuad
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,11 +32,6 @@ M.BarSection {
|
||||||
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
|
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
|
||||||
readonly property bool _showPanel: _anyHover || _pinned
|
readonly property bool _showPanel: _anyHover || _pinned
|
||||||
|
|
||||||
property M.ProcessList _procs: M.ProcessList {
|
|
||||||
sortBy: "cpu"
|
|
||||||
active: root._showPanel
|
|
||||||
}
|
|
||||||
|
|
||||||
on_AnyHoverChanged: {
|
on_AnyHoverChanged: {
|
||||||
if (_anyHover)
|
if (_anyHover)
|
||||||
_unpinTimer.stop();
|
_unpinTimer.stop();
|
||||||
|
|
@ -263,7 +258,7 @@ M.BarSection {
|
||||||
|
|
||||||
// Top processes by CPU
|
// Top processes by CPU
|
||||||
Repeater {
|
Repeater {
|
||||||
model: root._procs.processes
|
model: M.ProcessList.byCpu
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
required property var modelData
|
required property var modelData
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,6 @@ M.BarSection {
|
||||||
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
|
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
|
||||||
readonly property bool _showPanel: _anyHover || _pinned
|
readonly property bool _showPanel: _anyHover || _pinned
|
||||||
|
|
||||||
property M.ProcessList _procs: M.ProcessList {
|
|
||||||
sortBy: "mem"
|
|
||||||
active: root._showPanel
|
|
||||||
}
|
|
||||||
|
|
||||||
on_AnyHoverChanged: {
|
on_AnyHoverChanged: {
|
||||||
if (_anyHover)
|
if (_anyHover)
|
||||||
_unpinTimer.stop();
|
_unpinTimer.stop();
|
||||||
|
|
@ -228,7 +223,7 @@ M.BarSection {
|
||||||
|
|
||||||
// Top processes by memory
|
// Top processes by memory
|
||||||
Repeater {
|
Repeater {
|
||||||
model: root._procs.processes
|
model: M.ProcessList.byMem
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
required property var modelData
|
required property var modelData
|
||||||
|
|
|
||||||
|
|
@ -11,29 +11,6 @@ QtObject {
|
||||||
signal windowFocusChanged(var windowId)
|
signal windowFocusChanged(var windowId)
|
||||||
signal windowOpenedOrChanged(var window)
|
signal windowOpenedOrChanged(var window)
|
||||||
|
|
||||||
property string focusedTitle: ""
|
|
||||||
property string focusedAppId: ""
|
|
||||||
property bool overviewOpen: false
|
|
||||||
|
|
||||||
property var _focusedProc: Process {
|
|
||||||
running: true
|
|
||||||
command: ["niri", "msg", "--json", "focused-window"]
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: {
|
|
||||||
try {
|
|
||||||
const w = JSON.parse(text);
|
|
||||||
if (w) {
|
|
||||||
root.focusedTitle = w.title || "";
|
|
||||||
root.focusedAppId = w.app_id || "";
|
|
||||||
} else {
|
|
||||||
root.focusedTitle = "";
|
|
||||||
root.focusedAppId = "";
|
|
||||||
}
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
property var _eventStream: Process {
|
property var _eventStream: Process {
|
||||||
running: true
|
running: true
|
||||||
command: ["niri", "msg", "--json", "event-stream"]
|
command: ["niri", "msg", "--json", "event-stream"]
|
||||||
|
|
@ -46,24 +23,10 @@ QtObject {
|
||||||
root.workspacesChanged(ev.WorkspacesChanged.workspaces);
|
root.workspacesChanged(ev.WorkspacesChanged.workspaces);
|
||||||
else if (ev.WorkspaceActivated !== undefined)
|
else if (ev.WorkspaceActivated !== undefined)
|
||||||
root.workspaceActivated(ev.WorkspaceActivated.id, ev.WorkspaceActivated.focused);
|
root.workspaceActivated(ev.WorkspaceActivated.id, ev.WorkspaceActivated.focused);
|
||||||
else if (ev.WindowFocusChanged !== undefined) {
|
else if (ev.WindowFocusChanged !== undefined)
|
||||||
root.windowFocusChanged(ev.WindowFocusChanged.id);
|
root.windowFocusChanged(ev.WindowFocusChanged.id);
|
||||||
if (ev.WindowFocusChanged.id !== null)
|
else if (ev.WindowOpenedOrChanged !== undefined)
|
||||||
root._focusedProc.running = true;
|
|
||||||
else {
|
|
||||||
root.focusedTitle = "";
|
|
||||||
root.focusedAppId = "";
|
|
||||||
}
|
|
||||||
} else if (ev.OverviewOpenedOrClosed !== undefined) {
|
|
||||||
root.overviewOpen = ev.OverviewOpenedOrClosed.is_open;
|
|
||||||
} else if (ev.WindowOpenedOrChanged !== undefined) {
|
|
||||||
root.windowOpenedOrChanged(ev.WindowOpenedOrChanged.window);
|
root.windowOpenedOrChanged(ev.WindowOpenedOrChanged.window);
|
||||||
const w = ev.WindowOpenedOrChanged.window;
|
|
||||||
if (w.is_focused) {
|
|
||||||
root.focusedTitle = w.title || "";
|
|
||||||
root.focusedAppId = w.app_id || "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,18 +37,10 @@ PanelWindow {
|
||||||
property color uC1: M.Theme.base0E
|
property color uC1: M.Theme.base0E
|
||||||
property color uC2: M.Theme.base09
|
property color uC2: M.Theme.base09
|
||||||
|
|
||||||
Connections {
|
// Wave animation: 6s sweep + 8s pause
|
||||||
target: M.NiriIpc
|
|
||||||
function onOverviewOpenChanged() {
|
|
||||||
if (!M.NiriIpc.overviewOpen)
|
|
||||||
fx.uWavePhase = -200;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wave animation: 6s sweep + 8s pause, only while overview is open
|
|
||||||
SequentialAnimation on uWavePhase {
|
SequentialAnimation on uWavePhase {
|
||||||
loops: Animation.Infinite
|
loops: Animation.Infinite
|
||||||
running: M.NiriIpc.overviewOpen
|
running: true
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
from: -200
|
from: -200
|
||||||
to: fx.width + 200
|
to: fx.width + 200
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,48 @@
|
||||||
|
pragma Singleton
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
|
import "." as M
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string sortBy: "cpu" // "cpu" or "mem"
|
property var byCpu: []
|
||||||
|
property var byMem: []
|
||||||
property int maxItems: 8
|
property int maxItems: 8
|
||||||
property bool active: false
|
|
||||||
|
|
||||||
property var processes: []
|
|
||||||
|
|
||||||
property Process _proc: Process {
|
property Process _proc: Process {
|
||||||
command: ["sh", "-c", "ps --no-headers -eo pid,pcpu,pmem,comm --sort=-%" + root.sortBy + " | head -" + root.maxItems]
|
id: proc
|
||||||
|
running: true
|
||||||
|
command: ["sh", "-c", "ps aux --sort=-%cpu 2>/dev/null | awk 'NR>1 && NR<=50 {cmd=$11; for(i=12;i<=NF&&i<=13;i++) cmd=cmd\" \"$i; print $1\"|\"$2\"|\"$3\"|\"$4\"|\"cmd}'"]
|
||||||
stdout: StdioCollector {
|
stdout: StdioCollector {
|
||||||
onStreamFinished: {
|
onStreamFinished: {
|
||||||
const rows = [];
|
const rows = [];
|
||||||
for (const line of text.trim().split("\n")) {
|
for (const line of text.trim().split("\n")) {
|
||||||
if (!line)
|
if (!line)
|
||||||
continue;
|
continue;
|
||||||
const p = line.trim().split(/\s+/);
|
const p = line.split("|");
|
||||||
if (p.length < 4)
|
if (p.length < 5)
|
||||||
continue;
|
continue;
|
||||||
|
const cmd = p[4].replace(/^.*\//, "");
|
||||||
rows.push({
|
rows.push({
|
||||||
"pid": parseInt(p[0]),
|
"user": p[0],
|
||||||
"cpu": parseFloat(p[1]),
|
"pid": parseInt(p[1]),
|
||||||
"mem": parseFloat(p[2]),
|
"cpu": parseFloat(p[2]),
|
||||||
"cmd": p.slice(3).join(" ")
|
"mem": parseFloat(p[3]),
|
||||||
|
"cmd": cmd || p[4]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
root.processes = rows;
|
root.byCpu = rows.slice().sort((a, b) => b.cpu - a.cpu).slice(0, root.maxItems);
|
||||||
|
root.byMem = rows.slice().sort((a, b) => b.mem - a.mem).slice(0, root.maxItems);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
property Timer _timer: Timer {
|
property Timer _timer: Timer {
|
||||||
interval: 2000
|
interval: 2000
|
||||||
running: root.active
|
running: true
|
||||||
repeat: true
|
repeat: true
|
||||||
triggeredOnStart: true
|
onTriggered: proc.running = true
|
||||||
onTriggered: root._proc.running = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,63 @@
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Effects
|
import QtQuick.Effects
|
||||||
import Quickshell
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
import Quickshell.Widgets
|
import Quickshell.Widgets
|
||||||
import "." as M
|
import "." as M
|
||||||
|
|
||||||
M.BarSection {
|
M.BarSection {
|
||||||
id: root
|
id: root
|
||||||
spacing: M.Theme.moduleSpacing
|
spacing: M.Theme.moduleSpacing
|
||||||
visible: M.Modules.windowTitle.enable && M.NiriIpc.focusedTitle !== ""
|
visible: M.Modules.windowTitle.enable && root._title !== ""
|
||||||
|
|
||||||
tooltip: M.NiriIpc.focusedAppId ? M.NiriIpc.focusedAppId + "\n" + M.NiriIpc.focusedTitle : M.NiriIpc.focusedTitle
|
tooltip: root._appId ? root._appId + "\n" + root._title : root._title
|
||||||
|
|
||||||
|
property string _title: ""
|
||||||
|
property string _appId: ""
|
||||||
readonly property string _iconSource: {
|
readonly property string _iconSource: {
|
||||||
if (!M.NiriIpc.focusedAppId)
|
if (!root._appId)
|
||||||
return "";
|
return "";
|
||||||
const entry = DesktopEntries.heuristicLookup(M.NiriIpc.focusedAppId);
|
const entry = DesktopEntries.heuristicLookup(root._appId);
|
||||||
return entry ? Quickshell.iconPath(entry.icon) : "";
|
return entry ? Quickshell.iconPath(entry.icon) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initial state — niri event-stream doesn't replay current focus
|
||||||
|
Process {
|
||||||
|
id: initProc
|
||||||
|
running: true
|
||||||
|
command: ["niri", "msg", "--json", "focused-window"]
|
||||||
|
stdout: StdioCollector {
|
||||||
|
onStreamFinished: {
|
||||||
|
try {
|
||||||
|
const w = JSON.parse(text);
|
||||||
|
if (w) {
|
||||||
|
root._title = w.title || "";
|
||||||
|
root._appId = w.app_id || "";
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Live updates via shared NiriIpc singleton
|
||||||
|
Connections {
|
||||||
|
target: M.NiriIpc
|
||||||
|
function onWindowFocusChanged(windowId) {
|
||||||
|
if (windowId !== null)
|
||||||
|
initProc.running = true;
|
||||||
|
else {
|
||||||
|
root._title = "";
|
||||||
|
root._appId = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function onWindowOpenedOrChanged(window) {
|
||||||
|
if (window.is_focused) {
|
||||||
|
root._title = window.title || "";
|
||||||
|
root._appId = window.app_id || "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IconImage {
|
IconImage {
|
||||||
visible: root._iconSource !== ""
|
visible: root._iconSource !== ""
|
||||||
source: root._iconSource
|
source: root._iconSource
|
||||||
|
|
@ -31,7 +71,7 @@ M.BarSection {
|
||||||
}
|
}
|
||||||
|
|
||||||
M.BarLabel {
|
M.BarLabel {
|
||||||
label: M.NiriIpc.focusedTitle
|
label: root._title
|
||||||
color: root.accentColor
|
color: root.accentColor
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ IdleInhibitor 1.0 IdleInhibitor.qml
|
||||||
Notifications 1.0 Notifications.qml
|
Notifications 1.0 Notifications.qml
|
||||||
singleton NiriIpc 1.0 NiriIpc.qml
|
singleton NiriIpc 1.0 NiriIpc.qml
|
||||||
singleton SystemStats 1.0 SystemStats.qml
|
singleton SystemStats 1.0 SystemStats.qml
|
||||||
ProcessList 1.0 ProcessList.qml
|
singleton ProcessList 1.0 ProcessList.qml
|
||||||
singleton NotifService 1.0 NotifService.qml
|
singleton NotifService 1.0 NotifService.qml
|
||||||
NotifItem 1.0 NotifItem.qml
|
NotifItem 1.0 NotifItem.qml
|
||||||
NotifPopup 1.0 NotifPopup.qml
|
NotifPopup 1.0 NotifPopup.qml
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue