mirror of
https://github.com/Bismuth-Forge/bismuth.git
synced 2024-09-17 11:37:10 +03:00
fix: 🔥 Pass config object instead of global
QML JS engine does not allow global objects
This commit is contained in:
parent
3b87e93883
commit
33ae26a35b
27
src/config.d.ts
vendored
27
src/config.d.ts
vendored
@ -1,27 +0,0 @@
|
||||
// Copyright (c) 2018-2019 Eon S. Jeon <esjeon@hyunmu.am>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import IConfig from "./iconfig";
|
||||
import KWinConfig from "./driver/kwin/kwin_config";
|
||||
|
||||
declare global {
|
||||
var CONFIG: IConfig;
|
||||
var KWINCONFIG: KWinConfig;
|
||||
}
|
223
src/config.ts
Normal file
223
src/config.ts
Normal file
@ -0,0 +1,223 @@
|
||||
// Copyright (c) 2018-2019 Eon S. Jeon <esjeon@hyunmu.am>
|
||||
// Copyright (c) 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import MonocleLayout from "./layouts/monocle_layout";
|
||||
import TileLayout from "./layouts/tile_layout";
|
||||
import ThreeColumnLayout from "./layouts/three_column_layout";
|
||||
import StairLayout from "./layouts/stair_layout";
|
||||
import SpiralLayout from "./layouts/spiral_layout";
|
||||
import SpreadLayout from "./layouts/spread_layout";
|
||||
import FloatingLayout from "./layouts/floating_layout";
|
||||
import QuarterLayout from "./layouts/quarter_layout";
|
||||
import CascadeLayout from "./layouts/cascade_layout";
|
||||
|
||||
import { ILayout } from "./ilayout";
|
||||
import { ILayoutClass } from "./ilayout";
|
||||
import { debug } from "./util/debug";
|
||||
|
||||
export default interface IConfig {
|
||||
//#region Layout
|
||||
layoutOrder: string[];
|
||||
layoutFactories: { [key: string]: () => ILayout };
|
||||
monocleMaximize: boolean;
|
||||
maximizeSoleTile: boolean;
|
||||
monocleMinimizeRest: boolean; // KWin-specific
|
||||
//#endregion
|
||||
|
||||
//#region Features
|
||||
adjustLayout: boolean;
|
||||
adjustLayoutLive: boolean;
|
||||
keepFloatAbove: boolean;
|
||||
noTileBorder: boolean;
|
||||
limitTileWidthRatio: number;
|
||||
//#endregion
|
||||
|
||||
//#region Gap
|
||||
screenGapBottom: number;
|
||||
screenGapLeft: number;
|
||||
screenGapRight: number;
|
||||
screenGapTop: number;
|
||||
tileLayoutGap: number;
|
||||
//#endregion
|
||||
|
||||
//#region Behavior
|
||||
directionalKeyMode: "dwm" | "focus";
|
||||
newWindowAsMaster: boolean;
|
||||
//#endregion
|
||||
|
||||
//#region KWin-specific
|
||||
layoutPerActivity: boolean;
|
||||
layoutPerDesktop: boolean;
|
||||
preventMinimize: boolean;
|
||||
preventProtrusion: boolean;
|
||||
pollMouseXdotool: boolean;
|
||||
//#endregion
|
||||
|
||||
//#region KWin-specific Rules
|
||||
floatUtility: boolean;
|
||||
|
||||
floatingClass: string[];
|
||||
floatingTitle: string[];
|
||||
ignoreClass: string[];
|
||||
ignoreTitle: string[];
|
||||
ignoreRole: string[];
|
||||
|
||||
ignoreActivity: string[];
|
||||
ignoreScreen: number[];
|
||||
//#endregion
|
||||
}
|
||||
|
||||
export class Config implements IConfig {
|
||||
//#region Layout
|
||||
public layoutOrder: string[];
|
||||
public layoutFactories: { [key: string]: () => ILayout };
|
||||
public maximizeSoleTile: boolean;
|
||||
public monocleMaximize: boolean;
|
||||
public monocleMinimizeRest: boolean; // KWin-specific
|
||||
//#endregion
|
||||
|
||||
//#region Features
|
||||
public adjustLayout: boolean;
|
||||
public adjustLayoutLive: boolean;
|
||||
public keepFloatAbove: boolean;
|
||||
public noTileBorder: boolean;
|
||||
public limitTileWidthRatio: number;
|
||||
//#endregion
|
||||
|
||||
//#region Gap
|
||||
public screenGapBottom: number;
|
||||
public screenGapLeft: number;
|
||||
public screenGapRight: number;
|
||||
public screenGapTop: number;
|
||||
public tileLayoutGap: number;
|
||||
//#endregion
|
||||
|
||||
//#region Behavior
|
||||
public directionalKeyMode: "dwm" | "focus";
|
||||
public newWindowAsMaster: boolean;
|
||||
//#endregion
|
||||
|
||||
//#region KWin-specific
|
||||
public layoutPerActivity: boolean;
|
||||
public layoutPerDesktop: boolean;
|
||||
public preventMinimize: boolean;
|
||||
public preventProtrusion: boolean;
|
||||
public pollMouseXdotool: boolean;
|
||||
//#endregion
|
||||
|
||||
//#region KWin-specific Rules
|
||||
public floatUtility: boolean;
|
||||
|
||||
public floatingClass: string[];
|
||||
public floatingTitle: string[];
|
||||
public ignoreClass: string[];
|
||||
public ignoreTitle: string[];
|
||||
public ignoreRole: string[];
|
||||
|
||||
public ignoreActivity: string[];
|
||||
public ignoreScreen: number[];
|
||||
//#endregion
|
||||
|
||||
constructor() {
|
||||
function commaSeparate(str: string): string[] {
|
||||
if (!str || typeof str !== "string") return [];
|
||||
return str.split(",").map((part) => part.trim());
|
||||
}
|
||||
|
||||
DEBUG.enabled = DEBUG.enabled || KWin.readConfig("debug", false);
|
||||
|
||||
this.layoutOrder = [];
|
||||
this.layoutFactories = {};
|
||||
(
|
||||
[
|
||||
["enableTileLayout", true, TileLayout],
|
||||
["enableMonocleLayout", true, MonocleLayout],
|
||||
["enableThreeColumnLayout", true, ThreeColumnLayout],
|
||||
["enableSpreadLayout", true, SpreadLayout],
|
||||
["enableStairLayout", true, StairLayout],
|
||||
["enableSpiralLayout", true, SpiralLayout],
|
||||
["enableQuarterLayout", false, QuarterLayout],
|
||||
["enableFloatingLayout", false, FloatingLayout],
|
||||
["enableCascadeLayout", false, CascadeLayout], // TODO: add config
|
||||
] as Array<[string, boolean, ILayoutClass]>
|
||||
).forEach(([configKey, defaultValue, layoutClass]) => {
|
||||
if (KWin.readConfig(configKey, defaultValue))
|
||||
this.layoutOrder.push(layoutClass.id);
|
||||
// TODO: Refactor this: config should not create factories. It is not its responsibility
|
||||
this.layoutFactories[layoutClass.id] = () => new layoutClass(this);
|
||||
});
|
||||
|
||||
this.maximizeSoleTile = KWin.readConfig("maximizeSoleTile", false);
|
||||
this.monocleMaximize = KWin.readConfig("monocleMaximize", true);
|
||||
this.monocleMinimizeRest = KWin.readConfig("monocleMinimizeRest", false);
|
||||
|
||||
this.adjustLayout = KWin.readConfig("adjustLayout", true);
|
||||
this.adjustLayoutLive = KWin.readConfig("adjustLayoutLive", true);
|
||||
this.keepFloatAbove = KWin.readConfig("keepFloatAbove", true);
|
||||
this.noTileBorder = KWin.readConfig("noTileBorder", false);
|
||||
|
||||
this.limitTileWidthRatio = 0;
|
||||
if (KWin.readConfig("limitTileWidth", false))
|
||||
this.limitTileWidthRatio = KWin.readConfig("limitTileWidthRatio", 1.6);
|
||||
|
||||
this.screenGapBottom = KWin.readConfig("screenGapBottom", 0);
|
||||
this.screenGapLeft = KWin.readConfig("screenGapLeft", 0);
|
||||
this.screenGapRight = KWin.readConfig("screenGapRight", 0);
|
||||
this.screenGapTop = KWin.readConfig("screenGapTop", 0);
|
||||
this.tileLayoutGap = KWin.readConfig("tileLayoutGap", 0);
|
||||
|
||||
const directionalKeyDwm = KWin.readConfig("directionalKeyDwm", true);
|
||||
const directionalKeyFocus = KWin.readConfig("directionalKeyFocus", false);
|
||||
this.directionalKeyMode = directionalKeyDwm ? "dwm" : "focus";
|
||||
this.newWindowAsMaster = KWin.readConfig("newWindowAsMaster", false);
|
||||
|
||||
this.layoutPerActivity = KWin.readConfig("layoutPerActivity", true);
|
||||
this.layoutPerDesktop = KWin.readConfig("layoutPerDesktop", true);
|
||||
this.floatUtility = KWin.readConfig("floatUtility", true);
|
||||
this.preventMinimize = KWin.readConfig("preventMinimize", false);
|
||||
this.preventProtrusion = KWin.readConfig("preventProtrusion", true);
|
||||
this.pollMouseXdotool = KWin.readConfig("pollMouseXdotool", false);
|
||||
|
||||
this.floatingClass = commaSeparate(KWin.readConfig("floatingClass", ""));
|
||||
this.floatingTitle = commaSeparate(KWin.readConfig("floatingTitle", ""));
|
||||
this.ignoreActivity = commaSeparate(KWin.readConfig("ignoreActivity", ""));
|
||||
this.ignoreClass = commaSeparate(
|
||||
KWin.readConfig("ignoreClass", "krunner,yakuake,spectacle,kded5")
|
||||
);
|
||||
this.ignoreRole = commaSeparate(KWin.readConfig("ignoreRole", "quake"));
|
||||
|
||||
this.ignoreScreen = commaSeparate(KWin.readConfig("ignoreScreen", "")).map(
|
||||
(str) => parseInt(str, 10)
|
||||
);
|
||||
this.ignoreTitle = commaSeparate(KWin.readConfig("ignoreTitle", ""));
|
||||
|
||||
if (this.preventMinimize && this.monocleMinimizeRest) {
|
||||
debug(
|
||||
() => "preventMinimize is disabled because of monocleMinimizeRest."
|
||||
);
|
||||
this.preventMinimize = false;
|
||||
}
|
||||
}
|
||||
|
||||
public toString(): string {
|
||||
return "Config(" + JSON.stringify(this, undefined, 2) + ")";
|
||||
}
|
||||
}
|
@ -17,154 +17,3 @@
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import MonocleLayout from "../../layouts/monocle_layout";
|
||||
import TileLayout from "../../layouts/tile_layout";
|
||||
import ThreeColumnLayout from "../../layouts/three_column_layout";
|
||||
import StairLayout from "../../layouts/stair_layout";
|
||||
import SpiralLayout from "../../layouts/spiral_layout";
|
||||
import SpreadLayout from "../../layouts/spread_layout";
|
||||
import FloatingLayout from "../../layouts/floating_layout";
|
||||
import QuarterLayout from "../../layouts/quarter_layout";
|
||||
import CascadeLayout from "../../layouts/cascade_layout";
|
||||
|
||||
import IConfig from "../../iconfig";
|
||||
import { ILayout } from "../../ilayout";
|
||||
import { ILayoutClass } from "../../ilayout";
|
||||
import { debug } from "../../util/debug";
|
||||
|
||||
export default class KWinConfig implements IConfig {
|
||||
//#region Layout
|
||||
public layoutOrder: string[];
|
||||
public layoutFactories: { [key: string]: () => ILayout };
|
||||
public maximizeSoleTile: boolean;
|
||||
public monocleMaximize: boolean;
|
||||
public monocleMinimizeRest: boolean; // KWin-specific
|
||||
//#endregion
|
||||
|
||||
//#region Features
|
||||
public adjustLayout: boolean;
|
||||
public adjustLayoutLive: boolean;
|
||||
public keepFloatAbove: boolean;
|
||||
public noTileBorder: boolean;
|
||||
public limitTileWidthRatio: number;
|
||||
//#endregion
|
||||
|
||||
//#region Gap
|
||||
public screenGapBottom: number;
|
||||
public screenGapLeft: number;
|
||||
public screenGapRight: number;
|
||||
public screenGapTop: number;
|
||||
public tileLayoutGap: number;
|
||||
//#endregion
|
||||
|
||||
//#region Behavior
|
||||
public directionalKeyMode: "dwm" | "focus";
|
||||
public newWindowAsMaster: boolean;
|
||||
//#endregion
|
||||
|
||||
//#region KWin-specific
|
||||
public layoutPerActivity: boolean;
|
||||
public layoutPerDesktop: boolean;
|
||||
public preventMinimize: boolean;
|
||||
public preventProtrusion: boolean;
|
||||
public pollMouseXdotool: boolean;
|
||||
//#endregion
|
||||
|
||||
//#region KWin-specific Rules
|
||||
public floatUtility: boolean;
|
||||
|
||||
public floatingClass: string[];
|
||||
public floatingTitle: string[];
|
||||
public ignoreClass: string[];
|
||||
public ignoreTitle: string[];
|
||||
public ignoreRole: string[];
|
||||
|
||||
public ignoreActivity: string[];
|
||||
public ignoreScreen: number[];
|
||||
//#endregion
|
||||
|
||||
constructor() {
|
||||
function commaSeparate(str: string): string[] {
|
||||
if (!str || typeof str !== "string") return [];
|
||||
return str.split(",").map((part) => part.trim());
|
||||
}
|
||||
|
||||
DEBUG.enabled = DEBUG.enabled || KWin.readConfig("debug", false);
|
||||
|
||||
this.layoutOrder = [];
|
||||
this.layoutFactories = {};
|
||||
(
|
||||
[
|
||||
["enableTileLayout", true, TileLayout],
|
||||
["enableMonocleLayout", true, MonocleLayout],
|
||||
["enableThreeColumnLayout", true, ThreeColumnLayout],
|
||||
["enableSpreadLayout", true, SpreadLayout],
|
||||
["enableStairLayout", true, StairLayout],
|
||||
["enableSpiralLayout", true, SpiralLayout],
|
||||
["enableQuarterLayout", false, QuarterLayout],
|
||||
["enableFloatingLayout", false, FloatingLayout],
|
||||
["enableCascadeLayout", false, CascadeLayout], // TODO: add config
|
||||
] as Array<[string, boolean, ILayoutClass]>
|
||||
).forEach(([configKey, defaultValue, layoutClass]) => {
|
||||
if (KWin.readConfig(configKey, defaultValue))
|
||||
this.layoutOrder.push(layoutClass.id);
|
||||
this.layoutFactories[layoutClass.id] = () => new layoutClass();
|
||||
});
|
||||
|
||||
this.maximizeSoleTile = KWin.readConfig("maximizeSoleTile", false);
|
||||
this.monocleMaximize = KWin.readConfig("monocleMaximize", true);
|
||||
this.monocleMinimizeRest = KWin.readConfig("monocleMinimizeRest", false);
|
||||
|
||||
this.adjustLayout = KWin.readConfig("adjustLayout", true);
|
||||
this.adjustLayoutLive = KWin.readConfig("adjustLayoutLive", true);
|
||||
this.keepFloatAbove = KWin.readConfig("keepFloatAbove", true);
|
||||
this.noTileBorder = KWin.readConfig("noTileBorder", false);
|
||||
|
||||
this.limitTileWidthRatio = 0;
|
||||
if (KWin.readConfig("limitTileWidth", false))
|
||||
this.limitTileWidthRatio = KWin.readConfig("limitTileWidthRatio", 1.6);
|
||||
|
||||
this.screenGapBottom = KWin.readConfig("screenGapBottom", 0);
|
||||
this.screenGapLeft = KWin.readConfig("screenGapLeft", 0);
|
||||
this.screenGapRight = KWin.readConfig("screenGapRight", 0);
|
||||
this.screenGapTop = KWin.readConfig("screenGapTop", 0);
|
||||
this.tileLayoutGap = KWin.readConfig("tileLayoutGap", 0);
|
||||
|
||||
const directionalKeyDwm = KWin.readConfig("directionalKeyDwm", true);
|
||||
const directionalKeyFocus = KWin.readConfig("directionalKeyFocus", false);
|
||||
this.directionalKeyMode = directionalKeyDwm ? "dwm" : "focus";
|
||||
this.newWindowAsMaster = KWin.readConfig("newWindowAsMaster", false);
|
||||
|
||||
this.layoutPerActivity = KWin.readConfig("layoutPerActivity", true);
|
||||
this.layoutPerDesktop = KWin.readConfig("layoutPerDesktop", true);
|
||||
this.floatUtility = KWin.readConfig("floatUtility", true);
|
||||
this.preventMinimize = KWin.readConfig("preventMinimize", false);
|
||||
this.preventProtrusion = KWin.readConfig("preventProtrusion", true);
|
||||
this.pollMouseXdotool = KWin.readConfig("pollMouseXdotool", false);
|
||||
|
||||
this.floatingClass = commaSeparate(KWin.readConfig("floatingClass", ""));
|
||||
this.floatingTitle = commaSeparate(KWin.readConfig("floatingTitle", ""));
|
||||
this.ignoreActivity = commaSeparate(KWin.readConfig("ignoreActivity", ""));
|
||||
this.ignoreClass = commaSeparate(
|
||||
KWin.readConfig("ignoreClass", "krunner,yakuake,spectacle,kded5")
|
||||
);
|
||||
this.ignoreRole = commaSeparate(KWin.readConfig("ignoreRole", "quake"));
|
||||
|
||||
this.ignoreScreen = commaSeparate(KWin.readConfig("ignoreScreen", "")).map(
|
||||
(str) => parseInt(str, 10)
|
||||
);
|
||||
this.ignoreTitle = commaSeparate(KWin.readConfig("ignoreTitle", ""));
|
||||
|
||||
if (this.preventMinimize && this.monocleMinimizeRest) {
|
||||
debug(
|
||||
() => "preventMinimize is disabled because of monocleMinimizeRest."
|
||||
);
|
||||
this.preventMinimize = false;
|
||||
}
|
||||
}
|
||||
|
||||
public toString(): string {
|
||||
return "Config(" + JSON.stringify(this, undefined, 2) + ")";
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ import QuarterLayout from "../../layouts/quarter_layout";
|
||||
|
||||
import TilingEngine from "../../engine/tiling_engine";
|
||||
import TilingController from "../../engine/tiling_controler";
|
||||
import KWinConfig from "./kwin_config";
|
||||
import IDriverContext from "../../idriver_context";
|
||||
import ISurface from "../../isurface";
|
||||
import Window from "../../engine/window";
|
||||
@ -42,6 +41,7 @@ import { ILayoutClass } from "../../ilayout";
|
||||
import { WindowState } from "../../engine/window";
|
||||
import WrapperMap from "../../util/wrappermap";
|
||||
import { debug, debugObj } from "../../util/debug";
|
||||
import IConfig, { Config } from "../../config";
|
||||
// import { workspace } from "../../extern/global";
|
||||
|
||||
/**
|
||||
@ -66,7 +66,8 @@ export default class KWinDriver implements IDriverContext {
|
||||
this.kwinApi.workspace.currentActivity,
|
||||
this.kwinApi.workspace.currentDesktop,
|
||||
this.qml.activityInfo,
|
||||
this.kwinApi
|
||||
this.kwinApi,
|
||||
this.config
|
||||
);
|
||||
}
|
||||
|
||||
@ -100,7 +101,8 @@ export default class KWinDriver implements IDriverContext {
|
||||
this.kwinApi.workspace.currentActivity,
|
||||
this.kwinApi.workspace.currentDesktop,
|
||||
this.qml.activityInfo,
|
||||
this.kwinApi
|
||||
this.kwinApi,
|
||||
this.config
|
||||
)
|
||||
);
|
||||
return screens;
|
||||
@ -120,15 +122,23 @@ export default class KWinDriver implements IDriverContext {
|
||||
private qml: Bismuth.Qml.Main;
|
||||
private kwinApi: KWin.Api;
|
||||
|
||||
constructor(qmlObjects: Bismuth.Qml.Main, kwinScriptingApi: KWin.Api) {
|
||||
this.engine = new TilingEngine();
|
||||
this.control = new TilingController(this.engine);
|
||||
private config: IConfig;
|
||||
|
||||
constructor(qmlObjects: Bismuth.Qml.Main, kwinScriptingApi: KWin.Api, config?: IConfig) {
|
||||
if (config) {
|
||||
this.config = config;
|
||||
} else {
|
||||
this.config = new Config();
|
||||
}
|
||||
|
||||
this.engine = new TilingEngine(this.config);
|
||||
this.control = new TilingController(this.engine, this.config);
|
||||
this.windowMap = new WrapperMap(
|
||||
(client: KWin.Client) => KWinWindow.generateID(client),
|
||||
(client: KWin.Client) => new Window(new KWinWindow(client, this.qml, this.kwinApi))
|
||||
(client: KWin.Client) => new Window(new KWinWindow(client, this.qml, this.kwinApi, this.config), this.config)
|
||||
);
|
||||
this.entered = false;
|
||||
this.mousePoller = new KWinMousePoller(qmlObjects);
|
||||
this.mousePoller = new KWinMousePoller(qmlObjects, this.config);
|
||||
this.qml = qmlObjects;
|
||||
this.kwinApi = kwinScriptingApi;
|
||||
}
|
||||
@ -139,21 +149,25 @@ export default class KWinDriver implements IDriverContext {
|
||||
public main() {
|
||||
console.log("Initiating systems!");
|
||||
|
||||
CONFIG = KWINCONFIG = new KWinConfig();
|
||||
// debug(() => "Config: " + KWINCONFIG);
|
||||
// DEBUG = {
|
||||
// enabled: false,
|
||||
// started: new Date().getTime(),
|
||||
// };
|
||||
|
||||
// this.bindEvents();
|
||||
// this.bindShortcut();
|
||||
// debug(() => "Config: " + this.config);
|
||||
|
||||
// const clients = workspace.clientList();
|
||||
// for (let i = 0; i < clients.length; i++) {
|
||||
// const window = this.windowMap.add(clients[i]);
|
||||
// this.engine.manage(window);
|
||||
// if (window.state !== WindowState.Unmanaged)
|
||||
// this.bindWindowEvents(window, clients[i]);
|
||||
// else this.windowMap.remove(clients[i]);
|
||||
// }
|
||||
// this.engine.arrange(this);
|
||||
this.bindEvents();
|
||||
this.bindShortcut();
|
||||
|
||||
const clients = this.kwinApi.workspace.clientList();
|
||||
for (let i = 0; i < clients.length; i++) {
|
||||
const window = this.windowMap.add(clients[i]);
|
||||
this.engine.manage(window);
|
||||
if (window.state !== WindowState.Unmanaged)
|
||||
this.bindWindowEvents(window, clients[i]);
|
||||
else this.windowMap.remove(clients[i]);
|
||||
}
|
||||
this.engine.arrange(this);
|
||||
}
|
||||
|
||||
//#region implement methods of IDriverContext`
|
||||
@ -286,7 +300,8 @@ export default class KWinDriver implements IDriverContext {
|
||||
this.kwinApi.workspace.currentActivity,
|
||||
this.kwinApi.workspace.currentDesktop,
|
||||
this.qml.activityInfo,
|
||||
this.kwinApi
|
||||
this.kwinApi,
|
||||
this.config
|
||||
);
|
||||
this.control.onSurfaceUpdate(this, "resized " + srf.toString());
|
||||
});
|
||||
@ -353,7 +368,7 @@ export default class KWinDriver implements IDriverContext {
|
||||
);
|
||||
|
||||
this.connect(this.kwinApi.workspace.clientMinimized, (client: KWin.Client) => {
|
||||
if (KWINCONFIG.preventMinimize) {
|
||||
if (this.config.preventMinimize) {
|
||||
client.minimized = false;
|
||||
this.kwinApi.workspace.activeClient = client;
|
||||
} else
|
||||
|
@ -18,6 +18,7 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import IConfig from "../../config";
|
||||
import { KWinSetTimeout } from "./kwin_set_timeout";
|
||||
|
||||
export default class KWinMousePoller {
|
||||
@ -36,11 +37,13 @@ export default class KWinMousePoller {
|
||||
private startCount: number;
|
||||
private cmdResult: string | null;
|
||||
private qml: Bismuth.Qml.Main;
|
||||
private config: IConfig;
|
||||
|
||||
constructor(qml: Bismuth.Qml.Main) {
|
||||
constructor(qml: Bismuth.Qml.Main, config: IConfig) {
|
||||
this.startCount = 0;
|
||||
this.cmdResult = null;
|
||||
this.qml = qml;
|
||||
this.config = config;
|
||||
|
||||
/* we will poll manually, because this interval value will be
|
||||
* aligned to intervalAlignment, which probably is 1000. */
|
||||
@ -59,7 +62,7 @@ export default class KWinMousePoller {
|
||||
|
||||
public start() {
|
||||
this.startCount += 1;
|
||||
if (KWINCONFIG.pollMouseXdotool)
|
||||
if (this.config.pollMouseXdotool)
|
||||
this.qml.mousePoller.connectSource(KWinMousePoller.COMMAND);
|
||||
}
|
||||
|
||||
|
@ -18,15 +18,16 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import IConfig from "../../config";
|
||||
import ISurface from "../../isurface";
|
||||
import { toRect } from "../../util/kwinutil";
|
||||
import Rect from "../../util/rect";
|
||||
|
||||
export default class KWinSurface implements ISurface {
|
||||
public static generateId(screen: number, activity: string, desktop: number) {
|
||||
public static generateId(screen: number, activity: string, desktop: number, config: IConfig) {
|
||||
let path = String(screen);
|
||||
if (KWINCONFIG.layoutPerActivity) path += "@" + activity;
|
||||
if (KWINCONFIG.layoutPerDesktop) path += "#" + desktop;
|
||||
if (config.layoutPerActivity) path += "@" + activity;
|
||||
if (config.layoutPerDesktop) path += "#" + desktop;
|
||||
return path;
|
||||
}
|
||||
|
||||
@ -40,17 +41,19 @@ export default class KWinSurface implements ISurface {
|
||||
|
||||
private activityInfo: Plasma.TaskManager.ActivityInfo;
|
||||
private kwinApi: KWin.Api;
|
||||
private config: IConfig;
|
||||
|
||||
constructor(screen: number, activity: string, desktop: number, activityInfo: Plasma.TaskManager.ActivityInfo, kwinApi: KWin.Api) {
|
||||
constructor(screen: number, activity: string, desktop: number, activityInfo: Plasma.TaskManager.ActivityInfo, kwinApi: KWin.Api, config: IConfig) {
|
||||
const activityName = activityInfo.activityName(activity);
|
||||
|
||||
this.activityInfo = activityInfo;
|
||||
this.kwinApi = kwinApi;
|
||||
this.config = config;
|
||||
|
||||
this.id = KWinSurface.generateId(screen, activity, desktop);
|
||||
this.id = KWinSurface.generateId(screen, activity, desktop, this.config);
|
||||
this.ignore =
|
||||
KWINCONFIG.ignoreActivity.indexOf(activityName) >= 0 ||
|
||||
KWINCONFIG.ignoreScreen.indexOf(screen) >= 0;
|
||||
this.config.ignoreActivity.indexOf(activityName) >= 0 ||
|
||||
this.config.ignoreScreen.indexOf(screen) >= 0;
|
||||
this.workingArea = toRect(
|
||||
this.kwinApi.workspace.clientArea(KWin.PlacementArea, screen, desktop)
|
||||
);
|
||||
@ -66,7 +69,7 @@ export default class KWinSurface implements ISurface {
|
||||
/* TODO: option to create additional desktop */
|
||||
return null;
|
||||
|
||||
return new KWinSurface(this.screen, this.activity, this.desktop + 1, this.activityInfo, this.kwinApi);
|
||||
return new KWinSurface(this.screen, this.activity, this.desktop + 1, this.activityInfo, this.kwinApi, this.config);
|
||||
}
|
||||
|
||||
public toString(): string {
|
||||
|
@ -25,6 +25,7 @@ import Rect from "../../util/rect";
|
||||
import { toQRect, toRect } from "../../util/kwinutil";
|
||||
import { clip, matchWords } from "../../util/func";
|
||||
import { debugObj } from "../../util/debug";
|
||||
import IConfig from "../../config";
|
||||
|
||||
export default class KWinWindow implements IDriverWindow {
|
||||
public static generateID(client: KWin.Client) {
|
||||
@ -49,10 +50,10 @@ export default class KWinWindow implements IDriverWindow {
|
||||
return (
|
||||
this.client.specialWindow ||
|
||||
resourceClass === "plasmashell" ||
|
||||
KWINCONFIG.ignoreClass.indexOf(resourceClass) >= 0 ||
|
||||
KWINCONFIG.ignoreClass.indexOf(resourceName) >= 0 ||
|
||||
matchWords(this.client.caption, KWINCONFIG.ignoreTitle) >= 0 ||
|
||||
KWINCONFIG.ignoreRole.indexOf(windowRole) >= 0
|
||||
this.config.ignoreClass.indexOf(resourceClass) >= 0 ||
|
||||
this.config.ignoreClass.indexOf(resourceName) >= 0 ||
|
||||
matchWords(this.client.caption, this.config.ignoreTitle) >= 0 ||
|
||||
this.config.ignoreRole.indexOf(windowRole) >= 0
|
||||
);
|
||||
}
|
||||
|
||||
@ -62,11 +63,11 @@ export default class KWinWindow implements IDriverWindow {
|
||||
return (
|
||||
this.client.modal ||
|
||||
!this.client.resizeable ||
|
||||
(KWINCONFIG.floatUtility &&
|
||||
(this.config.floatUtility &&
|
||||
(this.client.dialog || this.client.splash || this.client.utility)) ||
|
||||
KWINCONFIG.floatingClass.indexOf(resourceClass) >= 0 ||
|
||||
KWINCONFIG.floatingClass.indexOf(resourceName) >= 0 ||
|
||||
matchWords(this.client.caption, KWINCONFIG.floatingTitle) >= 0
|
||||
this.config.floatingClass.indexOf(resourceClass) >= 0 ||
|
||||
this.config.floatingClass.indexOf(resourceName) >= 0 ||
|
||||
matchWords(this.client.caption, this.config.floatingTitle) >= 0
|
||||
);
|
||||
}
|
||||
|
||||
@ -83,7 +84,7 @@ export default class KWinWindow implements IDriverWindow {
|
||||
const desktop =
|
||||
this.client.desktop >= 0 ? this.client.desktop : this.kwinApi.workspace.currentDesktop;
|
||||
|
||||
return new KWinSurface(this.client.screen, activity, desktop, this.qml.activityInfo, this.kwinApi);
|
||||
return new KWinSurface(this.client.screen, activity, desktop, this.qml.activityInfo, this.kwinApi, this.config);
|
||||
}
|
||||
|
||||
public set surface(srf: ISurface) {
|
||||
@ -99,8 +100,9 @@ export default class KWinWindow implements IDriverWindow {
|
||||
private noBorderOriginal: boolean;
|
||||
private qml: Bismuth.Qml.Main;
|
||||
private kwinApi: KWin.Api;
|
||||
private config: IConfig;
|
||||
|
||||
constructor(client: KWin.Client, qml: Bismuth.Qml.Main, kwinApi: KWin.Api) {
|
||||
constructor(client: KWin.Client, qml: Bismuth.Qml.Main, kwinApi: KWin.Api, config: IConfig) {
|
||||
this.client = client;
|
||||
this.id = KWinWindow.generateID(client);
|
||||
this.maximized = false;
|
||||
@ -108,6 +110,7 @@ export default class KWinWindow implements IDriverWindow {
|
||||
this.noBorderOriginal = client.noBorder;
|
||||
this.qml = qml;
|
||||
this.kwinApi = kwinApi;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public commit(geometry?: Rect, noBorder?: boolean, keepAbove?: boolean) {
|
||||
@ -139,7 +142,7 @@ export default class KWinWindow implements IDriverWindow {
|
||||
|
||||
if (geometry !== undefined) {
|
||||
geometry = this.adjustGeometry(geometry);
|
||||
if (KWINCONFIG.preventProtrusion) {
|
||||
if (this.config.preventProtrusion) {
|
||||
const area = toRect(
|
||||
this.kwinApi.workspace.clientArea(
|
||||
KWin.PlacementArea,
|
||||
|
@ -22,7 +22,6 @@ import Window from "../../engine/window";
|
||||
import ISurface from "../../isurface";
|
||||
import Rect from "../../util/rect";
|
||||
import TestSurface from "./test_surface";
|
||||
// import { CONFIG } from "../../config";
|
||||
|
||||
export default class TestDriver {
|
||||
public currentScreen: number;
|
||||
@ -67,8 +66,3 @@ export default class TestDriver {
|
||||
setTimeout(func, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
function setTestConfig(name: string, value: any) {
|
||||
if (!CONFIG) CONFIG = {} as any;
|
||||
(CONFIG as any)[name] = value;
|
||||
}
|
||||
|
@ -22,9 +22,9 @@ import MonocleLayout from "../layouts/monocle_layout";
|
||||
import FloatingLayout from "../layouts/floating_layout";
|
||||
|
||||
import { ILayout } from "../ilayout";
|
||||
// import { CONFIG } from "../config";
|
||||
import ISurface from "../isurface";
|
||||
import { wrapIndex } from "../util/func";
|
||||
import IConfig from "../config";
|
||||
|
||||
export class LayoutStoreEntry {
|
||||
public get currentLayout(): ILayout {
|
||||
@ -36,9 +36,12 @@ export class LayoutStoreEntry {
|
||||
private layouts: { [key: string]: ILayout };
|
||||
private previousID: string;
|
||||
|
||||
constructor() {
|
||||
private config: IConfig;
|
||||
|
||||
constructor(config: IConfig) {
|
||||
this.config = config;
|
||||
this.currentIndex = 0;
|
||||
this.currentID = CONFIG.layoutOrder[0];
|
||||
this.currentID = this.config.layoutOrder[0];
|
||||
this.layouts = {};
|
||||
this.previousID = this.currentID;
|
||||
|
||||
@ -49,9 +52,9 @@ export class LayoutStoreEntry {
|
||||
this.previousID = this.currentID;
|
||||
this.currentIndex =
|
||||
this.currentIndex !== null
|
||||
? wrapIndex(this.currentIndex + step, CONFIG.layoutOrder.length)
|
||||
? wrapIndex(this.currentIndex + step, this.config.layoutOrder.length)
|
||||
: 0;
|
||||
this.currentID = CONFIG.layoutOrder[this.currentIndex];
|
||||
this.currentID = this.config.layoutOrder[this.currentIndex];
|
||||
return this.loadLayout(this.currentID);
|
||||
}
|
||||
|
||||
@ -74,13 +77,13 @@ export class LayoutStoreEntry {
|
||||
}
|
||||
|
||||
private updateCurrentIndex(): void {
|
||||
const idx = CONFIG.layoutOrder.indexOf(this.currentID);
|
||||
const idx = this.config.layoutOrder.indexOf(this.currentID);
|
||||
this.currentIndex = idx === -1 ? null : idx;
|
||||
}
|
||||
|
||||
private loadLayout(ID: string): ILayout {
|
||||
let layout = this.layouts[ID];
|
||||
if (!layout) layout = this.layouts[ID] = CONFIG.layoutFactories[ID]();
|
||||
if (!layout) layout = this.layouts[ID] = this.config.layoutFactories[ID]();
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
@ -88,7 +91,10 @@ export class LayoutStoreEntry {
|
||||
export default class LayoutStore {
|
||||
private store: { [key: string]: LayoutStoreEntry };
|
||||
|
||||
constructor() {
|
||||
private config: IConfig;
|
||||
|
||||
constructor(config: IConfig) {
|
||||
this.config = config;
|
||||
this.store = {};
|
||||
}
|
||||
|
||||
@ -109,7 +115,7 @@ export default class LayoutStore {
|
||||
}
|
||||
|
||||
private getEntry(key: string): LayoutStoreEntry {
|
||||
if (!this.store[key]) this.store[key] = new LayoutStoreEntry();
|
||||
if (!this.store[key]) this.store[key] = new LayoutStoreEntry(this.config);
|
||||
return this.store[key];
|
||||
}
|
||||
}
|
||||
|
@ -22,9 +22,9 @@ import TilingEngine from "./tiling_engine";
|
||||
import IDriverContext from "../idriver_context";
|
||||
import Window from "./window";
|
||||
import { WindowState } from "./window";
|
||||
// import { CONFIG } from "../config";
|
||||
import { Shortcut } from "../shortcut";
|
||||
import { debugObj } from "../util/debug";
|
||||
import IConfig from "../config";
|
||||
|
||||
/**
|
||||
* TilingController translates events to actions, implementing high-level
|
||||
@ -34,9 +34,11 @@ import { debugObj } from "../util/debug";
|
||||
*/
|
||||
export default class TilingController {
|
||||
private engine: TilingEngine;
|
||||
private config: IConfig;
|
||||
|
||||
public constructor(engine: TilingEngine) {
|
||||
public constructor(engine: TilingEngine, config: IConfig) {
|
||||
this.engine = engine;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public onSurfaceUpdate(ctx: IDriverContext, comment: string): void {
|
||||
@ -128,7 +130,7 @@ export default class TilingController {
|
||||
|
||||
public onWindowResize(ctx: IDriverContext, window: Window): void {
|
||||
debugObj(() => ["onWindowResize", { window }]);
|
||||
if (CONFIG.adjustLayout && CONFIG.adjustLayoutLive) {
|
||||
if (this.config.adjustLayout && this.config.adjustLayoutLive) {
|
||||
if (window.state === WindowState.Tiled) {
|
||||
this.engine.adjustLayout(window);
|
||||
this.engine.arrange(ctx);
|
||||
@ -138,10 +140,10 @@ export default class TilingController {
|
||||
|
||||
public onWindowResizeOver(ctx: IDriverContext, window: Window): void {
|
||||
debugObj(() => ["onWindowResizeOver", { window }]);
|
||||
if (CONFIG.adjustLayout && window.tiled) {
|
||||
if (this.config.adjustLayout && window.tiled) {
|
||||
this.engine.adjustLayout(window);
|
||||
this.engine.arrange(ctx);
|
||||
} else if (!CONFIG.adjustLayout) this.engine.enforceSize(ctx, window);
|
||||
} else if (!this.config.adjustLayout) this.engine.enforceSize(ctx, window);
|
||||
}
|
||||
|
||||
public onWindowMaximizeChanged(
|
||||
@ -178,7 +180,7 @@ export default class TilingController {
|
||||
}
|
||||
|
||||
public onShortcut(ctx: IDriverContext, input: Shortcut, data?: any) {
|
||||
if (CONFIG.directionalKeyMode === "focus") {
|
||||
if (this.config.directionalKeyMode === "focus") {
|
||||
switch (input) {
|
||||
case Shortcut.Up:
|
||||
input = Shortcut.FocusUp;
|
||||
|
@ -24,7 +24,6 @@ import LayoutStore from "./layout_store";
|
||||
import EngineContext from "./engine_context";
|
||||
import WindowStore from "./window_store";
|
||||
import Window from "./window";
|
||||
// import { CONFIG } from "../config";
|
||||
import IDriverContext from "../idriver_context";
|
||||
import ISurface from "../isurface";
|
||||
import { Shortcut } from "../shortcut";
|
||||
@ -33,6 +32,7 @@ import Rect from "../util/rect";
|
||||
import RectDelta from "../util/rectdelta";
|
||||
import { debug, debugObj } from "../util/debug";
|
||||
import { overlap, wrapIndex } from "../util/func";
|
||||
import IConfig from "../config";
|
||||
|
||||
export type Direction = "up" | "down" | "left" | "right";
|
||||
|
||||
@ -43,8 +43,11 @@ export default class TilingEngine {
|
||||
public layouts: LayoutStore;
|
||||
public windows: WindowStore;
|
||||
|
||||
constructor() {
|
||||
this.layouts = new LayoutStore();
|
||||
private config: IConfig;
|
||||
|
||||
constructor(config: IConfig) {
|
||||
this.config = config;
|
||||
this.layouts = new LayoutStore(this.config);
|
||||
this.windows = new WindowStore();
|
||||
}
|
||||
|
||||
@ -61,10 +64,10 @@ export default class TilingEngine {
|
||||
const layout = this.layouts.getCurrentLayout(srf);
|
||||
if (layout.adjust) {
|
||||
const area = srf.workingArea.gap(
|
||||
CONFIG.screenGapLeft,
|
||||
CONFIG.screenGapRight,
|
||||
CONFIG.screenGapTop,
|
||||
CONFIG.screenGapBottom
|
||||
this.config.screenGapLeft,
|
||||
this.config.screenGapRight,
|
||||
this.config.screenGapTop,
|
||||
this.config.screenGapBottom
|
||||
);
|
||||
const tiles = this.windows.getVisibleTiles(srf);
|
||||
layout.adjust(area, tiles, basis, basis.geometryDelta);
|
||||
@ -165,10 +168,10 @@ export default class TilingEngine {
|
||||
const layout = this.layouts.getCurrentLayout(srf);
|
||||
if (layout.adjust) {
|
||||
const area = srf.workingArea.gap(
|
||||
CONFIG.screenGapLeft,
|
||||
CONFIG.screenGapRight,
|
||||
CONFIG.screenGapTop,
|
||||
CONFIG.screenGapBottom
|
||||
this.config.screenGapLeft,
|
||||
this.config.screenGapRight,
|
||||
this.config.screenGapTop,
|
||||
this.config.screenGapBottom
|
||||
);
|
||||
layout.adjust(area, this.windows.getVisibleTileables(srf), basis, delta);
|
||||
}
|
||||
@ -211,14 +214,14 @@ export default class TilingEngine {
|
||||
const workingArea = srf.workingArea;
|
||||
|
||||
let tilingArea: Rect;
|
||||
if (CONFIG.monocleMaximize && layout instanceof MonocleLayout)
|
||||
if (this.config.monocleMaximize && layout instanceof MonocleLayout)
|
||||
tilingArea = workingArea;
|
||||
else
|
||||
tilingArea = workingArea.gap(
|
||||
CONFIG.screenGapLeft,
|
||||
CONFIG.screenGapRight,
|
||||
CONFIG.screenGapTop,
|
||||
CONFIG.screenGapBottom
|
||||
this.config.screenGapLeft,
|
||||
this.config.screenGapRight,
|
||||
this.config.screenGapTop,
|
||||
this.config.screenGapBottom
|
||||
);
|
||||
|
||||
const visibles = this.windows.getVisibleWindows(srf);
|
||||
@ -239,15 +242,15 @@ export default class TilingEngine {
|
||||
});
|
||||
|
||||
const tileables = this.windows.getVisibleTileables(srf);
|
||||
if (CONFIG.maximizeSoleTile && tileables.length === 1) {
|
||||
if (this.config.maximizeSoleTile && tileables.length === 1) {
|
||||
tileables[0].state = WindowState.Maximized;
|
||||
tileables[0].geometry = workingArea;
|
||||
} else if (tileables.length > 0)
|
||||
layout.apply(new EngineContext(ctx, this), tileables, tilingArea);
|
||||
|
||||
if (CONFIG.limitTileWidthRatio > 0 && !(layout instanceof MonocleLayout)) {
|
||||
if (this.config.limitTileWidthRatio > 0 && !(layout instanceof MonocleLayout)) {
|
||||
const maxWidth = Math.floor(
|
||||
workingArea.height * CONFIG.limitTileWidthRatio
|
||||
workingArea.height * this.config.limitTileWidthRatio
|
||||
);
|
||||
tileables
|
||||
.filter((tile) => tile.tiled && tile.geometry.width > maxWidth)
|
||||
@ -287,7 +290,7 @@ export default class TilingEngine {
|
||||
if (!window.shouldIgnore) {
|
||||
/* engine#arrange will update the state when required. */
|
||||
window.state = WindowState.Undecided;
|
||||
if (CONFIG.newWindowAsMaster) this.windows.unshift(window);
|
||||
if (this.config.newWindowAsMaster) this.windows.unshift(window);
|
||||
else this.windows.push(window);
|
||||
}
|
||||
}
|
||||
|
@ -18,12 +18,12 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import IConfig from "../config";
|
||||
import IDriverWindow from "../idriver_window";
|
||||
import ISurface from "../isurface";
|
||||
import { debugObj } from "../util/debug";
|
||||
import Rect from "../util/rect";
|
||||
import RectDelta from "../util/rectdelta";
|
||||
// import { CONFIG } from "../config";
|
||||
|
||||
export enum WindowState {
|
||||
/* initial value */
|
||||
@ -153,7 +153,11 @@ export default class Window {
|
||||
private shouldCommitFloat: boolean;
|
||||
private weightMap: { [key: string]: number };
|
||||
|
||||
constructor(window: IDriverWindow) {
|
||||
private config: IConfig;
|
||||
|
||||
constructor(window: IDriverWindow, config: IConfig) {
|
||||
this.config = config;
|
||||
|
||||
this.id = window.id;
|
||||
this.window = window;
|
||||
|
||||
@ -180,7 +184,7 @@ export default class Window {
|
||||
|
||||
case WindowState.Floating:
|
||||
if (!this.shouldCommitFloat) break;
|
||||
this.window.commit(this.floatGeometry, false, CONFIG.keepFloatAbove);
|
||||
this.window.commit(this.floatGeometry, false, this.config.keepFloatAbove);
|
||||
this.shouldCommitFloat = false;
|
||||
break;
|
||||
|
||||
@ -189,12 +193,12 @@ export default class Window {
|
||||
break;
|
||||
|
||||
case WindowState.Tiled:
|
||||
this.window.commit(this.geometry, CONFIG.noTileBorder, false);
|
||||
this.window.commit(this.geometry, this.config.noTileBorder, false);
|
||||
break;
|
||||
|
||||
case WindowState.TiledAfloat:
|
||||
if (!this.shouldCommitFloat) break;
|
||||
this.window.commit(this.floatGeometry, false, CONFIG.keepFloatAbove);
|
||||
this.window.commit(this.floatGeometry, false, this.config.keepFloatAbove);
|
||||
this.shouldCommitFloat = false;
|
||||
break;
|
||||
}
|
||||
|
@ -1,51 +0,0 @@
|
||||
// Copyright (c) 2018-2019 Eon S. Jeon <esjeon@hyunmu.am>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import { ILayout } from "./ilayout";
|
||||
|
||||
export default interface IConfig {
|
||||
//#region Layout
|
||||
layoutOrder: string[];
|
||||
layoutFactories: { [key: string]: () => ILayout };
|
||||
monocleMaximize: boolean;
|
||||
maximizeSoleTile: boolean;
|
||||
//#endregion
|
||||
|
||||
//#region Features
|
||||
adjustLayout: boolean;
|
||||
adjustLayoutLive: boolean;
|
||||
keepFloatAbove: boolean;
|
||||
noTileBorder: boolean;
|
||||
limitTileWidthRatio: number;
|
||||
//#endregion
|
||||
|
||||
//#region Gap
|
||||
screenGapBottom: number;
|
||||
screenGapLeft: number;
|
||||
screenGapRight: number;
|
||||
screenGapTop: number;
|
||||
tileLayoutGap: number;
|
||||
//#endregion
|
||||
|
||||
//#region Behavior
|
||||
directionalKeyMode: "dwm" | "focus";
|
||||
newWindowAsMaster: boolean;
|
||||
//#endregion
|
||||
}
|
@ -23,10 +23,11 @@ import { Shortcut } from "./shortcut";
|
||||
import Window from "./engine/window";
|
||||
import Rect from "./util/rect";
|
||||
import RectDelta from "./util/rectdelta";
|
||||
import IConfig from "./config";
|
||||
|
||||
export interface ILayoutClass {
|
||||
readonly id: string;
|
||||
new(): ILayout;
|
||||
new(config: IConfig): ILayout;
|
||||
}
|
||||
|
||||
export interface ILayout {
|
||||
|
@ -18,10 +18,10 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import IConfig from "../config";
|
||||
import Window from "../engine/window";
|
||||
import Rect from "../util/rect";
|
||||
import RectDelta from "../util/rectdelta";
|
||||
// import { CONFIG } from "../config";
|
||||
import LayoutUtils from "./layout_utils";
|
||||
|
||||
export interface ILayoutPart {
|
||||
@ -182,7 +182,10 @@ export class HalfSplitLayoutPart<L extends ILayoutPart, R extends ILayoutPart>
|
||||
export class StackLayoutPart implements ILayoutPart {
|
||||
public gap: number;
|
||||
|
||||
constructor() {
|
||||
private config: IConfig;
|
||||
|
||||
constructor(config: IConfig) {
|
||||
this.config = config;
|
||||
this.gap = 0;
|
||||
}
|
||||
|
||||
@ -195,7 +198,7 @@ export class StackLayoutPart implements ILayoutPart {
|
||||
const weights = LayoutUtils.adjustAreaWeights(
|
||||
area,
|
||||
tiles.map((tile) => tile.weight),
|
||||
CONFIG.tileLayoutGap,
|
||||
this.config.tileLayoutGap,
|
||||
tiles.indexOf(basis),
|
||||
delta,
|
||||
false
|
||||
|
@ -22,11 +22,11 @@ import EngineContext from "../engine/engine_context";
|
||||
import KWinDriver from "../driver/kwin/kwin_driver";
|
||||
import KWinWindow from "../driver/kwin/kwin_window";
|
||||
import Window from "../engine/window";
|
||||
// import { CONFIG } from "../config";
|
||||
import { ILayout } from "../ilayout";
|
||||
import { Shortcut } from "../shortcut";
|
||||
import { WindowState } from "../engine/window";
|
||||
import Rect from "../util/rect";
|
||||
import IConfig from "../config";
|
||||
|
||||
export default class MonocleLayout implements ILayout {
|
||||
public static readonly id = "MonocleLayout";
|
||||
@ -34,10 +34,16 @@ export default class MonocleLayout implements ILayout {
|
||||
|
||||
public readonly classID = MonocleLayout.id;
|
||||
|
||||
private config: IConfig;
|
||||
|
||||
constructor(config: IConfig) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public apply(ctx: EngineContext, tileables: Window[], area: Rect): void {
|
||||
/* Tile all tileables */
|
||||
tileables.forEach((tile) => {
|
||||
tile.state = CONFIG.monocleMaximize
|
||||
tile.state = this.config.monocleMaximize
|
||||
? WindowState.Maximized
|
||||
: WindowState.Tiled;
|
||||
tile.geometry = area;
|
||||
@ -46,7 +52,7 @@ export default class MonocleLayout implements ILayout {
|
||||
/* KWin-specific `monocleMinimizeRest` option */
|
||||
if (
|
||||
ctx.backend === KWinDriver.backendName &&
|
||||
KWINCONFIG.monocleMinimizeRest
|
||||
this.config.monocleMinimizeRest
|
||||
) {
|
||||
const tiles = [...tileables];
|
||||
ctx.setTimeout(() => {
|
||||
|
@ -25,7 +25,7 @@ import { WindowState } from "../engine/window";
|
||||
import { clip } from "../util/func";
|
||||
import Rect from "../util/rect";
|
||||
import RectDelta from "../util/rectdelta";
|
||||
// import { CONFIG } from "../config";
|
||||
import IConfig from "../config";
|
||||
|
||||
export default class QuarterLayout implements ILayout {
|
||||
public static readonly MAX_PROPORTION = 0.8;
|
||||
@ -42,10 +42,14 @@ export default class QuarterLayout implements ILayout {
|
||||
private rhsplit: number;
|
||||
private vsplit: number;
|
||||
|
||||
public constructor() {
|
||||
private config: IConfig;
|
||||
|
||||
public constructor(config: IConfig) {
|
||||
this.lhsplit = 0.5;
|
||||
this.rhsplit = 0.5;
|
||||
this.vsplit = 0.5;
|
||||
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public adjust(area: Rect, tiles: Window[], basis: Window, delta: RectDelta) {
|
||||
@ -101,7 +105,7 @@ export default class QuarterLayout implements ILayout {
|
||||
}
|
||||
|
||||
public clone(): ILayout {
|
||||
const other = new QuarterLayout();
|
||||
const other = new QuarterLayout(this.config);
|
||||
other.lhsplit = this.lhsplit;
|
||||
other.rhsplit = this.rhsplit;
|
||||
other.vsplit = this.vsplit;
|
||||
@ -122,8 +126,8 @@ export default class QuarterLayout implements ILayout {
|
||||
return;
|
||||
}
|
||||
|
||||
const gap1 = Math.floor(CONFIG.tileLayoutGap / 2);
|
||||
const gap2 = CONFIG.tileLayoutGap - gap1;
|
||||
const gap1 = Math.floor(this.config.tileLayoutGap / 2);
|
||||
const gap2 = this.config.tileLayoutGap - gap1;
|
||||
|
||||
const leftWidth = Math.floor(area.width * this.vsplit);
|
||||
const rightWidth = area.width - leftWidth;
|
||||
|
@ -22,11 +22,11 @@ import EngineContext from "../engine/engine_context";
|
||||
import { HalfSplitLayoutPart } from "./layout_part";
|
||||
import { FillLayoutPart } from "./layout_part";
|
||||
import { ILayout } from "../ilayout";
|
||||
// import { CONFIG } from "../config";
|
||||
import Window from "../engine/window";
|
||||
import { WindowState } from "../engine/window";
|
||||
import Rect from "../util/rect";
|
||||
import RectDelta from "../util/rectdelta";
|
||||
import IConfig from "../config";
|
||||
|
||||
export type SpiralLayoutPart = HalfSplitLayoutPart<
|
||||
FillLayoutPart,
|
||||
@ -39,14 +39,18 @@ export default class SpiralLayout implements ILayout {
|
||||
private depth: number;
|
||||
private parts: SpiralLayoutPart;
|
||||
|
||||
constructor() {
|
||||
private config: IConfig;
|
||||
|
||||
constructor(config: IConfig) {
|
||||
this.config = config;
|
||||
|
||||
this.depth = 1;
|
||||
this.parts = new HalfSplitLayoutPart(
|
||||
new FillLayoutPart(),
|
||||
new FillLayoutPart()
|
||||
);
|
||||
this.parts.angle = 0;
|
||||
this.parts.gap = CONFIG.tileLayoutGap;
|
||||
this.parts.gap = this.config.tileLayoutGap;
|
||||
}
|
||||
|
||||
public adjust(
|
||||
@ -87,7 +91,7 @@ export default class SpiralLayout implements ILayout {
|
||||
let npart: SpiralLayoutPart;
|
||||
while (i < depth - 1) {
|
||||
npart = new HalfSplitLayoutPart(new FillLayoutPart(), lastFillPart);
|
||||
npart.gap = CONFIG.tileLayoutGap;
|
||||
npart.gap = this.config.tileLayoutGap;
|
||||
switch ((i + 1) % 4) {
|
||||
case 0:
|
||||
npart.angle = 0;
|
||||
|
@ -21,13 +21,13 @@
|
||||
import EngineContext from "../engine/engine_context";
|
||||
import { ILayout } from "../ilayout";
|
||||
import Window from "../engine/window";
|
||||
// import { CONFIG } from "../config";
|
||||
import LayoutUtils from "./layout_utils";
|
||||
import { Shortcut } from "../shortcut";
|
||||
import { WindowState } from "../engine/window";
|
||||
import { partitionArrayBySizes, clip, slide } from "../util/func";
|
||||
import Rect from "../util/rect";
|
||||
import RectDelta from "../util/rectdelta";
|
||||
import IConfig from "../config";
|
||||
|
||||
export default class ThreeColumnLayout implements ILayout {
|
||||
public static readonly MIN_MASTER_RATIO = 0.2;
|
||||
@ -43,7 +43,10 @@ export default class ThreeColumnLayout implements ILayout {
|
||||
private masterRatio: number;
|
||||
private masterSize: number;
|
||||
|
||||
constructor() {
|
||||
private config: IConfig;
|
||||
|
||||
constructor(config: IConfig) {
|
||||
this.config = config;
|
||||
this.masterRatio = 0.6;
|
||||
this.masterSize = 1;
|
||||
}
|
||||
@ -65,7 +68,7 @@ export default class ThreeColumnLayout implements ILayout {
|
||||
LayoutUtils.adjustAreaWeights(
|
||||
area,
|
||||
tiles.map((tile) => tile.weight),
|
||||
CONFIG.tileLayoutGap,
|
||||
this.config.tileLayoutGap,
|
||||
tiles.indexOf(basis),
|
||||
delta
|
||||
).forEach((newWeight, i) => (tiles[i].weight = newWeight * tiles.length));
|
||||
@ -76,7 +79,7 @@ export default class ThreeColumnLayout implements ILayout {
|
||||
this.masterRatio = LayoutUtils.adjustAreaHalfWeights(
|
||||
area,
|
||||
this.masterRatio,
|
||||
CONFIG.tileLayoutGap,
|
||||
this.config.tileLayoutGap,
|
||||
basisIndex < this.masterSize ? 0 : 1,
|
||||
delta,
|
||||
true
|
||||
@ -88,7 +91,7 @@ export default class ThreeColumnLayout implements ILayout {
|
||||
LayoutUtils.adjustAreaWeights(
|
||||
area,
|
||||
masterTiles.map((tile) => tile.weight),
|
||||
CONFIG.tileLayoutGap,
|
||||
this.config.tileLayoutGap,
|
||||
basisIndex,
|
||||
delta
|
||||
).forEach(
|
||||
@ -111,7 +114,7 @@ export default class ThreeColumnLayout implements ILayout {
|
||||
const newRatios = LayoutUtils.adjustAreaWeights(
|
||||
area,
|
||||
[stackRatio, this.masterRatio, stackRatio],
|
||||
CONFIG.tileLayoutGap,
|
||||
this.config.tileLayoutGap,
|
||||
basisGroup,
|
||||
delta,
|
||||
true
|
||||
@ -128,7 +131,7 @@ export default class ThreeColumnLayout implements ILayout {
|
||||
LayoutUtils.adjustAreaWeights(
|
||||
area /* we only need height */,
|
||||
groupTiles.map((tile) => tile.weight),
|
||||
CONFIG.tileLayoutGap,
|
||||
this.config.tileLayoutGap,
|
||||
groupTiles.indexOf(basis),
|
||||
delta
|
||||
).forEach(
|
||||
@ -147,14 +150,14 @@ export default class ThreeColumnLayout implements ILayout {
|
||||
LayoutUtils.splitAreaWeighted(
|
||||
area,
|
||||
tiles.map((tile) => tile.weight),
|
||||
CONFIG.tileLayoutGap
|
||||
this.config.tileLayoutGap
|
||||
).forEach((tileArea, i) => (tiles[i].geometry = tileArea));
|
||||
} else if (tiles.length === this.masterSize + 1) {
|
||||
/* master & R-stack (only 1 window in stack) */
|
||||
const [masterArea, stackArea] = LayoutUtils.splitAreaHalfWeighted(
|
||||
area,
|
||||
this.masterRatio,
|
||||
CONFIG.tileLayoutGap,
|
||||
this.config.tileLayoutGap,
|
||||
true
|
||||
);
|
||||
|
||||
@ -162,7 +165,7 @@ export default class ThreeColumnLayout implements ILayout {
|
||||
LayoutUtils.splitAreaWeighted(
|
||||
masterArea,
|
||||
masterTiles.map((tile) => tile.weight),
|
||||
CONFIG.tileLayoutGap
|
||||
this.config.tileLayoutGap
|
||||
).forEach((tileArea, i) => (masterTiles[i].geometry = tileArea));
|
||||
|
||||
tiles[tiles.length - 1].geometry = stackArea;
|
||||
@ -174,7 +177,7 @@ export default class ThreeColumnLayout implements ILayout {
|
||||
const groupAreas = LayoutUtils.splitAreaWeighted(
|
||||
area,
|
||||
[stackRatio, this.masterRatio, stackRatio],
|
||||
CONFIG.tileLayoutGap,
|
||||
this.config.tileLayoutGap,
|
||||
true
|
||||
);
|
||||
|
||||
@ -185,14 +188,14 @@ export default class ThreeColumnLayout implements ILayout {
|
||||
LayoutUtils.splitAreaWeighted(
|
||||
groupAreas[group],
|
||||
groupTiles.map((tile) => tile.weight),
|
||||
CONFIG.tileLayoutGap
|
||||
this.config.tileLayoutGap
|
||||
).forEach((tileArea, i) => (groupTiles[i].geometry = tileArea));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public clone(): ILayout {
|
||||
const other = new ThreeColumnLayout();
|
||||
const other = new ThreeColumnLayout(this.config);
|
||||
other.masterRatio = this.masterRatio;
|
||||
other.masterSize = this.masterSize;
|
||||
return other;
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
import EngineContext from "../engine/engine_context";
|
||||
import { ILayout } from "../ilayout";
|
||||
// import { CONFIG } from "../config";
|
||||
import Window from "../engine/window";
|
||||
import { WindowState } from "../engine/window";
|
||||
import { Shortcut } from "../shortcut";
|
||||
@ -29,6 +28,7 @@ import { RotateLayoutPart, HalfSplitLayoutPart, StackLayoutPart } from "./layout
|
||||
import { clip, slide } from "../util/func";
|
||||
import Rect from "../util/rect";
|
||||
import RectDelta from "../util/rectdelta";
|
||||
import IConfig from "../config";
|
||||
|
||||
export default class TileLayout implements ILayout {
|
||||
public static readonly MIN_MASTER_RATIO = 0.2;
|
||||
@ -61,11 +61,15 @@ export default class TileLayout implements ILayout {
|
||||
this.parts.inner.ratio = value;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
private config: IConfig;
|
||||
|
||||
constructor(config: IConfig) {
|
||||
this.config = config;
|
||||
|
||||
this.parts = new RotateLayoutPart(
|
||||
new HalfSplitLayoutPart(
|
||||
new RotateLayoutPart(new StackLayoutPart()),
|
||||
new StackLayoutPart()
|
||||
new RotateLayoutPart(new StackLayoutPart(this.config)),
|
||||
new StackLayoutPart(this.config)
|
||||
)
|
||||
);
|
||||
|
||||
@ -73,7 +77,7 @@ export default class TileLayout implements ILayout {
|
||||
masterPart.gap =
|
||||
masterPart.primary.inner.gap =
|
||||
masterPart.secondary.gap =
|
||||
CONFIG.tileLayoutGap;
|
||||
this.config.tileLayoutGap;
|
||||
}
|
||||
|
||||
public adjust(area: Rect, tiles: Window[], basis: Window, delta: RectDelta) {
|
||||
@ -89,7 +93,7 @@ export default class TileLayout implements ILayout {
|
||||
}
|
||||
|
||||
public clone(): ILayout {
|
||||
const other = new TileLayout();
|
||||
const other = new TileLayout(this.config);
|
||||
other.masterRatio = this.masterRatio;
|
||||
other.numMaster = this.numMaster;
|
||||
return other;
|
||||
|
Loading…
Reference in New Issue
Block a user