2009-02-02 23:02:16 +00:00
|
|
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
2008-12-02 16:15:00 +00:00
|
|
|
|
|
|
|
const Clutter = imports.gi.Clutter;
|
2008-12-22 22:06:47 +00:00
|
|
|
const Lang = imports.lang;
|
2009-02-04 14:50:50 +00:00
|
|
|
const Mainloop = imports.mainloop;
|
2009-02-02 23:02:16 +00:00
|
|
|
const Meta = imports.gi.Meta;
|
2009-01-23 19:21:20 +00:00
|
|
|
const Pango = imports.gi.Pango;
|
2009-02-02 23:02:16 +00:00
|
|
|
const Shell = imports.gi.Shell;
|
2009-11-12 00:26:52 +00:00
|
|
|
const St = imports.gi.St;
|
2009-01-23 19:21:20 +00:00
|
|
|
const Signals = imports.signals;
|
2008-12-02 16:15:00 +00:00
|
|
|
|
2009-02-10 16:15:59 +00:00
|
|
|
const DND = imports.ui.dnd;
|
2009-09-22 19:24:14 +00:00
|
|
|
const Lightbox = imports.ui.lightbox;
|
2008-12-02 16:15:00 +00:00
|
|
|
const Main = imports.ui.main;
|
2009-08-11 11:46:10 +00:00
|
|
|
const Overview = imports.ui.overview;
|
2008-12-02 16:15:00 +00:00
|
|
|
const Panel = imports.ui.panel;
|
2009-02-10 16:12:58 +00:00
|
|
|
const Tweener = imports.ui.tweener;
|
2008-12-02 16:15:00 +00:00
|
|
|
|
2009-01-19 23:06:59 +00:00
|
|
|
const FOCUS_ANIMATION_TIME = 0.15;
|
2008-12-02 16:15:00 +00:00
|
|
|
|
2010-03-09 22:31:06 +00:00
|
|
|
const WINDOW_DND_SIZE = 256;
|
|
|
|
|
2009-09-04 19:25:17 +00:00
|
|
|
const SCROLL_SCALE_AMOUNT = 100 / 5;
|
|
|
|
|
2010-06-10 15:22:23 +00:00
|
|
|
const LIGHTBOX_FADE_TIME = 0.1;
|
|
|
|
const CLOSE_BUTTON_FADE_TIME = 0.1;
|
2009-09-04 19:25:17 +00:00
|
|
|
|
2010-03-09 22:31:06 +00:00
|
|
|
const DRAGGING_WINDOW_OPACITY = 100;
|
|
|
|
|
2008-12-02 16:15:00 +00:00
|
|
|
// Define a layout scheme for small window counts. For larger
|
|
|
|
// counts we fall back to an algorithm. We need more schemes here
|
|
|
|
// unless we have a really good algorithm.
|
|
|
|
|
|
|
|
// Each triplet is [xCenter, yCenter, scale] where the scale
|
2008-12-04 15:20:37 +00:00
|
|
|
// is relative to the width of the workspace.
|
2008-12-02 16:15:00 +00:00
|
|
|
const POSITIONS = {
|
2009-08-08 20:10:40 +00:00
|
|
|
1: [[0.5, 0.5, 0.95]],
|
|
|
|
2: [[0.25, 0.5, 0.48], [0.75, 0.5, 0.48]],
|
|
|
|
3: [[0.25, 0.25, 0.48], [0.75, 0.25, 0.48], [0.5, 0.75, 0.48]],
|
|
|
|
4: [[0.25, 0.25, 0.47], [0.75, 0.25, 0.47], [0.75, 0.75, 0.47], [0.25, 0.75, 0.47]],
|
|
|
|
5: [[0.165, 0.25, 0.32], [0.495, 0.25, 0.32], [0.825, 0.25, 0.32], [0.25, 0.75, 0.32], [0.75, 0.75, 0.32]]
|
2008-12-02 16:15:00 +00:00
|
|
|
};
|
2009-09-18 19:08:56 +00:00
|
|
|
// Used in _orderWindowsPermutations, 5! = 120 which is probably the highest we can go
|
|
|
|
const POSITIONING_PERMUTATIONS_MAX = 5;
|
2009-09-04 19:25:17 +00:00
|
|
|
|
|
|
|
function _interpolate(start, end, step) {
|
|
|
|
return start + (end - start) * step;
|
|
|
|
}
|
|
|
|
|
|
|
|
function _clamp(value, min, max) {
|
|
|
|
return Math.max(min, Math.min(max, value));
|
|
|
|
}
|
|
|
|
|
2008-12-04 15:16:16 +00:00
|
|
|
|
2009-09-04 19:25:17 +00:00
|
|
|
function ScaledPoint(x, y, scaleX, scaleY) {
|
|
|
|
[this.x, this.y, this.scaleX, this.scaleY] = arguments;
|
|
|
|
}
|
|
|
|
|
|
|
|
ScaledPoint.prototype = {
|
|
|
|
getPosition : function() {
|
|
|
|
return [this.x, this.y];
|
|
|
|
},
|
|
|
|
|
|
|
|
getScale : function() {
|
|
|
|
return [this.scaleX, this.scaleY];
|
|
|
|
},
|
|
|
|
|
|
|
|
setPosition : function(x, y) {
|
|
|
|
[this.x, this.y] = arguments;
|
|
|
|
},
|
|
|
|
|
|
|
|
setScale : function(scaleX, scaleY) {
|
|
|
|
[this.scaleX, this.scaleY] = arguments;
|
|
|
|
},
|
|
|
|
|
|
|
|
interpPosition : function(other, step) {
|
|
|
|
return [_interpolate(this.x, other.x, step),
|
|
|
|
_interpolate(this.y, other.y, step)];
|
|
|
|
},
|
|
|
|
|
|
|
|
interpScale : function(other, step) {
|
|
|
|
return [_interpolate(this.scaleX, other.scaleX, step),
|
|
|
|
_interpolate(this.scaleY, other.scaleY, step)];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2009-01-29 21:21:50 +00:00
|
|
|
function WindowClone(realWindow) {
|
|
|
|
this._init(realWindow);
|
|
|
|
}
|
|
|
|
|
|
|
|
WindowClone.prototype = {
|
|
|
|
_init : function(realWindow) {
|
2009-02-23 19:42:00 +00:00
|
|
|
this.actor = new Clutter.Clone({ source: realWindow.get_texture(),
|
|
|
|
reactive: true,
|
|
|
|
x: realWindow.x,
|
|
|
|
y: realWindow.y });
|
2009-02-10 16:12:58 +00:00
|
|
|
this.actor._delegate = this;
|
2009-01-29 21:21:50 +00:00
|
|
|
this.realWindow = realWindow;
|
2009-02-04 14:50:50 +00:00
|
|
|
this.metaWindow = realWindow.meta_window;
|
2009-09-10 01:14:31 +00:00
|
|
|
this.metaWindow._delegate = this;
|
2009-01-29 21:21:50 +00:00
|
|
|
this.origX = realWindow.x;
|
|
|
|
this.origY = realWindow.y;
|
|
|
|
|
2009-09-28 23:48:03 +00:00
|
|
|
this._stackAbove = null;
|
|
|
|
|
2011-01-30 22:03:12 +00:00
|
|
|
this._sizeChangedId = this.realWindow.connect('size-changed', Lang.bind(this, function() {
|
|
|
|
this.emit('size-changed');
|
|
|
|
}));
|
2011-02-03 18:25:59 +00:00
|
|
|
this._realWindowDestroyId = this.realWindow.connect('destroy',
|
|
|
|
Lang.bind(this, this._disconnectRealWindowSignals));
|
2011-01-30 22:03:12 +00:00
|
|
|
|
2009-01-29 21:21:50 +00:00
|
|
|
this.actor.connect('button-release-event',
|
|
|
|
Lang.bind(this, this._onButtonRelease));
|
2009-02-10 16:15:59 +00:00
|
|
|
|
2009-09-04 19:25:17 +00:00
|
|
|
this.actor.connect('scroll-event',
|
|
|
|
Lang.bind(this, this._onScroll));
|
|
|
|
|
2010-02-07 14:25:16 +00:00
|
|
|
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
2009-01-29 21:21:50 +00:00
|
|
|
this.actor.connect('leave-event',
|
|
|
|
Lang.bind(this, this._onLeave));
|
2009-02-10 16:15:59 +00:00
|
|
|
|
2010-03-19 20:46:08 +00:00
|
|
|
this._draggable = DND.makeDraggable(this.actor,
|
2010-05-20 14:44:45 +00:00
|
|
|
{ restoreOnSuccess: true,
|
|
|
|
dragActorMaxSize: WINDOW_DND_SIZE,
|
2010-03-19 20:46:08 +00:00
|
|
|
dragActorOpacity: DRAGGING_WINDOW_OPACITY });
|
2009-02-10 16:15:59 +00:00
|
|
|
this._draggable.connect('drag-begin', Lang.bind(this, this._onDragBegin));
|
2011-03-08 13:44:47 +00:00
|
|
|
this._draggable.connect('drag-cancelled', Lang.bind(this, this._onDragCancelled));
|
2009-02-10 16:15:59 +00:00
|
|
|
this._draggable.connect('drag-end', Lang.bind(this, this._onDragEnd));
|
2010-03-19 20:46:08 +00:00
|
|
|
this.inDrag = false;
|
2009-09-28 23:48:03 +00:00
|
|
|
|
2010-03-21 18:33:52 +00:00
|
|
|
this._windowIsZooming = false;
|
2009-09-28 23:48:03 +00:00
|
|
|
this._zooming = false;
|
2010-02-15 22:11:09 +00:00
|
|
|
this._selected = false;
|
2009-01-29 21:21:50 +00:00
|
|
|
},
|
|
|
|
|
2009-09-28 23:48:03 +00:00
|
|
|
setStackAbove: function (actor) {
|
|
|
|
this._stackAbove = actor;
|
2010-03-19 20:46:08 +00:00
|
|
|
if (this.inDrag || this._zooming)
|
2009-09-28 23:48:03 +00:00
|
|
|
// We'll fix up the stack after the drag/zooming
|
|
|
|
return;
|
2010-07-15 14:21:32 +00:00
|
|
|
if (this._stackAbove == null)
|
|
|
|
this.actor.lower_bottom();
|
|
|
|
else
|
|
|
|
this.actor.raise(this._stackAbove);
|
2009-09-28 23:48:03 +00:00
|
|
|
},
|
|
|
|
|
2009-01-29 21:21:50 +00:00
|
|
|
destroy: function () {
|
|
|
|
this.actor.destroy();
|
|
|
|
},
|
2009-02-10 16:15:59 +00:00
|
|
|
|
2010-02-15 22:11:09 +00:00
|
|
|
zoomFromOverview: function() {
|
|
|
|
if (this._zooming) {
|
|
|
|
// If the user clicked on the zoomed window, or we are
|
|
|
|
// returning there anyways, then we can zoom right to the
|
|
|
|
// window, but if we are going to some other window, then
|
|
|
|
// we need to cancel the zoom before animating, or it
|
|
|
|
// will look funny.
|
|
|
|
|
|
|
|
if (!this._selected &&
|
|
|
|
this.metaWindow != global.screen.get_display().focus_window)
|
|
|
|
this._zoomEnd();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2011-02-03 18:25:59 +00:00
|
|
|
_disconnectRealWindowSignals: function() {
|
|
|
|
if (this._sizeChangedId > 0)
|
|
|
|
this.realWindow.disconnect(this._sizeChangedId);
|
2011-01-30 22:03:12 +00:00
|
|
|
this._sizeChangedId = 0;
|
|
|
|
|
2011-02-03 18:25:59 +00:00
|
|
|
if (this._realWindowDestroyId > 0)
|
|
|
|
this.realWindow.disconnect(this._realWindowDestroyId);
|
|
|
|
this._realWindowDestroyId = 0;
|
|
|
|
},
|
|
|
|
|
|
|
|
_onDestroy: function() {
|
|
|
|
this._disconnectRealWindowSignals();
|
|
|
|
|
2010-03-17 22:23:32 +00:00
|
|
|
this.metaWindow._delegate = null;
|
|
|
|
this.actor._delegate = null;
|
2010-02-07 14:25:16 +00:00
|
|
|
if (this._zoomLightbox)
|
|
|
|
this._zoomLightbox.destroy();
|
2010-03-17 22:23:32 +00:00
|
|
|
|
2010-03-19 20:46:08 +00:00
|
|
|
if (this.inDrag) {
|
2010-03-18 20:39:11 +00:00
|
|
|
this.emit('drag-end');
|
2010-03-19 20:46:08 +00:00
|
|
|
this.inDrag = false;
|
2010-03-18 20:39:11 +00:00
|
|
|
}
|
|
|
|
|
2010-03-17 22:23:32 +00:00
|
|
|
this.disconnectAll();
|
2010-02-07 14:25:16 +00:00
|
|
|
},
|
|
|
|
|
2009-01-29 21:21:50 +00:00
|
|
|
_onLeave: function (actor, event) {
|
2009-09-04 19:25:17 +00:00
|
|
|
if (this._zoomStep)
|
|
|
|
this._zoomEnd();
|
|
|
|
},
|
2009-01-29 21:21:50 +00:00
|
|
|
|
2009-09-04 19:25:17 +00:00
|
|
|
_onScroll : function (actor, event) {
|
|
|
|
let direction = event.get_scroll_direction();
|
|
|
|
if (direction == Clutter.ScrollDirection.UP) {
|
|
|
|
if (this._zoomStep == undefined)
|
|
|
|
this._zoomStart();
|
|
|
|
if (this._zoomStep < 100) {
|
|
|
|
this._zoomStep += SCROLL_SCALE_AMOUNT;
|
|
|
|
this._zoomUpdate();
|
|
|
|
}
|
|
|
|
} else if (direction == Clutter.ScrollDirection.DOWN) {
|
|
|
|
if (this._zoomStep > 0) {
|
|
|
|
this._zoomStep -= SCROLL_SCALE_AMOUNT;
|
|
|
|
this._zoomStep = Math.max(0, this._zoomStep);
|
|
|
|
this._zoomUpdate();
|
|
|
|
}
|
|
|
|
if (this._zoomStep <= 0.0)
|
|
|
|
this._zoomEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
_zoomUpdate : function () {
|
|
|
|
[this.actor.x, this.actor.y] = this._zoomGlobalOrig.interpPosition(this._zoomTarget, this._zoomStep / 100);
|
|
|
|
[this.actor.scale_x, this.actor.scale_y] = this._zoomGlobalOrig.interpScale(this._zoomTarget, this._zoomStep / 100);
|
|
|
|
|
|
|
|
let [width, height] = this.actor.get_transformed_size();
|
|
|
|
|
2011-03-09 14:59:58 +00:00
|
|
|
let monitorIndex = this.metaWindow.get_monitor();
|
|
|
|
let availArea = global.get_monitors()[monitorIndex];
|
|
|
|
if (monitorIndex == global.get_primary_monitor_index()) {
|
|
|
|
availArea.y += Main.panel.actor.height;
|
|
|
|
availArea.height -= Main.panel.actor.height;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.actor.x = _clamp(this.actor.x, availArea.x, availArea.x + availArea.width - width);
|
|
|
|
this.actor.y = _clamp(this.actor.y, availArea.y, availArea.y + availArea.height - height);
|
2009-09-04 19:25:17 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_zoomStart : function () {
|
2009-09-28 23:48:03 +00:00
|
|
|
this._zooming = true;
|
2009-11-12 00:26:52 +00:00
|
|
|
this.emit('zoom-start');
|
2009-09-28 23:48:03 +00:00
|
|
|
|
2010-03-17 14:36:57 +00:00
|
|
|
if (!this._zoomLightbox)
|
|
|
|
this._zoomLightbox = new Lightbox.Lightbox(global.stage,
|
|
|
|
{ fadeTime: LIGHTBOX_FADE_TIME });
|
|
|
|
this._zoomLightbox.show();
|
2009-09-04 19:25:17 +00:00
|
|
|
|
|
|
|
this._zoomLocalOrig = new ScaledPoint(this.actor.x, this.actor.y, this.actor.scale_x, this.actor.scale_y);
|
|
|
|
this._zoomGlobalOrig = new ScaledPoint();
|
|
|
|
let parent = this._origParent = this.actor.get_parent();
|
2009-09-25 22:48:34 +00:00
|
|
|
let [width, height] = this.actor.get_transformed_size();
|
2009-09-04 19:25:17 +00:00
|
|
|
this._zoomGlobalOrig.setPosition.apply(this._zoomGlobalOrig, this.actor.get_transformed_position());
|
|
|
|
this._zoomGlobalOrig.setScale(width / this.actor.width, height / this.actor.height);
|
|
|
|
|
|
|
|
this.actor.reparent(global.stage);
|
2009-09-22 19:24:14 +00:00
|
|
|
this._zoomLightbox.highlight(this.actor);
|
2009-09-04 19:25:17 +00:00
|
|
|
|
|
|
|
[this.actor.x, this.actor.y] = this._zoomGlobalOrig.getPosition();
|
|
|
|
[this.actor.scale_x, this.actor.scale_y] = this._zoomGlobalOrig.getScale();
|
|
|
|
|
|
|
|
this.actor.raise_top();
|
|
|
|
|
|
|
|
this._zoomTarget = new ScaledPoint(0, 0, 1.0, 1.0);
|
|
|
|
this._zoomTarget.setPosition(this.actor.x - (this.actor.width - width) / 2, this.actor.y - (this.actor.height - height) / 2);
|
|
|
|
this._zoomStep = 0;
|
|
|
|
|
|
|
|
this._zoomUpdate();
|
|
|
|
},
|
|
|
|
|
|
|
|
_zoomEnd : function () {
|
2009-09-28 23:48:03 +00:00
|
|
|
this._zooming = false;
|
2009-11-12 00:26:52 +00:00
|
|
|
this.emit('zoom-end');
|
2009-09-28 23:48:03 +00:00
|
|
|
|
2009-09-04 19:25:17 +00:00
|
|
|
this.actor.reparent(this._origParent);
|
2010-07-15 14:21:32 +00:00
|
|
|
if (this._stackAbove == null)
|
|
|
|
this.actor.lower_bottom();
|
2010-02-07 14:25:16 +00:00
|
|
|
// If the workspace has been destroyed while we were reparented to
|
|
|
|
// the stage, _stackAbove will be unparented and we can't raise our
|
|
|
|
// actor above it - as we are bound to be destroyed anyway in that
|
|
|
|
// case, we can skip that step
|
2010-07-15 14:21:32 +00:00
|
|
|
else if (this._stackAbove.get_parent())
|
2010-02-07 14:25:16 +00:00
|
|
|
this.actor.raise(this._stackAbove);
|
2009-09-04 19:25:17 +00:00
|
|
|
|
|
|
|
[this.actor.x, this.actor.y] = this._zoomLocalOrig.getPosition();
|
|
|
|
[this.actor.scale_x, this.actor.scale_y] = this._zoomLocalOrig.getScale();
|
|
|
|
|
2010-03-17 14:36:57 +00:00
|
|
|
this._zoomLightbox.hide();
|
2009-09-04 19:25:17 +00:00
|
|
|
|
|
|
|
this._zoomLocalPosition = undefined;
|
|
|
|
this._zoomLocalScale = undefined;
|
|
|
|
this._zoomGlobalPosition = undefined;
|
|
|
|
this._zoomGlobalScale = undefined;
|
|
|
|
this._zoomTargetPosition = undefined;
|
2009-09-22 19:24:14 +00:00
|
|
|
this._zoomStep = undefined;
|
2009-01-29 21:21:50 +00:00
|
|
|
},
|
|
|
|
|
2009-02-10 16:15:59 +00:00
|
|
|
_onButtonRelease : function (actor, event) {
|
2010-02-15 22:11:09 +00:00
|
|
|
this._selected = true;
|
2009-02-10 16:15:59 +00:00
|
|
|
this.emit('selected', event.get_time());
|
2009-01-29 21:21:50 +00:00
|
|
|
},
|
|
|
|
|
2009-02-10 16:15:59 +00:00
|
|
|
_onDragBegin : function (draggable, time) {
|
2011-05-11 21:43:25 +00:00
|
|
|
if (this._zooming)
|
|
|
|
this._zoomEnd();
|
|
|
|
|
2011-03-08 13:46:34 +00:00
|
|
|
[this.dragOrigX, this.dragOrigY] = this.actor.get_position();
|
|
|
|
this.dragOrigScale = this.actor.scale_x;
|
2010-03-19 20:46:08 +00:00
|
|
|
this.inDrag = true;
|
2009-07-23 21:36:41 +00:00
|
|
|
this.emit('drag-begin');
|
2009-01-29 21:21:50 +00:00
|
|
|
},
|
|
|
|
|
2011-03-08 13:44:47 +00:00
|
|
|
_onDragCancelled : function (draggable, time) {
|
|
|
|
this.emit('drag-cancelled');
|
|
|
|
},
|
|
|
|
|
2009-07-23 21:36:41 +00:00
|
|
|
_onDragEnd : function (draggable, time, snapback) {
|
2010-03-19 20:46:08 +00:00
|
|
|
this.inDrag = false;
|
2009-01-29 21:21:50 +00:00
|
|
|
|
2009-09-28 23:48:03 +00:00
|
|
|
// We may not have a parent if DnD completed successfully, in
|
|
|
|
// which case our clone will shortly be destroyed and replaced
|
|
|
|
// with a new one on the target workspace.
|
2010-07-15 14:21:32 +00:00
|
|
|
if (this.actor.get_parent() != null) {
|
|
|
|
if (this._stackAbove == null)
|
|
|
|
this.actor.lower_bottom();
|
|
|
|
else
|
|
|
|
this.actor.raise(this._stackAbove);
|
2010-01-06 03:53:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-07-15 14:21:32 +00:00
|
|
|
this.emit('drag-end');
|
2009-01-29 21:21:50 +00:00
|
|
|
}
|
|
|
|
};
|
2010-07-15 14:21:32 +00:00
|
|
|
Signals.addSignalMethods(WindowClone.prototype);
|
2009-01-29 21:21:50 +00:00
|
|
|
|
|
|
|
|
2009-11-12 00:26:52 +00:00
|
|
|
/**
|
|
|
|
* @windowClone: Corresponding window clone
|
|
|
|
* @parentActor: The actor which will be the parent of all overlay items
|
|
|
|
* such as app icon and window caption
|
|
|
|
*/
|
|
|
|
function WindowOverlay(windowClone, parentActor) {
|
|
|
|
this._init(windowClone, parentActor);
|
|
|
|
}
|
|
|
|
|
|
|
|
WindowOverlay.prototype = {
|
|
|
|
_init : function(windowClone, parentActor) {
|
|
|
|
let metaWindow = windowClone.metaWindow;
|
|
|
|
|
2009-11-20 00:39:00 +00:00
|
|
|
this._windowClone = windowClone;
|
2009-11-12 00:26:52 +00:00
|
|
|
this._parentActor = parentActor;
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
this._hidden = false;
|
2009-11-12 00:26:52 +00:00
|
|
|
|
2010-05-13 19:46:04 +00:00
|
|
|
let title = new St.Label({ style_class: 'window-caption',
|
2010-01-22 02:33:48 +00:00
|
|
|
text: metaWindow.title });
|
2009-11-12 00:26:52 +00:00
|
|
|
title.clutter_text.ellipsize = Pango.EllipsizeMode.END;
|
|
|
|
title._spacing = 0;
|
|
|
|
|
2010-02-07 02:06:50 +00:00
|
|
|
this._updateCaptionId = metaWindow.connect('notify::title',
|
|
|
|
Lang.bind(this, function(w) {
|
|
|
|
this.title.text = w.title;
|
|
|
|
}));
|
|
|
|
|
2010-05-13 19:46:04 +00:00
|
|
|
let button = new St.Button({ style_class: 'window-close' });
|
2009-11-12 00:26:52 +00:00
|
|
|
button._overlap = 0;
|
|
|
|
|
2010-02-18 04:15:10 +00:00
|
|
|
this._idleToggleCloseId = 0;
|
|
|
|
button.connect('clicked', Lang.bind(this, this._closeWindow));
|
|
|
|
|
2009-11-21 05:46:02 +00:00
|
|
|
windowClone.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
2009-11-12 00:26:52 +00:00
|
|
|
windowClone.actor.connect('enter-event',
|
|
|
|
Lang.bind(this, this._onEnter));
|
|
|
|
windowClone.actor.connect('leave-event',
|
|
|
|
Lang.bind(this, this._onLeave));
|
|
|
|
|
2009-11-21 05:46:02 +00:00
|
|
|
this._windowAddedId = 0;
|
2009-11-12 00:26:52 +00:00
|
|
|
windowClone.connect('zoom-start', Lang.bind(this, this.hide));
|
|
|
|
windowClone.connect('zoom-end', Lang.bind(this, this.show));
|
|
|
|
|
|
|
|
button.hide();
|
|
|
|
|
|
|
|
this.title = title;
|
|
|
|
this.closeButton = button;
|
|
|
|
|
|
|
|
parentActor.add_actor(this.title);
|
|
|
|
parentActor.add_actor(this.closeButton);
|
2010-02-18 04:15:28 +00:00
|
|
|
title.connect('style-changed',
|
|
|
|
Lang.bind(this, this._onStyleChanged));
|
|
|
|
button.connect('style-changed',
|
|
|
|
Lang.bind(this, this._onStyleChanged));
|
|
|
|
// force a style change if we are already on a stage - otherwise
|
|
|
|
// the signal will be emitted normally when we are added
|
|
|
|
if (parentActor.get_stage())
|
|
|
|
this._onStyleChanged();
|
2009-11-12 00:26:52 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
hide: function() {
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
this._hidden = true;
|
2009-11-12 00:26:52 +00:00
|
|
|
this.closeButton.hide();
|
|
|
|
this.title.hide();
|
|
|
|
},
|
|
|
|
|
|
|
|
show: function() {
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
this._hidden = false;
|
2009-11-12 00:26:52 +00:00
|
|
|
this.title.show();
|
|
|
|
},
|
|
|
|
|
|
|
|
fadeIn: function() {
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
this.show();
|
2009-11-12 00:26:52 +00:00
|
|
|
this.title.opacity = 0;
|
2010-01-22 02:33:48 +00:00
|
|
|
this._parentActor.raise_top();
|
2009-11-12 00:26:52 +00:00
|
|
|
Tweener.addTween(this.title,
|
|
|
|
{ opacity: 255,
|
2010-06-10 15:22:23 +00:00
|
|
|
time: CLOSE_BUTTON_FADE_TIME,
|
2010-05-13 19:46:04 +00:00
|
|
|
transition: 'easeOutQuad' });
|
2009-11-12 00:26:52 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
chromeWidth: function () {
|
|
|
|
return this.closeButton.width - this.closeButton._overlap;
|
|
|
|
},
|
|
|
|
|
2010-02-17 16:52:50 +00:00
|
|
|
chromeHeights: function () {
|
|
|
|
return [this.closeButton.height - this.closeButton._overlap,
|
|
|
|
this.title.height + this.title._spacing];
|
2009-11-12 00:26:52 +00:00
|
|
|
},
|
|
|
|
|
2009-11-22 03:51:28 +00:00
|
|
|
/**
|
|
|
|
* @cloneX: x position of windowClone
|
|
|
|
* @cloneY: y position of windowClone
|
|
|
|
* @cloneWidth: width of windowClone
|
|
|
|
* @cloneHeight height of windowClone
|
|
|
|
*/
|
|
|
|
// These parameters are not the values retrieved with
|
|
|
|
// get_transformed_position() and get_transformed_size(),
|
|
|
|
// as windowClone might be moving.
|
2010-12-16 19:21:12 +00:00
|
|
|
// See Workspace._showWindowOverlay
|
2009-11-22 03:51:28 +00:00
|
|
|
updatePositions: function(cloneX, cloneY, cloneWidth, cloneHeight) {
|
2009-11-12 00:26:52 +00:00
|
|
|
let button = this.closeButton;
|
|
|
|
let title = this.title;
|
|
|
|
|
2011-03-04 00:08:59 +00:00
|
|
|
let buttonX;
|
|
|
|
let buttonY = cloneY - (button.height - button._overlap);
|
|
|
|
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
|
|
|
|
buttonX = cloneX - (button.width - button._overlap);
|
|
|
|
else
|
|
|
|
buttonX = cloneX + (cloneWidth - button._overlap);
|
|
|
|
|
2009-11-12 00:26:52 +00:00
|
|
|
button.set_position(Math.floor(buttonX), Math.floor(buttonY));
|
|
|
|
|
|
|
|
if (!title.fullWidth)
|
|
|
|
title.fullWidth = title.width;
|
2009-11-22 03:51:28 +00:00
|
|
|
title.width = Math.min(title.fullWidth, cloneWidth);
|
2009-11-12 00:26:52 +00:00
|
|
|
|
2009-11-22 03:51:28 +00:00
|
|
|
let titleX = cloneX + (cloneWidth - title.width) / 2;
|
|
|
|
let titleY = cloneY + cloneHeight + title._spacing;
|
2009-11-12 00:26:52 +00:00
|
|
|
title.set_position(Math.floor(titleX), Math.floor(titleY));
|
|
|
|
},
|
|
|
|
|
2010-02-18 04:15:10 +00:00
|
|
|
_closeWindow: function(actor) {
|
2009-11-21 05:46:02 +00:00
|
|
|
let metaWindow = this._windowClone.metaWindow;
|
|
|
|
this._workspace = metaWindow.get_workspace();
|
|
|
|
|
|
|
|
this._windowAddedId = this._workspace.connect('window-added',
|
|
|
|
Lang.bind(this,
|
|
|
|
this._onWindowAdded));
|
|
|
|
|
2010-02-18 04:15:10 +00:00
|
|
|
metaWindow.delete(global.get_current_time());
|
2009-11-21 05:46:02 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_onWindowAdded: function(workspace, win) {
|
|
|
|
let metaWindow = this._windowClone.metaWindow;
|
|
|
|
|
|
|
|
if (win.get_transient_for() == metaWindow) {
|
|
|
|
workspace.disconnect(this._windowAddedId);
|
|
|
|
this._windowAddedId = 0;
|
|
|
|
|
|
|
|
// use an idle handler to avoid mapping problems -
|
|
|
|
// see comment in Workspace._windowAdded
|
|
|
|
Mainloop.idle_add(Lang.bind(this,
|
|
|
|
function() {
|
|
|
|
this._windowClone.emit('selected');
|
|
|
|
return false;
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_onDestroy: function() {
|
|
|
|
if (this._windowAddedId > 0) {
|
|
|
|
this._workspace.disconnect(this._windowAddedId);
|
|
|
|
this._windowAddedId = 0;
|
|
|
|
}
|
|
|
|
if (this._idleToggleCloseId > 0) {
|
|
|
|
Mainloop.source_remove(this._idleToggleCloseId);
|
|
|
|
this._idleToggleCloseId = 0;
|
|
|
|
}
|
2010-02-07 02:06:50 +00:00
|
|
|
this._windowClone.metaWindow.disconnect(this._updateCaptionId);
|
2009-11-21 05:46:02 +00:00
|
|
|
this.title.destroy();
|
|
|
|
this.closeButton.destroy();
|
|
|
|
},
|
|
|
|
|
2009-11-12 00:26:52 +00:00
|
|
|
_onEnter: function() {
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
// We might get enter events on the clone while the overlay is
|
|
|
|
// hidden, e.g. during animations, we ignore these events,
|
|
|
|
// as the close button will be shown as needed when the overlays
|
|
|
|
// are shown again
|
|
|
|
if (this._hidden)
|
|
|
|
return;
|
2010-01-22 02:33:48 +00:00
|
|
|
this._parentActor.raise_top();
|
2009-11-12 00:26:52 +00:00
|
|
|
this.closeButton.show();
|
2009-11-20 00:39:00 +00:00
|
|
|
this.emit('show-close-button');
|
2009-11-12 00:26:52 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_onLeave: function() {
|
2009-11-20 00:39:00 +00:00
|
|
|
if (this._idleToggleCloseId == 0)
|
|
|
|
this._idleToggleCloseId = Mainloop.timeout_add(750, Lang.bind(this, this._idleToggleCloseButton));
|
|
|
|
},
|
|
|
|
|
|
|
|
_idleToggleCloseButton: function() {
|
|
|
|
this._idleToggleCloseId = 0;
|
2010-11-24 17:58:43 +00:00
|
|
|
if (!this._windowClone.actor.has_pointer &&
|
|
|
|
!this.closeButton.has_pointer)
|
2009-11-20 00:39:00 +00:00
|
|
|
this.closeButton.hide();
|
2010-11-24 17:58:43 +00:00
|
|
|
|
2009-11-20 00:39:00 +00:00
|
|
|
return false;
|
|
|
|
},
|
|
|
|
|
|
|
|
hideCloseButton: function() {
|
|
|
|
if (this._idleToggleCloseId > 0) {
|
|
|
|
Mainloop.source_remove(this._idleToggleCloseId);
|
|
|
|
this._idleToggleCloseId = 0;
|
|
|
|
}
|
2009-11-12 00:26:52 +00:00
|
|
|
this.closeButton.hide();
|
|
|
|
},
|
|
|
|
|
|
|
|
_onStyleChanged: function() {
|
|
|
|
let titleNode = this.title.get_theme_node();
|
StThemeNode: simplify use of get_color/get_double/get_length
Although within St itself there are situations where the semantics of
these functions (return TRUE or FALSE and return the actual value in
an out parameter) is useful, it's mostly just annoying at the
application level, where you generally know that the CSS property is
going to specified, and there is no especially sane fallback if it's
not.
So rename the current methods to lookup_color, lookup_double, and
lookup_length, and add new get_color, get_double, and get_length
methods that don't take an "inherit" parameter, and return their
values directly. (Well, except for get_color, due to the lack of (out
caller-allocates) in gjs.)
And update the code to use either the old or new methods as appropriate.
https://bugzilla.gnome.org/show_bug.cgi?id=632590
2010-09-26 21:38:36 +00:00
|
|
|
this.title._spacing = titleNode.get_length('-shell-caption-spacing');
|
2009-11-12 00:26:52 +00:00
|
|
|
|
|
|
|
let closeNode = this.closeButton.get_theme_node();
|
StThemeNode: simplify use of get_color/get_double/get_length
Although within St itself there are situations where the semantics of
these functions (return TRUE or FALSE and return the actual value in
an out parameter) is useful, it's mostly just annoying at the
application level, where you generally know that the CSS property is
going to specified, and there is no especially sane fallback if it's
not.
So rename the current methods to lookup_color, lookup_double, and
lookup_length, and add new get_color, get_double, and get_length
methods that don't take an "inherit" parameter, and return their
values directly. (Well, except for get_color, due to the lack of (out
caller-allocates) in gjs.)
And update the code to use either the old or new methods as appropriate.
https://bugzilla.gnome.org/show_bug.cgi?id=632590
2010-09-26 21:38:36 +00:00
|
|
|
this.closeButton._overlap = closeNode.get_length('-shell-close-overlap');
|
2009-11-12 00:26:52 +00:00
|
|
|
|
|
|
|
this._parentActor.queue_relayout();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Signals.addSignalMethods(WindowOverlay.prototype);
|
|
|
|
|
2010-01-22 02:33:48 +00:00
|
|
|
const WindowPositionFlags = {
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
INITIAL: 1 << 0,
|
2010-01-22 02:33:48 +00:00
|
|
|
ANIMATE: 1 << 1
|
|
|
|
};
|
2009-11-12 00:26:52 +00:00
|
|
|
|
2009-07-23 21:36:41 +00:00
|
|
|
/**
|
2011-03-03 21:33:27 +00:00
|
|
|
* @metaWorkspace: a #Meta.Workspace, or null
|
2009-07-23 21:36:41 +00:00
|
|
|
*/
|
2011-03-01 08:14:56 +00:00
|
|
|
function Workspace(metaWorkspace, monitorIndex) {
|
|
|
|
this._init(metaWorkspace, monitorIndex);
|
2008-12-22 21:51:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Workspace.prototype = {
|
2011-03-01 08:14:56 +00:00
|
|
|
_init : function(metaWorkspace, monitorIndex) {
|
2010-03-16 15:51:24 +00:00
|
|
|
// When dragging a window, we use this slot for reserve space.
|
|
|
|
this._reservedSlot = null;
|
2010-02-14 23:32:57 +00:00
|
|
|
this.metaWorkspace = metaWorkspace;
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
this._x = 0;
|
|
|
|
this._y = 0;
|
|
|
|
this._width = 0;
|
|
|
|
this._height = 0;
|
|
|
|
|
2011-03-01 08:14:56 +00:00
|
|
|
this.monitorIndex = monitorIndex;
|
|
|
|
this._monitor = global.get_monitors()[this.monitorIndex];
|
2010-01-22 02:33:48 +00:00
|
|
|
this._windowOverlaysGroup = new Clutter.Group();
|
|
|
|
// Without this the drop area will be overlapped.
|
|
|
|
this._windowOverlaysGroup.set_size(0, 0);
|
|
|
|
|
2011-01-21 18:47:54 +00:00
|
|
|
this.actor = new Clutter.Group();
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
this.actor.set_size(0, 0);
|
2010-02-18 15:43:58 +00:00
|
|
|
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
this._dropRect = new Clutter.Rectangle({ opacity: 0 });
|
|
|
|
this._dropRect._delegate = this;
|
2010-02-18 15:43:58 +00:00
|
|
|
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
this.actor.add_actor(this._dropRect);
|
|
|
|
this.actor.add_actor(this._windowOverlaysGroup);
|
2010-02-14 23:32:57 +00:00
|
|
|
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
2008-12-22 21:51:34 +00:00
|
|
|
|
2011-03-01 08:14:56 +00:00
|
|
|
let windows = global.get_window_actors().filter(this._isMyWindow, this);
|
2008-12-22 21:51:34 +00:00
|
|
|
|
2011-02-19 23:39:10 +00:00
|
|
|
// Create clones for windows that should be
|
2009-08-11 11:46:10 +00:00
|
|
|
// visible in the Overview
|
2010-07-15 14:21:32 +00:00
|
|
|
this._windows = [];
|
|
|
|
this._windowOverlays = [];
|
2008-12-22 21:51:34 +00:00
|
|
|
for (let i = 0; i < windows.length; i++) {
|
2009-08-11 11:46:10 +00:00
|
|
|
if (this._isOverviewWindow(windows[i])) {
|
2009-01-23 19:21:20 +00:00
|
|
|
this._addWindowClone(windows[i]);
|
2008-12-22 21:51:34 +00:00
|
|
|
}
|
|
|
|
}
|
2008-12-22 22:06:47 +00:00
|
|
|
|
2009-02-04 14:50:50 +00:00
|
|
|
// Track window changes
|
2011-03-03 21:33:27 +00:00
|
|
|
if (this.metaWorkspace) {
|
|
|
|
this._windowAddedId = this.metaWorkspace.connect('window-added',
|
|
|
|
Lang.bind(this, this._windowAdded));
|
|
|
|
this._windowRemovedId = this.metaWorkspace.connect('window-removed',
|
|
|
|
Lang.bind(this, this._windowRemoved));
|
|
|
|
}
|
2011-03-01 08:14:56 +00:00
|
|
|
this._windowEnteredMonitorId = global.screen.connect('window-entered-monitor',
|
|
|
|
Lang.bind(this, this._windowEnteredMonitor));
|
|
|
|
this._windowLeftMonitorId = global.screen.connect('window-left-monitor',
|
|
|
|
Lang.bind(this, this._windowLeftMonitor));
|
2010-02-28 06:56:04 +00:00
|
|
|
this._repositionWindowsId = 0;
|
2009-02-04 14:50:50 +00:00
|
|
|
|
2009-08-11 11:46:10 +00:00
|
|
|
this.leavingOverview = false;
|
2008-12-22 22:06:47 +00:00
|
|
|
},
|
|
|
|
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
setGeometry: function(x, y, width, height) {
|
|
|
|
this._x = x;
|
|
|
|
this._y = y;
|
|
|
|
this._width = width;
|
|
|
|
this._height = height;
|
|
|
|
|
|
|
|
// This is sometimes called during allocation, so we do this later
|
|
|
|
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
|
|
|
|
function () {
|
|
|
|
this._dropRect.set_position(x, y);
|
|
|
|
this._dropRect.set_size(width, height);
|
|
|
|
return false;
|
|
|
|
}));
|
|
|
|
|
|
|
|
},
|
|
|
|
|
2009-07-23 21:36:41 +00:00
|
|
|
_lookupIndex: function (metaWindow) {
|
2009-07-31 21:20:26 +00:00
|
|
|
for (let i = 0; i < this._windows.length; i++) {
|
|
|
|
if (this._windows[i].metaWindow == metaWindow) {
|
2009-07-23 21:36:41 +00:00
|
|
|
return i;
|
2009-07-31 21:20:26 +00:00
|
|
|
}
|
|
|
|
}
|
2009-07-23 21:36:41 +00:00
|
|
|
return -1;
|
2009-07-31 21:20:26 +00:00
|
|
|
},
|
|
|
|
|
2009-09-01 18:15:29 +00:00
|
|
|
containsMetaWindow: function (metaWindow) {
|
|
|
|
return this._lookupIndex(metaWindow) >= 0;
|
|
|
|
},
|
|
|
|
|
2011-01-21 18:47:54 +00:00
|
|
|
isEmpty: function() {
|
|
|
|
return this._windows.length == 0;
|
|
|
|
},
|
|
|
|
|
2010-02-14 23:32:57 +00:00
|
|
|
/**
|
|
|
|
* setReactive:
|
|
|
|
* @reactive: %true iff the workspace should be reactive
|
|
|
|
*
|
|
|
|
* Set the workspace (desktop) reactive
|
|
|
|
**/
|
|
|
|
setReactive: function(reactive) {
|
2010-07-15 14:21:32 +00:00
|
|
|
this.actor.reactive = reactive;
|
2010-02-14 23:32:57 +00:00
|
|
|
},
|
|
|
|
|
2009-09-18 19:08:56 +00:00
|
|
|
// Only use this for n <= 20 say
|
|
|
|
_factorial: function(n) {
|
|
|
|
let result = 1;
|
|
|
|
for (let i = 2; i <= n; i++)
|
|
|
|
result *= i;
|
|
|
|
return result;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* _permutation:
|
|
|
|
* @permutationIndex: An integer from [0, list.length!)
|
|
|
|
* @list: (inout): Array of objects to permute; will be modified in place
|
|
|
|
*
|
|
|
|
* Given an integer between 0 and length of array, re-order the array in-place
|
|
|
|
* into a permutation denoted by the index.
|
|
|
|
*/
|
|
|
|
_permutation: function(permutationIndex, list) {
|
|
|
|
for (let j = 2; j <= list.length; j++) {
|
|
|
|
let firstIndex = (permutationIndex % j);
|
|
|
|
let secondIndex = j - 1;
|
|
|
|
// Swap
|
|
|
|
let tmp = list[firstIndex];
|
|
|
|
list[firstIndex] = list[secondIndex];
|
|
|
|
list[secondIndex] = tmp;
|
|
|
|
permutationIndex = Math.floor(permutationIndex / j);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* _forEachPermutations:
|
|
|
|
* @list: Array
|
|
|
|
* @func: Function which takes a single array argument
|
|
|
|
*
|
|
|
|
* Call @func with each permutation of @list as an argument.
|
|
|
|
*/
|
|
|
|
_forEachPermutations: function(list, func) {
|
|
|
|
let nCombinations = this._factorial(list.length);
|
|
|
|
for (let i = 0; i < nCombinations; i++) {
|
|
|
|
let listCopy = list.concat();
|
|
|
|
this._permutation(i, listCopy);
|
|
|
|
func(listCopy);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* _computeWindowMotion:
|
2010-02-26 15:45:05 +00:00
|
|
|
* @actor: A #WindowClone's #ClutterActor
|
2009-09-18 19:08:56 +00:00
|
|
|
* @slot: An element of #POSITIONS
|
|
|
|
* @slotGeometry: Layout of @slot
|
|
|
|
*
|
|
|
|
* Returns a number corresponding to how much perceived motion
|
|
|
|
* would be involved in moving the window to the given slot.
|
|
|
|
* Currently this is the square of the distance between the
|
|
|
|
* centers.
|
|
|
|
*/
|
2010-02-26 15:45:05 +00:00
|
|
|
_computeWindowMotion: function (actor, slot) {
|
2010-02-22 17:07:58 +00:00
|
|
|
let [xCenter, yCenter, fraction] = slot;
|
|
|
|
let xDelta, yDelta, distanceSquared;
|
2010-02-26 15:45:05 +00:00
|
|
|
let actorWidth, actorHeight;
|
2009-09-18 19:08:56 +00:00
|
|
|
|
2011-03-08 13:46:34 +00:00
|
|
|
let x = actor.x;
|
|
|
|
let y = actor.y;
|
|
|
|
let scale = actor.scale_x;
|
|
|
|
|
|
|
|
if (actor._delegate.inDrag) {
|
|
|
|
x = actor._delegate.dragOrigX;
|
|
|
|
y = actor._delegate.dragOrigY;
|
|
|
|
scale = actor._delegate.dragOrigScale;
|
|
|
|
}
|
|
|
|
|
|
|
|
actorWidth = actor.width * scale;
|
|
|
|
actorHeight = actor.height * scale;
|
|
|
|
xDelta = x + actorWidth / 2.0 - xCenter * this._width - this._x;
|
|
|
|
yDelta = y + actorHeight / 2.0 - yCenter * this._height - this._y;
|
2009-09-18 19:08:56 +00:00
|
|
|
distanceSquared = xDelta * xDelta + yDelta * yDelta;
|
|
|
|
|
|
|
|
return distanceSquared;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* _orderWindowsPermutations:
|
|
|
|
*
|
|
|
|
* Iterate over all permutations of the windows, and determine the
|
|
|
|
* permutation which has the least total motion.
|
|
|
|
*/
|
2010-02-22 17:07:58 +00:00
|
|
|
_orderWindowsPermutations: function (clones, slots) {
|
2009-09-18 19:08:56 +00:00
|
|
|
let minimumMotionPermutation = null;
|
|
|
|
let minimumMotion = -1;
|
|
|
|
let permIndex = 0;
|
2010-02-19 18:27:07 +00:00
|
|
|
this._forEachPermutations(clones, Lang.bind(this, function (permutation) {
|
2009-09-18 19:08:56 +00:00
|
|
|
let motion = 0;
|
|
|
|
for (let i = 0; i < permutation.length; i++) {
|
2010-02-26 15:45:05 +00:00
|
|
|
let cloneActor = permutation[i].actor;
|
2009-09-18 19:08:56 +00:00
|
|
|
let slot = slots[i];
|
|
|
|
|
2010-02-26 15:45:05 +00:00
|
|
|
let delta = this._computeWindowMotion(cloneActor, slot);
|
2009-09-18 19:08:56 +00:00
|
|
|
|
|
|
|
motion += delta;
|
2011-03-03 15:29:05 +00:00
|
|
|
|
|
|
|
// Bail out early if we're already larger than the
|
|
|
|
// previous best
|
|
|
|
if (minimumMotionPermutation != null &&
|
|
|
|
motion > minimumMotion)
|
|
|
|
continue;
|
2009-09-18 19:08:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (minimumMotionPermutation == null || motion < minimumMotion) {
|
|
|
|
minimumMotionPermutation = permutation;
|
|
|
|
minimumMotion = motion;
|
|
|
|
}
|
|
|
|
permIndex++;
|
|
|
|
}));
|
|
|
|
return minimumMotionPermutation;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* _orderWindowsGreedy:
|
|
|
|
*
|
|
|
|
* Iterate over available slots in order, placing into each one the window
|
|
|
|
* we find with the smallest motion to that slot.
|
|
|
|
*/
|
2010-02-22 17:07:58 +00:00
|
|
|
_orderWindowsGreedy: function(clones, slots) {
|
2009-09-18 19:08:56 +00:00
|
|
|
let result = [];
|
|
|
|
let slotIndex = 0;
|
|
|
|
// Copy since we mutate below
|
2010-02-19 18:27:07 +00:00
|
|
|
let clonesCopy = clones.concat();
|
2009-09-18 19:08:56 +00:00
|
|
|
for (let i = 0; i < slots.length; i++) {
|
|
|
|
let slot = slots[i];
|
|
|
|
let minimumMotionIndex = -1;
|
|
|
|
let minimumMotion = -1;
|
2010-02-19 18:27:07 +00:00
|
|
|
for (let j = 0; j < clonesCopy.length; j++) {
|
2010-02-26 15:45:05 +00:00
|
|
|
let cloneActor = clonesCopy[j].actor;
|
|
|
|
let delta = this._computeWindowMotion(cloneActor, slot);
|
2009-09-18 19:08:56 +00:00
|
|
|
if (minimumMotionIndex == -1 || delta < minimumMotion) {
|
|
|
|
minimumMotionIndex = j;
|
|
|
|
minimumMotion = delta;
|
|
|
|
}
|
|
|
|
}
|
2010-02-19 18:27:07 +00:00
|
|
|
result.push(clonesCopy[minimumMotionIndex]);
|
|
|
|
clonesCopy.splice(minimumMotionIndex, 1);
|
2009-09-18 19:08:56 +00:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* _orderWindowsByMotionAndStartup:
|
|
|
|
* @windows: Array of #MetaWindow
|
|
|
|
* @slots: Array of slots
|
|
|
|
*
|
|
|
|
* Returns a copy of @windows, ordered in such a way that they require least motion
|
|
|
|
* to move to the final screen coordinates of @slots. Ties are broken in a stable
|
|
|
|
* fashion by the order in which the windows were created.
|
|
|
|
*/
|
2010-02-19 18:27:07 +00:00
|
|
|
_orderWindowsByMotionAndStartup: function(clones, slots) {
|
|
|
|
clones.sort(function(w1, w2) {
|
|
|
|
return w2.metaWindow.get_stable_sequence() - w1.metaWindow.get_stable_sequence();
|
2009-09-18 19:08:56 +00:00
|
|
|
});
|
2010-02-19 18:27:07 +00:00
|
|
|
if (clones.length <= POSITIONING_PERMUTATIONS_MAX)
|
2010-02-22 17:07:58 +00:00
|
|
|
return this._orderWindowsPermutations(clones, slots);
|
2009-09-18 19:08:56 +00:00
|
|
|
else
|
2010-02-22 17:07:58 +00:00
|
|
|
return this._orderWindowsGreedy(clones, slots);
|
2009-09-18 19:08:56 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
* _getSlotGeometry:
|
2009-09-18 19:08:56 +00:00
|
|
|
* @slot: A layout slot
|
|
|
|
*
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
* Returns: the screen-relative [x, y, width, height]
|
2009-09-18 19:08:56 +00:00
|
|
|
* of a given window layout slot.
|
|
|
|
*/
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
_getSlotGeometry: function(slot) {
|
2009-09-18 19:08:56 +00:00
|
|
|
let [xCenter, yCenter, fraction] = slot;
|
|
|
|
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
let width = this._width * fraction;
|
|
|
|
let height = this._height * fraction;
|
2009-09-18 19:08:56 +00:00
|
|
|
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
let x = this._x + xCenter * this._width - width / 2 ;
|
|
|
|
let y = this._y + yCenter * this._height - height / 2;
|
2009-09-18 19:08:56 +00:00
|
|
|
|
|
|
|
return [x, y, width, height];
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
* _computeWindowLayout:
|
2009-09-18 19:08:56 +00:00
|
|
|
* @metaWindow: A #MetaWindow
|
|
|
|
* @slot: A layout slot
|
|
|
|
*
|
|
|
|
* Given a window and slot to fit it in, compute its
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
* screen-relative [x, y, scale] where scale applies
|
2009-09-18 19:08:56 +00:00
|
|
|
* to both X and Y directions.
|
|
|
|
*/
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
_computeWindowLayout: function(metaWindow, slot) {
|
|
|
|
let [x, y, width, height] = this._getSlotGeometry(slot);
|
2009-09-18 19:08:56 +00:00
|
|
|
|
2010-11-22 21:18:30 +00:00
|
|
|
let rect = metaWindow.get_outer_rect();
|
2010-03-16 15:51:24 +00:00
|
|
|
let buttonOuterHeight, captionHeight;
|
|
|
|
let buttonOuterWidth = 0;
|
|
|
|
|
2010-07-15 14:21:32 +00:00
|
|
|
if (this._windowOverlays[0]) {
|
|
|
|
[buttonOuterHeight, captionHeight] = this._windowOverlays[0].chromeHeights();
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
buttonOuterWidth = this._windowOverlays[0].chromeWidth();
|
2010-03-16 15:51:24 +00:00
|
|
|
} else
|
|
|
|
[buttonOuterHeight, captionHeight] = [0, 0];
|
2009-11-12 00:26:52 +00:00
|
|
|
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
let scale = Math.min((width - buttonOuterWidth) / rect.width,
|
|
|
|
(height - buttonOuterHeight - captionHeight) / rect.height,
|
|
|
|
1.0);
|
2009-09-18 19:08:56 +00:00
|
|
|
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
x = Math.floor(x + (width - scale * rect.width) / 2);
|
2010-05-09 12:18:42 +00:00
|
|
|
|
|
|
|
// We want to center the window in case we have just one
|
|
|
|
if (metaWindow.get_workspace().n_windows == 1)
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
y = Math.floor(y + (height - scale * rect.height) / 2);
|
2010-05-09 12:18:42 +00:00
|
|
|
else
|
|
|
|
y = Math.floor(y + height - rect.height * scale - captionHeight);
|
2009-09-18 19:08:56 +00:00
|
|
|
|
|
|
|
return [x, y, scale];
|
|
|
|
},
|
|
|
|
|
2010-03-16 15:51:24 +00:00
|
|
|
setReservedSlot: function(clone) {
|
2011-02-10 00:42:01 +00:00
|
|
|
if (this._reservedSlot == clone)
|
|
|
|
return;
|
|
|
|
|
2010-03-16 15:51:24 +00:00
|
|
|
if (clone && this.containsMetaWindow(clone.metaWindow)) {
|
|
|
|
this._reservedSlot = null;
|
|
|
|
this.positionWindows(WindowPositionFlags.ANIMATE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (clone)
|
|
|
|
this._reservedSlot = clone;
|
|
|
|
else
|
|
|
|
this._reservedSlot = null;
|
|
|
|
this.positionWindows(WindowPositionFlags.ANIMATE);
|
|
|
|
},
|
|
|
|
|
2009-09-11 16:39:59 +00:00
|
|
|
/**
|
|
|
|
* positionWindows:
|
2010-01-22 02:33:48 +00:00
|
|
|
* @flags:
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
* INITIAL - this is the initial positioning of the windows.
|
2010-01-22 02:33:48 +00:00
|
|
|
* ANIMATE - Indicates that we need animate changing position.
|
2009-09-11 16:39:59 +00:00
|
|
|
*/
|
2010-01-22 02:33:48 +00:00
|
|
|
positionWindows : function(flags) {
|
2010-02-28 06:56:04 +00:00
|
|
|
if (this._repositionWindowsId > 0) {
|
|
|
|
Mainloop.source_remove(this._repositionWindowsId);
|
|
|
|
this._repositionWindowsId = 0;
|
|
|
|
}
|
|
|
|
|
2011-02-12 19:03:44 +00:00
|
|
|
let clones = this._windows.slice();
|
2010-03-16 15:51:24 +00:00
|
|
|
if (this._reservedSlot)
|
2011-02-12 19:03:44 +00:00
|
|
|
clones.push(this._reservedSlot);
|
2009-09-01 18:15:29 +00:00
|
|
|
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
let initialPositioning = flags & WindowPositionFlags.INITIAL;
|
2010-01-22 02:33:48 +00:00
|
|
|
let animate = flags & WindowPositionFlags.ANIMATE;
|
|
|
|
|
2009-09-28 23:48:03 +00:00
|
|
|
// Start the animations
|
2011-02-12 19:03:44 +00:00
|
|
|
let slots = this._computeAllWindowSlots(clones.length);
|
|
|
|
clones = this._orderWindowsByMotionAndStartup(clones, slots);
|
2009-01-23 19:21:20 +00:00
|
|
|
|
2010-12-16 19:21:12 +00:00
|
|
|
let currentWorkspace = global.screen.get_active_workspace();
|
2011-03-03 21:33:27 +00:00
|
|
|
let isOnCurrentWorkspace = this.metaWorkspace == null || this.metaWorkspace == currentWorkspace;
|
2010-12-16 19:21:12 +00:00
|
|
|
|
2011-02-12 19:03:44 +00:00
|
|
|
for (let i = 0; i < clones.length; i++) {
|
2009-09-18 19:08:56 +00:00
|
|
|
let slot = slots[i];
|
2011-02-12 19:03:44 +00:00
|
|
|
let clone = clones[i];
|
2010-02-19 18:27:07 +00:00
|
|
|
let metaWindow = clone.metaWindow;
|
2009-09-18 19:08:56 +00:00
|
|
|
let mainIndex = this._lookupIndex(metaWindow);
|
2009-11-12 00:26:52 +00:00
|
|
|
let overlay = this._windowOverlays[mainIndex];
|
2009-09-01 18:15:29 +00:00
|
|
|
|
2010-03-19 20:46:08 +00:00
|
|
|
// Positioning a window currently being dragged must be avoided;
|
|
|
|
// we'll just leave a blank spot in the layout for it.
|
|
|
|
if (clone.inDrag)
|
|
|
|
continue;
|
|
|
|
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
let [x, y, scale] = this._computeWindowLayout(metaWindow, slot);
|
2009-01-23 19:21:20 +00:00
|
|
|
|
2010-03-16 15:51:24 +00:00
|
|
|
if (overlay)
|
|
|
|
overlay.hide();
|
2010-12-16 19:21:12 +00:00
|
|
|
if (animate && isOnCurrentWorkspace) {
|
2010-01-23 07:37:34 +00:00
|
|
|
if (!metaWindow.showing_on_its_workspace()) {
|
|
|
|
/* Hidden windows should fade in and grow
|
|
|
|
* therefore we need to resize them now so they
|
|
|
|
* can be scaled up later */
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
if (initialPositioning) {
|
2010-01-23 07:37:34 +00:00
|
|
|
clone.actor.opacity = 0;
|
|
|
|
clone.actor.scale_x = 0;
|
|
|
|
clone.actor.scale_y = 0;
|
|
|
|
clone.actor.x = x;
|
|
|
|
clone.actor.y = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make the window slightly transparent to indicate it's hidden
|
|
|
|
Tweener.addTween(clone.actor,
|
|
|
|
{ opacity: 255,
|
|
|
|
time: Overview.ANIMATION_TIME,
|
2010-05-13 19:46:04 +00:00
|
|
|
transition: 'easeInQuad'
|
2010-01-23 07:37:34 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2010-01-22 02:33:48 +00:00
|
|
|
Tweener.addTween(clone.actor,
|
|
|
|
{ x: x,
|
|
|
|
y: y,
|
|
|
|
scale_x: scale,
|
|
|
|
scale_y: scale,
|
|
|
|
time: Overview.ANIMATION_TIME,
|
2010-05-13 19:46:04 +00:00
|
|
|
transition: 'easeOutQuad',
|
2010-01-22 02:33:48 +00:00
|
|
|
onComplete: Lang.bind(this, function() {
|
2010-12-16 19:21:12 +00:00
|
|
|
this._showWindowOverlay(clone, overlay, true);
|
2010-01-22 02:33:48 +00:00
|
|
|
})
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
clone.actor.set_position(x, y);
|
|
|
|
clone.actor.set_scale(scale, scale);
|
2010-12-16 19:21:12 +00:00
|
|
|
this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace);
|
2010-01-22 02:33:48 +00:00
|
|
|
}
|
2009-01-23 19:21:20 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2009-09-28 23:48:03 +00:00
|
|
|
syncStacking: function(stackIndices) {
|
2011-02-12 19:03:44 +00:00
|
|
|
let clones = this._windows.slice();
|
|
|
|
clones.sort(function (a, b) { return stackIndices[a.metaWindow.get_stable_sequence()] - stackIndices[b.metaWindow.get_stable_sequence()]; });
|
2009-09-28 23:48:03 +00:00
|
|
|
|
2011-02-12 19:03:44 +00:00
|
|
|
for (let i = 0; i < clones.length; i++) {
|
|
|
|
let clone = clones[i];
|
2009-09-28 23:48:03 +00:00
|
|
|
let metaWindow = clone.metaWindow;
|
|
|
|
if (i == 0) {
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
clone.setStackAbove(this._dropRect);
|
2009-09-28 23:48:03 +00:00
|
|
|
} else {
|
2011-02-12 19:03:44 +00:00
|
|
|
let previousClone = clones[i - 1];
|
2009-09-28 23:48:03 +00:00
|
|
|
clone.setStackAbove(previousClone.actor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2010-12-16 19:21:12 +00:00
|
|
|
_showWindowOverlay: function(clone, overlay, fade) {
|
2010-03-22 23:01:44 +00:00
|
|
|
if (clone.inDrag)
|
|
|
|
return;
|
|
|
|
|
2009-11-22 03:51:28 +00:00
|
|
|
// This is a little messy and complicated because when we
|
|
|
|
// start the fade-in we may not have done the final positioning
|
|
|
|
// of the workspaces. (Tweener doesn't necessarily finish
|
|
|
|
// all animations before calling onComplete callbacks.)
|
|
|
|
// So we need to manually compute where the window will
|
|
|
|
// be after the workspace animation finishes.
|
|
|
|
let [cloneX, cloneY] = clone.actor.get_position();
|
|
|
|
let [cloneWidth, cloneHeight] = clone.actor.get_size();
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
cloneWidth = clone.actor.scale_x * cloneWidth;
|
|
|
|
cloneHeight = clone.actor.scale_y * cloneHeight;
|
2009-11-22 03:51:28 +00:00
|
|
|
|
2010-03-16 15:51:24 +00:00
|
|
|
if (overlay) {
|
|
|
|
overlay.updatePositions(cloneX, cloneY, cloneWidth, cloneHeight);
|
2010-12-16 19:21:12 +00:00
|
|
|
if (fade)
|
|
|
|
overlay.fadeIn();
|
|
|
|
else
|
|
|
|
overlay.show();
|
2010-03-16 15:51:24 +00:00
|
|
|
}
|
2009-11-22 03:51:28 +00:00
|
|
|
},
|
|
|
|
|
2010-12-16 19:21:12 +00:00
|
|
|
_showAllOverlays: function() {
|
|
|
|
let currentWorkspace = global.screen.get_active_workspace();
|
2010-07-15 14:21:32 +00:00
|
|
|
for (let i = 0; i < this._windows.length; i++) {
|
2009-07-23 21:36:41 +00:00
|
|
|
let clone = this._windows[i];
|
2009-11-12 00:26:52 +00:00
|
|
|
let overlay = this._windowOverlays[i];
|
2011-03-03 21:33:27 +00:00
|
|
|
this._showWindowOverlay(clone, overlay,
|
|
|
|
this.metaWorkspace == null || this.metaWorkspace == currentWorkspace);
|
2009-07-23 21:36:41 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2010-02-28 06:56:04 +00:00
|
|
|
_delayedWindowRepositioning: function() {
|
2010-03-21 18:33:52 +00:00
|
|
|
if (this._windowIsZooming)
|
|
|
|
return true;
|
|
|
|
|
2010-04-08 18:41:54 +00:00
|
|
|
let [x, y, mask] = global.get_pointer();
|
2010-02-28 06:56:04 +00:00
|
|
|
|
|
|
|
let pointerHasMoved = (this._cursorX != x && this._cursorY != y);
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
let inWorkspace = (this._x < x && x < this._x + this._width &&
|
|
|
|
this._y < y && y < this._y + this._height);
|
2010-02-28 06:56:04 +00:00
|
|
|
|
|
|
|
if (pointerHasMoved && inWorkspace) {
|
|
|
|
// store current cursor position
|
|
|
|
this._cursorX = x;
|
|
|
|
this._cursorY = y;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.positionWindows(WindowPositionFlags.ANIMATE);
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
|
2010-03-16 15:51:24 +00:00
|
|
|
showWindowsOverlays: function() {
|
2011-02-10 21:41:07 +00:00
|
|
|
if (this.leavingOverview)
|
|
|
|
return;
|
|
|
|
|
2010-03-16 15:51:24 +00:00
|
|
|
this._windowOverlaysGroup.show();
|
2010-12-16 19:21:12 +00:00
|
|
|
this._showAllOverlays();
|
2010-03-16 15:51:24 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
hideWindowsOverlays: function() {
|
|
|
|
this._windowOverlaysGroup.hide();
|
|
|
|
},
|
|
|
|
|
2011-03-01 08:14:56 +00:00
|
|
|
_doRemoveWindow : function(metaWin) {
|
2009-02-04 14:50:50 +00:00
|
|
|
let win = metaWin.get_compositor_private();
|
|
|
|
|
2009-01-23 19:21:20 +00:00
|
|
|
// find the position of the window in our list
|
2009-07-23 21:36:41 +00:00
|
|
|
let index = this._lookupIndex (metaWin);
|
2009-01-23 19:21:20 +00:00
|
|
|
|
|
|
|
if (index == -1)
|
|
|
|
return;
|
2009-02-10 16:15:59 +00:00
|
|
|
|
2011-03-01 08:14:56 +00:00
|
|
|
// Check if window still should be here
|
|
|
|
if (win && this._isMyWindow(win))
|
|
|
|
return;
|
|
|
|
|
2009-07-23 21:36:41 +00:00
|
|
|
let clone = this._windows[index];
|
|
|
|
|
2009-01-23 19:21:20 +00:00
|
|
|
this._windows.splice(index, 1);
|
2009-11-12 00:26:52 +00:00
|
|
|
this._windowOverlays.splice(index, 1);
|
2009-02-04 14:50:50 +00:00
|
|
|
|
|
|
|
// If metaWin.get_compositor_private() returned non-NULL, that
|
|
|
|
// means the window still exists (and is just being moved to
|
2009-08-11 11:46:10 +00:00
|
|
|
// another workspace or something), so set its overviewHint
|
2009-02-04 14:50:50 +00:00
|
|
|
// accordingly. (If it returned NULL, then the window is being
|
|
|
|
// destroyed; we'd like to animate this, but it's too late at
|
|
|
|
// this point.)
|
|
|
|
if (win) {
|
|
|
|
let [stageX, stageY] = clone.actor.get_transformed_position();
|
|
|
|
let [stageWidth, stageHeight] = clone.actor.get_transformed_size();
|
2009-08-11 11:46:10 +00:00
|
|
|
win._overviewHint = {
|
2009-02-04 14:50:50 +00:00
|
|
|
x: stageX,
|
|
|
|
y: stageY,
|
|
|
|
scale: stageWidth / clone.actor.width
|
|
|
|
};
|
|
|
|
}
|
2009-01-23 19:21:20 +00:00
|
|
|
clone.destroy();
|
|
|
|
|
2010-02-28 06:56:04 +00:00
|
|
|
|
|
|
|
// We need to reposition the windows; to avoid shuffling windows
|
|
|
|
// around while the user is interacting with the workspace, we delay
|
|
|
|
// the positioning until the pointer remains still for at least 750 ms
|
|
|
|
// or is moved outside the workspace
|
|
|
|
|
|
|
|
// remove old handler
|
|
|
|
if (this._repositionWindowsId > 0) {
|
|
|
|
Mainloop.source_remove(this._repositionWindowsId);
|
|
|
|
this._repositionWindowsId = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// setup new handler
|
2010-04-08 18:41:54 +00:00
|
|
|
let [x, y, mask] = global.get_pointer();
|
2010-02-28 06:56:04 +00:00
|
|
|
this._cursorX = x;
|
|
|
|
this._cursorY = y;
|
|
|
|
|
|
|
|
this._repositionWindowsId = Mainloop.timeout_add(750,
|
|
|
|
Lang.bind(this, this._delayedWindowRepositioning));
|
2009-01-23 19:21:20 +00:00
|
|
|
},
|
|
|
|
|
2011-03-01 08:14:56 +00:00
|
|
|
_doAddWindow : function(metaWin) {
|
2009-08-11 11:46:10 +00:00
|
|
|
if (this.leavingOverview)
|
2009-03-17 22:22:25 +00:00
|
|
|
return;
|
|
|
|
|
2009-02-04 14:50:50 +00:00
|
|
|
let win = metaWin.get_compositor_private();
|
|
|
|
|
|
|
|
if (!win) {
|
|
|
|
// Newly-created windows are added to a workspace before
|
|
|
|
// the compositor finds out about them...
|
|
|
|
Mainloop.idle_add(Lang.bind(this,
|
|
|
|
function () {
|
2011-04-20 20:04:03 +00:00
|
|
|
if (this.actor &&
|
|
|
|
metaWin.get_compositor_private() &&
|
|
|
|
metaWin.get_workspace() == this.metaWorkspace)
|
2011-03-01 08:14:56 +00:00
|
|
|
this._doAddWindow(metaWin);
|
2009-02-04 14:50:50 +00:00
|
|
|
return false;
|
|
|
|
}));
|
|
|
|
return;
|
|
|
|
}
|
2010-01-22 02:33:48 +00:00
|
|
|
|
2011-03-01 08:14:56 +00:00
|
|
|
// We might have the window in our list already if it was on all workspaces and
|
|
|
|
// now was moved to this workspace
|
|
|
|
if (this._lookupIndex (metaWin) != -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!this._isMyWindow(win) || !this._isOverviewWindow(win))
|
2010-01-22 02:33:48 +00:00
|
|
|
return;
|
2009-02-04 14:50:50 +00:00
|
|
|
|
2009-01-23 19:21:20 +00:00
|
|
|
let clone = this._addWindowClone(win);
|
2009-02-04 14:50:50 +00:00
|
|
|
|
2009-08-11 11:46:10 +00:00
|
|
|
if (win._overviewHint) {
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
let x = win._overviewHint.x - this.actor.x;
|
|
|
|
let y = win._overviewHint.y - this.actor.y;
|
|
|
|
let scale = win._overviewHint.scale;
|
2009-08-11 11:46:10 +00:00
|
|
|
delete win._overviewHint;
|
2009-02-04 14:50:50 +00:00
|
|
|
|
|
|
|
clone.actor.set_position (x, y);
|
|
|
|
clone.actor.set_scale (scale, scale);
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
} else {
|
|
|
|
// Position new windows at the top corner of the workspace rather
|
|
|
|
// than where they were placed for real to avoid the window
|
|
|
|
// being clipped to the workspaceView. Its not really more
|
|
|
|
// natural for the window to suddenly appear in the overview
|
|
|
|
// on some seemingly random location anyway.
|
|
|
|
clone.actor.set_position (this._x, this._y);
|
2009-02-04 14:50:50 +00:00
|
|
|
}
|
|
|
|
|
2010-01-22 02:33:48 +00:00
|
|
|
this.positionWindows(WindowPositionFlags.ANIMATE);
|
2009-01-23 19:21:20 +00:00
|
|
|
},
|
|
|
|
|
2011-03-01 08:14:56 +00:00
|
|
|
_windowAdded : function(metaWorkspace, metaWin) {
|
|
|
|
this._doAddWindow(metaWin);
|
|
|
|
},
|
|
|
|
|
|
|
|
_windowRemoved : function(metaWorkspace, metaWin) {
|
|
|
|
this._doRemoveWindow(metaWin);
|
|
|
|
},
|
|
|
|
|
|
|
|
_windowEnteredMonitor : function(metaScreen, monitorIndex, metaWin) {
|
|
|
|
if (monitorIndex == this.monitorIndex) {
|
|
|
|
this._doAddWindow(metaWin);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_windowLeftMonitor : function(metaScreen, monitorIndex, metaWin) {
|
|
|
|
if (monitorIndex == this.monitorIndex) {
|
|
|
|
this._doRemoveWindow(metaWin);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2010-01-06 03:53:36 +00:00
|
|
|
// check for maximized windows on the workspace
|
2010-07-15 14:21:32 +00:00
|
|
|
hasMaximizedWindows: function() {
|
|
|
|
for (let i = 0; i < this._windows.length; i++) {
|
2010-01-06 03:53:36 +00:00
|
|
|
let metaWindow = this._windows[i].metaWindow;
|
|
|
|
if (metaWindow.showing_on_its_workspace() &&
|
|
|
|
metaWindow.maximized_horizontally &&
|
|
|
|
metaWindow.maximized_vertically)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
|
2009-08-11 11:46:10 +00:00
|
|
|
// Animate the full-screen to Overview transition.
|
2010-02-14 23:32:57 +00:00
|
|
|
zoomToOverview : function() {
|
2009-08-10 22:31:39 +00:00
|
|
|
// Position and scale the windows.
|
2010-02-14 23:32:57 +00:00
|
|
|
if (Main.overview.animationInProgress)
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
this.positionWindows(WindowPositionFlags.ANIMATE | WindowPositionFlags.INITIAL);
|
2010-01-22 02:33:48 +00:00
|
|
|
else
|
Restructure the way we handle positioning zooming in Workspace
We currently show the workspace in the overview in a rectangle
with the same aspect ratio as the screen. Originally this was
probably done since it showed the desktop, but we don't do this
anymore, and the positioning of the windows in the overview is
strictly a grid, so its not in any way related to monitor geometry.
Additionally, in the multihead case the screen aspect ratio is
very different from the overview monitor geometry, so a lot of
space is lost.
So, instead we just fill the entire inner rectangle of the overview
with the workspace. However, the way the zoom into and out of the
workspace right now is by scaling the workspace so that it covers
the entire monitor. This cannot really work anymore when the workspace
is a different aspect ratio. Furthermore the coordinates of the
window clone actors are of two very different types in the "original
window" case and the "window in a slot case". One is screen relative,
the other is workspace relative. This makes it very hard to compute
the cost of window motion distance in computeWindowMotion.
In order to handle this we change the way workspace actor positioning
and scaling work. All workspace window clone actors are stored in
true screen coordingates, both the original window positions and the
in-a-slot ones. Global scaling of the workspace is never done, we
just reposition everything in both the initial zoom and when the
controls appear from the side.
There is one issue in the initial and final animations, which is that
the clip region we normally have for the workspacesView will limit the
animation of the clones to/from the original positions, so we disable
the clip region during these animations.
https://bugzilla.gnome.org/show_bug.cgi?id=643786
2011-03-02 16:04:03 +00:00
|
|
|
this.positionWindows(WindowPositionFlags.INITIAL);
|
2008-12-22 21:51:34 +00:00
|
|
|
},
|
|
|
|
|
2009-08-11 11:46:10 +00:00
|
|
|
// Animates the return from Overview mode
|
|
|
|
zoomFromOverview : function() {
|
2010-12-16 19:21:12 +00:00
|
|
|
let currentWorkspace = global.screen.get_active_workspace();
|
|
|
|
|
2009-08-11 11:46:10 +00:00
|
|
|
this.leavingOverview = true;
|
2009-07-23 21:36:41 +00:00
|
|
|
|
2011-02-10 21:41:07 +00:00
|
|
|
this.hideWindowsOverlays();
|
2009-07-23 21:36:41 +00:00
|
|
|
|
2010-03-14 14:47:42 +00:00
|
|
|
if (this._repositionWindowsId > 0) {
|
|
|
|
Mainloop.source_remove(this._repositionWindowsId);
|
|
|
|
this._repositionWindowsId = 0;
|
|
|
|
}
|
2010-03-17 22:23:32 +00:00
|
|
|
this._overviewHiddenId = Main.overview.connect('hidden', Lang.bind(this,
|
|
|
|
this._doneLeavingOverview));
|
2009-08-10 22:31:39 +00:00
|
|
|
|
2011-03-03 21:33:27 +00:00
|
|
|
if (this.metaWorkspace != null && this.metaWorkspace != currentWorkspace)
|
2010-12-16 19:21:12 +00:00
|
|
|
return;
|
|
|
|
|
2009-08-10 22:31:39 +00:00
|
|
|
// Position and scale the windows.
|
2010-07-15 14:21:32 +00:00
|
|
|
for (let i = 0; i < this._windows.length; i++) {
|
2009-01-29 21:21:50 +00:00
|
|
|
let clone = this._windows[i];
|
2010-01-23 07:37:34 +00:00
|
|
|
|
2010-02-15 22:11:09 +00:00
|
|
|
clone.zoomFromOverview();
|
|
|
|
|
2010-01-23 07:37:34 +00:00
|
|
|
if (clone.metaWindow.showing_on_its_workspace()) {
|
|
|
|
Tweener.addTween(clone.actor,
|
|
|
|
{ x: clone.origX,
|
|
|
|
y: clone.origY,
|
|
|
|
scale_x: 1.0,
|
|
|
|
scale_y: 1.0,
|
|
|
|
time: Overview.ANIMATION_TIME,
|
|
|
|
opacity: 255,
|
2010-05-13 19:46:04 +00:00
|
|
|
transition: 'easeOutQuad'
|
2010-01-23 07:37:34 +00:00
|
|
|
});
|
|
|
|
} else {
|
|
|
|
// The window is hidden, make it shrink and fade it out
|
|
|
|
Tweener.addTween(clone.actor,
|
|
|
|
{ scale_x: 0,
|
|
|
|
scale_y: 0,
|
|
|
|
opacity: 0,
|
|
|
|
time: Overview.ANIMATION_TIME,
|
2010-05-13 19:46:04 +00:00
|
|
|
transition: 'easeOutQuad'
|
2010-01-23 07:37:34 +00:00
|
|
|
});
|
|
|
|
}
|
2008-12-22 21:51:34 +00:00
|
|
|
}
|
2008-12-22 22:06:47 +00:00
|
|
|
|
2008-12-22 21:51:34 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
destroy : function() {
|
|
|
|
this.actor.destroy();
|
2010-02-18 15:43:58 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_onDestroy: function(actor) {
|
2010-03-17 22:23:32 +00:00
|
|
|
if (this._overviewHiddenId) {
|
|
|
|
Main.overview.disconnect(this._overviewHiddenId);
|
|
|
|
this._overviewHiddenId = 0;
|
|
|
|
}
|
2010-02-18 15:43:58 +00:00
|
|
|
Tweener.removeTweens(actor);
|
2009-02-04 14:50:50 +00:00
|
|
|
|
2011-03-03 21:33:27 +00:00
|
|
|
if (this.metaWorkspace) {
|
|
|
|
this.metaWorkspace.disconnect(this._windowAddedId);
|
|
|
|
this.metaWorkspace.disconnect(this._windowRemovedId);
|
|
|
|
}
|
2011-03-01 08:14:56 +00:00
|
|
|
global.screen.disconnect(this._windowEnteredMonitorId);
|
|
|
|
global.screen.disconnect(this._windowLeftMonitorId);
|
2010-02-07 14:25:16 +00:00
|
|
|
|
2010-02-28 06:56:04 +00:00
|
|
|
if (this._repositionWindowsId > 0)
|
|
|
|
Mainloop.source_remove(this._repositionWindowsId);
|
|
|
|
|
2010-02-07 14:25:16 +00:00
|
|
|
// Usually, the windows will be destroyed automatically with
|
|
|
|
// their parent (this.actor), but we might have a zoomed window
|
|
|
|
// which has been reparented to the stage - _windows[0] holds
|
|
|
|
// the desktop window, which is never reparented
|
2010-07-15 14:21:32 +00:00
|
|
|
for (let w = 0; w < this._windows.length; w++)
|
2010-02-07 14:25:16 +00:00
|
|
|
this._windows[w].destroy();
|
2010-03-17 22:23:32 +00:00
|
|
|
this._windows = [];
|
2008-12-22 21:51:34 +00:00
|
|
|
},
|
|
|
|
|
2009-08-11 11:46:10 +00:00
|
|
|
// Sets this.leavingOverview flag to false.
|
|
|
|
_doneLeavingOverview : function() {
|
|
|
|
this.leavingOverview = false;
|
2009-03-17 22:22:25 +00:00
|
|
|
},
|
|
|
|
|
2011-03-01 08:14:56 +00:00
|
|
|
// Tests if @win belongs to this workspaces and monitor
|
2008-12-22 21:51:34 +00:00
|
|
|
_isMyWindow : function (win) {
|
2011-03-03 21:33:27 +00:00
|
|
|
return (this.metaWorkspace == null || Main.isWindowActorDisplayedOnWorkspace(win, this.metaWorkspace.index())) &&
|
2011-03-01 08:14:56 +00:00
|
|
|
(!win.get_meta_window() || win.get_meta_window().get_monitor() == this.monitorIndex);
|
2008-12-22 21:51:34 +00:00
|
|
|
},
|
|
|
|
|
2009-08-11 11:46:10 +00:00
|
|
|
// Tests if @win should be shown in the Overview
|
|
|
|
_isOverviewWindow : function (win) {
|
2010-03-15 13:50:05 +00:00
|
|
|
let tracker = Shell.WindowTracker.get_default();
|
2009-10-15 23:28:29 +00:00
|
|
|
return tracker.is_window_interesting(win.get_meta_window());
|
2008-12-22 21:51:34 +00:00
|
|
|
},
|
|
|
|
|
2009-01-23 19:21:20 +00:00
|
|
|
// Create a clone of a (non-desktop) window and add it to the window list
|
|
|
|
_addWindowClone : function(win) {
|
2009-01-29 21:21:50 +00:00
|
|
|
let clone = new WindowClone(win);
|
2010-01-22 02:33:48 +00:00
|
|
|
let overlay = new WindowOverlay(clone, this._windowOverlaysGroup);
|
2009-11-12 00:26:52 +00:00
|
|
|
|
2009-01-29 21:21:50 +00:00
|
|
|
clone.connect('selected',
|
|
|
|
Lang.bind(this, this._onCloneSelected));
|
2009-07-23 21:36:41 +00:00
|
|
|
clone.connect('drag-begin',
|
2010-03-16 15:51:24 +00:00
|
|
|
Lang.bind(this, function(clone) {
|
2010-11-15 20:58:27 +00:00
|
|
|
Main.overview.beginWindowDrag();
|
2009-11-12 00:26:52 +00:00
|
|
|
overlay.hide();
|
2009-07-23 21:36:41 +00:00
|
|
|
}));
|
2011-03-08 13:44:47 +00:00
|
|
|
clone.connect('drag-cancelled',
|
|
|
|
Lang.bind(this, function(clone) {
|
|
|
|
Main.overview.cancelledWindowDrag();
|
|
|
|
}));
|
2009-07-23 21:36:41 +00:00
|
|
|
clone.connect('drag-end',
|
2010-03-16 15:51:24 +00:00
|
|
|
Lang.bind(this, function(clone) {
|
2010-11-15 20:58:27 +00:00
|
|
|
Main.overview.endWindowDrag();
|
2009-11-12 00:26:52 +00:00
|
|
|
overlay.show();
|
2009-07-23 21:36:41 +00:00
|
|
|
}));
|
2010-03-21 18:33:52 +00:00
|
|
|
clone.connect('zoom-start',
|
|
|
|
Lang.bind(this, function() {
|
|
|
|
this._windowIsZooming = true;
|
|
|
|
}));
|
|
|
|
clone.connect('zoom-end',
|
|
|
|
Lang.bind(this, function() {
|
|
|
|
this._windowIsZooming = false;
|
|
|
|
}));
|
2011-01-30 22:03:12 +00:00
|
|
|
clone.connect('size-changed',
|
|
|
|
Lang.bind(this, function() {
|
|
|
|
this.positionWindows(0);
|
|
|
|
}));
|
2009-01-23 19:21:20 +00:00
|
|
|
|
2009-01-29 21:21:50 +00:00
|
|
|
this.actor.add_actor(clone.actor);
|
2009-07-23 21:36:41 +00:00
|
|
|
|
2009-11-20 00:39:00 +00:00
|
|
|
overlay.connect('show-close-button', Lang.bind(this, this._onShowOverlayClose));
|
|
|
|
|
2009-01-23 19:21:20 +00:00
|
|
|
this._windows.push(clone);
|
2009-11-12 00:26:52 +00:00
|
|
|
this._windowOverlays.push(overlay);
|
2009-01-23 19:21:20 +00:00
|
|
|
|
2008-12-22 21:51:34 +00:00
|
|
|
return clone;
|
|
|
|
},
|
|
|
|
|
2009-11-20 00:39:00 +00:00
|
|
|
_onShowOverlayClose: function (windowOverlay) {
|
2010-07-15 14:21:32 +00:00
|
|
|
for (let i = 0; i < this._windowOverlays.length; i++) {
|
2009-11-20 00:39:00 +00:00
|
|
|
let overlay = this._windowOverlays[i];
|
|
|
|
if (overlay == windowOverlay)
|
|
|
|
continue;
|
|
|
|
overlay.hideCloseButton();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2009-09-18 19:08:56 +00:00
|
|
|
_computeWindowSlot : function(windowIndex, numberOfWindows) {
|
2008-12-22 21:51:34 +00:00
|
|
|
if (numberOfWindows in POSITIONS)
|
|
|
|
return POSITIONS[numberOfWindows][windowIndex];
|
|
|
|
|
|
|
|
// If we don't have a predefined scheme for this window count,
|
2009-03-31 21:40:18 +00:00
|
|
|
// arrange the windows in a grid pattern.
|
|
|
|
let gridWidth = Math.ceil(Math.sqrt(numberOfWindows));
|
|
|
|
let gridHeight = Math.ceil(numberOfWindows / gridWidth);
|
|
|
|
|
2009-08-08 20:10:40 +00:00
|
|
|
let fraction = 0.95 * (1. / gridWidth);
|
2009-03-31 21:40:18 +00:00
|
|
|
|
|
|
|
let xCenter = (.5 / gridWidth) + ((windowIndex) % gridWidth) / gridWidth;
|
|
|
|
let yCenter = (.5 / gridHeight) + Math.floor((windowIndex / gridWidth)) / gridHeight;
|
2008-12-22 21:51:34 +00:00
|
|
|
|
|
|
|
return [xCenter, yCenter, fraction];
|
|
|
|
},
|
2009-01-21 20:35:20 +00:00
|
|
|
|
2009-09-18 19:08:56 +00:00
|
|
|
_computeAllWindowSlots: function(totalWindows) {
|
|
|
|
let slots = [];
|
|
|
|
for (let i = 0; i < totalWindows; i++) {
|
|
|
|
slots.push(this._computeWindowSlot(i, totalWindows));
|
|
|
|
}
|
|
|
|
return slots;
|
|
|
|
},
|
|
|
|
|
2009-01-29 21:21:50 +00:00
|
|
|
_onCloneSelected : function (clone, time) {
|
2011-03-03 21:33:27 +00:00
|
|
|
let wsIndex = undefined;
|
|
|
|
if (this.metaWorkspace)
|
|
|
|
wsIndex = this.metaWorkspace.index();
|
|
|
|
Main.activateWindow(clone.metaWindow, time, wsIndex);
|
2008-12-22 22:06:47 +00:00
|
|
|
},
|
|
|
|
|
2009-02-10 16:15:59 +00:00
|
|
|
// Draggable target interface
|
2010-09-10 02:00:28 +00:00
|
|
|
handleDragOver : function(source, actor, x, y, time) {
|
2011-02-14 22:13:25 +00:00
|
|
|
if (source.realWindow && !this._isMyWindow(source.realWindow))
|
2010-09-10 02:00:28 +00:00
|
|
|
return DND.DragMotionResult.MOVE_DROP;
|
|
|
|
if (source.shellWorkspaceLaunch)
|
|
|
|
return DND.DragMotionResult.COPY_DROP;
|
|
|
|
|
|
|
|
return DND.DragMotionResult.CONTINUE;
|
|
|
|
},
|
|
|
|
|
2009-02-10 16:15:59 +00:00
|
|
|
acceptDrop : function(source, actor, x, y, time) {
|
2011-01-31 01:25:00 +00:00
|
|
|
if (source.realWindow) {
|
2009-02-10 16:15:59 +00:00
|
|
|
let win = source.realWindow;
|
|
|
|
if (this._isMyWindow(win))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Set a hint on the Mutter.Window so its initial position
|
|
|
|
// in the new workspace will be correct
|
2009-08-11 11:46:10 +00:00
|
|
|
win._overviewHint = {
|
2009-02-10 16:15:59 +00:00
|
|
|
x: actor.x,
|
|
|
|
y: actor.y,
|
|
|
|
scale: actor.scale_x
|
|
|
|
};
|
|
|
|
|
|
|
|
let metaWindow = win.get_meta_window();
|
2011-03-03 21:33:27 +00:00
|
|
|
|
|
|
|
// We need to move the window before changing the workspace, because
|
|
|
|
// the move itself could cause a workspace change if the window enters
|
|
|
|
// the primary monitor
|
|
|
|
if (metaWindow.get_monitor() != this.monitorIndex)
|
2011-03-17 17:48:09 +00:00
|
|
|
metaWindow.move_to_monitor(this.monitorIndex);
|
2011-03-03 21:33:27 +00:00
|
|
|
|
|
|
|
let index = this.metaWorkspace ? this.metaWorkspace.index() : global.screen.get_active_workspace_index();
|
|
|
|
metaWindow.change_workspace_by_index(index,
|
2009-02-10 16:15:59 +00:00
|
|
|
false, // don't create workspace
|
|
|
|
time);
|
|
|
|
return true;
|
2009-08-18 00:29:54 +00:00
|
|
|
} else if (source.shellWorkspaceLaunch) {
|
2011-01-30 21:09:58 +00:00
|
|
|
source.shellWorkspaceLaunch({ workspace: this.metaWorkspace,
|
|
|
|
timestamp: time });
|
2009-02-10 16:15:59 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2008-12-22 21:51:34 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-01-23 19:21:20 +00:00
|
|
|
Signals.addSignalMethods(Workspace.prototype);
|