mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-05-03 02:52:07 -04:00
Compare commits
14 Commits
d084114149
...
v1.4.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db4de55338 | ||
|
|
37ecbbbbde | ||
|
|
d6a6d2a438 | ||
|
|
bf1c6eec74 | ||
|
|
0ddae80584 | ||
|
|
5c96c03bfa | ||
|
|
dfe36e47d8 | ||
|
|
63e1b75e57 | ||
|
|
29efdd8598 | ||
|
|
34d03cf11b | ||
|
|
c339389d44 | ||
|
|
af5f6eb656 | ||
|
|
a6d28e2553 | ||
|
|
6213267908 |
@@ -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
|
||||
|
||||
@@ -430,7 +430,7 @@ func (d *DebianDistribution) enableOBSRepos(ctx context.Context, obsPkgs []Packa
|
||||
}
|
||||
|
||||
// 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{
|
||||
Phase: PhaseSystemPackages,
|
||||
|
||||
@@ -33,6 +33,7 @@ const (
|
||||
TemplateKindTerminal
|
||||
TemplateKindGTK
|
||||
TemplateKindVSCode
|
||||
TemplateKindEmacs
|
||||
)
|
||||
|
||||
type TemplateDef struct {
|
||||
@@ -65,7 +66,7 @@ var templateRegistry = []TemplateDef{
|
||||
{ID: "dgop", Commands: []string{"dgop"}, ConfigFile: "dgop.toml"},
|
||||
{ID: "kcolorscheme", ConfigFile: "kcolorscheme.toml", RunUnconditionally: true},
|
||||
{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 {
|
||||
@@ -78,7 +79,8 @@ func (c *ColorMode) GTKTheme() string {
|
||||
}
|
||||
|
||||
var (
|
||||
matugenVersionOnce sync.Once
|
||||
matugenVersionMu sync.Mutex
|
||||
matugenVersionOK bool
|
||||
matugenSupportsCOE bool
|
||||
matugenIsV4 bool
|
||||
)
|
||||
@@ -334,6 +336,10 @@ output_path = '%s'
|
||||
appendVSCodeConfig(cfgFile, "cursor", filepath.Join(homeDir, ".cursor/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)
|
||||
case TemplateKindEmacs:
|
||||
if utils.EmacsConfigDir() != "" {
|
||||
appendConfig(opts, cfgFile, tmpl.Commands, tmpl.Flatpaks, tmpl.ConfigFile)
|
||||
}
|
||||
default:
|
||||
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, "'DATA_DIR/", "'"+utils.XDGDataHome()+"/")
|
||||
result = strings.ReplaceAll(result, "'CACHE_DIR/", "'"+utils.XDGCacheHome()+"/")
|
||||
if emacsDir := utils.EmacsConfigDir(); emacsDir != "" {
|
||||
result = strings.ReplaceAll(result, "'EMACS_DIR/", "'"+emacsDir+"/")
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -511,79 +520,160 @@ func extractTOMLSection(content, startMarker, endMarker string) string {
|
||||
return content[startIdx : startIdx+endIdx]
|
||||
}
|
||||
|
||||
func checkMatugenVersion() {
|
||||
matugenVersionOnce.Do(func() {
|
||||
cmd := exec.Command("matugen", "--version")
|
||||
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)
|
||||
}
|
||||
})
|
||||
type matugenFlags struct {
|
||||
supportsCOE bool
|
||||
isV4 bool
|
||||
}
|
||||
|
||||
func runMatugen(args []string) error {
|
||||
checkMatugenVersion()
|
||||
func detectMatugenVersion() (matugenFlags, error) {
|
||||
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 {
|
||||
args = append([]string{"--continue-on-error"}, args...)
|
||||
log.Infof("Matugen %s supports --continue-on-error", versionStr)
|
||||
}
|
||||
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")
|
||||
}
|
||||
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.Stdout = os.Stdout
|
||||
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) {
|
||||
checkMatugenVersion()
|
||||
|
||||
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()
|
||||
flags, err := detectMatugenVersion()
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -819,6 +909,8 @@ func CheckTemplates(checker utils.AppChecker) []TemplateCheck {
|
||||
detected = true
|
||||
case tmpl.Kind == TemplateKindVSCode:
|
||||
detected = checkVSCodeExtension(homeDir)
|
||||
case tmpl.Kind == TemplateKindEmacs:
|
||||
detected = appExists(checker, tmpl.Commands, tmpl.Flatpaks) && utils.EmacsConfigDir() != ""
|
||||
default:
|
||||
detected = appExists(checker, tmpl.Commands, tmpl.Flatpaks)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,22 @@ func XDGConfigHome() string {
|
||||
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) {
|
||||
expanded := os.ExpandEnv(path)
|
||||
expanded = filepath.Clean(expanded)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -83,9 +83,9 @@ FloatingWindow {
|
||||
|
||||
objectName: "processListModal"
|
||||
title: I18n.tr("System Monitor", "sysmon window title")
|
||||
minimumSize: Qt.size(750, 550)
|
||||
implicitWidth: 1000
|
||||
implicitHeight: 720
|
||||
minimumSize: Qt.size(Math.min(Math.round(Theme.fontSizeMedium * 48), Screen.width), Math.min(Math.round(Theme.fontSizeMedium * 34), Screen.height))
|
||||
implicitWidth: Math.round(Theme.fontSizeMedium * 71)
|
||||
implicitHeight: Math.round(Theme.fontSizeMedium * 51)
|
||||
color: Theme.surfaceContainer
|
||||
visible: false
|
||||
|
||||
@@ -236,7 +236,7 @@ FloatingWindow {
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 48
|
||||
Layout.preferredHeight: Math.round(Theme.fontSizeMedium * 3.4)
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
@@ -293,10 +293,10 @@ FloatingWindow {
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 52
|
||||
Layout.preferredHeight: Math.round(Theme.fontSizeMedium * 3.7)
|
||||
Layout.leftMargin: Theme.spacingL
|
||||
Layout.rightMargin: Theme.spacingL
|
||||
spacing: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Row {
|
||||
spacing: 2
|
||||
@@ -322,14 +322,15 @@ FloatingWindow {
|
||||
]
|
||||
|
||||
Rectangle {
|
||||
width: 120
|
||||
height: 44
|
||||
width: tabRowContent.implicitWidth + Theme.spacingM * 2
|
||||
height: Math.round(Theme.fontSizeMedium * 3.1)
|
||||
radius: Theme.cornerRadius
|
||||
color: currentTab === index ? Theme.primaryPressed : (tabMouseArea.containsMouse ? Theme.primaryHoverLight : "transparent")
|
||||
border.color: currentTab === index ? Theme.primary : "transparent"
|
||||
border.width: currentTab === index ? 1 : 0
|
||||
|
||||
Row {
|
||||
id: tabRowContent
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
@@ -373,11 +374,13 @@ FloatingWindow {
|
||||
|
||||
DankButtonGroup {
|
||||
id: processFilterGroup
|
||||
Layout.minimumWidth: implicitWidth + 8
|
||||
model: [I18n.tr("All"), I18n.tr("User"), I18n.tr("System")]
|
||||
currentIndex: 0
|
||||
checkEnabled: false
|
||||
buttonHeight: 36
|
||||
buttonHeight: Math.round(Theme.fontSizeSmall * 2.6)
|
||||
minButtonWidth: 0
|
||||
buttonPadding: Theme.spacingS
|
||||
textSize: Theme.fontSizeSmall
|
||||
visible: currentTab === 0
|
||||
onSelectionChanged: (index, selected) => {
|
||||
if (!selected)
|
||||
@@ -400,9 +403,9 @@ FloatingWindow {
|
||||
DankTextField {
|
||||
id: searchField
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: 250
|
||||
Layout.minimumWidth: 120
|
||||
Layout.preferredHeight: 40
|
||||
Layout.maximumWidth: Math.round(Theme.fontSizeMedium * 18)
|
||||
Layout.minimumWidth: Theme.fontSizeMedium * 4
|
||||
Layout.preferredHeight: Math.round(Theme.fontSizeMedium * 2.8)
|
||||
placeholderText: I18n.tr("Search processes...", "process search placeholder")
|
||||
leftIconName: "search"
|
||||
showClearButton: true
|
||||
@@ -470,7 +473,7 @@ FloatingWindow {
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 32
|
||||
Layout.preferredHeight: Math.round(Theme.fontSizeSmall * 2.7)
|
||||
Layout.leftMargin: Theme.spacingL
|
||||
Layout.rightMargin: Theme.spacingL
|
||||
Layout.bottomMargin: Theme.spacingM
|
||||
|
||||
@@ -155,6 +155,7 @@ BasePill {
|
||||
property real touchpadThreshold: 500
|
||||
|
||||
onWheel: function (wheelEvent) {
|
||||
wheelEvent.accepted = true;
|
||||
const deltaY = wheelEvent.angleDelta.y;
|
||||
const isMouseWheel = Math.abs(deltaY) >= 120 && (Math.abs(deltaY) % 120) === 0;
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 || "")
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -35,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
|
||||
|
||||
@@ -22,6 +22,8 @@ PanelWindow {
|
||||
property bool _isDestroying: false
|
||||
property bool _finalized: false
|
||||
property real _lastReportedAlignedHeight: -1
|
||||
property real _storedTopMargin: 0
|
||||
property real _storedBottomMargin: 0
|
||||
readonly property string clearText: I18n.tr("Dismiss")
|
||||
property bool descriptionExpanded: false
|
||||
readonly property bool hasExpandableBody: (notificationData?.htmlBody || "").replace(/<[^>]*>/g, "").trim().length > 0
|
||||
@@ -146,6 +148,8 @@ PanelWindow {
|
||||
}
|
||||
Component.onCompleted: {
|
||||
_lastReportedAlignedHeight = Theme.px(implicitHeight, dpr);
|
||||
_storedTopMargin = getTopMargin();
|
||||
_storedBottomMargin = getBottomMargin();
|
||||
if (SettingsData.notificationPopupPrivacyMode)
|
||||
descriptionExpanded = false;
|
||||
if (hasValidData) {
|
||||
@@ -179,14 +183,30 @@ PanelWindow {
|
||||
property bool isBottomCenter: SettingsData.notificationPopupPosition === SettingsData.Position.BottomCenter
|
||||
property bool isCenterPosition: isTopCenter || isBottomCenter
|
||||
|
||||
anchors.top: isTopCenter || SettingsData.notificationPopupPosition === SettingsData.Position.Top || SettingsData.notificationPopupPosition === SettingsData.Position.Left
|
||||
anchors.bottom: isBottomCenter || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom || SettingsData.notificationPopupPosition === SettingsData.Position.Right
|
||||
anchors.top: true
|
||||
anchors.bottom: true
|
||||
anchors.left: SettingsData.notificationPopupPosition === SettingsData.Position.Left || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom
|
||||
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 {
|
||||
top: getTopMargin()
|
||||
bottom: getBottomMargin()
|
||||
top: _storedTopMargin
|
||||
bottom: _storedBottomMargin
|
||||
left: getLeftMargin()
|
||||
right: getRightMargin()
|
||||
}
|
||||
@@ -263,7 +283,14 @@ PanelWindow {
|
||||
id: content
|
||||
|
||||
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
|
||||
height: alignedHeight
|
||||
visible: !win._finalized
|
||||
@@ -311,7 +338,7 @@ PanelWindow {
|
||||
id: bgShadowLayer
|
||||
anchors.fill: parent
|
||||
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.textureSize: Qt.size(Math.round(width * win.dpr), Math.round(height * win.dpr))
|
||||
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
||||
@@ -814,7 +841,7 @@ PanelWindow {
|
||||
Behavior on swipeOffset {
|
||||
enabled: !content.swipeActive && !content.swipeDismissing
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
duration: Theme.notificationExitDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
@@ -824,7 +851,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);
|
||||
|
||||
@@ -7,9 +7,10 @@ DankOSD {
|
||||
id: root
|
||||
|
||||
readonly property bool useVertical: isVerticalLayout
|
||||
property int targetBrightness: {
|
||||
DisplayService.brightnessVersion;
|
||||
return DisplayService.brightnessLevel;
|
||||
property int _displayBrightness: 0
|
||||
|
||||
function _syncBrightness() {
|
||||
_displayBrightness = DisplayService.brightnessLevel;
|
||||
}
|
||||
|
||||
osdWidth: useVertical ? (40 + Theme.spacingS * 2) : Math.min(260, Screen.width - Theme.spacingM * 2)
|
||||
@@ -20,9 +21,9 @@ DankOSD {
|
||||
Connections {
|
||||
target: DisplayService
|
||||
function onBrightnessChanged(showOsd) {
|
||||
if (showOsd && SettingsData.osdBrightnessEnabled) {
|
||||
root._syncBrightness();
|
||||
if (showOsd && SettingsData.osdBrightnessEnabled)
|
||||
root.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,13 +54,11 @@ DankOSD {
|
||||
anchors.centerIn: parent
|
||||
name: {
|
||||
const deviceInfo = DisplayService.getCurrentDeviceInfo();
|
||||
if (!deviceInfo || deviceInfo.class === "backlight" || deviceInfo.class === "ddc") {
|
||||
if (!deviceInfo || deviceInfo.class === "backlight" || deviceInfo.class === "ddc")
|
||||
return "brightness_medium";
|
||||
} else if (deviceInfo.name.includes("kbd")) {
|
||||
if (deviceInfo.name.includes("kbd"))
|
||||
return "keyboard";
|
||||
} else {
|
||||
return "lightbulb";
|
||||
}
|
||||
return "lightbulb";
|
||||
}
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
@@ -77,20 +76,16 @@ DankOSD {
|
||||
const deviceInfo = DisplayService.getCurrentDeviceInfo();
|
||||
if (!deviceInfo)
|
||||
return 1;
|
||||
const isExponential = SessionData.getBrightnessExponential(deviceInfo.id);
|
||||
if (isExponential) {
|
||||
if (SessionData.getBrightnessExponential(deviceInfo.id))
|
||||
return 1;
|
||||
}
|
||||
return (deviceInfo.class === "backlight" || deviceInfo.class === "ddc") ? 1 : 0;
|
||||
}
|
||||
maximum: {
|
||||
const deviceInfo = DisplayService.getCurrentDeviceInfo();
|
||||
if (!deviceInfo)
|
||||
return 100;
|
||||
const isExponential = SessionData.getBrightnessExponential(deviceInfo.id);
|
||||
if (isExponential) {
|
||||
if (SessionData.getBrightnessExponential(deviceInfo.id))
|
||||
return 100;
|
||||
}
|
||||
return deviceInfo.displayMax || 100;
|
||||
}
|
||||
enabled: DisplayService.brightnessAvailable
|
||||
@@ -99,28 +94,24 @@ DankOSD {
|
||||
const deviceInfo = DisplayService.getCurrentDeviceInfo();
|
||||
if (!deviceInfo)
|
||||
return "%";
|
||||
const isExponential = SessionData.getBrightnessExponential(deviceInfo.id);
|
||||
if (isExponential) {
|
||||
if (SessionData.getBrightnessExponential(deviceInfo.id))
|
||||
return "%";
|
||||
}
|
||||
return deviceInfo.class === "ddc" ? "" : "%";
|
||||
}
|
||||
thumbOutlineColor: Theme.surfaceContainer
|
||||
alwaysShowValue: SettingsData.osdAlwaysShowValue
|
||||
|
||||
onSliderValueChanged: newValue => {
|
||||
if (DisplayService.brightnessAvailable) {
|
||||
DisplayService.setBrightness(newValue, DisplayService.lastIpcDevice, true);
|
||||
resetHideTimer();
|
||||
}
|
||||
if (!DisplayService.brightnessAvailable)
|
||||
return;
|
||||
DisplayService.setBrightness(newValue, DisplayService.lastIpcDevice, true);
|
||||
resetHideTimer();
|
||||
}
|
||||
|
||||
onContainsMouseChanged: {
|
||||
setChildHovered(containsMouse);
|
||||
}
|
||||
onContainsMouseChanged: setChildHovered(containsMouse)
|
||||
|
||||
Binding on value {
|
||||
value: root.targetBrightness
|
||||
value: root._displayBrightness
|
||||
when: !brightnessSlider.isDragging
|
||||
}
|
||||
}
|
||||
@@ -146,13 +137,11 @@ DankOSD {
|
||||
anchors.centerIn: parent
|
||||
name: {
|
||||
const deviceInfo = DisplayService.getCurrentDeviceInfo();
|
||||
if (!deviceInfo || deviceInfo.class === "backlight" || deviceInfo.class === "ddc") {
|
||||
if (!deviceInfo || deviceInfo.class === "backlight" || deviceInfo.class === "ddc")
|
||||
return "brightness_medium";
|
||||
} else if (deviceInfo.name.includes("kbd")) {
|
||||
if (deviceInfo.name.includes("kbd"))
|
||||
return "keyboard";
|
||||
} else {
|
||||
return "lightbulb";
|
||||
}
|
||||
return "lightbulb";
|
||||
}
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
@@ -170,7 +159,7 @@ DankOSD {
|
||||
property int value: 50
|
||||
|
||||
Binding on value {
|
||||
value: root.targetBrightness
|
||||
value: root._displayBrightness
|
||||
when: !vertSlider.dragging
|
||||
}
|
||||
|
||||
@@ -178,8 +167,7 @@ DankOSD {
|
||||
const deviceInfo = DisplayService.getCurrentDeviceInfo();
|
||||
if (!deviceInfo)
|
||||
return 1;
|
||||
const isExponential = SessionData.getBrightnessExponential(deviceInfo.id);
|
||||
if (isExponential)
|
||||
if (SessionData.getBrightnessExponential(deviceInfo.id))
|
||||
return 1;
|
||||
return (deviceInfo.class === "backlight" || deviceInfo.class === "ddc") ? 1 : 0;
|
||||
}
|
||||
@@ -188,8 +176,7 @@ DankOSD {
|
||||
const deviceInfo = DisplayService.getCurrentDeviceInfo();
|
||||
if (!deviceInfo)
|
||||
return 100;
|
||||
const isExponential = SessionData.getBrightnessExponential(deviceInfo.id);
|
||||
if (isExponential)
|
||||
if (SessionData.getBrightnessExponential(deviceInfo.id))
|
||||
return 100;
|
||||
return deviceInfo.displayMax || 100;
|
||||
}
|
||||
@@ -240,33 +227,25 @@ DankOSD {
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onContainsMouseChanged: {
|
||||
setChildHovered(containsMouse);
|
||||
}
|
||||
onContainsMouseChanged: setChildHovered(containsMouse)
|
||||
|
||||
onPressed: mouse => {
|
||||
vertSlider.dragging = true;
|
||||
updateBrightness(mouse);
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
vertSlider.dragging = false;
|
||||
}
|
||||
onReleased: vertSlider.dragging = false
|
||||
|
||||
onPositionChanged: mouse => {
|
||||
if (pressed) {
|
||||
if (pressed)
|
||||
updateBrightness(mouse);
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: mouse => {
|
||||
updateBrightness(mouse);
|
||||
}
|
||||
onClicked: mouse => updateBrightness(mouse)
|
||||
|
||||
function updateBrightness(mouse) {
|
||||
if (!DisplayService.brightnessAvailable) {
|
||||
if (!DisplayService.brightnessAvailable)
|
||||
return;
|
||||
}
|
||||
const ratio = 1.0 - (mouse.y / height);
|
||||
const newValue = Math.round(vertSlider.minimum + ratio * (vertSlider.maximum - vertSlider.minimum));
|
||||
vertSlider.value = newValue;
|
||||
|
||||
@@ -8,13 +8,20 @@ DankOSD {
|
||||
|
||||
readonly property bool useVertical: isVerticalLayout
|
||||
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
|
||||
property bool _suppressNewPlayer: false
|
||||
property int _displayVolume: 0
|
||||
|
||||
function _syncVolume() {
|
||||
if (!player)
|
||||
return;
|
||||
_displayVolume = Math.min(100, Math.round(player.volume * 100));
|
||||
}
|
||||
|
||||
onPlayerChanged: {
|
||||
_suppressNewPlayer = true;
|
||||
_suppressTimer.restart();
|
||||
_syncVolume();
|
||||
}
|
||||
|
||||
Timer {
|
||||
@@ -37,25 +44,25 @@ DankOSD {
|
||||
}
|
||||
|
||||
function toggleMute() {
|
||||
if (player) {
|
||||
player.volume = player.volume > 0 ? 0 : 1;
|
||||
}
|
||||
if (!player)
|
||||
return;
|
||||
player.volume = player.volume > 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
function setVolume(volumePercent) {
|
||||
if (player) {
|
||||
player.volume = volumePercent / 100;
|
||||
resetHideTimer();
|
||||
}
|
||||
if (!player)
|
||||
return;
|
||||
player.volume = volumePercent / 100;
|
||||
resetHideTimer();
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: player
|
||||
|
||||
function onVolumeChanged() {
|
||||
if (SettingsData.osdMediaVolumeEnabled && volumeSupported && !_suppressNewPlayer) {
|
||||
root._syncVolume();
|
||||
if (SettingsData.osdMediaVolumeEnabled && volumeSupported && !_suppressNewPlayer)
|
||||
root.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,9 +103,7 @@ DankOSD {
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: toggleMute()
|
||||
onContainsMouseChanged: {
|
||||
setChildHovered(containsMouse || volumeSlider.containsMouse);
|
||||
}
|
||||
onContainsMouseChanged: setChildHovered(containsMouse || volumeSlider.containsMouse)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,29 +120,21 @@ DankOSD {
|
||||
showValue: true
|
||||
unit: "%"
|
||||
thumbOutlineColor: Theme.surfaceContainer
|
||||
valueOverride: currentVolume
|
||||
valueOverride: root._displayVolume
|
||||
alwaysShowValue: SettingsData.osdAlwaysShowValue
|
||||
|
||||
Component.onCompleted: {
|
||||
value = currentVolume;
|
||||
root._syncVolume();
|
||||
value = root._displayVolume;
|
||||
}
|
||||
|
||||
onSliderValueChanged: newValue => {
|
||||
setVolume(newValue);
|
||||
}
|
||||
onSliderValueChanged: newValue => setVolume(newValue)
|
||||
|
||||
onContainsMouseChanged: {
|
||||
setChildHovered(containsMouse || muteButton.containsMouse);
|
||||
}
|
||||
onContainsMouseChanged: setChildHovered(containsMouse || muteButton.containsMouse)
|
||||
|
||||
Connections {
|
||||
target: player
|
||||
|
||||
function onVolumeChanged() {
|
||||
if (volumeSlider && !volumeSlider.pressed) {
|
||||
volumeSlider.value = currentVolume;
|
||||
}
|
||||
}
|
||||
Binding on value {
|
||||
value: root._displayVolume
|
||||
when: !volumeSlider.pressed
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -172,9 +169,7 @@ DankOSD {
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: toggleMute()
|
||||
onContainsMouseChanged: {
|
||||
setChildHovered(containsMouse || vertSliderArea.containsMouse);
|
||||
}
|
||||
onContainsMouseChanged: setChildHovered(containsMouse || vertSliderArea.containsMouse)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +181,7 @@ DankOSD {
|
||||
y: gap * 2 + Theme.iconSize
|
||||
|
||||
property bool dragging: false
|
||||
property int value: currentVolume
|
||||
property int value: root._displayVolume
|
||||
|
||||
Rectangle {
|
||||
id: vertTrack
|
||||
@@ -231,28 +226,21 @@ DankOSD {
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onContainsMouseChanged: {
|
||||
setChildHovered(containsMouse || muteButtonVert.containsMouse);
|
||||
}
|
||||
onContainsMouseChanged: setChildHovered(containsMouse || muteButtonVert.containsMouse)
|
||||
|
||||
onPressed: mouse => {
|
||||
vertSlider.dragging = true;
|
||||
updateVolume(mouse);
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
vertSlider.dragging = false;
|
||||
}
|
||||
onReleased: vertSlider.dragging = false
|
||||
|
||||
onPositionChanged: mouse => {
|
||||
if (pressed) {
|
||||
if (pressed)
|
||||
updateVolume(mouse);
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: mouse => {
|
||||
updateVolume(mouse);
|
||||
}
|
||||
onClicked: mouse => updateVolume(mouse)
|
||||
|
||||
function updateVolume(mouse) {
|
||||
const ratio = 1.0 - (mouse.y / height);
|
||||
@@ -260,16 +248,6 @@ DankOSD {
|
||||
setVolume(volume);
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: player
|
||||
|
||||
function onVolumeChanged() {
|
||||
if (!vertSlider.dragging) {
|
||||
vertSlider.value = currentVolume;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,13 @@ DankOSD {
|
||||
id: root
|
||||
|
||||
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)
|
||||
osdHeight: useVertical ? Math.min(260, Screen.height - Theme.spacingM * 2) : (40 + Theme.spacingS * 2)
|
||||
@@ -14,18 +21,17 @@ DankOSD {
|
||||
enableMouseInteraction: true
|
||||
|
||||
Connections {
|
||||
target: AudioService.sink && AudioService.sink.audio ? AudioService.sink.audio : null
|
||||
target: AudioService.sink?.audio ?? null
|
||||
|
||||
function onVolumeChanged() {
|
||||
if (SettingsData.osdVolumeEnabled) {
|
||||
root._syncVolume();
|
||||
if (SettingsData.osdVolumeEnabled)
|
||||
root.show();
|
||||
}
|
||||
}
|
||||
|
||||
function onMutedChanged() {
|
||||
if (SettingsData.osdVolumeEnabled) {
|
||||
if (SettingsData.osdVolumeEnabled)
|
||||
root.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,9 +39,9 @@ DankOSD {
|
||||
target: AudioService
|
||||
|
||||
function onSinkChanged() {
|
||||
if (root.shouldBeVisible && SettingsData.osdVolumeEnabled) {
|
||||
root._syncVolume();
|
||||
if (root.shouldBeVisible && SettingsData.osdVolumeEnabled)
|
||||
root.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +70,7 @@ DankOSD {
|
||||
|
||||
DankIcon {
|
||||
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
|
||||
color: muteButton.containsMouse ? Theme.primary : Theme.surfaceText
|
||||
}
|
||||
@@ -75,60 +81,45 @@ DankOSD {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
AudioService.toggleMute();
|
||||
}
|
||||
onContainsMouseChanged: {
|
||||
setChildHovered(containsMouse || volumeSlider.containsMouse);
|
||||
}
|
||||
onClicked: AudioService.toggleMute()
|
||||
onContainsMouseChanged: setChildHovered(containsMouse || volumeSlider.containsMouse)
|
||||
}
|
||||
}
|
||||
|
||||
DankSlider {
|
||||
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
|
||||
height: 40
|
||||
x: parent.gap * 2 + Theme.iconSize
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
minimum: 0
|
||||
maximum: AudioService.sinkMaxVolume
|
||||
enabled: AudioService.sink && AudioService.sink.audio
|
||||
enabled: AudioService.sink?.audio
|
||||
showValue: true
|
||||
unit: "%"
|
||||
thumbOutlineColor: Theme.surfaceContainer
|
||||
valueOverride: displayPercent
|
||||
valueOverride: root._displayVolume
|
||||
alwaysShowValue: SettingsData.osdAlwaysShowValue
|
||||
|
||||
Component.onCompleted: {
|
||||
if (AudioService.sink && AudioService.sink.audio) {
|
||||
value = Math.min(AudioService.sinkMaxVolume, Math.round(AudioService.sink.audio.volume * 100));
|
||||
}
|
||||
root._syncVolume();
|
||||
value = root._displayVolume;
|
||||
}
|
||||
|
||||
onSliderValueChanged: newValue => {
|
||||
if (AudioService.sink && AudioService.sink.audio) {
|
||||
SessionData.suppressOSDTemporarily();
|
||||
AudioService.sink.audio.volume = newValue / 100;
|
||||
resetHideTimer();
|
||||
}
|
||||
if (!AudioService.sink?.audio)
|
||||
return;
|
||||
SessionData.suppressOSDTemporarily();
|
||||
AudioService.sink.audio.volume = newValue / 100;
|
||||
resetHideTimer();
|
||||
}
|
||||
|
||||
onContainsMouseChanged: {
|
||||
setChildHovered(containsMouse || muteButton.containsMouse);
|
||||
}
|
||||
onContainsMouseChanged: setChildHovered(containsMouse || muteButton.containsMouse)
|
||||
|
||||
Connections {
|
||||
target: AudioService.sink && AudioService.sink.audio ? AudioService.sink.audio : null
|
||||
|
||||
function onVolumeChanged() {
|
||||
if (volumeSlider && !volumeSlider.pressed) {
|
||||
volumeSlider.value = Math.min(AudioService.sinkMaxVolume, Math.round(AudioService.sink.audio.volume * 100));
|
||||
}
|
||||
}
|
||||
Binding on value {
|
||||
value: root._displayVolume
|
||||
when: !volumeSlider.pressed
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,7 +142,7 @@ DankOSD {
|
||||
|
||||
DankIcon {
|
||||
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
|
||||
color: muteButtonVert.containsMouse ? Theme.primary : Theme.surfaceText
|
||||
}
|
||||
@@ -162,12 +153,8 @@ DankOSD {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
AudioService.toggleMute();
|
||||
}
|
||||
onContainsMouseChanged: {
|
||||
setChildHovered(containsMouse || vertSliderArea.containsMouse);
|
||||
}
|
||||
onClicked: AudioService.toggleMute()
|
||||
onContainsMouseChanged: setChildHovered(containsMouse || vertSliderArea.containsMouse)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +166,7 @@ DankOSD {
|
||||
y: gap * 2 + Theme.iconSize
|
||||
|
||||
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 {
|
||||
id: vertTrack
|
||||
@@ -220,50 +207,35 @@ DankOSD {
|
||||
id: vertSliderArea
|
||||
anchors.fill: parent
|
||||
anchors.margins: -12
|
||||
enabled: AudioService.sink && AudioService.sink.audio
|
||||
enabled: AudioService.sink?.audio
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onContainsMouseChanged: {
|
||||
setChildHovered(containsMouse || muteButtonVert.containsMouse);
|
||||
}
|
||||
onContainsMouseChanged: setChildHovered(containsMouse || muteButtonVert.containsMouse)
|
||||
|
||||
onPressed: mouse => {
|
||||
vertSlider.dragging = true;
|
||||
updateVolume(mouse);
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
vertSlider.dragging = false;
|
||||
}
|
||||
onReleased: vertSlider.dragging = false
|
||||
|
||||
onPositionChanged: mouse => {
|
||||
if (pressed) {
|
||||
if (pressed)
|
||||
updateVolume(mouse);
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: mouse => {
|
||||
updateVolume(mouse);
|
||||
}
|
||||
onClicked: mouse => updateVolume(mouse)
|
||||
|
||||
function updateVolume(mouse) {
|
||||
if (AudioService.sink && AudioService.sink.audio) {
|
||||
const maxVol = AudioService.sinkMaxVolume;
|
||||
const ratio = 1.0 - (mouse.y / height);
|
||||
const volume = Math.max(0, Math.min(maxVol, Math.round(ratio * maxVol)));
|
||||
SessionData.suppressOSDTemporarily();
|
||||
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));
|
||||
if (!AudioService.sink?.audio)
|
||||
return;
|
||||
const maxVol = AudioService.sinkMaxVolume;
|
||||
const ratio = 1.0 - (mouse.y / height);
|
||||
const volume = Math.max(0, Math.min(maxVol, Math.round(ratio * maxVol)));
|
||||
SessionData.suppressOSDTemporarily();
|
||||
AudioService.sink.audio.volume = volume / 100;
|
||||
resetHideTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,36 +18,41 @@ Column {
|
||||
property bool isInitialized: false
|
||||
|
||||
function loadValue() {
|
||||
const settings = findSettings()
|
||||
const settings = findSettings();
|
||||
if (settings && settings.pluginService) {
|
||||
const loadedValue = settings.loadValue(settingKey, defaultValue)
|
||||
value = loadedValue
|
||||
textField.text = loadedValue
|
||||
isInitialized = true
|
||||
const loadedValue = settings.loadValue(settingKey, defaultValue);
|
||||
if (textField.activeFocus && isInitialized)
|
||||
return;
|
||||
value = loadedValue;
|
||||
textField.text = loadedValue;
|
||||
isInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
Qt.callLater(loadValue)
|
||||
Qt.callLater(loadValue);
|
||||
}
|
||||
|
||||
onValueChanged: {
|
||||
if (!isInitialized) return
|
||||
const settings = findSettings()
|
||||
if (settings) {
|
||||
settings.saveValue(settingKey, value)
|
||||
}
|
||||
function commit() {
|
||||
if (!isInitialized)
|
||||
return;
|
||||
if (textField.text === value)
|
||||
return;
|
||||
value = textField.text;
|
||||
const settings = findSettings();
|
||||
if (settings)
|
||||
settings.saveValue(settingKey, value);
|
||||
}
|
||||
|
||||
function findSettings() {
|
||||
let item = parent
|
||||
let item = parent;
|
||||
while (item) {
|
||||
if (item.saveValue !== undefined && item.loadValue !== undefined) {
|
||||
return item
|
||||
return item;
|
||||
}
|
||||
item = item.parent
|
||||
item = item.parent;
|
||||
}
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
StyledText {
|
||||
@@ -70,16 +75,10 @@ Column {
|
||||
id: textField
|
||||
width: parent.width
|
||||
placeholderText: root.placeholder
|
||||
onTextEdited: {
|
||||
root.value = text
|
||||
}
|
||||
onEditingFinished: {
|
||||
root.value = text
|
||||
}
|
||||
onEditingFinished: root.commit()
|
||||
onActiveFocusChanged: {
|
||||
if (!activeFocus) {
|
||||
root.value = text
|
||||
}
|
||||
if (!activeFocus)
|
||||
root.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,8 @@ DankPopout {
|
||||
open();
|
||||
}
|
||||
|
||||
popupWidth: 650
|
||||
popupHeight: 550
|
||||
popupWidth: Math.round(Theme.fontSizeMedium * 46)
|
||||
popupHeight: Math.round(Theme.fontSizeMedium * 39)
|
||||
triggerWidth: 55
|
||||
positioning: ""
|
||||
screen: triggerScreen
|
||||
@@ -151,11 +151,13 @@ DankPopout {
|
||||
|
||||
DankButtonGroup {
|
||||
id: processFilterGroup
|
||||
Layout.minimumWidth: implicitWidth + 8
|
||||
Layout.minimumWidth: implicitWidth
|
||||
model: [I18n.tr("All"), I18n.tr("User"), I18n.tr("System")]
|
||||
currentIndex: 0
|
||||
checkEnabled: false
|
||||
buttonHeight: Math.round(Theme.fontSizeMedium * 2.2)
|
||||
buttonHeight: Math.round(Theme.fontSizeSmall * 2.4)
|
||||
minButtonWidth: 0
|
||||
buttonPadding: Theme.spacingM
|
||||
textSize: Theme.fontSizeSmall
|
||||
onSelectionChanged: (index, selected) => {
|
||||
if (!selected)
|
||||
@@ -177,7 +179,8 @@ DankPopout {
|
||||
|
||||
DankTextField {
|
||||
id: searchField
|
||||
Layout.preferredWidth: Theme.fontSizeMedium * 14
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: Theme.fontSizeMedium * 8
|
||||
Layout.preferredHeight: Theme.fontSizeMedium * 2.5
|
||||
placeholderText: I18n.tr("Search...")
|
||||
leftIconName: "search"
|
||||
|
||||
@@ -375,8 +375,20 @@ FocusScope {
|
||||
if (!plugin || !PluginService.isPluginLoaded(pluginId))
|
||||
return;
|
||||
var isLauncher = plugin.type === "launcher" || (plugin.capabilities && plugin.capabilities.includes("launcher"));
|
||||
if (isLauncher)
|
||||
PluginService.reloadPlugin(pluginId);
|
||||
if (isLauncher) {
|
||||
pluginReloadTimer.pendingPluginId = pluginId;
|
||||
pluginReloadTimer.restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: pluginReloadTimer
|
||||
property string pendingPluginId: ""
|
||||
interval: 500
|
||||
onTriggered: {
|
||||
if (pendingPluginId)
|
||||
PluginService.reloadPlugin(pendingPluginId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -28,6 +28,10 @@ PanelWindow {
|
||||
function show() {
|
||||
if (SessionData.suppressOSD)
|
||||
return;
|
||||
if (shouldBeVisible) {
|
||||
hideTimer.restart();
|
||||
return;
|
||||
}
|
||||
OSDManager.showOSD(root);
|
||||
closeTimer.stop();
|
||||
shouldBeVisible = true;
|
||||
@@ -257,7 +261,7 @@ PanelWindow {
|
||||
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 * osdContainer.opacity))
|
||||
readonly property real effectiveShadowAlpha: shouldBeVisible ? Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha)) : 0
|
||||
|
||||
Rectangle {
|
||||
id: background
|
||||
|
||||
@@ -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 {
|
||||
id: contentWrapper
|
||||
anchors.centerIn: parent
|
||||
@@ -480,31 +518,10 @@ Item {
|
||||
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)
|
||||
|
||||
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.enabled: contentWrapper.opacity < 1
|
||||
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.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 {
|
||||
NumberAnimation {
|
||||
duration: animationDuration
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
[templates.dmsemacs]
|
||||
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'
|
||||
|
||||
Reference in New Issue
Block a user