Skip to content

feat: use NSPanel for macOS spotlight window - #161

Open
vuon9 wants to merge 8 commits into
mainfrom
feat/macos-nspanel-spotlight
Open

feat: use NSPanel for macOS spotlight window#161
vuon9 wants to merge 8 commits into
mainfrom
feat/macos-nspanel-spotlight

Conversation

@vuon9

@vuon9 vuon9 commented Aug 21, 2026

Copy link
Copy Markdown
Owner

Summary

  • Upgrade Wails v3 from beta.6 to master (beta.11 pseudo-version) to get MacWindowClassPanel support (Add macOS NSPanel window support wailsapp/wails#6008, merged 2026-08-21)
  • Spotlight window now uses a dedicated NSPanel with NonActivating, FloatingPanel and BecomesKeyOnlyIfNeeded preferences: showing or focusing the launcher no longer activates DevToolbox or steals focus from the active app (Spotlight/Raycast behaviour)
  • Removed the 100ms async-hide workaround for macOS reverting focus to the previously active app; non-activating panels make it unnecessary

Test Plan

  • go build ./... passes (macOS)
  • go vet ./... passes
  • go test ./internal/... ./service/... all pass
  • App launches with Wails v3.0.0-beta.11; main window and /spotlight window load, no crash
  • Manual: open spotlight via Cmd+Shift+Space from another app, confirm the other app stays active and focus returns correctly (needs Accessibility permission for hotkey)

Notes

  • Hotkey registration requires granting Accessibility (Input Monitoring) permission on first run
  • Working tree had an unrelated in-progress change (tray icon embeds in main.go); per decision it was reverted for this PR. Backed up to /tmp/main.go.bak

N/A

  • UI changes: N/A (no frontend changes)
  • Docs: N/A
  • Migration: N/A

vuon9 added 8 commits August 21, 2026 15:15
- Upgrade wails v3 beta.6 -> master (beta.11 pseudo-version) for
  MacWindowClassPanel support (wailsapp/wails#6008)
- Spotlight window now uses an NSPanel with NonActivating, FloatingPanel and
  BecomesKeyOnlyIfNeeded, so showing/focusing it no longer activates the app
  or steals focus from the active application
- Drop the 100ms async-hide workaround for macOS reverting focus to the
  previously active app; non-activating panels make it unnecessary

Entire-Checkpoint: 960b22501128
- Spotlight window height now follows the visible result count: the
  frontend emits spotlight:resize with the computed height and the backend
  resizes the NSPanel (SetSize + Center). Removed the fixed 384px
  MinHeight/MaxHeight cap (MinHeight 100, JS caps at 600)
- Fix Escape not closing the palette: frontend emitted command-palette:close
  but the backend listens for spotlight:close (event name mismatch, pre-existing)
- Fix opened-event mismatch: frontend now listens for spotlight:opened which
  the service emits
- Results area no longer has a hardcoded 264px height; list scrolls within
  the window (max-height: calc(100vh - 49px))
Replace Center() after resize with a fixed position: horizontally centered,
top edge at 15% of screen height, so the panel grows downward like macOS
Spotlight instead of re-centering. Also position the panel once at startup
instead of relying on WindowCentered.
- Draggable via the Wails runtime --wails-draggable: drag CSS hook on the
  panel container (input, clear button and result items stay no-drag)
- Persist the panel position to settings on WindowDidMove (debounced 200ms)
- On open, restore the last position; fall back to the default top position
  only on first run
- Resize no longer repositions the panel, so the user's placement is kept
The whole panel used to be a drag region, which made it unclear where
dragging works. Now only the search icon is draggable (grab cursor) and
everything else stays interactive.
The lucide search icon is an <svg> containing <circle>/<line> children.
Those SVG children report clientWidth/clientHeight of 0, so the Wails
runtime draggable check (offsetX < clientWidth) failed whenever the click
landed on a child element, making drag work only sometimes. Route pointer
events to the svg root with pointer-events: none on children.
…NSPanel support

WebviewPanel (NSPanel) does not implement handleLeftMouseDown/leftMouseEvent,
so the Wails runtime's --wails-draggable path would fail (and could crash on
startDrag). Replace it with a JS-tracked drag: mousedown on the search icon
records screen coords, mousemove emits spotlight:drag with the delta, and
the backend moves the panel with SetPosition. Position is saved on drag end.
- Drop unused SpotlightService.IsVisible() and Close() (no callers)
- Drop unlistened spotlight:closed emit
- Drop spotlight:theme:toggle handler (nothing emits it)
- Drop app:quit handler (nothing emits it)
- Update spotlight tests to only assert no-panic behaviour
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant