Browse Source

Fixed XI_Leave handling

pull/4905/head
Nikita Tsukanov 6 years ago
parent
commit
8f1e859089
  1. 76
      src/Avalonia.X11/XI2Manager.cs
  2. 43
      src/Avalonia.X11/XIStructs.cs

76
src/Avalonia.X11/XI2Manager.cs

@ -14,7 +14,9 @@ namespace Avalonia.X11
XiEventType.XI_Motion, XiEventType.XI_Motion,
XiEventType.XI_ButtonPress, XiEventType.XI_ButtonPress,
XiEventType.XI_ButtonRelease, XiEventType.XI_ButtonRelease,
XiEventType.XI_Leave XiEventType.XI_Leave,
XiEventType.XI_Enter,
}; };
private static readonly XiEventType[] MultiTouchEventTypes = new XiEventType[] private static readonly XiEventType[] MultiTouchEventTypes = new XiEventType[]
@ -180,13 +182,37 @@ namespace Avalonia.X11
if ((xev->evtype >= XiEventType.XI_ButtonPress && xev->evtype <= XiEventType.XI_Motion) if ((xev->evtype >= XiEventType.XI_ButtonPress && xev->evtype <= XiEventType.XI_Motion)
|| (xev->evtype >= XiEventType.XI_TouchBegin && xev->evtype <= XiEventType.XI_TouchEnd) || (xev->evtype >= XiEventType.XI_TouchBegin && xev->evtype <= XiEventType.XI_TouchEnd))
|| xev->evtype == XiEventType.XI_Leave)
{ {
var dev = (XIDeviceEvent*)xev; var dev = (XIDeviceEvent*)xev;
if (_clients.TryGetValue(dev->EventWindow, out var client)) if (_clients.TryGetValue(dev->EventWindow, out var client))
OnDeviceEvent(client, new ParsedDeviceEvent(dev)); OnDeviceEvent(client, new ParsedDeviceEvent(dev));
} }
if (xev->evtype == XiEventType.XI_Leave || xev->evtype == XiEventType.XI_Enter)
{
var rev = (XIEnterLeaveEvent*)xev;
if (_clients.TryGetValue(rev->EventWindow, out var client))
OnEnterLeaveEvent(client, ref *rev);
}
}
void OnEnterLeaveEvent(IXI2Client client, ref XIEnterLeaveEvent ev)
{
if (ev.evtype == XiEventType.XI_Leave)
{
var buttons = ParsedDeviceEvent.ParseButtonState(ev.buttons.MaskLen, ev.buttons.Mask);
var detail = ev.detail;
if ((detail == XiEnterLeaveDetail.XINotifyNonlinearVirtual ||
detail == XiEnterLeaveDetail.XINotifyNonlinear ||
detail == XiEnterLeaveDetail.XINotifyVirtual)
&& buttons == default)
{
client.ScheduleXI2Input(new RawPointerEventArgs(client.MouseDevice, (ulong)ev.time.ToInt64(),
client.InputRoot,
RawPointerEventType.LeaveWindow, new Point(ev.event_x, ev.event_y), buttons));
}
}
} }
void OnDeviceEvent(IXI2Client client, ParsedDeviceEvent ev) void OnDeviceEvent(IXI2Client client, ParsedDeviceEvent ev)
@ -205,12 +231,6 @@ namespace Avalonia.X11
return; return;
} }
if (ev.Type == XiEventType.XI_Leave)
{
client.ScheduleXI2Input(new RawPointerEventArgs(client.MouseDevice, ev.Timestamp, client.InputRoot,
RawPointerEventType.LeaveWindow, ev.Position, ev.Modifiers));
}
if (_multitouch && ev.Emulated) if (_multitouch && ev.Emulated)
return; return;
@ -294,6 +314,29 @@ namespace Avalonia.X11
public int Detail { get; set; } public int Detail { get; set; }
public bool Emulated { get; set; } public bool Emulated { get; set; }
public Dictionary<int, double> Valuators { get; } public Dictionary<int, double> Valuators { get; }
public static RawInputModifiers ParseButtonState(int len, byte* buttons)
{
RawInputModifiers rv = default;
if (len > 0)
{
if (XIMaskIsSet(buttons, 1))
rv |= RawInputModifiers.LeftMouseButton;
if (XIMaskIsSet(buttons, 2))
rv |= RawInputModifiers.MiddleMouseButton;
if (XIMaskIsSet(buttons, 3))
rv |= RawInputModifiers.RightMouseButton;
if (len > 1)
{
if (XIMaskIsSet(buttons, 8))
rv |= RawInputModifiers.XButton1MouseButton;
if (XIMaskIsSet(buttons, 9))
rv |= RawInputModifiers.XButton2MouseButton;
}
}
return rv;
}
public ParsedDeviceEvent(XIDeviceEvent* ev) public ParsedDeviceEvent(XIDeviceEvent* ev)
{ {
Type = ev->evtype; Type = ev->evtype;
@ -308,20 +351,7 @@ namespace Avalonia.X11
if (state.HasFlag(XModifierMask.Mod4Mask)) if (state.HasFlag(XModifierMask.Mod4Mask))
Modifiers |= RawInputModifiers.Meta; Modifiers |= RawInputModifiers.Meta;
if (ev->buttons.MaskLen > 1 && Type != XiEventType.XI_Leave) Modifiers = ParseButtonState(ev->buttons.MaskLen, ev->buttons.Mask);
{
var buttons = ev->buttons.Mask;
if (XIMaskIsSet(buttons, 1))
Modifiers |= RawInputModifiers.LeftMouseButton;
if (XIMaskIsSet(buttons, 2))
Modifiers |= RawInputModifiers.MiddleMouseButton;
if (XIMaskIsSet(buttons, 3))
Modifiers |= RawInputModifiers.RightMouseButton;
if (XIMaskIsSet(buttons, 8))
Modifiers |= RawInputModifiers.XButton1MouseButton;
if (XIMaskIsSet(buttons, 9))
Modifiers |= RawInputModifiers.XButton2MouseButton;
}
Valuators = new Dictionary<int, double>(); Valuators = new Dictionary<int, double>();
Position = new Point(ev->event_x, ev->event_y); Position = new Point(ev->event_x, ev->event_y);

43
src/Avalonia.X11/XIStructs.cs

@ -236,6 +236,34 @@ namespace Avalonia.X11
public XIModifierState mods; public XIModifierState mods;
public XIModifierState group; public XIModifierState group;
} }
[StructLayout(LayoutKind.Sequential)]
unsafe struct XIEnterLeaveEvent
{
public XEventName type; /* GenericEvent */
public UIntPtr serial; /* # of last request processed by server */
public Bool send_event; /* true if this came from a SendEvent request */
public IntPtr display; /* Display the event was read from */
public int extension; /* XI extension offset */
public XiEventType evtype;
public IntPtr time;
public int deviceid;
public int sourceid;
public XiEnterLeaveDetail detail;
public IntPtr RootWindow;
public IntPtr EventWindow;
public IntPtr ChildWindow;
public double root_x;
public double root_y;
public double event_x;
public double event_y;
public int mode;
public int focus;
public int same_screen;
public XIButtonState buttons;
public XIModifierState mods;
public XIModifierState group;
}
[Flags] [Flags]
public enum XiDeviceEventFlags : int public enum XiDeviceEventFlags : int
@ -286,5 +314,18 @@ namespace Avalonia.X11
XI_BarrierLeave = 26, XI_BarrierLeave = 26,
XI_LASTEVENT = XI_BarrierLeave, XI_LASTEVENT = XI_BarrierLeave,
} }
enum XiEnterLeaveDetail
{
XINotifyAncestor = 0,
XINotifyVirtual = 1,
XINotifyInferior = 2,
XINotifyNonlinear = 3,
XINotifyNonlinearVirtual = 4,
XINotifyPointer = 5,
XINotifyPointerRoot = 6,
XINotifyDetailNone = 7
}
} }

Loading…
Cancel
Save