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

Compare commits

..

7 Commits

Author SHA1 Message Date
bbedward
b76d0ce97d settings: fix child windows on newer quickshell-git 2026-01-13 16:58:08 -05:00
bbedward
fa66d330cf bump VERSION 2026-01-13 16:42:49 -05:00
Lucas
157eab2d07 settings: fix modal not opening on latest quickshell (#1357) 2026-01-13 16:42:38 -05:00
Lucas
f50ad2dc22 nix: escape version string (#1353) 2026-01-13 16:42:38 -05:00
bbedward
cd9d92d884 update changelog link and VERSION 2026-01-13 08:31:50 -05:00
Lucas
1b69a5e62b nix: add wtype dependency (#1346) 2026-01-13 08:27:46 -05:00
bbedward
61d311b157 widgets: fix running apps positioning and popup manager 2026-01-13 08:26:29 -05:00
16 changed files with 266 additions and 145 deletions

View File

@@ -19,7 +19,8 @@ in
]
++ lib.optional cfg.enableDynamicTheming pkgs.matugen
++ lib.optional cfg.enableAudioWavelength pkgs.cava
++ lib.optional cfg.enableCalendarEvents pkgs.khal;
++ lib.optional cfg.enableCalendarEvents pkgs.khal
++ lib.optional cfg.enableClipboardPaste pkgs.wtype;
plugins = lib.mapAttrs (name: plugin: {
source = plugin.src;

View File

@@ -70,6 +70,12 @@ in
description = "Add calendar events support via khal";
};
enableClipboardPaste = lib.mkOption {
type = types.bool;
default = true;
description = "Adds needed dependencies for directly pasting items from the clipboard history.";
};
quickshell = {
package = lib.mkPackageOption dmsPkgs "quickshell" {
extraDescription = "The quickshell package to use (defaults to be built from source, due to unreleased features used by DMS).";

View File

@@ -61,11 +61,13 @@
(builtins.substring 6 2 longDate)
];
version =
pkgs.lib.removePrefix "v" (pkgs.lib.trim (builtins.readFile ./quickshell/VERSION))
+ "+date="
+ mkDate (self.lastModifiedDate or "19700101")
+ "_"
+ (self.shortRev or "dirty");
let
rawVersion = pkgs.lib.removePrefix "v" (pkgs.lib.trim (builtins.readFile ./quickshell/VERSION));
cleanVersion = builtins.replaceStrings [ " " ] [ "" ] rawVersion;
dateSuffix = "+date=" + mkDate (self.lastModifiedDate or "19700101");
revSuffix = "_" + (self.shortRev or "dirty");
in
"${cleanVersion}${dateSuffix}${revSuffix}";
in
{
dms-shell = pkgs.buildGoModule (
@@ -83,7 +85,7 @@
ldflags = [
"-s"
"-w"
"-X main.Version=${version}"
"-X 'main.Version=${version}'"
];
nativeBuildInputs = with pkgs; [

View File

@@ -442,17 +442,15 @@ Item {
PopoutService.settingsModalLoader = settingsModalLoader;
}
onActiveChanged: {
if (active && item) {
PopoutService.settingsModal = item;
PopoutService._onSettingsModalLoaded();
}
}
SettingsModal {
id: settingsModal
property bool wasShown: false
Component.onCompleted: {
PopoutService.settingsModal = settingsModal;
PopoutService._onSettingsModalLoaded();
}
onVisibleChanged: {
if (visible) {
wasShown = true;

View File

@@ -797,11 +797,9 @@ Item {
const modal = PopoutService.settingsModal;
if (modal) {
if (type === "wallpaper") {
modal.wallpaperBrowser.allowStacking = false;
modal.wallpaperBrowser.open();
modal.openWallpaperBrowser(false);
} else if (type === "profile") {
modal.profileBrowser.allowStacking = false;
modal.profileBrowser.open();
modal.openProfileBrowser(false);
}
} else {
PopoutService.openSettings();

View File

@@ -128,9 +128,7 @@ FloatingWindow {
iconName: "open_in_new"
backgroundColor: Theme.surfaceContainerHighest
textColor: Theme.surfaceText
// ! TODO - replace with blog before tag
//onClicked: Qt.openUrlExternally("https://danklinux.com/blog/v1.2-release")
onClicked: Qt.openUrlExternally("https://github.com/AvengeMedia/DankMaterialShell/compare/v1.0.3...master")
onClicked: Qt.openUrlExternally("https://danklinux.com/blog/v1-2-release")
}
DankButton {

View File

@@ -74,9 +74,7 @@ Rectangle {
if (root.parentModal) {
root.parentModal.allowFocusOverride = true;
root.parentModal.shouldHaveFocus = false;
if (root.parentModal.profileBrowser) {
root.parentModal.profileBrowser.open();
}
root.parentModal.openProfileBrowser();
}
}
}

View File

@@ -8,8 +8,26 @@ import qs.Widgets
FloatingWindow {
id: settingsModal
property alias profileBrowser: profileBrowser
property alias wallpaperBrowser: wallpaperBrowser
property var profileBrowser: profileBrowserLoader.item
property var wallpaperBrowser: wallpaperBrowserLoader.item
function openProfileBrowser(allowStacking) {
profileBrowserLoader.active = true;
if (!profileBrowserLoader.item)
return;
if (allowStacking !== undefined)
profileBrowserLoader.item.allowStacking = allowStacking;
profileBrowserLoader.item.open();
}
function openWallpaperBrowser(allowStacking) {
wallpaperBrowserLoader.active = true;
if (!wallpaperBrowserLoader.item)
return;
if (allowStacking !== undefined)
wallpaperBrowserLoader.item.allowStacking = allowStacking;
wallpaperBrowserLoader.item.open();
}
property alias sidebar: sidebar
property int currentTabIndex: 0
property bool shouldHaveFocus: visible
@@ -96,41 +114,51 @@ FloatingWindow {
}
}
FileBrowserModal {
id: profileBrowser
LazyLoader {
id: profileBrowserLoader
active: false
allowStacking: true
parentModal: settingsModal
browserTitle: I18n.tr("Select Profile Image", "profile image file browser title")
browserIcon: "person"
browserType: "profile"
showHiddenFiles: true
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: path => {
PortalService.setProfileImage(path);
close();
}
onDialogClosed: () => {
allowStacking = true;
FileBrowserModal {
id: profileBrowserItem
allowStacking: true
parentModal: settingsModal
browserTitle: I18n.tr("Select Profile Image", "profile image file browser title")
browserIcon: "person"
browserType: "profile"
showHiddenFiles: true
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: path => {
PortalService.setProfileImage(path);
close();
}
onDialogClosed: () => {
allowStacking = true;
}
}
}
FileBrowserModal {
id: wallpaperBrowser
LazyLoader {
id: wallpaperBrowserLoader
active: false
allowStacking: true
parentModal: settingsModal
browserTitle: I18n.tr("Select Wallpaper", "wallpaper file browser title")
browserIcon: "wallpaper"
browserType: "wallpaper"
showHiddenFiles: true
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: path => {
SessionData.setWallpaper(path);
close();
}
onDialogClosed: () => {
allowStacking = true;
FileBrowserModal {
id: wallpaperBrowserItem
allowStacking: true
parentModal: settingsModal
browserTitle: I18n.tr("Select Wallpaper", "wallpaper file browser title")
browserIcon: "wallpaper"
browserType: "wallpaper"
showHiddenFiles: true
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: path => {
SessionData.setWallpaper(path);
close();
}
onDialogClosed: () => {
allowStacking = true;
}
}
}

View File

@@ -493,8 +493,10 @@ Item {
const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, 0);
const screenX = root.parentScreen ? root.parentScreen.x : 0;
const relativeX = globalPos.x - screenX;
const yPos = root.barThickness + root.barSpacing - 7;
windowContextMenuLoader.item.showAt(relativeX, yPos, false, "top");
const screenHeight = root.parentScreen ? root.parentScreen.height : Screen.height;
const isBottom = root.axis?.edge === "bottom";
const yPos = isBottom ? (screenHeight - root.barThickness - root.barSpacing - 32 - Theme.spacingXS) : (root.barThickness + root.barSpacing + Theme.spacingXS);
windowContextMenuLoader.item.showAt(relativeX, yPos, false, root.axis?.edge);
}
}
} else if (mouse.button === Qt.MiddleButton) {
@@ -726,8 +728,10 @@ Item {
const globalPos = delegateItem.mapToGlobal(delegateItem.width / 2, 0);
const screenX = root.parentScreen ? root.parentScreen.x : 0;
const relativeX = globalPos.x - screenX;
const yPos = root.barThickness + root.barSpacing - 7;
windowContextMenuLoader.item.showAt(relativeX, yPos, false, "top");
const screenHeight = root.parentScreen ? root.parentScreen.height : Screen.height;
const isBottom = root.axis?.edge === "bottom";
const yPos = isBottom ? (screenHeight - root.barThickness - root.barSpacing - 32 - Theme.spacingXS) : (root.barThickness + root.barSpacing + Theme.spacingXS);
windowContextMenuLoader.item.showAt(relativeX, yPos, false, root.axis?.edge);
}
}
}

View File

@@ -10,8 +10,9 @@ QtObject {
readonly property bool compactMode: SettingsData.notificationCompactMode
readonly property real cardPadding: compactMode ? Theme.spacingS : Theme.spacingM
readonly property real popupIconSize: compactMode ? 48 : 63
readonly property real popupSpacing: Theme.spacingS
readonly property int baseNotificationHeight: cardPadding * 3 + popupIconSize + popupSpacing
readonly property real actionButtonHeight: compactMode ? 20 : 24
readonly property real popupSpacing: 4
readonly property int baseNotificationHeight: cardPadding * 2 + popupIconSize + actionButtonHeight + Theme.spacingS + popupSpacing
property int maxTargetNotifications: 4
property var popupWindows: [] // strong refs to windows (live until exitFinished)
property var destroyingWindows: new Set()

View File

@@ -22,18 +22,38 @@ Item {
readonly property var allInstances: SettingsData.desktopWidgetInstances || []
readonly property var allGroups: SettingsData.desktopWidgetGroups || []
DesktopWidgetBrowser {
id: widgetBrowser
parentModal: root.parentModal
onWidgetAdded: widgetType => {
ToastService.showInfo(I18n.tr("Widget added"));
function showWidgetBrowser() {
widgetBrowserLoader.active = true;
if (widgetBrowserLoader.item)
widgetBrowserLoader.item.show();
}
function showDesktopPluginBrowser() {
desktopPluginBrowserLoader.active = true;
if (desktopPluginBrowserLoader.item)
desktopPluginBrowserLoader.item.show();
}
LazyLoader {
id: widgetBrowserLoader
active: false
DesktopWidgetBrowser {
parentModal: root.parentModal
onWidgetAdded: widgetType => {
ToastService.showInfo(I18n.tr("Widget added"));
}
}
}
PluginBrowser {
id: desktopPluginBrowser
parentModal: root.parentModal
typeFilter: "desktop-widget"
LazyLoader {
id: desktopPluginBrowserLoader
active: false
PluginBrowser {
parentModal: root.parentModal
typeFilter: "desktop-widget"
}
}
DankFlickable {
@@ -74,13 +94,13 @@ Item {
DankButton {
text: I18n.tr("Add Widget")
iconName: "add"
onClicked: widgetBrowser.show()
onClicked: root.showWidgetBrowser()
}
DankButton {
text: I18n.tr("Browse Plugins")
iconName: "store"
onClicked: desktopPluginBrowser.show()
onClicked: root.showDesktopPluginBrowser()
}
}
}

View File

@@ -1,4 +1,5 @@
import QtQuick
import Quickshell
import qs.Common
import qs.Services
import qs.Widgets
@@ -209,7 +210,7 @@ FocusScope {
iconName: "store"
enabled: DMSService.dmsAvailable
onClicked: {
pluginBrowser.show();
showPluginBrowser();
}
}
@@ -382,9 +383,11 @@ FocusScope {
Connections {
target: DMSService
function onPluginsListReceived(plugins) {
pluginBrowser.isLoading = false;
pluginBrowser.allPlugins = plugins;
pluginBrowser.updateFilteredPlugins();
if (!pluginBrowserLoader.item)
return;
pluginBrowserLoader.item.isLoading = false;
pluginBrowserLoader.item.allPlugins = plugins;
pluginBrowserLoader.item.updateFilteredPlugins();
}
function onInstalledPluginsReceived(plugins) {
var pluginMap = {};
@@ -410,22 +413,36 @@ FocusScope {
}
Component.onCompleted: {
pluginBrowser.parentModal = pluginsTab.parentModal;
if (DMSService.dmsAvailable && DMSService.apiVersion >= 8)
DMSService.listInstalled();
if (PopoutService.pendingPluginInstall)
Qt.callLater(() => pluginBrowser.show());
Qt.callLater(showPluginBrowser);
}
Connections {
target: PopoutService
function onPendingPluginInstallChanged() {
if (PopoutService.pendingPluginInstall)
pluginBrowser.show();
showPluginBrowser();
}
}
PluginBrowser {
id: pluginBrowser
LazyLoader {
id: pluginBrowserLoader
active: false
PluginBrowser {
id: pluginBrowserItem
Component.onCompleted: {
pluginBrowserItem.parentModal = pluginsTab.parentModal;
}
}
}
function showPluginBrowser() {
pluginBrowserLoader.active = true;
if (pluginBrowserLoader.item)
pluginBrowserLoader.item.show();
}
}

View File

@@ -131,7 +131,7 @@ Item {
if (DMSService.dmsAvailable)
DMSService.listInstalledThemes();
if (PopoutService.pendingThemeInstall)
Qt.callLater(() => themeBrowser.show());
Qt.callLater(() => showThemeBrowser());
templateCheckProcess.running = true;
if (CompositorService.isNiri || CompositorService.isHyprland || CompositorService.isDwl)
checkCursorIncludeStatus();
@@ -169,7 +169,7 @@ Item {
target: PopoutService
function onPendingThemeInstallChanged() {
if (PopoutService.pendingThemeInstall)
themeBrowser.show();
showThemeBrowser();
}
}
@@ -939,7 +939,7 @@ Item {
text: I18n.tr("Browse Themes", "browse themes button")
iconName: "store"
anchors.horizontalCenter: parent.horizontalCenter
onClicked: themeBrowser.show()
onClicked: showThemeBrowser()
}
}
}
@@ -2041,7 +2041,18 @@ Item {
}
}
ThemeBrowser {
id: themeBrowser
LazyLoader {
id: themeBrowserLoader
active: false
ThemeBrowser {
id: themeBrowserItem
}
}
function showThemeBrowser() {
themeBrowserLoader.active = true;
if (themeBrowserLoader.item)
themeBrowserLoader.item.show();
}
}

View File

@@ -139,7 +139,7 @@ Item {
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: mainWallpaperBrowser.open()
onClicked: root.openMainWallpaperBrowser()
}
}
@@ -476,7 +476,7 @@ Item {
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: lightWallpaperBrowser.open()
onClicked: root.openLightWallpaperBrowser()
}
}
@@ -660,7 +660,7 @@ Item {
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: darkWallpaperBrowser.open()
onClicked: root.openDarkWallpaperBrowser()
}
}
@@ -1242,53 +1242,83 @@ Item {
}
}
FileBrowserModal {
id: mainWallpaperBrowser
parentModal: root.parentModal
browserTitle: I18n.tr("Select Wallpaper", "wallpaper file browser title")
browserIcon: "wallpaper"
browserType: "wallpaper"
showHiddenFiles: true
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: path => {
if (SessionData.perMonitorWallpaper) {
SessionData.setMonitorWallpaper(selectedMonitorName, path);
} else {
SessionData.setWallpaper(path);
function openMainWallpaperBrowser() {
mainWallpaperBrowserLoader.active = true;
if (mainWallpaperBrowserLoader.item)
mainWallpaperBrowserLoader.item.open();
}
function openLightWallpaperBrowser() {
lightWallpaperBrowserLoader.active = true;
if (lightWallpaperBrowserLoader.item)
lightWallpaperBrowserLoader.item.open();
}
function openDarkWallpaperBrowser() {
darkWallpaperBrowserLoader.active = true;
if (darkWallpaperBrowserLoader.item)
darkWallpaperBrowserLoader.item.open();
}
LazyLoader {
id: mainWallpaperBrowserLoader
active: false
FileBrowserModal {
parentModal: root.parentModal
browserTitle: I18n.tr("Select Wallpaper", "wallpaper file browser title")
browserIcon: "wallpaper"
browserType: "wallpaper"
showHiddenFiles: true
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: path => {
if (SessionData.perMonitorWallpaper) {
SessionData.setMonitorWallpaper(selectedMonitorName, path);
} else {
SessionData.setWallpaper(path);
}
close();
}
close();
}
}
FileBrowserModal {
id: lightWallpaperBrowser
parentModal: root.parentModal
browserTitle: I18n.tr("Select Wallpaper", "light mode wallpaper file browser title")
browserIcon: "light_mode"
browserType: "wallpaper"
showHiddenFiles: true
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: path => {
SessionData.wallpaperPathLight = path;
SessionData.syncWallpaperForCurrentMode();
SessionData.saveSettings();
close();
LazyLoader {
id: lightWallpaperBrowserLoader
active: false
FileBrowserModal {
parentModal: root.parentModal
browserTitle: I18n.tr("Select Wallpaper", "light mode wallpaper file browser title")
browserIcon: "light_mode"
browserType: "wallpaper"
showHiddenFiles: true
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: path => {
SessionData.wallpaperPathLight = path;
SessionData.syncWallpaperForCurrentMode();
SessionData.saveSettings();
close();
}
}
}
FileBrowserModal {
id: darkWallpaperBrowser
parentModal: root.parentModal
browserTitle: I18n.tr("Select Wallpaper", "dark mode wallpaper file browser title")
browserIcon: "dark_mode"
browserType: "wallpaper"
showHiddenFiles: true
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: path => {
SessionData.wallpaperPathDark = path;
SessionData.syncWallpaperForCurrentMode();
SessionData.saveSettings();
close();
LazyLoader {
id: darkWallpaperBrowserLoader
active: false
FileBrowserModal {
parentModal: root.parentModal
browserTitle: I18n.tr("Select Wallpaper", "dark mode wallpaper file browser title")
browserIcon: "dark_mode"
browserType: "wallpaper"
showHiddenFiles: true
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
onFileSelected: path => {
SessionData.wallpaperPathDark = path;
SessionData.syncWallpaperForCurrentMode();
SessionData.saveSettings();
close();
}
}
}
}

View File

@@ -1,5 +1,6 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import qs.Common
import qs.Services
import qs.Widgets
@@ -916,14 +917,28 @@ Item {
});
}
WidgetSelectionPopup {
id: widgetSelectionPopup
parentModal: widgetsTab.parentModal
onWidgetSelected: (widgetId, targetSection) => {
widgetsTab.addWidgetToSection(widgetId, targetSection);
LazyLoader {
id: widgetSelectionPopupLoader
active: false
WidgetSelectionPopup {
id: widgetSelectionPopupItem
parentModal: widgetsTab.parentModal
onWidgetSelected: (widgetId, targetSection) => {
widgetsTab.addWidgetToSection(widgetId, targetSection);
}
}
}
function showWidgetSelectionPopup(sectionId) {
widgetSelectionPopupLoader.active = true;
if (!widgetSelectionPopupLoader.item)
return;
widgetSelectionPopupLoader.item.targetSection = sectionId;
widgetSelectionPopupLoader.item.allWidgets = widgetsTab.getWidgetsForPopup();
widgetSelectionPopupLoader.item.show();
}
DankFlickable {
anchors.fill: parent
clip: true
@@ -1113,9 +1128,7 @@ Item {
widgetsTab.handleItemOrderChanged(sectionId, newOrder);
}
onAddWidget: sectionId => {
widgetSelectionPopup.targetSection = sectionId;
widgetSelectionPopup.allWidgets = widgetsTab.getWidgetsForPopup();
widgetSelectionPopup.show();
showWidgetSelectionPopup(sectionId);
}
onRemoveWidget: (sectionId, index) => {
widgetsTab.removeWidgetFromSection(sectionId, index);
@@ -1170,9 +1183,7 @@ Item {
widgetsTab.handleItemOrderChanged(sectionId, newOrder);
}
onAddWidget: sectionId => {
widgetSelectionPopup.targetSection = sectionId;
widgetSelectionPopup.allWidgets = widgetsTab.getWidgetsForPopup();
widgetSelectionPopup.show();
showWidgetSelectionPopup(sectionId);
}
onRemoveWidget: (sectionId, index) => {
widgetsTab.removeWidgetFromSection(sectionId, index);
@@ -1227,9 +1238,7 @@ Item {
widgetsTab.handleItemOrderChanged(sectionId, newOrder);
}
onAddWidget: sectionId => {
widgetSelectionPopup.targetSection = sectionId;
widgetSelectionPopup.allWidgets = widgetsTab.getWidgetsForPopup();
widgetSelectionPopup.show();
showWidgetSelectionPopup(sectionId);
}
onRemoveWidget: (sectionId, index) => {
widgetsTab.removeWidgetFromSection(sectionId, index);

View File

@@ -1 +1 @@
v1.2-unstable
v1.2.1