mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 03:55:32 +00:00
cellOskDialog: add multi-line option and handle more permutations (WIP)
This commit is contained in:
parent
4a8b30c625
commit
17058113df
4 changed files with 156 additions and 49 deletions
|
@ -35,7 +35,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dia
|
|||
{
|
||||
cellOskDialog.warning("cellOskDialogLoadAsync(container=0x%x, dialogParam=*0x%x, inputFieldInfo=*0x%x)", container, dialogParam, inputFieldInfo);
|
||||
|
||||
if (!inputFieldInfo || !inputFieldInfo->message || !inputFieldInfo->init_text || inputFieldInfo->limit_length > CELL_OSKDIALOG_STRING_SIZE)
|
||||
if (!dialogParam || !inputFieldInfo || !inputFieldInfo->message || !inputFieldInfo->init_text || inputFieldInfo->limit_length > CELL_OSKDIALOG_STRING_SIZE)
|
||||
{
|
||||
return CELL_OSKDIALOG_ERROR_PARAM;
|
||||
}
|
||||
|
@ -52,8 +52,11 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dia
|
|||
return CELL_SYSUTIL_ERROR_BUSY;
|
||||
}
|
||||
|
||||
// Get max length of the return value
|
||||
// Get the OSK options
|
||||
u32 maxLength = (inputFieldInfo->limit_length >= CELL_OSKDIALOG_STRING_SIZE) ? 511 : (u32)inputFieldInfo->limit_length;
|
||||
u32 options = dialogParam->prohibitFlgs;
|
||||
bool use_seperate_windows = false; // TODO
|
||||
bool keep_dialog_open = false; // TODO maybe same as use_seperate_windows
|
||||
|
||||
// Get init text and prepare return value
|
||||
osk->osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_OK;
|
||||
|
@ -84,28 +87,15 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dia
|
|||
|
||||
bool result = false;
|
||||
|
||||
osk->on_close = [&maxLength, wptr = std::weak_ptr<OskDialogBase>(osk)](s32 status)
|
||||
osk->on_close = [maxLength, use_seperate_windows, keep_dialog_open, wptr = std::weak_ptr<OskDialogBase>(osk)](s32 status)
|
||||
{
|
||||
const auto osk = wptr.lock();
|
||||
osk->state = OskDialogState::Close;
|
||||
|
||||
if (status != CELL_MSGDIALOG_BUTTON_OK)
|
||||
{
|
||||
osk->osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_CANCELED;
|
||||
const bool accepted = status == CELL_MSGDIALOG_BUTTON_OK;
|
||||
|
||||
if (false/* TODO: check for seperate window */)
|
||||
{
|
||||
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_INPUT_CANCELED, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (accepted)
|
||||
{
|
||||
if (osk->osk_text[0] == 0 && false/* TODO: check for seperate window */)
|
||||
{
|
||||
cellOskDialog.warning("cellOskDialogLoadAsync: input result is CELL_OSKDIALOG_INPUT_FIELD_RESULT_NO_INPUT_TEXT");
|
||||
osk->osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_NO_INPUT_TEXT;
|
||||
}
|
||||
|
||||
if (osk->osk_confirm_callback)
|
||||
{
|
||||
vm::ptr<u16> string_to_send = vm::cast(vm::alloc(CELL_OSKDIALOG_STRING_SIZE * 2, vm::main));
|
||||
|
@ -133,24 +123,68 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dia
|
|||
return 0;
|
||||
});
|
||||
|
||||
// wait for check callback
|
||||
while (done == false)
|
||||
{
|
||||
// wait for check callback
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
// reset this here (just to make sure it's null)
|
||||
osk->osk_confirm_callback = vm::null;
|
||||
}
|
||||
|
||||
if (use_seperate_windows)
|
||||
{
|
||||
if (osk->osk_text[0] == 0)
|
||||
{
|
||||
cellOskDialog.warning("cellOskDialogLoadAsync: input result is CELL_OSKDIALOG_INPUT_FIELD_RESULT_NO_INPUT_TEXT");
|
||||
osk->osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_NO_INPUT_TEXT;
|
||||
}
|
||||
else
|
||||
{
|
||||
osk->osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osk->osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osk->osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_CANCELED;
|
||||
}
|
||||
|
||||
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0);
|
||||
// Send OSK status
|
||||
if (use_seperate_windows)
|
||||
{
|
||||
if (accepted)
|
||||
{
|
||||
if (keep_dialog_open)
|
||||
{
|
||||
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_INPUT_ENTERED, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_INPUT_CANCELED, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0);
|
||||
}
|
||||
|
||||
pad::SetIntercepted(false);
|
||||
};
|
||||
|
||||
osk->on_osk_input_entered = [&]()
|
||||
osk->on_osk_input_entered = [=]()
|
||||
{
|
||||
if (false/* TODO: check for seperate window */)
|
||||
if (use_seperate_windows)
|
||||
{
|
||||
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_INPUT_ENTERED, 0);
|
||||
}
|
||||
|
@ -158,9 +192,9 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dia
|
|||
|
||||
pad::SetIntercepted(true);
|
||||
|
||||
Emu.CallAfter([&]()
|
||||
Emu.CallAfter([=, &result]()
|
||||
{
|
||||
osk->Create("On Screen Keyboard", message, osk->osk_text, maxLength);
|
||||
osk->Create("On Screen Keyboard", message, osk->osk_text, maxLength, options);
|
||||
result = true;
|
||||
});
|
||||
|
||||
|
@ -274,7 +308,8 @@ error_code cellOskDialogAbort()
|
|||
}
|
||||
|
||||
osk->osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_ABORT;
|
||||
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0);
|
||||
osk->Close(false);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -365,9 +400,20 @@ error_code cellOskDialogExtEnableClipboard()
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellOskDialogExtSendFinishMessage(s32 /*CellOskDialogFinishReason*/ finishReason)
|
||||
error_code cellOskDialogExtSendFinishMessage(u32 /*CellOskDialogFinishReason*/ finishReason)
|
||||
{
|
||||
cellOskDialog.todo("cellOskDialogExtSendFinishMessage(finishReason=%d)", finishReason);
|
||||
cellOskDialog.warning("cellOskDialogExtSendFinishMessage(finishReason=%d)", finishReason);
|
||||
|
||||
const auto osk = fxm::get<OskDialogBase>();
|
||||
|
||||
// Check for open dialog.
|
||||
if (!osk || osk->state.load() != OskDialogState::Open)
|
||||
{
|
||||
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
|
||||
}
|
||||
|
||||
osk->Close(finishReason == CELL_OSKDIALOG_CLOSE_CONFIRM);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -243,7 +243,8 @@ enum class OskDialogState
|
|||
class OskDialogBase
|
||||
{
|
||||
public:
|
||||
virtual void Create(const std::string& title, const std::u16string& message, char16_t* init_text, u32 charlimit) = 0;
|
||||
virtual void Create(const std::string& title, const std::u16string& message, char16_t* init_text, u32 charlimit, u32 options) = 0;
|
||||
virtual void Close(bool accepted) = 0;
|
||||
virtual ~OskDialogBase();
|
||||
|
||||
std::function<void(s32 status)> on_close;
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
|
||||
|
||||
#include "osk_dialog_frame.h"
|
||||
#include "Emu/Cell/Modules/cellMsgDialog.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QTextEdit>
|
||||
#include <QHBoxLayout>
|
||||
#include <QFormLayout>
|
||||
#include <QPushButton>
|
||||
#include <QRegExpValidator>
|
||||
|
||||
constexpr auto qstr = QString::fromStdString;
|
||||
|
||||
|
@ -22,7 +24,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)
|
||||
void osk_dialog_frame::Create(const std::string& title, const std::u16string& message, char16_t* init_text, u32 charlimit, u32 options)
|
||||
{
|
||||
state = OskDialogState::Open;
|
||||
|
||||
|
@ -43,15 +45,9 @@ void osk_dialog_frame::Create(const std::string& title, const std::u16string& me
|
|||
// Message
|
||||
QLabel* message_label = new QLabel(QString::fromStdU16String(message));
|
||||
|
||||
// Text Input
|
||||
QLineEdit* input = new QLineEdit(m_dialog);
|
||||
input->setFixedWidth(lineEditWidth());
|
||||
input->setMaxLength(charlimit);
|
||||
input->setText(QString::fromStdU16String(std::u16string(init_text)));
|
||||
input->setFocus();
|
||||
|
||||
// Text Input Counter
|
||||
QLabel* inputCount = new QLabel(QString("%1/%2").arg(input->text().length()).arg(charlimit));
|
||||
const QString text = QString::fromStdU16String(std::u16string(init_text));
|
||||
QLabel* inputCount = new QLabel(QString("%1/%2").arg(text.length()).arg(charlimit));
|
||||
|
||||
// Ok Button
|
||||
QPushButton* button_ok = new QPushButton("Ok", m_dialog);
|
||||
|
@ -66,7 +62,63 @@ void osk_dialog_frame::Create(const std::string& title, const std::u16string& me
|
|||
// Input Layout
|
||||
QHBoxLayout* inputLayout = new QHBoxLayout;
|
||||
inputLayout->setAlignment(Qt::AlignHCenter);
|
||||
inputLayout->addWidget(input);
|
||||
|
||||
// Text Input
|
||||
if (options & CELL_OSKDIALOG_NO_RETURN)
|
||||
{
|
||||
QLineEdit* input = new QLineEdit(m_dialog);
|
||||
input->setFixedWidth(lineEditWidth());
|
||||
input->setMaxLength(charlimit);
|
||||
input->setText(text);
|
||||
input->setFocus();
|
||||
|
||||
if (options & CELL_OSKDIALOG_NO_SPACE)
|
||||
{
|
||||
input->setValidator(new QRegExpValidator(QRegExp("^\S*$"), this));
|
||||
}
|
||||
|
||||
connect(input, &QLineEdit::textChanged, [=](const QString& text)
|
||||
{
|
||||
inputCount->setText(QString("%1/%2").arg(text.length()).arg(charlimit));
|
||||
SetOskText(text);
|
||||
on_osk_input_entered();
|
||||
});
|
||||
connect(input, &QLineEdit::returnPressed, m_dialog, &QDialog::accept);
|
||||
|
||||
inputLayout->addWidget(input);
|
||||
}
|
||||
else
|
||||
{
|
||||
QTextEdit* input = new QTextEdit(m_dialog);
|
||||
input->setFixedWidth(lineEditWidth());
|
||||
input->setText(text);
|
||||
input->setFocus();
|
||||
|
||||
connect(input, &QTextEdit::textChanged, [=]()
|
||||
{
|
||||
QString text = input->toPlainText();
|
||||
text.chop(text.length() - charlimit);
|
||||
|
||||
if (options & CELL_OSKDIALOG_NO_SPACE)
|
||||
{
|
||||
text.remove(QRegExp("\\s+"));
|
||||
}
|
||||
|
||||
input->setPlainText(text);
|
||||
|
||||
QTextCursor cursor = input->textCursor();
|
||||
cursor.setPosition(QTextCursor::End);
|
||||
input->setTextCursor(cursor);
|
||||
|
||||
inputCount->setText(QString("%1/%2").arg(text.length()).arg(charlimit));
|
||||
SetOskText(text);
|
||||
|
||||
on_osk_input_entered();
|
||||
});
|
||||
|
||||
inputLayout->addWidget(input);
|
||||
}
|
||||
|
||||
inputLayout->addWidget(inputCount);
|
||||
|
||||
QFormLayout* layout = new QFormLayout(m_dialog);
|
||||
|
@ -77,18 +129,10 @@ void osk_dialog_frame::Create(const std::string& title, const std::u16string& me
|
|||
m_dialog->setLayout(layout);
|
||||
|
||||
// Events
|
||||
connect(input, &QLineEdit::textChanged, [=](const QString& text)
|
||||
{
|
||||
inputCount->setText(QString("%1/%2").arg(text.length()).arg(charlimit));
|
||||
on_osk_input_entered();
|
||||
});
|
||||
|
||||
connect(input, &QLineEdit::returnPressed, m_dialog, &QDialog::accept);
|
||||
connect(button_ok, &QAbstractButton::clicked, m_dialog, &QDialog::accept);
|
||||
|
||||
connect(m_dialog, &QDialog::accepted, [=]
|
||||
{
|
||||
std::memcpy(osk_text, reinterpret_cast<const char16_t*>(input->text().constData()), ((input->text()).size() + 1) * sizeof(char16_t));
|
||||
on_close(CELL_MSGDIALOG_BUTTON_OK);
|
||||
});
|
||||
|
||||
|
@ -101,3 +145,16 @@ void osk_dialog_frame::Create(const std::string& title, const std::u16string& me
|
|||
m_dialog->layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
m_dialog->show();
|
||||
}
|
||||
|
||||
void osk_dialog_frame::SetOskText(const QString& text)
|
||||
{
|
||||
std::memcpy(osk_text, reinterpret_cast<const char16_t*>(text.constData()), size_t(text.size() + 1) * sizeof(char16_t));
|
||||
}
|
||||
|
||||
void osk_dialog_frame::Close(bool accepted)
|
||||
{
|
||||
if (m_dialog)
|
||||
{
|
||||
m_dialog->done(accepted ? QDialog::Accepted : QDialog::Rejected);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Memory/vm.h"
|
||||
|
@ -15,8 +15,11 @@ class osk_dialog_frame : public QObject, public OskDialogBase
|
|||
public:
|
||||
osk_dialog_frame();
|
||||
~osk_dialog_frame();
|
||||
virtual void Create(const std::string& title, const std::u16string& message, char16_t* init_text, u32 charlimit) override;
|
||||
virtual void Create(const std::string& title, const std::u16string& message, char16_t* init_text, u32 charlimit, u32 options) override;
|
||||
virtual void Close(bool accepted) override;
|
||||
|
||||
private:
|
||||
void SetOskText(const QString& text);
|
||||
|
||||
custom_dialog* m_dialog = nullptr;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue