// 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) { } } }