[ Avaa Bypassed ]




Upload:

Command:

www-data@18.191.137.190: ~ $
/* Desktop Icons GNOME Shell extension
 *
 * Copyright (C) 2017 Carlos Soriano <csoriano@redhat.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

const Gtk = imports.gi.Gtk;
const Clutter = imports.gi.Clutter;
const GObject = imports.gi.GObject;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const St = imports.gi.St;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;

const Animation = imports.ui.animation;
const Background = imports.ui.background;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
const GrabHelper = imports.ui.grabHelper;

const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Extension = Me.imports.extension;
const DesktopGrid = Me.imports.desktopGrid;
const FileItem = Me.imports.fileItem;
const Prefs = Me.imports.prefs;
const DBusUtils = Me.imports.dbusUtils;
const DesktopIconsUtil = Me.imports.desktopIconsUtil;

const Clipboard = St.Clipboard.get_default();
const CLIPBOARD_TYPE = St.ClipboardType.CLIPBOARD;

var S_IWOTH = 0x00002;

function getDpy() {
    return global.screen || global.display;
}

function findMonitorIndexForPos(x, y) {
    return getDpy().get_monitor_index_for_rect(new Meta.Rectangle({x, y}));
}


var DesktopManager = GObject.registerClass({
    Properties: {
        'writable-by-others': GObject.ParamSpec.boolean(
            'writable-by-others',
            'WritableByOthers',
            'Whether the desktop\'s directory can be written by others (o+w unix permission)',
            GObject.ParamFlags.READABLE,
            false
        )
    }
}, class DesktopManager extends GObject.Object {
    _init(params) {
        super._init(params);

        this._layoutChildrenId = 0;
        this._deleteChildrenId = 0;
        this._monitorDesktopDir = null;
        this._desktopMonitorCancellable = null;
        this._desktopGrids = {};
        this._fileItemHandlers = new Map();
        this._fileItems = new Map();
        this._dragCancelled = false;
        this._queryFileInfoCancellable = null;
        this._unixMode = null;
        this._writableByOthers = null;

        this._monitorsChangedId = Main.layoutManager.connect('monitors-changed', () => this._recreateDesktopIcons());
        this._rubberBand = new St.Widget({ style_class: 'rubber-band' });
        this._rubberBand.hide();
        Main.layoutManager._backgroundGroup.add_child(this._rubberBand);
        this._grabHelper = new GrabHelper.GrabHelper(global.stage);

        this._addDesktopIcons();
        this._monitorDesktopFolder();

        this.settingsId = Prefs.settings.connect('changed', () => this._recreateDesktopIcons());
        this.gtkSettingsId = Prefs.gtkSettings.connect('changed', (obj, key) => {
            if (key == 'show-hidden')
                this._recreateDesktopIcons();
        });
        this.nautilusSettingsId = Prefs.nautilusSettings.connect('changed', (obj, key) => {
            if (key == 'show-image-thumbnails')
                this._recreateDesktopIcons();
        });

        this._selection = new Set();
        this._currentSelection = new Set();
        this._inDrag = false;
        this._dragXStart = Number.POSITIVE_INFINITY;
        this._dragYStart = Number.POSITIVE_INFINITY;
    }

    startRubberBand(x, y) {
        this._rubberBandInitialX = x;
        this._rubberBandInitialY = y;
        this._initRubberBandColor();
        this._updateRubberBand(x, y);
        this._rubberBand.show();
        this._grabHelper.grab({ actor: global.stage });
        Extension.lockActivitiesButton = true;
        this._stageReleaseEventId = global.stage.connect('button-release-event', (actor, event) => {
            this.endRubberBand();
        });
        this._rubberBandId = global.stage.connect('motion-event', (actor, event) => {
            /* In some cases, when the user starts a rubberband selection and ends it
             * (by releasing the left button) over a window instead of doing it over
             * the desktop, the stage doesn't receive the "button-release" event.
             * This happens currently with, at least, Dash to Dock extension, but
             * it probably also happens with other applications or extensions.
             * To fix this, we also end the rubberband selection if we detect mouse
             * motion in the stage without the left button pressed during a
             * rubberband selection.
             *  */
            let button = event.get_state();
            if (!(button & Clutter.ModifierType.BUTTON1_MASK)) {
                this.endRubberBand();
                return;
            }
            [x, y] = event.get_coords();
            this._updateRubberBand(x, y);
            let x0, y0, x1, y1;
            if (x >= this._rubberBandInitialX) {
                x0 = this._rubberBandInitialX;
                x1 = x;
            } else {
                x1 = this._rubberBandInitialX;
                x0 = x;
            }
            if (y >= this._rubberBandInitialY) {
                y0 = this._rubberBandInitialY;
                y1 = y;
            } else {
                y1 = this._rubberBandInitialY;
                y0 = y;
            }
            for (let [fileUri, fileItem] of this._fileItems) {
                fileItem.emit('selected', true, true,
                              fileItem.intersectsWith(x0, y0, x1 - x0, y1 - y0));
            }
        });
    }

    endRubberBand() {
        this._rubberBand.hide();
        Extension.lockActivitiesButton = false;
        this._grabHelper.ungrab();
        global.stage.disconnect(this._rubberBandId);
        global.stage.disconnect(this._stageReleaseEventId);
        this._rubberBandId = 0;
        this._stageReleaseEventId = 0;

        this._selection = new Set([...this._selection, ...this._currentSelection]);
        this._currentSelection.clear();
    }

    _updateRubberBand(currentX, currentY) {
        let x = this._rubberBandInitialX < currentX ? this._rubberBandInitialX
                                                    : currentX;
        let y = this._rubberBandInitialY < currentY ? this._rubberBandInitialY
                                                    : currentY;
        let width = Math.abs(this._rubberBandInitialX - currentX);
        let height = Math.abs(this._rubberBandInitialY - currentY);
        /* TODO: Convert to gobject.set for 3.30 */
        this._rubberBand.set_position(x, y);
        this._rubberBand.set_size(width, height);
    }

    _recreateDesktopIcons() {
        this.clearSelection();
        this._destroyDesktopIcons();
        this._addDesktopIcons();
    }

    _addDesktopIcons() {
        let first_element = true;
        forEachBackgroundManager(bgManager => {
            let newGrid = new DesktopGrid.DesktopGrid(bgManager);
            newGrid.connect('destroy', (actor) => {
                // if a grid loses its actor, remove it from the grid list
                for (let grid in this._desktopGrids)
                    if (this._desktopGrids[grid] == actor) {
                        delete this._desktopGrids[grid];
                        break;
                    }
            });
            newGrid.isFirst = first_element;
            first_element = false;
            this._desktopGrids[bgManager._monitorIndex] = newGrid;
        });

        this._scanFiles();
    }

    _destroyDesktopIcons() {
        Object.values(this._desktopGrids).forEach(grid => grid.destroy());
        this._desktopGrids = {};
    }

    /**
     * Initialize rubberband color from the GTK rubberband class
     * */
    _initRubberBandColor() {
        let rgba = DesktopIconsUtil.getGtkClassBackgroundColor('rubberband', Gtk.StateFlags.NORMAL);
        let background_color =
            'rgba(' + rgba.red * 255 + ', ' + rgba.green * 255 + ', ' + rgba.blue * 255 + ', 0.4)';
        this._rubberBand.set_style('background-color: ' + background_color);
    }

    async _scanFiles() {
        for (let [fileItem, fileItemHandler] of this._fileItemHandlers)
            Object.values(fileItemHandler).forEach(id => fileItem.disconnect(id));

        this._fileItemHandlers = new Map();

        if (!this._unixMode) {
            let desktopDir = DesktopIconsUtil.getDesktopDir();
            let fileInfo = desktopDir.query_info(Gio.FILE_ATTRIBUTE_UNIX_MODE,
                                                 Gio.FileQueryInfoFlags.NONE,
                                                 null);
            this._unixMode = fileInfo.get_attribute_uint32(Gio.FILE_ATTRIBUTE_UNIX_MODE);
            this._setWritableByOthers((this._unixMode & S_IWOTH) != 0);
        }

        try {
            let tmpFileItems = new Map();
            for (let [file, info, extra] of await this._enumerateDesktop()) {
                let fileItem = new FileItem.FileItem(file, info, extra);
                tmpFileItems.set(fileItem.file.get_uri(), fileItem);
                let fileItemHandler = {}
                fileItemHandler.selectedId = fileItem.connect('selected',
                    this._onFileItemSelected.bind(this));
                fileItemHandler.destroyId = fileItem.connect('destroy', () => {
                    this._fileItemHandlers.delete(fileItem);
                });
                this._fileItemHandlers.set(fileItem, fileItemHandler);
            }
            this._fileItems = tmpFileItems;
        } catch (e) {
            if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
                log(`Error loading desktop files ${e.message}`);
            return;
        }

        this.scheduleReLayoutChildren();
    }

    getDesktopFileNames () {
        let fileList = [];
        for (let [uri, item] of this._fileItems) {
            fileList.push(item.fileName);
        }
        return fileList;
    }

    _enumerateDesktop() {
        return new Promise((resolve, reject) => {
            if (this._desktopEnumerateCancellable)
                this._desktopEnumerateCancellable.cancel();

            this._desktopEnumerateCancellable = new Gio.Cancellable();

            let desktopDir = DesktopIconsUtil.getDesktopDir();
            desktopDir.enumerate_children_async(DesktopIconsUtil.DEFAULT_ATTRIBUTES,
                Gio.FileQueryInfoFlags.NONE,
                GLib.PRIORITY_DEFAULT,
                this._desktopEnumerateCancellable,
                (source, result) => {
                    try {
                        let fileEnum = source.enumerate_children_finish(result);
                        let resultGenerator = function *() {
                            let info;
                            for (let [newFolder, extras] of DesktopIconsUtil.getExtraFolders()) {
                                yield [newFolder, newFolder.query_info(DesktopIconsUtil.DEFAULT_ATTRIBUTES, Gio.FileQueryInfoFlags.NONE, this._desktopEnumerateCancellable), extras];
                            }
                            while ((info = fileEnum.next_file(null)))
                                yield [fileEnum.get_child(info), info, Prefs.FileType.NONE];
                        }.bind(this);
                        resolve(resultGenerator());
                    } catch (e) {
                        reject(e);
                    }
                });
        });
    }

    _monitorDesktopFolder() {
        if (this._monitorDesktopDir) {
            this._monitorDesktopDir.cancel();
            this._monitorDesktopDir = null;
        }

        let desktopDir = DesktopIconsUtil.getDesktopDir();
        this._monitorDesktopDir = desktopDir.monitor_directory(Gio.FileMonitorFlags.WATCH_MOVES, null);
        this._monitorDesktopDir.set_rate_limit(1000);
        this._monitorDesktopDir.connect('changed', (obj, file, otherFile, eventType) => this._updateDesktopIfChanged(file, otherFile, eventType));
    }

    checkIfSpecialFilesAreSelected() {
        for (let fileItem of this._selection) {
            if (fileItem.isSpecial)
                return true;
        }
        return false;
    }

    getNumberOfSelectedItems() {
        return this._selection.size;
    }

    get writableByOthers() {
        return this._writableByOthers;
    }

    _setWritableByOthers(value) {
        if (value == this._writableByOthers)
            return;

        this._writableByOthers = value
        this.notify('writable-by-others');
    }

    _updateDesktopIfChanged (file, otherFile, eventType) {
        let {
            DELETED, MOVED_IN, MOVED_OUT, CREATED, RENAMED, CHANGES_DONE_HINT, ATTRIBUTE_CHANGED
        } = Gio.FileMonitorEvent;

        let fileUri = file.get_uri();
        let fileItem = this._fileItems.get(fileUri);
        switch(eventType) {
            case RENAMED:
                /* when you save a file, a .goutputstream-XXX file would be created and
                 * renamed to orignial file, but the .goutputstream doesn't have fileItem */
                if (fileItem) {
                    this._fileItems.delete(fileUri);
                    this._fileItems.set(otherFile.get_uri(), fileItem);
                    fileItem.onFileRenamed(otherFile);
                }
                return;
            case CHANGES_DONE_HINT:
            case ATTRIBUTE_CHANGED:
                /* a file changed, rather than the desktop itself */
                let desktopDir = DesktopIconsUtil.getDesktopDir();
                if (fileItem && file.get_uri() != desktopDir.get_uri()) {
                    fileItem.onAttributeChanged();
                    return;
                }

                if (this._queryFileInfoCancellable)
                    this._queryFileInfoCancellable.cancel();

                file.query_info_async(Gio.FILE_ATTRIBUTE_UNIX_MODE,
                                      Gio.FileQueryInfoFlags.NONE,
                                      GLib.PRIORITY_DEFAULT,
                                      this._queryFileInfoCancellable,
                    (source, result) => {
                        try {
                            let info = source.query_info_finish(result);
                            this._queryFileInfoCancellable = null;

                            this._unixMode = info.get_attribute_uint32(Gio.FILE_ATTRIBUTE_UNIX_MODE);
                            this._setWritableByOthers((this._unixMode & S_IWOTH) != 0);

                            if (this._writableByOthers)
                                log(`desktop-icons: Desktop is writable by others - will not allow launching any desktop files`);
                        } catch(error) {
                            if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
                                global.log('Error getting desktop unix mode: ' + error);
                        }
                    });

                return;
        }

        // Only get a subset of events we are interested in.
        // Note that CREATED will emit a CHANGES_DONE_HINT
        if (![DELETED, MOVED_IN, MOVED_OUT, CREATED].includes(eventType))
            return;

        this._recreateDesktopIcons();
    }

    _setupDnD() {
        this._draggableContainer = new St.Widget({
            visible: true,
            width: 1,
            height: 1,
            x: 0,
            y: 0,
            style_class: 'draggable'
        });
        this._draggableContainer._delegate = this;
        this._draggable = DND.makeDraggable(this._draggableContainer,
            {
                manualMode: true,
                dragActorOpacity: 100
            });

        this._draggable.connect('drag-cancelled', () => this._onDragCancelled());
        this._draggable.connect('drag-end', () => this._onDragEnd());

        this._draggable._dragActorDropped = event => this._dragActorDropped(event);
    }

    dragStart() {
        if (this._inDrag) {
            return;
        }

        this._setupDnD();
        let event = Clutter.get_current_event();
        let [x, y] = event.get_coords();
        [this._dragXStart, this._dragYStart] = event.get_coords();
        this._inDrag = true;

        for (let fileItem of this._selection) {
            let clone = new Clutter.Clone({
                source: fileItem,
                reactive: false
            });
            clone.x = fileItem.get_transformed_position()[0];
            clone.y = fileItem.get_transformed_position()[1];
            this._draggableContainer.add_child(clone);
        }

        Main.layoutManager.uiGroup.add_child(this._draggableContainer);
        this._draggable.startDrag(x, y, global.get_current_time(), event.get_event_sequence());
    }

    _onDragCancelled() {
        let event = Clutter.get_current_event();
        let [x, y] = event.get_coords();
        this._dragCancelled = true;
    }

    _onDragEnd() {
        this._inDrag = false;
        Main.layoutManager.uiGroup.remove_child(this._draggableContainer);
    }

    _dragActorDropped(event) {
        let [dropX, dropY] = event.get_coords();
        let target = this._draggable._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
                                                                             dropX, dropY);

        // We call observers only once per motion with the innermost
        // target actor. If necessary, the observer can walk the
        // parent itself.
        let dropEvent = {
            dropActor: this._draggable._dragActor,
            targetActor: target,
            clutterEvent: event
        };
        for (let dragMonitor of DND.dragMonitors) {
            let dropFunc = dragMonitor.dragDrop;
            if (dropFunc)
                switch (dropFunc(dropEvent)) {
                    case DragDropResult.FAILURE:
                    case DragDropResult.SUCCESS:
                        return true;
                    case DragDropResult.CONTINUE:
                        continue;
                }
        }

        // At this point it is too late to cancel a drag by destroying
        // the actor, the fate of which is decided by acceptDrop and its
        // side-effects
        this._draggable._dragCancellable = false;

        let destroyActor = false;
        while (target) {
            if (target._delegate && target._delegate.acceptDrop) {
                let [r, targX, targY] = target.transform_stage_point(dropX, dropY);
                if (target._delegate.acceptDrop(this._draggable.actor._delegate,
                    this._draggable._dragActor,
                    targX,
                    targY,
                    event.get_time())) {
                    // If it accepted the drop without taking the actor,
                    // handle it ourselves.
                    if (this._draggable._dragActor.get_parent() == Main.uiGroup) {
                        if (this._draggable._restoreOnSuccess) {
                            this._draggable._restoreDragActor(event.get_time());
                            return true;
                        }
                        else {
                            // We need this in order to make sure drag-end is fired
                            destroyActor = true;
                        }
                    }

                    this._draggable._dragInProgress = false;
                    getDpy().set_cursor(Meta.Cursor.DEFAULT);
                    this._draggable.emit('drag-end', event.get_time(), true);
                    if (destroyActor) {
                        this._draggable._dragActor.destroy();
                    }
                    this._draggable._dragComplete();

                    return true;
                }
            }
            target = target.get_parent();
        }

        this._draggable._cancelDrag(event.get_time());

        return true;
    }

    acceptDrop(xEnd, yEnd) {
        let savedCoordinates = new Map();
        let [xDiff, yDiff] = [xEnd - this._dragXStart, yEnd - this._dragYStart];
        /* Remove all items before dropping new ones, so we can freely reposition
         * them.
         */
        for (let item of this._selection) {
            let [itemX, itemY] = item.get_transformed_position();
            let monitorIndex = findMonitorIndexForPos(itemX, itemY);
            savedCoordinates.set(item, [itemX, itemY]);
            this._desktopGrids[monitorIndex].removeFileItem(item);
        }

        for (let item of this._selection) {
            let [itemX, itemY] = savedCoordinates.get(item);
            /* Set the new ideal position where the item drop should happen */
            let newFileX = Math.round(xDiff + itemX);
            let newFileY = Math.round(yDiff + itemY);
            let monitorIndex = findMonitorIndexForPos(newFileX, newFileY);
            this._desktopGrids[monitorIndex].addFileItemCloseTo(item, newFileX, newFileY, DesktopGrid.StoredCoordinates.OVERWRITE);
        }

        return true;
    }

    selectionDropOnFileItem (fileItemDestination) {
        if (!fileItemDestination.isDirectory)
            return false;

        let droppedUris = [];
        for (let fileItem of this._selection) {
            if (fileItem.isSpecial)
                return false;
            if (fileItemDestination.file.get_uri() == fileItem.file.get_uri())
                return false;
            droppedUris.push(fileItem.file.get_uri());
        }

        if (droppedUris.length == 0)
            return true;

        DBusUtils.NautilusFileOperationsProxy.MoveURIsRemote(droppedUris,
                                                             fileItemDestination.file.get_uri(),
            (result, error) => {
                if (error)
                    throw new Error('Error moving files: ' + error.message);
            }
        );
        for (let fileItem of this._selection) {
            fileItem.state = FileItem.State.GONE;
        }

        this._recreateDesktopIcons();

        return true;
    }

    _resetGridsAndScheduleLayout() {
        this._deleteChildrenId = 0;

        Object.values(this._desktopGrids).forEach((grid) => grid.reset());

        if (!this._layoutChildrenId)
            this._layoutChildrenId = GLib.idle_add(GLib.PRIORITY_LOW, () => this._layoutChildren());

        return GLib.SOURCE_REMOVE;
    }

    scheduleReLayoutChildren() {
        if (this._deleteChildrenId != 0)
            return;

        if (this._layoutChildrenId != 0) {
            GLib.source_remove(this._layoutChildrenId);
            this._layoutChildrenId = 0;
        }


        this._deleteChildrenId = GLib.idle_add(GLib.PRIORITY_LOW, () => this._resetGridsAndScheduleLayout());
    }

    _addFileItemCloseTo(item) {
        let coordinates;
        let x = 0;
        let y = 0;
        let coordinatesAction = DesktopGrid.StoredCoordinates.ASSIGN;
        if (item.savedCoordinates != null) {
            [x, y] = item.savedCoordinates;
            coordinatesAction = DesktopGrid.StoredCoordinates.PRESERVE;
        }
        let monitorIndex = findMonitorIndexForPos(x, y);
        let desktopGrid = this._desktopGrids[monitorIndex];
        try {
            desktopGrid.addFileItemCloseTo(item, x, y, coordinatesAction);
        } catch (e) {
            log(`Error adding children to desktop: ${e.message}`);
        }
    }

    _layoutChildren() {
        let showHidden = Prefs.gtkSettings.get_boolean('show-hidden');
        /*
         * Paint the icons in two passes:
         * * first pass paints those that have their coordinates defined in the metadata
         * * second pass paints those new files that still don't have their definitive coordinates
         */
        for (let [fileUri, fileItem] of this._fileItems) {
            if (fileItem.savedCoordinates == null)
                continue;
            if (fileItem.state != FileItem.State.NORMAL)
                continue;
            if (!showHidden && fileItem.isHidden)
                continue;
            this._addFileItemCloseTo(fileItem);
        }

        for (let [fileUri, fileItem] of this._fileItems) {
            if (fileItem.savedCoordinates !== null)
                continue;
            if (fileItem.state != FileItem.State.NORMAL)
                continue;
            if (!showHidden && fileItem.isHidden)
                continue;
            this._addFileItemCloseTo(fileItem);
        }

        this._layoutChildrenId = 0;
        return GLib.SOURCE_REMOVE;
    }

    doRename() {
        if (this._selection.size != 1)
            return;

        let item = [...this._selection][0];
        if (item.canRename())
            item.doRename();
    }

    doOpen() {
        for (let fileItem of this._selection)
            fileItem.doOpen();
    }

    doTrash() {
        DBusUtils.NautilusFileOperationsProxy.TrashFilesRemote([...this._selection].map((x) => { return x.file.get_uri(); }),
            (source, error) => {
                if (error)
                    throw new Error('Error trashing files on the desktop: ' + error.message);
            }
        );
    }

    doEmptyTrash() {
        DBusUtils.NautilusFileOperationsProxy.EmptyTrashRemote( (source, error) => {
            if (error)
                throw new Error('Error trashing files on the desktop: ' + error.message);
        });
    }

    _onFileItemSelected(fileItem, keepCurrentSelection, rubberBandSelection, addToSelection) {

        if (!keepCurrentSelection && !this._inDrag)
            this.clearSelection();

        let selection = keepCurrentSelection && rubberBandSelection ? this._currentSelection : this._selection;
        if (addToSelection)
            selection.add(fileItem);
        else
            selection.delete(fileItem);

        for (let [fileUri, fileItem] of this._fileItems)
            fileItem.isSelected = this._currentSelection.has(fileItem) || this._selection.has(fileItem);
    }

    clearSelection() {
        for (let [fileUri, fileItem] of this._fileItems)
            fileItem.isSelected = false;
        this._selection = new Set();
        this._currentSelection = new Set();
    }

    _getClipboardText(isCopy) {
        let action = isCopy ? 'copy' : 'cut';
        let text = `x-special/nautilus-clipboard\n${action}\n${
            [...this._selection].map(s => s.file.get_uri()).join('\n')
        }\n`;

        return text;
    }

    doCopy() {
        Clipboard.set_text(CLIPBOARD_TYPE, this._getClipboardText(true));
    }

    doCut() {
        Clipboard.set_text(CLIPBOARD_TYPE, this._getClipboardText(false));
    }

    destroy() {
        if (this._monitorDesktopDir)
            this._monitorDesktopDir.cancel();
        this._monitorDesktopDir = null;

        if (this.settingsId)
            Prefs.settings.disconnect(this.settingsId);
        this.settingsId = 0;
        if (this.gtkSettingsId)
            Prefs.gtkSettings.disconnect(this.gtkSettingsId);
        this.gtkSettingsId = 0;
        if (this.nautilusSettingsId)
            Prefs.nautilusSettings.disconnect(this.nautilusSettingsId);
        this.nautilusSettingsId = 0;

        if (this._layoutChildrenId)
            GLib.source_remove(this._layoutChildrenId);
        this._layoutChildrenId = 0;

        if (this._deleteChildrenId)
            GLib.source_remove(this._deleteChildrenId);
        this._deleteChildrenId = 0;

        if (this._monitorsChangedId)
            Main.layoutManager.disconnect(this._monitorsChangedId);
        this._monitorsChangedId = 0;
        if (this._stageReleaseEventId)
            global.stage.disconnect(this._stageReleaseEventId);
        this._stageReleaseEventId = 0;

        if (this._rubberBandId)
            global.stage.disconnect(this._rubberBandId);
        this._rubberBandId = 0;

        this._rubberBand.destroy();

        if (this._queryFileInfoCancellable)
            this._queryFileInfoCancellable.cancel();

        Object.values(this._desktopGrids).forEach(grid => grid.destroy());
        this._desktopGrids = {}
    }
});

function forEachBackgroundManager(func) {
    Main.layoutManager._bgManagers.forEach(func);
}

Filemanager

Name Type Size Permission Actions
createFolderDialog.js File 6.13 KB 0644
createThumbnail.js File 1.45 KB 0755
dbusUtils.js File 3.74 KB 0644
desktopGrid.js File 25.46 KB 0644
desktopIconsUtil.js File 4.66 KB 0644
desktopManager.js File 27.92 KB 0644
extension.js File 2.44 KB 0644
fileItem.js File 35.64 KB 0644
metadata.json File 150 B 0644
prefs.js File 5.96 KB 0644
stylesheet.css File 694 B 0644