96 changed files with 7564 additions and 300 deletions
@ -1,5 +1,5 @@ |
|||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<ItemGroup> |
<ItemGroup> |
||||
<PackageReference Include="reactiveui" Version="8.7.1" /> |
<PackageReference Include="reactiveui" Version="9.0.1" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
</Project> |
</Project> |
||||
|
|||||
@ -0,0 +1,98 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Avalonia.Input.Platform |
||||
|
{ |
||||
|
public class PlatformHotkeyConfiguration |
||||
|
{ |
||||
|
public PlatformHotkeyConfiguration() : this(InputModifiers.Control) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public PlatformHotkeyConfiguration(InputModifiers commandModifiers, |
||||
|
InputModifiers selectionModifiers = InputModifiers.Shift, |
||||
|
InputModifiers wholeWordTextActionModifiers = InputModifiers.Control) |
||||
|
{ |
||||
|
CommandModifiers = commandModifiers; |
||||
|
SelectionModifiers = selectionModifiers; |
||||
|
WholeWordTextActionModifiers = wholeWordTextActionModifiers; |
||||
|
Copy = new List<KeyGesture> |
||||
|
{ |
||||
|
new KeyGesture(Key.C, commandModifiers) |
||||
|
}; |
||||
|
Cut = new List<KeyGesture> |
||||
|
{ |
||||
|
new KeyGesture(Key.X, commandModifiers) |
||||
|
}; |
||||
|
Paste = new List<KeyGesture> |
||||
|
{ |
||||
|
new KeyGesture(Key.V, commandModifiers) |
||||
|
}; |
||||
|
Undo = new List<KeyGesture> |
||||
|
{ |
||||
|
new KeyGesture(Key.Z, commandModifiers) |
||||
|
}; |
||||
|
Redo = new List<KeyGesture> |
||||
|
{ |
||||
|
new KeyGesture(Key.Y, commandModifiers), |
||||
|
new KeyGesture(Key.Z, commandModifiers | selectionModifiers) |
||||
|
}; |
||||
|
SelectAll = new List<KeyGesture> |
||||
|
{ |
||||
|
new KeyGesture(Key.A, commandModifiers) |
||||
|
}; |
||||
|
MoveCursorToTheStartOfLine = new List<KeyGesture> |
||||
|
{ |
||||
|
new KeyGesture(Key.Home) |
||||
|
}; |
||||
|
MoveCursorToTheEndOfLine = new List<KeyGesture> |
||||
|
{ |
||||
|
new KeyGesture(Key.End) |
||||
|
}; |
||||
|
MoveCursorToTheStartOfDocument = new List<KeyGesture> |
||||
|
{ |
||||
|
new KeyGesture(Key.Home, commandModifiers) |
||||
|
}; |
||||
|
MoveCursorToTheEndOfDocument = new List<KeyGesture> |
||||
|
{ |
||||
|
new KeyGesture(Key.End, commandModifiers) |
||||
|
}; |
||||
|
MoveCursorToTheStartOfLineWithSelection = new List<KeyGesture> |
||||
|
{ |
||||
|
new KeyGesture(Key.Home, selectionModifiers) |
||||
|
}; |
||||
|
MoveCursorToTheEndOfLineWithSelection = new List<KeyGesture> |
||||
|
{ |
||||
|
new KeyGesture(Key.End, selectionModifiers) |
||||
|
}; |
||||
|
MoveCursorToTheStartOfDocumentWithSelection = new List<KeyGesture> |
||||
|
{ |
||||
|
new KeyGesture(Key.Home, commandModifiers | selectionModifiers) |
||||
|
}; |
||||
|
MoveCursorToTheEndOfDocumentWithSelection = new List<KeyGesture> |
||||
|
{ |
||||
|
new KeyGesture(Key.End, commandModifiers | selectionModifiers) |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
public InputModifiers CommandModifiers { get; set; } |
||||
|
public InputModifiers WholeWordTextActionModifiers { get; set; } |
||||
|
public InputModifiers SelectionModifiers { get; set; } |
||||
|
public List<KeyGesture> Copy { get; set; } |
||||
|
public List<KeyGesture> Cut { get; set; } |
||||
|
public List<KeyGesture> Paste { get; set; } |
||||
|
public List<KeyGesture> Undo { get; set; } |
||||
|
public List<KeyGesture> Redo { get; set; } |
||||
|
public List<KeyGesture> SelectAll { get; set; } |
||||
|
public List<KeyGesture> MoveCursorToTheStartOfLine { get; set; } |
||||
|
public List<KeyGesture> MoveCursorToTheEndOfLine { get; set; } |
||||
|
public List<KeyGesture> MoveCursorToTheStartOfDocument { get; set; } |
||||
|
public List<KeyGesture> MoveCursorToTheEndOfDocument { get; set; } |
||||
|
public List<KeyGesture> MoveCursorToTheStartOfLineWithSelection { get; set; } |
||||
|
public List<KeyGesture> MoveCursorToTheEndOfLineWithSelection { get; set; } |
||||
|
public List<KeyGesture> MoveCursorToTheStartOfDocumentWithSelection { get; set; } |
||||
|
public List<KeyGesture> MoveCursorToTheEndOfDocumentWithSelection { get; set; } |
||||
|
|
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,4 @@ |
|||||
|
build |
||||
|
|
||||
|
Avalonia.Native.OSX.xcodeproj/xcuserdata |
||||
|
Avalonia.Native.OSX.xcodeproj/project.xcworkspace/xcuserdata |
||||
@ -0,0 +1,328 @@ |
|||||
|
// !$*UTF8*$! |
||||
|
{ |
||||
|
archiveVersion = 1; |
||||
|
classes = { |
||||
|
}; |
||||
|
objectVersion = 46; |
||||
|
objects = { |
||||
|
|
||||
|
/* Begin PBXBuildFile section */ |
||||
|
37A517B32159597E00FBA241 /* Screens.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37A517B22159597E00FBA241 /* Screens.mm */; }; |
||||
|
37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37C09D8721580FE4006A6758 /* SystemDialogs.mm */; }; |
||||
|
37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37E2330E21583241000CB7E2 /* KeyTransform.mm */; }; |
||||
|
5B21A982216530F500CEE36E /* cursor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B21A981216530F500CEE36E /* cursor.mm */; }; |
||||
|
5B8BD94F215BFEA6005ED2A7 /* clipboard.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */; }; |
||||
|
AB00E4F72147CA920032A60A /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB00E4F62147CA920032A60A /* main.mm */; }; |
||||
|
AB1E522C217613570091CD71 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB1E522B217613570091CD71 /* OpenGL.framework */; }; |
||||
|
AB573DC4217605E400D389A2 /* gl.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB573DC3217605E400D389A2 /* gl.mm */; }; |
||||
|
AB661C1E2148230F00291242 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB661C1D2148230F00291242 /* AppKit.framework */; }; |
||||
|
AB661C202148286E00291242 /* window.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB661C1F2148286E00291242 /* window.mm */; }; |
||||
|
AB8F7D6B21482D7F0057DBA5 /* platformthreading.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */; }; |
||||
|
/* End PBXBuildFile section */ |
||||
|
|
||||
|
/* Begin PBXFileReference section */ |
||||
|
379860FE214DA0C000CD0246 /* KeyTransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyTransform.h; sourceTree = "<group>"; }; |
||||
|
37A4E71A2178846A00EACBCD /* headers */ = {isa = PBXFileReference; lastKnownFileType = folder; name = headers; path = ../Avalonia.Native/headers; sourceTree = "<group>"; }; |
||||
|
37A517B22159597E00FBA241 /* Screens.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Screens.mm; sourceTree = "<group>"; }; |
||||
|
37C09D8721580FE4006A6758 /* SystemDialogs.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SystemDialogs.mm; sourceTree = "<group>"; }; |
||||
|
37C09D8A21581EF2006A6758 /* window.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = window.h; sourceTree = "<group>"; }; |
||||
|
37E2330E21583241000CB7E2 /* KeyTransform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyTransform.mm; sourceTree = "<group>"; }; |
||||
|
5B21A981216530F500CEE36E /* cursor.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = cursor.mm; sourceTree = "<group>"; }; |
||||
|
5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = clipboard.mm; sourceTree = "<group>"; }; |
||||
|
5BF943652167AD1D009CAE35 /* cursor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cursor.h; sourceTree = "<group>"; }; |
||||
|
AB00E4F62147CA920032A60A /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; }; |
||||
|
AB1E522B217613570091CD71 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; |
||||
|
AB573DC3217605E400D389A2 /* gl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = gl.mm; sourceTree = "<group>"; }; |
||||
|
AB661C1D2148230F00291242 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; |
||||
|
AB661C1F2148286E00291242 /* window.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = window.mm; sourceTree = "<group>"; }; |
||||
|
AB661C212148288600291242 /* common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = "<group>"; }; |
||||
|
AB7A61EF2147C815003C5833 /* libAvalonia.Native.OSX.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libAvalonia.Native.OSX.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; |
||||
|
AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = platformthreading.mm; sourceTree = "<group>"; }; |
||||
|
/* End PBXFileReference section */ |
||||
|
|
||||
|
/* Begin PBXFrameworksBuildPhase section */ |
||||
|
AB7A61EC2147C814003C5833 /* Frameworks */ = { |
||||
|
isa = PBXFrameworksBuildPhase; |
||||
|
buildActionMask = 2147483647; |
||||
|
files = ( |
||||
|
AB1E522C217613570091CD71 /* OpenGL.framework in Frameworks */, |
||||
|
AB661C1E2148230F00291242 /* AppKit.framework in Frameworks */, |
||||
|
); |
||||
|
runOnlyForDeploymentPostprocessing = 0; |
||||
|
}; |
||||
|
/* End PBXFrameworksBuildPhase section */ |
||||
|
|
||||
|
/* Begin PBXGroup section */ |
||||
|
AB661C1C2148230E00291242 /* Frameworks */ = { |
||||
|
isa = PBXGroup; |
||||
|
children = ( |
||||
|
AB1E522B217613570091CD71 /* OpenGL.framework */, |
||||
|
AB661C1D2148230F00291242 /* AppKit.framework */, |
||||
|
); |
||||
|
name = Frameworks; |
||||
|
sourceTree = "<group>"; |
||||
|
}; |
||||
|
AB7A61E62147C814003C5833 = { |
||||
|
isa = PBXGroup; |
||||
|
children = ( |
||||
|
37A4E71A2178846A00EACBCD /* headers */, |
||||
|
AB573DC3217605E400D389A2 /* gl.mm */, |
||||
|
5BF943652167AD1D009CAE35 /* cursor.h */, |
||||
|
5B21A981216530F500CEE36E /* cursor.mm */, |
||||
|
5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */, |
||||
|
AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */, |
||||
|
AB661C212148288600291242 /* common.h */, |
||||
|
379860FE214DA0C000CD0246 /* KeyTransform.h */, |
||||
|
37E2330E21583241000CB7E2 /* KeyTransform.mm */, |
||||
|
AB661C1F2148286E00291242 /* window.mm */, |
||||
|
37C09D8A21581EF2006A6758 /* window.h */, |
||||
|
AB00E4F62147CA920032A60A /* main.mm */, |
||||
|
37A517B22159597E00FBA241 /* Screens.mm */, |
||||
|
37C09D8721580FE4006A6758 /* SystemDialogs.mm */, |
||||
|
AB7A61F02147C815003C5833 /* Products */, |
||||
|
AB661C1C2148230E00291242 /* Frameworks */, |
||||
|
); |
||||
|
sourceTree = "<group>"; |
||||
|
}; |
||||
|
AB7A61F02147C815003C5833 /* Products */ = { |
||||
|
isa = PBXGroup; |
||||
|
children = ( |
||||
|
AB7A61EF2147C815003C5833 /* libAvalonia.Native.OSX.dylib */, |
||||
|
); |
||||
|
name = Products; |
||||
|
sourceTree = "<group>"; |
||||
|
}; |
||||
|
/* End PBXGroup section */ |
||||
|
|
||||
|
/* Begin PBXHeadersBuildPhase section */ |
||||
|
AB7A61ED2147C814003C5833 /* Headers */ = { |
||||
|
isa = PBXHeadersBuildPhase; |
||||
|
buildActionMask = 2147483647; |
||||
|
files = ( |
||||
|
); |
||||
|
runOnlyForDeploymentPostprocessing = 0; |
||||
|
}; |
||||
|
/* End PBXHeadersBuildPhase section */ |
||||
|
|
||||
|
/* Begin PBXNativeTarget section */ |
||||
|
AB7A61EE2147C814003C5833 /* Avalonia.Native.OSX */ = { |
||||
|
isa = PBXNativeTarget; |
||||
|
buildConfigurationList = AB7A61F82147C815003C5833 /* Build configuration list for PBXNativeTarget "Avalonia.Native.OSX" */; |
||||
|
buildPhases = ( |
||||
|
AB7A61EB2147C814003C5833 /* Sources */, |
||||
|
AB7A61EC2147C814003C5833 /* Frameworks */, |
||||
|
AB7A61ED2147C814003C5833 /* Headers */, |
||||
|
); |
||||
|
buildRules = ( |
||||
|
); |
||||
|
dependencies = ( |
||||
|
); |
||||
|
name = Avalonia.Native.OSX; |
||||
|
productName = Avalonia.Native.OSX; |
||||
|
productReference = AB7A61EF2147C815003C5833 /* libAvalonia.Native.OSX.dylib */; |
||||
|
productType = "com.apple.product-type.library.dynamic"; |
||||
|
}; |
||||
|
/* End PBXNativeTarget section */ |
||||
|
|
||||
|
/* Begin PBXProject section */ |
||||
|
AB7A61E72147C814003C5833 /* Project object */ = { |
||||
|
isa = PBXProject; |
||||
|
attributes = { |
||||
|
LastUpgradeCheck = 1000; |
||||
|
ORGANIZATIONNAME = Avalonia; |
||||
|
TargetAttributes = { |
||||
|
AB7A61EE2147C814003C5833 = { |
||||
|
CreatedOnToolsVersion = 8.3.2; |
||||
|
ProvisioningStyle = Automatic; |
||||
|
}; |
||||
|
}; |
||||
|
}; |
||||
|
buildConfigurationList = AB7A61EA2147C814003C5833 /* Build configuration list for PBXProject "Avalonia.Native.OSX" */; |
||||
|
compatibilityVersion = "Xcode 3.2"; |
||||
|
developmentRegion = English; |
||||
|
hasScannedForEncodings = 0; |
||||
|
knownRegions = ( |
||||
|
en, |
||||
|
); |
||||
|
mainGroup = AB7A61E62147C814003C5833; |
||||
|
productRefGroup = AB7A61F02147C815003C5833 /* Products */; |
||||
|
projectDirPath = ""; |
||||
|
projectRoot = ""; |
||||
|
targets = ( |
||||
|
AB7A61EE2147C814003C5833 /* Avalonia.Native.OSX */, |
||||
|
); |
||||
|
}; |
||||
|
/* End PBXProject section */ |
||||
|
|
||||
|
/* Begin PBXSourcesBuildPhase section */ |
||||
|
AB7A61EB2147C814003C5833 /* Sources */ = { |
||||
|
isa = PBXSourcesBuildPhase; |
||||
|
buildActionMask = 2147483647; |
||||
|
files = ( |
||||
|
5B8BD94F215BFEA6005ED2A7 /* clipboard.mm in Sources */, |
||||
|
5B21A982216530F500CEE36E /* cursor.mm in Sources */, |
||||
|
AB8F7D6B21482D7F0057DBA5 /* platformthreading.mm in Sources */, |
||||
|
37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */, |
||||
|
37A517B32159597E00FBA241 /* Screens.mm in Sources */, |
||||
|
AB00E4F72147CA920032A60A /* main.mm in Sources */, |
||||
|
37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */, |
||||
|
AB573DC4217605E400D389A2 /* gl.mm in Sources */, |
||||
|
AB661C202148286E00291242 /* window.mm in Sources */, |
||||
|
); |
||||
|
runOnlyForDeploymentPostprocessing = 0; |
||||
|
}; |
||||
|
/* End PBXSourcesBuildPhase section */ |
||||
|
|
||||
|
/* Begin XCBuildConfiguration section */ |
||||
|
AB7A61F62147C815003C5833 /* Debug */ = { |
||||
|
isa = XCBuildConfiguration; |
||||
|
buildSettings = { |
||||
|
ALWAYS_SEARCH_USER_PATHS = NO; |
||||
|
CLANG_ANALYZER_NONNULL = YES; |
||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; |
||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; |
||||
|
CLANG_CXX_LIBRARY = "libc++"; |
||||
|
CLANG_ENABLE_MODULES = YES; |
||||
|
CLANG_ENABLE_OBJC_ARC = YES; |
||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; |
||||
|
CLANG_WARN_BOOL_CONVERSION = YES; |
||||
|
CLANG_WARN_COMMA = YES; |
||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES; |
||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; |
||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; |
||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES; |
||||
|
CLANG_WARN_EMPTY_BODY = YES; |
||||
|
CLANG_WARN_ENUM_CONVERSION = YES; |
||||
|
CLANG_WARN_INFINITE_RECURSION = YES; |
||||
|
CLANG_WARN_INT_CONVERSION = YES; |
||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; |
||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; |
||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; |
||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; |
||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; |
||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES; |
||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES; |
||||
|
CLANG_WARN_UNREACHABLE_CODE = YES; |
||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; |
||||
|
CODE_SIGN_IDENTITY = "-"; |
||||
|
COPY_PHASE_STRIP = NO; |
||||
|
DEBUG_INFORMATION_FORMAT = dwarf; |
||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES; |
||||
|
ENABLE_TESTABILITY = YES; |
||||
|
GCC_C_LANGUAGE_STANDARD = gnu99; |
||||
|
GCC_DYNAMIC_NO_PIC = NO; |
||||
|
GCC_NO_COMMON_BLOCKS = YES; |
||||
|
GCC_OPTIMIZATION_LEVEL = 0; |
||||
|
GCC_PREPROCESSOR_DEFINITIONS = ( |
||||
|
"DEBUG=1", |
||||
|
"$(inherited)", |
||||
|
); |
||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES; |
||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; |
||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES; |
||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; |
||||
|
GCC_WARN_UNUSED_FUNCTION = YES; |
||||
|
GCC_WARN_UNUSED_VARIABLE = YES; |
||||
|
MACOSX_DEPLOYMENT_TARGET = 10.12; |
||||
|
MTL_ENABLE_DEBUG_INFO = YES; |
||||
|
ONLY_ACTIVE_ARCH = YES; |
||||
|
SDKROOT = macosx; |
||||
|
}; |
||||
|
name = Debug; |
||||
|
}; |
||||
|
AB7A61F72147C815003C5833 /* Release */ = { |
||||
|
isa = XCBuildConfiguration; |
||||
|
buildSettings = { |
||||
|
ALWAYS_SEARCH_USER_PATHS = NO; |
||||
|
CLANG_ANALYZER_NONNULL = YES; |
||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; |
||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; |
||||
|
CLANG_CXX_LIBRARY = "libc++"; |
||||
|
CLANG_ENABLE_MODULES = YES; |
||||
|
CLANG_ENABLE_OBJC_ARC = YES; |
||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; |
||||
|
CLANG_WARN_BOOL_CONVERSION = YES; |
||||
|
CLANG_WARN_COMMA = YES; |
||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES; |
||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; |
||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; |
||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES; |
||||
|
CLANG_WARN_EMPTY_BODY = YES; |
||||
|
CLANG_WARN_ENUM_CONVERSION = YES; |
||||
|
CLANG_WARN_INFINITE_RECURSION = YES; |
||||
|
CLANG_WARN_INT_CONVERSION = YES; |
||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; |
||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; |
||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; |
||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; |
||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; |
||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES; |
||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES; |
||||
|
CLANG_WARN_UNREACHABLE_CODE = YES; |
||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; |
||||
|
CODE_SIGN_IDENTITY = "-"; |
||||
|
COPY_PHASE_STRIP = NO; |
||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; |
||||
|
ENABLE_NS_ASSERTIONS = NO; |
||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES; |
||||
|
GCC_C_LANGUAGE_STANDARD = gnu99; |
||||
|
GCC_NO_COMMON_BLOCKS = YES; |
||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES; |
||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; |
||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES; |
||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; |
||||
|
GCC_WARN_UNUSED_FUNCTION = YES; |
||||
|
GCC_WARN_UNUSED_VARIABLE = YES; |
||||
|
MACOSX_DEPLOYMENT_TARGET = 10.12; |
||||
|
MTL_ENABLE_DEBUG_INFO = NO; |
||||
|
SDKROOT = macosx; |
||||
|
}; |
||||
|
name = Release; |
||||
|
}; |
||||
|
AB7A61F92147C815003C5833 /* Debug */ = { |
||||
|
isa = XCBuildConfiguration; |
||||
|
buildSettings = { |
||||
|
DYLIB_COMPATIBILITY_VERSION = 1; |
||||
|
DYLIB_CURRENT_VERSION = 1; |
||||
|
EXECUTABLE_PREFIX = lib; |
||||
|
HEADER_SEARCH_PATHS = ../Avalonia.Native/headers; |
||||
|
PRODUCT_NAME = "$(TARGET_NAME)"; |
||||
|
}; |
||||
|
name = Debug; |
||||
|
}; |
||||
|
AB7A61FA2147C815003C5833 /* Release */ = { |
||||
|
isa = XCBuildConfiguration; |
||||
|
buildSettings = { |
||||
|
DYLIB_COMPATIBILITY_VERSION = 1; |
||||
|
DYLIB_CURRENT_VERSION = 1; |
||||
|
EXECUTABLE_PREFIX = lib; |
||||
|
HEADER_SEARCH_PATHS = ../Avalonia.Native/headers; |
||||
|
PRODUCT_NAME = "$(TARGET_NAME)"; |
||||
|
}; |
||||
|
name = Release; |
||||
|
}; |
||||
|
/* End XCBuildConfiguration section */ |
||||
|
|
||||
|
/* Begin XCConfigurationList section */ |
||||
|
AB7A61EA2147C814003C5833 /* Build configuration list for PBXProject "Avalonia.Native.OSX" */ = { |
||||
|
isa = XCConfigurationList; |
||||
|
buildConfigurations = ( |
||||
|
AB7A61F62147C815003C5833 /* Debug */, |
||||
|
AB7A61F72147C815003C5833 /* Release */, |
||||
|
); |
||||
|
defaultConfigurationIsVisible = 0; |
||||
|
defaultConfigurationName = Release; |
||||
|
}; |
||||
|
AB7A61F82147C815003C5833 /* Build configuration list for PBXNativeTarget "Avalonia.Native.OSX" */ = { |
||||
|
isa = XCConfigurationList; |
||||
|
buildConfigurations = ( |
||||
|
AB7A61F92147C815003C5833 /* Debug */, |
||||
|
AB7A61FA2147C815003C5833 /* Release */, |
||||
|
); |
||||
|
defaultConfigurationIsVisible = 0; |
||||
|
defaultConfigurationName = Release; |
||||
|
}; |
||||
|
/* End XCConfigurationList section */ |
||||
|
}; |
||||
|
rootObject = AB7A61E72147C814003C5833 /* Project object */; |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<Workspace |
||||
|
version = "1.0"> |
||||
|
<FileRef |
||||
|
location = "self:Avalonia.Native.OSX.xcodeproj"> |
||||
|
</FileRef> |
||||
|
</Workspace> |
||||
@ -0,0 +1,91 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<Scheme |
||||
|
LastUpgradeVersion = "1000" |
||||
|
version = "1.3"> |
||||
|
<BuildAction |
||||
|
parallelizeBuildables = "YES" |
||||
|
buildImplicitDependencies = "YES"> |
||||
|
<BuildActionEntries> |
||||
|
<BuildActionEntry |
||||
|
buildForTesting = "YES" |
||||
|
buildForRunning = "YES" |
||||
|
buildForProfiling = "YES" |
||||
|
buildForArchiving = "YES" |
||||
|
buildForAnalyzing = "YES"> |
||||
|
<BuildableReference |
||||
|
BuildableIdentifier = "primary" |
||||
|
BlueprintIdentifier = "AB7A61EE2147C814003C5833" |
||||
|
BuildableName = "libAvalonia.Native.OSX.dylib" |
||||
|
BlueprintName = "Avalonia.Native.OSX" |
||||
|
ReferencedContainer = "container:Avalonia.Native.OSX.xcodeproj"> |
||||
|
</BuildableReference> |
||||
|
</BuildActionEntry> |
||||
|
</BuildActionEntries> |
||||
|
</BuildAction> |
||||
|
<TestAction |
||||
|
buildConfiguration = "Debug" |
||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
||||
|
shouldUseLaunchSchemeArgsEnv = "YES"> |
||||
|
<Testables> |
||||
|
</Testables> |
||||
|
<AdditionalOptions> |
||||
|
</AdditionalOptions> |
||||
|
</TestAction> |
||||
|
<LaunchAction |
||||
|
buildConfiguration = "Debug" |
||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
||||
|
launchStyle = "0" |
||||
|
useCustomWorkingDirectory = "YES" |
||||
|
customWorkingDirectory = "$PROJECT_DIR/../../samples/ControlCatalog" |
||||
|
ignoresPersistentStateOnLaunch = "NO" |
||||
|
debugDocumentVersioning = "YES" |
||||
|
debugServiceExtension = "internal" |
||||
|
allowLocationSimulation = "YES"> |
||||
|
<PathRunnable |
||||
|
runnableDebuggingMode = "0" |
||||
|
FilePath = "/usr/local/share/dotnet/dotnet"> |
||||
|
</PathRunnable> |
||||
|
<MacroExpansion> |
||||
|
<BuildableReference |
||||
|
BuildableIdentifier = "primary" |
||||
|
BlueprintIdentifier = "AB7A61EE2147C814003C5833" |
||||
|
BuildableName = "libAvalonia.Native.OSX.dylib" |
||||
|
BlueprintName = "Avalonia.Native.OSX" |
||||
|
ReferencedContainer = "container:Avalonia.Native.OSX.xcodeproj"> |
||||
|
</BuildableReference> |
||||
|
</MacroExpansion> |
||||
|
<CommandLineArguments> |
||||
|
<CommandLineArgument |
||||
|
argument = "bin/Debug/netcoreapp2.0/ControlCatalog.dll" |
||||
|
isEnabled = "YES"> |
||||
|
</CommandLineArgument> |
||||
|
</CommandLineArguments> |
||||
|
<AdditionalOptions> |
||||
|
</AdditionalOptions> |
||||
|
</LaunchAction> |
||||
|
<ProfileAction |
||||
|
buildConfiguration = "Release" |
||||
|
shouldUseLaunchSchemeArgsEnv = "YES" |
||||
|
savedToolIdentifier = "" |
||||
|
useCustomWorkingDirectory = "NO" |
||||
|
debugDocumentVersioning = "YES"> |
||||
|
<MacroExpansion> |
||||
|
<BuildableReference |
||||
|
BuildableIdentifier = "primary" |
||||
|
BlueprintIdentifier = "AB7A61EE2147C814003C5833" |
||||
|
BuildableName = "libAvalonia.Native.OSX.dylib" |
||||
|
BlueprintName = "Avalonia.Native.OSX" |
||||
|
ReferencedContainer = "container:Avalonia.Native.OSX.xcodeproj"> |
||||
|
</BuildableReference> |
||||
|
</MacroExpansion> |
||||
|
</ProfileAction> |
||||
|
<AnalyzeAction |
||||
|
buildConfiguration = "Debug"> |
||||
|
</AnalyzeAction> |
||||
|
<ArchiveAction |
||||
|
buildConfiguration = "Release" |
||||
|
revealArchiveInOrganizer = "YES"> |
||||
|
</ArchiveAction> |
||||
|
</Scheme> |
||||
@ -0,0 +1,12 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
#ifndef keytransform_h |
||||
|
#define keytransform_h |
||||
|
#include "common.h" |
||||
|
#include "key.h" |
||||
|
#include <map> |
||||
|
|
||||
|
extern std::map<int, AvnKey> s_KeyMap; |
||||
|
|
||||
|
#endif |
||||
@ -0,0 +1,241 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved. |
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information. |
||||
|
|
||||
|
#include "KeyTransform.h" |
||||
|
|
||||
|
const int kVK_ANSI_A = 0x00; |
||||
|
const int kVK_ANSI_S = 0x01; |
||||
|
const int kVK_ANSI_D = 0x02; |
||||
|
const int kVK_ANSI_F = 0x03; |
||||
|
const int kVK_ANSI_H = 0x04; |
||||
|
const int kVK_ANSI_G = 0x05; |
||||
|
const int kVK_ANSI_Z = 0x06; |
||||
|
const int kVK_ANSI_X = 0x07; |
||||
|
const int kVK_ANSI_C = 0x08; |
||||
|
const int kVK_ANSI_V = 0x09; |
||||
|
const int kVK_ANSI_B = 0x0B; |
||||
|
const int kVK_ANSI_Q = 0x0C; |
||||
|
const int kVK_ANSI_W = 0x0D; |
||||
|
const int kVK_ANSI_E = 0x0E; |
||||
|
const int kVK_ANSI_R = 0x0F; |
||||
|
const int kVK_ANSI_Y = 0x10; |
||||
|
const int kVK_ANSI_T = 0x11; |
||||
|
const int kVK_ANSI_1 = 0x12; |
||||
|
const int kVK_ANSI_2 = 0x13; |
||||
|
const int kVK_ANSI_3 = 0x14; |
||||
|
const int kVK_ANSI_4 = 0x15; |
||||
|
const int kVK_ANSI_6 = 0x16; |
||||
|
const int kVK_ANSI_5 = 0x17; |
||||
|
//const int kVK_ANSI_Equal = 0x18; |
||||
|
const int kVK_ANSI_9 = 0x19; |
||||
|
const int kVK_ANSI_7 = 0x1A; |
||||
|
const int kVK_ANSI_Minus = 0x1B; |
||||
|
const int kVK_ANSI_8 = 0x1C; |
||||
|
const int kVK_ANSI_0 = 0x1D; |
||||
|
const int kVK_ANSI_RightBracket = 0x1E; |
||||
|
const int kVK_ANSI_O = 0x1F; |
||||
|
const int kVK_ANSI_U = 0x20; |
||||
|
const int kVK_ANSI_LeftBracket = 0x21; |
||||
|
const int kVK_ANSI_I = 0x22; |
||||
|
const int kVK_ANSI_P = 0x23; |
||||
|
const int kVK_ANSI_L = 0x25; |
||||
|
const int kVK_ANSI_J = 0x26; |
||||
|
const int kVK_ANSI_Quote = 0x27; |
||||
|
const int kVK_ANSI_K = 0x28; |
||||
|
const int kVK_ANSI_Semicolon = 0x29; |
||||
|
const int kVK_ANSI_Backslash = 0x2A; |
||||
|
const int kVK_ANSI_Comma = 0x2B; |
||||
|
//const int kVK_ANSI_Slash = 0x2C; |
||||
|
const int kVK_ANSI_N = 0x2D; |
||||
|
const int kVK_ANSI_M = 0x2E; |
||||
|
const int kVK_ANSI_Period = 0x2F; |
||||
|
//const int kVK_ANSI_Grave = 0x32; |
||||
|
const int kVK_ANSI_KeypadDecimal = 0x41; |
||||
|
const int kVK_ANSI_KeypadMultiply = 0x43; |
||||
|
const int kVK_ANSI_KeypadPlus = 0x45; |
||||
|
const int kVK_ANSI_KeypadClear = 0x47; |
||||
|
const int kVK_ANSI_KeypadDivide = 0x4B; |
||||
|
const int kVK_ANSI_KeypadEnter = 0x4C; |
||||
|
const int kVK_ANSI_KeypadMinus = 0x4E; |
||||
|
//const int kVK_ANSI_KeypadEquals = 0x51; |
||||
|
const int kVK_ANSI_Keypad0 = 0x52; |
||||
|
const int kVK_ANSI_Keypad1 = 0x53; |
||||
|
const int kVK_ANSI_Keypad2 = 0x54; |
||||
|
const int kVK_ANSI_Keypad3 = 0x55; |
||||
|
const int kVK_ANSI_Keypad4 = 0x56; |
||||
|
const int kVK_ANSI_Keypad5 = 0x57; |
||||
|
const int kVK_ANSI_Keypad6 = 0x58; |
||||
|
const int kVK_ANSI_Keypad7 = 0x59; |
||||
|
const int kVK_ANSI_Keypad8 = 0x5B; |
||||
|
const int kVK_ANSI_Keypad9 = 0x5C; |
||||
|
const int kVK_Return = 0x24; |
||||
|
const int kVK_Tab = 0x30; |
||||
|
const int kVK_Space = 0x31; |
||||
|
const int kVK_Delete = 0x33; |
||||
|
const int kVK_Escape = 0x35; |
||||
|
const int kVK_Command = 0x37; |
||||
|
const int kVK_Shift = 0x38; |
||||
|
const int kVK_CapsLock = 0x39; |
||||
|
const int kVK_Option = 0x3A; |
||||
|
const int kVK_Control = 0x3B; |
||||
|
const int kVK_RightCommand = 0x36; |
||||
|
const int kVK_RightShift = 0x3C; |
||||
|
const int kVK_RightOption = 0x3D; |
||||
|
const int kVK_RightControl = 0x3E; |
||||
|
//const int kVK_Function = 0x3F; |
||||
|
const int kVK_F17 = 0x40; |
||||
|
const int kVK_VolumeUp = 0x48; |
||||
|
const int kVK_VolumeDown = 0x49; |
||||
|
const int kVK_Mute = 0x4A; |
||||
|
const int kVK_F18 = 0x4F; |
||||
|
const int kVK_F19 = 0x50; |
||||
|
const int kVK_F20 = 0x5A; |
||||
|
const int kVK_F5 = 0x60; |
||||
|
const int kVK_F6 = 0x61; |
||||
|
const int kVK_F7 = 0x62; |
||||
|
const int kVK_F3 = 0x63; |
||||
|
const int kVK_F8 = 0x64; |
||||
|
const int kVK_F9 = 0x65; |
||||
|
const int kVK_F11 = 0x67; |
||||
|
const int kVK_F13 = 0x69; |
||||
|
const int kVK_F16 = 0x6A; |
||||
|
const int kVK_F14 = 0x6B; |
||||
|
const int kVK_F10 = 0x6D; |
||||
|
const int kVK_F12 = 0x6F; |
||||
|
const int kVK_F15 = 0x71; |
||||
|
const int kVK_Help = 0x72; |
||||
|
const int kVK_Home = 0x73; |
||||
|
const int kVK_PageUp = 0x74; |
||||
|
const int kVK_ForwardDelete = 0x75; |
||||
|
const int kVK_F4 = 0x76; |
||||
|
const int kVK_End = 0x77; |
||||
|
const int kVK_F2 = 0x78; |
||||
|
const int kVK_PageDown = 0x79; |
||||
|
const int kVK_F1 = 0x7A; |
||||
|
const int kVK_LeftArrow = 0x7B; |
||||
|
const int kVK_RightArrow = 0x7C; |
||||
|
const int kVK_DownArrow = 0x7D; |
||||
|
const int kVK_UpArrow = 0x7E; |
||||
|
//const int kVK_ISO_Section = 0x0A; |
||||
|
//const int kVK_JIS_Yen = 0x5D; |
||||
|
//const int kVK_JIS_Underscore = 0x5E; |
||||
|
//const int kVK_JIS_KeypadComma = 0x5F; |
||||
|
//const int kVK_JIS_Eisu = 0x66; |
||||
|
//const int kVK_JIS_Kana = 0x68; |
||||
|
|
||||
|
std::map<int, AvnKey> s_KeyMap = |
||||
|
{ |
||||
|
{kVK_ANSI_A, A}, |
||||
|
{kVK_ANSI_S, S}, |
||||
|
{kVK_ANSI_D, D}, |
||||
|
{kVK_ANSI_F, F}, |
||||
|
{kVK_ANSI_H, H}, |
||||
|
{kVK_ANSI_G, G}, |
||||
|
{kVK_ANSI_Z, Z}, |
||||
|
{kVK_ANSI_X, X}, |
||||
|
{kVK_ANSI_C, C}, |
||||
|
{kVK_ANSI_V, V}, |
||||
|
{kVK_ANSI_B, B}, |
||||
|
{kVK_ANSI_Q, Q}, |
||||
|
{kVK_ANSI_W, W}, |
||||
|
{kVK_ANSI_E, E}, |
||||
|
{kVK_ANSI_R, R}, |
||||
|
{kVK_ANSI_Y, Y}, |
||||
|
{kVK_ANSI_T, T}, |
||||
|
{kVK_ANSI_1, D1}, |
||||
|
{kVK_ANSI_2, D2}, |
||||
|
{kVK_ANSI_3, D3}, |
||||
|
{kVK_ANSI_4, D4}, |
||||
|
{kVK_ANSI_6, D6}, |
||||
|
{kVK_ANSI_5, D5}, |
||||
|
//{kVK_ANSI_Equal, ?}, |
||||
|
{kVK_ANSI_9, D9}, |
||||
|
{kVK_ANSI_7, D7}, |
||||
|
{kVK_ANSI_Minus, OemMinus}, |
||||
|
{kVK_ANSI_8, D8}, |
||||
|
{kVK_ANSI_0, D0}, |
||||
|
{kVK_ANSI_RightBracket, OemCloseBrackets}, |
||||
|
{kVK_ANSI_O, O}, |
||||
|
{kVK_ANSI_U, U}, |
||||
|
{kVK_ANSI_LeftBracket, OemOpenBrackets}, |
||||
|
{kVK_ANSI_I, I}, |
||||
|
{kVK_ANSI_P, P}, |
||||
|
{kVK_ANSI_L, L}, |
||||
|
{kVK_ANSI_J, J}, |
||||
|
{kVK_ANSI_Quote, OemQuotes}, |
||||
|
{kVK_ANSI_K, AvnKeyK}, |
||||
|
{kVK_ANSI_Semicolon, OemSemicolon}, |
||||
|
{kVK_ANSI_Backslash, OemBackslash}, |
||||
|
{kVK_ANSI_Comma, OemComma}, |
||||
|
//{kVK_ANSI_Slash, ?}, |
||||
|
{kVK_ANSI_N, N}, |
||||
|
{kVK_ANSI_M, M}, |
||||
|
{kVK_ANSI_Period, OemPeriod}, |
||||
|
//{kVK_ANSI_Grave, ?}, |
||||
|
{kVK_ANSI_KeypadDecimal, Decimal}, |
||||
|
{kVK_ANSI_KeypadMultiply, Multiply}, |
||||
|
{kVK_ANSI_KeypadPlus, OemPlus}, |
||||
|
{kVK_ANSI_KeypadClear, AvnKeyClear}, |
||||
|
{kVK_ANSI_KeypadDivide, Divide}, |
||||
|
{kVK_ANSI_KeypadEnter, AvnKeyEnter}, |
||||
|
{kVK_ANSI_KeypadMinus, OemMinus}, |
||||
|
//{kVK_ANSI_KeypadEquals, ?}, |
||||
|
{kVK_ANSI_Keypad0, NumPad0}, |
||||
|
{kVK_ANSI_Keypad1, NumPad1}, |
||||
|
{kVK_ANSI_Keypad2, NumPad2}, |
||||
|
{kVK_ANSI_Keypad3, NumPad3}, |
||||
|
{kVK_ANSI_Keypad4, NumPad4}, |
||||
|
{kVK_ANSI_Keypad5, NumPad5}, |
||||
|
{kVK_ANSI_Keypad6, NumPad6}, |
||||
|
{kVK_ANSI_Keypad7, NumPad7}, |
||||
|
{kVK_ANSI_Keypad8, NumPad8}, |
||||
|
{kVK_ANSI_Keypad9, NumPad9}, |
||||
|
{kVK_Return, AvnKeyReturn}, |
||||
|
{kVK_Tab, AvnKeyTab}, |
||||
|
{kVK_Space, Space}, |
||||
|
{kVK_Delete, AvnKeyBack}, |
||||
|
{kVK_Escape, Escape}, |
||||
|
{kVK_Command, LWin}, |
||||
|
{kVK_Shift, LeftShift}, |
||||
|
{kVK_CapsLock, AvnKeyCapsLock}, |
||||
|
{kVK_Option, LeftAlt}, |
||||
|
{kVK_Control, LeftCtrl}, |
||||
|
{kVK_RightCommand, RWin}, |
||||
|
{kVK_RightShift, RightShift}, |
||||
|
{kVK_RightOption, RightAlt}, |
||||
|
{kVK_RightControl, RightCtrl}, |
||||
|
//{kVK_Function, ?}, |
||||
|
{kVK_F17, F17}, |
||||
|
{kVK_VolumeUp, VolumeUp}, |
||||
|
{kVK_VolumeDown, VolumeDown}, |
||||
|
{kVK_Mute, VolumeMute}, |
||||
|
{kVK_F18, F18}, |
||||
|
{kVK_F19, F19}, |
||||
|
{kVK_F20, F20}, |
||||
|
{kVK_F5, F5}, |
||||
|
{kVK_F6, F6}, |
||||
|
{kVK_F7, F7}, |
||||
|
{kVK_F3, F3}, |
||||
|
{kVK_F8, F8}, |
||||
|
{kVK_F9, F9}, |
||||
|
{kVK_F11, F11}, |
||||
|
{kVK_F13, F13}, |
||||
|
{kVK_F16, F16}, |
||||
|
{kVK_F14, F14}, |
||||
|
{kVK_F10, F10}, |
||||
|
{kVK_F12, F12}, |
||||
|
{kVK_F15, F15}, |
||||
|
{kVK_Help, Help}, |
||||
|
{kVK_Home, Home}, |
||||
|
{kVK_PageUp, PageUp}, |
||||
|
{kVK_ForwardDelete, Delete}, |
||||
|
{kVK_F4, F4}, |
||||
|
{kVK_End, End}, |
||||
|
{kVK_F2, F2}, |
||||
|
{kVK_PageDown, PageDown}, |
||||
|
{kVK_F1, F1}, |
||||
|
{kVK_LeftArrow, Left}, |
||||
|
{kVK_RightArrow, Right}, |
||||
|
{kVK_DownArrow, Down}, |
||||
|
{kVK_UpArrow, Up} |
||||
|
}; |
||||
@ -0,0 +1,51 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved. |
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information. |
||||
|
|
||||
|
#include "common.h" |
||||
|
|
||||
|
class Screens : public ComSingleObject<IAvnScreens, &IID_IAvnScreens> |
||||
|
{ |
||||
|
public: |
||||
|
FORWARD_IUNKNOWN() |
||||
|
virtual HRESULT GetScreenCount (int* ret) |
||||
|
{ |
||||
|
@autoreleasepool |
||||
|
{ |
||||
|
*ret = (int)[NSScreen screens].count; |
||||
|
|
||||
|
return S_OK; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
virtual HRESULT GetScreen (int index, AvnScreen* ret) |
||||
|
{ |
||||
|
@autoreleasepool |
||||
|
{ |
||||
|
if(index < 0 || index >= [NSScreen screens].count) |
||||
|
{ |
||||
|
return E_INVALIDARG; |
||||
|
} |
||||
|
|
||||
|
auto screen = [[NSScreen screens] objectAtIndex:index]; |
||||
|
|
||||
|
ret->Bounds.X = [screen frame].origin.x; |
||||
|
ret->Bounds.Y = [screen frame].origin.y; |
||||
|
ret->Bounds.Height = [screen frame].size.height; |
||||
|
ret->Bounds.Width = [screen frame].size.width; |
||||
|
|
||||
|
ret->WorkingArea.X = [screen visibleFrame].origin.x; |
||||
|
ret->WorkingArea.Y = [screen visibleFrame].origin.y; |
||||
|
ret->WorkingArea.Height = [screen visibleFrame].size.height; |
||||
|
ret->WorkingArea.Width = [screen visibleFrame].size.width; |
||||
|
|
||||
|
ret->Primary = index == 0; |
||||
|
|
||||
|
return S_OK; |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
extern IAvnScreens* CreateScreens() |
||||
|
{ |
||||
|
return new Screens(); |
||||
|
} |
||||
@ -0,0 +1,262 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved. |
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information. |
||||
|
|
||||
|
#include "common.h" |
||||
|
#include "window.h" |
||||
|
|
||||
|
class SystemDialogs : public ComSingleObject<IAvnSystemDialogs, &IID_IAvnSystemDialogs> |
||||
|
{ |
||||
|
public: |
||||
|
FORWARD_IUNKNOWN() |
||||
|
virtual void SelectFolderDialog (IAvnWindow* parentWindowHandle, |
||||
|
IAvnSystemDialogEvents* events, |
||||
|
const char* title, |
||||
|
const char* initialDirectory) |
||||
|
{ |
||||
|
@autoreleasepool |
||||
|
{ |
||||
|
auto panel = [NSOpenPanel openPanel]; |
||||
|
|
||||
|
panel.canChooseDirectories = true; |
||||
|
panel.canCreateDirectories = true; |
||||
|
panel.canChooseFiles = false; |
||||
|
|
||||
|
if(title != nullptr) |
||||
|
{ |
||||
|
panel.title = [NSString stringWithUTF8String:title]; |
||||
|
} |
||||
|
|
||||
|
if(initialDirectory != nullptr) |
||||
|
{ |
||||
|
auto directoryString = [NSString stringWithUTF8String:initialDirectory]; |
||||
|
panel.directoryURL = [NSURL fileURLWithPath:directoryString]; |
||||
|
} |
||||
|
|
||||
|
auto handler = ^(NSModalResponse result) { |
||||
|
if(result == NSFileHandlingPanelOKButton) |
||||
|
{ |
||||
|
auto urls = [panel URLs]; |
||||
|
|
||||
|
if(urls.count > 0) |
||||
|
{ |
||||
|
void* strings[urls.count]; |
||||
|
|
||||
|
for(int i = 0; i < urls.count; i++) |
||||
|
{ |
||||
|
auto url = [urls objectAtIndex:i]; |
||||
|
|
||||
|
auto string = [url absoluteString]; |
||||
|
string = [string substringFromIndex:7]; |
||||
|
|
||||
|
strings[i] = (void*)[string UTF8String]; |
||||
|
} |
||||
|
|
||||
|
events->OnCompleted((int)urls.count, &strings[0]); |
||||
|
|
||||
|
[panel orderOut:panel]; |
||||
|
|
||||
|
if(parentWindowHandle != nullptr) |
||||
|
{ |
||||
|
auto windowHolder = dynamic_cast<INSWindowHolder*>(parentWindowHandle); |
||||
|
[windowHolder->GetNSWindow() makeKeyAndOrderFront:windowHolder->GetNSWindow()]; |
||||
|
} |
||||
|
|
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
events->OnCompleted(0, nullptr); |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
if(parentWindowHandle != nullptr) |
||||
|
{ |
||||
|
auto windowBase = dynamic_cast<INSWindowHolder*>(parentWindowHandle); |
||||
|
|
||||
|
[panel beginSheetModalForWindow:windowBase->GetNSWindow() completionHandler:handler]; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
[panel beginWithCompletionHandler: handler]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
virtual void OpenFileDialog (IAvnWindow* parentWindowHandle, |
||||
|
IAvnSystemDialogEvents* events, |
||||
|
bool allowMultiple, |
||||
|
const char* title, |
||||
|
const char* initialDirectory, |
||||
|
const char* initialFile, |
||||
|
const char* filters) |
||||
|
{ |
||||
|
@autoreleasepool |
||||
|
{ |
||||
|
auto panel = [NSOpenPanel openPanel]; |
||||
|
|
||||
|
panel.allowsMultipleSelection = allowMultiple; |
||||
|
|
||||
|
if(title != nullptr) |
||||
|
{ |
||||
|
panel.title = [NSString stringWithUTF8String:title]; |
||||
|
} |
||||
|
|
||||
|
if(initialDirectory != nullptr) |
||||
|
{ |
||||
|
auto directoryString = [NSString stringWithUTF8String:initialDirectory]; |
||||
|
panel.directoryURL = [NSURL fileURLWithPath:directoryString]; |
||||
|
} |
||||
|
|
||||
|
if(initialFile != nullptr) |
||||
|
{ |
||||
|
panel.nameFieldStringValue = [NSString stringWithUTF8String:initialFile]; |
||||
|
} |
||||
|
|
||||
|
if(filters != nullptr) |
||||
|
{ |
||||
|
auto filtersString = [NSString stringWithUTF8String:filters]; |
||||
|
|
||||
|
if(filtersString.length > 0) |
||||
|
{ |
||||
|
auto allowedTypes = [filtersString componentsSeparatedByString:@";"]; |
||||
|
|
||||
|
panel.allowedFileTypes = allowedTypes; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
auto handler = ^(NSModalResponse result) { |
||||
|
if(result == NSFileHandlingPanelOKButton) |
||||
|
{ |
||||
|
auto urls = [panel URLs]; |
||||
|
|
||||
|
if(urls.count > 0) |
||||
|
{ |
||||
|
void* strings[urls.count]; |
||||
|
|
||||
|
for(int i = 0; i < urls.count; i++) |
||||
|
{ |
||||
|
auto url = [urls objectAtIndex:i]; |
||||
|
|
||||
|
auto string = [url absoluteString]; |
||||
|
string = [string substringFromIndex:7]; |
||||
|
|
||||
|
strings[i] = (void*)[string UTF8String]; |
||||
|
} |
||||
|
|
||||
|
events->OnCompleted((int)urls.count, &strings[0]); |
||||
|
|
||||
|
[panel orderOut:panel]; |
||||
|
|
||||
|
if(parentWindowHandle != nullptr) |
||||
|
{ |
||||
|
auto windowHolder = dynamic_cast<INSWindowHolder*>(parentWindowHandle); |
||||
|
[windowHolder->GetNSWindow() makeKeyAndOrderFront:windowHolder->GetNSWindow()]; |
||||
|
} |
||||
|
|
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
events->OnCompleted(0, nullptr); |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
if(parentWindowHandle != nullptr) |
||||
|
{ |
||||
|
auto windowHolder = dynamic_cast<INSWindowHolder*>(parentWindowHandle); |
||||
|
|
||||
|
[panel beginSheetModalForWindow:windowHolder->GetNSWindow() completionHandler:handler]; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
[panel beginWithCompletionHandler: handler]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
virtual void SaveFileDialog (IAvnWindow* parentWindowHandle, |
||||
|
IAvnSystemDialogEvents* events, |
||||
|
const char* title, |
||||
|
const char* initialDirectory, |
||||
|
const char* initialFile, |
||||
|
const char* filters) |
||||
|
{ |
||||
|
@autoreleasepool |
||||
|
{ |
||||
|
auto panel = [NSSavePanel savePanel]; |
||||
|
|
||||
|
if(title != nullptr) |
||||
|
{ |
||||
|
panel.title = [NSString stringWithUTF8String:title]; |
||||
|
} |
||||
|
|
||||
|
if(initialDirectory != nullptr) |
||||
|
{ |
||||
|
auto directoryString = [NSString stringWithUTF8String:initialDirectory]; |
||||
|
panel.directoryURL = [NSURL fileURLWithPath:directoryString]; |
||||
|
} |
||||
|
|
||||
|
if(initialFile != nullptr) |
||||
|
{ |
||||
|
panel.nameFieldStringValue = [NSString stringWithUTF8String:initialFile]; |
||||
|
} |
||||
|
|
||||
|
if(filters != nullptr) |
||||
|
{ |
||||
|
auto filtersString = [NSString stringWithUTF8String:filters]; |
||||
|
|
||||
|
if(filtersString.length > 0) |
||||
|
{ |
||||
|
auto allowedTypes = [filtersString componentsSeparatedByString:@";"]; |
||||
|
|
||||
|
panel.allowedFileTypes = allowedTypes; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
auto handler = ^(NSModalResponse result) { |
||||
|
if(result == NSFileHandlingPanelOKButton) |
||||
|
{ |
||||
|
void* strings[1]; |
||||
|
|
||||
|
auto url = [panel URL]; |
||||
|
|
||||
|
auto string = [url absoluteString]; |
||||
|
string = [string substringFromIndex:7]; |
||||
|
strings[0] = (void*)[string UTF8String]; |
||||
|
|
||||
|
events->OnCompleted(1, &strings[0]); |
||||
|
|
||||
|
[panel orderOut:panel]; |
||||
|
|
||||
|
if(parentWindowHandle != nullptr) |
||||
|
{ |
||||
|
auto windowHolder = dynamic_cast<INSWindowHolder*>(parentWindowHandle); |
||||
|
[windowHolder->GetNSWindow() makeKeyAndOrderFront:windowHolder->GetNSWindow()]; |
||||
|
} |
||||
|
|
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
events->OnCompleted(0, nullptr); |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
if(parentWindowHandle != nullptr) |
||||
|
{ |
||||
|
auto windowBase = dynamic_cast<INSWindowHolder*>(parentWindowHandle); |
||||
|
|
||||
|
[panel beginSheetModalForWindow:windowBase->GetNSWindow() completionHandler:handler]; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
[panel beginWithCompletionHandler: handler]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
extern IAvnSystemDialogs* CreateSystemDialogs() |
||||
|
{ |
||||
|
return new SystemDialogs(); |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved. |
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information. |
||||
|
|
||||
|
#include "common.h" |
||||
|
|
||||
|
class Clipboard : public ComSingleObject<IAvnClipboard, &IID_IAvnClipboard> |
||||
|
{ |
||||
|
public: |
||||
|
FORWARD_IUNKNOWN() |
||||
|
virtual HRESULT GetText (void** retOut) |
||||
|
{ |
||||
|
@autoreleasepool |
||||
|
{ |
||||
|
NSString *str = [[NSPasteboard generalPasteboard] stringForType:NSPasteboardTypeString]; |
||||
|
*retOut = (void *)str.UTF8String; |
||||
|
} |
||||
|
|
||||
|
return S_OK; |
||||
|
} |
||||
|
|
||||
|
virtual HRESULT SetText (char* text) |
||||
|
{ |
||||
|
@autoreleasepool |
||||
|
{ |
||||
|
NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; |
||||
|
[pasteBoard clearContents]; |
||||
|
[pasteBoard setString:@(text) forType:NSPasteboardTypeString]; |
||||
|
} |
||||
|
|
||||
|
return S_OK; |
||||
|
} |
||||
|
|
||||
|
virtual HRESULT Clear() |
||||
|
{ |
||||
|
@autoreleasepool |
||||
|
{ |
||||
|
[[NSPasteboard generalPasteboard] clearContents]; |
||||
|
} |
||||
|
|
||||
|
return S_OK; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
extern IAvnClipboard* CreateClipboard() |
||||
|
{ |
||||
|
return new Clipboard(); |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
#ifndef common_h |
||||
|
#define common_h |
||||
|
#include "comimpl.h" |
||||
|
#include "avalonia-native.h" |
||||
|
#include <stdio.h> |
||||
|
#import <Foundation/Foundation.h> |
||||
|
#import <AppKit/AppKit.h> |
||||
|
#include <pthread.h> |
||||
|
|
||||
|
extern IAvnPlatformThreadingInterface* CreatePlatformThreading(); |
||||
|
extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events); |
||||
|
extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events); |
||||
|
extern IAvnSystemDialogs* CreateSystemDialogs(); |
||||
|
extern IAvnScreens* CreateScreens(); |
||||
|
extern IAvnClipboard* CreateClipboard(); |
||||
|
extern IAvnCursorFactory* CreateCursorFactory(); |
||||
|
extern IAvnGlFeature* GetGlFeature(); |
||||
|
extern IAvnGlSurfaceRenderTarget* CreateGlRenderTarget(NSWindow* window, NSView* view); |
||||
|
|
||||
|
extern NSPoint ToNSPoint (AvnPoint p); |
||||
|
extern AvnPoint ToAvnPoint (NSPoint p); |
||||
|
extern AvnPoint ConvertPointY (AvnPoint p); |
||||
|
extern NSSize ToNSSize (AvnSize s); |
||||
|
|
||||
|
#ifdef DEBUG |
||||
|
#define NSDebugLog(...) NSLog(__VA_ARGS__) |
||||
|
#else |
||||
|
#define NSDebugLog(...) (void)0 |
||||
|
#endif |
||||
|
|
||||
|
#endif |
||||
@ -0,0 +1,29 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
#ifndef cursor_h |
||||
|
#define cursor_h |
||||
|
|
||||
|
#include "common.h" |
||||
|
#include <map> |
||||
|
|
||||
|
class Cursor : public ComSingleObject<IAvnCursor, &IID_IAvnCursor> |
||||
|
{ |
||||
|
private: |
||||
|
NSCursor * _native; |
||||
|
|
||||
|
public: |
||||
|
FORWARD_IUNKNOWN() |
||||
|
Cursor(NSCursor * cursor) |
||||
|
{ |
||||
|
_native = cursor; |
||||
|
} |
||||
|
|
||||
|
NSCursor* GetNative() |
||||
|
{ |
||||
|
return _native; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
extern std::map<AvnStandardCursorType, Cursor*> s_cursorMap; |
||||
|
#endif /* cursor_h */ |
||||
@ -0,0 +1,73 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved. |
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information. |
||||
|
|
||||
|
#include "common.h" |
||||
|
#include "cursor.h" |
||||
|
#include <map> |
||||
|
|
||||
|
class CursorFactory : public ComSingleObject<IAvnCursorFactory, &IID_IAvnCursorFactory> |
||||
|
{ |
||||
|
Cursor* arrowCursor = new Cursor([NSCursor arrowCursor]); |
||||
|
Cursor* crossCursor = new Cursor([NSCursor crosshairCursor]); |
||||
|
Cursor* resizeUpCursor = new Cursor([NSCursor resizeUpCursor]); |
||||
|
Cursor* resizeDownCursor = new Cursor([NSCursor resizeDownCursor]); |
||||
|
Cursor* resizeUpDownCursor = new Cursor([NSCursor resizeUpDownCursor]); |
||||
|
Cursor* dragCopyCursor = new Cursor([NSCursor dragCopyCursor]); |
||||
|
Cursor* dragLinkCursor = new Cursor([NSCursor dragLinkCursor]); |
||||
|
Cursor* pointingHandCursor = new Cursor([NSCursor pointingHandCursor]); |
||||
|
Cursor* contextualMenuCursor = new Cursor([NSCursor contextualMenuCursor]); |
||||
|
Cursor* IBeamCursor = new Cursor([NSCursor IBeamCursor]); |
||||
|
Cursor* resizeLeftCursor = new Cursor([NSCursor resizeLeftCursor]); |
||||
|
Cursor* resizeRightCursor = new Cursor([NSCursor resizeRightCursor]); |
||||
|
Cursor* resizeWestEastCursor = new Cursor([NSCursor resizeLeftRightCursor]); |
||||
|
Cursor* operationNotAllowedCursor = new Cursor([NSCursor operationNotAllowedCursor]); |
||||
|
|
||||
|
std::map<AvnStandardCursorType, Cursor*> s_cursorMap = |
||||
|
{ |
||||
|
{ CursorArrow, arrowCursor }, |
||||
|
{ CursorAppStarting, arrowCursor }, |
||||
|
{ CursorWait, arrowCursor }, |
||||
|
{ CursorTopLeftCorner, crossCursor }, |
||||
|
{ CursorTopRightCorner, crossCursor }, |
||||
|
{ CursorBottomLeftCorner, crossCursor }, |
||||
|
{ CursorBottomRightCorner, crossCursor }, |
||||
|
{ CursorCross, crossCursor }, |
||||
|
{ CursorSizeAll, crossCursor }, |
||||
|
{ CursorSizeNorthSouth, resizeUpDownCursor}, |
||||
|
{ CursorSizeWestEast, resizeWestEastCursor}, |
||||
|
{ CursorTopSide, resizeUpCursor }, |
||||
|
{ CursorUpArrow, resizeUpCursor }, |
||||
|
{ CursorBottomSize, resizeDownCursor }, |
||||
|
{ CursorDragCopy, dragCopyCursor }, |
||||
|
{ CursorDragMove, dragCopyCursor }, |
||||
|
{ CursorDragLink, dragLinkCursor }, |
||||
|
{ CursorHand, pointingHandCursor }, |
||||
|
{ CursorHelp, contextualMenuCursor }, |
||||
|
{ CursorIbeam, IBeamCursor }, |
||||
|
{ CursorLeftSide, resizeLeftCursor }, |
||||
|
{ CursorRightSide, resizeRightCursor }, |
||||
|
{ CursorNo, operationNotAllowedCursor } |
||||
|
}; |
||||
|
|
||||
|
public: |
||||
|
FORWARD_IUNKNOWN() |
||||
|
virtual HRESULT GetCursor (AvnStandardCursorType cursorType, IAvnCursor** retOut) |
||||
|
{ |
||||
|
*retOut = s_cursorMap[cursorType]; |
||||
|
|
||||
|
if(*retOut != nullptr) |
||||
|
{ |
||||
|
(*retOut)->AddRef(); |
||||
|
} |
||||
|
|
||||
|
return S_OK; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
extern IAvnCursorFactory* CreateCursorFactory() |
||||
|
{ |
||||
|
@autoreleasepool |
||||
|
{ |
||||
|
return new CursorFactory(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,255 @@ |
|||||
|
#include "common.h" |
||||
|
#include <OpenGL/gl.h> |
||||
|
#include <dlfcn.h> |
||||
|
|
||||
|
template <typename T, size_t N> char (&ArrayCounter(T (&a)[N]))[N]; |
||||
|
#define ARRAY_COUNT(a) (sizeof(ArrayCounter(a))) |
||||
|
|
||||
|
NSOpenGLPixelFormat* CreateFormat() |
||||
|
{ |
||||
|
NSOpenGLPixelFormatAttribute attribs[] = |
||||
|
{ |
||||
|
NSOpenGLPFADoubleBuffer, |
||||
|
NSOpenGLPFAColorSize, 32, |
||||
|
NSOpenGLPFAStencilSize, 8, |
||||
|
NSOpenGLPFADepthSize, 8, |
||||
|
0 |
||||
|
}; |
||||
|
return [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; |
||||
|
} |
||||
|
|
||||
|
class AvnGlContext : public virtual ComSingleObject<IAvnGlContext, &IID_IAvnGlContext> |
||||
|
{ |
||||
|
public: |
||||
|
FORWARD_IUNKNOWN() |
||||
|
NSOpenGLContext* GlContext; |
||||
|
GLuint Framebuffer, RenderBuffer, StencilBuffer; |
||||
|
AvnGlContext(NSOpenGLContext* gl, bool offscreen) |
||||
|
{ |
||||
|
Framebuffer = 0; |
||||
|
RenderBuffer = 0; |
||||
|
StencilBuffer = 0; |
||||
|
GlContext = gl; |
||||
|
if(offscreen) |
||||
|
{ |
||||
|
[GlContext makeCurrentContext]; |
||||
|
|
||||
|
glGenFramebuffersEXT(1, &Framebuffer); |
||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER, Framebuffer); |
||||
|
glGenRenderbuffersEXT(1, &RenderBuffer); |
||||
|
glGenRenderbuffersEXT(1, &StencilBuffer); |
||||
|
|
||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER, StencilBuffer); |
||||
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, StencilBuffer); |
||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER, RenderBuffer); |
||||
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, RenderBuffer); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
virtual HRESULT MakeCurrent() |
||||
|
{ |
||||
|
[GlContext makeCurrentContext];/* |
||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER, Framebuffer); |
||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER, RenderBuffer); |
||||
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, RenderBuffer); |
||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER, StencilBuffer); |
||||
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, StencilBuffer);*/ |
||||
|
return S_OK; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
class AvnGlDisplay : public virtual ComSingleObject<IAvnGlDisplay, &IID_IAvnGlDisplay> |
||||
|
{ |
||||
|
int _sampleCount, _stencilSize; |
||||
|
void* _libgl; |
||||
|
|
||||
|
public: |
||||
|
FORWARD_IUNKNOWN() |
||||
|
|
||||
|
AvnGlDisplay(int sampleCount, int stencilSize) |
||||
|
{ |
||||
|
_sampleCount = sampleCount; |
||||
|
_stencilSize = stencilSize; |
||||
|
_libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib", RTLD_LAZY); |
||||
|
} |
||||
|
|
||||
|
virtual HRESULT GetSampleCount(int* ret) |
||||
|
{ |
||||
|
*ret = _sampleCount; |
||||
|
return S_OK; |
||||
|
} |
||||
|
virtual HRESULT GetStencilSize(int* ret) |
||||
|
{ |
||||
|
*ret = _stencilSize; |
||||
|
return S_OK; |
||||
|
} |
||||
|
|
||||
|
virtual HRESULT ClearContext() |
||||
|
{ |
||||
|
[NSOpenGLContext clearCurrentContext]; |
||||
|
return S_OK; |
||||
|
} |
||||
|
|
||||
|
virtual void* GetProcAddress(char* proc) |
||||
|
{ |
||||
|
return dlsym(_libgl, proc); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
class GlFeature : public virtual ComSingleObject<IAvnGlFeature, &IID_IAvnGlFeature> |
||||
|
{ |
||||
|
IAvnGlDisplay* _display; |
||||
|
AvnGlContext *_immediate; |
||||
|
NSOpenGLContext* _shared; |
||||
|
public: |
||||
|
FORWARD_IUNKNOWN() |
||||
|
NSOpenGLPixelFormat* _format; |
||||
|
GlFeature(IAvnGlDisplay* display, AvnGlContext* immediate, NSOpenGLPixelFormat* format) |
||||
|
{ |
||||
|
_display = display; |
||||
|
_immediate = immediate; |
||||
|
_format = format; |
||||
|
_shared = [[NSOpenGLContext alloc] initWithFormat:_format shareContext:_immediate->GlContext]; |
||||
|
} |
||||
|
|
||||
|
NSOpenGLContext* CreateContext() |
||||
|
{ |
||||
|
return _shared; |
||||
|
//return [[NSOpenGLContext alloc] initWithFormat:_format shareContext:nil]; |
||||
|
} |
||||
|
|
||||
|
virtual HRESULT ObtainDisplay(IAvnGlDisplay**retOut) |
||||
|
{ |
||||
|
*retOut = _display; |
||||
|
_display->AddRef(); |
||||
|
return S_OK; |
||||
|
} |
||||
|
|
||||
|
virtual HRESULT ObtainImmediateContext(IAvnGlContext**retOut) |
||||
|
{ |
||||
|
*retOut = _immediate; |
||||
|
_immediate->AddRef(); |
||||
|
return S_OK; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
static GlFeature* Feature; |
||||
|
|
||||
|
GlFeature* CreateGlFeature() |
||||
|
{ |
||||
|
auto format = CreateFormat(); |
||||
|
if(format == nil) |
||||
|
{ |
||||
|
NSLog(@"Unable to choose pixel format"); |
||||
|
return NULL; |
||||
|
} |
||||
|
|
||||
|
auto immediateContext = [[NSOpenGLContext alloc] initWithFormat:format shareContext:nil]; |
||||
|
if(immediateContext == nil) |
||||
|
{ |
||||
|
NSLog(@"Unable to create NSOpenGLContext"); |
||||
|
return NULL; |
||||
|
} |
||||
|
|
||||
|
int stencilBits = 0, sampleCount = 0; |
||||
|
|
||||
|
auto fmt = CGLGetPixelFormat([immediateContext CGLContextObj]); |
||||
|
CGLDescribePixelFormat(fmt, 0, kCGLPFASamples, &sampleCount); |
||||
|
CGLDescribePixelFormat(fmt, 0, kCGLPFAStencilSize, &stencilBits); |
||||
|
|
||||
|
auto offscreen = new AvnGlContext(immediateContext, true); |
||||
|
auto display = new AvnGlDisplay(sampleCount, stencilBits); |
||||
|
|
||||
|
return new GlFeature(display, offscreen, format); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static GlFeature* GetFeature() |
||||
|
{ |
||||
|
if(Feature == nil) |
||||
|
Feature = CreateGlFeature(); |
||||
|
return Feature; |
||||
|
} |
||||
|
|
||||
|
extern IAvnGlFeature* GetGlFeature() |
||||
|
{ |
||||
|
return GetFeature(); |
||||
|
} |
||||
|
|
||||
|
class AvnGlRenderingSession : public ComSingleObject<IAvnGlSurfaceRenderingSession, &IID_IAvnGlSurfaceRenderingSession> |
||||
|
{ |
||||
|
NSView* _view; |
||||
|
NSWindow* _window; |
||||
|
NSOpenGLContext* _context; |
||||
|
public: |
||||
|
FORWARD_IUNKNOWN() |
||||
|
AvnGlRenderingSession(NSWindow*window, NSView* view, NSOpenGLContext* context) |
||||
|
{ |
||||
|
_context = context; |
||||
|
_window = window; |
||||
|
_view = view; |
||||
|
} |
||||
|
|
||||
|
virtual HRESULT GetPixelSize(AvnPixelSize* ret) |
||||
|
{ |
||||
|
auto fsize = [_view convertSizeToBacking: [_view frame].size]; |
||||
|
ret->Width = (int)fsize.width; |
||||
|
ret->Height = (int)fsize.height; |
||||
|
return S_OK; |
||||
|
} |
||||
|
virtual HRESULT GetScaling(double* ret) |
||||
|
{ |
||||
|
*ret = [_window backingScaleFactor]; |
||||
|
return S_OK; |
||||
|
} |
||||
|
|
||||
|
virtual ~AvnGlRenderingSession() |
||||
|
{ |
||||
|
glFlush(); |
||||
|
[_context flushBuffer]; |
||||
|
[_context setView:nil]; |
||||
|
CGLUnlockContext([_context CGLContextObj]); |
||||
|
[_view unlockFocus]; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
class AvnGlRenderTarget : public ComSingleObject<IAvnGlSurfaceRenderTarget, &IID_IAvnGlSurfaceRenderTarget> |
||||
|
{ |
||||
|
NSView* _view; |
||||
|
NSWindow* _window; |
||||
|
NSOpenGLContext* _context; |
||||
|
public: |
||||
|
FORWARD_IUNKNOWN() |
||||
|
AvnGlRenderTarget(NSWindow* window, NSView*view) |
||||
|
{ |
||||
|
_window = window; |
||||
|
_view = view; |
||||
|
_context = GetFeature()->CreateContext(); |
||||
|
} |
||||
|
|
||||
|
virtual HRESULT BeginDrawing(IAvnGlSurfaceRenderingSession** ret) |
||||
|
{ |
||||
|
auto f = GetFeature(); |
||||
|
if(f == NULL) |
||||
|
return E_FAIL; |
||||
|
if(![_view lockFocusIfCanDraw]) |
||||
|
return E_ABORT; |
||||
|
|
||||
|
auto gl = _context; |
||||
|
CGLLockContext([_context CGLContextObj]); |
||||
|
[gl setView: _view]; |
||||
|
[gl makeCurrentContext]; |
||||
|
auto frame = [_view frame]; |
||||
|
|
||||
|
*ret = new AvnGlRenderingSession(_window, _view, gl); |
||||
|
return S_OK; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
extern IAvnGlSurfaceRenderTarget* CreateGlRenderTarget(NSWindow* window, NSView* view) |
||||
|
{ |
||||
|
return new AvnGlRenderTarget(window, view); |
||||
|
} |
||||
@ -0,0 +1,178 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved. |
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information. |
||||
|
|
||||
|
//This file will contain actual IID structures |
||||
|
#define COM_GUIDS_MATERIALIZE |
||||
|
#include "common.h" |
||||
|
|
||||
|
static BOOL ShowInDock = 1; |
||||
|
|
||||
|
static void SetActivationPolicy() |
||||
|
{ |
||||
|
[[NSApplication sharedApplication] setActivationPolicy: (ShowInDock ? NSApplicationActivationPolicyRegular : NSApplicationActivationPolicyAccessory)]; |
||||
|
} |
||||
|
|
||||
|
class MacOptions : public ComSingleObject<IAvnMacOptions, &IID_IAvnMacOptions> |
||||
|
{ |
||||
|
public: |
||||
|
FORWARD_IUNKNOWN() |
||||
|
virtual HRESULT SetShowInDock(int show) |
||||
|
{ |
||||
|
ShowInDock = show; |
||||
|
SetActivationPolicy(); |
||||
|
return S_OK; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
|
||||
|
/// See "Using POSIX Threads in a Cocoa Application" section here: |
||||
|
/// https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html#//apple_ref/doc/uid/20000738-125024 |
||||
|
@interface ThreadingInitializer : NSObject |
||||
|
- (void) do; |
||||
|
@end |
||||
|
@implementation ThreadingInitializer |
||||
|
|
||||
|
pthread_mutex_t mutex; |
||||
|
pthread_cond_t cond; |
||||
|
|
||||
|
- (void) runOnce |
||||
|
{ |
||||
|
pthread_mutex_lock(&mutex); |
||||
|
pthread_cond_signal(&cond); |
||||
|
pthread_mutex_unlock(&mutex); |
||||
|
} |
||||
|
|
||||
|
- (void) do |
||||
|
{ |
||||
|
pthread_mutex_init(&mutex, NULL); |
||||
|
pthread_cond_init(&cond, NULL); |
||||
|
[[[NSThread alloc] initWithTarget:self selector:@selector(runOnce) object:nil] start]; |
||||
|
pthread_mutex_lock(&mutex); |
||||
|
pthread_cond_wait(&cond, &mutex); |
||||
|
pthread_mutex_unlock(&mutex); |
||||
|
pthread_cond_destroy(&cond); |
||||
|
pthread_mutex_destroy(&mutex); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
@end |
||||
|
|
||||
|
|
||||
|
class AvaloniaNative : public ComSingleObject<IAvaloniaNativeFactory, &IID_IAvaloniaNativeFactory> |
||||
|
{ |
||||
|
|
||||
|
public: |
||||
|
FORWARD_IUNKNOWN() |
||||
|
virtual HRESULT Initialize() |
||||
|
{ |
||||
|
@autoreleasepool{ |
||||
|
[[ThreadingInitializer new] do]; |
||||
|
return S_OK; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
virtual IAvnMacOptions* GetMacOptions() |
||||
|
{ |
||||
|
return (IAvnMacOptions*)new MacOptions(); |
||||
|
} |
||||
|
|
||||
|
virtual HRESULT CreateWindow(IAvnWindowEvents* cb, IAvnWindow** ppv) |
||||
|
{ |
||||
|
if(cb == nullptr || ppv == nullptr) |
||||
|
return E_POINTER; |
||||
|
*ppv = CreateAvnWindow(cb); |
||||
|
return S_OK; |
||||
|
}; |
||||
|
|
||||
|
virtual HRESULT CreatePopup(IAvnWindowEvents* cb, IAvnPopup** ppv) |
||||
|
{ |
||||
|
if(cb == nullptr || ppv == nullptr) |
||||
|
return E_POINTER; |
||||
|
|
||||
|
*ppv = CreateAvnPopup(cb); |
||||
|
return S_OK; |
||||
|
} |
||||
|
|
||||
|
virtual HRESULT CreatePlatformThreadingInterface(IAvnPlatformThreadingInterface** ppv) |
||||
|
{ |
||||
|
*ppv = CreatePlatformThreading(); |
||||
|
return S_OK; |
||||
|
} |
||||
|
|
||||
|
virtual HRESULT CreateSystemDialogs(IAvnSystemDialogs** ppv) |
||||
|
{ |
||||
|
*ppv = ::CreateSystemDialogs(); |
||||
|
return S_OK; |
||||
|
} |
||||
|
|
||||
|
virtual HRESULT CreateScreens (IAvnScreens** ppv) |
||||
|
{ |
||||
|
*ppv = ::CreateScreens (); |
||||
|
return S_OK; |
||||
|
} |
||||
|
|
||||
|
virtual HRESULT CreateClipboard(IAvnClipboard** ppv) |
||||
|
{ |
||||
|
*ppv = ::CreateClipboard (); |
||||
|
return S_OK; |
||||
|
} |
||||
|
|
||||
|
virtual HRESULT CreateCursorFactory(IAvnCursorFactory** ppv) |
||||
|
{ |
||||
|
*ppv = ::CreateCursorFactory(); |
||||
|
return S_OK; |
||||
|
} |
||||
|
|
||||
|
virtual HRESULT ObtainGlFeature(IAvnGlFeature** ppv) |
||||
|
{ |
||||
|
auto rv = ::GetGlFeature(); |
||||
|
if(rv == NULL) |
||||
|
return E_FAIL; |
||||
|
rv->AddRef(); |
||||
|
*ppv = rv; |
||||
|
return S_OK; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative() |
||||
|
{ |
||||
|
return new AvaloniaNative(); |
||||
|
}; |
||||
|
|
||||
|
NSSize ToNSSize (AvnSize s) |
||||
|
{ |
||||
|
NSSize result; |
||||
|
result.width = s.Width; |
||||
|
result.height = s.Height; |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
NSPoint ToNSPoint (AvnPoint p) |
||||
|
{ |
||||
|
NSPoint result; |
||||
|
result.x = p.X; |
||||
|
result.y = p.Y; |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
AvnPoint ToAvnPoint (NSPoint p) |
||||
|
{ |
||||
|
AvnPoint result; |
||||
|
result.X = p.x; |
||||
|
result.Y = p.y; |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
AvnPoint ConvertPointY (AvnPoint p) |
||||
|
{ |
||||
|
auto sw = [NSScreen.screens objectAtIndex:0].frame; |
||||
|
|
||||
|
auto t = MAX(sw.origin.y, sw.origin.y + sw.size.height); |
||||
|
p.Y = t - p.Y; |
||||
|
|
||||
|
return p; |
||||
|
} |
||||
@ -0,0 +1,190 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved. |
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information. |
||||
|
|
||||
|
#include "common.h" |
||||
|
|
||||
|
class PlatformThreadingInterface; |
||||
|
@interface Signaler : NSObject |
||||
|
-(void) setParent: (PlatformThreadingInterface*)parent; |
||||
|
-(void) signal: (int) priority; |
||||
|
-(Signaler*) init; |
||||
|
@end |
||||
|
|
||||
|
|
||||
|
@interface ActionCallback : NSObject |
||||
|
- (ActionCallback*) initWithCallback: (IAvnActionCallback*) callback; |
||||
|
- (void) action; |
||||
|
@end |
||||
|
|
||||
|
@implementation ActionCallback |
||||
|
{ |
||||
|
ComPtr<IAvnActionCallback> _callback; |
||||
|
|
||||
|
} |
||||
|
- (ActionCallback*) initWithCallback: (IAvnActionCallback*) callback |
||||
|
{ |
||||
|
_callback = callback; |
||||
|
return self; |
||||
|
} |
||||
|
|
||||
|
- (void) action |
||||
|
{ |
||||
|
_callback->Run(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
@end |
||||
|
|
||||
|
class TimerWrapper : public ComUnknownObject |
||||
|
{ |
||||
|
NSTimer* _timer; |
||||
|
public: |
||||
|
TimerWrapper(IAvnActionCallback* callback, int ms) |
||||
|
{ |
||||
|
auto cb = [[ActionCallback alloc] initWithCallback:callback]; |
||||
|
_timer = [NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval)(double)ms/1000 target:cb selector:@selector(action) userInfo:nullptr repeats:true]; |
||||
|
} |
||||
|
|
||||
|
virtual ~TimerWrapper() |
||||
|
{ |
||||
|
[_timer invalidate]; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
|
||||
|
class PlatformThreadingInterface : public ComSingleObject<IAvnPlatformThreadingInterface, &IID_IAvnPlatformThreadingInterface> |
||||
|
{ |
||||
|
private: |
||||
|
Signaler* _signaler; |
||||
|
|
||||
|
class LoopCancellation : public ComSingleObject<IAvnLoopCancellation, &IID_IAvnLoopCancellation> |
||||
|
{ |
||||
|
public: |
||||
|
FORWARD_IUNKNOWN() |
||||
|
bool Cancelled = 0; |
||||
|
virtual void Cancel() |
||||
|
{ |
||||
|
Cancelled = 1; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
public: |
||||
|
FORWARD_IUNKNOWN() |
||||
|
ComPtr<IAvnSignaledCallback> SignaledCallback; |
||||
|
|
||||
|
PlatformThreadingInterface() |
||||
|
{ |
||||
|
_signaler = [Signaler new]; |
||||
|
[_signaler setParent:this]; |
||||
|
} |
||||
|
|
||||
|
~PlatformThreadingInterface() |
||||
|
{ |
||||
|
if(_signaler) |
||||
|
[_signaler setParent: NULL]; |
||||
|
_signaler = NULL; |
||||
|
} |
||||
|
|
||||
|
virtual bool GetCurrentThreadIsLoopThread() |
||||
|
{ |
||||
|
return [[NSThread currentThread] isMainThread]; |
||||
|
} |
||||
|
virtual void SetSignaledCallback(IAvnSignaledCallback* cb) |
||||
|
{ |
||||
|
SignaledCallback = cb; |
||||
|
} |
||||
|
virtual IAvnLoopCancellation* CreateLoopCancellation() |
||||
|
{ |
||||
|
return new LoopCancellation(); |
||||
|
} |
||||
|
|
||||
|
virtual void RunLoop(IAvnLoopCancellation* cancel) |
||||
|
{ |
||||
|
@autoreleasepool { |
||||
|
auto can = dynamic_cast<LoopCancellation*>(cancel); |
||||
|
[[NSApplication sharedApplication] activateIgnoringOtherApps:true]; |
||||
|
while(true) |
||||
|
{ |
||||
|
@autoreleasepool |
||||
|
{ |
||||
|
if(can != NULL && can->Cancelled) |
||||
|
return; |
||||
|
NSEvent* ev = [[NSApplication sharedApplication] |
||||
|
nextEventMatchingMask:NSEventMaskAny |
||||
|
untilDate: [NSDate dateWithTimeIntervalSinceNow:1] |
||||
|
inMode:NSDefaultRunLoopMode |
||||
|
dequeue:true]; |
||||
|
if(can != NULL && can->Cancelled) |
||||
|
return; |
||||
|
if(ev != NULL) |
||||
|
[[NSApplication sharedApplication] sendEvent:ev]; |
||||
|
} |
||||
|
} |
||||
|
NSDebugLog(@"RunLoop exited"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
virtual void Signal(int priority) |
||||
|
{ |
||||
|
[_signaler signal:priority]; |
||||
|
} |
||||
|
|
||||
|
virtual IUnknown* StartTimer(int priority, int ms, IAvnActionCallback* callback) |
||||
|
{ |
||||
|
@autoreleasepool { |
||||
|
|
||||
|
return new TimerWrapper(callback, ms); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
@implementation Signaler |
||||
|
|
||||
|
PlatformThreadingInterface* _parent = 0; |
||||
|
bool _signaled = 0; |
||||
|
NSArray<NSString*>* _modes; |
||||
|
|
||||
|
-(Signaler*) init |
||||
|
{ |
||||
|
if(self = [super init]) |
||||
|
{ |
||||
|
_modes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEventTrackingRunLoopMode, NSModalPanelRunLoopMode, NSRunLoopCommonModes, NSConnectionReplyMode, nil]; |
||||
|
} |
||||
|
return self; |
||||
|
} |
||||
|
|
||||
|
-(void) perform |
||||
|
{ |
||||
|
@synchronized (self) { |
||||
|
_signaled = false; |
||||
|
if(_parent != NULL && _parent->SignaledCallback != NULL) |
||||
|
_parent->SignaledCallback->Signaled(0, false); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
-(void) setParent:(PlatformThreadingInterface *)parent |
||||
|
{ |
||||
|
@synchronized (self) { |
||||
|
_parent = parent; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
-(void) signal: (int) priority |
||||
|
{ |
||||
|
|
||||
|
@synchronized (self) { |
||||
|
if(_signaled) |
||||
|
return; |
||||
|
_signaled = true; |
||||
|
[self performSelector:@selector(perform) onThread:[NSThread mainThread] withObject:NULL waitUntilDone:false modes:_modes]; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
@end |
||||
|
|
||||
|
|
||||
|
extern IAvnPlatformThreadingInterface* CreatePlatformThreading() |
||||
|
{ |
||||
|
return new PlatformThreadingInterface(); |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
#ifndef window_h |
||||
|
#define window_h |
||||
|
|
||||
|
class WindowBaseImpl; |
||||
|
|
||||
|
@interface AvnView : NSView<NSTextInputClient> |
||||
|
-(AvnView* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent; |
||||
|
-(NSEvent* _Nonnull) lastMouseDownEvent; |
||||
|
-(AvnPoint) translateLocalPoint:(AvnPoint)pt; |
||||
|
-(void) setSwRenderedFrame: (AvnFramebuffer* _Nonnull) fb dispose: (IUnknown* _Nonnull) dispose; |
||||
|
-(void) onClosed; |
||||
|
@end |
||||
|
|
||||
|
@interface AvnWindow : NSWindow <NSWindowDelegate> |
||||
|
-(AvnWindow* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent; |
||||
|
-(void) setCanBecomeKeyAndMain; |
||||
|
-(void) pollModalSession: (NSModalSession _Nonnull) session; |
||||
|
@end |
||||
|
|
||||
|
struct INSWindowHolder |
||||
|
{ |
||||
|
virtual AvnWindow* _Nonnull GetNSWindow () = 0; |
||||
|
}; |
||||
|
|
||||
|
struct IWindowStateChanged |
||||
|
{ |
||||
|
virtual void WindowStateChanged () = 0; |
||||
|
}; |
||||
|
|
||||
|
#endif /* window_h */ |
||||
File diff suppressed because it is too large
@ -0,0 +1 @@ |
|||||
|
Generated |
||||
@ -0,0 +1,22 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<CastXmlPath Condition="Exists('/usr/bin/castxml')">/usr/bin/castxml</CastXmlPath> |
||||
|
<CastXmlPath Condition="Exists('/usr/local/bin/castxml')">/usr/local/bin/castxml</CastXmlPath> |
||||
|
|
||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> |
||||
|
<SharpGenGeneratedCodeFolder>$(MSBuildThisFileDirectory)/Generated</SharpGenGeneratedCodeFolder> |
||||
|
</PropertyGroup> |
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="SharpGenTools.Sdk" Version="1.1.2" PrivateAssets="all" /> |
||||
|
<PackageReference Include="SharpGen.Runtime.Com" Version="1.1.0" /> |
||||
|
<SharpGenMapping Include="Mappings.xml" /> |
||||
|
<ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" /> |
||||
|
<ProjectReference Include="..\Avalonia.Controls\Avalonia.Controls.csproj" /> |
||||
|
<ProjectReference Include="..\Avalonia.Input\Avalonia.Input.csproj" /> |
||||
|
<ProjectReference Include="..\Avalonia.Interactivity\Avalonia.Interactivity.csproj" /> |
||||
|
<ProjectReference Include="..\Avalonia.OpenGL\Avalonia.OpenGL.csproj" /> |
||||
|
<ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" /> |
||||
|
</ItemGroup> |
||||
|
</Project> |
||||
@ -0,0 +1,9 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
|
<ItemGroup> |
||||
|
<None Include="$(MSBuildThisFileDirectory)..\..\runtimes\osx-x64\native\libAvalonia.Native.OSX.dylib"> |
||||
|
<Link>libAvalonia.Native.OSX.dylib</Link> |
||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
||||
|
</None> |
||||
|
</ItemGroup> |
||||
|
</Project> |
||||
@ -0,0 +1,132 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
using System; |
||||
|
using System.Diagnostics.Contracts; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using Avalonia.Controls.Platform; |
||||
|
using Avalonia.Input; |
||||
|
using Avalonia.Input.Platform; |
||||
|
using Avalonia.Native.Interop; |
||||
|
using Avalonia.OpenGL; |
||||
|
using Avalonia.Platform; |
||||
|
using Avalonia.Rendering; |
||||
|
|
||||
|
namespace Avalonia.Native |
||||
|
{ |
||||
|
class AvaloniaNativePlatform : IPlatformSettings, IWindowingPlatform |
||||
|
{ |
||||
|
private readonly IAvaloniaNativeFactory _factory; |
||||
|
|
||||
|
[DllImport("libAvaloniaNative")] |
||||
|
static extern IntPtr CreateAvaloniaNative(); |
||||
|
|
||||
|
internal static readonly MouseDevice MouseDevice = new MouseDevice(); |
||||
|
internal static readonly KeyboardDevice KeyboardDevice = new KeyboardDevice(); |
||||
|
|
||||
|
public Size DoubleClickSize => new Size(4, 4); |
||||
|
|
||||
|
public TimeSpan DoubleClickTime => TimeSpan.FromMilliseconds(500); //TODO
|
||||
|
|
||||
|
public static void Initialize(IntPtr factory, Action<AvaloniaNativeOptions> configure) |
||||
|
{ |
||||
|
new AvaloniaNativePlatform(new IAvaloniaNativeFactory(factory)) |
||||
|
.DoInitialize(configure); |
||||
|
} |
||||
|
|
||||
|
delegate IntPtr CreateAvaloniaNativeDelegate(); |
||||
|
|
||||
|
public static void Initialize(string library, Action<AvaloniaNativeOptions> configure) |
||||
|
{ |
||||
|
var loader = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) |
||||
|
? (IDynLoader)new Win32Loader() : new UnixLoader(); |
||||
|
var lib = loader.LoadLibrary(library); |
||||
|
var proc = loader.GetProcAddress(lib, "CreateAvaloniaNative", false); |
||||
|
var d = Marshal.GetDelegateForFunctionPointer<CreateAvaloniaNativeDelegate>(proc); |
||||
|
|
||||
|
|
||||
|
Initialize(d(), configure); |
||||
|
} |
||||
|
|
||||
|
public static void Initialize(Action<AvaloniaNativeOptions> configure) |
||||
|
{ |
||||
|
Initialize(CreateAvaloniaNative(), configure); |
||||
|
} |
||||
|
|
||||
|
private AvaloniaNativePlatform(IAvaloniaNativeFactory factory) |
||||
|
{ |
||||
|
_factory = factory; |
||||
|
} |
||||
|
|
||||
|
void DoInitialize(Action<AvaloniaNativeOptions> configure) |
||||
|
{ |
||||
|
var opts = new AvaloniaNativeOptions(_factory); |
||||
|
configure?.Invoke(opts); |
||||
|
_factory.Initialize(); |
||||
|
|
||||
|
AvaloniaLocator.CurrentMutable |
||||
|
.Bind<IPlatformThreadingInterface>().ToConstant(new PlatformThreadingInterface(_factory.CreatePlatformThreadingInterface())) |
||||
|
.Bind<IStandardCursorFactory>().ToConstant(new CursorFactory(_factory.CreateCursorFactory())) |
||||
|
.Bind<IPlatformIconLoader>().ToSingleton<IconLoader>() |
||||
|
.Bind<IKeyboardDevice>().ToConstant(KeyboardDevice) |
||||
|
.Bind<IMouseDevice>().ToConstant(MouseDevice) |
||||
|
.Bind<IPlatformSettings>().ToConstant(this) |
||||
|
.Bind<IWindowingPlatform>().ToConstant(this) |
||||
|
.Bind<IClipboard>().ToConstant(new ClipboardImpl(_factory.CreateClipboard())) |
||||
|
.Bind<IRenderLoop>().ToConstant(new RenderLoop()) |
||||
|
.Bind<IRenderTimer>().ToConstant(new DefaultRenderTimer(60)) |
||||
|
.Bind<ISystemDialogImpl>().ToConstant(new SystemDialogs(_factory.CreateSystemDialogs())) |
||||
|
.Bind<IWindowingPlatformGlFeature>().ToConstant(new GlPlatformFeature(_factory.ObtainGlFeature())) |
||||
|
.Bind<AvaloniaNativeOptions>().ToConstant(opts); |
||||
|
} |
||||
|
|
||||
|
public IWindowImpl CreateWindow() |
||||
|
{ |
||||
|
return new WindowImpl(_factory); |
||||
|
} |
||||
|
|
||||
|
public IEmbeddableWindowImpl CreateEmbeddableWindow() |
||||
|
{ |
||||
|
throw new NotImplementedException(); |
||||
|
} |
||||
|
|
||||
|
public IPopupImpl CreatePopup() |
||||
|
{ |
||||
|
return new PopupImpl(_factory); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class AvaloniaNativeMacOptions |
||||
|
{ |
||||
|
private readonly IAvnMacOptions _opts; |
||||
|
private bool _showInDock; |
||||
|
internal AvaloniaNativeMacOptions(IAvnMacOptions opts) |
||||
|
{ |
||||
|
_opts = opts; |
||||
|
ShowInDock = true; |
||||
|
} |
||||
|
|
||||
|
public bool ShowInDock |
||||
|
{ |
||||
|
get => _showInDock; |
||||
|
set |
||||
|
{ |
||||
|
_showInDock = value; |
||||
|
_opts.ShowInDock = value ? 1 : 0; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class AvaloniaNativeOptions |
||||
|
{ |
||||
|
public AvaloniaNativeMacOptions MacOptions { get; set; } |
||||
|
public bool UseDeferredRendering { get; set; } = true; |
||||
|
public bool UseGpu { get; set; } = false; |
||||
|
internal AvaloniaNativeOptions(IAvaloniaNativeFactory factory) |
||||
|
{ |
||||
|
var mac = factory.GetMacOptions(); |
||||
|
if (mac != null) |
||||
|
MacOptions = new AvaloniaNativeMacOptions(mac); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Native; |
||||
|
|
||||
|
namespace Avalonia |
||||
|
{ |
||||
|
public static class AvaloniaNativePlatformExtensions |
||||
|
{ |
||||
|
public static T UseAvaloniaNative<T>(this T builder, |
||||
|
string libraryPath = null, |
||||
|
Action<AvaloniaNativeOptions> configure = null) |
||||
|
where T : AppBuilderBase<T>, new() |
||||
|
{ |
||||
|
if (libraryPath == null) |
||||
|
{ |
||||
|
builder.UseWindowingSubsystem(() => AvaloniaNativePlatform.Initialize(configure)); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
builder.UseWindowingSubsystem(() => AvaloniaNativePlatform.Initialize(libraryPath, configure)); |
||||
|
} |
||||
|
|
||||
|
return builder; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,80 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
using SharpGen.Runtime; |
||||
|
|
||||
|
namespace Avalonia.Native |
||||
|
{ |
||||
|
public class CallbackBase : SharpGen.Runtime.IUnknown |
||||
|
{ |
||||
|
private uint _refCount; |
||||
|
private bool _disposed; |
||||
|
private readonly object _lock = new object(); |
||||
|
private ShadowContainer _shadow; |
||||
|
|
||||
|
public CallbackBase() |
||||
|
{ |
||||
|
_refCount = 1; |
||||
|
} |
||||
|
|
||||
|
public ShadowContainer Shadow |
||||
|
{ |
||||
|
get => _shadow; |
||||
|
set |
||||
|
{ |
||||
|
lock (_lock) |
||||
|
{ |
||||
|
if (_disposed && value != null) |
||||
|
{ |
||||
|
throw new ObjectDisposedException("CallbackBase"); |
||||
|
} |
||||
|
|
||||
|
_shadow = value; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public uint AddRef() |
||||
|
{ |
||||
|
lock (_lock) |
||||
|
{ |
||||
|
return ++_refCount; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
lock (_lock) |
||||
|
{ |
||||
|
if (!_disposed) |
||||
|
{ |
||||
|
_disposed = true; |
||||
|
Release(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public uint Release() |
||||
|
{ |
||||
|
lock (_lock) |
||||
|
{ |
||||
|
_refCount--; |
||||
|
|
||||
|
if (_refCount == 0) |
||||
|
{ |
||||
|
Shadow?.Dispose(); |
||||
|
Shadow = null; |
||||
|
Destroyed(); |
||||
|
} |
||||
|
|
||||
|
return _refCount; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual void Destroyed() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System.Threading.Tasks; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using Avalonia.Input.Platform; |
||||
|
using Avalonia.Native.Interop; |
||||
|
|
||||
|
namespace Avalonia.Native |
||||
|
{ |
||||
|
class ClipboardImpl : IClipboard |
||||
|
{ |
||||
|
private IAvnClipboard _native; |
||||
|
|
||||
|
public ClipboardImpl(IAvnClipboard native) |
||||
|
{ |
||||
|
_native = native; |
||||
|
} |
||||
|
|
||||
|
public Task ClearAsync() |
||||
|
{ |
||||
|
_native.Clear(); |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
|
||||
|
public Task<string> GetTextAsync() |
||||
|
{ |
||||
|
var outPtr = _native.GetText(); |
||||
|
var text = Marshal.PtrToStringAnsi(outPtr); |
||||
|
|
||||
|
return Task.FromResult(text); |
||||
|
} |
||||
|
|
||||
|
public Task SetTextAsync(string text) |
||||
|
{ |
||||
|
_native.Clear(); |
||||
|
|
||||
|
if (text != null) |
||||
|
{ |
||||
|
_native.SetText(text); |
||||
|
} |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,45 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
using Avalonia.Input; |
||||
|
using Avalonia.Platform; |
||||
|
using Avalonia.Native.Interop; |
||||
|
|
||||
|
namespace Avalonia.Native |
||||
|
{ |
||||
|
class AvaloniaNativeCursor : IPlatformHandle, IDisposable |
||||
|
{ |
||||
|
public IAvnCursor Cursor { get; private set; } |
||||
|
public IntPtr Handle => IntPtr.Zero; |
||||
|
|
||||
|
public string HandleDescriptor => "<none>"; |
||||
|
|
||||
|
public AvaloniaNativeCursor(IAvnCursor cursor) |
||||
|
{ |
||||
|
Cursor = cursor; |
||||
|
} |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
Cursor.Dispose(); |
||||
|
Cursor = null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class CursorFactory : IStandardCursorFactory |
||||
|
{ |
||||
|
IAvnCursorFactory _native; |
||||
|
|
||||
|
public CursorFactory(IAvnCursorFactory native) |
||||
|
{ |
||||
|
_native = native; |
||||
|
} |
||||
|
|
||||
|
public IPlatformHandle GetCursor(StandardCursorType cursorType) |
||||
|
{ |
||||
|
var cursor = _native.GetCursor((AvnStandardCursorType)cursorType); |
||||
|
return new AvaloniaNativeCursor( cursor ); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,87 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,108 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Avalonia.Native.Interop; |
||||
|
using Avalonia.Rendering; |
||||
|
using Avalonia.VisualTree; |
||||
|
|
||||
|
namespace Avalonia.Native |
||||
|
{ |
||||
|
public class DeferredRendererProxy : IRenderer, IRenderLoopTask, IRenderLoop |
||||
|
{ |
||||
|
public DeferredRendererProxy(IRenderRoot root, IAvnWindowBase window) |
||||
|
{ |
||||
|
if (window != null) |
||||
|
{ |
||||
|
_useLock = true; |
||||
|
window.AddRef(); |
||||
|
_window = new IAvnWindowBase(window.NativePointer); |
||||
|
} |
||||
|
_renderer = new DeferredRenderer(root, this); |
||||
|
_rendererTask = (IRenderLoopTask)_renderer; |
||||
|
} |
||||
|
|
||||
|
void IRenderLoop.Add(IRenderLoopTask i) |
||||
|
{ |
||||
|
AvaloniaLocator.Current.GetService<IRenderLoop>().Add(this); |
||||
|
} |
||||
|
|
||||
|
void IRenderLoop.Remove(IRenderLoopTask i) |
||||
|
{ |
||||
|
AvaloniaLocator.Current.GetService<IRenderLoop>().Remove(this); |
||||
|
} |
||||
|
|
||||
|
private DeferredRenderer _renderer; |
||||
|
private IRenderLoopTask _rendererTask; |
||||
|
private IAvnWindowBase _window; |
||||
|
private bool _useLock; |
||||
|
|
||||
|
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(); |
||||
|
_window?.Dispose(); |
||||
|
_window = null; |
||||
|
} |
||||
|
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() |
||||
|
{ |
||||
|
if(_useLock) |
||||
|
{ |
||||
|
_rendererTask.Render(); |
||||
|
return; |
||||
|
} |
||||
|
if (_window == null) |
||||
|
return; |
||||
|
if (!_window.TryLock()) |
||||
|
return; |
||||
|
try |
||||
|
{ |
||||
|
_rendererTask.Render(); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
_window.Unlock(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,128 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Runtime.InteropServices; |
||||
|
|
||||
|
/* |
||||
|
* Source code imported from https://github.com/kekekeks/evhttp-sharp
|
||||
|
* Source is provided under MIT license for Avalonia project and derived works |
||||
|
*/ |
||||
|
|
||||
|
namespace Avalonia.Native |
||||
|
{ |
||||
|
internal interface IDynLoader |
||||
|
{ |
||||
|
IntPtr LoadLibrary(string dll); |
||||
|
IntPtr GetProcAddress(IntPtr dll, string proc, bool optional); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
class UnixLoader : IDynLoader |
||||
|
{ |
||||
|
// ReSharper disable InconsistentNaming
|
||||
|
static class LinuxImports |
||||
|
{ |
||||
|
[DllImport("libdl.so.2")] |
||||
|
private static extern IntPtr dlopen(string path, int flags); |
||||
|
|
||||
|
[DllImport("libdl.so.2")] |
||||
|
private static extern IntPtr dlsym(IntPtr handle, string symbol); |
||||
|
|
||||
|
[DllImport("libdl.so.2")] |
||||
|
private static extern IntPtr dlerror(); |
||||
|
|
||||
|
public static void Init() |
||||
|
{ |
||||
|
DlOpen = dlopen; |
||||
|
DlSym = dlsym; |
||||
|
DlError = dlerror; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static class OsXImports |
||||
|
{ |
||||
|
[DllImport("/usr/lib/libSystem.dylib")] |
||||
|
private static extern IntPtr dlopen(string path, int flags); |
||||
|
|
||||
|
[DllImport("/usr/lib/libSystem.dylib")] |
||||
|
private static extern IntPtr dlsym(IntPtr handle, string symbol); |
||||
|
|
||||
|
[DllImport("/usr/lib/libSystem.dylib")] |
||||
|
private static extern IntPtr dlerror(); |
||||
|
|
||||
|
public static void Init() |
||||
|
{ |
||||
|
DlOpen = dlopen; |
||||
|
DlSym = dlsym; |
||||
|
DlError = dlerror; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
[DllImport("libc")] |
||||
|
static extern int uname(IntPtr buf); |
||||
|
|
||||
|
static UnixLoader() |
||||
|
{ |
||||
|
var buffer = Marshal.AllocHGlobal(0x1000); |
||||
|
uname(buffer); |
||||
|
var unixName = Marshal.PtrToStringAnsi(buffer); |
||||
|
Marshal.FreeHGlobal(buffer); |
||||
|
if (unixName == "Darwin") |
||||
|
OsXImports.Init(); |
||||
|
else |
||||
|
LinuxImports.Init(); |
||||
|
} |
||||
|
|
||||
|
private static Func<string, int, IntPtr> DlOpen; |
||||
|
private static Func<IntPtr, string, IntPtr> DlSym; |
||||
|
private static Func<IntPtr> DlError; |
||||
|
// ReSharper restore InconsistentNaming
|
||||
|
|
||||
|
static string DlErrorString() => Marshal.PtrToStringAnsi(DlError()); |
||||
|
|
||||
|
public IntPtr LoadLibrary(string dll) |
||||
|
{ |
||||
|
var handle = DlOpen(dll, 1); |
||||
|
if (handle == IntPtr.Zero) |
||||
|
throw new Exception(DlErrorString()); |
||||
|
return handle; |
||||
|
} |
||||
|
|
||||
|
public IntPtr GetProcAddress(IntPtr dll, string proc, bool optional) |
||||
|
{ |
||||
|
var ptr = DlSym(dll, proc); |
||||
|
if (ptr == IntPtr.Zero && !optional) |
||||
|
throw new Exception(DlErrorString()); |
||||
|
return ptr; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
internal class Win32Loader : IDynLoader |
||||
|
{ |
||||
|
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] |
||||
|
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName); |
||||
|
|
||||
|
[DllImport("kernel32", EntryPoint = "LoadLibraryW", SetLastError = true, CharSet = CharSet.Unicode)] |
||||
|
private static extern IntPtr LoadLibrary(string lpszLib); |
||||
|
|
||||
|
IntPtr IDynLoader.LoadLibrary(string dll) |
||||
|
{ |
||||
|
var handle = LoadLibrary(dll); |
||||
|
if (handle != IntPtr.Zero) |
||||
|
return handle; |
||||
|
var err = Marshal.GetLastWin32Error(); |
||||
|
|
||||
|
throw new Exception("Error loading " + dll + " error " + err); |
||||
|
} |
||||
|
|
||||
|
IntPtr IDynLoader.GetProcAddress(IntPtr dll, string proc, bool optional) |
||||
|
{ |
||||
|
var ptr = GetProcAddress(dll, proc); |
||||
|
if (ptr == IntPtr.Zero && !optional) |
||||
|
throw new Exception("Error " + Marshal.GetLastWin32Error()); |
||||
|
return ptr; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,134 @@ |
|||||
|
using System; |
||||
|
using Avalonia.OpenGL; |
||||
|
using Avalonia.Native.Interop; |
||||
|
using System.Drawing; |
||||
|
using Avalonia.Threading; |
||||
|
|
||||
|
namespace Avalonia.Native |
||||
|
{ |
||||
|
class GlPlatformFeature : IWindowingPlatformGlFeature |
||||
|
{ |
||||
|
|
||||
|
public GlPlatformFeature(IAvnGlFeature feature) |
||||
|
{ |
||||
|
Display = new GlDisplay(feature.ObtainDisplay()); |
||||
|
ImmediateContext = new GlContext(Display, feature.ObtainImmediateContext()); |
||||
|
} |
||||
|
|
||||
|
public IGlContext ImmediateContext { get; } |
||||
|
public GlDisplay Display { get; } |
||||
|
} |
||||
|
|
||||
|
class GlDisplay : IGlDisplay |
||||
|
{ |
||||
|
private readonly IAvnGlDisplay _display; |
||||
|
|
||||
|
public GlDisplay(IAvnGlDisplay display) |
||||
|
{ |
||||
|
_display = display; |
||||
|
GlInterface = new GlInterface((name, optional) => |
||||
|
{ |
||||
|
var rv = _display.GetProcAddress(name); |
||||
|
if (rv == IntPtr.Zero && !optional) |
||||
|
throw new OpenGlException($"{name} not found in system OpenGL"); |
||||
|
return rv; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public GlDisplayType Type => GlDisplayType.OpenGL2; |
||||
|
|
||||
|
public GlInterface GlInterface { get; } |
||||
|
|
||||
|
public int SampleCount => _display.GetSampleCount(); |
||||
|
|
||||
|
public int StencilSize => _display.GetStencilSize(); |
||||
|
|
||||
|
public void ClearContext() => _display.ClearContext(); |
||||
|
} |
||||
|
|
||||
|
class GlContext : IGlContext |
||||
|
{ |
||||
|
public IAvnGlContext Context { get; } |
||||
|
|
||||
|
public GlContext(GlDisplay display, IAvnGlContext context) |
||||
|
{ |
||||
|
Display = display; |
||||
|
Context = context; |
||||
|
} |
||||
|
|
||||
|
public IGlDisplay Display { get; } |
||||
|
|
||||
|
public void MakeCurrent(IGlSurface surface) |
||||
|
{ |
||||
|
if (surface != null) |
||||
|
throw new ArgumentException(nameof(surface)); |
||||
|
Context.MakeCurrent(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
class GlPlatformSurfaceRenderTarget : IGlPlatformSurfaceRenderTarget |
||||
|
{ |
||||
|
private IAvnGlSurfaceRenderTarget _target; |
||||
|
public GlPlatformSurfaceRenderTarget(IAvnGlSurfaceRenderTarget target) |
||||
|
{ |
||||
|
_target = target; |
||||
|
} |
||||
|
|
||||
|
public IGlPlatformSurfaceRenderingSession BeginDraw() |
||||
|
{ |
||||
|
var feature = (GlPlatformFeature)AvaloniaLocator.Current.GetService<IWindowingPlatformGlFeature>(); |
||||
|
return new GlPlatformSurfaceRenderingSession(feature.Display, _target.BeginDrawing()); |
||||
|
} |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
_target?.Dispose(); |
||||
|
_target = null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class GlPlatformSurfaceRenderingSession : IGlPlatformSurfaceRenderingSession |
||||
|
{ |
||||
|
private IAvnGlSurfaceRenderingSession _session; |
||||
|
|
||||
|
public GlPlatformSurfaceRenderingSession(GlDisplay display, IAvnGlSurfaceRenderingSession session) |
||||
|
{ |
||||
|
Display = display; |
||||
|
_session = session; |
||||
|
} |
||||
|
|
||||
|
public IGlDisplay Display { get; } |
||||
|
|
||||
|
public System.Drawing.Size PixelSize |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
var s = _session.GetPixelSize(); |
||||
|
return new System.Drawing.Size(s.Width, s.Height); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public double Scaling => _session.GetScaling(); |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
_session?.Dispose(); |
||||
|
_session = null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class GlPlatformSurface : IGlPlatformSurface |
||||
|
{ |
||||
|
private readonly IAvnWindowBase _window; |
||||
|
|
||||
|
public GlPlatformSurface(IAvnWindowBase window) |
||||
|
{ |
||||
|
_window = window; |
||||
|
} |
||||
|
public IGlPlatformSurfaceRenderTarget CreateGlRenderTarget() |
||||
|
{ |
||||
|
return new GlPlatformSurfaceRenderTarget(_window.CreateGlRenderTarget()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using Avalonia.Native.Interop; |
||||
|
|
||||
|
namespace Avalonia.Native |
||||
|
{ |
||||
|
public static class Helpers |
||||
|
{ |
||||
|
public static Point ToAvaloniaPoint (this AvnPoint pt) |
||||
|
{ |
||||
|
return new Point(pt.X, pt.Y); |
||||
|
} |
||||
|
|
||||
|
public static AvnPoint ToAvnPoint (this Point pt) |
||||
|
{ |
||||
|
return new AvnPoint { X = pt.X, Y = pt.Y }; |
||||
|
} |
||||
|
|
||||
|
public static AvnSize ToAvnSize (this Size size) |
||||
|
{ |
||||
|
return new AvnSize { Height = size.Height, Width = size.Width }; |
||||
|
} |
||||
|
|
||||
|
public static Size ToAvaloniaSize (this AvnSize size) |
||||
|
{ |
||||
|
return new Size(size.Width, size.Height); |
||||
|
} |
||||
|
|
||||
|
public static Rect ToAvaloniaRect (this AvnRect rect) |
||||
|
{ |
||||
|
return new Rect(rect.X, rect.Y, rect.Width, rect.Height); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,50 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System.IO; |
||||
|
using Avalonia.Platform; |
||||
|
|
||||
|
namespace Avalonia.Native |
||||
|
{ |
||||
|
// OSX doesn't have a concept of *window* icon.
|
||||
|
// Icons in the title bar are only shown if there is
|
||||
|
// an opened file (on disk) associated with the current window
|
||||
|
// see http://stackoverflow.com/a/7038671/2231814
|
||||
|
class IconLoader : IPlatformIconLoader |
||||
|
{ |
||||
|
class IconStub : IWindowIconImpl |
||||
|
{ |
||||
|
private readonly IBitmapImpl _bitmap; |
||||
|
|
||||
|
public IconStub(IBitmapImpl bitmap) |
||||
|
{ |
||||
|
_bitmap = bitmap; |
||||
|
} |
||||
|
|
||||
|
public void Save(Stream outputStream) |
||||
|
{ |
||||
|
_bitmap.Save(outputStream); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public IWindowIconImpl LoadIcon(string fileName) |
||||
|
{ |
||||
|
return new IconStub( |
||||
|
AvaloniaLocator.Current.GetService<IPlatformRenderInterface>().LoadBitmap(fileName)); |
||||
|
} |
||||
|
|
||||
|
public IWindowIconImpl LoadIcon(Stream stream) |
||||
|
{ |
||||
|
return new IconStub( |
||||
|
AvaloniaLocator.Current.GetService<IPlatformRenderInterface>().LoadBitmap(stream)); |
||||
|
} |
||||
|
|
||||
|
public IWindowIconImpl LoadIcon(IBitmapImpl bitmap) |
||||
|
{ |
||||
|
var ms = new MemoryStream(); |
||||
|
bitmap.Save(ms); |
||||
|
ms.Seek(0, SeekOrigin.Begin); |
||||
|
return LoadIcon(ms); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<config id="AvaloniaNative" xmlns="urn:SharpGen.Config"> |
||||
|
<assembly>Avalonia.Native</assembly> |
||||
|
<namespace>Avalonia.Native.Interop</namespace> |
||||
|
<depends>SharpGen.Runtime.COM</depends> |
||||
|
<include-dir>$(THIS_CONFIG_PATH)/headers</include-dir> |
||||
|
<include file="avalonia-native.h" |
||||
|
namespace="Avalonia.Native.Interop" |
||||
|
attach="true" |
||||
|
pre="#define COM_GUIDS_MATERIALIZE\n"/> |
||||
|
<include file="com.h" |
||||
|
namespace="Avalonia.Native.Interop" |
||||
|
attach="true" |
||||
|
pre="#define COM_GUIDS_MATERIALIZE\n"/> |
||||
|
<bindings> |
||||
|
<bind from="HRESULT" to="SharpGen.Runtime.Result"/> |
||||
|
<bind from="HRESULT" to="SharpGen.Runtime.Result"/> |
||||
|
</bindings> |
||||
|
<mapping> |
||||
|
<remove function=".*" /> |
||||
|
<map interface="*.Events" callback="true" autogen-shadow="true"/> |
||||
|
<map interface="*.Callback" callback="true" autogen-shadow="true"/> |
||||
|
<map param=".*::.*::ppv" return="true"/> |
||||
|
<map param=".*::.*::ret" return="true"/> |
||||
|
<map param=".*::.*::retOut" attribute="out" return="true"/> |
||||
|
</mapping> |
||||
|
</config> |
||||
@ -0,0 +1,101 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Threading; |
||||
|
using Avalonia.Native.Interop; |
||||
|
using Avalonia.Platform; |
||||
|
using Avalonia.Threading; |
||||
|
using SharpGen.Runtime; |
||||
|
|
||||
|
namespace Avalonia.Native |
||||
|
{ |
||||
|
public class PlatformThreadingInterface : IPlatformThreadingInterface |
||||
|
{ |
||||
|
class TimerCallback : CallbackBase, IAvnActionCallback |
||||
|
{ |
||||
|
readonly Action _tick; |
||||
|
|
||||
|
public TimerCallback(Action tick) |
||||
|
{ |
||||
|
_tick = tick; |
||||
|
} |
||||
|
|
||||
|
public void Run() |
||||
|
{ |
||||
|
_tick(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class SignaledCallback : CallbackBase, IAvnSignaledCallback |
||||
|
{ |
||||
|
readonly PlatformThreadingInterface _parent; |
||||
|
|
||||
|
public SignaledCallback(PlatformThreadingInterface parent) |
||||
|
{ |
||||
|
_parent = parent; |
||||
|
} |
||||
|
|
||||
|
public void Signaled(int priority, bool priorityContainsMeaningfulValue) |
||||
|
{ |
||||
|
_parent.Signaled?.Invoke(priorityContainsMeaningfulValue ? (DispatcherPriority?)priority : null); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
readonly IAvnPlatformThreadingInterface _native; |
||||
|
|
||||
|
public PlatformThreadingInterface(IAvnPlatformThreadingInterface native) |
||||
|
{ |
||||
|
_native = native; |
||||
|
using (var cb = new SignaledCallback(this)) |
||||
|
_native.SignaledCallback = cb; |
||||
|
} |
||||
|
|
||||
|
public bool CurrentThreadIsLoopThread => _native.CurrentThreadIsLoopThread; |
||||
|
|
||||
|
public event Action<DispatcherPriority?> Signaled; |
||||
|
|
||||
|
public void RunLoop(CancellationToken cancellationToken) |
||||
|
{ |
||||
|
if (cancellationToken.CanBeCanceled == false) |
||||
|
_native.RunLoop(null); |
||||
|
else |
||||
|
{ |
||||
|
var l = new object(); |
||||
|
var cancellation = _native.CreateLoopCancellation(); |
||||
|
cancellationToken.Register(() => |
||||
|
{ |
||||
|
lock (l) |
||||
|
{ |
||||
|
cancellation?.Cancel(); |
||||
|
cancellation?.Dispose(); |
||||
|
cancellation = null; |
||||
|
} |
||||
|
}); |
||||
|
try |
||||
|
{ |
||||
|
_native.RunLoop(cancellation); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
lock(l) |
||||
|
{ |
||||
|
cancellation?.Dispose(); |
||||
|
cancellation = null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void Signal(DispatcherPriority priority) |
||||
|
{ |
||||
|
_native.Signal((int)priority); |
||||
|
} |
||||
|
|
||||
|
public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick) |
||||
|
{ |
||||
|
using (var cb = new TimerCallback(tick)) |
||||
|
return _native.StartTimer((int)priority, (int)interval.TotalMilliseconds, cb); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
using Avalonia.Native.Interop; |
||||
|
using Avalonia.Platform; |
||||
|
|
||||
|
namespace Avalonia.Native |
||||
|
{ |
||||
|
public class PopupImpl : WindowBaseImpl, IPopupImpl |
||||
|
{ |
||||
|
public PopupImpl(IAvaloniaNativeFactory factory) |
||||
|
{ |
||||
|
using (var e = new PopupEvents(this)) |
||||
|
{ |
||||
|
Init(factory.CreatePopup(e), factory.CreateScreens()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class PopupEvents : WindowBaseEvents, IAvnWindowEvents |
||||
|
{ |
||||
|
readonly PopupImpl _parent; |
||||
|
|
||||
|
public PopupEvents(PopupImpl parent) : base(parent) |
||||
|
{ |
||||
|
_parent = parent; |
||||
|
} |
||||
|
|
||||
|
bool IAvnWindowEvents.Closing() |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
void IAvnWindowEvents.WindowStateChanged(AvnWindowState state) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,45 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
using Avalonia.Native.Interop; |
||||
|
using Avalonia.Platform; |
||||
|
|
||||
|
namespace Avalonia.Native |
||||
|
{ |
||||
|
class ScreenImpl : IScreenImpl, IDisposable |
||||
|
{ |
||||
|
private IAvnScreens _native; |
||||
|
|
||||
|
public ScreenImpl(IAvnScreens native) |
||||
|
{ |
||||
|
_native = native; |
||||
|
} |
||||
|
|
||||
|
public int ScreenCount => _native.GetScreenCount(); |
||||
|
|
||||
|
public Screen[] AllScreens |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
var count = ScreenCount; |
||||
|
var result = new Screen[count]; |
||||
|
|
||||
|
for(int i = 0; i < count; i++) |
||||
|
{ |
||||
|
var screen = _native.GetScreen(i); |
||||
|
|
||||
|
result[i] = new Screen(screen.Bounds.ToAvaloniaRect(), screen.WorkingArea.ToAvaloniaRect(), screen.Primary); |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void Dispose () |
||||
|
{ |
||||
|
_native.Dispose(); |
||||
|
_native = null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,90 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using System.Threading.Tasks; |
||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Controls.Platform; |
||||
|
using Avalonia.Native.Interop; |
||||
|
using Avalonia.Platform; |
||||
|
|
||||
|
namespace Avalonia.Native |
||||
|
{ |
||||
|
public class SystemDialogs : ISystemDialogImpl |
||||
|
{ |
||||
|
IAvnSystemDialogs _native; |
||||
|
|
||||
|
public SystemDialogs(IAvnSystemDialogs native) |
||||
|
{ |
||||
|
_native = native; |
||||
|
} |
||||
|
|
||||
|
public Task<string[]> ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent) |
||||
|
{ |
||||
|
var events = new SystemDialogEvents(); |
||||
|
|
||||
|
if (dialog is OpenFileDialog ofd) |
||||
|
{ |
||||
|
_native.OpenFileDialog((parent as WindowImpl)?.Native, |
||||
|
events, ofd.AllowMultiple, |
||||
|
ofd.Title ?? "", |
||||
|
ofd.InitialDirectory ?? "", |
||||
|
ofd.InitialFileName ?? "", |
||||
|
string.Join(";", dialog.Filters.SelectMany(f => f.Extensions))); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
_native.SaveFileDialog((parent as WindowImpl)?.Native, |
||||
|
events, |
||||
|
dialog.Title ?? "", |
||||
|
dialog.InitialDirectory ?? "", |
||||
|
dialog.InitialFileName ?? "", |
||||
|
string.Join(";", dialog.Filters.SelectMany(f => f.Extensions))); |
||||
|
} |
||||
|
|
||||
|
return events.Task.ContinueWith(t => { events.Dispose(); return t.Result; }); |
||||
|
} |
||||
|
|
||||
|
public Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent) |
||||
|
{ |
||||
|
var events = new SystemDialogEvents(); |
||||
|
|
||||
|
_native.SelectFolderDialog((parent as WindowImpl)?.Native, events, dialog.Title ?? "", dialog.InitialDirectory ?? ""); |
||||
|
|
||||
|
return events.Task.ContinueWith(t => { events.Dispose(); return t.Result.FirstOrDefault(); }); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class SystemDialogEvents : CallbackBase, IAvnSystemDialogEvents |
||||
|
{ |
||||
|
private TaskCompletionSource<string[]> _tcs; |
||||
|
|
||||
|
public SystemDialogEvents() |
||||
|
{ |
||||
|
_tcs = new TaskCompletionSource<string[]>(); |
||||
|
} |
||||
|
|
||||
|
public Task<string[]> Task => _tcs.Task; |
||||
|
|
||||
|
public void OnCompleted(int numResults, IntPtr trFirstResultRef) |
||||
|
{ |
||||
|
string[] results = new string[numResults]; |
||||
|
|
||||
|
unsafe |
||||
|
{ |
||||
|
var ptr = (IntPtr*)trFirstResultRef.ToPointer(); |
||||
|
|
||||
|
for (int i = 0; i < numResults; i++) |
||||
|
{ |
||||
|
results[i] = Marshal.PtrToStringAnsi(*ptr); |
||||
|
|
||||
|
ptr++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
_tcs.SetResult(results); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,100 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Native.Interop; |
||||
|
using Avalonia.Platform; |
||||
|
|
||||
|
namespace Avalonia.Native |
||||
|
{ |
||||
|
public class WindowImpl : WindowBaseImpl, IWindowImpl |
||||
|
{ |
||||
|
IAvnWindow _native; |
||||
|
public WindowImpl(IAvaloniaNativeFactory factory) |
||||
|
{ |
||||
|
using (var e = new WindowEvents(this)) |
||||
|
{ |
||||
|
Init(_native = factory.CreateWindow(e), factory.CreateScreens()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class WindowEvents : WindowBaseEvents, IAvnWindowEvents |
||||
|
{ |
||||
|
readonly WindowImpl _parent; |
||||
|
|
||||
|
public WindowEvents(WindowImpl parent) : base(parent) |
||||
|
{ |
||||
|
_parent = parent; |
||||
|
} |
||||
|
|
||||
|
bool IAvnWindowEvents.Closing() |
||||
|
{ |
||||
|
if(_parent.Closing != null) |
||||
|
{ |
||||
|
return _parent.Closing(); |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
void IAvnWindowEvents.WindowStateChanged(AvnWindowState state) |
||||
|
{ |
||||
|
_parent.WindowStateChanged?.Invoke((WindowState)state); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public IAvnWindow Native => _native; |
||||
|
|
||||
|
public IDisposable ShowDialog() |
||||
|
{ |
||||
|
return _native.ShowDialog(); |
||||
|
} |
||||
|
|
||||
|
public void CanResize(bool value) |
||||
|
{ |
||||
|
_native.CanResize = value; |
||||
|
} |
||||
|
|
||||
|
public void SetSystemDecorations(bool enabled) |
||||
|
{ |
||||
|
_native.HasDecorations = enabled; |
||||
|
} |
||||
|
|
||||
|
public void SetTitleBarColor (Avalonia.Media.Color color) |
||||
|
{ |
||||
|
_native.SetTitleBarColor(new AvnColor { Alpha = color.A, Red = color.R, Green = color.G, Blue = color.B }); |
||||
|
} |
||||
|
|
||||
|
public void SetTitle(string title) |
||||
|
{ |
||||
|
_native.SetTitle(title); |
||||
|
} |
||||
|
|
||||
|
public WindowState WindowState |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return (WindowState)_native.GetWindowState(); |
||||
|
} |
||||
|
set |
||||
|
{ |
||||
|
_native.SetWindowState((AvnWindowState)value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public Action<WindowState> WindowStateChanged { get; set; } |
||||
|
|
||||
|
public void ShowTaskbarIcon(bool value) |
||||
|
{ |
||||
|
// NO OP On OSX
|
||||
|
} |
||||
|
|
||||
|
public void SetIcon(IWindowIconImpl icon) |
||||
|
{ |
||||
|
// NO OP on OSX
|
||||
|
} |
||||
|
|
||||
|
public Func<bool> Closing { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,351 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Controls.Platform.Surfaces; |
||||
|
using Avalonia.Input; |
||||
|
using Avalonia.Input.Raw; |
||||
|
using Avalonia.Native.Interop; |
||||
|
using Avalonia.OpenGL; |
||||
|
using Avalonia.Platform; |
||||
|
using Avalonia.Rendering; |
||||
|
using Avalonia.Threading; |
||||
|
|
||||
|
namespace Avalonia.Native |
||||
|
{ |
||||
|
public class WindowBaseImpl : IWindowBaseImpl, |
||||
|
IFramebufferPlatformSurface |
||||
|
{ |
||||
|
IInputRoot _inputRoot; |
||||
|
IAvnWindowBase _native; |
||||
|
private object _syncRoot = new object(); |
||||
|
private bool _deferredRendering = false; |
||||
|
private bool _gpu = false; |
||||
|
private readonly IMouseDevice _mouse; |
||||
|
private readonly IKeyboardDevice _keyboard; |
||||
|
private readonly IStandardCursorFactory _cursorFactory; |
||||
|
private Size _savedLogicalSize; |
||||
|
private Size _lastRenderedLogicalSize; |
||||
|
private double _savedScaling; |
||||
|
private GlPlatformSurface _glSurface; |
||||
|
|
||||
|
public WindowBaseImpl() |
||||
|
{ |
||||
|
var opts = AvaloniaLocator.Current.GetService<AvaloniaNativeOptions>(); |
||||
|
|
||||
|
_gpu = opts.UseGpu; |
||||
|
_deferredRendering = opts.UseDeferredRendering; |
||||
|
|
||||
|
_keyboard = AvaloniaLocator.Current.GetService<IKeyboardDevice>(); |
||||
|
_mouse = AvaloniaLocator.Current.GetService<IMouseDevice>(); |
||||
|
_cursorFactory = AvaloniaLocator.Current.GetService<IStandardCursorFactory>(); |
||||
|
} |
||||
|
|
||||
|
protected void Init(IAvnWindowBase window, IAvnScreens screens) |
||||
|
{ |
||||
|
_native = window; |
||||
|
_glSurface = new GlPlatformSurface(window); |
||||
|
Screen = new ScreenImpl(screens); |
||||
|
_savedLogicalSize = ClientSize; |
||||
|
_savedScaling = Scaling; |
||||
|
} |
||||
|
|
||||
|
public Size ClientSize |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
var s = _native.GetClientSize(); |
||||
|
return new Size(s.Width, s.Height); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public IEnumerable<object> Surfaces => new[] { |
||||
|
(_gpu ? _glSurface : (object)null), |
||||
|
this |
||||
|
}; |
||||
|
|
||||
|
public ILockedFramebuffer Lock() |
||||
|
{ |
||||
|
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); |
||||
|
_lastRenderedLogicalSize = _savedLogicalSize; |
||||
|
return true; |
||||
|
} |
||||
|
}, (int)w, (int)h, new Vector(dpi, dpi)); |
||||
|
} |
||||
|
|
||||
|
return new FramebufferWrapper(_native.GetSoftwareFramebuffer()); |
||||
|
} |
||||
|
|
||||
|
public Action<Rect> Paint { get; set; } |
||||
|
public Action<Size> Resized { get; set; } |
||||
|
public Action Closed { get; set; } |
||||
|
public IMouseDevice MouseDevice => AvaloniaNativePlatform.MouseDevice; |
||||
|
|
||||
|
|
||||
|
class FramebufferWrapper : ILockedFramebuffer |
||||
|
{ |
||||
|
public FramebufferWrapper(AvnFramebuffer fb) |
||||
|
{ |
||||
|
Address = fb.Data; |
||||
|
Width = fb.Width; |
||||
|
Height = fb.Height; |
||||
|
RowBytes = fb.Stride; |
||||
|
Dpi = new Vector(fb.Dpi.X, fb.Dpi.Y); |
||||
|
Format = (PixelFormat)fb.PixelFormat; |
||||
|
} |
||||
|
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; } |
||||
|
public void Dispose() |
||||
|
{ |
||||
|
// Do nothing
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected class WindowBaseEvents : CallbackBase, IAvnWindowBaseEvents |
||||
|
{ |
||||
|
private readonly WindowBaseImpl _parent; |
||||
|
|
||||
|
public WindowBaseEvents(WindowBaseImpl parent) |
||||
|
{ |
||||
|
_parent = parent; |
||||
|
} |
||||
|
|
||||
|
void IAvnWindowBaseEvents.Closed() |
||||
|
{ |
||||
|
var n = _parent._native; |
||||
|
_parent._native = null; |
||||
|
try |
||||
|
{ |
||||
|
_parent?.Closed?.Invoke(); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
n?.Dispose(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void IAvnWindowBaseEvents.Activated() => _parent.Activated?.Invoke(); |
||||
|
|
||||
|
void IAvnWindowBaseEvents.Deactivated() => _parent.Deactivated?.Invoke(); |
||||
|
|
||||
|
void IAvnWindowBaseEvents.Paint() |
||||
|
{ |
||||
|
Dispatcher.UIThread.RunJobs(DispatcherPriority.Render); |
||||
|
var s = _parent.ClientSize; |
||||
|
_parent.Paint?.Invoke(new Rect(0, 0, s.Width, s.Height)); |
||||
|
} |
||||
|
|
||||
|
void IAvnWindowBaseEvents.Resized(AvnSize size) |
||||
|
{ |
||||
|
var s = new Size(size.Width, size.Height); |
||||
|
_parent._savedLogicalSize = s; |
||||
|
_parent.Resized?.Invoke(s); |
||||
|
} |
||||
|
|
||||
|
void IAvnWindowBaseEvents.PositionChanged(AvnPoint position) |
||||
|
{ |
||||
|
_parent.PositionChanged?.Invoke(position.ToAvaloniaPoint()); |
||||
|
} |
||||
|
|
||||
|
void IAvnWindowBaseEvents.RawMouseEvent(AvnRawMouseEventType type, uint timeStamp, AvnInputModifiers modifiers, AvnPoint point, AvnVector delta) |
||||
|
{ |
||||
|
_parent.RawMouseEvent(type, timeStamp, modifiers, point, delta); |
||||
|
} |
||||
|
|
||||
|
bool IAvnWindowBaseEvents.RawKeyEvent(AvnRawKeyEventType type, uint timeStamp, AvnInputModifiers modifiers, uint key) |
||||
|
{ |
||||
|
return _parent.RawKeyEvent(type, timeStamp, modifiers, key); |
||||
|
} |
||||
|
|
||||
|
bool IAvnWindowBaseEvents.RawTextInputEvent(uint timeStamp, string text) |
||||
|
{ |
||||
|
return _parent.RawTextInputEvent(timeStamp, text); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void IAvnWindowBaseEvents.ScalingChanged(double scaling) |
||||
|
{ |
||||
|
_parent._savedScaling = scaling; |
||||
|
_parent.ScalingChanged?.Invoke(scaling); |
||||
|
} |
||||
|
|
||||
|
void IAvnWindowBaseEvents.RunRenderPriorityJobs() |
||||
|
{ |
||||
|
if (_parent._deferredRendering |
||||
|
&& _parent._lastRenderedLogicalSize != _parent.ClientSize) |
||||
|
// Hack to trigger Paint event on the renderer
|
||||
|
_parent.Paint?.Invoke(new Rect()); |
||||
|
Dispatcher.UIThread.RunJobs(DispatcherPriority.Render); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void Activate() |
||||
|
{ |
||||
|
_native.Activate(); |
||||
|
} |
||||
|
|
||||
|
public bool RawTextInputEvent(uint timeStamp, string text) |
||||
|
{ |
||||
|
Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1); |
||||
|
|
||||
|
var args = new RawTextInputEventArgs(_keyboard, timeStamp, text); |
||||
|
|
||||
|
Input?.Invoke(args); |
||||
|
|
||||
|
return args.Handled; |
||||
|
} |
||||
|
|
||||
|
public bool RawKeyEvent(AvnRawKeyEventType type, uint timeStamp, AvnInputModifiers modifiers, uint key) |
||||
|
{ |
||||
|
Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1); |
||||
|
|
||||
|
var args = new RawKeyEventArgs(_keyboard, timeStamp, (RawKeyEventType)type, (Key)key, (InputModifiers)modifiers); |
||||
|
|
||||
|
Input?.Invoke(args); |
||||
|
|
||||
|
return args.Handled; |
||||
|
} |
||||
|
|
||||
|
public void RawMouseEvent(AvnRawMouseEventType type, uint timeStamp, AvnInputModifiers modifiers, AvnPoint point, AvnVector delta) |
||||
|
{ |
||||
|
Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1); |
||||
|
|
||||
|
switch (type) |
||||
|
{ |
||||
|
case AvnRawMouseEventType.Wheel: |
||||
|
Input?.Invoke(new RawMouseWheelEventArgs(_mouse, timeStamp, _inputRoot, point.ToAvaloniaPoint(), new Vector(delta.X, delta.Y), (InputModifiers)modifiers)); |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
Input?.Invoke(new RawMouseEventArgs(_mouse, timeStamp, _inputRoot, (RawMouseEventType)type, point.ToAvaloniaPoint(), (InputModifiers)modifiers)); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void Resize(Size clientSize) |
||||
|
{ |
||||
|
_native.Resize(clientSize.Width, clientSize.Height); |
||||
|
} |
||||
|
|
||||
|
public IRenderer CreateRenderer(IRenderRoot root) |
||||
|
{ |
||||
|
if (_deferredRendering) |
||||
|
return new DeferredRendererProxy(root, _gpu ? _native : null); |
||||
|
return new ImmediateRenderer(root); |
||||
|
} |
||||
|
|
||||
|
public virtual void Dispose() |
||||
|
{ |
||||
|
_native?.Close(); |
||||
|
_native?.Dispose(); |
||||
|
_native = null; |
||||
|
|
||||
|
(Screen as ScreenImpl)?.Dispose(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public void Invalidate(Rect rect) |
||||
|
{ |
||||
|
if (!_deferredRendering && _native != null) |
||||
|
_native.Invalidate(new AvnRect { Height = rect.Height, Width = rect.Width, X = rect.X, Y = rect.Y }); |
||||
|
} |
||||
|
|
||||
|
public void SetInputRoot(IInputRoot inputRoot) |
||||
|
{ |
||||
|
_inputRoot = inputRoot; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public void Show() |
||||
|
{ |
||||
|
_native.Show(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public Point Position |
||||
|
{ |
||||
|
get => _native.GetPosition().ToAvaloniaPoint(); |
||||
|
set => _native.SetPosition(value.ToAvnPoint()); |
||||
|
} |
||||
|
|
||||
|
public Point PointToClient(Point point) |
||||
|
{ |
||||
|
return _native.PointToClient(point.ToAvnPoint()).ToAvaloniaPoint(); |
||||
|
} |
||||
|
|
||||
|
public Point PointToScreen(Point point) |
||||
|
{ |
||||
|
return _native.PointToScreen(point.ToAvnPoint()).ToAvaloniaPoint(); |
||||
|
} |
||||
|
|
||||
|
public void Hide() |
||||
|
{ |
||||
|
_native.Hide(); |
||||
|
} |
||||
|
|
||||
|
public void BeginMoveDrag() |
||||
|
{ |
||||
|
_native.BeginMoveDrag(); |
||||
|
} |
||||
|
|
||||
|
public Size MaxClientSize => _native.GetMaxClientSize().ToAvaloniaSize(); |
||||
|
|
||||
|
public void SetTopmost(bool value) |
||||
|
{ |
||||
|
_native.SetTopMost(value); |
||||
|
} |
||||
|
|
||||
|
public double Scaling => _native.GetScaling(); |
||||
|
|
||||
|
public Action Deactivated { get; set; } |
||||
|
public Action Activated { get; set; } |
||||
|
|
||||
|
public void SetCursor(IPlatformHandle cursor) |
||||
|
{ |
||||
|
var newCursor = cursor as AvaloniaNativeCursor; |
||||
|
newCursor = newCursor ?? (_cursorFactory.GetCursor(StandardCursorType.Arrow) as AvaloniaNativeCursor); |
||||
|
_native.Cursor = newCursor.Cursor; |
||||
|
} |
||||
|
|
||||
|
public Action<Point> PositionChanged { get; set; } |
||||
|
|
||||
|
public Action<RawInputEventArgs> Input { get; set; } |
||||
|
|
||||
|
Action<double> ScalingChanged { get; set; } |
||||
|
|
||||
|
Action<double> ITopLevelImpl.ScalingChanged { get; set; } |
||||
|
|
||||
|
public IScreenImpl Screen { get; private set; } |
||||
|
|
||||
|
// TODO
|
||||
|
|
||||
|
public void SetMinMaxSize(Size minSize, Size maxSize) |
||||
|
{ |
||||
|
_native.SetMinMaxSize(minSize.ToAvnSize(), maxSize.ToAvnSize()); |
||||
|
} |
||||
|
|
||||
|
public void BeginResizeDrag(WindowEdge edge) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public IPlatformHandle Handle => new PlatformHandle(IntPtr.Zero, "NOT SUPPORTED"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,5 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
#define COM_GUIDS_MATERIALIZE |
||||
|
#include "avalonia-native.h" |
||||
@ -0,0 +1,363 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
#include "com.h" |
||||
|
#include "key.h" |
||||
|
|
||||
|
#define AVNCOM(name, id) COMINTERFACE(name, 2e2cda0a, 9ae5, 4f1b, 8e, 20, 08, 1a, 04, 27, 9f, id) |
||||
|
|
||||
|
struct IAvnWindowEvents; |
||||
|
struct IAvnWindow; |
||||
|
struct IAvnPopup; |
||||
|
struct IAvnMacOptions; |
||||
|
struct IAvnPlatformThreadingInterface; |
||||
|
struct IAvnSystemDialogEvents; |
||||
|
struct IAvnSystemDialogs; |
||||
|
struct IAvnScreens; |
||||
|
struct IAvnClipboard; |
||||
|
struct IAvnCursor; |
||||
|
struct IAvnCursorFactory; |
||||
|
struct IAvnGlFeature; |
||||
|
struct IAvnGlContext; |
||||
|
struct IAvnGlDisplay; |
||||
|
struct IAvnGlSurfaceRenderTarget; |
||||
|
struct IAvnGlSurfaceRenderingSession; |
||||
|
|
||||
|
struct AvnSize |
||||
|
{ |
||||
|
double Width, Height; |
||||
|
}; |
||||
|
|
||||
|
struct AvnPixelSize |
||||
|
{ |
||||
|
int Width, Height; |
||||
|
}; |
||||
|
|
||||
|
struct AvnRect |
||||
|
{ |
||||
|
double X, Y, Width, Height; |
||||
|
}; |
||||
|
|
||||
|
struct AvnVector |
||||
|
{ |
||||
|
double X, Y; |
||||
|
}; |
||||
|
|
||||
|
struct AvnPoint |
||||
|
{ |
||||
|
double X, Y; |
||||
|
}; |
||||
|
|
||||
|
struct AvnScreen |
||||
|
{ |
||||
|
AvnRect Bounds; |
||||
|
AvnRect WorkingArea; |
||||
|
bool Primary; |
||||
|
}; |
||||
|
|
||||
|
enum AvnPixelFormat |
||||
|
{ |
||||
|
kAvnRgb565, |
||||
|
kAvnRgba8888, |
||||
|
kAvnBgra8888 |
||||
|
}; |
||||
|
|
||||
|
struct AvnFramebuffer |
||||
|
{ |
||||
|
void* Data; |
||||
|
int Width; |
||||
|
int Height; |
||||
|
int Stride; |
||||
|
AvnVector Dpi; |
||||
|
AvnPixelFormat PixelFormat; |
||||
|
}; |
||||
|
|
||||
|
struct AvnColor |
||||
|
{ |
||||
|
unsigned char Alpha; |
||||
|
unsigned char Red; |
||||
|
unsigned char Green; |
||||
|
unsigned char Blue; |
||||
|
}; |
||||
|
|
||||
|
enum AvnRawMouseEventType |
||||
|
{ |
||||
|
LeaveWindow, |
||||
|
LeftButtonDown, |
||||
|
LeftButtonUp, |
||||
|
RightButtonDown, |
||||
|
RightButtonUp, |
||||
|
MiddleButtonDown, |
||||
|
MiddleButtonUp, |
||||
|
Move, |
||||
|
Wheel, |
||||
|
NonClientLeftButtonDown |
||||
|
}; |
||||
|
|
||||
|
enum AvnRawKeyEventType |
||||
|
{ |
||||
|
KeyDown, |
||||
|
KeyUp |
||||
|
}; |
||||
|
|
||||
|
enum AvnInputModifiers |
||||
|
{ |
||||
|
AvnInputModifiersNone = 0, |
||||
|
Alt = 1, |
||||
|
Control = 2, |
||||
|
Shift = 4, |
||||
|
Windows = 8, |
||||
|
LeftMouseButton = 16, |
||||
|
RightMouseButton = 32, |
||||
|
MiddleMouseButton = 64 |
||||
|
}; |
||||
|
|
||||
|
enum AvnWindowState |
||||
|
{ |
||||
|
Normal, |
||||
|
Minimized, |
||||
|
Maximized, |
||||
|
}; |
||||
|
|
||||
|
enum AvnStandardCursorType |
||||
|
{ |
||||
|
CursorArrow, |
||||
|
CursorIbeam, |
||||
|
CursorWait, |
||||
|
CursorCross, |
||||
|
CursorUpArrow, |
||||
|
CursorSizeWestEast, |
||||
|
CursorSizeNorthSouth, |
||||
|
CursorSizeAll, |
||||
|
CursorNo, |
||||
|
CursorHand, |
||||
|
CursorAppStarting, |
||||
|
CursorHelp, |
||||
|
CursorTopSide, |
||||
|
CursorBottomSize, |
||||
|
CursorLeftSide, |
||||
|
CursorRightSide, |
||||
|
CursorTopLeftCorner, |
||||
|
CursorTopRightCorner, |
||||
|
CursorBottomLeftCorner, |
||||
|
CursorBottomRightCorner, |
||||
|
CursorDragMove, |
||||
|
CursorDragCopy, |
||||
|
CursorDragLink, |
||||
|
}; |
||||
|
|
||||
|
enum AvnWindowEdge |
||||
|
{ |
||||
|
WindowEdgeNorthWest, |
||||
|
WindowEdgeNorth, |
||||
|
WindowEdgeNorthEast, |
||||
|
WindowEdgeWest, |
||||
|
WindowEdgeEast, |
||||
|
WindowEdgeSouthWest, |
||||
|
WindowEdgeSouth, |
||||
|
WindowEdgeSouthEast |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvaloniaNativeFactory, 01) : IUnknown |
||||
|
{ |
||||
|
public: |
||||
|
virtual HRESULT Initialize() = 0; |
||||
|
virtual IAvnMacOptions* GetMacOptions() = 0; |
||||
|
virtual HRESULT CreateWindow(IAvnWindowEvents* cb, IAvnWindow** ppv) = 0; |
||||
|
virtual HRESULT CreatePopup (IAvnWindowEvents* cb, IAvnPopup** ppv) = 0; |
||||
|
virtual HRESULT CreatePlatformThreadingInterface(IAvnPlatformThreadingInterface** ppv) = 0; |
||||
|
virtual HRESULT CreateSystemDialogs (IAvnSystemDialogs** ppv) = 0; |
||||
|
virtual HRESULT CreateScreens (IAvnScreens** ppv) = 0; |
||||
|
virtual HRESULT CreateClipboard(IAvnClipboard** ppv) = 0; |
||||
|
virtual HRESULT CreateCursorFactory(IAvnCursorFactory** ppv) = 0; |
||||
|
virtual HRESULT ObtainGlFeature(IAvnGlFeature** ppv) = 0; |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnWindowBase, 02) : IUnknown |
||||
|
{ |
||||
|
virtual HRESULT Show() = 0; |
||||
|
virtual HRESULT Hide () = 0; |
||||
|
virtual HRESULT Close() = 0; |
||||
|
virtual HRESULT Activate () = 0; |
||||
|
virtual HRESULT GetClientSize(AvnSize*ret) = 0; |
||||
|
virtual HRESULT GetMaxClientSize(AvnSize* ret) = 0; |
||||
|
virtual HRESULT GetScaling(double*ret)=0; |
||||
|
virtual HRESULT SetMinMaxSize(AvnSize minSize, AvnSize maxSize) = 0; |
||||
|
virtual HRESULT Resize(double width, double height) = 0; |
||||
|
virtual HRESULT Invalidate (AvnRect rect) = 0; |
||||
|
virtual HRESULT BeginMoveDrag () = 0; |
||||
|
virtual HRESULT BeginResizeDrag (AvnWindowEdge edge) = 0; |
||||
|
virtual HRESULT GetPosition (AvnPoint*ret) = 0; |
||||
|
virtual HRESULT 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; |
||||
|
virtual HRESULT SetCursor(IAvnCursor* cursor) = 0; |
||||
|
virtual HRESULT CreateGlRenderTarget(IAvnGlSurfaceRenderTarget** ret) = 0; |
||||
|
virtual HRESULT GetSoftwareFramebuffer(AvnFramebuffer*ret) = 0; |
||||
|
virtual bool TryLock() = 0; |
||||
|
virtual void Unlock() = 0; |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnPopup, 03) : virtual IAvnWindowBase |
||||
|
{ |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnWindow, 04) : virtual IAvnWindowBase |
||||
|
{ |
||||
|
virtual HRESULT ShowDialog (IUnknown**ppv) = 0; |
||||
|
virtual HRESULT SetCanResize(bool value) = 0; |
||||
|
virtual HRESULT SetHasDecorations(bool value) = 0; |
||||
|
virtual HRESULT SetTitle (const char* title) = 0; |
||||
|
virtual HRESULT SetTitleBarColor (AvnColor color) = 0; |
||||
|
virtual HRESULT SetWindowState(AvnWindowState state) = 0; |
||||
|
virtual HRESULT GetWindowState(AvnWindowState*ret) = 0; |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnWindowBaseEvents, 05) : IUnknown |
||||
|
{ |
||||
|
virtual HRESULT Paint() = 0; |
||||
|
virtual void Closed() = 0; |
||||
|
virtual void Activated() = 0; |
||||
|
virtual void Deactivated() = 0; |
||||
|
virtual void Resized(const AvnSize& size) = 0; |
||||
|
virtual void PositionChanged (AvnPoint position) = 0; |
||||
|
virtual void RawMouseEvent (AvnRawMouseEventType type, |
||||
|
unsigned int timeStamp, |
||||
|
AvnInputModifiers modifiers, |
||||
|
AvnPoint point, |
||||
|
AvnVector delta) = 0; |
||||
|
virtual bool RawKeyEvent (AvnRawKeyEventType type, unsigned int timeStamp, AvnInputModifiers modifiers, unsigned int key) = 0; |
||||
|
virtual bool RawTextInputEvent (unsigned int timeStamp, const char* text) = 0; |
||||
|
virtual void ScalingChanged(double scaling) = 0; |
||||
|
virtual void RunRenderPriorityJobs() = 0; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
AVNCOM(IAvnWindowEvents, 06) : IAvnWindowBaseEvents |
||||
|
{ |
||||
|
/**
|
||||
|
* Closing Event |
||||
|
* Called when the user presses the OS window close button. |
||||
|
* return true to allow the close, return false to prevent close. |
||||
|
*/ |
||||
|
virtual bool Closing () = 0; |
||||
|
|
||||
|
virtual void WindowStateChanged (AvnWindowState state) = 0; |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnMacOptions, 07) : IUnknown |
||||
|
{ |
||||
|
virtual HRESULT SetShowInDock(int show) = 0; |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnActionCallback, 08) : IUnknown |
||||
|
{ |
||||
|
virtual void Run() = 0; |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnSignaledCallback, 09) : IUnknown |
||||
|
{ |
||||
|
virtual void Signaled(int priority, bool priorityContainsMeaningfulValue) = 0; |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnLoopCancellation, 0a) : IUnknown |
||||
|
{ |
||||
|
virtual void Cancel() = 0; |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnPlatformThreadingInterface, 0b) : IUnknown |
||||
|
{ |
||||
|
virtual bool GetCurrentThreadIsLoopThread() = 0; |
||||
|
virtual void SetSignaledCallback(IAvnSignaledCallback* cb) = 0; |
||||
|
virtual IAvnLoopCancellation* CreateLoopCancellation() = 0; |
||||
|
virtual void RunLoop(IAvnLoopCancellation* cancel) = 0; |
||||
|
// Can't pass int* to sharpgentools for some reason
|
||||
|
virtual void Signal(int priority) = 0; |
||||
|
virtual IUnknown* StartTimer(int priority, int ms, IAvnActionCallback* callback) = 0; |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnSystemDialogEvents, 0c) : IUnknown |
||||
|
{ |
||||
|
virtual void OnCompleted (int numResults, void* ptrFirstResult) = 0; |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnSystemDialogs, 0d) : IUnknown |
||||
|
{ |
||||
|
virtual void SelectFolderDialog (IAvnWindow* parentWindowHandle, |
||||
|
IAvnSystemDialogEvents* events, |
||||
|
const char* title, |
||||
|
const char* initialPath) = 0; |
||||
|
|
||||
|
virtual void OpenFileDialog (IAvnWindow* parentWindowHandle, |
||||
|
IAvnSystemDialogEvents* events, |
||||
|
bool allowMultiple, |
||||
|
const char* title, |
||||
|
const char* initialDirectory, |
||||
|
const char* initialFile, |
||||
|
const char* filters) = 0; |
||||
|
|
||||
|
virtual void SaveFileDialog (IAvnWindow* parentWindowHandle, |
||||
|
IAvnSystemDialogEvents* events, |
||||
|
const char* title, |
||||
|
const char* initialDirectory, |
||||
|
const char* initialFile, |
||||
|
const char* filters) = 0; |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnScreens, 0e) : IUnknown |
||||
|
{ |
||||
|
virtual HRESULT GetScreenCount (int* ret) = 0; |
||||
|
virtual HRESULT GetScreen (int index, AvnScreen* ret) = 0; |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnClipboard, 0f) : IUnknown |
||||
|
{ |
||||
|
virtual HRESULT GetText (void** retOut) = 0; |
||||
|
virtual HRESULT SetText (char* text) = 0; |
||||
|
virtual HRESULT Clear() = 0; |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnCursor, 10) : IUnknown |
||||
|
{ |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnCursorFactory, 11) : IUnknown |
||||
|
{ |
||||
|
virtual HRESULT GetCursor (AvnStandardCursorType cursorType, IAvnCursor** retOut) = 0; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
AVNCOM(IAvnGlFeature, 12) : IUnknown |
||||
|
{ |
||||
|
virtual HRESULT ObtainDisplay(IAvnGlDisplay**retOut) = 0; |
||||
|
virtual HRESULT ObtainImmediateContext(IAvnGlContext**retOut) = 0; |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnGlDisplay, 13) : IUnknown |
||||
|
{ |
||||
|
virtual HRESULT GetSampleCount(int* ret) = 0; |
||||
|
virtual HRESULT GetStencilSize(int* ret) = 0; |
||||
|
virtual HRESULT ClearContext() = 0; |
||||
|
virtual void* GetProcAddress(char* proc) = 0; |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnGlContext, 14) : IUnknown |
||||
|
{ |
||||
|
virtual HRESULT MakeCurrent() = 0; |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnGlSurfaceRenderTarget, 15) : IUnknown |
||||
|
{ |
||||
|
virtual HRESULT BeginDrawing(IAvnGlSurfaceRenderingSession** ret) = 0; |
||||
|
}; |
||||
|
|
||||
|
AVNCOM(IAvnGlSurfaceRenderingSession, 16) : IUnknown |
||||
|
{ |
||||
|
virtual HRESULT GetPixelSize(AvnPixelSize* ret) = 0; |
||||
|
virtual HRESULT GetScaling(double* ret) = 0; |
||||
|
}; |
||||
|
|
||||
|
extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative(); |
||||
@ -0,0 +1,57 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
#pragma clang diagnostic push |
||||
|
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection" |
||||
|
#ifndef COM_H_INCLUDED |
||||
|
#define COM_H_INCLUDED |
||||
|
|
||||
|
|
||||
|
typedef struct _GUID { |
||||
|
unsigned int Data1; |
||||
|
unsigned short Data2; |
||||
|
unsigned short Data3; |
||||
|
unsigned char Data4[ 8 ]; |
||||
|
} GUID; |
||||
|
typedef GUID IID; |
||||
|
typedef const IID* REFIID; |
||||
|
typedef unsigned int HRESULT; |
||||
|
typedef unsigned int DWORD; |
||||
|
typedef DWORD ULONG; |
||||
|
|
||||
|
#define STDMETHODCALLTYPE |
||||
|
|
||||
|
#define S_OK 0x0L |
||||
|
|
||||
|
#define E_NOTIMPL 0x80004001L |
||||
|
#define E_NOINTERFACE 0x80004002L |
||||
|
#define E_POINTER 0x80004003L |
||||
|
#define E_ABORT 0x80004004L |
||||
|
#define E_FAIL 0x80004005L |
||||
|
#define E_UNEXPECTED 0x8000FFFFL |
||||
|
#define E_HANDLE 0x80070006L |
||||
|
#define E_INVALIDARG 0x80070057L |
||||
|
|
||||
|
struct IUnknown |
||||
|
{ |
||||
|
virtual HRESULT STDMETHODCALLTYPE QueryInterface( |
||||
|
REFIID riid, |
||||
|
void **ppvObject) = 0; |
||||
|
|
||||
|
virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0; |
||||
|
|
||||
|
virtual ULONG STDMETHODCALLTYPE Release( void) = 0; |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
#ifdef COM_GUIDS_MATERIALIZE |
||||
|
#define __IID_DEF(name,d1,d2,d3, d41, d42, d43, d44, d45, d46, d47, d48) extern "C" const GUID IID_ ## name = {0x ## d1, 0x ## d2, 0x ## d3, \ |
||||
|
{0x ## d41, 0x ## d42, 0x ## d42, 0x ## d42, 0x ## d42, 0x ## d42, 0x ## d42, 0x ## d42 } }; |
||||
|
#else |
||||
|
#define __IID_DEF(name,d1,d2,d3, d41, d42, d43, d44, d45, d46, d47, d48) extern "C" const GUID IID_ ## name; |
||||
|
#endif |
||||
|
#define COMINTERFACE(name,d1,d2,d3, d41, d42, d43, d44, d45, d46, d47, d48) __IID_DEF(name,d1,d2,d3, d41, d42, d43, d44, d45, d46, d47, d48) \ |
||||
|
struct __attribute__((annotate("uuid(" #d1 "-" #d2 "-" #d3 "-" #d41 #d42 "-" #d43 #d44 #d45 #d46 #d47 #d48 ")" ))) name |
||||
|
|
||||
|
#endif // COM_H_INCLUDED
|
||||
|
#pragma clang diagnostic pop |
||||
@ -0,0 +1,183 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
#include "com.h" |
||||
|
#pragma clang diagnostic push |
||||
|
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection" |
||||
|
#ifndef COMIMPL_H_INCLUDED |
||||
|
#define COMIMPL_H_INCLUDED |
||||
|
|
||||
|
#include <cstring> |
||||
|
|
||||
|
__IID_DEF(IUnknown, 0, 0, 0, C0, 00, 00, 00, 00, 00, 00, 46); |
||||
|
|
||||
|
class ComObject : public virtual IUnknown |
||||
|
{ |
||||
|
private: |
||||
|
unsigned int _refCount; |
||||
|
public: |
||||
|
|
||||
|
virtual ULONG AddRef() |
||||
|
{ |
||||
|
_refCount++; |
||||
|
return _refCount; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
virtual ULONG Release() |
||||
|
{ |
||||
|
_refCount--; |
||||
|
ULONG rv = _refCount; |
||||
|
if(_refCount == 0) |
||||
|
delete(this); |
||||
|
return rv; |
||||
|
} |
||||
|
|
||||
|
ComObject() |
||||
|
{ |
||||
|
_refCount = 1; |
||||
|
|
||||
|
} |
||||
|
virtual ~ComObject() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
|
||||
|
virtual ::HRESULT STDMETHODCALLTYPE QueryInterfaceImpl(REFIID riid, void **ppvObject) = 0; |
||||
|
|
||||
|
virtual ::HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, |
||||
|
void **ppvObject) |
||||
|
{ |
||||
|
if(0 == memcmp(riid, &IID_IUnknown, sizeof(GUID))) |
||||
|
*ppvObject = (IUnknown*)this; |
||||
|
else |
||||
|
{ |
||||
|
auto rv = QueryInterfaceImpl(riid, ppvObject); |
||||
|
if(rv != S_OK) |
||||
|
return rv; |
||||
|
} |
||||
|
_refCount++; |
||||
|
return S_OK; |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
|
||||
|
#define FORWARD_IUNKNOWN() \ |
||||
|
virtual ULONG Release(){ \ |
||||
|
return ComObject::Release(); \ |
||||
|
} \ |
||||
|
virtual ULONG AddRef() \ |
||||
|
{ \ |
||||
|
return ComObject::AddRef(); \ |
||||
|
} \ |
||||
|
virtual HRESULT QueryInterface(REFIID riid, void **ppvObject) \ |
||||
|
{ \ |
||||
|
return ComObject::QueryInterface(riid, ppvObject); \ |
||||
|
} |
||||
|
|
||||
|
#define BEGIN_INTERFACE_MAP() public: virtual HRESULT STDMETHODCALLTYPE QueryInterfaceImpl(REFIID riid, void **ppvObject){ |
||||
|
#define INTERFACE_MAP_ENTRY(TInterface, IID) if(0 == memcmp(riid, &IID, sizeof(GUID))) { TInterface* casted = this; *ppvObject = casted; return S_OK; } |
||||
|
#define END_INTERFACE_MAP() return E_NOINTERFACE; } |
||||
|
#define INHERIT_INTERFACE_MAP(TBase) if(TBase::QueryInterfaceImpl(riid, ppvObject) == S_OK) return S_OK; |
||||
|
|
||||
|
|
||||
|
|
||||
|
class ComUnknownObject : public ComObject |
||||
|
{ |
||||
|
public: |
||||
|
FORWARD_IUNKNOWN() |
||||
|
virtual ::HRESULT STDMETHODCALLTYPE QueryInterfaceImpl(REFIID riid, void **ppvObject) override |
||||
|
{ |
||||
|
return E_NOINTERFACE; |
||||
|
}; |
||||
|
virtual ~ComUnknownObject(){} |
||||
|
}; |
||||
|
|
||||
|
template<class TInterface, GUID const* TIID> class ComSingleObject : public ComObject, public virtual TInterface |
||||
|
{ |
||||
|
BEGIN_INTERFACE_MAP() |
||||
|
INTERFACE_MAP_ENTRY(TInterface, *TIID) |
||||
|
END_INTERFACE_MAP() |
||||
|
|
||||
|
public: |
||||
|
virtual ~ComSingleObject(){} |
||||
|
}; |
||||
|
|
||||
|
template<class TInterface> |
||||
|
class ComPtr |
||||
|
{ |
||||
|
private: |
||||
|
TInterface* _obj; |
||||
|
public: |
||||
|
ComPtr() |
||||
|
{ |
||||
|
_obj = 0; |
||||
|
} |
||||
|
|
||||
|
ComPtr(TInterface* pObj) |
||||
|
{ |
||||
|
_obj = 0; |
||||
|
|
||||
|
if (pObj) |
||||
|
{ |
||||
|
_obj = pObj; |
||||
|
_obj->AddRef(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
ComPtr(const ComPtr& ptr) |
||||
|
{ |
||||
|
_obj = 0; |
||||
|
|
||||
|
if (ptr._obj) |
||||
|
{ |
||||
|
_obj = ptr._obj; |
||||
|
_obj->AddRef(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
ComPtr& operator=(ComPtr other) |
||||
|
{ |
||||
|
if(_obj != NULL) |
||||
|
_obj->Release(); |
||||
|
_obj = other._obj; |
||||
|
if(_obj != NULL) |
||||
|
_obj->AddRef(); |
||||
|
return *this; |
||||
|
} |
||||
|
|
||||
|
~ComPtr() |
||||
|
{ |
||||
|
if (_obj) |
||||
|
{ |
||||
|
_obj->Release(); |
||||
|
_obj = 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
TInterface* getRaw() |
||||
|
{ |
||||
|
return _obj; |
||||
|
} |
||||
|
|
||||
|
operator TInterface*() const |
||||
|
{ |
||||
|
return _obj; |
||||
|
} |
||||
|
TInterface& operator*() const |
||||
|
{ |
||||
|
return *_obj; |
||||
|
} |
||||
|
TInterface** operator&() |
||||
|
{ |
||||
|
return &_obj; |
||||
|
} |
||||
|
TInterface* operator->() const |
||||
|
{ |
||||
|
return _obj; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
#endif // COMIMPL_H_INCLUDED
|
||||
|
#pragma clang diagnostic pop |
||||
File diff suppressed because it is too large
@ -0,0 +1,2 @@ |
|||||
|
#!/bin/sh |
||||
|
dotnet msbuild /t:Clean,GenerateSharpGenBindings |
||||
@ -0,0 +1,62 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Reflection; |
||||
|
using System.Reactive.Linq; |
||||
|
using Avalonia; |
||||
|
using Avalonia.VisualTree; |
||||
|
using Avalonia.Controls; |
||||
|
using ReactiveUI; |
||||
|
|
||||
|
namespace Avalonia |
||||
|
{ |
||||
|
public class AvaloniaActivationForViewFetcher : IActivationForViewFetcher |
||||
|
{ |
||||
|
public int GetAffinityForView(Type view) |
||||
|
{ |
||||
|
return typeof(IVisual).GetTypeInfo().IsAssignableFrom(view.GetTypeInfo()) ? 10 : 0; |
||||
|
} |
||||
|
|
||||
|
public IObservable<bool> GetActivationForView(IActivatable view) |
||||
|
{ |
||||
|
if (!(view is IVisual visual)) return Observable.Return(false); |
||||
|
if (view is WindowBase window) return GetActivationForWindowBase(window); |
||||
|
return GetActivationForVisual(visual); |
||||
|
} |
||||
|
|
||||
|
private IObservable<bool> GetActivationForWindowBase(WindowBase window) |
||||
|
{ |
||||
|
var windowLoaded = Observable |
||||
|
.FromEventPattern( |
||||
|
x => window.Initialized += x, |
||||
|
x => window.Initialized -= x) |
||||
|
.Select(args => true); |
||||
|
var windowUnloaded = Observable |
||||
|
.FromEventPattern( |
||||
|
x => window.Closed += x, |
||||
|
x => window.Closed -= x) |
||||
|
.Select(args => false); |
||||
|
return windowLoaded |
||||
|
.Merge(windowUnloaded) |
||||
|
.DistinctUntilChanged(); |
||||
|
} |
||||
|
|
||||
|
private IObservable<bool> GetActivationForVisual(IVisual visual) |
||||
|
{ |
||||
|
var visualLoaded = Observable |
||||
|
.FromEventPattern<VisualTreeAttachmentEventArgs>( |
||||
|
x => visual.AttachedToVisualTree += x, |
||||
|
x => visual.AttachedToVisualTree -= x) |
||||
|
.Select(args => true); |
||||
|
var visualUnloaded = Observable |
||||
|
.FromEventPattern<VisualTreeAttachmentEventArgs>( |
||||
|
x => visual.DetachedFromVisualTree += x, |
||||
|
x => visual.DetachedFromVisualTree -= x) |
||||
|
.Select(args => false); |
||||
|
return visualLoaded |
||||
|
.Merge(visualUnloaded) |
||||
|
.DistinctUntilChanged(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,9 +0,0 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||
<packages> |
|
||||
<package id="Rx-Core" version="2.2.5" targetFramework="portable-net45+win8" userInstalled="true" /> |
|
||||
<package id="Rx-Interfaces" version="2.2.5" targetFramework="portable-net45+win8" userInstalled="true" /> |
|
||||
<package id="Rx-Linq" version="2.2.5" targetFramework="portable-net45+win8" userInstalled="true" /> |
|
||||
<package id="Rx-Main" version="2.2.5" targetFramework="portable-net45+win8" userInstalled="true" /> |
|
||||
<package id="Rx-PlatformServices" version="2.2.5" targetFramework="portable-net45+win8" userInstalled="true" /> |
|
||||
<package id="Splat" version="1.6.2" targetFramework="portable45-net45+win8" userInstalled="true" /> |
|
||||
</packages> |
|
||||
@ -0,0 +1,14 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netcoreapp2.0</TargetFramework> |
||||
|
</PropertyGroup> |
||||
|
<Import Project="..\..\build\UnitTests.NetCore.targets" /> |
||||
|
<Import Project="..\..\build\Moq.props" /> |
||||
|
<Import Project="..\..\build\XUnit.props" /> |
||||
|
<Import Project="..\..\build\Rx.props" /> |
||||
|
<Import Project="..\..\build\Microsoft.Reactive.Testing.props" /> |
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\Avalonia.UnitTests\Avalonia.UnitTests.csproj" /> |
||||
|
<ProjectReference Include="..\..\src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj"/> |
||||
|
</ItemGroup> |
||||
|
</Project> |
||||
@ -0,0 +1,124 @@ |
|||||
|
using System; |
||||
|
using System.Reactive.Concurrency; |
||||
|
using System.Reactive.Disposables; |
||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Rendering; |
||||
|
using Avalonia.Platform; |
||||
|
using Avalonia.UnitTests; |
||||
|
using Avalonia; |
||||
|
using ReactiveUI; |
||||
|
using DynamicData; |
||||
|
using Xunit; |
||||
|
using Splat; |
||||
|
|
||||
|
namespace Avalonia |
||||
|
{ |
||||
|
public class AvaloniaActivationForViewFetcherTest |
||||
|
{ |
||||
|
public class TestUserControl : UserControl, IActivatable { } |
||||
|
|
||||
|
public class TestUserControlWithWhenActivated : UserControl, IActivatable |
||||
|
{ |
||||
|
public bool Active { get; private set; } |
||||
|
|
||||
|
public TestUserControlWithWhenActivated() |
||||
|
{ |
||||
|
this.WhenActivated(disposables => { |
||||
|
Active = true; |
||||
|
Disposable |
||||
|
.Create(() => Active = false) |
||||
|
.DisposeWith(disposables); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class TestWindowWithWhenActivated : Window, IActivatable |
||||
|
{ |
||||
|
public bool Active { get; private set; } |
||||
|
|
||||
|
public TestWindowWithWhenActivated() |
||||
|
{ |
||||
|
this.WhenActivated(disposables => { |
||||
|
Active = true; |
||||
|
Disposable |
||||
|
.Create(() => Active = false) |
||||
|
.DisposeWith(disposables); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Visual_Element_Is_Activated_And_Deactivated() |
||||
|
{ |
||||
|
var userControl = new TestUserControl(); |
||||
|
var activationForViewFetcher = new AvaloniaActivationForViewFetcher(); |
||||
|
|
||||
|
activationForViewFetcher |
||||
|
.GetActivationForView(userControl) |
||||
|
.ToObservableChangeSet(scheduler: ImmediateScheduler.Instance) |
||||
|
.Bind(out var activated) |
||||
|
.Subscribe(); |
||||
|
|
||||
|
var fakeRenderedDecorator = new TestRoot(); |
||||
|
fakeRenderedDecorator.Child = userControl; |
||||
|
Assert.True(activated[0]); |
||||
|
Assert.Equal(1, activated.Count); |
||||
|
|
||||
|
fakeRenderedDecorator.Child = null; |
||||
|
Assert.True(activated[0]); |
||||
|
Assert.False(activated[1]); |
||||
|
Assert.Equal(2, activated.Count); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Get_Affinity_For_View_Should_Return_Non_Zero_For_Visual_Elements() |
||||
|
{ |
||||
|
var userControl = new TestUserControl(); |
||||
|
var activationForViewFetcher = new AvaloniaActivationForViewFetcher(); |
||||
|
|
||||
|
var forUserControl = activationForViewFetcher.GetAffinityForView(userControl.GetType()); |
||||
|
var forNonUserControl = activationForViewFetcher.GetAffinityForView(typeof(object)); |
||||
|
|
||||
|
Assert.NotEqual(0, forUserControl); |
||||
|
Assert.Equal(0, forNonUserControl); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Activation_For_View_Fetcher_Should_Support_When_Activated() |
||||
|
{ |
||||
|
Locator.CurrentMutable.RegisterConstant( |
||||
|
new AvaloniaActivationForViewFetcher(), |
||||
|
typeof(IActivationForViewFetcher)); |
||||
|
|
||||
|
var userControl = new TestUserControlWithWhenActivated(); |
||||
|
Assert.False(userControl.Active); |
||||
|
|
||||
|
var fakeRenderedDecorator = new TestRoot(); |
||||
|
fakeRenderedDecorator.Child = userControl; |
||||
|
Assert.True(userControl.Active); |
||||
|
|
||||
|
fakeRenderedDecorator.Child = null; |
||||
|
Assert.False(userControl.Active); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Activation_For_View_Fetcher_Should_Support_Windows() |
||||
|
{ |
||||
|
Locator.CurrentMutable.RegisterConstant( |
||||
|
new AvaloniaActivationForViewFetcher(), |
||||
|
typeof(IActivationForViewFetcher)); |
||||
|
|
||||
|
using (var application = UnitTestApplication.Start(TestServices.MockWindowingPlatform)) |
||||
|
{ |
||||
|
var window = new TestWindowWithWhenActivated(); |
||||
|
Assert.False(window.Active); |
||||
|
|
||||
|
window.Show(); |
||||
|
Assert.True(window.Active); |
||||
|
|
||||
|
window.Close(); |
||||
|
Assert.False(window.Active); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue