For anyone looking to exit any emulator using their xbox controller, I've written a AHK script that does two important things. the Back + LB combo presses alt f4 on the keyboard, exiting just about any emulator out there. The Back + RB combo brings BigBox back into focus using a class definition - which it monitors every few seconds. I've found this to be a VERY reliable way to get the focus back when sometimes it looses focus.
Hope this helps others:
; ======================================================
; Xbox One Controller (XInput) — BigBox Simple Focus
; - Back + LB → Alt+F4 (with safety hold)
; - Back + RB → Activate BigBox (auto-detects changing window class)
; AHK v1.1 compatible
; ======================================================
#NoEnv
#SingleInstance, Force
#Persistent
SetBatchLines, -1
Process, Priority,, High
SendMode, Event
SetKeyDelay, 50, 50
; -------- Config --------
userIndex := 0 ; 0 = first controller (try 1/2/3 if needed)
pollMs := 20 ; controller poll interval (ms)
closeHoldMs := 350 ; hold time for Back+LB before Alt+F4 fires (safety)
classRefreshMs := 1000 ; how often to update BigBox's class (ms)
bigBoxExe := "BigBox.exe" ; the process name to look for
; XInput button bitmasks
XINPUT_GAMEPAD_BACK := 0x0020
XINPUT_GAMEPAD_LEFT_SHOULDER := 0x0100 ; LB
XINPUT_GAMEPAD_RIGHT_SHOULDER := 0x0200 ; RB
; -------- State --------
comboCloseArmed := true
comboActivateArmed := true
closeHoldStart := 0
bigBoxClass := "" ; auto-detected class (changes each launch)
lastClassUpdate := 0
; Start timers
SetTimer, PollPad, %pollMs%
SetTimer, UpdateBigBoxClass, %classRefreshMs%
return
; -------- Controller polling --------
PollPad:
buttons := XInput_GetButtons(userIndex)
if (buttons = -1)
return
lbDown := (buttons & XINPUT_GAMEPAD_LEFT_SHOULDER) ? 1 : 0
rbDown := (buttons & XINPUT_GAMEPAD_RIGHT_SHOULDER) ? 1 : 0
backDown := (buttons & XINPUT_GAMEPAD_BACK) ? 1 : 0
; --- Back + LB → Alt+F4 (with safety hold) ---
if (backDown && lbDown) {
if (!closeHoldStart)
closeHoldStart := A_TickCount
if (comboCloseArmed && (A_TickCount - closeHoldStart >= closeHoldMs)) {
SendEvent, {Alt down}
Sleep, 60
SendEvent, {F4}
Sleep, 100
SendEvent, {Alt up}
comboCloseArmed := false
}
} else {
closeHoldStart := 0
if (!backDown && !lbDown)
comboCloseArmed := true
}
; --- Back + RB → Activate BigBox (uses auto-detected class) ---
if (backDown && rbDown && comboActivateArmed) {
ActivateBigBox()
comboActivateArmed := false
}
if (!backDown && !rbDown)
comboActivateArmed := true
return
; -------- BigBox class updater (runs periodically) --------
UpdateBigBoxClass:
DetectHiddenWindows, Off
SetTitleMatchMode, 2
crit := "ahk_exe " . bigBoxExe
WinGet, cnt, List, %crit%
if (cnt >= 1) {
; Find a visible, non-tool window for BigBox and grab its class
Loop, %cnt% {
h := cnt%A_Index%
WinGet, style, Style, ahk_id %h%
WinGet, ex, ExStyle, ahk_id %h%
if !(style & 0x10000000) ; WS_VISIBLE
continue
if (ex & 0x00000080) ; WS_EX_TOOLWINDOW
continue
WinGetClass, cls, ahk_id %h%
if (cls != "") {
if (cls != bigBoxClass) {
bigBoxClass := cls
lastClassUpdate := A_TickCount
; Optional: uncomment for debug
; TrayTip, BigBox, Class updated: %bigBoxClass%, 1000, 1
}
break
}
}
} else {
; Not running: clear class so we don’t target a stale one
bigBoxClass := ""
}
return
; -------- Activate BigBox using the freshest class (or exe as fallback) --------
ActivateBigBox() {
global bigBoxClass, bigBoxExe
DetectHiddenWindows, Off
SetTitleMatchMode, 2
crit := (bigBoxClass != "") ? ("ahk_class " . bigBoxClass) : ("ahk_exe " . bigBoxExe)
if !WinExist(crit)
return
WinGet, h, ID, %crit%
WinActivate, ahk_id %h%
WinWaitActive, ahk_id %h%,, 1
}
; ---- Debug: show current class (Ctrl+Alt+I) ----
^!i::
msg := "BigBox class: " . (bigBoxClass != "" ? bigBoxClass : "<not detected>") . "`n"
msg .= "Last update: " . (lastClassUpdate ? (A_TickCount - lastClassUpdate) . " ms ago" : "n/a")
MsgBox, 64, BigBox Info, %msg%
return
; ---- Quit (Ctrl+Alt+Q) ----
^!q::ExitApp
; ======================================================
; XInput helper (v1.1-safe)
; ======================================================
XInput_GetButtons(userIdx) {
static dll := ""
if (dll = "") {
if (DllCall("LoadLibrary", "Str", "xinput1_4.dll", "Ptr"))
dll := "xinput1_4.dll"
else if (DllCall("LoadLibrary", "Str", "xinput1_3.dll", "Ptr"))
dll := "xinput1_3.dll"
else if (DllCall("LoadLibrary", "Str", "xinput9_1_0.dll", "Ptr"))
dll := "xinput9_1_0.dll"
else if (DllCall("LoadLibrary", "Str", "xinput1_2.dll", "Ptr"))
dll := "xinput1_2.dll"
else if (DllCall("LoadLibrary", "Str", "xinput1_1.dll", "Ptr"))
dll := "xinput1_1.dll"
else
return -1
}
VarSetCapacity(state, 16, 0)
r := DllCall(dll . "\XInputGetState", "UInt", userIdx, "Ptr", &state, "UInt")
if (r != 0)
return -1
return NumGet(state, 4, "UShort") ; wButtons
}
Xbox_Controller_Launchbox_v2.ahk