create ClientState namespace
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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) {}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
25
src/world/clientstate/Docked.ts
Normal file
25
src/world/clientstate/Docked.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
src/world/clientstate/Manager.ts
Normal file
32
src/world/clientstate/Manager.ts
Normal 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) {}
|
||||
}
|
||||
}
|
||||
113
src/world/clientstate/Tiled.ts
Normal file
113
src/world/clientstate/Tiled.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user