//returns the next Press event, if available. should be useful public string GetNextBindEvent() { //this whole process is intimately involved with the data structures, which can conflict with the input thread. lock (this) { if (InputEvents.Count == 0) { return(null); } AllowInput allowInput = GlobalWin.MainForm.AllowInput(false); //we only listen to releases for input binding, because we need to distinguish releases of pure modifierkeys from modified keys //if you just pressed ctrl, wanting to bind ctrl, we'd see: pressed:ctrl, unpressed:ctrl //if you just pressed ctrl+c, wanting to bind ctrl+c, we'd see: pressed:ctrl, pressed:ctrl+c, unpressed:ctrl+c, unpressed:ctrl //so its the first unpress we need to listen for while (InputEvents.Count != 0) { var ie = DequeueEvent(); if (ShouldSwallow(allowInput, ie)) { continue; } //as a special perk, we'll accept escape immediately if (ie.EventType == InputEventType.Press && ie.LogicalButton.Button == "Escape") { goto ACCEPT; } if (ie.EventType == InputEventType.Press) { continue; } ACCEPT: Console.WriteLine("Bind Event: {0} ", ie); foreach (var kvp in LastState) { if (kvp.Value) { Console.WriteLine($"Unpressing {kvp.Key}"); UnpressState[kvp.Key] = true; } } InputEvents.Clear(); return(ie.LogicalButton.ToString()); } return(null); } }
//returns the next Press event, if available. should be useful public string GetNextBindEvent(ref InputEvent lastPress) { //this whole process is intimately involved with the data structures, which can conflict with the input thread. lock (this) { if (_inputEvents.Count == 0) { return(null); } AllowInput allowInput = GlobalWin.MainForm.AllowInput(false); //wait for the first release after a press to complete input binding, because we need to distinguish pure modifierkeys from modified keys //if you just pressed ctrl, wanting to bind ctrl, we'd see: pressed:ctrl, unpressed:ctrl //if you just pressed ctrl+c, wanting to bind ctrl+c, we'd see: pressed:ctrl, pressed:ctrl+c, unpressed:ctrl+c, unpressed:ctrl //but in the 2nd example the unpresses will be swapped if ctrl is released first, so we'll take the last press before the release while (_inputEvents.Count != 0) { InputEvent ie = DequeueEvent(); if (ShouldSwallow(allowInput, ie)) { continue; } if (ie.EventType == InputEventType.Press) { lastPress = ie; //don't allow presses to directly complete binding except escape which we'll accept as a special perk if (ie.LogicalButton.Button != "Escape") { continue; } } else if (lastPress == null) { continue; } Console.WriteLine("Bind Event: {0} ", lastPress); _inputEvents.Clear(); return(lastPress.LogicalButton.ToString()); } return(null); } }
private static bool ShouldSwallow(AllowInput allowInput, InputEvent inputEvent) { return(allowInput == AllowInput.None || (allowInput == AllowInput.OnlyController && inputEvent.Source != InputFocus.Pad)); }
private void UpdateThreadProc() { while (true) { #if true var keyEvents = OTK_Keyboard.Update(); OTK_GamePad.UpdateAll(); #else var keyEvents = OSTailoredCode.IsUnixHost ? OTK_Keyboard.Update() : KeyInput.Update().Concat(IPCKeyInput.Update()); if (OSTailoredCode.IsUnixHost) { OTK_GamePad.UpdateAll(); } else { GamePad.UpdateAll(); GamePad360.UpdateAll(); } #endif //this block is going to massively modify data structures that the binding method uses, so we have to lock it all lock (this) { _newEvents.Clear(); //analyze keys foreach (var ke in keyEvents) { HandleButton(ke.Key.ToString(), ke.Pressed, InputFocus.Keyboard); } lock (_floatValues) { //FloatValues.Clear(); // analyze OpenTK xinput (or is it libinput?) foreach (var pad in OTK_GamePad.EnumerateDevices()) { foreach (var but in pad.buttonObjects) { HandleButton(pad.InputNamePrefix + but.ButtonName, but.ButtonAction(), InputFocus.Pad); } foreach (var sv in pad.GetFloats()) { var n = $"{pad.InputNamePrefix}{sv.Item1} Axis"; var f = sv.Item2; if (_trackDeltas) { _floatDeltas[n] += Math.Abs(f - _floatValues[n]); } _floatValues[n] = f; } } #if false // analyze xinput foreach (var pad in GamePad360.EnumerateDevices()) { string xName = $"X{pad.PlayerNumber} "; for (int b = 0; b < pad.NumButtons; b++) { HandleButton(xName + pad.ButtonName(b), pad.Pressed(b), InputFocus.Pad); } foreach (var sv in pad.GetFloats()) { string n = xName + sv.Item1; float f = sv.Item2; if (_trackDeltas) { _floatDeltas[n] += Math.Abs(f - _floatValues[n]); } _floatValues[n] = f; } } // analyze joysticks foreach (var pad in GamePad.EnumerateDevices()) { string jName = $"J{pad.PlayerNumber} "; for (int b = 0; b < pad.NumButtons; b++) { HandleButton(jName + pad.ButtonName(b), pad.Pressed(b), InputFocus.Pad); } foreach (var sv in pad.GetFloats()) { string n = jName + sv.Item1; float f = sv.Item2; //if (n == "J5 RotationZ") // System.Diagnostics.Debugger.Break(); if (_trackDeltas) { _floatDeltas[n] += Math.Abs(f - _floatValues[n]); } _floatValues[n] = f; } } #endif // analyze moose // other sorts of mouse api (raw input) could easily be added as a separate listing under a different class if (_wantingMouseFocus.Contains(Form.ActiveForm)) { var mousePos = Control.MousePosition; if (_trackDeltas) { // these are relative to screen coordinates, but that's not terribly important _floatDeltas["WMouse X"] += Math.Abs(mousePos.X - _floatValues["WMouse X"]) * 50; _floatDeltas["WMouse Y"] += Math.Abs(mousePos.Y - _floatValues["WMouse Y"]) * 50; } // coordinate translation happens later _floatValues["WMouse X"] = mousePos.X; _floatValues["WMouse Y"] = mousePos.Y; var mouseBtns = Control.MouseButtons; HandleButton("WMouse L", (mouseBtns & MouseButtons.Left) != 0, InputFocus.Mouse); HandleButton("WMouse C", (mouseBtns & MouseButtons.Middle) != 0, InputFocus.Mouse); HandleButton("WMouse R", (mouseBtns & MouseButtons.Right) != 0, InputFocus.Mouse); HandleButton("WMouse 1", (mouseBtns & MouseButtons.XButton1) != 0, InputFocus.Mouse); HandleButton("WMouse 2", (mouseBtns & MouseButtons.XButton2) != 0, InputFocus.Mouse); } else { #if false // don't do this: for now, it will interfere with the virtualpad. don't do something similar for the mouse position either // unpress all buttons HandleButton("WMouse L", false, InputFocus.Mouse); HandleButton("WMouse C", false, InputFocus.Mouse); HandleButton("WMouse R", false, InputFocus.Mouse); HandleButton("WMouse 1", false, InputFocus.Mouse); HandleButton("WMouse 2", false, InputFocus.Mouse); #endif } } if (_newEvents.Count != 0) { //WHAT!? WE SHOULD NOT BE SO NAIVELY TOUCHING MAINFORM FROM THE INPUTTHREAD. ITS BUSY RUNNING. AllowInput allowInput = GlobalWin.MainForm.AllowInput(false); foreach (var ie in _newEvents) { //events are swallowed in some cases: if (ie.LogicalButton.Alt && ShouldSwallow(GlobalWin.MainForm.AllowInput(true), ie)) { continue; } if (ie.EventType == InputEventType.Press && ShouldSwallow(allowInput, ie)) { continue; } EnqueueEvent(ie); } } _ignoreEventsNextPoll = false; } //lock(this) //arbitrary selection of polling frequency: Thread.Sleep(10); } }
private void UpdateThreadProc() { while (true) { _currentConfig = _getConfigCallback(); UpdateModifierKeysEffective(); Adapter.UpdateConfig(_currentConfig); var keyEvents = Adapter.ProcessHostKeyboards(); Adapter.PreprocessHostGamepads(); //this block is going to massively modify data structures that the binding method uses, so we have to lock it all lock (this) { _newEvents.Clear(); //analyze keys foreach (var ke in keyEvents) { HandleButton(DistinctKeyNameOverrides.GetName(in ke.Key), ke.Pressed, ClientInputFocus.Keyboard); } lock (_axisValues) { //_axisValues.Clear(); Adapter.ProcessHostGamepads(HandleButton, HandleAxis); // analyze moose // other sorts of mouse api (raw input) could easily be added as a separate listing under a different class if (_wantingMouseFocus.Contains(Form.ActiveForm)) { var mousePos = Control.MousePosition; if (_trackDeltas) { // these are relative to screen coordinates, but that's not terribly important _axisDeltas["WMouse X"] += Math.Abs(mousePos.X - _axisValues["WMouse X"]) * 50; _axisDeltas["WMouse Y"] += Math.Abs(mousePos.Y - _axisValues["WMouse Y"]) * 50; } // coordinate translation happens later _axisValues["WMouse X"] = mousePos.X; _axisValues["WMouse Y"] = mousePos.Y; var mouseBtns = Control.MouseButtons; HandleButton("WMouse L", (mouseBtns & MouseButtons.Left) != 0, ClientInputFocus.Mouse); HandleButton("WMouse C", (mouseBtns & MouseButtons.Middle) != 0, ClientInputFocus.Mouse); HandleButton("WMouse R", (mouseBtns & MouseButtons.Right) != 0, ClientInputFocus.Mouse); HandleButton("WMouse 1", (mouseBtns & MouseButtons.XButton1) != 0, ClientInputFocus.Mouse); HandleButton("WMouse 2", (mouseBtns & MouseButtons.XButton2) != 0, ClientInputFocus.Mouse); } else { #if false // don't do this: for now, it will interfere with the virtualpad. don't do something similar for the mouse position either // unpress all buttons HandleButton("WMouse L", false, ClientInputFocus.Mouse); HandleButton("WMouse C", false, ClientInputFocus.Mouse); HandleButton("WMouse R", false, ClientInputFocus.Mouse); HandleButton("WMouse 1", false, ClientInputFocus.Mouse); HandleButton("WMouse 2", false, ClientInputFocus.Mouse); #endif } } if (_newEvents.Count != 0) { //WHAT!? WE SHOULD NOT BE SO NAIVELY TOUCHING MAINFORM FROM THE INPUTTHREAD. ITS BUSY RUNNING. AllowInput allowInput = MainFormInputAllowedCallback(false); foreach (var ie in _newEvents) { //events are swallowed in some cases: if ((ie.LogicalButton.Modifiers & LogicalButton.MASK_ALT) is not 0U && ShouldSwallow(MainFormInputAllowedCallback(true), ie)) { continue; } if (ie.EventType == InputEventType.Press && ShouldSwallow(allowInput, ie)) { continue; } EnqueueEvent(ie); } } _ignoreEventsNextPoll = false; } //lock(this) //arbitrary selection of polling frequency: Thread.Sleep(10); } }
void UpdateThreadProc() { while (true) { var keyEvents = OSTailoredCode.CurrentOS == OSTailoredCode.DistinctOS.Windows ? KeyInput.Update().Concat(IPCKeyInput.Update()) : OTK_Keyboard.Update(); if (OSTailoredCode.CurrentOS == OSTailoredCode.DistinctOS.Windows) { GamePad.UpdateAll(); GamePad360.UpdateAll(); } else { //TODO } //this block is going to massively modify data structures that the binding method uses, so we have to lock it all lock (this) { _NewEvents.Clear(); //analyze keys foreach (var ke in keyEvents) { HandleButton(ke.Key.ToString(), ke.Pressed, InputFocus.Keyboard); } lock (FloatValues) { //FloatValues.Clear(); //analyze xinput foreach (var pad in GamePad360.EnumerateDevices()) { string xname = $"X{pad.PlayerNumber} "; for (int b = 0; b < pad.NumButtons; b++) { HandleButton(xname + pad.ButtonName(b), pad.Pressed(b), InputFocus.Pad); } foreach (var sv in pad.GetFloats()) { string n = xname + sv.Item1; float f = sv.Item2; if (trackdeltas) { FloatDeltas[n] += Math.Abs(f - FloatValues[n]); } FloatValues[n] = f; } } //analyze joysticks foreach (var pad in GamePad.EnumerateDevices()) { string jname = $"J{pad.PlayerNumber} "; for (int b = 0; b < pad.NumButtons; b++) { HandleButton(jname + pad.ButtonName(b), pad.Pressed(b), InputFocus.Pad); } foreach (var sv in pad.GetFloats()) { string n = jname + sv.Item1; float f = sv.Item2; //if (n == "J5 RotationZ") // System.Diagnostics.Debugger.Break(); if (trackdeltas) { FloatDeltas[n] += Math.Abs(f - FloatValues[n]); } FloatValues[n] = f; } } // analyse moose // other sorts of mouse api (raw input) could easily be added as a separate listing under a different class if (WantingMouseFocus.Contains(System.Windows.Forms.Form.ActiveForm)) { var P = System.Windows.Forms.Control.MousePosition; if (trackdeltas) { // these are relative to screen coordinates, but that's not terribly important FloatDeltas["WMouse X"] += Math.Abs(P.X - FloatValues["WMouse X"]) * 50; FloatDeltas["WMouse Y"] += Math.Abs(P.Y - FloatValues["WMouse Y"]) * 50; } // coordinate translation happens later FloatValues["WMouse X"] = P.X; FloatValues["WMouse Y"] = P.Y; var B = System.Windows.Forms.Control.MouseButtons; HandleButton("WMouse L", (B & System.Windows.Forms.MouseButtons.Left) != 0, InputFocus.Mouse); HandleButton("WMouse C", (B & System.Windows.Forms.MouseButtons.Middle) != 0, InputFocus.Mouse); HandleButton("WMouse R", (B & System.Windows.Forms.MouseButtons.Right) != 0, InputFocus.Mouse); HandleButton("WMouse 1", (B & System.Windows.Forms.MouseButtons.XButton1) != 0, InputFocus.Mouse); HandleButton("WMouse 2", (B & System.Windows.Forms.MouseButtons.XButton2) != 0, InputFocus.Mouse); } else { //dont do this: for now, it will interfere with the virtualpad. dont do something similar for the mouse position either //unpress all buttons //HandleButton("WMouse L", false); //HandleButton("WMouse C", false); //HandleButton("WMouse R", false); //HandleButton("WMouse 1", false); //HandleButton("WMouse 2", false); } } //WHAT!? WE SHOULD NOT BE SO NAIVELY TOUCHING MAINFORM FROM THE INPUTTHREAD. ITS BUSY RUNNING. AllowInput allowInput = GlobalWin.MainForm.AllowInput(false); foreach (var ie in _NewEvents) { //events are swallowed in some cases: if (ie.LogicalButton.Alt && ShouldSwallow(GlobalWin.MainForm.AllowInput(true), ie)) { } else if (ie.EventType == InputEventType.Press && ShouldSwallow(allowInput, ie)) { } else { EnqueueEvent(ie); } } } //lock(this) //arbitrary selection of polling frequency: Thread.Sleep(10); } }