Merge pull request #66 from evilC/hotfix/issue-65

Fix #65
This commit is contained in:
Clive Galway 2020-05-14 17:21:35 +01:00 committed by GitHub
commit bb5cdb472a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 162 additions and 149 deletions

View File

@ -263,6 +263,7 @@ namespace AutoHotInterception
public void SubscribeMouseMoveAbsolute(int id, bool block, dynamic callback, bool concurrent = false) public void SubscribeMouseMoveAbsolute(int id, bool block, dynamic callback, bool concurrent = false)
{ {
HelperFunctions.IsValidDeviceId(true, id); HelperFunctions.IsValidDeviceId(true, id);
SetFilterState(false);
_mouseMoveAbsoluteMappings[id] = new MappingOptions _mouseMoveAbsoluteMappings[id] = new MappingOptions
{Block = block, Concurrent = concurrent, Callback = callback}; {Block = block, Concurrent = concurrent, Callback = callback};
@ -284,9 +285,13 @@ namespace AutoHotInterception
public void UnsubscribeMouseMoveAbsolute(int id) public void UnsubscribeMouseMoveAbsolute(int id)
{ {
HelperFunctions.IsValidDeviceId(true, id); HelperFunctions.IsValidDeviceId(true, id);
SetFilterState(false);
if (_mouseMoveAbsoluteMappings.TryRemove(id, out _)) if (_mouseMoveAbsoluteMappings.TryRemove(id, out _))
if (!DeviceHasBindings(id)) if (!DeviceHasBindings(id))
SetDeviceFilterState(id, false); SetDeviceFilterState(id, false);
SetFilterState(true);
SetThreadState(true);
} }
//Shorthand for SubscribeMouseMoveRelative //Shorthand for SubscribeMouseMoveRelative
@ -332,6 +337,7 @@ namespace AutoHotInterception
public void UnsubscribeMouseMoveRelative(int id) public void UnsubscribeMouseMoveRelative(int id)
{ {
HelperFunctions.IsValidDeviceId(true, id); HelperFunctions.IsValidDeviceId(true, id);
SetFilterState(false);
if (_mouseMoveRelativeMappings.TryRemove(id, out _)) if (_mouseMoveRelativeMappings.TryRemove(id, out _))
if (!DeviceHasBindings(id)) if (!DeviceHasBindings(id))
@ -680,182 +686,188 @@ namespace AutoHotInterception
while (ManagedWrapper.Receive(_deviceContext, i, ref stroke, 1) > 0) while (ManagedWrapper.Receive(_deviceContext, i, ref stroke, 1) > 0)
{ {
if (!isMonitoredMouse) continue;
var moveRemoved = false; var moveRemoved = false;
var hasMove = false; var hasMove = false;
var x = stroke.mouse.x; if (isMonitoredMouse)
var y = stroke.mouse.y; {
//Debug.WriteLine($"AHK| Stroke Seen. State = {stroke.mouse.state}, Flags = {stroke.mouse.flags}, x={x}, y={y}"); var x = stroke.mouse.x;
var y = stroke.mouse.y;
//Debug.WriteLine($"AHK| Stroke Seen. State = {stroke.mouse.state}, Flags = {stroke.mouse.flags}, x={x}, y={y}");
// Process mouse movement // Process mouse movement
var isAbsolute = (stroke.mouse.flags & (ushort) ManagedWrapper.MouseFlag.MouseMoveAbsolute) == var isAbsolute = (stroke.mouse.flags & (ushort) ManagedWrapper.MouseFlag.MouseMoveAbsolute) ==
(ushort) ManagedWrapper.MouseFlag.MouseMoveAbsolute; (ushort) ManagedWrapper.MouseFlag.MouseMoveAbsolute;
//Determine whether or not to report mouse movement. //Determine whether or not to report mouse movement.
// For Relative mode, this is fairly simple - if x and y are both 0, no movement was reported (Since a real mouse never reports x=0/y=0) // For Relative mode, this is fairly simple - if x and y are both 0, no movement was reported (Since a real mouse never reports x=0/y=0)
// For Absolute mode, x=0/y=0 is reported, but we should limit this to only reporting once... // For Absolute mode, x=0/y=0 is reported, but we should limit this to only reporting once...
// ... so when x=0/y=0 is seen in absolute mode, set the flag _absoluteMode00Reported to true and allow it to be reported... // ... so when x=0/y=0 is seen in absolute mode, set the flag _absoluteMode00Reported to true and allow it to be reported...
// then on subsequent reports of x=0/y=0 for absolute mode, if _absoluteMode00Reported is already true, then do not report movement... // then on subsequent reports of x=0/y=0 for absolute mode, if _absoluteMode00Reported is already true, then do not report movement...
// ... In absolute mode, when x!=0/y!=0 is received, clear the _absoluteMode00Reported flag // ... In absolute mode, when x!=0/y!=0 is received, clear the _absoluteMode00Reported flag
if (isAbsolute)
{
if (x == 0 && y == 0)
{
if (!_absoluteMode00Reported)
{
hasMove = true;
_absoluteMode00Reported = true;
}
else
{
hasMove = false;
}
}
else
{
hasMove = true;
_absoluteMode00Reported = false;
}
}
else
{
hasMove = (x != 0 || y != 0);
}
if (hasMove)
{
// Process Absolute Mouse Move
if (isAbsolute) if (isAbsolute)
{ {
if (_mouseMoveAbsoluteMappings.ContainsKey(i)) if (x == 0 && y == 0)
{ {
var mapping = _mouseMoveAbsoluteMappings[i]; if (!_absoluteMode00Reported)
hasSubscription = true;
//var debugStr = $"AHK| Mouse stroke has absolute move of {x}, {y}...";
if (mapping.Concurrent)
ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(x, y));
else if (_workerThreads.ContainsKey(i) && _workerThreads[i].ContainsKey(7))
_workerThreads[i][7]?.Actions.Add(() => mapping.Callback(x, y));
if (mapping.Block)
{ {
moveRemoved = true; hasMove = true;
stroke.mouse.x = 0; _absoluteMode00Reported = true;
stroke.mouse.y = 0;
//debugStr += "Blocking";
} }
else else
{ {
//debugStr += "Not Blocking"; hasMove = false;
} }
//Debug.WriteLine(debugStr); }
else
{
hasMove = true;
_absoluteMode00Reported = false;
} }
} }
// Process Relative Mouse Move
//else if ((stroke.mouse.flags & (ushort) ManagedWrapper.MouseFlag.MouseMoveRelative) == (ushort) ManagedWrapper.MouseFlag.MouseMoveRelative) / flag is 0, so always true!
else else
{ {
if (_mouseMoveRelativeMappings.ContainsKey(i)) hasMove = (x != 0 || y != 0);
}
if (hasMove)
{
// Process Absolute Mouse Move
if (isAbsolute)
{ {
var mapping = _mouseMoveRelativeMappings[i]; if (_mouseMoveAbsoluteMappings.ContainsKey(i))
{
var mapping = _mouseMoveAbsoluteMappings[i];
hasSubscription = true;
//var debugStr = $"AHK| Mouse stroke has absolute move of {x}, {y}...";
if (mapping.Concurrent)
ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(x, y));
else if (_workerThreads.ContainsKey(i) && _workerThreads[i].ContainsKey(7))
_workerThreads[i][7]?.Actions.Add(() => mapping.Callback(x, y));
if (mapping.Block)
{
moveRemoved = true;
stroke.mouse.x = 0;
stroke.mouse.y = 0;
//debugStr += "Blocking";
}
else
{
//debugStr += "Not Blocking";
}
//Debug.WriteLine(debugStr);
}
}
// Process Relative Mouse Move
//else if ((stroke.mouse.flags & (ushort) ManagedWrapper.MouseFlag.MouseMoveRelative) == (ushort) ManagedWrapper.MouseFlag.MouseMoveRelative) / flag is 0, so always true!
else
{
if (_mouseMoveRelativeMappings.ContainsKey(i))
{
var mapping = _mouseMoveRelativeMappings[i];
hasSubscription = true;
//var debugStr = $"AHK| Mouse stroke has relative move of {x}, {y}...";
if (mapping.Concurrent)
ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(x, y));
else if (_workerThreads.ContainsKey(i) && _workerThreads[i].ContainsKey(8))
_workerThreads[i][8]?.Actions.Add(() => mapping.Callback(x, y));
if (mapping.Block)
{
moveRemoved = true;
stroke.mouse.x = 0;
stroke.mouse.y = 0;
//debugStr += "Blocking";
}
else
{
//debugStr += "Not Blocking";
}
//Debug.WriteLine(debugStr);
}
}
}
var isMouseButtonsMapping = _mouseButtonsMappings.ContainsKey(i);
// Process Mouse Buttons - do this AFTER mouse movement, so that absolute mode has coordinates available at the point that the button callback is fired
if (stroke.mouse.state != 0 && _mouseButtonMappings.ContainsKey(i) || isMouseButtonsMapping)
{
var btnStates = HelperFunctions.MouseStrokeToButtonStates(stroke);
foreach (var btnState in btnStates)
{
if (!isMouseButtonsMapping && !_mouseButtonMappings[i].ContainsKey(btnState.Button))
continue;
hasSubscription = true; hasSubscription = true;
//var debugStr = $"AHK| Mouse stroke has relative move of {x}, {y}..."; MappingOptions mapping = null;
if (isMouseButtonsMapping)
{
mapping = _mouseButtonsMappings[i];
}
else
{
mapping = _mouseButtonMappings[i][btnState.Button];
}
var state = btnState;
if (mapping.Concurrent) if (mapping.Concurrent)
ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(x, y));
else if (_workerThreads.ContainsKey(i) && _workerThreads[i].ContainsKey(8))
_workerThreads[i][8]?.Actions.Add(() => mapping.Callback(x, y));
if (mapping.Block)
{ {
moveRemoved = true; if (isMouseButtonsMapping)
stroke.mouse.x = 0;
stroke.mouse.y = 0;
//debugStr += "Blocking";
}
else
{
//debugStr += "Not Blocking";
}
//Debug.WriteLine(debugStr);
}
}
}
var isMouseButtonsMapping = _mouseButtonsMappings.ContainsKey(i);
// Process Mouse Buttons - do this AFTER mouse movement, so that absolute mode has coordinates available at the point that the button callback is fired
if (stroke.mouse.state != 0 && _mouseButtonMappings.ContainsKey(i) || isMouseButtonsMapping)
{
var btnStates = HelperFunctions.MouseStrokeToButtonStates(stroke);
foreach (var btnState in btnStates)
{
if (!isMouseButtonsMapping && !_mouseButtonMappings[i].ContainsKey(btnState.Button)) continue;
hasSubscription = true;
MappingOptions mapping = null;
if (isMouseButtonsMapping)
{
mapping = _mouseButtonsMappings[i];
}
else
{
mapping = _mouseButtonMappings[i][btnState.Button];
}
var state = btnState;
if (mapping.Concurrent)
{
if (isMouseButtonsMapping)
{
ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(btnState.Button, state.State));
}
else
{
ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(state.State));
}
}
else
{
if (isMouseButtonsMapping)
{
_deviceWorkerThreads[i]?.Actions
.Add(() => mapping.Callback(btnState.Button, state.State));
}
else
{
_workerThreads[i][btnState.Button]?.Actions
.Add(() => mapping.Callback(state.State));
}
}
if (mapping.Block)
{
// Remove the event for this button from the stroke, leaving other button events intact
stroke.mouse.state -= btnState.Flag;
// If we are removing a mouse wheel event, then set rolling to 0 if no mouse wheel event left
if (btnState.Flag == 0x400 || btnState.Flag == 0x800)
{
if ((stroke.mouse.state & 0x400) != 0x400 && (stroke.mouse.state & 0x800) != 0x800)
{ {
//Debug.WriteLine("AHK| Removing rolling flag from stroke"); ThreadPool.QueueUserWorkItem(threadProc =>
stroke.mouse.rolling = 0; mapping.Callback(btnState.Button, state.State));
}
else
{
ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(state.State));
} }
} }
//Debug.WriteLine($"AHK| Removing flag {btnState.Flag} from stoke, leaving state {stroke.mouse.state}"); else
} {
else if (isMouseButtonsMapping)
{ {
//Debug.WriteLine($"AHK| Leaving flag {btnState.Flag} in stroke"); _deviceWorkerThreads[i]?.Actions
.Add(() => mapping.Callback(btnState.Button, state.State));
}
else
{
_workerThreads[i][btnState.Button]?.Actions
.Add(() => mapping.Callback(state.State));
}
}
if (mapping.Block)
{
// Remove the event for this button from the stroke, leaving other button events intact
stroke.mouse.state -= btnState.Flag;
// If we are removing a mouse wheel event, then set rolling to 0 if no mouse wheel event left
if (btnState.Flag == 0x400 || btnState.Flag == 0x800)
{
if ((stroke.mouse.state & 0x400) != 0x400 &&
(stroke.mouse.state & 0x800) != 0x800)
{
//Debug.WriteLine("AHK| Removing rolling flag from stroke");
stroke.mouse.rolling = 0;
}
}
//Debug.WriteLine($"AHK| Removing flag {btnState.Flag} from stoke, leaving state {stroke.mouse.state}");
}
else
{
//Debug.WriteLine($"AHK| Leaving flag {btnState.Flag} in stroke");
}
} }
} }
} }
// Forward on the stroke if required // Forward on the stroke if required
if (hasSubscription) if (hasSubscription)
{ {

View File

@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
### Deprecated ### Deprecated
### Removed ### Removed
### Fixed ### Fixed
- Fix Issue 65: UnsubscribeMouseMoveRelative when subscribed with blocking enabled did not restore mouse movement
## [0.5.2] - 2020-04-29 ## [0.5.2] - 2020-04-29
- Compiled scripts now pack the required DLLs inside the EXE and unpack them on run - Compiled scripts now pack the required DLLs inside the EXE and unpack them on run