1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-05-11 23:09:42 -04:00

quickshell: drop support for 0.2, require 0.3+

- Remove all compat code
- Rewire LegacyNetworkService to use Quickshell.Networking
- Add parentWindow to settings child windows
This commit is contained in:
bbedward
2026-05-11 13:04:29 -04:00
parent 3989c7f801
commit b8f4c350a8
52 changed files with 1472 additions and 2064 deletions

View File

@@ -85,8 +85,7 @@ Variants {
}
Component.onCompleted: {
if (typeof blurWallpaperWindow.updatesEnabled !== "undefined")
blurWallpaperWindow.updatesEnabled = Qt.binding(() => !root.source || root.effectActive || root._renderSettling || currentWallpaper.status === Image.Loading || nextWallpaper.status === Image.Loading);
blurWallpaperWindow.updatesEnabled = Qt.binding(() => !root.source || root.effectActive || root._renderSettling || currentWallpaper.status === Image.Loading || nextWallpaper.status === Image.Loading);
isInitialized = true;
}

View File

@@ -152,6 +152,20 @@ PanelWindow {
onTriggered: barBlur.rebuild()
}
Component {
id: blurRegionComp
Region {}
}
Component {
id: blurSubRegionComp
Region {
property Item w
item: w
radius: Theme.cornerRadius
}
}
Item {
id: barBlur
visible: false
@@ -173,33 +187,32 @@ PanelWindow {
if (!hasBar && widgets.length === 0)
return;
const cr = Theme.cornerRadius;
let qml = 'import QtQuick; import Quickshell; Region {';
const region = blurRegionComp.createObject(barWindow);
if (!region) {
log.warn("BarBlur: Failed to create blur region");
return;
}
if (hasBar) {
region.x = Qt.binding(() => topBarMouseArea.x + barUnitInset.x + topBarSlide.x);
region.y = Qt.binding(() => topBarMouseArea.y + barUnitInset.y + topBarSlide.y);
region.width = Qt.binding(() => barUnitInset.width);
region.height = Qt.binding(() => barUnitInset.height);
region.radius = Qt.binding(() => barBackground.rt);
}
const subRegions = [];
for (let i = 0; i < widgets.length; i++) {
qml += ` property Item w${i}; Region { item: w${i}; radius: ${cr} }`;
const sub = blurSubRegionComp.createObject(region, {
w: widgets[i]
});
if (sub)
subRegions.push(sub);
}
qml += '}';
region.regions = subRegions;
try {
const region = Qt.createQmlObject(qml, barWindow, "BarBlurRegion");
if (hasBar) {
region.x = Qt.binding(() => topBarMouseArea.x + barUnitInset.x + topBarSlide.x);
region.y = Qt.binding(() => topBarMouseArea.y + barUnitInset.y + topBarSlide.y);
region.width = Qt.binding(() => barUnitInset.width);
region.height = Qt.binding(() => barUnitInset.height);
region.radius = Qt.binding(() => barBackground.rt);
}
for (let i = 0; i < widgets.length; i++) {
region[`w${i}`] = widgets[i];
}
barWindow.BackgroundEffect.blurRegion = region;
barWindow.blurRegion = region;
} catch (e) {
log.warn("BarBlur: Failed to create blur region:", e);
}
barWindow.BackgroundEffect.blurRegion = region;
barWindow.blurRegion = region;
}
function teardown() {
@@ -529,27 +542,17 @@ PanelWindow {
implicitWidth: isVertical ? Theme.px(effectiveBarThickness + effectiveSpacing + ((barConfig?.gothCornersEnabled ?? false) && !hasMaximizedToplevel ? _wingR : 0), _dpr) + _shadowBuffer : 0
color: "transparent"
property var nativeInhibitor: null
Component.onCompleted: {
updateGpuTempConfig();
_updateBackgroundAlpha();
_updateHasMaximizedToplevel();
_updateHasFullscreenToplevel();
_updateShouldHideForWindows();
inhibitorInitTimer.start();
}
Timer {
id: inhibitorInitTimer
interval: 300
repeat: false
onTriggered: {
if (SessionService.nativeInhibitorAvailable) {
createNativeInhibitor();
}
}
IdleInhibitor {
window: barWindow
enabled: SessionService.idleInhibited
}
Connections {
@@ -581,35 +584,6 @@ PanelWindow {
DgopService.nonNvidiaGpuTempEnabled = hasGpuTempWidget || SessionData.nonNvidiaGpuTempEnabled;
}
function createNativeInhibitor() {
if (!SessionService.nativeInhibitorAvailable) {
return;
}
try {
const qmlString = `
import QtQuick
import Quickshell.Wayland
IdleInhibitor {
enabled: false
}
`;
nativeInhibitor = Qt.createQmlObject(qmlString, barWindow, "DankBar.NativeInhibitor");
nativeInhibitor.window = barWindow;
nativeInhibitor.enabled = Qt.binding(() => SessionService.idleInhibited);
nativeInhibitor.enabledChanged.connect(function () {
if (SessionService.idleInhibited !== nativeInhibitor.enabled) {
SessionService.idleInhibited = nativeInhibitor.enabled;
SessionService.inhibitorChanged();
}
});
} catch (e) {
nativeInhibitor = null;
}
}
Connections {
function onBarConfigChanged() {
barWindow.updateGpuTempConfig();

View File

@@ -1,6 +1,7 @@
import QtQuick
import Quickshell.Wayland
import qs.Common
import qs.Modals
import qs.Services
import qs.Widgets
@@ -18,9 +19,23 @@ DankPopout {
property bool _reopenAfterUpgrade: false
readonly property bool polkitModalOpen: PopoutService.polkitAuthModal?.visible ?? false
readonly property bool polkitModalOpen: polkitAuthSurfaceModal.shouldBeVisible
readonly property bool anyModalOpen: polkitModalOpen
Connections {
target: PolkitService.agent
enabled: PolkitService.polkitAvailable && systemUpdatePopout.shouldBeVisible
function onAuthenticationRequestStarted() {
polkitAuthSurfaceModal.open();
}
}
PolkitAuthSurfaceModal {
id: polkitAuthSurfaceModal
parentPopout: systemUpdatePopout
}
backgroundInteractive: !anyModalOpen
customKeyboardFocus: {
@@ -33,16 +48,6 @@ DankPopout {
return WlrKeyboardFocus.Exclusive;
}
Connections {
target: PolkitService.agent
enabled: PolkitService.polkitAvailable && triggerScreen !== null
function onAuthenticationRequestStarted() {
if (PopoutService.polkitAuthModal && triggerScreen)
PopoutService.polkitAuthModal.screen = triggerScreen;
}
}
Connections {
target: SystemUpdateService
function onIsUpgradingChanged() {

View File

@@ -1397,6 +1397,13 @@ BasePill {
close();
}
Timer {
id: pendingActionCloseTimer
interval: 80
repeat: false
onTriggered: menuRoot.closeWithAction()
}
function showSubMenu(entry) {
if (!entry || !entry.hasChildren)
return;
@@ -1853,7 +1860,7 @@ BasePill {
} else if (typeof menuEntry.triggered === "function") {
menuEntry.triggered();
}
Qt.createQmlObject('import QtQuick; Timer { interval: 80; running: true; repeat: false; onTriggered: menuRoot.closeWithAction() }', menuRoot);
pendingActionCloseTimer.restart();
}
}

View File

@@ -18,6 +18,7 @@ PanelWindow {
screen: targetScreen
visible: _frameActive
updatesEnabled: _connectedActive
WlrLayershell.namespace: "dms:frame"
WlrLayershell.layer: WlrLayer.Top

View File

@@ -4,11 +4,13 @@ import QtQuick
import Quickshell
import Quickshell.Wayland
import qs.Common
import qs.Services
PanelWindow {
id: root
property bool active: false
property bool _completed: false
signal fadeCompleted
signal fadeCancelled
@@ -35,7 +37,8 @@ PanelWindow {
opacity: 0
onOpacityChanged: {
if (opacity >= 0.99 && root.active) {
if (opacity >= 0.99 && root.active && !root._completed) {
root._completed = true;
root.fadeCompleted();
}
}
@@ -58,6 +61,7 @@ PanelWindow {
function startFade() {
if (!SettingsData.fadeToLockEnabled)
return;
_completed = false;
active = true;
fadeOverlay.opacity = 0.0;
fadeSeq.stop();
@@ -65,12 +69,29 @@ PanelWindow {
}
function cancelFade() {
if (_completed)
return;
fadeSeq.stop();
fadeOverlay.opacity = 0.0;
active = false;
fadeCancelled();
}
function dismiss() {
fadeSeq.stop();
fadeOverlay.opacity = 0.0;
active = false;
_completed = false;
}
Connections {
target: IdleService
function onIsShellLockedChanged() {
if (!IdleService.isShellLocked && root._completed)
root.dismiss();
}
}
MouseArea {
anchors.fill: parent
enabled: root.active

View File

@@ -15,7 +15,7 @@ Item {
property bool inputEnabled: false
property point lastMousePos: Qt.point(-1, -1)
property bool mouseInitialized: false
property var videoPlayer: null
readonly property var videoPlayer: playerLoader.item
signal dismissed
@@ -27,6 +27,24 @@ Item {
anchors.fill: parent
color: "black"
visible: root.active
Loader {
id: playerLoader
anchors.fill: parent
active: false
source: "VideoScreensaverPlayer.qml"
onLoaded: {
item.errorOccurred.connect((error, errorString) => {
log.warn("playback error:", errorString);
ToastService.showError(I18n.tr("Video Screensaver"), I18n.tr("Playback error: ") + errorString);
root.dismiss();
});
if (root.videoSource) {
item.source = root.videoSource;
item.play();
}
}
}
}
Timer {
@@ -82,43 +100,6 @@ Item {
}
}
function createVideoPlayer() {
if (videoPlayer)
return true;
try {
videoPlayer = Qt.createQmlObject(`
import QtQuick
import QtMultimedia
Video {
anchors.fill: parent
fillMode: VideoOutput.PreserveAspectCrop
loops: MediaPlayer.Infinite
volume: 0
}
`, background, "VideoScreensaver.VideoPlayer");
videoPlayer.errorOccurred.connect((error, errorString) => {
log.warn("playback error:", errorString);
ToastService.showError(I18n.tr("Video Screensaver"), I18n.tr("Playback error: ") + errorString);
root.dismiss();
});
return true;
} catch (e) {
log.warn("Failed to create video player:", e);
return false;
}
}
function destroyVideoPlayer() {
if (videoPlayer) {
videoPlayer.stop();
videoPlayer.destroy();
videoPlayer = null;
}
}
function start() {
if (!SettingsData.lockScreenVideoEnabled || !SettingsData.lockScreenVideoPath)
return;
@@ -128,8 +109,12 @@ Item {
return;
}
if (!createVideoPlayer())
playerLoader.active = true;
if (playerLoader.status === Loader.Error) {
log.warn("Failed to load video player");
playerLoader.active = false;
return;
}
videoPicker.result = "";
videoPicker.folder = "";
@@ -144,7 +129,9 @@ Item {
function dismiss() {
if (!active)
return;
destroyVideoPlayer();
if (videoPlayer)
videoPlayer.stop();
playerLoader.active = false;
inputEnabled = false;
active = false;
videoSource = "";

View File

@@ -0,0 +1,8 @@
import QtQuick
import QtMultimedia
Video {
fillMode: VideoOutput.PreserveAspectCrop
loops: MediaPlayer.Infinite
volume: 0
}

View File

@@ -3,6 +3,7 @@ pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Io
import qs.Common
import qs.Services
import qs.Widgets
@@ -230,44 +231,41 @@ Column {
if (!inlinePreviewVisible || !textArea.text)
return;
const content = textArea.text;
if (content.length > 0) {
const proc = Qt.createQmlObject(`
import QtQuick
import Quickshell.Io
Process {
property string content: ""
command: ["sh", "-c", "printf '%s' \\"$CONTENT\\" | dms clipboard copy"]
environment: { "CONTENT": content }
running: false
}`, root, "copyProc");
proc.content = content;
proc.running = true;
proc.exited.connect(() => {
ToastService.showInfo(I18n.tr("Copied to clipboard"));
proc.destroy();
});
}
if (content.length === 0)
return;
const proc = clipboardCopyProcComp.createObject(root, {
content: content,
running: true
});
proc.exited.connect(() => {
ToastService.showInfo(I18n.tr("Copied to clipboard"));
proc.destroy();
});
}
function copyHtmlToClipboard() {
if (!inlinePreviewVisible || !pluginHighlightedHtml)
return;
if (pluginHighlightedHtml.length > 0) {
const proc = Qt.createQmlObject(`
import QtQuick
import Quickshell.Io
Process {
property string content: ""
command: ["sh", "-c", "printf '%s' \\"$CONTENT\\" | dms clipboard copy"]
environment: { "CONTENT": content }
running: false
}`, root, "copyProcHtml");
proc.content = pluginHighlightedHtml;
proc.running = true;
proc.exited.connect(() => {
ToastService.showInfo(I18n.tr("HTML copied to clipboard"));
proc.destroy();
});
if (pluginHighlightedHtml.length === 0)
return;
const proc = clipboardCopyProcComp.createObject(root, {
content: pluginHighlightedHtml,
running: true
});
proc.exited.connect(() => {
ToastService.showInfo(I18n.tr("HTML copied to clipboard"));
proc.destroy();
});
}
Component {
id: clipboardCopyProcComp
Process {
property string content: ""
command: ["sh", "-c", "printf '%s' \"$CONTENT\" | dms clipboard copy"]
environment: ({
"CONTENT": content
})
}
}

View File

@@ -586,10 +586,11 @@ PanelWindow {
width: alignedWidth
height: alignedHeight
visible: !win._finalized && !chromeOnlyExit
scale: (!win.inlineHeightAnimating && cardHoverHandler.hovered) ? 1.01 : 1.0
transformOrigin: Item.Center
Behavior on scale {
property real chromeScale: (!win.inlineHeightAnimating && cardHoverHandler.hovered) ? 1.01 : 1.0
Behavior on chromeScale {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
@@ -650,6 +651,8 @@ PanelWindow {
id: bgShadowLayer
anchors.fill: parent
anchors.margins: -content.shadowRenderPadding
scale: content.chromeScale
transformOrigin: Item.Center
level: content.elevLevel
fallbackOffset: 6
shadowBlurPx: content.shadowBlurPx
@@ -684,6 +687,8 @@ PanelWindow {
visible: win.notificationData && win.notificationData.urgency === NotificationUrgency.Critical
opacity: 1
clip: true
scale: content.chromeScale
transformOrigin: Item.Center
gradient: Gradient {
orientation: Gradient.Horizontal
@@ -713,6 +718,8 @@ PanelWindow {
border.color: win.connectedFrameMode ? "transparent" : BlurService.borderColor
border.width: win.connectedFrameMode ? 0 : BlurService.borderWidth
z: 100
scale: content.chromeScale
transformOrigin: Item.Center
}
Item {

View File

@@ -15,6 +15,7 @@ FloatingWindow {
property int selectedIndex: -1
property bool keyboardNavigationActive: false
property var parentModal: null
parentWindow: parentModal
signal widgetAdded(string widgetType)
@@ -233,7 +234,7 @@ FloatingWindow {
spacing: Theme.spacingXS
DankActionButton {
visible: windowControls.supported
visible: windowControls.canMaximize
circular: false
iconName: root.maximized ? "fullscreen_exit" : "fullscreen"
iconSize: Theme.iconSize - 4

View File

@@ -17,6 +17,7 @@ FloatingWindow {
property bool keyboardNavigationActive: false
property bool isLoading: false
property var parentModal: null
parentWindow: parentModal
property bool pendingInstallHandled: false
property string typeFilter: ""
@@ -295,7 +296,7 @@ FloatingWindow {
}
DankActionButton {
visible: windowControls.supported
visible: windowControls.canMaximize
iconName: root.maximized ? "fullscreen_exit" : "fullscreen"
iconSize: Theme.iconSize - 2
iconColor: Theme.outline
@@ -723,6 +724,7 @@ FloatingWindow {
id: thirdPartyConfirmModal
property bool disablePopupTransparency: true
parentWindow: root
function show() {
visible = true;

View File

@@ -370,14 +370,6 @@ Item {
}
}
}
StyledText {
text: I18n.tr("Idle monitoring not supported - requires newer Quickshell version")
font.pixelSize: Theme.fontSizeSmall
color: Theme.error
anchors.horizontalCenter: parent.horizontalCenter
visible: !IdleService.idleMonitorAvailable
}
}
SettingsCard {

View File

@@ -17,6 +17,7 @@ FloatingWindow {
property bool keyboardNavigationActive: false
property bool isLoading: false
property var parentModal: null
parentWindow: parentModal
property bool pendingInstallHandled: false
property string pendingApplyThemeId: ""
@@ -264,7 +265,7 @@ FloatingWindow {
}
DankActionButton {
visible: windowControls.supported
visible: windowControls.canMaximize
iconName: root.maximized ? "fullscreen_exit" : "fullscreen"
iconSize: Theme.iconSize - 2
iconColor: Theme.outline

View File

@@ -3064,6 +3064,7 @@ Item {
ThemeBrowser {
id: themeBrowserItem
parentModal: themeColorsTab.parentModal
}
}

View File

@@ -14,6 +14,7 @@ FloatingWindow {
property int selectedIndex: -1
property bool keyboardNavigationActive: false
property var parentModal: null
parentWindow: parentModal
readonly property bool blurActive: Theme.blurForegroundLayers || Theme.transparentBlurLayers
readonly property real surfaceAlpha: blurActive ? Math.min(Theme.popupTransparency, Theme.transparentBlurLayers ? 0.36 : 0.78) : 1.0
readonly property real fieldAlpha: blurActive ? Math.min(Theme.popupTransparency, Theme.transparentBlurLayers ? 0.18 : 0.62) : 1.0
@@ -238,7 +239,7 @@ FloatingWindow {
spacing: Theme.spacingXS
DankActionButton {
visible: windowControls.supported
visible: windowControls.canMaximize
circular: false
iconName: root.maximized ? "fullscreen_exit" : "fullscreen"
iconSize: Theme.iconSize - 4

View File

@@ -222,8 +222,7 @@ Variants {
}
Component.onCompleted: {
if (typeof wallpaperWindow.updatesEnabled !== "undefined")
wallpaperWindow.updatesEnabled = Qt.binding(() => !root.source || root.effectActive || root._renderSettling || root.overviewBlurActive || root._overviewBlurSettling || root.pendingWallpaper !== "" || root._deferredSource !== "" || currentWallpaper.status === Image.Loading || nextWallpaper.status === Image.Loading);
wallpaperWindow.updatesEnabled = Qt.binding(() => !root.source || root.effectActive || root._renderSettling || root.overviewBlurActive || root._overviewBlurSettling || root.pendingWallpaper !== "" || root._deferredSource !== "" || currentWallpaper.status === Image.Loading || nextWallpaper.status === Image.Loading);
if (!source) {
root._renderSettling = false;