Skip to content
Back to skills

Extension Overview Search Stealing

ASecurity

Spotlight permanently takes over the GNOME Overview search infrastructure on enable. This is not a temporary reparenting on open and close. The widgets stay stolen for the entire lifetime of the extension.

  • 14 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 19, 2026
toolsgoshellreactapi

Works with

  • api

Security analysis

A100/100

Scanned September 19, 2026

npx -y skills add itsnin/spotlight --skill extension-overview-search-stealing --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Extension Overview Search Stealing?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Extension Overview Search Stealing
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/itsnin-extension-overview-search-stealing/badge)](https://www.skillsdirectory.com/skills/itsnin-extension-overview-search-stealing)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# Overview Search Stealing

Spotlight permanently takes over the GNOME Overview search infrastructure on enable. This is not a temporary reparenting on open and close. The widgets stay stolen for the entire lifetime of the extension.

## The Pattern

The `OverviewSearchStealer` class in `lib/overview/searchStealer.js` encapsulates all stealing and restoration logic. Thumbnail modifications live separately in `ThumbnailEnhancer` at `lib/overview/thumbnails.js`.

On enable, `steal()` does the following once:

1. Takes `Main.overview.searchEntry` and its parent reference
2. Takes `Main.overview._overview._controls._searchController` and its parent reference
3. Hides the entry with `visible = false` and a style class
4. Backs up and overrides `Main.overview.toggle` so toggling the overview while Spotlight is open focuses the search instead
5. Backs up and overrides `_searchResults.activateDefault` and `activate` to close the popup before running the original activation
6. Backs up and overrides `_search._searchCancelled` to be a no-op, preventing the controller from cancelling itself when its entry gets hidden
7. Connects a stage-level captured-event handler to intercept printable keys when the overview is visible, preventing the overview's type-to-search feature from activating
8. Increases workspace thumbnail scale to 200% by modifying `_thumbnailsBox._maxThumbnailScale` and overriding `SecondaryMonitorDisplay.prototype._getThumbnailsHeight`

On popup open, the already-stolen widgets are simply reparented into the popup container.

On popup close, they are removed from the popup but kept stolen and hidden. They are NOT returned to the overview.

Only on disable, returnOverviewSearch restores everything to its original state.

## Why This Works

The search controller continues running in the background regardless of where its widgets live. All GNOME search providers keep feeding it results. When Spotlight reparents the widgets into its popup, those already-active results render inside the popup instead of the overview. There is zero custom search provider code.

## Key Rules

- Never return widgets on popup close, only on extension disable
- Always back up original methods before overriding them
- The entry must be hidden when stolen, otherwise it would show in the overview in a broken state
- The search controller must not be allowed to cancel itself, which it would normally do when its entry gets hidden
- The overview toggle override ensures pressing Super while Spotlight is open does not dismiss Spotlight

## Black Screen Defense

KNOWN ISSUE: When Spotlight opens in the overview/app grid and the user types, the ControlsManager reacts to the search controller notify::search-active by calling _onSearchChanged(). This method eases _appDisplay and _workspacesDisplay to opacity 0, calls _updateThumbnailsBox(true) which hides thumbnails, and eases _searchController to opacity 255. Since the search controller widgets were permanently stolen, fading it in renders as empty black space behind the Spotlight popup. The overview wallpaper and workspace thumbnails disappear.

CRITICAL FINDING: _searchController.show() is essential. The controller gets hidden via this._search.hide() in stealOverviewSearch(). When the popup opens, the controller is reparented but never explicitly shown. Normally ControlsManager._onSearchChanged() calls _searchController.show() which makes the controller and its children visible. Blocking _onSearchChanged() without calling show() leaves results invisible.

FAILED APPROACHES:
1. Override _onSearchChanged() to return early when popup visible — skipped _searchController.show() which broke result rendering entirely.
2. Override ease() on individual actors — too broad, blocked normal workspace thumbnail animations; also _updateThumbnailsBox() uses its own ease on _thumbnailsBox which was not covered.
3. Run original _onSearchChanged() then immediately counteract with zero-duration ease animations — the zero-duration animations did not properly override/replace the ongoing 250ms fade transitions; black screen remained.

APPROACHES UNDER TEST:
B. Override _onSearchChanged(), call only _searchController.show() when popup visible and searchActive true. Run cleanup calls when searchActive false. Skip all ease animations and _updateThumbnailsBox.
A. Run original _onSearchChanged() fully, then call remove_transition('opacity') on each affected actor followed by direct property assignment. Also handle scale-x, scale-y, translation-y on _thumbnailsBox. Clutter.Actor.remove_transition(name) API verified via official Mutter docs.

Root cause verified in actual GNOME Shell source code: js/ui/overviewControls.js.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.