create ClientState namespace

This commit is contained in:
Peter Fajdiga
2023-08-25 15:27:16 +02:00
parent 4f06f17ba7
commit 0bdb4af0e6
8 changed files with 192 additions and 186 deletions

View File

@@ -24,17 +24,17 @@ class ClientManager {
console.assert(!this.hasClient(kwinClient));
const client = new ClientWrapper(
kwinClient,
new ClientStateFloating(),
new ClientState.Floating(),
this.findTransientFor(kwinClient),
this.windowRuleEnforcer.initClientSignalManager(this.world, kwinClient),
);
this.clientMap.set(kwinClient, client);
if (kwinClient.dock) {
client.stateManager.setState(new ClientStateDocked(this.world, kwinClient), false);
client.stateManager.setState(new ClientState.Docked(this.world, kwinClient), false);
} else if (this.windowRuleEnforcer.shouldTile(kwinClient)) {
const grid = this.desktopManager.getDesktopForClient(client.kwinClient).grid;
client.stateManager.setState(new ClientStateTiled(this.world, client, grid), false);
client.stateManager.setState(new ClientState.Tiled(this.world, client, grid), false);
}
}
@@ -66,8 +66,8 @@ class ClientManager {
if (client === undefined) {
return;
}
if (client.stateManager.getState() instanceof ClientStateTiled) {
client.stateManager.setState(new ClientStateTiledMinimized(), kwinClient === this.lastFocusedClient);
if (client.stateManager.getState() instanceof ClientState.Tiled) {
client.stateManager.setState(new ClientState.TiledMinimized(), kwinClient === this.lastFocusedClient);
}
}
@@ -76,9 +76,9 @@ class ClientManager {
if (client === undefined) {
return;
}
if (client.stateManager.getState() instanceof ClientStateTiledMinimized) {
if (client.stateManager.getState() instanceof ClientState.TiledMinimized) {
const grid = this.desktopManager.getDesktopForClient(client.kwinClient).grid;
client.stateManager.setState(new ClientStateTiled(this.world, client, grid), false);
client.stateManager.setState(new ClientState.Tiled(this.world, client, grid), false);
}
}
@@ -87,11 +87,11 @@ class ClientManager {
if (client === undefined) {
return;
}
if (client.stateManager.getState() instanceof ClientStateTiled) {
if (client.stateManager.getState() instanceof ClientState.Tiled) {
return;
}
const grid = this.desktopManager.getDesktopForClient(client.kwinClient).grid;
client.stateManager.setState(new ClientStateTiled(this.world, client, grid), false);
client.stateManager.setState(new ClientState.Tiled(this.world, client, grid), false);
}
public untileClient(kwinClient: AbstractClient) {
@@ -99,8 +99,8 @@ class ClientManager {
if (client === undefined) {
return;
}
if (client.stateManager.getState() instanceof ClientStateTiled) {
client.stateManager.setState(new ClientStateFloating(), false);
if (client.stateManager.getState() instanceof ClientState.Tiled) {
client.stateManager.setState(new ClientState.Floating(), false);
}
}
@@ -111,12 +111,12 @@ class ClientManager {
}
const clientState = client.stateManager.getState();
if (clientState instanceof ClientStateFloating && Clients.canTileEver(kwinClient)) {
if (clientState instanceof ClientState.Floating && Clients.canTileEver(kwinClient)) {
Clients.makeTileable(kwinClient);
const grid = this.desktopManager.getDesktopForClient(client.kwinClient).grid;
client.stateManager.setState(new ClientStateTiled(this.world, client, grid), false);
} else if (clientState instanceof ClientStateTiled) {
client.stateManager.setState(new ClientStateFloating(), false);
client.stateManager.setState(new ClientState.Tiled(this.world, client, grid), false);
} else if (clientState instanceof ClientState.Tiled) {
client.stateManager.setState(new ClientState.Floating(), false);
}
}
@@ -143,7 +143,7 @@ class ClientManager {
private findTiledWindowOfClient(client: ClientWrapper, followTransient: boolean): Window|null {
const clientState = client.stateManager.getState();
if (clientState instanceof ClientStateTiled) {
if (clientState instanceof ClientState.Tiled) {
return clientState.window;
} else if (followTransient && client.transientFor !== null) {
return this.findTiledWindowOfClient(client.transientFor, true);

View File

@@ -1,23 +0,0 @@
class ClientStateDocked {
private readonly world: World;
private readonly signalManager: SignalManager;
constructor(world: World, kwinClient: AbstractClient) {
this.world = world;
this.signalManager = ClientStateDocked.initSignalManager(world, kwinClient);
world.onScreenResized();
}
public destroy(passFocus: boolean) {
this.signalManager.destroy();
this.world.onScreenResized();
}
private static initSignalManager(world: World, kwinClient: AbstractClient) {
const manager = new SignalManager();
manager.connect(kwinClient.frameGeometryChanged, (kwinClient: TopLevel, oldGeometry: QRect) => {
world.onScreenResized();
});
return manager;
}
}

View File

@@ -1,30 +0,0 @@
class ClientStateManager {
private state: ClientState;
constructor(initialState: ClientState) {
this.state = initialState;
}
public setState(newState: ClientState, passFocus: boolean) {
this.state.destroy(passFocus);
this.state = newState;
}
public getState() {
return this.state;
}
public destroy(passFocus: boolean) {
this.state.destroy(passFocus);
}
}
type ClientState = ClientStateTiled | ClientStateTiledMinimized | ClientStateFloating | ClientStateDocked;
class ClientStateTiledMinimized {
public destroy(passFocus: boolean) {}
}
class ClientStateFloating {
public destroy(passFocus: boolean) {}
}

View File

@@ -1,111 +0,0 @@
class ClientStateTiled {
public readonly window: Window;
private readonly signalManager: SignalManager;
constructor(world: World, client: ClientWrapper, grid: Grid) {
client.prepareForTiling();
const column = new Column(grid, grid.getLastFocusedColumn() ?? grid.getLastColumn());
const window = new Window(client, column);
this.window = window;
this.signalManager = ClientStateTiled.initSignalManager(world, window);
}
public destroy(passFocus: boolean) {
this.signalManager.destroy();
const window = this.window;
const grid = window.column.grid;
const clientWrapper = window.client;
window.destroy(passFocus);
clientWrapper.prepareForFloating(grid.desktop.clientArea);
}
private static initSignalManager(world: World, window: Window) {
const client = window.client;
const kwinClient = client.kwinClient;
const manager = new SignalManager();
manager.connect(kwinClient.desktopChanged, () => {
world.do((clientManager, desktopManager) => {
if (kwinClient.desktop === -1) {
// windows on all desktops are not supported
clientManager.untileClient(kwinClient);
return;
}
ClientStateTiled.moveWindowToCorrectGrid(desktopManager, window);
});
});
manager.connect(kwinClient.activitiesChanged, (kwinClient: AbstractClient) => {
world.do((clientManager, desktopManager) => {
if (kwinClient.activities.length !== 1) {
// windows on multiple activities are not supported
clientManager.untileClient(kwinClient);
return;
}
ClientStateTiled.moveWindowToCorrectGrid(desktopManager, window);
});
})
let lastResize = false;
manager.connect(kwinClient.moveResizedChanged, () => {
world.do((clientManager, desktopManager) => {
if (world.untileOnDrag && kwinClient.move) {
clientManager.untileClient(kwinClient);
return;
}
const grid = window.column.grid;
const resize = kwinClient.resize;
if (!lastResize && resize) {
grid.onUserResizeStarted();
}
if (lastResize && !resize) {
grid.onUserResizeFinished();
}
lastResize = resize;
});
});
let cursorChangedAfterResizeStart = false;
manager.connect(kwinClient.moveResizeCursorChanged, () => {
cursorChangedAfterResizeStart = true;
});
manager.connect(kwinClient.clientStartUserMovedResized, () => {
cursorChangedAfterResizeStart = false;
});
manager.connect(kwinClient.frameGeometryChanged, (kwinClient: TopLevel, oldGeometry: QRect) => {
world.do((clientManager, desktopManager) => {
const desktop = window.column.grid.desktop;
if (kwinClient.resize) {
window.onUserResize(oldGeometry, !cursorChangedAfterResizeStart);
} else {
const maximized = rectEqual(kwinClient.frameGeometry, desktop.clientArea);
if (!client.isManipulatingGeometry() && !kwinClient.fullScreen && !maximized) {
window.onFrameGeometryChanged(oldGeometry);
}
}
});
});
return manager;
}
private static moveWindowToCorrectGrid(desktopManager: DesktopManager, window: Window) {
const kwinClient = window.client.kwinClient;
const oldGrid = window.column.grid;
const newGrid = desktopManager.getDesktopForClient(kwinClient).grid;
if (oldGrid === newGrid) {
// window already on the correct grid
return;
}
const newColumn = new Column(newGrid, newGrid.getLastFocusedColumn() ?? newGrid.getLastColumn());
window.moveToColumn(newColumn);
}
}

View File

@@ -1,6 +1,6 @@
class ClientWrapper {
public readonly kwinClient: AbstractClient;
public readonly stateManager: ClientStateManager;
public readonly stateManager: ClientState.Manager;
public transientFor: ClientWrapper | null;
private readonly transients: ClientWrapper[];
private readonly signalManager: SignalManager;
@@ -10,12 +10,12 @@ class ClientWrapper {
constructor(
kwinClient: AbstractClient,
initialState: ClientState,
initialState: ClientState.State,
transientFor: ClientWrapper | null,
rulesSignalManager: SignalManager | null,
) {
this.kwinClient = kwinClient;
this.stateManager = new ClientStateManager(initialState);
this.stateManager = new ClientState.Manager(initialState);
this.transientFor = transientFor;
this.transients = [];
if (transientFor !== null) {
@@ -39,7 +39,7 @@ class ClientWrapper {
private moveTransient(dx: number, dy: number, desktopNumber: number) {
// TODO: prevent moving off the grid
if (this.stateManager.getState() instanceof ClientStateFloating) {
if (this.stateManager.getState() instanceof ClientState.Floating) {
if (this.kwinClient.desktop === desktopNumber) {
const frame = this.kwinClient.frameGeometry;
this.kwinClient.frameGeometry = Qt.rect(
@@ -123,7 +123,7 @@ class ClientWrapper {
public ensureTransientsVisible(screenSize: QRect) {
for (const transient of this.transients) {
if (transient.stateManager.getState() instanceof ClientStateFloating) {
if (transient.stateManager.getState() instanceof ClientState.Floating) {
transient.ensureVisible(screenSize);
transient.ensureTransientsVisible(screenSize);
}
@@ -159,7 +159,7 @@ class ClientWrapper {
private static initSignalManager(client: ClientWrapper) {
const manager = new SignalManager();
manager.connect(client.kwinClient.frameGeometryChanged, (kwinClient: TopLevel, oldGeometry: QRect) => {
if (client.stateManager.getState() instanceof ClientStateTiled) {
if (client.stateManager.getState() instanceof ClientState.Tiled) {
const newGeometry = client.kwinClient.frameGeometry;
const oldCenterX = oldGeometry.x + oldGeometry.width/2;
const oldCenterY = oldGeometry.y + oldGeometry.height/2;

View File

@@ -0,0 +1,25 @@
namespace ClientState {
export class Docked {
private readonly world: World;
private readonly signalManager: SignalManager;
constructor(world: World, kwinClient: AbstractClient) {
this.world = world;
this.signalManager = ClientState.Docked.initSignalManager(world, kwinClient);
world.onScreenResized();
}
public destroy(passFocus: boolean) {
this.signalManager.destroy();
this.world.onScreenResized();
}
private static initSignalManager(world: World, kwinClient: AbstractClient) {
const manager = new SignalManager();
manager.connect(kwinClient.frameGeometryChanged, (kwinClient: TopLevel, oldGeometry: QRect) => {
world.onScreenResized();
});
return manager;
}
}
}

View File

@@ -0,0 +1,32 @@
namespace ClientState {
export class Manager {
private state: ClientState.State;
constructor(initialState: ClientState.State) {
this.state = initialState;
}
public setState(newState: ClientState.State, passFocus: boolean) {
this.state.destroy(passFocus);
this.state = newState;
}
public getState() {
return this.state;
}
public destroy(passFocus: boolean) {
this.state.destroy(passFocus);
}
}
export type State = ClientState.Tiled | ClientState.TiledMinimized | ClientState.Floating | ClientState.Docked;
export class TiledMinimized {
public destroy(passFocus: boolean) {}
}
export class Floating {
public destroy(passFocus: boolean) {}
}
}

View File

@@ -0,0 +1,113 @@
namespace ClientState {
export class Tiled {
public readonly window: Window;
private readonly signalManager: SignalManager;
constructor(world: World, client: ClientWrapper, grid: Grid) {
client.prepareForTiling();
const column = new Column(grid, grid.getLastFocusedColumn() ?? grid.getLastColumn());
const window = new Window(client, column);
this.window = window;
this.signalManager = ClientState.Tiled.initSignalManager(world, window);
}
public destroy(passFocus: boolean) {
this.signalManager.destroy();
const window = this.window;
const grid = window.column.grid;
const clientWrapper = window.client;
window.destroy(passFocus);
clientWrapper.prepareForFloating(grid.desktop.clientArea);
}
private static initSignalManager(world: World, window: Window) {
const client = window.client;
const kwinClient = client.kwinClient;
const manager = new SignalManager();
manager.connect(kwinClient.desktopChanged, () => {
world.do((clientManager, desktopManager) => {
if (kwinClient.desktop === -1) {
// windows on all desktops are not supported
clientManager.untileClient(kwinClient);
return;
}
ClientState.Tiled.moveWindowToCorrectGrid(desktopManager, window);
});
});
manager.connect(kwinClient.activitiesChanged, (kwinClient: AbstractClient) => {
world.do((clientManager, desktopManager) => {
if (kwinClient.activities.length !== 1) {
// windows on multiple activities are not supported
clientManager.untileClient(kwinClient);
return;
}
ClientState.Tiled.moveWindowToCorrectGrid(desktopManager, window);
});
})
let lastResize = false;
manager.connect(kwinClient.moveResizedChanged, () => {
world.do((clientManager, desktopManager) => {
if (world.untileOnDrag && kwinClient.move) {
clientManager.untileClient(kwinClient);
return;
}
const grid = window.column.grid;
const resize = kwinClient.resize;
if (!lastResize && resize) {
grid.onUserResizeStarted();
}
if (lastResize && !resize) {
grid.onUserResizeFinished();
}
lastResize = resize;
});
});
let cursorChangedAfterResizeStart = false;
manager.connect(kwinClient.moveResizeCursorChanged, () => {
cursorChangedAfterResizeStart = true;
});
manager.connect(kwinClient.clientStartUserMovedResized, () => {
cursorChangedAfterResizeStart = false;
});
manager.connect(kwinClient.frameGeometryChanged, (kwinClient: TopLevel, oldGeometry: QRect) => {
world.do((clientManager, desktopManager) => {
const desktop = window.column.grid.desktop;
if (kwinClient.resize) {
window.onUserResize(oldGeometry, !cursorChangedAfterResizeStart);
} else {
const maximized = rectEqual(kwinClient.frameGeometry, desktop.clientArea);
if (!client.isManipulatingGeometry() && !kwinClient.fullScreen && !maximized) {
window.onFrameGeometryChanged(oldGeometry);
}
}
});
});
return manager;
}
private static moveWindowToCorrectGrid(desktopManager: DesktopManager, window: Window) {
const kwinClient = window.client.kwinClient;
const oldGrid = window.column.grid;
const newGrid = desktopManager.getDesktopForClient(kwinClient).grid;
if (oldGrid === newGrid) {
// window already on the correct grid
return;
}
const newColumn = new Column(newGrid, newGrid.getLastFocusedColumn() ?? newGrid.getLastColumn());
window.moveToColumn(newColumn);
}
}
}