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

Compare commits

..

10 Commits

Author SHA1 Message Date
bbedward db4de55338 popout: decouple shadow from content layer 2026-02-18 10:46:01 -05:00
bbedward 37ecbbbbde popout: disable layer after animation 2026-02-18 10:34:21 -05:00
purian23 d6a6d2a438 notifications: Maintain shadow during expansion 2026-02-18 10:34:21 -05:00
purian23 bf1c6eec74 notifications: Update initial popup height surfaces 2026-02-18 10:34:21 -05:00
bbedward 0ddae80584 running apps: fix scroll events being propagated fixes #1724 2026-02-18 10:34:21 -05:00
bbedward 5c96c03bfa matugen: make v4 detection more resilient 2026-02-18 09:57:35 -05:00
bbedward dfe36e47d8 process list: fix scaling with fonts fixes #1721 2026-02-18 09:57:35 -05:00
purian23 63e1b75e57 dankinstall: Fix Debian ARM64 detection 2026-02-18 09:57:35 -05:00
bbedward 29efdd8598 matugen: detect emacs directory fixes #1720 2026-02-18 09:57:35 -05:00
bbedward 34d03cf11b osd: optimize bindings 2026-02-18 09:57:35 -05:00
15 changed files with 415 additions and 334 deletions
+1 -1
View File
@@ -430,7 +430,7 @@ func (d *DebianDistribution) enableOBSRepos(ctx context.Context, obsPkgs []Packa
} }
// Add repository // Add repository
repoLine := fmt.Sprintf("deb [signed-by=%s, arch=%s] %s/ /", keyringPath, runtime.GOARCH, baseURL) repoLine := fmt.Sprintf("deb [signed-by=%s arch=%s] %s/ /", keyringPath, runtime.GOARCH, baseURL)
progressChan <- InstallProgressMsg{ progressChan <- InstallProgressMsg{
Phase: PhaseSystemPackages, Phase: PhaseSystemPackages,
+149 -57
View File
@@ -33,6 +33,7 @@ const (
TemplateKindTerminal TemplateKindTerminal
TemplateKindGTK TemplateKindGTK
TemplateKindVSCode TemplateKindVSCode
TemplateKindEmacs
) )
type TemplateDef struct { type TemplateDef struct {
@@ -65,7 +66,7 @@ var templateRegistry = []TemplateDef{
{ID: "dgop", Commands: []string{"dgop"}, ConfigFile: "dgop.toml"}, {ID: "dgop", Commands: []string{"dgop"}, ConfigFile: "dgop.toml"},
{ID: "kcolorscheme", ConfigFile: "kcolorscheme.toml", RunUnconditionally: true}, {ID: "kcolorscheme", ConfigFile: "kcolorscheme.toml", RunUnconditionally: true},
{ID: "vscode", Kind: TemplateKindVSCode}, {ID: "vscode", Kind: TemplateKindVSCode},
{ID: "emacs", Commands: []string{"emacs"}, ConfigFile: "emacs.toml"}, {ID: "emacs", Commands: []string{"emacs"}, ConfigFile: "emacs.toml", Kind: TemplateKindEmacs},
} }
func (c *ColorMode) GTKTheme() string { func (c *ColorMode) GTKTheme() string {
@@ -78,7 +79,8 @@ func (c *ColorMode) GTKTheme() string {
} }
var ( var (
matugenVersionOnce sync.Once matugenVersionMu sync.Mutex
matugenVersionOK bool
matugenSupportsCOE bool matugenSupportsCOE bool
matugenIsV4 bool matugenIsV4 bool
) )
@@ -334,6 +336,10 @@ output_path = '%s'
appendVSCodeConfig(cfgFile, "cursor", filepath.Join(homeDir, ".cursor/extensions"), opts.ShellDir) appendVSCodeConfig(cfgFile, "cursor", filepath.Join(homeDir, ".cursor/extensions"), opts.ShellDir)
appendVSCodeConfig(cfgFile, "windsurf", filepath.Join(homeDir, ".windsurf/extensions"), opts.ShellDir) appendVSCodeConfig(cfgFile, "windsurf", filepath.Join(homeDir, ".windsurf/extensions"), opts.ShellDir)
appendVSCodeConfig(cfgFile, "vscode-insiders", filepath.Join(homeDir, ".vscode-insiders/extensions"), opts.ShellDir) appendVSCodeConfig(cfgFile, "vscode-insiders", filepath.Join(homeDir, ".vscode-insiders/extensions"), opts.ShellDir)
case TemplateKindEmacs:
if utils.EmacsConfigDir() != "" {
appendConfig(opts, cfgFile, tmpl.Commands, tmpl.Flatpaks, tmpl.ConfigFile)
}
default: default:
appendConfig(opts, cfgFile, tmpl.Commands, tmpl.Flatpaks, tmpl.ConfigFile) appendConfig(opts, cfgFile, tmpl.Commands, tmpl.Flatpaks, tmpl.ConfigFile)
} }
@@ -491,6 +497,9 @@ func substituteVars(content, shellDir string) string {
result = strings.ReplaceAll(result, "'CONFIG_DIR/", "'"+utils.XDGConfigHome()+"/") result = strings.ReplaceAll(result, "'CONFIG_DIR/", "'"+utils.XDGConfigHome()+"/")
result = strings.ReplaceAll(result, "'DATA_DIR/", "'"+utils.XDGDataHome()+"/") result = strings.ReplaceAll(result, "'DATA_DIR/", "'"+utils.XDGDataHome()+"/")
result = strings.ReplaceAll(result, "'CACHE_DIR/", "'"+utils.XDGCacheHome()+"/") result = strings.ReplaceAll(result, "'CACHE_DIR/", "'"+utils.XDGCacheHome()+"/")
if emacsDir := utils.EmacsConfigDir(); emacsDir != "" {
result = strings.ReplaceAll(result, "'EMACS_DIR/", "'"+emacsDir+"/")
}
return result return result
} }
@@ -511,79 +520,160 @@ func extractTOMLSection(content, startMarker, endMarker string) string {
return content[startIdx : startIdx+endIdx] return content[startIdx : startIdx+endIdx]
} }
func checkMatugenVersion() { type matugenFlags struct {
matugenVersionOnce.Do(func() { supportsCOE bool
cmd := exec.Command("matugen", "--version") isV4 bool
output, err := cmd.Output()
if err != nil {
return
}
versionStr := strings.TrimSpace(string(output))
versionStr = strings.TrimPrefix(versionStr, "matugen ")
parts := strings.Split(versionStr, ".")
if len(parts) < 2 {
return
}
major, err := strconv.Atoi(parts[0])
if err != nil {
return
}
minor, err := strconv.Atoi(parts[1])
if err != nil {
return
}
matugenSupportsCOE = major > 3 || (major == 3 && minor >= 1)
matugenIsV4 = major >= 4
if matugenSupportsCOE {
log.Infof("Matugen %s supports --continue-on-error", versionStr)
}
if matugenIsV4 {
log.Infof("Matugen %s: using v4 flags", versionStr)
}
})
} }
func runMatugen(args []string) error { func detectMatugenVersion() (matugenFlags, error) {
checkMatugenVersion() matugenVersionMu.Lock()
defer matugenVersionMu.Unlock()
if matugenVersionOK {
return matugenFlags{matugenSupportsCOE, matugenIsV4}, nil
}
return detectMatugenVersionLocked()
}
func redetectMatugenVersion(old matugenFlags) (matugenFlags, bool) {
matugenVersionMu.Lock()
defer matugenVersionMu.Unlock()
matugenVersionOK = false
flags, err := detectMatugenVersionLocked()
if err != nil {
return old, false
}
changed := flags.supportsCOE != old.supportsCOE || flags.isV4 != old.isV4
return flags, changed
}
func detectMatugenVersionLocked() (matugenFlags, error) {
cmd := exec.Command("matugen", "--version")
output, err := cmd.Output()
if err != nil {
return matugenFlags{}, fmt.Errorf("failed to get matugen version: %w", err)
}
versionStr := strings.TrimSpace(string(output))
versionStr = strings.TrimPrefix(versionStr, "matugen ")
parts := strings.Split(versionStr, ".")
if len(parts) < 2 {
return matugenFlags{}, fmt.Errorf("unexpected matugen version format: %q", versionStr)
}
major, err := strconv.Atoi(parts[0])
if err != nil {
return matugenFlags{}, fmt.Errorf("failed to parse matugen major version %q: %w", parts[0], err)
}
minor, err := strconv.Atoi(parts[1])
if err != nil {
return matugenFlags{}, fmt.Errorf("failed to parse matugen minor version %q: %w", parts[1], err)
}
matugenSupportsCOE = major > 3 || (major == 3 && minor >= 1)
matugenIsV4 = major >= 4
matugenVersionOK = true
if matugenSupportsCOE { if matugenSupportsCOE {
args = append([]string{"--continue-on-error"}, args...) log.Infof("Matugen %s supports --continue-on-error", versionStr)
} }
if matugenIsV4 { if matugenIsV4 {
log.Infof("Matugen %s: using v4 flags", versionStr)
}
return matugenFlags{matugenSupportsCOE, matugenIsV4}, nil
}
func buildMatugenArgs(baseArgs []string, flags matugenFlags) []string {
args := make([]string, 0, len(baseArgs)+4)
if flags.supportsCOE {
args = append(args, "--continue-on-error")
}
args = append(args, baseArgs...)
if flags.isV4 {
args = append(args, "--source-color-index", "0") args = append(args, "--source-color-index", "0")
} }
return args
}
func runMatugen(baseArgs []string) error {
flags, err := detectMatugenVersion()
if err != nil {
return err
}
args := buildMatugenArgs(baseArgs, flags)
cmd := exec.Command("matugen", args...) cmd := exec.Command("matugen", args...)
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
return cmd.Run() runErr := cmd.Run()
if runErr == nil {
return nil
}
log.Warnf("Matugen failed (v4=%v): %v", flags.isV4, runErr)
newFlags, changed := redetectMatugenVersion(flags)
if !changed {
return runErr
}
log.Warnf("Matugen version changed (v4: %v -> %v), retrying", flags.isV4, newFlags.isV4)
args = buildMatugenArgs(baseArgs, newFlags)
retryCmd := exec.Command("matugen", args...)
retryCmd.Stdout = os.Stdout
retryCmd.Stderr = os.Stderr
return retryCmd.Run()
} }
func runMatugenDryRun(opts *Options) (string, error) { func runMatugenDryRun(opts *Options) (string, error) {
checkMatugenVersion() flags, err := detectMatugenVersion()
var args []string
switch opts.Kind {
case "hex":
args = []string{"color", "hex", opts.Value}
default:
args = []string{opts.Kind, opts.Value}
}
args = append(args, "-m", "dark", "-t", opts.MatugenType, "--json", "hex", "--dry-run")
if matugenIsV4 {
args = append(args, "--source-color-index", "0", "--old-json-output")
}
cmd := exec.Command("matugen", args...)
output, err := cmd.Output()
if err != nil { if err != nil {
return "", err return "", err
} }
output, dryErr := execDryRun(opts, flags)
if dryErr == nil {
return output, nil
}
log.Warnf("Matugen dry-run failed (v4=%v): %v", flags.isV4, dryErr)
newFlags, changed := redetectMatugenVersion(flags)
if !changed {
return "", dryErr
}
log.Warnf("Matugen version changed (v4: %v -> %v), retrying dry-run", flags.isV4, newFlags.isV4)
return execDryRun(opts, newFlags)
}
func execDryRun(opts *Options, flags matugenFlags) (string, error) {
var baseArgs []string
switch opts.Kind {
case "hex":
baseArgs = []string{"color", "hex", opts.Value}
default:
baseArgs = []string{opts.Kind, opts.Value}
}
baseArgs = append(baseArgs, "-m", "dark", "-t", opts.MatugenType, "--json", "hex", "--dry-run")
if flags.isV4 {
baseArgs = append(baseArgs, "--source-color-index", "0", "--old-json-output")
}
cmd := exec.Command("matugen", baseArgs...)
var stderr strings.Builder
cmd.Stderr = &stderr
output, err := cmd.Output()
if err != nil {
if stderr.Len() > 0 {
return "", fmt.Errorf("matugen %v failed (v4=%v): %s", baseArgs, flags.isV4, strings.TrimSpace(stderr.String()))
}
return "", fmt.Errorf("matugen %v failed (v4=%v): %w", baseArgs, flags.isV4, err)
}
return strings.ReplaceAll(string(output), "\n", ""), nil return strings.ReplaceAll(string(output), "\n", ""), nil
} }
@@ -819,6 +909,8 @@ func CheckTemplates(checker utils.AppChecker) []TemplateCheck {
detected = true detected = true
case tmpl.Kind == TemplateKindVSCode: case tmpl.Kind == TemplateKindVSCode:
detected = checkVSCodeExtension(homeDir) detected = checkVSCodeExtension(homeDir)
case tmpl.Kind == TemplateKindEmacs:
detected = appExists(checker, tmpl.Commands, tmpl.Flatpaks) && utils.EmacsConfigDir() != ""
default: default:
detected = appExists(checker, tmpl.Commands, tmpl.Flatpaks) detected = appExists(checker, tmpl.Commands, tmpl.Flatpaks)
} }
+16
View File
@@ -38,6 +38,22 @@ func XDGConfigHome() string {
return filepath.Join(home, ".config") return filepath.Join(home, ".config")
} }
func EmacsConfigDir() string {
home, _ := os.UserHomeDir()
emacsD := filepath.Join(home, ".emacs.d")
if info, err := os.Stat(emacsD); err == nil && info.IsDir() {
return emacsD
}
xdgEmacs := filepath.Join(XDGConfigHome(), "emacs")
if info, err := os.Stat(xdgEmacs); err == nil && info.IsDir() {
return xdgEmacs
}
return ""
}
func ExpandPath(path string) (string, error) { func ExpandPath(path string) (string, error) {
expanded := os.ExpandEnv(path) expanded := os.ExpandEnv(path)
expanded = filepath.Clean(expanded) expanded = filepath.Clean(expanded)
+17 -14
View File
@@ -83,9 +83,9 @@ FloatingWindow {
objectName: "processListModal" objectName: "processListModal"
title: I18n.tr("System Monitor", "sysmon window title") title: I18n.tr("System Monitor", "sysmon window title")
minimumSize: Qt.size(750, 550) minimumSize: Qt.size(Math.min(Math.round(Theme.fontSizeMedium * 48), Screen.width), Math.min(Math.round(Theme.fontSizeMedium * 34), Screen.height))
implicitWidth: 1000 implicitWidth: Math.round(Theme.fontSizeMedium * 71)
implicitHeight: 720 implicitHeight: Math.round(Theme.fontSizeMedium * 51)
color: Theme.surfaceContainer color: Theme.surfaceContainer
visible: false visible: false
@@ -236,7 +236,7 @@ FloatingWindow {
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 48 Layout.preferredHeight: Math.round(Theme.fontSizeMedium * 3.4)
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
@@ -293,10 +293,10 @@ FloatingWindow {
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 52 Layout.preferredHeight: Math.round(Theme.fontSizeMedium * 3.7)
Layout.leftMargin: Theme.spacingL Layout.leftMargin: Theme.spacingL
Layout.rightMargin: Theme.spacingL Layout.rightMargin: Theme.spacingL
spacing: Theme.spacingL spacing: Theme.spacingM
Row { Row {
spacing: 2 spacing: 2
@@ -322,14 +322,15 @@ FloatingWindow {
] ]
Rectangle { Rectangle {
width: 120 width: tabRowContent.implicitWidth + Theme.spacingM * 2
height: 44 height: Math.round(Theme.fontSizeMedium * 3.1)
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: currentTab === index ? Theme.primaryPressed : (tabMouseArea.containsMouse ? Theme.primaryHoverLight : "transparent") color: currentTab === index ? Theme.primaryPressed : (tabMouseArea.containsMouse ? Theme.primaryHoverLight : "transparent")
border.color: currentTab === index ? Theme.primary : "transparent" border.color: currentTab === index ? Theme.primary : "transparent"
border.width: currentTab === index ? 1 : 0 border.width: currentTab === index ? 1 : 0
Row { Row {
id: tabRowContent
anchors.centerIn: parent anchors.centerIn: parent
spacing: Theme.spacingXS spacing: Theme.spacingXS
@@ -373,11 +374,13 @@ FloatingWindow {
DankButtonGroup { DankButtonGroup {
id: processFilterGroup id: processFilterGroup
Layout.minimumWidth: implicitWidth + 8
model: [I18n.tr("All"), I18n.tr("User"), I18n.tr("System")] model: [I18n.tr("All"), I18n.tr("User"), I18n.tr("System")]
currentIndex: 0 currentIndex: 0
checkEnabled: false checkEnabled: false
buttonHeight: 36 buttonHeight: Math.round(Theme.fontSizeSmall * 2.6)
minButtonWidth: 0
buttonPadding: Theme.spacingS
textSize: Theme.fontSizeSmall
visible: currentTab === 0 visible: currentTab === 0
onSelectionChanged: (index, selected) => { onSelectionChanged: (index, selected) => {
if (!selected) if (!selected)
@@ -400,9 +403,9 @@ FloatingWindow {
DankTextField { DankTextField {
id: searchField id: searchField
Layout.fillWidth: true Layout.fillWidth: true
Layout.maximumWidth: 250 Layout.maximumWidth: Math.round(Theme.fontSizeMedium * 18)
Layout.minimumWidth: 120 Layout.minimumWidth: Theme.fontSizeMedium * 4
Layout.preferredHeight: 40 Layout.preferredHeight: Math.round(Theme.fontSizeMedium * 2.8)
placeholderText: I18n.tr("Search processes...", "process search placeholder") placeholderText: I18n.tr("Search processes...", "process search placeholder")
leftIconName: "search" leftIconName: "search"
showClearButton: true showClearButton: true
@@ -470,7 +473,7 @@ FloatingWindow {
Rectangle { Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 32 Layout.preferredHeight: Math.round(Theme.fontSizeSmall * 2.7)
Layout.leftMargin: Theme.spacingL Layout.leftMargin: Theme.spacingL
Layout.rightMargin: Theme.spacingL Layout.rightMargin: Theme.spacingL
Layout.bottomMargin: Theme.spacingM Layout.bottomMargin: Theme.spacingM
@@ -155,6 +155,7 @@ BasePill {
property real touchpadThreshold: 500 property real touchpadThreshold: 500
onWheel: function (wheelEvent) { onWheel: function (wheelEvent) {
wheelEvent.accepted = true;
const deltaY = wheelEvent.angleDelta.y; const deltaY = wheelEvent.angleDelta.y;
const isMouseWheel = Math.abs(deltaY) >= 120 && (Math.abs(deltaY) % 120) === 0; const isMouseWheel = Math.abs(deltaY) >= 120 && (Math.abs(deltaY) % 120) === 0;
@@ -22,6 +22,8 @@ PanelWindow {
property bool _isDestroying: false property bool _isDestroying: false
property bool _finalized: false property bool _finalized: false
property real _lastReportedAlignedHeight: -1 property real _lastReportedAlignedHeight: -1
property real _storedTopMargin: 0
property real _storedBottomMargin: 0
readonly property string clearText: I18n.tr("Dismiss") readonly property string clearText: I18n.tr("Dismiss")
property bool descriptionExpanded: false property bool descriptionExpanded: false
readonly property bool hasExpandableBody: (notificationData?.htmlBody || "").replace(/<[^>]*>/g, "").trim().length > 0 readonly property bool hasExpandableBody: (notificationData?.htmlBody || "").replace(/<[^>]*>/g, "").trim().length > 0
@@ -146,6 +148,8 @@ PanelWindow {
} }
Component.onCompleted: { Component.onCompleted: {
_lastReportedAlignedHeight = Theme.px(implicitHeight, dpr); _lastReportedAlignedHeight = Theme.px(implicitHeight, dpr);
_storedTopMargin = getTopMargin();
_storedBottomMargin = getBottomMargin();
if (SettingsData.notificationPopupPrivacyMode) if (SettingsData.notificationPopupPrivacyMode)
descriptionExpanded = false; descriptionExpanded = false;
if (hasValidData) { if (hasValidData) {
@@ -179,14 +183,30 @@ PanelWindow {
property bool isBottomCenter: SettingsData.notificationPopupPosition === SettingsData.Position.BottomCenter property bool isBottomCenter: SettingsData.notificationPopupPosition === SettingsData.Position.BottomCenter
property bool isCenterPosition: isTopCenter || isBottomCenter property bool isCenterPosition: isTopCenter || isBottomCenter
anchors.top: isTopCenter || SettingsData.notificationPopupPosition === SettingsData.Position.Top || SettingsData.notificationPopupPosition === SettingsData.Position.Left anchors.top: true
anchors.bottom: isBottomCenter || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom || SettingsData.notificationPopupPosition === SettingsData.Position.Right anchors.bottom: true
anchors.left: SettingsData.notificationPopupPosition === SettingsData.Position.Left || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom anchors.left: SettingsData.notificationPopupPosition === SettingsData.Position.Left || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom
anchors.right: SettingsData.notificationPopupPosition === SettingsData.Position.Top || SettingsData.notificationPopupPosition === SettingsData.Position.Right anchors.right: SettingsData.notificationPopupPosition === SettingsData.Position.Top || SettingsData.notificationPopupPosition === SettingsData.Position.Right
mask: contentInputMask
Region {
id: contentInputMask
item: contentMaskRect
}
Item {
id: contentMaskRect
visible: false
x: content.x
y: content.y
width: alignedWidth
height: alignedHeight
}
margins { margins {
top: getTopMargin() top: _storedTopMargin
bottom: getBottomMargin() bottom: _storedBottomMargin
left: getLeftMargin() left: getLeftMargin()
right: getRightMargin() right: getRightMargin()
} }
@@ -263,7 +283,14 @@ PanelWindow {
id: content id: content
x: Theme.snap((win.width - alignedWidth) / 2, dpr) x: Theme.snap((win.width - alignedWidth) / 2, dpr)
y: Theme.snap((win.height - alignedHeight) / 2, dpr) y: {
const isTop = isTopCenter || SettingsData.notificationPopupPosition === SettingsData.Position.Top || SettingsData.notificationPopupPosition === SettingsData.Position.Left;
if (isTop) {
return Theme.snap(screenY, dpr);
} else {
return Theme.snap(win.height - alignedHeight - screenY, dpr);
}
}
width: alignedWidth width: alignedWidth
height: alignedHeight height: alignedHeight
visible: !win._finalized visible: !win._finalized
@@ -311,7 +338,7 @@ PanelWindow {
id: bgShadowLayer id: bgShadowLayer
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.snap(4, win.dpr) anchors.margins: Theme.snap(4, win.dpr)
layer.enabled: !win._isDestroying && win.screenValid && !implicitHeightAnim.running layer.enabled: !win._isDestroying && win.screenValid
layer.smooth: false layer.smooth: false
layer.textureSize: Qt.size(Math.round(width * win.dpr), Math.round(height * win.dpr)) layer.textureSize: Qt.size(Math.round(width * win.dpr), Math.round(height * win.dpr))
layer.textureMirroring: ShaderEffectSource.MirrorVertically layer.textureMirroring: ShaderEffectSource.MirrorVertically
+29 -50
View File
@@ -7,9 +7,10 @@ DankOSD {
id: root id: root
readonly property bool useVertical: isVerticalLayout readonly property bool useVertical: isVerticalLayout
property int targetBrightness: { property int _displayBrightness: 0
DisplayService.brightnessVersion;
return DisplayService.brightnessLevel; function _syncBrightness() {
_displayBrightness = DisplayService.brightnessLevel;
} }
osdWidth: useVertical ? (40 + Theme.spacingS * 2) : Math.min(260, Screen.width - Theme.spacingM * 2) osdWidth: useVertical ? (40 + Theme.spacingS * 2) : Math.min(260, Screen.width - Theme.spacingM * 2)
@@ -20,9 +21,9 @@ DankOSD {
Connections { Connections {
target: DisplayService target: DisplayService
function onBrightnessChanged(showOsd) { function onBrightnessChanged(showOsd) {
if (showOsd && SettingsData.osdBrightnessEnabled) { root._syncBrightness();
if (showOsd && SettingsData.osdBrightnessEnabled)
root.show(); root.show();
}
} }
} }
@@ -53,13 +54,11 @@ DankOSD {
anchors.centerIn: parent anchors.centerIn: parent
name: { name: {
const deviceInfo = DisplayService.getCurrentDeviceInfo(); const deviceInfo = DisplayService.getCurrentDeviceInfo();
if (!deviceInfo || deviceInfo.class === "backlight" || deviceInfo.class === "ddc") { if (!deviceInfo || deviceInfo.class === "backlight" || deviceInfo.class === "ddc")
return "brightness_medium"; return "brightness_medium";
} else if (deviceInfo.name.includes("kbd")) { if (deviceInfo.name.includes("kbd"))
return "keyboard"; return "keyboard";
} else { return "lightbulb";
return "lightbulb";
}
} }
size: Theme.iconSize size: Theme.iconSize
color: Theme.primary color: Theme.primary
@@ -77,20 +76,16 @@ DankOSD {
const deviceInfo = DisplayService.getCurrentDeviceInfo(); const deviceInfo = DisplayService.getCurrentDeviceInfo();
if (!deviceInfo) if (!deviceInfo)
return 1; return 1;
const isExponential = SessionData.getBrightnessExponential(deviceInfo.id); if (SessionData.getBrightnessExponential(deviceInfo.id))
if (isExponential) {
return 1; return 1;
}
return (deviceInfo.class === "backlight" || deviceInfo.class === "ddc") ? 1 : 0; return (deviceInfo.class === "backlight" || deviceInfo.class === "ddc") ? 1 : 0;
} }
maximum: { maximum: {
const deviceInfo = DisplayService.getCurrentDeviceInfo(); const deviceInfo = DisplayService.getCurrentDeviceInfo();
if (!deviceInfo) if (!deviceInfo)
return 100; return 100;
const isExponential = SessionData.getBrightnessExponential(deviceInfo.id); if (SessionData.getBrightnessExponential(deviceInfo.id))
if (isExponential) {
return 100; return 100;
}
return deviceInfo.displayMax || 100; return deviceInfo.displayMax || 100;
} }
enabled: DisplayService.brightnessAvailable enabled: DisplayService.brightnessAvailable
@@ -99,28 +94,24 @@ DankOSD {
const deviceInfo = DisplayService.getCurrentDeviceInfo(); const deviceInfo = DisplayService.getCurrentDeviceInfo();
if (!deviceInfo) if (!deviceInfo)
return "%"; return "%";
const isExponential = SessionData.getBrightnessExponential(deviceInfo.id); if (SessionData.getBrightnessExponential(deviceInfo.id))
if (isExponential) {
return "%"; return "%";
}
return deviceInfo.class === "ddc" ? "" : "%"; return deviceInfo.class === "ddc" ? "" : "%";
} }
thumbOutlineColor: Theme.surfaceContainer thumbOutlineColor: Theme.surfaceContainer
alwaysShowValue: SettingsData.osdAlwaysShowValue alwaysShowValue: SettingsData.osdAlwaysShowValue
onSliderValueChanged: newValue => { onSliderValueChanged: newValue => {
if (DisplayService.brightnessAvailable) { if (!DisplayService.brightnessAvailable)
DisplayService.setBrightness(newValue, DisplayService.lastIpcDevice, true); return;
resetHideTimer(); DisplayService.setBrightness(newValue, DisplayService.lastIpcDevice, true);
} resetHideTimer();
} }
onContainsMouseChanged: { onContainsMouseChanged: setChildHovered(containsMouse)
setChildHovered(containsMouse);
}
Binding on value { Binding on value {
value: root.targetBrightness value: root._displayBrightness
when: !brightnessSlider.isDragging when: !brightnessSlider.isDragging
} }
} }
@@ -146,13 +137,11 @@ DankOSD {
anchors.centerIn: parent anchors.centerIn: parent
name: { name: {
const deviceInfo = DisplayService.getCurrentDeviceInfo(); const deviceInfo = DisplayService.getCurrentDeviceInfo();
if (!deviceInfo || deviceInfo.class === "backlight" || deviceInfo.class === "ddc") { if (!deviceInfo || deviceInfo.class === "backlight" || deviceInfo.class === "ddc")
return "brightness_medium"; return "brightness_medium";
} else if (deviceInfo.name.includes("kbd")) { if (deviceInfo.name.includes("kbd"))
return "keyboard"; return "keyboard";
} else { return "lightbulb";
return "lightbulb";
}
} }
size: Theme.iconSize size: Theme.iconSize
color: Theme.primary color: Theme.primary
@@ -170,7 +159,7 @@ DankOSD {
property int value: 50 property int value: 50
Binding on value { Binding on value {
value: root.targetBrightness value: root._displayBrightness
when: !vertSlider.dragging when: !vertSlider.dragging
} }
@@ -178,8 +167,7 @@ DankOSD {
const deviceInfo = DisplayService.getCurrentDeviceInfo(); const deviceInfo = DisplayService.getCurrentDeviceInfo();
if (!deviceInfo) if (!deviceInfo)
return 1; return 1;
const isExponential = SessionData.getBrightnessExponential(deviceInfo.id); if (SessionData.getBrightnessExponential(deviceInfo.id))
if (isExponential)
return 1; return 1;
return (deviceInfo.class === "backlight" || deviceInfo.class === "ddc") ? 1 : 0; return (deviceInfo.class === "backlight" || deviceInfo.class === "ddc") ? 1 : 0;
} }
@@ -188,8 +176,7 @@ DankOSD {
const deviceInfo = DisplayService.getCurrentDeviceInfo(); const deviceInfo = DisplayService.getCurrentDeviceInfo();
if (!deviceInfo) if (!deviceInfo)
return 100; return 100;
const isExponential = SessionData.getBrightnessExponential(deviceInfo.id); if (SessionData.getBrightnessExponential(deviceInfo.id))
if (isExponential)
return 100; return 100;
return deviceInfo.displayMax || 100; return deviceInfo.displayMax || 100;
} }
@@ -240,33 +227,25 @@ DankOSD {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onContainsMouseChanged: { onContainsMouseChanged: setChildHovered(containsMouse)
setChildHovered(containsMouse);
}
onPressed: mouse => { onPressed: mouse => {
vertSlider.dragging = true; vertSlider.dragging = true;
updateBrightness(mouse); updateBrightness(mouse);
} }
onReleased: { onReleased: vertSlider.dragging = false
vertSlider.dragging = false;
}
onPositionChanged: mouse => { onPositionChanged: mouse => {
if (pressed) { if (pressed)
updateBrightness(mouse); updateBrightness(mouse);
}
} }
onClicked: mouse => { onClicked: mouse => updateBrightness(mouse)
updateBrightness(mouse);
}
function updateBrightness(mouse) { function updateBrightness(mouse) {
if (!DisplayService.brightnessAvailable) { if (!DisplayService.brightnessAvailable)
return; return;
}
const ratio = 1.0 - (mouse.y / height); const ratio = 1.0 - (mouse.y / height);
const newValue = Math.round(vertSlider.minimum + ratio * (vertSlider.maximum - vertSlider.minimum)); const newValue = Math.round(vertSlider.minimum + ratio * (vertSlider.maximum - vertSlider.minimum));
vertSlider.value = newValue; vertSlider.value = newValue;
+32 -65
View File
@@ -8,13 +8,20 @@ DankOSD {
readonly property bool useVertical: isVerticalLayout readonly property bool useVertical: isVerticalLayout
readonly property var player: MprisController.activePlayer readonly property var player: MprisController.activePlayer
readonly property int currentVolume: player ? Math.min(100, Math.round(player.volume * 100)) : 0
readonly property bool volumeSupported: player?.volumeSupported ?? false readonly property bool volumeSupported: player?.volumeSupported ?? false
property bool _suppressNewPlayer: false property bool _suppressNewPlayer: false
property int _displayVolume: 0
function _syncVolume() {
if (!player)
return;
_displayVolume = Math.min(100, Math.round(player.volume * 100));
}
onPlayerChanged: { onPlayerChanged: {
_suppressNewPlayer = true; _suppressNewPlayer = true;
_suppressTimer.restart(); _suppressTimer.restart();
_syncVolume();
} }
Timer { Timer {
@@ -37,25 +44,25 @@ DankOSD {
} }
function toggleMute() { function toggleMute() {
if (player) { if (!player)
player.volume = player.volume > 0 ? 0 : 1; return;
} player.volume = player.volume > 0 ? 0 : 1;
} }
function setVolume(volumePercent) { function setVolume(volumePercent) {
if (player) { if (!player)
player.volume = volumePercent / 100; return;
resetHideTimer(); player.volume = volumePercent / 100;
} resetHideTimer();
} }
Connections { Connections {
target: player target: player
function onVolumeChanged() { function onVolumeChanged() {
if (SettingsData.osdMediaVolumeEnabled && volumeSupported && !_suppressNewPlayer) { root._syncVolume();
if (SettingsData.osdMediaVolumeEnabled && volumeSupported && !_suppressNewPlayer)
root.show(); root.show();
}
} }
} }
@@ -96,9 +103,7 @@ DankOSD {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: toggleMute() onClicked: toggleMute()
onContainsMouseChanged: { onContainsMouseChanged: setChildHovered(containsMouse || volumeSlider.containsMouse)
setChildHovered(containsMouse || volumeSlider.containsMouse);
}
} }
} }
@@ -115,29 +120,21 @@ DankOSD {
showValue: true showValue: true
unit: "%" unit: "%"
thumbOutlineColor: Theme.surfaceContainer thumbOutlineColor: Theme.surfaceContainer
valueOverride: currentVolume valueOverride: root._displayVolume
alwaysShowValue: SettingsData.osdAlwaysShowValue alwaysShowValue: SettingsData.osdAlwaysShowValue
Component.onCompleted: { Component.onCompleted: {
value = currentVolume; root._syncVolume();
value = root._displayVolume;
} }
onSliderValueChanged: newValue => { onSliderValueChanged: newValue => setVolume(newValue)
setVolume(newValue);
}
onContainsMouseChanged: { onContainsMouseChanged: setChildHovered(containsMouse || muteButton.containsMouse)
setChildHovered(containsMouse || muteButton.containsMouse);
}
Connections { Binding on value {
target: player value: root._displayVolume
when: !volumeSlider.pressed
function onVolumeChanged() {
if (volumeSlider && !volumeSlider.pressed) {
volumeSlider.value = currentVolume;
}
}
} }
} }
} }
@@ -172,9 +169,7 @@ DankOSD {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: toggleMute() onClicked: toggleMute()
onContainsMouseChanged: { onContainsMouseChanged: setChildHovered(containsMouse || vertSliderArea.containsMouse)
setChildHovered(containsMouse || vertSliderArea.containsMouse);
}
} }
} }
@@ -186,7 +181,7 @@ DankOSD {
y: gap * 2 + Theme.iconSize y: gap * 2 + Theme.iconSize
property bool dragging: false property bool dragging: false
property int value: currentVolume property int value: root._displayVolume
Rectangle { Rectangle {
id: vertTrack id: vertTrack
@@ -231,28 +226,21 @@ DankOSD {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onContainsMouseChanged: { onContainsMouseChanged: setChildHovered(containsMouse || muteButtonVert.containsMouse)
setChildHovered(containsMouse || muteButtonVert.containsMouse);
}
onPressed: mouse => { onPressed: mouse => {
vertSlider.dragging = true; vertSlider.dragging = true;
updateVolume(mouse); updateVolume(mouse);
} }
onReleased: { onReleased: vertSlider.dragging = false
vertSlider.dragging = false;
}
onPositionChanged: mouse => { onPositionChanged: mouse => {
if (pressed) { if (pressed)
updateVolume(mouse); updateVolume(mouse);
}
} }
onClicked: mouse => { onClicked: mouse => updateVolume(mouse)
updateVolume(mouse);
}
function updateVolume(mouse) { function updateVolume(mouse) {
const ratio = 1.0 - (mouse.y / height); const ratio = 1.0 - (mouse.y / height);
@@ -260,16 +248,6 @@ DankOSD {
setVolume(volume); setVolume(volume);
} }
} }
Connections {
target: player
function onVolumeChanged() {
if (!vertSlider.dragging) {
vertSlider.value = currentVolume;
}
}
}
} }
StyledText { StyledText {
@@ -283,15 +261,4 @@ DankOSD {
} }
} }
} }
onOsdShown: {
if (player && contentLoader.item && contentLoader.item.item) {
if (!useVertical) {
const slider = contentLoader.item.item.children[0].children[1];
if (slider && slider.value !== undefined) {
slider.value = currentVolume;
}
}
}
}
} }
+46 -85
View File
@@ -7,6 +7,13 @@ DankOSD {
id: root id: root
readonly property bool useVertical: isVerticalLayout readonly property bool useVertical: isVerticalLayout
property int _displayVolume: 0
function _syncVolume() {
if (!AudioService.sink?.audio)
return;
_displayVolume = Math.min(AudioService.sinkMaxVolume, Math.round(AudioService.sink.audio.volume * 100));
}
osdWidth: useVertical ? (40 + Theme.spacingS * 2) : Math.min(260, Screen.width - Theme.spacingM * 2) osdWidth: useVertical ? (40 + Theme.spacingS * 2) : Math.min(260, Screen.width - Theme.spacingM * 2)
osdHeight: useVertical ? Math.min(260, Screen.height - Theme.spacingM * 2) : (40 + Theme.spacingS * 2) osdHeight: useVertical ? Math.min(260, Screen.height - Theme.spacingM * 2) : (40 + Theme.spacingS * 2)
@@ -14,18 +21,17 @@ DankOSD {
enableMouseInteraction: true enableMouseInteraction: true
Connections { Connections {
target: AudioService.sink && AudioService.sink.audio ? AudioService.sink.audio : null target: AudioService.sink?.audio ?? null
function onVolumeChanged() { function onVolumeChanged() {
if (SettingsData.osdVolumeEnabled) { root._syncVolume();
if (SettingsData.osdVolumeEnabled)
root.show(); root.show();
}
} }
function onMutedChanged() { function onMutedChanged() {
if (SettingsData.osdVolumeEnabled) { if (SettingsData.osdVolumeEnabled)
root.show(); root.show();
}
} }
} }
@@ -33,9 +39,9 @@ DankOSD {
target: AudioService target: AudioService
function onSinkChanged() { function onSinkChanged() {
if (root.shouldBeVisible && SettingsData.osdVolumeEnabled) { root._syncVolume();
if (root.shouldBeVisible && SettingsData.osdVolumeEnabled)
root.show(); root.show();
}
} }
} }
@@ -64,7 +70,7 @@ DankOSD {
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent
name: AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.muted ? "volume_off" : "volume_up" name: AudioService.sink?.audio?.muted ? "volume_off" : "volume_up"
size: Theme.iconSize size: Theme.iconSize
color: muteButton.containsMouse ? Theme.primary : Theme.surfaceText color: muteButton.containsMouse ? Theme.primary : Theme.surfaceText
} }
@@ -75,60 +81,45 @@ DankOSD {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: AudioService.toggleMute()
AudioService.toggleMute(); onContainsMouseChanged: setChildHovered(containsMouse || volumeSlider.containsMouse)
}
onContainsMouseChanged: {
setChildHovered(containsMouse || volumeSlider.containsMouse);
}
} }
} }
DankSlider { DankSlider {
id: volumeSlider id: volumeSlider
readonly property real actualVolumePercent: AudioService.sink && AudioService.sink.audio ? Math.round(AudioService.sink.audio.volume * 100) : 0
readonly property real displayPercent: actualVolumePercent
width: parent.width - Theme.iconSize - parent.gap * 3 width: parent.width - Theme.iconSize - parent.gap * 3
height: 40 height: 40
x: parent.gap * 2 + Theme.iconSize x: parent.gap * 2 + Theme.iconSize
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
minimum: 0 minimum: 0
maximum: AudioService.sinkMaxVolume maximum: AudioService.sinkMaxVolume
enabled: AudioService.sink && AudioService.sink.audio enabled: AudioService.sink?.audio
showValue: true showValue: true
unit: "%" unit: "%"
thumbOutlineColor: Theme.surfaceContainer thumbOutlineColor: Theme.surfaceContainer
valueOverride: displayPercent valueOverride: root._displayVolume
alwaysShowValue: SettingsData.osdAlwaysShowValue alwaysShowValue: SettingsData.osdAlwaysShowValue
Component.onCompleted: { Component.onCompleted: {
if (AudioService.sink && AudioService.sink.audio) { root._syncVolume();
value = Math.min(AudioService.sinkMaxVolume, Math.round(AudioService.sink.audio.volume * 100)); value = root._displayVolume;
}
} }
onSliderValueChanged: newValue => { onSliderValueChanged: newValue => {
if (AudioService.sink && AudioService.sink.audio) { if (!AudioService.sink?.audio)
SessionData.suppressOSDTemporarily(); return;
AudioService.sink.audio.volume = newValue / 100; SessionData.suppressOSDTemporarily();
resetHideTimer(); AudioService.sink.audio.volume = newValue / 100;
} resetHideTimer();
} }
onContainsMouseChanged: { onContainsMouseChanged: setChildHovered(containsMouse || muteButton.containsMouse)
setChildHovered(containsMouse || muteButton.containsMouse);
}
Connections { Binding on value {
target: AudioService.sink && AudioService.sink.audio ? AudioService.sink.audio : null value: root._displayVolume
when: !volumeSlider.pressed
function onVolumeChanged() {
if (volumeSlider && !volumeSlider.pressed) {
volumeSlider.value = Math.min(AudioService.sinkMaxVolume, Math.round(AudioService.sink.audio.volume * 100));
}
}
} }
} }
} }
@@ -151,7 +142,7 @@ DankOSD {
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent
name: AudioService.sink && AudioService.sink.audio && AudioService.sink.audio.muted ? "volume_off" : "volume_up" name: AudioService.sink?.audio?.muted ? "volume_off" : "volume_up"
size: Theme.iconSize size: Theme.iconSize
color: muteButtonVert.containsMouse ? Theme.primary : Theme.surfaceText color: muteButtonVert.containsMouse ? Theme.primary : Theme.surfaceText
} }
@@ -162,12 +153,8 @@ DankOSD {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: AudioService.toggleMute()
AudioService.toggleMute(); onContainsMouseChanged: setChildHovered(containsMouse || vertSliderArea.containsMouse)
}
onContainsMouseChanged: {
setChildHovered(containsMouse || vertSliderArea.containsMouse);
}
} }
} }
@@ -179,7 +166,7 @@ DankOSD {
y: gap * 2 + Theme.iconSize y: gap * 2 + Theme.iconSize
property bool dragging: false property bool dragging: false
property int value: AudioService.sink && AudioService.sink.audio ? Math.min(AudioService.sinkMaxVolume, Math.round(AudioService.sink.audio.volume * 100)) : 0 property int value: root._displayVolume
Rectangle { Rectangle {
id: vertTrack id: vertTrack
@@ -220,50 +207,35 @@ DankOSD {
id: vertSliderArea id: vertSliderArea
anchors.fill: parent anchors.fill: parent
anchors.margins: -12 anchors.margins: -12
enabled: AudioService.sink && AudioService.sink.audio enabled: AudioService.sink?.audio
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onContainsMouseChanged: { onContainsMouseChanged: setChildHovered(containsMouse || muteButtonVert.containsMouse)
setChildHovered(containsMouse || muteButtonVert.containsMouse);
}
onPressed: mouse => { onPressed: mouse => {
vertSlider.dragging = true; vertSlider.dragging = true;
updateVolume(mouse); updateVolume(mouse);
} }
onReleased: { onReleased: vertSlider.dragging = false
vertSlider.dragging = false;
}
onPositionChanged: mouse => { onPositionChanged: mouse => {
if (pressed) { if (pressed)
updateVolume(mouse); updateVolume(mouse);
}
} }
onClicked: mouse => { onClicked: mouse => updateVolume(mouse)
updateVolume(mouse);
}
function updateVolume(mouse) { function updateVolume(mouse) {
if (AudioService.sink && AudioService.sink.audio) { if (!AudioService.sink?.audio)
const maxVol = AudioService.sinkMaxVolume; return;
const ratio = 1.0 - (mouse.y / height); const maxVol = AudioService.sinkMaxVolume;
const volume = Math.max(0, Math.min(maxVol, Math.round(ratio * maxVol))); const ratio = 1.0 - (mouse.y / height);
SessionData.suppressOSDTemporarily(); const volume = Math.max(0, Math.min(maxVol, Math.round(ratio * maxVol)));
AudioService.sink.audio.volume = volume / 100; SessionData.suppressOSDTemporarily();
resetHideTimer(); AudioService.sink.audio.volume = volume / 100;
} resetHideTimer();
}
}
Connections {
target: AudioService.sink && AudioService.sink.audio ? AudioService.sink.audio : null
function onVolumeChanged() {
vertSlider.value = Math.min(AudioService.sinkMaxVolume, Math.round(AudioService.sink.audio.volume * 100));
} }
} }
} }
@@ -279,15 +251,4 @@ DankOSD {
} }
} }
} }
onOsdShown: {
if (AudioService.sink && AudioService.sink.audio && contentLoader.item && contentLoader.item.item) {
if (!useVertical) {
const slider = contentLoader.item.item.children[0].children[1];
if (slider && slider.value !== undefined) {
slider.value = Math.min(AudioService.sinkMaxVolume, Math.round(AudioService.sink.audio.volume * 100));
}
}
}
}
} }
+24 -25
View File
@@ -18,36 +18,41 @@ Column {
property bool isInitialized: false property bool isInitialized: false
function loadValue() { function loadValue() {
const settings = findSettings() const settings = findSettings();
if (settings && settings.pluginService) { if (settings && settings.pluginService) {
const loadedValue = settings.loadValue(settingKey, defaultValue) const loadedValue = settings.loadValue(settingKey, defaultValue);
value = loadedValue if (textField.activeFocus && isInitialized)
textField.text = loadedValue return;
isInitialized = true value = loadedValue;
textField.text = loadedValue;
isInitialized = true;
} }
} }
Component.onCompleted: { Component.onCompleted: {
Qt.callLater(loadValue) Qt.callLater(loadValue);
} }
onValueChanged: { function commit() {
if (!isInitialized) return if (!isInitialized)
const settings = findSettings() return;
if (settings) { if (textField.text === value)
settings.saveValue(settingKey, value) return;
} value = textField.text;
const settings = findSettings();
if (settings)
settings.saveValue(settingKey, value);
} }
function findSettings() { function findSettings() {
let item = parent let item = parent;
while (item) { while (item) {
if (item.saveValue !== undefined && item.loadValue !== undefined) { if (item.saveValue !== undefined && item.loadValue !== undefined) {
return item return item;
} }
item = item.parent item = item.parent;
} }
return null return null;
} }
StyledText { StyledText {
@@ -70,16 +75,10 @@ Column {
id: textField id: textField
width: parent.width width: parent.width
placeholderText: root.placeholder placeholderText: root.placeholder
onTextEdited: { onEditingFinished: root.commit()
root.value = text
}
onEditingFinished: {
root.value = text
}
onActiveFocusChanged: { onActiveFocusChanged: {
if (!activeFocus) { if (!activeFocus)
root.value = text root.commit();
}
} }
} }
} }
@@ -26,8 +26,8 @@ DankPopout {
open(); open();
} }
popupWidth: 650 popupWidth: Math.round(Theme.fontSizeMedium * 46)
popupHeight: 550 popupHeight: Math.round(Theme.fontSizeMedium * 39)
triggerWidth: 55 triggerWidth: 55
positioning: "" positioning: ""
screen: triggerScreen screen: triggerScreen
@@ -151,11 +151,13 @@ DankPopout {
DankButtonGroup { DankButtonGroup {
id: processFilterGroup id: processFilterGroup
Layout.minimumWidth: implicitWidth + 8 Layout.minimumWidth: implicitWidth
model: [I18n.tr("All"), I18n.tr("User"), I18n.tr("System")] model: [I18n.tr("All"), I18n.tr("User"), I18n.tr("System")]
currentIndex: 0 currentIndex: 0
checkEnabled: false checkEnabled: false
buttonHeight: Math.round(Theme.fontSizeMedium * 2.2) buttonHeight: Math.round(Theme.fontSizeSmall * 2.4)
minButtonWidth: 0
buttonPadding: Theme.spacingM
textSize: Theme.fontSizeSmall textSize: Theme.fontSizeSmall
onSelectionChanged: (index, selected) => { onSelectionChanged: (index, selected) => {
if (!selected) if (!selected)
@@ -177,7 +179,8 @@ DankPopout {
DankTextField { DankTextField {
id: searchField id: searchField
Layout.preferredWidth: Theme.fontSizeMedium * 14 Layout.fillWidth: true
Layout.minimumWidth: Theme.fontSizeMedium * 8
Layout.preferredHeight: Theme.fontSizeMedium * 2.5 Layout.preferredHeight: Theme.fontSizeMedium * 2.5
placeholderText: I18n.tr("Search...") placeholderText: I18n.tr("Search...")
leftIconName: "search" leftIconName: "search"
+14 -2
View File
@@ -375,8 +375,20 @@ FocusScope {
if (!plugin || !PluginService.isPluginLoaded(pluginId)) if (!plugin || !PluginService.isPluginLoaded(pluginId))
return; return;
var isLauncher = plugin.type === "launcher" || (plugin.capabilities && plugin.capabilities.includes("launcher")); var isLauncher = plugin.type === "launcher" || (plugin.capabilities && plugin.capabilities.includes("launcher"));
if (isLauncher) if (isLauncher) {
PluginService.reloadPlugin(pluginId); pluginReloadTimer.pendingPluginId = pluginId;
pluginReloadTimer.restart();
}
}
}
Timer {
id: pluginReloadTimer
property string pendingPluginId: ""
interval: 500
onTriggered: {
if (pendingPluginId)
PluginService.reloadPlugin(pendingPluginId);
} }
} }
+5 -1
View File
@@ -28,6 +28,10 @@ PanelWindow {
function show() { function show() {
if (SessionData.suppressOSD) if (SessionData.suppressOSD)
return; return;
if (shouldBeVisible) {
hideTimer.restart();
return;
}
OSDManager.showOSD(root); OSDManager.showOSD(root);
closeTimer.stop(); closeTimer.stop();
shouldBeVisible = true; shouldBeVisible = true;
@@ -257,7 +261,7 @@ PanelWindow {
property real shadowSpreadPx: 0 property real shadowSpreadPx: 0
property real shadowBaseAlpha: 0.60 property real shadowBaseAlpha: 0.60
readonly property real popupSurfaceAlpha: SettingsData.popupTransparency readonly property real popupSurfaceAlpha: SettingsData.popupTransparency
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha * osdContainer.opacity)) readonly property real effectiveShadowAlpha: shouldBeVisible ? Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha)) : 0
Rectangle { Rectangle {
id: background id: background
+39 -22
View File
@@ -469,6 +469,44 @@ Item {
} }
} }
Rectangle {
id: shadowSource
anchors.centerIn: parent
width: parent.width
height: parent.height
radius: Theme.cornerRadius
color: "black"
visible: false
opacity: contentWrapper.opacity
scale: contentWrapper.scale
x: contentWrapper.x
y: contentWrapper.y
property real shadowBlurPx: 10
property real shadowSpreadPx: 0
property real shadowBaseAlpha: 0.60
readonly property real popupSurfaceAlpha: SettingsData.popupTransparency
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
readonly property int blurMax: 64
layer.enabled: Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !(root.suspendShadowWhileResizing && root._resizeActive)
layer.smooth: false
layer.effect: MultiEffect {
id: shadowFx
autoPaddingEnabled: true
shadowEnabled: true
blurEnabled: false
maskEnabled: false
shadowBlur: Math.max(0, Math.min(1, shadowSource.shadowBlurPx / shadowSource.blurMax))
shadowScale: 1 + (2 * shadowSource.shadowSpreadPx) / Math.max(1, Math.min(shadowSource.width, shadowSource.height))
shadowColor: {
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest;
return Theme.withAlpha(baseColor, shadowSource.effectiveShadowAlpha);
}
}
}
Item { Item {
id: contentWrapper id: contentWrapper
anchors.centerIn: parent anchors.centerIn: parent
@@ -480,31 +518,10 @@ Item {
x: Theme.snap(contentContainer.animX + (parent.width - width) * (1 - contentContainer.scaleValue) * 0.5, root.dpr) x: Theme.snap(contentContainer.animX + (parent.width - width) * (1 - contentContainer.scaleValue) * 0.5, root.dpr)
y: Theme.snap(contentContainer.animY + (parent.height - height) * (1 - contentContainer.scaleValue) * 0.5, root.dpr) y: Theme.snap(contentContainer.animY + (parent.height - height) * (1 - contentContainer.scaleValue) * 0.5, root.dpr)
property real shadowBlurPx: 10 layer.enabled: contentWrapper.opacity < 1
property real shadowSpreadPx: 0
property real shadowBaseAlpha: 0.60
readonly property real popupSurfaceAlpha: SettingsData.popupTransparency
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
readonly property int blurMax: 64
layer.enabled: Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !(root.suspendShadowWhileResizing && root._resizeActive)
layer.smooth: false layer.smooth: false
layer.textureSize: root.dpr > 1 ? Qt.size(Math.ceil(width * root.dpr), Math.ceil(height * root.dpr)) : Qt.size(0, 0) layer.textureSize: root.dpr > 1 ? Qt.size(Math.ceil(width * root.dpr), Math.ceil(height * root.dpr)) : Qt.size(0, 0)
layer.effect: MultiEffect {
id: shadowFx
autoPaddingEnabled: true
shadowEnabled: true
blurEnabled: false
maskEnabled: false
shadowBlur: Math.max(0, Math.min(1, contentWrapper.shadowBlurPx / contentWrapper.blurMax))
shadowScale: 1 + (2 * contentWrapper.shadowSpreadPx) / Math.max(1, Math.min(contentWrapper.width, contentWrapper.height))
shadowColor: {
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest;
return Theme.withAlpha(baseColor, contentWrapper.effectiveShadowAlpha);
}
}
Behavior on opacity { Behavior on opacity {
NumberAnimation { NumberAnimation {
duration: animationDuration duration: animationDuration
+1 -1
View File
@@ -1,3 +1,3 @@
[templates.dmsemacs] [templates.dmsemacs]
input_path = 'SHELL_DIR/matugen/templates/dank-emacs.el' input_path = 'SHELL_DIR/matugen/templates/dank-emacs.el'
output_path = "~/.emacs.d/themes/dank-emacs-theme.el" output_path = 'EMACS_DIR/themes/dank-emacs-theme.el'