#include "ChromiumBrowser.h" #include "ClientApp.h" #include "include/cef_app.h" #include "include/cef_version.h" #if defined(GUI_GTK) && defined(GDK_WINDOWING_X11) #include #endif using namespace Upp; #ifdef COMPILER_GCC const char * const __attribute__((weak)) Upp::ChromiumBrowser::JSFunctions[]={ /* DO NOT forget about nullptr at the end of the table */ nullptr }; #endif #ifdef PLATFORM_POSIX static Vector GetArgs() { const Vector& cmdline = CommandLine(); static String app; Vector argv; app = GetExeTitle(); argv.Clear(); argv.Add((char *)~app); for (unsigned i = 0; i < cmdline.GetCount(); i++){ argv.Add((char *)~cmdline[i]); } return argv; } #endif void ChromiumBrowser::ChildProcess() { CefRefPtr app(new ClientApp); #ifdef PLATFORM_POSIX Vector args = GetArgs(); CefMainArgs main_args(args.GetCount(), &args[0]); #elif defined(PLATFORM_WIN32) CefMainArgs main_args(Ctrl::hInstance); #else #error "Unsupported platform" #endif int exit_code = CefExecuteProcess(main_args, app.get(), nullptr); if (exit_code >= 0){ RLOG("CefExecuteProcess error"); exit(exit_code); } } bool ChromiumBrowser::IsChildProcess() { const Vector& cmdline = CommandLine(); return (cmdline.GetCount() > 0 && cmdline[0].StartsWith("--type=")); } ChromiumBrowser::ChromiumBrowser(): handler(nullptr), start_page("about:blank") { CefRefPtr app(new ClientApp); #ifdef PLATFORM_POSIX Vector args = GetArgs(); CefMainArgs main_args(args.GetCount(), &args[0]); #elif defined(PLATFORM_WIN32) CefMainArgs main_args(Ctrl::hInstance); #else #error "Unsupported platform" #endif int exit_code = CefExecuteProcess(main_args, app.get(), nullptr); if (exit_code >= 0){ RLOG("CefExecuteProcess error"); exit(exit_code); } CefSettings cef_settings; //cef_settings.multi_threaded_message_loop = true; #ifdef _DEBUG cef_settings.log_severity = LOGSEVERITY_VERBOSE; #else cef_settings.log_severity = LOGSEVERITY_DISABLE; #endif tmp_dir = GetTempFileName(); CefString(&cef_settings.cache_path) = ~tmp_dir; CefInitialize(main_args, cef_settings, app.get(), nullptr); } void ChromiumBrowser::MessageLoop() { CefDoMessageLoopWork(); SetTimeCallback(30, THISBACK(MessageLoop)); } void ChromiumBrowser::State(int reason) { switch(reason){ case FOCUS: case ACTIVATE: case DEACTIVATE: case SHOW: case ENABLE: break; case OPEN: AfterInit(); break; case CLOSE: BeforeTerminate(); break; case LAYOUTPOS: case POSITION: Layout(); break; } } void ChromiumBrowser::AfterInit() { WhenGotFocus << [this](){ SetFocus(); }; handler = new ClientHandler(WhenUrlChange, WhenStatus, WhenMessage, WhenTakeFocus, WhenGotFocus, WhenKeyboard, WhenConsoleMessage, WhenCertificateError); CefBrowserSettings br_settings; br_settings.file_access_from_file_urls = STATE_DISABLED; Rect r = GetRect(); CefWindowInfo info; #ifdef GUI_X11 info.SetAsChild(GetParentWindow(), CefRect(r.left, r.top, r.Width(), r.Height())); #elif defined(GUI_GTK) && defined(GDK_WINDOWING_X11) info.SetAsChild(gdk_x11_drawable_get_xid(gtk_widget_get_window(GTK_WIDGET(GetTopCtrl()->gtk()))), CefRect(r.left, r.top, r.Width(), r.Height())); #elif defined(GUI_WIN32) RECT rect; rect.left = r.left; rect.top = r.top; rect.right = r.Width(); rect.bottom = r.Height(); info.SetAsChild(GetTopCtrl()->GetHWND(), rect); #else #error "Unsupported platform" #endif CefBrowserHost::CreateBrowser(info, handler.get(), ~start_page, br_settings, nullptr); SetTimeCallback(50, THISBACK(MessageLoop)); } void ChromiumBrowser::BeforeTerminate() { if (handler && handler->GetBrowser()) { handler->GetBrowser()->StopLoad(); Sleep(20); handler->GetBrowser()->GetHost()->CloseBrowser(false); } CefShutdown(); DeleteFolderDeep(tmp_dir); } void ChromiumBrowser::Layout() { if (handler && handler->GetBrowser()){ Rect r = GetRect(); #ifdef GUI_X11 XWindowChanges change = {0}; change.x = r.left; change.y = r.top; change.width = r.Width(); change.height = r.Height(); XConfigureWindow(Xdisplay, handler->GetBrowser()->GetHost()->GetWindowHandle(), CWHeight | CWWidth | CWY, &change); #elif defined(GUI_GTK) && defined(GDK_WINDOWING_X11) XWindowChanges change = {0}; change.x = r.left; change.y = r.top; change.width = r.Width(); change.height = r.Height(); XConfigureWindow(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), handler->GetBrowser()->GetHost()->GetWindowHandle(), CWHeight | CWWidth | CWY, &change); #elif defined(GUI_WIN32) CefWindowHandle hwnd = handler->GetBrowser()->GetHost()->GetWindowHandle(); HDWP hdwp = BeginDeferWindowPos(1); hdwp = DeferWindowPos(hdwp, hwnd, nullptr, r.left, r.top, r.Width(), r.Height(), SWP_NOZORDER); EndDeferWindowPos(hdwp); #else #error "Unsupported platform" #endif } } ChromiumBrowser::~ChromiumBrowser() { BeforeTerminate(); } bool ChromiumBrowser::SetFocus() { if (handler && handler->GetBrowser()) handler->GetBrowser()->GetHost()->SendFocusEvent(true); return true; } void ChromiumBrowser::GotFocus() { if (handler && handler->GetBrowser()) handler->GetBrowser()->GetHost()->SendFocusEvent(true); } void ChromiumBrowser::LostFocus() { if (handler && handler->GetBrowser()) handler->GetBrowser()->GetHost()->SendFocusEvent(false); } void ChromiumBrowser::Browse(const String & url) { if (handler && handler->GetBrowser()){ handler->GetBrowser()->StopLoad(); handler->GetBrowser()->GetMainFrame()->LoadURL(~url); } } void ChromiumBrowser::ShowHTML(const String& html) { if (handler && handler->GetBrowser()) handler->GetBrowser()->GetMainFrame()->LoadString(~html, "about:blank"); } String ChromiumBrowser::GetLocation() { if (handler && handler->GetBrowser()) return String(handler->GetBrowser()->GetMainFrame()->GetURL()); return String::GetVoid(); } void ChromiumBrowser::GoBack() { if (handler && handler->GetBrowser()) handler->GetBrowser()->GoBack(); } void ChromiumBrowser::RefreshPage() { if (handler && handler->GetBrowser()) handler->GetBrowser()->Reload(); } void ChromiumBrowser::GoForward() { if (handler && handler->GetBrowser()) handler->GetBrowser()->GoForward(); } void ChromiumBrowser::Stop() { if (handler && handler->GetBrowser()) handler->GetBrowser()->StopLoad(); } String ChromiumBrowser::GetVersion() { return Format("CEF %d.%d Chromium %d.%d.%d.%d", cef_version_info(0), cef_version_info(1), cef_version_info(2), cef_version_info(3), cef_version_info(4), cef_version_info(5)); } void ChromiumBrowser::ExecuteJavaScript(const char * js) { if (handler && handler->GetBrowser()){ CefRefPtr frame = handler->GetBrowser()->GetMainFrame(); frame->ExecuteJavaScript(js, frame->GetURL(), 0); } }