nova-shell/modules/WindowTitle.qml

89 lines
2.7 KiB
QML

import QtQuick
import QtQuick.Effects
import Quickshell
import Quickshell.Io
import Quickshell.Widgets
import "." as M
M.BarSection {
id: root
spacing: M.Theme.moduleSpacing
tooltip: root._appId ? root._appId + "\n" + root._title : root._title
property string _title: ""
property string _appId: ""
readonly property string _iconSource: {
if (!root._appId)
return "";
const entry = DesktopEntries.heuristicLookup(root._appId);
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 event stream
Process {
id: eventStream
running: true
command: ["niri", "msg", "--json", "event-stream"]
stdout: SplitParser {
splitMarker: "\n"
onRead: line => {
try {
const ev = JSON.parse(line);
if (ev.WindowFocusChanged !== undefined) {
// WindowFocusChanged only gives id, re-query for full info
if (ev.WindowFocusChanged.id !== null)
initProc.running = true;
else {
root._title = "";
root._appId = "";
}
} else if (ev.WindowOpenedOrChanged !== undefined) {
const w = ev.WindowOpenedOrChanged.window;
if (w.is_focused) {
root._title = w.title || "";
root._appId = w.app_id || "";
}
}
} catch (e) {}
}
}
}
IconImage {
visible: root._iconSource !== ""
source: root._iconSource
implicitSize: M.Theme.fontSize + 2
anchors.verticalCenter: parent.verticalCenter
layer.enabled: true
layer.effect: MultiEffect {
colorization: 1.0
colorizationColor: root.accentColor
}
}
M.BarLabel {
label: root._title
color: root.accentColor
elide: Text.ElideRight
anchors.verticalCenter: parent.verticalCenter
}
}