// 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;
using CefSharp.Enums;
using CefSharp.Structs;
using Point = System.Drawing.Point;
using Range = CefSharp.Structs.Range;
using Size = System.Drawing.Size;
namespace CefSharp.OffScreen
{
///
/// Default implementation of , this class handles Offscreen Rendering (OSR).
/// Upstream documentation at http://magpcss.org/ceforum/apidocs3/projects/(default)/CefRenderHandler.html
///
public class DefaultRenderHandler : IRenderHandler
{
private ChromiumWebBrowser browser;
private Size popupSize;
private Point popupPosition;
///
/// Need a lock because the caller may be asking for the bitmap
/// while Chromium async rendering has returned on another thread.
///
public readonly object BitmapLock = new object();
///
/// Gets or sets a value indicating whether the popup is open.
///
///
/// true if popup is opened; otherwise, false.
///
public bool PopupOpen { get; protected set; }
///
/// Contains the last bitmap buffer. Direct access
/// to the underlying buffer - there is no locking when trying
/// to access directly, use where appropriate.
///
/// The bitmap.
public BitmapBuffer BitmapBuffer { get; private set; }
///
/// The popup Bitmap.
///
public BitmapBuffer PopupBuffer { get; private set; }
///
/// Gets the size of the popup.
///
public Size PopupSize
{
get { return popupSize; }
}
///
/// Gets the popup position.
///
public Point PopupPosition
{
get { return popupPosition; }
}
///
/// Create a new instance of DefaultRenderHadler
///
/// reference to the ChromiumWebBrowser
public DefaultRenderHandler(ChromiumWebBrowser browser)
{
this.browser = browser;
popupPosition = new Point();
popupSize = new Size();
BitmapBuffer = new BitmapBuffer(BitmapLock);
PopupBuffer = new BitmapBuffer(BitmapLock);
}
///
/// Dispose of this instance.
///
public void Dispose()
{
browser = null;
BitmapBuffer = null;
PopupBuffer = null;
}
///
/// Called to allow the client to return a ScreenInfo object with appropriate values.
/// If null is returned then the rectangle from GetViewRect will be used.
/// If the rectangle is still empty or invalid popups may not be drawn correctly.
///
/// Return null if no screenInfo structure is provided.
public virtual ScreenInfo? GetScreenInfo()
{
var deviceScaleFactor = browser?.DeviceScaleFactor;
if (deviceScaleFactor == null)
{
return null;
}
var screenInfo = new ScreenInfo { DeviceScaleFactor = deviceScaleFactor.Value };
return screenInfo;
}
///
/// Called to retrieve the view rectangle which is relative to screen coordinates.
/// This method must always provide a non-empty rectangle.
///
/// Return a ViewRect strict containing the rectangle.
public virtual Rect GetViewRect()
{
//TODO: See if this can be refactored and remove browser reference
var size = browser?.Size;
if (size == null)
{
return new Rect(0, 0, 1, 1);
}
var viewRect = new Rect(0, 0, size.Value.Width, size.Value.Height);
return viewRect;
}
///
/// Called to retrieve the translation from view coordinates to actual screen coordinates.
///
/// x
/// y
/// screen x
/// screen y
/// Return true if the screen coordinates were provided.
public virtual bool GetScreenPoint(int viewX, int viewY, out int screenX, out int screenY)
{
screenX = viewX;
screenY = viewY;
return false;
}
///
/// Called when an element has been rendered to the shared texture handle.
/// This method is only called when is set to true
///
/// The underlying implementation uses a pool to deliver frames. As a result,
/// the handle may differ every frame depending on how many frames are
/// in-progress. The handle's resource cannot be cached and cannot be accessed
/// outside of this callback. It should be reopened each time this callback is
/// executed and the contents should be copied to a texture owned by the
/// client application. The contents of acceleratedPaintInfo
/// will be released back to the pool after this callback returns.
///
/// indicates whether the element is the view or the popup widget.
/// contains the set of rectangles in pixel coordinates that need to be repainted
/// contains the shared handle; on Windows it is a
/// HANDLE to a texture that can be opened with D3D11 OpenSharedResource.
public virtual void OnAcceleratedPaint(PaintElementType type, Rect dirtyRect, AcceleratedPaintInfo acceleratedPaintInfo)
{
//NOT USED
}
///
/// Called when an element should be painted. Pixel values passed to this method are scaled relative to view coordinates based on the
/// value of returned from .
/// This method is only called when is set to false.
/// Called on the CEF UI Thread
///
/// indicates whether the element is the view or the popup widget.
/// contains the set of rectangles in pixel coordinates that need to be repainted
/// The bitmap will be will be width * height *4 bytes in size and represents a BGRA image with an upper-left origin
/// width
/// height
public virtual void OnPaint(PaintElementType type, Rect dirtyRect, IntPtr buffer, int width, int height)
{
var isPopup = type == PaintElementType.Popup;
var bitmapBuffer = isPopup ? PopupBuffer : BitmapBuffer;
bitmapBuffer.UpdateBuffer(width, height, buffer, dirtyRect);
}
///
/// Called when the browser's cursor has changed.
///
/// If type is Custom then customCursorInfo will be populated with the custom cursor information
/// cursor type
/// custom cursor Information
public virtual void OnCursorChange(IntPtr cursor, CursorType type, CursorInfo customCursorInfo)
{
}
///
/// Called when the user starts dragging content in the web view. Contextual information about the dragged content is
/// supplied by dragData. OS APIs that run a system message loop may be used within the StartDragging call.
/// Don't call any of the IBrowserHost.DragSource*Ended* methods after returning false.
/// Return true to handle the drag operation. Call and either synchronously or asynchronously to inform
/// the web view that the drag operation has ended.
///
/// drag data
/// operation mask
/// combined x and y provide the drag start location in screen coordinates
/// combined x and y provide the drag start location in screen coordinates
/// Return false to abort the drag operation.
public virtual bool StartDragging(IDragData dragData, DragOperationsMask mask, int x, int y)
{
return false;
}
///
/// Called when the web view wants to update the mouse cursor during a drag & drop operation.
///
/// describes the allowed operation (none, move, copy, link).
public virtual void UpdateDragCursor(DragOperationsMask operation)
{
}
///
/// Called when the browser wants to show or hide the popup widget.
///
/// The popup should be shown if show is true and hidden if show is false.
public virtual void OnPopupShow(bool show)
{
PopupOpen = show;
}
///
/// Called when the browser wants to move or resize the popup widget.
///
/// contains the new location and size in view coordinates.
public virtual void OnPopupSize(Rect rect)
{
popupPosition.X = rect.X;
popupPosition.Y = rect.Y;
popupSize.Width = rect.Width;
popupSize.Height = rect.Height;
}
///
/// Called when the IME composition range has changed.
///
/// is the range of characters that have been selected
/// is the bounds of each character in view coordinates.
public virtual void OnImeCompositionRangeChanged(Range selectedRange, Rect[] characterBounds)
{
}
///
/// Called when an on-screen keyboard should be shown or hidden for the specified browser.
///
/// the browser
/// specifies what kind of keyboard should be opened. If , any existing keyboard for this browser should be hidden.
public virtual void OnVirtualKeyboardRequested(IBrowser browser, TextInputMode inputMode)
{
}
}
}