diff --git a/Documentation/build.md b/Documentation/build.md
index 56b028206d..8c2ef57b54 100644
--- a/Documentation/build.md
+++ b/Documentation/build.md
@@ -36,7 +36,7 @@ Avalonia requires [CastXML](https://github.com/CastXML/CastXML) for XML processi
On macOS:
```
-brew install castxml
+brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/8a004a91a7fcd3f6620d5b01b6541ff0a640ffba/Formula/castxml.rb
```
On Debian based Linux (Debian, Ubuntu, Mint, etc):
diff --git a/build/SkiaSharp.props b/build/SkiaSharp.props
index 08a9aa3ceb..4def44cbd0 100644
--- a/build/SkiaSharp.props
+++ b/build/SkiaSharp.props
@@ -1,6 +1,6 @@
-
-
+
+
diff --git a/native/Avalonia.Native/inc/avalonia-native.h b/native/Avalonia.Native/inc/avalonia-native.h
index b10db08adc..7782165263 100644
--- a/native/Avalonia.Native/inc/avalonia-native.h
+++ b/native/Avalonia.Native/inc/avalonia-native.h
@@ -22,6 +22,9 @@ struct IAvnGlSurfaceRenderTarget;
struct IAvnGlSurfaceRenderingSession;
struct IAvnMenu;
struct IAvnMenuItem;
+struct IAvnStringArray;
+struct IAvnDndResultCallback;
+struct IAvnGCHandleDeallocatorCallback;
struct IAvnMenuEvents;
enum SystemDecorations {
@@ -130,11 +133,28 @@ enum AvnInputModifiers
XButton2MouseButton = 256
};
+enum class AvnDragDropEffects
+{
+ None = 0,
+ Copy = 1,
+ Move = 2,
+ Link = 4,
+};
+
+enum class AvnDragEventType
+{
+ Enter,
+ Over,
+ Leave,
+ Drop
+};
+
enum AvnWindowState
{
Normal,
Minimized,
Maximized,
+ FullScreen,
};
enum AvnStandardCursorType
@@ -187,7 +207,7 @@ enum AvnMenuItemToggleType
AVNCOM(IAvaloniaNativeFactory, 01) : IUnknown
{
public:
- virtual HRESULT Initialize() = 0;
+ virtual HRESULT Initialize(IAvnGCHandleDeallocatorCallback* deallocator) = 0;
virtual IAvnMacOptions* GetMacOptions() = 0;
virtual HRESULT CreateWindow(IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnWindow** ppv) = 0;
virtual HRESULT CreatePopup (IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnPopup** ppv) = 0;
@@ -195,6 +215,7 @@ public:
virtual HRESULT CreateSystemDialogs (IAvnSystemDialogs** ppv) = 0;
virtual HRESULT CreateScreens (IAvnScreens** ppv) = 0;
virtual HRESULT CreateClipboard(IAvnClipboard** ppv) = 0;
+ virtual HRESULT CreateDndClipboard(IAvnClipboard** ppv) = 0;
virtual HRESULT CreateCursorFactory(IAvnCursorFactory** ppv) = 0;
virtual HRESULT ObtainGlDisplay(IAvnGlDisplay** ppv) = 0;
virtual HRESULT SetAppMenu(IAvnMenu* menu) = 0;
@@ -235,6 +256,8 @@ AVNCOM(IAvnWindowBase, 02) : IUnknown
virtual HRESULT ObtainNSWindowHandleRetained(void** retOut) = 0;
virtual HRESULT ObtainNSViewHandle(void** retOut) = 0;
virtual HRESULT ObtainNSViewHandleRetained(void** retOut) = 0;
+ virtual HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point,
+ IAvnClipboard* clipboard, IAvnDndResultCallback* cb, void* sourceHandle) = 0;
};
AVNCOM(IAvnPopup, 03) : virtual IAvnWindowBase
@@ -244,9 +267,10 @@ AVNCOM(IAvnPopup, 03) : virtual IAvnWindowBase
AVNCOM(IAvnWindow, 04) : virtual IAvnWindowBase
{
- virtual HRESULT ShowDialog (IAvnWindow* parent) = 0;
+ virtual HRESULT SetEnabled (bool enable) = 0;
+ virtual HRESULT SetParent (IAvnWindow* parent) = 0;
virtual HRESULT SetCanResize(bool value) = 0;
- virtual HRESULT SetHasDecorations(SystemDecorations value) = 0;
+ virtual HRESULT SetDecorations(SystemDecorations value) = 0;
virtual HRESULT SetTitle (void* utf8Title) = 0;
virtual HRESULT SetTitleBarColor (AvnColor color) = 0;
virtual HRESULT SetWindowState(AvnWindowState state) = 0;
@@ -270,6 +294,9 @@ AVNCOM(IAvnWindowBaseEvents, 05) : IUnknown
virtual bool RawTextInputEvent (unsigned int timeStamp, const char* text) = 0;
virtual void ScalingChanged(double scaling) = 0;
virtual void RunRenderPriorityJobs() = 0;
+ virtual AvnDragDropEffects DragEvent(AvnDragEventType type, AvnPoint position,
+ AvnInputModifiers modifiers, AvnDragDropEffects effects,
+ IAvnClipboard* clipboard, void* dataObjectHandle) = 0;
};
@@ -283,6 +310,8 @@ AVNCOM(IAvnWindowEvents, 06) : IAvnWindowBaseEvents
virtual bool Closing () = 0;
virtual void WindowStateChanged (AvnWindowState state) = 0;
+
+ virtual void GotInputWhenDisabled () = 0;
};
AVNCOM(IAvnMacOptions, 07) : IUnknown
@@ -353,8 +382,10 @@ AVNCOM(IAvnScreens, 0e) : IUnknown
AVNCOM(IAvnClipboard, 0f) : IUnknown
{
- virtual HRESULT GetText (IAvnString**ppv) = 0;
- virtual HRESULT SetText (void* utf8Text) = 0;
+ virtual HRESULT GetText (char* type, IAvnString**ppv) = 0;
+ virtual HRESULT SetText (char* type, void* utf8Text) = 0;
+ virtual HRESULT ObtainFormats(IAvnStringArray**ppv) = 0;
+ virtual HRESULT GetStrings(char* type, IAvnStringArray**ppv) = 0;
virtual HRESULT Clear() = 0;
};
@@ -427,4 +458,20 @@ AVNCOM(IAvnMenuEvents, 1A) : IUnknown
virtual void NeedsUpdate () = 0;
};
+AVNCOM(IAvnStringArray, 20) : IUnknown
+{
+ virtual unsigned int GetCount() = 0;
+ virtual HRESULT Get(unsigned int index, IAvnString**ppv) = 0;
+};
+
+AVNCOM(IAvnDndResultCallback, 21) : IUnknown
+{
+ virtual void OnDragAndDropComplete(AvnDragDropEffects effecct) = 0;
+};
+
+AVNCOM(IAvnGCHandleDeallocatorCallback, 22) : IUnknown
+{
+ virtual void FreeGCHandle(void* handle) = 0;
+};
+
extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative();
diff --git a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
index 50a85bdf9f..ea28780c81 100644
--- a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
+++ b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
@@ -12,6 +12,7 @@
1A3E5EAA23E9F26C00EDE661 /* IOSurface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A3E5EA923E9F26C00EDE661 /* IOSurface.framework */; };
1A3E5EAE23E9FB1300EDE661 /* cgl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A3E5EAD23E9FB1300EDE661 /* cgl.mm */; };
1A3E5EB023E9FE8300EDE661 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A3E5EAF23E9FE8300EDE661 /* QuartzCore.framework */; };
+ 1A465D10246AB61600C5858B /* dnd.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A465D0F246AB61600C5858B /* dnd.mm */; };
37155CE4233C00EB0034DCE9 /* menu.h in Headers */ = {isa = PBXBuildFile; fileRef = 37155CE3233C00EB0034DCE9 /* menu.h */; };
37A517B32159597E00FBA241 /* Screens.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37A517B22159597E00FBA241 /* Screens.mm */; };
37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37C09D8721580FE4006A6758 /* SystemDialogs.mm */; };
@@ -33,6 +34,7 @@
1A3E5EA923E9F26C00EDE661 /* IOSurface.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOSurface.framework; path = System/Library/Frameworks/IOSurface.framework; sourceTree = SDKROOT; };
1A3E5EAD23E9FB1300EDE661 /* cgl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = cgl.mm; sourceTree = ""; };
1A3E5EAF23E9FE8300EDE661 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+ 1A465D0F246AB61600C5858B /* dnd.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = dnd.mm; sourceTree = ""; };
37155CE3233C00EB0034DCE9 /* menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = menu.h; sourceTree = ""; };
379860FE214DA0C000CD0246 /* KeyTransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyTransform.h; sourceTree = ""; };
37A4E71A2178846A00EACBCD /* headers */ = {isa = PBXFileReference; lastKnownFileType = folder; name = headers; path = ../../inc; sourceTree = ""; };
@@ -92,6 +94,7 @@
5BF943652167AD1D009CAE35 /* cursor.h */,
5B21A981216530F500CEE36E /* cursor.mm */,
5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */,
+ 1A465D0F246AB61600C5858B /* dnd.mm */,
AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */,
AB661C212148288600291242 /* common.h */,
379860FE214DA0C000CD0246 /* KeyTransform.h */,
@@ -196,6 +199,7 @@
37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */,
520624B322973F4100C4DCEF /* menu.mm in Sources */,
37A517B32159597E00FBA241 /* Screens.mm in Sources */,
+ 1A465D10246AB61600C5858B /* dnd.mm in Sources */,
AB00E4F72147CA920032A60A /* main.mm in Sources */,
37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */,
AB661C202148286E00291242 /* window.mm in Sources */,
diff --git a/native/Avalonia.Native/src/OSX/AvnString.h b/native/Avalonia.Native/src/OSX/AvnString.h
index 9a8f5a1318..88bc4e6963 100644
--- a/native/Avalonia.Native/src/OSX/AvnString.h
+++ b/native/Avalonia.Native/src/OSX/AvnString.h
@@ -10,5 +10,6 @@
#define AvnString_h
extern IAvnString* CreateAvnString(NSString* string);
-
+extern IAvnStringArray* CreateAvnStringArray(NSArray* array);
+extern IAvnStringArray* CreateAvnStringArray(NSString* string);
#endif /* AvnString_h */
diff --git a/native/Avalonia.Native/src/OSX/AvnString.mm b/native/Avalonia.Native/src/OSX/AvnString.mm
index b62fe8a968..6445a9fef1 100644
--- a/native/Avalonia.Native/src/OSX/AvnString.mm
+++ b/native/Avalonia.Native/src/OSX/AvnString.mm
@@ -7,6 +7,7 @@
//
#include "common.h"
+#include
class AvnStringImpl : public virtual ComSingleObject
{
@@ -61,7 +62,55 @@ public:
}
};
+class AvnStringArrayImpl : public virtual ComSingleObject
+{
+private:
+ std::vector> _list;
+public:
+ FORWARD_IUNKNOWN()
+ AvnStringArrayImpl(NSArray* array)
+ {
+ for(int c = 0; c < [array count]; c++)
+ {
+ ComPtr s;
+ *s.getPPV() = new AvnStringImpl([array objectAtIndex:c]);
+ _list.push_back(s);
+ }
+ }
+
+ AvnStringArrayImpl(NSString* string)
+ {
+ ComPtr s;
+ *s.getPPV() = new AvnStringImpl(string);
+ _list.push_back(s);
+ }
+
+ virtual unsigned int GetCount() override
+ {
+ return (unsigned int)_list.size();
+ }
+
+ virtual HRESULT Get(unsigned int index, IAvnString**ppv) override
+ {
+ if(_list.size() <= index)
+ return E_INVALIDARG;
+ *ppv = _list[index].getRetainedReference();
+ return S_OK;
+ }
+};
+
IAvnString* CreateAvnString(NSString* string)
{
return new AvnStringImpl(string);
}
+
+
+IAvnStringArray* CreateAvnStringArray(NSArray * array)
+{
+ return new AvnStringArrayImpl(array);
+}
+
+IAvnStringArray* CreateAvnStringArray(NSString* string)
+{
+ return new AvnStringArrayImpl(string);
+}
diff --git a/native/Avalonia.Native/src/OSX/app.mm b/native/Avalonia.Native/src/OSX/app.mm
index c30c2c3d18..1e74a70e66 100644
--- a/native/Avalonia.Native/src/OSX/app.mm
+++ b/native/Avalonia.Native/src/OSX/app.mm
@@ -15,6 +15,10 @@ NSApplicationActivationPolicy AvnDesiredActivationPolicy = NSApplicationActivati
}
[[NSApplication sharedApplication] setActivationPolicy: AvnDesiredActivationPolicy];
+
+ [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSFullScreenMenuItemEverywhere"];
+
+ [[NSApplication sharedApplication] setHelpMenu: [[NSMenu new] initWithTitle:@""]];
}
}
diff --git a/native/Avalonia.Native/src/OSX/clipboard.mm b/native/Avalonia.Native/src/OSX/clipboard.mm
index c2cf1f1f61..18d60d3853 100644
--- a/native/Avalonia.Native/src/OSX/clipboard.mm
+++ b/native/Avalonia.Native/src/OSX/clipboard.mm
@@ -3,16 +3,27 @@
class Clipboard : public ComSingleObject
{
+private:
+ NSPasteboard* _pb;
+ NSPasteboardItem* _item;
public:
FORWARD_IUNKNOWN()
- Clipboard()
+ Clipboard(NSPasteboard* pasteboard, NSPasteboardItem* item)
{
- NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
- [pasteBoard stringForType:NSPasteboardTypeString];
+ if(pasteboard == nil && item == nil)
+ pasteboard = [NSPasteboard generalPasteboard];
+
+ _pb = pasteboard;
+ _item = item;
}
- virtual HRESULT GetText (IAvnString**ppv) override
+ NSPasteboardItem* TryGetItem()
+ {
+ return _item;
+ }
+
+ virtual HRESULT GetText (char* type, IAvnString**ppv) override
{
@autoreleasepool
{
@@ -20,20 +31,53 @@ public:
{
return E_POINTER;
}
+ NSString* typeString = [NSString stringWithUTF8String:(const char*)type];
+ NSString* string = _item == nil ? [_pb stringForType:typeString] : [_item stringForType:typeString];
- *ppv = CreateAvnString([[NSPasteboard generalPasteboard] stringForType:NSPasteboardTypeString]);
+ *ppv = CreateAvnString(string);
return S_OK;
}
}
- virtual HRESULT SetText (void* utf8String) override
+ virtual HRESULT GetStrings(char* type, IAvnStringArray**ppv) override
{
@autoreleasepool
{
- NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
- [pasteBoard clearContents];
- [pasteBoard setString:[NSString stringWithUTF8String:(const char*)utf8String] forType:NSPasteboardTypeString];
+ *ppv= nil;
+ NSString* typeString = [NSString stringWithUTF8String:(const char*)type];
+ NSObject* data = _item == nil ? [_pb propertyListForType: typeString] : [_item propertyListForType: typeString];
+ if(data == nil)
+ return S_OK;
+
+ if([data isKindOfClass: [NSString class]])
+ {
+ *ppv = CreateAvnStringArray((NSString*) data);
+ return S_OK;
+ }
+
+ NSArray* arr = (NSArray*)data;
+
+ for(int c = 0; c < [arr count]; c++)
+ if(![[arr objectAtIndex:c] isKindOfClass:[NSString class]])
+ return E_INVALIDARG;
+
+ *ppv = CreateAvnStringArray(arr);
+ return S_OK;
+ }
+ }
+
+ virtual HRESULT SetText (char* type, void* utf8String) override
+ {
+ Clear();
+ @autoreleasepool
+ {
+ auto string = [NSString stringWithUTF8String:(const char*)utf8String];
+ auto typeString = [NSString stringWithUTF8String:(const char*)type];
+ if(_item == nil)
+ [_pb setString: string forType: typeString];
+ else
+ [_item setString: string forType:typeString];
}
return S_OK;
@@ -43,16 +87,34 @@ public:
{
@autoreleasepool
{
- NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
- [pasteBoard clearContents];
- [pasteBoard setString:@"" forType:NSPasteboardTypeString];
+ if(_item != nil)
+ _item = [NSPasteboardItem new];
+ else
+ {
+ [_pb clearContents];
+ [_pb setString:@"" forType:NSPasteboardTypeString];
+ }
}
return S_OK;
}
+
+ virtual HRESULT ObtainFormats(IAvnStringArray** ppv) override
+ {
+ *ppv = CreateAvnStringArray(_item == nil ? [_pb types] : [_item types]);
+ return S_OK;
+ }
};
-extern IAvnClipboard* CreateClipboard()
+extern IAvnClipboard* CreateClipboard(NSPasteboard* pb, NSPasteboardItem* item)
+{
+ return new Clipboard(pb, item);
+}
+
+extern NSPasteboardItem* TryGetPasteboardItem(IAvnClipboard*cb)
{
- return new Clipboard();
+ auto clipboard = dynamic_cast(cb);
+ if(clipboard == nil)
+ return nil;
+ return clipboard->TryGetItem();
}
diff --git a/native/Avalonia.Native/src/OSX/common.h b/native/Avalonia.Native/src/OSX/common.h
index 7a433bfd9f..df6a7be91c 100644
--- a/native/Avalonia.Native/src/OSX/common.h
+++ b/native/Avalonia.Native/src/OSX/common.h
@@ -8,11 +8,17 @@
#include
extern IAvnPlatformThreadingInterface* CreatePlatformThreading();
+extern void FreeAvnGCHandle(void* handle);
extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events, IAvnGlContext* gl);
extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events, IAvnGlContext* gl);
extern IAvnSystemDialogs* CreateSystemDialogs();
extern IAvnScreens* CreateScreens();
-extern IAvnClipboard* CreateClipboard();
+extern IAvnClipboard* CreateClipboard(NSPasteboard*, NSPasteboardItem*);
+extern NSPasteboardItem* TryGetPasteboardItem(IAvnClipboard*);
+extern NSObject* CreateDraggingSource(NSDragOperation op, IAvnDndResultCallback* cb, void* handle);
+extern void* GetAvnDataObjectHandleFromDraggingInfo(NSObject* info);
+extern NSString* GetAvnCustomDataType();
+extern AvnDragDropEffects ConvertDragDropEffects(NSDragOperation nsop);
extern IAvnCursorFactory* CreateCursorFactory();
extern IAvnGlDisplay* GetGlDisplay();
extern IAvnMenu* CreateAppMenu(IAvnMenuEvents* events);
diff --git a/native/Avalonia.Native/src/OSX/dnd.mm b/native/Avalonia.Native/src/OSX/dnd.mm
new file mode 100644
index 0000000000..294b8ee8ea
--- /dev/null
+++ b/native/Avalonia.Native/src/OSX/dnd.mm
@@ -0,0 +1,89 @@
+#include "common.h"
+
+extern AvnDragDropEffects ConvertDragDropEffects(NSDragOperation nsop)
+{
+ int effects = 0;
+ if((nsop & NSDragOperationCopy) != 0)
+ effects |= (int)AvnDragDropEffects::Copy;
+ if((nsop & NSDragOperationMove) != 0)
+ effects |= (int)AvnDragDropEffects::Move;
+ if((nsop & NSDragOperationLink) != 0)
+ effects |= (int)AvnDragDropEffects::Link;
+ return (AvnDragDropEffects)effects;
+};
+
+extern NSString* GetAvnCustomDataType()
+{
+ char buffer[256];
+ sprintf(buffer, "net.avaloniaui.inproc.uti.n%in", getpid());
+ return [NSString stringWithUTF8String:buffer];
+}
+
+@interface AvnDndSource : NSObject
+
+@end
+
+@implementation AvnDndSource
+{
+ NSDragOperation _operation;
+ ComPtr _cb;
+ void* _sourceHandle;
+};
+
+- (NSDragOperation)draggingSession:(nonnull NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context
+{
+ return NSDragOperationCopy;
+}
+
+- (AvnDndSource*) initWithOperation: (NSDragOperation)operation
+ andCallback: (IAvnDndResultCallback*) cb
+ andSourceHandle: (void*) handle
+{
+ self = [super init];
+ _operation = operation;
+ _cb = cb;
+ _sourceHandle = handle;
+ return self;
+}
+
+- (void)draggingSession:(NSDraggingSession *)session
+ endedAtPoint:(NSPoint)screenPoint
+ operation:(NSDragOperation)operation
+{
+ if(_cb != nil)
+ {
+ auto cb = _cb;
+ _cb = nil;
+ cb->OnDragAndDropComplete(ConvertDragDropEffects(operation));
+ }
+ if(_sourceHandle != nil)
+ {
+ FreeAvnGCHandle(_sourceHandle);
+ _sourceHandle = nil;
+ }
+}
+
+- (void*) gcHandle
+{
+ return _sourceHandle;
+}
+
+@end
+
+extern NSObject* CreateDraggingSource(NSDragOperation op, IAvnDndResultCallback* cb, void* handle)
+{
+ return [[AvnDndSource alloc] initWithOperation:op andCallback:cb andSourceHandle:handle];
+};
+
+extern void* GetAvnDataObjectHandleFromDraggingInfo(NSObject* info)
+{
+ id obj = [info draggingSource];
+ if(obj == nil)
+ return nil;
+ if([obj isKindOfClass: [AvnDndSource class]])
+ {
+ auto src = (AvnDndSource*)obj;
+ return [src gcHandle];
+ }
+ return nil;
+}
diff --git a/native/Avalonia.Native/src/OSX/main.mm b/native/Avalonia.Native/src/OSX/main.mm
index a63353bc0a..e6c4a861fd 100644
--- a/native/Avalonia.Native/src/OSX/main.mm
+++ b/native/Avalonia.Native/src/OSX/main.mm
@@ -150,14 +150,15 @@ public:
}
@end
-
+static ComPtr _deallocator;
class AvaloniaNative : public ComSingleObject
{
public:
FORWARD_IUNKNOWN()
- virtual HRESULT Initialize() override
+ virtual HRESULT Initialize(IAvnGCHandleDeallocatorCallback* deallocator) override
{
+ _deallocator = deallocator;
@autoreleasepool{
[[ThreadingInitializer new] do];
}
@@ -207,7 +208,13 @@ public:
virtual HRESULT CreateClipboard(IAvnClipboard** ppv) override
{
- *ppv = ::CreateClipboard ();
+ *ppv = ::CreateClipboard (nil, nil);
+ return S_OK;
+ }
+
+ virtual HRESULT CreateDndClipboard(IAvnClipboard** ppv) override
+ {
+ *ppv = ::CreateClipboard (nil, [NSPasteboardItem new]);
return S_OK;
}
@@ -257,6 +264,12 @@ extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative()
return new AvaloniaNative();
};
+extern void FreeAvnGCHandle(void* handle)
+{
+ if(_deallocator != nil)
+ _deallocator->FreeGCHandle(handle);
+}
+
NSSize ToNSSize (AvnSize s)
{
NSSize result;
diff --git a/native/Avalonia.Native/src/OSX/window.h b/native/Avalonia.Native/src/OSX/window.h
index 505900d584..ca60914526 100644
--- a/native/Avalonia.Native/src/OSX/window.h
+++ b/native/Avalonia.Native/src/OSX/window.h
@@ -3,7 +3,7 @@
class WindowBaseImpl;
-@interface AvnView : NSView
+@interface AvnView : NSView
-(AvnView* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent;
-(NSEvent* _Nonnull) lastMouseDownEvent;
-(AvnPoint) translateLocalPoint:(AvnPoint)pt;
@@ -19,6 +19,7 @@ class WindowBaseImpl;
-(void) pollModalSession: (NSModalSession _Nonnull) session;
-(void) restoreParentWindow;
-(bool) shouldTryToHandleEvents;
+-(void) setEnabled: (bool) enable;
-(void) showAppMenuOnly;
-(void) showWindowMenuWithAppMenu;
-(void) applyMenu:(NSMenu* _Nullable)menu;
@@ -33,6 +34,10 @@ struct INSWindowHolder
struct IWindowStateChanged
{
virtual void WindowStateChanged () = 0;
+ virtual void StartStateTransition () = 0;
+ virtual void EndStateTransition () = 0;
+ virtual SystemDecorations Decorations () = 0;
+ virtual AvnWindowState WindowState () = 0;
};
#endif /* window_h */
diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm
index 109ed63e6f..fed2176580 100644
--- a/native/Avalonia.Native/src/OSX/window.mm
+++ b/native/Avalonia.Native/src/OSX/window.mm
@@ -382,6 +382,50 @@ public:
*ppv = [renderTarget createSurfaceRenderTarget];
return *ppv == nil ? E_FAIL : S_OK;
}
+
+ virtual HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point,
+ IAvnClipboard* clipboard, IAvnDndResultCallback* cb,
+ void* sourceHandle) override
+ {
+ auto item = TryGetPasteboardItem(clipboard);
+ [item setString:@"" forType:GetAvnCustomDataType()];
+ if(item == nil)
+ return E_INVALIDARG;
+ if(View == NULL)
+ return E_FAIL;
+
+ auto nsevent = [NSApp currentEvent];
+ auto nseventType = [nsevent type];
+
+ // If current event isn't a mouse one (probably due to malfunctioning user app)
+ // attempt to forge a new one
+ if(!((nseventType >= NSEventTypeLeftMouseDown && nseventType <= NSEventTypeMouseExited)
+ || (nseventType >= NSEventTypeOtherMouseDown && nseventType <= NSEventTypeOtherMouseDragged)))
+ {
+ auto nspoint = [Window convertBaseToScreen: ToNSPoint(point)];
+ CGPoint cgpoint = NSPointToCGPoint(nspoint);
+ auto cgevent = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, cgpoint, kCGMouseButtonLeft);
+ nsevent = [NSEvent eventWithCGEvent: cgevent];
+ CFRelease(cgevent);
+ }
+
+ auto dragItem = [[NSDraggingItem alloc] initWithPasteboardWriter: item];
+
+ auto dragItemImage = [NSImage imageNamed:NSImageNameMultipleDocuments];
+ NSRect dragItemRect = {(float)point.X, (float)point.Y, [dragItemImage size].width, [dragItemImage size].height};
+ [dragItem setDraggingFrame: dragItemRect contents: dragItemImage];
+
+ int op = 0; int ieffects = (int)effects;
+ if((ieffects & (int)AvnDragDropEffects::Copy) != 0)
+ op |= NSDragOperationCopy;
+ if((ieffects & (int)AvnDragDropEffects::Link) != 0)
+ op |= NSDragOperationLink;
+ if((ieffects & (int)AvnDragDropEffects::Move) != 0)
+ op |= NSDragOperationMove;
+ [View beginDraggingSessionWithItems: @[dragItem] event: nsevent
+ source: CreateDraggingSource((NSDragOperation) op, cb, sourceHandle)];
+ return S_OK;
+ }
protected:
virtual NSWindowStyleMask GetStyle()
@@ -391,7 +435,7 @@ protected:
void UpdateStyle()
{
- [Window setStyleMask:GetStyle()];
+ [Window setStyleMask: GetStyle()];
}
public:
@@ -404,10 +448,13 @@ public:
class WindowImpl : public virtual WindowBaseImpl, public virtual IAvnWindow, public IWindowStateChanged
{
private:
- bool _canResize = true;
- SystemDecorations _hasDecorations = SystemDecorationsFull;
- CGRect _lastUndecoratedFrame;
+ bool _canResize;
+ bool _fullScreenActive;
+ SystemDecorations _decorations;
AvnWindowState _lastWindowState;
+ bool _inSetWindowState;
+ NSRect _preZoomSize;
+ bool _transitioningWindowState;
FORWARD_IUNKNOWN()
BEGIN_INTERFACE_MAP()
@@ -421,25 +468,54 @@ private:
ComPtr WindowEvents;
WindowImpl(IAvnWindowEvents* events, IAvnGlContext* gl) : WindowBaseImpl(events, gl)
{
+ _fullScreenActive = false;
+ _canResize = true;
+ _decorations = SystemDecorationsFull;
+ _transitioningWindowState = false;
+ _inSetWindowState = false;
_lastWindowState = Normal;
WindowEvents = events;
[Window setCanBecomeKeyAndMain];
[Window disableCursorRects];
+ [Window setTabbingMode:NSWindowTabbingModeDisallowed];
+ }
+
+ void HideOrShowTrafficLights ()
+ {
+ for (id subview in Window.contentView.superview.subviews) {
+ if ([subview isKindOfClass:NSClassFromString(@"NSTitlebarContainerView")]) {
+ NSView *titlebarView = [subview subviews][0];
+ for (id button in titlebarView.subviews) {
+ if ([button isKindOfClass:[NSButton class]]) {
+ [button setHidden: (_decorations != SystemDecorationsFull)];
+ }
+ }
+ }
+ }
}
virtual HRESULT Show () override
{
@autoreleasepool
- {
- if([Window parentWindow] != nil)
- [[Window parentWindow] removeChildWindow:Window];
+ {
WindowBaseImpl::Show();
+ HideOrShowTrafficLights();
+
return SetWindowState(_lastWindowState);
}
}
- virtual HRESULT ShowDialog (IAvnWindow* parent) override
+ virtual HRESULT SetEnabled (bool enable) override
+ {
+ @autoreleasepool
+ {
+ [Window setEnabled:enable];
+ return S_OK;
+ }
+ }
+
+ virtual HRESULT SetParent (IAvnWindow* parent) override
{
@autoreleasepool
{
@@ -451,43 +527,70 @@ private:
return E_INVALIDARG;
[cparent->Window addChildWindow:Window ordered:NSWindowAbove];
- WindowBaseImpl::Show();
+
+ UpdateStyle();
return S_OK;
}
}
+ void StartStateTransition () override
+ {
+ _transitioningWindowState = true;
+ }
+
+ void EndStateTransition () override
+ {
+ _transitioningWindowState = false;
+ }
+
+ SystemDecorations Decorations () override
+ {
+ return _decorations;
+ }
+
+ AvnWindowState WindowState () override
+ {
+ return _lastWindowState;
+ }
+
void WindowStateChanged () override
{
- AvnWindowState state;
- GetWindowState(&state);
- WindowEvents->WindowStateChanged(state);
+ if(!_inSetWindowState && !_transitioningWindowState)
+ {
+ AvnWindowState state;
+ GetWindowState(&state);
+
+ if(_lastWindowState != state)
+ {
+ _lastWindowState = state;
+ WindowEvents->WindowStateChanged(state);
+ }
+ }
}
bool UndecoratedIsMaximized ()
{
- return CGRectEqualToRect([Window frame], [Window screen].visibleFrame);
+ auto windowSize = [Window frame];
+ auto available = [Window screen].visibleFrame;
+ return CGRectEqualToRect(windowSize, available);
}
bool IsZoomed ()
{
- return _hasDecorations != SystemDecorationsNone ? [Window isZoomed] : UndecoratedIsMaximized();
+ return _decorations == SystemDecorationsFull ? [Window isZoomed] : UndecoratedIsMaximized();
}
void DoZoom()
{
- switch (_hasDecorations)
+ switch (_decorations)
{
case SystemDecorationsNone:
- if (!UndecoratedIsMaximized())
- {
- _lastUndecoratedFrame = [Window frame];
- }
-
- [Window zoom:Window];
+ case SystemDecorationsBorderOnly:
+ [Window setFrame:[Window screen].visibleFrame display:true];
break;
- case SystemDecorationsBorderOnly:
+
case SystemDecorationsFull:
[Window performZoom:Window];
break;
@@ -504,25 +607,52 @@ private:
}
}
- virtual HRESULT SetHasDecorations(SystemDecorations value) override
+ virtual HRESULT SetDecorations(SystemDecorations value) override
{
@autoreleasepool
{
- _hasDecorations = value;
+ auto currentWindowState = _lastWindowState;
+ _decorations = value;
+
+ if(_fullScreenActive)
+ {
+ return S_OK;
+ }
+
+ auto currentFrame = [Window frame];
+
UpdateStyle();
+
+ HideOrShowTrafficLights();
- switch (_hasDecorations)
+ switch (_decorations)
{
case SystemDecorationsNone:
[Window setHasShadow:NO];
[Window setTitleVisibility:NSWindowTitleHidden];
[Window setTitlebarAppearsTransparent:YES];
+
+ if(currentWindowState == Maximized)
+ {
+ if(!UndecoratedIsMaximized())
+ {
+ DoZoom();
+ }
+ }
break;
case SystemDecorationsBorderOnly:
[Window setHasShadow:YES];
[Window setTitleVisibility:NSWindowTitleHidden];
[Window setTitlebarAppearsTransparent:YES];
+
+ if(currentWindowState == Maximized)
+ {
+ if(!UndecoratedIsMaximized())
+ {
+ DoZoom();
+ }
+ }
break;
case SystemDecorationsFull:
@@ -530,6 +660,13 @@ private:
[Window setTitleVisibility:NSWindowTitleVisible];
[Window setTitlebarAppearsTransparent:NO];
[Window setTitle:_lastTitle];
+
+ if(currentWindowState == Maximized)
+ {
+ auto newFrame = [Window contentRectForFrameRect:[Window frame]].size;
+
+ [View setFrameSize:newFrame];
+ }
break;
}
@@ -586,13 +723,19 @@ private:
return E_POINTER;
}
+ if(([Window styleMask] & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen)
+ {
+ *ret = FullScreen;
+ return S_OK;
+ }
+
if([Window isMiniaturized])
{
*ret = Minimized;
return S_OK;
}
- if([Window isZoomed])
+ if(IsZoomed())
{
*ret = Maximized;
return S_OK;
@@ -604,16 +747,57 @@ private:
}
}
+ void EnterFullScreenMode ()
+ {
+ _fullScreenActive = true;
+
+ [Window setHasShadow:YES];
+ [Window setTitleVisibility:NSWindowTitleVisible];
+ [Window setTitlebarAppearsTransparent:NO];
+ [Window setTitle:_lastTitle];
+
+ [Window setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskResizable];
+
+ [Window toggleFullScreen:nullptr];
+ }
+
+ void ExitFullScreenMode ()
+ {
+ [Window toggleFullScreen:nullptr];
+
+ _fullScreenActive = false;
+
+ SetDecorations(_decorations);
+ }
+
virtual HRESULT SetWindowState (AvnWindowState state) override
{
@autoreleasepool
{
+ if(_lastWindowState == state)
+ {
+ return S_OK;
+ }
+
+ _inSetWindowState = true;
+
+ auto currentState = _lastWindowState;
_lastWindowState = state;
+ if(currentState == Normal)
+ {
+ _preZoomSize = [Window frame];
+ }
+
if(_shown)
{
switch (state) {
case Maximized:
+ if(currentState == FullScreen)
+ {
+ ExitFullScreenMode();
+ }
+
lastPositionSet.X = 0;
lastPositionSet.Y = 0;
@@ -629,40 +813,66 @@ private:
break;
case Minimized:
- [Window miniaturize:Window];
+ if(currentState == FullScreen)
+ {
+ ExitFullScreenMode();
+ }
+ else
+ {
+ [Window miniaturize:Window];
+ }
+ break;
+
+ case FullScreen:
+ if([Window isMiniaturized])
+ {
+ [Window deminiaturize:Window];
+ }
+
+ EnterFullScreenMode();
break;
- default:
+ case Normal:
if([Window isMiniaturized])
{
[Window deminiaturize:Window];
}
+ if(currentState == FullScreen)
+ {
+ ExitFullScreenMode();
+ }
+
if(IsZoomed())
{
- DoZoom();
+ if(_decorations == SystemDecorationsFull)
+ {
+ DoZoom();
+ }
+ else
+ {
+ [Window setFrame:_preZoomSize display:true];
+ auto newFrame = [Window contentRectForFrameRect:[Window frame]].size;
+
+ [View setFrameSize:newFrame];
+ }
+
}
break;
}
}
+ _inSetWindowState = false;
+
return S_OK;
}
}
virtual void OnResized () override
{
- if(_shown)
+ if(_shown && !_inSetWindowState && !_transitioningWindowState)
{
- auto windowState = [Window isMiniaturized] ? Minimized
- : (IsZoomed() ? Maximized : Normal);
-
- if (windowState != _lastWindowState)
- {
- _lastWindowState = windowState;
-
- WindowEvents->WindowStateChanged(windowState);
- }
+ WindowStateChanged();
}
}
@@ -671,9 +881,10 @@ protected:
{
unsigned long s = NSWindowStyleMaskBorderless;
- switch (_hasDecorations)
+ switch (_decorations)
{
case SystemDecorationsNone:
+ s = s | NSWindowStyleMaskFullSizeContentView;
break;
case SystemDecorationsBorderOnly:
@@ -681,15 +892,19 @@ protected:
break;
case SystemDecorationsFull:
- s = s | NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskBorderless;
+ s = s | NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskBorderless;
+
if(_canResize)
{
s = s | NSWindowStyleMaskResizable;
}
-
break;
}
+ if([Window parentWindow] == nullptr)
+ {
+ s |= NSWindowStyleMaskMiniaturizable;
+ }
return s;
}
};
@@ -745,7 +960,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
_area = nullptr;
_lastPixelSize.Height = 100;
_lastPixelSize.Width = 100;
-
+ [self registerForDraggedTypes: @[@"public.data", GetAvnCustomDataType()]];
return self;
}
@@ -871,15 +1086,28 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
- (bool) ignoreUserInput
{
auto parentWindow = objc_cast([self window]);
+
if(parentWindow == nil || ![parentWindow shouldTryToHandleEvents])
+ {
+ auto window = dynamic_cast(_parent.getRaw());
+
+ if(window != nullptr)
+ {
+ window->WindowEvents->GotInputWhenDisabled();
+ }
+
return TRUE;
+ }
+
return FALSE;
}
- (void)mouseEvent:(NSEvent *)event withType:(AvnRawMouseEventType) type
{
if([self ignoreUserInput])
+ {
return;
+ }
[self becomeFirstResponder];
auto localPoint = [self convertPoint:[event locationInWindow] toView:self];
@@ -1024,7 +1252,10 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
- (void) keyboardEvent: (NSEvent *) event withType: (AvnRawKeyEventType)type
{
if([self ignoreUserInput])
+ {
return;
+ }
+
auto key = s_KeyMap[[event keyCode]];
auto timestamp = [event timestamp] * 1000;
@@ -1136,6 +1367,68 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
return result;
}
+
+- (NSDragOperation)triggerAvnDragEvent: (AvnDragEventType) type info: (id )info
+{
+ auto localPoint = [self convertPoint:[info draggingLocation] toView:self];
+ auto avnPoint = [self toAvnPoint:localPoint];
+ auto point = [self translateLocalPoint:avnPoint];
+ auto modifiers = [self getModifiers:[[NSApp currentEvent] modifierFlags]];
+ NSDragOperation nsop = [info draggingSourceOperationMask];
+
+ auto effects = ConvertDragDropEffects(nsop);
+ int reffects = (int)_parent->BaseEvents
+ ->DragEvent(type, point, modifiers, effects,
+ CreateClipboard([info draggingPasteboard], nil),
+ GetAvnDataObjectHandleFromDraggingInfo(info));
+
+ NSDragOperation ret = 0;
+
+ // Ensure that the managed part didn't add any new effects
+ reffects = (int)effects & (int)reffects;
+
+ // OSX requires exactly one operation
+ if((reffects & (int)AvnDragDropEffects::Copy) != 0)
+ ret = NSDragOperationCopy;
+ else if((reffects & (int)AvnDragDropEffects::Move) != 0)
+ ret = NSDragOperationMove;
+ else if((reffects & (int)AvnDragDropEffects::Link) != 0)
+ ret = NSDragOperationLink;
+ if(ret == 0)
+ ret = NSDragOperationNone;
+ return ret;
+}
+
+- (NSDragOperation)draggingEntered:(id )sender
+{
+ return [self triggerAvnDragEvent: AvnDragEventType::Enter info:sender];
+}
+
+- (NSDragOperation)draggingUpdated:(id )sender
+{
+ return [self triggerAvnDragEvent: AvnDragEventType::Over info:sender];
+}
+
+- (void)draggingExited:(id )sender
+{
+ [self triggerAvnDragEvent: AvnDragEventType::Leave info:sender];
+}
+
+- (BOOL)prepareForDragOperation:(id )sender
+{
+ return [self triggerAvnDragEvent: AvnDragEventType::Over info:sender] != NSDragOperationNone;
+}
+
+- (BOOL)performDragOperation:(id )sender
+{
+ return [self triggerAvnDragEvent: AvnDragEventType::Drop info:sender] != NSDragOperationNone;
+}
+
+- (void)concludeDragOperation:(nullable id )sender
+{
+
+}
+
@end
@@ -1144,6 +1437,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
ComPtr _parent;
bool _canBecomeKeyAndMain;
bool _closed;
+ bool _isEnabled;
AvnMenu* _menu;
double _lastScaling;
}
@@ -1164,6 +1458,20 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
}
}
+- (void)performClose:(id)sender
+{
+ if([[self delegate] respondsToSelector:@selector(windowShouldClose:)])
+ {
+ if(![[self delegate] windowShouldClose:self]) return;
+ }
+ else if([self respondsToSelector:@selector(windowShouldClose:)])
+ {
+ if(![self windowShouldClose:self]) return;
+ }
+
+ [self close];
+}
+
- (void)pollModalSession:(nonnull NSModalSession)session
{
auto response = [NSApp runModalSession:session];
@@ -1251,6 +1559,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
_parent = parent;
[self setDelegate:self];
_closed = false;
+ _isEnabled = true;
_lastScaling = [self backingScaleFactor];
[self setOpaque:NO];
@@ -1317,14 +1626,12 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
-(bool)shouldTryToHandleEvents
{
- for(NSWindow* uch in [self childWindows])
- {
- auto ch = objc_cast(uch);
- if(ch == nil)
- continue;
- return FALSE;
- }
- return TRUE;
+ return _isEnabled;
+}
+
+-(void) setEnabled:(bool)enable
+{
+ _isEnabled = enable;
}
-(void)makeKeyWindow
@@ -1378,7 +1685,66 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
- (void)windowDidResize:(NSNotification *)notification
{
- _parent->OnResized();
+ auto parent = dynamic_cast(_parent.operator->());
+
+ if(parent != nullptr)
+ {
+ parent->WindowStateChanged();
+ }
+}
+
+- (void)windowWillExitFullScreen:(NSNotification *)notification
+{
+ auto parent = dynamic_cast(_parent.operator->());
+
+ if(parent != nullptr)
+ {
+ parent->StartStateTransition();
+ }
+}
+
+- (void)windowDidExitFullScreen:(NSNotification *)notification
+{
+ auto parent = dynamic_cast(_parent.operator->());
+
+ if(parent != nullptr)
+ {
+ parent->EndStateTransition();
+
+ if(parent->Decorations() != SystemDecorationsFull && parent->WindowState() == Maximized)
+ {
+ NSRect screenRect = [[self screen] visibleFrame];
+ [self setFrame:screenRect display:YES];
+ }
+
+ if(parent->WindowState() == Minimized)
+ {
+ [self miniaturize:nullptr];
+ }
+
+ parent->WindowStateChanged();
+ }
+}
+
+- (void)windowWillEnterFullScreen:(NSNotification *)notification
+{
+ auto parent = dynamic_cast(_parent.operator->());
+
+ if(parent != nullptr)
+ {
+ parent->StartStateTransition();
+ }
+}
+
+- (void)windowDidEnterFullScreen:(NSNotification *)notification
+{
+ auto parent = dynamic_cast(_parent.operator->());
+
+ if(parent != nullptr)
+ {
+ parent->EndStateTransition();
+ parent->WindowStateChanged();
+ }
}
- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame
diff --git a/nukebuild/Build.cs b/nukebuild/Build.cs
index 358846a14e..5460dc7720 100644
--- a/nukebuild/Build.cs
+++ b/nukebuild/Build.cs
@@ -12,6 +12,7 @@ using Nuke.Common.ProjectModel;
using Nuke.Common.Tooling;
using Nuke.Common.Tools.DotNet;
using Nuke.Common.Tools.MSBuild;
+using Nuke.Common.Tools.Npm;
using Nuke.Common.Utilities;
using Nuke.Common.Utilities.Collections;
using static Nuke.Common.EnvironmentInfo;
@@ -121,8 +122,21 @@ partial class Build : NukeBuild
EnsureCleanDirectory(Parameters.TestResultsRoot);
});
+ Target CompileHtmlPreviewer => _ => _
+ .DependsOn(Clean)
+ .Executes(() =>
+ {
+ var webappDir = RootDirectory / "src" / "Avalonia.DesignerSupport" / "Remote" / "HtmlTransport" / "webapp";
+
+ NpmTasks.NpmInstall(c => c.SetWorkingDirectory(webappDir));
+ NpmTasks.NpmRun(c => c
+ .SetWorkingDirectory(webappDir)
+ .SetCommand("dist"));
+ });
+
Target Compile => _ => _
.DependsOn(Clean)
+ .DependsOn(CompileHtmlPreviewer)
.Executes(() =>
{
if (Parameters.IsRunningOnWindows)
diff --git a/packages/Avalonia/AvaloniaBuildTasks.targets b/packages/Avalonia/AvaloniaBuildTasks.targets
index 552713f94b..537495fcad 100644
--- a/packages/Avalonia/AvaloniaBuildTasks.targets
+++ b/packages/Avalonia/AvaloniaBuildTasks.targets
@@ -2,6 +2,7 @@
<_AvaloniaUseExternalMSBuild>$(AvaloniaUseExternalMSBuild)
<_AvaloniaUseExternalMSBuild Condition="'$(_AvaloniaForceInternalMSBuild)' == 'true'">false
+ low
+ EmbeddedResources="@(EmbeddedResources)"
+ ReportImportance="$(AvaloniaXamlReportImportance)"/>
@@ -67,6 +69,7 @@
OriginalCopyPath="$(AvaloniaXamlOriginalCopyFilePath)"
ProjectDirectory="$(MSBuildProjectDirectory)"
VerifyIl="$(AvaloniaXamlIlVerifyIl)"
+ ReportImportance="$(AvaloniaXamlReportImportance)"
/>
-
+
-
+
diff --git a/samples/BindingDemo/ViewModels/MainWindowViewModel.cs b/samples/BindingDemo/ViewModels/MainWindowViewModel.cs
index 22d01e0765..a66038ff3e 100644
--- a/samples/BindingDemo/ViewModels/MainWindowViewModel.cs
+++ b/samples/BindingDemo/ViewModels/MainWindowViewModel.cs
@@ -6,6 +6,7 @@ using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Threading;
using ReactiveUI;
+using Avalonia.Controls;
namespace BindingDemo.ViewModels
{
@@ -27,7 +28,7 @@ namespace BindingDemo.ViewModels
Detail = "Item " + x + " details",
}));
- SelectedItems = new ObservableCollection();
+ Selection = new SelectionModel();
ShuffleItems = ReactiveCommand.Create(() =>
{
@@ -56,7 +57,7 @@ namespace BindingDemo.ViewModels
}
public ObservableCollection Items { get; }
- public ObservableCollection SelectedItems { get; }
+ public SelectionModel Selection { get; }
public ReactiveCommand ShuffleItems { get; }
public string BooleanString
diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs
index 854cae484c..2a5294cacc 100644
--- a/samples/ControlCatalog.NetCore/Program.cs
+++ b/samples/ControlCatalog.NetCore/Program.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
@@ -6,6 +7,7 @@ using System.Threading;
using Avalonia;
using Avalonia.ReactiveUI;
using Avalonia.Dialogs;
+using Avalonia.OpenGL;
namespace ControlCatalog.NetCore
{
diff --git a/samples/ControlCatalog/ControlCatalog.csproj b/samples/ControlCatalog/ControlCatalog.csproj
index 11c0a4fa68..34a6e33677 100644
--- a/samples/ControlCatalog/ControlCatalog.csproj
+++ b/samples/ControlCatalog/ControlCatalog.csproj
@@ -1,6 +1,7 @@
- netstandard2.0
+ netstandard2.0
+ true
@@ -17,6 +18,7 @@
+
diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml
index f3f70719e3..30671ef083 100644
--- a/samples/ControlCatalog/MainView.xaml
+++ b/samples/ControlCatalog/MainView.xaml
@@ -47,6 +47,7 @@
+
@@ -59,8 +60,8 @@
-
-
+
+
No Decorations
Border Only
Full Decorations
@@ -69,6 +70,7 @@
Light
Dark
+
diff --git a/samples/ControlCatalog/MainWindow.xaml b/samples/ControlCatalog/MainWindow.xaml
index bea751ad4c..935db20757 100644
--- a/samples/ControlCatalog/MainWindow.xaml
+++ b/samples/ControlCatalog/MainWindow.xaml
@@ -7,7 +7,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:ControlCatalog.ViewModels"
xmlns:v="clr-namespace:ControlCatalog.Views"
- x:Class="ControlCatalog.MainWindow">
+ x:Class="ControlCatalog.MainWindow" WindowState="{Binding WindowState, Mode=TwoWay}">
diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml b/samples/ControlCatalog/Pages/DialogsPage.xaml
index 1ed5c0cbfd..0834e829d8 100644
--- a/samples/ControlCatalog/Pages/DialogsPage.xaml
+++ b/samples/ControlCatalog/Pages/DialogsPage.xaml
@@ -6,6 +6,7 @@
+
diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
index ba1921a185..dcb94a89e7 100644
--- a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Avalonia.Controls;
+using Avalonia.Dialogs;
using Avalonia.Markup.Xaml;
#pragma warning disable 4014
@@ -58,6 +59,19 @@ namespace ControlCatalog.Pages
Title = "Select folder",
}.ShowAsync(GetWindow());
};
+ this.FindControl