Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ packages/
CefGlue.Interop.Gen/Classes.Handlers.tmpl/
CefGlue.Interop.Gen/Classes.Proxies.tmpl/
**/.DS_Store
*.nupkg
2 changes: 1 addition & 1 deletion CefGlue.Avalonia/CefGlue.Avalonia.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>$(TargetDotnetVersions)</TargetFrameworks>
<TargetFramework>$(DotnetVersion)</TargetFramework>
<RootNamespace>Xilium.CefGlue.Avalonia</RootNamespace>
<AssemblyName>Xilium.CefGlue.Avalonia</AssemblyName>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
Expand Down
29 changes: 24 additions & 5 deletions CefGlue.Avalonia/Platform/AvaloniaControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Avalonia.Input;
using Avalonia.Platform;
using Avalonia.Threading;
using Xilium.CefGlue.Avalonia.Platform.Linux;
using Xilium.CefGlue.Avalonia.Platform.MacOS;
using Xilium.CefGlue.Avalonia.Platform.Windows;
using Xilium.CefGlue.Common.Helpers;
Expand Down Expand Up @@ -54,7 +55,18 @@ protected IPlatformHandle GetHostWindowPlatformHandle()
Dispatcher.UIThread.VerifyAccess();
if (_hostWindowPlatformHandle == null)
{
_hostWindowPlatformHandle = new Window().TryGetPlatformHandle();
switch (CefRuntime.Platform)
{
case CefRuntimePlatform.Windows:
_hostWindowPlatformHandle = new Window().TryGetPlatformHandle();
break;
case CefRuntimePlatform.Linux:
// Avalonia window doesn't work. It's color depth is 32.
// We should create a x11 window with color depth 24.
// Cef creates browser window with CopyFromParent colormap, so the color depth must be same.
_hostWindowPlatformHandle = XWindow.CreateHostWindow();
break;
}
}
return _hostWindowPlatformHandle;
}
Expand Down Expand Up @@ -83,7 +95,7 @@ public void OpenContextMenu(IEnumerable<MenuEntry> menuEntries, int x, int y, Ce
var menu = new ContextMenu();

menu.Items.Clear();

foreach (var menuEntry in menuEntries)
{
if (menuEntry.IsSeparator)
Expand Down Expand Up @@ -141,10 +153,17 @@ public virtual bool SetCursor(IntPtr cursorHandle, CefCursorType cursorType)

public void InitializeRender(IntPtr browserHandle)
{
if (CefRuntime.Platform == CefRuntimePlatform.Windows)
switch (CefRuntime.Platform)
{
// store cef window handle, to dispose later
_browserView = new HostWindow(browserHandle);
case CefRuntimePlatform.Windows:
// store cef window handle, to dispose later
_browserView = new HostWindow(browserHandle);
break;
case CefRuntimePlatform.Linux:
// This window is created by cef. It should be closed when browser close.
// We shouldn't close it directly, or disposing browser will not work as expected.
_browserView = new XWindow(browserHandle);
break;
}

Dispatcher.UIThread.Post(() =>
Expand Down
66 changes: 66 additions & 0 deletions CefGlue.Avalonia/Platform/Linux/XWindow.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using System.Runtime.InteropServices;
using Avalonia.Controls;
using Avalonia.Platform;

namespace Xilium.CefGlue.Avalonia.Platform.Linux
{
internal class XWindow : IHandleHolder, IPlatformHandle
{
[DllImport("libX11.so.6")]
private static extern int XDestroyWindow(IntPtr display, IntPtr w);

[DllImport("libX11.so.6")]
private static extern IntPtr XOpenDisplay([MarshalAs(UnmanagedType.LPUTF8Str)] string display_name);

[DllImport("libX11.so.6")]
private static extern IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, uint width, uint height, uint border_width, UIntPtr border, UIntPtr background);

[DllImport("libX11.so.6")]
private static extern IntPtr XDefaultRootWindow(IntPtr display);

[DllImport("libX11.so.6")]

private static extern int XFlush(IntPtr display);
private static IntPtr _display;
private readonly bool _needDispose;

public XWindow(IntPtr handle) : this(handle, false) { }

private XWindow(IntPtr handle, bool needDispose)
{
Handle = handle;
_needDispose = needDispose;
}

public IntPtr Handle { get; }

public string HandleDescriptor => "XWindow";

public static IPlatformHandle CreateHostWindow()
{
EnsureDisplay();
var handle = XCreateSimpleWindow(_display, XDefaultRootWindow(_display), 0, 0, 100, 100, 0, (UIntPtr)0, (UIntPtr)0);
XFlush(_display);
return new XWindow(handle, true);
}

private static void EnsureDisplay()
{
if (_display == IntPtr.Zero)
{
_display = XOpenDisplay(null);
}
}

public void Dispose()
{
var display = _display;
if (_needDispose && display != IntPtr.Zero)
{
XDestroyWindow(display, Handle);
XFlush(display);
}
}
}
}
36 changes: 30 additions & 6 deletions CefGlue.BrowserProcess/CefGlue.BrowserProcess.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFrameworks>$(TargetDotnetVersions)</TargetFrameworks>
<TargetFramework>$(DotnetVersion)</TargetFramework>
<AssemblyName>Xilium.CefGlue.BrowserProcess</AssemblyName>
<RootNamespace>Xilium.CefGlue.BrowserProcess</RootNamespace>
<RuntimeIdentifiers>osx-x64;win-x64;osx-arm64;win-arm64</RuntimeIdentifiers>
<RuntimeIdentifiers>osx-x64;osx-arm64;win-x64;win-arm64;linux-x64;linux-arm64</RuntimeIdentifiers>
<RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<PublishCommonConfig>Configuration=$(Configuration);Platform=$(Platform);TargetFramework=$(TargetFramework);IsPublishing=True;PublishTrimmed=True;SelfContained=True;RuntimeIdentifier=</PublishCommonConfig>
<IsEditbinEnabled>True</IsEditbinEnabled>
</PropertyGroup>

<ItemGroup>
Expand All @@ -27,15 +28,38 @@
<ItemGroup>
<PackageReference Include="System.Runtime.Loader" />
</ItemGroup>

<Target Name="PublishApp" AfterTargets="AfterBuild" Condition="'$(_AssemblyTimestampBeforeCompile)' != '$(_AssemblyTimestampAfterCompile)' and '$(IsPublishing)' != 'True'">

<Target Name="Editbin" AfterTargets="Compile" Condition="$(IsEditbinEnabled) == True And $(VcvarsFile) != '' And $([MSBuild]::IsOSPlatform('Windows'))">
<!--
Quick explanation: This target runs after compile, and currently 3 more times for each MSBuild command executed in the next target "PublishApp".
We just want this target to be executed for windows specs and when passed the VcvarsFile location.
Using VS Studio: VcvarsFile="$(DevEnvDir)..\..\VC\Auxiliary\Build\vcvars64.bat"
Using VS Studio tools: VcvarsFile="C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvars64.bat"
-->

<PropertyGroup>
<ApphostLocation>$(ProjectDir)$(BaseIntermediateOutputPath)$(Platform)\$(Configuration)\$(TargetFramework)\</ApphostLocation>
<ApphostLocation Condition="'$(IsPublishing)' == 'True'">$(ApphostLocation)$(RuntimeIdentifier)\</ApphostLocation> <!-- When publishing, we also use the runtime identifiers (check the next target "PublishApp") -->
</PropertyGroup>

<!--
This command aims at increasing the stack size of Xilium.CefGlue.BrowserProcess.exe to 8 MiBs, using the visual studio tool "editbin".
Since we are reaching the .exe at the compile time, the file name is "apphost.exe" instead and located at /obj folder
-->
<Exec Command="call &quot;$(VcvarsFile)&quot;&#xD;&#xA; editbin /STACK:0x800000 &quot;$(ApphostLocation)\apphost.exe&quot;&#xD;&#xA;" />
</Target>

<Target Name="PublishApp" AfterTargets="AfterBuild" Condition="'$(_AssemblyTimestampBeforeCompile)' != '$(_AssemblyTimestampAfterCompile)' and '$(IsPublishing)' != 'True'">
<!-- WINDOWS -->
<Message Text="Publishing CefGlue.BrowserProcess on Windows ($(Platform))..." Importance="High" />
<MSBuild Projects="CefGlue.BrowserProcess.csproj" Targets="Publish" Properties="$(PublishCommonConfig)win-$(ArchitectureConfig)" />
<MSBuild Projects="CefGlue.BrowserProcess.csproj" Targets="Publish" Properties="$(PublishCommonConfig)win-$(ArchitectureConfig);IsEditbinEnabled=True;" />

<!-- LINUX -->
<Message Text="Publishing CefGlue.BrowserProcess on Linux ($(Platform))..." Importance="High" />
<MSBuild Projects="CefGlue.BrowserProcess.csproj" Targets="Publish" Properties="$(PublishCommonConfig)linux-$(ArchitectureConfig);IsEditbinEnabled=False;" />

<!-- OSX -->
<Message Text="Publishing CefGlue.BrowserProcess on MacOS ($(Platform))..." Importance="High" />
<MSBuild Projects="CefGlue.BrowserProcess.csproj" Targets="Publish" Properties="$(PublishCommonConfig)osx-$(ArchitectureConfig)" />
<MSBuild Projects="CefGlue.BrowserProcess.csproj" Targets="Publish" Properties="$(PublishCommonConfig)osx-$(ArchitectureConfig);IsEditbinEnabled=False;" />
</Target>
</Project>
4 changes: 4 additions & 0 deletions CefGlue.BrowserProcess/Helpers/NativeLibsLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ public static void Install()
case CefRuntimePlatform.Windows:
extension = "dll";
break;

case CefRuntimePlatform.Linux:
extension = "so";
break;
}

AssemblyLoadContext.Default.ResolvingUnmanagedDll += (_, libName) =>
Expand Down
2 changes: 1 addition & 1 deletion CefGlue.Common.Shared/CefGlue.Common.Shared.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>$(TargetDotnetVersions)</TargetFrameworks>
<TargetFramework>$(DotnetVersion)</TargetFramework>
<AssemblyName>Xilium.CefGlue.Common.Shared</AssemblyName>
<RootNamespace>Xilium.CefGlue.Common.Shared</RootNamespace>
</PropertyGroup>
Expand Down
4 changes: 4 additions & 0 deletions CefGlue.Common/BrowserCefApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ protected override void OnBeforeCommandLineProcessing(string processType, CefCom
{
if (string.IsNullOrEmpty(processType))
{
if (CefRuntime.Platform == CefRuntimePlatform.Linux)
{
commandLine.AppendSwitch("no-zygote");
}
if (CefRuntimeLoader.IsOSREnabled)
{
commandLine.AppendSwitch("disable-gpu", "1");
Expand Down
14 changes: 9 additions & 5 deletions CefGlue.Common/CefGlue.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Import Project="..\CefGlue.Packages.props" />

<PropertyGroup>
<TargetFrameworks>$(TargetDotnetVersions)</TargetFrameworks>
<TargetFramework>$(DotnetVersion)</TargetFramework>
<AssemblyName>Xilium.CefGlue.Common</AssemblyName>
<RootNamespace>Xilium.CefGlue.Common</RootNamespace>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
Expand Down Expand Up @@ -56,12 +56,16 @@
<ItemGroup>
<BuildOutputInPackage Include="@(ReferenceCopyLocalPaths-&gt;WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))" />

<TfmSpecificPackageFile Include="..\CefGlue.BrowserProcess\bin\$(Platform)\$(Configuration)\$(TargetFramework)\win-$(ArchitectureConfig)\publish\**\*">
<PackagePath>bin\$(TargetFramework)\win-$(ArchitectureConfig)</PackagePath>
<TfmSpecificPackageFile Include="..\CefGlue.BrowserProcess\bin\$(Platform)\$(Configuration)\$(DotnetVersion)\win-$(ArchitectureConfig)\publish\**\*">
<PackagePath>bin\win-$(ArchitectureConfig)</PackagePath>
</TfmSpecificPackageFile>

<TfmSpecificPackageFile Include="..\CefGlue.BrowserProcess\bin\$(Platform)\$(Configuration)\$(DotnetVersion)\linux-$(ArchitectureConfig)\publish\**\*">
<PackagePath>bin\linux-$(ArchitectureConfig)</PackagePath>
</TfmSpecificPackageFile>

<TfmSpecificPackageFile Include="..\CefGlue.BrowserProcess\bin\$(Platform)\$(Configuration)\$(TargetFramework)\osx-$(ArchitectureConfig)\publish\**\*">
<PackagePath>bin\$(TargetFramework)\osx-$(ArchitectureConfig)</PackagePath>
<TfmSpecificPackageFile Include="..\CefGlue.BrowserProcess\bin\$(Platform)\$(Configuration)\$(DotnetVersion)\osx-$(ArchitectureConfig)\publish\**\*">
<PackagePath>bin\osx-$(ArchitectureConfig)</PackagePath>
</TfmSpecificPackageFile>
</ItemGroup>
</Target>
Expand Down
36 changes: 32 additions & 4 deletions CefGlue.Common/CefRuntimeLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Linq;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using Xilium.CefGlue.Common.Handlers;
using Xilium.CefGlue.Common.Shared;
Expand All @@ -11,7 +12,7 @@ namespace Xilium.CefGlue.Common
public static class CefRuntimeLoader
{
private const string DefaultBrowserProcessDirectory = "CefGlueBrowserProcess";

private static Action<BrowserProcessHandler> _delayedInitialization;

public static void Initialize(CefSettings settings = null, KeyValuePair<string, string>[] flags = null, CustomScheme[] customSchemes = null)
Expand Down Expand Up @@ -58,12 +59,37 @@ private static void InternalInitialize(CefSettings settings = null, KeyValuePair
settings.FrameworkDirPath = basePath;
settings.ResourcesDirPath = resourcesPath;
break;

case CefRuntimePlatform.Linux:
settings.NoSandbox = true;
settings.MultiThreadedMessageLoop = true;
break;
}

AppDomain.CurrentDomain.ProcessExit += delegate { CefRuntime.Shutdown(); };

IsOSREnabled = settings.WindowlessRenderingEnabled;
CefRuntime.Initialize(new CefMainArgs(new string[0]), settings, new BrowserCefApp(customSchemes, flags, browserProcessHandler), IntPtr.Zero);

// On Linux, with osr disable, the filename in CefMainArgs will be used as accessible name.
// If the name is empty, chromium will crash at ui::AXNodeData:SetNamechecked.
var exeFileName = Process.GetCurrentProcess().MainModule.FileName;
if (string.IsNullOrEmpty(exeFileName))
{
exeFileName = "CefGlue";
}

// Fix crash with youtube https://github.com/chromiumembedded/cef/issues/3643
{
#if DEBUG
if (CefRuntime.ChromeVersion.Split(".").First() != "120")
{
throw new Exception("Remove this fix block after CEF upgrade");
}
#endif
flags = (flags ?? []).Append(KeyValuePair.Create("disable-features", "FirstPartySets")).ToArray();
}

CefRuntime.Initialize(new CefMainArgs(new[] { exeFileName }), settings, new BrowserCefApp(customSchemes, flags, browserProcessHandler), IntPtr.Zero);

if (customSchemes != null)
{
Expand Down Expand Up @@ -102,8 +128,10 @@ internal static void Load(BrowserProcessHandler browserProcessHandler = null)

internal static bool IsOSREnabled { get; private set; }

private static string BrowserProcessFileName {
get {
private static string BrowserProcessFileName
{
get
{
const string Filename = "Xilium.CefGlue.BrowserProcess";
switch (CefRuntime.Platform)
{
Expand Down
18 changes: 13 additions & 5 deletions CefGlue.Common/CommonBrowserAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ private void NavigateTo(string url)
// Remove leading whitespace from the URL
url = url.TrimStart();

/// to play safe, load url must be called after <see cref="OnBrowserCreated(CefBrowser)"/> which runs on CefThreadId.UI,
/// otherwise the navigation will be aborted
// to play safe, load url must be called after OnBrowserCreated(CefBrowser) which runs on CefThreadId.UI,
// otherwise the navigation will be aborted
ActionTask.Run(() =>
{
if (IsInitialized)
Expand Down Expand Up @@ -232,7 +232,7 @@ public void ExecuteJavaScript(string code, string url, int line)

public Task<T> EvaluateJavaScript<T>(string code, string url, int line, string frameName = null, TimeSpan? timeout = null)
{
var frame = frameName != null ? _browser?.GetFrame(frameName) : _browser?.GetMainFrame();
var frame = frameName != null ? _browser?.GetFrameByName(frameName) : _browser?.GetMainFrame();
if (frame != null)
{
return EvaluateJavaScript<T>(code, url, line, frame, timeout);
Expand All @@ -254,9 +254,11 @@ public Task<T> EvaluateJavaScript<T>(string code, string url, int line, CefFrame
public void ShowDeveloperTools()
{
var windowInfo = CefWindowInfo.Create();
if (CefRuntime.Platform != CefRuntimePlatform.MacOS)

if (CefRuntime.Platform == CefRuntimePlatform.Windows)
{
// don't know why but I can't do this on macosx
// This function set ParentHandle (owner in Windows) and set Bounds to CW_USERDEFAULT (only works on Windows).
// So, it should be called only in Windows.
windowInfo.SetAsPopup(BrowserHost?.GetWindowHandle() ?? IntPtr.Zero, "DevTools");
}

Expand Down Expand Up @@ -484,6 +486,12 @@ protected virtual bool OnBrowserClose(CefBrowser browser)
Control.DestroyRender();
Cleanup(browser);

if (CefRuntime.Platform == CefRuntimePlatform.Linux)
{
// On Linux, we should return false to let cef close the browser window.
// We shouldn't close the window directly, or disposing browser will not work as expected.
return false;
}
return true;
}

Expand Down
5 changes: 3 additions & 2 deletions CefGlue.Common/InternalHandlers/CommonCefRenderHandler.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using CefGlue.Structs;
using System;
using Xilium.CefGlue.Common.Helpers.Logger;

namespace Xilium.CefGlue.Common.InternalHandlers
Expand Down Expand Up @@ -56,7 +57,7 @@ protected override void OnPopupSize(CefBrowser browser, CefRectangle rect)
_owner.HandlePopupSizeChange(rect);
}

protected override void OnAcceleratedPaint(CefBrowser browser, CefPaintElementType type, CefRectangle[] dirtyRects, IntPtr sharedHandle)
protected override void OnAcceleratedPaint(CefBrowser browser, CefPaintElementType type, CefRectangle[] dirtyRects, CefAcceleratedPaintInfo paintInfo)
{
}

Expand Down
Loading