Review of "Gtk4 Desktop Icons NG (DING)" version 100.30 (147)

Details Page Preview

Adw. Desktop Icons Libadwaita/Gtk4 port of Desktop Icons NG with multiple fixes and new features. Latest update (100.30): Drop or paste browser links, text, and images onto the desktop. **Paste as Link** creates symbolic links to copied local files. Added drag item counts and **Open in New Window** with Shift+Return when Nautilus is the default folder handler. Improved drag and drop, calendar dates, desktop stability, and translations. Previous update: Pinned widgets can now be positioned below all applications. Enable **Keep pinned widgets below application windows** in **Settings → Tweaks** to keep them above desktop icons but below normal applications, with their controls accessible without entering widget edit mode. Configurable keyboard shortcut available for toggling this mode. Now has a widget layer that can run widgets- like KDE desklets, they are little HTML display apps that run in Webkit. Icons cover this layer, layers can be moved up or down for editing. Widgets can be snapped to a grid to maintain row/column alignment or free positioned. Widgets are discovered automatically at startup from specific directories. You can install them manually by downloading the widget folder you want from the GitLab `widgets` directory and placing it in `$XDG_DATA_HOME/com.desktop.ding/widgets/` (typically `~/.local/share/com.desktop.ding/widgets/`). You can also use the Add Widget dialog's `Download Latest` button to automatically fetch and install the current widget set from the repository. Icons can be positioned anywhere on desktop or are snapped to a grid. Can make links on the Desktop. GSconnect Integration, can send files to connected devices. Drag and Drop support on to Dock, Dash, or from Dock, Dash to the Desktop. Updated and modified code base, uses Gio menus. All functions are asynchronous where possible. It is ported to ESM modules, supports Gnome 45 and higher. Translations available in- [ar, az, be, bg, bn, ca, cs, da, de, el, eo, es, et eu, fa, fi, fr, fur, ga, gl, he, hi, hr, hu, id, it, ja, ka, kab, kk, ko, ky, lv, lt, mi, ms, nb, nb_NO, nl, oc, pl, pt_BR, pt, ro, ru, sk, sl, sq, sv, ta, tl, tr, th, uk, ur, zh-Hans, zh-Hant, zh_CN, zh_TW] Translated using LibreTranslate, machine translation, not every string is verified manually. Although most strings in languages should be correct, errors are possible. Corrections, verification of translated strings, and new translations are welcome, all translations are on Weblate. You can help translate Adw. Desktop Icons NG on [Hosted Weblate](https://hosted.weblate.org/projects/gtk4-desktop-icons-ng/gtk4-ding-pot/). Multiple fixes and new features- * Add Widget dialog now includes a `Download Latest` button to automatically fetch and install the current widget set. * New media player/display widget in horizontal or vertical available for download. Multiple rendering fixes for the old widgets, please re-install. * Media widgets are now pinnable and include on-widget MPRIS controls for Previous, Play/Pause, Next, volume slider, +/- volume buttons, and mouse-wheel volume. * New Sticky Note widget with rich-text editing, checklist support, links, note colors, and floating/pinned window support. * Floating widget handling is improved with better overlay controls, focus retention, and more reliable redraw/reload behavior when moving widgets between desktop and pinned windows. * Add widget grid, improve widget chrome to stay on screen, multiple fixes to widget rendering to redisplay when desktop geometry changes, animates with icons on geometry changes. * Use GSK to draw instead of Cairo, optimizes GPU/CPU use. * Fixes to widget positioning, keyboard modifier selection of icons with arrow keys. * Fixes overview animation. * All widgets have been updated. Re-install from the widgets folder on GitLab Website, or use the Add Widget dialog's `Download Latest` button to install them automatically. * Widgets can now run backend processes for host side compute work. Added demo new metrics widget and Today(Calendar) view widget. Added helper classes for backend and widget for widget authors. * The program no explicitly asks for your permission prior to installing and running a widget and records this choice so you are not asked again. * Multiple fixes for the new widgets. * Widgets on desktop- little display desklets for Gnome. Demo widgets for weather and world clock available on Gitlab repo in the widgets subfolder. * Users can override CSS with their own CSS. * Uses LibreTranslate to automatically translate into 54 languages. * Right long click- launches shell background menu directly. * Animate margin changes with Adw.Animation. Respects global Gtk4/Gnome allow/disallow animation settings. * Improve search UI, files found containing the text in label are selected, non-selected files lose opacity an are dimmed so that found files are evident to the eye on a desktop with a large bunch of icons.. (Sundeep Mediratta) * Enable Gnome 49, use new API * Fixes, read xdg-terminals.list from correct system conf dirs. * Set localized default desktop name * Resizable open with dialog * Fix custom icons size * Update to more direct error message * Change name to Adw. Desktop Icons, version 100 :) * Feature complete shortcut manager with editable keybindings for app actions. * New About dialog and redesigned preferences. Proper credits and acknowledgements * Right click menu now displays and activates actions for .desktop files. * Added global hotkey accelerator to display or hide desktop icons. * New ShortCutsManager that displays Adw.Window and widgets for shortcuts. * Complete rewrite of the app, major clean up and restructuring. * Add a .desktop icon with actions for app, can be displayed in dock for windows, launcher, menus etc with right click actions, including hiding all windows * Show a shortcuts window for the application to list all available shortcuts. * Improve multi-monitor support, saves monitor positon with icon position, allow to change fractional scaling in app if a second monitor connected at different zoom level. * Fix dd-term focus loss isssue. * App rewritten as Adw.Application GObject subclass, better css handling, use Adw.Stylemanager, better icons and emblems for stackTop items. * Integrate ptyxis, replaces gnome-terminal on some distributions. Open ptyxis properly. * Modern emblems like Gnome Files, allow multiple emblems * Emblem for encrypted pdf, zip, 7z files * Allow setting any user folder as the Desktop folder following xdg-sepecifications and updating the xdg-files and vice versa in the running program. * Proper app icon, image and app name in Notifications. * Proper integration for AppImage files, treat them like .desktop files. Integration with AppImageLauncher. Prefer that to open AppImage files if available. * For Gnome 47, change highlighting and rubber band selection colors with accent-colors in Gnome Settings. * Selection rectangle with rounded corners, similar to Gnome Files aesthetic. * The stock gnome shell background menu can now be shown from the Gtk4 DING desktop right click menu. All shell settings can be accessed from that menu. * Icons can be placed on any arbitrary position. Make a mess! - icons can overlap each other etc. Neat people can keep the default behavior and have the icons always snapped to a grid. Controlled in preferences, tweaks, 'Snap to grid'. Affects the shape of icons and drag and drop behavior as well. Free positioning has trapezoidal icons, drop only works with direct overlap. Grid positioning has rectangular icons, and drag and drop works on overlap with the grid holding the icon. This behavior is consistent with other desktop environments. * Icons on background on overview, improved gesture switching icons appear to be on all work spaces on the background with workspace switching, with no flashing. * Support for dragging icons onto the dock - Drag icons from desktop to and drop over application icon to open them with the app. Works with Dash to Dock and Dash to Panel. * Support for dragging icons from desktop directly to Trash on Dash to Dock, or to mounted volumes on the dock, to copy them directly. * Set the correct cursor with proposed action on drop on dock. * Drag Navigation on Dock - dragging an icon over the Gnome Files icon on the dock or mounted drives, and hovering over it for 1/2 seconds will open a Gnome Files Window. Behavior can be changed in preferences. * Drag Navigation - dragging an icon over a folder icon or a drive icon, and then hovering over it for one and half seconds will open that location in Gnome Files. * Sets correct hovering behavior during drag and drop on the Dock, enables scrolling in the dock to icons when they are hidden. * Drag and drop Favorite apps from Dash to Dock, Dash to Panel directly to Desktop. Pressing shift, ctr or alt while doing this will copy or move the app to Desktop, allowing launching from the desktop. Just dropping an app from the dock to the desktop will remove from Dash/Dock. * Follows xdg-terminal-exec to display the correct terminal in right click menus, and will launch the correct terminal, even if xdg-terminal-exec is not installed. * Shows the correct file manager in the right click menu and give the user the option to change the file manager. * Gio menus, menus display all keyboard shortcuts. * Uses Gtk4 AlertDialog, uses asynchronous promises for dialog's, shows button to launch URL for help and troubleshooting information. * Automatically zip Folders if mailing them. * Tool tips are now positioned correctly to not go under the dash or make it auto hide, or go over/under any gnome shell actors on the edge of the screen. * Right Click Menus will not go under the dock. * Make Links on Desktop with Alt button on Wayland. Shift, Ctr or Alt button control the effect, move, copy, drop or link. (Linking may not work on X11) * Copied/dropped/pasted files retain dropped position. Undo action after trashing or moving files puts icons back in the old position. * Better multi monitor support, preference to place icons on non primary monitor. * GSconnect extension integration, can send files from desktop directly to connected mobile device. * Accessibility support with screen readers * Deals correctly with appimage files on desktop. * Display GIMP thumbnails, even for snap and flatpack installs. * Lazy Gtk.Widget tree creation and further refactoring and cleanup of all icon code. Please see Readme for full details of new features. Works best on Wayland. However your mileage may vary on X11. Multiple bugs fixed on X11. Please report all issues on the Gitlab link below, this page is not monitored. All known issues as well as all the features are detailed there.

Extension Homepage
https://gitlab.com/smedius/desktop-icons-ng

No comments.

Diff Against

Files

Note: Binary files aren't shown on the web site. To see all files, please download the extension zipfile.

Shexli (experimental) error 3 warning 20

Shexli found 23 issues that may need reviewer attention.

EGO-A-004 warning

extension files should not contain excessive ungated console logging

File contains 13 ungated console.log/warn/error calls (threshold: 5).

No excessive logging

  • app/desktopFolderMonitor.js:159
                        console.log('desktop-icons: The desktop is writable by' +
                            ' others. Not allowing launching any desktop files.'
                        )
  • app/desktopFolderMonitor.js:612
                console.log(
                    'Exception while updating Desktop after a' +
                    ` mount was added: ${e.message}\n${e.stack}`
                )
  • app/desktopFolderMonitor.js:621
                console.log(
                    'Exception while updating Desktop after a ' +
                    `mount was removed: ${e.message}\n${e.stack}`
                )
  • app/desktopFolderMonitor.js:45
    console.error(e)
  • app/desktopFolderMonitor.js:57
    console.error(e)
  • app/desktopFolderMonitor.js:130
    console.error(e)
  • app/desktopFolderMonitor.js:134
    console.error(e)
  • app/desktopFolderMonitor.js:198
    console.error(e)
  • app/desktopFolderMonitor.js:286
                            console.error(
                                e,
                                'Exception while updating desktop from' +
                                ` Directory Monitor attribute change: ${e.message}`
                            )
  • app/desktopFolderMonitor.js:301
                console.error(
                    e,
                    'Exception while updating desktop from Directory Monitor: ' +
                    `${e.message}`
                )
  • app/fileItemIcon.js:697
                console.log(
                    'Could not apply discrete GPU environment, switcheroo-control' +
                    ' not available'
                )
  • app/fileItemIcon.js:706
                console.log(
                    'Could not apply discrete GPU environment. No GPUs in list.'
                )
  • app/fileItemIcon.js:737
    console.log('Could not find discrete GPU data in switcheroo-control')
  • app/fileItemIcon.js:54
    console.error(e, `Error setting encryption status: ${e.message}`)
  • app/fileItemIcon.js:387
                    console.error(
                        e, `Error opening file ${this.file.get_uri()}: ${e.message}`
                    )
  • app/fileItemIcon.js:507
    console.error(e)
  • app/fileItemIcon.js:608
                    console.error(
                        e,
                        'Exception while updating icon on Metadata Changed: ' +
                        `${e.message}`
                    )
  • app/fileItemIcon.js:625
                    console.error(
                        e,
                        `Exception while updating ${
                            this._getVisibleName?.() ?? 'an icon'
                        }: ${e.message}`
                    )
  • app/fileItemIcon.js:646
    console.error(e)
  • app/fileItemIcon.js:733
    console.error(e)

EGO-A-004 warning

extension files should not contain excessive ungated console logging

File contains 8 ungated console.log/warn/error calls (threshold: 5).

No excessive logging

  • app/desktopManager.js:863
    console.log('Not enough space to add icons')
  • app/desktopManager.js:1874
                console.log('Exception while reloading desktop after icon ' +
                    `size change: ${e.message}\n${e.stack}`)
  • app/desktopManager.js:1073
    console.error(e, 'Error loading stackMarker icon')
  • app/desktopManager.js:1756
                        console.error(
                            e, `Failed to set attributes to ${dir.get_path()}`)
  • app/desktopManager.js:1763
    console.error(e, `Failed to create folder ${e.message}`)
  • app/desktopManager.js:1794
                console.error(
                    `Error while redrawing desktop: ${e.message}\n${e.stack}`
                )
  • app/desktopManager.js:1812
    console.error(`Error while refreshing desktop: ${e.message}`)
  • app/desktopManager.js:1825
    console.error(`Error while reframing desktop: ${e.message}`)
  • dependencies/gi.js:10
    console.log('GLibUnix not found.')
  • dependencies/gi.js:35
    console.log('GioUnix not found, falling back to Gio...')
  • dependencies/gi.js:51
    console.log(`WebKit GI not found; desktop widgets disabled\n${e}`)
  • dependencies/gi.js:58
    console.log(`Soup GI not found; desktop widgets disabled\n${e}`)
  • dependencies/gi.js:18
    console.error(e)
  • dependencies/gi.js:26
    console.error(`Install Poppler for proper fallback pdf thumbnailing \n ${e}`)
  • dependencies/gi.js:29
    console.error(`Install Cairo for proper fallback pdf thumbnailing \n ${e}`)
  • dependencies/gi.js:46
    console.error('DesktopAppInfo is not available on this system!')

EGO-A-004 warning

extension files should not contain excessive ungated console logging

File contains 11 ungated console.log/warn/error calls (threshold: 5).

No excessive logging

  • app/desktopMenu.js:55
    console.log(`Could not get activation token: ${e.message}`)
  • app/desktopMenu.js:275
                        console.log(
                            `Exception while updating desktop after pressing "F5":
                            ${e.message}\n${e.stack}`)
  • app/desktopMenu.js:68
    console.error(e)
  • app/desktopMenu.js:80
    console.error(e, 'Paste action failed')
  • app/desktopMenu.js:94
    console.error(e, 'Paste as Link failed')
  • app/desktopMenu.js:322
    console.error(e)
  • app/desktopMenu.js:446
    console.error(error, 'Error navigating preview')
  • app/desktopMenu.js:508
                console.error(
                    e, `Error opening desktop in GNOME Files: ${e.message}`
                )
  • app/desktopMenu.js:816
                    console.error(
                        e, `Failed to set template metadata ${e.message}`)
  • app/desktopMenu.js:823
    console.error(e, `Failed to create template ${e.message}`)

EGO-A-004 warning

extension files should not contain excessive ungated console logging

File contains 18 ungated console.log/warn/error calls (threshold: 5).

No excessive logging

  • app/fileItemMenu.js:922
    console.log('Reverting to old method of selecting')
  • app/fileItemMenu.js:1049
    console.log('zip command not installed, cannot send email')
  • app/fileItemMenu.js:1080
    console.log(`Error Zipping Files, ${e}`)
  • app/fileItemMenu.js:1097
    console.log('xdg-email command not installed, cannot send email')
  • app/fileItemMenu.js:1116
    console.log(`Error emailing Files, ${e}`)
  • app/fileItemMenu.js:1245
    console.log('Executed xdg-terminal-exec')
  • app/fileItemMenu.js:1248
    console.log(`Error opening xdg-terminal-exec ${e}`)
  • app/fileItemMenu.js:1273
    console.log(`{Error opening ${t.get_string('Name')}, ${e}`)
  • app/fileItemMenu.js:567
    console.error(e)
  • app/fileItemMenu.js:647
    console.error(e)

EGO-A-004 warning

extension files should not contain excessive ungated console logging

File contains 9 ungated console.log/warn/error calls (threshold: 5).

No excessive logging

  • app/gnomeShellDragDrop.js:239
                        console.log(
                            'Could not parse desktopFile as a desktop file,' +
                            ' cannot set shell cursor'
                        )
  • app/gnomeShellDragDrop.js:336
    console.log('Could not parse desktopFile as desktop file')
  • app/gnomeShellDragDrop.js:67
    console.error(e)
  • app/gnomeShellDragDrop.js:88
    console.error(e)
  • app/gnomeShellDragDrop.js:129
    console.error(e)
  • app/gnomeShellDragDrop.js:175
                    console.error(
                        e, `Error opening ${uri} in GNOME Files: ${e.message}`
                    )
  • app/gnomeShellDragDrop.js:298
                console.error(e,
                    'Error reading desktop file. Cannot set shell Cursor'
                )
  • app/gnomeShellDragDrop.js:373
                    console.error(e,
                        'Error reading desktop file. Cannot launch application.'
                    )
  • app/gnomeShellDragDrop.js:397
    console.error(e)
  • app/thumbnails.js:212
                    console.log(
                        `Timeout while generating thumbnail for ${file.displayName}`
                    )
  • app/thumbnails.js:589
                console.log(
                    `Error when asking for a thumbnail for ${file.displayName}:` +
                    ` ${error.message}\n${error.stack}`)
  • app/thumbnails.js:241
    console.error(`Error saving thumbnail ${e}`)
  • app/thumbnails.js:247
                    console.error(e,
                        'Error creating thumbnail with thumbnailFactory: ' +
                        `${e.message}`
                    )
  • app/thumbnails.js:276
    console.error(`Error saving thumbnail ${e}`)
  • app/thumbnails.js:294
                    console.error(e,
                        `Error while creating failed thumbnail: ${e.message}`
                    )
  • app/thumbnails.js:319
                    console.error(e,
                        `Error while generating icon image: ${e.message}`
                    )
  • app/thumbnails.js:394
                    console.error(e,
                        `Error creating pdf thumbnail pixbuf ${file.uri}`
                    )
  • app/thumbnails.js:438
                console.error(e,
                    `Error creating image thumbnail pixbuf ${file.uri}`
                )
  • app/utils/desktopIconsUtil.js:331
    console.log(`Failed to get the list of mounts with ${e}`)
  • app/utils/desktopIconsUtil.js:359
    console.log(`Failed with ${e} while getting volume`)
  • app/utils/desktopIconsUtil.js:856
                                            console.log(
                                                'Failed to make executable ' +
                                                `.desktop File: ${error.message}`
                                            )
  • app/utils/desktopIconsUtil.js:203
    console.error(e, `${commandLine} failed with ${e}`)
  • app/utils/desktopIconsUtil.js:670
    console.error(`Error determining encryption Zip file ${e}`)
  • app/utils/desktopIconsUtil.js:695
    console.error(`Error determining encryption 7z file ${e}`)
  • app/utils/desktopIconsUtil.js:867
    console.error(e)
  • app/utils/desktopIconsUtil.js:986
    console.error(`readJsonFile(${file.get_path?.() ?? '??'}):`, e)
  • app/utils/desktopIconsUtil.js:1017
    console.error('writeJsonFile: JSON.stringify failed:', e)

EGO-X-003 warning

extensions should not call run_dispose in extension code

Extension code should not call `run_dispose()`.

GObject.Object.run_dispose

  • app/htmlWidgetHost.js:158
    this._webView.run_dispose()

EGO-A-004 warning

extension files should not contain excessive ungated console logging

File contains 17 ungated console.log/warn/error calls (threshold: 5).

No excessive logging

  • app/htmlWidgetHostWithBackend.js:203
                    console.warn(
                        'HtmlWidgetHostWithBackend: failed to move backend to systemd scope:',
                        e
                    )
  • app/htmlWidgetHostWithBackend.js:239
                            console.warn(
                                'BACKEND stderr:',
                                inst?.instanceId ?? '<unknown>',
                                line.trim()
                            )
  • app/htmlWidgetHostWithBackend.js:502
    console.log(`HtmlWidget backend ${level}:`, inst.instanceId, text)
  • app/htmlWidgetHostWithBackend.js:90
                console.error(
                    'HtmlWidgetHostWithBackend: failed to fetch descriptor:',
                    e
                )
  • app/htmlWidgetHostWithBackend.js:98
                console.error(
                    'HtmlWidgetHostWithBackend: no descriptor for widget',
                    inst?.widgetId ?? '<unknown>'
                )
  • app/htmlWidgetHostWithBackend.js:146
    console.error(`Failed to move ${description} to systemd scope:`, e)
  • app/htmlWidgetHostWithBackend.js:156
                console.error(
                    'HtmlWidgetHostWithBackend: no backend configured for widget',
                    inst?.widgetId ?? '<unknown>'
                )
  • app/htmlWidgetHostWithBackend.js:230
    console.error('BACKEND stdout loop error:', e?.message ?? e)
  • app/htmlWidgetHostWithBackend.js:248
    console.error('BACKEND stderr loop error:', e?.message ?? e)
  • app/htmlWidgetHostWithBackend.js:263
                console.error(
                    'HtmlWidgetHostWithBackend: failed to start backend:', e
                )
  • dingManager.js:746
    console.warn(`Failed to move ${this._processID} to systemd scope:`, e)
  • dingManager.js:280
    console.log('Adw-DING enabled.')
  • dingManager.js:350
    console.log('Adw-DING disabled.')
  • dingManager.js:364
    console.log(`${name} DBus Name Acquired`)
  • dingManager.js:368
    console.log(`${name} DBus and Name Lost`)
  • dingManager.js:418
    console.log(`${this.dbusConnectionName} DBus Name Relinquished`)
  • dingManager.js:554
    console.log(`Killing old DING process ${filename}`)
  • dingManager.js:597
    console.log('Launching Adw-DING process')
  • dingManager.js:804
                    console.log(
                        `${this._processID}: ${textDecoder.decode(output)}`
                    )
  • dingManager.js:130
    console.error('Gtk4 DING extension requires a Wayland session')

EGO-A-004 warning

extension files should not contain excessive ungated console logging

File contains 29 ungated console.log/warn/error calls (threshold: 5).

No excessive logging

  • app/preferences.js:46
    console.log('System supports accent colors')
  • app/preferences.js:50
    console.log('System does not support accent colors')
  • app/preferences.js:166
    console.log('schemaObj does not exist!')
  • app/preferences.js:167
    console.log('Current extension path:', this._extensionPath)
  • app/preferences.js:168
    console.log('Current schemaFile:', schemaFile.get_path())
  • app/preferences.js:169
    console.log('Schema File exists:', schemaFile.query_exists(null))
  • app/preferences.js:285
                console.log(
                    'Error loading widget state from widgets.json:',
                    e.message ?? e
                )
  • app/preferences.js:312
                        console.log(
                            'Exception while updating desktop after "Dark Text"' +
                            ` changed: ${e.message}\n${e.stack}`
                        )
  • app/preferences.js:327
                        console.log(
                            'Exception while updating desktop after ' +
                            `"Show Emblems" changed: ${e.message}\n${e.stack}`
                        )
  • app/preferences.js:372
                        console.log('Exception while updating desktop after ' +
                            `icon size changed: ${e.message}\n${e.stack}`)

EGO-A-004 warning

extension files should not contain excessive ungated console logging

File contains 7 ungated console.log/warn/error calls (threshold: 5).

No excessive logging

  • app/templatesScriptsManager.js:263
                    console.warn(
                        'Folder Symlink in monitored templates/scripts folder...\n',
                        'This can lead to unlimited recursion.'
                    )
  • app/templatesScriptsManager.js:56
                                console.log(
                                    'Exception while updating entries in ' +
                                    `monitor: ${e.message}\n${e.stack}`
                                )
  • app/templatesScriptsManager.js:67
                    console.log(
                        'Exception while updating entries: ' +
                        `${e.message}\n${e.stack}`
                    )
  • app/templatesScriptsManager.js:144
                    console.log(
                        'Limiting the number of folders monitored in ' +
                        'templates/scripts...'
                    )
  • app/templatesScriptsManager.js:152
                    console.log(
                        'Limiting submenu depth of folders monitored' +
                        ' in templates/scripts...'
                    )
  • app/templatesScriptsManager.js:252
    console.log('Truncating menu entries templates/scripts submenu')
  • app/templatesScriptsManager.js:99
    console.error(e)
  • app/utils/desktopFolderUtils.js:110
                console.error(
                    `Unable to create Folder ${defaultDesktop}: ${e.message}`
                )
  • app/utils/desktopFolderUtils.js:143
    console.error(e, `XDG Desktop not set, ${e}`)
  • app/utils/desktopFolderUtils.js:164
    console.error('No system xdg user-dirs.default file')
  • app/utils/desktopFolderUtils.js:184
    console.error(e, `XDG Desktop not set in user-dirs.default, ${e}`)
  • app/utils/desktopFolderUtils.js:200
    console.error(e, `Error selecting folder: ${e.message}`)
  • app/utils/desktopFolderUtils.js:278
    console.error(e, `Failed to write XDG Desktop file with ${e}`)
  • app/utils/desktopFolderUtils.js:308
    console.error(e, `Failed to write XDG Desktop file with ${e}`)

EGO-A-004 warning

extension files should not contain excessive ungated console logging

File contains 37 ungated console.log/warn/error calls (threshold: 5).

No excessive logging

  • app/utils/dbusUtils.js:199
                    console.log(
                        `Error creating proxy, ${this._programNeeded[0]}:` +
                        ` ${e.message}\n${e.stack}`
                    )
  • app/utils/dbusUtils.js:272
                        console.log(
                            `Error creating proxy, ${this._programNeeded[0]}:` +
                            ` ${e.message}\n${e.stack}`
                        )
  • app/utils/dbusUtils.js:295
    console.log(this._programNeeded[0])
  • app/utils/dbusUtils.js:296
    console.log(this._programNeeded[1])
  • app/utils/dbusUtils.js:627
                    console.log(
                        'Error getting introspection data over Dbus: ' +
                        `${e.message}\n${e.stack}`
                    )
  • app/utils/dbusUtils.js:730
                            console.log(
                                'Can not get the extractable types:' +
                                ` ${error.message}.` +
                                `\nEnsure that File-Roller is installed.\n${error}.`
                            )
  • app/utils/dbusUtils.js:746
    console.log(e.message, e.stack)
  • app/utils/dbusUtils.js:773
    console.log(`Error showing properties: ${error.message}`)
  • app/utils/dbusUtils.js:796
    console.log(`Error showing folder: ${error.message}`)
  • app/utils/dbusUtils.js:816
                        console.log(
                            `Error showing file on desktop: ${error.message}`
                        )

EGO-X-004 warning

extensions should avoid synchronous file IO in shell code

Shell code should avoid synchronous file IO APIs like `GLib.file_get_contents()` and `Gio.File.load_contents()`.

File Operations

  • app/utils/desktopFolderUtils.js:137
    GLib.file_get_contents(userDirsGioFile.get_path())
  • app/utils/desktopFolderUtils.js:174
    GLib.file_get_contents(systemDirsGioFile.get_path())
  • app/utils/desktopFolderUtils.js:264
    GLib.file_get_contents(userDirsGioFile.get_path())

EGO-X-002 warning

extensions should not use synchronous subprocess APIs in shell code

Shell code should avoid synchronous subprocess APIs like `GLib.spawn_command_line_sync()` and `GLib.spawn_sync()`.

Complete Examples

  • app/utils/desktopIconsUtil.js:658
    GLib.spawn_command_line_sync(command)
  • app/utils/desktopIconsUtil.js:687
    GLib.spawn_command_line_sync(command)

EGO-A-004 warning

extension files should not contain excessive ungated console logging

File contains 26 ungated console.log/warn/error calls (threshold: 5).

No excessive logging

  • app/widgetManager.js:327
                console.warn(
                    `createInstanceForWidget: no descriptor for ${widgetId},` +
                    ' using fallback html kind'
                )
  • app/widgetManager.js:946
                console.warn(
                    `WidgetManager loadState: state version ${schemaVersion} ` +
                    `(current ${WIDGETS_STATE_SCHEMA_VERSION}); migrating`
                )
  • app/widgetManager.js:2567
    console.warn('No widget selected or widget has no preferences UI.')
  • app/widgetManager.js:2834
            console.warn(
                `WidgetManager: GTK widget kind requested for ${inst.widgetId}, ` +
                'but GTK widget support is not implemented yet'
            )
  • app/widgetManager.js:57
    console.error('WidgetManager: failed to clone widget config:', e)
  • app/widgetManager.js:308
    console.error('createInstanceForWidget: missing widgetId')
  • app/widgetManager.js:313
    console.error('createInstanceForWidget: widgetRegistry missing')
  • app/widgetManager.js:322
    console.error(`Descriptor load failed for ${widgetId}:`, e)
  • app/widgetManager.js:344
                console.error(
                    `createInstanceForWidget: invalid monitorIndex ${monitorIndex}`
                )
  • app/widgetManager.js:843
    console.error('WidgetManager: listAvailableWidgets failed:', e)

EGO-A-004 warning

extension files should not contain excessive ungated console logging

File contains 12 ungated console.log/warn/error calls (threshold: 5).

No excessive logging

  • app/widgetRegistry.js:202
    console.warn('WidgetRegistry: failed to resolve user root:', e)
  • app/widgetRegistry.js:217
    console.warn('WidgetRegistry: failed to build system roots:', e)
  • app/widgetRegistry.js:345
                            console.warn(
                                `WidgetRegistry:
                                rejecting widget with invalid id in ${mf}`
                            )
  • app/widgetRegistry.js:513
            console.warn(
                `WidgetRegistry: duplicate widget id "${id}": ` +
                `${existingPath} (${existingScope}) vs ` +
                `${newPath} (${newScope}) — ${action}`
            )
  • app/widgetRegistry.js:35
    console.error('WidgetRegistry: failed to clone JSON object:', e)
  • app/widgetRegistry.js:64
    console.error('WidgetRegistry.preload():', e)
  • app/widgetRegistry.js:160
                console.error(
                    'WidgetRegistry: getHtmlEntryFile failed for',
                    id,
                    e
                )
  • app/widgetRegistry.js:188
                console.error(
                    'WidgetRegistry: application-id not available; ' +
                    'widget paths will not be resolved.'
                )
  • app/widgetRegistry.js:289
                console.error(
                    'WidgetRegistry: enumerate_children failed for',
                    root.get_path?.(),
                    e
                )
  • app/widgetRegistry.js:440
                console.error(
                    'WidgetRegistry: error scanning root',
                    root.get_path?.(),
                    e
                )

EGO-A-004 warning

extension files should not contain excessive ungated console logging

File contains 34 ungated console.log/warn/error calls (threshold: 5).

No excessive logging

  • app/widgetWebContext.js:283
                console.warn(
                    'WebWidgetContext.openPreferencesForInstance: no instance',
                    instanceId
                )
  • app/widgetWebContext.js:439
                console.warn(
                    'WebWidgetContext: failed to configure ding-widget scheme security:',
                    e
                )
  • app/widgetWebContext.js:491
    console.warn('Unknown CSP profile, enforcing STRICT')
  • app/widgetWebContext.js:573
                console.warn(
                    'WebWidgetContext: unexpected widget message payload',
                    json,
                    typeof json,
                    'raw jsValue:',
                    jsValue,
                    'ctor:',
                    jsValue?.constructor?.name
                )
  • app/widgetWebContext.js:855
    console.warn('Widget openExternalLink rejected invalid URL:', rawUrl, error)
  • app/widgetWebContext.js:861
    console.warn('Widget openExternalLink rejected scheme:', scheme || '<none>')
  • app/widgetWebContext.js:1018
                console.warn(
                    'WebWidgetContext: suppressing config update burst for widget instance',
                    instanceId,
                    `(${guard.count} updates in ${CONFIG_UPDATE_WINDOW_MS}ms)`
                )
  • app/widgetWebContext.js:1051
                console.warn(
                    `WebWidgetContext: suppressing ${label} for widget instance`,
                    instanceId,
                    `type=${kind}`,
                    `(${guard.count} events in ${windowMs}ms)`
                )
  • app/widgetWebContext.js:1102
                console.warn(
                    'WebWidgetContext: failed to inspect request origin for widget response:',
                    e
                )
  • app/widgetWebContext.js:1204
            console.warn(
                'WebWidgetContext: served missing widget resource as 404',
                resourcePath
            )

EGO-I-002 error

Gtk, Gdk and Adw must not be imported in shell process files

GTK library `Adw` must not be imported in extension process files.

Do not import GTK libraries in GNOME Shell

  • dependencies/gi.js:1
    import Adw from 'gi://Adw';

EGO-I-002 error

Gtk, Gdk and Adw must not be imported in shell process files

GTK library `Gdk` must not be imported in extension process files.

Do not import GTK libraries in GNOME Shell

  • dependencies/gi.js:2
    import Gdk from 'gi://Gdk?version=4.0';

EGO-I-002 error

Gtk, Gdk and Adw must not be imported in shell process files

GTK library `Gtk` must not be imported in extension process files.

Do not import GTK libraries in GNOME Shell

  • dependencies/gi.js:22
    import Gtk from 'gi://Gtk';

EGO-P-007 warning

JavaScript files should be reachable from extension.js or prefs.js

Some JavaScript files are not reachable from `extension.js` or `prefs.js` imports.

Don't include unnecessary files

  • app/adw-ding.js

EGO-L-005 warning

owned object references should be released in disable()

Owned references that are cleaned up in `disable()` should also be released with `null` or `undefined`.

Destroy all objects

  • app/preferences.js:56
    this.gtkSettings = new Gio.Settings({settings_schema: schemaGtk})
  • app/preferences.js:99
                this.mutterSettings =
                    new Gio.Settings({settings_schema: schemaMutter})
  • app/preferences.js:90
                this.nautilusCompression =
                    new Gio.Settings({settings_schema: compressionSchema})
  • app/preferences.js:67
                this.nautilusSettings =
                    new Gio.Settings({settings_schema: schemaObj})
  • app/preferences.js:125
                this.schemaGnomeThemeSettings =
                    new Gio.Settings({settings_schema: schemaGnomeSettings})
  • app/preferences.js:108
                this.schemaTerminalSettings =
                    new Gio.Settings({settings_schema: schemaTerminalSettings})
  • app/windowManager.js:86
            this._dbusGeometryIface =
                    Gio.DBusExportedObject.wrapJSObject(signalXml, this)

EGO-L-003 warning

signals connected by extension should be disconnected in disable()

Signals assigned in `enable()` are missing matching disconnect calls in `disable()` or its helper methods.

Disconnect all signals

  • app/adwPreferencesWindow.js:191
            button.connect('clicked', () => {
                this.reloadCSS();
            })
  • app/adwPreferencesWindow.js:176
    this.cssOverrideButton.connect('activated', this.openUserCssOverrideFile.bind(this))
  • app/adwPreferencesWindow.js:257
    this.shortcutButton.connect('activated', this.showShortcuts.bind(this))
  • app/appChooser.js:146
            this.appChooserDialog.connect('close', () => {
                this.appChooserDialog.response(Gtk.ResponseType.CANCEL);
            })
  • app/appChooser.js:150
            this.appChooserDialog.connect('response', (actor, retval) => {
                if (retval === Gtk.ResponseType.OK) {
                    this._checkUpdateDefaultAppForMimeType();
                    this.applicationSelectionComplete(this.selectedAppInfo);
                } else {
                    this.applic
  • app/appChooser.js:129
            this.appChooserWidget.connect(
                'application-activated',
                this._onApplicationActivated.bind(this)
            )
  • app/appChooser.js:134
            this.appChooserWidget.connect(
                'application-selected',
                this._onApplicationSelected.bind(this)
            )
  • app/askRenamePopup.js:80
            this._buttonId =
                this._button.connect(
                    'clicked',
                    this._do_rename.bind(this)
                )
  • app/askRenamePopup.js:122
            this._focusTrackerID =
                this._focusTracker.connect('leave', this.close.bind(this))
  • app/askRenamePopup.js:125
            this._popoverId =
                this._popover.connect('closed', this.close.bind(this))
  • app/askRenamePopup.js:95
            this._textAreaActivateId =
                this._textArea.connect('activate', this._do_rename.bind(this))
  • app/askRenamePopup.js:86
            this._textAreaChangedId =
                this._textArea.connect(
                    'changed',
                    () => {
                        this._validate()
                        .catch(e => console.error(e));
                    }
                )
  • app/autoAr.js:41
            this._progressWindow.connect('close-request', () => {
                return true;
            })
  • app/autoAr.js:306
            this._cancelButton.connect('clicked', () => {
                if (this._buttonPromiseAccept) {
                    this._buttonPromiseAccept(false);
                    return;
                }
                this._cancellable.cancel();
            })
  • app/autoAr.js:344
    this._passEntry.connect('activate', passOKfunc)
  • app/autoAr.js:341
            this._passEntry.connect('icon-release', () => {
                this._passEntry.visibility = !this._passEntry.visibility;
            })
  • app/autoAr.js:323
    this._passOkButton.connect('clicked', passOKfunc)
  • app/autoAr.js:651
            this._dialog.connect('response', (dialog, id) => {
                if (id === Gtk.ResponseType.ACCEPT) {
                    const data =
                        this._desktopManager
                        .autoAr.getFormatAndFilterForExtension(
                            this._compressOptions[this._selectedT
  • app/autoAr.js:639
            this._extensionDropdown.connect('clicked', () => {
                this._extensionPopoverContainer.show();
                this._extensionPopover.popup();
                for (let index in this._compressOptions) {
                    const data = this._compressOptions[index];
                    data.selected_i
  • app/autoAr.js:649
    this._nameEntry.connect('activate', () => this._entryActivated())
  • app/autoAr.js:647
    this._nameEntry.connect('changed', () => this._updateStatus())
  • app/autoAr.js:650
    this._passEntry.connect('activate', () => this._entryActivated())
  • app/autoAr.js:648
    this._passEntry.connect('changed', () => this._updateStatus())
  • app/desktopFolderMonitor.js:216
            this._volumeMonitor.connect(
                'mount-added',
                () => {
                    this.onMountAdded();
                }
            )
  • app/desktopFolderMonitor.js:223
            this._volumeMonitor.connect(
                'mount-removed',
                () => {
                    GLib.timeout_add(
                        GLib.PRIORITY_DEFAULT,
                        500,
                        () => {
                            this.onMountRemoved();
                            return GLib.S
  • app/desktopFolderMonitor.js:63
            changeDesktop.connect('activate', () => {
                this.changeDesktop();
            })
  • app/desktopFolderMonitor.js:72
            this.restoreDefaultDesktopAction.connect('activate', () => {
                this.restoreDefaultDesktop();
            })
  • app/desktopFolderMonitor.js:202
            cancellable.connect(
                () => {
                    this._monitorDesktopDir.disconnect(monitorID);
                    this._monitorDesktopDir.cancel();
                    this._monitorDesktopDir = null;
                    this.monitorDesktopCancellable = null;
                }
            )
  • app/desktopGrid.js:113
            this._window.connect(
                'close-request',
                () => {
                    if (this._destroying)
                        return false;
    
                    if (this._asDesktop) {
                        // Do not destroy window when closing if the instance
                        // is working a
  • app/desktopGrid.js:91
                this._window.connect('map', () => {
                    if (!this._resolveMapped)
                        return;
                    this._resolveMapped(true);
                    this._resolveMapped = null;
                    // Maximize however creates an error where the window can
                    // be
  • app/desktopGrid.js:109
            this._window.connect('notify::css_classes', () => {
                this._window.set_css_classes(['background']);
            })
  • app/desktopGrid.js:1547
            this._buttonClick.connect('pressed', (actor, nPress, x, y) => {
                this._doGesturePress(actor, nPress, x, y);
            })
  • app/desktopGrid.js:1551
            this._buttonClick.connect('released', (actor, nPress, x, y) => {
                if (this._longHandled)
                    this._longHandled = false;
    
                this._doGestureRelease(actor, nPress, x, y);
            })
  • app/desktopGrid.js:1543
            this._buttonLongClick.connect('cancelled', _actor => {
                this._longHandled = false;
            })
  • app/desktopGrid.js:1538
            this._buttonLongClick.connect('pressed', (actor, x, y) => {
                this._longHandled = true;
                this._doGestureLongPress(actor, x, y);
            })
  • app/desktopGrid.js:1495
            this._eventKey.connect(
                'key-pressed',
                this._onKeyPress.bind(this)
            )
  • app/desktopGrid.js:1500
            this._eventKeyState.connect(
                'key-pressed',
                this._onModifierUpdate.bind(this)
            )
  • app/desktopGrid.js:1505
            this._eventKeyState.connect(
                'key-released',
                this._onModifierClear.bind(this)
            )
  • app/desktopGrid.js:1514
            this._eventMotion.connect(
                'motion',
                (actor, x, y) => {
                    if (!this._dragManager.rubberBand)
                        return false;
    
                    const [X, Y] = this.coordinatesLocalToGlobal(x, y);
                    this._dragManager.onMotion(X, Y);
            
  • app/desktopGrid.js:2967
            this._offsetAnim.connect('done', () => {
                this._setLiveOffset(-this._tweenDelta.dx, -this._tweenDelta.dy);
                // Ensure we end exactly at identity scale
                if (this._moveAway) {
                    this._setLiveTransform(
                        1.0, this._tweenDelta.piv
  • app/desktopMenu.js:408
            fileOperationsManager.connect('changed-status',
                (actor, available) => {
                    if (available)
                        this._syncUndoRedo();
                    else
                        this._syncUndoRedo(true);
                }
            )
  • app/desktopMenu.js:223
            arrangeByDescendingName.connect(
                'activate',
                () => this._mainApp.activate_action(
                    'arrangeaction',
                    new GLib.Variant('s', 'DESCENDINGNAME')
                )
            )
  • app/desktopMenu.js:244
            arrangeByKind.connect(
                'activate',
                () => this._mainApp.activate_action(
                    'arrangeaction',
                    new GLib.Variant('s', 'KIND')
                )
            )
  • app/desktopMenu.js:234
            arrangeByModifiedTime.connect(
                'activate',
                () => this._mainApp.activate_action(
                    'arrangeaction',
                    new GLib.Variant('s', 'MODIFIEDTIME')
                )
            )
  • app/desktopMenu.js:212
            arrangeByName.connect(
                'activate',
                () => this._mainApp.activate_action(
                    'arrangeaction',
                    new GLib.Variant('s', 'NAME')
                )
            )
  • app/desktopMenu.js:254
            arrangeBySize.connect(
                'activate',
                () => this._mainApp.activate_action(
                    'arrangeaction',
                    new GLib.Variant('s', 'SIZE')
                )
            )
  • app/desktopMenu.js:139
            changeBackGround.connect(
                'activate',
                () => {
                    const desktopFile =
                        DesktopAppInfo.new('gnome-background-panel.desktop');
                    const context =
                        Gdk.Display.get_default().get_app_launch_context();
            
  • app/desktopMenu.js:169
            changeDesktopIconSettings.connect(
                'activate',
                this._showPreferences.bind(this)
            )
  • app/desktopMenu.js:154
            changeDisplaySettings.connect(
                'activate',
                () => {
                    const desktopFile =
                        DesktopAppInfo.new('gnome-display-panel.desktop');
                    const context =
                        Gdk.Display.get_default().get_app_launch_context();
          
  • app/desktopMenu.js:352
            chooseIconDown.connect('activate', () => {
                this._selectFileItemInDirection(Gdk.KEY_Down);
            })
  • app/desktopMenu.js:334
            chooseIconLeft.connect('activate', () => {
                this._selectFileItemInDirection(Gdk.KEY_Left);
            })
  • app/desktopMenu.js:340
            chooseIconRight.connect('activate', () => {
                this._selectFileItemInDirection(Gdk.KEY_Right);
            })
  • app/desktopMenu.js:346
            chooseIconUp.connect('activate', () => {
                this._selectFileItemInDirection(Gdk.KEY_Up);
            })
  • app/desktopMenu.js:177
            cleanUpIconsAction.connect(
                'activate',
                () => this._desktopManager.sortAllFilesFromGridsByPosition()
                    .catch(e => logError(e))
            )
  • app/desktopMenu.js:374
            createDesktopShortcut.connect('activate', (action, parameter) => {
                this._createDesktopShortcut(parameter.recursiveUnpack());
            })
  • app/desktopMenu.js:365
            displayShellBackgroundMenu.connect('activate', () => {
                this._DBusUtils.RemoteExtensionControl.showShellBackgroundMenu();
            })
  • app/desktopMenu.js:74
            this.doPasteSimpleAction.connect(
                'activate',
                async () => {
                    try {
                        await this._clipboardManager.paste();
                    } catch (e) {
                        console.error(e, 'Paste action failed');
                    }
                }
         
  • app/desktopMenu.js:109
            this.doRedoSimpleAction.connect(
                'activate',
                () => this._doRedo()
            )
  • app/desktopMenu.js:102
            this.doUndoSimpleAction.connect(
                'activate',
                () => this._doUndo()
            )
  • app/desktopMenu.js:264
            findFilesAction.connect(
                'activate',
                () => this._desktopManager.findFiles(null)
            )
  • app/desktopMenu.js:358
            menuKeyPressed.connect('activate', () => {
                this._menuKeyPressed();
            })
  • app/desktopMenu.js:381
            newDocument.connect('activate', (action, parameter) => {
                this._newDocument(parameter.deep_unpack());
            })
  • app/desktopMenu.js:67
            newFolder.connect('activate', () => {
                this._desktopManager.doNewFolder().catch(e => console.error(e));
            })
  • app/desktopMenu.js:132
            openDesktopInTerminal.connect(
                'activate',
                this._onOpenTerminalClicked.bind(this)
            )
  • app/desktopMenu.js:88
            pasteAsLink.connect(
                'activate',
                async () => {
                    try {
                        await this._clipboardManager.paste(true);
                    } catch (e) {
                        console.error(e, 'Paste as Link failed');
                    }
                }
            )
  • app/desktopMenu.js:306
            previewAction.connect('activate', () => {
                if (this._desktopManager.popupmenu ||
                    this._desktopManager.fileItemMenu.popupmenu ||
                    !this.activeFileItem)
                    return;
    
                this._setKeyboardSelected(this.activeFileItem);
    
                c
  • app/desktopMenu.js:206
            radioArrangeAction.connect('change-state',
                this._syncArrangeOrder.bind(this))
  • app/desktopMenu.js:116
            selectAll.connect(
                'activate',
                () => this._selectAll()
            )
  • app/desktopMenu.js:124
            showDesktopInFiles.connect(
                'activate',
                () => this._onOpenDesktopInFilesClicked().catch(e => logError(e))
            )
  • app/desktopMenu.js:285
            showHideHiddenFiles.connect(
                'activate',
                () => {
                    this._Prefs.gtkSettings.set_boolean('show-hidden',
                        !this._Prefs.showHidden);
                }
            )
  • app/desktopMenu.js:328
            toggleKeyboardSelection.connect('activate', () => {
                this._toggleKeyboardSelection();
            })
  • app/desktopMenu.js:390
            toggleVisibility.connect('activate', () => {
                this._windowManager.toggleVisibility();
            })
  • app/desktopMenu.js:295
            unselectAll.connect(
                'activate',
                () => {
                    this._desktopManager.unselectAll();
                    if (this.searchString)
                        this.searchString = null;
                }
            )
  • app/desktopMenu.js:271
            updateDesktop.connect(
                'activate',
                async () => {
                    await this._desktopManager.reLoadDesktop().catch(e => {
                        console.log(
                            `Exception while updating desktop after pressing "F5":
                            ${e.message
  • app/fileItemMenu.js:601
            this._docopy.connect(
                'activate',
                this._doCopy.bind(this)
            )
  • app/fileItemMenu.js:594
            this._docut.connect(
                'activate',
                this._doCut.bind(this)
            )
  • app/fileItemMenu.js:641
            allowdisallowlaunching.connect('activate', () => {
                if (!this.activeFileItem)
                    return;
    
                this.activeFileItem
                    .onAllowDisallowLaunchingClicked()
                    .catch(e => console.error(e));
            })
  • app/fileItemMenu.js:740
            bulkCopy.connect(
                'activate',
                this._bulkCopy.bind(this)
            )
  • app/fileItemMenu.js:747
            bulkMove.connect(
                'activate',
                this._bulkMove.bind(this)
            )
  • app/fileItemMenu.js:696
            compressfiles.connect(
                'activate',
                this._doCompressFilesFromSelection.bind(this, null)
            )
  • app/fileItemMenu.js:625
            this.deletePermanantly.connect(
                'activate',
                () => this.doDeletePermanently()
            )
  • app/fileItemMenu.js:765
            desktopAction.connect(
                'activate',
                (_action, parameter) => {
                    const [path, actionName, action] = parameter.deepUnpack();
                    this._desktopFileAction(path, actionName, action);
                }
            )
  • app/fileItemMenu.js:573
            doopenwith.connect('activate', () => {
                this._doOpenWith().catch(e => logError(e));
            })
  • app/fileItemMenu.js:608
            dorename.connect('activate', () => {
                this._desktopManager
                    .doRename(this.activeFileItem, false)
                    .catch(e => logError(e));
            })
  • app/fileItemMenu.js:652
            eject.connect('activate', () => {
                this.activeFileItem.eject().catch(e => console.error(e));
            })
  • app/fileItemMenu.js:633
            emptytrash.connect(
                'activate',
                () => this.doEmptyTrash()
            )
  • app/fileItemMenu.js:664
            extractautoar.connect(
                'activate',
                () => {
                    this._desktopManager.getCurrentSelection()
                    ?.forEach(
                        f => this._desktopManager.autoAr.extractFile(f.fileName));
                }
            )
  • app/fileItemMenu.js:675
            extracthere.connect(
                'activate',
                this._extractFileFromSelection.bind(this, true)
            )
  • app/fileItemMenu.js:682
            extractto.connect(
                'activate',
                this._extractFileFromSelection.bind(this, false)
            )
  • app/fileItemMenu.js:579
            graphicslaunch.connect('activate', () => {
                if (!this.activeFileItem)
                    return;
                this.activeFileItem._doDiscreteGpu();
            })
  • app/fileItemMenu.js:732
            makeLinks.connect(
                'activate',
                this._makeLinks.bind(this)
            )
  • app/fileItemMenu.js:616
            this.moveToTrash.connect(
                'activate',
                () => this.doTrash()
            )
  • app/fileItemMenu.js:704
            newfolderfromselection.connect(
                'activate',
                this._newFolderFromSelection.bind(this)
            )
  • app/fileItemMenu.js:755
            onScriptClicked.connect(
                'activate',
                (_action, parameter) => {
                    this._onScriptClicked(parameter.unpack());
                }
            )
  • app/fileItemMenu.js:565
            openInNewWindow.connect('activate', () => {
                this._doOpenInNewWindow(this.activeFileItem)
                    .catch(e => console.error(e));
            })
  • app/fileItemMenu.js:529
            openMultipleFileAction.connect(
                'activate',
                this._doMultiOpen.bind(this)
            )
  • app/fileItemMenu.js:537
            openOneFileAction.connect(
                'activate',
                () => {
                    if (this.activeFileItem) {
                        if (this.activeFileItem.isStackMarker) {
                            this._onToggleStackUnstackThisTypeClicked(
                                this.activeFileItem.at
  • app/fileItemMenu.js:725
            openinterminal.connect(
                'activate',
                this._openInTerminal.bind(this)
            )
  • app/fileItemMenu.js:711
            properties.connect(
                'activate',
                this._onPropertiesClicked.bind(this)
            )
  • app/fileItemMenu.js:587
            runasaprogram.connect(
                'activate',
                this._runExecutableScript.bind(this)
            )
  • app/fileItemMenu.js:689
            sendto.connect(
                'activate',
                this._mailFilesFromSelection.bind(this, null)
            )
  • app/fileItemMenu.js:718
            showinfiles.connect(
                'activate',
                this._onShowInFilesClicked.bind(this)
            )
  • app/fileItemMenu.js:555
            stackunstack.connect(
                'activate',
                (_action, paramenter) => {
                    this._onToggleStackUnstackThisTypeClicked(paramenter.unpack());
                })
  • app/fileItemMenu.js:658
            unmount.connect('activate', () => {
                this.activeFileItem.unmount().catch(e => console.error(e));
            })
  • app/preferences.js:77
            this._fileManagerMonitor.connect('changed', () => {
                this._updateFileManager();
            })
  • app/shortcutManager.js:463
            this._userShortcutMonitor = this._desktopSettings.connect(
                'changed',
                (obj, key) => {
                    if (key === 'shortcutoverrides')
                        this._refreshUserShortcuts();
                }
            )
  • app/shortcutManager.js:434
            this._mainApp.connect(
                'action-added',
                (_app, name) => this._setAccel(name)
            )
  • app/shortcutManager.js:438
            this._mainApp.connect(
                'action-enabled-changed',
                (_app, name, _enabled) => this._setAccel(name)
            )
  • app/shortcutManager.js:584
            showShortcutViewer.connect('activate', () => {
                this._showShortcutViewer();
            })
  • app/shortcutManager.js:598
            textEntryAccelsTurnOff.connect('activate', () => {
                this._textEntryAccelsTurnOff();
            })
  • app/shortcutManager.js:591
            textEntryAccelsTurnOn.connect('activate', () => {
                this._textEntryAccelsTurnOn();
            })
  • app/showErrorPopup.js:75
    this._dialog.connect('response', this._callback.bind(this))
  • app/symLinkIcon.js:132
                    this._symlinkFileMonitorId = this._symlinkFileMonitor.connect(
                        'changed',
                        this._updateSymlinkIcon.bind(this)
                    )
  • app/templatesScriptsManager.js:50
                this._monitorDir.connect(
                    'changed',
                    () => {
                        this.updateEntries()
                        .catch(
                            e => {
                                console.log(
                                    'Exception while updating entries in '
  • app/utils/dbusUtils.js:86
            dbusManager.connect(
                inSystemBus
                    ? 'changed-availability-system'
                    : 'changed-availability-local',
                () => {
                    this._makeProxy(makeAsync);
                }
            )
  • app/utils/dbusUtils.js:699
            this.archiveConnectionId =
                this.gnomeArchiveManager.connect(
                    'changed-status',
                    (_actor, available) => {
                        if (available) {
                            // wait a second to ensure that everything has settled
                            GLib
  • app/utils/dbusUtils.js:1001
            GnomeNautilusPreview.connect('changed-status', (_manager, available) => {
                if (!available)
                    this._releasePreviewHandle();
            })
  • app/utils/dbusUtils.js:1005
            mainApp.connect('shutdown', () => {
                this._previewRequest++;
                this._releasePreviewHandle();
            })
  • app/utils/dbusUtils.js:1399
            this.SwitcherooControl.connect('changed-status', (obj, newStatus) => {
                this.discreteGpuAvailable = newStatus;
            })
  • app/utils/gsConnect.js:36
            this.GsConnectManager.connect('changed-status', () => {
                GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => {
                    this._startGsConnectService();
                    return false;
                });
            })
  • app/utils/gsConnect.js:158
            sendfiles.connect('activate', (action, parameter) => {
                let device = parameter.recursiveUnpack();
                this._send_files(device);
            })
  • app/utils/gsConnect.js:56
                this.signalID =
                    this.gsConnectProxy.connect(
                        'g-signal',
                        this._on_g_signal.bind(this)
                    )
  • app/widgetManager.js:269
            this._dbusScreenSaverActiveChangedId =
                this._desktopManager.DBusUtils.connect(
                    'screen-saver-active-changed',
                    (_dbusUtils, active) => {
                        if (active)
                            return;
    
                        this.schedulePinnedWindowWa
  • app/widgetManager.js:2933
                addButton.connect('clicked', async () => {
                    if (creationInProgress)
                        return;
    
                    const row = list.get_selected_row();
                    if (!row || !row._widgetId) {
                        window.close();
                        resolve(null);
          
  • app/widgetManager.js:3238
            addWidgetAction.connect('activate', () => {
                const parentWindow =
                    this._desktopManager.getDialogParentWindow();
                if (!parentWindow)
                    return;
    
                this.clearSelectedInstance();
    
                const monitorIndex = this.getMonitorIndexF
  • app/widgetManager.js:2910
                cancelButton.connect('clicked', () => {
                    window.close();
                })
  • app/widgetManager.js:3287
    closeWidget.connect('activate', this.deleteSelectedInstance.bind(this))
  • app/widgetManager.js:2914
                downloadButton.connect('clicked', async () => {
                    try {
                        const didInstall = await this.downloadLatestWidgets(
                            parentWindow,
                            cancellable
                        );
    
                        if (didInstall) {
             
  • app/widgetManager.js:2963
                list.connect('row-activated', () => {
                    addButton.activate();
                })
  • app/widgetManager.js:3257
            showGridAction.connect('activate', () => {
                const parentWindow = this._desktopManager.getDialogParentWindow();
                if (!parentWindow)
                    return;
    
                const parentSurfaceWindow = parentWindow;
                const monitorIndex = this.getMonitorIndexForWind
  • app/widgetManager.js:3294
            updatePinnedWindowPosition.connect('activate', (_action, parameter) => {
                if (!parameter)
                    return;
    
                const [instanceId, x, y] = parameter.deepUnpack();
                this.updatePinnedWindowPosition(instanceId, x, y);
            })
  • app/widgetManager.js:2968
                window.connect('close-request', () => {
                    cancellable.cancel();
    
                    if (reopeningAfterDownload)
                        return false;
    
                    if (!creationInProgress)
                        resolve(null);
    
                    GLib.idle_add(GLib.PRIORITY_DEFAULT_I
  • app/widgetWindow.js:422
            this._dragGesture.connect(
                'drag-begin',
                this._onOverlayDragBegin.bind(this)
            )
  • app/widgetWindow.js:337
            this._hoverController.connect('enter', () => {
                this._overlay.add_css_class('pointer-inside');
                this._showControlsStrip();
            })
  • app/widgetWindow.js:341
            this._hoverController.connect('leave', () => {
                this._overlay.remove_css_class('pointer-inside');
                this._hideControlsStrip();
            })
  • app/windowManager.js:633
            this._Prefs.desktopSettings.connect(
                'changed::show-desktop-widgets',
                syncPinnedWidgetsAction
            )
  • app/windowManager.js:593
            action.connect('activate', () => {
                this.toggleWidgetLayers();
            })
  • app/windowManager.js:601
            lowerAction.connect('activate', () => {
                this.lowerWidgetLayers();
            })
  • app/windowManager.js:609
            raiseAction.connect('activate', () => {
                this.raiseWidgetLayers();
            })
  • app/windowManager.js:619
            togglePinnedWidgetsBelowApps.connect('activate', () => {
                const settings = this._Prefs.desktopSettings;
                settings.set_boolean(
                    'keep-pinned-widgets-below-apps',
                    !settings.get_boolean('keep-pinned-widgets-below-apps')
                );
          
  • app/windowManager.js:64
            updateGridWindows.connect('activate', (action, parameter) => {
                this.updateGridWindows(parameter)
                .catch(e => logError(e));
            })
  • windowTypeManager.js:585
            this._restackedBottomID = global.display.connect('restacked',
                this._syncToBottomOfStack.bind(this)
            )
  • windowTypeManager.js:636
            this._restackedTopID = global.display.connect('restacked',
                this._syncToTopOfStack.bind(this)
            )
  • windowTypeManager.js:78
            this._titleID = this._window.connect('notify::title', () => {
                this.refreshProperties();
            })
  • windowTypeManager.js:361
                    this._window.connect_after('raised', () => {
                        if (this._desktopWindow && !this.windowInstanceId &&
                            !this._raiseDesktopAsDock)
                            this._syncToBottomOfStack();
                    })

EGO-L-004 warning

main loop sources should be removed in disable()

Main loop sources assigned in `enable()` are missing matching removals in `disable()` or its helper methods.

Remove main loop sources

  • app/desktopFolderMonitor.js:226
                    GLib.timeout_add(
                        GLib.PRIORITY_DEFAULT,
                        500,
                        () => {
                            this.onMountRemoved();
                            return GLib.SOURCE_REMOVE;
                        }
                    )
  • app/utils/dbusUtils.js:453
            this._signalTimerID =
                GLib.timeout_add(
                    GLib.PRIORITY_DEFAULT,
                    1000,
                    () => {
                        this._signalTimerID = 0;
                        this._updateAllAvailabilities();
    
                        if (this._pendingLocalSignal)
          
  • app/utils/dbusUtils.js:705
                            GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => {
                                try {
                                    this._getExtractionSupportedTypes();
                                } catch (e) {}
                                return false;
                            })
  • app/utils/gsConnect.js:37
                GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => {
                    this._startGsConnectService();
                    return false;
                })
  • app/widgetManager.js:257
            this._pendingPinnedWindowReloadId = GLib.idle_add(
                GLib.PRIORITY_DEFAULT_IDLE,
                () => {
                    this._pendingPinnedWindowReloadId = 0;
                    this._reloadPinnedHtmlWidgetsInWindows(reason)
                        .catch(e => logError(e));
                    r
  • app/widgetManager.js:2977
                    GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
                        this.restoreWidgetLayerFocus(monitorIndex);
                        return GLib.SOURCE_REMOVE;
                    })
  • windowTypeManager.js:484
            this._moveIntoPlaceID =
                GLib.timeout_add(GLib.PRIORITY_LOW, 250, () => {
                    if (force || this._needsMoveToParsedPosition()) {
                        if (this.windowInstanceId) {
                            this._moveFrameWithoutTrackingFeedback(
                                

EGO-M-008 warning

extensions using unlock-dialog must document it in disable() comments

Extensions using `unlock-dialog` should document the reason in `disable()` comments.

Session Modes

  • extension.js:22
        disable() {
            this.dingManager?.disable();
            this.dingManager = null;
            this.DesktopIconsUsableArea = null;
        }

All Versions

Version Status
100.30 (147) Active
100.30 (146) Rejected
100.29 (145) Active
100.29 (144) Rejected
100.29 (143) Active
100.28 (142) Active
100.27 (141) Active
100.26 (140) Active
100.25 (139) Inactive
100.24 (138) Inactive
100.24 (137) Rejected
100.23 (136) Inactive
100.22 (135) Active
100.21 (134) Rejected
100.20 (133) Rejected
100.19 (132) Active
100.18 (131) Rejected
100.17 (130) Rejected
100.17 (129) Active
100.16 (128) Active
100.15 (127) Inactive
100.14 (126) Active
100.14 (125) Rejected
100.14 (124) Rejected
100.14 (123) Rejected
100.13 (122) Active
100.12 (121) Inactive
100.12 (120) Rejected
100.11 (119) Active
100.9 (118) Active
100.8 (117) Active
100.8 (116) Inactive
100.7 (115) Active
100.6 (114) Inactive
100.5 (113) Active
100.4 (112) Active
100.3 (111) Active
100.2 (110) Active
100.1 (109) Active
100 (108) Active
100 (107) Active
99 (106) Active
98 (105) Active
98 (104) Rejected
97 (103) Active
96 (102) Active
95 (101) Inactive
94 (100) Inactive
93 (99) Inactive
92 (98) Active
91 (97) Inactive
91 (96) Rejected
91 (95) Inactive
90 (94) Active
90 (93) Rejected
89 (92) Active
88 (91) Active
87 (90) Active
86 (89) Active
85 (88) Active
84 (87) Active
83 (86) Active
82 (85) Active
81 (84) Inactive
80 (83) Active
79 (82) Active
78 (81) Active
77 (80) Active
76 (79) Active
75 (78) Inactive
74 (77) Inactive
74 (76) Inactive
74 (75) Rejected
74 (74) Rejected
73 (73) Active
72 (72) Active
71 (71) Active
70 (70) Active
69 (69) Active
68 Active
67 Active
66 Active
65 Rejected
64 Rejected
63 Active
62 Active
61 Active
60 Active
59 Active
58 Inactive
57 Active
56 Active
55 Active
54 Active
53 Rejected
52 Rejected
51 Rejected
50 Rejected
49 Active
48 Rejected
47 Active
46 Active
45 Active
44 Rejected
43 Active
42 Active
41 Active
40 Active
39 Active
38 Active
37 Active
36 Active
35 Active
34 Active
33 Active
32 Active
31 Active
30 Active
29 Rejected
28 Active
27 Active
26 Active
25 Active
24 Active
23 Active
22 Active
21 Active
20 Active
19 Rejected
18 Active
17 Active
16 Active
15 Active
14 Active
13 Active
12 Active
11 Active
10 Active
9 Active
8 Active
7 Active
6 Active
5 Active
4 Rejected
3 Active
2 Active
1 Rejected

Previous Reviews on this Version

GdH active