aboutsummaryrefslogtreecommitdiff
path: root/src/yuzu_cmd
diff options
context:
space:
mode:
authorSssnowyyy <78863999+Sssnowyyy@users.noreply.github.com>2026-10-30 20:47:12 -0400
committerSssnowyyy <78863999+Sssnowyyy@users.noreply.github.com>2026-10-31 18:16:44 -0400
commitb8813c6797fc9cb00caa834b112668a7161e2b10 (patch)
tree8ab0cd8629f09a40b8771feb19afb1b577b98c31 /src/yuzu_cmd
parent514cc97980e6ddc5f6a4f36631b7d002dc2cd2e0 (diff)
eden-cli: set the window title from the main thread
The titlebar timer runs on SDL's timer thread, and on macOS AppKit throws when a window title is set from there, aborting eden-cli two seconds in. The timer now only prepares the title; the main loop applies it. Assisted-by: Claude Opus 5.5 (code changes, debugging and commit message)
Diffstat (limited to 'src/yuzu_cmd')
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl3.cpp14
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl3.h6
-rw-r--r--src/yuzu_cmd/yuzu.cpp3
3 files changed, 21 insertions, 2 deletions
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl3.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl3.cpp
index ecb8171ac7..93bbbfb8fc 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl3.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl3.cpp
@@ -38,8 +38,10 @@ EmuWindow_SDL3::EmuWindow_SDL3(InputCommon::InputSubsystem* input_subsystem_, Co
titlebar_timer = SDL_AddTimer(2000, [](void *userdata, SDL_TimerID, Uint32) -> Uint32 {
auto* this_ = (EmuWindow_SDL3*)userdata;
auto const results = this_->system.GetAndResetPerfStats();
- auto const title = fmt::format("{} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname, Common::g_scm_branch, Common::g_scm_desc, results.average_game_fps, results.emulation_speed * 100.0f);
- SDL_SetWindowTitle(this_->render_window, title.c_str());
+ auto* const title = new std::string(fmt::format("{} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname, Common::g_scm_branch, Common::g_scm_desc, results.average_game_fps, results.emulation_speed * 100.0f));
+ // Timers run on their own thread and AppKit throws when a title is set off the main
+ // thread: ApplyPendingTitle sets it from the main loop.
+ delete this_->pending_title.exchange(title);
return 2000;
}, this);
mouse_timer = SDL_AddTimer(100, [](void *userdata, SDL_TimerID, Uint32) -> Uint32 {
@@ -55,6 +57,7 @@ EmuWindow_SDL3::EmuWindow_SDL3(InputCommon::InputSubsystem* input_subsystem_, Co
EmuWindow_SDL3::~EmuWindow_SDL3() {
SDL_RemoveTimer(titlebar_timer);
SDL_RemoveTimer(mouse_timer);
+ delete pending_title.exchange(nullptr);
system.HIDCore().UnloadInputDevices();
input_subsystem->Shutdown();
SDL_Quit();
@@ -154,6 +157,13 @@ bool EmuWindow_SDL3::IsOpen() const {
return is_open;
}
+void EmuWindow_SDL3::ApplyPendingTitle() {
+ if (std::string* const title = pending_title.exchange(nullptr)) {
+ SDL_SetWindowTitle(render_window, title->c_str());
+ delete title;
+ }
+}
+
bool EmuWindow_SDL3::IsShown() const {
return is_shown;
}
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl3.h b/src/yuzu_cmd/emu_window/emu_window_sdl3.h
index 0dc2a4983a..a76a2bfd85 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl3.h
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl3.h
@@ -6,7 +6,9 @@
#pragma once
+#include <atomic>
#include <cstdlib>
+#include <string>
#include <tuple>
#include <utility>
@@ -41,6 +43,9 @@ public:
/// Whether the window is still open, and a close request hasn't yet been sent
bool IsOpen() const;
+ /// Sets the title the titlebar timer prepared; call from the main thread.
+ void ApplyPendingTitle();
+
/// Returns if window is shown (not minimized)
bool IsShown() const override;
@@ -92,6 +97,7 @@ protected:
/// Periodic changer of titlebar (independent of event loop)
SDL_TimerID titlebar_timer;
+ std::atomic<std::string*> pending_title{};
// Mouse resetter once it
SDL_TimerID mouse_timer;
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index 22abe6a759..4d71a29993 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -481,6 +481,9 @@ static void RunKeyScript(InputCommon::InputSubsystem& input_subsystem) {
extern "C" SDL_AppResult SDL_AppIterate(void *appstate) {
SdlState *state = (SdlState *)appstate;
RunKeyScript(state->input_subsystem);
+ if (state->emu_window) {
+ state->emu_window->ApplyPendingTitle();
+ }
return state->emu_window && state->emu_window->IsOpen() ? SDL_APP_CONTINUE : SDL_APP_SUCCESS;
}
extern "C" SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {