This commit is contained in:
mika-n 2019-02-19 15:09:00 +02:00
commit 7da6b3434a
2 changed files with 177 additions and 172 deletions

View File

@ -2,10 +2,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Diagnostics; using System.Diagnostics;
using static DS4Windows.Global; using static DS4Windows.Global;
namespace DS4Windows namespace DS4Windows
{ {
public class Mapping public class Mapping
@ -77,6 +79,8 @@ namespace DS4Windows
new Queue<ControlToXInput>(), new Queue<ControlToXInput>() new Queue<ControlToXInput>(), new Queue<ControlToXInput>()
}; };
static ReaderWriterLockSlim syncStateLock = new ReaderWriterLockSlim();
public static SyntheticState globalState = new SyntheticState(); public static SyntheticState globalState = new SyntheticState();
public static SyntheticState[] deviceState = new SyntheticState[4] public static SyntheticState[] deviceState = new SyntheticState[4]
{ new SyntheticState(), new SyntheticState(), new SyntheticState(), { new SyntheticState(), new SyntheticState(), new SyntheticState(),
@ -190,206 +194,207 @@ namespace DS4Windows
public static void Commit(int device) public static void Commit(int device)
{ {
SyntheticState state = deviceState[device]; SyntheticState state = deviceState[device];
lock (globalState) syncStateLock.EnterWriteLock();
globalState.currentClicks.leftCount += state.currentClicks.leftCount - state.previousClicks.leftCount;
globalState.currentClicks.middleCount += state.currentClicks.middleCount - state.previousClicks.middleCount;
globalState.currentClicks.rightCount += state.currentClicks.rightCount - state.previousClicks.rightCount;
globalState.currentClicks.fourthCount += state.currentClicks.fourthCount - state.previousClicks.fourthCount;
globalState.currentClicks.fifthCount += state.currentClicks.fifthCount - state.previousClicks.fifthCount;
globalState.currentClicks.wUpCount += state.currentClicks.wUpCount - state.previousClicks.wUpCount;
globalState.currentClicks.wDownCount += state.currentClicks.wDownCount - state.previousClicks.wDownCount;
globalState.currentClicks.toggleCount += state.currentClicks.toggleCount - state.previousClicks.toggleCount;
globalState.currentClicks.toggle = state.currentClicks.toggle;
if (globalState.currentClicks.toggleCount != 0 && globalState.previousClicks.toggleCount == 0 && globalState.currentClicks.toggle)
{ {
globalState.currentClicks.leftCount += state.currentClicks.leftCount - state.previousClicks.leftCount; if (globalState.currentClicks.leftCount != 0 && globalState.previousClicks.leftCount == 0)
globalState.currentClicks.middleCount += state.currentClicks.middleCount - state.previousClicks.middleCount; InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTDOWN);
globalState.currentClicks.rightCount += state.currentClicks.rightCount - state.previousClicks.rightCount; if (globalState.currentClicks.rightCount != 0 && globalState.previousClicks.rightCount == 0)
globalState.currentClicks.fourthCount += state.currentClicks.fourthCount - state.previousClicks.fourthCount; InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTDOWN);
globalState.currentClicks.fifthCount += state.currentClicks.fifthCount - state.previousClicks.fifthCount; if (globalState.currentClicks.middleCount != 0 && globalState.previousClicks.middleCount == 0)
globalState.currentClicks.wUpCount += state.currentClicks.wUpCount - state.previousClicks.wUpCount; InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEDOWN);
globalState.currentClicks.wDownCount += state.currentClicks.wDownCount - state.previousClicks.wDownCount; if (globalState.currentClicks.fourthCount != 0 && globalState.previousClicks.fourthCount == 0)
globalState.currentClicks.toggleCount += state.currentClicks.toggleCount - state.previousClicks.toggleCount; InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 1);
globalState.currentClicks.toggle = state.currentClicks.toggle; if (globalState.currentClicks.fifthCount != 0 && globalState.previousClicks.fifthCount == 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 2);
}
else if (globalState.currentClicks.toggleCount != 0 && globalState.previousClicks.toggleCount == 0 && !globalState.currentClicks.toggle)
{
if (globalState.currentClicks.leftCount != 0 && globalState.previousClicks.leftCount == 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTUP);
if (globalState.currentClicks.rightCount != 0 && globalState.previousClicks.rightCount == 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTUP);
if (globalState.currentClicks.middleCount != 0 && globalState.previousClicks.middleCount == 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEUP);
if (globalState.currentClicks.fourthCount != 0 && globalState.previousClicks.fourthCount == 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 1);
if (globalState.currentClicks.fifthCount != 0 && globalState.previousClicks.fifthCount == 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 2);
}
if (globalState.currentClicks.toggleCount != 0 && globalState.previousClicks.toggleCount == 0 && globalState.currentClicks.toggle) if (globalState.currentClicks.toggleCount == 0 && globalState.previousClicks.toggleCount == 0)
{
if (globalState.currentClicks.leftCount != 0 && globalState.previousClicks.leftCount == 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTDOWN);
else if (globalState.currentClicks.leftCount == 0 && globalState.previousClicks.leftCount != 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTUP);
if (globalState.currentClicks.middleCount != 0 && globalState.previousClicks.middleCount == 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEDOWN);
else if (globalState.currentClicks.middleCount == 0 && globalState.previousClicks.middleCount != 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEUP);
if (globalState.currentClicks.rightCount != 0 && globalState.previousClicks.rightCount == 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTDOWN);
else if (globalState.currentClicks.rightCount == 0 && globalState.previousClicks.rightCount != 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTUP);
if (globalState.currentClicks.fourthCount != 0 && globalState.previousClicks.fourthCount == 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 1);
else if (globalState.currentClicks.fourthCount == 0 && globalState.previousClicks.fourthCount != 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 1);
if (globalState.currentClicks.fifthCount != 0 && globalState.previousClicks.fifthCount == 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 2);
else if (globalState.currentClicks.fifthCount == 0 && globalState.previousClicks.fifthCount != 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 2);
if (globalState.currentClicks.wUpCount != 0 && globalState.previousClicks.wUpCount == 0)
{ {
if (globalState.currentClicks.leftCount != 0 && globalState.previousClicks.leftCount == 0) InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_WHEEL, 120);
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTDOWN); oldnow = DateTime.UtcNow;
if (globalState.currentClicks.rightCount != 0 && globalState.previousClicks.rightCount == 0) wheel = 120;
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTDOWN);
if (globalState.currentClicks.middleCount != 0 && globalState.previousClicks.middleCount == 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEDOWN);
if (globalState.currentClicks.fourthCount != 0 && globalState.previousClicks.fourthCount == 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 1);
if (globalState.currentClicks.fifthCount != 0 && globalState.previousClicks.fifthCount == 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 2);
} }
else if (globalState.currentClicks.toggleCount != 0 && globalState.previousClicks.toggleCount == 0 && !globalState.currentClicks.toggle) else if (globalState.currentClicks.wUpCount == 0 && globalState.previousClicks.wUpCount != 0)
wheel = 0;
if (globalState.currentClicks.wDownCount != 0 && globalState.previousClicks.wDownCount == 0)
{ {
if (globalState.currentClicks.leftCount != 0 && globalState.previousClicks.leftCount == 0) InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_WHEEL, -120);
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTUP); oldnow = DateTime.UtcNow;
if (globalState.currentClicks.rightCount != 0 && globalState.previousClicks.rightCount == 0) wheel = -120;
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTUP);
if (globalState.currentClicks.middleCount != 0 && globalState.previousClicks.middleCount == 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEUP);
if (globalState.currentClicks.fourthCount != 0 && globalState.previousClicks.fourthCount == 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 1);
if (globalState.currentClicks.fifthCount != 0 && globalState.previousClicks.fifthCount == 0)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 2);
} }
if (globalState.currentClicks.wDownCount == 0 && globalState.previousClicks.wDownCount != 0)
wheel = 0;
}
if (globalState.currentClicks.toggleCount == 0 && globalState.previousClicks.toggleCount == 0)
if (wheel != 0) //Continue mouse wheel movement
{
DateTime now = DateTime.UtcNow;
if (now >= oldnow + TimeSpan.FromMilliseconds(100) && !pressagain)
{ {
if (globalState.currentClicks.leftCount != 0 && globalState.previousClicks.leftCount == 0) oldnow = now;
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTDOWN); InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_WHEEL, wheel);
else if (globalState.currentClicks.leftCount == 0 && globalState.previousClicks.leftCount != 0) }
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTUP); }
if (globalState.currentClicks.middleCount != 0 && globalState.previousClicks.middleCount == 0) // Merge and synthesize all key presses/releases that are present in this device's mapping.
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEDOWN); // TODO what about the rest? e.g. repeat keys really ought to be on some set schedule
else if (globalState.currentClicks.middleCount == 0 && globalState.previousClicks.middleCount != 0) Dictionary<UInt16, SyntheticState.KeyPresses>.KeyCollection kvpKeys = state.keyPresses.Keys;
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEUP); //foreach (KeyValuePair<UInt16, SyntheticState.KeyPresses> kvp in state.keyPresses)
//for (int i = 0, keyCount = kvpKeys.Count; i < keyCount; i++)
for (var keyEnum = kvpKeys.GetEnumerator(); keyEnum.MoveNext();)
{
//UInt16 kvpKey = kvpKeys.ElementAt(i);
UInt16 kvpKey = keyEnum.Current;
SyntheticState.KeyPresses kvpValue = state.keyPresses[kvpKey];
if (globalState.currentClicks.rightCount != 0 && globalState.previousClicks.rightCount == 0) SyntheticState.KeyPresses gkp;
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTDOWN); if (globalState.keyPresses.TryGetValue(kvpKey, out gkp))
else if (globalState.currentClicks.rightCount == 0 && globalState.previousClicks.rightCount != 0) {
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTUP); gkp.current.vkCount += kvpValue.current.vkCount - kvpValue.previous.vkCount;
gkp.current.scanCodeCount += kvpValue.current.scanCodeCount - kvpValue.previous.scanCodeCount;
if (globalState.currentClicks.fourthCount != 0 && globalState.previousClicks.fourthCount == 0) gkp.current.repeatCount += kvpValue.current.repeatCount - kvpValue.previous.repeatCount;
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 1); gkp.current.toggle = kvpValue.current.toggle;
else if (globalState.currentClicks.fourthCount == 0 && globalState.previousClicks.fourthCount != 0) gkp.current.toggleCount += kvpValue.current.toggleCount - kvpValue.previous.toggleCount;
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 1); }
else
if (globalState.currentClicks.fifthCount != 0 && globalState.previousClicks.fifthCount == 0) {
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONDOWN, 2); gkp = new SyntheticState.KeyPresses();
else if (globalState.currentClicks.fifthCount == 0 && globalState.previousClicks.fifthCount != 0) gkp.current = kvpValue.current;
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_XBUTTONUP, 2); globalState.keyPresses[kvpKey] = gkp;
}
if (globalState.currentClicks.wUpCount != 0 && globalState.previousClicks.wUpCount == 0) if (gkp.current.toggleCount != 0 && gkp.previous.toggleCount == 0 && gkp.current.toggle)
{
if (gkp.current.scanCodeCount != 0)
InputMethods.performSCKeyPress(kvpKey);
else
InputMethods.performKeyPress(kvpKey);
}
else if (gkp.current.toggleCount != 0 && gkp.previous.toggleCount == 0 && !gkp.current.toggle)
{
if (gkp.previous.scanCodeCount != 0) // use the last type of VK/SC
InputMethods.performSCKeyRelease(kvpKey);
else
InputMethods.performKeyRelease(kvpKey);
}
else if (gkp.current.vkCount + gkp.current.scanCodeCount != 0 && gkp.previous.vkCount + gkp.previous.scanCodeCount == 0)
{
if (gkp.current.scanCodeCount != 0)
{ {
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_WHEEL, 120);
oldnow = DateTime.UtcNow; oldnow = DateTime.UtcNow;
wheel = 120; InputMethods.performSCKeyPress(kvpKey);
} pressagain = false;
else if (globalState.currentClicks.wUpCount == 0 && globalState.previousClicks.wUpCount != 0) keyshelddown = kvpKey;
wheel = 0;
if (globalState.currentClicks.wDownCount != 0 && globalState.previousClicks.wDownCount == 0)
{
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_WHEEL, -120);
oldnow = DateTime.UtcNow;
wheel = -120;
}
if (globalState.currentClicks.wDownCount == 0 && globalState.previousClicks.wDownCount != 0)
wheel = 0;
}
if (wheel != 0) //Continue mouse wheel movement
{
DateTime now = DateTime.UtcNow;
if (now >= oldnow + TimeSpan.FromMilliseconds(100) && !pressagain)
{
oldnow = now;
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_WHEEL, wheel);
}
}
// Merge and synthesize all key presses/releases that are present in this device's mapping.
// TODO what about the rest? e.g. repeat keys really ought to be on some set schedule
Dictionary<UInt16, SyntheticState.KeyPresses>.KeyCollection kvpKeys = state.keyPresses.Keys;
//foreach (KeyValuePair<UInt16, SyntheticState.KeyPresses> kvp in state.keyPresses)
//for (int i = 0, keyCount = kvpKeys.Count; i < keyCount; i++)
for (var keyEnum = kvpKeys.GetEnumerator(); keyEnum.MoveNext();)
{
//UInt16 kvpKey = kvpKeys.ElementAt(i);
UInt16 kvpKey = keyEnum.Current;
SyntheticState.KeyPresses kvpValue = state.keyPresses[kvpKey];
SyntheticState.KeyPresses gkp;
if (globalState.keyPresses.TryGetValue(kvpKey, out gkp))
{
gkp.current.vkCount += kvpValue.current.vkCount - kvpValue.previous.vkCount;
gkp.current.scanCodeCount += kvpValue.current.scanCodeCount - kvpValue.previous.scanCodeCount;
gkp.current.repeatCount += kvpValue.current.repeatCount - kvpValue.previous.repeatCount;
gkp.current.toggle = kvpValue.current.toggle;
gkp.current.toggleCount += kvpValue.current.toggleCount - kvpValue.previous.toggleCount;
} }
else else
{ {
gkp = new SyntheticState.KeyPresses(); oldnow = DateTime.UtcNow;
gkp.current = kvpValue.current; InputMethods.performKeyPress(kvpKey);
globalState.keyPresses[kvpKey] = gkp; pressagain = false;
keyshelddown = kvpKey;
} }
if (gkp.current.toggleCount != 0 && gkp.previous.toggleCount == 0 && gkp.current.toggle) }
else if (gkp.current.toggleCount != 0 || gkp.previous.toggleCount != 0 || gkp.current.repeatCount != 0 || // repeat or SC/VK transition
((gkp.previous.scanCodeCount == 0) != (gkp.current.scanCodeCount == 0))) //repeat keystroke after 500ms
{
if (keyshelddown == kvpKey)
{ {
if (gkp.current.scanCodeCount != 0) DateTime now = DateTime.UtcNow;
InputMethods.performSCKeyPress(kvpKey); if (now >= oldnow + TimeSpan.FromMilliseconds(500) && !pressagain)
else
InputMethods.performKeyPress(kvpKey);
}
else if (gkp.current.toggleCount != 0 && gkp.previous.toggleCount == 0 && !gkp.current.toggle)
{
if (gkp.previous.scanCodeCount != 0) // use the last type of VK/SC
InputMethods.performSCKeyRelease(kvpKey);
else
InputMethods.performKeyRelease(kvpKey);
}
else if (gkp.current.vkCount + gkp.current.scanCodeCount != 0 && gkp.previous.vkCount + gkp.previous.scanCodeCount == 0)
{
if (gkp.current.scanCodeCount != 0)
{ {
oldnow = DateTime.UtcNow; oldnow = now;
InputMethods.performSCKeyPress(kvpKey); pressagain = true;
pressagain = false;
keyshelddown = kvpKey;
} }
else if (pressagain && gkp.current.scanCodeCount != 0)
{ {
oldnow = DateTime.UtcNow; now = DateTime.UtcNow;
InputMethods.performKeyPress(kvpKey); if (now >= oldnow + TimeSpan.FromMilliseconds(25) && pressagain)
pressagain = false;
keyshelddown = kvpKey;
}
}
else if (gkp.current.toggleCount != 0 || gkp.previous.toggleCount != 0 || gkp.current.repeatCount != 0 || // repeat or SC/VK transition
((gkp.previous.scanCodeCount == 0) != (gkp.current.scanCodeCount == 0))) //repeat keystroke after 500ms
{
if (keyshelddown == kvpKey)
{
DateTime now = DateTime.UtcNow;
if (now >= oldnow + TimeSpan.FromMilliseconds(500) && !pressagain)
{ {
oldnow = now; oldnow = now;
pressagain = true; InputMethods.performSCKeyPress(kvpKey);
}
if (pressagain && gkp.current.scanCodeCount != 0)
{
now = DateTime.UtcNow;
if (now >= oldnow + TimeSpan.FromMilliseconds(25) && pressagain)
{
oldnow = now;
InputMethods.performSCKeyPress(kvpKey);
}
}
else if (pressagain)
{
now = DateTime.UtcNow;
if (now >= oldnow + TimeSpan.FromMilliseconds(25) && pressagain)
{
oldnow = now;
InputMethods.performKeyPress(kvpKey);
}
} }
} }
} else if (pressagain)
if ((gkp.current.toggleCount == 0 && gkp.previous.toggleCount == 0) && gkp.current.vkCount + gkp.current.scanCodeCount == 0 && gkp.previous.vkCount + gkp.previous.scanCodeCount != 0)
{
if (gkp.previous.scanCodeCount != 0) // use the last type of VK/SC
{ {
InputMethods.performSCKeyRelease(kvpKey); now = DateTime.UtcNow;
pressagain = false; if (now >= oldnow + TimeSpan.FromMilliseconds(25) && pressagain)
} {
else oldnow = now;
{ InputMethods.performKeyPress(kvpKey);
InputMethods.performKeyRelease(kvpKey); }
pressagain = false;
} }
} }
} }
globalState.SaveToPrevious(false); if ((gkp.current.toggleCount == 0 && gkp.previous.toggleCount == 0) && gkp.current.vkCount + gkp.current.scanCodeCount == 0 && gkp.previous.vkCount + gkp.previous.scanCodeCount != 0)
{
if (gkp.previous.scanCodeCount != 0) // use the last type of VK/SC
{
InputMethods.performSCKeyRelease(kvpKey);
pressagain = false;
}
else
{
InputMethods.performKeyRelease(kvpKey);
pressagain = false;
}
}
} }
globalState.SaveToPrevious(false);
syncStateLock.ExitWriteLock();
state.SaveToPrevious(true); state.SaveToPrevious(true);
} }

View File

@ -43,12 +43,12 @@ namespace DS4Windows
{ {
byte alphacolor = Math.Max(red, Math.Max(green, blue)); byte alphacolor = Math.Max(red, Math.Max(green, blue));
Color reg = Color.FromArgb(red, green, blue); Color reg = Color.FromArgb(red, green, blue);
Color full = HuetoRGB(reg.GetHue(), reg.GetBrightness(), reg); Color full = HuetoRGB(reg.GetHue(), reg.GetBrightness(), ref reg);
return Color.FromArgb((alphacolor > 205 ? 255 : (alphacolor + 50)), full); return Color.FromArgb((alphacolor > 205 ? 255 : (alphacolor + 50)), full);
} }
} }
private Color HuetoRGB(float hue, float light, Color rgb) private Color HuetoRGB(float hue, float light, ref Color rgb)
{ {
float L = (float)Math.Max(.5, light); float L = (float)Math.Max(.5, light);
float C = (1 - Math.Abs(2 * L - 1)); float C = (1 - Math.Abs(2 * L - 1));