/* DING: Desktop Icons New Generation for GNOME Shell * * Gtk4 Port Copyright (C) 2022, 2025 Sundeep Mediratta (smedius@gmail.com) * Copyright (C) 2019 Sergio Costas (rastersoft@gmail.com) * Based on code original (C) Carlos Soriano * * 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, version 3 of the License. * * 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 . */ import {Adw, GLib, Gtk, Gio, Gdk, GdkX11, DesktopAppInfo} from '../dependencies/gi.js'; import {DesktopWidgetCapability} from '../dependencies/gi.js'; import {_} from '../dependencies/gettext.js'; export {Preferences}; const GioSSS = Gio.SettingsSchemaSource; const Preferences = class { constructor(Data, AdwPreferencesWindow) { this._extensionPath = Data.extensionPath; this._programVersion = Data.programversion; this._mainApp = Data.mainApp; this._Enums = Data.Enums; let schemaSource = GioSSS.get_default(); this._desktopManager = null; this._widgetState = null; this._widgetStateMonitor = null; this._suppressWidgetMonitorEvent = false; this.desktopWidgetCapability = DesktopWidgetCapability; // Adw Style Manager this._adwStyleManager = Adw.StyleManager.get_default(); try { if (this._adwStyleManager.get_system_supports_accent_colors()) { console.log('System supports accent colors'); this.accentColorsAvailable = true; } } catch (e) { console.log('System does not support accent colors'); this.accentColorsAvailable = false; } // Gtk const schemaGtk = schemaSource.lookup(this._Enums.SCHEMA_GTK, true); this.gtkSettings = new Gio.Settings({settings_schema: schemaGtk}); // Gnome Files const schemaObj = schemaSource.lookup(this._Enums.SCHEMA_NAUTILUS, true); if (!schemaObj) { this.nautilusSettings = null; this.CLICK_POLICY_SINGLE = false; this.openFolderOnDndHover = false; } else { this.nautilusSettings = new Gio.Settings({settings_schema: schemaObj}); } this._gnomeFilesAppInfo = DesktopAppInfo.new('org.gnome.Nautilus.desktop'); // Compression const compressionSchema = schemaSource.lookup(this._Enums.SCHEMA_NAUTILUS_COMPRESSION, true); if (!compressionSchema) { this.nautilusCompression = null; } else { this.nautilusCompression = new Gio.Settings({settings_schema: compressionSchema}); } // Mutter Settings this.usingX11 = Gdk.Display.get_default() instanceof GdkX11.X11Display; const schemaMutter = schemaSource.lookup(this._Enums.SCHEMA_MUTTER, true); if (schemaMutter) { this.mutterSettings = new Gio.Settings({settings_schema: schemaMutter}); } // Depreciated Gnome Default Terminal Settings const schemaTerminalSettings = schemaSource.lookup(this._Enums.TERMINAL_SCHEMA, true); if (schemaTerminalSettings) { this.schemaTerminalSettings = new Gio.Settings({settings_schema: schemaTerminalSettings}); } else { this.schemaTerminalSettings = null; } // Our Settings this.desktopSettings = this._get_schema(this._Enums.SCHEMA); this._cacheInitialSettings(); // Gnome Theme settings for fallback for older // Adw and Gnome versions accent colors const schemaGnomeSettings = schemaSource.lookup(this._Enums.SCHEMA_GNOME_SETTINGS, true); if (schemaGnomeSettings) { this.schemaGnomeThemeSettings = new Gio.Settings({settings_schema: schemaGnomeSettings}); } this._adwPreferencesWindow = new AdwPreferencesWindow.AdwPreferencesWindow( this.desktopSettings, this.nautilusSettings, this.gtkSettings, this._programVersion, this._mainApp ); } _get_schema(schema) { // check if this extension was built with "make zip-file", and thus // has the schema files in a subfolder // otherwise assume that extension has been installed in the // same prefix as gnome-shell (and therefore schemas are available // in the standard folders) let schemaSource; const schemaFile = Gio.File.new_build_filenamev( [this._extensionPath, 'schemas', 'gschemas.compiled'] ); if (schemaFile.query_exists(null)) { schemaSource = GioSSS.new_from_directory( GLib.build_filenamev([this._extensionPath, 'schemas']), GioSSS.get_default(), false ); } else { schemaSource = GioSSS.get_default(); } let schemaObj = schemaSource.lookup(schema, true); if (!schemaObj) { console.log('schemaObj does not exist!'); console.log('Current extension path:', this._extensionPath); console.log('Current schemaFile:', schemaFile.get_path()); console.log('Schema File exists:', schemaFile.query_exists(null)); throw new Error( `Schema ${schema} could not be found for extension.` + ' Please check your installation.' ); } return new Gio.Settings({settings_schema: schemaObj}); } _cacheInitialSettings() { this._updateIconSize(); this._StartCorner = this._Enums.START_CORNER[ this.desktopSettings.get_string('start-corner') ]; this._UnstackList = this.desktopSettings.get_strv('unstackedtypes'); this.sortOrder = this.desktopSettings.get_enum(this._Enums.SortOrder.ORDER); this.addVolumesOpposite = this.desktopSettings.get_boolean('add-volumes-opposite'); this.showHidden = this.gtkSettings.get_boolean('show-hidden'); this._showDropPlace = this.desktopSettings.get_boolean('show-drop-place'); this.showLinkEmblem = this.desktopSettings.get_boolean('show-link-emblem'); this.darkText = this.desktopSettings.get_boolean('dark-text-in-labels'); this.keepStacked = this.desktopSettings.get_boolean('keep-stacked'); this.keepArranged = this.desktopSettings.get_boolean('keep-arranged'); this.sortSpecialFolders = this.desktopSettings.get_boolean('sort-special-folders'); this.showOnSecondaryMonitor = this.desktopSettings.get_boolean('show-second-monitor'); this.freePositionIcons = this.desktopSettings.get_boolean('free-position-icons'); this.desktopWidgetsEnabled = this.desktopSettings.get_boolean('show-desktop-widgets'); this.CLICK_POLICY_SINGLE = this.nautilusSettings.get_string('click-policy') === 'single'; this.openFolderOnDndHover = this.nautilusSettings.get_boolean('open-folder-on-dnd-hover'); this.showImageThumbnails = this.nautilusSettings .get_string('show-image-thumbnails') !== 'never'; this.darkmode = this._adwStyleManager.get_dark(); this._premultiplied = this._getPreMultiplied(); // Gtk Theme and animation Changes this._gtkSettings = Gtk.Settings.get_for_display(Gdk.Display.get_default()); this._refreshAnimations(); } getAdwPreferencesWindow() { this.AdwPreferencesWindow = this._adwPreferencesWindow.getAdwPreferencesWindow(); return this.AdwPreferencesWindow; } // Updaters _updateIconSize() { let iconSize = this.desktopSettings.get_string('icon-size'); this.IconSize = this._Enums.ICON_SIZE[iconSize]; this.DesiredWidth = this._Enums.ICON_WIDTH[iconSize]; this.DesiredHeight = this._Enums.ICON_HEIGHT[iconSize]; } // Monitoring init(desktopManager) { this._desktopManager = desktopManager; this._desktopIconsUtil = desktopManager.DesktopIconsUtil; this._configureSelectionColor(); this._configureHoverColor(); this._setCSSColors(); this._initLocalCSSprovider(); this._monitorDesktopSettings(); this._monitorTerminalSettings(); this._monitorWidgetState(); } _monitorWidgetState() { if (!this._desktopIconsUtil) return; const widgetsFile = this._desktopIconsUtil.getWidgetsStateFile(); if (!widgetsFile) return; try { this._widgetStateMonitor = widgetsFile.monitor_file( Gio.FileMonitorFlags.WATCH_MOVES, null ); this._widgetStateMonitor.set_rate_limit(500); this._widgetStateMonitor.connect('changed', () => { if (this._suppressWidgetMonitorEvent) return; if (this._widgetStateReloadTimeoutId) { GLib.source_remove(this._widgetStateReloadTimeoutId); this._widgetStateReloadTimeoutId = null; } this._widgetStateReloadTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 250, () => { this._widgetStateReloadTimeoutId = null; this._loadWidgetState() .catch(e => { console.log( 'Error loading widget state from widgets.json:', e.message ?? e ); this._widgetState = null; this._applyWidgetStateToManager(); }); return GLib.SOURCE_REMOVE; }); }); } catch (e) { console.log( 'Error monitoring widget state from widgets.json:', e.message ?? e ); this._widgetStateMonitor = null; return; } this._loadWidgetState() .catch(e => { console.log( 'Error loading widget state from widgets.json:', e.message ?? e ); this._widgetState = null; this._applyWidgetStateToManager(); }); } _monitorDesktopSettings() { if (!this._desktopManager) return; // Desktop Settings this.desktopSettings.connect('changed', (obj, key) => { if (key === 'dark-text-in-labels') { this.darkText = this.desktopSettings.get_boolean('dark-text-in-labels'); this._desktopManager.redrawDesktop() .catch(e => { console.log( 'Exception while updating desktop after "Dark Text"' + ` changed: ${e.message}\n${e.stack}` ); }); return; } if (key === 'show-link-emblem') { this.showLinkEmblem = this.desktopSettings.get_boolean('show-link-emblem'); this._desktopManager.redrawDesktop() .catch(e => { console.log( 'Exception while updating desktop after ' + `"Show Emblems" changed: ${e.message}\n${e.stack}` ); }); return; } if (key === 'sort-special-folders') { this.sortSpecialFolders = this.desktopSettings.get_boolean('sort-special-folders'); return; } if (key === 'add-volumes-opposite') { this.addVolumesOpposite = this.desktopSettings.get_boolean('add-volumes-opposite'); return; } if (key === 'show-second-monitor') { this.showOnSecondaryMonitor = this.desktopSettings.get_boolean('show-second-monitor'); // The initialRead parameter insures tha grid positions are // recalculated and remapped to new monitors. Recaculated // postions of all fileItems will be re-written to disk with // write mode 'OVERWRITE' if (this.showOnSecondaryMonitor) { this._desktopManager.refreshDesktop(); } else { const mainApp = this._desktopManager.mainApp; mainApp.lookup_action('cleanUpIcons').activate(null); } return; } if (key === 'icon-size') { this._updateIconSize(); this._desktopManager.onIconSizeChanged(); return; } if (key === this._Enums.SortOrder.ORDER) { this.sortOrder = this.desktopSettings.get_enum(this._Enums.SortOrder.ORDER); const value = GLib.Variant.new_string( this.desktopSettings .get_string(this._Enums.SortOrder.ORDER) ); const mainApp = this._desktopManager.mainApp; mainApp.activate_action('arrangeaction', value); return; } if (key === 'unstackedtypes') { this._UnstackList = this.desktopSettings.get_strv('unstackedtypes'); this._desktopManager.onUnstackedTypesChanged(); return; } if (key === 'keep-stacked') { this.keepStacked = this.desktopSettings.get_boolean('keep-stacked'); this._desktopManager.onkeepStackedChanged(); return; } if (key === 'keep-arranged') { this.keepArranged = this.desktopSettings.get_boolean('keep-arranged'); this._desktopManager.onKeepArrangedChanged(); return; } if (key === 'show-drop-place') { this._showDropPlace = this.desktopSettings.get_boolean('show-drop-place'); return; } if (key === 'start-corner') { this._StartCorner = this._Enums.START_CORNER[ this.desktopSettings.get_string('start-corner') ]; return; } if (key === 'free-position-icons') { this.freePositionIcons = this.desktopSettings.get_boolean('free-position-icons'); } if (key === 'show-desktop-widgets') { this.desktopWidgetsEnabled = this.desktopSettings.get_boolean('show-desktop-widgets'); this._desktopManager.onWidgetDisplayChanged(); } // fallthrough this._desktopManager.reLoadDesktop() .catch(e => { console.log('Exception while updating Desktop after the' + ` settings changed: ${e.message}\n${e.stack}` ); }); }); // Gtk Settings this.gtkSettings.connect('changed', (obj, key) => { if (key === 'show-hidden') { this.showHidden = this.gtkSettings.get_boolean('show-hidden'); this._desktopManager.onGtkSettingsChanged() .catch(e => { console.log('Exception while updating desktop after' + ` "Show Hidden" changed: ${e.message}\n${e.stack}` ); }); } }); // Gnome Files Settings this.nautilusSettings.connect('changed', (obj, key) => { if (key === 'show-image-thumbnails') { this.showImageThumbnails = this.nautilusSettings .get_string('show-image-thumbnails') !== 'never'; this._desktopManager.redrawDesktop() .catch(e => { console.log('Exception while updating Desktop after the' + ` GNOME Files settings changed: ${e.message}\n${e.stack}` ); }); return; } if (key === 'click-policy') { this.CLICK_POLICY_SINGLE = this.nautilusSettings .get_string('click-policy') === 'single'; } if (key === 'open-folder-on-dnd-hover') { this.openFolderOnDndHover = this.nautilusSettings .get_boolean('open-folder-on-dnd-hover'); } }); // Icon Theme Changes this._gtkIconTheme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default()); this._gtkIconTheme.connect('changed', () => { this._refreshDesktopAndColors(); }); this._gtkSettings.connect('notify', (actor, paramSpec) => { if (paramSpec.name === 'gtk-theme-name') this._refreshDesktopAndColors(); if (paramSpec.name === 'gtk-enable-animations') this._refreshAnimations(); }); // Callback to handle accent color changes this._adwStyleManager.connect('notify::accent-color', () => { this._refreshBackgroundColor(); }); // Callback to handle theme (color scheme) changes this._adwStyleManager.connect('notify::dark', () => { this.darkmode = this._adwStyleManager.get_dark(); this._refreshBackgroundColor(); }); // Terminal settings Changes this.schemaTerminalSettings?.connect('changed', () => { this._updateTerminalSettings() .catch(e => logError(e)); }); // Mutter settings this.mutterSettings.connect('changed', () => { this._premultiplied = this._getPreMultiplied(); this._desktopManager.onMutterSettingsChanged(); }); if (this.accentColorsAvailable) return; // Gnome Theme Settings monitoring for older gnome and Adw versions this.schemaGnomeThemeSettings?.connect('changed', (obj, key) => { if (key === 'accent-color') { // Color changes do not seem to be applied immediately, wait.. if (this.cssColorDefinitionChangeID) GLib.source_remove(this.cssColorDefinitionChangeID); this.cssColorDefinitionChangeID = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 500, () => { this._refreshDesktopAndColors(); this.cssColorDefinitionChangeID = 0; return GLib.SOURCE_REMOVE; }); } }); } _configureHoverColor() { const box = new Gtk.Label(); const styleContext = box.get_style_context(); styleContext.add_class('view'); const [exists, color] = styleContext.lookup_color('accent_fg_color'); if (exists) { this.hoverColor = color; } else { this.hoverColor = new Gdk.RGBA({ red: 0.9, green: 0.9, blue: 0.9, alpha: 1.0, }); } } _configureSelectionColor() { try { if (this.accentColorsAvailable) { this.selectColor = this._adwStyleManager.get_accent_color_rgba(); } else { const box = new Gtk.Label(); const styleContext = box.get_style_context(); styleContext.add_class('view'); const [exists, color] = styleContext.lookup_color('accent_bg_color'); if (exists) { this.selectColor = color; } else { throw new Error( 'Style Context does not provide accent_bg_color' ); } } } catch (e) { console.log(e.message); console.log('Setting default accent color to blue'); this.selectColor = new Gdk.RGBA({ red: 0, green: 0, blue: 0.9, alpha: 1.0, }); } } _setCSSColors() { const cssColorDefinition = `@define-color desktop_icons_fg_color ${this.hoverColor.to_string()}; @define-color desktop_icons_bg_color ${this.selectColor.to_string()};`; this._cssColorProviderSelection = new Gtk.CssProvider(); // fix for api change Gtk 4.9 try { this._cssColorProviderSelection.load_from_data(cssColorDefinition); } catch (e) { const gsizeLength = -1; // NULL terminated string this._cssColorProviderSelection.load_from_data( cssColorDefinition, gsizeLength ); } Gtk.StyleContext.add_provider_for_display( Gdk.Display.get_default(), this._cssColorProviderSelection, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ); } _refreshColors() { Gtk.StyleContext.remove_provider_for_display( Gdk.Display.get_default(), this._cssColorProviderSelection); this._configureSelectionColor(); this._configureHoverColor(); this._setCSSColors(); } _refreshBackgroundColor() { Gtk.StyleContext.remove_provider_for_display( Gdk.Display.get_default(), this._cssColorProviderSelection); this._configureSelectionColor(); this._setCSSColors(); this._desktopManager?.onDarkModeChanged(); } _refreshDesktopAndColors() { this._refreshColors(); this._desktopManager.redrawDesktop() .catch(e => { console.log( 'Exception while updating desktop after an GTK icon-theme' + ` change: ${e.message}\n${e.stack}` ); }); } _refreshAnimations() { this.globalAnimations = this._gtkSettings.gtk_enable_animations ?? false; const enabled = this.globalAnimations ? 'enabled' : 'disabled'; console.log('System animations are', enabled); this._desktopManager?.onAnimationChanged(); } _initLocalCSSprovider() { const cssProvider = new Gtk.CssProvider(); const resourcePath = this._mainApp.get_resource_base_path(); cssProvider.load_from_resource(`${resourcePath}/stylesheet.css`); // Load user-local stylesheet override from config directory this._cssOverrideProvider = new Gtk.CssProvider(); this._loadCSSOverride(); Gtk.StyleContext.add_provider_for_display( Gdk.Display.get_default(), cssProvider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ); Gtk.StyleContext.add_provider_for_display( Gdk.Display.get_default(), this._cssOverrideProvider, Gtk.STYLE_PROVIDER_PRIORITY_USER ); this._createReloadCSSAction(); } _loadCSSOverride() { const configDir = GLib.get_user_config_dir(); const cssOverridePath = GLib.build_filenamev([ configDir, this._mainApp.get_application_id(), 'stylesheet-override.css', ]); const overrideFile = Gio.File.new_for_path(cssOverridePath); const overrideExists = overrideFile.query_exists(null); if (!overrideExists) { this._cssOverrideProvider.load_from_string(''); return; } try { this._cssOverrideProvider.load_from_path(cssOverridePath); console.info('Loaded CSS override file'); } catch (e) { console.error(`Failed to load CSS override: ${e}`); } } _createReloadCSSAction() { const reloadCSSAction = Gio.SimpleAction.new('reloadCSS', null); reloadCSSAction.connect('activate', this._loadCSSOverride.bind(this)); this._mainApp.add_action(reloadCSSAction); } _setupTerminalMonitors() { this._xdgTerminalMonitors = []; const systemFiles = this._xdgSystemConf.concat(this._xdgSystemData); const userFiles = [this._xdgUserConf, this._xdgUserData]; const filesToMonitor = userFiles.concat(systemFiles); filesToMonitor.forEach(f => { const fileMonitor = f.monitor( Gio.FileMonitorFlags.WATCH_MOVES, null ); fileMonitor.set_rate_limit(1000); fileMonitor.connect('changed', () => { this._updateTerminalSettings() .catch(e => { console.log( 'Exception while updating entries in System Terminal' + ` monitor: ${e.message}\n${e.stack}` ); }); }); this._xdgTerminalMonitors.push(fileMonitor); }); } _monitorTerminalSettings() { this._xdgUserConf = this._desktopIconsUtil.getUserTerminalConfFile(); this._xdgSystemConf = this._desktopIconsUtil.getSystemTerminalConfFile(); this._xdgUserData = this._desktopIconsUtil.getUserDataTerminalDir(); this._xdgSystemData = this._desktopIconsUtil.getSystemDataTerminalDirs(); this._setupTerminalMonitors(); this._updateTerminalSettings().catch(e => logError(e)); } _updateTerminalDconfSettings() { let defaultTerminal = null; if (this.schemaTerminalSettings) { defaultTerminal = this.schemaTerminalSettings .get_string(this._Enums.DCONF_TERMINAL_EXEC_KEY); } let terminal; let terminalappinfo; switch (defaultTerminal) { case 'gnome-terminal': terminal = 'org.gnome.Terminal.desktop'; terminalappinfo = DesktopAppInfo.new(terminal); if (!terminalappinfo) { terminal = 'org.gnome.Ptyxis.desktop'; terminalappinfo = DesktopAppInfo.new(terminal); } break; case 'gnome-console': default: terminal = 'org.gnome.Console.desktop'; terminalappinfo = DesktopAppInfo.new(terminal); } return terminalappinfo ? [terminalappinfo] : []; } async _updateTerminalXdgConf() { let userfileList = []; let systemfileList = []; if (this._xdgUserConf.query_exists(null)) { let userfilecontents; try { userfilecontents = await this._desktopIconsUtil .readFileContentsAsync( this._xdgUserConf ) .catch(e => console.error(e)); if (userfilecontents) { userfileList = this._desktopIconsUtil .parseTerminalList(userfilecontents); } } catch (e) { console.error(e); } } for (let f of this._xdgSystemConf) { if (f.query_exists(null)) { const systemFileContent = // eslint-disable-next-line no-await-in-loop await this._desktopIconsUtil.readFileContentsAsync(f); const x = this._desktopIconsUtil.parseTerminalList(systemFileContent); systemfileList = systemfileList.concat(x); } } return userfileList.concat(systemfileList); } async _updateTerminalXdgData() { let xdgDataFiles = []; const scanFiles = [this._xdgUserData, ...this._xdgSystemData]; for (let f of scanFiles) { if (f.query_exists(null)) { const systemFileContent = // eslint-disable-next-line no-await-in-loop await this._desktopIconsUtil.readFileContentsAsync(f); const x = this._desktopIconsUtil.parseTerminalList(systemFileContent); xdgDataFiles = xdgDataFiles.concat(x); } } return xdgDataFiles; } async _updateTerminalSettings() { this._terminalGioDesktopAppInfoList = []; const a = await this._updateTerminalXdgConf() .catch(e => console.error(e)); const b = await this._updateTerminalXdgData() .catch(e => console.error(e)); const c = this._updateTerminalDconfSettings(); this._terminalGioDesktopAppInfoList = a.concat(b.concat(c)); if (!this._terminalGioDesktopAppInfoList.length) return; this._terminal = this._terminalGioDesktopAppInfoList[0]; this._terminalExecString = this._terminal ?.get_string(this._Enums.DESKTOPFILE_TERMINAL_EXEC_SWITCH); if (!this._terminalExecString) this._terminalExecString = '-e'; } _getPreMultiplied() { if (this.usingX11) return false; const scalingEnabled = 'scale-monitor-framebuffer'; try { return this.mutterSettings .get_strv('experimental-features') .includes(scalingEnabled); } catch (e) {} return false; } _setPreMultiplied(premultiplied) { if (this.usingX11) return; const scalingEnabled = 'scale-monitor-framebuffer'; try { const featurearray = this.mutterSettings.get_strv('experimental-features'); if (premultiplied && !featurearray.includes(scalingEnabled)) featurearray.push(scalingEnabled); if (!premultiplied && featurearray.includes(scalingEnabled)) { const index = featurearray.indexOf(scalingEnabled); featurearray.splice(index, 1); } this.mutterSettings.set_strv('experimental-features', featurearray); } catch (e) { console.log('Error setting premultiplied:', e); } } /* * Load widget layout/config state from widgets.json into _widgetState. */ async _loadWidgetState(cancellable = null) { if (!this._desktopIconsUtil) return; const file = this._desktopIconsUtil.getWidgetsStateFile(); this._widgetState = await this._desktopIconsUtil.readJsonFile(file, cancellable) .catch(e => { console.log( 'Error reading widget state from widgets.json:', e.message ?? e ); return null; }); this._applyWidgetStateToManager(); } _applyWidgetStateToManager() { if (!this._desktopManager?.widgetManager) return; const state = this._widgetState ?? { version: 1, instances: [], }; this._desktopManager.widgetManager.loadState(state); } /* * Save widget layout/config state back to widgets.json. * * @param {object|null} state plain JSON-serializable object * (or null to just clear cache) */ async _saveWidgetState(state, cancellable = null) { if (!this._desktopIconsUtil) return; this._widgetState = state ?? null; if (!state) return; const file = this._desktopIconsUtil.getWidgetsStateFile(); // Prevent triggering monitor event while we write the file this._suppressWidgetMonitorEvent = true; await this._desktopIconsUtil.writeJsonFile(file, state, cancellable); // Allow monitor events after idle GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { this._suppressWidgetMonitorEvent = false; return GLib.SOURCE_REMOVE; }); } // Setters /** * @param {any} order */ set SortOrder(order) { this._sortOrder = order; this.desktopSettings.set_enum(this._Enums.SortOrder.ORDER, order); } set UnstackList(array) { this._UnstackList = array; this.desktopSettings.set_strv('unstackedtypes', array); } set fractionalScaling(boolean) { this._setPreMultiplied(boolean); } set widgetState(state = null) { this._widgetState = state; this._saveWidgetState(state).catch(e => { console.log( 'Error saving widget state to widgets.json:', e.message ?? e ); }); } // Getters get StartCorner() { // Return a shallow copy that can be mutated without affecting other // icons with cornerinversion in DesktopGrid return [...this._StartCorner]; } get UnstackList() { // Return a shallow copy that can be mutated without // affecting the original return [...this._UnstackList]; } get Terminal() { return this._terminal ?? null; } get TerminalGioList() { return this._terminalGioDesktopAppInfoList; } get TerminalExecString() { return this._terminalExecString; } get TerminalName() { if (this._terminal) return this._terminal.get_locale_string('Name'); else return _('Console'); } get NautilusName() { return this._gnomeFilesAppInfo.get_locale_string('Name'); } get showDropPlace() { return this._showDropPlace && !this.freePositionIcons; } get fractionalScaling() { if (this.usingX11) return false; return this._premultiplied; } get widgetState() { return this._widgetState; } get showDesktopWidgets() { return this.desktopWidgetsEnabled && this.desktopWidgetCapability; } };