workspace: Prevent overlapping windows when scaling to fit the screen

The previous code was applying the per row scaling factor of the current
row to the cumulative sum of all previous rows when calculating the y
position of a row. This resulted in the row being shifted up so it would
overlap other windows when the previous rows were not using the same
scaling as the current one.

Also the previous code was not considering that the spacing does not get
scaled when calculating the scaling factor. This is wrong as well and
could result in the overview overlapping the workspace switcher in
situations with lots of windows open.

This fix gives each row the appropriate height according to its scaling
factor and then ensures that the grid remains vertically centered after
losing some of its height.

https://bugzilla.gnome.org/show_bug.cgi?id=744883
This commit is contained in:
Sebastian Keller 2015-03-03 20:07:22 +01:00 committed by Florian Müllner
parent 55df98298a
commit b4bfe9a0c6

View File

@ -912,14 +912,18 @@ const LayoutStrategy = new Lang.Class({
let slots = [];
// Do this in three parts.
let height = 0;
let heightWithoutSpacing = 0;
for (let i = 0; i < rows.length; i++) {
let row = rows[i];
height += row.height + this._rowSpacing;
heightWithoutSpacing += row.height;
}
height -= this._rowSpacing;
let verticalSpacing = (rows.length - 1) * this._rowSpacing;
let additionalVerticalScale = Math.min(1, (area.height - verticalSpacing) / heightWithoutSpacing);
// keep track how much smaller the grid becomes due to scaling
// so it can be centered again
let compensation = 0
let y = 0;
for (let i = 0; i < rows.length; i++) {
@ -927,13 +931,27 @@ const LayoutStrategy = new Lang.Class({
// If this window layout row doesn't fit in the actual
// geometry, then apply an additional scale to it.
row.additionalScale = Math.min(1, area.width / row.width, area.height / height);
let horizontalSpacing = (row.windows.length - 1) * this._columnSpacing;
let widthWithoutSpacing = row.width - horizontalSpacing;
let additionalHorizontalScale = Math.min(1, (area.width - horizontalSpacing) / widthWithoutSpacing);
row.x = area.x + (Math.max(area.width - row.width, 0) / 2) * row.additionalScale;
row.y = area.y + (y + Math.max(area.height - height, 0) / 2) * row.additionalScale;
y += row.height + this._rowSpacing;
if (additionalHorizontalScale < additionalVerticalScale) {
row.additionalScale = additionalHorizontalScale;
// Only consider the scaling in addition to the vertical scaling for centering.
compensation += (additionalVerticalScale - additionalHorizontalScale) * row.height;
} else {
row.additionalScale = additionalVerticalScale;
// No compensation when scaling vertically since centering based on a too large
// height would undo what vertical scaling is trying to achieve.
}
row.x = area.x + (Math.max(area.width - (widthWithoutSpacing * row.additionalScale + horizontalSpacing), 0) / 2)
row.y = area.y + (Math.max(area.height - (heightWithoutSpacing + verticalSpacing), 0) / 2) + y;
y += row.height * row.additionalScale + this._rowSpacing;
}
compensation = compensation / 2;
for (let i = 0; i < rows.length; i++) {
let row = rows[i];
let x = row.x;
@ -948,7 +966,7 @@ const LayoutStrategy = new Lang.Class({
let cloneWidth = window.width * s;
let cloneX = x + (cellWidth - cloneWidth) / 2;
let cloneY = row.y + row.height - cellHeight;
let cloneY = row.y + row.height * row.additionalScale - cellHeight + compensation;
slots.push([cloneX, cloneY, s, window]);
x += cellWidth + this._columnSpacing;