WindowImplBase.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. // Copyright (c) The Avalonia Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using Avalonia.Controls;
  7. using Avalonia.Controls.Platform.Surfaces;
  8. using Avalonia.Input;
  9. using Avalonia.Input.Raw;
  10. using Avalonia.Native.Interop;
  11. using Avalonia.OpenGL;
  12. using Avalonia.Platform;
  13. using Avalonia.Rendering;
  14. using Avalonia.Threading;
  15. namespace Avalonia.Native
  16. {
  17. public abstract class WindowBaseImpl : IWindowBaseImpl,
  18. IFramebufferPlatformSurface
  19. {
  20. IInputRoot _inputRoot;
  21. IAvnWindowBase _native;
  22. private object _syncRoot = new object();
  23. private bool _deferredRendering = false;
  24. private bool _gpu = false;
  25. private readonly MouseDevice _mouse;
  26. private readonly IKeyboardDevice _keyboard;
  27. private readonly IStandardCursorFactory _cursorFactory;
  28. private Size _savedLogicalSize;
  29. private Size _lastRenderedLogicalSize;
  30. private double _savedScaling;
  31. private GlPlatformSurface _glSurface;
  32. public WindowBaseImpl(AvaloniaNativePlatformOptions opts)
  33. {
  34. _gpu = opts.UseGpu;
  35. _deferredRendering = opts.UseDeferredRendering;
  36. _keyboard = AvaloniaLocator.Current.GetService<IKeyboardDevice>();
  37. _mouse = new MouseDevice();
  38. _cursorFactory = AvaloniaLocator.Current.GetService<IStandardCursorFactory>();
  39. }
  40. protected void Init(IAvnWindowBase window, IAvnScreens screens)
  41. {
  42. _native = window;
  43. _glSurface = new GlPlatformSurface(window);
  44. Screen = new ScreenImpl(screens);
  45. _savedLogicalSize = ClientSize;
  46. _savedScaling = Scaling;
  47. var monitor = Screen.AllScreens.OrderBy(x => x.PixelDensity)
  48. .FirstOrDefault(m => m.Bounds.Contains(Position));
  49. Resize(new Size(monitor.WorkingArea.Width * 0.75d, monitor.WorkingArea.Height * 0.7d));
  50. }
  51. public Size ClientSize
  52. {
  53. get
  54. {
  55. var s = _native.GetClientSize();
  56. return new Size(s.Width, s.Height);
  57. }
  58. }
  59. public IEnumerable<object> Surfaces => new[] {
  60. (_gpu ? _glSurface : (object)null),
  61. this
  62. };
  63. public ILockedFramebuffer Lock()
  64. {
  65. if(_deferredRendering)
  66. {
  67. var w = _savedLogicalSize.Width * _savedScaling;
  68. var h = _savedLogicalSize.Height * _savedScaling;
  69. var dpi = _savedScaling * 96;
  70. return new DeferredFramebuffer(cb =>
  71. {
  72. lock (_syncRoot)
  73. {
  74. if (_native == null)
  75. return false;
  76. cb(_native);
  77. _lastRenderedLogicalSize = _savedLogicalSize;
  78. return true;
  79. }
  80. }, (int)w, (int)h, new Vector(dpi, dpi));
  81. }
  82. return new FramebufferWrapper(_native.GetSoftwareFramebuffer());
  83. }
  84. public Action<Rect> Paint { get; set; }
  85. public Action<Size> Resized { get; set; }
  86. public Action Closed { get; set; }
  87. public IMouseDevice MouseDevice => AvaloniaNativePlatform.MouseDevice;
  88. public abstract IPopupImpl CreatePopup();
  89. class FramebufferWrapper : ILockedFramebuffer
  90. {
  91. public FramebufferWrapper(AvnFramebuffer fb)
  92. {
  93. Address = fb.Data;
  94. Size = new PixelSize(fb.Width, fb.Height);
  95. RowBytes = fb.Stride;
  96. Dpi = new Vector(fb.Dpi.X, fb.Dpi.Y);
  97. Format = (PixelFormat)fb.PixelFormat;
  98. }
  99. public IntPtr Address { get; set; }
  100. public PixelSize Size { get; set; }
  101. public int RowBytes {get;set;}
  102. public Vector Dpi { get; set; }
  103. public PixelFormat Format { get; }
  104. public void Dispose()
  105. {
  106. // Do nothing
  107. }
  108. }
  109. protected class WindowBaseEvents : CallbackBase, IAvnWindowBaseEvents
  110. {
  111. private readonly WindowBaseImpl _parent;
  112. public WindowBaseEvents(WindowBaseImpl parent)
  113. {
  114. _parent = parent;
  115. }
  116. void IAvnWindowBaseEvents.Closed()
  117. {
  118. var n = _parent._native;
  119. _parent._native = null;
  120. try
  121. {
  122. _parent?.Closed?.Invoke();
  123. }
  124. finally
  125. {
  126. n?.Dispose();
  127. }
  128. _parent._mouse.Dispose();
  129. }
  130. void IAvnWindowBaseEvents.Activated() => _parent.Activated?.Invoke();
  131. void IAvnWindowBaseEvents.Deactivated() => _parent.Deactivated?.Invoke();
  132. void IAvnWindowBaseEvents.Paint()
  133. {
  134. Dispatcher.UIThread.RunJobs(DispatcherPriority.Render);
  135. var s = _parent.ClientSize;
  136. _parent.Paint?.Invoke(new Rect(0, 0, s.Width, s.Height));
  137. }
  138. void IAvnWindowBaseEvents.Resized(AvnSize size)
  139. {
  140. var s = new Size(size.Width, size.Height);
  141. _parent._savedLogicalSize = s;
  142. _parent.Resized?.Invoke(s);
  143. }
  144. void IAvnWindowBaseEvents.PositionChanged(AvnPoint position)
  145. {
  146. _parent.PositionChanged?.Invoke(position.ToAvaloniaPixelPoint());
  147. }
  148. void IAvnWindowBaseEvents.RawMouseEvent(AvnRawMouseEventType type, uint timeStamp, AvnInputModifiers modifiers, AvnPoint point, AvnVector delta)
  149. {
  150. _parent.RawMouseEvent(type, timeStamp, modifiers, point, delta);
  151. }
  152. bool IAvnWindowBaseEvents.RawKeyEvent(AvnRawKeyEventType type, uint timeStamp, AvnInputModifiers modifiers, uint key)
  153. {
  154. return _parent.RawKeyEvent(type, timeStamp, modifiers, key);
  155. }
  156. bool IAvnWindowBaseEvents.RawTextInputEvent(uint timeStamp, string text)
  157. {
  158. return _parent.RawTextInputEvent(timeStamp, text);
  159. }
  160. void IAvnWindowBaseEvents.ScalingChanged(double scaling)
  161. {
  162. _parent._savedScaling = scaling;
  163. _parent.ScalingChanged?.Invoke(scaling);
  164. }
  165. void IAvnWindowBaseEvents.RunRenderPriorityJobs()
  166. {
  167. Dispatcher.UIThread.RunJobs(DispatcherPriority.Render);
  168. }
  169. }
  170. public void Activate()
  171. {
  172. _native.Activate();
  173. }
  174. public bool RawTextInputEvent(uint timeStamp, string text)
  175. {
  176. Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1);
  177. var args = new RawTextInputEventArgs(_keyboard, timeStamp, _inputRoot, text);
  178. Input?.Invoke(args);
  179. return args.Handled;
  180. }
  181. public bool RawKeyEvent(AvnRawKeyEventType type, uint timeStamp, AvnInputModifiers modifiers, uint key)
  182. {
  183. Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1);
  184. var args = new RawKeyEventArgs(_keyboard, timeStamp, _inputRoot, (RawKeyEventType)type, (Key)key, (RawInputModifiers)modifiers);
  185. Input?.Invoke(args);
  186. return args.Handled;
  187. }
  188. public void RawMouseEvent(AvnRawMouseEventType type, uint timeStamp, AvnInputModifiers modifiers, AvnPoint point, AvnVector delta)
  189. {
  190. Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1);
  191. switch (type)
  192. {
  193. case AvnRawMouseEventType.Wheel:
  194. Input?.Invoke(new RawMouseWheelEventArgs(_mouse, timeStamp, _inputRoot, point.ToAvaloniaPoint(), new Vector(delta.X, delta.Y), (RawInputModifiers)modifiers));
  195. break;
  196. default:
  197. Input?.Invoke(new RawPointerEventArgs(_mouse, timeStamp, _inputRoot, (RawPointerEventType)type, point.ToAvaloniaPoint(), (RawInputModifiers)modifiers));
  198. break;
  199. }
  200. }
  201. public void Resize(Size clientSize)
  202. {
  203. _native.Resize(clientSize.Width, clientSize.Height);
  204. }
  205. public IRenderer CreateRenderer(IRenderRoot root)
  206. {
  207. if (_deferredRendering)
  208. return new DeferredRenderer(root, AvaloniaLocator.Current.GetService<IRenderLoop>(),
  209. rendererLock:
  210. _gpu ? new AvaloniaNativeDeferredRendererLock(_native) : null);
  211. return new ImmediateRenderer(root);
  212. }
  213. public virtual void Dispose()
  214. {
  215. _native?.Close();
  216. _native?.Dispose();
  217. _native = null;
  218. (Screen as ScreenImpl)?.Dispose();
  219. }
  220. public void Invalidate(Rect rect)
  221. {
  222. if (!_deferredRendering && _native != null)
  223. _native.Invalidate(new AvnRect { Height = rect.Height, Width = rect.Width, X = rect.X, Y = rect.Y });
  224. }
  225. public void SetInputRoot(IInputRoot inputRoot)
  226. {
  227. _inputRoot = inputRoot;
  228. }
  229. public void Show()
  230. {
  231. _native.Show();
  232. }
  233. public PixelPoint Position
  234. {
  235. get => _native.GetPosition().ToAvaloniaPixelPoint();
  236. set => _native.SetPosition(value.ToAvnPoint());
  237. }
  238. public Point PointToClient(PixelPoint point)
  239. {
  240. return _native.PointToClient(point.ToAvnPoint()).ToAvaloniaPoint();
  241. }
  242. public PixelPoint PointToScreen(Point point)
  243. {
  244. return _native.PointToScreen(point.ToAvnPoint()).ToAvaloniaPixelPoint();
  245. }
  246. public void Hide()
  247. {
  248. _native.Hide();
  249. }
  250. public void BeginMoveDrag(PointerPressedEventArgs e)
  251. {
  252. _native.BeginMoveDrag();
  253. }
  254. public Size MaxClientSize => Screen.AllScreens.Select(s => s.Bounds.Size.ToSize(s.PixelDensity))
  255. .OrderByDescending(x => x.Width + x.Height).FirstOrDefault();
  256. public void SetTopmost(bool value)
  257. {
  258. _native.SetTopMost(value);
  259. }
  260. public double Scaling => _native.GetScaling();
  261. public Action Deactivated { get; set; }
  262. public Action Activated { get; set; }
  263. public void SetCursor(IPlatformHandle cursor)
  264. {
  265. var newCursor = cursor as AvaloniaNativeCursor;
  266. newCursor = newCursor ?? (_cursorFactory.GetCursor(StandardCursorType.Arrow) as AvaloniaNativeCursor);
  267. _native.Cursor = newCursor.Cursor;
  268. }
  269. public Action<PixelPoint> PositionChanged { get; set; }
  270. public Action<RawInputEventArgs> Input { get; set; }
  271. Action<double> ScalingChanged { get; set; }
  272. Action<double> ITopLevelImpl.ScalingChanged { get; set; }
  273. public IScreenImpl Screen { get; private set; }
  274. // TODO
  275. public void SetMinMaxSize(Size minSize, Size maxSize)
  276. {
  277. _native.SetMinMaxSize(minSize.ToAvnSize(), maxSize.ToAvnSize());
  278. }
  279. public void BeginResizeDrag(WindowEdge edge, PointerPressedEventArgs e)
  280. {
  281. }
  282. public IPlatformHandle Handle => new PlatformHandle(IntPtr.Zero, "NOT SUPPORTED");
  283. }
  284. }