9 Commits
v0.8.1 ... v0.9

Author SHA1 Message Date
Peter Fajdiga
c7cfa261b9 bump version to 0.9 2024-03-30 12:46:59 +01:00
Peter Fajdiga
56955e4df3 src/config: don't tile kded windows 2024-03-30 12:45:42 +01:00
Peter Fajdiga
bb308cfbfb config: merge X11 and Wayland class regexes in window rules 2024-03-30 12:45:40 +01:00
Peter Fajdiga
6c00245943 config: escape . in window rules 2024-03-30 12:45:38 +01:00
Peter Fajdiga
2efdbe5a7b support regex for class selector in window rules (resolves #41) 2024-03-30 12:45:36 +01:00
Peter Fajdiga
092cbf3ff1 kwin.d.ts: remove unused signal maximizedChanged 2024-03-30 12:45:33 +01:00
Peter Fajdiga
f9ae299ce8 Tiled: restore opacity after un-tiling 2024-03-30 12:45:28 +01:00
Peter Fajdiga
695f5edf6a config: add option to disable layering (resolves #41) 2024-03-30 12:45:25 +01:00
Peter Fajdiga
9b80b535a1 readme: update QML dependencies 2024-03-19 10:58:51 +01:00
9 changed files with 67 additions and 65 deletions

View File

@@ -19,7 +19,7 @@ Similar window managers include [PaperWM](https://github.com/paperwm/PaperWM),
## Dependencies ## Dependencies
Karousel requires the following QML modules: Karousel requires the following QML modules:
- QtQuick 2.15 - QtQuick 6.0
- org.kde.kwin 3.0 - org.kde.kwin 3.0
- org.kde.notification 1.0 - org.kde.notification 1.0

View File

@@ -121,6 +121,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QRadioButton" name="kcfg_noLayering">
<property name="text">
<string>No layering</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View File

@@ -9,7 +9,7 @@
"Name": "Peter Fajdiga" "Name": "Peter Fajdiga"
}], }],
"Id": "karousel", "Id": "karousel",
"Version": "0.8.1", "Version": "0.9",
"License": "GPLv3", "License": "GPLv3",
"Website": "https://github.com/peterfajdiga/karousel", "Website": "https://github.com/peterfajdiga/karousel",
"BugReportUrl": "https://github.com/peterfajdiga/karousel/issues" "BugReportUrl": "https://github.com/peterfajdiga/karousel/issues"

View File

@@ -4,51 +4,31 @@ const defaultWindowRules = `[
"tile": false "tile": false
}, },
{ {
"class": "plasmashell", "class": "(org\\\\.kde\\\\.)?plasmashell",
"tile": false "tile": false
}, },
{ {
"class": "org.kde.plasmashell", "class": "(org\\\\.kde\\\\.)?kded6",
"tile": false "tile": false
}, },
{ {
"class": "kcalc", "class": "(org\\\\.kde\\\\.)?kcalc",
"tile": false "tile": false
}, },
{ {
"class": "org.kde.kcalc", "class": "(org\\\\.kde\\\\.)?kfind",
"tile": false
},
{
"class": "kfind",
"tile": true "tile": true
}, },
{ {
"class": "org.kde.kfind", "class": "(org\\\\.kde\\\\.)?kruler",
"tile": true
},
{
"class": "kruler",
"tile": false "tile": false
}, },
{ {
"class": "org.kde.kruler", "class": "(org\\\\.kde\\\\.)?krunner",
"tile": false "tile": false
}, },
{ {
"class": "krunner", "class": "(org\\\\.kde\\\\.)?yakuake",
"tile": false
},
{
"class": "org.kde.krunner",
"tile": false
},
{
"class": "yakuake",
"tile": false
},
{
"class": "org.kde.yakuake",
"tile": false "tile": false
}, },
{ {
@@ -174,6 +154,11 @@ const configDef = [
type: "Bool", type: "Bool",
default: false, default: false,
}, },
{
name: "noLayering",
type: "Bool",
default: false,
},
{ {
name: "windowRules", name: "windowRules",
type: "String", type: "String",

View File

@@ -81,7 +81,6 @@ interface KwinClient {
readonly desktopsChanged: QSignal<[]>; readonly desktopsChanged: QSignal<[]>;
readonly activitiesChanged: QSignal<[]>; readonly activitiesChanged: QSignal<[]>;
readonly minimizedChanged: QSignal<[]>; readonly minimizedChanged: QSignal<[]>;
readonly maximizedChanged: QSignal<[]>
readonly maximizedAboutToChange: QSignal<[MaximizedMode]> readonly maximizedAboutToChange: QSignal<[MaximizedMode]>
readonly captionChanged: QSignal<[]>; readonly captionChanged: QSignal<[]>;
readonly tileChanged: QSignal<[]>; readonly tileChanged: QSignal<[]>;

View File

@@ -1,15 +1,19 @@
class ClientMatcher { class ClientMatcher {
private readonly rules: Map<string, RegExp>; private readonly regex: RegExp;
constructor(rules: Map<string, RegExp>) { constructor(regex: RegExp) {
this.rules = rules; this.regex = regex;
} }
public matches(kwinClient: KwinClient) { public matches(kwinClient: KwinClient) {
const rule = this.rules.get(kwinClient.resourceClass); return this.regex.test(ClientMatcher.getClientString(kwinClient));
if (rule === undefined) { }
return false;
} public static getClientString(kwinClient: KwinClient) {
return rule.test(kwinClient.caption); return ClientMatcher.getRuleString(kwinClient.resourceClass, kwinClient.caption);
}
public static getRuleString(ruleClass: string, ruleCaption: string) {
return ruleClass + "\0" + ruleCaption;
} }
} }

View File

@@ -1,5 +1,5 @@
type WindowRule = { type WindowRule = {
class: string, class: string | undefined,
caption: string, caption: string | undefined,
tile: boolean, tile: boolean,
}; };

View File

@@ -1,13 +1,16 @@
class WindowRuleEnforcer { class WindowRuleEnforcer {
private readonly preferFloating: ClientMatcher; private readonly preferFloating: ClientMatcher;
private readonly preferTiling: ClientMatcher; private readonly preferTiling: ClientMatcher;
private readonly followCaption: Set<string>; private readonly followCaption: RegExp;
constructor(windowRules: WindowRule[]) { constructor(windowRules: WindowRule[]) {
const [mapFloat, mapTile] = WindowRuleEnforcer.createWindowRuleMaps(windowRules); const [floatRegex, tileRegex, followCaptionRegex] = WindowRuleEnforcer.createWindowRuleRegexes(windowRules);
this.preferFloating = new ClientMatcher(mapFloat); log("floatRegex", floatRegex);
this.preferTiling = new ClientMatcher(mapTile); log("tileRegex", tileRegex);
this.followCaption = new Set([...mapFloat.keys(), ...mapTile.keys()]); log("followCaptionRegex", followCaptionRegex);
this.preferFloating = new ClientMatcher(floatRegex);
this.preferTiling = new ClientMatcher(tileRegex);
this.followCaption = followCaptionRegex;
} }
public shouldTile(kwinClient: KwinClient) { public shouldTile(kwinClient: KwinClient) {
@@ -22,7 +25,7 @@ class WindowRuleEnforcer {
} }
public initClientSignalManager(world: World, kwinClient: KwinClient) { public initClientSignalManager(world: World, kwinClient: KwinClient) {
if (!this.followCaption.has(kwinClient.resourceClass)) { if (!this.followCaption.test(kwinClient.resourceClass)) {
return null; return null;
} }
@@ -42,38 +45,39 @@ class WindowRuleEnforcer {
return manager; return manager;
} }
private static createWindowRuleMaps(windowRules: WindowRule[]) { private static createWindowRuleRegexes(windowRules: WindowRule[]) {
const mapFloat = new Map<string, string[]>(); const floatRegexes: string[] = [];
const mapTile = new Map<string, string[]>(); const tileRegexes: string[] = [];
const followCaptionRegexes: string[] = [];
for (const windowRule of windowRules) { for (const windowRule of windowRules) {
const map = windowRule.tile ? mapTile : mapFloat; const ruleClass = WindowRuleEnforcer.parseRegex(windowRule.class);
let captions = map.get(windowRule.class); const ruleCaption = WindowRuleEnforcer.parseRegex(windowRule.caption);
if (captions === undefined) { const ruleString = ClientMatcher.getRuleString(ruleClass, ruleCaption);
captions = [];
map.set(windowRule.class, captions); (windowRule.tile ? tileRegexes : floatRegexes).push(ruleString);
} if (ruleCaption !== ".*") {
if (windowRule.caption !== undefined) { followCaptionRegexes.push(ruleClass);
captions.push(windowRule.caption);
} }
} }
return [ return [
WindowRuleEnforcer.createWindowRuleRegexMap(mapFloat), WindowRuleEnforcer.joinRegexes(floatRegexes),
WindowRuleEnforcer.createWindowRuleRegexMap(mapTile), WindowRuleEnforcer.joinRegexes(tileRegexes),
WindowRuleEnforcer.joinRegexes(followCaptionRegexes),
]; ];
} }
private static createWindowRuleRegexMap(windowRuleMap: Map<string, string[]>) { private static parseRegex(rawRule: string | undefined) {
const regexMap = new Map<string, RegExp>; if (rawRule === undefined || rawRule === "" || rawRule === ".*") {
for (const [k, v] of windowRuleMap) { return ".*";
regexMap.set(k, WindowRuleEnforcer.joinRegexes(v)); } else {
return rawRule;
} }
return regexMap;
} }
private static joinRegexes(regexes: string[]) { private static joinRegexes(regexes: string[]) {
if (regexes.length === 0) { if (regexes.length === 0) {
return new RegExp(""); return new RegExp("a^"); // match nothing
} }
if (regexes.length === 1) { if (regexes.length === 1) {

View File

@@ -174,6 +174,9 @@ namespace ClientState {
if (config.tiledKeepBelow) { if (config.tiledKeepBelow) {
client.kwinClient.keepBelow = false; client.kwinClient.keepBelow = false;
} }
if (config.offScreenOpacity < 1.0) {
client.kwinClient.opacity = 1.0;
}
client.setShade(false); client.setShade(false);
client.setFullScreen(false); client.setFullScreen(false);
if (client.kwinClient.tile === null) { if (client.kwinClient.tile === null) {