internal void HandleEvent(WebClient sender, WebMouseEvent e) { //Synchronize lock (m_Events) { m_Events.Add(e); } //If we need to update if (m_Updates.Count <= 12 && (m_SendClicks && e.MouseButtons != 0 && m_SendRightClick && e.MouseButtons.HasFlag(WebMouseButtons.Right)) || (m_SendScrollWheel && e.ScrollDelta != 0)) { Signal(/*true*/); } else if (m_Updates.Count > 13) { JITEvents(); } }
/// <summary> /// Mice move a lot, this algorithm helps to eliminate events in the history which make unnecessary movement or that save bandwidth /// </summary> internal void JITEvents(bool force) { //Do not JIT Too Soon or when not needed if (m_InJIT && !force && m_Events.Count <= 12 || (DateTime.Now - m_LastJitTime) <= m_UpdateThreshold - m_Share.Owner.Server.Wake) { return; } WebMouseEvent currentEvent = m_Events.FirstOrDefault(); if (currentEvent == null) { return; } m_InJIT = true; m_LastJitTime = DateTime.Now; var events = Events.OrderBy((e) => e.RecievedOn); Clear(); int X = 0, Y = 0, Z = 0; var temp = default(IOrderedEnumerable <WebMouseEvent>); List <WebMouseEvent> newEvents = new List <WebMouseEvent>(); //Compress based on pulse if (currentEvent.PulseMS > 0) { //Take the MouseEvents which were within the pulseTime var compress = events.TakeWhile((e) => (e.RecievedOn - currentEvent.RecievedOn).TotalMilliseconds <= currentEvent.PulseMS); if (compress.Count() > 0) { //make compressed frames consisting of all the events which can be compressed List <WebMouseEvent> compressed = new List <WebMouseEvent>(); //compress them compress.Where((c) => !c.JITEvent).ToList().ForEach((c) => { //Ensure we get all clicks and deltas if (c.MouseButtons != 0 || c.ScrollDelta != 0) { compressed.Add(c); c.JITEvent = true; return; } List <WebMouseEvent> movements = new List <WebMouseEvent>(); //combined x,y,z movements within a few of the last if ((X - c.X) + (Y - c.Y) > 5 || c.Z != 0 || compressed.Count == 0) { X = c.X; Y = c.Y; Z = c.Z; c.JITEvent = true; movements.Add(c); return; } compressed.Zip(movements, (a, b) => { return(a); }); }); } } //Other compression bool significantCompression = false; //Compress the remaining events with the main Events temp = Events.OrderBy((e) => e.RecievedOn); Clear(); events.Zip(temp, (a, b) => { if (!b.JITEvent) { return(b = a); } else { return(a = b); } }); //Add the compressed events back into the stack lock (m_Events) { m_Events.AddRange(events); } //If we made any real progress time to Signal if (significantCompression) { Signal(); } m_InJIT = false; }