Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2013 Fabian Homborg <FHomborg@gmail.com>
based on spirallayout.js by Matthias Gottschlag
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
// FIXME: Neighbour stuff is bogus (just copied from spirallayout)
// FIXME: Crash on moving client to another desktop
/**
* Class which arranges the windows in a spiral with the largest window filling
* the left half of the screen.
*/
function HalfLayout(screenRectangle) {
print("Creating HalfLayout");
Layout.call(this, screenRectangle);
// TODO
}
HalfLayout.name = "Half";
// TODO: Add an image for the layout switcher
HalfLayout.image = null;
HalfLayout.prototype = new Layout();
HalfLayout.prototype.constructor = HalfLayout;
HalfLayout.prototype.resetTileSizes = function() {
// Simply erase all tiles and recreate them to recompute the initial sizes
var tileCount = this.tiles.length;
this.tiles.length = 0;
for (var i = 0; i < tileCount; i++) {
this.addTile();
}
}
HalfLayout.prototype.addTile = function() {
if (this.tiles.length == 0) {
// The first tile fills the whole screen
var rect = Qt.rect(this.screenRectangle.x,
this.screenRectangle.y,
this.screenRectangle.width,
this.screenRectangle.height);
this._createTile(rect);
return;
}
if (this.tiles.length == 1) {
// The second tile fills the right half of the screen
// Also, javascript sucks
var firstRect = Qt.rect(this.tiles[0].rectangle.x,
this.tiles[0].rectangle.y,
this.tiles[0].rectangle.width,
this.tiles[0].rectangle.height);
firstRect.width = Math.floor(this.screenRectangle.width / 2);
this.tiles[0].rectangle = firstRect;
var newRect = Qt.rect(firstRect.x + firstRect.width,
firstRect.y,
firstRect.width,
firstRect.height)
this._createTile(newRect);
return;
}
if (this.tiles.length > 1) {
// Every other tile separates the right half
var lastRect = this.tiles[0].rectangle;
var newRect = Qt.rect(lastRect.x + lastRect.width,
lastRect.y,
Math.floor(lastRect.height / (this.tiles.length)));
newRect.y = newRect.y + newRect.height * (this.tiles.length - 1);
// FIXME: Try to keep ratio
for (i = 1; i < this.tiles.length; i++) {
var rect = this.tiles[i].rectangle;
rect.x = newRect.x;
var offset = newRect.height * (i - 1);
rect.y = lastRect.y + offset;
rect.width = newRect.width;
rect.height = newRect.height;
this.tiles[i].rectangle = rect;
}
// Adjust lowest tile's height for rounding errors
//newRect.y = newRect.y + newRect.width * (this.tiles.length - 1);
newRect.height = (this.screenRectangle.y + this.screenRectangle.height) - newRect.y;
this._createTile(newRect);
}
}
HalfLayout.prototype.removeTile = function(tileIndex) {
//FIXME: There is a crash here
// Remove the array entry
var oldrect = this.tiles[tileIndex].rectangle;
this.tiles.splice(tileIndex, 1);
// Update the other tiles
if (this.tiles.length == 1) {
this.tiles[0].rectangle = this.screenRectangle;
this.tiles[0].hasDirectNeighbour[Direction.Left] = false;
this.tiles[0].hasDirectNeighbour[Direction.Right] = false;
this.tiles[0].hasDirectNeighbour[Direction.Up] = false;
this.tiles[0].hasDirectNeighbour[Direction.Down] = false;
}
if (this.tiles.length > 1) {
if (tileIndex == 0) {
this.tiles[0].rectangle = oldrect;
this.tiles[0].hasDirectNeighbour[Direction.Left] = false;
this.tiles[0].hasDirectNeighbour[Direction.Right] = true;
this.tiles[0].hasDirectNeighbour[Direction.Up] = false;
this.tiles[0].hasDirectNeighbour[Direction.Down] = false;
this.tiles[0].neighbours[Direction.Right] = 1;
var tileCount = this.tiles.length - 1;
var lastRect = this.tiles[0].rectangle;
var newRect = Qt.rect(lastRect.width,
lastRect.y,
lastRect.width,
Math.floor(lastRect.height / tileCount));
var lowest = 1;
for (i = 1; i < this.tiles.length; i++) {
var rect = this.tiles[i].rectangle;
rect.y = newRect.y + newRect.height * (i - 1);
rect.height = newRect.height;
this.tiles[i].rectangle = rect;
if (this.tiles[lowest].rectangle.y < this.tiles[i].rectangle.y) {
lowest = i;
}
this.tiles[i].hasDirectNeighbour[Direction.Left] = true;
this.tiles[i].hasDirectNeighbour[Direction.Right] = false;
if (i == 1) {
this.tiles[i].hasDirectNeighbour[Direction.Up] = false;
} else {
this.tiles[i].hasDirectNeighbour[Direction.Up] = true;
}
if (i == this.tiles.length - 1) {
this.tiles[i].hasDirectNeighbour[Direction.Down] = false;
} else {
this.tiles[i].hasDirectNeighbour[Direction.Down] = true;
}
this.tiles[i].neighbours[Direction.Left] = 0;
this.tiles[i].neighbours[Direction.Up] = i - 1;
this.tiles[i].neighbours[Direction.Down] = i + 1;
}
// Adjust lowest tile's height for rounding errors
this.tiles[lowest].rectangle.height = (this.screenRectangle.y + this.screenRectangle.height) - this.tiles[lowest].rectangle.y;
/*
this.tiles[1].hasDirectNeighbour[Direction.Up] = false;
this.tiles[this.tiles.length - 1].hasDirectNeighbour[Direction.Down] = false;
*/
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
}
}
HalfLayout.prototype.resizeTile = function(tileIndex, rectangle) {
// TODO: Mark tile as resized so it can keep its size on tileadd/remove
if (tileIndex < 0 || tileIndex > this.tiles.length) {
print("Tileindex invalid", tileIndex, "/", this.tiles.length);
return;
}
var tile = this.tiles[tileIndex];
if (tile == null) {
print("No tile");
return;
}
if (rectangle == null){
print("No rect");
return;
}
// Cap rectangle at screenedges
if (rectangle.x < this.screenRectangle.x) {
rectangle.x = this.screenRectangle.x;
}
if (rectangle.y < this.screenRectangle.y) {
rectangle.y = this.screenRectangle.y;
}
if (rectangle.y + rectangle.height > this.screenRectangle.y + this.screenRectangle.height) {
rectangle.height = this.screenRectangle.y + this.screenRectangle.height - rectangle.y;
}
if (rectangle.x + rectangle.width > this.screenRectangle.x + this.screenRectangle.width) {
rectangle.width = this.screenRectangle.x + this.screenRectangle.width - rectangle.x;
}
if (tileIndex == 0) {
// Simply adjust width on everything else, no height adjustment
rectangle.x = tile.rectangle.x;
rectangle.y = tile.rectangle.y;
rectangle.height = tile.rectangle.height;
tile.rectangle = rectangle;
for (i = 1; i < this.tiles.length; i++) {
this.tiles[i].rectangle.width = this.screenRectangle.width - rectangle.width;
this.tiles[i].rectangle.x = this.screenRectangle.x + rectangle.width;
}
} else {
this.tiles[0].rectangle.width = this.screenRectangle.width - rectangle.width;
var belows = new Array();
var aboves = new Array();
for (i = 1; i < this.tiles.length; i++) {
if (this.tiles[i].rectangle.y < tile.rectangle.y){
aboves.push(i);
}
if (this.tiles[i].rectangle.y > tile.rectangle.y){
belows.push(i);
}
}
// Dividing by zero sucks
if (aboves.length == 0) {
var newHeightAbove = 0;
} else {
var newHeightAbove = Math.floor((rectangle.y - this.screenRectangle.y) / aboves.length);
}
if (belows.length == 0) {
var newHeightBelow = 0;
} else {
var newHeightBelow = Math.floor((this.screenRectangle.height - rectangle.height) / belows.length);
}
if (belows.length > 0) {
for (i = 0; i < belows.length; i++) {
this.tiles[belows[i]].rectangle.width = rectangle.width;
this.tiles[belows[i]].rectangle.x = rectangle.x;
this.tiles[belows[i]].rectangle.y = rectangle.y + rectangle.height + newHeightBelow * i;
this.tiles[belows[i]].rectangle.height = newHeightBelow;
}
}
if (aboves.length > 0) {
for (i = 0; i < aboves.length; i++) {
this.tiles[aboves[i]].rectangle.width = rectangle.width;
this.tiles[aboves[i]].rectangle.x = rectangle.x;
this.tiles[aboves[i]].rectangle.y = this.screenRectangle.y + newHeightAbove * i;
this.tiles[aboves[i]].rectangle.height = newHeightAbove;
}
}
tile.rectangle = rectangle;
// No reason to set height when we have the full screen
if (this.tiles.length == 2) {
tile.rectangle.height = this.screenRectangle.height;
tile.rectangle.y = this.screenRectangle.y;
}
}
}
HalfLayout.prototype._createTile = function(rect) {
// Update the last tile in the list
var lastTile = this.tiles[this.tiles.length - 1];
lastTile.neighbours[Direction.Down] = this.tiles.length;
lastTile.hasDirectNeighbour[Direction.Down] = true;
}
if (this.tiles.length == 1) {
var lastTile2 = this.tiles[0];
lastTile2.neighbours[Direction.Right] = 1;
lastTile2.hasDirectNeighbour[Direction.Right] = true;
}
// Create a new tile and add it to the list
var tile = {};
tile.rectangle = rect;
tile.neighbours = [];
tile.hasDirectNeighbour = [];
tile.neighbours[Direction.Left] = 0;
tile.hasDirectNeighbour[Direction.Left] = (this.tiles.length > 0);
tile.neighbours[Direction.Right] = - 1;
tile.hasDirectNeighbour[Direction.Right] = false;
if (this.tiles.length > 1) {
tile.hasDirectNeighbour[Direction.Up] = true;
tile.neighbours[Direction.Up] = this.tiles.length - 1;
} else {
tile.hasDirectNeighbour[Direction.Up] = false;
tile.neighbours[Direction.Up] = - 1;
}
tile.neighbours[Direction.Down] = - 1;
tile.hasDirectNeighbour[Direction.Down] = false;
tile.index = this.tiles.length;
this.tiles.push(tile);
}