mac: subclass NSApplication for CEF and fix close handling

Add NebulaApplication (NSApplication<CefAppProtocol>) to implement isHandlingSendEvent/setHandlingSendEvent and override sendEvent to use CefScopedSendingEvent, preventing "unrecognized selector" crashes during CEF event/window teardown. Instantiate NebulaApplication in PrepareApp. Also relax the Windows-only guard in NebulaController::OnWindowCloseRequested and update the comment so per-tab closes on macOS don't trigger full app shutdown. Files changed: src/platform/mac/startup_mac.mm, src/app/nebula_controller.cpp.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-09-23 19:31:41 +12:00
co-authored by Copilot
parent 0009ee83b0
commit ab2bbc0f79
2 changed files with 37 additions and 4 deletions
+2 -3
View File
@@ -241,13 +241,12 @@ void NebulaController::OnWindowResized(const nebula::window::BrowserLayout& layo
} }
void NebulaController::OnWindowCloseRequested() { void NebulaController::OnWindowCloseRequested() {
#if defined(_WIN32)
if (!closing_ && !closing_tab_browsers_.empty()) { if (!closing_ && !closing_tab_browsers_.empty()) {
// CEF Alloy can bubble a child browser close as WM_CLOSE on the host // CEF Alloy can bubble a child browser close as WM_CLOSE on the host
// window. Per-tab closes should not turn into full app shutdown. // window (Windows) or performClose: on the host window (OS X). Per-tab
// closes should not turn into full app shutdown.
return; return;
} }
#endif
if (launch_options_.mode == AppMode::BigPicture && !closing_) { if (launch_options_.mode == AppMode::BigPicture && !closing_) {
if (!SwitchToSiblingMode(AppMode::Desktop)) { if (!SwitchToSiblingMode(AppMode::Desktop)) {
+35 -1
View File
@@ -8,9 +8,40 @@
#include <sys/file.h> #include <sys/file.h>
#include <unistd.h> #include <unistd.h>
#include "include/cef_application_mac.h"
#include "include/cef_command_line.h" #include "include/cef_command_line.h"
#include "ui/paths.h" #include "ui/paths.h"
// All CEF client applications must subclass NSApplication and implement the
// CefAppProtocol. CEF's message pump and window teardown code calls
// -[NSApplication isHandlingSendEvent:]/setHandlingSendEvent: (through
// CefScopedSendingEvent) while dispatching events. Against the plain
// NSApplication those selectors do not exist, so any code path that reaches
// them (for example closing a tab while a browser view is being torn down)
// raises "unrecognized selector sent to NSApplication" and crashes.
@interface NebulaApplication : NSApplication <CefAppProtocol> {
@private
BOOL handling_send_event_;
}
@end
@implementation NebulaApplication
- (BOOL)isHandlingSendEvent {
return handling_send_event_;
}
- (void)setHandlingSendEvent:(BOOL)handlingSendEvent {
handling_send_event_ = handlingSendEvent;
}
- (void)sendEvent:(NSEvent*)event {
CefScopedSendingEvent sending_event_scoper;
[super sendEvent:event];
}
@end
namespace nebula::platform { namespace nebula::platform {
namespace { namespace {
@@ -20,7 +51,10 @@ int g_single_instance_lock = -1;
void PrepareApp() { void PrepareApp() {
@autoreleasepool { @autoreleasepool {
[NSApplication sharedApplication]; // Create the shared application as NebulaApplication (CefAppProtocol)
// before anything else touches NSApp so the CEF pipeline always sees
// the protocol methods it requires.
[NebulaApplication sharedApplication];
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
[NSApp finishLaunching]; [NSApp finishLaunching];
} }