Browse Source

Added support for extra mouse buttons.

pull/3033/head
José Pedro 7 years ago
parent
commit
fc1a60b159
No known key found for this signature in database GPG Key ID: B8247B9301707B83
  1. 14
      native/Avalonia.Native/inc/avalonia-native.h
  2. 41
      native/Avalonia.Native/src/OSX/window.mm
  3. 2
      src/Avalonia.Input/IKeyboardDevice.cs
  4. 16
      src/Avalonia.Input/MouseDevice.cs
  5. 22
      src/Avalonia.Input/PointerPoint.cs
  6. 4
      src/Avalonia.Input/Raw/RawPointerEventArgs.cs
  7. 36
      src/Avalonia.X11/X11Window.cs
  8. 52
      src/Windows/Avalonia.Win32/WindowImpl.cs

14
native/Avalonia.Native/inc/avalonia-native.h

@ -92,9 +92,17 @@ enum AvnRawMouseEventType
RightButtonUp,
MiddleButtonDown,
MiddleButtonUp,
XButton1Down,
XButton1Up,
XButton2Down,
XButton2Up,
Move,
Wheel,
NonClientLeftButtonDown
NonClientLeftButtonDown,
TouchBegin,
TouchUpdate,
TouchEnd,
TouchCancel
};
enum AvnRawKeyEventType
@ -112,7 +120,9 @@ enum AvnInputModifiers
Windows = 8,
LeftMouseButton = 16,
RightMouseButton = 32,
MiddleMouseButton = 64
MiddleMouseButton = 64,
XButton1MouseButton = 128,
XButton2MouseButton = 256
};
enum AvnWindowState

41
native/Avalonia.Native/src/OSX/window.mm

@ -716,7 +716,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
AvnFramebuffer _swRenderedFrameBuffer;
bool _queuedDisplayFromThread;
NSTrackingArea* _area;
bool _isLeftPressed, _isMiddlePressed, _isRightPressed, _isMouseOver;
bool _isLeftPressed, _isMiddlePressed, _isRightPressed, _isXButton1Pressed, _isXButton2Pressed, _isMouseOver;
NSEvent* _lastMouseDownEvent;
bool _lastKeyHandled;
}
@ -941,9 +941,23 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
- (void)otherMouseDown:(NSEvent *)event
{
_isMiddlePressed = true;
_lastMouseDownEvent = event;
[self mouseEvent:event withType:MiddleButtonDown];
switch(event.buttonNumber)
{
case 3:
_isMiddlePressed = true;
[self mouseEvent:event withType:MiddleButtonDown];
break;
case 4:
_isXButton1Pressed = true;
[self mouseEvent:event withType:XButton1Down];
break;
case 5:
_isXButton2Pressed = true;
[self mouseEvent:event withType:XButton2Down];
break;
}
}
- (void)rightMouseDown:(NSEvent *)event
@ -961,8 +975,21 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
- (void)otherMouseUp:(NSEvent *)event
{
_isMiddlePressed = false;
[self mouseEvent:event withType:MiddleButtonUp];
switch(event.buttonNumber)
{
case 3:
_isMiddlePressed = false;
[self mouseEvent:event withType:MiddleButtonUp];
break;
case 4:
_isXButton1Pressed = false;
[self mouseEvent:event withType:XButton1Up];
break;
case 5:
_isXButton2Pressed = false;
[self mouseEvent:event withType:XButton2Up];
break;
}
}
- (void)rightMouseUp:(NSEvent *)event
@ -1061,6 +1088,10 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
rv |= MiddleMouseButton;
if (_isRightPressed)
rv |= RightMouseButton;
if (_isXButton1Pressed)
rv |= XButton1MouseButton;
if (_isXButton2Pressed)
rv |= XButton2MouseButton;
return (AvnInputModifiers)rv;
}

2
src/Avalonia.Input/IKeyboardDevice.cs

@ -48,6 +48,8 @@ namespace Avalonia.Input
LeftMouseButton = 16,
RightMouseButton = 32,
MiddleMouseButton = 64,
XButton1MouseButton = 128,
XButton2MouseButton = 256,
KeyboardMask = Alt | Control | Shift | Meta
}

16
src/Avalonia.Input/MouseDevice.cs

@ -120,6 +120,10 @@ namespace Avalonia.Input
rv++;
if (props.IsRightButtonPressed)
rv++;
if (props.IsXButton1Pressed)
rv++;
if (props.IsXButton2Pressed)
rv++;
return rv;
}
@ -142,6 +146,8 @@ namespace Avalonia.Input
case RawPointerEventType.LeftButtonDown:
case RawPointerEventType.RightButtonDown:
case RawPointerEventType.MiddleButtonDown:
case RawPointerEventType.XButton1Down:
case RawPointerEventType.XButton2Down:
if (ButtonCount(props) > 1)
e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers);
else
@ -151,6 +157,8 @@ namespace Avalonia.Input
case RawPointerEventType.LeftButtonUp:
case RawPointerEventType.RightButtonUp:
case RawPointerEventType.MiddleButtonUp:
case RawPointerEventType.XButton1Up:
case RawPointerEventType.XButton2Up:
if (ButtonCount(props) != 0)
e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers);
else
@ -186,12 +194,20 @@ namespace Avalonia.Input
kind = PointerUpdateKind.MiddleButtonPressed;
if (args.Type == RawPointerEventType.RightButtonDown)
kind = PointerUpdateKind.RightButtonPressed;
if (args.Type == RawPointerEventType.XButton1Down)
kind = PointerUpdateKind.XButton1Pressed;
if (args.Type == RawPointerEventType.XButton2Down)
kind = PointerUpdateKind.XButton2Pressed;
if (args.Type == RawPointerEventType.LeftButtonUp)
kind = PointerUpdateKind.LeftButtonReleased;
if (args.Type == RawPointerEventType.MiddleButtonUp)
kind = PointerUpdateKind.MiddleButtonReleased;
if (args.Type == RawPointerEventType.RightButtonUp)
kind = PointerUpdateKind.RightButtonReleased;
if (args.Type == RawPointerEventType.XButton1Up)
kind = PointerUpdateKind.XButton1Released;
if (args.Type == RawPointerEventType.XButton2Up)
kind = PointerUpdateKind.XButton2Released;
return new PointerPointProperties(args.InputModifiers, kind);
}

22
src/Avalonia.Input/PointerPoint.cs

@ -21,18 +21,24 @@ namespace Avalonia.Input
public bool IsLeftButtonPressed { get; }
public bool IsMiddleButtonPressed { get; }
public bool IsRightButtonPressed { get; }
public bool IsXButton1Pressed { get; }
public bool IsXButton2Pressed { get; }
public PointerUpdateKind PointerUpdateKind { get; }
private PointerPointProperties()
{
{
}
public PointerPointProperties(RawInputModifiers modifiers, PointerUpdateKind kind)
{
PointerUpdateKind = kind;
IsLeftButtonPressed = modifiers.HasFlagCustom(RawInputModifiers.LeftMouseButton);
IsMiddleButtonPressed = modifiers.HasFlagCustom(RawInputModifiers.MiddleMouseButton);
IsRightButtonPressed = modifiers.HasFlagCustom(RawInputModifiers.RightMouseButton);
IsXButton1Pressed = modifiers.HasFlagCustom(RawInputModifiers.XButton1MouseButton);
IsXButton2Pressed = modifiers.HasFlagCustom(RawInputModifiers.XButton2MouseButton);
// The underlying input source might be reporting the previous state,
// so make sure that we reflect the current state
@ -49,6 +55,14 @@ namespace Avalonia.Input
IsRightButtonPressed = true;
if (kind == PointerUpdateKind.RightButtonReleased)
IsRightButtonPressed = false;
if (kind == PointerUpdateKind.XButton1Pressed)
IsXButton1Pressed = true;
if (kind == PointerUpdateKind.XButton1Released)
IsXButton1Pressed = false;
if (kind == PointerUpdateKind.XButton2Pressed)
IsXButton2Pressed = true;
if (kind == PointerUpdateKind.XButton2Released)
IsXButton2Pressed = false;
}
public static PointerPointProperties None { get; } = new PointerPointProperties();
@ -59,9 +73,13 @@ namespace Avalonia.Input
LeftButtonPressed,
MiddleButtonPressed,
RightButtonPressed,
XButton1Pressed,
XButton2Pressed,
LeftButtonReleased,
MiddleButtonReleased,
RightButtonReleased,
XButton1Released,
XButton2Released,
Other
}

4
src/Avalonia.Input/Raw/RawPointerEventArgs.cs

@ -14,6 +14,10 @@ namespace Avalonia.Input.Raw
RightButtonUp,
MiddleButtonDown,
MiddleButtonUp,
XButton1Down,
XButton1Up,
XButton2Down,
XButton2Up,
Move,
Wheel,
NonClientLeftButtonDown,

36
src/Avalonia.X11/X11Window.cs

@ -351,10 +351,17 @@ namespace Avalonia.X11
{
if (ActivateTransientChildIfNeeded())
return;
if (ev.ButtonEvent.button < 4)
MouseEvent(ev.ButtonEvent.button == 1 ? RawPointerEventType.LeftButtonDown
: ev.ButtonEvent.button == 2 ? RawPointerEventType.MiddleButtonDown
: RawPointerEventType.RightButtonDown, ref ev, ev.ButtonEvent.state);
if (ev.ButtonEvent.button < 4 || ev.ButtonEvent.button == 8 || ev.ButtonEvent.button == 9)
MouseEvent(
ev.ButtonEvent.button switch
{
1 => RawPointerEventType.LeftButtonDown,
2 => RawPointerEventType.MiddleButtonDown,
3 => RawPointerEventType.RightButtonDown,
8 => RawPointerEventType.XButton1Down,
9 => RawPointerEventType.XButton2Down
},
ref ev, ev.ButtonEvent.state);
else
{
var delta = ev.ButtonEvent.button == 4
@ -372,10 +379,17 @@ namespace Avalonia.X11
}
else if (ev.type == XEventName.ButtonRelease)
{
if (ev.ButtonEvent.button < 4)
MouseEvent(ev.ButtonEvent.button == 1 ? RawPointerEventType.LeftButtonUp
: ev.ButtonEvent.button == 2 ? RawPointerEventType.MiddleButtonUp
: RawPointerEventType.RightButtonUp, ref ev, ev.ButtonEvent.state);
if (ev.ButtonEvent.button < 4 || ev.ButtonEvent.button == 8 || ev.ButtonEvent.button == 9)
MouseEvent(
ev.ButtonEvent.button switch
{
1 => RawPointerEventType.LeftButtonUp,
2 => RawPointerEventType.MiddleButtonUp,
3 => RawPointerEventType.RightButtonUp,
8 => RawPointerEventType.XButton1Up,
9 => RawPointerEventType.XButton2Up
},
ref ev, ev.ButtonEvent.state);
}
else if (ev.type == XEventName.ConfigureNotify)
{
@ -586,8 +600,12 @@ namespace Avalonia.X11
rv |= RawInputModifiers.LeftMouseButton;
if (state.HasFlag(XModifierMask.Button2Mask))
rv |= RawInputModifiers.RightMouseButton;
if (state.HasFlag(XModifierMask.Button2Mask))
if (state.HasFlag(XModifierMask.Button3Mask))
rv |= RawInputModifiers.MiddleMouseButton;
if (state.HasFlag(XModifierMask.Button4Mask))
rv |= RawInputModifiers.XButton1MouseButton;
if (state.HasFlag(XModifierMask.Button5Mask))
rv |= RawInputModifiers.XButton2MouseButton;
if (state.HasFlag(XModifierMask.ShiftMask))
rv |= RawInputModifiers.Shift;
if (state.HasFlag(XModifierMask.ControlMask))

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

@ -540,34 +540,42 @@ namespace Avalonia.Win32
case UnmanagedMethods.WindowsMessage.WM_LBUTTONDOWN:
case UnmanagedMethods.WindowsMessage.WM_RBUTTONDOWN:
case UnmanagedMethods.WindowsMessage.WM_MBUTTONDOWN:
if(ShouldIgnoreTouchEmulatedMessage())
case UnmanagedMethods.WindowsMessage.WM_XBUTTONDOWN:
if (ShouldIgnoreTouchEmulatedMessage())
break;
e = new RawPointerEventArgs(
_mouseDevice,
timestamp,
_owner,
msg == (int)UnmanagedMethods.WindowsMessage.WM_LBUTTONDOWN
? RawPointerEventType.LeftButtonDown
: msg == (int)UnmanagedMethods.WindowsMessage.WM_RBUTTONDOWN
? RawPointerEventType.RightButtonDown
: RawPointerEventType.MiddleButtonDown,
(UnmanagedMethods.WindowsMessage)msg switch
{
UnmanagedMethods.WindowsMessage.WM_LBUTTONDOWN => RawPointerEventType.LeftButtonDown,
UnmanagedMethods.WindowsMessage.WM_RBUTTONDOWN => RawPointerEventType.RightButtonDown,
UnmanagedMethods.WindowsMessage.WM_MBUTTONDOWN => RawPointerEventType.MiddleButtonDown,
UnmanagedMethods.WindowsMessage.WM_XBUTTONDOWN =>
HighWord(ToInt32(wParam)) == 1 ? RawPointerEventType.XButton1Down : RawPointerEventType.XButton2Down
},
DipFromLParam(lParam), GetMouseModifiers(wParam));
break;
case UnmanagedMethods.WindowsMessage.WM_LBUTTONUP:
case UnmanagedMethods.WindowsMessage.WM_RBUTTONUP:
case UnmanagedMethods.WindowsMessage.WM_MBUTTONUP:
if(ShouldIgnoreTouchEmulatedMessage())
case UnmanagedMethods.WindowsMessage.WM_XBUTTONUP:
if (ShouldIgnoreTouchEmulatedMessage())
break;
e = new RawPointerEventArgs(
_mouseDevice,
timestamp,
_owner,
msg == (int)UnmanagedMethods.WindowsMessage.WM_LBUTTONUP
? RawPointerEventType.LeftButtonUp
: msg == (int)UnmanagedMethods.WindowsMessage.WM_RBUTTONUP
? RawPointerEventType.RightButtonUp
: RawPointerEventType.MiddleButtonUp,
(UnmanagedMethods.WindowsMessage)msg switch
{
UnmanagedMethods.WindowsMessage.WM_LBUTTONUP => RawPointerEventType.LeftButtonUp,
UnmanagedMethods.WindowsMessage.WM_RBUTTONUP => RawPointerEventType.RightButtonUp,
UnmanagedMethods.WindowsMessage.WM_MBUTTONUP => RawPointerEventType.MiddleButtonUp,
UnmanagedMethods.WindowsMessage.WM_XBUTTONUP =>
HighWord(ToInt32(wParam)) == 1 ? RawPointerEventType.XButton1Up : RawPointerEventType.XButton2Up,
},
DipFromLParam(lParam), GetMouseModifiers(wParam));
break;
@ -627,15 +635,19 @@ namespace Avalonia.Win32
case UnmanagedMethods.WindowsMessage.WM_NCLBUTTONDOWN:
case UnmanagedMethods.WindowsMessage.WM_NCRBUTTONDOWN:
case UnmanagedMethods.WindowsMessage.WM_NCMBUTTONDOWN:
case UnmanagedMethods.WindowsMessage.WM_NCXBUTTONDOWN:
e = new RawPointerEventArgs(
_mouseDevice,
timestamp,
_owner,
msg == (int)UnmanagedMethods.WindowsMessage.WM_NCLBUTTONDOWN
? RawPointerEventType.NonClientLeftButtonDown
: msg == (int)UnmanagedMethods.WindowsMessage.WM_NCRBUTTONDOWN
? RawPointerEventType.RightButtonDown
: RawPointerEventType.MiddleButtonDown,
(UnmanagedMethods.WindowsMessage)msg switch
{
UnmanagedMethods.WindowsMessage.WM_NCLBUTTONDOWN => RawPointerEventType.NonClientLeftButtonDown,
UnmanagedMethods.WindowsMessage.WM_NCRBUTTONDOWN => RawPointerEventType.RightButtonDown,
UnmanagedMethods.WindowsMessage.WM_NCMBUTTONDOWN => RawPointerEventType.MiddleButtonDown,
UnmanagedMethods.WindowsMessage.WM_NCXBUTTONDOWN =>
HighWord(ToInt32(wParam)) == 1 ? RawPointerEventType.XButton1Down : RawPointerEventType.XButton2Down,
},
PointToClient(PointFromLParam(lParam)), GetMouseModifiers(wParam));
break;
case WindowsMessage.WM_TOUCH:
@ -778,6 +790,10 @@ namespace Avalonia.Win32
modifiers |= RawInputModifiers.RightMouseButton;
if (keys.HasFlagCustom(UnmanagedMethods.ModifierKeys.MK_MBUTTON))
modifiers |= RawInputModifiers.MiddleMouseButton;
if (keys.HasFlag(UnmanagedMethods.ModifierKeys.MK_XBUTTON1))
modifiers |= RawInputModifiers.XButton1MouseButton;
if (keys.HasFlag(UnmanagedMethods.ModifierKeys.MK_XBUTTON2))
modifiers |= RawInputModifiers.XButton2MouseButton;
return modifiers;
}
@ -1056,5 +1072,7 @@ namespace Avalonia.Win32
}
}
IntPtr EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Handle => Handle.Handle;
private static int HighWord(int param) => param >> 16;
}
}

Loading…
Cancel
Save