mirror of https://github.com/PCSX2/pcsx2.git
Qt: Allow language change without shutting down VM
This commit is contained in:
parent
ce539f30a5
commit
d572765f09
|
@ -457,8 +457,15 @@ void MainWindow::connectVMThreadSignals(EmuThread* thread)
|
||||||
|
|
||||||
void MainWindow::recreate()
|
void MainWindow::recreate()
|
||||||
{
|
{
|
||||||
if (s_vm_valid)
|
const bool was_display_created = m_display_created;
|
||||||
requestShutdown(false, true, EmuConfig.SaveStateOnShutdown);
|
if (was_display_created)
|
||||||
|
{
|
||||||
|
g_emu_thread->setSurfaceless(true);
|
||||||
|
while (m_display_widget || !g_emu_thread->isSurfaceless())
|
||||||
|
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 1);
|
||||||
|
|
||||||
|
m_display_created = false;
|
||||||
|
}
|
||||||
|
|
||||||
// We need to close input sources, because e.g. DInput uses our window handle.
|
// We need to close input sources, because e.g. DInput uses our window handle.
|
||||||
g_emu_thread->closeInputSources();
|
g_emu_thread->closeInputSources();
|
||||||
|
@ -467,6 +474,7 @@ void MainWindow::recreate()
|
||||||
g_main_window = nullptr;
|
g_main_window = nullptr;
|
||||||
|
|
||||||
MainWindow* new_main_window = new MainWindow();
|
MainWindow* new_main_window = new MainWindow();
|
||||||
|
pxAssert(g_main_window == new_main_window);
|
||||||
new_main_window->initialize();
|
new_main_window->initialize();
|
||||||
new_main_window->refreshGameList(false);
|
new_main_window->refreshGameList(false);
|
||||||
new_main_window->show();
|
new_main_window->show();
|
||||||
|
@ -474,6 +482,13 @@ void MainWindow::recreate()
|
||||||
|
|
||||||
// Reload the sources we just closed.
|
// Reload the sources we just closed.
|
||||||
g_emu_thread->reloadInputSources();
|
g_emu_thread->reloadInputSources();
|
||||||
|
|
||||||
|
if (was_display_created)
|
||||||
|
{
|
||||||
|
g_emu_thread->setSurfaceless(false);
|
||||||
|
g_main_window->updateEmulationActions(false, s_vm_valid, Achievements::IsHardcoreModeActive());
|
||||||
|
g_main_window->onFullscreenUIStateChange(g_emu_thread->isRunningFullscreenUI());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::recreateSettings()
|
void MainWindow::recreateSettings()
|
||||||
|
@ -1824,10 +1839,10 @@ void MainWindow::showEvent(QShowEvent* event)
|
||||||
void MainWindow::closeEvent(QCloseEvent* event)
|
void MainWindow::closeEvent(QCloseEvent* event)
|
||||||
{
|
{
|
||||||
// If there's no VM, we can just exit as normal.
|
// If there's no VM, we can just exit as normal.
|
||||||
if (!s_vm_valid)
|
if (!s_vm_valid || !m_display_created)
|
||||||
{
|
{
|
||||||
saveStateToConfig();
|
saveStateToConfig();
|
||||||
if (m_display_widget)
|
if (m_display_created)
|
||||||
g_emu_thread->stopFullscreenUI();
|
g_emu_thread->stopFullscreenUI();
|
||||||
destroySubWindows();
|
destroySubWindows();
|
||||||
QMainWindow::closeEvent(event);
|
QMainWindow::closeEvent(event);
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "common/StringUtil.h"
|
#include "common/StringUtil.h"
|
||||||
|
|
||||||
#include "pcsx2/ImGui/ImGuiManager.h"
|
#include "pcsx2/ImGui/ImGuiManager.h"
|
||||||
|
#include "pcsx2/MTGS.h"
|
||||||
|
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
|
@ -69,8 +70,6 @@ namespace QtHost
|
||||||
static void UpdateGlyphRanges(const std::string_view& language);
|
static void UpdateGlyphRanges(const std::string_view& language);
|
||||||
static const GlyphInfo* GetGlyphInfo(const std::string_view& language);
|
static const GlyphInfo* GetGlyphInfo(const std::string_view& language);
|
||||||
|
|
||||||
static std::vector<ImWchar> s_glyph_ranges;
|
|
||||||
|
|
||||||
static QLocale s_current_locale;
|
static QLocale s_current_locale;
|
||||||
static QCollator s_current_collator;
|
static QCollator s_current_collator;
|
||||||
} // namespace QtHost
|
} // namespace QtHost
|
||||||
|
@ -195,10 +194,18 @@ void QtHost::InstallTranslator()
|
||||||
s_translators.push_back(translator);
|
s_translators.push_back(translator);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateGlyphRanges(language.toStdString());
|
// We end up here both on language change, and on startup.
|
||||||
|
if (g_emu_thread)
|
||||||
// Clear translation cache after installing translators, to prevent races.
|
{
|
||||||
|
Host::RunOnCPUThread([language = language.toStdString()]() {
|
||||||
|
UpdateGlyphRanges(language);
|
||||||
Host::ClearTranslationCache();
|
Host::ClearTranslationCache();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateGlyphRanges(language.toStdString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string QtHost::GetFontPath(const GlyphInfo* gi)
|
static std::string QtHost::GetFontPath(const GlyphInfo* gi)
|
||||||
|
@ -307,10 +314,10 @@ void QtHost::UpdateGlyphRanges(const std::string_view& language)
|
||||||
const GlyphInfo* gi = GetGlyphInfo(language);
|
const GlyphInfo* gi = GetGlyphInfo(language);
|
||||||
|
|
||||||
std::string font_path;
|
std::string font_path;
|
||||||
s_glyph_ranges.clear();
|
std::vector<ImWchar> glyph_ranges;
|
||||||
|
|
||||||
// Base Latin range is always included.
|
// Base Latin range is always included.
|
||||||
s_glyph_ranges.insert(s_glyph_ranges.begin(), std::begin(s_base_latin_range), std::end(s_base_latin_range));
|
glyph_ranges.insert(glyph_ranges.begin(), std::begin(s_base_latin_range), std::end(s_base_latin_range));
|
||||||
|
|
||||||
if (gi)
|
if (gi)
|
||||||
{
|
{
|
||||||
|
@ -321,8 +328,8 @@ void QtHost::UpdateGlyphRanges(const std::string_view& language)
|
||||||
{
|
{
|
||||||
// Always should be in pairs.
|
// Always should be in pairs.
|
||||||
pxAssert(ptr[0] != 0 && ptr[1] != 0);
|
pxAssert(ptr[0] != 0 && ptr[1] != 0);
|
||||||
s_glyph_ranges.push_back(*(ptr++));
|
glyph_ranges.push_back(*(ptr++));
|
||||||
s_glyph_ranges.push_back(*(ptr++));
|
glyph_ranges.push_back(*(ptr++));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,16 +339,25 @@ void QtHost::UpdateGlyphRanges(const std::string_view& language)
|
||||||
// If we don't have any specific glyph range, assume Central European, except if English, then keep the size down.
|
// If we don't have any specific glyph range, assume Central European, except if English, then keep the size down.
|
||||||
if ((!gi || !gi->used_glyphs) && language != "en")
|
if ((!gi || !gi->used_glyphs) && language != "en")
|
||||||
{
|
{
|
||||||
s_glyph_ranges.insert(
|
glyph_ranges.insert(
|
||||||
s_glyph_ranges.begin(), std::begin(s_central_european_ranges), std::end(s_central_european_ranges));
|
glyph_ranges.begin(), std::begin(s_central_european_ranges), std::end(s_central_european_ranges));
|
||||||
}
|
}
|
||||||
|
|
||||||
// List terminator.
|
// List terminator.
|
||||||
s_glyph_ranges.push_back(0);
|
glyph_ranges.push_back(0);
|
||||||
s_glyph_ranges.push_back(0);
|
glyph_ranges.push_back(0);
|
||||||
|
|
||||||
ImGuiManager::SetFontPath(std::move(font_path));
|
// Called on CPU thread, so we need to do this on the GS thread if it's active.
|
||||||
ImGuiManager::SetFontRange(s_glyph_ranges.data());
|
if (MTGS::IsOpen())
|
||||||
|
{
|
||||||
|
MTGS::RunOnGSThread([font_path = std::move(font_path), glyph_ranges = std::move(glyph_ranges)]() mutable {
|
||||||
|
ImGuiManager::SetFontPathAndRange(std::move(font_path), std::move(glyph_ranges));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImGuiManager::SetFontPathAndRange(std::move(font_path), std::move(glyph_ranges));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
|
@ -1233,8 +1233,12 @@ std::string GSDeviceMTL::GetDriverInfo() const
|
||||||
void GSDeviceMTL::ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale)
|
void GSDeviceMTL::ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale)
|
||||||
{
|
{
|
||||||
m_window_info.surface_scale = new_window_scale;
|
m_window_info.surface_scale = new_window_scale;
|
||||||
if (m_window_info.surface_width == static_cast<u32>(new_window_width) && m_window_info.surface_height == static_cast<u32>(new_window_height))
|
if (!m_layer ||
|
||||||
|
(m_window_info.surface_width == static_cast<u32>(new_window_width) && m_window_info.surface_height == static_cast<u32>(new_window_height)))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_window_info.surface_width = new_window_width;
|
m_window_info.surface_width = new_window_width;
|
||||||
m_window_info.surface_height = new_window_height;
|
m_window_info.surface_height = new_window_height;
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
|
|
|
@ -891,8 +891,9 @@ bool GSDeviceOGL::UpdateWindow()
|
||||||
void GSDeviceOGL::ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale)
|
void GSDeviceOGL::ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale)
|
||||||
{
|
{
|
||||||
m_window_info.surface_scale = new_window_scale;
|
m_window_info.surface_scale = new_window_scale;
|
||||||
if (m_window_info.surface_width == static_cast<u32>(new_window_width) &&
|
if (m_window_info.type == WindowInfo::Type::Surfaceless ||
|
||||||
m_window_info.surface_height == static_cast<u32>(new_window_height))
|
(m_window_info.surface_width == static_cast<u32>(new_window_width) &&
|
||||||
|
m_window_info.surface_height == static_cast<u32>(new_window_height)))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2216,7 +2216,7 @@ bool GSDeviceVK::UpdateWindow()
|
||||||
|
|
||||||
void GSDeviceVK::ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale)
|
void GSDeviceVK::ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale)
|
||||||
{
|
{
|
||||||
if (m_swap_chain->GetWidth() == static_cast<u32>(new_window_width) &&
|
if (!m_swap_chain || m_swap_chain->GetWidth() == static_cast<u32>(new_window_width) &&
|
||||||
m_swap_chain->GetHeight() == static_cast<u32>(new_window_height))
|
m_swap_chain->GetHeight() == static_cast<u32>(new_window_height))
|
||||||
{
|
{
|
||||||
// skip unnecessary resizes
|
// skip unnecessary resizes
|
||||||
|
|
|
@ -81,7 +81,7 @@ namespace ImGuiManager
|
||||||
static float s_global_scale = 1.0f;
|
static float s_global_scale = 1.0f;
|
||||||
|
|
||||||
static std::string s_font_path;
|
static std::string s_font_path;
|
||||||
static const ImWchar* s_font_range = nullptr;
|
static std::vector<ImWchar> s_font_range;
|
||||||
|
|
||||||
static ImFont* s_standard_font;
|
static ImFont* s_standard_font;
|
||||||
static ImFont* s_fixed_font;
|
static ImFont* s_fixed_font;
|
||||||
|
@ -112,16 +112,30 @@ static bool s_fullscreen_ui_was_initialized = false;
|
||||||
|
|
||||||
static std::array<ImGuiManager::SoftwareCursor, InputManager::MAX_SOFTWARE_CURSORS> s_software_cursors = {};
|
static std::array<ImGuiManager::SoftwareCursor, InputManager::MAX_SOFTWARE_CURSORS> s_software_cursors = {};
|
||||||
|
|
||||||
void ImGuiManager::SetFontPath(std::string path)
|
void ImGuiManager::SetFontPathAndRange(std::string path, std::vector<u16> range)
|
||||||
{
|
{
|
||||||
s_font_path = std::move(path);
|
if (s_font_path == path && s_font_range == range)
|
||||||
s_standard_font_data = {};
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
void ImGuiManager::SetFontRange(const u16* range)
|
s_font_path = std::move(path);
|
||||||
{
|
s_font_range = std::move(range);
|
||||||
s_font_range = range;
|
|
||||||
s_standard_font_data = {};
|
s_standard_font_data = {};
|
||||||
|
|
||||||
|
if (ImGui::GetCurrentContext())
|
||||||
|
{
|
||||||
|
ImGui::EndFrame();
|
||||||
|
|
||||||
|
if (!LoadFontData())
|
||||||
|
pxFailRel("Failed to load font data");
|
||||||
|
|
||||||
|
if (!AddImGuiFonts(HasFullscreenFonts()))
|
||||||
|
pxFailRel("Failed to create ImGui font text");
|
||||||
|
|
||||||
|
if (!g_gs_device->UpdateImGuiFontTexture())
|
||||||
|
pxFailRel("Failed to recreate font texture after scale+resize");
|
||||||
|
|
||||||
|
NewFrame();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGuiManager::Initialize()
|
bool ImGuiManager::Initialize()
|
||||||
|
@ -235,7 +249,7 @@ void ImGuiManager::UpdateScale()
|
||||||
const float window_scale = g_gs_device ? g_gs_device->GetWindowScale() : 1.0f;
|
const float window_scale = g_gs_device ? g_gs_device->GetWindowScale() : 1.0f;
|
||||||
const float scale = std::max(window_scale * (EmuConfig.GS.OsdScale / 100.0f), 0.5f);
|
const float scale = std::max(window_scale * (EmuConfig.GS.OsdScale / 100.0f), 0.5f);
|
||||||
|
|
||||||
if (scale == s_global_scale && (!HasFullscreenFonts() || !ImGuiFullscreen::UpdateLayoutScale()))
|
if ((!HasFullscreenFonts() || !ImGuiFullscreen::UpdateLayoutScale()) && scale == s_global_scale)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// This is assumed to be called mid-frame.
|
// This is assumed to be called mid-frame.
|
||||||
|
@ -456,7 +470,8 @@ ImFont* ImGuiManager::AddTextFont(float size)
|
||||||
ImFontConfig cfg;
|
ImFontConfig cfg;
|
||||||
cfg.FontDataOwnedByAtlas = false;
|
cfg.FontDataOwnedByAtlas = false;
|
||||||
return ImGui::GetIO().Fonts->AddFontFromMemoryTTF(
|
return ImGui::GetIO().Fonts->AddFontFromMemoryTTF(
|
||||||
s_standard_font_data.data(), static_cast<int>(s_standard_font_data.size()), size, &cfg, s_font_range ? s_font_range : default_ranges);
|
s_standard_font_data.data(), static_cast<int>(s_standard_font_data.size()), size, &cfg,
|
||||||
|
s_font_range.empty() ? default_ranges : s_font_range.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
ImFont* ImGuiManager::AddFixedFont(float size)
|
ImFont* ImGuiManager::AddFixedFont(float size)
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "common/Pcsx2Defs.h"
|
#include "common/Pcsx2Defs.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
struct ImFont;
|
struct ImFont;
|
||||||
|
|
||||||
|
@ -27,10 +28,7 @@ enum class GenericInputBinding : u8;
|
||||||
namespace ImGuiManager
|
namespace ImGuiManager
|
||||||
{
|
{
|
||||||
/// Sets the path to the font to use. Empty string means to use the default.
|
/// Sets the path to the font to use. Empty string means to use the default.
|
||||||
void SetFontPath(std::string path);
|
void SetFontPathAndRange(std::string path, std::vector<u16> range);
|
||||||
|
|
||||||
/// Sets the glyph range to use when loading fonts.
|
|
||||||
void SetFontRange(const u16* range);
|
|
||||||
|
|
||||||
/// Initializes ImGui, creates fonts, etc.
|
/// Initializes ImGui, creates fonts, etc.
|
||||||
bool Initialize();
|
bool Initialize();
|
||||||
|
|
Loading…
Reference in New Issue