BossBey File Manager
PHP:
8.2.30
OS:
Linux
User:
htmlandpixel
Root
/
usr
/
share
/
gnome-shell
/
extensions
/
desktop-icons@gnome-shell-extensions.gcampax.github.com
📤 Upload
📝 New File
📁 New Folder
Close
Editing: desktopManager.js
/* 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 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 { loadInterfaceXML } = imports.misc.fileUtils; 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})); } async function queryInfo(file, attributes = DesktopIconsUtil.DEFAULT_ATTRIBUTES, cancellable = null) { const flags = Gio.FileQueryInfoFlags.NONE; const priority = GLib.PRIORITY_DEFAULT; return new Promise((resolve, reject) => { file.query_info_async(attributes, flags, priority, cancellable, (o, res) => { try { const info = file.query_info_finish(res); resolve(info); } catch (e) { reject(e); } }); }); } 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._discreteGpuAvailable = false; this._rubberBandActive = false; 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._mountMonitor = Gio.VolumeMonitor.get(); this._mountAddedId = this._mountMonitor.connect('mount-added', (monitor, mount) => { this._recreateDesktopIcons(); }); this._mountRemovedId = this._mountMonitor.connect('mount-removed', (monitor, mount) => { this._recreateDesktopIcons(); }); let origCapturedEvent = this._grabHelper.onCapturedEvent; this._grabHelper.onCapturedEvent = (event) => { if (event.type() === Clutter.EventType.MOTION) { /* We handle motion events from a captured event handler so we * we can see motion over actors that are on other parts of the * stage. */ this._handleMotion(event); return Clutter.EVENT_STOP; } return origCapturedEvent.bind(this._grabHelper)(event); }; this._origUpdateBackgrounds = Main.layoutManager._updateBackgrounds; Main.layoutManager._updateBackgrounds = () => { this._origUpdateBackgrounds.call(Main.layoutManager); this._recreateDesktopIcons(); }; 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; this._switcherooNotifyId = global.connect('notify::switcheroo-control', () => this._updateDiscreteGpuAvailable()); this._updateDiscreteGpuAvailable(); } _updateDiscreteGpuAvailable() { this._switcherooProxy = global.get_switcheroo_control(); if (this._switcherooProxy) { let prop = this._switcherooProxy.get_cached_property('HasDualGpu'); this._discreteGpuAvailable = prop ? prop.unpack() : false; } else { this._discreteGpuAvailable = false; } } startRubberBand(x, y) { this._rubberBandInitialX = x; this._rubberBandInitialY = y; this._updateRubberBand(x, y); this._rubberBand.show(); this._rubberBandActive = true; this._grabHelper.grab({ actor: Main.layoutManager._backgroundGroup, onUngrab: () => this.endRubberBand(false), }); Extension.lockActivitiesButton = true; this._stageReleaseEventId = global.stage.connect('button-release-event', (actor, event) => { this.endRubberBand(); }); this._rubberBandId = global.stage.connect('motion-event', (actor, event) => { }); } _handleMotion(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; } let [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(ungrab=true) { if (!this._rubberBandActive) return; this._rubberBandActive = false; this._rubberBand.hide(); Extension.lockActivitiesButton = false; if (ungrab) this._grabHelper.ungrab(); global.stage.disconnect(this._stageReleaseEventId); 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 = {}; } 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 = await queryInfo(desktopDir, Gio.FILE_ATTRIBUTE_UNIX_MODE); this._unixMode = fileInfo.get_attribute_uint32(Gio.FILE_ATTRIBUTE_UNIX_MODE); this._setWritableByOthers((this._unixMode & S_IWOTH) != 0); } try { let items = []; for (let item of await this._enumerateDesktop()) items.push(item); for (let item of await this._getMounts()) items.push(item); let tmpFileItems = new Map(); for (let [file, info, extra] of items) { 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}`, logError(e)); 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, async (source, result) => { try { let fileEnum = source.enumerate_children_finish(result); let extraFolders = await Promise.all(DesktopIconsUtil.getExtraFolders() .map(async ([folder, extras]) => { const info = await queryInfo(folder, DesktopIconsUtil.DEFAULT_ATTRIBUTES, this._desktopEnumerateCancellable); return [folder, info, extras]; })); let resultGenerator = function *() { for (let [newFolder, info, extras] of extraFolders) yield [newFolder, info, extras]; let info; 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)); } async _getMounts() { let files = []; if (!Prefs.settings.get_boolean('show-mount')) return files; this._mountMonitor.get_mounts().forEach(async mount => { if (this._isNetworkMount(mount)) return; let file = mount.get_root(); let info = await queryInfo(file); files.push([file, info, Prefs.FileType.MOUNT_DISK]); }); return files; } _isNetworkMount(mount) { let volume = mount.get_volume(); if (!volume) return true; return volume.get_identifier('class') == 'network'; } 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'); } get discreteGpuAvailable() { return this._discreteGpuAvailable; } get switcherooProxyGPUs() { if (!this._switcherooProxy) { log('Could not apply discrete GPU environment, switcheroo-control not available'); return null; } let prop = this._switcherooProxy.get_cached_property("GPUs"); return prop ? prop.unpack() : null; } _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: 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); if (this._draggableContainer.get_fixed_position !== undefined) this._draggableContainer.allocate_preferred_size(0, 0); this._draggable.startDrag(x, y, global.get_current_time(), event.get_event_sequence()); Main.overview.beginItemDrag(this._draggableContainer); } _onDragCancelled() { let event = Clutter.get_current_event(); let [x, y] = event.get_coords(); this._dragCancelled = true; Main.overview.cancelledItemDrag(this._draggableContainer); } _onDragEnd() { this._inDrag = false; Main.layoutManager.uiGroup.remove_child(this._draggableContainer); Main.overview.endItemDrag(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(); } doPreview() { if (this._selection.size == 0) return; let item = [...this._selection][0]; DBusUtils.GnomeNautilusPreviewProxy.ShowFileRemote(item.file.get_uri(), 0, false); } 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._mountAddedId) this._mountMonitor.disconnect(this._mountAddedId); this._mountAddedId = 0; if (this._mountRemovedId) this._mountMonitor.disconnect(this._mountRemovedId); this._mountRemovedId = 0; 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._origUpdateBackgrounds) Main.layoutManager._updateBackgrounds = this._origUpdateBackgrounds; delete this._origUpdateBackgrounds; if (this._stageReleaseEventId) global.stage.disconnect(this._stageReleaseEventId); this._stageReleaseEventId = 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); }
Save
Cancel