Add platform abstraction & cross-platform ports

Introduce a cross-platform platform layer and port scaffolding for macOS and Linux. CMakeLists.txt refactored to select platform sources, set executable type per OS, and use CEF helper macros for runtime deployment. Add platform/types.h, startup/paths/browser_host APIs and implementations for Windows, macOS, and Linux (many are stubs for mac/linux). Refactor app entry and lifetime to use nebula::platform::AppStartup (app/main, run.{h,cpp}), move window/browser host logic into platform/browser_host.*, and update NebulaController to use platform APIs (native handles, sizing, visibility, cache-busting token, etc.). Add README and detailed docs/cross-platform.md describing build layout and porting status.
This commit is contained in:
Andrew Zambazos
2026-05-18 17:25:04 +12:00
parent 18bc607d93
commit e51594a010
28 changed files with 1461 additions and 508 deletions
+8 -47
View File
@@ -4,41 +4,15 @@
#include "cef/nebula_app.h"
#include "include/cef_app.h"
#include "include/cef_command_line.h"
#include "platform/startup.h"
#include "ui/paths.h"
namespace nebula::app {
namespace {
constexpr wchar_t kMainInstanceMutexName[] = L"Local\\NebulaBrowserMainInstance";
int RunNebula(const nebula::platform::AppStartup& startup) {
nebula::platform::PrepareApp();
void EnableDpiAwareness() {
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
}
class ScopedHandle {
public:
explicit ScopedHandle(HANDLE handle) : handle_(handle) {}
~ScopedHandle() {
if (handle_) {
CloseHandle(handle_);
}
}
ScopedHandle(const ScopedHandle&) = delete;
ScopedHandle& operator=(const ScopedHandle&) = delete;
bool valid() const { return handle_ != nullptr; }
private:
HANDLE handle_ = nullptr;
};
} // namespace
int RunNebula(HINSTANCE instance, int show_command) {
EnableDpiAwareness();
CefMainArgs main_args(instance);
const CefMainArgs main_args = nebula::platform::MakeMainArgs(startup);
CefRefPtr<nebula::cef::NebulaApp> app(new nebula::cef::NebulaApp);
const int subprocess_exit_code = CefExecuteProcess(main_args, app, nullptr);
@@ -46,41 +20,28 @@ int RunNebula(HINSTANCE instance, int show_command) {
return subprocess_exit_code;
}
ScopedHandle main_instance_mutex(CreateMutexW(nullptr, TRUE, kMainInstanceMutexName));
if (main_instance_mutex.valid() && GetLastError() == ERROR_ALREADY_EXISTS) {
if (!nebula::platform::TryAcquireSingleInstance()) {
return 0;
}
CefSettings settings;
settings.no_sandbox = true;
settings.persist_session_cookies = true;
// A persistent profile is required for the GPU shader cache and several
// hardware acceleration features. Without these Chromium silently falls
// back to software rendering, which causes choppy video and disables
// WebGL/WebGL2 in the GPU diagnostics page.
const std::wstring user_data_dir = nebula::ui::GetUserDataDirectory().wstring();
const std::wstring cache_dir = nebula::ui::GetCacheDirectory().wstring();
if (!user_data_dir.empty()) {
CefString(&settings.root_cache_path).FromWString(user_data_dir);
}
if (!cache_dir.empty()) {
CefString(&settings.cache_path).FromWString(cache_dir);
}
nebula::platform::ConfigureCefSettings(settings);
if (!CefInitialize(main_args, settings, app, nullptr)) {
return CefGetExitCode();
}
CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
command_line->InitFromString(GetCommandLineW());
nebula::platform::InitCommandLine(command_line, startup);
std::string initial_url = command_line->GetSwitchValue("url");
if (!initial_url.empty() && nebula::ui::IsChromiumNewTabUrl(initial_url)) {
initial_url = nebula::ui::GetHomeUrl();
}
NebulaController controller(instance, initial_url, show_command);
NebulaController controller(startup, std::move(initial_url));
const bool created = controller.Create();
if (created) {
CefRunMessageLoop();