/// <summary> /// Begins running a standard application message loop on the current thread.<para/> /// This function should only be called on the main application thread and only if /// <see cref="Initialize"/> is called with a <see cref="CefSettings.MultiThreadedMessageLoop"/> /// value of false. This function will block until a quit message is received by the system. /// </summary> /// <remarks> /// Use this function instead of an application-provided message loop to get the best /// balance between performance and CPU usage. /// </remarks> public static void Run() { CefApi.RunMessageLoop(); }
private unsafe IntPtr WndProcHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { const int WM_ENTERMENULOOP = 0x0211; const int WM_EXITMENULOOP = 0x0212; switch (msg) { case 0x020E: // WM_MOUSEHWHEEL handled = WmMouseHWheel((long)lParam, (long)wParam); break; case 0x0002: // WM_DESTROY _source.RemoveHook(_delegate); foreach (var tuple in GetViews(hwnd)) { tuple.Item1.Close(); } lock (_HookedWindows) { _HookedWindows.Remove(_source.Handle); _source.Dispose(); } break; case 0x0047: // WM_WINDOWPOSCHANGED WINDOWPOS *windowPos = (WINDOWPOS *)lParam; if ((windowPos->flags & 0x0002) != 0) // SWP_NOMOVE { break; } foreach (var tuple in GetViews(hwnd)) { tuple.Item1.OnUpdateRootBounds(); } break; case 0x0231: // WM_ENTERSIZEMOVE foreach (var tuple in GetViews(hwnd)) { tuple.Item1.OnRootResizeBegin(EventArgs.Empty); } break; case 0x0232: // WM_EXITSIZEMOVE foreach (var tuple in GetViews(hwnd)) { tuple.Item1.OnRootResizeEnd(EventArgs.Empty); } break; case 0x0112: // WM_SYSCOMMAND const int SC_KEYMENU = 0xF100; // Menu loop must not be runned with Alt key handled = ((int)(wParam.ToInt64() & 0xFFF0) == SC_KEYMENU && lParam == IntPtr.Zero); break; case WM_ENTERMENULOOP: if (wParam == IntPtr.Zero) { CefApi.SetOSModalLoop(true); } break; case WM_EXITMENULOOP: if (wParam == IntPtr.Zero) { CefApi.SetOSModalLoop(false); } break; } return(IntPtr.Zero); }
protected virtual void OnCreateBrowser() { if (this.Opener != null) { return; } if (GetState(State.Creating) || GetState(State.Created)) { throw new InvalidOperationException(); } SetState(State.Creating, true); Dictionary <InitialPropertyKeys, object> propertyBag = InitialPropertyBag; InitialPropertyBag = null; var avaloniaWindow = this.GetVisualRoot() as Window; if (avaloniaWindow is null) { throw new InvalidOperationException("Window not found!"); } using (var windowInfo = new CefWindowInfo()) { IPlatformHandle platformHandle = avaloniaWindow.PlatformImpl.Handle; if (platformHandle is IMacOSTopLevelPlatformHandle macOSHandle) { windowInfo.SetAsWindowless(macOSHandle.GetNSWindowRetained()); } else { windowInfo.SetAsWindowless(platformHandle.Handle); } string initialUrl = null; CefDictionaryValue extraInfo = null; CefRequestContext requestContext = null; CefBrowserSettings browserSettings = null; if (propertyBag != null) { object value; if (propertyBag.TryGetValue(InitialPropertyKeys.Url, out value)) { initialUrl = value as string; } if (propertyBag.TryGetValue(InitialPropertyKeys.BrowserSettings, out value)) { browserSettings = value as CefBrowserSettings; } if (propertyBag.TryGetValue(InitialPropertyKeys.RequestContext, out value)) { requestContext = value as CefRequestContext; } if (propertyBag.TryGetValue(InitialPropertyKeys.ExtraInfo, out value)) { extraInfo = value as CefDictionaryValue; } } if (initialUrl == null) { initialUrl = "about:blank"; } if (browserSettings == null) { browserSettings = DefaultBrowserSettings; } if (!CefApi.CreateBrowser(windowInfo, ViewGlue.Client, initialUrl, browserSettings, extraInfo, requestContext)) { throw new InvalidOperationException("Failed to create browser instance."); } } }
static void Main(string[] args) { Application.SetHighDpiMode(HighDpiMode.SystemAware); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); string cefPath = Path.Combine(Path.GetDirectoryName(GetProjectPath()), "cef"); bool externalMessagePump = args.Contains("--external-message-pump"); AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; Application.ThreadException += Application_ThreadException; var settings = new CefSettings(); settings.MultiThreadedMessageLoop = !externalMessagePump; settings.ExternalMessagePump = externalMessagePump; settings.NoSandbox = true; settings.WindowlessRenderingEnabled = true; settings.LocalesDirPath = Path.Combine(cefPath, "Resources", "locales"); settings.ResourcesDirPath = Path.Combine(cefPath, "Resources"); settings.LogSeverity = CefLogSeverity.Warning; settings.IgnoreCertificateErrors = true; settings.UncaughtExceptionStackSize = 8; var app = new CefAppImpl(); app.ScheduleMessagePumpWorkCallback = OnScheduleMessagePumpWork; app.CefProcessMessageReceived += ScriptableObjectTests.HandleScriptableObjectTestMessage; try { UIContext = new WindowsFormsSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(UIContext); app.Initialize(Path.Combine(cefPath, "Release"), settings); if (externalMessagePump) { messagePump = new System.Threading.Timer(_ => UIContext.Post(_ => CefApi.DoMessageLoopWork(), null), null, messagePumpDelay, messagePumpDelay); } Application.Run(new MainForm()); using (var ev = new ManualResetEvent(false)) { app.SignalForShutdown(() => ev.Set()); ev.WaitOne(); } } finally { messagePump?.Dispose(); app.Shutdown(); app.Dispose(); } }
private static async void OnScheduleMessagePumpWork(long delayMs) { await Task.Delay((int)delayMs); UIContext.Post(_ => CefApi.DoMessageLoopWork(), null); }
protected virtual void OnCreateBrowser() { if (this.Opener != null) { return; } if (GetState(State.Creating) || GetState(State.Created)) { throw new InvalidOperationException(); } SetState(State.Creating, true); Dictionary <InitialPropertyKeys, object> propertyBag = InitialPropertyBag; InitialPropertyBag = null; var wpfwindow = System.Windows.Window.GetWindow(this); if (wpfwindow == null) { throw new InvalidOperationException("Window not found!"); } using (var windowInfo = new CefWindowInfo()) { windowInfo.SetAsWindowless(new WindowInteropHelper(wpfwindow).Handle); string initialUrl = null; CefDictionaryValue extraInfo = null; CefRequestContext requestContext = null; CefBrowserSettings browserSettings = null; if (propertyBag != null) { object value; if (propertyBag.TryGetValue(InitialPropertyKeys.Url, out value)) { initialUrl = value as string; } if (propertyBag.TryGetValue(InitialPropertyKeys.BrowserSettings, out value)) { browserSettings = value as CefBrowserSettings; } if (propertyBag.TryGetValue(InitialPropertyKeys.RequestContext, out value)) { requestContext = value as CefRequestContext; } if (propertyBag.TryGetValue(InitialPropertyKeys.ExtraInfo, out value)) { extraInfo = value as CefDictionaryValue; } } if (initialUrl == null) { initialUrl = "about:blank"; } if (browserSettings == null) { browserSettings = DefaultBrowserSettings; } if (!CefApi.CreateBrowser(windowInfo, ViewGlue.Client, initialUrl, browserSettings, extraInfo, requestContext)) { throw new InvalidOperationException("Failed to create browser instance."); } } }
/// <summary> /// Quit the CEF message loop that was started by calling <see cref="Run"/>.<para/> /// This function should only be called on the main application thread and only /// if <see cref="Run"/> was used. /// </summary> public static void Exit() { CefApi.QuitMessageLoop(); }
/// <summary> /// Initializes CEF from specified path with user-provided settings. This /// function should be called on the main application thread to initialize /// CEF processes. /// </summary> /// <param name="path"></param> /// <param name="settings"></param> /// <exception cref="DllNotFoundException"></exception> /// <exception cref="DirectoryNotFoundException"></exception> /// <exception cref="CefVersionMismatchException"></exception> /// <exception cref="InvalidOperationException"></exception> public void Initialize(string path, CefSettings settings) { if (PlatformInfo.IsWindows) { if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA) { throw new InvalidOperationException("The calling thread must be STA"); } } if (IsInitialized) { throw new InvalidOperationException("CEF already initialized. You must call Initialize once per application process."); } path = InitializeDllPath(path); if (PlatformInfo.IsWindows) { const int LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008; _cefLibHandle = NativeMethods.LoadLibraryEx(path, IntPtr.Zero, LOAD_WITH_ALTERED_SEARCH_PATH); if (IntPtr.Zero == _cefLibHandle) { throw new DllNotFoundException(string.Format("Can't load '{0}' (error: {1}).", path, Marshal.GetLastWin32Error())); } } else if (PlatformInfo.IsLinux || PlatformInfo.IsMacOS) { const int RTLD_NOW = 2; _cefLibHandle = NativeMethods.dlopen(path, RTLD_NOW); if (IntPtr.Zero == _cefLibHandle) { throw new DllNotFoundException(string.Format("Can't load '{0}'.", path)); } } else { throw new PlatformNotSupportedException(); } if (!TryInitializeDllImportResolver(_cefLibHandle) && PlatformInfo.IsMacOS) { throw new NotSupportedException("Requires .NET Core 3.0 or later."); } AssertApiVersion(); OnBeforeInitalize(EventArgs.Empty); Interlocked.Exchange(ref _initThreadId, Thread.CurrentThread.ManagedThreadId); Instance = this; // Main args CefMainArgs main_args = CefMainArgs.CreateDefault(); int retval = CefApi.ExecuteProcess(main_args, this, IntPtr.Zero); if (retval != -1) { Environment.Exit(retval); } UsesExternalMessageLoop = settings.ExternalMessagePump; if (!CefApi.Initialize(main_args, settings, this, IntPtr.Zero)) { throw new CefRuntimeException("Failed to initialize the CEF browser process."); } GC.KeepAlive(settings); }
public unsafe static void Main(string[] args) { //string cefPath = Path.Combine(Path.GetDirectoryName(GetProjectPath()), "cef", "Release"); string cefPath = "/home/vlad/work/cefnetdev/CefNetTest/bin/Debug/netcoreapp3.0"; var path = Environment.GetEnvironmentVariable("PATH"); Environment.SetEnvironmentVariable("PATH", cefPath + ";" + path); string libname = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "libcef.dll" : "libcef.so"; IntPtr pLibCef = NativeMethods.LoadLibrary(Path.Combine(cefPath, libname)); // This executable is called many times, because it // is also used for subprocesses. Let's print args // so we can differentiate between main process and // subprocesses. If one of the first args is for // example "--type=renderer" then it means that // this is a Renderer process. There may be more // subprocesses like GPU (--type=gpu-process) and // others. On Linux there are also special Zygote // processes. Console.Write("\nProcess args: "); if (args.Length == 0) { Console.Write("none (Main process)"); } else { Console.WriteLine(); for (int i = 0; i < args.Length; i++) { if (args[i].Length > 128) { Console.WriteLine(args[i].Remove(128) + "..."); } else { Console.WriteLine(args[i]); } } } Console.Write("\n\n"); // CEF version if (args.Length == 0) { var version = new int[8]; for (int i = 0; i < version.Length; i++) { version[i] = CefApi.CefVersionInfo((CefVersionEntry)i); } Console.Write("CEF version: {0}\n", string.Join(".", version)); } // Main args CefMainArgs main_args = CefMainArgs.CreateDefault(); // Main args //cef_main_args_t main_args = default; //main_args..instance = GetModuleHandle(null); // Cef app var cef_app = CefApp2.NewCefApp(); // Execute subprocesses. It is also possible to have // a separate executable for subprocesses by setting // cef_settings_t.browser_subprocess_path. In such // case cef_execute_process should not be called here. Console.Write("cef_execute_process, argc={0}\n", args.Length); int code = CefNativeApi.cef_execute_process((cef_main_args_t *)&main_args, cef_app, (void *)0); if (code >= 0) { Environment.Exit(code); } // Application settings. It is mandatory to set the // "size" member. var settings = new CefSettings(); //settings.MultiThreadedMessageLoop = true; settings.LocalesDirPath = Path.Combine(CefPath, "Resources", "locales"); settings.ResourcesDirPath = Path.Combine(CefPath, "Resources"); settings.LogSeverity = CefLogSeverity.Warning; // Show only warnings/errors settings.NoSandbox = true; // Initialize CEF Console.Write("cef_initialize\n"); CefNativeApi.cef_initialize((cef_main_args_t *)&main_args, settings.GetNativeInstance(), cef_app, (void *)0); GC.KeepAlive(settings); // Window info //cef_window_info_windows_t window_info = default; //window_info.style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE; //window_info.parent_window = IntPtr.Zero; //window_info.x = CW_USEDEFAULT; //window_info.y = CW_USEDEFAULT; //window_info.width = CW_USEDEFAULT; //window_info.height = CW_USEDEFAULT; cef_window_info_linux_t window_info = default; // Window info - window title byte[] window_name = Encoding.ASCII.GetBytes("cefcapi example"); cef_string_t cef_window_name = default; fixed(byte *aWindowName = window_name) { CefNativeApi.cef_string_utf8_to_utf16(aWindowName, (UIntPtr)window_name.Length, (cef_string_utf16_t *)&cef_window_name); } window_info.window_name = cef_window_name; // Initial url byte[] url = Encoding.ASCII.GetBytes("https://www.google.com/ncr"); cef_string_t cef_url = default; fixed(byte *aUrl = url) { CefNativeApi.cef_string_utf8_to_utf16(aUrl, (UIntPtr)url.Length, (cef_string_utf16_t *)&cef_url); } // Browser settings. It is mandatory to set the // "size" member. var browser_settings = new CefBrowserSettings(); // Client handlers var client = new CefClientClass(); // Create browser asynchronously. There is also a // synchronous version of this function available. Console.WriteLine("cef_browser_host_create_browser\n"); CefNativeApi.cef_browser_host_create_browser((cef_window_info_t *)&window_info, client.GetNativeInstance(), &cef_url, browser_settings.GetNativeInstance(), default, default);
/// <summary> /// Shuts down a CEF application. /// </summary> public void Shutdown() { AssertAccess(); CefApi.Shutdown(); }