Jelajahi Sumber

Merge branch 'master' into linux-ime-cjk

Nikita Tsukanov 5 tahun lalu
induk
melakukan
91828f2621
80 mengubah file dengan 1231 tambahan dan 1441 penghapusan
  1. 31 0
      .github/ISSUE_TEMPLATE/bug_report.md
  2. 20 0
      .github/ISSUE_TEMPLATE/feature_request.md
  3. 3 3
      azure-pipelines.yml
  4. 1 1
      build/ApiDiff.props
  5. 0 1020
      native/Avalonia.Native/inc/key.h
  6. 8 4
      native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
  7. 6 1
      native/Avalonia.Native/src/OSX/KeyTransform.h
  8. 151 0
      native/Avalonia.Native/src/OSX/KeyTransform.mm
  9. 1 1
      native/Avalonia.Native/src/OSX/menu.h
  10. 51 14
      native/Avalonia.Native/src/OSX/menu.mm
  11. 4 4
      native/Avalonia.Native/src/OSX/window.mm
  12. 10 1
      readme.md
  13. 1 2
      samples/ControlCatalog.NetCore/Program.cs
  14. 0 4
      src/Avalonia.Base/ApiCompatBaseline.txt
  15. 12 12
      src/Avalonia.Base/AvaloniaProperty.cs
  16. 4 4
      src/Avalonia.Base/AvaloniaPropertyMetadata.cs
  17. 3 3
      src/Avalonia.Base/AvaloniaProperty`1.cs
  18. 3 3
      src/Avalonia.Base/DirectPropertyBase.cs
  19. 2 2
      src/Avalonia.Base/DirectPropertyMetadata`1.cs
  20. 5 0
      src/Avalonia.Base/Logging/LogArea.cs
  21. 2 0
      src/Avalonia.Base/Properties/AssemblyInfo.cs
  22. 2 2
      src/Avalonia.Base/StyledPropertyMetadata`1.cs
  23. 2 23
      src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs
  24. 14 0
      src/Avalonia.Base/Utilities/NonPumpingLockHelper.cs
  25. 0 5
      src/Avalonia.Controls.DataGrid/ApiCompatBaseline.txt
  26. 21 0
      src/Avalonia.Controls.DataGrid/Primitives/DataGridRowsPresenter.cs
  27. 27 2
      src/Avalonia.Controls.DataGrid/Themes/Default.xaml
  28. 22 4
      src/Avalonia.Controls.DataGrid/Utils/ReflectionHelper.cs
  29. 0 26
      src/Avalonia.Controls/ApiCompatBaseline.txt
  30. 3 1
      src/Avalonia.Controls/Button.cs
  31. 10 0
      src/Avalonia.Controls/ContextMenu.cs
  32. 17 9
      src/Avalonia.Controls/HotkeyManager.cs
  33. 3 1
      src/Avalonia.Controls/MenuItem.cs
  34. 1 1
      src/Avalonia.Controls/NativeMenuItem.cs
  35. 2 2
      src/Avalonia.Controls/Platform/IWindowBaseImpl.cs
  36. 4 1
      src/Avalonia.Controls/TextBox.cs
  37. 17 3
      src/Avalonia.Controls/Window.cs
  38. 1 1
      src/Avalonia.Controls/WindowBase.cs
  39. 1 1
      src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs
  40. 1 1
      src/Avalonia.DesignerSupport/Remote/Stubs.cs
  41. 3 0
      src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml
  42. 0 1
      src/Avalonia.Dialogs/ApiCompatBaseline.txt
  43. 1 1
      src/Avalonia.FreeDesktop/DBusHelper.cs
  44. 4 3
      src/Avalonia.Headless/HeadlessWindowImpl.cs
  45. 0 4
      src/Avalonia.Input/ApiCompatBaseline.txt
  46. 36 0
      src/Avalonia.Input/ICommandSource.cs
  47. 2 2
      src/Avalonia.Native/IAvnMenuItem.cs
  48. 0 152
      src/Avalonia.Native/OsxUnicodeKeys.cs
  49. 2 2
      src/Avalonia.Native/PopupImpl.cs
  50. 2 2
      src/Avalonia.Native/WindowImplBase.cs
  51. 208 3
      src/Avalonia.Native/avn.idl
  52. 0 3
      src/Avalonia.Styling/ApiCompatBaseline.txt
  53. 5 1
      src/Avalonia.Themes.Default/CaptionButtons.xaml
  54. 0 4
      src/Avalonia.Themes.Fluent/ApiCompatBaseline.txt
  55. 5 1
      src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml
  56. 1 0
      src/Avalonia.Themes.Fluent/Controls/ContextMenu.xaml
  57. 1 1
      src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml
  58. 0 5
      src/Avalonia.Visuals/ApiCompatBaseline.txt
  59. 1 0
      src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
  60. 1 1
      src/Avalonia.Visuals/Visual.cs
  61. 1 1
      src/Avalonia.X11/X11Window.cs
  62. 7 16
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs
  63. 93 7
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathTransformer.cs
  64. 1 7
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformSyntheticCompiledBindingMembers.cs
  65. 0 4
      src/Markup/Avalonia.Markup.Xaml/ApiCompatBaseline.txt
  66. 10 0
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindingExtension.cs
  67. 2 2
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  68. 52 0
      src/Windows/Avalonia.Win32/NonPumpingSyncContext.cs
  69. 0 15
      src/Windows/Avalonia.Win32/NonPumpingWaitProvider.cs
  70. 2 1
      src/Windows/Avalonia.Win32/PopupImpl.cs
  71. 6 2
      src/Windows/Avalonia.Win32/Win32GlManager.cs
  72. 27 10
      src/Windows/Avalonia.Win32/Win32Platform.cs
  73. 2 0
      src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
  74. 8 6
      src/Windows/Avalonia.Win32/WindowImpl.cs
  75. 11 11
      tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs
  76. 8 8
      tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs
  77. 141 0
      tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs
  78. 1 1
      tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs
  79. 120 1
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs
  80. 1 1
      tests/Avalonia.UnitTests/MockWindowingPlatform.cs

+ 31 - 0
.github/ISSUE_TEMPLATE/bug_report.md

@@ -0,0 +1,31 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Desktop (please complete the following information):**
+ - OS: [e.g. Windows, Mac, Linux (State distribution)]
+ - Version [e.g. 0.10.0-rc1 or 0.9.12]
+
+**Additional context**
+Add any other context about the problem here.

+ 20 - 0
.github/ISSUE_TEMPLATE/feature_request.md

@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.

+ 3 - 3
azure-pipelines.yml

@@ -27,7 +27,7 @@ jobs:
   variables:
     SolutionDir: '$(Build.SourcesDirectory)'
   pool:
-    vmImage: 'macOS-10.14'
+    vmImage: 'macOS-10.15'
   steps:
   - task: UseDotNet@2
     displayName: 'Use .NET Core SDK 3.1.401'
@@ -51,10 +51,10 @@ jobs:
     inputs:
       actions: 'build'
       scheme: ''
-      sdk: 'macosx10.14'
+      sdk: 'macosx11.1'
       configuration: 'Release'
       xcWorkspacePath: '**/*.xcodeproj/project.xcworkspace'
-      xcodeVersion: '10' # Options: 8, 9, default, specifyPath
+      xcodeVersion: '12' # Options: 8, 9, default, specifyPath
       args: '-derivedDataPath ./'
 
   - task: CmdLine@2

+ 1 - 1
build/ApiDiff.props

@@ -1,6 +1,6 @@
 <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
-    <ApiContractPackageVersion>0.10.0-preview6</ApiContractPackageVersion>
+    <ApiContractPackageVersion>0.10.0-rc1</ApiContractPackageVersion>
     <NugetPackageName Condition="'$(PackageId)' != ''">$(PackageId)</NugetPackageName>
     <NugetPackageName Condition="'$(PackageId)' == ''">Avalonia</NugetPackageName>
   </PropertyGroup>

+ 0 - 1020
native/Avalonia.Native/inc/key.h

@@ -1,1020 +0,0 @@
-#ifndef _KEY_H_
-#define _KEY_H_
-
-/// <summary>
-/// Defines the keys available on a keyboard.
-/// </summary>
-enum AvnKey
-{
-    /// <summary>
-    /// No key pressed.
-    /// </summary>
-    AvnKeyNone = 0,
-    
-    /// <summary>
-    /// The Cancel key.
-    /// </summary>
-    AvnKeyCancel = 1,
-    
-    /// <summary>
-    /// The Back key.
-    /// </summary>
-    AvnKeyBack = 2,
-    
-    /// <summary>
-    /// The Tab key.
-    /// </summary>
-    AvnKeyTab = 3,
-    
-    /// <summary>
-    /// The Linefeed key.
-    /// </summary>
-    AvnKeyLineFeed = 4,
-    
-    /// <summary>
-    /// The Clear key.
-    /// </summary>
-    AvnKeyClear = 5,
-    
-    /// <summary>
-    /// The Return key.
-    /// </summary>
-    AvnKeyReturn = 6,
-    
-    /// <summary>
-    /// The Enter key.
-    /// </summary>
-    AvnKeyEnter = 6,
-    
-    /// <summary>
-    /// The Pause key.
-    /// </summary>
-    AvnKeyPause = 7,
-    
-    /// <summary>
-    /// The Caps Lock key.
-    /// </summary>
-    AvnKeyCapsLock = 8,
-    
-    /// <summary>
-    /// The Caps Lock key.
-    /// </summary>
-    AvnKeyCapital = 8,
-    
-    /// <summary>
-    /// The IME Hangul mode key.
-    /// </summary>
-    AvnKeyHangulMode = 9,
-    
-    /// <summary>
-    /// The IME Kana mode key.
-    /// </summary>
-    AvnKeyKanaMode = 9,
-    
-    /// <summary>
-    /// The IME Junja mode key.
-    /// </summary>
-    AvnKeyJunjaMode = 10,
-    
-    /// <summary>
-    /// The IME Final mode key.
-    /// </summary>
-    AvnKeyFinalMode = 11,
-    
-    /// <summary>
-    /// The IME Kanji mode key.
-    /// </summary>
-    AvnKeyKanjiMode = 12,
-    
-    /// <summary>
-    /// The IME Hanja mode key.
-    /// </summary>
-    HanjaMode = 12,
-    
-    /// <summary>
-    /// The Escape key.
-    /// </summary>
-    Escape = 13,
-    
-    /// <summary>
-    /// The IME Convert key.
-    /// </summary>
-    ImeConvert = 14,
-    
-    /// <summary>
-    /// The IME NonConvert key.
-    /// </summary>
-    ImeNonConvert = 15,
-    
-    /// <summary>
-    /// The IME Accept key.
-    /// </summary>
-    ImeAccept = 16,
-    
-    /// <summary>
-    /// The IME Mode change key.
-    /// </summary>
-    ImeModeChange = 17,
-    
-    /// <summary>
-    /// The space bar.
-    /// </summary>
-    Space = 18,
-    
-    /// <summary>
-    /// The Page Up key.
-    /// </summary>
-    PageUp = 19,
-    
-    /// <summary>
-    /// The Page Up key.
-    /// </summary>
-    Prior = 19,
-    
-    /// <summary>
-    /// The Page Down key.
-    /// </summary>
-    PageDown = 20,
-    
-    /// <summary>
-    /// The Page Down key.
-    /// </summary>
-    Next = 20,
-    
-    /// <summary>
-    /// The End key.
-    /// </summary>
-    End = 21,
-    
-    /// <summary>
-    /// The Home key.
-    /// </summary>
-    Home = 22,
-    
-    /// <summary>
-    /// The Left arrow key.
-    /// </summary>
-    Left = 23,
-    
-    /// <summary>
-    /// The Up arrow key.
-    /// </summary>
-    Up = 24,
-    
-    /// <summary>
-    /// The Right arrow key.
-    /// </summary>
-    Right = 25,
-    
-    /// <summary>
-    /// The Down arrow key.
-    /// </summary>
-    Down = 26,
-    
-    /// <summary>
-    /// The Select key.
-    /// </summary>
-    Select = 27,
-    
-    /// <summary>
-    /// The Print key.
-    /// </summary>
-    Print = 28,
-    
-    /// <summary>
-    /// The Execute key.
-    /// </summary>
-    Execute = 29,
-    
-    /// <summary>
-    /// The Print Screen key.
-    /// </summary>
-    Snapshot = 30,
-    
-    /// <summary>
-    /// The Print Screen key.
-    /// </summary>
-    PrintScreen = 30,
-    
-    /// <summary>
-    /// The Insert key.
-    /// </summary>
-    Insert = 31,
-    
-    /// <summary>
-    /// The Delete key.
-    /// </summary>
-    Delete = 32,
-    
-    /// <summary>
-    /// The Help key.
-    /// </summary>
-    Help = 33,
-    
-    /// <summary>
-    /// The 0 key.
-    /// </summary>
-    D0 = 34,
-    
-    /// <summary>
-    /// The 1 key.
-    /// </summary>
-    D1 = 35,
-    
-    /// <summary>
-    /// The 2 key.
-    /// </summary>
-    D2 = 36,
-    
-    /// <summary>
-    /// The 3 key.
-    /// </summary>
-    D3 = 37,
-    
-    /// <summary>
-    /// The 4 key.
-    /// </summary>
-    D4 = 38,
-    
-    /// <summary>
-    /// The 5 key.
-    /// </summary>
-    D5 = 39,
-    
-    /// <summary>
-    /// The 6 key.
-    /// </summary>
-    D6 = 40,
-    
-    /// <summary>
-    /// The 7 key.
-    /// </summary>
-    D7 = 41,
-    
-    /// <summary>
-    /// The 8 key.
-    /// </summary>
-    D8 = 42,
-    
-    /// <summary>
-    /// The 9 key.
-    /// </summary>
-    D9 = 43,
-    
-    /// <summary>
-    /// The A key.
-    /// </summary>
-    A = 44,
-    
-    /// <summary>
-    /// The B key.
-    /// </summary>
-    B = 45,
-    
-    /// <summary>
-    /// The C key.
-    /// </summary>
-    C = 46,
-    
-    /// <summary>
-    /// The D key.
-    /// </summary>
-    D = 47,
-    
-    /// <summary>
-    /// The E key.
-    /// </summary>
-    E = 48,
-    
-    /// <summary>
-    /// The F key.
-    /// </summary>
-    F = 49,
-    
-    /// <summary>
-    /// The G key.
-    /// </summary>
-    G = 50,
-    
-    /// <summary>
-    /// The H key.
-    /// </summary>
-    H = 51,
-    
-    /// <summary>
-    /// The I key.
-    /// </summary>
-    I = 52,
-    
-    /// <summary>
-    /// The J key.
-    /// </summary>
-    J = 53,
-    
-    /// <summary>
-    /// The K key.
-    /// </summary>
-    AvnKeyK = 54,
-    
-    /// <summary>
-    /// The L key.
-    /// </summary>
-    L = 55,
-    
-    /// <summary>
-    /// The M key.
-    /// </summary>
-    M = 56,
-    
-    /// <summary>
-    /// The N key.
-    /// </summary>
-    N = 57,
-    
-    /// <summary>
-    /// The O key.
-    /// </summary>
-    O = 58,
-    
-    /// <summary>
-    /// The P key.
-    /// </summary>
-    P = 59,
-    
-    /// <summary>
-    /// The Q key.
-    /// </summary>
-    Q = 60,
-    
-    /// <summary>
-    /// The R key.
-    /// </summary>
-    R = 61,
-    
-    /// <summary>
-    /// The S key.
-    /// </summary>
-    S = 62,
-    
-    /// <summary>
-    /// The T key.
-    /// </summary>
-    T = 63,
-    
-    /// <summary>
-    /// The U key.
-    /// </summary>
-    U = 64,
-    
-    /// <summary>
-    /// The V key.
-    /// </summary>
-    V = 65,
-    
-    /// <summary>
-    /// The W key.
-    /// </summary>
-    W = 66,
-    
-    /// <summary>
-    /// The X key.
-    /// </summary>
-    X = 67,
-    
-    /// <summary>
-    /// The Y key.
-    /// </summary>
-    Y = 68,
-    
-    /// <summary>
-    /// The Z key.
-    /// </summary>
-    Z = 69,
-    
-    /// <summary>
-    /// The left Windows key.
-    /// </summary>
-    LWin = 70,
-    
-    /// <summary>
-    /// The right Windows key.
-    /// </summary>
-    RWin = 71,
-    
-    /// <summary>
-    /// The Application key.
-    /// </summary>
-    Apps = 72,
-    
-    /// <summary>
-    /// The Sleep key.
-    /// </summary>
-    Sleep = 73,
-    
-    /// <summary>
-    /// The 0 key on the numeric keypad.
-    /// </summary>
-    NumPad0 = 74,
-    
-    /// <summary>
-    /// The 1 key on the numeric keypad.
-    /// </summary>
-    NumPad1 = 75,
-    
-    /// <summary>
-    /// The 2 key on the numeric keypad.
-    /// </summary>
-    NumPad2 = 76,
-    
-    /// <summary>
-    /// The 3 key on the numeric keypad.
-    /// </summary>
-    NumPad3 = 77,
-    
-    /// <summary>
-    /// The 4 key on the numeric keypad.
-    /// </summary>
-    NumPad4 = 78,
-    
-    /// <summary>
-    /// The 5 key on the numeric keypad.
-    /// </summary>
-    NumPad5 = 79,
-    
-    /// <summary>
-    /// The 6 key on the numeric keypad.
-    /// </summary>
-    NumPad6 = 80,
-    
-    /// <summary>
-    /// The 7 key on the numeric keypad.
-    /// </summary>
-    NumPad7 = 81,
-    
-    /// <summary>
-    /// The 8 key on the numeric keypad.
-    /// </summary>
-    NumPad8 = 82,
-    
-    /// <summary>
-    /// The 9 key on the numeric keypad.
-    /// </summary>
-    NumPad9 = 83,
-    
-    /// <summary>
-    /// The Multiply key.
-    /// </summary>
-    Multiply = 84,
-    
-    /// <summary>
-    /// The Add key.
-    /// </summary>
-    Add = 85,
-    
-    /// <summary>
-    /// The Separator key.
-    /// </summary>
-    Separator = 86,
-    
-    /// <summary>
-    /// The Subtract key.
-    /// </summary>
-    Subtract = 87,
-    
-    /// <summary>
-    /// The Decimal key.
-    /// </summary>
-    Decimal = 88,
-    
-    /// <summary>
-    /// The Divide key.
-    /// </summary>
-    Divide = 89,
-    
-    /// <summary>
-    /// The F1 key.
-    /// </summary>
-    F1 = 90,
-    
-    /// <summary>
-    /// The F2 key.
-    /// </summary>
-    F2 = 91,
-    
-    /// <summary>
-    /// The F3 key.
-    /// </summary>
-    F3 = 92,
-    
-    /// <summary>
-    /// The F4 key.
-    /// </summary>
-    F4 = 93,
-    
-    /// <summary>
-    /// The F5 key.
-    /// </summary>
-    F5 = 94,
-    
-    /// <summary>
-    /// The F6 key.
-    /// </summary>
-    F6 = 95,
-    
-    /// <summary>
-    /// The F7 key.
-    /// </summary>
-    F7 = 96,
-    
-    /// <summary>
-    /// The F8 key.
-    /// </summary>
-    F8 = 97,
-    
-    /// <summary>
-    /// The F9 key.
-    /// </summary>
-    F9 = 98,
-    
-    /// <summary>
-    /// The F10 key.
-    /// </summary>
-    F10 = 99,
-    
-    /// <summary>
-    /// The F11 key.
-    /// </summary>
-    F11 = 100,
-    
-    /// <summary>
-    /// The F12 key.
-    /// </summary>
-    F12 = 101,
-    
-    /// <summary>
-    /// The F13 key.
-    /// </summary>
-    F13 = 102,
-    
-    /// <summary>
-    /// The F14 key.
-    /// </summary>
-    F14 = 103,
-    
-    /// <summary>
-    /// The F15 key.
-    /// </summary>
-    F15 = 104,
-    
-    /// <summary>
-    /// The F16 key.
-    /// </summary>
-    F16 = 105,
-    
-    /// <summary>
-    /// The F17 key.
-    /// </summary>
-    F17 = 106,
-    
-    /// <summary>
-    /// The F18 key.
-    /// </summary>
-    F18 = 107,
-    
-    /// <summary>
-    /// The F19 key.
-    /// </summary>
-    F19 = 108,
-    
-    /// <summary>
-    /// The F20 key.
-    /// </summary>
-    F20 = 109,
-    
-    /// <summary>
-    /// The F21 key.
-    /// </summary>
-    F21 = 110,
-    
-    /// <summary>
-    /// The F22 key.
-    /// </summary>
-    F22 = 111,
-    
-    /// <summary>
-    /// The F23 key.
-    /// </summary>
-    F23 = 112,
-    
-    /// <summary>
-    /// The F24 key.
-    /// </summary>
-    F24 = 113,
-    
-    /// <summary>
-    /// The Numlock key.
-    /// </summary>
-    NumLock = 114,
-    
-    /// <summary>
-    /// The Scroll key.
-    /// </summary>
-    Scroll = 115,
-    
-    /// <summary>
-    /// The left Shift key.
-    /// </summary>
-    LeftShift = 116,
-    
-    /// <summary>
-    /// The right Shift key.
-    /// </summary>
-    RightShift = 117,
-    
-    /// <summary>
-    /// The left Ctrl key.
-    /// </summary>
-    LeftCtrl = 118,
-    
-    /// <summary>
-    /// The right Ctrl key.
-    /// </summary>
-    RightCtrl = 119,
-    
-    /// <summary>
-    /// The left Alt key.
-    /// </summary>
-    LeftAlt = 120,
-    
-    /// <summary>
-    /// The right Alt key.
-    /// </summary>
-    RightAlt = 121,
-    
-    /// <summary>
-    /// The browser Back key.
-    /// </summary>
-    BrowserBack = 122,
-    
-    /// <summary>
-    /// The browser Forward key.
-    /// </summary>
-    BrowserForward = 123,
-    
-    /// <summary>
-    /// The browser Refresh key.
-    /// </summary>
-    BrowserRefresh = 124,
-    
-    /// <summary>
-    /// The browser Stop key.
-    /// </summary>
-    BrowserStop = 125,
-    
-    /// <summary>
-    /// The browser Search key.
-    /// </summary>
-    BrowserSearch = 126,
-    
-    /// <summary>
-    /// The browser Favorites key.
-    /// </summary>
-    BrowserFavorites = 127,
-    
-    /// <summary>
-    /// The browser Home key.
-    /// </summary>
-    BrowserHome = 128,
-    
-    /// <summary>
-    /// The Volume Mute key.
-    /// </summary>
-    VolumeMute = 129,
-    
-    /// <summary>
-    /// The Volume Down key.
-    /// </summary>
-    VolumeDown = 130,
-    
-    /// <summary>
-    /// The Volume Up key.
-    /// </summary>
-    VolumeUp = 131,
-    
-    /// <summary>
-    /// The media Next Track key.
-    /// </summary>
-    MediaNextTrack = 132,
-    
-    /// <summary>
-    /// The media Previous Track key.
-    /// </summary>
-    MediaPreviousTrack = 133,
-    
-    /// <summary>
-    /// The media Stop key.
-    /// </summary>
-    MediaStop = 134,
-    
-    /// <summary>
-    /// The media Play/Pause key.
-    /// </summary>
-    MediaPlayPause = 135,
-    
-    /// <summary>
-    /// The Launch Mail key.
-    /// </summary>
-    LaunchMail = 136,
-    
-    /// <summary>
-    /// The Select Media key.
-    /// </summary>
-    SelectMedia = 137,
-    
-    /// <summary>
-    /// The Launch Application 1 key.
-    /// </summary>
-    LaunchApplication1 = 138,
-    
-    /// <summary>
-    /// The Launch Application 2 key.
-    /// </summary>
-    LaunchApplication2 = 139,
-    
-    /// <summary>
-    /// The OEM Semicolon key.
-    /// </summary>
-    OemSemicolon = 140,
-    
-    /// <summary>
-    /// The OEM 1 key.
-    /// </summary>
-    Oem1 = 140,
-    
-    /// <summary>
-    /// The OEM Plus key.
-    /// </summary>
-    OemPlus = 141,
-    
-    /// <summary>
-    /// The OEM Comma key.
-    /// </summary>
-    OemComma = 142,
-    
-    /// <summary>
-    /// The OEM Minus key.
-    /// </summary>
-    OemMinus = 143,
-    
-    /// <summary>
-    /// The OEM Period key.
-    /// </summary>
-    OemPeriod = 144,
-    
-    /// <summary>
-    /// The OEM Question Mark key.
-    /// </summary>
-    OemQuestion = 145,
-    
-    /// <summary>
-    /// The OEM 2 key.
-    /// </summary>
-    Oem2 = 145,
-    
-    /// <summary>
-    /// The OEM Tilde key.
-    /// </summary>
-    OemTilde = 146,
-    
-    /// <summary>
-    /// The OEM 3 key.
-    /// </summary>
-    Oem3 = 146,
-    
-    /// <summary>
-    /// The ABNT_C1 (Brazilian) key.
-    /// </summary>
-    AbntC1 = 147,
-    
-    /// <summary>
-    /// The ABNT_C2 (Brazilian) key.
-    /// </summary>
-    AbntC2 = 148,
-    
-    /// <summary>
-    /// The OEM Open Brackets key.
-    /// </summary>
-    OemOpenBrackets = 149,
-    
-    /// <summary>
-    /// The OEM 4 key.
-    /// </summary>
-    Oem4 = 149,
-    
-    /// <summary>
-    /// The OEM Pipe key.
-    /// </summary>
-    OemPipe = 150,
-    
-    /// <summary>
-    /// The OEM 5 key.
-    /// </summary>
-    Oem5 = 150,
-    
-    /// <summary>
-    /// The OEM Close Brackets key.
-    /// </summary>
-    OemCloseBrackets = 151,
-    
-    /// <summary>
-    /// The OEM 6 key.
-    /// </summary>
-    Oem6 = 151,
-    
-    /// <summary>
-    /// The OEM Quotes key.
-    /// </summary>
-    OemQuotes = 152,
-    
-    /// <summary>
-    /// The OEM 7 key.
-    /// </summary>
-    Oem7 = 152,
-    
-    /// <summary>
-    /// The OEM 8 key.
-    /// </summary>
-    Oem8 = 153,
-    
-    /// <summary>
-    /// The OEM Backslash key.
-    /// </summary>
-    OemBackslash = 154,
-    
-    /// <summary>
-    /// The OEM 3 key.
-    /// </summary>
-    Oem102 = 154,
-    
-    /// <summary>
-    /// A special key masking the real key being processed by an IME.
-    /// </summary>
-    ImeProcessed = 155,
-    
-    /// <summary>
-    /// A special key masking the real key being processed as a system key.
-    /// </summary>
-    System = 156,
-    
-    /// <summary>
-    /// The OEM ATTN key.
-    /// </summary>
-    OemAttn = 157,
-    
-    /// <summary>
-    /// The DBE_ALPHANUMERIC key.
-    /// </summary>
-    DbeAlphanumeric = 157,
-    
-    /// <summary>
-    /// The OEM Finish key.
-    /// </summary>
-    OemFinish = 158,
-    
-    /// <summary>
-    /// The DBE_KATAKANA key.
-    /// </summary>
-    DbeKatakana = 158,
-    
-    /// <summary>
-    /// The DBE_HIRAGANA key.
-    /// </summary>
-    DbeHiragana = 159,
-    
-    /// <summary>
-    /// The OEM Copy key.
-    /// </summary>
-    OemCopy = 159,
-    
-    /// <summary>
-    /// The DBE_SBCSCHAR key.
-    /// </summary>
-    DbeSbcsChar = 160,
-    
-    /// <summary>
-    /// The OEM Auto key.
-    /// </summary>
-    OemAuto = 160,
-    
-    /// <summary>
-    /// The DBE_DBCSCHAR key.
-    /// </summary>
-    DbeDbcsChar = 161,
-    
-    /// <summary>
-    /// The OEM ENLW key.
-    /// </summary>
-    OemEnlw = 161,
-    
-    /// <summary>
-    /// The OEM BackTab key.
-    /// </summary>
-    OemBackTab = 162,
-    
-    /// <summary>
-    /// The DBE_ROMAN key.
-    /// </summary>
-    DbeRoman = 162,
-    
-    /// <summary>
-    /// The DBE_NOROMAN key.
-    /// </summary>
-    DbeNoRoman = 163,
-    
-    /// <summary>
-    /// The ATTN key.
-    /// </summary>
-    Attn = 163,
-    
-    /// <summary>
-    /// The CRSEL key.
-    /// </summary>
-    CrSel = 164,
-    
-    /// <summary>
-    /// The DBE_ENTERWORDREGISTERMODE key.
-    /// </summary>
-    DbeEnterWordRegisterMode = 164,
-    
-    /// <summary>
-    /// The EXSEL key.
-    /// </summary>
-    ExSel = 165,
-    
-    /// <summary>
-    /// The DBE_ENTERIMECONFIGMODE key.
-    /// </summary>
-    DbeEnterImeConfigureMode = 165,
-    
-    /// <summary>
-    /// The ERASE EOF Key.
-    /// </summary>
-    EraseEof = 166,
-    
-    /// <summary>
-    /// The DBE_FLUSHSTRING key.
-    /// </summary>
-    DbeFlushString = 166,
-    
-    /// <summary>
-    /// The Play key.
-    /// </summary>
-    Play = 167,
-    
-    /// <summary>
-    /// The DBE_CODEINPUT key.
-    /// </summary>
-    DbeCodeInput = 167,
-    
-    /// <summary>
-    /// The DBE_NOCODEINPUT key.
-    /// </summary>
-    DbeNoCodeInput = 168,
-    
-    /// <summary>
-    /// The Zoom key.
-    /// </summary>
-    Zoom = 168,
-    
-    /// <summary>
-    /// Reserved for future use.
-    /// </summary>
-    NoName = 169,
-    
-    /// <summary>
-    /// The DBE_DETERMINESTRING key.
-    /// </summary>
-    DbeDetermineString = 169,
-    
-    /// <summary>
-    /// The DBE_ENTERDLGCONVERSIONMODE key.
-    /// </summary>
-    DbeEnterDialogConversionMode = 170,
-    
-    /// <summary>
-    /// The PA1 key.
-    /// </summary>
-    Pa1 = 170,
-    
-    /// <summary>
-    /// The OEM Clear key.
-    /// </summary>
-    OemClear = 171,
-    
-    /// <summary>
-    /// The key is used with another key to create a single combined character.
-    /// </summary>
-    DeadCharProcessed = 172,
-};
-
-#endif

+ 8 - 4
native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj

@@ -8,19 +8,20 @@
 
 /* Begin PBXBuildFile section */
 		1A002B9E232135EE00021753 /* app.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A002B9D232135EE00021753 /* app.mm */; };
+		1A1852DC23E05814008F0DED /* deadlock.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A1852DB23E05814008F0DED /* deadlock.mm */; };
 		1A3E5EA823E9E83B00EDE661 /* rendertarget.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A3E5EA723E9E83B00EDE661 /* rendertarget.mm */; };
 		1A3E5EAA23E9F26C00EDE661 /* IOSurface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A3E5EA923E9F26C00EDE661 /* IOSurface.framework */; };
-		1A1852DC23E05814008F0DED /* deadlock.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A1852DB23E05814008F0DED /* deadlock.mm */; };
-		1AFD334123E03C4F0042899B /* controlhost.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AFD334023E03C4F0042899B /* controlhost.mm */; };
 		1A3E5EAE23E9FB1300EDE661 /* cgl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A3E5EAD23E9FB1300EDE661 /* cgl.mm */; };
 		1A3E5EB023E9FE8300EDE661 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A3E5EAF23E9FE8300EDE661 /* QuartzCore.framework */; };
 		1A465D10246AB61600C5858B /* dnd.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A465D0F246AB61600C5858B /* dnd.mm */; };
+		1AFD334123E03C4F0042899B /* controlhost.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AFD334023E03C4F0042899B /* controlhost.mm */; };
 		37155CE4233C00EB0034DCE9 /* menu.h in Headers */ = {isa = PBXBuildFile; fileRef = 37155CE3233C00EB0034DCE9 /* menu.h */; };
 		37A517B32159597E00FBA241 /* Screens.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37A517B22159597E00FBA241 /* Screens.mm */; };
 		37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37C09D8721580FE4006A6758 /* SystemDialogs.mm */; };
 		37DDA9B0219330F8002E132B /* AvnString.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37DDA9AF219330F8002E132B /* AvnString.mm */; };
 		37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37E2330E21583241000CB7E2 /* KeyTransform.mm */; };
 		520624B322973F4100C4DCEF /* menu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 520624B222973F4100C4DCEF /* menu.mm */; };
+		522D5959258159C1006F7F7A /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 522D5958258159C1006F7F7A /* Carbon.framework */; };
 		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 */; };
@@ -32,13 +33,13 @@
 
 /* Begin PBXFileReference section */
 		1A002B9D232135EE00021753 /* app.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = app.mm; sourceTree = "<group>"; };
+		1A1852DB23E05814008F0DED /* deadlock.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = deadlock.mm; sourceTree = "<group>"; };
 		1A3E5EA723E9E83B00EDE661 /* rendertarget.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = rendertarget.mm; sourceTree = "<group>"; };
 		1A3E5EA923E9F26C00EDE661 /* IOSurface.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOSurface.framework; path = System/Library/Frameworks/IOSurface.framework; sourceTree = SDKROOT; };
-		1A1852DB23E05814008F0DED /* deadlock.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = deadlock.mm; sourceTree = "<group>"; };
-		1AFD334023E03C4F0042899B /* controlhost.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = controlhost.mm; sourceTree = "<group>"; };
 		1A3E5EAD23E9FB1300EDE661 /* cgl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = cgl.mm; sourceTree = "<group>"; };
 		1A3E5EAF23E9FE8300EDE661 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
 		1A465D0F246AB61600C5858B /* dnd.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = dnd.mm; sourceTree = "<group>"; };
+		1AFD334023E03C4F0042899B /* controlhost.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = controlhost.mm; sourceTree = "<group>"; };
 		37155CE3233C00EB0034DCE9 /* menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = menu.h; sourceTree = "<group>"; };
 		379860FE214DA0C000CD0246 /* KeyTransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyTransform.h; sourceTree = "<group>"; };
 		37A4E71A2178846A00EACBCD /* headers */ = {isa = PBXFileReference; lastKnownFileType = folder; name = headers; path = ../../inc; sourceTree = "<group>"; };
@@ -49,6 +50,7 @@
 		37DDA9B121933371002E132B /* AvnString.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AvnString.h; sourceTree = "<group>"; };
 		37E2330E21583241000CB7E2 /* KeyTransform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyTransform.mm; sourceTree = "<group>"; };
 		520624B222973F4100C4DCEF /* menu.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = menu.mm; sourceTree = "<group>"; };
+		522D5958258159C1006F7F7A /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
 		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>"; };
@@ -69,6 +71,7 @@
 				1A3E5EB023E9FE8300EDE661 /* QuartzCore.framework in Frameworks */,
 				1A3E5EAA23E9F26C00EDE661 /* IOSurface.framework in Frameworks */,
 				AB1E522C217613570091CD71 /* OpenGL.framework in Frameworks */,
+				522D5959258159C1006F7F7A /* Carbon.framework in Frameworks */,
 				AB661C1E2148230F00291242 /* AppKit.framework in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -79,6 +82,7 @@
 		AB661C1C2148230E00291242 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
+				522D5958258159C1006F7F7A /* Carbon.framework */,
 				1A3E5EAF23E9FE8300EDE661 /* QuartzCore.framework */,
 				1A3E5EA923E9F26C00EDE661 /* IOSurface.framework */,
 				AB1E522B217613570091CD71 /* OpenGL.framework */,

+ 6 - 1
native/Avalonia.Native/src/OSX/KeyTransform.h

@@ -1,9 +1,14 @@
 #ifndef keytransform_h
 #define keytransform_h
 #include "common.h"
-#include "key.h"
 #include <map>
 
 extern std::map<int, AvnKey> s_KeyMap;
 
+extern std::map<AvnKey, int> s_AvnKeyMap;
+
+extern std::map<int, const char*> s_QwertyKeyMap;
+
+extern std::map<AvnKey, int> s_UnicodeKeyMap;
+
 #endif

+ 151 - 0
native/Avalonia.Native/src/OSX/KeyTransform.mm

@@ -120,6 +120,138 @@ const int kVK_UpArrow = 0x7E;
 //const int kVK_JIS_Eisu = 0x66;
 const int kVK_JIS_Kana = 0x68;
 
+// converts from AvaloniaKeys to UnicodeSpecial keys.
+std::map<AvnKey, int> s_UnicodeKeyMap =
+{
+    { Up, NSUpArrowFunctionKey },
+    { Down, NSDownArrowFunctionKey },
+    { Left, NSLeftArrowFunctionKey },
+    { Right, NSRightArrowFunctionKey },
+    { F1, NSF1FunctionKey },
+    { F2, NSF2FunctionKey },
+    { F3, NSF3FunctionKey },
+    { F4, NSF4FunctionKey },
+    { F5, NSF5FunctionKey },
+    { F6, NSF6FunctionKey },
+    { F7, NSF7FunctionKey },
+    { F8, NSF8FunctionKey },
+    { F9, NSF9FunctionKey },
+    { F10, NSF10FunctionKey },
+    { F11, NSF11FunctionKey },
+    { F12, NSF12FunctionKey },
+    { F13, NSF13FunctionKey },
+    { F14, NSF14FunctionKey },
+    { F15, NSF15FunctionKey },
+    { F16, NSF16FunctionKey },
+    { F17, NSF17FunctionKey },
+    { F18, NSF18FunctionKey },
+    { F19, NSF19FunctionKey },
+    { F20, NSF20FunctionKey },
+    { F21, NSF21FunctionKey },
+    { F22, NSF22FunctionKey },
+    { F23, NSF23FunctionKey },
+    { F24, NSF24FunctionKey },
+    { Insert, NSInsertFunctionKey },
+    { Delete, NSDeleteFunctionKey },
+    { Home, NSHomeFunctionKey },
+    //{ Begin, NSBeginFunctionKey },
+    { End, NSEndFunctionKey },
+    { PageUp, NSPageUpFunctionKey },
+    { PageDown, NSPageDownFunctionKey },
+    { PrintScreen, NSPrintScreenFunctionKey },
+    { Scroll, NSScrollLockFunctionKey },
+    //{ SysReq, NSSysReqFunctionKey },
+    //{ Break, NSBreakFunctionKey },
+    //{ Reset, NSResetFunctionKey },
+    //{ Stop, NSStopFunctionKey },
+    //{ Menu, NSMenuFunctionKey },
+    //{ UserFunction, NSUserFunctionKey },
+    //{ SystemFunction, NSSystemFunctionKey },
+    { Print, NSPrintFunctionKey },
+    //{ ClearLine, NSClearLineFunctionKey },
+    //{ ClearDisplay, NSClearDisplayFunctionKey },
+};
+
+// Converts from Ansi virtual keys to Qwerty Keyboard map.
+std::map<int, const char*> s_QwertyKeyMap =
+{
+    { 0, "a" },
+    { 1, "s" },
+    { 2, "d" },
+    { 3, "f" },
+    { 4, "h" },
+    { 5, "g" },
+    { 6, "z" },
+    { 7, "x" },
+    { 8, "c" },
+    { 9, "v" },
+    { 10, "§" },
+    { 11, "b" },
+    { 12, "q" },
+    { 13, "w" },
+    { 14, "e" },
+    { 15, "r" },
+    { 16, "y" },
+    { 17, "t" },
+    { 18, "1" },
+    { 19, "2" },
+    { 20, "3" },
+    { 21, "4" },
+    { 22, "6" },
+    { 23, "5" },
+    { 24, "=" },
+    { 25, "9" },
+    { 26, "7" },
+    { 27, "-" },
+    { 28, "8" },
+    { 29, "0" },
+    { 30, "]" },
+    { 31, "o" },
+    { 32, "u" },
+    { 33, "[" },
+    { 34, "i" },
+    { 35, "p" },
+    { 37, "l" },
+    { 38, "j" },
+    { 39, "'" },
+    { 40, "k" },
+    { 41, ";" },
+    { 42, "\\" },
+    { 43, "," },
+    { 44, "/" },
+    { 45, "n" },
+    { 46, "m" },
+    { 47, "." },
+    { 49, " " },
+    { 50, "`" },
+    { 51, "" },
+    { 52, "" },
+    { 53, "" },
+    { 65, "." },
+    { 66, "" },
+    { 67, "*" },
+    { 69, "+" },
+    { 70, "" },
+    { 71, "" },
+    { 72, "" },
+    { 75, "/" },
+    { 76, "" },
+    { 77, "" },
+    { 78, "-" },
+    { 81, "=" },
+    { 82, "0" },
+    { 83, "1" },
+    { 84, "2" },
+    { 85, "3" },
+    { 86, "4" },
+    { 87, "5" },
+    { 88, "6" },
+    { 89, "7" },
+    { 91, "8" },
+    { 92, "9" }
+};
+
+// converts from ansi virtualkeys to AvnKeys.
  std::map<int, AvnKey> s_KeyMap =
  {
     {kVK_ANSI_A, A},
@@ -237,3 +369,22 @@ const int kVK_JIS_Kana = 0x68;
     {kVK_UpArrow, Up},
     {kVK_JIS_Kana, AvnKeyKanaMode},
 };
+
+static std::map<AvnKey, int> BuildAvnKeyMap ()
+{
+    std::map<AvnKey, int> result;
+    
+    for( auto it = s_KeyMap.begin(); it != s_KeyMap.end(); ++it )
+    {
+        int key = it->first;
+        AvnKey value = it->second;
+        
+        result[value] = key;
+    }
+    
+    return result;
+}
+
+// Converts AvnKeys to Ansi VirtualKeys
+std::map<AvnKey, int> s_AvnKeyMap = BuildAvnKeyMap();
+

+ 1 - 1
native/Avalonia.Native/src/OSX/menu.h

@@ -45,7 +45,7 @@ public:
     
     virtual HRESULT SetTitle (char* utf8String) override;
     
-    virtual HRESULT SetGesture (char* key, AvnInputModifiers modifiers) override;
+    virtual HRESULT SetGesture (AvnKey key, AvnInputModifiers modifiers) override;
     
     virtual HRESULT SetAction (IAvnPredicateCallback* predicate, IAvnActionCallback* callback) override;
     

+ 51 - 14
native/Avalonia.Native/src/OSX/menu.mm

@@ -2,6 +2,9 @@
 #include "common.h"
 #include "menu.h"
 #include "window.h"
+#include "KeyTransform.h"
+#include <CoreFoundation/CoreFoundation.h>
+#include <Carbon/Carbon.h> /* For kVK_ constants, and TIS functions. */
 
 @implementation AvnMenu
 {
@@ -122,23 +125,57 @@ HRESULT AvnAppMenuItem::SetTitle (char* utf8String)
     }
 }
 
-HRESULT AvnAppMenuItem::SetGesture (char* key, AvnInputModifiers modifiers)
+
+HRESULT AvnAppMenuItem::SetGesture (AvnKey key, AvnInputModifiers modifiers)
 {
     @autoreleasepool
     {
-        NSEventModifierFlags flags = 0;
-        
-        if (modifiers & Control)
-            flags |= NSEventModifierFlagControl;
-        if (modifiers & Shift)
-            flags |= NSEventModifierFlagShift;
-        if (modifiers & Alt)
-            flags |= NSEventModifierFlagOption;
-        if (modifiers & Windows)
-            flags |= NSEventModifierFlagCommand;
-        
-        [_native setKeyEquivalent:[NSString stringWithUTF8String:(const char*)key]];
-        [_native setKeyEquivalentModifierMask:flags];
+        if(key != AvnKeyNone)
+        {
+            NSEventModifierFlags flags = 0;
+            
+            if (modifiers & Control)
+                flags |= NSEventModifierFlagControl;
+            if (modifiers & Shift)
+                flags |= NSEventModifierFlagShift;
+            if (modifiers & Alt)
+                flags |= NSEventModifierFlagOption;
+            if (modifiers & Windows)
+                flags |= NSEventModifierFlagCommand;
+            
+            auto it = s_UnicodeKeyMap.find(key);
+            
+            if(it != s_UnicodeKeyMap.end())
+            {
+                auto keyString= [NSString stringWithFormat:@"%C", (unsigned short)it->second];
+                
+                [_native setKeyEquivalent: keyString];
+                [_native setKeyEquivalentModifierMask:flags];
+                
+                return S_OK;
+            }
+            else
+            {
+                auto it = s_AvnKeyMap.find(key); // check if a virtual key is mapped.
+                
+                if(it != s_AvnKeyMap.end())
+                {
+                    auto it1 = s_QwertyKeyMap.find(it->second); // convert virtual key to qwerty string.
+                    
+                    if(it1 != s_QwertyKeyMap.end())
+                    {
+                        [_native setKeyEquivalent: [NSString  stringWithUTF8String: it1->second]];
+                        [_native setKeyEquivalentModifierMask:flags];
+                        
+                        return S_OK;
+                    }
+                }
+            }
+        }
+        
+        // Nothing matched... clear.
+        [_native setKeyEquivalent: @""];
+        [_native setKeyEquivalentModifierMask: 0];
         
         return S_OK;
     }

+ 4 - 4
native/Avalonia.Native/src/OSX/window.mm

@@ -106,13 +106,13 @@ public:
         return Window;
     }
     
-    virtual HRESULT Show() override
+    virtual HRESULT Show(bool activate) override
     {
         @autoreleasepool
         {
             SetPosition(lastPositionSet);
             UpdateStyle();
-            if(ShouldTakeFocusOnShow())
+            if(ShouldTakeFocusOnShow() && activate)
             {
                 [Window makeKeyAndOrderFront:Window];
                 [NSApp activateIgnoringOtherApps:YES];
@@ -561,11 +561,11 @@ private:
         }
     }
     
-    virtual HRESULT Show () override
+    virtual HRESULT Show (bool activate) override
     {
         @autoreleasepool
         {            
-            WindowBaseImpl::Show();
+            WindowBaseImpl::Show(activate);
             
             HideOrShowTrafficLights();
             

+ 10 - 1
readme.md

@@ -10,6 +10,8 @@ Avalonia is a cross-platform XAML-based UI framework providing a flexible stylin
 
 <img src="https://user-images.githubusercontent.com/6759207/84751662-7c79da00-afc5-11ea-8780-dda28db70b76.png" width="700" />
 
+([Xaml Control Gallery](https://github.com/AvaloniaUI/xamlcontrolsgallery))
+
 > **Note:** The UI theme you see in the picture above is still work-in-progress and will be available in the upcoming Avalonia 0.10.0 release. However, you can connect to our nightly build feed and install latest pre-release versions of Avalonia NuGet packages, if you are willing to help out with the development and testing. See [Using nightly build feed](https://github.com/AvaloniaUI/Avalonia/wiki/Using-nightly-build-feed) for more info.
 
 To see the status of some of our features, please see our [Roadmap](https://github.com/AvaloniaUI/Avalonia/issues/2239). You can also see what [breaking changes](https://github.com/AvaloniaUI/Avalonia/issues/3538) we have planned and what our [past breaking changes](https://github.com/AvaloniaUI/Avalonia/wiki/Breaking-Changes) have been. [Awesome Avalonia](https://github.com/AvaloniaCommunity/awesome-avalonia) is community-curated list of awesome Avalonia UI tools, libraries, projects and resources. Go and see what people are building with Avalonia!
@@ -31,15 +33,22 @@ Install-Package Avalonia.Desktop
 Examples of UIs built with Avalonia
 ![image](https://user-images.githubusercontent.com/4672627/84707589-5b69a880-af35-11ea-87a6-7ad57a31d314.png)
 
+([Synfonia](https://github.com/jmacato/Synfonia))
+
 ![image](https://user-images.githubusercontent.com/4672627/85069644-d8419000-b18a-11ea-8732-be9055bb61fd.PNG)
+([Xaml Control Gallery](https://github.com/AvaloniaUI/xamlcontrolsgallery))
 
 ![image](https://user-images.githubusercontent.com/4672627/85069659-dc6dad80-b18a-11ea-8375-39ef95315b5c.PNG)
+([Xaml Control Gallery](https://github.com/AvaloniaUI/xamlcontrolsgallery))
 
 ![image](https://user-images.githubusercontent.com/4672627/84708947-c3b98980-af37-11ea-8c9d-503334615bbf.png)
+([Xaml Control Gallery](https://github.com/AvaloniaUI/xamlcontrolsgallery))
 
 ## JetBrains Rider
 
-If you need to develop Avalonia app with JetBrains Rider you can use latest Rider [preview builds](https://www.jetbrains.com/rider/nextversion/).
+[JetBrains Rider](https://www.jetbrains.com/rider/whatsnew/?mkt_tok=eyJpIjoiTURBNU1HSmhNV0kwTUdFMiIsInQiOiJtNnU2VEc1TlNLa1ZRVkROYmdZYVpYREJsaU1qdUhmS3dxSzRHczdYWHl0RVlTNDMwSFwvNUs3VENTNVM0bVcyNFdaRmVYZzVWTTF1N3VrQWNGTkJreEhlam1hMlB4UVVWcHBGM1dNOUxoXC95YnRQdGgyUXl1YmZCM3h3d3BVWWdBIn0%3D#avalonia-support) now has official support for Avalonia.
+
+Code completion, inspections and refactorings are supported out of the box, for XAML previewer add `https://plugins.jetbrains.com/plugins/dev/14839` to plugin repositories and install [AvaloniaRider](https://github.com/ForNeVeR/AvaloniaRider) plugin.
 
 ## Bleeding Edge Builds
 

+ 1 - 2
samples/ControlCatalog.NetCore/Program.cs

@@ -114,8 +114,7 @@ namespace ControlCatalog.NetCore
                 })
                 .With(new Win32PlatformOptions
                 {
-                    EnableMultitouch = true,
-                    AllowEglInitialization = true
+                    EnableMultitouch = true
                 })
                 .UseSkia()
                 .UseManagedSystemDialogs()

+ 0 - 4
src/Avalonia.Base/ApiCompatBaseline.txt

@@ -1,4 +0,0 @@
-Compat issues with assembly Avalonia.Base:
-CannotAddAbstractMembers : Member 'protected System.IObservable<Avalonia.AvaloniaPropertyChangedEventArgs> Avalonia.AvaloniaProperty.GetChanged()' is abstract in the implementation but is missing in the contract.
-TypesMustExist : Type 'Avalonia.Logging.DebugLogSink' does not exist in the implementation but it does exist in the contract.
-Total Issues: 2

+ 12 - 12
src/Avalonia.Base/AvaloniaProperty.cs

@@ -17,9 +17,9 @@ namespace Avalonia
         public static readonly object UnsetValue = new UnsetValueType();
 
         private static int s_nextId;
-        private readonly PropertyMetadata _defaultMetadata;
-        private readonly Dictionary<Type, PropertyMetadata> _metadata;
-        private readonly Dictionary<Type, PropertyMetadata> _metadataCache = new Dictionary<Type, PropertyMetadata>();
+        private readonly AvaloniaPropertyMetadata _defaultMetadata;
+        private readonly Dictionary<Type, AvaloniaPropertyMetadata> _metadata;
+        private readonly Dictionary<Type, AvaloniaPropertyMetadata> _metadataCache = new Dictionary<Type, AvaloniaPropertyMetadata>();
 
         private bool _hasMetadataOverrides;
 
@@ -35,7 +35,7 @@ namespace Avalonia
             string name,
             Type valueType,
             Type ownerType,
-            PropertyMetadata metadata,
+            AvaloniaPropertyMetadata metadata,
             Action<IAvaloniaObject, bool> notifying = null)
         {
             Contract.Requires<ArgumentNullException>(name != null);
@@ -48,7 +48,7 @@ namespace Avalonia
                 throw new ArgumentException("'name' may not contain periods.");
             }
 
-            _metadata = new Dictionary<Type, PropertyMetadata>();
+            _metadata = new Dictionary<Type, AvaloniaPropertyMetadata>();
 
             Name = name;
             PropertyType = valueType;
@@ -69,12 +69,12 @@ namespace Avalonia
         protected AvaloniaProperty(
             AvaloniaProperty source,
             Type ownerType,
-            PropertyMetadata metadata)
+            AvaloniaPropertyMetadata metadata)
         {
             Contract.Requires<ArgumentNullException>(source != null);
             Contract.Requires<ArgumentNullException>(ownerType != null);
 
-            _metadata = new Dictionary<Type, PropertyMetadata>();
+            _metadata = new Dictionary<Type, AvaloniaPropertyMetadata>();
 
             Name = source.Name;
             PropertyType = source.PropertyType;
@@ -419,7 +419,7 @@ namespace Avalonia
         /// <returns>
         /// The property metadata.
         /// </returns>
-        public PropertyMetadata GetMetadata<T>() where T : IAvaloniaObject
+        public AvaloniaPropertyMetadata GetMetadata<T>() where T : IAvaloniaObject
         {
             return GetMetadata(typeof(T));
         }
@@ -432,7 +432,7 @@ namespace Avalonia
         /// The property metadata.
         /// </returns>
         ///
-        public PropertyMetadata GetMetadata(Type type)
+        public AvaloniaPropertyMetadata GetMetadata(Type type)
         {
             if (!_hasMetadataOverrides)
             {
@@ -521,7 +521,7 @@ namespace Avalonia
         /// </summary>
         /// <param name="type">The type.</param>
         /// <param name="metadata">The metadata.</param>
-        protected void OverrideMetadata(Type type, PropertyMetadata metadata)
+        protected void OverrideMetadata(Type type, AvaloniaPropertyMetadata metadata)
         {
             Contract.Requires<ArgumentNullException>(type != null);
             Contract.Requires<ArgumentNullException>(metadata != null);
@@ -542,14 +542,14 @@ namespace Avalonia
 
         protected abstract IObservable<AvaloniaPropertyChangedEventArgs> GetChanged();
 
-        private PropertyMetadata GetMetadataWithOverrides(Type type)
+        private AvaloniaPropertyMetadata GetMetadataWithOverrides(Type type)
         {
             if (type is null)
             {
                 throw new ArgumentNullException(nameof(type));
             }
 
-            if (_metadataCache.TryGetValue(type, out PropertyMetadata result))
+            if (_metadataCache.TryGetValue(type, out AvaloniaPropertyMetadata result))
             {
                 return result;
             }

+ 4 - 4
src/Avalonia.Base/PropertyMetadata.cs → src/Avalonia.Base/AvaloniaPropertyMetadata.cs

@@ -5,15 +5,15 @@ namespace Avalonia
     /// <summary>
     /// Base class for avalonia property metadata.
     /// </summary>
-    public class PropertyMetadata
+    public class AvaloniaPropertyMetadata
     {
         private BindingMode _defaultBindingMode;
 
         /// <summary>
-        /// Initializes a new instance of the <see cref="PropertyMetadata"/> class.
+        /// Initializes a new instance of the <see cref="AvaloniaPropertyMetadata"/> class.
         /// </summary>
         /// <param name="defaultBindingMode">The default binding mode.</param>
-        public PropertyMetadata(
+        public AvaloniaPropertyMetadata(
             BindingMode defaultBindingMode = BindingMode.Default)
         {
             _defaultBindingMode = defaultBindingMode;
@@ -37,7 +37,7 @@ namespace Avalonia
         /// <param name="baseMetadata">The base metadata to merge.</param>
         /// <param name="property">The property to which the metadata is being applied.</param>
         public virtual void Merge(
-            PropertyMetadata baseMetadata, 
+            AvaloniaPropertyMetadata baseMetadata, 
             AvaloniaProperty property)
         {
             if (_defaultBindingMode == BindingMode.Default)

+ 3 - 3
src/Avalonia.Base/AvaloniaProperty`1.cs

@@ -23,7 +23,7 @@ namespace Avalonia
         protected AvaloniaProperty(
             string name,
             Type ownerType,
-            PropertyMetadata metadata,
+            AvaloniaPropertyMetadata metadata,
             Action<IAvaloniaObject, bool> notifying = null)
             : base(name, typeof(TValue), ownerType, metadata, notifying)
         {
@@ -40,7 +40,7 @@ namespace Avalonia
         protected AvaloniaProperty(
             AvaloniaProperty source,
             Type ownerType,
-            PropertyMetadata metadata)
+            AvaloniaPropertyMetadata metadata)
             : this(source as AvaloniaProperty<TValue> ?? throw new InvalidOperationException(), ownerType, metadata)
         {
         }
@@ -54,7 +54,7 @@ namespace Avalonia
         protected AvaloniaProperty(
             AvaloniaProperty<TValue> source,
             Type ownerType,
-            PropertyMetadata metadata)
+            AvaloniaPropertyMetadata metadata)
             : base(source, ownerType, metadata)
         {
             _changed = source._changed;

+ 3 - 3
src/Avalonia.Base/DirectPropertyBase.cs

@@ -26,7 +26,7 @@ namespace Avalonia
         protected DirectPropertyBase(
             string name,
             Type ownerType,
-            PropertyMetadata metadata)
+            AvaloniaPropertyMetadata metadata)
             : base(name, ownerType, metadata)
         {
         }
@@ -41,7 +41,7 @@ namespace Avalonia
         protected DirectPropertyBase(
             AvaloniaProperty source,
             Type ownerType,
-            PropertyMetadata metadata)
+            AvaloniaPropertyMetadata metadata)
             : this(source as DirectPropertyBase<TValue> ?? throw new InvalidOperationException(), ownerType, metadata)
         {
         }
@@ -55,7 +55,7 @@ namespace Avalonia
         protected DirectPropertyBase(
             DirectPropertyBase<TValue> source,
             Type ownerType,
-            PropertyMetadata metadata)
+            AvaloniaPropertyMetadata metadata)
             : base(source, ownerType, metadata)
         {
         }

+ 2 - 2
src/Avalonia.Base/DirectPropertyMetadata`1.cs

@@ -5,7 +5,7 @@ namespace Avalonia
     /// <summary>
     /// Metadata for direct avalonia properties.
     /// </summary>
-    public class DirectPropertyMetadata<TValue> : PropertyMetadata, IDirectPropertyMetadata
+    public class DirectPropertyMetadata<TValue> : AvaloniaPropertyMetadata, IDirectPropertyMetadata
     {
         /// <summary>
         /// Initializes a new instance of the <see cref="StyledPropertyMetadata{TValue}"/> class.
@@ -47,7 +47,7 @@ namespace Avalonia
         object IDirectPropertyMetadata.UnsetValue => UnsetValue;
 
         /// <inheritdoc/>
-        public override void Merge(PropertyMetadata baseMetadata, AvaloniaProperty property)
+        public override void Merge(AvaloniaPropertyMetadata baseMetadata, AvaloniaProperty property)
         {
             base.Merge(baseMetadata, property);
 

+ 5 - 0
src/Avalonia.Base/Logging/LogArea.cs

@@ -34,5 +34,10 @@ namespace Avalonia.Logging
         /// The log event comes from the control system.
         /// </summary>
         public const string Control = "Control";
+
+        /// <summary>
+        /// The log event comes from Win32Platform.
+        /// </summary>
+        public const string Win32Platform = nameof(Win32Platform);
     }
 }

+ 2 - 0
src/Avalonia.Base/Properties/AssemblyInfo.cs

@@ -11,10 +11,12 @@ using Avalonia.Metadata;
 [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] 
 [assembly: InternalsVisibleTo("Avalonia.Controls.DataGrid, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
 [assembly: InternalsVisibleTo("Avalonia.Markup.Xaml.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+[assembly: InternalsVisibleTo("Avalonia.Visuals, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
 #else
 [assembly: InternalsVisibleTo("Avalonia.Base.UnitTests")]
 [assembly: InternalsVisibleTo("Avalonia.UnitTests")]
 [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
 [assembly: InternalsVisibleTo("Avalonia.Controls.DataGrid")]
 [assembly: InternalsVisibleTo("Avalonia.Markup.Xaml.UnitTests")]
+[assembly: InternalsVisibleTo("Avalonia.Visuals")]
 #endif

+ 2 - 2
src/Avalonia.Base/StyledPropertyMetadata`1.cs

@@ -6,7 +6,7 @@ namespace Avalonia
     /// <summary>
     /// Metadata for styled avalonia properties.
     /// </summary>
-    public class StyledPropertyMetadata<TValue> : PropertyMetadata, IStyledPropertyMetadata
+    public class StyledPropertyMetadata<TValue> : AvaloniaPropertyMetadata, IStyledPropertyMetadata
     {
         private Optional<TValue> _defaultValue;
 
@@ -39,7 +39,7 @@ namespace Avalonia
         object IStyledPropertyMetadata.DefaultValue => DefaultValue;
 
         /// <inheritdoc/>
-        public override void Merge(PropertyMetadata baseMetadata, AvaloniaProperty property)
+        public override void Merge(AvaloniaPropertyMetadata baseMetadata, AvaloniaProperty property)
         {
             base.Merge(baseMetadata, property);
 

+ 2 - 23
src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs

@@ -9,20 +9,6 @@ namespace Avalonia.Threading
     /// </summary>
     public class AvaloniaSynchronizationContext : SynchronizationContext
     {
-        public interface INonPumpingPlatformWaitProvider
-        {
-            int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout);
-        }
-
-        private readonly INonPumpingPlatformWaitProvider _waitProvider;
-
-        public AvaloniaSynchronizationContext(INonPumpingPlatformWaitProvider waitProvider)
-        {
-            _waitProvider = waitProvider;
-            if (_waitProvider != null)
-                SetWaitNotificationRequired();
-        }
-
         /// <summary>
         /// Controls if SynchronizationContext should be installed in InstallIfNeeded. Used by Designer.
         /// </summary>
@@ -38,8 +24,7 @@ namespace Avalonia.Threading
                 return;
             }
 
-            SetSynchronizationContext(new AvaloniaSynchronizationContext(AvaloniaLocator.Current
-                .GetService<INonPumpingPlatformWaitProvider>()));
+            SetSynchronizationContext(new AvaloniaSynchronizationContext());
         }
 
         /// <inheritdoc/>
@@ -57,12 +42,6 @@ namespace Avalonia.Threading
                 Dispatcher.UIThread.InvokeAsync(() => d(state), DispatcherPriority.Send).Wait();
         }
 
-        [PrePrepareMethod]
-        public override int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
-        {
-            if (_waitProvider != null)
-                return _waitProvider.Wait(waitHandles, waitAll, millisecondsTimeout);
-            return base.Wait(waitHandles, waitAll, millisecondsTimeout);
-        }
+
     }
 }

+ 14 - 0
src/Avalonia.Base/Utilities/NonPumpingLockHelper.cs

@@ -0,0 +1,14 @@
+using System;
+
+namespace Avalonia.Utilities
+{
+    public class NonPumpingLockHelper
+    {
+        public interface IHelperImpl
+        {
+            IDisposable Use();
+        }
+
+        public static IDisposable Use() => AvaloniaLocator.Current.GetService<IHelperImpl>()?.Use();
+    }
+}

+ 0 - 5
src/Avalonia.Controls.DataGrid/ApiCompatBaseline.txt

@@ -1,5 +0,0 @@
-Compat issues with assembly Avalonia.Controls.DataGrid:
-MembersMustExist : Member 'public Avalonia.StyledProperty<System.String> Avalonia.StyledProperty<System.String> Avalonia.Controls.DataGridTextColumn.FontFamilyProperty' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public System.String Avalonia.Controls.DataGridTextColumn.FontFamily.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public void Avalonia.Controls.DataGridTextColumn.FontFamily.set(System.String)' does not exist in the implementation but it does exist in the contract.
-Total Issues: 3

+ 21 - 0
src/Avalonia.Controls.DataGrid/Primitives/DataGridRowsPresenter.cs

@@ -22,6 +22,22 @@ namespace Avalonia.Controls.Primitives
         }
 
         private double _measureHeightOffset = 0;
+        private double _effectiveViewPortHeight = 0;
+
+        public DataGridRowsPresenter()
+        {
+            EffectiveViewportChanged += OnEffectiveViewportChanged;
+        }
+
+        private void OnEffectiveViewportChanged(object sender, Layout.EffectiveViewportChangedEventArgs e)
+        {
+            if (_effectiveViewPortHeight != e.EffectiveViewport.Height)
+            {
+                _effectiveViewPortHeight = e.EffectiveViewport.Height;
+                InvalidateMeasure();
+            }
+        }
+
         private double CalculateEstimatedAvailableHeight(Size availableSize)
         {
             if(!Double.IsPositiveInfinity(availableSize.Height))
@@ -108,6 +124,11 @@ namespace Avalonia.Controls.Primitives
         /// </returns>
         protected override Size MeasureOverride(Size availableSize)
         {
+            if (double.IsInfinity(availableSize.Height))
+            {
+                availableSize = availableSize.WithHeight(_effectiveViewPortHeight);
+            }
+
             if (availableSize.Height == 0 || OwningGrid == null)
             {
                 return base.MeasureOverride(availableSize);

+ 27 - 2
src/Avalonia.Controls.DataGrid/Themes/Default.xaml

@@ -137,12 +137,37 @@
   </Style>
 
   <Style Selector="DataGridRowHeader">
+    <Setter Property="Focusable" Value="False" />
     <Setter Property="Template">
       <ControlTemplate>
         <Grid x:Name="PART_Root"
-        RowDefinitions="*,*,Auto"
-        ColumnDefinitions="Auto,*">
+              RowDefinitions="*,*,Auto"
+              ColumnDefinitions="Auto,*">
+          <Border Grid.RowSpan="3"
+                  Grid.ColumnSpan="2"
+                  BorderBrush="{TemplateBinding SeparatorBrush}"
+                  BorderThickness="0,0,1,0">
+            <Grid Background="{TemplateBinding Background}">
+              <Rectangle x:Name="RowInvalidVisualElement"
+                         Stretch="Fill" />
+              <Rectangle x:Name="BackgroundRectangle"
+                         Stretch="Fill" />
+            </Grid>
+          </Border>
+          <Rectangle x:Name="HorizontalSeparator"
+                     Grid.Row="2"
+                     Grid.ColumnSpan="2"
+                     Height="1"
+                     Margin="1,0,1,0"
+                     HorizontalAlignment="Stretch"
+                     Fill="{TemplateBinding SeparatorBrush}"
+                     IsVisible="{TemplateBinding AreSeparatorsVisible}" />
 
+          <ContentPresenter Grid.RowSpan="2"
+                            Grid.Column="1"
+                            HorizontalAlignment="Center"
+                            VerticalAlignment="Center"
+                            Content="{TemplateBinding Content}" />
         </Grid>
       </ControlTemplate>
     </Setter>

+ 22 - 4
src/Avalonia.Controls.DataGrid/Utils/ReflectionHelper.cs

@@ -352,19 +352,37 @@ namespace Avalonia.Controls.Utils
                 return null;
             }
 
-            PropertyInfo indexer = null;
             string stringIndex = propertyPath.Substring(1, propertyPath.Length - 2);
-            indexer = FindIndexerInMembers(type.GetDefaultMembers(), stringIndex, out index);
+            var indexer = FindIndexerInMembers(type.GetDefaultMembers(), stringIndex, out index);
             if (indexer != null)
             {
                 // We found the indexer, so return it.
                 return indexer;
             }
 
-            if (typeof(IList).IsAssignableFrom(type))
+            var elementType = type.GetElementType();
+            if (elementType == null)
+            {
+                var genericArguments = type.GetGenericArguments();
+                if (genericArguments.Length == 1)
+                {
+                    elementType = genericArguments[0];
+                }
+            }
+
+            if (elementType != null)
             {
                 // If the object is of type IList, try to use its default indexer.
-                indexer = FindIndexerInMembers(typeof(IList).GetDefaultMembers(), stringIndex, out index);
+                if (typeof(IList<>).MakeGenericType(elementType) is Type genericList
+                    && genericList.IsAssignableFrom(type))
+                {
+                    indexer = FindIndexerInMembers(genericList.GetDefaultMembers(), stringIndex, out index);
+                }
+                if (typeof(IReadOnlyList<>).MakeGenericType(elementType) is Type genericReadOnlyList
+                   && genericReadOnlyList.IsAssignableFrom(type))
+                {
+                    indexer = FindIndexerInMembers(genericReadOnlyList.GetDefaultMembers(), stringIndex, out index);
+                }
             }
 
             return indexer;

+ 0 - 26
src/Avalonia.Controls/ApiCompatBaseline.txt

@@ -1,26 +0,0 @@
-Compat issues with assembly Avalonia.Controls:
-TypesMustExist : Type 'Avalonia.Controls.IndexPath' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'Avalonia.Controls.ISelectedItemInfo' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'Avalonia.Controls.ISelectionModel' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public Avalonia.DirectProperty<Avalonia.Controls.Primitives.SelectingItemsControl, Avalonia.Controls.ISelectionModel> Avalonia.DirectProperty<Avalonia.Controls.Primitives.SelectingItemsControl, Avalonia.Controls.ISelectionModel> Avalonia.Controls.ListBox.SelectionProperty' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public Avalonia.Controls.ISelectionModel Avalonia.Controls.ListBox.Selection.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public void Avalonia.Controls.ListBox.Selection.set(Avalonia.Controls.ISelectionModel)' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'Avalonia.Controls.SelectionModel' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'Avalonia.Controls.SelectionModelChildrenRequestedEventArgs' does not exist in the implementation but it does exist in the contract.
-TypesMustExist : Type 'Avalonia.Controls.SelectionModelSelectionChangedEventArgs' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public Avalonia.StyledProperty<Avalonia.Controls.IControl> Avalonia.StyledProperty<Avalonia.Controls.IControl> Avalonia.Controls.SplitView.ContentProperty' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public Avalonia.StyledProperty<Avalonia.Controls.IControl> Avalonia.StyledProperty<Avalonia.Controls.IControl> Avalonia.Controls.SplitView.PaneProperty' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public Avalonia.Controls.IControl Avalonia.Controls.SplitView.Content.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public void Avalonia.Controls.SplitView.Content.set(Avalonia.Controls.IControl)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public Avalonia.Controls.IControl Avalonia.Controls.SplitView.Pane.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public void Avalonia.Controls.SplitView.Pane.set(Avalonia.Controls.IControl)' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public Avalonia.DirectProperty<Avalonia.Controls.TreeView, Avalonia.Controls.ISelectionModel> Avalonia.DirectProperty<Avalonia.Controls.TreeView, Avalonia.Controls.ISelectionModel> Avalonia.Controls.TreeView.SelectionProperty' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent<Avalonia.Controls.SelectionChangedEventArgs> Avalonia.Interactivity.RoutedEvent<Avalonia.Controls.SelectionChangedEventArgs> Avalonia.Controls.TreeView.SelectionChangedEvent' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public Avalonia.Controls.ISelectionModel Avalonia.Controls.TreeView.Selection.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public void Avalonia.Controls.TreeView.Selection.set(Avalonia.Controls.ISelectionModel)' does not exist in the implementation but it does exist in the contract.
-InterfacesShouldHaveSameMembers : Interface member 'public System.String[] Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime.Args' is present in the implementation but not in the contract.
-InterfacesShouldHaveSameMembers : Interface member 'public System.String[] Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime.Args.get()' is present in the implementation but not in the contract.
-MembersMustExist : Member 'public Avalonia.DirectProperty<Avalonia.Controls.Primitives.SelectingItemsControl, Avalonia.Controls.ISelectionModel> Avalonia.DirectProperty<Avalonia.Controls.Primitives.SelectingItemsControl, Avalonia.Controls.ISelectionModel> Avalonia.Controls.Primitives.SelectingItemsControl.SelectionProperty' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'protected Avalonia.Controls.ISelectionModel Avalonia.Controls.Primitives.SelectingItemsControl.Selection.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'protected void Avalonia.Controls.Primitives.SelectingItemsControl.Selection.set(Avalonia.Controls.ISelectionModel)' does not exist in the implementation but it does exist in the contract.
-Total Issues: 24

+ 3 - 1
src/Avalonia.Controls/Button.cs

@@ -30,7 +30,7 @@ namespace Avalonia.Controls
     /// A button control.
     /// </summary>
     [PseudoClasses(":pressed")]
-    public class Button : ContentControl
+    public class Button : ContentControl, ICommandSource
     {
         /// <summary>
         /// Defines the <see cref="ClickMode"/> property.
@@ -492,5 +492,7 @@ namespace Avalonia.Controls
         {
             PseudoClasses.Set(":pressed", isPressed);
         }
+
+        void ICommandSource.CanExecuteChanged(object sender, EventArgs e) => this.CanExecuteChanged(sender, e);
     }
 }

+ 10 - 0
src/Avalonia.Controls/ContextMenu.cs

@@ -233,6 +233,16 @@ namespace Avalonia.Controls
             }
         }
 
+        protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change)
+        {
+            base.OnPropertyChanged(change);
+
+            if (change.Property == WindowManagerAddShadowHintProperty && _popup != null)
+            {
+                _popup.WindowManagerAddShadowHint = change.NewValue.GetValueOrDefault<bool>();
+            }
+        }
+
         /// <summary>
         /// Opens the menu.
         /// </summary>

+ 17 - 9
src/Avalonia.Controls/HotkeyManager.cs

@@ -12,18 +12,21 @@ namespace Avalonia.Controls
 
         class HotkeyCommandWrapper : ICommand
         {
-            public HotkeyCommandWrapper(IControl control)
+            public HotkeyCommandWrapper(ICommandSource control)
             {
-                Control = control;
+                CommandSource = control;
             }
 
-            public readonly IControl Control;
+            public readonly ICommandSource CommandSource;
 
-            private ICommand GetCommand() => Control.GetValue(Button.CommandProperty);
+            private ICommand GetCommand() => CommandSource.Command;
 
-            public bool CanExecute(object parameter) => GetCommand()?.CanExecute(parameter) ?? false;
+            public bool CanExecute(object parameter) =>
+                CommandSource.Command?.CanExecute(CommandSource.CommandParameter) == true
+                && CommandSource.IsEffectivelyEnabled;
 
-            public void Execute(object parameter) => GetCommand()?.Execute(parameter);
+            public void Execute(object parameter) =>
+                GetCommand()?.Execute(CommandSource.CommandParameter);
 
 #pragma warning disable 67 // Event not used
             public event EventHandler CanExecuteChanged;
@@ -44,7 +47,7 @@ namespace Avalonia.Controls
             public Manager(IControl control)
             {
                 _control = control;
-                _wrapper = new HotkeyCommandWrapper(_control);
+                _wrapper = new HotkeyCommandWrapper(_control as ICommandSource);
             }
 
             public void Init()
@@ -84,7 +87,7 @@ namespace Avalonia.Controls
             {
                 if (_root != null && _hotkey != null)
                 {
-                    _binding = new KeyBinding() {Gesture = _hotkey, Command = _wrapper};
+                    _binding = new KeyBinding() { Gesture = _hotkey, Command = _wrapper };
                     _root.KeyBindings.Add(_binding);
                 }
             }
@@ -102,8 +105,13 @@ namespace Avalonia.Controls
             HotKeyProperty.Changed.Subscribe(args =>
             {
                 var control = args.Sender as IControl;
-                if (args.OldValue != null|| control == null)
+                if (args.OldValue != null || control == null || !(control is ICommandSource))
+                {
+                    Logging.Logger.TryGet(Logging.LogEventLevel.Warning, Logging.LogArea.Control)?.
+                        Log(control, $"The element {args.Sender.GetType().Name} does not support binding a HotKey ({args.NewValue}).");
                     return;
+                }
+
                 new Manager(control).Init();
             });
         }

+ 3 - 1
src/Avalonia.Controls/MenuItem.cs

@@ -22,7 +22,7 @@ namespace Avalonia.Controls
     /// A menu item control.
     /// </summary>
     [PseudoClasses(":separator", ":icon", ":open", ":pressed", ":selected")]
-    public class MenuItem : HeaderedSelectingItemsControl, IMenuItem, ISelectable
+    public class MenuItem : HeaderedSelectingItemsControl, IMenuItem, ISelectable, ICommandSource
     {
         /// <summary>
         /// Defines the <see cref="Command"/> property.
@@ -609,6 +609,8 @@ namespace Avalonia.Controls
             SelectedItem = null;
         }
 
+        void ICommandSource.CanExecuteChanged(object sender, EventArgs e) => this.CanExecuteChanged(sender, e);
+
         /// <summary>
         /// A dependency resolver which returns a <see cref="MenuItemAccessKeyHandler"/>.
         /// </summary>

+ 1 - 1
src/Avalonia.Controls/NativeMenuItem.cs

@@ -150,7 +150,7 @@ namespace Avalonia.Controls
 
         void CanExecuteChanged()
         {
-            IsEnabled = _command?.CanExecute(null) ?? true;
+            IsEnabled = _command?.CanExecute(CommandParameter) ?? true;
         }
 
         public bool HasClickHandlers => Click != null;

+ 2 - 2
src/Avalonia.Controls/Platform/IWindowBaseImpl.cs

@@ -5,9 +5,9 @@ namespace Avalonia.Platform
     public interface IWindowBaseImpl : ITopLevelImpl
     {
         /// <summary>
-        /// Shows the top level.
+        /// Shows the window.
         /// </summary>
-        void Show();
+        void Show(bool activate);
 
         /// <summary>
         /// Hides the window.

+ 4 - 1
src/Avalonia.Controls/TextBox.cs

@@ -872,7 +872,10 @@ namespace Avalonia.Controls
             {
                 var point = e.GetPosition(_presenter);
 
-                point = new Point(MathUtilities.Clamp(point.X, 0, _presenter.Bounds.Width - 1), MathUtilities.Clamp(point.Y, 0, _presenter.Bounds.Height - 1));
+                point = new Point(
+                    MathUtilities.Clamp(point.X, 0, Math.Max(_presenter.Bounds.Width - 1, 0)),
+                    MathUtilities.Clamp(point.Y, 0, Math.Max(_presenter.Bounds.Height - 1, 0)));
+
                 CaretIndex = SelectionEnd = _presenter.GetCaretIndex(point);
             }
         }

+ 17 - 3
src/Avalonia.Controls/Window.cs

@@ -129,6 +129,12 @@ namespace Avalonia.Controls
         public static readonly StyledProperty<SystemDecorations> SystemDecorationsProperty =
             AvaloniaProperty.Register<Window, SystemDecorations>(nameof(SystemDecorations), SystemDecorations.Full);
 
+        /// <summary>
+        /// Defines the <see cref="ShowActivated"/> property.
+        /// </summary>
+        public static readonly StyledProperty<bool> ShowActivatedProperty =
+            AvaloniaProperty.Register<Window, bool>(nameof(ShowActivated), true);
+
         /// <summary>
         /// Enables or disables the taskbar icon
         /// </summary>
@@ -352,13 +358,21 @@ namespace Avalonia.Controls
         /// <summary>
         /// Sets the system decorations (title bar, border, etc)
         /// </summary>
-        /// 
         public SystemDecorations SystemDecorations
         {
             get { return GetValue(SystemDecorationsProperty); }
             set { SetValue(SystemDecorationsProperty, value); }
         }
 
+        /// <summary>
+        /// Gets or sets a value that indicates whether a window is activated when first shown. 
+        /// </summary>
+        public bool ShowActivated
+        {
+            get { return GetValue(ShowActivatedProperty); }
+            set { SetValue(ShowActivatedProperty, value); }
+        }
+
         /// <summary>
         /// Enables or disables the taskbar icon
         /// </summary>
@@ -650,7 +664,7 @@ namespace Avalonia.Controls
                 Owner = parent;
                 parent?.AddChild(this, false);
 
-                PlatformImpl?.Show();
+                PlatformImpl?.Show(ShowActivated);
                 Renderer?.Start();
                 SetWindowStartupLocation(Owner?.PlatformImpl);
             }
@@ -720,7 +734,7 @@ namespace Avalonia.Controls
                 PlatformImpl?.SetParent(owner.PlatformImpl);
                 Owner = owner;
                 owner.AddChild(this, true);
-                PlatformImpl?.Show();
+                PlatformImpl?.Show(ShowActivated);
 
                 Renderer?.Start();
 

+ 1 - 1
src/Avalonia.Controls/WindowBase.cs

@@ -162,7 +162,7 @@ namespace Avalonia.Controls
                     LayoutManager.ExecuteInitialLayoutPass();
                     _hasExecutedInitialLayoutPass = true;
                 }
-                PlatformImpl?.Show();
+                PlatformImpl?.Show(true);
                 Renderer?.Start();
                 OnOpened(EventArgs.Empty);
             }

+ 1 - 1
src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs

@@ -20,7 +20,7 @@ namespace Avalonia.DesignerSupport.Remote
             ClientSize = new Size(1, 1);
         }
 
-        public void Show()
+        public void Show(bool activate)
         {
         }
 

+ 1 - 1
src/Avalonia.DesignerSupport/Remote/Stubs.cs

@@ -77,7 +77,7 @@ namespace Avalonia.DesignerSupport.Remote
         {
         }
 
-        public void Show()
+        public void Show(bool activate)
         {
         }
 

+ 3 - 0
src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml

@@ -12,6 +12,9 @@
     <StyleInclude Source="resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default"/>
     <StyleInclude Source="resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"/>
     <StyleInclude Source="resm:Avalonia.Controls.DataGrid.Themes.Default.xaml?assembly=Avalonia.Controls.DataGrid"/>
+    <Style Selector="DataGrid ContextMenu">
+      <Setter Property="Foreground" Value="Black"/>
+    </Style>
   </Window.Styles>
   
   <views:MainView/>

+ 0 - 1
src/Avalonia.Dialogs/ApiCompatBaseline.txt

@@ -1 +0,0 @@
-Total Issues: 0

+ 1 - 1
src/Avalonia.FreeDesktop/DBusHelper.cs

@@ -44,7 +44,7 @@ namespace Avalonia.FreeDesktop
             public void Initialized()
             {
                 lock (_lock)
-                    _ctx = new AvaloniaSynchronizationContext(null);
+                    _ctx = new AvaloniaSynchronizationContext();
             }
         }
         public static Connection Connection { get; private set; }

+ 4 - 3
src/Avalonia.Headless/HeadlessWindowImpl.cs

@@ -75,9 +75,10 @@ namespace Avalonia.Headless
         public Action Closed { get; set; }
         public IMouseDevice MouseDevice { get; }
 
-        public void Show()
+        public void Show(bool activate)
         {
-            Dispatcher.UIThread.Post(() => Activated?.Invoke(), DispatcherPriority.Input);
+            if (activate)
+                Dispatcher.UIThread.Post(() => Activated?.Invoke(), DispatcherPriority.Input);
         }
 
         public void Hide()
@@ -148,7 +149,7 @@ namespace Avalonia.Headless
 
         public void ShowDialog(IWindowImpl parent)
         {
-            Show();
+            Show(true);
         }
 
         public void SetSystemDecorations(bool enabled)

+ 0 - 4
src/Avalonia.Input/ApiCompatBaseline.txt

@@ -1,4 +0,0 @@
-Compat issues with assembly Avalonia.Input:
-InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalonia.Input.IInputElement.IsKeyboardFocusWithin' is present in the implementation but not in the contract.
-InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalonia.Input.IInputElement.IsKeyboardFocusWithin.get()' is present in the implementation but not in the contract.
-Total Issues: 2

+ 36 - 0
src/Avalonia.Input/ICommandSource.cs

@@ -0,0 +1,36 @@
+using System.Windows.Input;
+
+namespace Avalonia.Input
+{
+    ///<summary>
+    /// An interface for classes that know how to invoke a Command.
+    ///</summary>
+    public interface ICommandSource
+    {
+        /// <summary>
+        /// The command that will be executed when the class is "invoked."
+        /// Classes that implement this interface should enable or disable based on the command's CanExecute return value.
+        /// The property may be implemented as read-write if desired.
+        /// </summary>
+        ICommand Command { get; }
+
+        /// <summary>
+        /// The parameter that will be passed to the command when executing the command.
+        /// The property may be implemented as read-write if desired.
+        /// </summary>
+        object CommandParameter { get; }
+
+
+        /// <summary>
+        /// Bor the bheavior CanExecuteChanged
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        void CanExecuteChanged(object sender, System.EventArgs e);
+
+        /// <summary>
+        /// Gets a value indicating whether this control and all its parents are enabled.
+        /// </summary>
+        bool IsEffectivelyEnabled { get; }
+    }
+}

+ 2 - 2
src/Avalonia.Native/IAvnMenuItem.cs

@@ -55,9 +55,9 @@ namespace Avalonia.Native.Interop.Impl
 
         private void UpdateGesture(Input.KeyGesture gesture)
         {
-            var text = gesture == null ? "" : OsxUnicodeKeys.ConvertOSXSpecialKeyCodes(gesture.Key);
             var modifiers = gesture == null ? AvnInputModifiers.AvnInputModifiersNone : (AvnInputModifiers)gesture.KeyModifiers;
-            SetGesture(text, modifiers);
+            var key = gesture == null ? AvnKey.AvnKeyNone : (AvnKey)gesture.Key;
+            SetGesture(key, modifiers);
         }
 
         private void UpdateAction(NativeMenuItem item)

+ 0 - 152
src/Avalonia.Native/OsxUnicodeKeys.cs

@@ -1,152 +0,0 @@
-using System.Collections.Generic;
-using Avalonia.Input;
-
-namespace Avalonia.Native.Interop
-{
-    internal static class OsxUnicodeKeys
-    {
-        enum OsxUnicodeSpecialKey
-        {
-            NSUpArrowFunctionKey = 0xF700,
-            NSDownArrowFunctionKey = 0xF701,
-            NSLeftArrowFunctionKey = 0xF702,
-            NSRightArrowFunctionKey = 0xF703,
-            NSF1FunctionKey = 0xF704,
-            NSF2FunctionKey = 0xF705,
-            NSF3FunctionKey = 0xF706,
-            NSF4FunctionKey = 0xF707,
-            NSF5FunctionKey = 0xF708,
-            NSF6FunctionKey = 0xF709,
-            NSF7FunctionKey = 0xF70A,
-            NSF8FunctionKey = 0xF70B,
-            NSF9FunctionKey = 0xF70C,
-            NSF10FunctionKey = 0xF70D,
-            NSF11FunctionKey = 0xF70E,
-            NSF12FunctionKey = 0xF70F,
-            NSF13FunctionKey = 0xF710,
-            NSF14FunctionKey = 0xF711,
-            NSF15FunctionKey = 0xF712,
-            NSF16FunctionKey = 0xF713,
-            NSF17FunctionKey = 0xF714,
-            NSF18FunctionKey = 0xF715,
-            NSF19FunctionKey = 0xF716,
-            NSF20FunctionKey = 0xF717,
-            NSF21FunctionKey = 0xF718,
-            NSF22FunctionKey = 0xF719,
-            NSF23FunctionKey = 0xF71A,
-            NSF24FunctionKey = 0xF71B,
-            NSF25FunctionKey = 0xF71C,
-            NSF26FunctionKey = 0xF71D,
-            NSF27FunctionKey = 0xF71E,
-            NSF28FunctionKey = 0xF71F,
-            NSF29FunctionKey = 0xF720,
-            NSF30FunctionKey = 0xF721,
-            NSF31FunctionKey = 0xF722,
-            NSF32FunctionKey = 0xF723,
-            NSF33FunctionKey = 0xF724,
-            NSF34FunctionKey = 0xF725,
-            NSF35FunctionKey = 0xF726,
-            NSInsertFunctionKey = 0xF727,
-            NSDeleteFunctionKey = 0xF728,
-            NSHomeFunctionKey = 0xF729,
-            NSBeginFunctionKey = 0xF72A,
-            NSEndFunctionKey = 0xF72B,
-            NSPageUpFunctionKey = 0xF72C,
-            NSPageDownFunctionKey = 0xF72D,
-            NSPrintScreenFunctionKey = 0xF72E,
-            NSScrollLockFunctionKey = 0xF72F,
-            NSPauseFunctionKey = 0xF730,
-            NSSysReqFunctionKey = 0xF731,
-            NSBreakFunctionKey = 0xF732,
-            NSResetFunctionKey = 0xF733,
-            NSStopFunctionKey = 0xF734,
-            NSMenuFunctionKey = 0xF735,
-            NSUserFunctionKey = 0xF736,
-            NSSystemFunctionKey = 0xF737,
-            NSPrintFunctionKey = 0xF738,
-            NSClearLineFunctionKey = 0xF739,
-            NSClearDisplayFunctionKey = 0xF73A,
-            NSInsertLineFunctionKey = 0xF73B,
-            NSDeleteLineFunctionKey = 0xF73C,
-            NSInsertCharFunctionKey = 0xF73D,
-            NSDeleteCharFunctionKey = 0xF73E,
-            NSPrevFunctionKey = 0xF73F,
-            NSNextFunctionKey = 0xF740,
-            NSSelectFunctionKey = 0xF741,
-            NSExecuteFunctionKey = 0xF742,
-            NSUndoFunctionKey = 0xF743,
-            NSRedoFunctionKey = 0xF744,
-            NSFindFunctionKey = 0xF745,
-            NSHelpFunctionKey = 0xF746,
-            NSModeSwitchFunctionKey = 0xF747
-        }
-
-        private static Dictionary<Key, OsxUnicodeSpecialKey> s_osxKeys = new Dictionary<Key, OsxUnicodeSpecialKey>
-        {
-            {Key.Up, OsxUnicodeSpecialKey.NSUpArrowFunctionKey },
-            {Key.Down, OsxUnicodeSpecialKey.NSDownArrowFunctionKey },
-            {Key.Left, OsxUnicodeSpecialKey.NSLeftArrowFunctionKey },
-            {Key.Right, OsxUnicodeSpecialKey.NSRightArrowFunctionKey },
-            { Key.F1, OsxUnicodeSpecialKey.NSF1FunctionKey },
-            { Key.F2, OsxUnicodeSpecialKey.NSF2FunctionKey },
-            { Key.F3, OsxUnicodeSpecialKey.NSF3FunctionKey },
-            { Key.F4, OsxUnicodeSpecialKey.NSF4FunctionKey },
-            { Key.F5, OsxUnicodeSpecialKey.NSF5FunctionKey },
-            { Key.F6, OsxUnicodeSpecialKey.NSF6FunctionKey },
-            { Key.F7, OsxUnicodeSpecialKey.NSF7FunctionKey },
-            { Key.F8, OsxUnicodeSpecialKey.NSF8FunctionKey },
-            { Key.F9, OsxUnicodeSpecialKey.NSF9FunctionKey },
-            { Key.F10, OsxUnicodeSpecialKey.NSF10FunctionKey },
-            { Key.F11, OsxUnicodeSpecialKey.NSF11FunctionKey },
-            { Key.F12, OsxUnicodeSpecialKey.NSF12FunctionKey },
-            { Key.F13, OsxUnicodeSpecialKey.NSF13FunctionKey },
-            { Key.F14, OsxUnicodeSpecialKey.NSF14FunctionKey },
-            { Key.F15, OsxUnicodeSpecialKey.NSF15FunctionKey },
-            { Key.F16, OsxUnicodeSpecialKey.NSF16FunctionKey },
-            { Key.F17, OsxUnicodeSpecialKey.NSF17FunctionKey },
-            { Key.F18, OsxUnicodeSpecialKey.NSF18FunctionKey },
-            { Key.F19, OsxUnicodeSpecialKey.NSF19FunctionKey },
-            { Key.F20, OsxUnicodeSpecialKey.NSF20FunctionKey },
-            { Key.F21, OsxUnicodeSpecialKey.NSF21FunctionKey },
-            { Key.F22, OsxUnicodeSpecialKey.NSF22FunctionKey },
-            { Key.F23, OsxUnicodeSpecialKey.NSF23FunctionKey },
-            { Key.F24, OsxUnicodeSpecialKey.NSF24FunctionKey },
-            { Key.Insert, OsxUnicodeSpecialKey.NSInsertFunctionKey },
-            { Key.Delete, OsxUnicodeSpecialKey.NSDeleteFunctionKey },
-            { Key.Home, OsxUnicodeSpecialKey.NSHomeFunctionKey },
-            //{ Key.Begin, OsxUnicodeSpecialKey.NSBeginFunctionKey },
-            { Key.End, OsxUnicodeSpecialKey.NSEndFunctionKey },
-            { Key.PageUp, OsxUnicodeSpecialKey.NSPageUpFunctionKey },
-            { Key.PageDown, OsxUnicodeSpecialKey.NSPageDownFunctionKey },
-            { Key.PrintScreen, OsxUnicodeSpecialKey.NSPrintScreenFunctionKey },
-            { Key.Scroll, OsxUnicodeSpecialKey.NSScrollLockFunctionKey },
-            //{ Key.SysReq, OsxUnicodeSpecialKey.NSSysReqFunctionKey },
-            //{ Key.Break, OsxUnicodeSpecialKey.NSBreakFunctionKey },
-            //{ Key.Reset, OsxUnicodeSpecialKey.NSResetFunctionKey },
-            //{ Key.Stop, OsxUnicodeSpecialKey.NSStopFunctionKey },
-            //{ Key.Menu, OsxUnicodeSpecialKey.NSMenuFunctionKey },
-            //{ Key.UserFunction, OsxUnicodeSpecialKey.NSUserFunctionKey },
-            //{ Key.SystemFunction, OsxUnicodeSpecialKey.NSSystemFunctionKey },
-            { Key.Print, OsxUnicodeSpecialKey.NSPrintFunctionKey },
-            //{ Key.ClearLine, OsxUnicodeSpecialKey.NSClearLineFunctionKey },
-            //{ Key.ClearDisplay, OsxUnicodeSpecialKey.NSClearDisplayFunctionKey },
-        };
-
-        public static string ConvertOSXSpecialKeyCodes(Key key)
-        {
-            if (s_osxKeys.ContainsKey(key))
-            {
-                return ((char)s_osxKeys[key]).ToString();
-            }
-            else
-            {
-                if (key >= Key.D0 && key <= Key.D9)
-                {
-                    return key.ToString().Replace("D", "");
-                }
-                
-                return key.ToString().ToLower();
-            }
-        }
-    }
-}

+ 2 - 2
src/Avalonia.Native/PopupImpl.cs

@@ -60,14 +60,14 @@ namespace Avalonia.Native
             }
         }
 
-        public override void Show()
+        public override void Show(bool activate)
         {
             var parent = _parent;
             while (parent is PopupImpl p) 
                 parent = p._parent;
             if (parent is WindowImpl w)
                 w.Native.TakeFocusFromChildren();
-            base.Show();
+            base.Show(false);
         }
 
         public override IPopupImpl CreatePopup() => new PopupImpl(_factory, _opts, _glFeature, this);

+ 2 - 2
src/Avalonia.Native/WindowImplBase.cs

@@ -351,9 +351,9 @@ namespace Avalonia.Native
         }
 
 
-        public virtual void Show()
+        public virtual void Show(bool activate)
         {
-            _native.Show();
+            _native.Show(activate.AsComBool());
         }
 
 

+ 208 - 3
src/Avalonia.Native/avn.idl

@@ -3,10 +3,215 @@
 @clr-map bool int
 @cpp-preamble @@
 #include "com.h"
-#include "key.h"
 #include "stddef.h"
 @@
 
+enum AvnKey
+{
+    AvnKeyNone = 0,
+    AvnKeyCancel = 1,
+    AvnKeyBack = 2,
+    AvnKeyTab = 3,
+    AvnKeyLineFeed = 4,
+    AvnKeyClear = 5,
+    AvnKeyReturn = 6,
+    AvnKeyEnter = 6,
+    AvnKeyPause = 7,
+    AvnKeyCapsLock = 8,
+    AvnKeyCapital = 8,
+    AvnKeyHangulMode = 9,
+    AvnKeyKanaMode = 9,
+    AvnKeyJunjaMode = 10,
+    AvnKeyFinalMode = 11,
+    AvnKeyKanjiMode = 12,
+    HanjaMode = 12,
+    Escape = 13,
+    ImeConvert = 14,
+    ImeNonConvert = 15,
+    ImeAccept = 16,
+    ImeModeChange = 17,
+    Space = 18,
+    PageUp = 19,
+    Prior = 19,
+    PageDown = 20,
+    Next = 20,
+    End = 21,
+    Home = 22,
+    Left = 23,
+    Up = 24,
+    Right = 25,
+    Down = 26,
+    Select = 27,
+    Print = 28,
+    Execute = 29,
+    Snapshot = 30,
+    PrintScreen = 30,
+    Insert = 31,
+    Delete = 32,
+    Help = 33,
+    D0 = 34,
+    D1 = 35,
+    D2 = 36,
+    D3 = 37,
+    D4 = 38,
+    D5 = 39,
+    D6 = 40,
+    D7 = 41,
+    D8 = 42,
+    D9 = 43,
+    A = 44,
+    B = 45,
+    C = 46,
+    D = 47,
+    E = 48,
+    F = 49,
+    G = 50,
+    H = 51,
+    I = 52,
+    J = 53,
+    AvnKeyK = 54,
+    L = 55,
+    M = 56,
+    N = 57,
+    O = 58,
+    P = 59,
+    Q = 60,
+    R = 61,
+    S = 62,
+    T = 63,
+    U = 64,
+    V = 65,
+    W = 66,
+    X = 67,
+    Y = 68,
+    Z = 69,
+    LWin = 70,
+    RWin = 71,
+    Apps = 72,
+    Sleep = 73,
+    NumPad0 = 74,
+    NumPad1 = 75,
+    NumPad2 = 76,
+    NumPad3 = 77,
+    NumPad4 = 78,
+    NumPad5 = 79,
+    NumPad6 = 80,
+    NumPad7 = 81,
+    NumPad8 = 82,
+    NumPad9 = 83,
+    Multiply = 84,
+    Add = 85,
+    Separator = 86,
+    Subtract = 87,
+    Decimal = 88,
+    Divide = 89,
+    F1 = 90,
+    F2 = 91,
+    F3 = 92,
+    F4 = 93,
+    F5 = 94,
+    F6 = 95,
+    F7 = 96,
+    F8 = 97,
+    F9 = 98,
+    F10 = 99,
+    F11 = 100,
+    F12 = 101,
+    F13 = 102,
+    F14 = 103,
+    F15 = 104,
+    F16 = 105,
+    F17 = 106,
+    F18 = 107,
+    F19 = 108,
+    F20 = 109,
+    F21 = 110,
+    F22 = 111,
+    F23 = 112,
+    F24 = 113,
+    NumLock = 114,
+    Scroll = 115,
+    LeftShift = 116,
+    RightShift = 117,
+    LeftCtrl = 118,
+    RightCtrl = 119,
+    LeftAlt = 120,
+    RightAlt = 121,
+    BrowserBack = 122,
+    BrowserForward = 123,
+    BrowserRefresh = 124,
+    BrowserStop = 125,
+    BrowserSearch = 126,
+    BrowserFavorites = 127,
+    BrowserHome = 128,
+    VolumeMute = 129,
+    VolumeDown = 130,
+    VolumeUp = 131,
+    MediaNextTrack = 132,
+    MediaPreviousTrack = 133,
+    MediaStop = 134,
+    MediaPlayPause = 135,
+    LaunchMail = 136,
+    SelectMedia = 137,
+    LaunchApplication1 = 138,
+    LaunchApplication2 = 139,
+    OemSemicolon = 140,
+    Oem1 = 140,
+    OemPlus = 141,
+    OemComma = 142,
+    OemMinus = 143,
+    OemPeriod = 144,
+    OemQuestion = 145,
+    Oem2 = 145,
+    OemTilde = 146,
+    Oem3 = 146,
+    AbntC1 = 147,
+    AbntC2 = 148,
+    OemOpenBrackets = 149,
+    Oem4 = 149,
+    OemPipe = 150,
+    Oem5 = 150,
+    OemCloseBrackets = 151,
+    Oem6 = 151,
+    OemQuotes = 152,
+    Oem7 = 152,
+    Oem8 = 153,
+    OemBackslash = 154,
+    Oem102 = 154,
+    ImeProcessed = 155,
+    System = 156,
+    OemAttn = 157,
+    DbeAlphanumeric = 157,
+    OemFinish = 158,
+    DbeKatakana = 158,
+    DbeHiragana = 159,
+    OemCopy = 159,
+    DbeSbcsChar = 160,
+    OemAuto = 160,
+    DbeDbcsChar = 161,
+    OemEnlw = 161,
+    OemBackTab = 162,
+    DbeRoman = 162,
+    DbeNoRoman = 163,
+    Attn = 163,
+    CrSel = 164,
+    DbeEnterWordRegisterMode = 164,
+    ExSel = 165,
+    DbeEnterImeConfigureMode = 165,
+    EraseEof = 166,
+    DbeFlushString = 166,
+    Play = 167,
+    DbeCodeInput = 167,
+    DbeNoCodeInput = 168,
+    Zoom = 168,
+    NoName = 169,
+    DbeDetermineString = 169,
+    DbeEnterDialogConversionMode = 170,
+    Pa1 = 170,
+    OemClear = 171,
+    DeadCharProcessed = 172,
+};
+
 enum SystemDecorations {
     SystemDecorationsNone = 0,
     SystemDecorationsBorderOnly = 1,
@@ -225,7 +430,7 @@ interface IAvnString : IUnknown
 [uuid(e5aca675-02b7-4129-aa79-d6e417210bda)]
 interface IAvnWindowBase : IUnknown
 {
-     HRESULT Show();
+     HRESULT Show(bool activate);
      HRESULT Hide();
      HRESULT Close();
      HRESULT Activate();
@@ -468,7 +673,7 @@ interface IAvnMenuItem : IUnknown
 {
      HRESULT SetSubMenu(IAvnMenu* menu);
      HRESULT SetTitle(char* utf8String);
-     HRESULT SetGesture(char* utf8String, AvnInputModifiers modifiers);
+     HRESULT SetGesture(AvnKey key, AvnInputModifiers modifiers);
      HRESULT SetAction(IAvnPredicateCallback* predicate, IAvnActionCallback* callback);
      HRESULT SetIsChecked(bool isChecked);
      HRESULT SetToggleType(AvnMenuItemToggleType toggleType);

+ 0 - 3
src/Avalonia.Styling/ApiCompatBaseline.txt

@@ -1,3 +0,0 @@
-Compat issues with assembly Avalonia.Styling:
-MembersMustExist : Member 'public System.IObservable<System.Object> Avalonia.Controls.ResourceNodeExtensions.GetResourceObservable(Avalonia.IStyledElement, System.Object, System.Func<System.Object, System.Object>)' does not exist in the implementation but it does exist in the contract.
-Total Issues: 1

+ 5 - 1
src/Avalonia.Themes.Default/CaptionButtons.xaml

@@ -4,7 +4,7 @@
     <Setter Property="MaxHeight" Value="30" />
     <Setter Property="Template">
       <ControlTemplate>
-        <StackPanel Spacing="2" Margin="0 0 7 0" VerticalAlignment="Stretch" TextBlock.FontSize="10" Orientation="Horizontal">
+        <StackPanel Spacing="2" VerticalAlignment="Stretch" TextBlock.FontSize="10" Orientation="Horizontal">
           <StackPanel.Styles>
             <Style Selector="Panel">
               <Setter Property="Width" Value="45" />
@@ -57,10 +57,14 @@
   <Style Selector="CaptionButtons:maximized Panel#PART_RestoreButton Path">
     <Setter Property="Data" Value="M2048 410h-410v-410h-1638v1638h410v410h1638v-1638zM1434 1434h-1229v-1229h1229v1229zM1843 1843h-1229v-205h1024v-1024h205v1229z" />
   </Style>
+  <Style Selector="CaptionButtons Panel#PART_FullScreenButton Path">
+    <Setter Property="IsVisible" Value="False" />
+  </Style>
   <Style Selector="CaptionButtons Panel#PART_FullScreenButton Path">
     <Setter Property="Data" Value="M2048 2048v-819h-205v469l-1493 -1493h469v-205h-819v819h205v-469l1493 1493h-469v205h819z" />
   </Style>
   <Style Selector="CaptionButtons:fullscreen Panel#PART_FullScreenButton Path">
+    <Setter Property="IsVisible" Value="True" />
     <Setter Property="Data" Value="M205 1024h819v-819h-205v469l-674 -674l-145 145l674 674h-469v205zM1374 1229h469v-205h-819v819h205v-469l674 674l145 -145z" />
   </Style>
   <Style Selector="CaptionButtons:fullscreen Panel#PART_RestoreButton, CaptionButtons:fullscreen Panel#PART_MinimiseButton">

+ 0 - 4
src/Avalonia.Themes.Fluent/ApiCompatBaseline.txt

@@ -1,4 +0,0 @@
-Compat issues with assembly Avalonia.Themes.Fluent:
-CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Themes.Fluent.FluentTheme' does not inherit from base type 'Avalonia.Styling.Styles' in the implementation but it does in the contract.
-MembersMustExist : Member 'public void Avalonia.Themes.Fluent.FluentTheme..ctor()' does not exist in the implementation but it does exist in the contract.
-Total Issues: 2

+ 5 - 1
src/Avalonia.Themes.Fluent/Controls/CaptionButtons.xaml

@@ -3,7 +3,7 @@
     <Setter Property="MaxHeight" Value="30" />
     <Setter Property="Template">
       <ControlTemplate>
-        <StackPanel Spacing="2" Margin="0 0 7 0" VerticalAlignment="Stretch" TextBlock.FontSize="10" Orientation="Horizontal">
+        <StackPanel Spacing="2" VerticalAlignment="Stretch" TextBlock.FontSize="10" Orientation="Horizontal">
           <StackPanel.Styles>
             <Style Selector="Panel">
               <Setter Property="Width" Value="45" />
@@ -56,10 +56,14 @@
   <Style Selector="CaptionButtons:maximized Panel#PART_RestoreButton Path">
     <Setter Property="Data" Value="M2048 410h-410v-410h-1638v1638h410v410h1638v-1638zM1434 1434h-1229v-1229h1229v1229zM1843 1843h-1229v-205h1024v-1024h205v1229z" />
   </Style>
+  <Style Selector="CaptionButtons Panel#PART_FullScreenButton Path">
+    <Setter Property="IsVisible" Value="False" />
+  </Style>
   <Style Selector="CaptionButtons Panel#PART_FullScreenButton Path">
     <Setter Property="Data" Value="M2048 2048v-819h-205v469l-1493 -1493h469v-205h-819v819h205v-469l1493 1493h-469v205h819z" />
   </Style>
   <Style Selector="CaptionButtons:fullscreen Panel#PART_FullScreenButton Path">
+    <Setter Property="IsVisible" Value="True" />
     <Setter Property="Data" Value="M205 1024h819v-819h-205v469l-674 -674l-145 145l674 674h-469v205zM1374 1229h469v-205h-819v819h205v-469l674 674l145 -145z" />
   </Style>
   <Style Selector="CaptionButtons:fullscreen Panel#PART_RestoreButton, CaptionButtons:fullscreen Panel#PART_MinimiseButton">

+ 1 - 0
src/Avalonia.Themes.Fluent/Controls/ContextMenu.xaml

@@ -39,6 +39,7 @@
   <Setter Property="HorizontalAlignment" Value="Stretch" />
   <Setter Property="TextBlock.FontSize" Value="{DynamicResource ContentControlFontSize}" />
   <Setter Property="TextBlock.FontWeight" Value="Normal" />
+  <Setter Property="WindowManagerAddShadowHint" Value="False" />
   <Setter Property="Template">
     <ControlTemplate>
       <Border Background="{TemplateBinding Background}"

+ 1 - 1
src/Avalonia.Themes.Fluent/Controls/MenuItem.xaml

@@ -110,7 +110,7 @@
             </Grid>
           </Border>
           <Popup Name="PART_Popup"
-                 WindowManagerAddShadowHint="True"
+                 WindowManagerAddShadowHint="False"
                  PlacementMode="Right"
                  HorizontalOffset="{StaticResource MenuFlyoutSubItemPopupHorizontalOffset}"
                  IsLightDismissEnabled="True"

+ 0 - 5
src/Avalonia.Visuals/ApiCompatBaseline.txt

@@ -1,5 +0,0 @@
-Compat issues with assembly Avalonia.Visuals:
-MembersMustExist : Member 'public Avalonia.StyledProperty<System.Collections.Generic.IReadOnlyList<System.Double>> Avalonia.StyledProperty<System.Collections.Generic.IReadOnlyList<System.Double>> Avalonia.Media.DashStyle.DashesProperty' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public System.Collections.Generic.IReadOnlyList<System.Double> Avalonia.Media.DashStyle.Dashes.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public void Avalonia.Media.DashStyle.Dashes.set(System.Collections.Generic.IReadOnlyList<System.Double>)' does not exist in the implementation but it does exist in the contract.
-Total Issues: 3

+ 1 - 0
src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

@@ -607,6 +607,7 @@ namespace Avalonia.Rendering
         private bool? UpdateScene()
         {
             Dispatcher.UIThread.VerifyAccess();
+            using var noPump = NonPumpingLockHelper.Use();
             lock (_sceneLock)
             {
                 if (_disposed)

+ 1 - 1
src/Avalonia.Visuals/Visual.cs

@@ -485,7 +485,7 @@ namespace Avalonia
                 BindingPriority.LocalValue);
         }
 
-        protected override sealed void LogBindingError(AvaloniaProperty property, Exception e)
+        protected internal sealed override void LogBindingError(AvaloniaProperty property, Exception e)
         {
             // Don't log a binding error unless the control is attached to a logical or visual tree.
             // In theory this should only need to check for logical tree attachment, but in practise

+ 1 - 1
src/Avalonia.X11/X11Window.cs

@@ -809,7 +809,7 @@ namespace Avalonia.X11
                 XSetTransientForHint(_x11.Display, _handle, parent.Handle.Handle);
         }
 
-        public void Show()
+        public void Show(bool activate)
         {
             _wasMappedAtLeastOnce = true;
             XMapWindow(_x11.Display, _handle);

+ 7 - 16
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs

@@ -72,16 +72,16 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
                     v.Property is AvaloniaSyntheticCompiledBindingProperty prop
                     && prop.Name == SyntheticCompiledBindingPropertyName.ElementName);
 
-            var sourceProperty = syntheticCompiledBindingProperties
-                .FirstOrDefault(v =>
-                    v.Property is AvaloniaSyntheticCompiledBindingProperty prop
-                    && prop.Name == SyntheticCompiledBindingPropertyName.Source);
-
             var relativeSourceProperty = syntheticCompiledBindingProperties
                 .FirstOrDefault(v =>
                     v.Property is AvaloniaSyntheticCompiledBindingProperty prop
                     && prop.Name == SyntheticCompiledBindingPropertyName.RelativeSource);
 
+            var sourceProperty = binding.Children.OfType<XamlAstXamlPropertyValueNode>()
+                .FirstOrDefault(v =>
+                    v.Property is XamlAstClrProperty prop
+                    && prop.Name == "Source");
+
             if (elementNameProperty?.Values[0] is XamlAstTextNode elementName)
             {
                 convertedNode = new BindingExpressionGrammar.NameNode { Name = elementName.Text };
@@ -91,14 +91,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
                 throw new XamlParseException($"Invalid ElementName '{elementNameProperty.Values[0]}'.", elementNameProperty.Values[0]);
             }
 
-            if (sourceProperty?.Values[0] != null)
+            if (sourceProperty != null && convertedNode != null)
             {
-                if (convertedNode != null)
-                {
-                    throw new XamlParseException("Only one of ElementName, Source, or RelativeSource specified as a binding source. Only one property is allowed.", binding);
-                }
-
-                convertedNode = new RawSourceBindingExpressionNode(sourceProperty?.Values[0]);
+                throw new XamlParseException("Only one of ElementName, Source, or RelativeSource specified as a binding source. Only one property is allowed.", binding);
             }
 
             if (GetRelativeSourceObjectFromAssignment(
@@ -223,10 +218,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
             {
                 binding.Children.Remove(elementNameProperty);
             }
-            if (sourceProperty != null)
-            {
-                binding.Children.Remove(sourceProperty);
-            }
             if (relativeSourceProperty != null)
             {
                 binding.Children.Remove(relativeSourceProperty);

+ 93 - 7
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathTransformer.cs

@@ -1,8 +1,6 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Text;
-using XamlX;
 using XamlX.Ast;
 using XamlX.Transform;
 using XamlX.TypeSystem;
@@ -15,14 +13,102 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
         {
             if (node is XamlAstConstructableObjectNode binding && binding.Type.GetClrType().Equals(context.GetAvaloniaTypes().CompiledBindingExtension))
             {
-                IXamlType startType;
-                var parentDataContextNode = context.ParentNodes().OfType<AvaloniaXamlIlDataContextTypeMetadataNode>().FirstOrDefault();
-                if (parentDataContextNode is null)
+                IXamlType startType = null;
+                var sourceProperty = binding.Children.OfType<XamlPropertyAssignmentNode>().FirstOrDefault(c => c.Property.Name == "Source");
+                if ((sourceProperty?.Values.Count ?? 0) == 1)
                 {
-                    throw new XamlX.XamlParseException("Cannot parse a compiled binding without an explicit x:DataType directive to give a starting data type for bindings.", binding);
+                    var sourceValue = sourceProperty.Values[0];
+                    switch (sourceValue)
+                    {
+                        case XamlAstTextNode textNode:
+                            startType = textNode.Type?.GetClrType();
+                            break;
+
+                        case XamlMarkupExtensionNode extension:
+                            startType = extension.Type?.GetClrType();
+
+                            //let's try to infer StaticResource type from parent resources in xaml
+                            if (extension.Value.Type.GetClrType().FullName == "Avalonia.Markup.Xaml.MarkupExtensions.StaticResourceExtension" &&
+                                extension.Value is XamlAstConstructableObjectNode cn &&
+                                cn.Arguments.Count == 1 && cn.Arguments[0] is XamlAstTextNode keyNode)
+                            {
+                                bool matchProperty(IXamlAstNode node, IXamlType styledElementType, string propertyName)
+                                {
+                                    return (node is XamlPropertyAssignmentNode p &&
+                                            p.Property.DeclaringType == styledElementType && p.Property.Name == propertyName)
+                                           ||
+                                           (node is XamlManipulationGroupNode m && m.Children.Count > 0 &&
+                                            m.Children[0] is XamlPropertyAssignmentNode pm &&
+                                            pm.Property.DeclaringType == styledElementType && pm.Property.Name == propertyName);
+                                }
+
+                                string getResourceValue_xKey(XamlPropertyAssignmentNode node)
+                                    => node.Values.Count == 2 && node.Values[0] is XamlAstTextNode t ? t.Text : "";
+
+                                IXamlType getResourceValue_Type(XamlPropertyAssignmentNode node, IXamlType xamlType)
+                                    => node.Values.Count == 2 ? node.Values[1].Type.GetClrType() : xamlType;
+
+                                IEnumerable<XamlPropertyAssignmentNode> getResourceValues(IXamlAstNode node)
+                                {
+                                    if (node is XamlPropertyAssignmentNode propertyNode)
+                                    {
+                                        if (propertyNode.Values.Count == 1 &&
+                                            propertyNode.Values[0] is XamlAstConstructableObjectNode obj &&
+                                            obj.Type.GetClrType().FullName == "Avalonia.Controls.ResourceDictionary")
+                                        {
+                                            foreach (var r in obj.Children.SelectMany(c => getResourceValues(c)))
+                                            {
+                                                yield return r;
+                                            }
+                                        }
+                                        else
+                                        {
+                                            yield return propertyNode;
+                                        }
+                                    }
+                                    else if (node is XamlManipulationGroupNode m)
+                                    {
+                                        foreach (var r in m.Children.OfType<XamlPropertyAssignmentNode>())
+                                        {
+                                            yield return r;
+                                        }
+                                    }
+                                }
+
+                                string key = keyNode.Text;
+
+                                var styledElement = context.GetAvaloniaTypes().StyledElement;
+                                var resource = context.ParentNodes()
+                                                        .OfType<XamlAstConstructableObjectNode>()
+                                                        .Where(o => styledElement.IsAssignableFrom(o.Type.GetClrType()))
+                                                        .Select(o => o.Children.FirstOrDefault(p => matchProperty(p, styledElement, "Resources")))
+                                                        .Where(r => r != null)
+                                                        .SelectMany(r => getResourceValues(r))
+                                                        .FirstOrDefault(r => getResourceValue_xKey(r) == key);
+
+                                if (resource != null)
+                                {
+                                    startType = getResourceValue_Type(resource, startType);
+                                }
+                            }
+                            break;
+
+                        case XamlStaticExtensionNode staticExtension:
+                            startType = staticExtension.Type?.GetClrType();
+                            break;
+                    }
                 }
 
-                startType = parentDataContextNode.DataContextType;
+                if (startType == null)
+                {
+                    var parentDataContextNode = context.ParentNodes().OfType<AvaloniaXamlIlDataContextTypeMetadataNode>().FirstOrDefault();
+                    if (parentDataContextNode is null)
+                    {
+                        throw new XamlX.XamlParseException("Cannot parse a compiled binding without an explicit x:DataType directive to give a starting data type for bindings.", binding);
+                    }
+
+                    startType = parentDataContextNode.DataContextType;
+                }
 
                 XamlIlBindingPathHelper.UpdateCompiledBindingExtension(context, binding, startType);
             }

+ 1 - 7
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformSyntheticCompiledBindingMembers.cs

@@ -25,11 +25,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
                     return new AvaloniaSyntheticCompiledBindingProperty(node,
                         SyntheticCompiledBindingPropertyName.RelativeSource);
                 }
-                else if (prop.Name == "Source")
-                {
-                    return new AvaloniaSyntheticCompiledBindingProperty(node,
-                        SyntheticCompiledBindingPropertyName.Source);
-                }
             }
 
             return node;
@@ -39,8 +34,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
     enum SyntheticCompiledBindingPropertyName
     {
         ElementName,
-        RelativeSource,
-        Source
+        RelativeSource
     }
 
     class AvaloniaSyntheticCompiledBindingProperty : XamlAstNode, IXamlAstPropertyReference

+ 0 - 4
src/Markup/Avalonia.Markup.Xaml/ApiCompatBaseline.txt

@@ -1,4 +0,0 @@
-Compat issues with assembly Avalonia.Markup.Xaml:
-MembersMustExist : Member 'public Avalonia.Data.Binding Avalonia.Markup.Xaml.Templates.TreeDataTemplate.ItemsSource.get()' does not exist in the implementation but it does exist in the contract.
-MembersMustExist : Member 'public void Avalonia.Markup.Xaml.Templates.TreeDataTemplate.ItemsSource.set(Avalonia.Data.Binding)' does not exist in the implementation but it does exist in the contract.
-Total Issues: 2

+ 10 - 0
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindingExtension.cs

@@ -32,6 +32,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
                 Mode = Mode,
                 Priority = Priority,
                 StringFormat = StringFormat,
+                Source = Source,
                 DefaultAnchor = new WeakReference(GetDefaultAnchor(provider))
             };
         }
@@ -52,6 +53,13 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
 
         protected override ExpressionObserver CreateExpressionObserver(IAvaloniaObject target, AvaloniaProperty targetProperty, object anchor, bool enableDataValidation)
         {
+            if (Source != null)
+            {
+                return CreateSourceObserver(
+                    Source,
+                    Path.BuildExpression(enableDataValidation));
+            }
+
             if (Path.RawSource != null)
             {
                 return CreateSourceObserver(
@@ -77,5 +85,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
 
         [ConstructorArgument("path")]
         public CompiledBindingPath Path { get; set; }
+
+        public object Source { get; set; }
     }
 }

+ 2 - 2
src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs

@@ -931,8 +931,8 @@ namespace Avalonia.Win32.Interop
         [DllImport("user32.dll", EntryPoint = "MapVirtualKeyW")]
         public static extern uint MapVirtualKey(uint uCode, uint uMapType);
 
-        [DllImport("user32.dll", EntryPoint = "GetMessageW")]
-        public static extern sbyte GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
+        [DllImport("user32.dll", EntryPoint = "GetMessageW", SetLastError = true)]
+        public static extern int GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
 
         [DllImport("user32.dll")]
         public static extern int GetMessageTime();

+ 52 - 0
src/Windows/Avalonia.Win32/NonPumpingSyncContext.cs

@@ -0,0 +1,52 @@
+using System;
+using System.Runtime.ConstrainedExecution;
+using System.Threading;
+using Avalonia.Threading;
+using Avalonia.Utilities;
+using Avalonia.Win32.Interop;
+
+namespace Avalonia.Win32
+{
+    internal class NonPumpingSyncContext : SynchronizationContext, IDisposable
+    {
+        private readonly SynchronizationContext _inner;
+
+        private NonPumpingSyncContext(SynchronizationContext inner)
+        {
+            _inner = inner;
+            SetWaitNotificationRequired();
+            SetSynchronizationContext(this);
+        }
+
+        public override void Post(SendOrPostCallback d, object state) => _inner.Post(d, state);
+        public override void Send(SendOrPostCallback d, object state) => _inner.Send(d, state);
+        
+        [PrePrepareMethod]
+        public override int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
+        {
+            return UnmanagedMethods.WaitForMultipleObjectsEx(waitHandles.Length, waitHandles, waitAll,
+                millisecondsTimeout, false);
+        }
+
+        public void Dispose() => SetSynchronizationContext(_inner);
+
+        public static IDisposable Use()
+        {
+            var current = Current;
+            if (current == null)
+            {
+                if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
+                    return null;
+            }
+            if (current is NonPumpingSyncContext)
+                return null;
+            
+            return new NonPumpingSyncContext(current);
+        }
+
+        internal class HelperImpl : NonPumpingLockHelper.IHelperImpl
+        {
+            IDisposable NonPumpingLockHelper.IHelperImpl.Use() => NonPumpingSyncContext.Use();
+        }
+    }
+}

+ 0 - 15
src/Windows/Avalonia.Win32/NonPumpingWaitProvider.cs

@@ -1,15 +0,0 @@
-using System;
-using Avalonia.Threading;
-using Avalonia.Win32.Interop;
-
-namespace Avalonia.Win32
-{
-    internal class NonPumpingWaitProvider : AvaloniaSynchronizationContext.INonPumpingPlatformWaitProvider
-    {
-        public int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
-        {
-            return UnmanagedMethods.WaitForMultipleObjectsEx(waitHandles.Length, waitHandles, waitAll,
-                millisecondsTimeout, false);
-        }
-    }
-}

+ 2 - 1
src/Windows/Avalonia.Win32/PopupImpl.cs

@@ -17,8 +17,9 @@ namespace Avalonia.Win32
         [ThreadStatic]
         private static IntPtr s_parentHandle;
 
-        public override void Show()
+        public override void Show(bool activate)
         {
+            // Popups are always shown non-activated.
             UnmanagedMethods.ShowWindow(Handle.Handle, UnmanagedMethods.ShowWindowCommand.ShowNoActivate);
 
             // We need to steal focus if it's held by a child window of our toplevel window

+ 6 - 2
src/Windows/Avalonia.Win32/Win32GlManager.cs

@@ -20,13 +20,17 @@ namespace Avalonia.Win32
                     return wgl;
                 }
 
-                if (opts?.AllowEglInitialization == true)
+                if (opts?.AllowEglInitialization == true ||
+                    ((!opts?.AllowEglInitialization.HasValue ?? false) &&
+                     Win32Platform.WindowsVersion > new Version(6, 1)))
                 {
                     var egl = EglPlatformOpenGlInterface.TryCreate(() => new AngleWin32EglDisplay());
 
                     if (egl is { } &&
-                        opts?.UseWindowsUIComposition == true) 
+                        opts?.UseWindowsUIComposition == true)
+                    {
                         WinUICompositorConnection.TryCreateAndRegister(egl);
+                    }
 
                     return egl;
                 }

+ 27 - 10
src/Windows/Avalonia.Win32/Win32Platform.cs

@@ -16,6 +16,8 @@ using Avalonia.OpenGL.Egl;
 using Avalonia.Platform;
 using Avalonia.Rendering;
 using Avalonia.Threading;
+using Avalonia.Utilities;
+using Avalonia.Win32;
 using Avalonia.Win32.Input;
 using Avalonia.Win32.Interop;
 using static Avalonia.Win32.Interop.UnmanagedMethods;
@@ -38,7 +40,9 @@ namespace Avalonia
     public class Win32PlatformOptions
     {
         public bool UseDeferredRendering { get; set; } = true;
-        public bool AllowEglInitialization { get; set; } = true;
+        
+        public bool? AllowEglInitialization { get; set; }
+        
         public bool? EnableMultitouch { get; set; }
         public bool OverlayPopups { get; set; }
         public bool UseWgl { get; set; }
@@ -110,7 +114,7 @@ namespace Avalonia.Win32
                 .Bind<IWindowingPlatform>().ToConstant(s_instance)
                 .Bind<PlatformHotkeyConfiguration>().ToSingleton<PlatformHotkeyConfiguration>()
                 .Bind<IPlatformIconLoader>().ToConstant(s_instance)
-                .Bind<AvaloniaSynchronizationContext.INonPumpingPlatformWaitProvider>().ToConstant(new NonPumpingWaitProvider())
+                .Bind<NonPumpingLockHelper.IHelperImpl>().ToConstant(new NonPumpingSyncContext.HelperImpl())
                 .Bind<IMountedVolumeInfoProvider>().ToConstant(new WindowsMountedVolumeInfoProvider());
 
             Win32GlManager.Initialize();
@@ -129,21 +133,34 @@ namespace Avalonia.Win32
 
         public void ProcessMessage()
         {
-            UnmanagedMethods.MSG msg;
-            UnmanagedMethods.GetMessage(out msg, IntPtr.Zero, 0, 0);
-            UnmanagedMethods.TranslateMessage(ref msg);
-            UnmanagedMethods.DispatchMessage(ref msg);
+
+            if (UnmanagedMethods.GetMessage(out var msg, IntPtr.Zero, 0, 0) > -1)
+            {
+                UnmanagedMethods.TranslateMessage(ref msg);
+                UnmanagedMethods.DispatchMessage(ref msg);
+            }
+            else
+            {
+                Logging.Logger.TryGet(Logging.LogEventLevel.Error, Logging.LogArea.Win32Platform)
+                    ?.Log(this, "Unmanaged error in {0}. Error Code: {1}", nameof(ProcessMessage), Marshal.GetLastWin32Error());
+
+            }
         }
 
         public void RunLoop(CancellationToken cancellationToken)
         {
-            while (!cancellationToken.IsCancellationRequested)
+            var result = 0;
+            while (!cancellationToken.IsCancellationRequested 
+                && (result = UnmanagedMethods.GetMessage(out var msg, IntPtr.Zero, 0, 0)) > 0)
             {
-                UnmanagedMethods.MSG msg;
-                UnmanagedMethods.GetMessage(out msg, IntPtr.Zero, 0, 0);
                 UnmanagedMethods.TranslateMessage(ref msg);
                 UnmanagedMethods.DispatchMessage(ref msg);
             }
+            if (result < 0)
+            {
+                Logging.Logger.TryGet(Logging.LogEventLevel.Error, Logging.LogArea.Win32Platform)
+                    ?.Log(this, "Unmanaged error in {0}. Error Code: {1}", nameof(RunLoop), Marshal.GetLastWin32Error());
+            }
         }
 
         public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action callback)
@@ -229,7 +246,7 @@ namespace Avalonia.Win32
         public IWindowImpl CreateEmbeddableWindow()
         {
             var embedded = new EmbeddedWindowImpl();
-            embedded.Show();
+            embedded.Show(true);
             return embedded;
         }
 

+ 2 - 0
src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs

@@ -348,6 +348,7 @@ namespace Avalonia.Win32
 
                 case WindowsMessage.WM_PAINT:
                 {
+                    using(NonPumpingSyncContext.Use())
                     using (_rendererLock.Lock())
                     {
                         if (BeginPaint(_hwnd, out PAINTSTRUCT ps) != IntPtr.Zero)
@@ -365,6 +366,7 @@ namespace Avalonia.Win32
 
                 case WindowsMessage.WM_SIZE:
                     {
+                        using(NonPumpingSyncContext.Use())
                         using (_rendererLock.Lock())
                         {
                             // Do nothing here, just block until the pending frame render is completed on the render thread

+ 8 - 6
src/Windows/Avalonia.Win32/WindowImpl.cs

@@ -243,7 +243,7 @@ namespace Avalonia.Win32
             {
                 if (IsWindowVisible(_hwnd))
                 {
-                    ShowWindow(value);
+                    ShowWindow(value, true);
                 }
                 else
                 {
@@ -567,10 +567,11 @@ namespace Avalonia.Win32
             UnmanagedMethods.ShowWindow(_hwnd, ShowWindowCommand.Hide);
         }
 
-        public virtual void Show()
+        public virtual void Show(bool activate)
         {
             SetWindowLongPtr(_hwnd, (int)WindowLongParam.GWL_HWNDPARENT, _parent != null ? _parent._hwnd : IntPtr.Zero);
-            ShowWindow(_showWindowState);
+
+            ShowWindow(_showWindowState, activate);
         }
 
         public Action GotInputWhenDisabled { get; set; }
@@ -908,7 +909,7 @@ namespace Avalonia.Win32
             ExtendClientAreaToDecorationsChanged?.Invoke(_isClientAreaExtended);
         }
 
-        private void ShowWindow(WindowState state)
+        private void ShowWindow(WindowState state, bool activate)
         {
             ShowWindowCommand? command;
 
@@ -918,7 +919,7 @@ namespace Avalonia.Win32
             {
                 case WindowState.Minimized:
                     newWindowProperties.IsFullScreen = false;
-                    command = ShowWindowCommand.Minimize;
+                    command = activate ? ShowWindowCommand.Minimize : ShowWindowCommand.ShowMinNoActive;
                     break;
                 case WindowState.Maximized:
                     newWindowProperties.IsFullScreen = false;
@@ -927,7 +928,8 @@ namespace Avalonia.Win32
 
                 case WindowState.Normal:
                     newWindowProperties.IsFullScreen = false;
-                    command = ShowWindowCommand.Restore;
+                    command = IsWindowVisible(_hwnd) ? ShowWindowCommand.Restore : 
+                        activate ? ShowWindowCommand.Normal : ShowWindowCommand.ShowNoActivate;
                     break;
 
                 case WindowState.FullScreen:

+ 11 - 11
tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs

@@ -27,7 +27,7 @@ namespace Avalonia.Base.UnitTests
         [Fact]
         public void GetMetadata_Returns_Supplied_Value()
         {
-            var metadata = new PropertyMetadata();
+            var metadata = new AvaloniaPropertyMetadata();
             var target = new TestProperty<string>("test", typeof(Class1), metadata);
 
             Assert.Same(metadata, target.GetMetadata<Class1>());
@@ -36,7 +36,7 @@ namespace Avalonia.Base.UnitTests
         [Fact]
         public void GetMetadata_Returns_Supplied_Value_For_Derived_Class()
         {
-            var metadata = new PropertyMetadata();
+            var metadata = new AvaloniaPropertyMetadata();
             var target = new TestProperty<string>("test", typeof(Class1), metadata);
 
             Assert.Same(metadata, target.GetMetadata<Class2>());
@@ -45,7 +45,7 @@ namespace Avalonia.Base.UnitTests
         [Fact]
         public void GetMetadata_Returns_Supplied_Value_For_Unrelated_Class()
         {
-            var metadata = new PropertyMetadata();
+            var metadata = new AvaloniaPropertyMetadata();
             var target = new TestProperty<string>("test", typeof(Class3), metadata);
 
             Assert.Same(metadata, target.GetMetadata<Class2>());
@@ -54,8 +54,8 @@ namespace Avalonia.Base.UnitTests
         [Fact]
         public void GetMetadata_Returns_Overridden_Value()
         {
-            var metadata = new PropertyMetadata();
-            var overridden = new PropertyMetadata();
+            var metadata = new AvaloniaPropertyMetadata();
+            var overridden = new AvaloniaPropertyMetadata();
             var target = new TestProperty<string>("test", typeof(Class1), metadata);
 
             target.OverrideMetadata<Class2>(overridden);
@@ -66,9 +66,9 @@ namespace Avalonia.Base.UnitTests
         [Fact]
         public void OverrideMetadata_Should_Merge_Values()
         {
-            var metadata = new PropertyMetadata(BindingMode.TwoWay);
+            var metadata = new AvaloniaPropertyMetadata(BindingMode.TwoWay);
             var notify = (Action<IAvaloniaObject, bool>)((a, b) => { });
-            var overridden = new PropertyMetadata();
+            var overridden = new AvaloniaPropertyMetadata();
             var target = new TestProperty<string>("test", typeof(Class1), metadata);
 
             target.OverrideMetadata<Class2>(overridden);
@@ -129,19 +129,19 @@ namespace Avalonia.Base.UnitTests
         [Fact]
         public void PropertyMetadata_BindingMode_Default_Returns_OneWay()
         {
-            var data = new PropertyMetadata(defaultBindingMode: BindingMode.Default);
+            var data = new AvaloniaPropertyMetadata(defaultBindingMode: BindingMode.Default);
 
             Assert.Equal(BindingMode.OneWay, data.DefaultBindingMode);
         }
 
         private class TestProperty<TValue> : AvaloniaProperty<TValue>
         {
-            public TestProperty(string name, Type ownerType, PropertyMetadata metadata = null)
-                : base(name, ownerType, metadata ?? new PropertyMetadata())
+            public TestProperty(string name, Type ownerType, AvaloniaPropertyMetadata metadata = null)
+                : base(name, ownerType, metadata ?? new AvaloniaPropertyMetadata())
             {
             }
 
-            public void OverrideMetadata<T>(PropertyMetadata metadata)
+            public void OverrideMetadata<T>(AvaloniaPropertyMetadata metadata)
             {
                 OverrideMetadata(typeof(T), metadata);
             }

+ 8 - 8
tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs

@@ -79,7 +79,7 @@ namespace Avalonia.Controls.UnitTests
         {
             using (Application())
             {
-                popupImpl.Setup(x => x.Show()).Verifiable();
+                popupImpl.Setup(x => x.Show(true)).Verifiable();
                 popupImpl.Setup(x => x.Hide()).Verifiable();
 
                 var sut = new ContextMenu();
@@ -99,7 +99,7 @@ namespace Avalonia.Controls.UnitTests
                 _mouse.Click(target);
 
                 Assert.False(sut.IsOpen);
-                popupImpl.Verify(x => x.Show(), Times.Once);
+                popupImpl.Verify(x => x.Show(true), Times.Once);
                 popupImpl.Verify(x => x.Hide(), Times.Once);
             }
         }
@@ -109,7 +109,7 @@ namespace Avalonia.Controls.UnitTests
         {
             using (Application())
             {
-                popupImpl.Setup(x => x.Show()).Verifiable();
+                popupImpl.Setup(x => x.Show(true)).Verifiable();
                 popupImpl.Setup(x => x.Hide()).Verifiable();
 
                 var sut = new ContextMenu();
@@ -130,7 +130,7 @@ namespace Avalonia.Controls.UnitTests
 
                 Assert.True(sut.IsOpen);
                 popupImpl.Verify(x => x.Hide(), Times.Once);
-                popupImpl.Verify(x => x.Show(), Times.Exactly(2));
+                popupImpl.Verify(x => x.Show(true), Times.Exactly(2));
             }
         }
         
@@ -177,7 +177,7 @@ namespace Avalonia.Controls.UnitTests
         {
             using (Application())
             {
-                popupImpl.Setup(x => x.Show()).Verifiable();
+                popupImpl.Setup(x => x.Show(true)).Verifiable();
 
                 bool eventCalled = false;
                 var sut = new ContextMenu();
@@ -193,7 +193,7 @@ namespace Avalonia.Controls.UnitTests
 
                 Assert.True(eventCalled);
                 Assert.False(sut.IsOpen);
-                popupImpl.Verify(x => x.Show(), Times.Never);
+                popupImpl.Verify(x => x.Show(true), Times.Never);
             }
         }
 
@@ -297,7 +297,7 @@ namespace Avalonia.Controls.UnitTests
         {
             using (Application())
             {
-                popupImpl.Setup(x => x.Show()).Verifiable();
+                popupImpl.Setup(x => x.Show(true)).Verifiable();
                 popupImpl.Setup(x => x.Hide()).Verifiable();
 
                 bool eventCalled = false;
@@ -321,7 +321,7 @@ namespace Avalonia.Controls.UnitTests
                 Assert.True(eventCalled);
                 Assert.True(sut.IsOpen);
 
-                popupImpl.Verify(x => x.Show(), Times.Once());
+                popupImpl.Verify(x => x.Show(true), Times.Once());
                 popupImpl.Verify(x => x.Hide(), Times.Never);
             }
         }

+ 141 - 0
tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs

@@ -5,6 +5,9 @@ using Avalonia.Input;
 using Avalonia.Platform;
 using Avalonia.Styling;
 using Xunit;
+using System;
+using Avalonia.Input.Raw;
+using Factory = System.Func<int, System.Action<object>, Avalonia.Controls.Window, Avalonia.AvaloniaObject>;
 
 namespace Avalonia.Controls.UnitTests.Utils
 {
@@ -54,6 +57,127 @@ namespace Avalonia.Controls.UnitTests.Utils
             }
         }
 
+        [Theory]
+        [MemberData(nameof(ElementsFactory))]
+        public void HotKeyManager_Should_Use_CommandParameter(string factoryName, Factory factory)
+        {
+            using (AvaloniaLocator.EnterScope())
+            {
+                var styler = new Mock<Styler>();
+                var target = new KeyboardDevice();
+                var commandResult = 0;
+                var expectedParameter = 1;
+                AvaloniaLocator.CurrentMutable
+                    .Bind<IWindowingPlatform>().ToConstant(new WindowingPlatformMock())
+                    .Bind<IStyler>().ToConstant(styler.Object);
+
+                var gesture = new KeyGesture(Key.A, KeyModifiers.Control);
+
+                var action = new Action<object>(parameter =>
+                {
+                    if (parameter is int value)
+                    {
+                        commandResult = value;
+                    }
+                });
+
+                var root = new Window();
+                var element = factory(expectedParameter, action, root);
+
+                root.Template = CreateWindowTemplate();
+                root.ApplyTemplate();
+                root.Presenter.ApplyTemplate();
+
+                HotKeyManager.SetHotKey(element, gesture);
+
+                target.ProcessRawEvent(new RawKeyEventArgs(target,
+                    0,
+                    root,
+                    RawKeyEventType.KeyDown,
+                    Key.A,
+                    RawInputModifiers.Control));
+
+                Assert.True(expectedParameter == commandResult, $"{factoryName} HotKey did not carry the CommandParameter.");
+            }
+        }
+
+
+        [Theory]
+        [MemberData(nameof(ElementsFactory))]
+        public void HotKeyManager_Should_Do_Not_Executed_When_IsEnabled_False(string factoryName, Factory factory)
+        {
+            using (AvaloniaLocator.EnterScope())
+            {
+                var styler = new Mock<Styler>();
+                var target = new KeyboardDevice();
+                var isExecuted = false;
+                AvaloniaLocator.CurrentMutable
+                    .Bind<IWindowingPlatform>().ToConstant(new WindowingPlatformMock())
+                    .Bind<IStyler>().ToConstant(styler.Object);
+
+                var gesture = new KeyGesture(Key.A, KeyModifiers.Control);
+
+                var action = new Action<object>(parameter =>
+                {
+                    isExecuted = true;
+                });
+
+                var root = new Window();
+                var element = factory(0, action, root) as InputElement;
+
+                element.IsEnabled = false;
+
+                root.Template = CreateWindowTemplate();
+                root.ApplyTemplate();
+                root.Presenter.ApplyTemplate();
+
+                HotKeyManager.SetHotKey(element, gesture);
+
+                target.ProcessRawEvent(new RawKeyEventArgs(target,
+                    0,
+                    root,
+                    RawKeyEventType.KeyDown,
+                    Key.A,
+                    RawInputModifiers.Control));
+
+                Assert.True(isExecuted == false, $"{factoryName} Execution raised when IsEnabled is false.");
+            }
+        }
+
+        public static TheoryData<string, Factory> ElementsFactory =>
+            new TheoryData<string, Factory>()
+            {
+                {nameof(Button), MakeButton},
+                {nameof(MenuItem),MakeMenu},
+            };
+
+        private static AvaloniaObject MakeMenu(int expectedParameter, Action<object> action, Window root)
+        {
+            var menuitem = new MenuItem()
+            {
+                Command = new Command(action),
+                CommandParameter = expectedParameter,
+            };
+            var rootMenu = new Menu();
+
+            rootMenu.Items = new[] { menuitem };
+
+            root.Content = rootMenu;
+            return menuitem;
+        }
+
+        private static AvaloniaObject MakeButton(int expectedParameter, Action<object> action, Window root)
+        {
+            var button = new Button()
+            {
+                Command = new Command(action),
+                CommandParameter = expectedParameter,
+            };
+
+            root.Content = button;
+            return button;
+        }
+
         private FuncControlTemplate CreateWindowTemplate()
         {
             return new FuncControlTemplate<Window>((parent, scope) =>
@@ -65,5 +189,22 @@ namespace Avalonia.Controls.UnitTests.Utils
                 }.RegisterInNameScope(scope);
             });
         }
+
+        class Command : System.Windows.Input.ICommand
+        {
+            private readonly Action<object> _execeute;
+
+#pragma warning disable 67 // Event not used
+            public event EventHandler CanExecuteChanged;
+#pragma warning restore 67 // Event not used
+
+            public Command(Action<object> execeute)
+            {
+                _execeute = execeute;
+            }
+            public bool CanExecute(object parameter) => true;
+
+            public void Execute(object parameter) => _execeute?.Invoke(parameter);
+        }
     }
 }

+ 1 - 1
tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs

@@ -137,7 +137,7 @@ namespace Avalonia.Controls.UnitTests
                 var target = new TestWindowBase(windowImpl.Object);
                 target.IsVisible = true;
 
-                windowImpl.Verify(x => x.Show());
+                windowImpl.Verify(x => x.Show(true));
             }
         }
 

+ 120 - 1
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs

@@ -10,6 +10,7 @@ using Avalonia.Controls.Presenters;
 using Avalonia.Data.Converters;
 using Avalonia.Data.Core;
 using Avalonia.Markup.Data;
+using Avalonia.Media;
 using Avalonia.UnitTests;
 using XamlX;
 using Xunit;
@@ -536,7 +537,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
         }
 
         [Fact]
-        public void ResolvesSourceBindingLongForm()
+        public void Binds_To_Source()
         {
             using (UnitTestApplication.Start(TestServices.StyledWindow))
             {
@@ -559,6 +560,124 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
             }
         }
 
+        [Fact]
+        public void Binds_To_Source_StaticResource()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var xaml = @"
+<Window xmlns='https://github.com/avaloniaui'
+             xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+             xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
+             x:CompileBindings='True'>
+    <Window.Resources>
+        <local:TestDataContext x:Key='dataKey' StringProperty='foobar'/>
+    </Window.Resources>
+    <TextBlock Name='textBlock' Text='{Binding StringProperty, Source={StaticResource dataKey}}'/>
+</Window>";
+
+                var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+                var textBlock = window.FindControl<TextBlock>("textBlock");
+
+                Assert.Equal("foobar", textBlock.Text);
+            }
+        }
+
+        [Fact]
+        public void Binds_To_Source_StaticResource1()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var xaml = @"
+<Window xmlns='https://github.com/avaloniaui'
+             xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+             xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
+             x:CompileBindings='True'>
+    <Window.Resources>
+        <local:TestDataContext x:Key='dataKey' StringProperty='foobar'/>
+        <x:String x:Key='otherObjectKey'>test</x:String>
+    </Window.Resources>
+    <TextBlock Name='textBlock' Text='{Binding StringProperty, Source={StaticResource dataKey}}'/>
+</Window>";
+
+                var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+                var textBlock = window.FindControl<TextBlock>("textBlock");
+
+                Assert.Equal("foobar", textBlock.Text);
+            }
+        }
+
+        [Fact]
+        public void Binds_To_Source_StaticResource_In_ResourceDictionary()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var xaml = @"
+<Window xmlns='https://github.com/avaloniaui'
+             xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+             xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
+             x:DataType='local:TestDataContext' x:CompileBindings='True'>
+    <Window.Resources>
+        <ResourceDictionary>
+            <local:TestDataContext x:Key='dataKey' StringProperty='foobar'/>
+        </ResourceDictionary>
+    </Window.Resources>
+    <TextBlock Name='textBlock' Text='{Binding StringProperty, Source={StaticResource dataKey}}'/>
+</Window>";
+
+                var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+                var textBlock = window.FindControl<TextBlock>("textBlock");
+
+                Assert.Equal("foobar", textBlock.Text);
+            }
+        }
+
+        [Fact]
+        public void Binds_To_Source_StaticResource_In_ResourceDictionary1()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var xaml = @"
+<Window xmlns='https://github.com/avaloniaui'
+             xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+             xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
+             x:DataType='local:TestDataContext' x:CompileBindings='True'>
+    <Window.Resources>
+        <ResourceDictionary>
+            <local:TestDataContext x:Key='dataKey' StringProperty='foobar'/>
+            <x:String x:Key='otherObjectKey'>test</x:String>
+        </ResourceDictionary>
+    </Window.Resources>
+    <TextBlock Name='textBlock' Text='{Binding StringProperty, Source={StaticResource dataKey}}'/>
+</Window>";
+
+                var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+                var textBlock = window.FindControl<TextBlock>("textBlock");
+
+                Assert.Equal("foobar", textBlock.Text);
+            }
+        }
+
+        [Fact]
+        public void Binds_To_Source_xStatic()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var xaml = @"
+<Window xmlns='https://github.com/avaloniaui'
+             xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+             xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
+             x:CompileBindings='True'>
+    <ContentControl Name='contentControl' Content='{Binding Color, Source={x:Static Brushes.Red}}'/>
+</Window>";
+
+                var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+                var contentControl = window.FindControl<ContentControl>("contentControl");
+
+                Assert.Equal(Brushes.Red.Color, contentControl.Content);
+            }
+        }
+
         [Fact]
         public void CompilesBindingWhenRequested()
         {

+ 1 - 1
tests/Avalonia.UnitTests/MockWindowingPlatform.cs

@@ -58,7 +58,7 @@ namespace Avalonia.UnitTests
                 windowImpl.Object.Resized?.Invoke(clientSize);
             });
 
-            windowImpl.Setup(x => x.Show()).Callback(() =>
+            windowImpl.Setup(x => x.Show(true)).Callback(() =>
             {
                 windowImpl.Object.Activated?.Invoke();
             });