diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
index b575db6cddd..2027ef06744 100644
--- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
+++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
@@ -112,7 +112,7 @@ public enum ShowWindowCommand
///
Hide = 0,
///
- /// Activates and displays a window. If the window is minimized, maximized, or arranged, the system restores it to its original
+ /// Activates and displays a window. If the window is minimized, maximized, or arranged, the system restores it to its original
/// size and position. An application should specify this flag when displaying the window for the first time.
///
Normal = 1,
@@ -147,12 +147,12 @@ public enum ShowWindowCommand
///
ShowNA = 8,
///
- /// Activates and displays the window. If the window is minimized, maximized, or arranged, the system restores it to its original size and position.
+ /// Activates and displays the window. If the window is minimized, maximized, or arranged, the system restores it to its original size and position.
/// An application should specify this flag when restoring a minimized window.
///
Restore = 9,
///
- /// Sets the show state based on the value specified in the STARTUPINFO structure passed to the CreateProcess function
+ /// Sets the show state based on the value specified in the STARTUPINFO structure passed to the CreateProcess function
/// by the program that started the application.
///
ShowDefault = 10,
@@ -1173,6 +1173,9 @@ public struct MOUSEMOVEPOINT
[DllImport("user32.dll", SetLastError = true)]
public static extern bool GetPointerTouchInfo(uint pointerId, out POINTER_TOUCH_INFO touchInfo);
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern bool GetPointerDeviceRects(IntPtr device, out RECT pointerDeviceRect, out RECT displayRect);
+
[DllImport("user32.dll", SetLastError = true)]
public static extern bool GetPointerTouchInfoHistory(uint pointerId, ref int entriesCount, [MarshalAs(UnmanagedType.LPArray), In, Out] POINTER_TOUCH_INFO[] touchInfos);
@@ -1221,12 +1224,12 @@ public static extern IntPtr CreateWindowEx(
[DllImport("user32.dll", EntryPoint = "DefWindowProcW")]
public static extern IntPtr DefWindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
-
+
public const int SC_MOUSEMOVE = 0xf012;
-
+
[DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "SendMessageW")]
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
-
+
[DllImport("user32.dll", EntryPoint = "DispatchMessageW")]
public static extern IntPtr DispatchMessage(ref MSG lpmsg);
@@ -1534,7 +1537,7 @@ public static IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex)
[DllImport("user32.dll", EntryPoint = "SetCursor")]
internal static extern IntPtr SetCursor(IntPtr hCursor);
-
+
[DllImport("ole32.dll", PreserveSig = true)]
internal static extern int CoCreateInstance(in Guid clsid,
IntPtr ignore1, int ignore2, in Guid iid, [Out] out IntPtr pUnkOuter);
@@ -2176,7 +2179,7 @@ public enum ClipboardFormat
///
CF_UNICODETEXT = 13,
///
- /// A handle to type HDROP that identifies a list of files.
+ /// A handle to type HDROP that identifies a list of files.
///
CF_HDROP = 15,
}
diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
index caa2d33a25d..1f663607ac3 100644
--- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
+++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
@@ -164,7 +164,7 @@ protected virtual unsafe IntPtr AppWndProc(IntPtr hWnd, uint msg, IntPtr wParam,
{
requestDpi = _dpi;
}
-
+
return LoadIcon(requestIcon, requestDpi)?.Handle ?? default;
case WindowsMessage.WM_KEYDOWN:
@@ -766,7 +766,7 @@ protected virtual unsafe IntPtr AppWndProc(IntPtr hWnd, uint msg, IntPtr wParam,
{
LostFocus?.Invoke();
}
-
+
break;
case WindowsMessage.WM_INPUTLANGCHANGE:
@@ -1083,8 +1083,8 @@ private RawPointerPoint CreateRawPointerPoint(POINTER_INFO pointerInfo)
}
private RawPointerPoint CreateRawPointerPoint(POINTER_TOUCH_INFO info)
{
- var pointerInfo = info.pointerInfo;
- var point = PointToClient(new PixelPoint(pointerInfo.ptPixelLocationX, pointerInfo.ptPixelLocationY));
+ var himetricLocation = GetHimetricLocation(info.pointerInfo);
+ var point = PointToClient(himetricLocation);
var pointerPoint = new RawPointerPoint
{
@@ -1117,8 +1117,8 @@ private RawPointerPoint CreateRawPointerPoint(POINTER_TOUCH_INFO info)
}
private RawPointerPoint CreateRawPointerPoint(POINTER_PEN_INFO info)
{
- var pointerInfo = info.pointerInfo;
- var point = PointToClient(new PixelPoint(pointerInfo.ptPixelLocationX, pointerInfo.ptPixelLocationY));
+ var himetricLocation = GetHimetricLocation(info.pointerInfo);
+ var point = PointToClient(himetricLocation);
return new RawPointerPoint
{
Position = point,
@@ -1186,6 +1186,20 @@ private void UpdateInputMethod(IntPtr hkl)
Imm32InputMethod.Current.SetLanguageAndWindow(this, Hwnd, hkl);
}
+ ///
+ /// Get the location of the pointer in himetric units.
+ ///
+ /// The pointer info.
+ /// The location of the pointer in himetric units.
+ private Point GetHimetricLocation(POINTER_INFO info)
+ {
+ GetPointerDeviceRects(info.sourceDevice, out var pointerDeviceRect, out var displayRect);
+ var himetricLocation = new Point(
+ info.ptHimetricLocationRawX * displayRect.Width / (double)pointerDeviceRect.Width + displayRect.left,
+ info.ptHimetricLocationRawY * displayRect.Height / (double)pointerDeviceRect.Height + displayRect.top);
+ return himetricLocation;
+ }
+
private static int ToInt32(IntPtr ptr)
{
if (IntPtr.Size == 4)
diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs
index f18c358525a..c8139f27354 100644
--- a/src/Windows/Avalonia.Win32/WindowImpl.cs
+++ b/src/Windows/Avalonia.Win32/WindowImpl.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
@@ -454,7 +454,7 @@ private bool SetTransparencyMica()
{
SetUseHostBackdropBrush(false);
SetLegacyTransparency(false);
-
+
CompositionEffectsSurface!.SetBlur(_currentThemeVariant switch
{
PlatformThemeVariant.Light => BlurEffect.MicaLight,
@@ -468,7 +468,7 @@ private bool SetLegacyTransparency(bool enabled)
{
if (Win32Platform.WindowsVersion < PlatformConstants.Windows8 || !UseRedirectionBitmap)
return false;
-
+
// On pre-Win8 this method was blurring a window, which is a different from desired behavior.
// On win8+ we use this method as a fallback, when WinUI/DComp composition with true transparency isn't available.
// Note: there is no guarantee that this behavior won't be changed back to true blur in Win12.
@@ -496,7 +496,7 @@ private unsafe bool SetUseHostBackdropBrush(bool useHostBackdropBrush)
// AcrylicBlur requires window to set DWMWA_USE_HOSTBACKDROPBRUSH flag on Win11+.
// It's not necessary on older versions and it's not necessary with Mica brush.
-
+
var pvUseBackdropBrush = useHostBackdropBrush ? 1 : 0;
var result = DwmSetWindowAttribute(_hwnd, (int)DwmWindowAttribute.DWMWA_USE_HOSTBACKDROPBRUSH, &pvUseBackdropBrush, sizeof(int));
return result == 0;
@@ -642,6 +642,12 @@ public void Invalidate(Rect rect)
InvalidateRect(_hwnd, ref r, false);
}
+ ///
+ /// Transform a screen pixel point to the point in the client area.
+ /// To transform a point with precise value, use the overload instead.
+ ///
+ /// The screen pixel point to be transformed.
+ /// The point in the client area.
public Point PointToClient(PixelPoint point)
{
var p = new POINT { X = point.X, Y = point.Y };
@@ -649,6 +655,19 @@ public Point PointToClient(PixelPoint point)
return new Point(p.X, p.Y) / RenderScaling;
}
+ ///
+ /// Transform a screen point to the point in the client area.
+ /// Comparing to the overload, this method receives double values and can be more precise.
+ ///
+ /// The screen point to be transformed.
+ /// The point in the client area.
+ public Point PointToClient(Point point)
+ {
+ var p = new POINT { X = 0, Y = 0 };
+ ClientToScreen(_hwnd, ref p);
+ return new Point(point.X - p.X, point.Y - p.Y) / RenderScaling;
+ }
+
public PixelPoint PointToScreen(Point point)
{
point *= RenderScaling;
@@ -945,7 +964,7 @@ private void CreateWindow()
Handle = new WindowImplPlatformHandle(this);
- RegisterTouchWindow(_hwnd, 0);
+ RegisterTouchWindow(_hwnd, 0);
if (ShCoreAvailable && Win32Platform.WindowsVersion >= PlatformConstants.Windows8_1)
{