internal void OnMouseInputReceived(object sender, Model.Input.MouseInput e) { // do not forward mouse-move events to extensions (they are unecessary, and it wastes cpu) // TODO: consider dispatching on a 'tile-snapped' basis, if 'tile under cursor' would change, dispatch a single update if (e.WM == WinAPI.WM.MOUSEMOVE) { return; } // TODO: consider queued mouse input instead of spawning a new task fro every event Task.Factory.StartNew(delegate() { // translate input var client = GetClientByHandle(e.WindowHandle) ?? GetActiveClient(); // dispatch to extensions _extensions.Values.ToList() .ForEach(ext => { try { var L_e = new Extensibility.Input.MouseEventArgs { Client = client, Handled = e.Handled, Time = e.Time, IsAbsolute = e.IsAbsolute, X = e.Point.X, Y = e.Point.Y, WM = e.WM, Flags = e.Flags, }; ext.Bridge.Mouse.OnInputReceived(client, L_e); e.Handled = e.Handled || L_e.Handled; } catch (Exception ex) { ex.Log(); } }); }, TaskCreationOptions.PreferFairness); }
private void OnMouseInputReceived(Model.Input.MouseInput mouseInput) { //bool useTIQ = true; //TODO: this needs test and reverification of semantics/rules because it does not appear to allow mouse broadcast // translate message and track MK changes //WinAPI.WM wm = WinAPI.WM.USER; //bool isButtonUpEvent = false; // strip 'absolute' flag from mask and process result // denormalize coordinates to local //WinAPI.Windows.RECT clientRect; //WinAPI.Windows.GetClientRect(WindowHandle, out clientRect); //int lPointX = (int)(((double)clientRect.Width / (double)65536) * mouseInput.Point.X); //int lPointY = (int)(((double)clientRect.Height / (double)65536) * mouseInput.Point.Y); // TODO: the X and Y coordinates here should be "relative" -- might want to dig up the old "mrel" code -- it doesnt matter if we xlate coordinates to client area/pixels or not InputManager.Enqueue(mouseInput); /* superceded by InputManager (above) * // no target window? can't use * if (WindowHandle == IntPtr.Zero) * { * ("NoWindowHandle Failed OnMouseInputReceived, Input Loss for " + this.DisplayName).Log(); * return; * } * * lock (_tiqLock) * { * if (useTIQ) * { * // can't resolve TIQ? can't use * IntPtr windowInputQueue = WindowInputQueue; * if (windowInputQueue == IntPtr.Zero) * { * ("NoWindowInputQueue Failed OnMouseInputReceived, Input Loss for " + this.DisplayName).Log(); * useTIQ = false; * } * else * { * // resolve TIQ * IntPtr foregroundWindowHandle; * IntPtr foregroundInputQueue; * if (!TryResolveTIQ(out foregroundInputQueue, out foregroundWindowHandle, DateTime.Now.AddMilliseconds(300).Ticks)) * { * ("TryResolveTIQ Failed OnMouseInputReceived, Input Loss for " + this.DisplayName).Log(); * useTIQ = false; * } * else * { * ActionViaTIQ(() => * { * //WinAPI.SendInputApi.MouseActionViaSendInput(mouseInput.Flags, mouseInput.Time, (int)mouseInput.Point.X, (int)mouseInput.Point.Y, mouseInput.MouseData); * MouseActionViaPostMessage((int)mouseInput.Point.X, (int)mouseInput.Point.Y, lPointX, lPointY, wm, mouseInput.MouseData, isButtonUpEvent); * }, * foregroundInputQueue, "OnMouseInputReceived"); * } * } * } * * if (!useTIQ) * { * // dispatch * MouseActionViaSendMessage((int)mouseInput.Point.X, (int)mouseInput.Point.Y, lPointX, lPointY, wm, mouseInput.MouseData, isButtonUpEvent); * } * } */ }
private void OnMouseInputReceived(Model.Input.MouseInput mouseInput) { bool useVIQ = (Win32.SendInputApi.MouseEventFlags.MOUSEEVENTF_ABSOLUTE == (mouseInput.Flags & Win32.SendInputApi.MouseEventFlags.MOUSEEVENTF_ABSOLUTE)); // translate message and track MK changes Win32.WM wm = Win32.WM.USER; bool isButtonUpEvent = false; ushort wheelDelta = 0; Win32.SendInputApi.MouseEventFlags lFlags = useVIQ ? mouseInput.Flags ^ Win32.SendInputApi.MouseEventFlags.MOUSEEVENTF_ABSOLUTE : mouseInput.Flags; switch (lFlags) { case Win32.SendInputApi.MouseEventFlags.MOUSEEVENTF_MOVE: wm = Win32.WM.MOUSEMOVE; break; case Win32.SendInputApi.MouseEventFlags.MOUSEEVENTF_LEFTDOWN: wm = Win32.WM.LBUTTONDOWN; CurrentMK |= Win32.Windows.MK.MK_LBUTTON; break; case Win32.SendInputApi.MouseEventFlags.MOUSEEVENTF_LEFTUP: wm = Win32.WM.LBUTTONUP; isButtonUpEvent = true; CurrentMK = (CurrentMK | Win32.Windows.MK.MK_LBUTTON) ^ Win32.Windows.MK.MK_LBUTTON; break; case Win32.SendInputApi.MouseEventFlags.MOUSEEVENTF_RIGHTDOWN: wm = Win32.WM.RBUTTONDOWN; CurrentMK |= Win32.Windows.MK.MK_RBUTTON; break; case Win32.SendInputApi.MouseEventFlags.MOUSEEVENTF_RIGHTUP: wm = Win32.WM.RBUTTONUP; CurrentMK = (CurrentMK | Win32.Windows.MK.MK_RBUTTON) ^ Win32.Windows.MK.MK_RBUTTON; isButtonUpEvent = true; break; case Win32.SendInputApi.MouseEventFlags.MOUSEEVENTF_MIDDLEDOWN: wm = Win32.WM.MBUTTONDOWN; CurrentMK |= Win32.Windows.MK.MK_MBUTTON; break; case Win32.SendInputApi.MouseEventFlags.MOUSEEVENTF_MIDDLEUP: wm = Win32.WM.MBUTTONUP; CurrentMK = (CurrentMK | Win32.Windows.MK.MK_MBUTTON) ^ Win32.Windows.MK.MK_MBUTTON; isButtonUpEvent = true; break; case Win32.SendInputApi.MouseEventFlags.MOUSEEVENTF_XDOWN: wm = Win32.WM.XBUTTONDOWN; { var xbutton = Win32.MACROS.GET_XBUTTON_WPARAM(mouseInput.MouseData); wheelDelta = (ushort)xbutton; switch (xbutton) { case Win32.MACROS.XBUTTONS.XBUTTON1: CurrentMK |= Win32.Windows.MK.MK_XBUTTON1; break; case Win32.MACROS.XBUTTONS.XBUTTON2: CurrentMK |= Win32.Windows.MK.MK_XBUTTON2; break; default: Debug.WriteLine("UnsupportedButtonDown in MouseData(" + xbutton + ") for " + this.DisplayName); break; } } break; case Win32.SendInputApi.MouseEventFlags.MOUSEEVENTF_XUP: wm = Win32.WM.XBUTTONUP; isButtonUpEvent = true; { var xbutton = Win32.MACROS.GET_XBUTTON_WPARAM(mouseInput.MouseData); wheelDelta = (ushort)xbutton; switch (xbutton) { case Win32.MACROS.XBUTTONS.XBUTTON1: CurrentMK = (CurrentMK | Win32.Windows.MK.MK_XBUTTON1) ^ Win32.Windows.MK.MK_XBUTTON1; break; case Win32.MACROS.XBUTTONS.XBUTTON2: CurrentMK = (CurrentMK | Win32.Windows.MK.MK_XBUTTON2) ^ Win32.Windows.MK.MK_XBUTTON2; break; default: Debug.WriteLine("UnsupportedButtonUp in MouseData(" + xbutton + ") for " + this.DisplayName); break; } } break; case Win32.SendInputApi.MouseEventFlags.MOUSEEVENTF_WHEEL: wheelDelta = Win32.MACROS.HIWORD(mouseInput.MouseData); wm = Win32.WM.MOUSEWHEEL; break; default: return; } mouseInput.MouseData = Win32.MACROS.MAKEWPARAM((ushort)CurrentMK, wheelDelta); // only use VIQ for "mouse clone" events if (!useVIQ) { Win32.SendInputApi.SendInputViaMSParams(mouseInput.Flags, mouseInput.Time, (int)mouseInput.Point.X, (int)mouseInput.Point.Y, mouseInput.MouseData); return; } // no target window? can't use if (WindowHandle == IntPtr.Zero) { Debug.WriteLine("NoWindowHandle Failed OnMouseInputReceived, Input Loss for " + this.DisplayName); return; } // can't resolve VIQ? can't use IntPtr windowInputQueue = WindowInputQueue; if (windowInputQueue == IntPtr.Zero) { Debug.WriteLine("NoWindowInputQueue Failed OnMouseInputReceived, Input Loss for " + this.DisplayName); return; } // denormalize coordinates Win32.Windows.RECT clientRect; Win32.Windows.GetClientRect(WindowHandle, out clientRect); int lPointX = (int)(((double)clientRect.Width / (double)65536) * mouseInput.Point.X); int lPointY = (int)(((double)clientRect.Height / (double)65536) * mouseInput.Point.Y); // prep action Action action = () => { Debug.WriteLine("MouseVIQAction for " + this.DisplayName); OnMouseEvent_Action((int)mouseInput.Point.X, (int)mouseInput.Point.Y, lPointX, lPointY, wm, mouseInput.MouseData, isButtonUpEvent); }; // resolve VIQ IntPtr foregroundWindowHandle; IntPtr foregroundInputQueue; if (!TryResolveViq(out foregroundInputQueue, out foregroundWindowHandle, DateTime.Now.AddMilliseconds(1000).Ticks)) { Debug.WriteLine("TryResolveVIQ Failed OnMouseInputReceived, Input Loss for " + this.DisplayName); return; } ActionViaViq(action, foregroundInputQueue, "OnMouseInputReceived"); }