A customizable GNOME Shell extension that enhances the user experience with various modules and features. Clipboard History reads and stores clipboard content locally so it can be browsed and restored. Capture Tools writes captured images and locally recognized text to the clipboard when requested. No clipboard or OCR data is shared with third parties, and the Clipboard History shortcut is unset by default.
Note: Binary files aren't shown on the web site. To see all files, please download the extension zipfile.
EGO-A-005 manual_review
extensions should not access the clipboard directly
Direct clipboard access via `St.Clipboard.get_default()` requires reviewer scrutiny.
capture/captureTools.js:566
St.Clipboard.get_default()
capture/screenshotCapture.js:38
St.Clipboard.get_default()
clipboard/clipboardHistory.js:158
St.Clipboard.get_default()
clipboard/clipboardHistory.js:169
St.Clipboard.get_default()
clipboard/clipboardMonitor.js:52
St.Clipboard.get_default()
EGO-L-002 warning
objects created by extension should be destroyed in disable()
Objects assigned in `enable()` are missing matching `.destroy()` calls in `disable()` or its helper methods.
capture/captureTools.js:115
this._ocrLayer = new St.Widget({ reactive: false, x_expand: true, y_expand: true })
capture/captureTools.js:511
this._textEntry = entry
dock/externalStorageIcon.js:242
this._ejectItem = new PopupMenu.PopupMenuItem(ejectLabel)
dock/externalStorageIcon.js:220
this._iconActor = new St.Icon({
gicon: this._item.icon,
icon_size: size,
style_class: 'show-apps-icon',
track_hover: true,
})
dock/externalStorageIcon.js:230
this._menu = new PopupMenu.PopupMenu(this.toggleButton, 0.5, St.Side.TOP)
dock/externalStorageIcon.js:234
this._menuManager = new PopupMenu.PopupMenuManager(this.toggleButton)
dock/externalStorageIcon.js:236
this._openItem = new PopupMenu.PopupMenuItem(
this._item.mount ? _('Open') : _('Mount and Open'),
)
dock/externalStorageIcon.js:177
this.toggleButton = new St.Button({
style_class: 'show-apps',
track_hover: true,
can_focus: true,
reactive: true,
})
dock/trashIcon.js:97
this._emptyItem = new PopupMenu.PopupMenuItem(_('Empty Trash'))
dock/trashIcon.js:78
this._iconActor = new St.Icon({
icon_name: this._empty ? ICON_EMPTY : ICON_FULL,
icon_size: size,
style_class: 'show-apps-icon',
track_hover: true,
})
dock/trashIcon.js:88
this._menu = new PopupMenu.PopupMenu(this.toggleButton, 0.5, St.Side.TOP)
dock/trashIcon.js:92
this._menuManager = new PopupMenu.PopupMenuManager(this.toggleButton)
dock/trashIcon.js:33
this.toggleButton = new St.Button({
style_class: 'show-apps',
track_hover: true,
can_focus: true,
reactive: true,
})
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`.
dock/externalStorageIcon.js:242
this._ejectItem = new PopupMenu.PopupMenuItem(ejectLabel)
dock/externalStorageIcon.js:220
this._iconActor = new St.Icon({
gicon: this._item.icon,
icon_size: size,
style_class: 'show-apps-icon',
track_hover: true,
})
dock/externalStorageIcon.js:230
this._menu = new PopupMenu.PopupMenu(this.toggleButton, 0.5, St.Side.TOP)
dock/externalStorageIcon.js:234
this._menuManager = new PopupMenu.PopupMenuManager(this.toggleButton)
dock/externalStorageIcon.js:236
this._openItem = new PopupMenu.PopupMenuItem(
this._item.mount ? _('Open') : _('Mount and Open'),
)
dock/externalStorageIcon.js:177
this.toggleButton = new St.Button({
style_class: 'show-apps',
track_hover: true,
can_focus: true,
reactive: true,
})
dock/trashIcon.js:97
this._emptyItem = new PopupMenu.PopupMenuItem(_('Empty Trash'))
dock/trashIcon.js:78
this._iconActor = new St.Icon({
icon_name: this._empty ? ICON_EMPTY : ICON_FULL,
icon_size: size,
style_class: 'show-apps-icon',
track_hover: true,
})
dock/trashIcon.js:88
this._menu = new PopupMenu.PopupMenu(this.toggleButton, 0.5, St.Side.TOP)
dock/trashIcon.js:92
this._menuManager = new PopupMenu.PopupMenuManager(this.toggleButton)
dock/trashIcon.js:33
this.toggleButton = new St.Button({
style_class: 'show-apps',
track_hover: true,
can_focus: true,
reactive: true,
})
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.
capture/captureTools.js:199
scope.connect(ui, 'closed', () => this._resetSession())
capture/captureTools.js:201
scope.connect(button, 'notify::checked', () => this._syncVisibility())
capture/captureTools.js:203
scope.connect(button, 'notify::checked', () => this._clearOcr())
capture/captureTools.js:204
scope.connect(ui._selectionButton, 'notify::checked', () => this._syncToolbarPlacement())
capture/captureTools.js:205
scope.connect(ui._areaSelector, 'drag-started', () => {
this._clearOcr();
this._setInteractionState('selection');
})
capture/captureTools.js:209
scope.connect(ui._areaSelector, 'drag-ended', () => {
this._setInteractionState('idle');
this._syncToolbarPlacement();
})
capture/captureTools.js:214
scope.connect(this._toolbar, 'notify::allocation', () => this._syncToolbarPlacement())
capture/captureTools.js:503
entry.clutter_text.connect('activate', () => this._commitText(true))
capture/captureTools.js:509
entry.clutter_text.connect('key-focus-out', () => this._commitText(true))
capture/captureTools.js:504
entry.clutter_text.connect('key-press-event', (_actor, event) => {
if (event.get_key_symbol() !== Clutter.KEY_Escape) return Clutter.EVENT_PROPAGATE;
this._commitText(false);
return Clutter.EVENT_STOP;
})
clipboard/clipboardHistory.js:80
this._lifecycle.connect(rawSettings, 'changed::clipboard-history-poll-interval', () => {
this._monitor?.setInterval(rawSettings.get_int('clipboard-history-poll-interval'));
})
desktop/trayIcons/trayIcons.js:113
this._lifecycle.connect(settings, 'changed::tray-icons-hide-bg-quick-settings', () => {
if (settings.get_boolean('tray-icons-hide-bg-quick-settings')) {
this._hideBgAppsQuickSettings();
} else {
this._restoreBgAppsQuickSettings();
}
})
desktop/trayIcons/trayIcons.js:120
this._lifecycle.connect(settings, 'changed::tray-icons-recolor-symbolic-pixmaps', () => {
logger.debug(
`Recolor symbolic SNI pixmaps=${settings.get_boolean('tray-icons-recolor-symbolic-pixmaps')}; refreshing SNI icons`,
{ prefix: LOG_PREFIX },
);
this._sniHost?
desktop/trayIcons/trayIcons.js:75
this._lifecycle.connect(this._desktopSettings, 'changed::color-scheme', () => {
const scheme = this._desktopSettings?.getString('color-scheme') ?? 'unknown';
logger.debug(`Color scheme changed to ${scheme}; refreshing SNI icons`, {
prefix: LOG_PREFIX,
});
this._sn
desktop/trayIcons/trayIcons.js:89
this._lifecycle.connect(settings, 'changed::tray-icons-limit', () => {
this._container?.setLimit(settings.get_int('tray-icons-limit'));
})
desktop/trayIcons/trayIcons.js:92
this._lifecycle.connect(settings, 'changed::tray-icons-icon-size', () => {
this._container?.setIconSize(settings.get_int('tray-icons-icon-size'));
})
desktop/trayIcons/trayIcons.js:95
this._lifecycle.connect(settings, 'changed::tray-icons-attention-timeout', () => {
this._container?.setAttentionTimeout(settings.get_int('tray-icons-attention-timeout'));
})
desktop/trayIcons/trayIcons.js:98
this._lifecycle.connect(settings, 'changed::tray-icons-dedup-bg-apps', () => {
this._dedupBgApps = settings.get_boolean('tray-icons-dedup-bg-apps');
if (this._dedupBgApps) {
for (const [appId, entry] of [...this._bgItemAppIds]) {
this._sniCoversApp(appId, entry.app)
panel/auroraMenu.js:78
this._lifecycle.connect(settings, `changed::${MENU_ICON_KEY}`, () => this._syncPanelIcon())
panel/auroraMenu.js:79
this._lifecycle.connect(settings, `changed::${APP_STORE_COMMAND_KEY}`, rebuildMenu)
panel/auroraMenu.js:80
this._lifecycle.connect(settings, `changed::${CUSTOM_ITEMS_KEY}`, rebuildMenu)
panel/auroraMenu.js:81
this._lifecycle.connect(settings, `changed::${CUSTOM_ENABLED_KEY}`, rebuildMenu)
panel/auroraMenu.js:82
this._lifecycle.connect(settings, `changed::${CUSTOM_LABEL_KEY}`, rebuildMenu)
panel/auroraMenu.js:83
this._lifecycle.connect(settings, `changed::${CUSTOM_COMMAND_KEY}`, rebuildMenu)
panel/auroraMenu.js:84
this._lifecycle.connect(settings, `changed::${SHOW_ABOUT_KEY}`, rebuildMenu)
panel/auroraMenu.js:85
this._lifecycle.connect(settings, `changed::${SHOW_HOME_KEY}`, rebuildMenu)
panel/auroraMenu.js:86
this._lifecycle.connect(settings, `changed::${SHOW_DOWNLOADS_KEY}`, rebuildMenu)
panel/auroraMenu.js:87
this._lifecycle.connect(settings, `changed::${SHOW_RECENT_KEY}`, rebuildMenu)
panel/auroraMenu.js:88
this._lifecycle.connect(settings, `changed::${SHOW_SETTINGS_KEY}`, rebuildMenu)
panel/auroraMenu.js:89
this._lifecycle.connect(settings, `changed::${SHOW_SOFTWARE_KEY}`, rebuildMenu)
panel/auroraMenu.js:90
this._lifecycle.connect(settings, `changed::${SHOW_EXTENSIONS_KEY}`, rebuildMenu)
panel/auroraMenu.js:91
this._lifecycle.connect(settings, `changed::${HIDE_ACTIVITIES_KEY}`, () =>
this._syncActivitiesButton(),
)
panel/clock/meetingClock/meetingClock.js:102
this._lifecycle.connect(settings, `changed::${SNOOZE_MINUTES_KEY}`, () =>
this._scheduleAlerts(),
)
panel/clock/meetingClock/meetingClock.js:105
this._lifecycle.connect(settings, `changed::${ALERT_EVENTS_WITHOUT_LINK_KEY}`, () =>
this._scheduleAlerts(),
)
panel/clock/meetingClock/meetingClock.js:108
this._lifecycle.connect(settings, `changed::${PANEL_REVEAL_INTERVAL_MINUTES_KEY}`, () =>
this._schedulePanelRevealTimer(),
)
panel/clock/meetingClock/meetingClock.js:111
this._lifecycle.connect(settings, `changed::${PANEL_LOOKAHEAD_MINUTES_KEY}`, () =>
this._render(),
)
panel/clock/meetingClock/meetingClock.js:114
this._lifecycle.connect(settings, `changed::${EXCLUDE_ALL_DAY_KEY}`, () => {
this._render();
this._scheduleAlerts();
})
panel/clock/meetingClock/meetingClock.js:96
this._lifecycle.connect(settings, `changed::${ALERTS_ENABLED_KEY}`, () =>
this._scheduleAlerts(),
)
panel/clock/meetingClock/meetingClock.js:99
this._lifecycle.connect(settings, `changed::${ALERT_MINUTES_KEY}`, () =>
this._scheduleAlerts(),
)
panel/clock/weatherClock/weatherClock.js:181
this._lifecycle?.connect(obj, signalName, callback)
panel/clock/weatherClock/weatherClock.js:50
this._lifecycle.connect(this._gweatherSettings, `changed::${TEMPERATURE_UNIT_KEY}`, () =>
this._onWeatherChanged(),
)
panel/clock/weatherClock/weatherClock.js:56
this._lifecycle.connect(this.context.settings, `changed::${AFTER_CLOCK_KEY}`, () =>
this._registerClockWidget(),
)
privacy/privacy.js:24
this._lifecycle.connect(settings, `changed::${DND_KEY}`, () => this._applyDnd())
privacy/privacy.js:25
this._lifecycle.connect(settings, `changed::${PANEL_KEY}`, () => this._applyPanel())
theme/autoThemeSwitcher.js:28
this._lifecycle.connect(settings, `changed::${LIGHT_HOURS_KEY}`, () => this._tick())
theme/autoThemeSwitcher.js:29
this._lifecycle.connect(settings, `changed::${LIGHT_MINUTES_KEY}`, () => this._tick())
theme/autoThemeSwitcher.js:30
this._lifecycle.connect(settings, `changed::${DARK_HOURS_KEY}`, () => this._tick())
theme/autoThemeSwitcher.js:31
this._lifecycle.connect(settings, `changed::${DARK_MINUTES_KEY}`, () => this._tick())
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.
clipboard/clipboardHistory.js:53
this._startupIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
this._startupIdleId = 0;
this._monitor?.start();
return GLib.SOURCE_REMOVE;
})
shared/ui/dash.js:900
this._autohideTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, AUTOHIDE_TIMEOUT, () => {
if (this._isDestroyed) {
this._autohideTimeoutId = 0;
return GLib.SOURCE_REMOVE;
}
if (this._dashContainerHasHover()) {
this._autohideTimeoutId = 0;
shared/ui/dash.js:861
this._springLoadTimerId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
SPRING_LOAD_DELAY,
() => {
this._springLoadTimerId = 0;
if (this._isDestroyed) return GLib.SOURCE_REMOVE;
const windo
shared/ui/dash.js:1007
this._workAreaUpdateId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this._workAreaUpdateId = 0;
if (this._workArea) {
this.applyWorkArea(this._workArea);
}
return GLib.SOURCE_REMOVE;
})
theme/autoThemeSwitcher.js:83
this._sourceId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, delay, () => {
this._sourceId = null;
this._tick();
return GLib.SOURCE_REMOVE;
})
| Version | Status |
|---|---|
| 50.10 (27) | Unreviewed |
| 50.9 (26) | Active |
| 50.8 (25) | Active |
| 50.6 (24) | Active |
| 50.5 (23) | Rejected |
| 50.4 (22) | Rejected |
| 50.2 (21) | Rejected |
| 50.3 (20) | Rejected |
| 50.2 (19) | Rejected |
| 18 | Rejected |
| 17 | Active |
| 16 | Active |
| 15 | Rejected |
| 14 | Rejected |
| 13 | Rejected |
| 12 | Rejected |
| 11 | Rejected |
| 10 | Active |
| 9 | Rejected |
| 8 | Active |
| 7 | Rejected |
| 6 | Active |
| 5 | Active |
| 4 | Rejected |
| 3 | Rejected |
| 2 | Rejected |
| 1 | Rejected |
Very very very sorry about the very large diff :'(. I need to change the architecture to make possible a mobile approach Most of shexli is false-positive. Like the PopupMenuItem that does not have destroy function, just remove