mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-28 14:07:47 -04:00
fix(windowrules): preserve niri exclude clauses
fixes #2996
port 1.5
(cherry picked from commit 8e2168ecf8)
This commit is contained in:
1 parent
a34037f49c
commit
8200c72f8c
4 files changed
+72
-5
No files matched your search
@@ -37,6 +37,7 @@ type NiriWindowRule struct {
|
||||
MatchIsUrgent *bool
|
||||
MatchAtStartup *bool
|
||||
Matches []NiriMatch
|
||||
Excludes []NiriMatch
|
||||
Opacity *float64
|
||||
OpenFloating *bool
|
||||
OpenMaximized *bool
|
||||
@@ -212,6 +213,8 @@ func (p *NiriRulesParser) parseWindowRuleNode(node *document.Node) {
|
||||
switch childName {
|
||||
case "match":
|
||||
rule.Matches = append(rule.Matches, p.parseMatchNode(child))
|
||||
case "exclude":
|
||||
rule.Excludes = append(rule.Excludes, p.parseMatchNode(child))
|
||||
case "opacity":
|
||||
if len(child.Arguments) > 0 {
|
||||
val := child.Arguments[0].ResolvedValue()
|
||||
@@ -597,7 +600,8 @@ func ConvertNiriRulesToWindowRules(niriRules []NiriWindowRule) []windowrules.Win
|
||||
IsUrgent: nr.MatchIsUrgent,
|
||||
AtStartup: nr.MatchAtStartup,
|
||||
},
|
||||
Matches: convertNiriMatches(nr.Matches),
|
||||
Matches: convertNiriMatches(nr.Matches),
|
||||
Excludes: convertNiriMatches(nr.Excludes),
|
||||
Actions: windowrules.Actions{
|
||||
Opacity: nr.Opacity,
|
||||
OpenFloating: nr.OpenFloating,
|
||||
@@ -810,7 +814,8 @@ func (p *NiriWritableProvider) LoadDMSRules() ([]windowrules.WindowRule, error)
|
||||
IsUrgent: nr.MatchIsUrgent,
|
||||
AtStartup: nr.MatchAtStartup,
|
||||
},
|
||||
Matches: convertNiriMatches(nr.Matches),
|
||||
Matches: convertNiriMatches(nr.Matches),
|
||||
Excludes: convertNiriMatches(nr.Excludes),
|
||||
Actions: windowrules.Actions{
|
||||
Opacity: nr.Opacity,
|
||||
OpenFloating: nr.OpenFloating,
|
||||
@@ -874,7 +879,7 @@ func (p *NiriWritableProvider) writeDMSRules(rules []windowrules.WindowRule) err
|
||||
return os.WriteFile(rulesPath, []byte(strings.Join(lines, "\n")), 0644)
|
||||
}
|
||||
|
||||
func formatNiriMatchLine(m windowrules.MatchCriteria) (string, bool) {
|
||||
func formatNiriMatchLine(keyword string, m windowrules.MatchCriteria) (string, bool) {
|
||||
var matchProps []string
|
||||
if m.AppID != "" {
|
||||
matchProps = append(matchProps, fmt.Sprintf("app-id=%q", m.AppID))
|
||||
@@ -906,7 +911,7 @@ func formatNiriMatchLine(m windowrules.MatchCriteria) (string, bool) {
|
||||
if len(matchProps) == 0 {
|
||||
return "", false
|
||||
}
|
||||
return " match " + strings.Join(matchProps, " "), true
|
||||
return " " + keyword + " " + strings.Join(matchProps, " "), true
|
||||
}
|
||||
|
||||
func (p *NiriWritableProvider) formatRule(rule windowrules.WindowRule) string {
|
||||
@@ -919,7 +924,12 @@ func (p *NiriWritableProvider) formatRule(rule windowrules.WindowRule) string {
|
||||
matches = []windowrules.MatchCriteria{rule.MatchCriteria}
|
||||
}
|
||||
for _, m := range matches {
|
||||
if line, ok := formatNiriMatchLine(m); ok {
|
||||
if line, ok := formatNiriMatchLine("match", m); ok {
|
||||
lines = append(lines, line)
|
||||
}
|
||||
}
|
||||
for _, m := range rule.Excludes {
|
||||
if line, ok := formatNiriMatchLine("exclude", m); ok {
|
||||
lines = append(lines, line)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,3 +333,56 @@ window-rule {
|
||||
t.Error("DMSStatus.Exists should be false when dms rules file doesn't exist")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNiriExcludesSurviveEditOfOtherRule(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
provider := NewNiriWritableProvider(tmpDir)
|
||||
|
||||
dmsDir := filepath.Join(tmpDir, "dms")
|
||||
if err := os.MkdirAll(dmsDir, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
existing := `// @id=thunderbird @name=Thunderbird
|
||||
window-rule {
|
||||
match app-id="^org.mozilla.Thunderbird$"
|
||||
open-floating true
|
||||
exclude title="^Mozilla Thunderbird$"
|
||||
exclude title="^Verfassen:.*"
|
||||
}
|
||||
|
||||
// @id=firefox @name=Firefox
|
||||
window-rule {
|
||||
match app-id="^firefox$"
|
||||
open-floating true
|
||||
}
|
||||
`
|
||||
if err := os.WriteFile(filepath.Join(dmsDir, "windowrules.kdl"), []byte(existing), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
edited := newTestWindowRule("firefox", "Firefox", "^firefox$")
|
||||
edited.Actions.OpenFloating = boolPtr(false)
|
||||
if err := provider.SetRule(edited); err != nil {
|
||||
t.Fatalf("SetRule failed: %v", err)
|
||||
}
|
||||
|
||||
rules, err := provider.LoadDMSRules()
|
||||
if err != nil {
|
||||
t.Fatalf("LoadDMSRules failed: %v", err)
|
||||
}
|
||||
if len(rules) != 2 {
|
||||
t.Fatalf("expected 2 rules, got %d", len(rules))
|
||||
}
|
||||
if len(rules[0].Excludes) != 2 {
|
||||
t.Fatalf("expected 2 excludes on untouched rule, got %d", len(rules[0].Excludes))
|
||||
}
|
||||
if rules[0].Excludes[0].Title != "^Mozilla Thunderbird$" {
|
||||
t.Errorf("Excludes[0].Title = %q", rules[0].Excludes[0].Title)
|
||||
}
|
||||
if rules[0].Excludes[1].Title != "^Verfassen:.*" {
|
||||
t.Errorf("Excludes[1].Title = %q", rules[0].Excludes[1].Title)
|
||||
}
|
||||
if rules[1].Actions.OpenFloating == nil || *rules[1].Actions.OpenFloating {
|
||||
t.Error("edited rule should have open-floating false")
|
||||
}
|
||||
}
|
||||
@@ -77,6 +77,7 @@ type WindowRule struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
MatchCriteria MatchCriteria `json:"matchCriteria"`
|
||||
Matches []MatchCriteria `json:"matches,omitempty"`
|
||||
Excludes []MatchCriteria `json:"excludes,omitempty"`
|
||||
Actions Actions `json:"actions"`
|
||||
Source string `json:"source,omitempty"`
|
||||
}
|
||||
|
||||
@@ -457,6 +457,9 @@ FloatingWindow {
|
||||
};
|
||||
if (isNiri && extraMatchModel.count > 0)
|
||||
ruleData.matches = matches;
|
||||
// No exclude editor yet — carry existing excludes through so an edit doesn't delete them (#2996)
|
||||
if (isEditMode && (editingRule.excludes?.length ?? 0) > 0)
|
||||
ruleData.excludes = editingRule.excludes;
|
||||
|
||||
submitting = true;
|
||||
|
||||
|
||||
Reference in new issue
Block a user