4 Commits

Author SHA1 Message Date
Peter Fajdiga
aec5750dc0 add TODOs 2024-07-08 20:52:13 +02:00
Peter Fajdiga
6784259c12 Desktop: implement per-screen desktops 2024-07-08 20:25:09 +02:00
Peter Fajdiga
23186bbe91 DesktopManager: remove desktops for removed screens 2024-07-08 20:25:09 +02:00
Peter Fajdiga
d7df3901e2 DesktopManager: add per-screen support 2024-07-08 20:25:09 +02:00
7 changed files with 104 additions and 43 deletions

View File

@@ -8,6 +8,7 @@ type Workspace = {
readonly currentDesktop: KwinDesktop; readonly currentDesktop: KwinDesktop;
readonly currentActivity: string; readonly currentActivity: string;
readonly activeScreen: Output; readonly activeScreen: Output;
readonly screens: Output[];
readonly windows: KwinClient[]; readonly windows: KwinClient[];
readonly cursorPos: Readonly<QmlPoint>; readonly cursorPos: Readonly<QmlPoint>;
@@ -17,8 +18,9 @@ type Workspace = {
readonly windowAdded: QSignal<[KwinClient]>; readonly windowAdded: QSignal<[KwinClient]>;
readonly windowRemoved: QSignal<[KwinClient]>; readonly windowRemoved: QSignal<[KwinClient]>;
readonly windowActivated: QSignal<[KwinClient]>; readonly windowActivated: QSignal<[KwinClient]>;
readonly desktopsChanged: QSignal<[]>; readonly screensChanged: QSignal<[]>;
readonly activitiesChanged: QSignal<[]>; readonly activitiesChanged: QSignal<[]>;
readonly desktopsChanged: QSignal<[]>;
readonly currentActivityChanged: QSignal<[]>; readonly currentActivityChanged: QSignal<[]>;
readonly virtualScreenSizeChanged: QSignal<[]>; readonly virtualScreenSizeChanged: QSignal<[]>;
@@ -44,7 +46,10 @@ const enum MaximizedMode {
} }
type Tile = unknown; type Tile = unknown;
type Output = unknown;
type Output = {
name: string;
};
interface KwinClient { interface KwinClient {
readonly shadeable: boolean; readonly shadeable: boolean;
@@ -81,6 +86,7 @@ interface KwinClient {
readonly fullScreenChanged: QSignal<[]>; readonly fullScreenChanged: QSignal<[]>;
readonly desktopsChanged: QSignal<[]>; readonly desktopsChanged: QSignal<[]>;
readonly outputChanged: QSignal<[]>;
readonly activitiesChanged: QSignal<[]>; readonly activitiesChanged: QSignal<[]>;
readonly minimizedChanged: QSignal<[]>; readonly minimizedChanged: QSignal<[]>;
readonly maximizedAboutToChange: QSignal<[MaximizedMode]> readonly maximizedAboutToChange: QSignal<[MaximizedMode]>

View File

@@ -1,5 +1,6 @@
class Desktop { class Desktop {
public readonly grid: Grid; public readonly grid: Grid;
public readonly screen: Output;
public readonly kwinDesktop: KwinDesktop; public readonly kwinDesktop: KwinDesktop;
private readonly pinManager: PinManager; private readonly pinManager: PinManager;
private readonly config: Desktop.Config; private readonly config: Desktop.Config;
@@ -10,21 +11,22 @@ class Desktop {
public clientArea: QmlRect; public clientArea: QmlRect;
public tilingArea: QmlRect; public tilingArea: QmlRect;
constructor(kwinDesktop: KwinDesktop, pinManager: PinManager, config: Desktop.Config, layoutConfig: LayoutConfig) { constructor(screen: Output, kwinDesktop: KwinDesktop, pinManager: PinManager, config: Desktop.Config, layoutConfig: LayoutConfig) {
this.pinManager = pinManager; this.pinManager = pinManager;
this.config = config; this.config = config;
this.scrollX = 0; this.scrollX = 0;
this.dirty = true; this.dirty = true;
this.dirtyScroll = true; this.dirtyScroll = true;
this.dirtyPins = true; this.dirtyPins = true;
this.screen = screen;
this.kwinDesktop = kwinDesktop; this.kwinDesktop = kwinDesktop;
this.grid = new Grid(this, layoutConfig); this.grid = new Grid(this, layoutConfig);
this.clientArea = Desktop.getClientArea(kwinDesktop); this.clientArea = Desktop.getClientArea(screen, kwinDesktop);
this.tilingArea = Desktop.getTilingArea(this.clientArea, kwinDesktop, pinManager, config); this.tilingArea = Desktop.getTilingArea(this.clientArea, kwinDesktop, pinManager, config);
} }
private updateArea() { private updateArea() {
const newClientArea = Desktop.getClientArea(this.kwinDesktop); const newClientArea = Desktop.getClientArea(this.screen, this.kwinDesktop);
if (newClientArea === this.clientArea && !this.dirtyPins) { if (newClientArea === this.clientArea && !this.dirtyPins) {
return; return;
} }
@@ -37,8 +39,8 @@ class Desktop {
this.autoAdjustScroll(); this.autoAdjustScroll();
} }
private static getClientArea(kwinDesktop: KwinDesktop) { private static getClientArea(screen: Output, kwinDesktop: KwinDesktop) {
return Workspace.clientArea(ClientAreaOption.PlacementArea, Workspace.activeScreen, kwinDesktop); return Workspace.clientArea(ClientAreaOption.PlacementArea, screen, kwinDesktop);
} }
private static getTilingArea(clientArea: QmlRect, kwinDesktop: KwinDesktop, pinManager: PinManager, config: Desktop.Config) { private static getTilingArea(clientArea: QmlRect, kwinDesktop: KwinDesktop, pinManager: PinManager, config: Desktop.Config) {

View File

@@ -34,19 +34,25 @@ function initWorkspaceSignalHandlers(world: World) {
world.do(() => {}); // re-arrange desktop world.do(() => {}); // re-arrange desktop
}); });
manager.connect(Workspace.screensChanged, () => {
world.do((clientManager, desktopManager) => {
desktopManager.updateScreens();
})
});
manager.connect(Workspace.activitiesChanged, () => {
world.do((clientManager, desktopManager) => {
desktopManager.updateActivities();
})
});
manager.connect(Workspace.desktopsChanged, () => { manager.connect(Workspace.desktopsChanged, () => {
world.do((clientManager, desktopManager) => { world.do((clientManager, desktopManager) => {
desktopManager.updateDesktops(); desktopManager.updateDesktops();
}) })
}); });
manager.connect(Workspace.activitiesChanged, () => { manager.connect(Workspace.virtualScreenSizeChanged, () => {
world.do((clientManager, desktopManager) => {
desktopManager.updateActivities();
})
});
manager.connect(Workspace.virtualScreenSizeChanged, () => {
world.onScreenResized(); world.onScreenResized();
}); });

View File

@@ -1,55 +1,76 @@
class DesktopManager { class DesktopManager {
// TODO: fix issue with removed and re-added screens
private readonly pinManager: PinManager; private readonly pinManager: PinManager;
private readonly config: Desktop.Config; private readonly config: Desktop.Config;
public readonly layoutConfig: LayoutConfig; public readonly layoutConfig: LayoutConfig;
private readonly desktops: Map<string, Desktop>; // key is activityId|desktopId private readonly desktops: Map<string, Desktop>; // key is activityId|desktopId
private kwinScreens: Set<Output>;
private kwinActivities: Set<string>; private kwinActivities: Set<string>;
private kwinDesktops: Set<KwinDesktop>; private kwinDesktops: Set<KwinDesktop>;
constructor(pinManager: PinManager, config: Desktop.Config, layoutConfig: LayoutConfig, currentActivity: string, currentDesktop: KwinDesktop) { constructor(
pinManager: PinManager,
config: Desktop.Config,
layoutConfig: LayoutConfig,
currentScreen: Output,
currentActivity: string,
currentDesktop: KwinDesktop
) {
this.pinManager = pinManager; this.pinManager = pinManager;
this.config = config; this.config = config;
this.layoutConfig = layoutConfig; this.layoutConfig = layoutConfig;
this.desktops = new Map(); this.desktops = new Map();
this.kwinScreens = new Set(Workspace.screens);
this.kwinActivities = new Set(Workspace.activities); this.kwinActivities = new Set(Workspace.activities);
this.kwinDesktops = new Set(Workspace.desktops); this.kwinDesktops = new Set(Workspace.desktops);
this.addDesktop(currentActivity, currentDesktop); this.addDesktop(currentScreen, currentActivity, currentDesktop);
} }
public getDesktop(activity: string, kwinDesktop: KwinDesktop) { public getDesktop(screen: Output, activity: string, kwinDesktop: KwinDesktop) {
const desktopKey = DesktopManager.getDesktopKey(activity, kwinDesktop); const desktopKey = DesktopManager.getDesktopKey(screen, activity, kwinDesktop);
const desktop = this.desktops.get(desktopKey); const desktop = this.desktops.get(desktopKey);
if (desktop !== undefined) { if (desktop !== undefined) {
return desktop; return desktop;
} else { } else {
return this.addDesktop(activity, kwinDesktop); return this.addDesktop(screen, activity, kwinDesktop);
} }
} }
public getCurrentDesktop() { public getCurrentDesktop() {
return this.getDesktop(Workspace.currentActivity, Workspace.currentDesktop); return this.getDesktop(Workspace.activeScreen, Workspace.currentActivity, Workspace.currentDesktop);
} }
public getDesktopInCurrentActivity(kwinDesktop: KwinDesktop) { public getDesktopInCurrentActivity(kwinDesktop: KwinDesktop) {
return this.getDesktop(Workspace.currentActivity, kwinDesktop); return this.getDesktop(Workspace.activeScreen, Workspace.currentActivity, kwinDesktop);
} }
public getDesktopForClient(kwinClient: KwinClient) { public getDesktopForClient(kwinClient: KwinClient) {
if (kwinClient.activities.length !== 1 || kwinClient.desktops.length !== 1) { if (kwinClient.activities.length !== 1 || kwinClient.desktops.length !== 1) {
return undefined; return undefined;
} }
return this.getDesktop(kwinClient.activities[0], kwinClient.desktops[0]); return this.getDesktop(kwinClient.output, kwinClient.activities[0], kwinClient.desktops[0]);
} }
private addDesktop(activity: string, kwinDesktop: KwinDesktop) { private addDesktop(screen: Output, activity: string, kwinDesktop: KwinDesktop) {
const desktopKey = DesktopManager.getDesktopKey(activity, kwinDesktop); const desktopKey = DesktopManager.getDesktopKey(screen, activity, kwinDesktop);
const desktop = new Desktop(kwinDesktop, this.pinManager, this.config, this.layoutConfig); const desktop = new Desktop(screen, kwinDesktop, this.pinManager, this.config, this.layoutConfig);
this.desktops.set(desktopKey, desktop); this.desktops.set(desktopKey, desktop);
return desktop; return desktop;
} }
private static getDesktopKey(activity: string, kwinDesktop: KwinDesktop) { private static getDesktopKey(screen: Output, activity: string, kwinDesktop: KwinDesktop) {
return activity + "|" + kwinDesktop.id; return screen.name + "|" + activity + "|" + kwinDesktop.id;
}
public updateScreens() {
const newScreens = new Set(Workspace.screens);
for (const screen of this.kwinScreens) {
if (!newScreens.has(screen)) {
this.removeScreen(screen);
}
}
this.kwinScreens = newScreens;
} }
public updateActivities() { public updateActivities() {
@@ -72,20 +93,32 @@ class DesktopManager {
this.kwinDesktops = newDesktops; this.kwinDesktops = newDesktops;
} }
private removeScreen(kwinScreen: Output) {
for (const activity of this.kwinActivities) {
for (const kwinDesktop of this.kwinDesktops) {
this.destroyDesktop(kwinScreen, activity, kwinDesktop);
}
}
}
private removeActivity(activity: string) { private removeActivity(activity: string) {
for (const kwinDesktop of this.kwinDesktops) { for (const kwinScreen of this.kwinScreens) {
this.destroyDesktop(activity, kwinDesktop); for (const kwinDesktop of this.kwinDesktops) {
this.destroyDesktop(kwinScreen, activity, kwinDesktop);
}
} }
} }
private removeKwinDesktop(kwinDesktop: KwinDesktop) { private removeKwinDesktop(kwinDesktop: KwinDesktop) {
for (const activity of this.kwinActivities) { for (const kwinScreen of this.kwinScreens) {
this.destroyDesktop(activity, kwinDesktop); for (const activity of this.kwinActivities) {
this.destroyDesktop(kwinScreen, activity, kwinDesktop);
}
} }
} }
private destroyDesktop(activity: string, kwinDesktop: KwinDesktop) { private destroyDesktop(screen: Output, activity: string, kwinDesktop: KwinDesktop) {
const desktopKey = DesktopManager.getDesktopKey(activity, kwinDesktop); const desktopKey = DesktopManager.getDesktopKey(screen, activity, kwinDesktop);
const desktop = this.desktops.get(desktopKey); const desktop = this.desktops.get(desktopKey);
if (desktop !== undefined) { if (desktop !== undefined) {
desktop.destroy(); desktop.destroy();
@@ -106,20 +139,23 @@ class DesktopManager {
} }
public getDesktopsForClient(kwinClient: KwinClient) { public getDesktopsForClient(kwinClient: KwinClient) {
const desktops = this.getDesktops(kwinClient.activities, kwinClient.desktops); // workaround for QTBUG-109880 const desktops = this.getDesktops([kwinClient.output], kwinClient.activities, kwinClient.desktops); // workaround for QTBUG-109880
return desktops; return desktops;
} }
// empty array means all // empty array means all
public *getDesktops(activities: string[], kwinDesktops: KwinDesktop[]) { public *getDesktops(screens: Output[], activities: string[], kwinDesktops: KwinDesktop[]) {
const matchedScreens = screens.length > 0 ? screens : this.kwinScreens.keys();
const matchedActivities = activities.length > 0 ? activities : this.kwinActivities.keys(); const matchedActivities = activities.length > 0 ? activities : this.kwinActivities.keys();
const matchedDesktops = kwinDesktops.length > 0 ? kwinDesktops : this.kwinDesktops.keys(); const matchedDesktops = kwinDesktops.length > 0 ? kwinDesktops : this.kwinDesktops.keys();
for (const matchedActivity of matchedActivities) { for (const matchedScreen of matchedScreens) {
for (const matchedDesktop of matchedDesktops) { for (const matchedActivity of matchedActivities) {
const desktopKey = DesktopManager.getDesktopKey(matchedActivity, matchedDesktop); for (const matchedDesktop of matchedDesktops) {
const desktop = this.desktops.get(desktopKey); const desktopKey = DesktopManager.getDesktopKey(matchedScreen, matchedActivity, matchedDesktop);
if (desktop !== undefined) { const desktop = this.desktops.get(desktopKey);
yield desktop; if (desktop !== undefined) {
yield desktop;
}
} }
} }
} }

View File

@@ -1,4 +1,6 @@
class PinManager { class PinManager {
// TODO: per-screen
private readonly pinnedClients: Set<KwinClient>; private readonly pinnedClients: Set<KwinClient>;
constructor() { constructor() {

View File

@@ -49,6 +49,7 @@ class World {
clamper: config.scrollingLazy ? new EdgeClamper() : new CenterClamper(), clamper: config.scrollingLazy ? new EdgeClamper() : new CenterClamper(),
}, },
layoutConfig, layoutConfig,
Workspace.activeScreen,
Workspace.currentActivity, Workspace.currentActivity,
Workspace.currentDesktop, Workspace.currentDesktop,
); );

View File

@@ -61,7 +61,7 @@ namespace ClientState {
[] : [] :
union(oldDesktops, kwinClient.desktops); union(oldDesktops, kwinClient.desktops);
world.do((clientManager, desktopManager) => { world.do((clientManager, desktopManager) => {
for (const desktop of desktopManager.getDesktops(kwinClient.activities, changedDesktops)) { for (const desktop of desktopManager.getDesktops([kwinClient.output], kwinClient.activities, changedDesktops)) {
desktop.onPinsChanged(); desktop.onPinsChanged();
} }
}); });
@@ -73,13 +73,21 @@ namespace ClientState {
[] : [] :
union(oldActivities, kwinClient.activities); union(oldActivities, kwinClient.activities);
world.do((clientManager, desktopManager) => { world.do((clientManager, desktopManager) => {
for (const desktop of desktopManager.getDesktops(changedActivities, kwinClient.desktops)) { for (const desktop of desktopManager.getDesktops([kwinClient.output], changedActivities, kwinClient.desktops)) {
desktop.onPinsChanged(); desktop.onPinsChanged();
} }
}); });
oldActivities = kwinClient.activities; oldActivities = kwinClient.activities;
}); });
manager.connect(kwinClient.outputChanged, () => {
world.do((clientManager, desktopManager) => {
for (const desktop of desktopManager.getDesktops([kwinClient.output], kwinClient.activities, kwinClient.desktops)) {
desktop.onPinsChanged();
}
});
});
return manager; return manager;
} }
} }