workspace: Lay out windows based on the real allocation
Instead of doing an entire recalculation of window positions when sliding the thumbnails box, simply recalculate the position and scale with basic aspect ratio math. This also ensures that windows won't miraculously swap positions, even if we reposition windows while the thumbnails box is expanded. https://bugzilla.gnome.org/show_bug.cgi?id=694469
This commit is contained in:
parent
bde8cc3285
commit
c37259b01d
@ -768,20 +768,27 @@ const LayoutStrategy = new Lang.Class({
|
||||
let slots = [];
|
||||
|
||||
// Do this in three parts.
|
||||
let width = 0;
|
||||
let height = 0;
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
let row = rows[i];
|
||||
width = Math.max(width, row.width);
|
||||
height += row.height + this._rowSpacing;
|
||||
}
|
||||
|
||||
height -= this._rowSpacing;
|
||||
|
||||
// If the window layout doesn't fit in the actual
|
||||
// geometry, then apply this additional scale to
|
||||
// tne entire layout.
|
||||
let additionalScale = Math.min(1, area.width / width, area.height / height);
|
||||
|
||||
let y = 0;
|
||||
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
let row = rows[i];
|
||||
row.x = area.x + (area.width - row.width) / 2;
|
||||
row.y = area.y + y + (area.height - height) / 2;
|
||||
row.x = area.x + (Math.max(area.width - row.width, 0) / 2) * additionalScale;
|
||||
row.y = area.y + (y + Math.max(area.height - height, 0) / 2) * additionalScale;
|
||||
y += row.height + this._rowSpacing;
|
||||
|
||||
row.windows.sort(Lang.bind(this, function(a, b) {
|
||||
@ -795,7 +802,7 @@ const LayoutStrategy = new Lang.Class({
|
||||
for (let j = 0; j < row.windows.length; j++) {
|
||||
let window = row.windows[j];
|
||||
|
||||
let s = scale * this._computeWindowScale(window);
|
||||
let s = scale * this._computeWindowScale(window) * additionalScale;
|
||||
let cellWidth = window.actor.width * s;
|
||||
let cellHeight = window.actor.height * s;
|
||||
|
||||
@ -915,6 +922,14 @@ const Workspace = new Lang.Class({
|
||||
// this, like if the workspace switcher is slid out.
|
||||
this._fullGeometry = null;
|
||||
|
||||
// The actual geometry is the geometry we need to arrange windows
|
||||
// in. If this is a smaller area than the full geometry, we'll
|
||||
// do some simple aspect ratio like math to fit the layout calculated
|
||||
// for the full geometry into this area.
|
||||
this._actualGeometry = null;
|
||||
|
||||
this._currentLayout = null;
|
||||
|
||||
this.monitorIndex = monitorIndex;
|
||||
this._monitor = Main.layoutManager.monitors[this.monitorIndex];
|
||||
this._windowOverlaysGroup = new Clutter.Actor();
|
||||
@ -967,14 +982,19 @@ const Workspace = new Lang.Class({
|
||||
|
||||
setFullGeometry: function(geom) {
|
||||
this._fullGeometry = geom;
|
||||
this._recalculateWindowPositions(WindowPositionFlags.NONE);
|
||||
},
|
||||
|
||||
setActualGeometry: function(geom) {
|
||||
this._actualGeometry = geom;
|
||||
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
|
||||
this._dropRect.set_position(geom.x, geom.y);
|
||||
this._dropRect.set_size(geom.width, geom.height);
|
||||
if (this._currentLayout != null)
|
||||
this._updateWindowPositions(WindowPositionFlags.NONE);
|
||||
return false;
|
||||
}));
|
||||
|
||||
this._recalculateWindowPositions(WindowPositionFlags.NONE);
|
||||
},
|
||||
|
||||
_lookupIndex: function (metaWindow) {
|
||||
@ -1048,7 +1068,7 @@ const Workspace = new Lang.Class({
|
||||
let strategy = layout.strategy;
|
||||
|
||||
let [, , padding] = this._getSpacingAndPadding();
|
||||
let area = padArea(this._fullGeometry, padding);
|
||||
let area = padArea(this._actualGeometry, padding);
|
||||
let slots = strategy.computeWindowSlots(layout, area);
|
||||
|
||||
let currentWorkspace = global.screen.get_active_workspace();
|
||||
|
@ -56,6 +56,7 @@ const WorkspacesView = new Lang.Class({
|
||||
}));
|
||||
|
||||
this._fullGeometry = null;
|
||||
this._actualGeometry = null;
|
||||
|
||||
this._spacing = 0;
|
||||
this._animating = false; // tweening
|
||||
@ -135,6 +136,7 @@ const WorkspacesView = new Lang.Class({
|
||||
|
||||
let ws = new Workspace.Workspace(null, i);
|
||||
ws.setFullGeometry(monitors[i]);
|
||||
ws.setActualGeometry(monitors[i]);
|
||||
global.overlay_group.add_actor(ws.actor);
|
||||
this._extraWorkspaces.push(ws);
|
||||
}
|
||||
@ -156,6 +158,16 @@ const WorkspacesView = new Lang.Class({
|
||||
this._workspaces[i].setFullGeometry(geom);
|
||||
},
|
||||
|
||||
setActualGeometry: function(geom) {
|
||||
if (rectEqual(this._actualGeometry, geom))
|
||||
return;
|
||||
|
||||
this._actualGeometry = geom;
|
||||
|
||||
for (let i = 0; i < this._workspaces.length; i++)
|
||||
this._workspaces[i].setActualGeometry(geom);
|
||||
},
|
||||
|
||||
_lookupWorkspaceForMetaWindow: function (metaWindow) {
|
||||
for (let i = 0; i < this._workspaces.length; i++) {
|
||||
if (this._workspaces[i].containsMetaWindow(metaWindow))
|
||||
@ -432,6 +444,7 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
|
||||
_init: function() {
|
||||
this.actor = new St.Widget({ clip_to_allocation: true });
|
||||
this.actor.connect('notify::allocation', Lang.bind(this, this._updateWorkspacesActualGeometry));
|
||||
this.actor.connect('parent-set', Lang.bind(this, this._parentSet));
|
||||
|
||||
let clickAction = new Clutter.ClickAction()
|
||||
@ -576,6 +589,7 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
}
|
||||
|
||||
this._updateWorkspacesFullGeometry();
|
||||
this._updateWorkspacesActualGeometry();
|
||||
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
global.overlay_group.add_actor(this._workspacesViews[i].actor);
|
||||
@ -660,6 +674,28 @@ const WorkspacesDisplay = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
_updateWorkspacesActualGeometry: function() {
|
||||
if (!this._workspacesViews.length)
|
||||
return;
|
||||
|
||||
let [x, y] = this.actor.get_transformed_position();
|
||||
let width = this.actor.allocation.x2 - this.actor.allocation.x1;
|
||||
let height = this.actor.allocation.y2 - this.actor.allocation.y1;
|
||||
let geometry = { x: x, y: y, width: width, height: height };
|
||||
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
let m = 0;
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
if (i == this._primaryIndex) {
|
||||
this._workspacesViews[m].setActualGeometry(geometry);
|
||||
m++;
|
||||
} else if (!this._workspacesOnlyOnPrimary) {
|
||||
this._workspacesViews[m].setActualGeometry(monitors[i]);
|
||||
m++;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_onRestacked: function(overview, stackIndices) {
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].syncStacking(stackIndices);
|
||||
|
Loading…
Reference in New Issue
Block a user