[gnome] Move to Grimble tiling manager
This commit is contained in:
@ -0,0 +1,287 @@
|
||||
import {Tile, TileState} from './tile.js';
|
||||
import {Direction} from './tileWindowManager.js';
|
||||
import {Position} from './position.js';
|
||||
export class Monitor {
|
||||
_root;
|
||||
_index;
|
||||
_fullscreenState = false;
|
||||
constructor(index) {
|
||||
this._index = index;
|
||||
this._root = null;
|
||||
}
|
||||
|
||||
set root(root) {
|
||||
this._root = root;
|
||||
}
|
||||
|
||||
get root() {
|
||||
return this._root;
|
||||
}
|
||||
|
||||
get index() {
|
||||
return this._index;
|
||||
}
|
||||
|
||||
get fullscreen() {
|
||||
return this._fullscreenState;
|
||||
}
|
||||
|
||||
set fullscreen(b) {
|
||||
this._fullscreenState = b;
|
||||
}
|
||||
|
||||
size() {
|
||||
return this._root ? this._root._nr_tiles : 0;
|
||||
}
|
||||
|
||||
updateSize() {
|
||||
if (this._root) {
|
||||
const area = global.workspace_manager.get_active_workspace().get_work_area_for_monitor(this.index);
|
||||
if (area) {
|
||||
let pos = new Position(1.0, 0, 0, area.width, area.height);
|
||||
pos.splitProportion = this._root.position.splitProportion;
|
||||
this._root.resize(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bestFitMonitor(monitors) {
|
||||
return monitors.reduce((acc, val) => val.size() < acc.size() ? val : acc, monitors[0]);
|
||||
}
|
||||
|
||||
static tileDistance(t1, t2) {
|
||||
let vector = [t1.position.x - t2.position.x, t1.position.y - t2.position.y];
|
||||
return Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1]);
|
||||
}
|
||||
|
||||
closestTile(source, dir) {
|
||||
// Class to store the result
|
||||
class BestTile {
|
||||
tile = null;
|
||||
distance = null;
|
||||
constructor(tile = null, distance = null) {
|
||||
this.tile = tile;
|
||||
this.distance = distance;
|
||||
}
|
||||
}
|
||||
;
|
||||
// We search for the closest tile in a Direction. We recursively iterate the tree
|
||||
let findClosest = tile => {
|
||||
switch (dir) {
|
||||
case Direction.East:
|
||||
if (tile.leaf && tile.position.x > source.position.x) {
|
||||
return new BestTile(tile, Monitor.tileDistance(tile, source));
|
||||
} else if (tile.leaf) {
|
||||
return new BestTile();
|
||||
} else if (tile.child1 && tile.child2) {
|
||||
let res1 = findClosest(tile.child1);
|
||||
let res2 = findClosest(tile.child2);
|
||||
if ((res1.distance && res2.distance && res1.distance > res2.distance) ||
|
||||
(res2.distance && !res1.distance))
|
||||
return res2;
|
||||
|
||||
else if ((res1.distance && res2.distance && res1.distance < res2.distance) ||
|
||||
(res1.distance && !res2.distance))
|
||||
return res1;
|
||||
|
||||
else
|
||||
return new BestTile();
|
||||
}
|
||||
return new BestTile();
|
||||
case Direction.West:
|
||||
if (tile.leaf && tile.position.x < source.position.x) {
|
||||
return new BestTile(tile, Monitor.tileDistance(tile, source));
|
||||
} else if (tile.leaf) {
|
||||
return new BestTile();
|
||||
} else if (tile.child1 && tile.child2) {
|
||||
let res1 = findClosest(tile.child1);
|
||||
let res2 = findClosest(tile.child2);
|
||||
if ((res1.distance && res2.distance && res1.distance > res2.distance) ||
|
||||
(res2.distance && !res1.distance))
|
||||
return res2;
|
||||
|
||||
else if ((res1.distance && res2.distance && res1.distance < res2.distance) ||
|
||||
(res1.distance && !res2.distance))
|
||||
return res1;
|
||||
|
||||
else
|
||||
return new BestTile();
|
||||
}
|
||||
return new BestTile();
|
||||
case Direction.North:
|
||||
if (tile.leaf && tile.position.y < source.position.y) {
|
||||
return new BestTile(tile, Monitor.tileDistance(tile, source));
|
||||
} else if (tile.leaf) {
|
||||
return new BestTile();
|
||||
} else if (tile.child1 && tile.child2) {
|
||||
let res1 = findClosest(tile.child1);
|
||||
let res2 = findClosest(tile.child2);
|
||||
if ((res1.distance && res2.distance && res1.distance > res2.distance) ||
|
||||
(res2.distance && !res1.distance))
|
||||
return res2;
|
||||
|
||||
else if ((res1.distance && res2.distance && res1.distance < res2.distance) ||
|
||||
(res1.distance && !res2.distance))
|
||||
return res1;
|
||||
|
||||
else
|
||||
return new BestTile();
|
||||
}
|
||||
return new BestTile();
|
||||
case Direction.South:
|
||||
if (tile.leaf && tile.position.y > source.position.y) {
|
||||
return new BestTile(tile, Monitor.tileDistance(tile, source));
|
||||
} else if (tile.leaf) {
|
||||
return new BestTile();
|
||||
} else if (tile.child1 && tile.child2) {
|
||||
let res1 = findClosest(tile.child1);
|
||||
let res2 = findClosest(tile.child2);
|
||||
if ((res1.distance && res2.distance && res1.distance > res2.distance) ||
|
||||
(res2.distance && !res1.distance))
|
||||
return res2;
|
||||
|
||||
else if ((res1.distance && res2.distance && res1.distance < res2.distance) ||
|
||||
(res1.distance && !res2.distance))
|
||||
return res1;
|
||||
|
||||
else
|
||||
return new BestTile();
|
||||
}
|
||||
return new BestTile();
|
||||
default:
|
||||
return new BestTile();
|
||||
}
|
||||
};
|
||||
if (this.root) {
|
||||
let res = findClosest(this.root);
|
||||
return res.tile;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this._index = -1;
|
||||
this._root = null;
|
||||
}
|
||||
|
||||
static fromObject(obj) {
|
||||
let monitor = new Monitor(obj._index);
|
||||
monitor.fullscreen = obj._fullscreenState;
|
||||
if (!obj._root)
|
||||
monitor.root = null;
|
||||
else
|
||||
monitor.root = Tile.fromObject(obj._root);
|
||||
return monitor;
|
||||
}
|
||||
|
||||
closestMonitor(dir) {
|
||||
let nMonitors = global.display.get_n_monitors();
|
||||
let _currGeo = global.display.get_monitor_geometry(this.index);
|
||||
let min;
|
||||
let best = null;
|
||||
switch (dir) {
|
||||
case Direction.North:
|
||||
for (let i = 0; i < nMonitors; i++) {
|
||||
if (this.index !== i) {
|
||||
let _geometry = global.display.get_monitor_geometry(i);
|
||||
if (_geometry.y < _currGeo.y && (min === undefined || _geometry.y > min)) {
|
||||
min = _geometry.y;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return best;
|
||||
case Direction.South:
|
||||
for (let i = 0; i < nMonitors; i++) {
|
||||
if (this.index !== i) {
|
||||
let _geometry = global.display.get_monitor_geometry(i);
|
||||
if (_geometry.y > _currGeo.y && (min === undefined || _geometry.y < min)) {
|
||||
min = _geometry.y;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return best;
|
||||
case Direction.East:
|
||||
for (let i = 0; i < nMonitors; i++) {
|
||||
if (this.index !== i) {
|
||||
let _geometry = global.display.get_monitor_geometry(i);
|
||||
if (_geometry.x > _currGeo.x && (min === undefined || _geometry.x < min)) {
|
||||
min = _geometry.x;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return best;
|
||||
case Direction.West:
|
||||
for (let i = 0; i < nMonitors; i++) {
|
||||
if (this.index !== i) {
|
||||
let _geometry = global.display.get_monitor_geometry(i);
|
||||
if (_geometry.x < _currGeo.x && (!min || _geometry.x > min)) {
|
||||
min = _geometry.x;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return best;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns tile closest to the edge on a monitor
|
||||
* - If the monitor is in fullscreen it returns the maximized window
|
||||
*
|
||||
* @param {Direction} dir
|
||||
* @returns {Tile | null}
|
||||
*/
|
||||
getTile(dir) {
|
||||
if (this.root === null)
|
||||
return null;
|
||||
if (this.fullscreen)
|
||||
return this.root.find(t => t.state === TileState.MAXIMIZED);
|
||||
let getTileBis = t => {
|
||||
switch (dir) {
|
||||
case Direction.East:
|
||||
if (t.child2 !== null && t.child1 !== null)
|
||||
return t.child1.position.x > t.child2.position.x ? getTileBis(t.child1) : getTileBis(t.child2);
|
||||
else if (t.child1 !== null)
|
||||
return getTileBis(t.child1);
|
||||
else if (t.child2 !== null)
|
||||
return getTileBis(t.child2);
|
||||
else
|
||||
return t;
|
||||
case Direction.West:
|
||||
if (t.child2 !== null && t.child1 !== null)
|
||||
return t.child1.position.x < t.child2.position.x ? getTileBis(t.child1) : getTileBis(t.child2);
|
||||
else if (t.child1 !== null)
|
||||
return getTileBis(t.child1);
|
||||
else if (t.child2 !== null)
|
||||
return getTileBis(t.child2);
|
||||
else
|
||||
return t;
|
||||
case Direction.North:
|
||||
if (t.child2 !== null && t.child1 !== null)
|
||||
return t.child1.position.y < t.child2.position.y ? getTileBis(t.child1) : getTileBis(t.child2);
|
||||
else if (t.child1 !== null)
|
||||
return getTileBis(t.child1);
|
||||
else if (t.child2 !== null)
|
||||
return getTileBis(t.child2);
|
||||
else
|
||||
return t;
|
||||
case Direction.South:
|
||||
if (t.child2 !== null && t.child1 !== null)
|
||||
return t.child1.position.y > t.child2.position.y ? getTileBis(t.child1) : getTileBis(t.child2);
|
||||
else if (t.child1 !== null)
|
||||
return getTileBis(t.child1);
|
||||
else if (t.child2 !== null)
|
||||
return getTileBis(t.child2);
|
||||
else
|
||||
return t;
|
||||
default:
|
||||
return t;
|
||||
}
|
||||
};
|
||||
return getTileBis(this.root);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user