Add Desktops settings tab to control which virtual desktops Karousel operates on (#133)
* Add Desktops settings tab to control which virtual desktops Karousel operates on * Fix cursor follow focus to only work on matched desktops * Resolve review comments - Implement a RegExp-based DesktopFilter. - Add new config key tiledDesktops (String) with default ".*" (match all). - Make DesktopManager return undefined for desktops that should not be tiled. - Mark KWinDesktop.name as readonly. - Replace multiline desktop editor in settings UI with a single-line QLineEdit (moved to top of Window Rules tab), shorten label to "Tiled desktops:" and add a tooltip with examples. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -458,6 +458,30 @@
|
||||
<string>Window Rules</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_desktops">
|
||||
<property name="text">
|
||||
<string>Tiled desktops:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="kcfg_tiledDesktops">
|
||||
<property name="font">
|
||||
<font><family>Monospace</family></font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Regex string to match desktops. Default value is ".*". Example: "Desktop [1-3]"</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="kcfg_windowRules">
|
||||
<property name="tabChangesFocus">
|
||||
|
||||
@@ -25,4 +25,5 @@ interface Config {
|
||||
tiledKeepBelow: boolean;
|
||||
floatingKeepAbove: boolean;
|
||||
windowRules: string;
|
||||
tiledDesktops: string;
|
||||
}
|
||||
|
||||
@@ -189,4 +189,9 @@ const configDef = [
|
||||
type: "String",
|
||||
default: defaultWindowRules,
|
||||
},
|
||||
{
|
||||
name: "tiledDesktops",
|
||||
type: "String",
|
||||
default: ".*",
|
||||
},
|
||||
];
|
||||
|
||||
1
src/lib/extern/kwin.ts
vendored
1
src/lib/extern/kwin.ts
vendored
@@ -102,6 +102,7 @@ interface KwinDesktop {
|
||||
__brand: "KwinDesktop";
|
||||
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
}
|
||||
|
||||
interface ShortcutHandler extends QmlObject {
|
||||
|
||||
@@ -62,7 +62,11 @@ class Actions {
|
||||
};
|
||||
|
||||
public readonly focusStart = (cm: ClientManager, dm: DesktopManager) => {
|
||||
const grid = dm.getCurrentDesktop().grid;
|
||||
const desktop = dm.getCurrentDesktop();
|
||||
if (desktop === undefined) {
|
||||
return;
|
||||
}
|
||||
const grid = desktop.grid;
|
||||
const firstColumn = grid.getFirstColumn();
|
||||
if (firstColumn === null) {
|
||||
return;
|
||||
@@ -71,7 +75,11 @@ class Actions {
|
||||
};
|
||||
|
||||
public readonly focusEnd = (cm: ClientManager, dm: DesktopManager) => {
|
||||
const grid = dm.getCurrentDesktop().grid;
|
||||
const desktop = dm.getCurrentDesktop();
|
||||
if (desktop === undefined) {
|
||||
return;
|
||||
}
|
||||
const grid = desktop.grid;
|
||||
const lastColumn = grid.getLastColumn();
|
||||
if (lastColumn === null) {
|
||||
return;
|
||||
@@ -196,6 +204,9 @@ class Actions {
|
||||
|
||||
public readonly columnsWidthEqualize = (cm: ClientManager, dm: DesktopManager) => {
|
||||
const desktop = dm.getCurrentDesktop();
|
||||
if (desktop === undefined) {
|
||||
return;
|
||||
}
|
||||
const visibleRange = desktop.getCurrentVisibleRange();
|
||||
const visibleColumns = Array.from(desktop.grid.getVisibleColumns(visibleRange, true));
|
||||
|
||||
@@ -297,11 +308,18 @@ class Actions {
|
||||
};
|
||||
|
||||
private readonly gridScroll = (desktopManager: DesktopManager, amount: number) => {
|
||||
desktopManager.getCurrentDesktop().adjustScroll(amount, false);
|
||||
const desktop = desktopManager.getCurrentDesktop();
|
||||
if (desktop !== undefined) {
|
||||
desktop.adjustScroll(amount, false);
|
||||
}
|
||||
};
|
||||
|
||||
public readonly gridScrollStart = (cm: ClientManager, dm: DesktopManager) => {
|
||||
const grid = dm.getCurrentDesktop().grid;
|
||||
const desktop = dm.getCurrentDesktop();
|
||||
if (desktop === undefined) {
|
||||
return;
|
||||
}
|
||||
const grid = desktop.grid;
|
||||
const firstColumn = grid.getFirstColumn();
|
||||
if (firstColumn === null) {
|
||||
return;
|
||||
@@ -310,7 +328,11 @@ class Actions {
|
||||
};
|
||||
|
||||
public readonly gridScrollEnd = (cm: ClientManager, dm: DesktopManager) => {
|
||||
const grid = dm.getCurrentDesktop().grid;
|
||||
const desktop = dm.getCurrentDesktop();
|
||||
if (desktop === undefined) {
|
||||
return;
|
||||
}
|
||||
const grid = desktop.grid;
|
||||
const lastColumn = grid.getLastColumn();
|
||||
if (lastColumn === null) {
|
||||
return;
|
||||
@@ -328,7 +350,11 @@ class Actions {
|
||||
};
|
||||
|
||||
public readonly gridScrollLeftColumn = (cm: ClientManager, dm: DesktopManager) => {
|
||||
const grid = dm.getCurrentDesktop().grid;
|
||||
const desktop = dm.getCurrentDesktop();
|
||||
if (desktop === undefined) {
|
||||
return;
|
||||
}
|
||||
const grid = desktop.grid;
|
||||
const column = grid.getLeftmostVisibleColumn(grid.desktop.getCurrentVisibleRange(), true);
|
||||
if (column === null) {
|
||||
return;
|
||||
@@ -343,7 +369,11 @@ class Actions {
|
||||
};
|
||||
|
||||
public readonly gridScrollRightColumn = (cm: ClientManager, dm: DesktopManager) => {
|
||||
const grid = dm.getCurrentDesktop().grid;
|
||||
const desktop = dm.getCurrentDesktop();
|
||||
if (desktop === undefined) {
|
||||
return;
|
||||
}
|
||||
const grid = desktop.grid;
|
||||
const column = grid.getRightmostVisibleColumn(grid.desktop.getCurrentVisibleRange(), true);
|
||||
if (column === null) {
|
||||
return;
|
||||
@@ -362,7 +392,11 @@ class Actions {
|
||||
};
|
||||
|
||||
public readonly focus = (columnIndex: number, cm: ClientManager, dm: DesktopManager) => {
|
||||
const grid = dm.getCurrentDesktop().grid;
|
||||
const desktop = dm.getCurrentDesktop();
|
||||
if (desktop === undefined) {
|
||||
return;
|
||||
}
|
||||
const grid = desktop.grid;
|
||||
const targetColumn = grid.getColumnAtIndex(columnIndex);
|
||||
if (targetColumn === null) {
|
||||
return;
|
||||
@@ -396,7 +430,11 @@ class Actions {
|
||||
if (kwinDesktop === undefined) {
|
||||
return;
|
||||
}
|
||||
const newGrid = dm.getDesktopInCurrentActivity(kwinDesktop).grid;
|
||||
const newDesktop = dm.getDesktopInCurrentActivity(kwinDesktop);
|
||||
if (newDesktop === undefined) {
|
||||
return;
|
||||
}
|
||||
const newGrid = newDesktop.grid;
|
||||
if (newGrid === null || newGrid === oldGrid) {
|
||||
return;
|
||||
}
|
||||
@@ -408,7 +446,11 @@ class Actions {
|
||||
if (kwinDesktop === undefined) {
|
||||
return;
|
||||
}
|
||||
const newGrid = dm.getDesktopInCurrentActivity(kwinDesktop).grid;
|
||||
const newDesktop = dm.getDesktopInCurrentActivity(kwinDesktop);
|
||||
if (newDesktop === undefined) {
|
||||
return;
|
||||
}
|
||||
const newGrid = newDesktop.grid;
|
||||
if (newGrid === null || newGrid === oldGrid) {
|
||||
return;
|
||||
}
|
||||
|
||||
29
src/lib/rules/DesktopFilter.ts
Normal file
29
src/lib/rules/DesktopFilter.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
class DesktopFilter {
|
||||
private readonly desktopRegex: RegExp | null; // null means all desktops
|
||||
|
||||
constructor(desktopsConfig: string) {
|
||||
this.desktopRegex = DesktopFilter.parseDesktopConfig(desktopsConfig);
|
||||
}
|
||||
|
||||
public shouldWorkOnDesktop(kwinDesktop: KwinDesktop): boolean {
|
||||
if (this.desktopRegex === null) {
|
||||
return true; // Work on all desktops
|
||||
}
|
||||
return this.desktopRegex.test(kwinDesktop.name);
|
||||
}
|
||||
|
||||
private static parseDesktopConfig(config: string): RegExp | null {
|
||||
const trimmed = config.trim();
|
||||
|
||||
if (trimmed.length === 0) {
|
||||
return null; // Empty config means work on all desktops
|
||||
}
|
||||
|
||||
try {
|
||||
return new RegExp(`^${trimmed}$`);
|
||||
} catch (e) {
|
||||
log(`Invalid regex pattern in tiledDesktops config: ${trimmed}. Working on all desktops.`);
|
||||
return null; // Invalid regex means work on all desktops as fallback
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,16 +31,16 @@ class ClientManager {
|
||||
console.assert(!this.hasClient(kwinClient));
|
||||
|
||||
let constructState: (client: ClientWrapper) => ClientState.State;
|
||||
let desktop: Desktop | undefined;
|
||||
if (kwinClient.dock) {
|
||||
constructState = () => new ClientState.Docked(this.world, kwinClient);
|
||||
} else if (
|
||||
Clients.canTileEver(kwinClient) &&
|
||||
this.windowRuleEnforcer.shouldTile(kwinClient)
|
||||
this.windowRuleEnforcer.shouldTile(kwinClient) &&
|
||||
(desktop = this.desktopManager.getDesktopForClient(kwinClient)) !== undefined
|
||||
) {
|
||||
Clients.makeTileable(kwinClient);
|
||||
console.assert(Clients.canTileNow(kwinClient));
|
||||
const desktop = this.desktopManager.getDesktopForClient(kwinClient);
|
||||
console.assert(desktop !== undefined);
|
||||
constructState = (client: ClientWrapper) => new ClientState.Tiled(this.world, client, desktop!.grid);
|
||||
} else {
|
||||
constructState = (client: ClientWrapper) => new ClientState.Floating(this.world, client, this.config, false);
|
||||
|
||||
@@ -9,6 +9,7 @@ class DesktopManager {
|
||||
private readonly config: Desktop.Config,
|
||||
private readonly layoutConfig: LayoutConfig,
|
||||
private readonly focusPasser: FocusPassing.Passer,
|
||||
private readonly desktopFilter: DesktopFilter,
|
||||
currentActivity: string,
|
||||
currentDesktop: KwinDesktop,
|
||||
) {
|
||||
@@ -19,10 +20,15 @@ class DesktopManager {
|
||||
this.selectedScreen = Workspace.activeScreen;
|
||||
this.kwinActivities = new Set(Workspace.activities);
|
||||
this.kwinDesktops = new Set(Workspace.desktops);
|
||||
this.addDesktop(currentActivity, currentDesktop);
|
||||
if (this.desktopFilter.shouldWorkOnDesktop(currentDesktop)) {
|
||||
this.addDesktop(currentActivity, currentDesktop);
|
||||
}
|
||||
}
|
||||
|
||||
public getDesktop(activity: string, kwinDesktop: KwinDesktop) {
|
||||
if (!this.desktopFilter.shouldWorkOnDesktop(kwinDesktop)) {
|
||||
return undefined;
|
||||
}
|
||||
const desktopKey = DesktopManager.getDesktopKey(activity, kwinDesktop);
|
||||
const desktop = this.desktops.get(desktopKey);
|
||||
if (desktop !== undefined) {
|
||||
|
||||
@@ -5,12 +5,10 @@ class World {
|
||||
private readonly workspaceSignalManager: SignalManager;
|
||||
private readonly shortcutActions: ShortcutAction[];
|
||||
private readonly screenResizedDelayer: Delayer;
|
||||
private readonly cursorFollowsFocus: boolean;
|
||||
|
||||
constructor(config: Config) {
|
||||
const focusPasser = new FocusPassing.Passer();
|
||||
this.workspaceSignalManager = initWorkspaceSignalHandlers(this, focusPasser);
|
||||
this.cursorFollowsFocus = config.cursorFollowsFocus;
|
||||
|
||||
let presetWidths = {
|
||||
next: (currentWidth: number, minWidth: number, maxWidth: number) => currentWidth,
|
||||
@@ -70,6 +68,7 @@ class World {
|
||||
},
|
||||
layoutConfig,
|
||||
focusPasser,
|
||||
new DesktopFilter(config.tiledDesktops),
|
||||
Workspace.currentActivity,
|
||||
Workspace.currentDesktop,
|
||||
);
|
||||
@@ -98,12 +97,20 @@ class World {
|
||||
}
|
||||
|
||||
private update() {
|
||||
this.desktopManager.getCurrentDesktop().arrange();
|
||||
this.moveCursorToFocus();
|
||||
const currentDesktop = this.desktopManager.getCurrentDesktop();
|
||||
if (currentDesktop !== undefined) {
|
||||
currentDesktop.arrange();
|
||||
this.moveCursorToFocus();
|
||||
}
|
||||
}
|
||||
|
||||
private moveCursorToFocus() {
|
||||
if (this.cursorFollowsFocus && Workspace.activeWindow !== null) {
|
||||
if (Workspace.activeWindow !== null) {
|
||||
// Only move cursor for tiled windows
|
||||
const tiledWindow = this.clientManager.findTiledWindow(Workspace.activeWindow);
|
||||
if (tiledWindow === null) {
|
||||
return;
|
||||
}
|
||||
const cursorAlreadyInFocus = rectContainsPoint(Workspace.activeWindow.frameGeometry, Workspace.cursorPos);
|
||||
if (cursorAlreadyInFocus) {
|
||||
return;
|
||||
@@ -141,11 +148,21 @@ class World {
|
||||
}
|
||||
|
||||
public gestureScroll(amount: number) {
|
||||
this.do((clientManager, desktopManager) => desktopManager.getCurrentDesktop().gestureScroll(amount));
|
||||
this.do((clientManager, desktopManager) => {
|
||||
const currentDesktop = desktopManager.getCurrentDesktop();
|
||||
if (currentDesktop !== undefined) {
|
||||
currentDesktop.gestureScroll(amount);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public gestureScrollFinish() {
|
||||
this.do((clientManager, desktopManager) => desktopManager.getCurrentDesktop().gestureScrollFinish());
|
||||
this.do((clientManager, desktopManager) => {
|
||||
const currentDesktop = desktopManager.getCurrentDesktop();
|
||||
if (currentDesktop !== undefined) {
|
||||
currentDesktop.gestureScrollFinish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
|
||||
@@ -34,3 +34,49 @@ tests.register("Drag tiled window, untile", 10, () => {
|
||||
Workspace.activeWindow = null;
|
||||
Assert.assert(pointEquals(Workspace.cursorPos, lastCursorPos), { message: "Cursor should not have been moved" });
|
||||
});
|
||||
|
||||
tests.register("Cursor follows focus only on matched desktops", 1, () => {
|
||||
// Test that cursor follow focus only works for windows on matched desktops (tiled windows)
|
||||
const config = getDefaultConfig();
|
||||
config.cursorFollowsFocus = true;
|
||||
config.tiledDesktops = "^Desktop 1$"; // Only work on Desktop 1
|
||||
const { workspaceMock, world } = init(config);
|
||||
|
||||
// Create a client on Desktop 1 (matched desktop) - should be tiled
|
||||
const client1 = new MockKwinClient();
|
||||
client1.desktops = [workspaceMock.desktops[0]]; // Desktop 1
|
||||
workspaceMock.createWindows(client1);
|
||||
|
||||
// Create a client on Desktop 2 (non-matched desktop) - should be floating
|
||||
const client2 = new MockKwinClient();
|
||||
client2.desktops = [workspaceMock.desktops[1]]; // Desktop 2
|
||||
workspaceMock.createWindows(client2);
|
||||
|
||||
// Set initial cursor position outside both windows
|
||||
const initialCursorPos = new MockQmlPoint(10, 10);
|
||||
workspaceMock.cursorPos = initialCursorPos.clone();
|
||||
|
||||
// Test 1: Focus client1 on matched desktop (Desktop 1) - cursor should move
|
||||
workspaceMock.currentDesktop = workspaceMock.desktops[0]; // Switch to Desktop 1
|
||||
Workspace.activeWindow = client1;
|
||||
world.do(() => {});
|
||||
Assert.assert(rectContainsPoint(client1.frameGeometry, Workspace.cursorPos),
|
||||
{ message: "Cursor should have moved to tiled window on matched desktop" });
|
||||
|
||||
// Test 2: Switch to non-matched desktop (Desktop 2) and focus client2 - cursor should NOT move
|
||||
workspaceMock.cursorPos = initialCursorPos.clone();
|
||||
workspaceMock.currentDesktop = workspaceMock.desktops[1]; // Switch to Desktop 2
|
||||
Workspace.activeWindow = client2;
|
||||
world.do(() => {});
|
||||
Assert.assert(pointEquals(Workspace.cursorPos, initialCursorPos),
|
||||
{ message: "Cursor should NOT move on non-matched desktop" });
|
||||
|
||||
// Test 3: Even if we focus client1 (tiled) while on Desktop 2, cursor should NOT move
|
||||
// because the current desktop is not matched
|
||||
workspaceMock.cursorPos = initialCursorPos.clone();
|
||||
workspaceMock.currentDesktop = workspaceMock.desktops[1]; // Stay on Desktop 2
|
||||
Workspace.activeWindow = client1;
|
||||
world.do(() => {});
|
||||
Assert.assert(pointEquals(Workspace.cursorPos, initialCursorPos),
|
||||
{ message: "Cursor should NOT move even for tiled window when current desktop is not matched" });
|
||||
});
|
||||
|
||||
73
src/tests/flows/desktopFiltering.ts
Normal file
73
src/tests/flows/desktopFiltering.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
tests.register("Desktop filtering", 1, () => {
|
||||
// Test 1: Default config should work on all desktops
|
||||
const config1 = getDefaultConfig();
|
||||
const { workspaceMock: wm1, world: world1 } = init(config1);
|
||||
|
||||
const client1 = new MockKwinClient();
|
||||
client1.desktops = [wm1.desktops[0]];
|
||||
wm1.createWindows(client1);
|
||||
|
||||
world1.do((clientManager) => {
|
||||
Assert.tiledClient(clientManager, client1, { message: "Client should be tiled on desktop1 with default config (*)" });
|
||||
});
|
||||
});
|
||||
|
||||
tests.register("Desktop filtering - specific desktop", 1, () => {
|
||||
// Test 2: Specific desktop name - should work only on matching desktop
|
||||
const config2 = getDefaultConfig();
|
||||
config2.tiledDesktops = "^Desktop 1$";
|
||||
const { workspaceMock: wm2, world: world2 } = init(config2);
|
||||
|
||||
const client1 = new MockKwinClient();
|
||||
client1.desktops = [wm2.desktops[0]]; // Desktop 1
|
||||
wm2.createWindows(client1);
|
||||
world2.do((clientManager) => {
|
||||
Assert.tiledClient(clientManager, client1, { message: "Client should be tiled on Desktop 1" });
|
||||
});
|
||||
|
||||
wm2.removeWindow(client1);
|
||||
|
||||
const client2 = new MockKwinClient();
|
||||
client2.desktops = [wm2.desktops[1]]; // Desktop 2
|
||||
wm2.createWindows(client2);
|
||||
world2.do((clientManager) => {
|
||||
Assert.notTiledClient(clientManager, client2, { message: "Client should NOT be tiled on Desktop 2" });
|
||||
});
|
||||
});
|
||||
|
||||
tests.register("Desktop filtering - multiple desktops", 1, () => {
|
||||
// Test 3: Multiple desktop names using regex alternation
|
||||
const config3 = getDefaultConfig();
|
||||
config3.tiledDesktops = "^Desktop [12]$";
|
||||
const { workspaceMock: wm3, world: world3 } = init(config3);
|
||||
|
||||
const client1 = new MockKwinClient();
|
||||
client1.desktops = [wm3.desktops[0]]; // Desktop 1
|
||||
wm3.createWindows(client1);
|
||||
world3.do((clientManager) => {
|
||||
Assert.tiledClient(clientManager, client1, { message: "Client should be tiled on Desktop 1" });
|
||||
});
|
||||
|
||||
wm3.removeWindow(client1);
|
||||
|
||||
const client2 = new MockKwinClient();
|
||||
client2.desktops = [wm3.desktops[1]]; // Desktop 2
|
||||
wm3.createWindows(client2);
|
||||
world3.do((clientManager) => {
|
||||
Assert.tiledClient(clientManager, client2, { message: "Client should be tiled on Desktop 2" });
|
||||
});
|
||||
});
|
||||
|
||||
tests.register("Desktop filtering - windows on multiple desktops", 1, () => {
|
||||
// Test 4: Windows on multiple desktops should not be tiled (fallback to floating)
|
||||
const config4 = getDefaultConfig();
|
||||
config4.tiledDesktops = ".*";
|
||||
const { workspaceMock: wm4, world: world4 } = init(config4);
|
||||
|
||||
const client1 = new MockKwinClient();
|
||||
client1.desktops = [wm4.desktops[0], wm4.desktops[1]]; // Multiple desktops
|
||||
wm4.createWindows(client1);
|
||||
world4.do((clientManager) => {
|
||||
Assert.notTiledClient(clientManager, client1, { message: "Client on multiple desktops should not be tiled" });
|
||||
});
|
||||
});
|
||||
41
src/tests/units/rules/DesktopFilter.ts
Normal file
41
src/tests/units/rules/DesktopFilter.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
tests.register("DesktopFilter", 1, () => {
|
||||
const desktop1 = { __brand: "KwinDesktop" as const, id: "1", name: "Desktop 1" };
|
||||
const desktop2 = { __brand: "KwinDesktop" as const, id: "2", name: "Work" };
|
||||
const desktop3 = { __brand: "KwinDesktop" as const, id: "3", name: "Desktop 2" };
|
||||
|
||||
// Test 1: Empty config means all desktops
|
||||
let filter = new DesktopFilter("");
|
||||
Assert.assert(filter.shouldWorkOnDesktop(desktop1), { message: "Empty config should work on desktop1" });
|
||||
Assert.assert(filter.shouldWorkOnDesktop(desktop2), { message: "Empty config should work on desktop2" });
|
||||
|
||||
// Test 2: Whitespace only means all desktops
|
||||
filter = new DesktopFilter(" \n \n ");
|
||||
Assert.assert(filter.shouldWorkOnDesktop(desktop1), { message: "Whitespace only should work on desktop1" });
|
||||
Assert.assert(filter.shouldWorkOnDesktop(desktop2), { message: "Whitespace only should work on desktop2" });
|
||||
|
||||
// Test 3: Match all regex pattern
|
||||
filter = new DesktopFilter(".*");
|
||||
Assert.assert(filter.shouldWorkOnDesktop(desktop1), { message: "Regex '.*' should work on desktop1" });
|
||||
Assert.assert(filter.shouldWorkOnDesktop(desktop2), { message: "Regex '.*' should work on desktop2" });
|
||||
|
||||
// Test 4: Partial match without anchors
|
||||
filter = new DesktopFilter("Work");
|
||||
Assert.assert(!filter.shouldWorkOnDesktop(desktop1), { message: "Should not work on desktop1" });
|
||||
Assert.assert(filter.shouldWorkOnDesktop(desktop2), { message: "Should work on desktop2 containing 'Work'" });
|
||||
|
||||
// Test 5: Regex alternation for multiple desktops
|
||||
filter = new DesktopFilter("Desktop 1|Work");
|
||||
Assert.assert(filter.shouldWorkOnDesktop(desktop1), { message: "Should work on desktop1" });
|
||||
Assert.assert(filter.shouldWorkOnDesktop(desktop2), { message: "Should work on desktop2" });
|
||||
Assert.assert(!filter.shouldWorkOnDesktop(desktop3), { message: "Should not work on desktop3" });
|
||||
|
||||
// Test 6: Regex pattern with character class
|
||||
filter = new DesktopFilter("Desktop [12]");
|
||||
Assert.assert(filter.shouldWorkOnDesktop(desktop1), { message: "Should work on desktop1" });
|
||||
Assert.assert(!filter.shouldWorkOnDesktop(desktop2), { message: "Should not work on desktop2" });
|
||||
Assert.assert(filter.shouldWorkOnDesktop(desktop3), { message: "Should work on desktop3" });
|
||||
|
||||
// Test 7: Case-sensitive matching
|
||||
filter = new DesktopFilter("work");
|
||||
Assert.assert(!filter.shouldWorkOnDesktop(desktop2), { message: "Should not work on desktop2 (case mismatch)" });
|
||||
});
|
||||
@@ -52,6 +52,7 @@ class MockKwinClient {
|
||||
this.windowedFrameGeometry = _frameGeometry.clone();
|
||||
this.transient = transientFor !== null;
|
||||
this._desktops = [Workspace.currentDesktop];
|
||||
this.activities = [Workspace.currentActivity];
|
||||
}
|
||||
|
||||
setMaximize(vertically: boolean, horizontally: boolean) {
|
||||
|
||||
@@ -3,8 +3,8 @@ class MockWorkspace {
|
||||
|
||||
public activities = ["test-activity"];
|
||||
public desktops: KwinDesktop[] = [
|
||||
{ __brand: "KwinDesktop", id: "desktop1" },
|
||||
{ __brand: "KwinDesktop", id: "desktop2" },
|
||||
{ __brand: "KwinDesktop", id: "desktop1", name: "Desktop 1" },
|
||||
{ __brand: "KwinDesktop", id: "desktop2", name: "Desktop 2" },
|
||||
];
|
||||
public currentActivity = this.activities[0];
|
||||
public activeScreen: Output = { __brand: "Output" };
|
||||
|
||||
Reference in New Issue
Block a user