Skip to content

Commit be32e94

Browse files
committed
frontend: Add utf-8 manifest and move locale setup
Utf-8 manifest allows Win32 API to use utf-8 instead of ANSI codepages. This changes the "A" versions of fucntions to work with utf-8. Manifest also treats command line arguments as utf8. This allows for example --profile <name> to load profiles with special characters. The locale setup routine is moved to the beginning of program to better cover io streams, without the need to reconfigure them later. The caveat is that unix will need to re-do the routine after initilizing OBSApp, because Qt overwrites the locales for unix during it's construction. Added logging for locale info and app language to better diagnose potential errors.
1 parent 40ed1a1 commit be32e94

File tree

3 files changed

+56
-43
lines changed

3 files changed

+56
-43
lines changed

frontend/OBSApp.cpp

Lines changed: 5 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151

5252
#ifdef _WIN32
5353
#include <sstream>
54-
#include <mbctype.h>
5554
#define WIN32_LEAN_AND_MEAN
5655
#include <windows.h>
5756
#else
@@ -871,53 +870,13 @@ std::vector<UpdateBranch> OBSApp::GetBranches()
871870
return out;
872871
}
873872

874-
static bool set_utf8_locale(void)
875-
{
876-
// Use system locale with UTF-8 codepage (available from Windows 10 version 1803)
877-
bool usingUTF8 = !!setlocale(LC_ALL, ".UTF-8");
878-
879-
#ifdef _WIN32
880-
usingUTF8 = usingUTF8 && (_setmbcp(CP_UTF8) == 0);
881-
#endif
882-
883-
/*
884-
Fallback to minimal C locale
885-
Could use "" for system defaults, but the Windows default ANSI codepages (.125x or .9xx)
886-
mismatch with UTF-8 that is assumed by many parts of the codebase. "C" only covers ASCII, so no mismatches.
887-
*/
888-
usingUTF8 = usingUTF8 || !!setlocale(LC_ALL, "C.UTF-8");
889-
if (!usingUTF8)
890-
setlocale(LC_ALL, "C");
891-
892-
// fix float handling
893-
setlocale(LC_NUMERIC, "C");
894-
895-
// Copy C runtime locale for C++
896-
std::locale defaultLocale(setlocale(LC_ALL, nullptr));
897-
std::locale::global(defaultLocale);
898-
899-
/*
900-
system() is already the QLocale default, but just to be explicit about the intention.
901-
Unlike CRT and C++ locales above, QLocale doesn't support customization of locale categories and codepages.
902-
Ie. We can't enforce decimal point to be a dot and at the same time use user's preferred locale.
903-
*/
904-
QLocale::setDefault(QLocale::system());
905-
906-
blog(LOG_INFO, "Set locale to: %s", defaultLocale.name().c_str());
907-
908-
return usingUTF8;
909-
}
910-
911873
OBSApp::OBSApp(int &argc, char **argv, profiler_name_store_t *store)
912874
: QApplication(argc, argv),
913875
profilerNameStore(store),
914876
appLaunchUUID_(QUuid::createUuid())
915877
{
916878
installNativeEventFilter(new OBS::NativeEventFilter);
917879

918-
if (!set_utf8_locale())
919-
blog(LOG_WARNING, "Failed to set UTF-8 codepage for locales");
920-
921880
#ifndef _WIN32
922881
/* Handle SIGINT properly */
923882
socketpair(AF_UNIX, SOCK_STREAM, 0, sigintFd);
@@ -1250,6 +1209,11 @@ bool OBSApp::OBSInit()
12501209

12511210
obs_set_ui_task_handler(ui_task_handler);
12521211

1212+
QString localeStr(std::locale().name().c_str());
1213+
1214+
blog(LOG_INFO, "Locale: %s", QT_TO_UTF8(localeStr.replace(";", "\n\t")));
1215+
blog(LOG_INFO, "App language: %s", locale.c_str());
1216+
12531217
#if defined(_WIN32) || defined(__APPLE__) || defined(__linux__)
12541218
bool browserHWAccel = config_get_bool(appConfig, "General", "BrowserHWAccel");
12551219

frontend/cmake/windows/obs.manifest

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
</requestedPrivileges>
1212
</security>
1313
</trustInfo>
14+
<application>
15+
<windowsSettings>
16+
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
17+
</windowsSettings>
18+
</application>
1419
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
1520
<application>
1621
<!-- Windows 10 and Windows 11 -->

frontend/obs-main.cpp

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include <shellapi.h>
4646
#define WIN32_LEAN_AND_MEAN
4747
#include <windows.h>
48+
#include <mbctype.h>
4849
#else
4950
#include <signal.h>
5051
#endif
@@ -77,6 +78,7 @@ bool opt_disable_missing_files_check = false;
7778
string opt_starting_collection;
7879
string opt_starting_profile;
7980
string opt_starting_scene;
81+
bool using_utf8 = false;
8082

8183
bool restart = false;
8284
bool restart_safe = false;
@@ -408,8 +410,6 @@ static void create_log_file(fstream &logFile)
408410

409411
BPtr<char> path(GetAppConfigPathPtr(dst.str().c_str()));
410412

411-
logFile.imbue(std::locale());
412-
413413
#ifdef _WIN32
414414
BPtr<wchar_t> wpath;
415415
os_utf8_to_wcs_ptr(path, 0, &wpath);
@@ -426,6 +426,41 @@ static void create_log_file(fstream &logFile)
426426
}
427427
}
428428

429+
static bool set_utf8_locale(void)
430+
{
431+
// Use system locale with UTF-8 codepage (available from Windows 10 version 1803)
432+
bool usingUTF8 = !!setlocale(LC_ALL, ".UTF-8");
433+
434+
/*
435+
Fallback to minimal C locale
436+
Could use "" for system defaults, but the Windows default ANSI codepages (such as .125x or .9xx)
437+
mismatch with UTF-8 that is assumed by many parts of the codebase. "C" only covers ASCII, so no mismatches.
438+
*/
439+
usingUTF8 = usingUTF8 || !!setlocale(LC_ALL, "C.UTF-8");
440+
441+
#ifdef _WIN32
442+
usingUTF8 = usingUTF8 && (_setmbcp(CP_UTF8) == 0);
443+
#endif
444+
if (!usingUTF8)
445+
setlocale(LC_ALL, "C");
446+
447+
// fix float handling
448+
setlocale(LC_NUMERIC, "C");
449+
450+
// Copy C runtime locale for C++
451+
std::locale defaultLocale(setlocale(LC_ALL, nullptr));
452+
std::locale::global(defaultLocale);
453+
454+
/*
455+
system() is already the QLocale default, but just to be explicit about the intention.
456+
Unlike CRT and C++ locales above, QLocale doesn't support customization of locale categories and codepages.
457+
Ie. We can't enforce decimal point to be a dot and at the same time use user's preferred locale.
458+
*/
459+
QLocale::setDefault(QLocale::system());
460+
461+
return usingUTF8;
462+
}
463+
429464
static auto ProfilerNameStoreRelease = [](profiler_name_store_t *store) {
430465
profiler_name_store_free(store);
431466
};
@@ -538,6 +573,14 @@ static int run_program(fstream &logFile, int argc, char *argv[])
538573
qputenv("QT_NO_SUBTRACTOPAQUESIBLINGS", "1");
539574

540575
OBSApp program(argc, argv, profilerNameStore.get());
576+
577+
#if defined(Q_OS_UNIX)
578+
// OBSApp (QApplication) constructor overwrote the locale for unix, so set it again
579+
using_utf8 = set_utf8_locale();
580+
#endif
581+
if (!using_utf8)
582+
blog(LOG_WARNING, "Failed to set UTF-8 locale");
583+
541584
try {
542585
QAccessible::installFactory(accessibleFactory);
543586
QFontDatabase::addApplicationFont(":/fonts/OpenSans-Regular.ttf");
@@ -858,6 +901,7 @@ static bool vc_runtime_outdated()
858901

859902
int main(int argc, char *argv[])
860903
{
904+
using_utf8 = set_utf8_locale();
861905
#ifndef _WIN32
862906
signal(SIGPIPE, SIG_IGN);
863907

0 commit comments

Comments
 (0)