3070 lines
120 KiB
JavaScript
3070 lines
120 KiB
JavaScript
"use strict";
|
|
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
if (ar || !(i in from)) {
|
|
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
ar[i] = from[i];
|
|
}
|
|
}
|
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
};
|
|
var Shortcut;
|
|
(function (Shortcut) {
|
|
Shortcut[Shortcut["FocusNext"] = 0] = "FocusNext";
|
|
Shortcut[Shortcut["FocusPrev"] = 1] = "FocusPrev";
|
|
Shortcut[Shortcut["DWMLeft"] = 2] = "DWMLeft";
|
|
Shortcut[Shortcut["DWMRight"] = 3] = "DWMRight";
|
|
Shortcut[Shortcut["FocusUp"] = 4] = "FocusUp";
|
|
Shortcut[Shortcut["FocusDown"] = 5] = "FocusDown";
|
|
Shortcut[Shortcut["FocusLeft"] = 6] = "FocusLeft";
|
|
Shortcut[Shortcut["FocusRight"] = 7] = "FocusRight";
|
|
Shortcut[Shortcut["ShiftLeft"] = 8] = "ShiftLeft";
|
|
Shortcut[Shortcut["ShiftRight"] = 9] = "ShiftRight";
|
|
Shortcut[Shortcut["ShiftUp"] = 10] = "ShiftUp";
|
|
Shortcut[Shortcut["ShiftDown"] = 11] = "ShiftDown";
|
|
Shortcut[Shortcut["SwapUp"] = 12] = "SwapUp";
|
|
Shortcut[Shortcut["SwapDown"] = 13] = "SwapDown";
|
|
Shortcut[Shortcut["SwapLeft"] = 14] = "SwapLeft";
|
|
Shortcut[Shortcut["SwapRight"] = 15] = "SwapRight";
|
|
Shortcut[Shortcut["GrowWidth"] = 16] = "GrowWidth";
|
|
Shortcut[Shortcut["GrowHeight"] = 17] = "GrowHeight";
|
|
Shortcut[Shortcut["ShrinkWidth"] = 18] = "ShrinkWidth";
|
|
Shortcut[Shortcut["ShrinkHeight"] = 19] = "ShrinkHeight";
|
|
Shortcut[Shortcut["Increase"] = 20] = "Increase";
|
|
Shortcut[Shortcut["Decrease"] = 21] = "Decrease";
|
|
Shortcut[Shortcut["ShiftIncrease"] = 22] = "ShiftIncrease";
|
|
Shortcut[Shortcut["ShiftDecrease"] = 23] = "ShiftDecrease";
|
|
Shortcut[Shortcut["ToggleFloat"] = 24] = "ToggleFloat";
|
|
Shortcut[Shortcut["ToggleFloatAll"] = 25] = "ToggleFloatAll";
|
|
Shortcut[Shortcut["SetMaster"] = 26] = "SetMaster";
|
|
Shortcut[Shortcut["NextLayout"] = 27] = "NextLayout";
|
|
Shortcut[Shortcut["PreviousLayout"] = 28] = "PreviousLayout";
|
|
Shortcut[Shortcut["SetLayout"] = 29] = "SetLayout";
|
|
Shortcut[Shortcut["Rotate"] = 30] = "Rotate";
|
|
Shortcut[Shortcut["RotatePart"] = 31] = "RotatePart";
|
|
})(Shortcut || (Shortcut = {}));
|
|
var CONFIG;
|
|
var KWinConfig = (function () {
|
|
function KWinConfig() {
|
|
var _this = this;
|
|
function commaSeparate(str) {
|
|
if (!str || typeof str !== "string")
|
|
return [];
|
|
return str
|
|
.split(",")
|
|
.map(function (part) { return part.trim(); })
|
|
.filter(function (part) { return part != ""; });
|
|
}
|
|
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],
|
|
["enableStackedLayout", false, StackedLayout],
|
|
["enableFloatingLayout", false, FloatingLayout],
|
|
["enableBTreeLayout", false, BTreeLayout],
|
|
["enableCascadeLayout", false, CascadeLayout],
|
|
].forEach(function (_a) {
|
|
var configKey = _a[0], defaultValue = _a[1], layoutClass = _a[2];
|
|
if (KWIN.readConfig(configKey, defaultValue))
|
|
_this.layoutOrder.push(layoutClass.id);
|
|
_this.layoutFactories[layoutClass.id] = function () { return new layoutClass(); };
|
|
});
|
|
this.maximizeSoleTile = KWIN.readConfig("maximizeSoleTile", false);
|
|
this.monocleMaximize = KWIN.readConfig("monocleMaximize", true);
|
|
this.monocleMinimizeRest = KWIN.readConfig("monocleMinimizeRest", false);
|
|
this.stairReverse = KWIN.readConfig("stairReverse", false);
|
|
this.adjustLayout = KWIN.readConfig("adjustLayout", true);
|
|
this.adjustLayoutLive = KWIN.readConfig("adjustLayoutLive", true);
|
|
this.keepFloatAbove = KWIN.readConfig("keepFloatAbove", true);
|
|
this.keepTilingOnDrag = KWIN.readConfig("keepTilingOnDrag", false);
|
|
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);
|
|
var directionalKeyDwm = KWIN.readConfig("directionalKeyDwm", false);
|
|
var directionalKeyFocus = KWIN.readConfig("directionalKeyFocus", true);
|
|
this.directionalKeyMode = directionalKeyDwm ? "dwm" : "focus";
|
|
this.newWindowPosition = KWIN.readConfig("newWindowPosition", 0);
|
|
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,xwaylandvideobridge,plasmashell,ksplashqml"));
|
|
this.ignoreRole = commaSeparate(KWIN.readConfig("ignoreRole", "quake"));
|
|
this.ignoreScreen = commaSeparate(KWIN.readConfig("ignoreScreen", ""));
|
|
this.ignoreTitle = commaSeparate(KWIN.readConfig("ignoreTitle", ""));
|
|
this.screenDefaultLayout = commaSeparate(KWIN.readConfig("screenDefaultLayout", ""));
|
|
if (this.preventMinimize && this.monocleMinimizeRest) {
|
|
debug(function () { return "preventMinimize is disabled because of monocleMinimizeRest."; });
|
|
this.preventMinimize = false;
|
|
}
|
|
}
|
|
KWinConfig.prototype.toString = function () {
|
|
return "Config(" + JSON.stringify(this, undefined, 2) + ")";
|
|
};
|
|
return KWinConfig;
|
|
}());
|
|
var KWINCONFIG;
|
|
var KWIN;
|
|
var KWinDriver = (function () {
|
|
function KWinDriver(api) {
|
|
var _this = this;
|
|
KWIN = api.kwin;
|
|
this.workspace = api.workspace;
|
|
this.shortcuts = api.shortcuts;
|
|
this.engine = new TilingEngine();
|
|
this.control = new TilingController(this.engine);
|
|
this.windowMap = new WrapperMap(function (client) { return KWinWindow.generateID(client); }, function (client) {
|
|
return new WindowClass(new KWinWindow(client, _this.workspace));
|
|
});
|
|
this.entered = false;
|
|
this.mousePoller = new KWinMousePoller();
|
|
}
|
|
Object.defineProperty(KWinDriver.prototype, "backend", {
|
|
get: function () {
|
|
return KWinDriver.backendName;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(KWinDriver.prototype, "currentSurface", {
|
|
get: function () {
|
|
return new KWinSurface(this.workspace.activeWindow
|
|
? this.workspace.activeWindow.output
|
|
: this.workspace.activeScreen, this.workspace.currentActivity, this.workspace.currentDesktop, this.workspace);
|
|
},
|
|
set: function (value) {
|
|
var ksrf = value;
|
|
if (this.workspace.currentDesktop.name !== ksrf.desktop.name)
|
|
this.workspace.currentDesktop = ksrf.desktop;
|
|
if (this.workspace.currentActivity !== ksrf.activity)
|
|
this.workspace.currentActivity = ksrf.activity;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(KWinDriver.prototype, "currentWindow", {
|
|
get: function () {
|
|
var client = this.workspace.activeWindow;
|
|
return client ? this.windowMap.get(client) : null;
|
|
},
|
|
set: function (window) {
|
|
if (window !== null)
|
|
this.workspace.activeWindow = window.window.window;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(KWinDriver.prototype, "screens", {
|
|
get: function () {
|
|
var _this = this;
|
|
var screens = [];
|
|
this.workspace.screens.forEach(function (screen) {
|
|
screens.push(new KWinSurface(screen, _this.workspace.currentActivity, _this.workspace.currentDesktop, _this.workspace));
|
|
});
|
|
return screens;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(KWinDriver.prototype, "cursorPosition", {
|
|
get: function () {
|
|
return this.mousePoller.mousePosition;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
KWinDriver.prototype.main = function () {
|
|
CONFIG = KWINCONFIG = new KWinConfig();
|
|
debug(function () { return "Config: " + KWINCONFIG; });
|
|
this.bindEvents();
|
|
this.bindShortcut();
|
|
var clients = this.workspace.stackingOrder;
|
|
for (var i = 0; i < clients.length; i++) {
|
|
this.addWindow(clients[i]);
|
|
}
|
|
};
|
|
KWinDriver.prototype.addWindow = function (client) {
|
|
if (client.normalWindow &&
|
|
!client.hidden &&
|
|
client.width * client.height > 10) {
|
|
if (KWIN.readConfig("debugActiveWin", false))
|
|
print(debugWin(client));
|
|
var window = this.windowMap.add(client);
|
|
this.control.onWindowAdded(this, window);
|
|
if (window.state !== WindowState.Unmanaged) {
|
|
this.bindWindowEvents(window, client);
|
|
}
|
|
else {
|
|
this.windowMap.remove(client);
|
|
if (KWIN.readConfig("debugActiveWin", false))
|
|
print("Unmanaged: " + debugWin(client));
|
|
}
|
|
}
|
|
else {
|
|
if (KWIN.readConfig("debugActiveWin", false))
|
|
print("Filtered: " + debugWin(client));
|
|
}
|
|
};
|
|
KWinDriver.prototype.setTimeout = function (func, timeout) {
|
|
var _this = this;
|
|
KWinSetTimeout(function () { return _this.enter(func); }, timeout);
|
|
};
|
|
KWinDriver.prototype.showNotification = function (text) {
|
|
popupDialog.show(text);
|
|
};
|
|
KWinDriver.prototype.bindShortcut = function () {
|
|
var _this = this;
|
|
var callbackShortcut = function (shortcut) {
|
|
return function () {
|
|
_this.enter(function () { return _this.control.onShortcut(_this, shortcut); });
|
|
};
|
|
};
|
|
this.shortcuts
|
|
.getFocusNext()
|
|
.activated.connect(callbackShortcut(Shortcut.FocusNext));
|
|
this.shortcuts
|
|
.getFocusPrev()
|
|
.activated.connect(callbackShortcut(Shortcut.FocusPrev));
|
|
this.shortcuts
|
|
.getFocusDown()
|
|
.activated.connect(callbackShortcut(Shortcut.FocusDown));
|
|
this.shortcuts
|
|
.getFocusUp()
|
|
.activated.connect(callbackShortcut(Shortcut.FocusUp));
|
|
this.shortcuts
|
|
.getFocusLeft()
|
|
.activated.connect(callbackShortcut(Shortcut.FocusLeft));
|
|
this.shortcuts
|
|
.getFocusRight()
|
|
.activated.connect(callbackShortcut(Shortcut.FocusRight));
|
|
this.shortcuts
|
|
.getShiftDown()
|
|
.activated.connect(callbackShortcut(Shortcut.ShiftDown));
|
|
this.shortcuts
|
|
.getShiftUp()
|
|
.activated.connect(callbackShortcut(Shortcut.ShiftUp));
|
|
this.shortcuts
|
|
.getShiftLeft()
|
|
.activated.connect(callbackShortcut(Shortcut.ShiftLeft));
|
|
this.shortcuts
|
|
.getShiftRight()
|
|
.activated.connect(callbackShortcut(Shortcut.ShiftRight));
|
|
this.shortcuts
|
|
.getGrowHeight()
|
|
.activated.connect(callbackShortcut(Shortcut.GrowHeight));
|
|
this.shortcuts
|
|
.getShrinkHeight()
|
|
.activated.connect(callbackShortcut(Shortcut.ShrinkHeight));
|
|
this.shortcuts
|
|
.getShrinkWidth()
|
|
.activated.connect(callbackShortcut(Shortcut.ShrinkWidth));
|
|
this.shortcuts
|
|
.getGrowWidth()
|
|
.activated.connect(callbackShortcut(Shortcut.GrowWidth));
|
|
this.shortcuts
|
|
.getIncrease()
|
|
.activated.connect(callbackShortcut(Shortcut.Increase));
|
|
this.shortcuts
|
|
.getDecrease()
|
|
.activated.connect(callbackShortcut(Shortcut.Decrease));
|
|
this.shortcuts
|
|
.getToggleFloat()
|
|
.activated.connect(callbackShortcut(Shortcut.ToggleFloat));
|
|
this.shortcuts
|
|
.getFloatAll()
|
|
.activated.connect(callbackShortcut(Shortcut.ToggleFloatAll));
|
|
this.shortcuts
|
|
.getNextLayout()
|
|
.activated.connect(callbackShortcut(Shortcut.NextLayout));
|
|
this.shortcuts
|
|
.getPreviousLayout()
|
|
.activated.connect(callbackShortcut(Shortcut.PreviousLayout));
|
|
this.shortcuts
|
|
.getRotate()
|
|
.activated.connect(callbackShortcut(Shortcut.Rotate));
|
|
this.shortcuts
|
|
.getRotatePart()
|
|
.activated.connect(callbackShortcut(Shortcut.RotatePart));
|
|
this.shortcuts
|
|
.getSetMaster()
|
|
.activated.connect(callbackShortcut(Shortcut.SetMaster));
|
|
var callbackShortcutLayout = function (layoutClass) {
|
|
return function () {
|
|
_this.enter(function () {
|
|
return _this.control.onShortcut(_this, Shortcut.SetLayout, layoutClass.id);
|
|
});
|
|
};
|
|
};
|
|
this.shortcuts
|
|
.getTileLayout()
|
|
.activated.connect(callbackShortcutLayout(TileLayout));
|
|
this.shortcuts
|
|
.getMonocleLayout()
|
|
.activated.connect(callbackShortcutLayout(MonocleLayout));
|
|
this.shortcuts
|
|
.getThreeColumnLayout()
|
|
.activated.connect(callbackShortcutLayout(ThreeColumnLayout));
|
|
this.shortcuts
|
|
.getSpreadLayout()
|
|
.activated.connect(callbackShortcutLayout(SpreadLayout));
|
|
this.shortcuts
|
|
.getStairLayout()
|
|
.activated.connect(callbackShortcutLayout(StairLayout));
|
|
this.shortcuts
|
|
.getFloatingLayout()
|
|
.activated.connect(callbackShortcutLayout(FloatingLayout));
|
|
this.shortcuts
|
|
.getQuarterLayout()
|
|
.activated.connect(callbackShortcutLayout(QuarterLayout));
|
|
this.shortcuts
|
|
.getStackedLayout()
|
|
.activated.connect(callbackShortcutLayout(StackedLayout));
|
|
this.shortcuts
|
|
.getSpiralLayout()
|
|
.activated.connect(callbackShortcutLayout(SpiralLayout));
|
|
this.shortcuts
|
|
.getBTreeLayout()
|
|
.activated.connect(callbackShortcutLayout(BTreeLayout));
|
|
};
|
|
KWinDriver.prototype.connect = function (signal, handler) {
|
|
var _this = this;
|
|
var wrapper = function () {
|
|
var args = [];
|
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
args[_i] = arguments[_i];
|
|
}
|
|
if (typeof _this.workspace === "undefined")
|
|
signal.disconnect(wrapper);
|
|
else
|
|
_this.enter(function () { return handler.apply(_this, args); });
|
|
};
|
|
signal.connect(wrapper);
|
|
return wrapper;
|
|
};
|
|
KWinDriver.prototype.enter = function (callback) {
|
|
if (this.entered)
|
|
return;
|
|
this.entered = true;
|
|
try {
|
|
callback();
|
|
}
|
|
catch (e) {
|
|
debug(function () { return "Error raised from line " + e.lineNumber; });
|
|
debug(function () { return e; });
|
|
}
|
|
finally {
|
|
this.entered = false;
|
|
}
|
|
};
|
|
KWinDriver.prototype.bindEvents = function () {
|
|
var _this = this;
|
|
this.connect(this.workspace.screensChanged, function () {
|
|
return _this.control.onSurfaceUpdate(_this, "screens (Outputs) changed");
|
|
});
|
|
this.connect(this.workspace.virtualScreenGeometryChanged, function () {
|
|
_this.control.onSurfaceUpdate(_this, "virtualScreenGeometryChanged");
|
|
});
|
|
this.connect(this.workspace.currentActivityChanged, function (activityId) {
|
|
return _this.control.onCurrentActivityChanged(_this, activityId);
|
|
});
|
|
this.connect(this.workspace.currentDesktopChanged, function (virtualDesktop) {
|
|
return _this.control.onSurfaceUpdate(_this, "currentDesktopChanged");
|
|
});
|
|
this.connect(this.workspace.windowAdded, function (client) {
|
|
_this.addWindow(client);
|
|
});
|
|
this.connect(this.workspace.windowRemoved, function (client) {
|
|
var window = _this.windowMap.get(client);
|
|
if (window) {
|
|
_this.control.onWindowRemoved(_this, window);
|
|
_this.windowMap.remove(client);
|
|
}
|
|
});
|
|
};
|
|
KWinDriver.prototype.bindWindowEvents = function (window, client) {
|
|
var _this = this;
|
|
var moving = false;
|
|
var resizing = false;
|
|
this.connect(client.maximizedAboutToChange, function (mode) {
|
|
var maximized = mode === 3;
|
|
window.window.maximized = maximized;
|
|
_this.control.onWindowMaximizeChanged(_this, window, maximized);
|
|
});
|
|
this.connect(client.minimizedChanged, function () {
|
|
if (KWINCONFIG.preventMinimize) {
|
|
client.minimized = false;
|
|
_this.workspace.activeWindow = client;
|
|
}
|
|
else {
|
|
var comment = client.minimized ? "minimized" : "unminimized";
|
|
_this.control.onWindowChanged(_this, window, comment);
|
|
}
|
|
});
|
|
this.connect(client.fullScreenChanged, function () {
|
|
return _this.control.onWindowChanged(_this, window, "fullscreen=" + client.fullScreen);
|
|
});
|
|
this.connect(client.moveResizedChanged, function () {
|
|
debugObj(function () { return [
|
|
"moveResizedChanged",
|
|
{ window: window, move: client.move, resize: client.resize },
|
|
]; });
|
|
if (moving !== client.move) {
|
|
moving = client.move;
|
|
if (moving) {
|
|
_this.mousePoller.start();
|
|
_this.control.onWindowMoveStart(window);
|
|
}
|
|
else {
|
|
_this.control.onWindowMoveOver(_this, window);
|
|
_this.mousePoller.stop();
|
|
}
|
|
}
|
|
if (resizing !== client.resize) {
|
|
resizing = client.resize;
|
|
if (resizing)
|
|
_this.control.onWindowResizeStart(window);
|
|
else
|
|
_this.control.onWindowResizeOver(_this, window);
|
|
}
|
|
});
|
|
this.connect(client.bufferGeometryChanged, function () {
|
|
if (moving)
|
|
_this.control.onWindowMove(window);
|
|
else if (resizing)
|
|
_this.control.onWindowResize(_this, window);
|
|
else {
|
|
if (!window.actualGeometry.equals(window.geometry))
|
|
_this.control.onWindowGeometryChanged(_this, window);
|
|
}
|
|
});
|
|
this.connect(client.activeChanged, function () {
|
|
if (client.active)
|
|
_this.control.onWindowFocused(_this, window);
|
|
});
|
|
this.connect(client.outputChanged, function () {
|
|
return _this.control.onWindowChanged(_this, window, "screen=" + client.output.name);
|
|
});
|
|
this.connect(client.activitiesChanged, function () {
|
|
return _this.control.onWindowChanged(_this, window, "activity=" + client.activities.join(","));
|
|
});
|
|
this.connect(client.desktopsChanged, function () {
|
|
return _this.control.onWindowChanged(_this, window, "Window's desktop changed.");
|
|
});
|
|
};
|
|
KWinDriver.backendName = "kwin";
|
|
return KWinDriver;
|
|
}());
|
|
var KWinMousePoller = (function () {
|
|
function KWinMousePoller() {
|
|
var _this = this;
|
|
this.startCount = 0;
|
|
this.cmdResult = null;
|
|
mousePoller.interval = 0;
|
|
mousePoller.onNewData.connect(function (sourceName, data) {
|
|
_this.cmdResult = data["exit code"] === 0 ? data["stdout"] : null;
|
|
mousePoller.disconnectSource(KWinMousePoller.COMMAND);
|
|
KWinSetTimeout(function () {
|
|
if (_this.started)
|
|
mousePoller.connectSource(KWinMousePoller.COMMAND);
|
|
}, KWinMousePoller.INTERVAL);
|
|
});
|
|
}
|
|
Object.defineProperty(KWinMousePoller.prototype, "started", {
|
|
get: function () {
|
|
return this.startCount > 0;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(KWinMousePoller.prototype, "mousePosition", {
|
|
get: function () {
|
|
return this.parseResult();
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
KWinMousePoller.prototype.start = function () {
|
|
this.startCount += 1;
|
|
if (KWINCONFIG.pollMouseXdotool)
|
|
mousePoller.connectSource(KWinMousePoller.COMMAND);
|
|
};
|
|
KWinMousePoller.prototype.stop = function () {
|
|
this.startCount = Math.max(this.startCount - 1, 0);
|
|
};
|
|
KWinMousePoller.prototype.parseResult = function () {
|
|
if (!this.cmdResult)
|
|
return null;
|
|
var x = null;
|
|
var y = null;
|
|
this.cmdResult
|
|
.split(" ")
|
|
.slice(0, 2)
|
|
.forEach(function (part) {
|
|
var _a = part.split(":"), key = _a[0], value = _a[1], _ = _a[2];
|
|
if (key === "x")
|
|
x = parseInt(value, 10);
|
|
if (key === "y")
|
|
y = parseInt(value, 10);
|
|
});
|
|
if (x === null || y === null)
|
|
return null;
|
|
return [x, y];
|
|
};
|
|
KWinMousePoller.COMMAND = "xdotool getmouselocation";
|
|
KWinMousePoller.INTERVAL = 50;
|
|
return KWinMousePoller;
|
|
}());
|
|
var KWinTimerPool = (function () {
|
|
function KWinTimerPool() {
|
|
this.timers = [];
|
|
this.numTimers = 0;
|
|
}
|
|
KWinTimerPool.prototype.setTimeout = function (func, timeout) {
|
|
var _this = this;
|
|
if (this.timers.length === 0) {
|
|
this.numTimers++;
|
|
debugObj(function () { return ["setTimeout/newTimer", { numTimers: _this.numTimers }]; });
|
|
}
|
|
var timer = this.timers.pop() ||
|
|
Qt.createQmlObject("import QtQuick 2.0; Timer {}", scriptRoot);
|
|
var callback = function () {
|
|
try {
|
|
timer.triggered.disconnect(callback);
|
|
}
|
|
catch (e) {
|
|
}
|
|
try {
|
|
func();
|
|
}
|
|
catch (e) {
|
|
}
|
|
_this.timers.push(timer);
|
|
};
|
|
timer.interval = timeout;
|
|
timer.repeat = false;
|
|
timer.triggered.connect(callback);
|
|
timer.start();
|
|
};
|
|
KWinTimerPool.instance = new KWinTimerPool();
|
|
return KWinTimerPool;
|
|
}());
|
|
function KWinSetTimeout(func, timeout) {
|
|
KWinTimerPool.instance.setTimeout(func, timeout);
|
|
}
|
|
var KWinSurface = (function () {
|
|
function KWinSurface(output, activity, desktop, workspace) {
|
|
this.id = KWinSurface.generateId(output.name, activity, desktop.name);
|
|
this.ignore =
|
|
KWINCONFIG.ignoreActivity.indexOf(activity) >= 0 ||
|
|
KWINCONFIG.ignoreScreen.indexOf(output.name) >= 0;
|
|
this.workingArea = toRect(workspace.clientArea(0, output, desktop));
|
|
this.output = output;
|
|
this.activity = activity;
|
|
this.desktop = desktop;
|
|
}
|
|
KWinSurface.generateId = function (screenName, activity, desktopName) {
|
|
var path = screenName;
|
|
if (KWINCONFIG.layoutPerActivity)
|
|
path += "@" + activity;
|
|
if (KWINCONFIG.layoutPerDesktop)
|
|
path += "#" + desktopName;
|
|
return path;
|
|
};
|
|
KWinSurface.prototype.next = function () {
|
|
return null;
|
|
};
|
|
KWinSurface.prototype.toString = function () {
|
|
return ("KWinSurface(" +
|
|
[this.output.name, this.activity, this.desktop.name].join(", ") +
|
|
")");
|
|
};
|
|
return KWinSurface;
|
|
}());
|
|
var KWinWindow = (function () {
|
|
function KWinWindow(window, workspace) {
|
|
this.workspace = workspace;
|
|
this.window = window;
|
|
this.id = KWinWindow.generateID(window);
|
|
this.maximized = false;
|
|
this.noBorderManaged = false;
|
|
this.noBorderOriginal = window.noBorder;
|
|
}
|
|
KWinWindow.generateID = function (w) {
|
|
return w.internalId.toString();
|
|
};
|
|
Object.defineProperty(KWinWindow.prototype, "fullScreen", {
|
|
get: function () {
|
|
return this.window.fullScreen;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(KWinWindow.prototype, "geometry", {
|
|
get: function () {
|
|
return toRect(this.window.bufferGeometry);
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(KWinWindow.prototype, "shouldIgnore", {
|
|
get: function () {
|
|
var resourceClass = String(this.window.resourceClass);
|
|
var resourceName = String(this.window.resourceName);
|
|
var windowRole = String(this.window.windowRole);
|
|
return (this.window.specialWindow ||
|
|
resourceClass === "plasmashell" ||
|
|
KWINCONFIG.ignoreClass.indexOf(resourceClass) >= 0 ||
|
|
KWINCONFIG.ignoreClass.indexOf(resourceName) >= 0 ||
|
|
matchWords(this.window.caption, KWINCONFIG.ignoreTitle) >= 0 ||
|
|
KWINCONFIG.ignoreRole.indexOf(windowRole) >= 0);
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(KWinWindow.prototype, "shouldFloat", {
|
|
get: function () {
|
|
var resourceClass = String(this.window.resourceClass);
|
|
var resourceName = String(this.window.resourceName);
|
|
var moreOneDesktop = this.window.desktops.length !== 1;
|
|
return (moreOneDesktop ||
|
|
this.window.onAllDesktops ||
|
|
this.window.modal ||
|
|
this.window.transient ||
|
|
!this.window.resizeable ||
|
|
(KWINCONFIG.floatUtility &&
|
|
(this.window.dialog || this.window.splash || this.window.utility)) ||
|
|
KWINCONFIG.floatingClass.indexOf(resourceClass) >= 0 ||
|
|
KWINCONFIG.floatingClass.indexOf(resourceName) >= 0 ||
|
|
matchWords(this.window.caption, KWINCONFIG.floatingTitle) >= 0);
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(KWinWindow.prototype, "surface", {
|
|
get: function () {
|
|
var activity;
|
|
if (this.window.activities.length === 0)
|
|
activity = this.workspace.currentActivity;
|
|
else if (this.window.activities.indexOf(this.workspace.currentActivity) >= 0)
|
|
activity = this.workspace.currentActivity;
|
|
else
|
|
activity = this.window.activities[0];
|
|
var desktop = this.window.desktops[0];
|
|
return new KWinSurface(this.window.output, activity, desktop, this.workspace);
|
|
},
|
|
set: function (srf) {
|
|
var ksrf = srf;
|
|
if (this.window.desktops[0] !== ksrf.desktop)
|
|
this.window.desktops = [ksrf.desktop];
|
|
if (this.window.activities[0] !== ksrf.activity)
|
|
this.window.activities = [ksrf.activity];
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
KWinWindow.prototype.commit = function (geometry, noBorder, keepAbove) {
|
|
debugObj(function () { return ["KWinWindow#commit", { geometry: geometry, noBorder: noBorder, keepAbove: keepAbove }]; });
|
|
if (this.window.move || this.window.resize)
|
|
return;
|
|
if (noBorder !== undefined) {
|
|
if (!this.noBorderManaged && noBorder)
|
|
this.noBorderOriginal = this.window.noBorder;
|
|
else if (this.noBorderManaged && !this.window.noBorder)
|
|
this.noBorderOriginal = false;
|
|
if (noBorder)
|
|
this.window.noBorder = true;
|
|
else if (this.noBorderManaged)
|
|
this.window.noBorder = this.noBorderOriginal;
|
|
this.noBorderManaged = noBorder;
|
|
}
|
|
if (keepAbove !== undefined)
|
|
this.window.keepAbove = keepAbove;
|
|
if (geometry !== undefined) {
|
|
geometry = this.adjustGeometry(geometry);
|
|
if (KWINCONFIG.preventProtrusion) {
|
|
var area = toRect(this.workspace.clientArea(0, this.window.output, this.workspace.currentDesktop));
|
|
if (!area.includes(geometry)) {
|
|
var x = geometry.x + Math.min(area.maxX - geometry.maxX, 0);
|
|
var y = geometry.y + Math.min(area.maxY - geometry.maxY, 0);
|
|
geometry = new Rect(x, y, geometry.width, geometry.height);
|
|
geometry = this.adjustGeometry(geometry);
|
|
}
|
|
}
|
|
this.window.frameGeometry = toQRect(geometry);
|
|
this.window.rect;
|
|
}
|
|
};
|
|
KWinWindow.prototype.toString = function () {
|
|
return ("KWin(" +
|
|
this.window.internalId.toString() +
|
|
"." +
|
|
this.window.resourceClass +
|
|
")");
|
|
};
|
|
KWinWindow.prototype.visible = function (srf) {
|
|
var ksrf = srf;
|
|
return (!this.window.minimized &&
|
|
(this.window.onAllDesktops ||
|
|
this.window.desktops.indexOf(ksrf.desktop) !== -1) &&
|
|
(this.window.activities.length === 0 ||
|
|
this.window.activities.indexOf(ksrf.activity) !== -1) &&
|
|
this.window.output === ksrf.output);
|
|
};
|
|
KWinWindow.prototype.adjustGeometry = function (geometry) {
|
|
var width = geometry.width;
|
|
var height = geometry.height;
|
|
if (!this.window.resizeable) {
|
|
width = this.window.width;
|
|
height = this.window.height;
|
|
}
|
|
else {
|
|
width = clip(width, this.window.minSize.width, this.window.maxSize.width);
|
|
height = clip(height, this.window.minSize.height, this.window.maxSize.height);
|
|
}
|
|
return new Rect(geometry.x, geometry.y, width, height);
|
|
};
|
|
return KWinWindow;
|
|
}());
|
|
function debugWin(win) {
|
|
var w_props = [
|
|
{ name: "caption", opt: win.caption },
|
|
{ name: "output.name", opt: win.output.name },
|
|
{ name: "resourceName", opt: win.resourceName },
|
|
{ name: "resourceClass", opt: win.resourceClass },
|
|
{ name: "desktopWindow", opt: win.desktopWindow },
|
|
{ name: "windowRole", opt: win.windowRole },
|
|
{ name: "windowType", opt: win.windowType },
|
|
{ name: "pid", opt: win.pid },
|
|
{ name: "internalId", opt: win.internalId },
|
|
{ name: "stackingOrder", opt: win.stackingOrder },
|
|
{ name: "size", opt: win.size },
|
|
{ name: "width", opt: win.width },
|
|
{ name: "height", opt: win.height },
|
|
{ name: "dock", opt: win.dock },
|
|
{ name: "toolbar", opt: win.toolbar },
|
|
{ name: "menu", opt: win.menu },
|
|
{ name: "dialog", opt: win.dialog },
|
|
{ name: "splash", opt: win.splash },
|
|
{ name: "utility", opt: win.utility },
|
|
{ name: "dropdownMenu", opt: win.dropdownMenu },
|
|
{ name: "popupMenu", opt: win.popupMenu },
|
|
{ name: "tooltip", opt: win.tooltip },
|
|
{ name: "notification", opt: win.notification },
|
|
{ name: "criticalNotification", opt: win.criticalNotification },
|
|
{ name: "appletPopup", opt: win.appletPopup },
|
|
{ name: "onScreenDisplay", opt: win.onScreenDisplay },
|
|
{ name: "comboBox", opt: win.comboBox },
|
|
{ name: "managed", opt: win.managed },
|
|
{ name: "popupWindow", opt: win.popupWindow },
|
|
{ name: "outline", opt: win.outline },
|
|
{ name: "fullScreenable", opt: win.fullScreenable },
|
|
{ name: "closeable", opt: win.closeable },
|
|
{ name: "minimizable", opt: win.minimizable },
|
|
{ name: "specialWindow", opt: win.specialWindow },
|
|
{ name: "modal", opt: win.modal },
|
|
{ name: "resizeable", opt: win.resizeable },
|
|
{ name: "minimized", opt: win.minimized },
|
|
{ name: "tile", opt: win.tile },
|
|
{ name: "minSize", opt: win.minSize },
|
|
{ name: "maxSize", opt: win.maxSize },
|
|
{ name: "transient", opt: win.transient },
|
|
{ name: "transientFor", opt: win.transientFor },
|
|
{ name: "maximizable", opt: win.maximizable },
|
|
{ name: "moveable", opt: win.moveable },
|
|
{ name: "moveableAcrossScreens", opt: win.moveableAcrossScreens },
|
|
{ name: "hidden", opt: win.hidden },
|
|
{ name: "keepAbove", opt: win.keepAbove },
|
|
{ name: "keepBelow", opt: win.keepBelow },
|
|
{ name: "opacity", opt: win.opacity },
|
|
];
|
|
var s = "krohnkite:";
|
|
w_props.forEach(function (el) {
|
|
if (typeof el.opt !== "undefined" &&
|
|
(el.opt || el.opt === 0 || el.opt === "0")) {
|
|
s += "<";
|
|
s += el.name;
|
|
s += ": ";
|
|
s += el.opt;
|
|
s += "> ";
|
|
}
|
|
});
|
|
return s;
|
|
}
|
|
var TestDriver = (function () {
|
|
function TestDriver() {
|
|
this.currentScreen = 0;
|
|
this.currentWindow = 0;
|
|
this.numScreen = 1;
|
|
this.screenSize = new Rect(0, 0, 10000, 10000);
|
|
this.windows = [];
|
|
}
|
|
TestDriver.prototype.forEachScreen = function (func) {
|
|
for (var screen = 0; screen < this.numScreen; screen++)
|
|
func(new TestSurface(this, screen));
|
|
};
|
|
TestDriver.prototype.getCurrentContext = function () {
|
|
var window = this.getCurrentWindow();
|
|
if (window)
|
|
return window.surface;
|
|
return new TestSurface(this, 0);
|
|
};
|
|
TestDriver.prototype.getCurrentWindow = function () {
|
|
return this.windows.length !== 0 ? this.windows[this.currentWindow] : null;
|
|
};
|
|
TestDriver.prototype.getWorkingArea = function (srf) {
|
|
return this.screenSize;
|
|
};
|
|
TestDriver.prototype.setCurrentWindow = function (window) {
|
|
var idx = this.windows.indexOf(window);
|
|
if (idx !== -1)
|
|
this.currentWindow = idx;
|
|
};
|
|
TestDriver.prototype.setTimeout = function (func, timeout) {
|
|
setTimeout(func, timeout);
|
|
};
|
|
return TestDriver;
|
|
}());
|
|
var TestSurface = (function () {
|
|
function TestSurface(driver, screen) {
|
|
this.driver = driver;
|
|
this.screen = screen;
|
|
}
|
|
Object.defineProperty(TestSurface.prototype, "id", {
|
|
get: function () {
|
|
return String(this.screen);
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(TestSurface.prototype, "ignore", {
|
|
get: function () {
|
|
return false;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(TestSurface.prototype, "workingArea", {
|
|
get: function () {
|
|
return this.driver.screenSize;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
TestSurface.prototype.next = function () {
|
|
return new TestSurface(this.driver, this.screen + 1);
|
|
};
|
|
return TestSurface;
|
|
}());
|
|
var TestWindow = (function () {
|
|
function TestWindow(srf, geometry, ignore, float) {
|
|
this.id = String(TestWindow.windowCount);
|
|
TestWindow.windowCount += 1;
|
|
this.shouldFloat = float !== undefined ? float : false;
|
|
this.shouldIgnore = ignore !== undefined ? ignore : false;
|
|
this.surface = srf;
|
|
this.fullScreen = false;
|
|
this.geometry = geometry || new Rect(0, 0, 100, 100);
|
|
this.keepAbove = false;
|
|
this.maximized = false;
|
|
this.noBorder = false;
|
|
}
|
|
TestWindow.prototype.commit = function (geometry, noBorder, keepAbove) {
|
|
if (geometry)
|
|
this.geometry = geometry;
|
|
if (noBorder !== undefined)
|
|
this.noBorder = noBorder;
|
|
if (keepAbove !== undefined)
|
|
this.keepAbove = keepAbove;
|
|
};
|
|
TestWindow.prototype.focus = function () {
|
|
};
|
|
TestWindow.prototype.visible = function (srf) {
|
|
var tctx = srf;
|
|
return this.surface.screen === tctx.screen;
|
|
};
|
|
TestWindow.windowCount = 0;
|
|
return TestWindow;
|
|
}());
|
|
function setTestConfig(name, value) {
|
|
if (!CONFIG)
|
|
CONFIG = {};
|
|
CONFIG[name] = value;
|
|
}
|
|
var TilingController = (function () {
|
|
function TilingController(engine) {
|
|
this.engine = engine;
|
|
}
|
|
TilingController.prototype.onSurfaceUpdate = function (ctx, comment) {
|
|
debugObj(function () { return ["onSurfaceUpdate", { comment: comment }]; });
|
|
this.engine.arrange(ctx);
|
|
};
|
|
TilingController.prototype.onCurrentActivityChanged = function (ctx, activityId) {
|
|
debugObj(function () { return ["onCurrentActivityChanged", { activityId: activityId }]; });
|
|
this.engine.arrange(ctx);
|
|
};
|
|
TilingController.prototype.onCurrentSurfaceChanged = function (ctx) {
|
|
debugObj(function () { return ["onCurrentSurfaceChanged", { srf: ctx.currentSurface }]; });
|
|
this.engine.arrange(ctx);
|
|
};
|
|
TilingController.prototype.onWindowAdded = function (ctx, window) {
|
|
debugObj(function () { return ["onWindowAdded", { window: window }]; });
|
|
this.engine.manage(window);
|
|
if (window.tileable) {
|
|
var srf = ctx.currentSurface;
|
|
var tiles = this.engine.windows.getVisibleTiles(srf);
|
|
var layoutCapcity = this.engine.layouts.getCurrentLayout(srf).capacity;
|
|
if (layoutCapcity !== undefined && tiles.length > layoutCapcity) {
|
|
var nsrf = ctx.currentSurface.next();
|
|
if (nsrf) {
|
|
window.surface = nsrf;
|
|
ctx.currentSurface = nsrf;
|
|
}
|
|
}
|
|
}
|
|
this.engine.arrange(ctx);
|
|
};
|
|
TilingController.prototype.onWindowRemoved = function (ctx, window) {
|
|
debugObj(function () { return ["onWindowRemoved", { window: window }]; });
|
|
this.engine.unmanage(window);
|
|
this.engine.arrange(ctx);
|
|
};
|
|
TilingController.prototype.onWindowMoveStart = function (window) {
|
|
};
|
|
TilingController.prototype.onWindowMove = function (window) {
|
|
};
|
|
TilingController.prototype.onWindowMoveOver = function (ctx, window) {
|
|
debugObj(function () { return ["onWindowMoveOver", { window: window }]; });
|
|
if (window.state === WindowState.Tiled) {
|
|
var tiles = this.engine.windows.getVisibleTiles(ctx.currentSurface);
|
|
var cursorPos_1 = ctx.cursorPosition || window.actualGeometry.center;
|
|
var targets = tiles.filter(function (tile) {
|
|
return tile !== window && tile.actualGeometry.includesPoint(cursorPos_1);
|
|
});
|
|
if (targets.length === 1) {
|
|
this.engine.windows.swap(window, targets[0]);
|
|
this.engine.arrange(ctx);
|
|
return;
|
|
}
|
|
}
|
|
if (!CONFIG.keepTilingOnDrag && window.state === WindowState.Tiled) {
|
|
var diff = window.actualGeometry.subtract(window.geometry);
|
|
var distance = Math.sqrt(Math.pow(diff.x, 2) + Math.pow(diff.y, 2));
|
|
if (distance > 30) {
|
|
window.floatGeometry = window.actualGeometry;
|
|
window.state = WindowState.Floating;
|
|
this.engine.arrange(ctx);
|
|
return;
|
|
}
|
|
}
|
|
window.commit();
|
|
};
|
|
TilingController.prototype.onWindowResizeStart = function (window) {
|
|
};
|
|
TilingController.prototype.onWindowResize = function (ctx, window) {
|
|
debugObj(function () { return ["onWindowResize", { window: window }]; });
|
|
if (CONFIG.adjustLayout && CONFIG.adjustLayoutLive) {
|
|
if (window.state === WindowState.Tiled) {
|
|
this.engine.adjustLayout(window);
|
|
this.engine.arrange(ctx);
|
|
}
|
|
}
|
|
};
|
|
TilingController.prototype.onWindowResizeOver = function (ctx, window) {
|
|
debugObj(function () { return ["onWindowResizeOver", { window: window }]; });
|
|
if (CONFIG.adjustLayout && window.tiled) {
|
|
this.engine.adjustLayout(window);
|
|
this.engine.arrange(ctx);
|
|
}
|
|
else if (!CONFIG.adjustLayout)
|
|
this.engine.enforceSize(ctx, window);
|
|
};
|
|
TilingController.prototype.onWindowMaximizeChanged = function (ctx, window, maximized) {
|
|
this.engine.arrange(ctx);
|
|
};
|
|
TilingController.prototype.onWindowGeometryChanged = function (ctx, window) {
|
|
debugObj(function () { return ["onWindowGeometryChanged", { window: window }]; });
|
|
this.engine.enforceSize(ctx, window);
|
|
};
|
|
TilingController.prototype.onWindowChanged = function (ctx, window, comment) {
|
|
if (window) {
|
|
debugObj(function () { return ["onWindowChanged", { window: window, comment: comment }]; });
|
|
if (comment === "unminimized")
|
|
ctx.currentWindow = window;
|
|
this.engine.arrange(ctx);
|
|
}
|
|
};
|
|
TilingController.prototype.onWindowFocused = function (ctx, window) {
|
|
window.timestamp = new Date().getTime();
|
|
};
|
|
TilingController.prototype.onShortcut = function (ctx, input, data) {
|
|
if (CONFIG.directionalKeyMode === "dwm") {
|
|
switch (input) {
|
|
case Shortcut.FocusUp:
|
|
input = Shortcut.FocusNext;
|
|
break;
|
|
case Shortcut.FocusDown:
|
|
input = Shortcut.FocusPrev;
|
|
break;
|
|
case Shortcut.FocusLeft:
|
|
input = Shortcut.DWMLeft;
|
|
break;
|
|
case Shortcut.FocusRight:
|
|
input = Shortcut.DWMRight;
|
|
break;
|
|
}
|
|
}
|
|
else if (CONFIG.directionalKeyMode === "focus") {
|
|
switch (input) {
|
|
case Shortcut.ShiftUp:
|
|
input = Shortcut.SwapUp;
|
|
break;
|
|
case Shortcut.ShiftDown:
|
|
input = Shortcut.SwapDown;
|
|
break;
|
|
case Shortcut.ShiftLeft:
|
|
input = Shortcut.SwapLeft;
|
|
break;
|
|
case Shortcut.ShiftRight:
|
|
input = Shortcut.SwapRight;
|
|
break;
|
|
}
|
|
}
|
|
if (this.engine.handleLayoutShortcut(ctx, input, data)) {
|
|
this.engine.arrange(ctx);
|
|
return;
|
|
}
|
|
var window = ctx.currentWindow;
|
|
switch (input) {
|
|
case Shortcut.FocusNext:
|
|
this.engine.focusOrder(ctx, -1);
|
|
break;
|
|
case Shortcut.FocusPrev:
|
|
this.engine.focusOrder(ctx, +1);
|
|
break;
|
|
case Shortcut.FocusUp:
|
|
this.engine.focusDir(ctx, "up");
|
|
break;
|
|
case Shortcut.FocusDown:
|
|
this.engine.focusDir(ctx, "down");
|
|
break;
|
|
case Shortcut.DWMLeft:
|
|
case Shortcut.FocusLeft:
|
|
this.engine.focusDir(ctx, "left");
|
|
break;
|
|
case Shortcut.DWMRight:
|
|
case Shortcut.FocusRight:
|
|
this.engine.focusDir(ctx, "right");
|
|
break;
|
|
case Shortcut.GrowWidth:
|
|
if (window)
|
|
this.engine.resizeWindow(window, "east", 1);
|
|
break;
|
|
case Shortcut.ShrinkWidth:
|
|
if (window)
|
|
this.engine.resizeWindow(window, "east", -1);
|
|
break;
|
|
case Shortcut.GrowHeight:
|
|
if (window)
|
|
this.engine.resizeWindow(window, "south", 1);
|
|
break;
|
|
case Shortcut.ShrinkHeight:
|
|
if (window)
|
|
this.engine.resizeWindow(window, "south", -1);
|
|
break;
|
|
case Shortcut.ShiftUp:
|
|
if (window)
|
|
this.engine.swapOrder(window, -1);
|
|
break;
|
|
case Shortcut.ShiftDown:
|
|
if (window)
|
|
this.engine.swapOrder(window, +1);
|
|
break;
|
|
case Shortcut.SwapUp:
|
|
this.engine.swapDirOrMoveFloat(ctx, "up");
|
|
break;
|
|
case Shortcut.SwapDown:
|
|
this.engine.swapDirOrMoveFloat(ctx, "down");
|
|
break;
|
|
case Shortcut.SwapLeft:
|
|
this.engine.swapDirOrMoveFloat(ctx, "left");
|
|
break;
|
|
case Shortcut.SwapRight:
|
|
this.engine.swapDirOrMoveFloat(ctx, "right");
|
|
break;
|
|
case Shortcut.SetMaster:
|
|
if (window)
|
|
this.engine.setMaster(window);
|
|
break;
|
|
case Shortcut.ToggleFloat:
|
|
if (window)
|
|
this.engine.toggleFloat(window);
|
|
break;
|
|
case Shortcut.ToggleFloatAll:
|
|
this.engine.floatAll(ctx, ctx.currentSurface);
|
|
break;
|
|
case Shortcut.NextLayout:
|
|
this.engine.cycleLayout(ctx, 1);
|
|
break;
|
|
case Shortcut.PreviousLayout:
|
|
this.engine.cycleLayout(ctx, -1);
|
|
break;
|
|
case Shortcut.SetLayout:
|
|
if (typeof data === "string")
|
|
this.engine.setLayout(ctx, data);
|
|
break;
|
|
}
|
|
this.engine.arrange(ctx);
|
|
};
|
|
return TilingController;
|
|
}());
|
|
var TilingEngine = (function () {
|
|
function TilingEngine() {
|
|
this.layouts = new LayoutStore();
|
|
this.windows = new WindowStore();
|
|
}
|
|
TilingEngine.prototype.adjustLayout = function (basis) {
|
|
var srf = basis.surface;
|
|
var layout = this.layouts.getCurrentLayout(srf);
|
|
if (layout.adjust) {
|
|
var area = srf.workingArea.gap(CONFIG.screenGapLeft, CONFIG.screenGapRight, CONFIG.screenGapTop, CONFIG.screenGapBottom);
|
|
var tiles = this.windows.getVisibleTiles(srf);
|
|
layout.adjust(area, tiles, basis, basis.geometryDelta);
|
|
}
|
|
};
|
|
TilingEngine.prototype.resizeFloat = function (window, dir, step) {
|
|
var srf = window.surface;
|
|
var hStepSize = srf.workingArea.width * 0.05;
|
|
var vStepSize = srf.workingArea.height * 0.05;
|
|
var hStep, vStep;
|
|
switch (dir) {
|
|
case "east":
|
|
(hStep = step), (vStep = 0);
|
|
break;
|
|
case "west":
|
|
(hStep = -step), (vStep = 0);
|
|
break;
|
|
case "south":
|
|
(hStep = 0), (vStep = step);
|
|
break;
|
|
case "north":
|
|
(hStep = 0), (vStep = -step);
|
|
break;
|
|
}
|
|
var geometry = window.actualGeometry;
|
|
var width = geometry.width + hStepSize * hStep;
|
|
var height = geometry.height + vStepSize * vStep;
|
|
window.forceSetGeometry(new Rect(geometry.x, geometry.y, width, height));
|
|
};
|
|
TilingEngine.prototype.resizeTile = function (basis, dir, step) {
|
|
var srf = basis.surface;
|
|
if (dir === "east") {
|
|
var maxX_1 = basis.geometry.maxX;
|
|
var easternNeighbor = this.windows
|
|
.getVisibleTiles(srf)
|
|
.filter(function (tile) { return tile.geometry.x >= maxX_1; });
|
|
if (easternNeighbor.length === 0) {
|
|
dir = "west";
|
|
step *= -1;
|
|
}
|
|
}
|
|
else if (dir === "south") {
|
|
var maxY_1 = basis.geometry.maxY;
|
|
var southernNeighbor = this.windows
|
|
.getVisibleTiles(srf)
|
|
.filter(function (tile) { return tile.geometry.y >= maxY_1; });
|
|
if (southernNeighbor.length === 0) {
|
|
dir = "north";
|
|
step *= -1;
|
|
}
|
|
}
|
|
var hStepSize = srf.workingArea.width * 0.03;
|
|
var vStepSize = srf.workingArea.height * 0.03;
|
|
var delta;
|
|
switch (dir) {
|
|
case "east":
|
|
delta = new RectDelta(hStepSize * step, 0, 0, 0);
|
|
break;
|
|
case "west":
|
|
delta = new RectDelta(0, hStepSize * step, 0, 0);
|
|
break;
|
|
case "south":
|
|
delta = new RectDelta(0, 0, vStepSize * step, 0);
|
|
break;
|
|
case "north":
|
|
default:
|
|
delta = new RectDelta(0, 0, 0, vStepSize * step);
|
|
break;
|
|
}
|
|
var layout = this.layouts.getCurrentLayout(srf);
|
|
if (layout.adjust) {
|
|
var area = srf.workingArea.gap(CONFIG.screenGapLeft, CONFIG.screenGapRight, CONFIG.screenGapTop, CONFIG.screenGapBottom);
|
|
layout.adjust(area, this.windows.getVisibleTileables(srf), basis, delta);
|
|
}
|
|
};
|
|
TilingEngine.prototype.resizeWindow = function (window, dir, step) {
|
|
var state = window.state;
|
|
if (WindowClass.isFloatingState(state))
|
|
this.resizeFloat(window, dir, step);
|
|
else if (WindowClass.isTiledState(state))
|
|
this.resizeTile(window, dir, step);
|
|
};
|
|
TilingEngine.prototype.arrange = function (ctx) {
|
|
var _this = this;
|
|
debug(function () { return "arrange"; });
|
|
ctx.screens.forEach(function (srf) {
|
|
_this.arrangeScreen(ctx, srf);
|
|
});
|
|
};
|
|
TilingEngine.prototype.arrangeScreen = function (ctx, srf) {
|
|
var layout = this.layouts.getCurrentLayout(srf);
|
|
var workingArea = srf.workingArea;
|
|
var tilingArea;
|
|
if (CONFIG.monocleMaximize && layout instanceof MonocleLayout)
|
|
tilingArea = workingArea;
|
|
else
|
|
tilingArea = workingArea.gap(CONFIG.screenGapLeft, CONFIG.screenGapRight, CONFIG.screenGapTop, CONFIG.screenGapBottom);
|
|
var visibles = this.windows.getVisibleWindows(srf);
|
|
debugObj(function () { return [
|
|
"arrangeScreen",
|
|
{
|
|
layout: layout,
|
|
srf: srf,
|
|
visibles: visibles.length,
|
|
},
|
|
]; });
|
|
visibles.forEach(function (window) {
|
|
if (window.state === WindowState.Undecided)
|
|
window.state = window.shouldFloat
|
|
? WindowState.Floating
|
|
: WindowState.Tiled;
|
|
});
|
|
var tileables = this.windows.getVisibleTileables(srf);
|
|
if (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)) {
|
|
var maxWidth_1 = Math.floor(workingArea.height * CONFIG.limitTileWidthRatio);
|
|
tileables
|
|
.filter(function (tile) { return tile.tiled && tile.geometry.width > maxWidth_1; })
|
|
.forEach(function (tile) {
|
|
var g = tile.geometry;
|
|
tile.geometry = new Rect(g.x + Math.floor((g.width - maxWidth_1) / 2), g.y, maxWidth_1, g.height);
|
|
});
|
|
}
|
|
visibles.forEach(function (window) { return window.commit(); });
|
|
debugObj(function () { return ["arrangeScreen/finished", { srf: srf }]; });
|
|
};
|
|
TilingEngine.prototype.enforceSize = function (ctx, window) {
|
|
if (window.tiled && !window.actualGeometry.equals(window.geometry))
|
|
ctx.setTimeout(function () {
|
|
if (window.tiled)
|
|
window.commit();
|
|
}, 10);
|
|
};
|
|
TilingEngine.prototype.manage = function (window) {
|
|
if (!window.shouldIgnore) {
|
|
window.state = WindowState.Undecided;
|
|
if (CONFIG.newWindowPosition === 1)
|
|
this.windows.unshift(window);
|
|
else if (CONFIG.newWindowPosition === 2) {
|
|
this.windows.beside_first(window);
|
|
}
|
|
else
|
|
this.windows.push(window);
|
|
}
|
|
};
|
|
TilingEngine.prototype.unmanage = function (window) {
|
|
this.windows.remove(window);
|
|
};
|
|
TilingEngine.prototype.focusOrder = function (ctx, step) {
|
|
var window = ctx.currentWindow;
|
|
if (window === null) {
|
|
var tiles = this.windows.getVisibleTiles(ctx.currentSurface);
|
|
if (tiles.length > 1)
|
|
ctx.currentWindow = tiles[0];
|
|
return;
|
|
}
|
|
var visibles = this.windows.getVisibleWindows(ctx.currentSurface);
|
|
if (visibles.length === 0)
|
|
return;
|
|
var idx = visibles.indexOf(window);
|
|
if (!window || idx < 0) {
|
|
ctx.currentWindow = visibles[0];
|
|
return;
|
|
}
|
|
var num = visibles.length;
|
|
var newIndex = (idx + (step % num) + num) % num;
|
|
ctx.currentWindow = visibles[newIndex];
|
|
};
|
|
TilingEngine.prototype.focusDir = function (ctx, dir) {
|
|
var window = ctx.currentWindow;
|
|
if (window === null) {
|
|
var tiles = this.windows.getVisibleTiles(ctx.currentSurface);
|
|
if (tiles.length > 1)
|
|
ctx.currentWindow = tiles[0];
|
|
return;
|
|
}
|
|
var neighbor = this.getNeighborByDirection(ctx, window, dir);
|
|
if (neighbor)
|
|
ctx.currentWindow = neighbor;
|
|
};
|
|
TilingEngine.prototype.swapOrder = function (window, step) {
|
|
var srf = window.surface;
|
|
var visibles = this.windows.getVisibleWindows(srf);
|
|
if (visibles.length < 2)
|
|
return;
|
|
var vsrc = visibles.indexOf(window);
|
|
var vdst = wrapIndex(vsrc + step, visibles.length);
|
|
var dstWin = visibles[vdst];
|
|
this.windows.move(window, dstWin);
|
|
};
|
|
TilingEngine.prototype.swapDirection = function (ctx, dir) {
|
|
var window = ctx.currentWindow;
|
|
if (window === null) {
|
|
var tiles = this.windows.getVisibleTiles(ctx.currentSurface);
|
|
if (tiles.length > 1)
|
|
ctx.currentWindow = tiles[0];
|
|
return;
|
|
}
|
|
var neighbor = this.getNeighborByDirection(ctx, window, dir);
|
|
if (neighbor)
|
|
this.windows.swap(window, neighbor);
|
|
};
|
|
TilingEngine.prototype.moveFloat = function (window, dir) {
|
|
var srf = window.surface;
|
|
var hStepSize = srf.workingArea.width * 0.05;
|
|
var vStepSize = srf.workingArea.height * 0.05;
|
|
var hStep, vStep;
|
|
switch (dir) {
|
|
case "up":
|
|
(hStep = 0), (vStep = -1);
|
|
break;
|
|
case "down":
|
|
(hStep = 0), (vStep = 1);
|
|
break;
|
|
case "left":
|
|
(hStep = -1), (vStep = 0);
|
|
break;
|
|
case "right":
|
|
(hStep = 1), (vStep = 0);
|
|
break;
|
|
}
|
|
var geometry = window.actualGeometry;
|
|
var x = geometry.x + hStepSize * hStep;
|
|
var y = geometry.y + vStepSize * vStep;
|
|
window.forceSetGeometry(new Rect(x, y, geometry.width, geometry.height));
|
|
};
|
|
TilingEngine.prototype.swapDirOrMoveFloat = function (ctx, dir) {
|
|
var window = ctx.currentWindow;
|
|
if (!window)
|
|
return;
|
|
var state = window.state;
|
|
if (WindowClass.isFloatingState(state))
|
|
this.moveFloat(window, dir);
|
|
else if (WindowClass.isTiledState(state))
|
|
this.swapDirection(ctx, dir);
|
|
};
|
|
TilingEngine.prototype.toggleFloat = function (window) {
|
|
window.state = !window.tileable ? WindowState.Tiled : WindowState.Floating;
|
|
};
|
|
TilingEngine.prototype.floatAll = function (ctx, srf) {
|
|
var windows = this.windows.getVisibleWindows(srf);
|
|
var numFloats = windows.reduce(function (count, window) {
|
|
return window.state === WindowState.Floating ? count + 1 : count;
|
|
}, 0);
|
|
if (numFloats < windows.length / 2) {
|
|
windows.forEach(function (window) {
|
|
window.floatGeometry = window.actualGeometry.gap(4, 4, 4, 4);
|
|
window.state = WindowState.Floating;
|
|
});
|
|
ctx.showNotification("Float All");
|
|
}
|
|
else {
|
|
windows.forEach(function (window) {
|
|
window.state = WindowState.Tiled;
|
|
});
|
|
ctx.showNotification("Tile All");
|
|
}
|
|
};
|
|
TilingEngine.prototype.setMaster = function (window) {
|
|
this.windows.setMaster(window);
|
|
};
|
|
TilingEngine.prototype.cycleLayout = function (ctx, step) {
|
|
var layout = this.layouts.cycleLayout(ctx.currentSurface, step);
|
|
if (layout)
|
|
ctx.showNotification(layout.description);
|
|
};
|
|
TilingEngine.prototype.setLayout = function (ctx, layoutClassID) {
|
|
var layout = this.layouts.setLayout(ctx.currentSurface, layoutClassID);
|
|
if (layout)
|
|
ctx.showNotification(layout.description);
|
|
};
|
|
TilingEngine.prototype.handleLayoutShortcut = function (ctx, input, data) {
|
|
var layout = this.layouts.getCurrentLayout(ctx.currentSurface);
|
|
if (layout.handleShortcut)
|
|
return layout.handleShortcut(new EngineContext(ctx, this), input, data);
|
|
return false;
|
|
};
|
|
TilingEngine.prototype.getNeighborByDirection = function (ctx, basis, dir) {
|
|
var vertical;
|
|
var sign;
|
|
switch (dir) {
|
|
case "up":
|
|
vertical = true;
|
|
sign = -1;
|
|
break;
|
|
case "down":
|
|
vertical = true;
|
|
sign = 1;
|
|
break;
|
|
case "left":
|
|
vertical = false;
|
|
sign = -1;
|
|
break;
|
|
case "right":
|
|
vertical = false;
|
|
sign = 1;
|
|
break;
|
|
default:
|
|
return null;
|
|
}
|
|
var candidates = this.windows
|
|
.getVisibleTiles(ctx.currentSurface)
|
|
.filter(vertical
|
|
? function (tile) { return tile.geometry.y * sign > basis.geometry.y * sign; }
|
|
: function (tile) { return tile.geometry.x * sign > basis.geometry.x * sign; })
|
|
.filter(vertical
|
|
? function (tile) {
|
|
return overlap(basis.geometry.x, basis.geometry.maxX, tile.geometry.x, tile.geometry.maxX);
|
|
}
|
|
: function (tile) {
|
|
return overlap(basis.geometry.y, basis.geometry.maxY, tile.geometry.y, tile.geometry.maxY);
|
|
});
|
|
if (candidates.length === 0)
|
|
return null;
|
|
var min = sign *
|
|
candidates.reduce(vertical
|
|
? function (prevMin, tile) { return Math.min(tile.geometry.y * sign, prevMin); }
|
|
: function (prevMin, tile) {
|
|
return Math.min(tile.geometry.x * sign, prevMin);
|
|
}, Infinity);
|
|
var closest = candidates.filter(vertical
|
|
? function (tile) { return tile.geometry.y === min; }
|
|
: function (tile) { return tile.geometry.x === min; });
|
|
return closest.sort(function (a, b) { return b.timestamp - a.timestamp; })[0];
|
|
};
|
|
return TilingEngine;
|
|
}());
|
|
var EngineContext = (function () {
|
|
function EngineContext(drvctx, engine) {
|
|
this.drvctx = drvctx;
|
|
this.engine = engine;
|
|
}
|
|
Object.defineProperty(EngineContext.prototype, "backend", {
|
|
get: function () {
|
|
return this.drvctx.backend;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(EngineContext.prototype, "currentWindow", {
|
|
get: function () {
|
|
return this.drvctx.currentWindow;
|
|
},
|
|
set: function (window) {
|
|
this.drvctx.currentWindow = window;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
EngineContext.prototype.setTimeout = function (func, timeout) {
|
|
this.drvctx.setTimeout(func, timeout);
|
|
};
|
|
EngineContext.prototype.cycleFocus = function (step) {
|
|
this.engine.focusOrder(this.drvctx, step);
|
|
};
|
|
EngineContext.prototype.moveWindow = function (window, target, after) {
|
|
this.engine.windows.move(window, target, after);
|
|
};
|
|
EngineContext.prototype.showNotification = function (text) {
|
|
this.drvctx.showNotification(text);
|
|
};
|
|
return EngineContext;
|
|
}());
|
|
var LayoutStoreEntry = (function () {
|
|
function LayoutStoreEntry(output_name, desktop_name) {
|
|
var _this = this;
|
|
var layouts_str = CONFIG.layoutOrder.map(function (layout, i) { return i + "." + layout + ", "; });
|
|
print("Krohnkite: Screen(output):".concat(output_name, ", Desktop(name):").concat(desktop_name, ", layouts: ").concat(layouts_str));
|
|
this.currentIndex = 0;
|
|
this.currentID = CONFIG.layoutOrder[0];
|
|
CONFIG.screenDefaultLayout.some(function (entry) {
|
|
var cfg = entry.split(":");
|
|
var cfg_output = cfg[0];
|
|
var cfg_desktop = cfg.length == 2 ? undefined : cfg[1];
|
|
var cfg_screen_id_str = cfg.length == 2 ? cfg[1] : cfg[2];
|
|
var cfg_screen_id = parseInt(cfg_screen_id_str);
|
|
if ((output_name === cfg_output || cfg_output === '') &&
|
|
(desktop_name === cfg_desktop || cfg_desktop === undefined) &&
|
|
cfg_screen_id >= 0 &&
|
|
cfg_screen_id < CONFIG.layoutOrder.length) {
|
|
_this.currentIndex = cfg_screen_id;
|
|
_this.currentID = CONFIG.layoutOrder[_this.currentIndex];
|
|
return true;
|
|
}
|
|
});
|
|
this.layouts = {};
|
|
this.previousID = this.currentID;
|
|
this.loadLayout(this.currentID);
|
|
}
|
|
Object.defineProperty(LayoutStoreEntry.prototype, "currentLayout", {
|
|
get: function () {
|
|
return this.loadLayout(this.currentID);
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
LayoutStoreEntry.prototype.cycleLayout = function (step) {
|
|
this.previousID = this.currentID;
|
|
this.currentIndex =
|
|
this.currentIndex !== null
|
|
? wrapIndex(this.currentIndex + step, CONFIG.layoutOrder.length)
|
|
: 0;
|
|
this.currentID = CONFIG.layoutOrder[this.currentIndex];
|
|
return this.loadLayout(this.currentID);
|
|
};
|
|
LayoutStoreEntry.prototype.setLayout = function (targetID) {
|
|
var targetLayout = this.loadLayout(targetID);
|
|
if (targetLayout instanceof MonocleLayout &&
|
|
this.currentLayout instanceof MonocleLayout) {
|
|
this.currentID = this.previousID;
|
|
this.previousID = targetID;
|
|
}
|
|
else if (this.currentID !== targetID) {
|
|
this.previousID = this.currentID;
|
|
this.currentID = targetID;
|
|
}
|
|
this.updateCurrentIndex();
|
|
return targetLayout;
|
|
};
|
|
LayoutStoreEntry.prototype.updateCurrentIndex = function () {
|
|
var idx = CONFIG.layoutOrder.indexOf(this.currentID);
|
|
this.currentIndex = idx === -1 ? null : idx;
|
|
};
|
|
LayoutStoreEntry.prototype.loadLayout = function (ID) {
|
|
var layout = this.layouts[ID];
|
|
if (!layout)
|
|
layout = this.layouts[ID] = CONFIG.layoutFactories[ID]();
|
|
return layout;
|
|
};
|
|
return LayoutStoreEntry;
|
|
}());
|
|
var LayoutStore = (function () {
|
|
function LayoutStore() {
|
|
this.store = {};
|
|
}
|
|
LayoutStore.prototype.getCurrentLayout = function (srf) {
|
|
return srf.ignore
|
|
? FloatingLayout.instance
|
|
: this.getEntry(srf.id).currentLayout;
|
|
};
|
|
LayoutStore.prototype.cycleLayout = function (srf, step) {
|
|
if (srf.ignore)
|
|
return null;
|
|
return this.getEntry(srf.id).cycleLayout(step);
|
|
};
|
|
LayoutStore.prototype.setLayout = function (srf, layoutClassID) {
|
|
if (srf.ignore)
|
|
return null;
|
|
return this.getEntry(srf.id).setLayout(layoutClassID);
|
|
};
|
|
LayoutStore.prototype.getEntry = function (key) {
|
|
if (!this.store[key]) {
|
|
var i1 = key.indexOf("@");
|
|
var i2 = key.indexOf("#");
|
|
var key_without_activity = key.slice(0, i1 + 1) + key.slice(i2);
|
|
if (i1 > 0 && i2 > 0 && i2 - i1 > 1 && this.store[key_without_activity]) {
|
|
this.store[key] = this.store[key_without_activity];
|
|
delete this.store[key_without_activity];
|
|
}
|
|
else {
|
|
var output_name = key.slice(0, key.indexOf("@"));
|
|
var desktop_name = i2 !== -1 ? key.slice(i2 + 1) : undefined;
|
|
this.store[key] = new LayoutStoreEntry(output_name, desktop_name);
|
|
}
|
|
}
|
|
return this.store[key];
|
|
};
|
|
return LayoutStore;
|
|
}());
|
|
var WindowState;
|
|
(function (WindowState) {
|
|
WindowState[WindowState["Unmanaged"] = 0] = "Unmanaged";
|
|
WindowState[WindowState["NativeFullscreen"] = 1] = "NativeFullscreen";
|
|
WindowState[WindowState["NativeMaximized"] = 2] = "NativeMaximized";
|
|
WindowState[WindowState["Floating"] = 3] = "Floating";
|
|
WindowState[WindowState["Maximized"] = 4] = "Maximized";
|
|
WindowState[WindowState["Tiled"] = 5] = "Tiled";
|
|
WindowState[WindowState["TiledAfloat"] = 6] = "TiledAfloat";
|
|
WindowState[WindowState["Undecided"] = 7] = "Undecided";
|
|
})(WindowState || (WindowState = {}));
|
|
var WindowClass = (function () {
|
|
function WindowClass(window) {
|
|
this.id = window.id;
|
|
this.window = window;
|
|
this.floatGeometry = window.geometry;
|
|
this.geometry = window.geometry;
|
|
this.timestamp = 0;
|
|
this.internalState = WindowState.Unmanaged;
|
|
this.shouldCommitFloat = this.shouldFloat;
|
|
this.weightMap = {};
|
|
}
|
|
WindowClass.isTileableState = function (state) {
|
|
return (state === WindowState.Tiled ||
|
|
state === WindowState.Maximized ||
|
|
state === WindowState.TiledAfloat);
|
|
};
|
|
WindowClass.isTiledState = function (state) {
|
|
return state === WindowState.Tiled || state === WindowState.Maximized;
|
|
};
|
|
WindowClass.isFloatingState = function (state) {
|
|
return state === WindowState.Floating || state === WindowState.TiledAfloat;
|
|
};
|
|
Object.defineProperty(WindowClass.prototype, "actualGeometry", {
|
|
get: function () {
|
|
return this.window.geometry;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(WindowClass.prototype, "shouldFloat", {
|
|
get: function () {
|
|
return this.window.shouldFloat;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(WindowClass.prototype, "shouldIgnore", {
|
|
get: function () {
|
|
return this.window.shouldIgnore;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(WindowClass.prototype, "tileable", {
|
|
get: function () {
|
|
return WindowClass.isTileableState(this.state);
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(WindowClass.prototype, "tiled", {
|
|
get: function () {
|
|
return WindowClass.isTiledState(this.state);
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(WindowClass.prototype, "floating", {
|
|
get: function () {
|
|
return WindowClass.isFloatingState(this.state);
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(WindowClass.prototype, "geometryDelta", {
|
|
get: function () {
|
|
return RectDelta.fromRects(this.geometry, this.actualGeometry);
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(WindowClass.prototype, "state", {
|
|
get: function () {
|
|
if (this.window.fullScreen)
|
|
return WindowState.NativeFullscreen;
|
|
if (this.window.maximized)
|
|
return WindowState.NativeMaximized;
|
|
return this.internalState;
|
|
},
|
|
set: function (value) {
|
|
var state = this.state;
|
|
if (state === value)
|
|
return;
|
|
if ((state === WindowState.Unmanaged || WindowClass.isTileableState(state)) &&
|
|
WindowClass.isFloatingState(value))
|
|
this.shouldCommitFloat = true;
|
|
else if (WindowClass.isFloatingState(state) &&
|
|
WindowClass.isTileableState(value))
|
|
this.floatGeometry = this.actualGeometry;
|
|
this.internalState = value;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(WindowClass.prototype, "surface", {
|
|
get: function () {
|
|
return this.window.surface;
|
|
},
|
|
set: function (srf) {
|
|
this.window.surface = srf;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(WindowClass.prototype, "weight", {
|
|
get: function () {
|
|
var srfID = this.window.surface.id;
|
|
var weight = this.weightMap[srfID];
|
|
if (weight === undefined) {
|
|
this.weightMap[srfID] = 1.0;
|
|
return 1.0;
|
|
}
|
|
return weight;
|
|
},
|
|
set: function (value) {
|
|
var srfID = this.window.surface.id;
|
|
this.weightMap[srfID] = value;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
WindowClass.prototype.commit = function () {
|
|
var state = this.state;
|
|
debugObj(function () { return ["Window#commit", { state: WindowState[state] }]; });
|
|
switch (state) {
|
|
case WindowState.NativeMaximized:
|
|
this.window.commit(undefined, undefined, false);
|
|
break;
|
|
case WindowState.NativeFullscreen:
|
|
this.window.commit(undefined, undefined, undefined);
|
|
break;
|
|
case WindowState.Floating:
|
|
if (!this.shouldCommitFloat)
|
|
break;
|
|
this.window.commit(this.floatGeometry, false, CONFIG.keepFloatAbove);
|
|
this.shouldCommitFloat = false;
|
|
break;
|
|
case WindowState.Maximized:
|
|
this.window.commit(this.geometry, true, false);
|
|
break;
|
|
case WindowState.Tiled:
|
|
this.window.commit(this.geometry, CONFIG.noTileBorder, false);
|
|
break;
|
|
case WindowState.TiledAfloat:
|
|
if (!this.shouldCommitFloat)
|
|
break;
|
|
this.window.commit(this.floatGeometry, false, CONFIG.keepFloatAbove);
|
|
this.shouldCommitFloat = false;
|
|
break;
|
|
}
|
|
};
|
|
WindowClass.prototype.forceSetGeometry = function (geometry) {
|
|
this.window.commit(geometry);
|
|
};
|
|
WindowClass.prototype.visible = function (srf) {
|
|
return this.window.visible(srf);
|
|
};
|
|
WindowClass.prototype.toString = function () {
|
|
return "Window(" + String(this.window) + ")";
|
|
};
|
|
return WindowClass;
|
|
}());
|
|
var WindowStore = (function () {
|
|
function WindowStore(windows) {
|
|
this.list = windows || [];
|
|
}
|
|
WindowStore.prototype.move = function (srcWin, destWin, after) {
|
|
var srcIdx = this.list.indexOf(srcWin);
|
|
var destIdx = this.list.indexOf(destWin);
|
|
if (srcIdx === -1 || destIdx === -1)
|
|
return;
|
|
this.list.splice(srcIdx, 1);
|
|
this.list.splice(after ? destIdx + 1 : destIdx, 0, srcWin);
|
|
};
|
|
WindowStore.prototype.setMaster = function (window) {
|
|
var idx = this.list.indexOf(window);
|
|
if (idx === -1)
|
|
return;
|
|
this.list.splice(idx, 1);
|
|
this.list.splice(0, 0, window);
|
|
};
|
|
WindowStore.prototype.swap = function (alpha, beta) {
|
|
var alphaIndex = this.list.indexOf(alpha);
|
|
var betaIndex = this.list.indexOf(beta);
|
|
if (alphaIndex < 0 || betaIndex < 0)
|
|
return;
|
|
this.list[alphaIndex] = beta;
|
|
this.list[betaIndex] = alpha;
|
|
};
|
|
Object.defineProperty(WindowStore.prototype, "length", {
|
|
get: function () {
|
|
return this.list.length;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
WindowStore.prototype.at = function (idx) {
|
|
return this.list[idx];
|
|
};
|
|
WindowStore.prototype.indexOf = function (window) {
|
|
return this.list.indexOf(window);
|
|
};
|
|
WindowStore.prototype.push = function (window) {
|
|
this.list.push(window);
|
|
};
|
|
WindowStore.prototype.beside_first = function (window) {
|
|
this.list.splice(1, 0, window);
|
|
};
|
|
WindowStore.prototype.remove = function (window) {
|
|
var idx = this.list.indexOf(window);
|
|
if (idx >= 0)
|
|
this.list.splice(idx, 1);
|
|
};
|
|
WindowStore.prototype.unshift = function (window) {
|
|
this.list.unshift(window);
|
|
};
|
|
WindowStore.prototype.getVisibleWindows = function (srf) {
|
|
return this.list.filter(function (win) { return win.visible(srf); });
|
|
};
|
|
WindowStore.prototype.getVisibleTiles = function (srf) {
|
|
return this.list.filter(function (win) { return win.tiled && win.visible(srf); });
|
|
};
|
|
WindowStore.prototype.getVisibleTileables = function (srf) {
|
|
return this.list.filter(function (win) { return win.tileable && win.visible(srf); });
|
|
};
|
|
return WindowStore;
|
|
}());
|
|
var BTreeLayout = (function () {
|
|
function BTreeLayout() {
|
|
this.classID = BTreeLayout.id;
|
|
this.parts = new HalfSplitLayoutPart(new FillLayoutPart(), new FillLayoutPart());
|
|
this.parts.angle = 0;
|
|
this.parts.gap = CONFIG.tileLayoutGap;
|
|
}
|
|
Object.defineProperty(BTreeLayout.prototype, "description", {
|
|
get: function () {
|
|
return "BTree";
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
BTreeLayout.prototype.apply = function (ctx, tileables, area) {
|
|
tileables.forEach(function (tileable) { return (tileable.state = WindowState.Tiled); });
|
|
this.create_parts(tileables.length);
|
|
var rectangles = this.parts.apply(area, tileables);
|
|
rectangles.forEach(function (geometry, i) {
|
|
tileables[i].geometry = geometry;
|
|
});
|
|
};
|
|
BTreeLayout.prototype.create_parts = function (tiles_len) {
|
|
var head = this.get_head();
|
|
head.angle = 0;
|
|
head.gap = CONFIG.tileLayoutGap;
|
|
if (tiles_len > 2) {
|
|
var level = Math.ceil(Math.log(tiles_len) * 1.442695);
|
|
var level_capacity = Math.pow(2, (level - 1));
|
|
var half_level_capacity = Math.pow(2, (level - 2));
|
|
if (tiles_len > level_capacity + half_level_capacity) {
|
|
head.primarySize = tiles_len - level_capacity;
|
|
}
|
|
else {
|
|
head.primarySize = half_level_capacity;
|
|
}
|
|
this.build_binary_tree(head, level, 2, tiles_len);
|
|
}
|
|
this.parts = head;
|
|
};
|
|
BTreeLayout.prototype.build_binary_tree = function (head, max_level, current_level, tiles_len) {
|
|
if (current_level <= max_level) {
|
|
if (head.primarySize > 1) {
|
|
var primary = this.get_head();
|
|
primary.primarySize = Math.floor(head.primarySize / 2);
|
|
primary.gap = CONFIG.tileLayoutGap;
|
|
primary.angle = current_level % 2 ? 0 : 90;
|
|
head.primary = primary;
|
|
this.build_binary_tree(primary, max_level, current_level + 1, head.primarySize);
|
|
}
|
|
if (tiles_len - head.primarySize > 1) {
|
|
var secondary = this.get_head();
|
|
secondary.primarySize = Math.floor((tiles_len - head.primarySize) / 2);
|
|
secondary.gap = CONFIG.tileLayoutGap;
|
|
secondary.angle = current_level % 2 ? 0 : 90;
|
|
head.secondary = secondary;
|
|
this.build_binary_tree(secondary, max_level, current_level + 1, tiles_len - head.primarySize);
|
|
}
|
|
}
|
|
};
|
|
BTreeLayout.prototype.get_head = function () {
|
|
return new HalfSplitLayoutPart(new FillLayoutPart(), new FillLayoutPart());
|
|
};
|
|
BTreeLayout.prototype.clone = function () {
|
|
var other = new StackedLayout();
|
|
return other;
|
|
};
|
|
BTreeLayout.prototype.toString = function () {
|
|
return "BTreeLayout()";
|
|
};
|
|
BTreeLayout.id = "BTreeLayout";
|
|
return BTreeLayout;
|
|
}());
|
|
var CascadeDirection;
|
|
(function (CascadeDirection) {
|
|
CascadeDirection[CascadeDirection["NorthWest"] = 0] = "NorthWest";
|
|
CascadeDirection[CascadeDirection["North"] = 1] = "North";
|
|
CascadeDirection[CascadeDirection["NorthEast"] = 2] = "NorthEast";
|
|
CascadeDirection[CascadeDirection["East"] = 3] = "East";
|
|
CascadeDirection[CascadeDirection["SouthEast"] = 4] = "SouthEast";
|
|
CascadeDirection[CascadeDirection["South"] = 5] = "South";
|
|
CascadeDirection[CascadeDirection["SouthWest"] = 6] = "SouthWest";
|
|
CascadeDirection[CascadeDirection["West"] = 7] = "West";
|
|
})(CascadeDirection || (CascadeDirection = {}));
|
|
var CascadeLayout = (function () {
|
|
function CascadeLayout(dir) {
|
|
if (dir === void 0) { dir = CascadeDirection.SouthEast; }
|
|
this.dir = dir;
|
|
this.classID = CascadeLayout.id;
|
|
}
|
|
CascadeLayout.decomposeDirection = function (dir) {
|
|
switch (dir) {
|
|
case CascadeDirection.NorthWest:
|
|
return [-1, -1];
|
|
case CascadeDirection.North:
|
|
return [-1, 0];
|
|
case CascadeDirection.NorthEast:
|
|
return [-1, 1];
|
|
case CascadeDirection.East:
|
|
return [0, 1];
|
|
case CascadeDirection.SouthEast:
|
|
return [1, 1];
|
|
case CascadeDirection.South:
|
|
return [1, 0];
|
|
case CascadeDirection.SouthWest:
|
|
return [1, -1];
|
|
case CascadeDirection.West:
|
|
return [0, -1];
|
|
}
|
|
};
|
|
Object.defineProperty(CascadeLayout.prototype, "description", {
|
|
get: function () {
|
|
return "Cascade [" + CascadeDirection[this.dir] + "]";
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
CascadeLayout.prototype.apply = function (ctx, tileables, area) {
|
|
var _a = CascadeLayout.decomposeDirection(this.dir), vertStep = _a[0], horzStep = _a[1];
|
|
var stepSize = 25;
|
|
var windowWidth = horzStep !== 0
|
|
? area.width - stepSize * (tileables.length - 1)
|
|
: area.width;
|
|
var windowHeight = vertStep !== 0
|
|
? area.height - stepSize * (tileables.length - 1)
|
|
: area.height;
|
|
var baseX = horzStep >= 0 ? area.x : area.maxX - windowWidth;
|
|
var baseY = vertStep >= 0 ? area.y : area.maxY - windowHeight;
|
|
var x = baseX, y = baseY;
|
|
tileables.forEach(function (tile) {
|
|
tile.state = WindowState.Tiled;
|
|
tile.geometry = new Rect(x, y, windowWidth, windowHeight);
|
|
x += horzStep * stepSize;
|
|
y += vertStep * stepSize;
|
|
});
|
|
};
|
|
CascadeLayout.prototype.clone = function () {
|
|
return new CascadeLayout(this.dir);
|
|
};
|
|
CascadeLayout.prototype.handleShortcut = function (ctx, input, data) {
|
|
switch (input) {
|
|
case Shortcut.Increase:
|
|
this.dir = (this.dir + 1 + 8) % 8;
|
|
ctx.showNotification(this.description);
|
|
break;
|
|
case Shortcut.Decrease:
|
|
this.dir = (this.dir - 1 + 8) % 8;
|
|
ctx.showNotification(this.description);
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
CascadeLayout.id = "CascadeLayout";
|
|
return CascadeLayout;
|
|
}());
|
|
var FloatingLayout = (function () {
|
|
function FloatingLayout() {
|
|
this.classID = FloatingLayout.id;
|
|
this.description = "Floating";
|
|
}
|
|
FloatingLayout.prototype.apply = function (ctx, tileables, area) {
|
|
tileables.forEach(function (tileable) { return (tileable.state = WindowState.TiledAfloat); });
|
|
};
|
|
FloatingLayout.prototype.clone = function () {
|
|
return this;
|
|
};
|
|
FloatingLayout.prototype.toString = function () {
|
|
return "FloatingLayout()";
|
|
};
|
|
FloatingLayout.id = "FloatingLayout ";
|
|
FloatingLayout.instance = new FloatingLayout();
|
|
return FloatingLayout;
|
|
}());
|
|
var FillLayoutPart = (function () {
|
|
function FillLayoutPart() {
|
|
}
|
|
FillLayoutPart.prototype.adjust = function (area, tiles, basis, delta) {
|
|
return delta;
|
|
};
|
|
FillLayoutPart.prototype.apply = function (area, tiles) {
|
|
return tiles.map(function (tile) {
|
|
return area;
|
|
});
|
|
};
|
|
FillLayoutPart.prototype.toString = function () {
|
|
return "FillLayoutPart";
|
|
};
|
|
return FillLayoutPart;
|
|
}());
|
|
var HalfSplitLayoutPart = (function () {
|
|
function HalfSplitLayoutPart(primary, secondary) {
|
|
this.primary = primary;
|
|
this.secondary = secondary;
|
|
this.angle = 0;
|
|
this.gap = 0;
|
|
this.primarySize = 1;
|
|
this.ratio = 0.5;
|
|
}
|
|
Object.defineProperty(HalfSplitLayoutPart.prototype, "horizontal", {
|
|
get: function () {
|
|
return this.angle === 0 || this.angle === 180;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(HalfSplitLayoutPart.prototype, "reversed", {
|
|
get: function () {
|
|
return this.angle === 180 || this.angle === 270;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
HalfSplitLayoutPart.prototype.adjust = function (area, tiles, basis, delta) {
|
|
var basisIndex = tiles.indexOf(basis);
|
|
if (basisIndex < 0)
|
|
return delta;
|
|
if (tiles.length <= this.primarySize) {
|
|
return this.primary.adjust(area, tiles, basis, delta);
|
|
}
|
|
else if (this.primarySize === 0) {
|
|
return this.secondary.adjust(area, tiles, basis, delta);
|
|
}
|
|
else {
|
|
var targetIndex = basisIndex < this.primarySize ? 0 : 1;
|
|
if (targetIndex === 0) {
|
|
delta = this.primary.adjust(area, tiles.slice(0, this.primarySize), basis, delta);
|
|
}
|
|
else {
|
|
delta = this.secondary.adjust(area, tiles.slice(this.primarySize), basis, delta);
|
|
}
|
|
this.ratio = LayoutUtils.adjustAreaHalfWeights(area, this.reversed ? 1 - this.ratio : this.ratio, this.gap, this.reversed ? 1 - targetIndex : targetIndex, delta, this.horizontal);
|
|
if (this.reversed)
|
|
this.ratio = 1 - this.ratio;
|
|
switch (this.angle * 10 + targetIndex + 1) {
|
|
case 1:
|
|
case 1802:
|
|
return new RectDelta(0, delta.west, delta.south, delta.north);
|
|
case 2:
|
|
case 1801:
|
|
return new RectDelta(delta.east, 0, delta.south, delta.north);
|
|
case 901:
|
|
case 2702:
|
|
return new RectDelta(delta.east, delta.west, 0, delta.north);
|
|
case 902:
|
|
case 2701:
|
|
return new RectDelta(delta.east, delta.west, delta.south, 0);
|
|
}
|
|
return delta;
|
|
}
|
|
};
|
|
HalfSplitLayoutPart.prototype.toString = function () {
|
|
return "<HalfSplitLayout: angle:".concat(this.angle, ",ratio:").concat(this.ratio, ",pr_size:").concat(this.primarySize, ".<<<Primary:").concat(this.primary, "---Secondary:").concat(this.secondary, ">>>");
|
|
};
|
|
HalfSplitLayoutPart.prototype.apply = function (area, tiles) {
|
|
if (tiles.length <= this.primarySize) {
|
|
return this.primary.apply(area, tiles);
|
|
}
|
|
else if (this.primarySize === 0) {
|
|
return this.secondary.apply(area, tiles);
|
|
}
|
|
else {
|
|
var reversed = this.reversed;
|
|
var ratio = reversed ? 1 - this.ratio : this.ratio;
|
|
var _a = LayoutUtils.splitAreaHalfWeighted(area, ratio, this.gap, this.horizontal), area1 = _a[0], area2 = _a[1];
|
|
var result1 = this.primary.apply(reversed ? area2 : area1, tiles.slice(0, this.primarySize));
|
|
var result2 = this.secondary.apply(reversed ? area1 : area2, tiles.slice(this.primarySize));
|
|
return result1.concat(result2);
|
|
}
|
|
};
|
|
return HalfSplitLayoutPart;
|
|
}());
|
|
var StackLayoutPart = (function () {
|
|
function StackLayoutPart() {
|
|
this.gap = 0;
|
|
}
|
|
StackLayoutPart.prototype.adjust = function (area, tiles, basis, delta) {
|
|
var weights = LayoutUtils.adjustAreaWeights(area, tiles.map(function (tile) { return tile.weight; }), CONFIG.tileLayoutGap, tiles.indexOf(basis), delta, false);
|
|
weights.forEach(function (weight, i) {
|
|
tiles[i].weight = weight * tiles.length;
|
|
});
|
|
var idx = tiles.indexOf(basis);
|
|
return new RectDelta(delta.east, delta.west, idx === tiles.length - 1 ? delta.south : 0, idx === 0 ? delta.north : 0);
|
|
};
|
|
StackLayoutPart.prototype.apply = function (area, tiles) {
|
|
var weights = tiles.map(function (tile) { return tile.weight; });
|
|
return LayoutUtils.splitAreaWeighted(area, weights, this.gap);
|
|
};
|
|
return StackLayoutPart;
|
|
}());
|
|
var RotateLayoutPart = (function () {
|
|
function RotateLayoutPart(inner, angle) {
|
|
if (angle === void 0) { angle = 0; }
|
|
this.inner = inner;
|
|
this.angle = angle;
|
|
}
|
|
RotateLayoutPart.prototype.adjust = function (area, tiles, basis, delta) {
|
|
switch (this.angle) {
|
|
case 0:
|
|
break;
|
|
case 90:
|
|
area = new Rect(area.y, area.x, area.height, area.width);
|
|
delta = new RectDelta(delta.south, delta.north, delta.east, delta.west);
|
|
break;
|
|
case 180:
|
|
delta = new RectDelta(delta.west, delta.east, delta.south, delta.north);
|
|
break;
|
|
case 270:
|
|
area = new Rect(area.y, area.x, area.height, area.width);
|
|
delta = new RectDelta(delta.north, delta.south, delta.east, delta.west);
|
|
break;
|
|
}
|
|
delta = this.inner.adjust(area, tiles, basis, delta);
|
|
switch (this.angle) {
|
|
case 0:
|
|
delta = delta;
|
|
break;
|
|
case 90:
|
|
delta = new RectDelta(delta.south, delta.north, delta.east, delta.west);
|
|
break;
|
|
case 180:
|
|
delta = new RectDelta(delta.west, delta.east, delta.south, delta.north);
|
|
break;
|
|
case 270:
|
|
delta = new RectDelta(delta.north, delta.south, delta.east, delta.west);
|
|
break;
|
|
}
|
|
return delta;
|
|
};
|
|
RotateLayoutPart.prototype.apply = function (area, tiles) {
|
|
switch (this.angle) {
|
|
case 0:
|
|
break;
|
|
case 90:
|
|
area = new Rect(area.y, area.x, area.height, area.width);
|
|
break;
|
|
case 180:
|
|
break;
|
|
case 270:
|
|
area = new Rect(area.y, area.x, area.height, area.width);
|
|
break;
|
|
}
|
|
var innerResult = this.inner.apply(area, tiles);
|
|
switch (this.angle) {
|
|
case 0:
|
|
return innerResult;
|
|
case 90:
|
|
return innerResult.map(function (g) { return new Rect(g.y, g.x, g.height, g.width); });
|
|
case 180:
|
|
return innerResult.map(function (g) {
|
|
var rx = g.x - area.x;
|
|
var newX = area.x + area.width - (rx + g.width);
|
|
return new Rect(newX, g.y, g.width, g.height);
|
|
});
|
|
case 270:
|
|
return innerResult.map(function (g) {
|
|
var rx = g.x - area.x;
|
|
var newY = area.x + area.width - (rx + g.width);
|
|
return new Rect(g.y, newY, g.height, g.width);
|
|
});
|
|
}
|
|
};
|
|
RotateLayoutPart.prototype.rotate = function (amount) {
|
|
var angle = this.angle + amount;
|
|
if (angle < 0)
|
|
angle = 270;
|
|
else if (angle >= 360)
|
|
angle = 0;
|
|
this.angle = angle;
|
|
};
|
|
return RotateLayoutPart;
|
|
}());
|
|
var LayoutUtils = (function () {
|
|
function LayoutUtils() {
|
|
}
|
|
LayoutUtils.splitWeighted = function (_a, weights, gap) {
|
|
var begin = _a[0], length = _a[1];
|
|
gap = gap !== undefined ? gap : 0;
|
|
var n = weights.length;
|
|
var actualLength = length - (n - 1) * gap;
|
|
var weightSum = weights.reduce(function (sum, weight) { return sum + weight; }, 0);
|
|
var weightAcc = 0;
|
|
return weights.map(function (weight, i) {
|
|
var partBegin = (actualLength * weightAcc) / weightSum + i * gap;
|
|
var partLength = (actualLength * weight) / weightSum;
|
|
weightAcc += weight;
|
|
return [begin + Math.floor(partBegin), Math.floor(partLength)];
|
|
});
|
|
};
|
|
LayoutUtils.splitAreaWeighted = function (area, weights, gap, horizontal) {
|
|
gap = gap !== undefined ? gap : 0;
|
|
horizontal = horizontal !== undefined ? horizontal : false;
|
|
var line = horizontal
|
|
? [area.x, area.width]
|
|
: [area.y, area.height];
|
|
var parts = LayoutUtils.splitWeighted(line, weights, gap);
|
|
return parts.map(function (_a) {
|
|
var begin = _a[0], length = _a[1];
|
|
return horizontal
|
|
? new Rect(begin, area.y, length, area.height)
|
|
: new Rect(area.x, begin, area.width, length);
|
|
});
|
|
};
|
|
LayoutUtils.splitAreaHalfWeighted = function (area, weight, gap, horizontal) {
|
|
return LayoutUtils.splitAreaWeighted(area, [weight, 1 - weight], gap, horizontal);
|
|
};
|
|
LayoutUtils.adjustWeights = function (_a, weights, gap, target, deltaFw, deltaBw) {
|
|
var begin = _a[0], length = _a[1];
|
|
var minLength = 1;
|
|
var parts = this.splitWeighted([begin, length], weights, gap);
|
|
var _b = parts[target], targetBase = _b[0], targetLength = _b[1];
|
|
if (target > 0 && deltaBw !== 0) {
|
|
var neighbor = target - 1;
|
|
var _c = parts[neighbor], neighborBase = _c[0], neighborLength = _c[1];
|
|
var delta = clip(deltaBw, minLength - targetLength, neighborLength - minLength);
|
|
parts[target] = [targetBase - delta, targetLength + delta];
|
|
parts[neighbor] = [neighborBase, neighborLength - delta];
|
|
}
|
|
if (target < parts.length - 1 && deltaFw !== 0) {
|
|
var neighbor = target + 1;
|
|
var _d = parts[neighbor], neighborBase = _d[0], neighborLength = _d[1];
|
|
var delta = clip(deltaFw, minLength - targetLength, neighborLength - minLength);
|
|
parts[target] = [targetBase, targetLength + delta];
|
|
parts[neighbor] = [neighborBase + delta, neighborLength - delta];
|
|
}
|
|
return LayoutUtils.calculateWeights(parts);
|
|
};
|
|
LayoutUtils.adjustAreaWeights = function (area, weights, gap, target, delta, horizontal) {
|
|
var line = horizontal
|
|
? [area.x, area.width]
|
|
: [area.y, area.height];
|
|
var _a = horizontal
|
|
? [delta.east, delta.west]
|
|
: [delta.south, delta.north], deltaFw = _a[0], deltaBw = _a[1];
|
|
return LayoutUtils.adjustWeights(line, weights, gap, target, deltaFw, deltaBw);
|
|
};
|
|
LayoutUtils.adjustAreaHalfWeights = function (area, weight, gap, target, delta, horizontal) {
|
|
var weights = [weight, 1 - weight];
|
|
var newWeights = LayoutUtils.adjustAreaWeights(area, weights, gap, target, delta, horizontal);
|
|
return newWeights[0];
|
|
};
|
|
LayoutUtils.calculateWeights = function (parts) {
|
|
var totalLength = parts.reduce(function (acc, _a) {
|
|
var base = _a[0], length = _a[1];
|
|
return acc + length;
|
|
}, 0);
|
|
return parts.map(function (_a) {
|
|
var base = _a[0], length = _a[1];
|
|
return length / totalLength;
|
|
});
|
|
};
|
|
LayoutUtils.calculateAreaWeights = function (area, geometries, gap, horizontal) {
|
|
gap = gap !== undefined ? gap : 0;
|
|
horizontal = horizontal !== undefined ? horizontal : false;
|
|
var line = horizontal ? area.width : area.height;
|
|
var parts = horizontal
|
|
? geometries.map(function (geometry) { return [geometry.x, geometry.width]; })
|
|
: geometries.map(function (geometry) { return [geometry.y, geometry.height]; });
|
|
return LayoutUtils.calculateWeights(parts);
|
|
};
|
|
return LayoutUtils;
|
|
}());
|
|
var MonocleLayout = (function () {
|
|
function MonocleLayout() {
|
|
this.description = "Monocle";
|
|
this.classID = MonocleLayout.id;
|
|
}
|
|
MonocleLayout.prototype.apply = function (ctx, tileables, area) {
|
|
tileables.forEach(function (tile) {
|
|
tile.state = CONFIG.monocleMaximize
|
|
? WindowState.Maximized
|
|
: WindowState.Tiled;
|
|
tile.geometry = area;
|
|
});
|
|
if (ctx.backend === KWinDriver.backendName &&
|
|
KWINCONFIG.monocleMinimizeRest) {
|
|
var tiles_1 = __spreadArray([], tileables, true);
|
|
ctx.setTimeout(function () {
|
|
var current = ctx.currentWindow;
|
|
if (current && current.tiled) {
|
|
tiles_1.forEach(function (window) {
|
|
if (window !== current)
|
|
window.window.window.minimized = true;
|
|
});
|
|
}
|
|
}, 50);
|
|
}
|
|
};
|
|
MonocleLayout.prototype.clone = function () {
|
|
return this;
|
|
};
|
|
MonocleLayout.prototype.handleShortcut = function (ctx, input, data) {
|
|
switch (input) {
|
|
case Shortcut.DWMLeft:
|
|
case Shortcut.FocusNext:
|
|
case Shortcut.FocusUp:
|
|
case Shortcut.FocusLeft:
|
|
ctx.cycleFocus(-1);
|
|
return true;
|
|
case Shortcut.DWMRight:
|
|
case Shortcut.FocusPrev:
|
|
case Shortcut.FocusDown:
|
|
case Shortcut.FocusRight:
|
|
ctx.cycleFocus(1);
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
};
|
|
MonocleLayout.prototype.toString = function () {
|
|
return "MonocleLayout()";
|
|
};
|
|
MonocleLayout.id = "MonocleLayout";
|
|
return MonocleLayout;
|
|
}());
|
|
var QuarterLayout = (function () {
|
|
function QuarterLayout() {
|
|
this.classID = QuarterLayout.id;
|
|
this.description = "Quarter";
|
|
this.lhsplit = 0.5;
|
|
this.rhsplit = 0.5;
|
|
this.vsplit = 0.5;
|
|
}
|
|
Object.defineProperty(QuarterLayout.prototype, "capacity", {
|
|
get: function () {
|
|
return 4;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
QuarterLayout.prototype.adjust = function (area, tiles, basis, delta) {
|
|
if (tiles.length <= 1 || tiles.length > 4)
|
|
return;
|
|
var idx = tiles.indexOf(basis);
|
|
if (idx < 0)
|
|
return;
|
|
if ((idx === 0 || idx === 3) && delta.east !== 0)
|
|
this.vsplit =
|
|
(Math.floor(area.width * this.vsplit) + delta.east) / area.width;
|
|
else if ((idx === 1 || idx === 2) && delta.west !== 0)
|
|
this.vsplit =
|
|
(Math.floor(area.width * this.vsplit) - delta.west) / area.width;
|
|
if (tiles.length === 4) {
|
|
if (idx === 0 && delta.south !== 0)
|
|
this.lhsplit =
|
|
(Math.floor(area.height * this.lhsplit) + delta.south) / area.height;
|
|
if (idx === 3 && delta.north !== 0)
|
|
this.lhsplit =
|
|
(Math.floor(area.height * this.lhsplit) - delta.north) / area.height;
|
|
}
|
|
if (tiles.length >= 3) {
|
|
if (idx === 1 && delta.south !== 0)
|
|
this.rhsplit =
|
|
(Math.floor(area.height * this.rhsplit) + delta.south) / area.height;
|
|
if (idx === 2 && delta.north !== 0)
|
|
this.rhsplit =
|
|
(Math.floor(area.height * this.rhsplit) - delta.north) / area.height;
|
|
}
|
|
this.vsplit = clip(this.vsplit, 1 - QuarterLayout.MAX_PROPORTION, QuarterLayout.MAX_PROPORTION);
|
|
this.lhsplit = clip(this.lhsplit, 1 - QuarterLayout.MAX_PROPORTION, QuarterLayout.MAX_PROPORTION);
|
|
this.rhsplit = clip(this.rhsplit, 1 - QuarterLayout.MAX_PROPORTION, QuarterLayout.MAX_PROPORTION);
|
|
};
|
|
QuarterLayout.prototype.clone = function () {
|
|
var other = new QuarterLayout();
|
|
other.lhsplit = this.lhsplit;
|
|
other.rhsplit = this.rhsplit;
|
|
other.vsplit = this.vsplit;
|
|
return other;
|
|
};
|
|
QuarterLayout.prototype.apply = function (ctx, tileables, area) {
|
|
for (var i = 0; i < 4 && i < tileables.length; i++)
|
|
tileables[i].state = WindowState.Tiled;
|
|
if (tileables.length > 4)
|
|
tileables
|
|
.slice(4)
|
|
.forEach(function (tile) { return (tile.state = WindowState.TiledAfloat); });
|
|
if (tileables.length === 1) {
|
|
tileables[0].geometry = area;
|
|
return;
|
|
}
|
|
var gap1 = Math.floor(CONFIG.tileLayoutGap / 2);
|
|
var gap2 = CONFIG.tileLayoutGap - gap1;
|
|
var leftWidth = Math.floor(area.width * this.vsplit);
|
|
var rightWidth = area.width - leftWidth;
|
|
var rightX = area.x + leftWidth;
|
|
if (tileables.length === 2) {
|
|
tileables[0].geometry = new Rect(area.x, area.y, leftWidth, area.height).gap(0, gap1, 0, 0);
|
|
tileables[1].geometry = new Rect(rightX, area.y, rightWidth, area.height).gap(gap2, 0, 0, 0);
|
|
return;
|
|
}
|
|
var rightTopHeight = Math.floor(area.height * this.rhsplit);
|
|
var rightBottomHeight = area.height - rightTopHeight;
|
|
var rightBottomY = area.y + rightTopHeight;
|
|
if (tileables.length === 3) {
|
|
tileables[0].geometry = new Rect(area.x, area.y, leftWidth, area.height).gap(0, gap1, 0, 0);
|
|
tileables[1].geometry = new Rect(rightX, area.y, rightWidth, rightTopHeight).gap(gap2, 0, 0, gap1);
|
|
tileables[2].geometry = new Rect(rightX, rightBottomY, rightWidth, rightBottomHeight).gap(gap2, 0, gap2, 0);
|
|
return;
|
|
}
|
|
var leftTopHeight = Math.floor(area.height * this.lhsplit);
|
|
var leftBottomHeight = area.height - leftTopHeight;
|
|
var leftBottomY = area.y + leftTopHeight;
|
|
if (tileables.length >= 4) {
|
|
tileables[0].geometry = new Rect(area.x, area.y, leftWidth, leftTopHeight).gap(0, gap1, 0, gap1);
|
|
tileables[1].geometry = new Rect(rightX, area.y, rightWidth, rightTopHeight).gap(gap2, 0, 0, gap1);
|
|
tileables[2].geometry = new Rect(rightX, rightBottomY, rightWidth, rightBottomHeight).gap(gap2, 0, gap2, 0);
|
|
tileables[3].geometry = new Rect(area.x, leftBottomY, leftWidth, leftBottomHeight).gap(0, gap2, gap2, 0);
|
|
}
|
|
};
|
|
QuarterLayout.prototype.toString = function () {
|
|
return "QuarterLayout()";
|
|
};
|
|
QuarterLayout.MAX_PROPORTION = 0.8;
|
|
QuarterLayout.id = "QuarterLayout";
|
|
return QuarterLayout;
|
|
}());
|
|
var SpiralLayout = (function () {
|
|
function SpiralLayout() {
|
|
this.description = "Spiral";
|
|
this.classID = SpiralLayout.id;
|
|
this.depth = 1;
|
|
this.parts = new HalfSplitLayoutPart(new FillLayoutPart(), new FillLayoutPart());
|
|
this.parts.angle = 0;
|
|
this.parts.gap = CONFIG.tileLayoutGap;
|
|
}
|
|
SpiralLayout.prototype.adjust = function (area, tiles, basis, delta) {
|
|
this.parts.adjust(area, tiles, basis, delta);
|
|
};
|
|
SpiralLayout.prototype.apply = function (ctx, tileables, area) {
|
|
tileables.forEach(function (tileable) { return (tileable.state = WindowState.Tiled); });
|
|
this.bore(tileables.length);
|
|
this.parts.apply(area, tileables).forEach(function (geometry, i) {
|
|
tileables[i].geometry = geometry;
|
|
});
|
|
};
|
|
SpiralLayout.prototype.toString = function () {
|
|
return "Spiral()";
|
|
};
|
|
SpiralLayout.prototype.bore = function (depth) {
|
|
if (this.depth >= depth)
|
|
return;
|
|
var hpart = this.parts;
|
|
var i;
|
|
for (i = 0; i < this.depth - 1; i++) {
|
|
hpart = hpart.secondary;
|
|
}
|
|
var lastFillPart = hpart.secondary;
|
|
var npart;
|
|
while (i < depth - 1) {
|
|
npart = new HalfSplitLayoutPart(new FillLayoutPart(), lastFillPart);
|
|
npart.gap = CONFIG.tileLayoutGap;
|
|
switch ((i + 1) % 4) {
|
|
case 0:
|
|
npart.angle = 0;
|
|
break;
|
|
case 1:
|
|
npart.angle = 90;
|
|
break;
|
|
case 2:
|
|
npart.angle = 180;
|
|
break;
|
|
case 3:
|
|
npart.angle = 270;
|
|
break;
|
|
}
|
|
hpart.secondary = npart;
|
|
hpart = npart;
|
|
i++;
|
|
}
|
|
this.depth = depth;
|
|
};
|
|
SpiralLayout.id = "SpiralLayout";
|
|
return SpiralLayout;
|
|
}());
|
|
var SpreadLayout = (function () {
|
|
function SpreadLayout() {
|
|
this.classID = SpreadLayout.id;
|
|
this.description = "Spread";
|
|
this.space = 0.07;
|
|
}
|
|
SpreadLayout.prototype.apply = function (ctx, tileables, area) {
|
|
tileables.forEach(function (tileable) { return (tileable.state = WindowState.Tiled); });
|
|
var tiles = tileables;
|
|
var numTiles = tiles.length;
|
|
var spaceWidth = Math.floor(area.width * this.space);
|
|
var cardWidth = area.width - spaceWidth * (numTiles - 1);
|
|
var miniumCardWidth = area.width * 0.4;
|
|
while (cardWidth < miniumCardWidth) {
|
|
cardWidth += spaceWidth;
|
|
numTiles -= 1;
|
|
}
|
|
for (var i = 0; i < tiles.length; i++)
|
|
tiles[i].geometry = new Rect(area.x + (i < numTiles ? spaceWidth * (numTiles - i - 1) : 0), area.y, cardWidth, area.height);
|
|
};
|
|
SpreadLayout.prototype.clone = function () {
|
|
var other = new SpreadLayout();
|
|
other.space = this.space;
|
|
return other;
|
|
};
|
|
SpreadLayout.prototype.handleShortcut = function (ctx, input) {
|
|
switch (input) {
|
|
case Shortcut.Decrease:
|
|
this.space = Math.max(0.04, this.space - 0.01);
|
|
break;
|
|
case Shortcut.Increase:
|
|
this.space = Math.min(0.1, this.space + 0.01);
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
SpreadLayout.prototype.toString = function () {
|
|
return "SpreadLayout(" + this.space + ")";
|
|
};
|
|
SpreadLayout.id = "SpreadLayout";
|
|
return SpreadLayout;
|
|
}());
|
|
var StackedLayout = (function () {
|
|
function StackedLayout() {
|
|
this.classID = StackedLayout.id;
|
|
this.parts = new RotateLayoutPart(new HalfSplitLayoutPart(new StackLayoutPart(), new StackLayoutPart()));
|
|
var masterPart = this.parts.inner;
|
|
masterPart.gap =
|
|
masterPart.secondary.gap =
|
|
CONFIG.tileLayoutGap;
|
|
}
|
|
Object.defineProperty(StackedLayout.prototype, "description", {
|
|
get: function () {
|
|
return "Stacked";
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
StackedLayout.prototype.adjust = function (area, tiles, basis, delta) {
|
|
this.parts.adjust(area, tiles, basis, delta);
|
|
};
|
|
StackedLayout.prototype.apply = function (ctx, tileables, area) {
|
|
tileables.forEach(function (tileable) { return (tileable.state = WindowState.Tiled); });
|
|
if (tileables.length > 1) {
|
|
this.parts.inner.angle = 90;
|
|
}
|
|
this.parts.apply(area, tileables).forEach(function (geometry, i) {
|
|
tileables[i].geometry = geometry;
|
|
});
|
|
};
|
|
StackedLayout.prototype.clone = function () {
|
|
var other = new StackedLayout();
|
|
return other;
|
|
};
|
|
StackedLayout.prototype.handleShortcut = function (ctx, input) {
|
|
switch (input) {
|
|
case Shortcut.Rotate:
|
|
this.parts.rotate(90);
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
StackedLayout.prototype.toString = function () {
|
|
return ("StackedLayout()");
|
|
};
|
|
StackedLayout.id = "StackedLayout";
|
|
return StackedLayout;
|
|
}());
|
|
var StairLayout = (function () {
|
|
function StairLayout() {
|
|
this.classID = StairLayout.id;
|
|
this.description = "Stair";
|
|
this.space = 24;
|
|
}
|
|
StairLayout.prototype.apply = function (ctx, tileables, area) {
|
|
tileables.forEach(function (tileable) { return (tileable.state = WindowState.Tiled); });
|
|
var tiles = tileables;
|
|
var len = tiles.length;
|
|
var space = this.space;
|
|
var alignRight = Number(!KWINCONFIG.stairReverse);
|
|
for (var i = 0; i < len; i++) {
|
|
var dx = space * (len - i - 1);
|
|
var dy = space * i;
|
|
tiles[i].geometry = new Rect(area.x + alignRight * dx, area.y + dy, area.width - dx, area.height - dy);
|
|
}
|
|
};
|
|
StairLayout.prototype.clone = function () {
|
|
var other = new StairLayout();
|
|
other.space = this.space;
|
|
return other;
|
|
};
|
|
StairLayout.prototype.handleShortcut = function (ctx, input) {
|
|
switch (input) {
|
|
case Shortcut.Decrease:
|
|
this.space = Math.max(16, this.space - 8);
|
|
break;
|
|
case Shortcut.Increase:
|
|
this.space = Math.min(160, this.space + 8);
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
StairLayout.prototype.toString = function () {
|
|
return "StairLayout(" + this.space + ")";
|
|
};
|
|
StairLayout.id = "StairLayout";
|
|
return StairLayout;
|
|
}());
|
|
var ThreeColumnLayout = (function () {
|
|
function ThreeColumnLayout() {
|
|
this.classID = ThreeColumnLayout.id;
|
|
this.masterRatio = 0.6;
|
|
this.masterSize = 1;
|
|
}
|
|
Object.defineProperty(ThreeColumnLayout.prototype, "description", {
|
|
get: function () {
|
|
return "Three-Column [" + this.masterSize + "]";
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
ThreeColumnLayout.prototype.adjust = function (area, tiles, basis, delta) {
|
|
var basisIndex = tiles.indexOf(basis);
|
|
if (basisIndex < 0)
|
|
return;
|
|
if (tiles.length === 0)
|
|
return;
|
|
else if (tiles.length <= this.masterSize) {
|
|
LayoutUtils.adjustAreaWeights(area, tiles.map(function (tile) { return tile.weight; }), CONFIG.tileLayoutGap, tiles.indexOf(basis), delta).forEach(function (newWeight, i) { return (tiles[i].weight = newWeight * tiles.length); });
|
|
}
|
|
else if (tiles.length === this.masterSize + 1) {
|
|
this.masterRatio = LayoutUtils.adjustAreaHalfWeights(area, this.masterRatio, CONFIG.tileLayoutGap, basisIndex < this.masterSize ? 0 : 1, delta, true);
|
|
if (basisIndex < this.masterSize) {
|
|
var masterTiles_1 = tiles.slice(0, -1);
|
|
LayoutUtils.adjustAreaWeights(area, masterTiles_1.map(function (tile) { return tile.weight; }), CONFIG.tileLayoutGap, basisIndex, delta).forEach(function (newWeight, i) {
|
|
return (masterTiles_1[i].weight = newWeight * masterTiles_1.length);
|
|
});
|
|
}
|
|
}
|
|
else if (tiles.length > this.masterSize + 1) {
|
|
var basisGroup = void 0;
|
|
if (basisIndex < this.masterSize)
|
|
basisGroup = 1;
|
|
else if (basisIndex < Math.floor((this.masterSize + tiles.length) / 2))
|
|
basisGroup = 2;
|
|
else
|
|
basisGroup = 0;
|
|
var stackRatio = 1 - this.masterRatio;
|
|
var newRatios = LayoutUtils.adjustAreaWeights(area, [stackRatio, this.masterRatio, stackRatio], CONFIG.tileLayoutGap, basisGroup, delta, true);
|
|
var newMasterRatio = newRatios[1];
|
|
var newStackRatio = basisGroup === 0 ? newRatios[0] : newRatios[2];
|
|
this.masterRatio = newMasterRatio / (newMasterRatio + newStackRatio);
|
|
var rstackNumTile = Math.floor((tiles.length - this.masterSize) / 2);
|
|
var _a = partitionArrayBySizes(tiles, [
|
|
this.masterSize,
|
|
rstackNumTile,
|
|
]), masterTiles = _a[0], rstackTiles = _a[1], lstackTiles = _a[2];
|
|
var groupTiles_1 = [lstackTiles, masterTiles, rstackTiles][basisGroup];
|
|
LayoutUtils.adjustAreaWeights(area, groupTiles_1.map(function (tile) { return tile.weight; }), CONFIG.tileLayoutGap, groupTiles_1.indexOf(basis), delta).forEach(function (newWeight, i) { return (groupTiles_1[i].weight = newWeight * groupTiles_1.length); });
|
|
}
|
|
};
|
|
ThreeColumnLayout.prototype.apply = function (ctx, tileables, area) {
|
|
tileables.forEach(function (tileable) { return (tileable.state = WindowState.Tiled); });
|
|
var tiles = tileables;
|
|
if (tiles.length <= this.masterSize) {
|
|
LayoutUtils.splitAreaWeighted(area, tiles.map(function (tile) { return tile.weight; }), CONFIG.tileLayoutGap).forEach(function (tileArea, i) { return (tiles[i].geometry = tileArea); });
|
|
}
|
|
else if (tiles.length === this.masterSize + 1) {
|
|
var _a = LayoutUtils.splitAreaHalfWeighted(area, this.masterRatio, CONFIG.tileLayoutGap, true), masterArea = _a[0], stackArea = _a[1];
|
|
var masterTiles_2 = tiles.slice(0, this.masterSize);
|
|
LayoutUtils.splitAreaWeighted(masterArea, masterTiles_2.map(function (tile) { return tile.weight; }), CONFIG.tileLayoutGap).forEach(function (tileArea, i) { return (masterTiles_2[i].geometry = tileArea); });
|
|
tiles[tiles.length - 1].geometry = stackArea;
|
|
}
|
|
else if (tiles.length > this.masterSize + 1) {
|
|
var stackRatio = 1 - this.masterRatio;
|
|
var groupAreas_1 = LayoutUtils.splitAreaWeighted(area, [stackRatio, this.masterRatio, stackRatio], CONFIG.tileLayoutGap, true);
|
|
var rstackSize = Math.floor((tiles.length - this.masterSize) / 2);
|
|
var _b = partitionArrayBySizes(tiles, [
|
|
this.masterSize,
|
|
rstackSize,
|
|
]), masterTiles = _b[0], rstackTiles = _b[1], lstackTiles = _b[2];
|
|
[lstackTiles, masterTiles, rstackTiles].forEach(function (groupTiles, group) {
|
|
LayoutUtils.splitAreaWeighted(groupAreas_1[group], groupTiles.map(function (tile) { return tile.weight; }), CONFIG.tileLayoutGap).forEach(function (tileArea, i) { return (groupTiles[i].geometry = tileArea); });
|
|
});
|
|
}
|
|
};
|
|
ThreeColumnLayout.prototype.clone = function () {
|
|
var other = new ThreeColumnLayout();
|
|
other.masterRatio = this.masterRatio;
|
|
other.masterSize = this.masterSize;
|
|
return other;
|
|
};
|
|
ThreeColumnLayout.prototype.handleShortcut = function (ctx, input, data) {
|
|
switch (input) {
|
|
case Shortcut.Increase:
|
|
this.resizeMaster(ctx, +1);
|
|
return true;
|
|
case Shortcut.Decrease:
|
|
this.resizeMaster(ctx, -1);
|
|
return true;
|
|
case Shortcut.DWMLeft:
|
|
this.masterRatio = clip(slide(this.masterRatio, -0.05), ThreeColumnLayout.MIN_MASTER_RATIO, ThreeColumnLayout.MAX_MASTER_RATIO);
|
|
return true;
|
|
case Shortcut.DWMRight:
|
|
this.masterRatio = clip(slide(this.masterRatio, +0.05), ThreeColumnLayout.MIN_MASTER_RATIO, ThreeColumnLayout.MAX_MASTER_RATIO);
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
};
|
|
ThreeColumnLayout.prototype.toString = function () {
|
|
return "ThreeColumnLayout(nmaster=" + this.masterSize + ")";
|
|
};
|
|
ThreeColumnLayout.prototype.resizeMaster = function (ctx, step) {
|
|
this.masterSize = clip(this.masterSize + step, 1, 10);
|
|
ctx.showNotification(this.description);
|
|
};
|
|
ThreeColumnLayout.MIN_MASTER_RATIO = 0.2;
|
|
ThreeColumnLayout.MAX_MASTER_RATIO = 0.75;
|
|
ThreeColumnLayout.id = "ThreeColumnLayout";
|
|
return ThreeColumnLayout;
|
|
}());
|
|
var TileLayout = (function () {
|
|
function TileLayout() {
|
|
this.classID = TileLayout.id;
|
|
this.parts = new RotateLayoutPart(new HalfSplitLayoutPart(new RotateLayoutPart(new StackLayoutPart()), new StackLayoutPart()));
|
|
var masterPart = this.parts.inner;
|
|
masterPart.gap =
|
|
masterPart.primary.inner.gap =
|
|
masterPart.secondary.gap =
|
|
CONFIG.tileLayoutGap;
|
|
}
|
|
Object.defineProperty(TileLayout.prototype, "description", {
|
|
get: function () {
|
|
return "Tile [" + this.numMaster + "]";
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(TileLayout.prototype, "numMaster", {
|
|
get: function () {
|
|
return this.parts.inner.primarySize;
|
|
},
|
|
set: function (value) {
|
|
this.parts.inner.primarySize = value;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(TileLayout.prototype, "masterRatio", {
|
|
get: function () {
|
|
return this.parts.inner.ratio;
|
|
},
|
|
set: function (value) {
|
|
this.parts.inner.ratio = value;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
TileLayout.prototype.adjust = function (area, tiles, basis, delta) {
|
|
this.parts.adjust(area, tiles, basis, delta);
|
|
};
|
|
TileLayout.prototype.apply = function (ctx, tileables, area) {
|
|
tileables.forEach(function (tileable) { return (tileable.state = WindowState.Tiled); });
|
|
this.parts.apply(area, tileables).forEach(function (geometry, i) {
|
|
tileables[i].geometry = geometry;
|
|
});
|
|
};
|
|
TileLayout.prototype.clone = function () {
|
|
var other = new TileLayout();
|
|
other.masterRatio = this.masterRatio;
|
|
other.numMaster = this.numMaster;
|
|
return other;
|
|
};
|
|
TileLayout.prototype.handleShortcut = function (ctx, input) {
|
|
switch (input) {
|
|
case Shortcut.DWMLeft:
|
|
this.masterRatio = clip(slide(this.masterRatio, -0.05), TileLayout.MIN_MASTER_RATIO, TileLayout.MAX_MASTER_RATIO);
|
|
break;
|
|
case Shortcut.DWMRight:
|
|
this.masterRatio = clip(slide(this.masterRatio, +0.05), TileLayout.MIN_MASTER_RATIO, TileLayout.MAX_MASTER_RATIO);
|
|
break;
|
|
case Shortcut.Increase:
|
|
if (this.numMaster < 10)
|
|
this.numMaster += 1;
|
|
ctx.showNotification(this.description);
|
|
break;
|
|
case Shortcut.Decrease:
|
|
if (this.numMaster > 0)
|
|
this.numMaster -= 1;
|
|
ctx.showNotification(this.description);
|
|
break;
|
|
case Shortcut.Rotate:
|
|
this.parts.rotate(90);
|
|
break;
|
|
case Shortcut.RotatePart:
|
|
this.parts.inner.primary.rotate(90);
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
TileLayout.prototype.toString = function () {
|
|
return ("TileLayout(nmaster=" +
|
|
this.numMaster +
|
|
", ratio=" +
|
|
this.masterRatio +
|
|
")");
|
|
};
|
|
TileLayout.MIN_MASTER_RATIO = 0.2;
|
|
TileLayout.MAX_MASTER_RATIO = 0.8;
|
|
TileLayout.id = "TileLayout";
|
|
return TileLayout;
|
|
}());
|
|
var DEBUG = {
|
|
enabled: false,
|
|
started: new Date().getTime(),
|
|
};
|
|
function debug(f) {
|
|
if (DEBUG.enabled) {
|
|
var timestamp = (new Date().getTime() - DEBUG.started) / 1000;
|
|
console.log("[" + timestamp + "]", f());
|
|
}
|
|
}
|
|
function debugObj(f) {
|
|
if (DEBUG.enabled) {
|
|
var timestamp = (new Date().getTime() - DEBUG.started) / 1000;
|
|
var _a = f(), name = _a[0], obj = _a[1];
|
|
var buf = [];
|
|
for (var i in obj)
|
|
buf.push(i + "=" + obj[i]);
|
|
console.log("[" + timestamp + "]", name + ": " + buf.join(" "));
|
|
}
|
|
}
|
|
function clip(value, min, max) {
|
|
if (value < min)
|
|
return min;
|
|
if (value > max)
|
|
return max;
|
|
return value;
|
|
}
|
|
function slide(value, step) {
|
|
if (step === 0)
|
|
return value;
|
|
return Math.floor(value / step + 1.000001) * step;
|
|
}
|
|
function matchWords(str, words) {
|
|
for (var i = 0; i < words.length; i++) {
|
|
if (str.indexOf(words[i]) >= 0)
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
function wrapIndex(index, length) {
|
|
if (index < 0)
|
|
return index + length;
|
|
if (index >= length)
|
|
return index - length;
|
|
return index;
|
|
}
|
|
function partitionArray(array, predicate) {
|
|
return array.reduce(function (parts, item, index) {
|
|
parts[predicate(item, index) ? 0 : 1].push(item);
|
|
return parts;
|
|
}, [[], []]);
|
|
}
|
|
function partitionArrayBySizes(array, sizes) {
|
|
var base = 0;
|
|
var chunks = sizes.map(function (size) {
|
|
var chunk = array.slice(base, base + size);
|
|
base += size;
|
|
return chunk;
|
|
});
|
|
chunks.push(array.slice(base));
|
|
return chunks;
|
|
}
|
|
function overlap(min1, max1, min2, max2) {
|
|
var min = Math.min;
|
|
var max = Math.max;
|
|
var dx = max(0, min(max1, max2) - max(min1, min2));
|
|
return dx > 0;
|
|
}
|
|
function toQRect(rect) {
|
|
return Qt.rect(rect.x, rect.y, rect.width, rect.height);
|
|
}
|
|
function toRect(qrect) {
|
|
return new Rect(qrect.x, qrect.y, qrect.width, qrect.height);
|
|
}
|
|
var Rect = (function () {
|
|
function Rect(x, y, width, height) {
|
|
this.x = x;
|
|
this.y = y;
|
|
this.width = width;
|
|
this.height = height;
|
|
}
|
|
Object.defineProperty(Rect.prototype, "maxX", {
|
|
get: function () {
|
|
return this.x + this.width;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(Rect.prototype, "maxY", {
|
|
get: function () {
|
|
return this.y + this.height;
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(Rect.prototype, "center", {
|
|
get: function () {
|
|
return [
|
|
this.x + Math.floor(this.width / 2),
|
|
this.y + Math.floor(this.height / 2),
|
|
];
|
|
},
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
Rect.prototype.clone = function () {
|
|
return new Rect(this.x, this.y, this.width, this.height);
|
|
};
|
|
Rect.prototype.equals = function (other) {
|
|
return (this.x === other.x &&
|
|
this.y === other.y &&
|
|
this.width === other.width &&
|
|
this.height === other.height);
|
|
};
|
|
Rect.prototype.gap = function (left, right, top, bottom) {
|
|
return new Rect(this.x + left, this.y + top, this.width - (left + right), this.height - (top + bottom));
|
|
};
|
|
Rect.prototype.gap_mut = function (left, right, top, bottom) {
|
|
this.x += left;
|
|
this.y += top;
|
|
this.width -= left + right;
|
|
this.height -= top + bottom;
|
|
return this;
|
|
};
|
|
Rect.prototype.includes = function (other) {
|
|
return (this.x <= other.x &&
|
|
this.y <= other.y &&
|
|
other.maxX < this.maxX &&
|
|
other.maxY < this.maxY);
|
|
};
|
|
Rect.prototype.includesPoint = function (_a) {
|
|
var x = _a[0], y = _a[1];
|
|
return this.x <= x && x <= this.maxX && this.y <= y && y <= this.maxY;
|
|
};
|
|
Rect.prototype.subtract = function (other) {
|
|
return new Rect(this.x - other.x, this.y - other.y, this.width - other.width, this.height - other.height);
|
|
};
|
|
Rect.prototype.toString = function () {
|
|
return "Rect(" + [this.x, this.y, this.width, this.height].join(", ") + ")";
|
|
};
|
|
return Rect;
|
|
}());
|
|
var RectDelta = (function () {
|
|
function RectDelta(east, west, south, north) {
|
|
this.east = east;
|
|
this.west = west;
|
|
this.south = south;
|
|
this.north = north;
|
|
}
|
|
RectDelta.fromRects = function (basis, target) {
|
|
var diff = target.subtract(basis);
|
|
return new RectDelta(diff.width + diff.x, -diff.x, diff.height + diff.y, -diff.y);
|
|
};
|
|
RectDelta.prototype.toString = function () {
|
|
return ("WindowResizeDelta(" +
|
|
[
|
|
"east=" + this.east,
|
|
"west=" + this.west,
|
|
"north=" + this.north,
|
|
"south=" + this.south,
|
|
].join(" ") +
|
|
")");
|
|
};
|
|
return RectDelta;
|
|
}());
|
|
var WrapperMap = (function () {
|
|
function WrapperMap(hasher, wrapper) {
|
|
this.hasher = hasher;
|
|
this.wrapper = wrapper;
|
|
this.items = {};
|
|
}
|
|
WrapperMap.prototype.add = function (item) {
|
|
var key = this.hasher(item);
|
|
if (this.items[key] !== undefined)
|
|
throw "WrapperMap: the key [" + key + "] already exists!";
|
|
var wrapped = this.wrapper(item);
|
|
this.items[key] = wrapped;
|
|
return wrapped;
|
|
};
|
|
WrapperMap.prototype.get = function (item) {
|
|
var key = this.hasher(item);
|
|
return this.items[key] || null;
|
|
};
|
|
WrapperMap.prototype.getByKey = function (key) {
|
|
return this.items[key] || null;
|
|
};
|
|
WrapperMap.prototype.remove = function (item) {
|
|
var key = this.hasher(item);
|
|
return delete this.items[key];
|
|
};
|
|
WrapperMap.prototype.length = function () {
|
|
return Object.keys(this.items).length;
|
|
};
|
|
return WrapperMap;
|
|
}());
|