Files
dms-gamebar/overlay/Panel.qml
T

200 lines
5.0 KiB
QML

import QtQuick
import Quickshell
import Quickshell.Services.Pipewire
import qs.Common
import qs.Services
import qs.Widgets
import "../widgets"
FocusScope {
id: root
property var overlayRef: null
readonly property var daemon: overlayRef ? overlayRef.daemon : null
readonly property var pluginData: (daemon && daemon.pluginData) ? daemon.pluginData : ({})
readonly property var targetScreen: overlayRef ? overlayRef.effectiveScreen : null
readonly property real edgeMargin: Theme.spacingM
// Changes when the overlay lands on a different monitor (or that monitor
// changes resolution); widgets re-read their saved spot when it does.
readonly property string screenKey: daemon ? daemon.screenKey(root.targetScreen) : ""
readonly property real topLimit: topBar.y + topBar.height + Theme.spacingM
property int windowZCounter: 1
function nextWindowZ() {
root.windowZCounter = root.windowZCounter + 1;
return root.windowZCounter;
}
function requestClose() {
if (overlayRef)
overlayRef.requestClose();
}
function isWidgetVisible(widgetId) {
return daemon ? daemon.isWidgetVisible(widgetId) : false;
}
function toggleWidget(widgetId) {
if (daemon)
daemon.toggleWidget(widgetId);
}
function widgetPosition(widgetId) {
if (daemon)
return daemon.widgetPosition(root.targetScreen, widgetId, root.width, root.height);
return {
"x": root.width * 0.1,
"y": root.height * 0.15
};
}
function saveWidgetPosition(widgetId, x, y) {
if (daemon)
daemon.saveWidgetPosition(root.targetScreen, widgetId, x, y);
}
anchors.fill: parent
focus: true
// The modal's own Escape handler sits on a sibling focus scope, so the key
// never reaches it once this content holds focus - handle it here instead.
Keys.onEscapePressed: event => {
root.requestClose();
event.accepted = true;
}
Component.onCompleted: root.forceActiveFocus()
// Keeps the default sink/source properties live while the overlay is open.
PwObjectTracker {
objects: [AudioService.sink, AudioService.source].filter(node => !!node)
}
// Clicking empty space closes, like clicking outside a dialog.
MouseArea {
anchors.fill: parent
onClicked: root.requestClose()
}
TopBar {
id: topBar
panel: root
anchors.top: parent.top
anchors.topMargin: Theme.spacingL
anchors.horizontalCenter: parent.horizontalCenter
}
Repeater {
model: root.daemon ? root.daemon.widgetDefs : []
delegate: WidgetWindow {
required property var modelData
panel: root
widgetId: modelData.id
title: modelData.title
icon: modelData.icon
widgetWidth: modelData.width
widgetHeight: modelData.height
minimumY: root.topLimit
shown: root.isWidgetVisible(modelData.id)
contentComponent: {
switch (modelData.id) {
case "audio":
return audioWidgetComponent;
case "apps":
return appsWidgetComponent;
case "timer":
return timerWidgetComponent;
case "capture":
return captureWidgetComponent;
case "media":
return mediaWidgetComponent;
case "visualizer":
return visualizerWidgetComponent;
case "bluetooth":
return bluetoothWidgetComponent;
case "notepad":
return notepadWidgetComponent;
case "home":
return homeWidgetComponent;
case "system":
return systemWidgetComponent;
}
return null;
}
}
}
Component {
id: audioWidgetComponent
AudioWidget {}
}
Component {
id: appsWidgetComponent
AppMixer {}
}
Component {
id: timerWidgetComponent
TimerWidget {
service: root.daemon ? root.daemon.timerService : null
}
}
Component {
id: captureWidgetComponent
CaptureWidget {
service: root.daemon ? root.daemon.captureService : null
panel: root
}
}
Component {
id: visualizerWidgetComponent
VisualizerWidget {}
}
Component {
id: bluetoothWidgetComponent
BluetoothWidget {}
}
Component {
id: notepadWidgetComponent
NotepadWidget {}
}
Component {
id: mediaWidgetComponent
MediaWidget {}
}
Component {
id: homeWidgetComponent
HomeWidget {
service: root.daemon ? root.daemon.homeService : null
}
}
Component {
id: systemWidgetComponent
SystemWidget {}
}
}