feat(darwin): Add NSPanel support for Spotlight-like windows#5024
feat(darwin): Add NSPanel support for Spotlight-like windows#5024Grantmartin2002 wants to merge 10 commits intowailsapp:v3-alphafrom
Conversation
This adds support for creating NSPanel-based windows instead of NSWindow, enabling Spotlight-like auxiliary windows that can appear over fullscreen apps without yanking the user out of fullscreen. Key changes: - Add UsePanel and PanelOptions to MacWindow configuration - Implement WebviewPanel class (NSPanel subclass) with same functionality as WebviewWindow - Add panelNew() function to create panels with NonactivatingPanel style - Override sendEvent: on both WebviewWindow and WebviewPanel to ensure KeyBindings work regardless of WKWebView first responder state - Add collection behavior and window level configuration options The NSPanel with NSWindowStyleMaskNonactivatingPanel allows the panel to receive keyboard input without activating the owning application, which is the key feature for Spotlight/Alfred-like interfaces. Fixes wailsapp#5023 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
WalkthroughAdds NSPanel support on macOS: introduces a WebviewPanel (NSPanel subclass) and C API Changes
Sequence Diagram(s)sequenceDiagram
participant App as Go App
participant Router as Window Creation Router
participant PanelC as panelNew (C)
participant Panel as WebviewPanel
participant Delegate as Window Delegate
participant WebKit as WKWebView
App->>Router: Request window with WindowClass=NSPanel
Router->>PanelC: Call panelNew with options
PanelC->>Panel: Instantiate WebviewPanel with styleMask & panel flags
PanelC->>WebKit: Create WKWebView with WebviewPreferences
Panel->>Panel: Embed WKWebView in content view
PanelC->>Delegate: Set delegate and register drag types
PanelC->>App: Return panel instance
Note over Panel: Keyboard Event Flow
App->>Panel: User keydown
Panel->>Panel: sendEvent -> intercept keydown
Panel->>Panel: keyDown -> keyStringFromEvent
Panel->>Delegate: processWindowKeyDownEvent(modifier+key)
Delegate->>App: Route to handler
sequenceDiagram
participant Comparison as Creation Paths
rect rgba(100,150,200,0.5)
Note over Comparison: windowNew (NSWindow)
participant WindowC as windowNew (C)
participant Window as WebviewWindow
WindowC->>Window: Create standard NSWindow, set WKWebView, delegate
end
rect rgba(150,100,200,0.5)
Note over Comparison: panelNew (NSPanel) — NEW
participant PanelC as panelNew (C)
participant Panel as WebviewPanel
PanelC->>Panel: Create NSPanel with panel-specific flags, set WKWebView, delegate
end
Note over Comparison: Both converge on delegate, WKWebView setup, and keyboard interception
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
d8ef125 to
ffe6e91
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
v3/pkg/application/webview_window_darwin.m (1)
279-411: Extract shared key mapping/serialization for window + panel.
WebviewPanelandWebviewWindownow duplicate the full key parsing map. Consider a shared helper to avoid future divergence.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@v3/pkg/application/webview_window_darwin.m` around lines 279 - 411, Both WebviewPanel and WebviewWindow duplicate the full key parsing/map logic; extract the mapping and serialization into a shared helper to prevent divergence. Create a shared utility (e.g., KeyMapper or WebviewKeyHelper) that exports a method like keyStringFromEvent:(NSEvent*)event and a serializer that builds the "modifier+key" string (used by keyDown:); replace the local implementations in WebviewWindow (keyStringFromEvent and keyDown:) and the analogous methods in WebviewPanel to call the shared helper, keeping existing method names (keyDown:, keyStringFromEvent:) as thin wrappers so callers/delegates (e.g., WebviewWindowDelegate, processWindowKeyDownEvent) continue to work unchanged.v3/pkg/application/webview_window_darwin.go (1)
183-289:panelNew()andwindowNew()are now heavily duplicated.This is likely to drift over time (preferences, delegates, drag-drop, and webview setup). Consider extracting a shared builder/helper for common setup and keep only style-mask/class-specific bits separate.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@v3/pkg/application/webview_window_darwin.go` around lines 183 - 289, panelNew() and windowNew() contain nearly identical webview/delegate/preferences setup (WebviewWindowDelegate, WKWebViewConfiguration config, WKUserContentController, WKWebView webView, drag/drop wiring), so extract the common logic into a shared helper (eg. configureWebviewContent or buildWebviewForContainer) that accepts the container view/panel/window, id, WebviewPreferences, fraudulentWebsiteWarningEnabled, enableDragAndDrop and returns or assigns the configured WKWebView and delegate; leave only the style mask and panel-specific bits (frameless, floatingPanel, WebviewPanel creation) in panelNew(), and call the new helper to set preferences, set URL scheme handler, userContentController setup, assign navigation/UIDelegate, and attach drag view when requested.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@v3/pkg/application/webview_window_darwin.go`:
- Around line 202-203: The panel's floating state set in panelNew() via [panel
setFloatingPanel:YES] is being overridden later by an unconditional [window
setLevel:MacWindowLevelNormal] call; update the logic that sets default window
level (the code paths around setWindowLevel / setLevel and MacWindowLevelNormal)
to skip applying a default level when WindowClass == NSPanel and
PanelOptions.FloatingPanel is true (or alternatively detect when
setFloatingPanel was explicitly set and avoid calling setLevel), ensuring
panelNew's setFloatingPanel remains effective; look for functions/methods named
panelNew, setFloatingPanel, setWindowLevel/setLevel, and references to
PanelOptions.FloatingPanel, WindowClass/NSPanel and MacWindowLevelNormal to
apply the conditional.
In `@v3/pkg/application/webview_window_darwin.m`:
- Around line 33-41: sendEvent: is causing duplicate key handling by
unconditionally invoking [self keyDown:event] before [super sendEvent:event];
update the sendEvent: implementations in WebviewWindow and WebviewPanel to only
call [self keyDown:event] when the window's firstResponder is not the WKWebView
(or a subview of it) — i.e., obtain the firstResponder from the window and skip
the manual keyDown dispatch if it isKindOfClass: WKWebView (or resides within
the WKWebView), otherwise call [self keyDown:event] and then [super
sendEvent:event] as before.
In `@website/src/pages/changelog.mdx`:
- Line 18: Fix the spelling typo in the changelog entry: replace the misspelled
word "auxillary" with "auxiliary" in the sentence describing NSPanel support
(the line mentioning "Panels serve as auxillary windows..."); ensure the rest of
the text (references to `NSWindowStyleMaskNonactivatingPanel`,
`Mac.WindowClass`, and `Mac.PanelOptions`) remains unchanged.
---
Nitpick comments:
In `@v3/pkg/application/webview_window_darwin.go`:
- Around line 183-289: panelNew() and windowNew() contain nearly identical
webview/delegate/preferences setup (WebviewWindowDelegate,
WKWebViewConfiguration config, WKUserContentController, WKWebView webView,
drag/drop wiring), so extract the common logic into a shared helper (eg.
configureWebviewContent or buildWebviewForContainer) that accepts the container
view/panel/window, id, WebviewPreferences, fraudulentWebsiteWarningEnabled,
enableDragAndDrop and returns or assigns the configured WKWebView and delegate;
leave only the style mask and panel-specific bits (frameless, floatingPanel,
WebviewPanel creation) in panelNew(), and call the new helper to set
preferences, set URL scheme handler, userContentController setup, assign
navigation/UIDelegate, and attach drag view when requested.
In `@v3/pkg/application/webview_window_darwin.m`:
- Around line 279-411: Both WebviewPanel and WebviewWindow duplicate the full
key parsing/map logic; extract the mapping and serialization into a shared
helper to prevent divergence. Create a shared utility (e.g., KeyMapper or
WebviewKeyHelper) that exports a method like keyStringFromEvent:(NSEvent*)event
and a serializer that builds the "modifier+key" string (used by keyDown:);
replace the local implementations in WebviewWindow (keyStringFromEvent and
keyDown:) and the analogous methods in WebviewPanel to call the shared helper,
keeping existing method names (keyDown:, keyStringFromEvent:) as thin wrappers
so callers/delegates (e.g., WebviewWindowDelegate, processWindowKeyDownEvent)
continue to work unchanged.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
v3/pkg/application/webview_window_darwin.gov3/pkg/application/webview_window_darwin.hv3/pkg/application/webview_window_darwin.mv3/pkg/application/webview_window_options.gowebsite/src/pages/changelog.mdx
| [panel setFloatingPanel:floatingPanel]; | ||
| [panel setBecomesKeyOnlyIfNeeded:becomesKeyOnlyIfNeeded]; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's examine the exact code at the lines mentioned in the review
cd /tmp/repo 2>/dev/null || cd .
# Check the file exists and view the key sections
if [ -f "v3/pkg/application/webview_window_darwin.go" ]; then
echo "=== Lines 195-210 (around panelNew setup) ==="
sed -n '195,210p' "v3/pkg/application/webview_window_darwin.go"
echo -e "\n=== Lines 1370-1405 (NSPanel branching logic) ==="
sed -n '1370,1405p' "v3/pkg/application/webview_window_darwin.go"
echo -e "\n=== Lines 1420-1440 (default WindowLevel logic) ==="
sed -n '1420,1440p' "v3/pkg/application/webview_window_darwin.go"
else
echo "File not found, listing directory structure..."
find . -name "webview_window_darwin.go" -type f
fiRepository: wailsapp/wails
Length of output: 2532
🌐 Web query:
AppKit NSPanel setFloatingPanel behavior when combined with setLevel NSNormalWindowLevel
💡 Result:
-[NSPanel setFloatingPanel:] is effectively a window-level toggle: a panel is considered “floating” when its level is NSFloatingWindowLevel rather than NSNormalWindowLevel (and -isFloatingPanel reflects that) [1]. So if you do:
panel.setFloatingPanel(true)→ AppKit treats it as floating by setting/keeping its level atNSFloatingWindowLevel[1][2]- then
panel.setLevel(NSNormalWindowLevel)→ you’ve overridden the floating behavior; the panel will no longer be “floating” in the sense that it won’t sit above normal-level windows (andisFloatingPanelwould no longer match “floating” semantics) [1]
In other words, combining them is not additive—level “wins” for z-order, and “floating panel” is primarily shorthand for using the floating window level rather than an independent mode [1][2]. If you later call setFloatingPanel(true) again, expect it to push the panel back to the floating level again [1][2].
Sources: [1] NSPanel docs describing floating as “window level is NSFloatingWindowLevel instead of NSNormalWindowLevel” (GNUstep) [2] NSPanel overview noting panels “can be made to float above all other windows” (O’Reilly Cocoa in a Nutshell)
FloatingPanel is unintentionally overridden by the default window level fallback.
When WindowClass == NSPanel and only PanelOptions.FloatingPanel = true is set, the floating behavior is lost because panelNew() applies setFloatingPanel:true (line 202), but the subsequent default logic at line 1428 calls setWindowLevel(MacWindowLevelNormal), which overrides the floating level. In AppKit, an explicit setLevel() call supersedes setFloatingPanel(), causing the panel to no longer float above other windows.
Users who omit WindowLevel when using FloatingPanel = true will get a non-floating panel, which violates the expected behavior.
Suggested fix
if macOptions.WindowLevel == "" {
- macOptions.WindowLevel = MacWindowLevelNormal
+ if macOptions.WindowClass == NSPanel && macOptions.PanelOptions.FloatingPanel {
+ macOptions.WindowLevel = MacWindowLevelFloating
+ } else {
+ macOptions.WindowLevel = MacWindowLevelNormal
+ }
}Also applies to: 1375-1399
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@v3/pkg/application/webview_window_darwin.go` around lines 202 - 203, The
panel's floating state set in panelNew() via [panel setFloatingPanel:YES] is
being overridden later by an unconditional [window
setLevel:MacWindowLevelNormal] call; update the logic that sets default window
level (the code paths around setWindowLevel / setLevel and MacWindowLevelNormal)
to skip applying a default level when WindowClass == NSPanel and
PanelOptions.FloatingPanel is true (or alternatively detect when
setFloatingPanel was explicitly set and avoid calling setLevel), ensuring
panelNew's setFloatingPanel remains effective; look for functions/methods named
panelNew, setFloatingPanel, setWindowLevel/setLevel, and references to
PanelOptions.FloatingPanel, WindowClass/NSPanel and MacWindowLevelNormal to
apply the conditional.
| - (void)sendEvent:(NSEvent *)event { | ||
| if (event.type == NSEventTypeKeyDown) { | ||
| // Process through keybinding system first | ||
| [self keyDown:event]; | ||
| // Still pass to WKWebView for normal input handling | ||
| // (keybinding callbacks like Hide will take effect regardless) | ||
| } | ||
| [super sendEvent:event]; | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -name "webview_window_darwin.m" -type fRepository: wailsapp/wails
Length of output: 102
🏁 Script executed:
cat -n ./v3/pkg/application/webview_window_darwin.m | head -100Repository: wailsapp/wails
Length of output: 4612
🏁 Script executed:
cat -n ./v3/pkg/application/webview_window_darwin.m | sed -n '260,290p'Repository: wailsapp/wails
Length of output: 1505
🌐 Web query:
NSWindow sendEvent keyDown double dispatch macOS Cocoa responder chain
💡 Result:
In AppKit, a physical key press can traverse two stages before your view/controller sees it, which is why people often observe “double dispatch”:
-
NSApplicationpre-processing (key equivalents / commands)
Before the event is delivered as a normal key event,NSAppfirst tries to treat it as a key equivalent (menu shortcuts, control-key handling, etc.) viaperformKeyEquivalent:and related routing. If it’s not recognized, it may then fall through and be delivered as a normalNSKeyDownto the window/first responder. Apple explicitly documents this behavior (notably since 10.5) and that some events can be tried as key equivalents first and then still sent asNSKeyDown. [1] -
Normal key event dispatch (window → first responder → responder chain)
For “most key events,” the key window receivessendEvent:, and the window dispatches the event to the first responder askeyDown:; if unhandled it continues up the responder chain. [0] [2]
The most common “double delivery” pitfalls
-
Overriding
NSWindow.sendEvent:and manually callingkeyDown:(or forwarding) and then also callingsuper.sendEvent:
super.sendEvent:will also dispatch the key event to the first responder, so your manual dispatch +superyields two deliveries. (Fix: only dispatch yourself or callsuper, not both; if you fully handle it, return without callingsuper.) -
Seeing both
performKeyEquivalent:andkeyDown:for the same physical key press
This is expected for certain key combinations: AppKit may attempt key-equivalent handling first, then (if not handled) deliver it asNSKeyDownthrough the responder chain. [1] -
Event monitors stacking up (local monitors added multiple times)
If you add a local monitor repeatedly and don’t remove it, you can observe repeated handling for one press (each monitor runs). Removing the monitor stops the duplication. [6]
Practical guidance
- If your goal is “global within the window” handling, prefer overriding
keyDown:in the actual first responder (often the view), and let the responder chain work. [0] [2] - If your goal is intercepting menu shortcuts / key equivalents, implement/inspect
performKeyEquivalent:(usually on views), and returnYESonly when you truly handled it; returningNOallows further routing. [1] - Avoid overriding
NSWindow.performKeyEquivalent:(Apple discourages it). [1]
🏁 Script executed:
grep -n "canBecomeKeyWindow\|acceptsFirstResponder" ./v3/pkg/application/webview_window_darwin.mRepository: wailsapp/wails
Length of output: 197
🏁 Script executed:
cat -n ./v3/pkg/application/webview_window_darwin.m | sed -n '190,200p;412,422p'Repository: wailsapp/wails
Length of output: 646
🌐 Web query:
WKWebView first responder macOS NSWindow sendEvent keyDown dispatch
💡 Result:
On macOS, keyboard events do not go to the view under the mouse; they go to the first responder of the key window:
NSApplication.sendEvent(_:)first checks for key equivalents (e.g. many ⌘ shortcuts) viaperformKeyEquivalent:routing; if not handled that way, it dispatches the event to the key window, and the window delivers it to its first responder viakeyDown:. [1]- If your
WKWebView(or something inside it) is not actually the window’s first responder, it won’t receivekeyDown:—this is the classic “mouseDown works but keyDown doesn’t” issue. [2]
Practical implications for WKWebView
-
Make sure the web view (or the correct subview) is first responder
- Ensure the window is key, then call:
window.makeFirstResponder(webView)(or the specific subview that should type)
- A view must accept first responder; many views won’t unless
acceptsFirstResponderreturnstrue. [2]
- Ensure the window is key, then call:
-
If you’re overriding
NSWindow.sendEvent(_:)- If you intercept
.keyDownand don’t callsuper.sendEvent(event), you can break the normal dispatch path to the first responder. The “default” path is: app → window → first responder. [1]
- If you intercept
-
Why some ⌘ shortcuts may not arrive as
keyDown:- They can be handled earlier as key equivalents (
performKeyEquivalent:) before the window sendskeyDown:to the responder chain. [1]
- They can be handled earlier as key equivalents (
-
If you need to observe/intercept keyDown before it reaches
WKWebView- Use a local event monitor (
NSEvent.addLocalMonitorForEvents) to see events as your app dispatches them; unlike a global monitor, it’s within your app’s event stream. [3]
- Use a local event monitor (
Sources: Apple Cocoa Event Handling Guide on key-event routing and key equivalents [1], responder/first-responder behavior explanation [2], Apple docs on event monitors [3].
Double keybinding dispatch risk: sendEvent: calls both window and responder keyDown: for same event.
Manually calling [self keyDown:event] before [super sendEvent:event] causes the key event to be processed twice: once by the window's override, then again by the first responder (likely WKWebView) when super dispatches it. This violates Cocoa's event dispatch pattern and can cause unintended duplicate handling.
This applies to both the WebviewWindow (lines 33–41) and WebviewPanel (lines 270–278) classes.
Suggested fix
- (void)sendEvent:(NSEvent *)event {
if (event.type == NSEventTypeKeyDown) {
- [self keyDown:event];
+ id responder = self.firstResponder;
+ BOOL responderInsideWebView = NO;
+ if ([responder isKindOfClass:[NSView class]] && self.webView != nil) {
+ responderInsideWebView = [((NSView *)responder) isDescendantOf:self.webView];
+ }
+ if (!responderInsideWebView) {
+ [self keyDown:event];
+ }
}
[super sendEvent:event];
}This guard ensures the window's keybinding processing runs only when the first responder is outside the WebView, avoiding double dispatch.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - (void)sendEvent:(NSEvent *)event { | |
| if (event.type == NSEventTypeKeyDown) { | |
| // Process through keybinding system first | |
| [self keyDown:event]; | |
| // Still pass to WKWebView for normal input handling | |
| // (keybinding callbacks like Hide will take effect regardless) | |
| } | |
| [super sendEvent:event]; | |
| } | |
| - (void)sendEvent:(NSEvent *)event { | |
| if (event.type == NSEventTypeKeyDown) { | |
| id responder = self.firstResponder; | |
| BOOL responderInsideWebView = NO; | |
| if ([responder isKindOfClass:[NSView class]] && self.webView != nil) { | |
| responderInsideWebView = [((NSView *)responder) isDescendantOf:self.webView]; | |
| } | |
| if (!responderInsideWebView) { | |
| [self keyDown:event]; | |
| } | |
| } | |
| [super sendEvent:event]; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@v3/pkg/application/webview_window_darwin.m` around lines 33 - 41, sendEvent:
is causing duplicate key handling by unconditionally invoking [self
keyDown:event] before [super sendEvent:event]; update the sendEvent:
implementations in WebviewWindow and WebviewPanel to only call [self
keyDown:event] when the window's firstResponder is not the WKWebView (or a
subview of it) — i.e., obtain the firstResponder from the window and skip the
manual keyDown dispatch if it isKindOfClass: WKWebView (or resides within the
WKWebView), otherwise call [self keyDown:event] and then [super sendEvent:event]
as before.
| ## [Unreleased] | ||
|
|
||
| ### Added | ||
| - Added NSPanel support for macOS. Panels serve as auxillary windows and can appear over fullscreen apps without activating the application using `NSWindowStyleMaskNonactivatingPanel`. Configure via `Mac.WindowClass` and `Mac.PanelOptions` in window options. Added by [@Grantmartin2002](https://github.com/Grantmartin2002) in [PR](https://github.com/wailsapp/wails/pull/5024) |
There was a problem hiding this comment.
Fix spelling typo in changelog entry.
Line 18: use “auxiliary” instead of “auxillary”.
✍️ Suggested edit
-- Added NSPanel support for macOS. Panels serve as auxillary windows and can appear over fullscreen apps without activating the application using `NSWindowStyleMaskNonactivatingPanel`. Configure via `Mac.WindowClass` and `Mac.PanelOptions` in window options. Added by [`@Grantmartin2002`](https://github.com/Grantmartin2002) in [PR](https://github.com/wailsapp/wails/pull/5024)
+- Added NSPanel support for macOS. Panels serve as auxiliary windows and can appear over fullscreen apps without activating the application using `NSWindowStyleMaskNonactivatingPanel`. Configure via `Mac.WindowClass` and `Mac.PanelOptions` in window options. Added by [`@Grantmartin2002`](https://github.com/Grantmartin2002) in [PR](https://github.com/wailsapp/wails/pull/5024)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - Added NSPanel support for macOS. Panels serve as auxillary windows and can appear over fullscreen apps without activating the application using `NSWindowStyleMaskNonactivatingPanel`. Configure via `Mac.WindowClass` and `Mac.PanelOptions` in window options. Added by [@Grantmartin2002](https://github.com/Grantmartin2002) in [PR](https://github.com/wailsapp/wails/pull/5024) | |
| - Added NSPanel support for macOS. Panels serve as auxiliary windows and can appear over fullscreen apps without activating the application using `NSWindowStyleMaskNonactivatingPanel`. Configure via `Mac.WindowClass` and `Mac.PanelOptions` in window options. Added by [`@Grantmartin2002`](https://github.com/Grantmartin2002) in [PR](https://github.com/wailsapp/wails/pull/5024) |
🧰 Tools
🪛 LanguageTool
[grammar] ~18-~18: Ensure spelling is correct
Context: ...anel support for macOS. Panels serve as auxillary windows and can appear over fullscreen ...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@website/src/pages/changelog.mdx` at line 18, Fix the spelling typo in the
changelog entry: replace the misspelled word "auxillary" with "auxiliary" in the
sentence describing NSPanel support (the line mentioning "Panels serve as
auxillary windows..."); ensure the rest of the text (references to
`NSWindowStyleMaskNonactivatingPanel`, `Mac.WindowClass`, and
`Mac.PanelOptions`) remains unchanged.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/src/content/docs/features/windows/options.mdx (1)
831-864:⚠️ Potential issue | 🔴 CriticalUnescaped
{}in prose will break MDX parsing (lines 831, 864).In Astro Starlight
.mdxfiles, a left curly brace{starts a JavaScript expression. Wrap these code references in backticks to render them literally.Proposed fix
-**Note:** NSWindow fullscreen overlay requires application.Options{ Mac: application.MacOptions{ ActivationPolicy: application.ActivationPolicyAccessory } } +**Note:** NSWindow fullscreen overlay requires `application.Options{ Mac: application.MacOptions{ ActivationPolicy: application.ActivationPolicyAccessory } }` -**Note:** Unlike NSWindow, NSPanel fullscreen overlay does NOT require application.Options{ Mac: application.MacOptions{ ActivationPolicy: application.ActivationPolicyAccessory } } +**Note:** Unlike NSWindow, NSPanel fullscreen overlay does **not** require `application.Options{ Mac: application.MacOptions{ ActivationPolicy: application.ActivationPolicyAccessory } }`🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/src/content/docs/features/windows/options.mdx` around lines 831 - 864, The MDX contains unescaped curly-brace expressions that break parsing; wrap the literal references containing braces in inline code ticks (e.g., `application.Options{ Mac: application.MacOptions{ ActivationPolicy: application.ActivationPolicyAccessory } }`) and similarly backtick the examples and type names that include braces or look like struct literals (references such as `Mac: application.MacWindow{ ... }`, `application.MacWindowCollectionBehaviorCanJoinAllSpaces | application.MacWindowCollectionBehaviorFullScreenAuxiliary`, `application.MacWindowLevelFloating`, `MacWindowClass`, `NSWindow`, `NSPanel`, `MacPanelOptions`, and the panel option names) so the `{}` are rendered literally and MDX parsing is preserved.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@docs/src/content/docs/features/windows/options.mdx`:
- Around line 831-864: The MDX contains unescaped curly-brace expressions that
break parsing; wrap the literal references containing braces in inline code
ticks (e.g., `application.Options{ Mac: application.MacOptions{
ActivationPolicy: application.ActivationPolicyAccessory } }`) and similarly
backtick the examples and type names that include braces or look like struct
literals (references such as `Mac: application.MacWindow{ ... }`,
`application.MacWindowCollectionBehaviorCanJoinAllSpaces |
application.MacWindowCollectionBehaviorFullScreenAuxiliary`,
`application.MacWindowLevelFloating`, `MacWindowClass`, `NSWindow`, `NSPanel`,
`MacPanelOptions`, and the panel option names) so the `{}` are rendered
literally and MDX parsing is preserved.
This adds support for creating NSPanel-based windows instead of NSWindow, enabling auxiliary windows that can appear over fullscreen apps without activating the application.
Key changes
WindowClass MacWindowClasstoMacWindowconfiguration withNSWindow(default) andNSPaneloptionsMacPanelOptionsstruct with panel-specific options:FloatingPanel- float above other windowsBecomesKeyOnlyIfNeeded- become key only when neededNonactivatingPanel- receive input without activating the appUtilityWindow- utility window styleWebviewPanelclass (NSPanel subclass) with same functionality asWebviewWindowpanelNew()function to create panels with configurable style maskssendEvent:on bothWebviewWindowandWebviewPanelto ensure key bindings work regardless of WKWebView first responder state. My keybindings no longer worked when I used a panel until I did this. Side effect free??? maybe add an option for this?The
NSWindowStyleMaskNonactivatingPanelstyle allows the panel to receive keyboard input without activating the owning application.Feedback wanted:
Fixes #5023
Type of change
Please select the option that is relevant.
How Has This Been Tested?
Checklist:
website/src/pages/changelog.mdxwith details of this PRSummary by CodeRabbit
New Features
Documentation