Hi,
I still have the Windows Procedure message 281 that gives {begin ; parsed content by Windows at each instant ; end} events in Rhinoceros 5.14 and only {begin ; end} in Rhinoceros 7.16.
I have disabled the parameter described in this thread, given that Iβd like to have the Windows native behavior of the message 281, and the Rhinoceros commands runned by its UI or its scripts by tapping the screen.
This is a critical feature on the plugins I develop. I have reported below the comparison with the code I have around my plugins to handle this feature. If you need more info let me know.
The link is made with DllImport and Rhinocommon in .NET 4.8 as the following signatures:
public struct GESTUREINFO
{
public uint cbSize;
public uint dwFlags;
public uint dwID;
public IntPtr hwndTarget;
public POINTS ptsLocation;
public uint dwInstanceID;
public uint dwSequenceID;
public ulong ullArguments;
public uint cbExtraArgs;
}
internal static class User32
{
public const int WM_NCDESTROY = 130;
public const int GWLP_WNDPROC = -4;
public const int WM_TOUCH = 576;
public const int TOUCHEVENTF_MOVE = 1;
public const int TOUCHEVENTF_DOWN = 2;
public const int TOUCHEVENTF_UP = 4;
public const int TOUCHEVENTF_INRANGE = 8;
public const int TOUCHEVENTF_PRIMARY = 16;
public const int TOUCHEVENTF_NOCOALESCE = 32;
public const int TOUCHEVENTF_PEN = 64;
public const int TOUCHEVENTF_PALM = 128;
public const int TOUCHINPUTMASKF_TIMEFROMSYSTEM = 1;
public const int TOUCHINPUTMASKF_EXTRAINFO = 2;
public const int TOUCHINPUTMASKF_CONTACTAREA = 4;
public const uint GC_ALLGESTURES = 1;
public const uint WM_GESTURE = 281;
public const uint WM_GESTURENOTIFY = 282;
public const uint GF_BEGIN = 1;
public const uint GF_INERTIA = 2;
public const uint GF_END = 4;
public const uint GID_BEGIN = 1;
public const uint GID_END = 2;
public const uint GID_ZOOM = 3;
public const uint GID_PAN = 4;
public const uint GID_ROTATE = 5;
public const uint GID_TWOFINGERTAP = 6;
public const uint GID_PRESSANDTAP = 7;
[DllImport("user32")]
public static extern bool SetProcessDPIAware();
[DllImport("user32")]
public static extern bool IsWindow(IntPtr hWnd);
[DllImport("user32")]
public static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint);
[DllImport("user32", EntryPoint = "SetWindowLongPtr")]
public static extern IntPtr SubclassWindow64(
IntPtr hWnd,
int nIndex,
User32.WindowProcDelegate dwNewLong);
[DllImport("user32", EntryPoint = "SetWindowLong")]
public static extern IntPtr SubclassWindow(
IntPtr hWnd,
int nIndex,
User32.WindowProcDelegate dwNewLong);
[DllImport("user32")]
public static extern uint CallWindowProc(
IntPtr prevWndFunc,
IntPtr hWnd,
int msg,
IntPtr wparam,
IntPtr lparam);
[DllImport("user32", EntryPoint = "GetSystemMetrics")]
public static extern int GetDigitizerCapabilities(User32.DigitizerIndex index);
[DllImport("user32")]
public static extern bool RegisterTouchWindow(IntPtr hWnd, User32.TouchWindowFlag flags);
[DllImport("user32")]
public static extern bool UnregisterTouchWindow(IntPtr hWnd);
[DllImport("user32")]
public static extern bool IsTouchWindow(IntPtr hWnd, out uint ulFlags);
[DllImport("user32")]
public static extern bool GetTouchInputInfo(
IntPtr hTouchInput,
int cInputs,
[In, Out] TOUCHINPUT[] pInputs,
int cbSize);
[DllImport("user32")]
public static extern void CloseTouchInputHandle(IntPtr lParam);
[DllImport("user32")]
public static extern bool SetProp(IntPtr hWnd, string lpString, IntPtr hData);
public static ushort LoWord(uint number) => (ushort) (number & (uint) ushort.MaxValue);
public static ushort HiWord(uint number) => (ushort) (number >> 16 & (uint) ushort.MaxValue);
public static uint LoDWord(ulong number) => (uint) (number & (ulong) uint.MaxValue);
public static uint HiDWord(ulong number) => (uint) (number >> 32 & (ulong) uint.MaxValue);
public static short LoWord(int number) => (short) number;
public static short HiWord(int number) => (short) (number >> 16);
public static int LoDWord(long number) => (int) number;
public static int HiDWord(long number) => (int) (number >> 32);
[DllImport("user32")]
public static extern bool SetGestureConfig(
IntPtr hwnd,
uint dwReserved,
uint cIDs,
GESTURECONFIG[] pGestureConfig,
uint cbSize);
[DllImport("user32")]
public static extern bool GetGestureInfo(IntPtr hGestureInfo, ref GESTUREINFO pGestureInfo);
public static ushort GID_ROTATE_ANGLE_TO_ARGUMENT(ushort arg) => (ushort) (((double) arg + 6.2831853) / 12.5663706 * (double) ushort.MaxValue);
public static double GID_ROTATE_ANGLE_FROM_ARGUMENT(ushort arg) => (double) arg / (double) ushort.MaxValue * 4.0 * 3.14159265 - 6.2831853;
[DllImport("user32")]
public static extern bool CloseGestureInfoHandle(IntPtr hGestureInfo);
public delegate uint WindowProcDelegate(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam);
public enum DigitizerIndex
{
SM_DIGITIZER = 94, // 0x0000005E
SM_MAXIMUMTOUCHES = 95, // 0x0000005F
}
public enum TouchWindowFlag : uint
{
FineTouch = 1,
WantPalm = 2,
}
public struct GESTURENOTIFYSTRUCT
{
public uint cbSize;
public uint dwFlags;
public IntPtr hwndTarget;
public POINTS ptsLocation;
public uint dwInstanceID;
}
}
public abstract class Handler
{
private readonly IHwndWrapper _hWndWrapper;
private static List<object> _controlInUse = new List<object>();
private User32.WindowProcDelegate _windowProcDelegate;
private IntPtr _originalWindowProcId;
protected abstract bool SetHWndTouchInfo();
protected abstract uint WindowProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam);
internal static T CreateHandler<T>(IHwndWrapper hWndWrapper) where T : Handler
{
if (Handler._controlInUse.Contains(hWndWrapper.Source))
throw new Exception("Only one handler can be registered for a control.");
hWndWrapper.HandleDestroyed += (EventHandler) ((s, e) => Handler._controlInUse.Remove(s));
Handler._controlInUse.Add(hWndWrapper.Source);
return Activator.CreateInstance(typeof (T), BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod | BindingFlags.CreateInstance, (Binder) null, new object[1]
{
(object) hWndWrapper
}, Thread.CurrentThread.CurrentCulture) as T;
}
internal Handler(IHwndWrapper hWndWrapper)
{
this._hWndWrapper = hWndWrapper;
if (this._hWndWrapper.IsHandleCreated)
this.Initialize();
else
this._hWndWrapper.HandleCreated += (EventHandler) ((s, e) => this.Initialize());
}
private void Initialize()
{
if (!this.SetHWndTouchInfo())
throw new NotSupportedException("Cannot register window");
this._windowProcDelegate = new User32.WindowProcDelegate(this.WindowProcSubClass);
this._originalWindowProcId = IntPtr.Size == 4 ? User32.SubclassWindow(this._hWndWrapper.Handle, -4, this._windowProcDelegate) : User32.SubclassWindow64(this._hWndWrapper.Handle, -4, this._windowProcDelegate);
using (Graphics graphics = Graphics.FromHwnd(this._hWndWrapper.Handle))
{
this.DpiX = graphics.DpiX;
this.DpiY = graphics.DpiY;
}
this.WindowMessage += (EventHandler<WMEventArgs>) ((s, e) => {});
}
private uint WindowProcSubClass(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam)
{
this.WindowMessage((object) this, new WMEventArgs(hWnd, msg, wparam, lparam));
if (msg == 282 && this.GestureNotify != null)
{
this.GestureNotify((object) this, new GestureNotifyEventArgs(lparam));
}
else
{
uint num = this.WindowProc(hWnd, msg, wparam, lparam);
if (num != 0U)
return num;
}
return User32.CallWindowProc(this._originalWindowProcId, hWnd, msg, wparam, lparam);
}
internal IHwndWrapper HWndWrapper => this._hWndWrapper;
protected IntPtr ControlHandle => !this._hWndWrapper.IsHandleCreated ? IntPtr.Zero : this._hWndWrapper.Handle;
public float DpiX { get; private set; }
public float DpiY { get; private set; }
public event EventHandler<GestureNotifyEventArgs> GestureNotify;
internal event EventHandler<WMEventArgs> WindowMessage;
public static bool IsTouchWindows(IntPtr hWnd) => User32.IsTouchWindow(hWnd, out uint _);
public static class DigitizerCapabilities
{
public static DigitizerStatus Status => (DigitizerStatus) User32.GetDigitizerCapabilities(User32.DigitizerIndex.SM_DIGITIZER);
public static int MaxumumTouches => User32.GetDigitizerCapabilities(User32.DigitizerIndex.SM_MAXIMUMTOUCHES);
public static bool IsIntegratedTouch => (Handler.DigitizerCapabilities.Status & DigitizerStatus.IntegratedTouch) != (DigitizerStatus) 0;
public static bool IsExternalTouch => (Handler.DigitizerCapabilities.Status & DigitizerStatus.ExternalTouch) != (DigitizerStatus) 0;
public static bool IsIntegratedPan => (Handler.DigitizerCapabilities.Status & DigitizerStatus.IntegratedPan) != (DigitizerStatus) 0;
public static bool IsExternalPan => (Handler.DigitizerCapabilities.Status & DigitizerStatus.ExternalPan) != (DigitizerStatus) 0;
public static bool IsMultiInput => (Handler.DigitizerCapabilities.Status & DigitizerStatus.MultiInput) != (DigitizerStatus) 0;
public static bool IsStackReady => (Handler.DigitizerCapabilities.Status & DigitizerStatus.StackReady) != (DigitizerStatus) 0;
public static bool IsMultiTouchReady => (Handler.DigitizerCapabilities.Status & (DigitizerStatus.MultiInput | DigitizerStatus.StackReady)) != (DigitizerStatus) 0;
}
}
public class GestureHandler : Handler
{
private static readonly EventHandler<GestureEventArgs> _emptyFunc = (EventHandler<GestureEventArgs>)((s, e) => { });
private readonly Dictionary<uint, EventHandler<GestureEventArgs>> _eventMap = new Dictionary<uint, EventHandler<GestureEventArgs>>()
{
{
GestureHandler.EventMapID.Begin,
GestureHandler._emptyFunc
},
{
GestureHandler.EventMapID.End,
GestureHandler._emptyFunc
},
{
GestureHandler.EventMapID.PanBegin,
GestureHandler._emptyFunc
},
{
GestureHandler.EventMapID.Pan,
GestureHandler._emptyFunc
},
{
GestureHandler.EventMapID.PanEnd,
GestureHandler._emptyFunc
},
{
GestureHandler.EventMapID.PressAndTap,
GestureHandler._emptyFunc
},
{
GestureHandler.EventMapID.RotateBegin,
GestureHandler._emptyFunc
},
{
GestureHandler.EventMapID.Rotate,
GestureHandler._emptyFunc
},
{
GestureHandler.EventMapID.RotateEnd,
GestureHandler._emptyFunc
},
{
GestureHandler.EventMapID.TwoFingerTap,
GestureHandler._emptyFunc
},
{
GestureHandler.EventMapID.ZoomBegin,
GestureHandler._emptyFunc
},
{
GestureHandler.EventMapID.Zoom,
GestureHandler._emptyFunc
},
{
GestureHandler.EventMapID.ZoomEnd,
GestureHandler._emptyFunc
}
};
private static uint MapWM2EventId(uint dwID, uint dwFlags) => (uint)(((int)dwID << 3) + (dwID == 6U || dwID == 7U || (dwID == 1U || dwID == 2U) ? 0 : (int)dwFlags & 5));
internal GestureHandler(IHwndWrapper hWndWrapper)
: base(hWndWrapper)
{
}
protected override bool SetHWndTouchInfo()
{
var gestureConfig = new GESTURECONFIG[]
{
new GESTURECONFIG() { dwID = 3U, dwWant = 1U, dwBlock = 0U },
new GESTURECONFIG() { dwID = 4U, dwWant = 1U, dwBlock = 0U },
new GESTURECONFIG() { dwID = 5U, dwWant = 1U, dwBlock = 0U },
new GESTURECONFIG() { dwID = 6U, dwWant = 1U, dwBlock = 0U }
};
var result = User32.SetGestureConfig(
this.ControlHandle,
0U,
(uint)gestureConfig.Length,
gestureConfig,
(uint)Marshal.SizeOf(typeof(GESTURECONFIG)));
return result;
}
internal GestureEventArgs LastBeginEvent { get; set; }
internal GestureEventArgs LastEvent { get; set; }
public event EventHandler<GestureEventArgs> Begin
{
add => this._eventMap[GestureHandler.EventMapID.Begin] += value;
remove => this._eventMap[GestureHandler.EventMapID.Begin] -= value;
}
public event EventHandler<GestureEventArgs> End
{
add => this._eventMap[GestureHandler.EventMapID.End] += value;
remove => this._eventMap[GestureHandler.EventMapID.End] -= value;
}
public event EventHandler<GestureEventArgs> PanBegin
{
add => this._eventMap[GestureHandler.EventMapID.PanBegin] += value;
remove => this._eventMap[GestureHandler.EventMapID.PanBegin] -= value;
}
public event EventHandler<GestureEventArgs> Pan
{
add => this._eventMap[GestureHandler.EventMapID.Pan] += value;
remove => this._eventMap[GestureHandler.EventMapID.Pan] -= value;
}
public event EventHandler<GestureEventArgs> PanEnd
{
add => this._eventMap[GestureHandler.EventMapID.PanEnd] += value;
remove => this._eventMap[GestureHandler.EventMapID.PanEnd] -= value;
}
public event EventHandler<GestureEventArgs> PressAndTap
{
add => this._eventMap[GestureHandler.EventMapID.PressAndTap] += value;
remove => this._eventMap[GestureHandler.EventMapID.PressAndTap] -= value;
}
public event EventHandler<GestureEventArgs> RotateBegin
{
add => this._eventMap[GestureHandler.EventMapID.RotateBegin] += value;
remove => this._eventMap[GestureHandler.EventMapID.RotateBegin] -= value;
}
public event EventHandler<GestureEventArgs> Rotate
{
add => this._eventMap[GestureHandler.EventMapID.Rotate] += value;
remove => this._eventMap[GestureHandler.EventMapID.Rotate] -= value;
}
public event EventHandler<GestureEventArgs> RotateEnd
{
add => this._eventMap[GestureHandler.EventMapID.RotateEnd] += value;
remove => this._eventMap[GestureHandler.EventMapID.RotateEnd] -= value;
}
public event EventHandler<GestureEventArgs> TwoFingerTap
{
add => this._eventMap[GestureHandler.EventMapID.TwoFingerTap] += value;
remove => this._eventMap[GestureHandler.EventMapID.TwoFingerTap] -= value;
}
public event EventHandler<GestureEventArgs> ZoomBegin
{
add => this._eventMap[GestureHandler.EventMapID.ZoomBegin] += value;
remove => this._eventMap[GestureHandler.EventMapID.ZoomBegin] -= value;
}
public event EventHandler<GestureEventArgs> Zoom
{
add => this._eventMap[GestureHandler.EventMapID.Zoom] += value;
remove => this._eventMap[GestureHandler.EventMapID.Zoom] -= value;
}
public event EventHandler<GestureEventArgs> ZoomEnd
{
add => this._eventMap[GestureHandler.EventMapID.ZoomEnd] += value;
remove => this._eventMap[GestureHandler.EventMapID.ZoomEnd] -= value;
}
protected override uint WindowProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam)
{
if (msg != 281)
{
return 0;
}
GESTUREINFO gestureinfo = new GESTUREINFO()
{
cbSize = (uint)Marshal.SizeOf(typeof(GESTUREINFO))
};
GestureEventArgs e = User32.GetGestureInfo(lParam, ref gestureinfo) ? new GestureEventArgs(this, ref gestureinfo) : throw new Exception("Cannot get gesture information");
try
{
var mapWM2EventId = GestureHandler.MapWM2EventId(gestureinfo.dwID, gestureinfo.dwFlags);
this._eventMap[mapWM2EventId]((object)this, e);
var message = string.Format(
"time='{0}' mapWM2EventId='{1}'",
DateTime.Now.ToLongTimeString(),
mapWM2EventId
);
System.Diagnostics.Trace.WriteLine(message);
}
catch (ArgumentOutOfRangeException ex)
{
}
this.LastEvent = e;
if (e.IsBegin)
this.LastBeginEvent = e;
if (gestureinfo.dwID != 6U && gestureinfo.dwID != 7U)
return 0;
User32.CloseGestureInfoHandle(lParam);
return 1;
}
private static class EventMapID
{
public static readonly uint Begin = GestureHandler.MapWM2EventId(1U, 0U);
public static readonly uint End = GestureHandler.MapWM2EventId(2U, 0U);
public static readonly uint PanBegin = GestureHandler.MapWM2EventId(4U, 1U);
public static readonly uint Pan = GestureHandler.MapWM2EventId(4U, 0U);
public static readonly uint PanEnd = GestureHandler.MapWM2EventId(4U, 4U);
public static readonly uint PressAndTap = GestureHandler.MapWM2EventId(7U, 0U);
public static readonly uint RotateBegin = GestureHandler.MapWM2EventId(5U, 1U);
public static readonly uint Rotate = GestureHandler.MapWM2EventId(5U, 0U);
public static readonly uint RotateEnd = GestureHandler.MapWM2EventId(5U, 4U);
public static readonly uint TwoFingerTap = GestureHandler.MapWM2EventId(6U, 0U);
public static readonly uint ZoomBegin = GestureHandler.MapWM2EventId(3U, 1U);
public static readonly uint Zoom = GestureHandler.MapWM2EventId(3U, 0U);
public static readonly uint ZoomEnd = GestureHandler.MapWM2EventId(3U, 4U);
}
}
public class GestureEventArgs : EventArgs
{
private readonly uint _dwFlags;
internal GestureEventArgs(GestureHandler handler, ref GESTUREINFO gestureInfo)
{
this._dwFlags = gestureInfo.dwFlags;
this.GestureId = gestureInfo.dwID;
this.GestureArguments = gestureInfo.ullArguments;
this.LastEvent = handler.LastEvent;
this.LastBeginEvent = handler.LastBeginEvent;
this.DecodeGesture(handler.HWndWrapper, ref gestureInfo);
if (!this.IsBegin)
return;
this.LastBeginEvent = (GestureEventArgs) null;
this.LastEvent = (GestureEventArgs) null;
}
private void DecodeGesture(IHwndWrapper hWndWrapper, ref GESTUREINFO gestureInfo)
{
this.Location = hWndWrapper.PointToClient(new Point((int) gestureInfo.ptsLocation.x, (int) gestureInfo.ptsLocation.y));
this.Center = this.Location;
switch (this.GestureId)
{
case 3:
Point point = this.IsBegin ? this.Location : this.LastBeginEvent.Location;
this.Center = new Point((this.Location.X + point.X) / 2, (this.Location.Y + point.Y) / 2);
this.ZoomFactor = this.IsBegin ? 1.0 : (double) gestureInfo.ullArguments / (double) this.LastEvent.GestureArguments;
break;
case 4:
this.PanTranslation = this.IsBegin ? new Size(0, 0) : new Size(this.Location.X - this.LastEvent.Location.X, this.Location.Y - this.LastEvent.Location.Y);
int number = User32.HiDWord((long) gestureInfo.ullArguments);
this.PanVelocity = new Size((int) User32.LoWord(number), (int) User32.HiWord(number));
break;
case 5:
ushort num = this.IsBegin ? (ushort) 0 : (ushort) this.LastEvent.GestureArguments;
this.RotateAngle = User32.GID_ROTATE_ANGLE_FROM_ARGUMENT((ushort) (gestureInfo.ullArguments - (ulong) num));
break;
}
}
public uint GestureId { get; private set; }
public ulong GestureArguments { get; private set; }
public Point Location { get; private set; }
public bool IsBegin => ((int) this._dwFlags & 1) != 0;
public bool IsEnd => ((int) this._dwFlags & 4) != 0;
public bool IsInertia => ((int) this._dwFlags & 2) != 0;
public double RotateAngle { get; private set; }
public Point Center { get; private set; }
public double ZoomFactor { get; private set; }
public Size PanTranslation { get; private set; }
public Size PanVelocity { get; private set; }
public GestureEventArgs LastBeginEvent { get; internal set; }
public GestureEventArgs LastEvent { get; internal set; }
}
main event in GestureHandler class:
`
protected static uint WindowProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam)
{
if (msg != 281)
return 0;
GESTUREINFO gestureinfo = new GESTUREINFO()
{
cbSize = (uint) Marshal.SizeOf(typeof (GESTUREINFO))
};
GestureEventArgs e = User32.GetGestureInfo(lParam, ref gestureinfo) ? new GestureEventArgs(this, ref gestureinfo) : throw new Exception(βCannot get gesture informationβ);
β¦
this.LastEvent = e;
if (e.IsBegin)
this.LastBeginEvent = e;
if (gestureinfo.dwID != 6U && gestureinfo.dwID != 7U)
return 0;
User32.CloseGestureInfoHandle(lParam);
return 1;}
`
initialization in GestureHandler class:
private bool SetGesturesDesired()
{
var gestureConfig = new GESTURECONFIG
{
new GESTURECONFIG() { dwID = 3U, dwWant = 1U, dwBlock = 0U },
new GESTURECONFIG() { dwID = 4U, dwWant = 1U, dwBlock = 0U },
new GESTURECONFIG() { dwID = 5U, dwWant = 1U, dwBlock = 0U },
new GESTURECONFIG() { dwID = 6U, dwWant = 1U, dwBlock = 0U }
};
var result = User32.SetGestureConfig(
this.ControlHandle,
0U,
(uint)gestureConfig.Length,
gestureConfig,
(uint)Marshal.SizeOf(typeof(GESTURECONFIG)));
return result;
}
private void Initialize()
{
var mainWindowHandle = Rhino.RhinoApp.MainWindowHandle();
if (!SetGesturesDesired())
throw new NotSupportedException(βCannot register windowβ);
this._windowProcDelegate = new User32.WindowProcDelegate(this.WindowProcSubClass);
this._originalWindowProcId = IntPtr.Size == 4 ? User32.SubclassWindow(mainWindowHandle, -4, this._windowProcDelegate) : User32.SubclassWindow64(mainWindowHandle, -4, this._windowProcDelegate);
using (Graphics graphics = Graphics.FromHwnd(mainWindowHandle))
{
this.DpiX = graphics.DpiX;
this.DpiY = graphics.DpiY;
}
this.WindowMessage += (EventHandler) ((s, e) => {});
}
I have tried the same gestures on the same pc with Rhinoceros 5.14 compared to Rhinoceros 7.16 and the results are reported below:
Rhinoceros 7.16 one zoom gesture (down index and thumb, drag index and thumb closing their distance, up index and thumb)
03/06/2022 11:39:40.120 DEBUG: time=β11:39:40β mapWM2EventId=β8β
03/06/2022 11:39:40.581 DEBUG: time=β11:39:40β mapWM2EventId=β16β
Rhinoceros 7.16 one rotate gesture (down index and thumb, rotate index and thumb reciprocally, up index and thumb)
03/06/2022 11:40:10.810 DEBUG: time=β11:40:10β mapWM2EventId=β8β
03/06/2022 11:40:11.567 DEBUG: time=β11:40:11β mapWM2EventId=β16β
Rhinoceros 7.16 one pan gesture (down index and medium, drag index and medium equally, up index and medium)
03/06/2022 11:40:36.678 DEBUG: time=β11:40:36β mapWM2EventId=β8β
03/06/2022 11:40:37.103 DEBUG: time=β11:40:37β mapWM2EventId=β16β
Rhinoceros 5.14 one zoom gesture
03/06/2022 10:48:26.666 DEBUG: time=β10:48:26β mapWM2EventId=β8β
03/06/2022 10:48:26.666 DEBUG: time=β10:48:26β mapWM2EventId=β25β
03/06/2022 10:48:26.666 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.681 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.681 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.744 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.759 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.759 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.759 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.775 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.806 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.806 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.806 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.806 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.806 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.837 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.837 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.837 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.837 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.853 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.853 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.853 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.853 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.884 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.884 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.884 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.884 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.900 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.900 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.900 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.900 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.916 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.932 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.932 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.932 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.962 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.962 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.978 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.978 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.994 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.994 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.994 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:26.994 DEBUG: time=β10:48:26β mapWM2EventId=β24β
03/06/2022 10:48:27.009 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.025 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.025 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.025 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.040 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.040 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.040 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.040 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.072 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.072 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.072 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.072 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.103 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.119 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.119 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.150 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.150 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.181 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.197 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.212 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.228 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.259 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.306 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.353 DEBUG: time=β10:48:27β mapWM2EventId=β24β
03/06/2022 10:48:27.385 DEBUG: time=β10:48:27β mapWM2EventId=β28β
03/06/2022 10:48:27.385 DEBUG: time=β10:48:27β mapWM2EventId=β16β
Rhinoceros 5.14 one rotate gesture
03/06/2022 10:49:56.172 DEBUG: time=β10:49:56β mapWM2EventId=β8β
03/06/2022 10:49:56.204 DEBUG: time=β10:49:56β mapWM2EventId=β41β
03/06/2022 10:49:56.250 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.282 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.329 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.360 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.406 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.438 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.454 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.484 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.516 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.532 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.563 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.579 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.609 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.625 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.656 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.672 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.703 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.719 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.735 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.766 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.797 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.813 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.844 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.860 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.891 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.906 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.937 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.953 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:56.984 DEBUG: time=β10:49:56β mapWM2EventId=β40β
03/06/2022 10:49:57.001 DEBUG: time=β10:49:57β mapWM2EventId=β40β
03/06/2022 10:49:57.032 DEBUG: time=β10:49:57β mapWM2EventId=β40β
03/06/2022 10:49:57.047 DEBUG: time=β10:49:57β mapWM2EventId=β40β
03/06/2022 10:49:57.079 DEBUG: time=β10:49:57β mapWM2EventId=β40β
03/06/2022 10:49:57.094 DEBUG: time=β10:49:57β mapWM2EventId=β40β
03/06/2022 10:49:57.125 DEBUG: time=β10:49:57β mapWM2EventId=β40β
03/06/2022 10:49:57.157 DEBUG: time=β10:49:57β mapWM2EventId=β40β
03/06/2022 10:49:57.172 DEBUG: time=β10:49:57β mapWM2EventId=β40β
03/06/2022 10:49:57.203 DEBUG: time=β10:49:57β mapWM2EventId=β40β
03/06/2022 10:49:57.219 DEBUG: time=β10:49:57β mapWM2EventId=β40β
03/06/2022 10:49:57.250 DEBUG: time=β10:49:57β mapWM2EventId=β40β
03/06/2022 10:49:57.266 DEBUG: time=β10:49:57β mapWM2EventId=β40β
03/06/2022 10:49:57.313 DEBUG: time=β10:49:57β mapWM2EventId=β40β
03/06/2022 10:49:57.344 DEBUG: time=β10:49:57β mapWM2EventId=β44β
03/06/2022 10:49:57.344 DEBUG: time=β10:49:57β mapWM2EventId=β16β
Rhinoceros 5.14 one pan gesture
03/06/2022 11:11:41.307 DEBUG: time=β11:11:41β mapWM2EventId=β8β
03/06/2022 11:11:41.314 DEBUG: time=β11:11:41β mapWM2EventId=β33β
03/06/2022 11:11:41.324 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.337 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.366 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.382 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.413 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.432 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.437 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.443 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.460 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.466 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.485 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.491 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.515 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.520 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.539 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.545 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.557 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.563 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.576 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.581 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.607 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.622 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.627 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.644 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.656 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.667 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.674 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.692 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.698 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.716 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.765 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.796 DEBUG: time=β11:11:41β mapWM2EventId=β32β
03/06/2022 11:11:41.815 DEBUG: time=β11:11:41β mapWM2EventId=β36β
03/06/2022 11:11:41.820 DEBUG: time=β11:11:41β mapWM2EventId=β16β