From 5819842923af3949c63711b658e4fa28c760318b Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 31 Mar 2026 21:37:48 -0700
Subject: [PATCH] Pause when a controller is disconnected
---
game/controls.cpp | 14 ++++++++------
game/game.cpp | 9 ++++-----
game/gameinfo.cpp | 21 +++++++++++++++++++++
game/gameinfo.h | 11 ++++++++++-
4 files changed, 43 insertions(+), 12 deletions(-)
diff --git a/game/controls.cpp b/game/controls.cpp
index 90231dd1..1ed05ffe 100644
--- a/game/controls.cpp
+++ b/game/controls.cpp
@@ -535,7 +535,7 @@ void HandleEvent(SDL_Event *event)
switch (event->gbutton.button) {
case SDL_GAMEPAD_BUTTON_START:
if (!event->gbutton.down) {
- gGameInfo.ToggleLocalState(STATE_PAUSE);
+ gGameInfo.TogglePauseRequest();
}
break;
case SDL_GAMEPAD_BUTTON_BACK:
@@ -602,7 +602,7 @@ void HandleEvent(SDL_Event *event)
screen->ToggleFullScreen();
break;
} else if ( key == controls.gPauseControl ) {
- gGameInfo.ToggleLocalState(STATE_PAUSE);
+ gGameInfo.TogglePauseRequest();
break;
} else if ( key == controls.gQuitControl ) {
gGameInfo.SetLocalState(STATE_ABORT, true);
@@ -629,11 +629,11 @@ void HandleEvent(SDL_Event *event)
break;
case SDL_EVENT_WINDOW_MINIMIZED:
- gGameInfo.SetLocalState(STATE_MINIMIZE, true);
+ gGameInfo.SetPauseReason(PAUSE_MINIMIZED, true);
break;
case SDL_EVENT_WINDOW_RESTORED:
- gGameInfo.SetLocalState(STATE_MINIMIZE, false);
+ gGameInfo.SetPauseReason(PAUSE_MINIMIZED, false);
break;
}
}
@@ -641,14 +641,16 @@ void HandleEvent(SDL_Event *event)
static bool SDLCALL GamepadEventWatch(void *userdata, SDL_Event *event)
{
switch (event->type) {
- /* -- Handle joystick added */
+ /* -- Handle gamepad added */
case SDL_EVENT_GAMEPAD_ADDED:
OpenGamepad(event->gdevice.which);
+ gGameInfo.SetPauseReason(PAUSE_CONTROLLER, false);
break;
- /* -- Handle joystick removed */
+ /* -- Handle gamepad removed */
case SDL_EVENT_GAMEPAD_REMOVED:
CloseGamepad(event->gdevice.which);
+ gGameInfo.SetPauseReason(PAUSE_CONTROLLER, true);
break;
default:
diff --git a/game/game.cpp b/game/game.cpp
index 9d87eae3..7567ee7b 100644
--- a/game/game.cpp
+++ b/game/game.cpp
@@ -959,7 +959,7 @@ GamePanelDelegate::UpdateGameState()
for (i = 0; i < gGameInfo.GetNumNodes(); ++i) {
Uint8 state = gGameInfo.GetNodeState(i);
paused |= state;
- if (state & (STATE_PAUSE|STATE_MINIMIZE)) {
+ if (state & STATE_PAUSE) {
if (i == gGameInfo.GetLocalIndex()) {
locally_paused = true;
} else {
@@ -967,13 +967,12 @@ GamePanelDelegate::UpdateGameState()
}
}
}
- if ((paused & (STATE_PAUSE|STATE_MINIMIZE)) &&
- !(gPaused & (STATE_PAUSE|STATE_MINIMIZE))) {
+ if ((paused & STATE_PAUSE) && !(gPaused & STATE_PAUSE)) {
sound->PlaySound(gPauseSound, 5);
}
if (m_paused) {
// Update the pause label
- if (paused & (STATE_PAUSE|STATE_MINIMIZE)) {
+ if (paused & STATE_PAUSE) {
char label[128] = { 0 };
if (!locally_paused) {
const GameInfoPlayer *player = gGameInfo.GetPlayer(index_paused);
@@ -986,7 +985,7 @@ GamePanelDelegate::UpdateGameState()
}
m_paused->SetText(label);
m_paused->Show();
- } else if (gPaused & (STATE_PAUSE|STATE_MINIMIZE)) {
+ } else if (gPaused & STATE_PAUSE) {
m_paused->Hide();
}
}
diff --git a/game/gameinfo.cpp b/game/gameinfo.cpp
index 6f6f14bc..36d45e5c 100644
--- a/game/gameinfo.cpp
+++ b/game/gameinfo.cpp
@@ -434,6 +434,27 @@ GameInfo::IsFull() const
return true;
}
+void
+GameInfo::TogglePauseRequest()
+{
+ if (paused & (PAUSE_REQUEST|PAUSE_CONTROLLER)) {
+ SetPauseReason((PAUSE_REQUEST|PAUSE_CONTROLLER), false);
+ } else {
+ SetPauseReason(PAUSE_REQUEST, true);
+ }
+}
+
+void
+GameInfo::SetPauseReason(Uint8 reason, bool enabled)
+{
+ if (enabled) {
+ paused |= reason;
+ } else {
+ paused &= ~reason;
+ }
+ SetLocalState(STATE_PAUSE, paused ? true : false);
+}
+
void
GameInfo::SetLocalState(Uint8 state, bool enabled)
{
diff --git a/game/gameinfo.h b/game/gameinfo.h
index 2b431e7f..f7b0642e 100644
--- a/game/gameinfo.h
+++ b/game/gameinfo.h
@@ -56,10 +56,15 @@ enum NODE_STATE_FLAG {
STATE_ABORT = 0x01,
STATE_PAUSE = 0x02,
STATE_BONUS = 0x04,
- STATE_MINIMIZE = 0x08,
STATE_DIALOG = 0x10,
};
+enum PAUSE_REASON {
+ PAUSE_REQUEST = 0x01,
+ PAUSE_MINIMIZED = 0x02,
+ PAUSE_CONTROLLER = 0x04,
+};
+
enum PING_STATUS {
PING_LOCAL,
PING_GOOD,
@@ -203,6 +208,8 @@ class GameInfo
void SetNodeState(int index, Uint8 state);
Uint8 GetNodeState(int index) const;
+ void TogglePauseRequest();
+ void SetPauseReason(Uint8 reason, bool enabled);
void SetLocalState(Uint8 state, bool enabled);
void ToggleLocalState(Uint8 state);
Uint8 GetLocalState() const {
@@ -231,6 +238,8 @@ class GameInfo
Uint32 localID;
+ Uint8 paused;
+
protected:
Uint8 numNodes;
GameInfoNode nodes[MAX_NODES];