1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-05-03 02:52:07 -04:00

Compare commits

...

12 Commits

Author SHA1 Message Date
bbedward
242ead722a screenshot: adjust cursor CLI option to be more explicit 2026-02-17 22:28:19 -05:00
bbedward
8a6d9696a8 settings: workaround crash 2026-02-17 22:20:01 -05:00
purian23
896b7ea242 notifications: Tweak animation scale & settings 2026-02-17 22:05:19 -05:00
bbedward
0c7f4c7828 settings: guard internal writes from watcher 2026-02-17 22:03:36 -05:00
bbedward
3d35af2a87 cc: fix plugin reloading in bar position changes 2026-02-17 17:24:22 -05:00
bbedward
fed3c36f84 popout: anchor height changing popout surfaces to top and bottom 2026-02-17 17:18:07 -05:00
bbedward
414d81aa40 workspaces: fix named workspace icons 2026-02-17 16:02:13 -05:00
bbedward
d548803769 dankinstall: no_anim on dms layers 2026-02-17 15:32:08 -05:00
bbedward
1180258394 system updater: fix hide no update option 2026-02-17 13:53:17 -05:00
bbedward
48a566a24b launcher: fix kb navigation not always showing last delegate in view 2026-02-17 13:07:43 -05:00
bbedward
3bc5d1df81 doctor: add qt6-imageformats check 2026-02-17 12:58:09 -05:00
bbedward
c7222e2e86 bump version, codename, disable changelog 2026-02-17 12:02:36 -05:00
27 changed files with 283 additions and 220 deletions

View File

@@ -45,9 +45,9 @@ body:
- type: textarea
id: dms_doctor
attributes:
label: dms doctor -v
description: Output of `dms doctor -v` command
placeholder: Paste the output of `dms doctor -v` here
label: dms doctor -vC
description: Output of `dms doctor -vC` command
placeholder: Paste the output of `dms doctor -vC` here
validations:
required: true
- type: textarea

View File

@@ -30,9 +30,9 @@ body:
- type: textarea
id: dms_doctor
attributes:
label: dms doctor -v
description: Output of `dms doctor -v` command
placeholder: Paste the output of `dms doctor -v` here
label: dms doctor -vC
description: Output of `dms doctor -vC` command
placeholder: Paste the output of `dms doctor -vC` here
validations:
required: false
- type: textarea

View File

@@ -649,40 +649,73 @@ func checkI2CAvailability() checkResult {
return checkResult{catOptionalFeatures, "I2C/DDC", statusOK, fmt.Sprintf("%d monitor(s) detected", len(devices)), "External monitor brightness control", doctorDocsURL + "#optional-features"}
}
func checkKImageFormats() checkResult {
func checkImageFormatPlugins() []checkResult {
url := doctorDocsURL + "#optional-features"
desc := "Extra image format support (AVIF, HEIF, JXL)"
pluginDir := findQtPluginDir()
if pluginDir == "" {
return checkResult{catOptionalFeatures, "kimageformats", statusInfo, "Cannot detect (qtpaths not found)", desc, url}
}
imageFormatsDir := filepath.Join(pluginDir, "imageformats")
keyPlugins := []struct{ file, format string }{
{"kimg_avif.so", "AVIF"},
{"kimg_heif.so", "HEIF"},
{"kimg_jxl.so", "JXL"},
{"kimg_exr.so", "EXR"},
}
var found []string
for _, p := range keyPlugins {
if _, err := os.Stat(filepath.Join(imageFormatsDir, p.file)); err == nil {
found = append(found, p.format)
return []checkResult{
{catOptionalFeatures, "qt6-imageformats", statusInfo, "Cannot detect (plugin dir not found)", "WebP, TIFF, JP2 support", url},
{catOptionalFeatures, "kimageformats", statusInfo, "Cannot detect (plugin dir not found)", "AVIF, HEIF, JXL support", url},
}
}
if len(found) == 0 {
return checkResult{catOptionalFeatures, "kimageformats", statusWarn, "Not installed", desc, url}
imageFormatsDir := filepath.Join(pluginDir, "imageformats")
type pluginCheck struct {
name string
desc string
plugins []struct{ file, format string }
}
details := ""
if doctorVerbose {
details = fmt.Sprintf("Formats: %s (%s)", strings.Join(found, ", "), imageFormatsDir)
checks := []pluginCheck{
{
name: "qt6-imageformats",
desc: "WebP, TIFF, GIF, JP2 support",
plugins: []struct{ file, format string }{
{"libqwebp.so", "WebP"},
{"libqtiff.so", "TIFF"},
{"libqgif.so", "GIF"},
{"libqjp2.so", "JP2"},
{"libqicns.so", "ICNS"},
},
},
{
name: "kimageformats",
desc: "AVIF, HEIF, JXL support",
plugins: []struct{ file, format string }{
{"kimg_avif.so", "AVIF"},
{"kimg_heif.so", "HEIF"},
{"kimg_jxl.so", "JXL"},
{"kimg_exr.so", "EXR"},
},
},
}
return checkResult{catOptionalFeatures, "kimageformats", statusOK, fmt.Sprintf("Installed (%d formats)", len(found)), details, url}
var results []checkResult
for _, c := range checks {
var found []string
for _, p := range c.plugins {
if _, err := os.Stat(filepath.Join(imageFormatsDir, p.file)); err == nil {
found = append(found, p.format)
}
}
var result checkResult
switch {
case len(found) == 0:
result = checkResult{catOptionalFeatures, c.name, statusWarn, "Not installed", c.desc, url}
default:
details := ""
if doctorVerbose {
details = fmt.Sprintf("Formats: %s (%s)", strings.Join(found, ", "), imageFormatsDir)
}
result = checkResult{catOptionalFeatures, c.name, statusOK, fmt.Sprintf("Installed (%d formats)", len(found)), details, url}
}
results = append(results, result)
}
return results
}
func findQtPluginDir() string {
@@ -773,7 +806,7 @@ func checkOptionalDependencies() []checkResult {
results = append(results, checkResult{catOptionalFeatures, "cups-pk-helper", cupsPkStatus, cupsPkMsg, "Printer management", optionalFeaturesURL})
results = append(results, checkI2CAvailability())
results = append(results, checkKImageFormats())
results = append(results, checkImageFormatPlugins()...)
terminals := []string{"ghostty", "kitty", "alacritty", "foot", "wezterm"}
if idx := slices.IndexFunc(terminals, utils.CommandExists); idx >= 0 {

View File

@@ -13,16 +13,16 @@ import (
)
var (
ssOutputName string
ssIncludeCursor bool
ssFormat string
ssQuality int
ssOutputDir string
ssFilename string
ssNoClipboard bool
ssNoFile bool
ssNoNotify bool
ssStdout bool
ssOutputName string
ssCursor string
ssFormat string
ssQuality int
ssOutputDir string
ssFilename string
ssNoClipboard bool
ssNoFile bool
ssNoNotify bool
ssStdout bool
)
var screenshotCmd = &cobra.Command{
@@ -52,7 +52,7 @@ Examples:
dms screenshot last # Last region (pre-selected)
dms screenshot --no-clipboard # Save file only
dms screenshot --no-file # Clipboard only
dms screenshot --cursor # Include cursor
dms screenshot --cursor=on # Include cursor
dms screenshot -f jpg -q 85 # JPEG with quality 85`,
}
@@ -111,7 +111,7 @@ var notifyActionCmd = &cobra.Command{
func init() {
screenshotCmd.PersistentFlags().StringVarP(&ssOutputName, "output", "o", "", "Output name for 'output' mode")
screenshotCmd.PersistentFlags().BoolVar(&ssIncludeCursor, "cursor", false, "Include cursor in screenshot")
screenshotCmd.PersistentFlags().StringVar(&ssCursor, "cursor", "off", "Include cursor in screenshot (on/off)")
screenshotCmd.PersistentFlags().StringVarP(&ssFormat, "format", "f", "png", "Output format (png, jpg, ppm)")
screenshotCmd.PersistentFlags().IntVarP(&ssQuality, "quality", "q", 90, "JPEG quality (1-100)")
screenshotCmd.PersistentFlags().StringVarP(&ssOutputDir, "dir", "d", "", "Output directory")
@@ -136,7 +136,9 @@ func getScreenshotConfig(mode screenshot.Mode) screenshot.Config {
config := screenshot.DefaultConfig()
config.Mode = mode
config.OutputName = ssOutputName
config.IncludeCursor = ssIncludeCursor
if strings.EqualFold(ssCursor, "on") {
config.Cursor = screenshot.CursorOn
}
config.Clipboard = !ssNoClipboard
config.SaveFile = !ssNoFile
config.Notify = !ssNoNotify

View File

@@ -111,6 +111,7 @@ windowrule = float on, match:class ^(zoom)$
# windowrule = float on, match:class ^(org.quickshell)$
layerrule = no_anim on, match:namespace ^(quickshell)$
layerrule = no_anim on, match:namespace ^dms:.*
source = ./dms/colors.conf
source = ./dms/outputs.conf

View File

@@ -108,7 +108,7 @@ func NewRegionSelector(s *Screenshoter) *RegionSelector {
screenshoter: s,
outputs: make(map[uint32]*WaylandOutput),
preCapture: make(map[*WaylandOutput]*PreCapture),
showCapturedCursor: true,
showCapturedCursor: s.config.Cursor == CursorOn,
}
}

View File

@@ -453,10 +453,7 @@ func (s *Screenshoter) blitBuffer(dst, src *ShmBuffer, dstX, dstY int, yInverted
}
func (s *Screenshoter) captureWholeOutput(output *WaylandOutput) (*CaptureResult, error) {
cursor := int32(0)
if s.config.IncludeCursor {
cursor = 1
}
cursor := int32(s.config.Cursor)
frame, err := s.screencopy.CaptureOutput(cursor, output.wlOutput)
if err != nil {
@@ -624,10 +621,7 @@ func (s *Screenshoter) captureRegionOnOutput(output *WaylandOutput, region Regio
}
}
cursor := int32(0)
if s.config.IncludeCursor {
cursor = 1
}
cursor := int32(s.config.Cursor)
frame, err := s.screencopy.CaptureOutputRegion(cursor, output.wlOutput, localX, localY, w, h)
if err != nil {

View File

@@ -19,6 +19,13 @@ const (
FormatPPM
)
type CursorMode int
const (
CursorOff CursorMode = iota
CursorOn
)
type Region struct {
X int32 `json:"x"`
Y int32 `json:"y"`
@@ -42,29 +49,29 @@ type Output struct {
}
type Config struct {
Mode Mode
OutputName string
IncludeCursor bool
Format Format
Quality int
OutputDir string
Filename string
Clipboard bool
SaveFile bool
Notify bool
Stdout bool
Mode Mode
OutputName string
Cursor CursorMode
Format Format
Quality int
OutputDir string
Filename string
Clipboard bool
SaveFile bool
Notify bool
Stdout bool
}
func DefaultConfig() Config {
return Config{
Mode: ModeRegion,
IncludeCursor: false,
Format: FormatPNG,
Quality: 90,
OutputDir: "",
Filename: "",
Clipboard: true,
SaveFile: true,
Notify: true,
Mode: ModeRegion,
Cursor: CursorOff,
Format: FormatPNG,
Quality: 90,
OutputDir: "",
Filename: "",
Clipboard: true,
SaveFile: true,
Notify: true,
}
}

View File

@@ -1 +1 @@
Saffron Bloom
The Wolverine

View File

@@ -60,6 +60,7 @@ Singleton {
property bool _hasLoaded: false
property bool _isReadOnly: false
property bool _hasUnsavedChanges: false
property bool _selfWrite: false
property var _loadedSettingsSnapshot: null
property var pluginSettings: ({})
property var builtInPluginSettings: ({})
@@ -1243,6 +1244,7 @@ Singleton {
function saveSettings() {
if (_loading || _parseError || !_hasLoaded)
return;
_selfWrite = true;
settingsFile.setText(JSON.stringify(Store.toJson(root), null, 2));
if (_isReadOnly)
_checkSettingsWritable();
@@ -2589,7 +2591,13 @@ Singleton {
blockWrites: true
atomicWrites: true
watchChanges: true
onFileChanged: settingsFileReloadDebounce.restart()
onFileChanged: {
if (_selfWrite) {
_selfWrite = false;
return;
}
settingsFileReloadDebounce.restart();
}
onLoaded: {
if (isGreeterMode)
return;

View File

@@ -81,6 +81,12 @@ function calculateNextIndex(flatModel, selectedFlatIndex, sectionId, viewMode, g
return bounds.start + newPosInSection;
}
var currentRow = Math.floor(posInSection / cols);
var lastRow = Math.floor((bounds.count - 1) / cols);
if (currentRow < lastRow) {
return bounds.start + bounds.count - 1;
}
var nextSection = findNextNonHeaderIndex(flatModel, bounds.end + 1);
return nextSection !== -1 ? nextSection : selectedFlatIndex;
}

View File

@@ -130,24 +130,17 @@ Item {
if (!entry || entry.isHeader)
return;
var rowIndex = _flatIndexToRowMap[index];
if (rowIndex === undefined || rowIndex >= _cumulativeHeights.length)
return;
var row = _visualRows[rowIndex];
if (!row)
if (rowIndex === undefined)
return;
var rowY = _cumulativeHeights[rowIndex];
var rowHeight = row.height;
var scrollY = mainListView.contentY - mainListView.originY;
var viewHeight = mainListView.height;
var headerH = stickyHeader.height;
mainListView.positionViewAtIndex(rowIndex, ListView.Contain);
if (rowY < scrollY + headerH) {
mainListView.contentY = Math.max(mainListView.originY, rowY - headerH + mainListView.originY);
return;
}
if (rowY + rowHeight > scrollY + viewHeight) {
mainListView.contentY = rowY + rowHeight - viewHeight + mainListView.originY;
if (stickyHeader.visible && rowIndex < _cumulativeHeights.length) {
var rowY = _cumulativeHeights[rowIndex];
var scrollY = mainListView.contentY - mainListView.originY;
if (rowY < scrollY + stickyHeader.height) {
mainListView.contentY = Math.max(mainListView.originY, rowY - stickyHeader.height + mainListView.originY);
}
}
}

View File

@@ -945,22 +945,31 @@ Column {
}
}
Component.onCompleted: {
Qt.callLater(() => {
const pluginComponent = PluginService.pluginWidgetComponents[pluginId];
if (pluginComponent) {
const instance = pluginComponent.createObject(null, {
"pluginId": pluginId,
"pluginService": PluginService,
"visible": false,
"width": 0,
"height": 0
});
if (instance) {
pluginInstance = instance;
}
function tryCreatePluginInstance() {
const pluginComponent = PluginService.pluginWidgetComponents[pluginId];
if (!pluginComponent)
return false;
try {
const instance = pluginComponent.createObject(null, {
"pluginId": pluginId,
"pluginService": PluginService,
"visible": false,
"width": 0,
"height": 0
});
if (instance) {
pluginInstance = instance;
return true;
}
});
} catch (e) {
console.warn("DragDropGrid: stale plugin component for", pluginId, "- reloading");
PluginService.reloadPlugin(pluginId);
}
return false;
}
Component.onCompleted: {
Qt.callLater(() => tryCreatePluginInstance());
}
Connections {
@@ -970,6 +979,11 @@ Column {
pluginInstance.loadPluginData();
}
}
function onPluginLoaded(loadedPluginId) {
if (loadedPluginId !== pluginId || pluginInstance)
return;
Qt.callLater(() => tryCreatePluginInstance());
}
}
Component.onDestruction: {

View File

@@ -13,8 +13,8 @@ Row {
property Item popoutContent: null
signal addWidget(string widgetId)
signal resetToDefault()
signal clearAll()
signal resetToDefault
signal clearAll
height: 48
spacing: Theme.spacingS
@@ -28,7 +28,7 @@ Row {
y: parent ? Math.round((parent.height - height) / 2) : 0
width: 400
height: 300
modal: true
modal: false
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
@@ -133,7 +133,7 @@ Row {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.addWidget(modelData.id)
root.addWidget(modelData.id);
}
}
}

View File

@@ -12,6 +12,7 @@ DankPopout {
id: root
layerNamespace: "dms:control-center"
fullHeightSurface: true
property string expandedSection: ""
property var triggerScreen: null

View File

@@ -216,14 +216,18 @@ QtObject {
}
const pluginComponent = PluginService.pluginWidgetComponents[plugin.id];
if (!pluginComponent || typeof pluginComponent.createObject !== 'function') {
if (!pluginComponent)
continue;
}
const tempInstance = pluginComponent.createObject(null);
if (!tempInstance) {
let tempInstance;
try {
tempInstance = pluginComponent.createObject(null);
} catch (e) {
PluginService.reloadPlugin(plugin.id);
continue;
}
if (!tempInstance)
continue;
const hasCCWidget = tempInstance.ccWidgetIcon && tempInstance.ccWidgetIcon.length > 0;
tempInstance.destroy();

View File

@@ -10,6 +10,45 @@ BasePill {
property bool isActive: false
readonly property bool hasUpdates: SystemUpdateService.updateCount > 0
readonly property bool isChecking: SystemUpdateService.isChecking
readonly property bool shouldHide: SettingsData.updaterHideWidget && !hasUpdates && !isChecking && !SystemUpdateService.hasError
opacity: shouldHide ? 0 : 1
states: [
State {
name: "hidden_horizontal"
when: root.shouldHide && !isVerticalOrientation
PropertyChanges {
target: root
width: 0
}
},
State {
name: "hidden_vertical"
when: root.shouldHide && isVerticalOrientation
PropertyChanges {
target: root
height: 0
}
}
]
transitions: [
Transition {
NumberAnimation {
properties: "width,height"
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
]
Behavior on opacity {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Ref {
service: SystemUpdateService

View File

@@ -924,8 +924,13 @@ Item {
return loadedIsUrgent;
return false;
}
property var loadedIconData: null
property bool loadedHasIcon: false
readonly property var loadedIconData: {
if (isPlaceholder) return null;
const name = modelData?.name;
if (!name) return null;
return SettingsData.getWorkspaceNameIcon(name);
}
readonly property bool loadedHasIcon: loadedIconData !== null
property var loadedIcons: []
readonly property int stableIconCount: {
@@ -986,8 +991,8 @@ Item {
readonly property real baseHeight: root.isVertical ? (isActive ? root.widgetHeight * 1.05 : root.widgetHeight * 0.7) : (SettingsData.showWorkspaceApps ? Math.max(widgetHeight * 0.7, root.appIconSize + Theme.spacingXS * 2) : widgetHeight * 0.5)
readonly property bool hasWorkspaceName: SettingsData.showWorkspaceName && modelData?.name && modelData.name !== ""
readonly property bool workspaceNamesEnabled: SettingsData.showWorkspaceName && (CompositorService.isNiri || CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle)
readonly property real contentImplicitWidth: (hasWorkspaceName || loadedHasIcon) ? (appIconsLoader.item?.contentWidth ?? 0) : 0
readonly property real contentImplicitHeight: (workspaceNamesEnabled || loadedHasIcon) ? (appIconsLoader.item?.contentHeight ?? 0) : 0
readonly property real contentImplicitWidth: hasWorkspaceName ? (appIconsLoader.item?.contentWidth ?? 0) : 0
readonly property real contentImplicitHeight: workspaceNamesEnabled ? (appIconsLoader.item?.contentHeight ?? 0) : 0
readonly property real iconsExtraWidth: {
if (!root.isVertical && SettingsData.showWorkspaceApps && stableIconCount > 0) {
@@ -1222,8 +1227,6 @@ Item {
onTriggered: {
if (isPlaceholder) {
delegateRoot.loadedWorkspaceData = null;
delegateRoot.loadedIconData = null;
delegateRoot.loadedHasIcon = false;
delegateRoot.loadedIcons = [];
delegateRoot.loadedIsUrgent = false;
return;
@@ -1249,13 +1252,6 @@ Item {
delegateRoot.loadedIsUrgent = wsData?.urgent ?? false;
}
var icData = null;
if (wsData?.name) {
icData = SettingsData.getWorkspaceNameIcon(wsData.name);
}
delegateRoot.loadedIconData = icData;
delegateRoot.loadedHasIcon = icData !== null;
if (SettingsData.showWorkspaceApps) {
if (CompositorService.isDwl || CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle) {
delegateRoot.loadedIcons = root.getWorkspaceIcons(modelData);
@@ -1420,7 +1416,7 @@ Item {
Item {
visible: loadedHasIcon && loadedIconData?.type === "icon"
width: wsIcon.width + (isActive && loadedIcons.length > 0 ? 4 : 0)
width: wsIcon.width
height: root.appIconSize
DankIcon {
@@ -1435,7 +1431,7 @@ Item {
Item {
visible: loadedHasIcon && loadedIconData?.type === "text"
width: wsText.implicitWidth + (isActive && loadedIcons.length > 0 ? 4 : 0)
width: wsText.implicitWidth
height: root.appIconSize
StyledText {
@@ -1449,14 +1445,14 @@ Item {
}
Item {
visible: (SettingsData.showWorkspaceIndex || SettingsData.showWorkspaceName) && !loadedHasIcon
width: wsIndexText.implicitWidth + (isActive && loadedIcons.length > 0 ? 4 : 0)
visible: ((SettingsData.showWorkspaceIndex || SettingsData.showWorkspaceName) && !loadedHasIcon) || (loadedHasIcon && SettingsData.showWorkspaceName && hasWorkspaceName)
width: wsIndexText.implicitWidth
height: root.appIconSize
StyledText {
id: wsIndexText
anchors.verticalCenter: parent.verticalCenter
text: root.getWorkspaceIndex(modelData, index)
text: loadedHasIcon ? (modelData?.name ?? "") : root.getWorkspaceIndex(modelData, index)
color: (isActive || isUrgent) ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium
font.pixelSize: Theme.barTextSize(barThickness, barConfig?.fontScale)
font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal
@@ -1574,9 +1570,9 @@ Item {
}
StyledText {
visible: (SettingsData.showWorkspaceIndex || SettingsData.showWorkspaceName) && !loadedHasIcon
visible: ((SettingsData.showWorkspaceIndex || SettingsData.showWorkspaceName) && !loadedHasIcon) || (loadedHasIcon && SettingsData.showWorkspaceName && hasWorkspaceName)
anchors.horizontalCenter: parent.horizontalCenter
text: root.getWorkspaceIndex(modelData, index)
text: loadedHasIcon ? (root.isVertical ? (modelData?.name ?? "").charAt(0) : (modelData?.name ?? "")) : root.getWorkspaceIndex(modelData, index)
color: (isActive || isUrgent) ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium
font.pixelSize: Theme.barTextSize(barThickness, barConfig?.fontScale)
font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal
@@ -1670,55 +1666,6 @@ Item {
}
}
// Loader for Custom Name Icon
Loader {
id: customIconLoader
anchors.fill: parent
active: !isPlaceholder && loadedHasIcon && loadedIconData.type === "icon" && !SettingsData.showWorkspaceApps
sourceComponent: Item {
DankIcon {
anchors.centerIn: parent
name: loadedIconData ? loadedIconData.value : "" // NULL CHECK
size: Theme.fontSizeSmall
color: isActive ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : Theme.surfaceTextMedium
weight: isActive && !isPlaceholder ? 500 : 400
}
}
}
// Loader for Custom Name Text
Loader {
id: customTextLoader
anchors.fill: parent
active: !isPlaceholder && loadedHasIcon && loadedIconData.type === "text" && !SettingsData.showWorkspaceApps
sourceComponent: Item {
StyledText {
anchors.centerIn: parent
text: loadedIconData ? loadedIconData.value : "" // NULL CHECK
color: isActive ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : Theme.surfaceTextMedium
font.pixelSize: Theme.barTextSize(barThickness, barConfig?.fontScale)
font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal
}
}
}
// Loader for Workspace Index
Loader {
id: indexLoader
anchors.fill: parent
active: (SettingsData.showWorkspaceIndex || SettingsData.showWorkspaceName) && !loadedHasIcon && !SettingsData.showWorkspaceApps
sourceComponent: Item {
StyledText {
anchors.centerIn: parent
text: {
return root.getWorkspaceIndex(modelData, index);
}
color: (isActive || isUrgent) ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium
font.pixelSize: Theme.barTextSize(barThickness, barConfig?.fontScale)
font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal
}
}
}
}
Component.onCompleted: updateAllData()

View File

@@ -278,7 +278,7 @@ Item {
Behavior on x {
enabled: !swipeDragHandler.active && delegateRoot.__delegateInitialized
NumberAnimation {
duration: Theme.shortDuration
duration: Theme.notificationExitDuration
easing.type: Theme.standardEasing
}
}
@@ -286,7 +286,7 @@ Item {
Behavior on opacity {
enabled: delegateRoot.__delegateInitialized
NumberAnimation {
duration: delegateRoot.__delegateInitialized ? Theme.shortDuration : 0
duration: delegateRoot.__delegateInitialized ? Theme.notificationExitDuration : 0
}
}
}

View File

@@ -257,7 +257,7 @@ DankListView {
target: delegateRoot
property: "swipeOffset"
to: 0
duration: Theme.shortDuration
duration: Theme.notificationExitDuration
easing.type: Easing.OutCubic
onStopped: NotificationService.dismissGroup(delegateRoot.modelData?.key || "")
}

View File

@@ -764,7 +764,7 @@ Rectangle {
target: expandedDelegateWrapper
property: "swipeOffset"
to: expandedDelegateWrapper.swipeOffset > 0 ? expandedDelegateWrapper.width : -expandedDelegateWrapper.width
duration: Theme.shortDuration
duration: Theme.notificationExitDuration
easing.type: Easing.OutCubic
onStopped: NotificationService.dismissNotification(modelData)
}

View File

@@ -7,6 +7,7 @@ DankPopout {
id: root
layerNamespace: "dms:notification-center-popout"
fullHeightSurface: true
property bool notificationHistoryVisible: false
property var triggerScreen: null
@@ -34,9 +35,9 @@ DankPopout {
popupWidth: triggerScreen ? Math.min(500, Math.max(380, triggerScreen.width - 48)) : 400
popupHeight: stablePopupHeight
positioning: ""
animationScaleCollapsed: 1.0
animationScaleCollapsed: 0.94
animationOffset: 0
suspendShadowWhileResizing: true
suspendShadowWhileResizing: false
screen: triggerScreen
shouldBeVisible: notificationHistoryVisible

View File

@@ -814,7 +814,7 @@ PanelWindow {
Behavior on swipeOffset {
enabled: !content.swipeActive && !content.swipeDismissing
NumberAnimation {
duration: Theme.shortDuration
duration: Theme.notificationExitDuration
easing.type: Theme.standardEasing
}
}
@@ -824,7 +824,7 @@ PanelWindow {
target: content
property: "swipeOffset"
to: isTopCenter ? -content.height : isBottomCenter ? content.height : (SettingsData.notificationPopupPosition === SettingsData.Position.Left || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom ? -content.width : content.width)
duration: Theme.shortDuration
duration: Theme.notificationExitDuration
easing.type: Easing.OutCubic
onStopped: {
NotificationService.dismissNotification(notificationData);

View File

@@ -16,7 +16,7 @@ Item {
property var cachedCursorThemes: SettingsData.availableCursorThemes
property var cachedMatugenSchemes: Theme.availableMatugenSchemes.map(option => option.label)
property var installedRegistryThemes: []
property var templateDetection: ({})
property var templateDetection: []
property var cursorIncludeStatus: ({
"exists": false,
@@ -106,9 +106,10 @@ Item {
}
function isTemplateDetected(templateId) {
if (!templateDetection || Object.keys(templateDetection).length === 0)
if (!templateDetection || templateDetection.length === 0)
return true;
return templateDetection[templateId] !== false;
var item = templateDetection.find(i => i.id === templateId);
return !item || item.detected !== false;
}
function getTemplateDescription(templateId, baseDescription) {
@@ -145,30 +146,17 @@ Item {
DMSService.listInstalledThemes();
if (PopoutService.pendingThemeInstall)
Qt.callLater(() => showThemeBrowser());
templateCheckProcess.running = true;
Proc.runCommand("template-check", ["dms", "matugen", "check"], (output, exitCode) => {
if (exitCode !== 0)
return;
try {
themeColorsTab.templateDetection = JSON.parse(output.trim());
} catch (e) {}
});
if (CompositorService.isNiri || CompositorService.isHyprland || CompositorService.isDwl)
checkCursorIncludeStatus();
}
Process {
id: templateCheckProcess
command: ["dms", "matugen", "check"]
running: false
stdout: StdioCollector {
onStreamFinished: {
try {
const results = JSON.parse(text);
const detection = {};
for (const item of results) {
detection[item.id] = item.detected;
}
themeColorsTab.templateDetection = detection;
} catch (e) {}
}
}
}
Connections {
target: DMSService
function onInstalledThemesReceived(themes) {

View File

@@ -11,7 +11,7 @@ Singleton {
id: root
readonly property string currentVersion: "1.4"
readonly property bool changelogEnabled: true
readonly property bool changelogEnabled: false
readonly property string configDir: Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation)) + "/DankMaterialShell"
readonly property string changelogMarkerPath: configDir + "/.changelog-" + currentVersion

View File

@@ -1 +1 @@
v1.4.0
v1.5-beta

View File

@@ -30,7 +30,10 @@ Item {
property var customKeyboardFocus: null
property bool backgroundInteractive: true
property bool contentHandlesKeys: false
property bool fullHeightSurface: false
property bool _resizeActive: false
property real _surfaceMarginLeft: 0
property real _surfaceW: 0
property real storedBarThickness: Theme.barHeight - 4
property real storedBarSpacing: 4
@@ -125,6 +128,10 @@ Item {
_lastOpenedScreen = screen;
shouldBeVisible = true;
if (useBackgroundWindow) {
_surfaceMarginLeft = alignedX - shadowBuffer;
_surfaceW = alignedWidth + shadowBuffer * 2;
}
Qt.callLater(() => {
if (shouldBeVisible && screen) {
if (useBackgroundWindow)
@@ -360,20 +367,38 @@ Item {
return WlrKeyboardFocus.Exclusive;
}
readonly property bool _fullHeight: useBackgroundWindow && root.fullHeightSurface
anchors {
left: true
top: true
right: !useBackgroundWindow
bottom: !useBackgroundWindow
bottom: _fullHeight || !useBackgroundWindow
}
WlrLayershell.margins {
left: useBackgroundWindow ? (root.alignedX - shadowBuffer) : 0
top: useBackgroundWindow ? (root.alignedY - shadowBuffer) : 0
left: useBackgroundWindow ? root._surfaceMarginLeft : 0
top: (useBackgroundWindow && !_fullHeight) ? (root.alignedY - shadowBuffer) : 0
}
implicitWidth: useBackgroundWindow ? (root.alignedWidth + (shadowBuffer * 2)) : 0
implicitHeight: useBackgroundWindow ? (root.alignedHeight + (shadowBuffer * 2)) : 0
implicitWidth: useBackgroundWindow ? root._surfaceW : 0
implicitHeight: (useBackgroundWindow && !_fullHeight) ? (root.alignedHeight + shadowBuffer * 2) : 0
mask: (useBackgroundWindow && _fullHeight) ? contentInputMask : null
Region {
id: contentInputMask
item: contentMaskRect
}
Item {
id: contentMaskRect
visible: false
x: contentContainer.x - root.shadowBuffer
y: contentContainer.y - root.shadowBuffer
width: root.alignedWidth + root.shadowBuffer * 2
height: root.alignedHeight + root.shadowBuffer * 2
}
MouseArea {
anchors.fill: parent
@@ -393,7 +418,7 @@ Item {
Item {
id: contentContainer
x: useBackgroundWindow ? shadowBuffer : root.alignedX
y: useBackgroundWindow ? shadowBuffer : root.alignedY
y: (useBackgroundWindow && !contentWindow._fullHeight) ? shadowBuffer : root.alignedY
width: root.alignedWidth
height: root.alignedHeight