Force close browsers and handle bigpicture exit

Call CloseBrowser(true) for chrome, popup and tab browsers to force shutdown. Immediately destroy the top-level window and call MaybeFinishShutdown() to avoid hangs when WM_CLOSE is not resent by Alloy child-window paths. Route "close" and new "exit-bigpicture" chrome commands through OnWindowCloseRequested so they trigger the same shutdown flow. Add IsBigPictureFrame and permit the "exit-bigpicture" process message from bigpicture internal frames.
This commit is contained in:
Andrew Zambazos
2026-05-18 18:35:18 +12:00
parent c514e4faec
commit b4d93f24cd
2 changed files with 28 additions and 9 deletions
+14 -8
View File
@@ -162,10 +162,6 @@ void NebulaController::OnWindowCloseRequested() {
} }
if (closing_) { if (closing_) {
// CEF re-sends WM_CLOSE to the top-level window after each Alloy
// child browser finishes its JS unload + DoClose phase. Destroy the
// Nebula window now so CEF can tear down the child browser HWNDs and
// fire OnBeforeClose; MaybeFinishShutdown will then quit the loop.
if (window_ && window_->native_handle()) { if (window_ && window_->native_handle()) {
nebula::platform::DestroyTopLevelWindow(window_->native_handle()); nebula::platform::DestroyTopLevelWindow(window_->native_handle());
} }
@@ -180,16 +176,24 @@ void NebulaController::OnWindowCloseRequested() {
} }
if (chrome_browser_) { if (chrome_browser_) {
chrome_browser_->GetHost()->CloseBrowser(false); chrome_browser_->GetHost()->CloseBrowser(true);
} }
if (menu_popup_browser_) { if (menu_popup_browser_) {
menu_popup_browser_->GetHost()->CloseBrowser(false); menu_popup_browser_->GetHost()->CloseBrowser(true);
} }
for (const auto& tab : tabs_.Tabs()) { for (const auto& tab : tabs_.Tabs()) {
if (tab.browser) { if (tab.browser) {
tab.browser->GetHost()->CloseBrowser(false); tab.browser->GetHost()->CloseBrowser(true);
} }
} }
// Do not wait for CEF to re-send WM_CLOSE to the host window. On some
// Alloy child-window paths that message never arrives, leaving the app
// alive with all close affordances disabled until the process is killed.
if (window_ && window_->native_handle()) {
nebula::platform::DestroyTopLevelWindow(window_->native_handle());
}
MaybeFinishShutdown();
} }
void NebulaController::OnActiveTabChanged(const nebula::browser::NebulaTab& tab) { void NebulaController::OnActiveTabChanged(const nebula::browser::NebulaTab& tab) {
@@ -307,7 +311,9 @@ void NebulaController::OnChromeCommand(const std::string& command, const std::st
} else if (command == "maximize" && window_) { } else if (command == "maximize" && window_) {
window_->ToggleMaximize(); window_->ToggleMaximize();
} else if (command == "close" && window_) { } else if (command == "close" && window_) {
window_->Close(); OnWindowCloseRequested();
} else if (command == "exit-bigpicture" && window_) {
OnWindowCloseRequested();
} else if (command == "drag" && window_) { } else if (command == "drag" && window_) {
window_->BeginDrag(); window_->BeginDrag();
} }
+14 -1
View File
@@ -25,6 +25,16 @@ bool IsSettingsFrame(CefRefPtr<CefFrame> frame) {
return nebula::ui::ToInternalUrl(frame->GetURL().ToString()).starts_with("nebula://settings"); return nebula::ui::ToInternalUrl(frame->GetURL().ToString()).starts_with("nebula://settings");
} }
bool IsBigPictureFrame(CefRefPtr<CefFrame> frame) {
if (!frame) {
return false;
}
const std::string url = nebula::ui::ToInternalUrl(frame->GetURL().ToString());
return url.starts_with("nebula://bigpicture") ||
url.starts_with("nebula://big-picture");
}
std::vector<std::string> ToStringVector(const std::vector<CefString>& values) { std::vector<std::string> ToStringVector(const std::vector<CefString>& values) {
std::vector<std::string> result; std::vector<std::string> result;
result.reserve(values.size()); result.reserve(values.size());
@@ -67,7 +77,10 @@ bool NebulaBrowserClient::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser
command == "new-tab" || command == "new-tab" ||
command == "clear-site-history" || command == "clear-site-history" ||
command == "clear-search-history"); command == "clear-search-history");
if (!allowed_insecure_command && !allowed_settings_command) { const bool allowed_big_picture_command =
IsBigPictureFrame(frame) && command == "exit-bigpicture";
if (!allowed_insecure_command && !allowed_settings_command &&
!allowed_big_picture_command) {
return false; return false;
} }
} }