diff --git a/src/Avalonia.X11/Selections/DragDrop/X11DragSource.cs b/src/Avalonia.X11/Selections/DragDrop/X11DragSource.cs index 8c3de02d61..ebbbe0a78f 100644 --- a/src/Avalonia.X11/Selections/DragDrop/X11DragSource.cs +++ b/src/Avalonia.X11/Selections/DragDrop/X11DragSource.cs @@ -158,8 +158,8 @@ internal sealed class X11DragSource(AvaloniaX11Platform platform) : IPlatformDra { if (_lastTarget is { } lastTarget) { - if (lastTarget.InProcessWindow is not null) - ProcessRawDragEvent(lastTarget.InProcessWindow, RawDragEventType.DragLeave, rootPosition); + if (lastTarget.InProcessWindow is { } window) + ProcessRawDragEvent(window, RawDragEventType.DragLeave, rootPosition, motion.state); else SendXdndLeave(lastTarget); } @@ -169,8 +169,8 @@ internal sealed class X11DragSource(AvaloniaX11Platform platform) : IPlatformDra if (target is { } newTarget) { - if (newTarget.InProcessWindow is not null) - ProcessRawDragEvent(newTarget.InProcessWindow, RawDragEventType.DragEnter, rootPosition); + if (newTarget.InProcessWindow is { } window) + ProcessRawDragEvent(window, RawDragEventType.DragEnter, rootPosition, motion.state); else SendXdndEnter(newTarget); } @@ -178,8 +178,8 @@ internal sealed class X11DragSource(AvaloniaX11Platform platform) : IPlatformDra if (target is { } currentTarget) { - if (currentTarget.InProcessWindow is not null) - ProcessRawDragEvent(currentTarget.InProcessWindow, RawDragEventType.DragOver, rootPosition); + if (currentTarget.InProcessWindow is { } window) + ProcessRawDragEvent(window, RawDragEventType.DragOver, rootPosition, motion.state); else { var action = XdndActionHelper.EffectsToAction(_allowedEffects, _platform.Info.Atoms); @@ -198,7 +198,7 @@ internal sealed class X11DragSource(AvaloniaX11Platform platform) : IPlatformDra if (lastTarget.InProcessWindow is not null) { var rootPosition = new PixelPoint(button.x_root, button.y_root); - ProcessRawDragEvent(lastTarget.InProcessWindow, RawDragEventType.Drop, rootPosition); + ProcessRawDragEvent(lastTarget.InProcessWindow, RawDragEventType.Drop, rootPosition, button.state); _lastTarget = null; Complete(_currentEffects); } @@ -382,7 +382,11 @@ internal sealed class X11DragSource(AvaloniaX11Platform platform) : IPlatformDra XFlush(_platform.Display); } - private void ProcessRawDragEvent(X11Window targetWindow, RawDragEventType eventType, PixelPoint rootPosition) + private void ProcessRawDragEvent( + X11Window targetWindow, + RawDragEventType eventType, + PixelPoint rootPosition, + XModifierMask modifierMask) { if (targetWindow.DragDropDevice is not { } dragDropDevice) { @@ -391,6 +395,7 @@ internal sealed class X11DragSource(AvaloniaX11Platform platform) : IPlatformDra } var localPosition = targetWindow.PointToClient(rootPosition); + var modifiers = modifierMask.ToRawInputModifiers(); var dragEvent = new RawDragEvent( dragDropDevice, @@ -399,7 +404,7 @@ internal sealed class X11DragSource(AvaloniaX11Platform platform) : IPlatformDra localPosition, _dataTransfer, _allowedEffects, - RawInputModifiers.None); + modifiers); dragDropDevice.ProcessRawEvent(dragEvent); diff --git a/src/Avalonia.X11/Selections/DragDrop/X11DropTarget.cs b/src/Avalonia.X11/Selections/DragDrop/X11DropTarget.cs index 3fa5928d51..26a910ec90 100644 --- a/src/Avalonia.X11/Selections/DragDrop/X11DropTarget.cs +++ b/src/Avalonia.X11/Selections/DragDrop/X11DropTarget.cs @@ -85,6 +85,7 @@ internal sealed class X11DropTarget var position = _window.PointToClient(new PixelPoint(screenX, screenY)); var requestedEffects = XdndActionHelper.ActionToEffects(message.ptr5, _atoms); var eventType = drag.LastPosition is null ? RawDragEventType.DragEnter : RawDragEventType.DragOver; + var modifiers = GetModifiers(); drag.LastPosition = position; drag.LastTimestamp = message.ptr4; @@ -96,7 +97,7 @@ internal sealed class X11DropTarget position, drag, requestedEffects, - RawInputModifiers.None); + modifiers); _dragDropDevice.ProcessRawEvent(dragEvent); @@ -111,6 +112,8 @@ internal sealed class X11DropTarget if (_currentDrag is not { } drag || message.ptr1 != drag.SourceWindow) return; + var modifiers = GetModifiers(); + var dragLeave = new RawDragEvent( _dragDropDevice, RawDragEventType.DragLeave, @@ -118,7 +121,7 @@ internal sealed class X11DropTarget default, drag, DragDropEffects.None, - RawInputModifiers.None); + modifiers); _dragDropDevice.ProcessRawEvent(dragLeave); @@ -130,6 +133,8 @@ internal sealed class X11DropTarget if (_currentDrag is not { } drag || message.ptr1 != drag.SourceWindow) return; + var modifiers = GetModifiers(); + var drop = new RawDragEvent( _dragDropDevice, RawDragEventType.Drop, @@ -137,7 +142,7 @@ internal sealed class X11DropTarget drag.LastPosition ?? default, drag, drag.ResultEffects, - RawInputModifiers.None); + modifiers); _dragDropDevice.ProcessRawEvent(drop); @@ -176,6 +181,11 @@ internal sealed class X11DropTarget XFlush(_display); } + private RawInputModifiers GetModifiers() + => XQueryPointer(_display, _window.Handle, out _, out _, out _, out _, out _, out _, out var mask) ? + mask.ToRawInputModifiers() : + RawInputModifiers.None; + private void DisposeCurrentDrag() { if (_currentDrag is not { } drag) diff --git a/src/Avalonia.X11/X11EnumExtensions.cs b/src/Avalonia.X11/X11EnumExtensions.cs new file mode 100644 index 0000000000..a374a24bbd --- /dev/null +++ b/src/Avalonia.X11/X11EnumExtensions.cs @@ -0,0 +1,30 @@ +using Avalonia.Input; + +namespace Avalonia.X11; + +internal static class X11EnumExtensions +{ + public static RawInputModifiers ToRawInputModifiers(this XModifierMask state) + { + var rv = default(RawInputModifiers); + if (state.HasAllFlags(XModifierMask.Button1Mask)) + rv |= RawInputModifiers.LeftMouseButton; + if (state.HasAllFlags(XModifierMask.Button2Mask)) + rv |= RawInputModifiers.RightMouseButton; + if (state.HasAllFlags(XModifierMask.Button3Mask)) + rv |= RawInputModifiers.MiddleMouseButton; + if (state.HasAllFlags(XModifierMask.Button4Mask)) + rv |= RawInputModifiers.XButton1MouseButton; + if (state.HasAllFlags(XModifierMask.Button5Mask)) + rv |= RawInputModifiers.XButton2MouseButton; + if (state.HasAllFlags(XModifierMask.ShiftMask)) + rv |= RawInputModifiers.Shift; + if (state.HasAllFlags(XModifierMask.ControlMask)) + rv |= RawInputModifiers.Control; + if (state.HasAllFlags(XModifierMask.Mod1Mask)) + rv |= RawInputModifiers.Alt; + if (state.HasAllFlags(XModifierMask.Mod4Mask)) + rv |= RawInputModifiers.Meta; + return rv; + } +} diff --git a/src/Avalonia.X11/X11Window.Ime.cs b/src/Avalonia.X11/X11Window.Ime.cs index 768a79af3d..e51934e65d 100644 --- a/src/Avalonia.X11/X11Window.Ime.cs +++ b/src/Avalonia.X11/X11Window.Ime.cs @@ -116,7 +116,7 @@ namespace Avalonia.X11 { var physicalKey = X11KeyTransform.PhysicalKeyFromScanCode(ev.KeyEvent.keycode); var (x11Key, key, symbol) = LookupKey(ref ev.KeyEvent, physicalKey); - var modifiers = TranslateModifiers(ev.KeyEvent.state); + var modifiers = ev.KeyEvent.state.ToRawInputModifiers(); var timestamp = (ulong)ev.KeyEvent.time.ToInt64(); var args = ev.type == XEventName.KeyPress ? diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index c4b9b19545..37eff383db 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -580,7 +580,7 @@ namespace Avalonia.X11 : new Vector(-1, 0); ScheduleInput(new RawMouseWheelEventArgs(_mouse, (ulong)ev.ButtonEvent.time.ToInt64(), _inputRoot, new Point(ev.ButtonEvent.x, ev.ButtonEvent.y), delta, - TranslateModifiers(ev.ButtonEvent.state)), ref ev); + ev.ButtonEvent.state.ToRawInputModifiers()), ref ev); } } @@ -855,30 +855,6 @@ namespace Avalonia.X11 } - private static RawInputModifiers TranslateModifiers(XModifierMask state) - { - var rv = default(RawInputModifiers); - if (state.HasAllFlags(XModifierMask.Button1Mask)) - rv |= RawInputModifiers.LeftMouseButton; - if (state.HasAllFlags(XModifierMask.Button2Mask)) - rv |= RawInputModifiers.RightMouseButton; - if (state.HasAllFlags(XModifierMask.Button3Mask)) - rv |= RawInputModifiers.MiddleMouseButton; - if (state.HasAllFlags(XModifierMask.Button4Mask)) - rv |= RawInputModifiers.XButton1MouseButton; - if (state.HasAllFlags(XModifierMask.Button5Mask)) - rv |= RawInputModifiers.XButton2MouseButton; - if (state.HasAllFlags(XModifierMask.ShiftMask)) - rv |= RawInputModifiers.Shift; - if (state.HasAllFlags(XModifierMask.ControlMask)) - rv |= RawInputModifiers.Control; - if (state.HasAllFlags(XModifierMask.Mod1Mask)) - rv |= RawInputModifiers.Alt; - if (state.HasAllFlags(XModifierMask.Mod4Mask)) - rv |= RawInputModifiers.Meta; - return rv; - } - private WindowDecorations _requestedWindowDecorations = WindowDecorations.Full; private WindowDecorations _windowDecorations = WindowDecorations.Full; private bool _canResize = true; @@ -986,7 +962,7 @@ namespace Avalonia.X11 return; var mev = new RawPointerEventArgs( _mouse, (ulong)ev.ButtonEvent.time.ToInt64(), _inputRoot, - type, new Point(ev.ButtonEvent.x, ev.ButtonEvent.y), TranslateModifiers(mods)); + type, new Point(ev.ButtonEvent.x, ev.ButtonEvent.y), mods.ToRawInputModifiers()); ScheduleInput(mev, ref ev); } diff --git a/src/Avalonia.X11/XLib.cs b/src/Avalonia.X11/XLib.cs index c6172eb02a..089ab03c0b 100644 --- a/src/Avalonia.X11/XLib.cs +++ b/src/Avalonia.X11/XLib.cs @@ -175,7 +175,7 @@ namespace Avalonia.X11 [DllImport(libX11)] public static extern bool XQueryPointer(IntPtr display, IntPtr window, out IntPtr root, out IntPtr child, - out int root_x, out int root_y, out int win_x, out int win_y, out int keys_buttons); + out int root_x, out int root_y, out int win_x, out int win_y, out XModifierMask mask); [DllImport(libX11)] public static extern bool XTranslateCoordinates(IntPtr display, IntPtr src_w, IntPtr dest_w, int src_x, @@ -694,7 +694,7 @@ namespace Avalonia.X11 public static void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child, out int root_x, out int root_y, out int child_x, out int child_y, - out int mask) + out XModifierMask mask) { IntPtr c; @@ -729,7 +729,7 @@ namespace Avalonia.X11 int root_y; int win_x; int win_y; - int keys_buttons; + XModifierMask keys_buttons;