srctree

Robin Linden parent d5add949 a30458ee
os/system_info: Support getting the system's dark-mode preference

inlinesplit
os/BUILD added: 56, removed: 9, total 47
@@ -64,6 +64,7 @@ cc_library(
"@platforms//os:linux": [],
"@platforms//os:macos": [],
"@platforms//os:windows": [
"-DEFAULTLIB:Advapi32",
"-DEFAULTLIB:Shcore",
"-DEFAULTLIB:User32",
],
 
os/system_info.h added: 56, removed: 9, total 47
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2022-2023 Robin Lindén <dev@robinlinden.eu>
// SPDX-FileCopyrightText: 2022-2024 Robin Lindén <dev@robinlinden.eu>
//
// SPDX-License-Identifier: BSD-2-Clause
 
@@ -7,6 +7,7 @@
 
namespace os {
unsigned active_window_scale_factor();
bool is_dark_mode();
} // namespace os
 
#endif
 
os/system_info_linux.cpp added: 56, removed: 9, total 47
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2021-2023 Robin Lindén <dev@robinlinden.eu>
// SPDX-FileCopyrightText: 2021-2024 Robin Lindén <dev@robinlinden.eu>
//
// SPDX-License-Identifier: BSD-2-Clause
 
@@ -30,6 +30,14 @@ unsigned active_window_scale_factor() {
return 1;
}
 
bool is_dark_mode() {
if (auto const *env_var = std::getenv("HST_DARK_MODE")) {
return std::strcmp(env_var, "1") == 0;
}
 
return false;
}
 
// NOLINTEND(concurrency-mt-unsafe)
 
} // namespace os
 
os/system_info_linux_test.cpp added: 56, removed: 9, total 47
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2022-2023 Robin Lindén <dev@robinlinden.eu>
// SPDX-FileCopyrightText: 2022-2024 Robin Lindén <dev@robinlinden.eu>
//
// SPDX-License-Identifier: BSD-2-Clause
 
@@ -28,6 +28,8 @@ int main() {
unsetenv("GDK_SCALE");
unsetenv("ELM_SCALE");
 
unsetenv("HST_DARK_MODE");
 
s.add_test("active_window_scale_factor", [](etest::IActions &a) {
static constexpr int kOnlyIfUnset = 0;
 
@@ -47,6 +49,19 @@ int main() {
a.expect_eq(os::active_window_scale_factor(), 50u);
});
 
s.add_test("is_dark_mode", [](etest::IActions &a) {
static constexpr int kOverwrite = 1;
 
// We default to false.
a.expect_eq(os::is_dark_mode(), false);
 
setenv("HST_DARK_MODE", "0", kOverwrite);
a.expect_eq(os::is_dark_mode(), false);
 
setenv("HST_DARK_MODE", "1", kOverwrite);
a.expect_eq(os::is_dark_mode(), true);
});
 
return s.run();
}
 
 
os/system_info_windows.cpp added: 56, removed: 9, total 47
@@ -8,14 +8,17 @@
 
#include <shellscalingapi.h>
 
#include <array>
#include <charconv>
#include <cmath>
#include <cstdint>
#include <cstring>
#include <iostream>
 
namespace os {
// NOLINTBEGIN(concurrency-mt-unsafe): We never modify the environment variables.
 
unsigned active_window_scale_factor() {
// NOLINTNEXTLINE(concurrency-mt-unsafe): We never modify the environment variables.
if (auto const *env_var = std::getenv("HST_SCALE")) {
if (int result{}; std::from_chars(env_var, env_var + std::strlen(env_var), result).ec == std::errc{}) {
return result;
@@ -31,4 +34,23 @@ unsigned active_window_scale_factor() {
return static_cast<unsigned>(std::lround(static_cast<float>(scale_factor) / 100.f));
}
 
bool is_dark_mode() {
if (auto const *env_var = std::getenv("HST_DARK_MODE")) {
return std::strcmp(env_var, "1") == 0;
}
 
std::array<std::uint8_t, sizeof(DWORD)> value{};
auto size = static_cast<DWORD>(value.size());
static constexpr auto *kPath = R"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)";
if (auto ret = RegGetValueA(
HKEY_CURRENT_USER, kPath, "AppsUseLightTheme", RRF_RT_REG_DWORD, nullptr, value.data(), &size);
ret != ERROR_SUCCESS) {
std::cerr << "Unable to read system dark mode preference: '" << ret << "'\n";
return false;
}
 
return value[0] == 0;
}
 
// NOLINTEND(concurrency-mt-unsafe)
} // namespace os