Compare commits
2 Commits
citadel
...
wip/gcampa
Author | SHA1 | Date | |
---|---|---|---|
|
6d4ca1fcc8 | ||
|
93b1af401f |
@ -174,15 +174,6 @@ const WindowManager = new Lang.Class({
|
|||||||
Meta.KeyBindingFlags.NONE,
|
Meta.KeyBindingFlags.NONE,
|
||||||
Shell.KeyBindingMode.NORMAL,
|
Shell.KeyBindingMode.NORMAL,
|
||||||
Lang.bind(this, this._openAppMenu));
|
Lang.bind(this, this._openAppMenu));
|
||||||
|
|
||||||
Main.overview.connect('showing', Lang.bind(this, function() {
|
|
||||||
for (let i = 0; i < this._dimmedWindows.length; i++)
|
|
||||||
this._undimWindow(this._dimmedWindows[i]);
|
|
||||||
}));
|
|
||||||
Main.overview.connect('hiding', Lang.bind(this, function() {
|
|
||||||
for (let i = 0; i < this._dimmedWindows.length; i++)
|
|
||||||
this._dimWindow(this._dimmedWindows[i]);
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setCustomKeybindingHandler: function(name, modes, handler) {
|
setCustomKeybindingHandler: function(name, modes, handler) {
|
||||||
@ -342,15 +333,13 @@ const WindowManager = new Lang.Class({
|
|||||||
if (shouldDim && !window._dimmed) {
|
if (shouldDim && !window._dimmed) {
|
||||||
window._dimmed = true;
|
window._dimmed = true;
|
||||||
this._dimmedWindows.push(window);
|
this._dimmedWindows.push(window);
|
||||||
if (!Main.overview.visible)
|
this._dimWindow(window);
|
||||||
this._dimWindow(window);
|
|
||||||
} else if (!shouldDim && window._dimmed) {
|
} else if (!shouldDim && window._dimmed) {
|
||||||
window._dimmed = false;
|
window._dimmed = false;
|
||||||
this._dimmedWindows = this._dimmedWindows.filter(function(win) {
|
this._dimmedWindows = this._dimmedWindows.filter(function(win) {
|
||||||
return win != window;
|
return win != window;
|
||||||
});
|
});
|
||||||
if (!Main.overview.visible)
|
this._undimWindow(window);
|
||||||
this._undimWindow(window);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ const Main = imports.ui.main;
|
|||||||
const Overview = imports.ui.overview;
|
const Overview = imports.ui.overview;
|
||||||
const Panel = imports.ui.panel;
|
const Panel = imports.ui.panel;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
|
const WindowManager = imports.ui.windowManager;
|
||||||
|
|
||||||
const FOCUS_ANIMATION_TIME = 0.15;
|
const FOCUS_ANIMATION_TIME = 0.15;
|
||||||
|
|
||||||
@ -41,6 +42,68 @@ function _interpolate(start, end, step) {
|
|||||||
return start + (end - start) * step;
|
return start + (end - start) * step;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const WindowCloneLayout = new Lang.Class({
|
||||||
|
Name: 'WindowCloneLayout',
|
||||||
|
Extends: Clutter.LayoutManager,
|
||||||
|
|
||||||
|
_init: function(boundingBox) {
|
||||||
|
this.parent();
|
||||||
|
|
||||||
|
this._boundingBox = boundingBox;
|
||||||
|
},
|
||||||
|
|
||||||
|
get boundingBox() {
|
||||||
|
return this._boundingBox;
|
||||||
|
},
|
||||||
|
|
||||||
|
set boundingBox(b) {
|
||||||
|
this._boundingBox = b;
|
||||||
|
this.layout_changed();
|
||||||
|
},
|
||||||
|
|
||||||
|
_makeBoxForWindow: function(window) {
|
||||||
|
// We need to adjust the position of the actor because of the
|
||||||
|
// consequences of invisible borders -- in reality, the texture
|
||||||
|
// has an extra set of "padding" around it that we need to trim
|
||||||
|
// down.
|
||||||
|
|
||||||
|
// The outer rect (from which we compute the bounding box)
|
||||||
|
// paradoxically is the smaller rectangle, containing the positions
|
||||||
|
// of the visible frame. The input rect contains everything,
|
||||||
|
// including the invisible border padding.
|
||||||
|
let inputRect = window.get_input_rect();
|
||||||
|
|
||||||
|
let box = new Clutter.ActorBox();
|
||||||
|
|
||||||
|
box.set_origin(inputRect.x - this._boundingBox.x,
|
||||||
|
inputRect.y - this._boundingBox.y);
|
||||||
|
box.set_size(inputRect.width, inputRect.height);
|
||||||
|
|
||||||
|
return box;
|
||||||
|
},
|
||||||
|
|
||||||
|
vfunc_get_preferred_height: function(container, forWidth) {
|
||||||
|
return [this._boundingBox.height, this._boundingBox.height];
|
||||||
|
},
|
||||||
|
|
||||||
|
vfunc_get_preferred_width: function(container, forHeight) {
|
||||||
|
return [this._boundingBox.width, this._boundingBox.width];
|
||||||
|
},
|
||||||
|
|
||||||
|
vfunc_allocate: function(container, box, flags) {
|
||||||
|
let clone = container.get_children().forEach(function (child) {
|
||||||
|
let realWindow;
|
||||||
|
if (child == container._delegate._windowClone)
|
||||||
|
realWindow = container._delegate.realWindow;
|
||||||
|
else
|
||||||
|
realWindow = child.source;
|
||||||
|
|
||||||
|
child.allocate(this._makeBoxForWindow(realWindow.meta_window),
|
||||||
|
flags);
|
||||||
|
}, this);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const WindowClone = new Lang.Class({
|
const WindowClone = new Lang.Class({
|
||||||
Name: 'WindowClone',
|
Name: 'WindowClone',
|
||||||
|
|
||||||
@ -50,10 +113,7 @@ const WindowClone = new Lang.Class({
|
|||||||
this.metaWindow._delegate = this;
|
this.metaWindow._delegate = this;
|
||||||
this._workspace = workspace;
|
this._workspace = workspace;
|
||||||
|
|
||||||
let [borderX, borderY] = this._getInvisibleBorderPadding();
|
this._windowClone = new Clutter.Clone({ source: realWindow.get_texture() });
|
||||||
this._windowClone = new Clutter.Clone({ source: realWindow.get_texture(),
|
|
||||||
x: -borderX,
|
|
||||||
y: -borderY });
|
|
||||||
// We expect this.actor to be used for all interaction rather than
|
// We expect this.actor to be used for all interaction rather than
|
||||||
// this._windowClone; as the former is reactive and the latter
|
// this._windowClone; as the former is reactive and the latter
|
||||||
// is not, this just works for most cases. However, for DND all
|
// is not, this just works for most cases. However, for DND all
|
||||||
@ -61,20 +121,15 @@ const WindowClone = new Lang.Class({
|
|||||||
// To avoid this, we hide it from pick.
|
// To avoid this, we hide it from pick.
|
||||||
Shell.util_set_hidden_from_pick(this._windowClone, true);
|
Shell.util_set_hidden_from_pick(this._windowClone, true);
|
||||||
|
|
||||||
this.origX = realWindow.x + borderX;
|
|
||||||
this.origY = realWindow.y + borderY;
|
|
||||||
|
|
||||||
let outerRect = realWindow.meta_window.get_outer_rect();
|
|
||||||
|
|
||||||
// The MetaShapedTexture that we clone has a size that includes
|
// The MetaShapedTexture that we clone has a size that includes
|
||||||
// the invisible border; this is inconvenient; rather than trying
|
// the invisible border; this is inconvenient; rather than trying
|
||||||
// to compensate all over the place we insert a ClutterActor into
|
// to compensate all over the place we insert a custom container into
|
||||||
// the hierarchy that is sized to only the visible portion.
|
// the hierarchy that is sized to only the visible portion.
|
||||||
|
// As usual, we cannot use a ShellGenericContainer or StWidget here,
|
||||||
|
// because Workspace plays dirty tricks with reparenting to do DNDs
|
||||||
|
// and scroll-to-zoom.
|
||||||
this.actor = new Clutter.Actor({ reactive: true,
|
this.actor = new Clutter.Actor({ reactive: true,
|
||||||
x: this.origX,
|
layout_manager: new WindowCloneLayout() });
|
||||||
y: this.origY,
|
|
||||||
width: outerRect.width,
|
|
||||||
height: outerRect.height });
|
|
||||||
|
|
||||||
this.actor.add_child(this._windowClone);
|
this.actor.add_child(this._windowClone);
|
||||||
|
|
||||||
@ -84,10 +139,19 @@ const WindowClone = new Lang.Class({
|
|||||||
this._dragSlot = [0, 0, 0, 0];
|
this._dragSlot = [0, 0, 0, 0];
|
||||||
this._stackAbove = null;
|
this._stackAbove = null;
|
||||||
|
|
||||||
this._sizeChangedId = this.realWindow.connect('size-changed',
|
this._windowClone._updateId = this.realWindow.connect('size-changed',
|
||||||
Lang.bind(this, this._onRealWindowSizeChanged));
|
Lang.bind(this, this._onRealWindowSizeChanged));
|
||||||
this._realWindowDestroyId = this.realWindow.connect('destroy',
|
this._windowClone._destroyId = this.realWindow.connect('destroy', Lang.bind(this, function() {
|
||||||
Lang.bind(this, this._disconnectRealWindowSignals));
|
// First destroy the clone and then destroy everything
|
||||||
|
// This will ensure that we never see it in the _disconnectSignals loop
|
||||||
|
this._windowClone.destroy();
|
||||||
|
this.destroy();
|
||||||
|
}));
|
||||||
|
|
||||||
|
this._updateAttachedDialogs();
|
||||||
|
this._computeBoundingBox();
|
||||||
|
this.actor.x = this._boundingBox.x;
|
||||||
|
this.actor.y = this._boundingBox.y;
|
||||||
|
|
||||||
let clickAction = new Clutter.ClickAction();
|
let clickAction = new Clutter.ClickAction();
|
||||||
clickAction.connect('clicked', Lang.bind(this, this._onClicked));
|
clickAction.connect('clicked', Lang.bind(this, this._onClicked));
|
||||||
@ -121,6 +185,97 @@ const WindowClone = new Lang.Class({
|
|||||||
return this._slot;
|
return this._slot;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
deleteAll: function() {
|
||||||
|
// Delete all windows, starting from the bottom-most (most-modal) one
|
||||||
|
|
||||||
|
let windows = this.actor.get_children();
|
||||||
|
for (let i = windows.length - 1; i >= 1; i--) {
|
||||||
|
let realWindow = windows[i].source;
|
||||||
|
let metaWindow = realWindow.meta_window;
|
||||||
|
|
||||||
|
metaWindow.delete(global.get_current_time());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.metaWindow.delete(global.get_current_time());
|
||||||
|
},
|
||||||
|
|
||||||
|
addAttachedDialog: function(win) {
|
||||||
|
this._doAddAttachedDialog(win, win.get_compositor_private());
|
||||||
|
this._computeBoundingBox();
|
||||||
|
this._updateDimmer();
|
||||||
|
this.emit('size-changed');
|
||||||
|
},
|
||||||
|
|
||||||
|
_doAddAttachedDialog: function(metaWin, realWin) {
|
||||||
|
let clone = new Clutter.Clone({ source: realWin });
|
||||||
|
clone._updateId = realWin.connect('size-changed', Lang.bind(this, function() {
|
||||||
|
this._computeBoundingBox();
|
||||||
|
this.emit('size-changed');
|
||||||
|
}));
|
||||||
|
clone._destroyId = realWin.connect('destroy', Lang.bind(this, function() {
|
||||||
|
clone.destroy();
|
||||||
|
|
||||||
|
this._computeBoundingBox();
|
||||||
|
this._updateDimmer();
|
||||||
|
this.emit('size-changed');
|
||||||
|
}));
|
||||||
|
this.actor.add_child(clone);
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateAttachedDialogs: function() {
|
||||||
|
let iter = Lang.bind(this, function(win) {
|
||||||
|
let actor = win.get_compositor_private();
|
||||||
|
|
||||||
|
if (!actor)
|
||||||
|
return false;
|
||||||
|
if (!win.is_attached_dialog())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
this._doAddAttachedDialog(win, actor);
|
||||||
|
win.foreach_transient(iter);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
this.metaWindow.foreach_transient(iter);
|
||||||
|
|
||||||
|
this._dimmer = new WindowManager.WindowDimmer(this._windowClone);
|
||||||
|
this._updateDimmer();
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateDimmer: function() {
|
||||||
|
if (this.actor.get_n_children() > 1) {
|
||||||
|
this._dimmer.setEnabled(true);
|
||||||
|
this._dimmer.dimFactor = 1.0;
|
||||||
|
} else {
|
||||||
|
this._dimmer.setEnabled(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
get boundingBox() {
|
||||||
|
return this._boundingBox;
|
||||||
|
},
|
||||||
|
|
||||||
|
getOriginalPosition: function() {
|
||||||
|
return [this._boundingBox.x, this._boundingBox.y];
|
||||||
|
},
|
||||||
|
|
||||||
|
_computeBoundingBox: function() {
|
||||||
|
let rect = this.metaWindow.get_outer_rect();
|
||||||
|
|
||||||
|
this.actor.get_children().forEach(function (child) {
|
||||||
|
let realWindow;
|
||||||
|
if (child == this._windowClone)
|
||||||
|
realWindow = this.realWindow;
|
||||||
|
else
|
||||||
|
realWindow = child.source;
|
||||||
|
|
||||||
|
let metaWindow = realWindow.meta_window;
|
||||||
|
rect = rect.union(metaWindow.get_outer_rect());
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
this._boundingBox = rect;
|
||||||
|
this.actor.layout_manager.boundingBox = rect;
|
||||||
|
},
|
||||||
|
|
||||||
setStackAbove: function (actor) {
|
setStackAbove: function (actor) {
|
||||||
this._stackAbove = actor;
|
this._stackAbove = actor;
|
||||||
if (this.inDrag)
|
if (this.inDrag)
|
||||||
@ -136,44 +291,26 @@ const WindowClone = new Lang.Class({
|
|||||||
this.actor.destroy();
|
this.actor.destroy();
|
||||||
},
|
},
|
||||||
|
|
||||||
_disconnectRealWindowSignals: function() {
|
_disconnectSignals: function() {
|
||||||
if (this._sizeChangedId > 0)
|
this.actor.get_children().forEach(Lang.bind(this, function (child) {
|
||||||
this.realWindow.disconnect(this._sizeChangedId);
|
let realWindow;
|
||||||
this._sizeChangedId = 0;
|
if (child == this._windowClone)
|
||||||
|
realWindow = this.realWindow;
|
||||||
|
else
|
||||||
|
realWindow = child.source;
|
||||||
|
|
||||||
if (this._realWindowDestroyId > 0)
|
realWindow.disconnect(child._updateId);
|
||||||
this.realWindow.disconnect(this._realWindowDestroyId);
|
realWindow.disconnect(child._destroyId);
|
||||||
this._realWindowDestroyId = 0;
|
}));
|
||||||
},
|
|
||||||
|
|
||||||
_getInvisibleBorderPadding: function() {
|
|
||||||
// We need to adjust the position of the actor because of the
|
|
||||||
// consequences of invisible borders -- in reality, the texture
|
|
||||||
// has an extra set of "padding" around it that we need to trim
|
|
||||||
// down.
|
|
||||||
|
|
||||||
// The outer rect paradoxically is the smaller rectangle,
|
|
||||||
// containing the positions of the visible frame. The input
|
|
||||||
// rect contains everything, including the invisible border
|
|
||||||
// padding.
|
|
||||||
let outerRect = this.metaWindow.get_outer_rect();
|
|
||||||
let inputRect = this.metaWindow.get_input_rect();
|
|
||||||
let [borderX, borderY] = [outerRect.x - inputRect.x,
|
|
||||||
outerRect.y - inputRect.y];
|
|
||||||
|
|
||||||
return [borderX, borderY];
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onRealWindowSizeChanged: function() {
|
_onRealWindowSizeChanged: function() {
|
||||||
let [borderX, borderY] = this._getInvisibleBorderPadding();
|
this._computeBoundingBox();
|
||||||
let outerRect = this.metaWindow.get_outer_rect();
|
|
||||||
this.actor.set_size(outerRect.width, outerRect.height);
|
|
||||||
this._windowClone.set_position(-borderX, -borderY);
|
|
||||||
this.emit('size-changed');
|
this.emit('size-changed');
|
||||||
},
|
},
|
||||||
|
|
||||||
_onDestroy: function() {
|
_onDestroy: function() {
|
||||||
this._disconnectRealWindowSignals();
|
this._disconnectSignals();
|
||||||
|
|
||||||
this.metaWindow._delegate = null;
|
this.metaWindow._delegate = null;
|
||||||
this.actor._delegate = null;
|
this.actor._delegate = null;
|
||||||
@ -432,7 +569,7 @@ const WindowOverlay = new Lang.Class({
|
|||||||
Lang.bind(this,
|
Lang.bind(this,
|
||||||
this._onWindowAdded));
|
this._onWindowAdded));
|
||||||
|
|
||||||
metaWindow.delete(global.get_current_time());
|
this._windowClone.deleteAll();
|
||||||
},
|
},
|
||||||
|
|
||||||
_onWindowAdded: function(workspace, win) {
|
_onWindowAdded: function(workspace, win) {
|
||||||
@ -1220,9 +1357,29 @@ const Workspace = new Lang.Class({
|
|||||||
if (this._lookupIndex (metaWin) != -1)
|
if (this._lookupIndex (metaWin) != -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!this._isMyWindow(win) || !this._isOverviewWindow(win))
|
if (!this._isMyWindow(win))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!this._isOverviewWindow(win)) {
|
||||||
|
if (metaWin.is_attached_dialog()) {
|
||||||
|
let parent = metaWin.get_transient_for();
|
||||||
|
while (parent.is_attached_dialog())
|
||||||
|
parent = metaWin.get_transient_for();
|
||||||
|
|
||||||
|
let idx = this._lookupIndex (parent);
|
||||||
|
if (idx < 0) {
|
||||||
|
// parent was not created yet, it will take care
|
||||||
|
// of the dialog when created
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let clone = this._windows[idx];
|
||||||
|
clone.addAttachedDialog(metaWin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let [clone, overlay] = this._addWindowClone(win);
|
let [clone, overlay] = this._addWindowClone(win);
|
||||||
|
|
||||||
if (win._overviewHint) {
|
if (win._overviewHint) {
|
||||||
@ -1321,9 +1478,11 @@ const Workspace = new Lang.Class({
|
|||||||
overlay.hide();
|
overlay.hide();
|
||||||
|
|
||||||
if (clone.metaWindow.showing_on_its_workspace()) {
|
if (clone.metaWindow.showing_on_its_workspace()) {
|
||||||
|
let [origX, origY] = clone.getOriginalPosition();
|
||||||
|
|
||||||
Tweener.addTween(clone.actor,
|
Tweener.addTween(clone.actor,
|
||||||
{ x: clone.origX,
|
{ x: origX,
|
||||||
y: clone.origY,
|
y: origY,
|
||||||
scale_x: 1.0,
|
scale_x: 1.0,
|
||||||
scale_y: 1.0,
|
scale_y: 1.0,
|
||||||
time: Overview.ANIMATION_TIME,
|
time: Overview.ANIMATION_TIME,
|
||||||
|
@ -13,6 +13,7 @@ const Background = imports.ui.background;
|
|||||||
const DND = imports.ui.dnd;
|
const DND = imports.ui.dnd;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
|
const WindowManager = imports.ui.windowManager;
|
||||||
const Workspace = imports.ui.workspace;
|
const Workspace = imports.ui.workspace;
|
||||||
const WorkspacesView = imports.ui.workspacesView;
|
const WorkspacesView = imports.ui.workspacesView;
|
||||||
|
|
||||||
@ -31,20 +32,49 @@ const WORKSPACE_KEEP_ALIVE_TIME = 100;
|
|||||||
|
|
||||||
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
|
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
|
||||||
|
|
||||||
|
/* A layout manager that requests size only for primary_actor, but then allocates
|
||||||
|
all using a fixed layout */
|
||||||
|
const PrimaryActorLayout = new Lang.Class({
|
||||||
|
Name: 'PrimaryActorLayout',
|
||||||
|
Extends: Clutter.FixedLayout,
|
||||||
|
|
||||||
|
_init: function(primaryActor) {
|
||||||
|
this.parent();
|
||||||
|
|
||||||
|
this.primaryActor = primaryActor;
|
||||||
|
},
|
||||||
|
|
||||||
|
vfunc_get_preferred_width: function(forHeight) {
|
||||||
|
return this.primaryActor.get_preferred_width(forHeight);
|
||||||
|
},
|
||||||
|
|
||||||
|
vfunc_get_preferred_height: function(forWidth) {
|
||||||
|
return this.primaryActor.get_preferred_height(forWidth);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const WindowClone = new Lang.Class({
|
const WindowClone = new Lang.Class({
|
||||||
Name: 'WindowClone',
|
Name: 'WindowClone',
|
||||||
|
|
||||||
_init : function(realWindow) {
|
_init : function(realWindow) {
|
||||||
this.actor = new Clutter.Clone({ source: realWindow.get_texture(),
|
this.clone = new Clutter.Clone({ source: realWindow });
|
||||||
|
|
||||||
|
/* Can't use a Shell.GenericContainer because of DND and reparenting... */
|
||||||
|
this.actor = new Clutter.Actor({ layout_manager: new PrimaryActorLayout(this.clone),
|
||||||
reactive: true });
|
reactive: true });
|
||||||
this.actor._delegate = this;
|
this.actor._delegate = this;
|
||||||
|
this.actor.add_child(this.clone);
|
||||||
this.realWindow = realWindow;
|
this.realWindow = realWindow;
|
||||||
this.metaWindow = realWindow.meta_window;
|
this.metaWindow = realWindow.meta_window;
|
||||||
|
|
||||||
this._positionChangedId = this.realWindow.connect('position-changed',
|
this.clone._updateId = this.realWindow.connect('position-changed',
|
||||||
Lang.bind(this, this._onPositionChanged));
|
Lang.bind(this, this._onPositionChanged));
|
||||||
this._realWindowDestroyedId = this.realWindow.connect('destroy',
|
this.clone._destroyId = this.realWindow.connect('destroy', Lang.bind(this, function() {
|
||||||
Lang.bind(this, this._disconnectRealWindowSignals));
|
// First destroy the clone and then destroy everything
|
||||||
|
// This will ensure that we never see it in the _disconnectSignals loop
|
||||||
|
this.clone.destroy();
|
||||||
|
this.destroy();
|
||||||
|
}));
|
||||||
this._onPositionChanged();
|
this._onPositionChanged();
|
||||||
|
|
||||||
this.actor.connect('button-release-event',
|
this.actor.connect('button-release-event',
|
||||||
@ -60,6 +90,24 @@ const WindowClone = new Lang.Class({
|
|||||||
this._draggable.connect('drag-cancelled', Lang.bind(this, this._onDragCancelled));
|
this._draggable.connect('drag-cancelled', Lang.bind(this, this._onDragCancelled));
|
||||||
this._draggable.connect('drag-end', Lang.bind(this, this._onDragEnd));
|
this._draggable.connect('drag-end', Lang.bind(this, this._onDragEnd));
|
||||||
this.inDrag = false;
|
this.inDrag = false;
|
||||||
|
|
||||||
|
let iter = Lang.bind(this, function(win) {
|
||||||
|
let actor = win.get_compositor_private();
|
||||||
|
|
||||||
|
if (!actor)
|
||||||
|
return false;
|
||||||
|
if (!win.is_attached_dialog())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
this._doAddAttachedDialog(win, actor);
|
||||||
|
win.foreach_transient(iter);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
this.metaWindow.foreach_transient(iter);
|
||||||
|
|
||||||
|
this._dimmer = new WindowManager.WindowDimmer(this.clone);
|
||||||
|
this._updateDimmer();
|
||||||
},
|
},
|
||||||
|
|
||||||
setStackAbove: function (actor) {
|
setStackAbove: function (actor) {
|
||||||
@ -74,25 +122,57 @@ const WindowClone = new Lang.Class({
|
|||||||
this.actor.destroy();
|
this.actor.destroy();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
addAttachedDialog: function(win) {
|
||||||
|
this._doAddAttachedDialog(win, win.get_compositor_private());
|
||||||
|
this._updateDimmer();
|
||||||
|
},
|
||||||
|
|
||||||
|
_doAddAttachedDialog: function(metaDialog, realDialog) {
|
||||||
|
let clone = new Clutter.Clone({ source: realDialog });
|
||||||
|
this._updateDialogPosition(realDialog, clone);
|
||||||
|
|
||||||
|
clone._updateId = realDialog.connect('position-changed',
|
||||||
|
Lang.bind(this, this._updateDialogPosition, clone));
|
||||||
|
clone._destroyId = realDialog.connect('destroy', Lang.bind(this, function() {
|
||||||
|
clone.destroy();
|
||||||
|
this._updateDimmer();
|
||||||
|
}));
|
||||||
|
this.actor.add_child(clone);
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateDimmer: function() {
|
||||||
|
if (this.actor.get_n_children() > 1) {
|
||||||
|
this._dimmer.setEnabled(true);
|
||||||
|
this._dimmer.dimFactor = 1.0;
|
||||||
|
} else {
|
||||||
|
this._dimmer.setEnabled(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateDialogPosition: function(realDialog, cloneDialog) {
|
||||||
|
let metaDialog = realDialog.meta_window;
|
||||||
|
let dialogRect = metaDialog.get_outer_rect();
|
||||||
|
let rect = this.metaWindow.get_outer_rect();
|
||||||
|
|
||||||
|
cloneDialog.set_position(dialogRect.x - rect.x, dialogRect.y - rect.y);
|
||||||
|
},
|
||||||
|
|
||||||
_onPositionChanged: function() {
|
_onPositionChanged: function() {
|
||||||
let rect = this.metaWindow.get_outer_rect();
|
let rect = this.metaWindow.get_outer_rect();
|
||||||
this.actor.set_position(this.realWindow.x, this.realWindow.y);
|
this.actor.set_position(this.realWindow.x, this.realWindow.y);
|
||||||
},
|
},
|
||||||
|
|
||||||
_disconnectRealWindowSignals: function() {
|
_disconnectSignals: function() {
|
||||||
if (this._positionChangedId != 0) {
|
this.actor.get_children().forEach(function(child) {
|
||||||
this.realWindow.disconnect(this._positionChangedId);
|
let realWindow = child.source;
|
||||||
this._positionChangedId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._realWindowDestroyedId != 0) {
|
realWindow.disconnect(child._updateId);
|
||||||
this.realWindow.disconnect(this._realWindowDestroyedId);
|
realWindow.disconnect(child._destroyId);
|
||||||
this._realWindowDestroyedId = 0;
|
});
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onDestroy: function() {
|
_onDestroy: function() {
|
||||||
this._disconnectRealWindowSignals();
|
this._disconnectSignals();
|
||||||
|
|
||||||
this.actor._delegate = null;
|
this.actor._delegate = null;
|
||||||
|
|
||||||
@ -320,10 +400,26 @@ const WorkspaceThumbnail = new Lang.Class({
|
|||||||
if (this._lookupIndex (metaWin) != -1)
|
if (this._lookupIndex (metaWin) != -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!this._isMyWindow(win) || !this._isOverviewWindow(win))
|
if (!this._isMyWindow(win))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let clone = this._addWindowClone(win);
|
if (this._isOverviewWindow(win)) {
|
||||||
|
this._addWindowClone(win);
|
||||||
|
} else if (metaWin.is_attached_dialog()) {
|
||||||
|
let parent = metaWin.get_transient_for();
|
||||||
|
while (parent.is_attached_dialog())
|
||||||
|
parent = metaWin.get_transient_for();
|
||||||
|
|
||||||
|
let idx = this._lookupIndex (parent);
|
||||||
|
if (idx < 0) {
|
||||||
|
// parent was not created yet, it will take care
|
||||||
|
// of the dialog when created
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let clone = this._windows[idx];
|
||||||
|
clone.addAttachedDialog(metaWin);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_windowAdded : function(metaWorkspace, metaWin) {
|
_windowAdded : function(metaWorkspace, metaWin) {
|
||||||
|
Loading…
Reference in New Issue
Block a user