#include #include #include #include #include #include #include #include #include #include #include #include #include "WebClient.h" #include "WebBrowserHost.h" namespace Atomic { #ifdef ATOMIC_PLATFORM_OSX void* GetNSWindowContentView(void* window); #endif class WebBrowserHostPrivate : public CefLifeSpanHandler { friend class WebBrowserHost; public: WebBrowserHostPrivate(WebBrowserHost* host) { host_ = host; } virtual ~WebBrowserHostPrivate() { host_ = 0; } // CefLifeSpanHandler methods: virtual void OnAfterCreated(CefRefPtr browser) OVERRIDE { CEF_REQUIRE_UI_THREAD(); browsers_.Push(browser); } virtual bool DoClose(CefRefPtr browser) OVERRIDE { return false; } virtual void OnBeforeClose(CefRefPtr browser) OVERRIDE { CEF_REQUIRE_UI_THREAD(); // Remove from the list of existing browsers. Vector>::Iterator itr = browsers_.Begin(); while (itr != browsers_.End()) { if ((*itr)->IsSame(browser)) { browsers_.Erase(itr); break; } itr++; } } void CloseAllBrowsers(bool force_close) { if (!CefCurrentlyOn(TID_UI)) { // Execute on the UI thread. CefPostTask(TID_UI, base::Bind(&WebBrowserHostPrivate::CloseAllBrowsers, this, force_close)); return; } if (!browsers_.Size()) return; // make a copy of vector, as we'll be erasing as we go Vector> browsers = browsers_; Vector>::Iterator itr = browsers.Begin(); while (itr != browsers.End()) { (*itr)->GetHost()->CloseBrowser(force_close); itr++; } browsers_.Clear(); } IMPLEMENT_REFCOUNTING(WebBrowserHostPrivate); private: Vector> browsers_; WeakPtr host_; }; WebBrowserHost::WebBrowserHost(Context* context) : Object (context) { const Vector& arguments = GetArguments(); const char** _argv { 0 }; PODVector argv; for (unsigned i = 0; i < arguments.Size(); i++) argv.Push(arguments[i].CString()); CefMainArgs args(arguments.Size(), arguments.Size() ? (char**) &argv[0] : (char **) _argv); int result = CefExecuteProcess(args, nullptr, nullptr); if (result >= 0) { LOGERROR("CEFExecuteProcess - Error"); } CefSettings settings; settings.windowless_rendering_enabled = true; // If losing OSX system menu, it means we're calling this // before initializing graphics subsystem if (!CefInitialize(args, settings, nullptr, nullptr)) { LOGERROR("CefInitialize - Error"); } d_ = new WebBrowserHostPrivate(this); d_->AddRef(); SubscribeToEvent(E_BEGINFRAME, HANDLER(WebBrowserHost, HandleBeginFrame)); } WebBrowserHost::~WebBrowserHost() { d_->CloseAllBrowsers(true); d_->Release(); CefShutdown(); } CefLifeSpanHandler* WebBrowserHost::GetCefLifeSpanHandler() { return d_; } bool WebBrowserHost::CreateBrowser(WebClient* webClient) { CefWindowInfo windowInfo; CefBrowserSettings browserSettings; Graphics* graphics = GetSubsystem(); SDL_Window* sdlWindow = static_cast(graphics->GetSDLWindow()); SDL_SysWMinfo info; SDL_VERSION(&info.version); if(SDL_GetWindowWMInfo(sdlWindow, &info)) { NSView* view = (NSView*) GetNSWindowContentView(info.info.cocoa.window); windowInfo.SetAsWindowless(view, false); return CefBrowserHost::CreateBrowser(windowInfo, (CefClient*) webClient->d_, "https://html5test.com/", browserSettings, nullptr); } return false; } void WebBrowserHost::HandleBeginFrame(StringHash eventType, VariantMap& eventData) { CefDoMessageLoopWork(); } }