Browse Source

Addressed feedback on PR #10307

pull/10307/head
Julien Lebosquain 4 years ago
parent
commit
2b08668c64
No known key found for this signature in database GPG Key ID: 1833CAD10ACC46FD
  1. 43
      src/Windows/Avalonia.Win32/NonPumpingSyncContext.cs
  2. 67
      src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
  3. 57
      src/Windows/Avalonia.Win32/WindowImpl.cs

43
src/Windows/Avalonia.Win32/NonPumpingSyncContext.cs

@ -8,17 +8,42 @@ namespace Avalonia.Win32
{
internal class NonPumpingSyncContext : SynchronizationContext, IDisposable
{
private readonly SynchronizationContext _inner;
private readonly SynchronizationContext? _inner;
private NonPumpingSyncContext(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);
public override void Post(SendOrPostCallback d, object? state)
{
if (_inner is null)
{
#if NET6_0_OR_GREATER
ThreadPool.QueueUserWorkItem(static x => x.d(x.state), (d, state), false);
#else
ThreadPool.QueueUserWorkItem(_ => d(state));
#endif
}
else
{
_inner.Post(d, state);
}
}
public override void Send(SendOrPostCallback d, object? state)
{
if (_inner is null)
{
d(state);
}
else
{
_inner.Send(d, state);
}
}
#if !NET6_0_OR_GREATER
[PrePrepareMethod]
@ -34,7 +59,15 @@ namespace Avalonia.Win32
public static IDisposable? Use()
{
var current = Current;
return current is null or NonPumpingSyncContext ? null : new NonPumpingSyncContext(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

67
src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs

@ -137,12 +137,12 @@ namespace Avalonia.Win32
{
var key = KeyInterop.KeyFromVirtualKey(ToInt32(wParam), ToInt32(lParam));
if (key != Key.None && _owner is not null)
if (key != Key.None)
{
e = new RawKeyEventArgs(
WindowsKeyboardDevice.Instance,
timestamp,
_owner,
Owner,
RawKeyEventType.KeyDown,
key,
WindowsKeyboardDevice.Instance.Modifiers);
@ -167,12 +167,12 @@ namespace Avalonia.Win32
{
var key = KeyInterop.KeyFromVirtualKey(ToInt32(wParam), ToInt32(lParam));
if (key != Key.None && _owner is not null)
if (key != Key.None)
{
e = new RawKeyEventArgs(
WindowsKeyboardDevice.Instance,
timestamp,
_owner,
Owner,
RawKeyEventType.KeyUp,
key,
WindowsKeyboardDevice.Instance.Modifiers);
@ -182,9 +182,9 @@ namespace Avalonia.Win32
case WindowsMessage.WM_CHAR:
{
// Ignore control chars and chars that were handled in WM_KEYDOWN.
if (ToInt32(wParam) >= 32 && !_ignoreWmChar && _owner is not null)
if (ToInt32(wParam) >= 32 && !_ignoreWmChar)
{
e = new RawTextInputEventArgs(WindowsKeyboardDevice.Instance, timestamp, _owner,
e = new RawTextInputEventArgs(WindowsKeyboardDevice.Instance, timestamp, Owner,
new string((char)ToInt32(wParam), 1));
}
@ -201,7 +201,7 @@ namespace Avalonia.Win32
break;
}
shouldTakeFocus = ShouldTakeFocusOnClick;
if (ShouldIgnoreTouchEmulatedMessage() || _owner is null)
if (ShouldIgnoreTouchEmulatedMessage())
{
break;
}
@ -209,7 +209,7 @@ namespace Avalonia.Win32
e = new RawPointerEventArgs(
_mouseDevice,
timestamp,
_owner,
Owner,
#pragma warning disable CS8509
message switch
#pragma warning restore CS8509
@ -235,7 +235,7 @@ namespace Avalonia.Win32
{
break;
}
if (ShouldIgnoreTouchEmulatedMessage() || _owner is null)
if (ShouldIgnoreTouchEmulatedMessage())
{
break;
}
@ -243,7 +243,7 @@ namespace Avalonia.Win32
e = new RawPointerEventArgs(
_mouseDevice,
timestamp,
_owner,
Owner,
#pragma warning disable CS8509
message switch
#pragma warning restore CS8509
@ -310,15 +310,10 @@ namespace Avalonia.Win32
var prevPoint = _lastWmMousePoint;
_lastWmMousePoint = currPoint;
if (_owner is null)
{
break;
}
e = new RawPointerEventArgs(
_mouseDevice,
timestamp,
_owner,
Owner,
RawPointerEventType.Move,
point,
GetMouseModifiers(wParam))
@ -331,14 +326,14 @@ namespace Avalonia.Win32
case WindowsMessage.WM_MOUSEWHEEL:
{
if (IsMouseInPointerEnabled || _owner is null)
if (IsMouseInPointerEnabled)
{
break;
}
e = new RawMouseWheelEventArgs(
_mouseDevice,
timestamp,
_owner,
Owner,
PointToClient(PointFromLParam(lParam)),
new Vector(0, (ToInt32(wParam) >> 16) / wheelDelta),
GetMouseModifiers(wParam));
@ -347,14 +342,14 @@ namespace Avalonia.Win32
case WindowsMessage.WM_MOUSEHWHEEL:
{
if (IsMouseInPointerEnabled || _owner is null)
if (IsMouseInPointerEnabled)
{
break;
}
e = new RawMouseWheelEventArgs(
_mouseDevice,
timestamp,
_owner,
Owner,
PointToClient(PointFromLParam(lParam)),
new Vector(-(ToInt32(wParam) >> 16) / wheelDelta, 0),
GetMouseModifiers(wParam));
@ -368,14 +363,10 @@ namespace Avalonia.Win32
break;
}
_trackingMouse = false;
if (_owner is null)
{
break;
}
e = new RawPointerEventArgs(
_mouseDevice,
timestamp,
_owner,
Owner,
RawPointerEventType.LeaveWindow,
new Point(-1, -1),
WindowsKeyboardDevice.Instance.Modifiers);
@ -387,14 +378,14 @@ namespace Avalonia.Win32
case WindowsMessage.WM_NCMBUTTONDOWN:
case WindowsMessage.WM_NCXBUTTONDOWN:
{
if (IsMouseInPointerEnabled || _owner is null)
if (IsMouseInPointerEnabled)
{
break;
}
e = new RawPointerEventArgs(
_mouseDevice,
timestamp,
_owner,
Owner,
#pragma warning disable CS8509
message switch
#pragma warning restore CS8509
@ -413,7 +404,7 @@ namespace Avalonia.Win32
}
case WindowsMessage.WM_TOUCH:
{
if (_wmPointerEnabled || _owner is null || Input is not { } input)
if (_wmPointerEnabled || Input is not { } input)
{
break;
}
@ -427,7 +418,7 @@ namespace Avalonia.Win32
foreach (var touchInput in touchInputs)
{
input.Invoke(new RawTouchEventArgs(_touchDevice, touchInput.Time,
_owner,
Owner,
touchInput.Flags.HasAllFlags(TouchInputFlags.TOUCHEVENTF_UP) ?
RawPointerEventType.TouchEnd :
touchInput.Flags.HasAllFlags(TouchInputFlags.TOUCHEVENTF_DOWN) ?
@ -450,14 +441,14 @@ namespace Avalonia.Win32
case WindowsMessage.WM_POINTERUP:
case WindowsMessage.WM_POINTERUPDATE:
{
if (!_wmPointerEnabled || _owner is null)
if (!_wmPointerEnabled)
{
break;
}
GetDevicePointerInfo(wParam, out var device, out var info, out var point, out var modifiers, ref timestamp);
var eventType = GetEventType(message, info);
var args = CreatePointerArgs(device, timestamp, _owner, eventType, point, modifiers, info.pointerId);
var args = CreatePointerArgs(device, timestamp, eventType, point, modifiers, info.pointerId);
args.IntermediatePoints = CreateLazyIntermediatePoints(info);
e = args;
break;
@ -466,19 +457,19 @@ namespace Avalonia.Win32
case WindowsMessage.WM_POINTERLEAVE:
case WindowsMessage.WM_POINTERCAPTURECHANGED:
{
if (!_wmPointerEnabled || _owner is null)
if (!_wmPointerEnabled)
{
break;
}
GetDevicePointerInfo(wParam, out var device, out var info, out var point, out var modifiers, ref timestamp);
var eventType = device is TouchDevice ? RawPointerEventType.TouchCancel : RawPointerEventType.LeaveWindow;
e = CreatePointerArgs(device, timestamp, _owner, eventType, point, modifiers, info.pointerId);
e = CreatePointerArgs(device, timestamp, eventType, point, modifiers, info.pointerId);
break;
}
case WindowsMessage.WM_POINTERWHEEL:
case WindowsMessage.WM_POINTERHWHEEL:
{
if (!_wmPointerEnabled || _owner is null)
if (!_wmPointerEnabled)
{
break;
}
@ -486,7 +477,7 @@ namespace Avalonia.Win32
var val = (ToInt32(wParam) >> 16) / wheelDelta;
var delta = message == WindowsMessage.WM_POINTERWHEEL ? new Vector(0, val) : new Vector(val, 0);
e = new RawMouseWheelEventArgs(device, timestamp, _owner, point.Position, delta, modifiers)
e = new RawMouseWheelEventArgs(device, timestamp, Owner, point.Position, delta, modifiers)
{
RawPointerId = info.pointerId
};
@ -900,11 +891,11 @@ namespace Avalonia.Win32
}
}
private RawPointerEventArgs CreatePointerArgs(IInputDevice device, ulong timestamp, IInputRoot owner, RawPointerEventType eventType, RawPointerPoint point, RawInputModifiers modifiers, uint rawPointerId)
private RawPointerEventArgs CreatePointerArgs(IInputDevice device, ulong timestamp, RawPointerEventType eventType, RawPointerPoint point, RawInputModifiers modifiers, uint rawPointerId)
{
return device is TouchDevice
? new RawTouchEventArgs(device, timestamp, owner, eventType, point, modifiers, rawPointerId)
: new RawPointerEventArgs(device, timestamp, owner, eventType, point, modifiers)
? new RawTouchEventArgs(device, timestamp, Owner, eventType, point, modifiers, rawPointerId)
: new RawPointerEventArgs(device, timestamp, Owner, eventType, point, modifiers)
{
RawPointerId = rawPointerId
};

57
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -180,40 +180,31 @@ namespace Avalonia.Win32
s_instances.Add(this);
}
/// <inheritdoc />
private IInputRoot Owner
=> _owner ?? throw new InvalidOperationException($"{nameof(SetInputRoot)} must have been called");
public Action? Activated { get; set; }
/// <inheritdoc />
public Func<WindowCloseReason, bool>? Closing { get; set; }
/// <inheritdoc />
public Action? Closed { get; set; }
/// <inheritdoc />
public Action? Deactivated { get; set; }
/// <inheritdoc />
public Action<RawInputEventArgs>? Input { get; set; }
/// <inheritdoc />
public Action<Rect>? Paint { get; set; }
/// <inheritdoc />
public Action<Size, PlatformResizeReason>? Resized { get; set; }
/// <inheritdoc />
public Action<double>? ScalingChanged { get; set; }
/// <inheritdoc />
public Action<PixelPoint>? PositionChanged { get; set; }
/// <inheritdoc />
public Action<WindowState>? WindowStateChanged { get; set; }
/// <inheritdoc />
public Action? LostFocus { get; set; }
/// <inheritdoc />
public Action<WindowTransparencyLevel>? TransparencyLevelChanged { get; set; }
public Thickness BorderThickness
@ -245,13 +236,10 @@ namespace Avalonia.Win32
private double PrimaryScreenRenderScaling => Screen.AllScreens.FirstOrDefault(screen => screen.IsPrimary)?.Scaling ?? 1;
/// <inheritdoc />
public double RenderScaling => _scaling;
/// <inheritdoc />
public double DesktopScaling => RenderScaling;
/// <inheritdoc />
public Size ClientSize
{
get
@ -262,7 +250,6 @@ namespace Avalonia.Win32
}
}
/// <inheritdoc />
public Size? FrameSize
{
get
@ -278,18 +265,14 @@ namespace Avalonia.Win32
}
}
/// <inheritdoc />
public IScreenImpl Screen { get; }
/// <inheritdoc />
public IPlatformHandle Handle { get; private set; }
/// <inheritdoc />
public virtual Size MaxAutoSizeHint => new Size(_maxTrackSize.X / RenderScaling, _maxTrackSize.Y / RenderScaling);
public IMouseDevice MouseDevice => _mouseDevice;
/// <inheritdoc />
public WindowState WindowState
{
get
@ -327,14 +310,12 @@ namespace Avalonia.Win32
}
}
/// <inheritdoc />
public WindowTransparencyLevel TransparencyLevel { get; private set; }
protected IntPtr Hwnd => _hwnd;
private bool IsMouseInPointerEnabled => _wmPointerEnabled && IsMouseInPointerEnabled();
/// <inheritdoc />
public object? TryGetFeature(Type featureType)
{
if (featureType == typeof(ITextInputMethodImpl))
@ -355,7 +336,6 @@ namespace Avalonia.Win32
return null;
}
/// <inheritdoc />
public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel)
{
TransparencyLevel = EnableBlur(transparencyLevel);
@ -537,13 +517,11 @@ namespace Avalonia.Win32
}
}
/// <inheritdoc />
public IEnumerable<object> Surfaces
=> _gl is null ?
new object[] { Handle, _framebuffer } :
new object[] { Handle, _gl, _framebuffer };
/// <inheritdoc />
public PixelPoint Position
{
get
@ -589,21 +567,17 @@ namespace Avalonia.Win32
}
}
/// <inheritdoc />
public void Move(PixelPoint point) => Position = point;
/// <inheritdoc />
public void SetMinMaxSize(Size minSize, Size maxSize)
{
_minSize = minSize;
_maxSize = maxSize;
}
/// <inheritdoc />
public IRenderer CreateRenderer(IRenderRoot root) =>
new CompositingRenderer(root, Win32Platform.Compositor, () => Surfaces);
/// <inheritdoc />
public void Resize(Size value, PlatformResizeReason reason)
{
if (WindowState != WindowState.Normal)
@ -631,16 +605,13 @@ namespace Avalonia.Win32
}
}
/// <inheritdoc />
public void Activate()
{
SetForegroundWindow(_hwnd);
}
/// <inheritdoc />
public IPopupImpl? CreatePopup() => Win32Platform.UseOverlayPopups ? null : new PopupImpl(this);
/// <inheritdoc />
public void Dispose()
{
(_gl as IDisposable)?.Dispose();
@ -682,7 +653,6 @@ namespace Avalonia.Win32
InvalidateRect(_hwnd, ref r, false);
}
/// <inheritdoc />
public Point PointToClient(PixelPoint point)
{
var p = new POINT { X = point.X, Y = point.Y };
@ -690,7 +660,6 @@ namespace Avalonia.Win32
return new Point(p.X, p.Y) / RenderScaling;
}
/// <inheritdoc />
public PixelPoint PointToScreen(Point point)
{
point *= RenderScaling;
@ -699,31 +668,26 @@ namespace Avalonia.Win32
return new PixelPoint(p.X, p.Y);
}
/// <inheritdoc />
public void SetInputRoot(IInputRoot inputRoot)
{
_owner = inputRoot;
CreateDropTarget(inputRoot);
}
/// <inheritdoc />
public void Hide()
{
UnmanagedMethods.ShowWindow(_hwnd, ShowWindowCommand.Hide);
_shown = false;
}
/// <inheritdoc />
public virtual void Show(bool activate, bool isDialog)
{
SetParent(_parent);
ShowWindow(_showWindowState, activate);
}
/// <inheritdoc />
public Action? GotInputWhenDisabled { get; set; }
/// <inheritdoc />
public void SetParent(IWindowImpl? parent)
{
_parent = parent as WindowImpl;
@ -739,10 +703,8 @@ namespace Avalonia.Win32
SetWindowLongPtr(_hwnd, (int)WindowLongParam.GWL_HWNDPARENT, parentHwnd);
}
/// <inheritdoc />
public void SetEnabled(bool enable) => EnableWindow(_hwnd, enable);
/// <inheritdoc />
public void BeginMoveDrag(PointerPressedEventArgs e)
{
e.Pointer.Capture(null);
@ -750,7 +712,6 @@ namespace Avalonia.Win32
new IntPtr((int)HitTestValues.HTCAPTION), IntPtr.Zero);
}
/// <inheritdoc />
public void BeginResizeDrag(WindowEdge edge, PointerPressedEventArgs e)
{
if (_windowProperties.IsResizable)
@ -765,13 +726,11 @@ namespace Avalonia.Win32
}
}
/// <inheritdoc />
public void SetTitle(string? title)
{
SetWindowText(_hwnd, title);
}
/// <inheritdoc />
public void SetCursor(ICursorImpl? cursor)
{
var impl = cursor as CursorImpl;
@ -779,13 +738,12 @@ namespace Avalonia.Win32
var hCursor = impl?.Handle ?? s_defaultCursor;
SetClassLong(_hwnd, ClassLongIndex.GCLP_HCURSOR, hCursor);
if (_owner?.IsPointerOver == true)
if (Owner.IsPointerOver)
{
UnmanagedMethods.SetCursor(hCursor);
}
}
/// <inheritdoc />
public void SetIcon(IWindowIconImpl? icon)
{
var impl = icon as IconImpl;
@ -795,7 +753,6 @@ namespace Avalonia.Win32
new IntPtr((int)Icons.ICON_BIG), hIcon);
}
/// <inheritdoc />
public void ShowTaskbarIcon(bool value)
{
var newWindowProperties = _windowProperties;
@ -805,7 +762,6 @@ namespace Avalonia.Win32
UpdateWindowProperties(newWindowProperties);
}
/// <inheritdoc />
public void CanResize(bool value)
{
var newWindowProperties = _windowProperties;
@ -815,7 +771,6 @@ namespace Avalonia.Win32
UpdateWindowProperties(newWindowProperties);
}
/// <inheritdoc />
public void SetSystemDecorations(SystemDecorations value)
{
var newWindowProperties = _windowProperties;
@ -825,7 +780,6 @@ namespace Avalonia.Win32
UpdateWindowProperties(newWindowProperties);
}
/// <inheritdoc />
public void SetTopmost(bool value)
{
if (value == _topmost)
@ -842,7 +796,6 @@ namespace Avalonia.Win32
_topmost = value;
}
/// <inheritdoc />
public unsafe void SetFrameThemeVariant(PlatformThemeVariant themeVariant)
{
if (Win32Platform.WindowsVersion.Build >= 22000)
@ -1457,7 +1410,6 @@ namespace Avalonia.Win32
IntPtr EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Handle => Handle.Handle;
/// <inheritdoc />
public void SetExtendClientAreaToDecorationsHint(bool hint)
{
_isClientAreaExtended = hint;
@ -1465,7 +1417,6 @@ namespace Avalonia.Win32
ExtendClientArea();
}
/// <inheritdoc />
public void SetExtendClientAreaChromeHints(ExtendClientAreaChromeHints hints)
{
_extendChromeHints = hints;

Loading…
Cancel
Save