CefRenderHandler.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. namespace Xilium.CefGlue
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Runtime.InteropServices;
  7. using Xilium.CefGlue.Interop;
  8. /// <summary>
  9. /// Implement this interface to handle events when window rendering is disabled.
  10. /// The methods of this class will be called on the UI thread.
  11. /// </summary>
  12. public abstract unsafe partial class CefRenderHandler
  13. {
  14. private static readonly CefRectangle[] s_emptyRectangleArray = new CefRectangle[0];
  15. private cef_accessibility_handler_t* get_accessibility_handler(cef_render_handler_t* self)
  16. {
  17. CheckSelf(self);
  18. var result = GetAccessibilityHandler();
  19. if (result == null) return null;
  20. return result.ToNative();
  21. }
  22. /// <summary>
  23. /// Return the handler for accessibility notifications. If no handler is
  24. /// provided the default implementation will be used.
  25. /// </summary>
  26. protected abstract CefAccessibilityHandler GetAccessibilityHandler();
  27. private int get_root_screen_rect(cef_render_handler_t* self, cef_browser_t* browser, cef_rect_t* rect)
  28. {
  29. CheckSelf(self);
  30. var m_browser = CefBrowser.FromNative(browser);
  31. var m_rect = new CefRectangle();
  32. var result = GetRootScreenRect(m_browser, ref m_rect);
  33. if (result)
  34. {
  35. rect->x = m_rect.X;
  36. rect->y = m_rect.Y;
  37. rect->width = m_rect.Width;
  38. rect->height = m_rect.Height;
  39. return 1;
  40. }
  41. else return 0;
  42. }
  43. /// <summary>
  44. /// Called to retrieve the root window rectangle in screen coordinates. Return
  45. /// true if the rectangle was provided. If this method returns false the
  46. /// rectangle from GetViewRect will be used.
  47. /// </summary>
  48. protected virtual bool GetRootScreenRect(CefBrowser browser, ref CefRectangle rect)
  49. {
  50. // TODO: return CefRectangle? (Nullable<CefRectangle>) instead of returning bool?
  51. return false;
  52. }
  53. private void get_view_rect(cef_render_handler_t* self, cef_browser_t* browser, cef_rect_t* rect)
  54. {
  55. CheckSelf(self);
  56. var m_browser = CefBrowser.FromNative(browser);
  57. CefRectangle m_rect;
  58. GetViewRect(m_browser, out m_rect);
  59. rect->x = m_rect.X;
  60. rect->y = m_rect.Y;
  61. rect->width = m_rect.Width;
  62. rect->height = m_rect.Height;
  63. }
  64. /// <summary>
  65. /// Called to retrieve the view rectangle which is relative to screen
  66. /// coordinates. This method must always provide a non-empty rectangle.
  67. /// </summary>
  68. protected abstract void GetViewRect(CefBrowser browser, out CefRectangle rect);
  69. private int get_screen_point(cef_render_handler_t* self, cef_browser_t* browser, int viewX, int viewY, int* screenX, int* screenY)
  70. {
  71. CheckSelf(self);
  72. var m_browser = CefBrowser.FromNative(browser);
  73. int m_screenX = 0;
  74. int m_screenY = 0;
  75. var result = GetScreenPoint(m_browser, viewX, viewY, ref m_screenX, ref m_screenY);
  76. if (result)
  77. {
  78. *screenX = m_screenX;
  79. *screenY = m_screenY;
  80. return 1;
  81. }
  82. else return 0;
  83. }
  84. /// <summary>
  85. /// Called to retrieve the translation from view coordinates to actual screen
  86. /// coordinates. Return true if the screen coordinates were provided.
  87. /// </summary>
  88. protected virtual bool GetScreenPoint(CefBrowser browser, int viewX, int viewY, ref int screenX, ref int screenY)
  89. {
  90. return false;
  91. }
  92. private int get_screen_info(cef_render_handler_t* self, cef_browser_t* browser, cef_screen_info_t* screen_info)
  93. {
  94. CheckSelf(self);
  95. var m_browser = CefBrowser.FromNative(browser);
  96. var m_screenInfo = new CefScreenInfo(screen_info);
  97. var result = GetScreenInfo(m_browser, m_screenInfo);
  98. m_screenInfo.Dispose();
  99. m_browser.Dispose();
  100. return result ? 1 : 0;
  101. }
  102. /// <summary>
  103. /// Called to allow the client to fill in the CefScreenInfo object with
  104. /// appropriate values. Return true if the |screen_info| structure has been
  105. /// modified.
  106. /// If the screen info rectangle is left empty the rectangle from GetViewRect
  107. /// will be used. If the rectangle is still empty or invalid popups may not be
  108. /// drawn correctly.
  109. /// </summary>
  110. protected abstract bool GetScreenInfo(CefBrowser browser, CefScreenInfo screenInfo);
  111. private void on_popup_show(cef_render_handler_t* self, cef_browser_t* browser, int show)
  112. {
  113. CheckSelf(self);
  114. var m_browser = CefBrowser.FromNative(browser);
  115. OnPopupShow(m_browser, show != 0);
  116. }
  117. /// <summary>
  118. /// Called when the browser wants to show or hide the popup widget. The popup
  119. /// should be shown if |show| is true and hidden if |show| is false.
  120. /// </summary>
  121. protected virtual void OnPopupShow(CefBrowser browser, bool show)
  122. {
  123. }
  124. private void on_popup_size(cef_render_handler_t* self, cef_browser_t* browser, cef_rect_t* rect)
  125. {
  126. CheckSelf(self);
  127. var m_browser = CefBrowser.FromNative(browser);
  128. var m_rect = new CefRectangle(rect->x, rect->y, rect->width, rect->height);
  129. OnPopupSize(m_browser, m_rect);
  130. }
  131. /// <summary>
  132. /// Called when the browser wants to move or resize the popup widget. |rect|
  133. /// contains the new location and size in view coordinates.
  134. /// </summary>
  135. protected abstract void OnPopupSize(CefBrowser browser, CefRectangle rect);
  136. private void on_paint(cef_render_handler_t* self, cef_browser_t* browser, CefPaintElementType type, UIntPtr dirtyRectsCount, cef_rect_t* dirtyRects, void* buffer, int width, int height)
  137. {
  138. CheckSelf(self);
  139. var m_browser = CefBrowser.FromNative(browser);
  140. // TODO: reuse arrays?
  141. var m_dirtyRects = new CefRectangle[(int)dirtyRectsCount];
  142. var count = (int)dirtyRectsCount;
  143. var rect = dirtyRects;
  144. for (var i = 0; i < count; i++)
  145. {
  146. m_dirtyRects[i].X = rect->x;
  147. m_dirtyRects[i].Y = rect->y;
  148. m_dirtyRects[i].Width = rect->width;
  149. m_dirtyRects[i].Height = rect->height;
  150. rect++;
  151. }
  152. OnPaint(m_browser, type, m_dirtyRects, (IntPtr)buffer, width, height);
  153. }
  154. /// <summary>
  155. /// Called when an element should be painted. Pixel values passed to this
  156. /// method are scaled relative to view coordinates based on the value of
  157. /// CefScreenInfo.device_scale_factor returned from GetScreenInfo. |type|
  158. /// indicates whether the element is the view or the popup widget. |buffer|
  159. /// contains the pixel data for the whole image. |dirtyRects| contains the set
  160. /// of rectangles in pixel coordinates that need to be repainted. |buffer| will
  161. /// be |width|*|height|*4 bytes in size and represents a BGRA image with an
  162. /// upper-left origin. This method is only called when CefWindowInfo::SharedTextureEnabled
  163. /// is set to false.
  164. /// </summary>
  165. protected abstract void OnPaint(CefBrowser browser, CefPaintElementType type, CefRectangle[] dirtyRects, IntPtr buffer, int width, int height);
  166. private void on_accelerated_paint(cef_render_handler_t* self, cef_browser_t* browser, CefPaintElementType type, UIntPtr dirtyRectsCount, cef_rect_t* dirtyRects, void* shared_handle)
  167. {
  168. CheckSelf(self);
  169. var m_browser = CefBrowser.FromNative(browser);
  170. // TODO: reuse arrays?
  171. var m_dirtyRects = new CefRectangle[(int)dirtyRectsCount];
  172. var count = (int)dirtyRectsCount;
  173. var rect = dirtyRects;
  174. for (var i = 0; i < count; i++)
  175. {
  176. m_dirtyRects[i].X = rect->x;
  177. m_dirtyRects[i].Y = rect->y;
  178. m_dirtyRects[i].Width = rect->width;
  179. m_dirtyRects[i].Height = rect->height;
  180. rect++;
  181. }
  182. OnAcceleratedPaint(m_browser, type, m_dirtyRects, (IntPtr)shared_handle);
  183. }
  184. /// <summary>
  185. /// Called when an element has been rendered to the shared texture handle.
  186. /// |type| indicates whether the element is the view or the popup widget.
  187. /// |dirtyRects| contains the set of rectangles in pixel coordinates that need
  188. /// to be repainted. |shared_handle| is the handle for a D3D11 Texture2D that
  189. /// can be accessed via ID3D11Device using the OpenSharedResource method. This
  190. /// method is only called when CefWindowInfo::SharedTextureEnabled is set to
  191. /// true, and is currently only supported on Windows.
  192. /// </summary>
  193. protected abstract void OnAcceleratedPaint(CefBrowser browser, CefPaintElementType type, CefRectangle[] dirtyRects, IntPtr sharedHandle);
  194. private int start_dragging(cef_render_handler_t* self, cef_browser_t* browser, cef_drag_data_t* drag_data, CefDragOperationsMask allowed_ops, int x, int y)
  195. {
  196. CheckSelf(self);
  197. var m_browser = CefBrowser.FromNative(browser);
  198. var m_dragData = CefDragData.FromNative(drag_data); // TODO dispose?
  199. var m_result = StartDragging(m_browser, m_dragData, allowed_ops, x, y);
  200. return m_result ? 1 : 0;
  201. }
  202. /// <summary>
  203. /// Called when the user starts dragging content in the web view. Contextual
  204. /// information about the dragged content is supplied by |drag_data|.
  205. /// (|x|, |y|) is the drag start location in screen coordinates.
  206. /// OS APIs that run a system message loop may be used within the
  207. /// StartDragging call.
  208. /// Return false to abort the drag operation. Don't call any of
  209. /// CefBrowserHost::DragSource*Ended* methods after returning false.
  210. /// Return true to handle the drag operation. Call
  211. /// CefBrowserHost::DragSourceEndedAt and DragSourceSystemDragEnded either
  212. /// synchronously or asynchronously to inform the web view that the drag
  213. /// operation has ended.
  214. /// </summary>
  215. protected virtual bool StartDragging(CefBrowser browser, CefDragData dragData, CefDragOperationsMask allowedOps, int x, int y)
  216. {
  217. return false;
  218. }
  219. private void update_drag_cursor(cef_render_handler_t* self, cef_browser_t* browser, CefDragOperationsMask operation)
  220. {
  221. CheckSelf(self);
  222. var m_browser = CefBrowser.FromNative(browser);
  223. UpdateDragCursor(m_browser, operation);
  224. }
  225. /// <summary>
  226. /// Called when the web view wants to update the mouse cursor during a
  227. /// drag &amp; drop operation. |operation| describes the allowed operation
  228. /// (none, move, copy, link).
  229. /// </summary>
  230. protected virtual void UpdateDragCursor(CefBrowser browser, CefDragOperationsMask operation)
  231. {
  232. }
  233. private void on_scroll_offset_changed(cef_render_handler_t* self, cef_browser_t* browser, double x, double y)
  234. {
  235. CheckSelf(self);
  236. var m_browser = CefBrowser.FromNative(browser);
  237. OnScrollOffsetChanged(m_browser, x, y);
  238. }
  239. /// <summary>
  240. /// Called when the scroll offset has changed.
  241. /// </summary>
  242. protected abstract void OnScrollOffsetChanged(CefBrowser browser, double x, double y);
  243. private void on_ime_composition_range_changed(cef_render_handler_t* self, cef_browser_t* browser, cef_range_t* selected_range, UIntPtr character_boundsCount, cef_rect_t* character_bounds)
  244. {
  245. CheckSelf(self);
  246. // TODO: reuse array/special list for rectange - this method called only from one thread and can be reused
  247. var m_browser = CefBrowser.FromNative(browser);
  248. var m_selectedRange = new CefRange(selected_range->from, selected_range->to);
  249. CefRectangle[] m_characterBounds;
  250. if (character_boundsCount == UIntPtr.Zero)
  251. {
  252. m_characterBounds = s_emptyRectangleArray;
  253. }
  254. else
  255. {
  256. var m_characterBoundsCount = checked((int)character_boundsCount);
  257. m_characterBounds = new CefRectangle[m_characterBoundsCount];
  258. for (var i = 0; i < m_characterBoundsCount; i++)
  259. {
  260. m_characterBounds[i] = new CefRectangle(
  261. character_bounds[i].x,
  262. character_bounds[i].y,
  263. character_bounds[i].width,
  264. character_bounds[i].height
  265. );
  266. }
  267. }
  268. OnImeCompositionRangeChanged(m_browser, m_selectedRange, m_characterBounds);
  269. }
  270. /// <summary>
  271. /// Called when the IME composition range has changed. |selected_range| is the
  272. /// range of characters that have been selected. |character_bounds| is the
  273. /// bounds of each character in view coordinates.
  274. /// </summary>
  275. protected abstract void OnImeCompositionRangeChanged(CefBrowser browser, CefRange selectedRange, CefRectangle[] characterBounds);
  276. private void on_text_selection_changed(cef_render_handler_t* self, cef_browser_t* browser, cef_string_t* selected_text, cef_range_t* selected_range)
  277. {
  278. CheckSelf(self);
  279. var m_browser = CefBrowser.FromNative(browser);
  280. var m_selected_text = cef_string_t.ToString(selected_text);
  281. var m_selected_range = new CefRange(selected_range->from, selected_range->to);
  282. OnTextSelectionChanged(m_browser, m_selected_text, m_selected_range);
  283. }
  284. /// <summary>
  285. /// Called when text selection has changed for the specified |browser|.
  286. /// |selected_text| is the currently selected text and |selected_range| is
  287. /// the character range.
  288. /// </summary>
  289. protected virtual void OnTextSelectionChanged(CefBrowser browser, string selectedText, CefRange selectedRange) { }
  290. private void on_virtual_keyboard_requested(cef_render_handler_t* self, cef_browser_t* browser, CefTextInputMode input_mode)
  291. {
  292. CheckSelf(self);
  293. var mBrowser = CefBrowser.FromNative(browser);
  294. OnVirtualKeyboardRequested(mBrowser, input_mode);
  295. }
  296. /// <summary>
  297. /// Called when an on-screen keyboard should be shown or hidden for the
  298. /// specified |browser|. |input_mode| specifies what kind of keyboard
  299. /// should be opened. If |input_mode| is CEF_TEXT_INPUT_MODE_NONE, any
  300. /// existing keyboard for this browser should be hidden.
  301. /// </summary>
  302. protected virtual void OnVirtualKeyboardRequested(CefBrowser browser, CefTextInputMode inputMode) { }
  303. }
  304. }