overlays/osk: implement "support languages"

Some languages/panels in the osk need to be activated by the developer.
They are not available otherwise.
So let's check if they were pre-configured and only add the panels if they are supported.
This commit is contained in:
Megamouse 2023-01-18 20:14:42 +01:00
parent 6c3b2b938a
commit 34df4509af
6 changed files with 135 additions and 75 deletions

View File

@ -531,7 +531,19 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dia
Emu.BlockingCallFromMainThread([=, &info]()
{
osk->Create(get_localized_string(localized_string_id::CELL_OSK_DIALOG_TITLE), message, osk->osk_text, maxLength, prohibitFlgs, allowOskPanelFlg, firstViewPanel, info.base_color.load(), info.dimmer_enabled.load(), false);
osk->Create({
.title = get_localized_string(localized_string_id::CELL_OSK_DIALOG_TITLE),
.message = message,
.init_text = osk->osk_text,
.charlimit = maxLength,
.prohibit_flags = prohibitFlgs,
.panel_flag = allowOskPanelFlg,
.support_language = info.supported_languages,
.first_view_panel = firstViewPanel,
.base_color = info.base_color.load(),
.dimmer_enabled = info.dimmer_enabled.load(),
.intercept_input = false
});
});
if (info.osk_continuous_mode == CELL_OSKDIALOG_CONTINUOUS_MODE_HIDE)
@ -775,7 +787,7 @@ error_code cellOskDialogSetInitialInputDevice(u32 inputDevice)
g_fxo->get<osk_info>().initial_input_device = static_cast<CellOskDialogInputDevice>(inputDevice);
// TODO: use value
// TODO: use initial_input_device
// TODO: Signal CELL_SYSUTIL_OSKDIALOG_INPUT_DEVICE_CHANGED if the input device changed (probably only when the dialog is already open)
return CELL_OK;
@ -792,7 +804,7 @@ error_code cellOskDialogSetInitialKeyLayout(u32 initialKeyLayout)
g_fxo->get<osk_info>().initial_key_layout = static_cast<CellOskDialogInitialKeyLayout>(initialKeyLayout);
// TODO: use value
// TODO: use initial_key_layout
return CELL_OK;
}
@ -817,7 +829,7 @@ error_code cellOskDialogSetKeyLayoutOption(u32 option)
g_fxo->get<osk_info>().key_layout = option;
// TODO: use value
// TODO: use key_layout
return CELL_OK;
}
@ -830,19 +842,6 @@ error_code cellOskDialogAddSupportLanguage(u32 supportLanguage)
g_fxo->get<osk_info>().supported_languages = supportLanguage;
// TODO: disable extra languages unless they were enabled here
// Extra languages are:
// CELL_OSKDIALOG_PANELMODE_POLISH
// CELL_OSKDIALOG_PANELMODE_KOREAN
// CELL_OSKDIALOG_PANELMODE_TURKEY
// CELL_OSKDIALOG_PANELMODE_TRADITIONAL_CHINESE
// CELL_OSKDIALOG_PANELMODE_SIMPLIFIED_CHINESE
// CELL_OSKDIALOG_PANELMODE_PORTUGUESE_BRAZIL
// CELL_OSKDIALOG_PANELMODE_DANISH
// CELL_OSKDIALOG_PANELMODE_SWEDISH
// CELL_OSKDIALOG_PANELMODE_NORWEGIAN
// CELL_OSKDIALOG_PANELMODE_FINNISH
return CELL_OK;
}

View File

@ -261,7 +261,22 @@ public:
f32 a = 1.0f;
};
virtual void Create(const std::string& title, const std::u16string& message, char16_t* init_text, u32 charlimit, u32 prohibit_flags, u32 panel_flag, u32 first_view_panel, color base_color, bool dimmer_enabled, bool intercept_input) = 0;
struct osk_params
{
std::string title;
std::u16string message;
char16_t* init_text = nullptr;
u32 charlimit = 0;
u32 prohibit_flags = 0;
u32 panel_flag = 0;
u32 support_language = 0;
u32 first_view_panel = 0;
color base_color{};
bool dimmer_enabled = false;
bool intercept_input = false;
};
virtual void Create(const osk_params& params) = 0;
// Closes the dialog.
// Set status to CELL_OSKDIALOG_CLOSE_CONFIRM or CELL_OSKDIALOG_CLOSE_CANCEL for user input.

View File

@ -945,17 +945,17 @@ namespace rsx
static constexpr auto thread_name = "OSK Thread"sv;
};
void osk_dialog::Create(const std::string& /*title*/, const std::u16string& message, char16_t* init_text, u32 charlimit, u32 prohibit_flags, u32 panel_flag, u32 first_view_panel, color base_color, bool dimmer_enabled, bool intercept_input)
void osk_dialog::Create(const osk_params& params)
{
state = OskDialogState::Open;
flags = prohibit_flags;
char_limit = charlimit;
m_frame.back_color.r = base_color.r;
m_frame.back_color.g = base_color.g;
m_frame.back_color.b = base_color.b;
m_frame.back_color.a = base_color.a;
m_background.back_color.a = dimmer_enabled ? 0.8f : 0.0f;
m_start_pad_interception = intercept_input;
flags = params.prohibit_flags;
char_limit = params.charlimit;
m_frame.back_color.r = params.base_color.r;
m_frame.back_color.g = params.base_color.g;
m_frame.back_color.b = params.base_color.b;
m_frame.back_color.a = params.base_color.a;
m_background.back_color.a = params.dimmer_enabled ? 0.8f : 0.0f;
m_start_pad_interception = params.intercept_input;
const callback_t shift_cb = [this](const std::u32string& text){ on_shift(text); };
const callback_t layer_cb = [this](const std::u32string& text){ on_layer(text); };
@ -963,7 +963,45 @@ namespace rsx
const callback_t delete_cb = [this](const std::u32string& text){ on_backspace(text); };
const callback_t enter_cb = [this](const std::u32string& text){ on_enter(text); };
if (panel_flag & CELL_OSKDIALOG_PANELMODE_PASSWORD)
const auto is_supported = [&](u32 mode) -> bool
{
switch (mode)
{
case CELL_OSKDIALOG_PANELMODE_POLISH:
case CELL_OSKDIALOG_PANELMODE_KOREAN:
case CELL_OSKDIALOG_PANELMODE_TURKEY:
case CELL_OSKDIALOG_PANELMODE_TRADITIONAL_CHINESE:
case CELL_OSKDIALOG_PANELMODE_SIMPLIFIED_CHINESE:
case CELL_OSKDIALOG_PANELMODE_PORTUGUESE_BRAZIL:
case CELL_OSKDIALOG_PANELMODE_DANISH:
case CELL_OSKDIALOG_PANELMODE_SWEDISH:
case CELL_OSKDIALOG_PANELMODE_NORWEGIAN:
case CELL_OSKDIALOG_PANELMODE_FINNISH:
return (params.panel_flag & mode) && (params.support_language & mode);
default:
return (params.panel_flag & mode);
}
};
const auto has_language_support = [&](CellSysutilLang language)
{
switch (language)
{
case CELL_SYSUTIL_LANG_KOREAN: return is_supported(CELL_OSKDIALOG_PANELMODE_KOREAN);
case CELL_SYSUTIL_LANG_FINNISH: return is_supported(CELL_OSKDIALOG_PANELMODE_FINNISH);
case CELL_SYSUTIL_LANG_SWEDISH: return is_supported(CELL_OSKDIALOG_PANELMODE_SWEDISH);
case CELL_SYSUTIL_LANG_DANISH: return is_supported(CELL_OSKDIALOG_PANELMODE_DANISH);
case CELL_SYSUTIL_LANG_NORWEGIAN: return is_supported(CELL_OSKDIALOG_PANELMODE_NORWEGIAN);
case CELL_SYSUTIL_LANG_POLISH: return is_supported(CELL_OSKDIALOG_PANELMODE_POLISH);
case CELL_SYSUTIL_LANG_PORTUGUESE_BR: return is_supported(CELL_OSKDIALOG_PANELMODE_PORTUGUESE_BRAZIL);
case CELL_SYSUTIL_LANG_TURKISH: return is_supported(CELL_OSKDIALOG_PANELMODE_TURKEY);
case CELL_SYSUTIL_LANG_CHINESE_T: return is_supported(CELL_OSKDIALOG_PANELMODE_TRADITIONAL_CHINESE);
case CELL_SYSUTIL_LANG_CHINESE_S: return is_supported(CELL_OSKDIALOG_PANELMODE_SIMPLIFIED_CHINESE);
default: return true;
}
};
if (params.panel_flag & CELL_OSKDIALOG_PANELMODE_PASSWORD)
{
// If password was requested, then password has to be the only osk panel mode available to the user
// first_view_panel can be ignored
@ -972,15 +1010,23 @@ namespace rsx
m_password_mode = true;
}
else if (panel_flag == CELL_OSKDIALOG_PANELMODE_DEFAULT || panel_flag == CELL_OSKDIALOG_PANELMODE_DEFAULT_NO_JAPANESE)
else if (params.panel_flag == CELL_OSKDIALOG_PANELMODE_DEFAULT || params.panel_flag == CELL_OSKDIALOG_PANELMODE_DEFAULT_NO_JAPANESE)
{
// Prefer the systems settings
// first_view_panel is ignored
CellSysutilLang language = g_cfg.sys.language;
// Fall back to english if the panel is not supported
if (!has_language_support(language))
{
language = CELL_SYSUTIL_LANG_ENGLISH_US;
}
switch (g_cfg.sys.language)
{
case CELL_SYSUTIL_LANG_JAPANESE:
if (panel_flag == CELL_OSKDIALOG_PANELMODE_DEFAULT_NO_JAPANESE)
if (params.panel_flag == CELL_OSKDIALOG_PANELMODE_DEFAULT_NO_JAPANESE)
add_panel(osk_panel_english(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
else
add_panel(osk_panel_japanese(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
@ -1049,111 +1095,111 @@ namespace rsx
// TODO: find out the exact order
if (panel_flag & CELL_OSKDIALOG_PANELMODE_LATIN)
if (is_supported(CELL_OSKDIALOG_PANELMODE_LATIN))
{
add_panel(osk_panel_latin(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_ENGLISH)
if (is_supported(CELL_OSKDIALOG_PANELMODE_ENGLISH))
{
add_panel(osk_panel_english(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_FRENCH)
if (is_supported(CELL_OSKDIALOG_PANELMODE_FRENCH))
{
add_panel(osk_panel_french(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_SPANISH)
if (is_supported(CELL_OSKDIALOG_PANELMODE_SPANISH))
{
add_panel(osk_panel_spanish(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_ITALIAN)
if (is_supported(CELL_OSKDIALOG_PANELMODE_ITALIAN))
{
add_panel(osk_panel_italian(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_GERMAN)
if (is_supported(CELL_OSKDIALOG_PANELMODE_GERMAN))
{
add_panel(osk_panel_german(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_TURKEY)
if (is_supported(CELL_OSKDIALOG_PANELMODE_TURKEY))
{
add_panel(osk_panel_turkey(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_POLISH)
if (is_supported(CELL_OSKDIALOG_PANELMODE_POLISH))
{
add_panel(osk_panel_polish(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_RUSSIAN)
if (is_supported(CELL_OSKDIALOG_PANELMODE_RUSSIAN))
{
add_panel(osk_panel_russian(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_DANISH)
if (is_supported(CELL_OSKDIALOG_PANELMODE_DANISH))
{
add_panel(osk_panel_danish(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_NORWEGIAN)
if (is_supported(CELL_OSKDIALOG_PANELMODE_NORWEGIAN))
{
add_panel(osk_panel_norwegian(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_DUTCH)
if (is_supported(CELL_OSKDIALOG_PANELMODE_DUTCH))
{
add_panel(osk_panel_dutch(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_SWEDISH)
if (is_supported(CELL_OSKDIALOG_PANELMODE_SWEDISH))
{
add_panel(osk_panel_swedish(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_FINNISH)
if (is_supported(CELL_OSKDIALOG_PANELMODE_FINNISH))
{
add_panel(osk_panel_finnish(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_PORTUGUESE)
if (is_supported(CELL_OSKDIALOG_PANELMODE_PORTUGUESE))
{
add_panel(osk_panel_portuguese_pt(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_PORTUGUESE_BRAZIL)
if (is_supported(CELL_OSKDIALOG_PANELMODE_PORTUGUESE_BRAZIL))
{
add_panel(osk_panel_portuguese_br(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_KOREAN)
if (is_supported(CELL_OSKDIALOG_PANELMODE_KOREAN))
{
add_panel(osk_panel_korean(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_TRADITIONAL_CHINESE)
if (is_supported(CELL_OSKDIALOG_PANELMODE_TRADITIONAL_CHINESE))
{
add_panel(osk_panel_traditional_chinese(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_SIMPLIFIED_CHINESE)
if (is_supported(CELL_OSKDIALOG_PANELMODE_SIMPLIFIED_CHINESE))
{
add_panel(osk_panel_simplified_chinese(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_JAPANESE)
if (is_supported(CELL_OSKDIALOG_PANELMODE_JAPANESE))
{
add_panel(osk_panel_japanese(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_JAPANESE_HIRAGANA)
if (is_supported(CELL_OSKDIALOG_PANELMODE_JAPANESE_HIRAGANA))
{
add_panel(osk_panel_japanese_hiragana(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_JAPANESE_KATAKANA)
if (is_supported(CELL_OSKDIALOG_PANELMODE_JAPANESE_KATAKANA))
{
add_panel(osk_panel_japanese_katakana(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_ALPHABET)
if (is_supported(CELL_OSKDIALOG_PANELMODE_ALPHABET))
{
add_panel(osk_panel_alphabet_half_width(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_ALPHABET_FULL_WIDTH)
if (is_supported(CELL_OSKDIALOG_PANELMODE_ALPHABET_FULL_WIDTH))
{
add_panel(osk_panel_alphabet_full_width(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_NUMERAL)
if (is_supported(CELL_OSKDIALOG_PANELMODE_NUMERAL))
{
add_panel(osk_panel_numeral_half_width(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_NUMERAL_FULL_WIDTH)
if (is_supported(CELL_OSKDIALOG_PANELMODE_NUMERAL_FULL_WIDTH))
{
add_panel(osk_panel_numeral_full_width(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
if (panel_flag & CELL_OSKDIALOG_PANELMODE_URL)
if (is_supported(CELL_OSKDIALOG_PANELMODE_URL))
{
add_panel(osk_panel_url(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
@ -1161,7 +1207,7 @@ namespace rsx
// Get initial panel based on first_view_panel
for (usz i = 0; i < m_panels.size(); ++i)
{
if (first_view_panel == m_panels[i].osk_panel_mode)
if (params.first_view_panel == m_panels[i].osk_panel_mode)
{
m_panel_index = i;
break;
@ -1176,7 +1222,7 @@ namespace rsx
add_panel(osk_panel_english(shift_cb, layer_cb, space_cb, delete_cb, enter_cb));
}
initialize_layout(utf16_to_u32string(message), utf16_to_u32string(init_text));
initialize_layout(utf16_to_u32string(params.message), utf16_to_u32string(params.init_text));
update_panel();

View File

@ -82,7 +82,7 @@ namespace rsx
osk_dialog();
~osk_dialog() override = default;
void Create(const std::string& title, const std::u16string& message, char16_t* init_text, u32 charlimit, u32 prohibit_flags, u32 panel_flag, u32 first_view_panel, color base_color, bool dimmer_enabled, bool intercept_input) override;
void Create(const osk_params& params) override;
void Close(s32 status) override;
void initialize_layout(const std::u32string& title, const std::u32string& initial_text);

View File

@ -22,7 +22,7 @@ osk_dialog_frame::~osk_dialog_frame()
}
}
void osk_dialog_frame::Create(const std::string& title, const std::u16string& message, char16_t* init_text, u32 charlimit, u32 prohibit_flags, u32 panel_flag, u32 /*first_view_panel*/, color /*base_color*/, bool /*dimmer_enabled*/, bool /*intercept_input*/)
void osk_dialog_frame::Create(const osk_params& params)
{
state = OskDialogState::Open;
@ -38,14 +38,14 @@ void osk_dialog_frame::Create(const std::string& title, const std::u16string& me
m_dialog->setModal(true);
// Title
m_dialog->setWindowTitle(qstr(title));
m_dialog->setWindowTitle(qstr(params.title));
// Message
QLabel* message_label = new QLabel(QString::fromStdU16String(message));
QLabel* message_label = new QLabel(QString::fromStdU16String(params.message));
// Text Input Counter
const QString input_text = QString::fromStdU16String(std::u16string(init_text));
QLabel* input_count_label = new QLabel(QString("%1/%2").arg(input_text.length()).arg(charlimit));
const QString input_text = QString::fromStdU16String(std::u16string(params.init_text));
QLabel* input_count_label = new QLabel(QString("%1/%2").arg(input_text.length()).arg(params.charlimit));
// Button Layout
QDialogButtonBox* button_box = new QDialogButtonBox(QDialogButtonBox::Ok);
@ -55,25 +55,25 @@ void osk_dialog_frame::Create(const std::string& title, const std::u16string& me
inputLayout->setAlignment(Qt::AlignHCenter);
// Text Input
if (prohibit_flags & CELL_OSKDIALOG_NO_RETURN)
if (params.prohibit_flags & CELL_OSKDIALOG_NO_RETURN)
{
QLineEdit* input = new QLineEdit(m_dialog);
input->setFixedWidth(lineEditWidth());
input->setMaxLength(charlimit);
input->setMaxLength(params.charlimit);
input->setText(input_text);
input->setFocus();
if (panel_flag & CELL_OSKDIALOG_PANELMODE_PASSWORD)
if (params.panel_flag & CELL_OSKDIALOG_PANELMODE_PASSWORD)
{
input->setEchoMode(QLineEdit::Password); // Let's assume that games only use the password mode with single-line edit fields
}
if (prohibit_flags & CELL_OSKDIALOG_NO_SPACE)
if (params.prohibit_flags & CELL_OSKDIALOG_NO_SPACE)
{
input->setValidator(new QRegularExpressionValidator(QRegularExpression("^\\S*$"), this));
}
connect(input, &QLineEdit::textChanged, input_count_label, [input_count_label, charlimit, this](const QString& text)
connect(input, &QLineEdit::textChanged, input_count_label, [input_count_label, charlimit = params.charlimit, this](const QString& text)
{
input_count_label->setText(QString("%1/%2").arg(text.length()).arg(charlimit));
SetOskText(text);
@ -106,7 +106,7 @@ void osk_dialog_frame::Create(const std::string& title, const std::u16string& me
const int cursor_pos_old = cursor_pos_new + m_text_old.length() - text.length();
// Reset to old state if character limit was reached
if (m_text_old.length() >= static_cast<int>(charlimit) && text.length() > static_cast<int>(charlimit))
if (m_text_old.length() >= static_cast<int>(params.charlimit) && text.length() > static_cast<int>(params.charlimit))
{
input->blockSignals(true);
input->setPlainText(m_text_old);
@ -119,7 +119,7 @@ void osk_dialog_frame::Create(const std::string& title, const std::u16string& me
int cursor_pos = cursor.position();
// Clear text of spaces if necessary
if (prohibit_flags & CELL_OSKDIALOG_NO_SPACE)
if (params.prohibit_flags & CELL_OSKDIALOG_NO_SPACE)
{
int trim_len = text.length();
text.remove(QRegularExpression("\\s+"));
@ -128,7 +128,7 @@ void osk_dialog_frame::Create(const std::string& title, const std::u16string& me
}
// Crop if more than one character was pasted and the character limit was exceeded
text.chop(text.length() - charlimit);
text.chop(text.length() - params.charlimit);
// Set new text and block signals to prevent infinite loop
input->blockSignals(true);
@ -139,7 +139,7 @@ void osk_dialog_frame::Create(const std::string& title, const std::u16string& me
m_text_old = text;
input_count_label->setText(QString("%1/%2").arg(text.length()).arg(charlimit));
input_count_label->setText(QString("%1/%2").arg(text.length()).arg(params.charlimit));
SetOskText(text);
// if (on_osk_key_input_entered) on_osk_key_input_entered({}); // Not applicable
});

View File

@ -16,7 +16,7 @@ class osk_dialog_frame : public QObject, public OskDialogBase
public:
osk_dialog_frame() = default;
~osk_dialog_frame();
void Create(const std::string& title, const std::u16string& message, char16_t* init_text, u32 charlimit, u32 prohibit_flags, u32 panel_flag, u32 first_view_panel, color base_color, bool dimmer_enabled, bool intercept_input) override;
void Create(const osk_params& params) override;
void Close(s32 status) override;
private: