Compare commits
	
		
			2 Commits
		
	
	
		
			gbsneto/ne
			...
			wip/gcampa
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					6d4ca1fcc8 | ||
| 
						 | 
					93b1af401f | 
@@ -174,15 +174,6 @@ const WindowManager = new Lang.Class({
 | 
			
		||||
                           Meta.KeyBindingFlags.NONE,
 | 
			
		||||
                           Shell.KeyBindingMode.NORMAL,
 | 
			
		||||
                           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) {
 | 
			
		||||
@@ -342,15 +333,13 @@ const WindowManager = new Lang.Class({
 | 
			
		||||
        if (shouldDim && !window._dimmed) {
 | 
			
		||||
            window._dimmed = true;
 | 
			
		||||
            this._dimmedWindows.push(window);
 | 
			
		||||
            if (!Main.overview.visible)
 | 
			
		||||
                this._dimWindow(window);
 | 
			
		||||
            this._dimWindow(window);
 | 
			
		||||
        } else if (!shouldDim && window._dimmed) {
 | 
			
		||||
            window._dimmed = false;
 | 
			
		||||
            this._dimmedWindows = this._dimmedWindows.filter(function(win) {
 | 
			
		||||
                                                                 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 Panel = imports.ui.panel;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
const WindowManager = imports.ui.windowManager;
 | 
			
		||||
 | 
			
		||||
const FOCUS_ANIMATION_TIME = 0.15;
 | 
			
		||||
 | 
			
		||||
@@ -41,6 +42,68 @@ function _interpolate(start, end, 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({
 | 
			
		||||
    Name: 'WindowClone',
 | 
			
		||||
 | 
			
		||||
@@ -50,10 +113,7 @@ const WindowClone = new Lang.Class({
 | 
			
		||||
        this.metaWindow._delegate = this;
 | 
			
		||||
        this._workspace = workspace;
 | 
			
		||||
 | 
			
		||||
        let [borderX, borderY] = this._getInvisibleBorderPadding();
 | 
			
		||||
        this._windowClone = new Clutter.Clone({ source: realWindow.get_texture(),
 | 
			
		||||
                                                x: -borderX,
 | 
			
		||||
                                                y: -borderY });
 | 
			
		||||
        this._windowClone = new Clutter.Clone({ source: realWindow.get_texture() });
 | 
			
		||||
        // We expect this.actor to be used for all interaction rather than
 | 
			
		||||
        // this._windowClone; as the former is reactive and the latter
 | 
			
		||||
        // 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.
 | 
			
		||||
        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 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.
 | 
			
		||||
        // 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,
 | 
			
		||||
                                         x: this.origX,
 | 
			
		||||
                                         y: this.origY,
 | 
			
		||||
                                         width: outerRect.width,
 | 
			
		||||
                                         height: outerRect.height });
 | 
			
		||||
                                         layout_manager: new WindowCloneLayout() });
 | 
			
		||||
 | 
			
		||||
        this.actor.add_child(this._windowClone);
 | 
			
		||||
 | 
			
		||||
@@ -84,10 +139,19 @@ const WindowClone = new Lang.Class({
 | 
			
		||||
        this._dragSlot = [0, 0, 0, 0];
 | 
			
		||||
        this._stackAbove = null;
 | 
			
		||||
 | 
			
		||||
        this._sizeChangedId = this.realWindow.connect('size-changed',
 | 
			
		||||
        this._windowClone._updateId = this.realWindow.connect('size-changed',
 | 
			
		||||
            Lang.bind(this, this._onRealWindowSizeChanged));
 | 
			
		||||
        this._realWindowDestroyId = this.realWindow.connect('destroy',
 | 
			
		||||
            Lang.bind(this, this._disconnectRealWindowSignals));
 | 
			
		||||
        this._windowClone._destroyId = this.realWindow.connect('destroy', Lang.bind(this, function() {
 | 
			
		||||
            // 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();
 | 
			
		||||
        clickAction.connect('clicked', Lang.bind(this, this._onClicked));
 | 
			
		||||
@@ -121,6 +185,97 @@ const WindowClone = new Lang.Class({
 | 
			
		||||
            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) {
 | 
			
		||||
        this._stackAbove = actor;
 | 
			
		||||
        if (this.inDrag)
 | 
			
		||||
@@ -136,44 +291,26 @@ const WindowClone = new Lang.Class({
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _disconnectRealWindowSignals: function() {
 | 
			
		||||
        if (this._sizeChangedId > 0)
 | 
			
		||||
            this.realWindow.disconnect(this._sizeChangedId);
 | 
			
		||||
        this._sizeChangedId = 0;
 | 
			
		||||
    _disconnectSignals: function() {
 | 
			
		||||
        this.actor.get_children().forEach(Lang.bind(this, function (child) {
 | 
			
		||||
            let realWindow;
 | 
			
		||||
            if (child == this._windowClone)
 | 
			
		||||
                realWindow = this.realWindow;
 | 
			
		||||
            else
 | 
			
		||||
                realWindow = child.source;
 | 
			
		||||
 | 
			
		||||
        if (this._realWindowDestroyId > 0)
 | 
			
		||||
            this.realWindow.disconnect(this._realWindowDestroyId);
 | 
			
		||||
        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];
 | 
			
		||||
            realWindow.disconnect(child._updateId);
 | 
			
		||||
            realWindow.disconnect(child._destroyId);
 | 
			
		||||
        }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onRealWindowSizeChanged: function() {
 | 
			
		||||
        let [borderX, borderY] = this._getInvisibleBorderPadding();
 | 
			
		||||
        let outerRect = this.metaWindow.get_outer_rect();
 | 
			
		||||
        this.actor.set_size(outerRect.width, outerRect.height);
 | 
			
		||||
        this._windowClone.set_position(-borderX, -borderY);
 | 
			
		||||
        this._computeBoundingBox();
 | 
			
		||||
        this.emit('size-changed');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDestroy: function() {
 | 
			
		||||
        this._disconnectRealWindowSignals();
 | 
			
		||||
        this._disconnectSignals();
 | 
			
		||||
 | 
			
		||||
        this.metaWindow._delegate = null;
 | 
			
		||||
        this.actor._delegate = null;
 | 
			
		||||
@@ -432,7 +569,7 @@ const WindowOverlay = new Lang.Class({
 | 
			
		||||
                                                      Lang.bind(this,
 | 
			
		||||
                                                                this._onWindowAdded));
 | 
			
		||||
 | 
			
		||||
        metaWindow.delete(global.get_current_time());
 | 
			
		||||
        this._windowClone.deleteAll();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onWindowAdded: function(workspace, win) {
 | 
			
		||||
@@ -1220,9 +1357,29 @@ const Workspace = new Lang.Class({
 | 
			
		||||
        if (this._lookupIndex (metaWin) != -1)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (!this._isMyWindow(win) || !this._isOverviewWindow(win))
 | 
			
		||||
        if (!this._isMyWindow(win))
 | 
			
		||||
            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);
 | 
			
		||||
 | 
			
		||||
        if (win._overviewHint) {
 | 
			
		||||
@@ -1321,9 +1478,11 @@ const Workspace = new Lang.Class({
 | 
			
		||||
                overlay.hide();
 | 
			
		||||
 | 
			
		||||
            if (clone.metaWindow.showing_on_its_workspace()) {
 | 
			
		||||
                let [origX, origY] = clone.getOriginalPosition();
 | 
			
		||||
 | 
			
		||||
                Tweener.addTween(clone.actor,
 | 
			
		||||
                                 { x: clone.origX,
 | 
			
		||||
                                   y: clone.origY,
 | 
			
		||||
                                 { x: origX,
 | 
			
		||||
                                   y: origY,
 | 
			
		||||
                                   scale_x: 1.0,
 | 
			
		||||
                                   scale_y: 1.0,
 | 
			
		||||
                                   time: Overview.ANIMATION_TIME,
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ const Background = imports.ui.background;
 | 
			
		||||
const DND = imports.ui.dnd;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
const WindowManager = imports.ui.windowManager;
 | 
			
		||||
const Workspace = imports.ui.workspace;
 | 
			
		||||
const WorkspacesView = imports.ui.workspacesView;
 | 
			
		||||
 | 
			
		||||
@@ -31,20 +32,49 @@ const WORKSPACE_KEEP_ALIVE_TIME = 100;
 | 
			
		||||
 | 
			
		||||
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({
 | 
			
		||||
    Name: 'WindowClone',
 | 
			
		||||
 | 
			
		||||
    _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 });
 | 
			
		||||
        this.actor._delegate = this;
 | 
			
		||||
        this.actor.add_child(this.clone);
 | 
			
		||||
        this.realWindow = realWindow;
 | 
			
		||||
        this.metaWindow = realWindow.meta_window;
 | 
			
		||||
 | 
			
		||||
        this._positionChangedId = this.realWindow.connect('position-changed',
 | 
			
		||||
                                                          Lang.bind(this, this._onPositionChanged));
 | 
			
		||||
        this._realWindowDestroyedId = this.realWindow.connect('destroy',
 | 
			
		||||
                                                              Lang.bind(this, this._disconnectRealWindowSignals));
 | 
			
		||||
        this.clone._updateId = this.realWindow.connect('position-changed',
 | 
			
		||||
                                                       Lang.bind(this, this._onPositionChanged));
 | 
			
		||||
        this.clone._destroyId = this.realWindow.connect('destroy', Lang.bind(this, function() {
 | 
			
		||||
            // 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.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-end', Lang.bind(this, this._onDragEnd));
 | 
			
		||||
        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) {
 | 
			
		||||
@@ -74,25 +122,57 @@ const WindowClone = new Lang.Class({
 | 
			
		||||
        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() {
 | 
			
		||||
        let rect = this.metaWindow.get_outer_rect();
 | 
			
		||||
        this.actor.set_position(this.realWindow.x, this.realWindow.y);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _disconnectRealWindowSignals: function() {
 | 
			
		||||
        if (this._positionChangedId != 0) {
 | 
			
		||||
            this.realWindow.disconnect(this._positionChangedId);
 | 
			
		||||
            this._positionChangedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
    _disconnectSignals: function() {
 | 
			
		||||
        this.actor.get_children().forEach(function(child) {
 | 
			
		||||
            let realWindow = child.source;
 | 
			
		||||
 | 
			
		||||
        if (this._realWindowDestroyedId != 0) {
 | 
			
		||||
            this.realWindow.disconnect(this._realWindowDestroyedId);
 | 
			
		||||
            this._realWindowDestroyedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
            realWindow.disconnect(child._updateId);
 | 
			
		||||
            realWindow.disconnect(child._destroyId);
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDestroy: function() {
 | 
			
		||||
        this._disconnectRealWindowSignals();
 | 
			
		||||
        this._disconnectSignals();
 | 
			
		||||
 | 
			
		||||
        this.actor._delegate = null;
 | 
			
		||||
 | 
			
		||||
@@ -320,10 +400,26 @@ const WorkspaceThumbnail = new Lang.Class({
 | 
			
		||||
        if (this._lookupIndex (metaWin) != -1)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (!this._isMyWindow(win) || !this._isOverviewWindow(win))
 | 
			
		||||
        if (!this._isMyWindow(win))
 | 
			
		||||
            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) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user