mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-04 23:55:08 +01:00
Make every setting observable individually
A `Setting` delegate class has been introduced, holding the raw value of the setting and adding support for registering callbacks to that setting. Callbacks will then be called when the value of that setting changes. As a result of this, raw setting values have been made accessible through pointer dereference semantics.
This commit is contained in:
parent
2d70be60d1
commit
3905728447
@ -60,8 +60,6 @@ template<> void skyline::Settings::Update<skyline::KtSettings>(KtSettings newSet
|
||||
systemLanguage = newSettings.GetInt<skyline::language::SystemLanguage>("systemLanguage");
|
||||
forceTripleBuffering = newSettings.GetBool("forceTripleBuffering");
|
||||
disableFrameThrottling = newSettings.GetBool("disableFrameThrottling");
|
||||
|
||||
OnSettingsChanged();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_emu_skyline_SkylineApplication_initializeLog(
|
||||
|
@ -4,16 +4,6 @@
|
||||
#include "settings.h"
|
||||
|
||||
namespace skyline {
|
||||
void Settings::Subscribe(Callback callback) {
|
||||
callbacks.push_back(std::move(callback));
|
||||
}
|
||||
|
||||
void Settings::OnSettingsChanged() {
|
||||
std::for_each(callbacks.begin(), callbacks.end(), [&](const Callback& listener) {
|
||||
listener(*this);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @note This is a placeholder implementation, it must be overridden via template specialisation for platform-specific behavior
|
||||
*/
|
||||
|
@ -10,15 +10,55 @@ namespace skyline {
|
||||
* @brief The Settings class is used to access preferences set in the Kotlin component of Skyline
|
||||
*/
|
||||
class Settings {
|
||||
template<typename T>
|
||||
class Setting {
|
||||
using Callback = std::function<void(const T &)>;
|
||||
std::vector<Callback> callbacks; //!< Callbacks to be called when this setting changes
|
||||
T value;
|
||||
|
||||
/**
|
||||
* @brief Calls all callbacks registered for this setting
|
||||
*/
|
||||
void OnSettingChanged() {
|
||||
for (const auto &callback : callbacks)
|
||||
callback(value);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @return The underlying setting value
|
||||
*/
|
||||
const T &operator*() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the underlying setting value, signalling any callbacks if necessary
|
||||
*/
|
||||
void operator=(T newValue) {
|
||||
if (value != newValue) {
|
||||
value = std::move(newValue);
|
||||
OnSettingChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register a callback to be run when this setting changes
|
||||
*/
|
||||
void AddCallback(Callback callback) {
|
||||
callbacks.push_back(std::move(callback));
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
// System
|
||||
bool isDocked; //!< If the emulated Switch should be handheld or docked
|
||||
std::string usernameValue; //!< The name set by the user to be supplied to the guest
|
||||
language::SystemLanguage systemLanguage; //!< The system language set by the user
|
||||
Setting<bool> isDocked; //!< If the emulated Switch should be handheld or docked
|
||||
Setting<std::string> usernameValue; //!< The user name to be supplied to the guest
|
||||
Setting<language::SystemLanguage> systemLanguage; //!< The system language
|
||||
|
||||
// Display
|
||||
bool forceTripleBuffering; //!< If the presentation engine should always triple buffer even if the swapchain supports double buffering
|
||||
bool disableFrameThrottling; //!< Allow the guest to submit frames without any blocking calls
|
||||
Setting<bool> forceTripleBuffering; //!< If the presentation engine should always triple buffer even if the swapchain supports double buffering
|
||||
Setting<bool> disableFrameThrottling; //!< Allow the guest to submit frames without any blocking calls
|
||||
|
||||
template<class T>
|
||||
Settings(T settings) {
|
||||
@ -27,23 +67,9 @@ namespace skyline {
|
||||
|
||||
/**
|
||||
* @brief Updates settings with the given values
|
||||
* @note The implementations of this method must call OnSettingsChanged
|
||||
* @param newSettings A platform-specific object containing the new settings' values
|
||||
*/
|
||||
template<class T>
|
||||
void Update(T newSettings);
|
||||
|
||||
using Callback = std::function<void(const Settings &)>;
|
||||
|
||||
/**
|
||||
* @brief Subscribe to settings changes
|
||||
* @param callback The function to be called when settings change
|
||||
*/
|
||||
void Subscribe(Callback callback);
|
||||
|
||||
private:
|
||||
std::vector<Callback> callbacks; //!< Callbacks to be called when settings change
|
||||
|
||||
void OnSettingsChanged();
|
||||
};
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ namespace skyline::gpu {
|
||||
}
|
||||
|
||||
void PresentationEngine::UpdateSwapchain(texture::Format format, texture::Dimensions extent) {
|
||||
auto minImageCount{std::max(vkSurfaceCapabilities.minImageCount, state.settings->forceTripleBuffering ? 3U : 2U)};
|
||||
auto minImageCount{std::max(vkSurfaceCapabilities.minImageCount, *state.settings->forceTripleBuffering ? 3U : 2U)};
|
||||
if (minImageCount > MaxSwapchainImageCount)
|
||||
throw exception("Requesting swapchain with higher image count ({}) than maximum slot count ({})", minImageCount, MaxSwapchainImageCount);
|
||||
|
||||
@ -131,7 +131,7 @@ namespace skyline::gpu {
|
||||
if ((capabilities.supportedUsageFlags & presentUsage) != presentUsage)
|
||||
throw exception("Swapchain doesn't support image usage '{}': {}", vk::to_string(presentUsage), vk::to_string(capabilities.supportedUsageFlags));
|
||||
|
||||
auto requestedMode{state.settings->disableFrameThrottling ? vk::PresentModeKHR::eMailbox : vk::PresentModeKHR::eFifo};
|
||||
auto requestedMode{*state.settings->disableFrameThrottling ? vk::PresentModeKHR::eMailbox : vk::PresentModeKHR::eFifo};
|
||||
auto modes{gpu.vkPhysicalDevice.getSurfacePresentModesKHR(**vkSurface)};
|
||||
if (std::find(modes.begin(), modes.end(), requestedMode) == modes.end())
|
||||
throw exception("Swapchain doesn't support present mode: {}", vk::to_string(requestedMode));
|
||||
|
@ -31,8 +31,8 @@ namespace skyline::service::account {
|
||||
.uid = userId,
|
||||
};
|
||||
|
||||
size_t usernameSize{std::min(accountProfileBase.nickname.size() - 1, state.settings->usernameValue.size())};
|
||||
std::memcpy(accountProfileBase.nickname.data(), state.settings->usernameValue.c_str(), usernameSize);
|
||||
size_t usernameSize{std::min(accountProfileBase.nickname.size() - 1, (*state.settings->usernameValue).size())};
|
||||
std::memcpy(accountProfileBase.nickname.data(), (*state.settings->usernameValue).c_str(), usernameSize);
|
||||
|
||||
response.Push(accountProfileBase);
|
||||
|
||||
|
@ -58,7 +58,7 @@ namespace skyline::service::am {
|
||||
}
|
||||
|
||||
Result IApplicationFunctions::GetDesiredLanguage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
auto desiredLanguage{language::GetApplicationLanguage(state.settings->systemLanguage)};
|
||||
auto desiredLanguage{language::GetApplicationLanguage(*state.settings->systemLanguage)};
|
||||
|
||||
// In the future we might want to trigger an UI dialog if the user-selected language is not available, for now it will use the first one available
|
||||
if (((1 << static_cast<u32>(desiredLanguage)) & state.loader->nacp->nacpContents.supportedLanguageFlag) == 0)
|
||||
|
@ -15,7 +15,7 @@ namespace skyline::service::am {
|
||||
: BaseService(state, manager),
|
||||
messageEvent(std::make_shared<type::KEvent>(state, false)),
|
||||
defaultDisplayResolutionChangeEvent(std::make_shared<type::KEvent>(state, false)) {
|
||||
operationMode = static_cast<OperationMode>(state.settings->isDocked);
|
||||
operationMode = static_cast<OperationMode>(*state.settings->isDocked);
|
||||
Logger::Info("Switch to mode: {}", static_cast<bool>(operationMode) ? "Docked" : "Handheld");
|
||||
QueueMessage(Message::FocusStateChange);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user