Option to accept background input only from controller. Closes #1396.

This commit is contained in:
J.D. Purcell 2019-10-13 19:49:17 -04:00
parent 2e31d38568
commit 6504387302
5 changed files with 62 additions and 27 deletions

View File

@ -104,6 +104,7 @@ namespace BizHawk.Client.Common
public int MainHeight = -1; public int MainHeight = -1;
public bool RunInBackground = true; public bool RunInBackground = true;
public bool AcceptBackgroundInput = false; public bool AcceptBackgroundInput = false;
public bool AcceptBackgroundInputControllerOnly = false;
public bool SingleInstanceMode = false; public bool SingleInstanceMode = false;
public bool AllowUD_LR = false; public bool AllowUD_LR = false;
public bool ForbidUD_LR = false; public bool ForbidUD_LR = false;

View File

@ -70,6 +70,13 @@ namespace BizHawk.Client.EmuHawk
Pad = 4 Pad = 4
} }
public enum AllowInput
{
None = 0,
All = 1,
OnlyController = 2
}
/// <summary> /// <summary>
/// If your form needs this kind of input focus, be sure to say so. /// 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 /// 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 LogicalButton LogicalButton;
public InputEventType EventType; public InputEventType EventType;
public InputFocus Source;
public override string ToString() public override string ToString()
{ {
return $"{EventType.ToString()}:{LogicalButton.ToString()}"; return $"{EventType.ToString()}:{LogicalButton.ToString()}";
@ -210,7 +218,7 @@ namespace BizHawk.Client.EmuHawk
private readonly WorkingDictionary<string, float> FloatDeltas = new WorkingDictionary<string, float>(); private readonly WorkingDictionary<string, float> FloatDeltas = new WorkingDictionary<string, float>();
private bool trackdeltas = false; private bool trackdeltas = false;
void HandleButton(string button, bool newState) void HandleButton(string button, bool newState, InputFocus source)
{ {
bool isModifier = IgnoreKeys.Contains(button); bool isModifier = IgnoreKeys.Contains(button);
if (EnableIgnoreModifiers && isModifier) return; if (EnableIgnoreModifiers && isModifier) return;
@ -253,7 +261,8 @@ namespace BizHawk.Client.EmuHawk
var ie = new InputEvent var ie = new InputEvent
{ {
EventType = newState ? InputEventType.Press : InputEventType.Release, EventType = newState ? InputEventType.Press : InputEventType.Release,
LogicalButton = new LogicalButton(button, mods) LogicalButton = new LogicalButton(button, mods),
Source = source
}; };
LastState[button] = newState; LastState[button] = newState;
@ -276,7 +285,8 @@ namespace BizHawk.Client.EmuHawk
var ieModified = new InputEvent var ieModified = new InputEvent
{ {
LogicalButton = (LogicalButton)ModifierState[button], LogicalButton = (LogicalButton)ModifierState[button],
EventType = InputEventType.Release EventType = InputEventType.Release,
Source = source
}; };
if (ieModified.LogicalButton != alreadyReleased) if (ieModified.LogicalButton != alreadyReleased)
_NewEvents.Add(ieModified); _NewEvents.Add(ieModified);
@ -351,7 +361,7 @@ namespace BizHawk.Client.EmuHawk
//analyze keys //analyze keys
foreach (var ke in keyEvents) foreach (var ke in keyEvents)
HandleButton(ke.Key.ToString(), ke.Pressed); HandleButton(ke.Key.ToString(), ke.Pressed, InputFocus.Keyboard);
lock (FloatValues) lock (FloatValues)
{ {
@ -362,7 +372,7 @@ namespace BizHawk.Client.EmuHawk
{ {
string xname = $"X{pad.PlayerNumber} "; string xname = $"X{pad.PlayerNumber} ";
for (int b = 0; b < pad.NumButtons; b++) 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()) foreach (var sv in pad.GetFloats())
{ {
string n = xname + sv.Item1; string n = xname + sv.Item1;
@ -378,7 +388,7 @@ namespace BizHawk.Client.EmuHawk
{ {
string jname = $"J{pad.PlayerNumber} "; string jname = $"J{pad.PlayerNumber} ";
for (int b = 0; b < pad.NumButtons; b++) 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()) foreach (var sv in pad.GetFloats())
{ {
string n = jname + sv.Item1; string n = jname + sv.Item1;
@ -407,11 +417,11 @@ namespace BizHawk.Client.EmuHawk
FloatValues["WMouse Y"] = P.Y; FloatValues["WMouse Y"] = P.Y;
var B = System.Windows.Forms.Control.MouseButtons; var B = System.Windows.Forms.Control.MouseButtons;
HandleButton("WMouse L", (B & System.Windows.Forms.MouseButtons.Left) != 0); HandleButton("WMouse L", (B & System.Windows.Forms.MouseButtons.Left) != 0, InputFocus.Mouse);
HandleButton("WMouse C", (B & System.Windows.Forms.MouseButtons.Middle) != 0); HandleButton("WMouse C", (B & System.Windows.Forms.MouseButtons.Middle) != 0, InputFocus.Mouse);
HandleButton("WMouse R", (B & System.Windows.Forms.MouseButtons.Right) != 0); HandleButton("WMouse R", (B & System.Windows.Forms.MouseButtons.Right) != 0, InputFocus.Mouse);
HandleButton("WMouse 1", (B & System.Windows.Forms.MouseButtons.XButton1) != 0); HandleButton("WMouse 1", (B & System.Windows.Forms.MouseButtons.XButton1) != 0, InputFocus.Mouse);
HandleButton("WMouse 2", (B & System.Windows.Forms.MouseButtons.XButton2) != 0); HandleButton("WMouse 2", (B & System.Windows.Forms.MouseButtons.XButton2) != 0, InputFocus.Mouse);
} }
else else
{ {
@ -427,14 +437,14 @@ namespace BizHawk.Client.EmuHawk
} }
//WHAT!? WE SHOULD NOT BE SO NAIVELY TOUCHING MAINFORM FROM THE INPUTTHREAD. ITS BUSY RUNNING. //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) foreach (var ie in _NewEvents)
{ {
//events are swallowed in some cases: //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 else
EnqueueEvent(ie); 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() public void StartListeningForFloatEvents()
{ {
lock (FloatValues) lock (FloatValues)
@ -490,7 +505,7 @@ namespace BizHawk.Client.EmuHawk
lock (this) lock (this)
{ {
if (InputEvents.Count == 0) return null; 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 //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, wanting to bind ctrl, we'd see: pressed:ctrl, unpressed:ctrl
@ -501,6 +516,8 @@ namespace BizHawk.Client.EmuHawk
{ {
var ie = DequeueEvent(); var ie = DequeueEvent();
if (ShouldSwallow(allowInput, ie)) continue;
//as a special perk, we'll accept escape immediately //as a special perk, we'll accept escape immediately
if (ie.EventType == InputEventType.Press && ie.LogicalButton.Button == "Escape") if (ie.EventType == InputEventType.Press && ie.LogicalButton.Button == "Escape")
goto ACCEPT; goto ACCEPT;

View File

@ -650,12 +650,12 @@ namespace BizHawk.Client.EmuHawk
/// <summary> /// <summary>
/// Controls whether the app generates input events. should be turned off for most modal dialogs /// Controls whether the app generates input events. should be turned off for most modal dialogs
/// </summary> /// </summary>
public bool AllowInput(bool yieldAlt) public Input.AllowInput AllowInput(bool yieldAlt)
{ {
// the main form gets input // the main form gets input
if (ActiveForm == this) if (ActiveForm == this)
{ {
return true; return Input.AllowInput.All;
} }
// even more special logic for TAStudio: // even more special logic for TAStudio:
@ -663,14 +663,9 @@ namespace BizHawk.Client.EmuHawk
var maybeTAStudio = ActiveForm as TAStudio; var maybeTAStudio = ActiveForm as TAStudio;
if (maybeTAStudio != null) if (maybeTAStudio != null)
{ {
if (yieldAlt) if (yieldAlt || maybeTAStudio.IsInMenuLoop)
{ {
return false; return Input.AllowInput.None;
}
if (maybeTAStudio.IsInMenuLoop)
{
return false;
} }
} }
@ -680,16 +675,16 @@ namespace BizHawk.Client.EmuHawk
|| ActiveForm is TAStudio || ActiveForm is TAStudio
|| ActiveForm is VirtualpadTool) || ActiveForm is VirtualpadTool)
{ {
return true; return Input.AllowInput.All;
} }
// if no form is active on this process, then the background input setting applies // if no form is active on this process, then the background input setting applies
if (ActiveForm == null && Global.Config.AcceptBackgroundInput) 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 // TODO: make this an actual property, set it when loading a Rom, and pass it dialogs, etc

View File

@ -42,6 +42,7 @@
this.NeverAskSaveCheckbox = new System.Windows.Forms.CheckBox(); this.NeverAskSaveCheckbox = new System.Windows.Forms.CheckBox();
this.label2 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label();
this.AcceptBackgroundInputCheckbox = new System.Windows.Forms.CheckBox(); this.AcceptBackgroundInputCheckbox = new System.Windows.Forms.CheckBox();
this.AcceptBackgroundInputControllerOnlyCheckBox = new System.Windows.Forms.CheckBox();
this.label1 = new System.Windows.Forms.Label(); this.label1 = new System.Windows.Forms.Label();
this.RunInBackgroundCheckbox = new System.Windows.Forms.CheckBox(); this.RunInBackgroundCheckbox = new System.Windows.Forms.CheckBox();
this.SaveWindowPositionCheckbox = 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.NeverAskSaveCheckbox);
this.tabPage1.Controls.Add(this.label2); this.tabPage1.Controls.Add(this.label2);
this.tabPage1.Controls.Add(this.AcceptBackgroundInputCheckbox); this.tabPage1.Controls.Add(this.AcceptBackgroundInputCheckbox);
this.tabPage1.Controls.Add(this.AcceptBackgroundInputControllerOnlyCheckBox);
this.tabPage1.Controls.Add(this.label1); this.tabPage1.Controls.Add(this.label1);
this.tabPage1.Controls.Add(this.RunInBackgroundCheckbox); this.tabPage1.Controls.Add(this.RunInBackgroundCheckbox);
this.tabPage1.Controls.Add(this.SaveWindowPositionCheckbox); this.tabPage1.Controls.Add(this.SaveWindowPositionCheckbox);
@ -227,6 +229,18 @@
this.AcceptBackgroundInputCheckbox.TabIndex = 8; this.AcceptBackgroundInputCheckbox.TabIndex = 8;
this.AcceptBackgroundInputCheckbox.Text = "Accept background input"; this.AcceptBackgroundInputCheckbox.Text = "Accept background input";
this.AcceptBackgroundInputCheckbox.UseVisualStyleBackColor = true; 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 // label1
// //
@ -593,6 +607,7 @@
private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2; private System.Windows.Forms.Label label2;
private System.Windows.Forms.CheckBox AcceptBackgroundInputCheckbox; private System.Windows.Forms.CheckBox AcceptBackgroundInputCheckbox;
private System.Windows.Forms.CheckBox AcceptBackgroundInputControllerOnlyCheckBox;
private System.Windows.Forms.CheckBox NeverAskSaveCheckbox; private System.Windows.Forms.CheckBox NeverAskSaveCheckbox;
private System.Windows.Forms.Label label3; private System.Windows.Forms.Label label3;
private System.Windows.Forms.CheckBox SingleInstanceModeCheckbox; private System.Windows.Forms.CheckBox SingleInstanceModeCheckbox;

View File

@ -49,6 +49,7 @@ namespace BizHawk.Client.EmuHawk
SaveWindowPositionCheckbox.Checked = Global.Config.SaveWindowPosition; SaveWindowPositionCheckbox.Checked = Global.Config.SaveWindowPosition;
RunInBackgroundCheckbox.Checked = Global.Config.RunInBackground; RunInBackgroundCheckbox.Checked = Global.Config.RunInBackground;
AcceptBackgroundInputCheckbox.Checked = Global.Config.AcceptBackgroundInput; AcceptBackgroundInputCheckbox.Checked = Global.Config.AcceptBackgroundInput;
AcceptBackgroundInputControllerOnlyCheckBox.Checked = Global.Config.AcceptBackgroundInputControllerOnly;
NeverAskSaveCheckbox.Checked = Global.Config.SupressAskSave; NeverAskSaveCheckbox.Checked = Global.Config.SupressAskSave;
SingleInstanceModeCheckbox.Checked = Global.Config.SingleInstanceMode; SingleInstanceModeCheckbox.Checked = Global.Config.SingleInstanceMode;
@ -83,6 +84,7 @@ namespace BizHawk.Client.EmuHawk
Global.Config.SaveWindowPosition = SaveWindowPositionCheckbox.Checked; Global.Config.SaveWindowPosition = SaveWindowPositionCheckbox.Checked;
Global.Config.RunInBackground = RunInBackgroundCheckbox.Checked; Global.Config.RunInBackground = RunInBackgroundCheckbox.Checked;
Global.Config.AcceptBackgroundInput = AcceptBackgroundInputCheckbox.Checked; Global.Config.AcceptBackgroundInput = AcceptBackgroundInputCheckbox.Checked;
Global.Config.AcceptBackgroundInputControllerOnly = AcceptBackgroundInputControllerOnlyCheckBox.Checked;
Global.Config.SupressAskSave = NeverAskSaveCheckbox.Checked; Global.Config.SupressAskSave = NeverAskSaveCheckbox.Checked;
Global.Config.SingleInstanceMode = SingleInstanceModeCheckbox.Checked; Global.Config.SingleInstanceMode = SingleInstanceModeCheckbox.Checked;
@ -113,6 +115,11 @@ namespace BizHawk.Client.EmuHawk
GlobalWin.OSD.AddMessage("Customizing aborted."); 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) private void AutosaveSRAMCheckbox_CheckedChanged(object sender, EventArgs e)
{ {
groupBox2.Enabled = AutosaveSRAMCheckbox.Checked; groupBox2.Enabled = AutosaveSRAMCheckbox.Checked;