Skip to content
Draft
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
96 changes: 74 additions & 22 deletions CefSharp.OutOfProcess.BrowserProcess/BrowserProcessHandler.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using CefSharp.Internals;
using CefSharp.Internals;
using PInvoke;
using StreamJsonRpc;
using System;
Expand All @@ -13,27 +13,28 @@ namespace CefSharp.OutOfProcess.BrowserProcess
public class BrowserProcessHandler : CefSharp.Handler.BrowserProcessHandler, IOutOfProcessClientRpc
{
private readonly int _parentProcessId;
private IList<OutOfProcessChromiumWebBrowser> _browsers = new List<OutOfProcessChromiumWebBrowser>();
private readonly bool _offscreenRendering;
private readonly IList<OutOfProcessChromiumWebBrowser> _browsers = new List<OutOfProcessChromiumWebBrowser>();
/// <summary>
/// JSON RPC used for IPC with host
/// </summary>
private JsonRpc _jsonRpc;
private IOutOfProcessHostRpc _outOfProcessServer;

public BrowserProcessHandler(int parentProcessId)
public BrowserProcessHandler(int parentProcessId, bool offscreenRendering)
{
_parentProcessId = parentProcessId;
_offscreenRendering = offscreenRendering;
}

protected override void OnContextInitialized()
{
base.OnContextInitialized();

_jsonRpc = JsonRpc.Attach(Console.OpenStandardOutput(), Console.OpenStandardInput());
_outOfProcessServer = _jsonRpc.Attach<IOutOfProcessHostRpc>();
_jsonRpc.AllowModificationWhileListening = true;
_outOfProcessServer = _jsonRpc.Attach<IOutOfProcessHostRpc>();
_jsonRpc.AddLocalRpcTarget<IOutOfProcessClientRpc>(this, null);
_jsonRpc.AllowModificationWhileListening = false;

var threadId = Kernel32.GetCurrentThreadId();

Expand Down Expand Up @@ -69,10 +70,25 @@ Task IOutOfProcessClientRpc.SendDevToolsMessage(int browserId, string message)
{
return CefThread.ExecuteOnUiThread(() =>
{
var browser = _browsers.FirstOrDefault(x => x.Id == browserId);
GetBrowser(browserId)?.GetBrowserHost().SendDevToolsMessage(message);
return true;
});
}

browser?.GetBrowserHost().SendDevToolsMessage(message);
Task IOutOfProcessClientRpc.ShowDevTools(int browserId)
{
return CefThread.ExecuteOnUiThread(() =>
{
GetBrowser(browserId).ShowDevTools();
return true;
});
}

Task IOutOfProcessClientRpc.LoadUrl(int browserId, string url)
{
return CefThread.ExecuteOnUiThread(() =>
{
GetBrowser(browserId).LoadUrl(url);
return true;
});
}
Expand All @@ -93,15 +109,30 @@ Task IOutOfProcessClientRpc.CreateBrowser(IntPtr parentHwnd, string url, int id)

return CefThread.ExecuteOnUiThread(() =>
{
var browser = new OutOfProcessChromiumWebBrowser(_outOfProcessServer, id, url);

var windowInfo = new WindowInfo();
windowInfo.WindowName = "CefSharpBrowserProcess";
windowInfo.SetAsChild(parentHwnd);

//Disable Window activation by default
//https://bitbucket.org/chromiumembedded/cef/issues/1856/branch-2526-cef-activates-browser-window
windowInfo.ExStyle |= OutOfProcessChromiumWebBrowser.WS_EX_NOACTIVATE;
OutOfProcessChromiumWebBrowser browser;

IWindowInfo windowInfo;

if (_offscreenRendering)
{
browser = new OffscreenOutOfProcessChromiumWebBrowser(_outOfProcessServer, id, url);
windowInfo = Core.ObjectFactory.CreateWindowInfo();
windowInfo.SetAsWindowless(parentHwnd);
windowInfo.Width = 0;
windowInfo.Height = 0;
}
else
{
browser = new OutOfProcessChromiumWebBrowser(_outOfProcessServer, id, url);
windowInfo = new WindowInfo();
windowInfo.WindowName = "CefSharpBrowserProcess";
windowInfo.SetAsChild(parentHwnd);

//Disable Window activation by default
//https://bitbucket.org/chromiumembedded/cef/issues/1856/branch-2526-cef-activates-browser-window
windowInfo.ExStyle |= OutOfProcessChromiumWebBrowser.WS_EX_NOACTIVATE;

}

browser.CreateBrowser(windowInfo);

Expand All @@ -111,18 +142,39 @@ Task IOutOfProcessClientRpc.CreateBrowser(IntPtr parentHwnd, string url, int id)
});
}

void IOutOfProcessClientRpc.NotifyMoveOrResizeStarted(int browserId)
void IOutOfProcessClientRpc.NotifyMoveOrResizeStarted(int browserId, Rect rect)
{
var browser = _browsers.FirstOrDefault(x => x.Id == browserId);
var browser = GetBrowser(browserId);
if(browser == null)
{
return;
}

browser?.GetBrowserHost().NotifyMoveOrResizeStarted();
var host = browser.GetBrowserHost();
host.NotifyMoveOrResizeStarted();

if (_offscreenRendering && browser is OffscreenOutOfProcessChromiumWebBrowser offscreenBrowser)
{
host.NotifyMoveOrResizeStarted();
offscreenBrowser.ViewRect = new Structs.Rect(rect.X, rect.Y, rect.Width, rect.Height);
host.WasResized();
}
}

void IOutOfProcessClientRpc.SetFocus(int browserId, bool focus)
{
var browser = _browsers.FirstOrDefault(x => x.Id == browserId);
GetBrowser(browserId)?.GetBrowserHost().SetFocus(focus);
}

browser?.GetBrowserHost().SetFocus(focus);
void IOutOfProcessClientRpc.SendMouseClickEvent(int browserId, int x, int y, string mouseButtonType, bool mouseUp, int clickCount, uint eventFlags)
{
CefThread.ExecuteOnUiThread(() =>
{
GetBrowser(browserId)?.GetBrowserHost().SendMouseClickEvent(x, y, (MouseButtonType)Enum.Parse(typeof(MouseButtonType), mouseButtonType), mouseUp, clickCount, (CefEventFlags)eventFlags);
return true;
});
}

private OutOfProcessChromiumWebBrowser GetBrowser(int id) => _browsers.FirstOrDefault(x => x.Id == id);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>WinExe</OutputType>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright © 2018 The CefSharp Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

using System.Runtime.InteropServices;
using CefSharp.Structs;

namespace CefSharp.Wpf.Internals
{
/// <summary>
/// The RECT structure defines the coordinates of the upper-left and lower-right corners of a rectangle.
/// </summary>
/// <see cref="https://docs.microsoft.com/en-us/previous-versions/dd162897(v=vs.85)"/>
/// <remarks>
/// By convention, the right and bottom edges of the rectangle are normally considered exclusive.
/// In other words, the pixel whose coordinates are ( right, bottom ) lies immediately outside of the the rectangle.
/// For example, when RECT is passed to the FillRect function, the rectangle is filled up to, but not including,
/// the right column and bottom row of pixels. This structure is identical to the RECTL structure.
/// </remarks>
[StructLayout(LayoutKind.Sequential)]
public struct RectStruct
{
/// <summary>
/// The x-coordinate of the upper-left corner of the rectangle.
/// </summary>
public int Left;

/// <summary>
/// The y-coordinate of the upper-left corner of the rectangle.
/// </summary>
public int Top;

/// <summary>
/// The x-coordinate of the lower-right corner of the rectangle.
/// </summary>
public int Right;

/// <summary>
/// The y-coordinate of the lower-right corner of the rectangle.
/// </summary>
public int Bottom;

public static implicit operator Rect(RectStruct rect)
{
return new Rect(0, 0, rect.Right - rect.Left, rect.Bottom - rect.Top);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
using CefSharp.Internals;
using System;
using CefSharp.OutOfProcess.Interface;
using CefSharp.Structs;
using CefSharp.Enums;

namespace CefSharp.OutOfProcess.BrowserProcess
{
/// <summary>
/// An ChromiumWebBrowser instance specifically for hosting CEF out of process
/// </summary>
public class OffscreenOutOfProcessChromiumWebBrowser : OutOfProcessChromiumWebBrowser, IRenderWebBrowser
{
private readonly RenderHandler renderHandler;
private readonly RenderHandler popupRenderHandler;

public OffscreenOutOfProcessChromiumWebBrowser(IOutOfProcessHostRpc outOfProcessServer, int id, string address = "", IRequestContext requestContext = null)
: base(outOfProcessServer, id, address, requestContext, true)
{
renderHandler = new RenderHandler($"0render_{Id}_");
popupRenderHandler = new RenderHandler($"0render_{Id}_popup_");
}

/// <summary>
/// The dpi scale factor, if the browser has already been initialized
/// you must manually call IBrowserHost.NotifyScreenInfoChanged for the
/// browser to be notified of the change.
/// </summary>
public float DpiScaleFactor { get; set; } = 1;

internal CefSharp.Structs.Rect ViewRect { get; set; }

/// <summary>
/// Gets the ScreenInfo - currently used to get the DPI scale factor.
/// </summary>
/// <returns>ScreenInfo containing the current DPI scale factor</returns>
ScreenInfo? IRenderWebBrowser.GetScreenInfo() => GetScreenInfo();

/// <summary>
/// Gets the ScreenInfo - currently used to get the DPI scale factor.
/// </summary>
/// <returns>ScreenInfo containing the current DPI scale factor</returns>
protected virtual ScreenInfo? GetScreenInfo()
{
CefSharp.Structs.Rect rect = new CefSharp.Structs.Rect();
CefSharp.Structs.Rect availableRect = new CefSharp.Structs.Rect();

if (DpiScaleFactor > 1.0)
{
rect = rect.ScaleByDpi(DpiScaleFactor);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hier meckert er bei mir, weil rect nicht initalisiert wurde

availableRect = availableRect.ScaleByDpi(DpiScaleFactor);
}

var screenInfo = new ScreenInfo
{
DeviceScaleFactor = DpiScaleFactor,
Rect = rect,
AvailableRect = availableRect,
};

return screenInfo;
}

Structs.Rect IRenderWebBrowser.GetViewRect() => ViewRect;

bool IRenderWebBrowser.GetScreenPoint(int viewX, int viewY, out int screenX, out int screenY)
{
screenX = ViewRect.X + viewX;
screenY = ViewRect.Y + viewY;

return true;
}

void IRenderWebBrowser.OnAcceleratedPaint(PaintElementType type, Structs.Rect dirtyRect, IntPtr sharedHandle)
{
throw new NotImplementedException();
}

void IRenderWebBrowser.OnPaint(PaintElementType type, Structs.Rect dirtyRect, IntPtr buffer, int width, int height)
{
var dirtyRectCopy = new Interface.Rect(dirtyRect.X, dirtyRect.Y, dirtyRect.Width, dirtyRect.Height);
string file = type == PaintElementType.Popup
? popupRenderHandler.OnPaint(buffer, width, height)
: renderHandler.OnPaint(buffer, width, height);

OutofProcessHostRpc.NotifyPaint(Id, type == PaintElementType.Popup, dirtyRectCopy, width, height, file);
}

void IRenderWebBrowser.OnCursorChange(IntPtr cursor, CursorType type, CursorInfo customCursorInfo)
{
// not implemented
}

bool IRenderWebBrowser.StartDragging(IDragData dragData, DragOperationsMask mask, int x, int y)
{
// not implemented
return false;
}

void IRenderWebBrowser.UpdateDragCursor(DragOperationsMask operation)
{
// not implemented
}

void IRenderWebBrowser.OnPopupShow(bool show) => OutofProcessHostRpc.NotifyPopupShow(Id, show);

void IRenderWebBrowser.OnPopupSize(CefSharp.Structs.Rect rect) => OutofProcessHostRpc.NotifyPopupSize(Id, new Interface.Rect(rect.X, rect.Y, rect.Width, rect.Height));

void IRenderWebBrowser.OnImeCompositionRangeChanged(Structs.Range selectedRange, CefSharp.Structs.Rect[] characterBounds)
{
throw new NotImplementedException();
}

void IRenderWebBrowser.OnVirtualKeyboardRequested(IBrowser browser, TextInputMode inputMode)
{
// not implemented
}
}
}
Loading