Compare commits
9 Commits
signal-gro
...
v0.15
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d4eab03b9 | ||
|
|
7070e59044 | ||
|
|
7f5745b2cf | ||
|
|
c7752bf20a | ||
|
|
8149100aac | ||
|
|
99bf71f0b9 | ||
|
|
2b882768d9 | ||
|
|
bb42e4d3ad | ||
|
|
c7effc8913 |
@@ -32,7 +32,7 @@
|
||||
<item>
|
||||
<widget class="QCheckBox" name="kcfg_cursorFollowsFocus">
|
||||
<property name="text">
|
||||
<string>Cursor follows focus</string>
|
||||
<string>Cursor follows focus (experimental)</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>When a window gains focus, move the cursor to it</string>
|
||||
@@ -458,6 +458,27 @@
|
||||
<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="toolTip">
|
||||
<string>Regex string to match desktops by desktop name"</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="kcfg_windowRules">
|
||||
<property name="tabChangesFocus">
|
||||
|
||||
@@ -16,6 +16,16 @@ Item {
|
||||
qmlBase.karouselInstance.destroy();
|
||||
}
|
||||
|
||||
Notification {
|
||||
id: notificationInvalidTiledDesktops
|
||||
componentName: "plasma_workspace"
|
||||
eventId: "notification"
|
||||
title: "Karousel"
|
||||
text: "Your Tiled Desktops regex is malformed, please review your Karousel configuration"
|
||||
flags: Notification.Persistent
|
||||
urgency: Notification.HighUrgency
|
||||
}
|
||||
|
||||
Notification {
|
||||
id: notificationInvalidWindowRules
|
||||
componentName: "plasma_workspace"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"Name": "Peter Fajdiga"
|
||||
}],
|
||||
"Id": "karousel",
|
||||
"Version": "0.14",
|
||||
"Version": "0.15",
|
||||
"License": "GPLv3",
|
||||
"Website": "https://github.com/peterfajdiga/karousel",
|
||||
"BugReportUrl": "https://github.com/peterfajdiga/karousel/issues"
|
||||
|
||||
1
src/extern/global.d.ts
vendored
1
src/extern/global.d.ts
vendored
@@ -2,6 +2,7 @@ declare const Qt: Qt;
|
||||
declare const KWin: KWin;
|
||||
declare const Workspace: Workspace;
|
||||
declare const qmlBase: QmlObject;
|
||||
declare const notificationInvalidTiledDesktops: Notification;
|
||||
declare const notificationInvalidWindowRules: Notification;
|
||||
declare const notificationInvalidPresetWidths: Notification;
|
||||
declare const moveCursorToFocus: DBusCall;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
30
src/lib/rules/DesktopFilter.ts
Normal file
30
src/lib/rules/DesktopFilter.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
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) {
|
||||
notificationInvalidTiledDesktops.sendEvent();
|
||||
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,8 +9,7 @@ class DesktopManager {
|
||||
private readonly config: Desktop.Config,
|
||||
private readonly layoutConfig: LayoutConfig,
|
||||
private readonly focusPasser: FocusPassing.Passer,
|
||||
currentActivity: string,
|
||||
currentDesktop: KwinDesktop,
|
||||
private readonly desktopFilter: DesktopFilter,
|
||||
) {
|
||||
this.pinManager = pinManager;
|
||||
this.config = config;
|
||||
@@ -19,10 +18,12 @@ class DesktopManager {
|
||||
this.selectedScreen = Workspace.activeScreen;
|
||||
this.kwinActivities = new Set(Workspace.activities);
|
||||
this.kwinDesktops = new Set(Workspace.desktops);
|
||||
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) {
|
||||
|
||||
@@ -70,8 +70,7 @@ class World {
|
||||
},
|
||||
layoutConfig,
|
||||
focusPasser,
|
||||
Workspace.currentActivity,
|
||||
Workspace.currentDesktop,
|
||||
new DesktopFilter(config.tiledDesktops),
|
||||
);
|
||||
this.clientManager = new ClientManager(config, this, this.desktopManager, this.pinManager);
|
||||
this.addExistingClients();
|
||||
@@ -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) {
|
||||
// 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)" });
|
||||
});
|
||||
@@ -2,6 +2,7 @@ let Qt: Qt;
|
||||
let KWin: KWin;
|
||||
let Workspace: Workspace;
|
||||
let qmlBase: QmlObject;
|
||||
let notificationInvalidTiledDesktops: Notification;
|
||||
let notificationInvalidWindowRules: Notification;
|
||||
let notificationInvalidPresetWidths: Notification;
|
||||
let moveCursorToFocus: DBusCall;
|
||||
|
||||
@@ -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