-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
feat: Support ContactRect in X11 and Windows platform #16498
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c15f9a1
5942d37
6ad31f4
f62d790
95c2ad8
d050f20
f772973
29fe3c1
eed1ecd
0c29c8d
6817142
5eeb7df
4c745d0
75d6dbf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -143,6 +143,14 @@ public record struct RawPointerPoint | |
/// <inheritdoc cref="PointerPointProperties.YTilt" /> | ||
public float YTilt { get; set; } | ||
|
||
/// <inheritdoc cref="PointerPointProperties.ContactRect" /> | ||
public Rect ContactRect | ||
{ | ||
get => _contactRect ?? new Rect(Position, new Size()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it should be new Size(1,1) by default I believe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @maxkatz6 Sorry, I do not think so. I think the size should be zero here as the WinUI do. |
||
set => _contactRect = value; | ||
} | ||
|
||
private Rect? _contactRect; | ||
|
||
public RawPointerPoint() | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -436,14 +436,46 @@ protected virtual unsafe IntPtr AppWndProc(IntPtr hWnd, uint msg, IntPtr wParam, | |
{ | ||
foreach (var touchInput in touchInputs) | ||
{ | ||
var position = PointToClient(new PixelPoint(touchInput.X / 100, touchInput.Y / 100)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Feel free to drop WM_TOUCH handling for ContactRect, as it's not going to be used anywhere on modern devices. WM_POINTER is the main way we handle touch/pen input. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @maxkatz6 There is the other issues in avalonia, that the RegisterTouchWindow will be call event enable the WM_POINTER. And the win7 system still use the WM_TOUCH now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't support win7 at this point. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To clarify, we try to keep Avalonia compatible with Win7, but we don't go extra miles to support some specific features. And if some code is only used on Win7, we don't really need it, as it only adds maintenance cost. |
||
var rawPointerPoint = new RawPointerPoint() | ||
{ | ||
Position = position, | ||
}; | ||
|
||
// Try to get the touch width and height. | ||
// See https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-touchinput | ||
// > The width of the touch contact area in hundredths of a pixel in physical screen coordinates. This value is only valid if the dwMask member has the TOUCHEVENTFMASK_CONTACTAREA flag set. | ||
const int TOUCHEVENTFMASK_CONTACTAREA = 0x0004; // Known as TOUCHINPUTMASKF_CONTACTAREA in the docs. | ||
if ((touchInput.Mask & TOUCHEVENTFMASK_CONTACTAREA) != 0) | ||
{ | ||
var centerX = touchInput.X / 100.0; | ||
var centerY = touchInput.Y / 100.0; | ||
|
||
var rightX = centerX + touchInput.CxContact / 100.0 / | ||
2 /*The center X add the half width is the right X*/; | ||
var bottomY = centerY + touchInput.CyContact / 100.0 / | ||
2 /*The center Y add the half height is the bottom Y*/; | ||
|
||
var bottomRightPixelPoint = | ||
new PixelPoint((int)rightX, (int)bottomY); | ||
var bottomRightPosition = PointToClient(bottomRightPixelPoint); | ||
|
||
var centerPosition = position; | ||
var halfWidth = bottomRightPosition.X - centerPosition.X; | ||
var halfHeight = bottomRightPosition.Y - centerPosition.Y; | ||
var leftTopPosition = new Point(centerPosition.X - halfWidth, centerPosition.Y - halfHeight); | ||
|
||
rawPointerPoint.ContactRect = new Rect(leftTopPosition, bottomRightPosition); | ||
} | ||
|
||
input.Invoke(new RawTouchEventArgs(_touchDevice, touchInput.Time, | ||
Owner, | ||
touchInput.Flags.HasAllFlags(TouchInputFlags.TOUCHEVENTF_UP) ? | ||
RawPointerEventType.TouchEnd : | ||
touchInput.Flags.HasAllFlags(TouchInputFlags.TOUCHEVENTF_DOWN) ? | ||
RawPointerEventType.TouchBegin : | ||
RawPointerEventType.TouchUpdate, | ||
PointToClient(new PixelPoint(touchInput.X / 100, touchInput.Y / 100)), | ||
rawPointerPoint, | ||
WindowsKeyboardDevice.Instance.Modifiers, | ||
touchInput.Id)); | ||
} | ||
|
@@ -1053,13 +1085,35 @@ private RawPointerPoint CreateRawPointerPoint(POINTER_TOUCH_INFO info) | |
{ | ||
var pointerInfo = info.pointerInfo; | ||
var point = PointToClient(new PixelPoint(pointerInfo.ptPixelLocationX, pointerInfo.ptPixelLocationY)); | ||
return new RawPointerPoint | ||
|
||
var pointerPoint = new RawPointerPoint | ||
{ | ||
Position = point, | ||
// POINTER_PEN_INFO.pressure is normalized to a range between 0 and 1024, with 512 as a default. | ||
// But in our API we use range from 0.0 to 1.0. | ||
Pressure = info.pressure / 1024f | ||
Pressure = info.pressure / 1024f, | ||
}; | ||
|
||
// See https://learn.microsoft.com/en-us/windows/win32/inputmsg/touch-mask-constants | ||
// > TOUCH_MASK_CONTACTAREA: rcContact of the POINTER_TOUCH_INFO structure is valid. | ||
if ((info.touchMask & TouchMask.TOUCH_MASK_CONTACTAREA) != 0) | ||
{ | ||
// See https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-pointer_touch_info | ||
// > The predicted screen coordinates of the contact area, in pixels. By default, if the device does not report a contact area, this field defaults to a 0-by-0 rectangle centered around the pointer location. | ||
var leftTopPixelPoint = | ||
new PixelPoint(info.rcContactLeft, info.rcContactTop); | ||
var leftTopPosition = PointToClient(leftTopPixelPoint); | ||
|
||
var bottomRightPixelPoint = | ||
new PixelPoint(info.rcContactRight, info.rcContactBottom); | ||
var bottomRightPosition = PointToClient(bottomRightPixelPoint); | ||
|
||
// Why not use ptPixelLocationX and ptPixelLocationY to as leftTopPosition? | ||
// Because ptPixelLocationX and ptPixelLocationY will be the center of the contact area. | ||
pointerPoint.ContactRect = new Rect(leftTopPosition, bottomRightPosition); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Addition: The behavior here is identical to that of WinUI 3, even when the DPI is not set to 100%. |
||
} | ||
|
||
return pointerPoint; | ||
} | ||
private RawPointerPoint CreateRawPointerPoint(POINTER_PEN_INFO info) | ||
{ | ||
|
Uh oh!
There was an error while loading. Please reload this page.