support regex for class selector in window rules (resolves #41)
This commit is contained in:
@@ -1,15 +1,19 @@
|
||||
class ClientMatcher {
|
||||
private readonly rules: Map<string, RegExp>;
|
||||
private readonly regex: RegExp;
|
||||
|
||||
constructor(rules: Map<string, RegExp>) {
|
||||
this.rules = rules;
|
||||
constructor(regex: RegExp) {
|
||||
this.regex = regex;
|
||||
}
|
||||
|
||||
public matches(kwinClient: KwinClient) {
|
||||
const rule = this.rules.get(kwinClient.resourceClass);
|
||||
if (rule === undefined) {
|
||||
return false;
|
||||
}
|
||||
return rule.test(kwinClient.caption);
|
||||
return this.regex.test(ClientMatcher.getClientString(kwinClient));
|
||||
}
|
||||
|
||||
public static getClientString(kwinClient: KwinClient) {
|
||||
return ClientMatcher.getRuleString(kwinClient.resourceClass, kwinClient.caption);
|
||||
}
|
||||
|
||||
public static getRuleString(ruleClass: string, ruleCaption: string) {
|
||||
return ruleClass + "\0" + ruleCaption;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
type WindowRule = {
|
||||
class: string,
|
||||
caption: string,
|
||||
class: string | undefined,
|
||||
caption: string | undefined,
|
||||
tile: boolean,
|
||||
};
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
class WindowRuleEnforcer {
|
||||
private readonly preferFloating: ClientMatcher;
|
||||
private readonly preferTiling: ClientMatcher;
|
||||
private readonly followCaption: Set<string>;
|
||||
private readonly followCaption: RegExp;
|
||||
|
||||
constructor(windowRules: WindowRule[]) {
|
||||
const [mapFloat, mapTile] = WindowRuleEnforcer.createWindowRuleMaps(windowRules);
|
||||
this.preferFloating = new ClientMatcher(mapFloat);
|
||||
this.preferTiling = new ClientMatcher(mapTile);
|
||||
this.followCaption = new Set([...mapFloat.keys(), ...mapTile.keys()]);
|
||||
const [floatRegex, tileRegex, followCaptionRegex] = WindowRuleEnforcer.createWindowRuleRegexes(windowRules);
|
||||
log("floatRegex", floatRegex);
|
||||
log("tileRegex", tileRegex);
|
||||
log("followCaptionRegex", followCaptionRegex);
|
||||
this.preferFloating = new ClientMatcher(floatRegex);
|
||||
this.preferTiling = new ClientMatcher(tileRegex);
|
||||
this.followCaption = followCaptionRegex;
|
||||
}
|
||||
|
||||
public shouldTile(kwinClient: KwinClient) {
|
||||
@@ -22,7 +25,7 @@ class WindowRuleEnforcer {
|
||||
}
|
||||
|
||||
public initClientSignalManager(world: World, kwinClient: KwinClient) {
|
||||
if (!this.followCaption.has(kwinClient.resourceClass)) {
|
||||
if (!this.followCaption.test(kwinClient.resourceClass)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -42,38 +45,39 @@ class WindowRuleEnforcer {
|
||||
return manager;
|
||||
}
|
||||
|
||||
private static createWindowRuleMaps(windowRules: WindowRule[]) {
|
||||
const mapFloat = new Map<string, string[]>();
|
||||
const mapTile = new Map<string, string[]>();
|
||||
private static createWindowRuleRegexes(windowRules: WindowRule[]) {
|
||||
const floatRegexes: string[] = [];
|
||||
const tileRegexes: string[] = [];
|
||||
const followCaptionRegexes: string[] = [];
|
||||
for (const windowRule of windowRules) {
|
||||
const map = windowRule.tile ? mapTile : mapFloat;
|
||||
let captions = map.get(windowRule.class);
|
||||
if (captions === undefined) {
|
||||
captions = [];
|
||||
map.set(windowRule.class, captions);
|
||||
}
|
||||
if (windowRule.caption !== undefined) {
|
||||
captions.push(windowRule.caption);
|
||||
const ruleClass = WindowRuleEnforcer.parseRegex(windowRule.class);
|
||||
const ruleCaption = WindowRuleEnforcer.parseRegex(windowRule.caption);
|
||||
const ruleString = ClientMatcher.getRuleString(ruleClass, ruleCaption);
|
||||
|
||||
(windowRule.tile ? tileRegexes : floatRegexes).push(ruleString);
|
||||
if (ruleCaption !== ".*") {
|
||||
followCaptionRegexes.push(ruleClass);
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
WindowRuleEnforcer.createWindowRuleRegexMap(mapFloat),
|
||||
WindowRuleEnforcer.createWindowRuleRegexMap(mapTile),
|
||||
WindowRuleEnforcer.joinRegexes(floatRegexes),
|
||||
WindowRuleEnforcer.joinRegexes(tileRegexes),
|
||||
WindowRuleEnforcer.joinRegexes(followCaptionRegexes),
|
||||
];
|
||||
}
|
||||
|
||||
private static createWindowRuleRegexMap(windowRuleMap: Map<string, string[]>) {
|
||||
const regexMap = new Map<string, RegExp>;
|
||||
for (const [k, v] of windowRuleMap) {
|
||||
regexMap.set(k, WindowRuleEnforcer.joinRegexes(v));
|
||||
private static parseRegex(rawRule: string | undefined) {
|
||||
if (rawRule === undefined || rawRule === "" || rawRule === ".*") {
|
||||
return ".*";
|
||||
} else {
|
||||
return rawRule;
|
||||
}
|
||||
return regexMap;
|
||||
}
|
||||
|
||||
private static joinRegexes(regexes: string[]) {
|
||||
if (regexes.length === 0) {
|
||||
return new RegExp("");
|
||||
return new RegExp("a^"); // match nothing
|
||||
}
|
||||
|
||||
if (regexes.length === 1) {
|
||||
|
||||
Reference in New Issue
Block a user