Browse Source

Merge branch 'master' into features/keyboard-input

pull/1977/head
danwalmsley 8 years ago
committed by GitHub
parent
commit
cd414a735c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 24
      src/Avalonia.Native.OSX/SystemDialogs.mm
  2. 157
      src/Avalonia.Native.OSX/window.h
  3. 274
      src/Avalonia.Native.OSX/window.mm
  4. 77
      src/Avalonia.Native/DeferredFramebuffer.cs
  5. 78
      src/Avalonia.Native/DeferredRendererProxy.cs
  6. 5
      src/Avalonia.Native/Helpers.cs
  7. 95
      src/Avalonia.Native/WindowImplBase.cs
  8. 25
      src/headers/avalonia-native.h

24
src/Avalonia.Native.OSX/SystemDialogs.mm

@ -52,8 +52,8 @@ class SystemDialogs : public ComSingleObject<IAvnSystemDialogs, &IID_IAvnSystemD
if(parentWindowHandle != nullptr)
{
auto windowBase = dynamic_cast<WindowBaseImpl*>(parentWindowHandle);
[windowBase->Window makeKeyAndOrderFront:windowBase->Window];
auto windowHolder = dynamic_cast<INSWindowHolder*>(parentWindowHandle);
[windowHolder->GetNSWindow() makeKeyAndOrderFront:windowHolder->GetNSWindow()];
}
return;
@ -66,9 +66,9 @@ class SystemDialogs : public ComSingleObject<IAvnSystemDialogs, &IID_IAvnSystemD
if(parentWindowHandle != nullptr)
{
auto windowBase = dynamic_cast<WindowBaseImpl*>(parentWindowHandle);
auto windowBase = dynamic_cast<INSWindowHolder*>(parentWindowHandle);
[panel beginSheetModalForWindow:windowBase->Window completionHandler:handler];
[panel beginSheetModalForWindow:windowBase->GetNSWindow() completionHandler:handler];
}
else
{
@ -144,8 +144,8 @@ class SystemDialogs : public ComSingleObject<IAvnSystemDialogs, &IID_IAvnSystemD
if(parentWindowHandle != nullptr)
{
auto windowBase = dynamic_cast<WindowBaseImpl*>(parentWindowHandle);
[windowBase->Window makeKeyAndOrderFront:windowBase->Window];
auto windowHolder = dynamic_cast<INSWindowHolder*>(parentWindowHandle);
[windowHolder->GetNSWindow() makeKeyAndOrderFront:windowHolder->GetNSWindow()];
}
return;
@ -158,9 +158,9 @@ class SystemDialogs : public ComSingleObject<IAvnSystemDialogs, &IID_IAvnSystemD
if(parentWindowHandle != nullptr)
{
auto windowBase = dynamic_cast<WindowBaseImpl*>(parentWindowHandle);
auto windowHolder = dynamic_cast<INSWindowHolder*>(parentWindowHandle);
[panel beginSheetModalForWindow:windowBase->Window completionHandler:handler];
[panel beginSheetModalForWindow:windowHolder->GetNSWindow() completionHandler:handler];
}
else
{
@ -225,8 +225,8 @@ class SystemDialogs : public ComSingleObject<IAvnSystemDialogs, &IID_IAvnSystemD
if(parentWindowHandle != nullptr)
{
auto windowBase = dynamic_cast<WindowBaseImpl*>(parentWindowHandle);
[windowBase->Window makeKeyAndOrderFront:windowBase->Window];
auto windowHolder = dynamic_cast<INSWindowHolder*>(parentWindowHandle);
[windowHolder->GetNSWindow() makeKeyAndOrderFront:windowHolder->GetNSWindow()];
}
return;
@ -238,9 +238,9 @@ class SystemDialogs : public ComSingleObject<IAvnSystemDialogs, &IID_IAvnSystemD
if(parentWindowHandle != nullptr)
{
auto windowBase = dynamic_cast<WindowBaseImpl*>(parentWindowHandle);
auto windowBase = dynamic_cast<INSWindowHolder*>(parentWindowHandle);
[panel beginSheetModalForWindow:windowBase->Window completionHandler:handler];
[panel beginSheetModalForWindow:windowBase->GetNSWindow() completionHandler:handler];
}
else
{

157
src/Avalonia.Native.OSX/window.h

@ -15,6 +15,7 @@ class WindowBaseImpl;
-(AvnView*) initWithParent: (WindowBaseImpl*) parent;
-(NSEvent*) lastMouseDownEvent;
-(AvnPoint) translateLocalPoint:(AvnPoint)pt;
-(void) setSwRenderedFrame: (AvnFramebuffer*) fb dispose: (IUnknown*) dispose;
@end
@interface AvnWindow : NSWindow <NSWindowDelegate>
@ -22,161 +23,9 @@ class WindowBaseImpl;
-(void) setCanBecomeKeyAndMain;
@end
class WindowBaseImpl : public ComSingleObject<IAvnWindowBase, &IID_IAvnWindowBase>
struct INSWindowHolder
{
public:
AvnView* View;
AvnWindow* Window;
ComPtr<IAvnWindowBaseEvents> BaseEvents;
AvnPoint lastPositionSet;
WindowBaseImpl(IAvnWindowBaseEvents* events)
{
BaseEvents = events;
View = [[AvnView alloc] initWithParent:this];
Window = [[AvnWindow alloc] initWithParent:this];
lastPositionSet.X = 100;
lastPositionSet.Y = 100;
[Window setStyleMask:NSWindowStyleMaskBorderless];
[Window setBackingType:NSBackingStoreBuffered];
[Window setContentView: View];
}
virtual HRESULT Show()
{
SetPosition(lastPositionSet);
UpdateStyle();
[Window makeKeyAndOrderFront:Window];
return S_OK;
}
virtual HRESULT Hide ()
{
if(Window != nullptr)
{
[Window orderOut:Window];
}
return S_OK;
}
virtual HRESULT Close()
{
[Window close];
return S_OK;
}
virtual HRESULT GetClientSize(AvnSize* ret)
{
if(ret == nullptr)
return E_POINTER;
auto frame = [View frame];
ret->Width = frame.size.width;
ret->Height = frame.size.height;
return S_OK;
}
virtual HRESULT GetScaling (double* ret)
{
if(ret == nullptr)
return E_POINTER;
if(Window == nullptr)
{
*ret = 1;
return S_OK;
}
*ret = [Window backingScaleFactor];
return S_OK;
}
virtual HRESULT Resize(double x, double y)
{
[Window setContentSize:NSSize{x, y}];
return S_OK;
}
virtual void Invalidate (AvnRect rect)
{
[View setNeedsDisplayInRect:[View frame]];
}
virtual void BeginMoveDrag ()
{
auto lastEvent = [View lastMouseDownEvent];
if(lastEvent == nullptr)
{
return;
}
[Window performWindowDragWithEvent:lastEvent];
}
virtual HRESULT GetPosition (AvnPoint* ret)
{
if(ret == nullptr)
{
return E_POINTER;
}
auto frame = [Window frame];
ret->X = frame.origin.x;
ret->Y = frame.origin.y + frame.size.height;
*ret = ConvertPointY(*ret);
return S_OK;
}
virtual void SetPosition (AvnPoint point)
{
lastPositionSet = point;
[Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(point))];
}
virtual HRESULT PointToClient (AvnPoint point, AvnPoint* ret)
{
if(ret == nullptr)
{
return E_POINTER;
}
point = ConvertPointY(point);
auto viewPoint = [Window convertPointFromScreen:ToNSPoint(point)];
*ret = [View translateLocalPoint:ToAvnPoint(viewPoint)];
return S_OK;
}
virtual HRESULT PointToScreen (AvnPoint point, AvnPoint* ret)
{
if(ret == nullptr)
{
return E_POINTER;
}
auto cocoaViewPoint = ToNSPoint([View translateLocalPoint:point]);
auto cocoaScreenPoint = [Window convertPointToScreen:cocoaViewPoint];
*ret = ConvertPointY(ToAvnPoint(cocoaScreenPoint));
return S_OK;
}
protected:
virtual NSWindowStyleMask GetStyle()
{
return NSWindowStyleMaskBorderless;
}
void UpdateStyle()
{
[Window setStyleMask:GetStyle()];
}
virtual AvnWindow* GetNSWindow () = 0;
};
#endif /* window_h */

274
src/Avalonia.Native.OSX/window.mm

@ -2,9 +2,202 @@
#include "window.h"
#include "KeyTransform.h"
class WindowBaseImpl : public ComSingleObject<IAvnWindowBase, &IID_IAvnWindowBase>, public INSWindowHolder
{
public:
AvnView* View;
AvnWindow* Window;
ComPtr<IAvnWindowBaseEvents> BaseEvents;
AvnPoint lastPositionSet;
WindowBaseImpl(IAvnWindowBaseEvents* events)
{
BaseEvents = events;
View = [[AvnView alloc] initWithParent:this];
Window = [[AvnWindow alloc] initWithParent:this];
lastPositionSet.X = 100;
lastPositionSet.Y = 100;
[Window setStyleMask:NSWindowStyleMaskBorderless];
[Window setBackingType:NSBackingStoreBuffered];
[Window setContentView: View];
}
virtual AvnWindow* GetNSWindow()
{
return Window;
}
virtual HRESULT Show()
{
SetPosition(lastPositionSet);
UpdateStyle();
[Window makeKeyAndOrderFront:Window];
return S_OK;
}
virtual HRESULT Hide ()
{
if(Window != nullptr)
{
[Window orderOut:Window];
}
return S_OK;
}
virtual HRESULT SetTopMost (bool value)
{
[Window setLevel: value ? NSFloatingWindowLevel : NSNormalWindowLevel];
return S_OK;
}
virtual HRESULT Close()
{
[Window close];
return S_OK;
}
virtual HRESULT GetClientSize(AvnSize* ret)
{
if(ret == nullptr)
return E_POINTER;
auto frame = [View frame];
ret->Width = frame.size.width;
ret->Height = frame.size.height;
return S_OK;
}
virtual HRESULT GetMaxClientSize(AvnSize* ret)
{
if(ret == nullptr)
return E_POINTER;
auto size = [NSScreen.screens objectAtIndex:0].frame.size;
ret->Height = size.height;
ret->Width = size.width;
return S_OK;
}
virtual HRESULT GetScaling (double* ret)
{
if(ret == nullptr)
return E_POINTER;
if(Window == nullptr)
{
*ret = 1;
return S_OK;
}
*ret = [Window backingScaleFactor];
return S_OK;
}
virtual HRESULT Resize(double x, double y)
{
[Window setContentSize:NSSize{x, y}];
return S_OK;
}
virtual void Invalidate (AvnRect rect)
{
[View setNeedsDisplayInRect:[View frame]];
}
virtual void BeginMoveDrag ()
{
auto lastEvent = [View lastMouseDownEvent];
if(lastEvent == nullptr)
{
return;
}
[Window performWindowDragWithEvent:lastEvent];
}
virtual HRESULT GetPosition (AvnPoint* ret)
{
if(ret == nullptr)
{
return E_POINTER;
}
auto frame = [Window frame];
ret->X = frame.origin.x;
ret->Y = frame.origin.y + frame.size.height;
*ret = ConvertPointY(*ret);
return S_OK;
}
virtual void SetPosition (AvnPoint point)
{
lastPositionSet = point;
[Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(point))];
}
virtual HRESULT PointToClient (AvnPoint point, AvnPoint* ret)
{
if(ret == nullptr)
{
return E_POINTER;
}
point = ConvertPointY(point);
auto viewPoint = [Window convertScreenToBase:ToNSPoint(point)];
*ret = [View translateLocalPoint:ToAvnPoint(viewPoint)];
return S_OK;
}
virtual HRESULT PointToScreen (AvnPoint point, AvnPoint* ret)
{
if(ret == nullptr)
{
return E_POINTER;
}
auto cocoaViewPoint = ToNSPoint([View translateLocalPoint:point]);
auto cocoaScreenPoint = [Window convertBaseToScreen:cocoaViewPoint];
*ret = ConvertPointY(ToAvnPoint(cocoaScreenPoint));
return S_OK;
}
virtual HRESULT ThreadSafeSetSwRenderedFrame(AvnFramebuffer* fb, IUnknown* dispose)
{
[View setSwRenderedFrame: fb dispose: dispose];
return S_OK;
}
protected:
virtual NSWindowStyleMask GetStyle()
{
return NSWindowStyleMaskBorderless;
}
void UpdateStyle()
{
[Window setStyleMask:GetStyle()];
}
};
NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEventTrackingRunLoopMode, NSModalPanelRunLoopMode, NSRunLoopCommonModes, NSConnectionReplyMode, nil];
@implementation AvnView
{
ComPtr<WindowBaseImpl> _parent;
ComPtr<IUnknown> _swRenderedFrame;
AvnFramebuffer _swRenderedFrameBuffer;
bool _queuedDisplayFromThread;
NSTrackingArea* _area;
bool _isLeftPressed, _isMiddlePressed, _isRightPressed, _isMouseOver;
NSEvent* _lastMouseDownEvent;
@ -49,18 +242,10 @@
_parent->BaseEvents->Resized(AvnSize{newSize.width, newSize.height});
}
- (void)drawRect:(NSRect)dirtyRect
- (void) drawFb: (AvnFramebuffer*) fb
{
auto logicalSize = [self frame].size;
auto pixelSize = [self convertSizeToBacking:logicalSize];
int w = pixelSize.width;
int h = pixelSize.height;
int stride = w * 4;
void*ptr = malloc(h * stride);
_parent->BaseEvents->SoftwareDraw(ptr, stride, w, h, AvnSize{logicalSize.width, logicalSize.height});
auto colorSpace = CGColorSpaceCreateDeviceRGB();
auto bctx = CGBitmapContextCreate(ptr, w, h, 8, stride, colorSpace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast);
auto bctx = CGBitmapContextCreate(fb->Data, fb->Width, fb->Height, 8, fb->Stride, colorSpace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast);
auto image = CGBitmapContextCreateImage(bctx);
CGContextRelease(bctx);
CGColorSpaceRelease(colorSpace);
@ -70,13 +255,74 @@
[ctx saveGraphicsState];
auto cgc = [ctx CGContext];
CGContextDrawImage(cgc, CGRect{0,0, logicalSize.width, logicalSize.height}, image);
CGContextDrawImage(cgc, CGRect{0,0, fb->Width/(fb->Dpi.X/96), fb->Height/(fb->Dpi.Y/96)}, image);
CGImageRelease(image);
[ctx restoreGraphicsState];
}
- (void)drawRect:(NSRect)dirtyRect
{
_parent->BaseEvents->RunRenderPriorityJobs();
@synchronized (self) {
if(_swRenderedFrame != NULL)
{
[self drawFb: &_swRenderedFrameBuffer];
return;
}
}
auto logicalSize = [self frame].size;
auto pixelSize = [self convertSizeToBacking:logicalSize];
int w = pixelSize.width;
int h = pixelSize.height;
int stride = w * 4;
void*ptr = malloc(h * stride);
AvnFramebuffer fb = {
.Data = ptr,
.Stride = stride,
.Width = w,
.Height = h,
.PixelFormat = kAvnRgba8888,
.Dpi = AvnVector { .X = w / logicalSize.width * 96, .Y = h / logicalSize.height * 96}
};
_parent->BaseEvents->SoftwareDraw(&fb);
[self drawFb: &fb];
free(ptr);
}
-(void) redrawSelf
{
@autoreleasepool
{
@synchronized(self)
{
if(!_queuedDisplayFromThread)
return;
_queuedDisplayFromThread = false;
}
[self setNeedsDisplayInRect:[self frame]];
[self display];
}
}
-(void) setSwRenderedFrame: (AvnFramebuffer*) fb dispose: (IUnknown*) dispose
{
@autoreleasepool {
@synchronized (self) {
_swRenderedFrame = dispose;
_swRenderedFrameBuffer = *fb;
if(!_queuedDisplayFromThread)
{
_queuedDisplayFromThread = true;
[self performSelector:@selector(redrawSelf) onThread:[NSThread mainThread] withObject:NULL waitUntilDone:false modes: AllLoopModes];
}
}
}
}
- (AvnPoint) translateLocalPoint:(AvnPoint)pt
{
pt.Y = [self bounds].size.height - pt.Y;
@ -93,6 +339,12 @@
return result;
}
- (void) viewDidChangeBackingProperties
{
_parent->BaseEvents->ScalingChanged([_parent->Window backingScaleFactor]);
[super viewDidChangeBackingProperties];
}
- (void)mouseEvent:(NSEvent *)event withType:(AvnRawMouseEventType) type
{
auto localPoint = [self convertPoint:[event locationInWindow] toView:self];

77
src/Avalonia.Native/DeferredFramebuffer.cs

@ -0,0 +1,77 @@
using System;
using System.Runtime.InteropServices;
using Avalonia.Native.Interop;
using Avalonia.Platform;
using SharpGen.Runtime;
namespace Avalonia.Native
{
public class DeferredFramebuffer : ILockedFramebuffer
{
private readonly Func<Action<IAvnWindowBase>, bool> _lockWindow;
public DeferredFramebuffer(Func<Action<IAvnWindowBase>, bool> lockWindow,
int width, int height, Vector dpi)
{
_lockWindow = lockWindow;
Address = Marshal.AllocHGlobal(width * height * 4);
Width = width;
Height = height;
RowBytes = width * 4;
Dpi = dpi;
Format = PixelFormat.Rgba8888;
}
public IntPtr Address { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public int RowBytes { get; set; }
public Vector Dpi { get; set; }
public PixelFormat Format { get; set; }
class Disposer : CallbackBase
{
private IntPtr _ptr;
public Disposer(IntPtr ptr)
{
_ptr = ptr;
}
protected override void Destroyed()
{
if(_ptr != IntPtr.Zero)
{
Marshal.FreeHGlobal(_ptr);
_ptr = IntPtr.Zero;
}
}
}
public void Dispose()
{
if (Address == IntPtr.Zero)
return;
if (!_lockWindow(win =>
{
var fb = new AvnFramebuffer
{
Data = Address,
Dpi = new AvnVector
{
X = Dpi.X,
Y = Dpi.Y
},
Width = Width,
Height = Height,
PixelFormat = (AvnPixelFormat)Format,
Stride = RowBytes
};
using (var d = new Disposer(Address))
win.ThreadSafeSetSwRenderedFrame(ref fb, d);
}))
Marshal.FreeHGlobal(Address);
Address = IntPtr.Zero;
}
}
}

78
src/Avalonia.Native/DeferredRendererProxy.cs

@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.VisualTree;
namespace Avalonia.Native
{
public class DeferredRendererProxy : IRenderer, IRenderLoopTask, IRenderLoop
{
object _lock = new object();
void IRenderLoop.Add(IRenderLoopTask i)
{
AvaloniaLocator.Current.GetService<IRenderLoop>().Add(this);
}
void IRenderLoop.Remove(IRenderLoopTask i)
{
AvaloniaLocator.Current.GetService<IRenderLoop>().Remove(this);
}
DeferredRenderer _renderer;
IRenderLoopTask _rendererTask;
public DeferredRendererProxy(IRenderRoot root)
{
_renderer = new DeferredRenderer(root, this);
_rendererTask = (IRenderLoopTask)_renderer;
}
public bool DrawFps{
get => _renderer.DrawFps;
set => _renderer.DrawFps = value;
}
public bool DrawDirtyRects
{
get => _renderer.DrawDirtyRects;
set => _renderer.DrawDirtyRects = value;
}
public bool NeedsUpdate => _rendererTask.NeedsUpdate;
public void AddDirty(IVisual visual) => _renderer.AddDirty(visual);
public void Dispose() => _renderer.Dispose();
public IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool> filter)
{
return _renderer.HitTest(p, root, filter);
}
public void Paint(Rect rect)
{
if (NeedsUpdate)
Update(TimeSpan.FromMilliseconds(Environment.TickCount));
Render();
}
public void Resized(Size size) => _renderer.Resized(size);
public void Start() => _renderer.Start();
public void Stop() => _renderer.Stop();
public void Update(TimeSpan time)
{
_rendererTask.Update(time);
}
public void Render()
{
lock(_lock)
{
_rendererTask.Render();
}
}
}
}

5
src/Avalonia.Native/Helpers.cs

@ -14,5 +14,10 @@ namespace Avalonia.Native
{
return new AvnPoint { X = pt.X, Y = pt.Y };
}
public static Size ToAvaloniaSize (this AvnSize size)
{
return new Size(size.Width, size.Height);
}
}
}

95
src/Avalonia.Native/WindowImplBase.cs

@ -15,10 +15,12 @@ namespace Avalonia.Native
{
IInputRoot _inputRoot;
IAvnWindowBase _native;
private bool _deferredRendering = false;
private object _syncRoot = new object();
private bool _deferredRendering = true;
private readonly IMouseDevice _mouse;
private readonly IKeyboardDevice _keyboard;
private Size _savedLogicalSize;
private double _savedScaling;
public WindowBaseImpl()
{
@ -29,6 +31,8 @@ namespace Avalonia.Native
protected void Init(IAvnWindowBase window)
{
_native = window;
_savedLogicalSize = ClientSize;
_savedScaling = Scaling;
}
public Size ClientSize
@ -44,7 +48,28 @@ namespace Avalonia.Native
public IEnumerable<object> Surfaces => new[] { this };
public ILockedFramebuffer Lock()
{
return _framebuffer;
if(_deferredRendering)
{
var w = _savedLogicalSize.Width * _savedScaling;
var h = _savedLogicalSize.Height * _savedScaling;
var dpi = _savedScaling * 96;
return new DeferredFramebuffer(cb =>
{
lock (_syncRoot)
{
if (_native == null)
return false;
cb(_native);
return true;
}
}, (int)w, (int)h, new Vector(dpi, dpi));
}
var fb = _framebuffer;
_framebuffer = null;
if (fb == null)
throw new InvalidOperationException("Lock call without corresponding Paint event");
return fb;
}
public Action<Rect> Paint { get; set; }
@ -82,26 +107,31 @@ namespace Avalonia.Native
void IAvnWindowBaseEvents.Deactivated() => _parent.Deactivated?.Invoke();
void IAvnWindowBaseEvents.SoftwareDraw(IntPtr ptr, int stride, int pixelWidth, int pixelHeight, AvnSize logicalSize)
void IAvnWindowBaseEvents.SoftwareDraw(ref AvnFramebuffer fb)
{
Dispatcher.UIThread.RunJobs(DispatcherPriority.Render);
_parent._framebuffer = new SavedFramebuffer
{
Address = ptr,
RowBytes = stride,
Width = pixelWidth,
Height = pixelHeight,
Dpi = new Vector(pixelWidth / logicalSize.Width * 96, pixelHeight / logicalSize.Height * 96)
Address = fb.Data,
RowBytes = fb.Stride,
Width = fb.Width,
Height = fb.Height,
Dpi = new Vector(fb.Dpi.X, fb.Dpi.Y)
};
_parent.Paint?.Invoke(new Rect(0, 0, logicalSize.Width, logicalSize.Height));
_parent.Paint?.Invoke(new Rect(0, 0, fb.Width / (fb.Dpi.X / 96), fb.Height / (fb.Dpi.Y / 96)));
}
void IAvnWindowBaseEvents.Resized(AvnSize size) => _parent.Resized?.Invoke(new Size(size.Width, size.Height));
void IAvnWindowBaseEvents.Resized(AvnSize size)
{
var s = new Size(size.Width, size.Height);
_parent._savedLogicalSize = s;
_parent.Resized?.Invoke(s);
}
public void RawMouseEvent(AvnRawMouseEventType type, uint timeStamp, AvnInputModifiers modifiers, AvnPoint point, AvnVector delta)
void IAvnWindowBaseEvents.RawMouseEvent(AvnRawMouseEventType type, uint timeStamp, AvnInputModifiers modifiers, AvnPoint point, AvnVector delta)
{
_parent.RawMouseEvent(type, timeStamp, modifiers, point, delta);
}
@ -110,8 +140,21 @@ namespace Avalonia.Native
{
return _parent.RawKeyEvent(type, timeStamp, modifiers, key);
}
}
void IAvnWindowBaseEvents.ScalingChanged(double scaling)
{
_parent._savedScaling = scaling;
_parent.ScalingChanged?.Invoke(scaling);
}
void IAvnWindowBaseEvents.RunRenderPriorityJobs()
{
if (_parent._deferredRendering)
// Hack to trigger Paint event on the renderer
_parent.Paint?.Invoke(new Rect());
Dispatcher.UIThread.RunJobs(DispatcherPriority.Render);
}
}
public void Activate()
{
@ -150,8 +193,8 @@ namespace Avalonia.Native
public IRenderer CreateRenderer(IRenderRoot root)
{
//_deferredRendering = true;
//return new DeferredRenderer(root, AvaloniaLocator.Current.GetService<IRenderLoop>());
if(_deferredRendering)
return new DeferredRendererProxy(root);
return new ImmediateRenderer(root);
}
@ -165,7 +208,8 @@ namespace Avalonia.Native
public void Invalidate(Rect rect)
{
_native.Invalidate(new AvnRect { Height = rect.Height, Width = rect.Width, X = rect.X, Y = rect.Y });
if (!_deferredRendering)
_native.Invalidate(new AvnRect { Height = rect.Height, Width = rect.Width, X = rect.X, Y = rect.Y });
}
public void SetInputRoot(IInputRoot inputRoot)
@ -206,27 +250,32 @@ namespace Avalonia.Native
_native.BeginMoveDrag();
}
#region Stubs
public Size MaxClientSize => _native.GetMaxClientSize().ToAvaloniaSize();
public void SetTopmost(bool value)
{
_native.SetTopMost(value);
}
public double Scaling => _native.GetScaling();
public Action<Point> PositionChanged { get; set; }
public Action Deactivated { get; set; }
public Action Activated { get; set; }
#region Stubs
public Action<Point> PositionChanged { get; set; }
public Action<RawInputEventArgs> Input { get; set; }
Action<double> ScalingChanged { get; set; }
public IPlatformHandle Handle => new PlatformHandle(IntPtr.Zero, "NOT SUPPORTED");
public Size MaxClientSize => new Size(1600, 900);
public IScreenImpl Screen => new ScreenImpl();
Action<double> ITopLevelImpl.ScalingChanged { get; set; }
public void SetTopmost(bool value)
{
}
public void SetMinMaxSize(Size minSize, Size maxSize)
{
}

25
src/headers/avalonia-native.h

@ -31,6 +31,23 @@ struct AvnPoint
double X, Y;
};
enum AvnPixelFormat
{
kAvnRgb565,
kAvnRgba8888,
kAvnBgra8888
};
struct AvnFramebuffer
{
void* Data;
int Width;
int Height;
int Stride;
AvnVector Dpi;
AvnPixelFormat PixelFormat;
};
enum AvnRawMouseEventType
{
LeaveWindow,
@ -80,6 +97,7 @@ AVNCOM(IAvnWindowBase, 02) : virtual IUnknown
virtual HRESULT Hide () = 0;
virtual HRESULT Close() = 0;
virtual HRESULT GetClientSize(AvnSize*ret) = 0;
virtual HRESULT GetMaxClientSize(AvnSize* ret) = 0;
virtual HRESULT GetScaling(double*ret)=0;
virtual HRESULT Resize(double width, double height) = 0;
virtual void Invalidate (AvnRect rect) = 0;
@ -88,6 +106,8 @@ AVNCOM(IAvnWindowBase, 02) : virtual IUnknown
virtual void SetPosition (AvnPoint point) = 0;
virtual HRESULT PointToClient (AvnPoint point, AvnPoint*ret) = 0;
virtual HRESULT PointToScreen (AvnPoint point, AvnPoint*ret) = 0;
virtual HRESULT ThreadSafeSetSwRenderedFrame(AvnFramebuffer* fb, IUnknown* dispose) = 0;
virtual HRESULT SetTopMost (bool value) = 0;
};
AVNCOM(IAvnPopup, 03) : virtual IAvnWindowBase
@ -103,7 +123,7 @@ AVNCOM(IAvnWindow, 04) : virtual IAvnWindowBase
AVNCOM(IAvnWindowBaseEvents, 05) : IUnknown
{
virtual HRESULT SoftwareDraw(void* ptr, int stride, int pixelWidth, int pixelHeight, const AvnSize& logicalSize) = 0;
virtual HRESULT SoftwareDraw(AvnFramebuffer* fb) = 0;
virtual void Closed() = 0;
virtual void Activated() = 0;
virtual void Deactivated() = 0;
@ -113,8 +133,9 @@ AVNCOM(IAvnWindowBaseEvents, 05) : IUnknown
AvnInputModifiers modifiers,
AvnPoint point,
AvnVector delta) = 0;
virtual bool RawKeyEvent (AvnRawKeyEventType type, unsigned int timeStamp, AvnInputModifiers modifiers, unsigned int key) = 0;
virtual void ScalingChanged(double scaling) = 0;
virtual void RunRenderPriorityJobs() = 0;
};

Loading…
Cancel
Save