diff --git a/BizHawk.Client.Common/config/Config.cs b/BizHawk.Client.Common/config/Config.cs index 057ec89c0b..b48b85a0dc 100644 --- a/BizHawk.Client.Common/config/Config.cs +++ b/BizHawk.Client.Common/config/Config.cs @@ -104,6 +104,7 @@ namespace BizHawk.Client.Common public int MainHeight = -1; public bool RunInBackground = true; public bool AcceptBackgroundInput = false; + public bool AcceptBackgroundInputControllerOnly = false; public bool SingleInstanceMode = false; public bool AllowUD_LR = false; public bool ForbidUD_LR = false; diff --git a/BizHawk.Client.EmuHawk/Input/Input.cs b/BizHawk.Client.EmuHawk/Input/Input.cs index a890029682..d187149c59 100644 --- a/BizHawk.Client.EmuHawk/Input/Input.cs +++ b/BizHawk.Client.EmuHawk/Input/Input.cs @@ -70,6 +70,13 @@ namespace BizHawk.Client.EmuHawk Pad = 4 } + public enum AllowInput + { + None = 0, + All = 1, + OnlyController = 2 + } + /// /// If your form needs this kind of input focus, be sure to say so. /// Really, this only makes sense for mouse, but I've started building it out for other things @@ -196,6 +203,7 @@ namespace BizHawk.Client.EmuHawk { public LogicalButton LogicalButton; public InputEventType EventType; + public InputFocus Source; public override string ToString() { return $"{EventType.ToString()}:{LogicalButton.ToString()}"; @@ -210,7 +218,7 @@ namespace BizHawk.Client.EmuHawk private readonly WorkingDictionary FloatDeltas = new WorkingDictionary(); private bool trackdeltas = false; - void HandleButton(string button, bool newState) + void HandleButton(string button, bool newState, InputFocus source) { bool isModifier = IgnoreKeys.Contains(button); if (EnableIgnoreModifiers && isModifier) return; @@ -253,7 +261,8 @@ namespace BizHawk.Client.EmuHawk var ie = new InputEvent { EventType = newState ? InputEventType.Press : InputEventType.Release, - LogicalButton = new LogicalButton(button, mods) + LogicalButton = new LogicalButton(button, mods), + Source = source }; LastState[button] = newState; @@ -276,7 +285,8 @@ namespace BizHawk.Client.EmuHawk var ieModified = new InputEvent { LogicalButton = (LogicalButton)ModifierState[button], - EventType = InputEventType.Release + EventType = InputEventType.Release, + Source = source }; if (ieModified.LogicalButton != alreadyReleased) _NewEvents.Add(ieModified); @@ -351,7 +361,7 @@ namespace BizHawk.Client.EmuHawk //analyze keys foreach (var ke in keyEvents) - HandleButton(ke.Key.ToString(), ke.Pressed); + HandleButton(ke.Key.ToString(), ke.Pressed, InputFocus.Keyboard); lock (FloatValues) { @@ -362,7 +372,7 @@ namespace BizHawk.Client.EmuHawk { string xname = $"X{pad.PlayerNumber} "; for (int b = 0; b < pad.NumButtons; b++) - HandleButton(xname + pad.ButtonName(b), pad.Pressed(b)); + HandleButton(xname + pad.ButtonName(b), pad.Pressed(b), InputFocus.Pad); foreach (var sv in pad.GetFloats()) { string n = xname + sv.Item1; @@ -378,7 +388,7 @@ namespace BizHawk.Client.EmuHawk { string jname = $"J{pad.PlayerNumber} "; for (int b = 0; b < pad.NumButtons; b++) - HandleButton(jname + pad.ButtonName(b), pad.Pressed(b)); + HandleButton(jname + pad.ButtonName(b), pad.Pressed(b), InputFocus.Pad); foreach (var sv in pad.GetFloats()) { string n = jname + sv.Item1; @@ -407,11 +417,11 @@ namespace BizHawk.Client.EmuHawk FloatValues["WMouse Y"] = P.Y; var B = System.Windows.Forms.Control.MouseButtons; - HandleButton("WMouse L", (B & System.Windows.Forms.MouseButtons.Left) != 0); - HandleButton("WMouse C", (B & System.Windows.Forms.MouseButtons.Middle) != 0); - HandleButton("WMouse R", (B & System.Windows.Forms.MouseButtons.Right) != 0); - HandleButton("WMouse 1", (B & System.Windows.Forms.MouseButtons.XButton1) != 0); - HandleButton("WMouse 2", (B & System.Windows.Forms.MouseButtons.XButton2) != 0); + 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 { @@ -427,14 +437,14 @@ namespace BizHawk.Client.EmuHawk } //WHAT!? WE SHOULD NOT BE SO NAIVELY TOUCHING MAINFORM FROM THE INPUTTHREAD. ITS BUSY RUNNING. - bool swallow = !GlobalWin.MainForm.AllowInput(false); + AllowInput allowInput = GlobalWin.MainForm.AllowInput(false); foreach (var ie in _NewEvents) { //events are swallowed in some cases: - if (ie.LogicalButton.Alt && !GlobalWin.MainForm.AllowInput(true)) + if (ie.LogicalButton.Alt && ShouldSwallow(GlobalWin.MainForm.AllowInput(true), ie)) { } - else if (ie.EventType == InputEventType.Press && swallow) + else if (ie.EventType == InputEventType.Press && ShouldSwallow(allowInput, ie)) { } else EnqueueEvent(ie); @@ -446,6 +456,11 @@ namespace BizHawk.Client.EmuHawk } } + private static bool ShouldSwallow(AllowInput allowInput, InputEvent inputEvent) + { + return allowInput == AllowInput.None || (allowInput == AllowInput.OnlyController && inputEvent.Source != InputFocus.Pad); + } + public void StartListeningForFloatEvents() { lock (FloatValues) @@ -490,7 +505,7 @@ namespace BizHawk.Client.EmuHawk lock (this) { if (InputEvents.Count == 0) return null; - if (!GlobalWin.MainForm.AllowInput(false)) 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 @@ -501,6 +516,8 @@ namespace BizHawk.Client.EmuHawk { 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; diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs index 444e73cc3d..0d32cd12f9 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -650,12 +650,12 @@ namespace BizHawk.Client.EmuHawk /// /// Controls whether the app generates input events. should be turned off for most modal dialogs /// - public bool AllowInput(bool yieldAlt) + public Input.AllowInput AllowInput(bool yieldAlt) { // the main form gets input if (ActiveForm == this) { - return true; + return Input.AllowInput.All; } // even more special logic for TAStudio: @@ -663,14 +663,9 @@ namespace BizHawk.Client.EmuHawk var maybeTAStudio = ActiveForm as TAStudio; if (maybeTAStudio != null) { - if (yieldAlt) + if (yieldAlt || maybeTAStudio.IsInMenuLoop) { - return false; - } - - if (maybeTAStudio.IsInMenuLoop) - { - return false; + return Input.AllowInput.None; } } @@ -680,16 +675,16 @@ namespace BizHawk.Client.EmuHawk || ActiveForm is TAStudio || ActiveForm is VirtualpadTool) { - return true; + return Input.AllowInput.All; } // if no form is active on this process, then the background input setting applies if (ActiveForm == null && Global.Config.AcceptBackgroundInput) { - return true; + return Global.Config.AcceptBackgroundInputControllerOnly ? Input.AllowInput.OnlyController : Input.AllowInput.All; } - return false; + return Input.AllowInput.None; } // TODO: make this an actual property, set it when loading a Rom, and pass it dialogs, etc diff --git a/BizHawk.Client.EmuHawk/config/GuiOptions.Designer.cs b/BizHawk.Client.EmuHawk/config/GuiOptions.Designer.cs index 70e35459eb..1daf1356b7 100644 --- a/BizHawk.Client.EmuHawk/config/GuiOptions.Designer.cs +++ b/BizHawk.Client.EmuHawk/config/GuiOptions.Designer.cs @@ -42,6 +42,7 @@ this.NeverAskSaveCheckbox = new System.Windows.Forms.CheckBox(); this.label2 = new System.Windows.Forms.Label(); this.AcceptBackgroundInputCheckbox = new System.Windows.Forms.CheckBox(); + this.AcceptBackgroundInputControllerOnlyCheckBox = new System.Windows.Forms.CheckBox(); this.label1 = new System.Windows.Forms.Label(); this.RunInBackgroundCheckbox = new System.Windows.Forms.CheckBox(); this.SaveWindowPositionCheckbox = new System.Windows.Forms.CheckBox(); @@ -124,6 +125,7 @@ this.tabPage1.Controls.Add(this.NeverAskSaveCheckbox); this.tabPage1.Controls.Add(this.label2); this.tabPage1.Controls.Add(this.AcceptBackgroundInputCheckbox); + this.tabPage1.Controls.Add(this.AcceptBackgroundInputControllerOnlyCheckBox); this.tabPage1.Controls.Add(this.label1); this.tabPage1.Controls.Add(this.RunInBackgroundCheckbox); this.tabPage1.Controls.Add(this.SaveWindowPositionCheckbox); @@ -227,6 +229,18 @@ this.AcceptBackgroundInputCheckbox.TabIndex = 8; this.AcceptBackgroundInputCheckbox.Text = "Accept background input"; this.AcceptBackgroundInputCheckbox.UseVisualStyleBackColor = true; + this.AcceptBackgroundInputCheckbox.CheckedChanged += new System.EventHandler(this.AcceptBackgroundInputCheckbox_CheckedChanged); + // + // AcceptBackgroundInputControllerOnlyCheckBox + // + this.AcceptBackgroundInputControllerOnlyCheckBox.AutoSize = true; + this.AcceptBackgroundInputControllerOnlyCheckBox.Enabled = false; + this.AcceptBackgroundInputControllerOnlyCheckBox.Location = new System.Drawing.Point(156, 135); + this.AcceptBackgroundInputControllerOnlyCheckBox.Name = "AcceptBackgroundInputControllerOnlyCheckBox"; + this.AcceptBackgroundInputControllerOnlyCheckBox.Size = new System.Drawing.Size(117, 17); + this.AcceptBackgroundInputControllerOnlyCheckBox.TabIndex = 14; + this.AcceptBackgroundInputControllerOnlyCheckBox.Text = "From controller only"; + this.AcceptBackgroundInputControllerOnlyCheckBox.UseVisualStyleBackColor = true; // // label1 // @@ -593,6 +607,7 @@ private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label2; private System.Windows.Forms.CheckBox AcceptBackgroundInputCheckbox; + private System.Windows.Forms.CheckBox AcceptBackgroundInputControllerOnlyCheckBox; private System.Windows.Forms.CheckBox NeverAskSaveCheckbox; private System.Windows.Forms.Label label3; private System.Windows.Forms.CheckBox SingleInstanceModeCheckbox; diff --git a/BizHawk.Client.EmuHawk/config/GuiOptions.cs b/BizHawk.Client.EmuHawk/config/GuiOptions.cs index d5106c9d24..76e29d2a03 100644 --- a/BizHawk.Client.EmuHawk/config/GuiOptions.cs +++ b/BizHawk.Client.EmuHawk/config/GuiOptions.cs @@ -49,6 +49,7 @@ namespace BizHawk.Client.EmuHawk SaveWindowPositionCheckbox.Checked = Global.Config.SaveWindowPosition; RunInBackgroundCheckbox.Checked = Global.Config.RunInBackground; AcceptBackgroundInputCheckbox.Checked = Global.Config.AcceptBackgroundInput; + AcceptBackgroundInputControllerOnlyCheckBox.Checked = Global.Config.AcceptBackgroundInputControllerOnly; NeverAskSaveCheckbox.Checked = Global.Config.SupressAskSave; SingleInstanceModeCheckbox.Checked = Global.Config.SingleInstanceMode; @@ -83,6 +84,7 @@ namespace BizHawk.Client.EmuHawk Global.Config.SaveWindowPosition = SaveWindowPositionCheckbox.Checked; Global.Config.RunInBackground = RunInBackgroundCheckbox.Checked; Global.Config.AcceptBackgroundInput = AcceptBackgroundInputCheckbox.Checked; + Global.Config.AcceptBackgroundInputControllerOnly = AcceptBackgroundInputControllerOnlyCheckBox.Checked; Global.Config.SupressAskSave = NeverAskSaveCheckbox.Checked; Global.Config.SingleInstanceMode = SingleInstanceModeCheckbox.Checked; @@ -113,6 +115,11 @@ namespace BizHawk.Client.EmuHawk GlobalWin.OSD.AddMessage("Customizing aborted."); } + private void AcceptBackgroundInputCheckbox_CheckedChanged(object sender, EventArgs e) + { + AcceptBackgroundInputControllerOnlyCheckBox.Enabled = AcceptBackgroundInputCheckbox.Checked; + } + private void AutosaveSRAMCheckbox_CheckedChanged(object sender, EventArgs e) { groupBox2.Enabled = AutosaveSRAMCheckbox.Checked;