├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ └── bug_report.md └── dependabot.yml ├── .gitignore ├── DS4Windows ├── App.xaml ├── App.xaml.cs ├── ArgumentParser.cs ├── AutoProfileChecker.cs ├── AutoProfileHolder.cs ├── BezierCurveEditor │ ├── BezierCurve.cs │ ├── build.js │ └── index.html ├── Changelog.json ├── Changelog.min.json ├── DS4Control │ ├── ControlService.cs │ ├── ControlServiceDeviceOptions.cs │ ├── ControllerSlotManager.cs │ ├── DS4LightBar.cs │ ├── DS4OutDevice.cs │ ├── DS4OutDevices │ │ ├── DS4OutDeviceBasic.cs │ │ ├── DS4OutDeviceExt.cs │ │ ├── DS4OutDeviceExtras.cs │ │ └── DS4OutDeviceFactory.cs │ ├── DS4StateFieldMapping.cs │ ├── HidHideAPIDevice.cs │ ├── ITouchpadBehaviour.cs │ ├── InputMethods.cs │ ├── Log.cs │ ├── MacroParser.cs │ ├── Mapping.cs │ ├── Mouse.cs │ ├── MouseCursor.cs │ ├── MouseWheel.cs │ ├── OutSlotDevice.cs │ ├── OutputDevice.cs │ ├── OutputKBM │ │ ├── FakerInputHandler.cs │ │ ├── FakerInputMapping.cs │ │ ├── SendInputHandler.cs │ │ ├── SendInputMapping.cs │ │ ├── VirtualKBMBase.cs │ │ ├── VirtualKBMFactory.cs │ │ └── VirtualKBMMapping.cs │ ├── OutputSlotManager.cs │ ├── OutputSlotPersist.cs │ ├── PresetOption.cs │ ├── ProfileMigration.cs │ ├── ProfilePropGroups.cs │ ├── Program.cs │ ├── ScpUtil.cs │ ├── UdpServer.cs │ ├── Util.cs │ └── Xbox360OutDevice.cs ├── DS4Forms │ ├── About.xaml │ ├── About.xaml.cs │ ├── AutoProfiles.xaml │ ├── AutoProfiles.xaml.cs │ ├── AxialStickUserControl.xaml │ ├── AxialStickUserControl.xaml.cs │ ├── BindingWindow.xaml │ ├── BindingWindow.xaml.cs │ ├── ChangelogWindow.xaml │ ├── ChangelogWindow.xaml.cs │ ├── ColorPickerWindow.xaml │ ├── ColorPickerWindow.xaml.cs │ ├── ControllerReadingsControl.xaml │ ├── ControllerReadingsControl.xaml.cs │ ├── ControllerRegisterOptionsWindow.xaml │ ├── ControllerRegisterOptionsWindow.xaml.cs │ ├── Converters │ │ ├── EscapeAccessKeysConverter.cs │ │ └── InvertBoolToVisibilityConverter.cs │ ├── DupBox.xaml │ ├── DupBox.xaml.cs │ ├── LanguagePackControl.xaml │ ├── LanguagePackControl.xaml.cs │ ├── LogMessageDisplay.xaml │ ├── LogMessageDisplay.xaml.cs │ ├── MainWindow.xaml │ ├── MainWindow.xaml.cs │ ├── OutputSlotManagerControl.xaml │ ├── OutputSlotManagerControl.xaml.cs │ ├── PluginOutDevWindow.xaml │ ├── PluginOutDevWindow.xaml.cs │ ├── PresetOptionWindow.xaml │ ├── PresetOptionWindow.xaml.cs │ ├── ProfileEditor.xaml │ ├── ProfileEditor.xaml.cs │ ├── RecordBox.xaml │ ├── RecordBox.xaml.cs │ ├── RecordBoxWindow.xaml │ ├── RecordBoxWindow.xaml.cs │ ├── RenameProfileWindow.xaml │ ├── RenameProfileWindow.xaml.cs │ ├── SaveWhere.xaml │ ├── SaveWhere.xaml.cs │ ├── SpecialActionEditor.xaml │ ├── SpecialActionEditor.xaml.cs │ ├── Themes │ │ ├── DarkTheme.xaml │ │ └── DefaultTheme.xaml │ ├── UpdaterWindow.xaml │ ├── UpdaterWindow.xaml.cs │ ├── UtilMethods.cs │ ├── ViewModels │ │ ├── AutoProfilesViewModel.cs │ │ ├── AxialStickControlViewModel.cs │ │ ├── BindingWindowViewModel.cs │ │ ├── ChangelogViewModel.cs │ │ ├── ControllerListViewModel.cs │ │ ├── ControllerRegDeviceOptsViewModel.cs │ │ ├── CurrentOutDeviceViewModel.cs │ │ ├── LanguagePackViewModel.cs │ │ ├── LogViewModel.cs │ │ ├── MainWindowsViewModel.cs │ │ ├── MappingListViewModel.cs │ │ ├── PresetOptionViewModel.cs │ │ ├── ProfileSettingsViewModel.cs │ │ ├── RecordBoxViewModel.cs │ │ ├── RenameProfileViewModel.cs │ │ ├── SettingsViewModel.cs │ │ ├── SpecialActEditorViewModel.cs │ │ ├── SpecialActions │ │ │ ├── CheckBatteryViewModel.cs │ │ │ ├── DisconnectBTViewModel.cs │ │ │ ├── LaunchProgramViewModel.cs │ │ │ ├── LoadProfileViewModel.cs │ │ │ ├── MacroViewModel.cs │ │ │ ├── MultiActButtonViewModel.cs │ │ │ ├── PressKeyViewModel.cs │ │ │ └── SASteeringWheelViewModel.cs │ │ ├── SpecialActionsListViewModel.cs │ │ ├── TrayIconViewModel.cs │ │ ├── UpdaterWindowViewModel.cs │ │ └── Util │ │ │ ├── EnumChoiceSelection.cs │ │ │ └── NotifyDataErrorBase.cs │ ├── WelcomeDialog.xaml │ └── WelcomeDialog.xaml.cs ├── DS4Library │ ├── Crc32.cs │ ├── DS4Device.cs │ ├── DS4Devices.cs │ ├── DS4Sixaxis.cs │ ├── DS4State.cs │ ├── DS4StateExposed.cs │ ├── DS4Touchpad.cs │ ├── InputDevices │ │ ├── DualSenseDevice.cs │ │ ├── InputDeviceFactory.cs │ │ ├── JoyConDevice.cs │ │ ├── SwitchProDevice.cs │ │ └── TriggerEffects.cs │ └── LICENSE-Crc32.txt ├── DS4W.ico ├── DS4WinWPF.csproj ├── DateTimeJsonConverter.cs ├── HidLibrary │ ├── Extensions.cs │ ├── HidDevice.cs │ ├── HidDeviceAttributes.cs │ ├── HidDeviceCapabilities.cs │ ├── HidDevices.cs │ ├── LICENSE │ └── NativeMethods.cs ├── LogItem.cs ├── LogWriter.cs ├── LoggerHolder.cs ├── NLog.config ├── OneEuroFilter.cs ├── ProfileEntity.cs ├── ProfileList.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.ja.resx │ ├── Resources.resx │ ├── Resources.ru.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── ReaderWriteLockSlimWrappers.cs ├── Resources │ ├── 360 fades.png │ ├── 360 highlight.png │ ├── 360 map.png │ ├── A.PNG │ ├── B.png │ ├── BACK.png │ ├── BT.png │ ├── BT_white.png │ ├── DOWN.png │ ├── DS4 Config.png │ ├── DS4 Config_white.png │ ├── DS4 Controller.png │ ├── DS4 lightbar.png │ ├── DS4-Config_Circle.png │ ├── DS4-Config_Cross.png │ ├── DS4-Config_Down.png │ ├── DS4-Config_L1.png │ ├── DS4-Config_L2.png │ ├── DS4-Config_LS.png │ ├── DS4-Config_Left.png │ ├── DS4-Config_PS.png │ ├── DS4-Config_R1.png │ ├── DS4-Config_R2.png │ ├── DS4-Config_RS.png │ ├── DS4-Config_Right.png │ ├── DS4-Config_Share.png │ ├── DS4-Config_Square.png │ ├── DS4-Config_TouchLeft.png │ ├── DS4-Config_TouchMulti.png │ ├── DS4-Config_TouchRight.png │ ├── DS4-Config_TouchUpper.png │ ├── DS4-Config_Triangle.png │ ├── DS4-Config_Up.png │ ├── DS4-Config_options.png │ ├── DS4.ico │ ├── DS4W - Black.ico │ ├── DS4W - White.ico │ ├── DS4W.ico │ ├── LB.png │ ├── LEFT.png │ ├── LS.png │ ├── LSD.png │ ├── LSL.png │ ├── LSR.png │ ├── LSU.png │ ├── LT.png │ ├── Pairmode.png │ ├── RB.png │ ├── RIGHT.png │ ├── RS.png │ ├── RSD.png │ ├── RSL.png │ ├── RSR.png │ ├── RSU.png │ ├── RT.png │ ├── Red Circle.png │ ├── START.png │ ├── UP.png │ ├── USB.png │ ├── USB_white.png │ ├── UpperTouch.png │ ├── X.png │ ├── Y.png │ ├── cancel.png │ ├── cancel_white.png │ ├── checked.png │ ├── checked_white.png │ ├── clock.png │ ├── clock_white.png │ ├── copy.png │ ├── copy_white.png │ ├── delete.png │ ├── delete_white.png │ ├── edit.png │ ├── edit_white.png │ ├── export.png │ ├── export_white.png │ ├── import.png │ ├── import_white.png │ ├── key-solid.png │ ├── key-solid_white.png │ ├── keydown.png │ ├── keydown_white.png │ ├── keyup.png │ ├── keyup_white.png │ ├── left touch.png │ ├── mouse.png │ ├── newprofile.png │ ├── newprofile_white.png │ ├── none.png │ ├── rainbow.png │ ├── rainbowC.png │ ├── rainbowCCrop.png │ ├── right touch.png │ ├── saveprofile.png │ ├── size.png │ ├── social │ │ ├── GitHub-Mark-64px.png │ │ ├── GitHub-Mark-Light-64px.png │ │ ├── bittube.png │ │ ├── twitter_logo_initial.png │ │ └── youtube_social_icon_red.png │ ├── x360test.png │ └── xbox_360_controller.png ├── StartupMethods.cs ├── StatusLogMsg.cs ├── Translations │ ├── Strings.Designer.cs │ ├── Strings.ar.resx │ ├── Strings.cs.resx │ ├── Strings.de.resx │ ├── Strings.es.resx │ ├── Strings.fr.resx │ ├── Strings.he.resx │ ├── Strings.hu-HU.resx │ ├── Strings.it.resx │ ├── Strings.ja.resx │ ├── Strings.nl.resx │ ├── Strings.pl.resx │ ├── Strings.pt-BR.resx │ ├── Strings.pt.resx │ ├── Strings.resx │ ├── Strings.ru.resx │ ├── Strings.uk-UA.resx │ ├── Strings.zh-Hans.resx │ └── Strings.zh-Hant.resx ├── VJoyFeeder │ └── vJoyFeeder.cs ├── app.manifest ├── libs │ ├── x64 │ │ ├── FakerInputWrapper │ │ │ ├── FakerInputDll.dll │ │ │ └── FakerInputWrapper.dll │ │ ├── Nefarius.ViGEm.Client │ │ │ └── Nefarius.ViGEm.Client.dll │ │ └── SharpOSC │ │ │ └── SharpOSC.dll │ └── x86 │ │ ├── FakerInputWrapper │ │ ├── FakerInputDll.dll │ │ └── FakerInputWrapper.dll │ │ ├── Nefarius.ViGEm.Client │ │ └── Nefarius.ViGEm.Client.dll │ │ └── SharpOSC │ │ └── SharpOSC.dll ├── newest.txt └── runtimeconfig.template.json ├── DS4WindowsWPF.sln ├── LICENSE.txt ├── NOTICE.txt ├── README.md ├── TODO.md ├── contributors.txt ├── disabled_device_example.png ├── disabled_device_example_small.png ├── doc └── dev │ └── profile_version_info.md ├── ds4winwpf_screen_20200412.png ├── extras ├── ViGEmBusInstaller_DS4Win.zip └── Virtual Bus Driver.zip └── utils └── inject_deps_path.py /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots and Logs** 24 | If applicable, add screenshots to help explain your problem. Also, please add the most 25 | log file (ds4windows_log.txt) from the Logs folder in your DS4Windows config folder. 26 | 27 | **Desktop (please complete the following information):** 28 | - Controller Make and Model: Sony DS4 v.2 (CUH-ZCT2U) 29 | - OS: [e.g. Windows 10 Pro Build 2004] 30 | - DS4Windows Version [e.g. 3.0.3] 31 | 32 | **Additional context** 33 | Add any other context about the problem here. 34 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "nuget" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | -------------------------------------------------------------------------------- /DS4Windows/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 27 | 28 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /DS4Windows/ArgumentParser.cs: -------------------------------------------------------------------------------- 1 |  2 | using System.Collections.Generic; 3 | using DS4Windows.DS4Control; 4 | 5 | namespace DS4WinWPF 6 | { 7 | public class ArgumentParser 8 | { 9 | private bool mini; 10 | private bool stop; 11 | private bool driverinstall; 12 | private bool reenableDevice; 13 | private string deviceInstanceId; 14 | private bool runtask; 15 | private bool command; 16 | private string commandArgs; 17 | private string virtualkbmHandler = VirtualKBMFactory.DEFAULT_IDENTIFIER; 18 | 19 | private Dictionary errors = 20 | new Dictionary(); 21 | 22 | public bool Mini { get => mini; } 23 | public bool Stop { get => stop; } 24 | public bool Driverinstall { get => driverinstall; } 25 | public bool ReenableDevice { get => reenableDevice; } 26 | public bool Runtask { get => runtask; } 27 | public bool Command { get => command; } 28 | public string DeviceInstanceId { get => deviceInstanceId; } 29 | public string CommandArgs { get => commandArgs; } 30 | public string VirtualkbmHandler { get => virtualkbmHandler; } 31 | public Dictionary Errors { get => errors; } 32 | 33 | public bool HasErrors => errors.Count > 0; 34 | 35 | public void Parse(string[] args) 36 | { 37 | errors.Clear(); 38 | //foreach (string arg in args) 39 | for (int i = 0; i < args.Length; i++) 40 | { 41 | string arg = args[i]; 42 | switch(arg) 43 | { 44 | case "driverinstall": 45 | case "-driverinstall": 46 | driverinstall = true; 47 | break; 48 | 49 | case "re-enabledevice": 50 | case "-re-enabledevice": 51 | reenableDevice = true; 52 | if (i + 1 < args.Length) 53 | { 54 | deviceInstanceId = args[++i]; 55 | } 56 | 57 | break; 58 | 59 | case "runtask": 60 | case "-runtask": 61 | runtask = true; 62 | break; 63 | 64 | case "-stop": 65 | stop = true; 66 | break; 67 | 68 | case "-m": 69 | mini = true; 70 | break; 71 | 72 | case "command": 73 | case "-command": 74 | command = true; 75 | if (i + 1 < args.Length) 76 | { 77 | i++; 78 | string temp = args[i]; 79 | if (temp.Length > 0 && temp.Length <= 256) 80 | { 81 | commandArgs = temp; 82 | } 83 | else 84 | { 85 | command = false; 86 | errors["Command"] = "Command length is invalid"; 87 | } 88 | } 89 | else 90 | { 91 | errors["Command"] = "Command string not given"; 92 | } 93 | break; 94 | case "-virtualkbm": 95 | if (i + 1 < args.Length) 96 | { 97 | i++; 98 | string temp = args[i]; 99 | bool valid = VirtualKBMFactory.IsValidHandler(temp); 100 | if (valid) 101 | { 102 | virtualkbmHandler = temp; 103 | } 104 | } 105 | 106 | break; 107 | 108 | default: break; 109 | } 110 | } 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /DS4Windows/BezierCurveEditor/build.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ds4windowsapp/DS4Windows/65609b470f53a4f832fb07ac24085d3e28ec15bd/DS4Windows/BezierCurveEditor/build.js -------------------------------------------------------------------------------- /DS4Windows/BezierCurveEditor/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Bezier Curve Editor for DS4Windows 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /DS4Windows/DS4Control/ControllerSlotManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | 5 | namespace DS4Windows 6 | { 7 | public class ControllerSlotManager 8 | { 9 | private ReaderWriterLockSlim collectionLocker = new ReaderWriterLockSlim(); 10 | public ReaderWriterLockSlim CollectionLocker { get => collectionLocker; } 11 | 12 | private List controllerColl; 13 | public List ControllerColl { get => controllerColl; set => controllerColl = value; } 14 | 15 | private Dictionary controllerDict; 16 | private Dictionary reverseControllerDict; 17 | public Dictionary ControllerDict { get => controllerDict; } 18 | public Dictionary ReverseControllerDict { get => reverseControllerDict; } 19 | 20 | public ControllerSlotManager() 21 | { 22 | controllerColl = new List(); 23 | controllerDict = new Dictionary(); 24 | reverseControllerDict = new Dictionary(); 25 | } 26 | 27 | public void AddController(DS4Device device, int slotIdx) 28 | { 29 | using (WriteLocker locker = new WriteLocker(collectionLocker)) 30 | { 31 | controllerColl.Add(device); 32 | controllerDict.Add(slotIdx, device); 33 | reverseControllerDict.Add(device, slotIdx); 34 | } 35 | } 36 | 37 | public void RemoveController(DS4Device device, int slotIdx) 38 | { 39 | using (WriteLocker locker = new WriteLocker(collectionLocker)) 40 | { 41 | controllerColl.Remove(device); 42 | controllerDict.Remove(slotIdx); 43 | reverseControllerDict.Remove(device); 44 | } 45 | } 46 | 47 | public void ClearControllerList() 48 | { 49 | using (WriteLocker locker = new WriteLocker(collectionLocker)) 50 | { 51 | controllerColl.Clear(); 52 | controllerDict.Clear(); 53 | reverseControllerDict.Clear(); 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /DS4Windows/DS4Control/DS4OutDevice.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Nefarius.ViGEm.Client; 7 | using Nefarius.ViGEm.Client.Targets; 8 | using Nefarius.ViGEm.Client.Targets.DualShock4; 9 | 10 | namespace DS4Windows 11 | { 12 | abstract class DS4OutDevice : OutputDevice 13 | { 14 | public const string devtype = "DS4"; 15 | 16 | public IDualShock4Controller cont; 17 | //public DualShock4FeedbackReceivedEventHandler forceFeedbackCall; 18 | public Dictionary forceFeedbacksDict = 19 | new Dictionary(); 20 | 21 | public DS4OutDevice(ViGEmClient client) 22 | { 23 | cont = client.CreateDualShock4Controller(); 24 | //cont = client.CreateDualShock4Controller(0x054C, 0x09CC); 25 | cont.AutoSubmitReport = false; 26 | } 27 | 28 | public override void Connect() 29 | { 30 | cont.Connect(); 31 | connected = true; 32 | } 33 | public override void Disconnect() 34 | { 35 | foreach (KeyValuePair pair in forceFeedbacksDict) 36 | { 37 | cont.FeedbackReceived -= pair.Value; 38 | } 39 | 40 | forceFeedbacksDict.Clear(); 41 | 42 | connected = false; 43 | cont.Disconnect(); 44 | //cont.Dispose(); 45 | cont = null; 46 | } 47 | public override string GetDeviceType() => devtype; 48 | 49 | public override void RemoveFeedbacks() 50 | { 51 | foreach (KeyValuePair pair in forceFeedbacksDict) 52 | { 53 | cont.FeedbackReceived -= pair.Value; 54 | } 55 | 56 | forceFeedbacksDict.Clear(); 57 | } 58 | 59 | public override void RemoveFeedback(int inIdx) 60 | { 61 | if (forceFeedbacksDict.TryGetValue(inIdx, out DualShock4FeedbackReceivedEventHandler handler)) 62 | { 63 | cont.FeedbackReceived -= handler; 64 | forceFeedbacksDict.Remove(inIdx); 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /DS4Windows/DS4Control/DS4OutDevices/DS4OutDeviceExtras.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DS4Windows 9 | { 10 | [StructLayout(LayoutKind.Sequential, Size = 9)] 11 | unsafe struct DS4_TOUCH 12 | { 13 | public byte bPacketCounter; 14 | public byte bIsUpTrackingNum1; 15 | public fixed byte bTouchData1[3]; 16 | public byte bIsUpTrackingNum2; 17 | public fixed byte bTouchData2[3]; 18 | } 19 | 20 | [StructLayout(LayoutKind.Explicit)] 21 | unsafe struct DS4_REPORT_UNION 22 | { 23 | [FieldOffset(0)] 24 | public DS4_REPORT_EX reportStruct; 25 | 26 | [FieldOffset(0)] 27 | public fixed byte Report[63]; 28 | } 29 | 30 | /// 31 | /// Used to set data for DS4 Extended output report. StructLayout 32 | /// will be used to align data for a raw byte array of 63 bytes. 33 | /// ViGEmBus will place report ID byte into the output so this data 34 | /// will technically start with byte 1 of the final output report 35 | /// 36 | [StructLayout(LayoutKind.Explicit, Size = 63)] 37 | unsafe struct DS4_REPORT_EX 38 | { 39 | [FieldOffset(0)] 40 | public byte bThumbLX; 41 | [FieldOffset(1)] 42 | public byte bThumbLY; 43 | [FieldOffset(2)] 44 | public byte bThumbRX; 45 | [FieldOffset(3)] 46 | public byte bThumbRY; 47 | [FieldOffset(4)] 48 | public ushort wButtons; 49 | [FieldOffset(6)] 50 | public byte bSpecial; 51 | [FieldOffset(7)] 52 | public byte bTriggerL; 53 | [FieldOffset(8)] 54 | public byte bTriggerR; 55 | [FieldOffset(9)] 56 | public ushort wTimestamp; 57 | [FieldOffset(11)] 58 | public byte bBatteryLvl; 59 | [FieldOffset(12)] 60 | public short wGyroX; 61 | [FieldOffset(14)] 62 | public short wGyroY; 63 | [FieldOffset(16)] 64 | public short wGyroZ; 65 | [FieldOffset(18)] 66 | public short wAccelX; 67 | [FieldOffset(20)] 68 | public short wAccelY; 69 | [FieldOffset(22)] 70 | public short wAccelZ; 71 | [FieldOffset(24)] 72 | public fixed byte _bUnknown1[5]; 73 | [FieldOffset(29)] 74 | public byte bBatteryLvlSpecial; 75 | [FieldOffset(30)] 76 | public fixed byte _bUnknown2[2]; 77 | [FieldOffset(32)] 78 | public byte bTouchPacketsN; 79 | [FieldOffset(33)] 80 | public DS4_TOUCH sCurrentTouch; 81 | [FieldOffset(42)] 82 | public DS4_TOUCH sPreviousTouch1; 83 | [FieldOffset(51)] 84 | public DS4_TOUCH sPreviousTouch2; 85 | } 86 | 87 | internal static class DS4OutDeviceExtras 88 | { 89 | public static void CopyBytes(ref DS4_REPORT_EX outReport, byte[] outBuffer) 90 | { 91 | GCHandle h = GCHandle.Alloc(outReport, GCHandleType.Pinned); 92 | Marshal.Copy(h.AddrOfPinnedObject(), outBuffer, 0, 63); 93 | h.Free(); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /DS4Windows/DS4Control/DS4OutDevices/DS4OutDeviceFactory.cs: -------------------------------------------------------------------------------- 1 | using Nefarius.ViGEm.Client; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DS4Windows 9 | { 10 | static class DS4OutDeviceFactory 11 | { 12 | private static Version extAPIMinVersion = new Version("1.17.333.0"); 13 | 14 | public static DS4OutDevice CreateDS4Device(ViGEmClient client, 15 | Version driverVersion) 16 | { 17 | DS4OutDevice result = null; 18 | if (extAPIMinVersion.CompareTo(driverVersion) <= 0) 19 | { 20 | result = new DS4OutDeviceExt(client); 21 | } 22 | else 23 | { 24 | result = new DS4OutDeviceBasic(client); 25 | } 26 | 27 | return result; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /DS4Windows/DS4Control/ITouchpadBehaviour.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DS4Windows 4 | { 5 | interface ITouchpadBehaviour 6 | { 7 | void touchesBegan(DS4Touchpad sender, TouchpadEventArgs arg); 8 | void touchesMoved(DS4Touchpad sender, TouchpadEventArgs arg); 9 | void touchButtonUp(DS4Touchpad sender, TouchpadEventArgs arg); 10 | void touchButtonDown(DS4Touchpad sender, TouchpadEventArgs arg); 11 | void touchesEnded(DS4Touchpad sender, TouchpadEventArgs arg); 12 | void sixaxisMoved(DS4SixAxis sender, SixAxisEventArgs unused); 13 | void touchUnchanged(DS4Touchpad sender, EventArgs unused); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /DS4Windows/DS4Control/Log.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DS4Windows 4 | { 5 | public class AppLogger 6 | { 7 | public static event EventHandler TrayIconLog; 8 | public static event EventHandler GuiLog; 9 | 10 | public static void LogToGui(string data, bool warning, bool temporary = false) 11 | { 12 | if (GuiLog != null) 13 | { 14 | GuiLog(null, new DebugEventArgs(data, warning, temporary)); 15 | } 16 | } 17 | 18 | public static void LogToTray(string data, bool warning = false, bool ignoreSettings = false) 19 | { 20 | if (TrayIconLog != null) 21 | { 22 | if (ignoreSettings) 23 | TrayIconLog(ignoreSettings, new DebugEventArgs(data, warning)); 24 | else 25 | TrayIconLog(null, new DebugEventArgs(data, warning)); 26 | } 27 | } 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /DS4Windows/DS4Control/MouseWheel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DS4Windows 4 | { 5 | class MouseWheel 6 | { 7 | private readonly int deviceNumber; 8 | public MouseWheel(int deviceNum) 9 | { 10 | deviceNumber = deviceNum; 11 | } 12 | 13 | // Keep track of remainders when performing scrolls or we lose fractional parts. 14 | private double horizontalRemainder = 0.0, verticalRemainder = 0.0; 15 | 16 | public void touchesBegan(TouchpadEventArgs arg) 17 | { 18 | if (arg.touches.Length == 2) 19 | horizontalRemainder = verticalRemainder = 0.0; 20 | } 21 | 22 | public void touchesMoved(TouchpadEventArgs arg, bool dragging) 23 | { 24 | if (arg.touches.Length != 2 || dragging) 25 | return; 26 | 27 | Touch lastT0 = arg.touches[0].previousTouch; 28 | Touch lastT1 = arg.touches[1].previousTouch; 29 | Touch T0 = arg.touches[0]; 30 | Touch T1 = arg.touches[1]; 31 | 32 | //mouse wheel 120 == 1 wheel click according to Windows API 33 | double lastMidX = (lastT0.hwX + lastT1.hwX) / 2d, lastMidY = (lastT0.hwY + lastT1.hwY) / 2d, 34 | currentMidX = (T0.hwX + T1.hwX) / 2d, currentMidY = (T0.hwY + T1.hwY) / 2d; 35 | 36 | // Express coefficient as a ratio 37 | double coefficient = Global.ScrollSensitivity[deviceNumber] / 100.0; 38 | 39 | // Adjust for touch distance: "standard" distance is 960 pixels, i.e. half the width. Scroll farther if fingers are farther apart, and vice versa, in linear proportion. 40 | double touchXDistance = T1.hwX - T0.hwX, touchYDistance = T1.hwY - T0.hwY, touchDistance = Math.Sqrt(touchXDistance * touchXDistance + touchYDistance * touchYDistance); 41 | coefficient *= touchDistance / 960.0; 42 | 43 | // Collect rounding errors instead of losing motion. 44 | double xMotion = coefficient * (currentMidX - lastMidX); 45 | if ((xMotion > 0.0 && horizontalRemainder > 0.0) || (xMotion < 0.0 && horizontalRemainder < 0.0)) 46 | { 47 | xMotion += horizontalRemainder; 48 | } 49 | 50 | int xAction = (int)xMotion; 51 | horizontalRemainder = xMotion - xAction; 52 | 53 | double yMotion = coefficient * (lastMidY - currentMidY); 54 | if ((yMotion > 0.0 && verticalRemainder > 0.0) || (yMotion < 0.0 && verticalRemainder < 0.0)) 55 | { 56 | yMotion += verticalRemainder; 57 | } 58 | 59 | int yAction = (int)yMotion; 60 | verticalRemainder = yMotion - yAction; 61 | 62 | if (yAction != 0 || xAction != 0) 63 | { 64 | yAction = yAction < 0 ? yAction * -1 * Global.outputKBMMapping.WHEEL_TICK_DOWN : 65 | yAction * Global.outputKBMMapping.WHEEL_TICK_UP; 66 | 67 | xAction = xAction < 0 ? xAction * -1 * Global.outputKBMMapping.WHEEL_TICK_DOWN : 68 | xAction * Global.outputKBMMapping.WHEEL_TICK_UP; 69 | 70 | Global.outputKBMHandler.PerformMouseWheelEvent(yAction, xAction); 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /DS4Windows/DS4Control/OutputDevice.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DS4Windows 4 | { 5 | public abstract class OutputDevice 6 | { 7 | protected bool connected; 8 | 9 | public abstract void ConvertandSendReport(DS4State state, int device); 10 | public abstract void Connect(); 11 | public abstract void Disconnect(); 12 | public abstract void ResetState(bool submit=true); 13 | public abstract string GetDeviceType(); 14 | 15 | public abstract void RemoveFeedbacks(); 16 | 17 | public abstract void RemoveFeedback(int inIdx); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /DS4Windows/DS4Control/OutputKBM/SendInputMapping.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace DS4Windows.DS4Control 3 | { 4 | public class SendInputMapping : VirtualKBMMapping 5 | { 6 | public override void PopulateConstants() 7 | { 8 | MOUSEEVENTF_LEFTDOWN = 2; MOUSEEVENTF_LEFTUP = 4; 9 | MOUSEEVENTF_RIGHTDOWN = 8; MOUSEEVENTF_RIGHTUP = 16; 10 | MOUSEEVENTF_MIDDLEDOWN = 32; MOUSEEVENTF_MIDDLEUP = 64; 11 | MOUSEEVENTF_XBUTTONDOWN = 128; MOUSEEVENTF_XBUTTONUP = 256; 12 | MOUSEEVENTF_WHEEL = 0x0800; MOUSEEVENTF_HWHEEL = 0x1000; 13 | } 14 | 15 | /// 16 | /// Not really needed as Window keys are the standard being mapped against 17 | /// 18 | public override void PopulateMappings() 19 | { 20 | } 21 | 22 | /// 23 | /// Not really needed here as Window keys are the standard being mapped against. Just return key 24 | /// 25 | /// Windows Virtual Key value 26 | /// Windows Virtual Key value 27 | public override uint GetRealEventKey(uint winVkKey) 28 | { 29 | return winVkKey; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /DS4Windows/DS4Control/OutputKBM/VirtualKBMBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DS4Windows.DS4Control 8 | { 9 | public abstract class VirtualKBMBase 10 | { 11 | protected string errorMessage = string.Empty; 12 | public string ErrorMessage { get => errorMessage; } 13 | 14 | public bool fakeKeyRepeat = false; 15 | 16 | public Version version = new Version("0.0.0.0"); 17 | public string Version 18 | { 19 | get => version.ToString(); 20 | set => version = new Version(value); 21 | } 22 | 23 | public abstract bool Connect(); 24 | public abstract bool Disconnect(); 25 | 26 | public abstract void MoveRelativeMouse(int x, int y); 27 | 28 | public abstract void MoveAbsoluteMouse(double x, double y); 29 | 30 | public abstract void PerformMouseWheelEvent(int vertical, int horizontal); 31 | public abstract void PerformMouseButtonEvent(uint mouseButton); 32 | public virtual void PerformMouseButtonEventAlt(uint mouseButton, int type) 33 | { 34 | 35 | } 36 | 37 | public abstract void PerformMouseButtonPress(uint mouseButton); 38 | public abstract void PerformMouseButtonRelease(uint mouseButton); 39 | 40 | public abstract void PerformKeyPress(uint key); 41 | public abstract void PerformKeyPressAlt(uint key); 42 | public abstract void PerformKeyRelease(uint key); 43 | public abstract void PerformKeyReleaseAlt(uint key); 44 | 45 | public virtual void Sync() 46 | { 47 | } 48 | 49 | public abstract string GetDisplayName(); 50 | public abstract string GetIdentifier(); 51 | 52 | public abstract string GetFullDisplayName(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /DS4Windows/DS4Control/OutputKBM/VirtualKBMFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DS4Windows.DS4Control 4 | { 5 | public static class VirtualKBMFactory 6 | { 7 | public const string DEFAULT_IDENTIFIER = "default"; 8 | 9 | public static VirtualKBMBase DetermineHandler(string identifier = 10 | SendInputHandler.IDENTIFIER) 11 | { 12 | VirtualKBMBase handler = null; 13 | if (identifier == DEFAULT_IDENTIFIER) 14 | { 15 | // Run through event handler discovery routine 16 | if (Global.fakerInputInstalled) 17 | { 18 | handler = new FakerInputHandler(); 19 | } 20 | else 21 | { 22 | // Virtual KB+M driver not found. Use fallback system instead 23 | handler = GetFallbackHandler(); 24 | } 25 | } 26 | else if (identifier == SendInputHandler.IDENTIFIER) 27 | { 28 | handler = new SendInputHandler(); 29 | } 30 | else if (identifier == FakerInputHandler.IDENTIFIER) 31 | { 32 | handler = new FakerInputHandler(); 33 | } 34 | else 35 | { 36 | handler = GetFallbackHandler(); 37 | } 38 | 39 | return handler; 40 | //return new SendInputHandler(); 41 | //return new FakerInputMapping(); 42 | } 43 | 44 | public static VirtualKBMMapping GetMappingInstance(string identifier = 45 | SendInputHandler.IDENTIFIER) 46 | { 47 | VirtualKBMMapping temp = null; 48 | if (identifier == SendInputHandler.IDENTIFIER) 49 | { 50 | temp = new SendInputMapping(); 51 | } 52 | else if (identifier == FakerInputHandler.IDENTIFIER) 53 | { 54 | temp = new FakerInputMapping(); 55 | } 56 | else 57 | { 58 | temp = GetFallbackMapping(); 59 | } 60 | 61 | //VirtualKBMMapping temp = new VMultiMapping(); 62 | //temp.PopulateConstants(); 63 | return temp; 64 | } 65 | 66 | public static VirtualKBMBase GetFallbackHandler() 67 | { 68 | return new SendInputHandler(); 69 | } 70 | 71 | public static VirtualKBMMapping GetFallbackMapping() 72 | { 73 | return new SendInputMapping(); 74 | } 75 | 76 | /// 77 | /// Retrieves identifier string of fallback virtualkbm handler without 78 | /// creating an instance of the handler 79 | /// 80 | /// Identifier string of the default virtualkbm handler 81 | public static string GetFallbackHandlerIdentifier() 82 | { 83 | return SendInputHandler.IDENTIFIER; 84 | } 85 | 86 | public static bool IsValidHandler(string identifier) 87 | { 88 | bool result = false; 89 | switch (identifier) 90 | { 91 | case SendInputHandler.IDENTIFIER: 92 | result = true; 93 | break; 94 | case FakerInputHandler.IDENTIFIER: 95 | result = true; 96 | break; 97 | default: 98 | break; 99 | } 100 | 101 | return result; 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /DS4Windows/DS4Control/OutputKBM/VirtualKBMMapping.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace DS4Windows.DS4Control 3 | { 4 | public abstract class VirtualKBMMapping 5 | { 6 | public uint MOUSEEVENTF_LEFTDOWN = 2, MOUSEEVENTF_LEFTUP = 4, 7 | MOUSEEVENTF_RIGHTDOWN = 8, MOUSEEVENTF_RIGHTUP = 16, 8 | MOUSEEVENTF_MIDDLEDOWN = 32, MOUSEEVENTF_MIDDLEUP = 64, 9 | MOUSEEVENTF_XBUTTONDOWN = 128, MOUSEEVENTF_XBUTTONUP = 256, 10 | MOUSEEVENTF_WHEEL = 0x0800, MOUSEEVENTF_HWHEEL = 0x1000; 11 | 12 | public uint KEY_TAB = 0x09, KEY_LALT = 0x12; 13 | public int WHEEL_TICK_DOWN = -120, WHEEL_TICK_UP = 120; 14 | public bool macroKeyTranslate = false; 15 | 16 | public abstract void PopulateConstants(); 17 | public abstract void PopulateMappings(); 18 | public abstract uint GetRealEventKey(uint winVkKey); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /DS4Windows/DS4Control/OutputSlotPersist.cs: -------------------------------------------------------------------------------- 1 | using DS4Windows; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Xml; 9 | 10 | namespace DS4WinWPF.DS4Control 11 | { 12 | public static class OutputSlotPersist 13 | { 14 | private const string CONFIG_FILENAME = "OutputSlots.xml"; 15 | 16 | public static bool ReadConfig(OutputSlotManager slotManager) 17 | { 18 | bool result = false; 19 | string output_path = Path.Combine(Global.appdatapath, CONFIG_FILENAME); 20 | if (File.Exists(output_path)) 21 | { 22 | XmlDocument m_Xdoc = new XmlDocument(); 23 | try { m_Xdoc.Load(output_path); } 24 | catch (UnauthorizedAccessException) { } 25 | catch (XmlException) { } 26 | 27 | XmlElement rootElement = m_Xdoc.DocumentElement; 28 | if (rootElement == null) return false; 29 | 30 | foreach(XmlElement element in rootElement.GetElementsByTagName("Slot")) 31 | { 32 | OutSlotDevice tempDev = null; 33 | string temp = element.GetAttribute("idx"); 34 | if (int.TryParse(temp, out int idx) && idx >= 0 && idx <= 3) 35 | { 36 | tempDev = slotManager.OutputSlots[idx]; 37 | } 38 | 39 | if (tempDev != null) 40 | { 41 | tempDev.CurrentReserveStatus = OutSlotDevice.ReserveStatus.Permanent; 42 | XmlNode tempNode = element.SelectSingleNode("DeviceType"); 43 | if (tempNode != null && Enum.TryParse(tempNode.InnerText, out OutContType tempType)) 44 | { 45 | tempDev.PermanentType = tempType; 46 | } 47 | } 48 | } 49 | 50 | result = true; 51 | } 52 | 53 | return result; 54 | } 55 | 56 | public static bool WriteConfig(OutputSlotManager slotManager) 57 | { 58 | bool result = false; 59 | XmlDocument m_Xdoc = new XmlDocument(); 60 | XmlNode rootNode; 61 | rootNode = m_Xdoc.CreateXmlDeclaration("1.0", "utf-8", string.Empty); 62 | m_Xdoc.AppendChild(rootNode); 63 | 64 | rootNode = m_Xdoc.CreateComment(string.Format(" Made with DS4Windows version {0} ", Global.exeversion)); 65 | m_Xdoc.AppendChild(rootNode); 66 | 67 | rootNode = m_Xdoc.CreateWhitespace("\r\n"); 68 | m_Xdoc.AppendChild(rootNode); 69 | 70 | XmlElement baseElement = m_Xdoc.CreateElement("OutputSlots", null); 71 | baseElement.SetAttribute("app_version", Global.exeversion); 72 | 73 | int idx = 0; 74 | foreach (OutSlotDevice dev in slotManager.OutputSlots) 75 | { 76 | if (dev.CurrentReserveStatus == OutSlotDevice.ReserveStatus.Permanent) 77 | { 78 | XmlElement slotElement = m_Xdoc.CreateElement("Slot"); 79 | slotElement.SetAttribute("idx", idx.ToString()); 80 | 81 | XmlElement propElement; 82 | propElement = m_Xdoc.CreateElement("DeviceType"); 83 | propElement.InnerText = dev.PermanentType.ToString(); 84 | slotElement.AppendChild(propElement); 85 | 86 | baseElement.AppendChild(slotElement); 87 | } 88 | 89 | idx++; 90 | } 91 | 92 | m_Xdoc.AppendChild(baseElement); 93 | 94 | string output_path = Path.Combine(Global.appdatapath, CONFIG_FILENAME); 95 | try { m_Xdoc.Save(output_path); result = true; } 96 | catch (UnauthorizedAccessException) { result = false; } 97 | 98 | return result; 99 | } 100 | } 101 | } -------------------------------------------------------------------------------- /DS4Windows/DS4Control/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DS4Windows 8 | { 9 | public class Program 10 | { 11 | public static ControlService rootHub; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /DS4Windows/DS4Forms/About.xaml.cs: -------------------------------------------------------------------------------- 1 | using DS4Windows; 2 | using System.Windows; 3 | 4 | namespace DS4WinWPF.DS4Forms 5 | { 6 | /// 7 | /// Interaction logic for About.xaml 8 | /// 9 | public partial class About : Window 10 | { 11 | public About() 12 | { 13 | InitializeComponent(); 14 | 15 | string version = Global.exeversion; 16 | headerLb.Content += version + ")"; 17 | } 18 | 19 | private void ChangeLogLink_Click(object sender, RoutedEventArgs e) 20 | { 21 | Util.StartProcessHelper("https://docs.google.com/document/d/1CovpH08fbPSXrC6TmEprzgPwCe0tTjQ_HTFfDotpmxk/edit?usp=sharing"); 22 | } 23 | 24 | private void PaypalLink_Click(object sender, RoutedEventArgs e) 25 | { 26 | Util.StartProcessHelper("https://paypal.me/ryochan7"); 27 | } 28 | 29 | private void PatreonLink_Click(object sender, RoutedEventArgs e) 30 | { 31 | Util.StartProcessHelper("https://patreon.com/user?u=501036"); 32 | } 33 | 34 | private void SubscribeStartLink_Click(object sender, RoutedEventArgs e) 35 | { 36 | Util.StartProcessHelper("https://subscribestar.com/ryochan7"); 37 | } 38 | 39 | private void SiteLink_Click(object sender, RoutedEventArgs e) 40 | { 41 | Util.StartProcessHelper("https://ryochan7.github.io/ds4windows-site/"); 42 | } 43 | 44 | private void SourceLink_Click(object sender, RoutedEventArgs e) 45 | { 46 | Util.StartProcessHelper("https://github.com/Ryochan7/DS4Windows"); 47 | } 48 | 49 | private void Jays2KingsLink_Click(object sender, RoutedEventArgs e) 50 | { 51 | Util.StartProcessHelper("https://github.com/Jays2Kings/"); 52 | } 53 | 54 | private void InhexSTERLink_Click(object sender, RoutedEventArgs e) 55 | { 56 | Util.StartProcessHelper("https://code.google.com/p/ds4-tool/"); 57 | } 58 | 59 | private void ElectrobrainsLink_Click(object sender, RoutedEventArgs e) 60 | { 61 | Util.StartProcessHelper("https://code.google.com/r/brianfundakowskifeldman-ds4windows/"); 62 | } 63 | 64 | private void YoutubeSocialBtn_Click(object sender, RoutedEventArgs e) 65 | { 66 | Util.StartProcessHelper("https://www.youtube.com/channel/UCIoUA_XLlCSZbvZGeg3Byeg"); 67 | } 68 | 69 | private void BittubeSocialBtn_Click(object sender, RoutedEventArgs e) 70 | { 71 | Util.StartProcessHelper("https://bittube.tv/profile/ds4windows"); 72 | } 73 | 74 | private void TwitterSocialBtn_Click(object sender, RoutedEventArgs e) 75 | { 76 | Util.StartProcessHelper("https://twitter.com/ds4windows"); 77 | } 78 | 79 | private void GithubSocialBtn_Click(object sender, RoutedEventArgs e) 80 | { 81 | Util.StartProcessHelper("https://github.com/Ryochan7/DS4Windows"); 82 | } 83 | 84 | private void ViGEmBusLink_Click(object sender, RoutedEventArgs e) 85 | { 86 | Util.StartProcessHelper("https://vigem.org/"); 87 | } 88 | 89 | private void HidHideLink_Click(object sender, RoutedEventArgs e) 90 | { 91 | Util.StartProcessHelper("https://vigem.org/projects/HidHide/"); 92 | } 93 | 94 | private void Crc32Link_Click(object sender, RoutedEventArgs e) 95 | { 96 | Util.StartProcessHelper("https://github.com/dariogriffo/Crc32"); 97 | } 98 | 99 | private void OneEuroLink_Click(object sender, RoutedEventArgs e) 100 | { 101 | Util.StartProcessHelper("http://cristal.univ-lille.fr/~casiez/1euro/"); 102 | } 103 | 104 | private void FakerInputLink_Click(object sender, RoutedEventArgs e) 105 | { 106 | Util.StartProcessHelper("https://github.com/Ryochan7/FakerInput/"); 107 | } 108 | 109 | private void HNotifyIconLink_Click(object sender, RoutedEventArgs e) 110 | { 111 | Util.StartProcessHelper("https://github.com/HavenDV/H.NotifyIcon/"); 112 | } 113 | } 114 | 115 | public class AboutImgPathLocations 116 | { 117 | private string gitHubImg = 118 | $"{Global.RESOURCES_PREFIX}/social/GitHub-Mark-64px.png"; 119 | public string GitHubImg { get => gitHubImg; } 120 | 121 | public AboutImgPathLocations() 122 | { 123 | App current = App.Current as App; 124 | if (current != null) 125 | { 126 | PopulateFromAppResources(current); 127 | } 128 | } 129 | 130 | private void PopulateFromAppResources(App currentApp) 131 | { 132 | gitHubImg = $"{Global.RESOURCES_PREFIX}/social/{currentApp.FindResource("GitHubImg")}"; 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /DS4Windows/DS4Forms/AxialStickUserControl.xaml: -------------------------------------------------------------------------------- 1 |  14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 62 | 63 | -------------------------------------------------------------------------------- /DS4Windows/DS4Forms/AxialStickUserControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Controls; 3 | using DS4Windows; 4 | using DS4WinWPF.DS4Forms.ViewModels; 5 | 6 | namespace DS4WinWPF.DS4Forms 7 | { 8 | /// 9 | /// Interaction logic for AxialStickUserControl.xaml 10 | /// 11 | public partial class AxialStickUserControl : UserControl 12 | { 13 | private AxialStickControlViewModel axialVM; 14 | public AxialStickControlViewModel AxialVM 15 | { 16 | get => axialVM; 17 | } 18 | 19 | public AxialStickUserControl() 20 | { 21 | InitializeComponent(); 22 | } 23 | 24 | public void UseDevice(StickDeadZoneInfo stickDeadInfo) 25 | { 26 | axialVM = new AxialStickControlViewModel(stickDeadInfo); 27 | mainGrid.DataContext = axialVM; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /DS4Windows/DS4Forms/ChangelogWindow.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 |