implement CELL_PAD_INFO_INTERCEPTED

This commit is contained in:
Megamouse 2018-12-30 02:34:15 +01:00
parent 8ad14c4ada
commit 6f7b25de90
13 changed files with 250 additions and 153 deletions

View File

@ -87,7 +87,12 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
if (auto manager = fxm::get<rsx::overlays::display_manager>())
{
manager->create<rsx::overlays::message_dialog>()->show(msgString.get_ptr(), _type, [callback, userData](s32 status)
if (manager->get<rsx::overlays::message_dialog>())
{
return CELL_SYSUTIL_ERROR_BUSY;
}
const auto res = manager->create<rsx::overlays::message_dialog>()->show(msgString.get_ptr(), _type, [callback, userData](s32 status)
{
if (callback)
{
@ -99,7 +104,7 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
}
});
return CELL_OK;
return res;
}
const auto dlg = fxm::import<MsgDialogBase>(Emu.GetCallbacks().get_msg_dialog);
@ -128,8 +133,12 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
fxm::remove<MsgDialogBase>();
}
pad::SetIntercepted(false);
};
pad::SetIntercepted(true);
atomic_t<bool> result(false);
// Run asynchronously in GUI thread

View File

@ -1,6 +1,8 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/Cell/PPUModule.h"
#include "pad_thread.h"
#include "cellSysutil.h"
#include "cellOskDialog.h"
@ -22,14 +24,28 @@ s32 cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dialogPara
for (u32 i = 0; (i < maxLength) && (inputFieldInfo->init_text[i] != 0); i++)
s_osk_text[i] = inputFieldInfo->init_text[i];
const auto osk = Emu.GetCallbacks().get_msg_dialog();
const auto osk = fxm::import<MsgDialogBase>(Emu.GetCallbacks().get_msg_dialog);
if (!osk)
{
return CELL_SYSUTIL_ERROR_BUSY;
}
bool result = false;
osk->on_close = [&](s32 status)
osk->on_close = [wptr = std::weak_ptr<MsgDialogBase>(osk)](s32 status)
{
const auto osk = wptr.lock();
if (osk && osk->state.compare_and_swap_test(MsgDialogState::Open, MsgDialogState::Close))
{
fxm::remove<MsgDialogBase>();
}
if (status != CELL_MSGDIALOG_BUTTON_OK) sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_INPUT_CANCELED, 0);
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0);
result = true;
pad::SetIntercepted(false);
};
osk->on_osk_input_entered = [&]()
@ -37,9 +53,12 @@ s32 cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dialogPara
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_INPUT_ENTERED, 0);
};
pad::SetIntercepted(true);
Emu.CallAfter([&]()
{
osk->CreateOsk("On Screen Keyboard", s_osk_text, maxLength);
result = true;
});
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_LOADED, 0);
@ -78,6 +97,21 @@ s32 cellOskDialogGetSize(vm::ptr<u16> width, vm::ptr<u16> height, vm::ptr<CellOs
s32 cellOskDialogAbort()
{
cellOskDialog.warning("cellOskDialogAbort()");
const auto dlg = fxm::get<MsgDialogBase>();
if (!dlg)
{
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED;
}
if (!dlg->state.compare_and_swap_test(MsgDialogState::Open, MsgDialogState::Abort))
{
return CELL_SYSUTIL_ERROR_BUSY;
}
verify(HERE), fxm::remove<MsgDialogBase>();
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0);
return CELL_OK;
}
@ -133,7 +167,7 @@ s32 cellOskDialogSetLayoutMode(s32 layoutMode)
s32 cellOskDialogGetInputText(vm::ptr<CellOskDialogCallbackReturnParam> OutputInfo)
{
cellOskDialog.warning("cellOskDialogGetInputText(OutputInfo=*0x%x)", OutputInfo);
return cellOskDialogUnloadAsync(OutputInfo); //Same but for use with cellOskDialogSetSeparateWindowOption(). TODO.
return cellOskDialogUnloadAsync(OutputInfo); // Same but for use with cellOskDialogSetSeparateWindowOption(). TODO.
}
s32 cellOskDialogExtInputDeviceUnlock()
@ -220,9 +254,9 @@ s32 cellOskDialogExtSetPointerEnable(b8 enable)
return CELL_OK;
}
s32 cellOskDialogExtUpdatePointerDisplayPos()
s32 cellOskDialogExtUpdatePointerDisplayPos(/*const CellOskDialogPoint pos*/)
{
cellOskDialog.todo("cellOskDialogExtUpdatePointerDisplayPos"); // Missing arguments
cellOskDialog.todo("cellOskDialogExtUpdatePointerDisplayPos(posX=%f, posY=%f)"/*, pos.x, pos.y*/);
return CELL_OK;
}

View File

@ -2,7 +2,7 @@
//error codes
// error codes
enum
{
CELL_OSKDIALOG_ERROR_IME_ALREADY_IN_USE = 0x8002b501,
@ -11,7 +11,7 @@ enum
CELL_OSKDIALOG_ERROR_PARAM = 0x8002b504,
};
//OSK status for the callback
// OSK status for the callback
enum
{
CELL_SYSUTIL_OSKDIALOG_LOADED = 0x0502,
@ -94,7 +94,7 @@ enum CellOskDialogType
enum
{
CELL_OSKDIALOG_STRING_SIZE = 512, //Theroretical maxium for osk input, games can specify a lower limit
CELL_OSKDIALOG_STRING_SIZE = 512, // Theroretical maximum for osk input, games can specify a lower limit
};
struct CellOskDialogInputFieldInfo
@ -118,10 +118,10 @@ struct CellOskDialogParam
be_t<s32> prohibitFlgs;
};
//Actual input data
// Actual input data
struct CellOskDialogCallbackReturnParam
{
be_t<s32> result; //CellOskDialogInputFieldResult
be_t<s32> result; // CellOskDialogInputFieldResult
be_t<s32> numCharsResultString;
vm::bptr<u16> pResultString;
};

View File

@ -10,6 +10,11 @@
// TODO: HLE info (constants, structs, etc.) should not be available here
enum SystemInfo
{
CELL_PAD_INFO_INTERCEPTED = 0x00000001
};
enum PortStatus
{
CELL_PAD_STATUS_DISCONNECTED = 0x00000000,

View File

@ -9,6 +9,134 @@ namespace rsx
// Singleton instance declaration
fontmgr* fontmgr::m_instance = nullptr;
s32 user_interface::run_input_loop()
{
std::array<std::chrono::steady_clock::time_point, CELL_PAD_MAX_PORT_NUM> timestamp;
timestamp.fill(std::chrono::steady_clock::now());
std::array<std::array<bool, 8>, CELL_PAD_MAX_PORT_NUM> button_state;
for (auto& state : button_state)
{
state.fill(true);
}
input_timer.Start();
{
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_current_handler();
handler->SetIntercepted(true);
}
while (!exit)
{
if (Emu.IsStopped())
return selection_code::canceled;
std::this_thread::sleep_for(1ms);
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_current_handler();
const PadInfo& rinfo = handler->GetInfo();
if (Emu.IsPaused() || !rinfo.now_connect)
{
continue;
}
int pad_index = -1;
for (const auto &pad : handler->GetPads())
{
if (++pad_index >= CELL_PAD_MAX_PORT_NUM)
{
LOG_FATAL(RSX, "The native overlay cannot handle more than 7 pads! Current number of pads: %d", pad_index + 1);
continue;
}
for (auto &button : pad->m_buttons)
{
u8 button_id = 255;
if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL1)
{
switch (button.m_outKeyCode)
{
case CELL_PAD_CTRL_LEFT:
button_id = pad_button::dpad_left;
break;
case CELL_PAD_CTRL_RIGHT:
button_id = pad_button::dpad_right;
break;
case CELL_PAD_CTRL_DOWN:
button_id = pad_button::dpad_down;
break;
case CELL_PAD_CTRL_UP:
button_id = pad_button::dpad_up;
break;
}
}
else if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL2)
{
switch (button.m_outKeyCode)
{
case CELL_PAD_CTRL_TRIANGLE:
button_id = pad_button::triangle;
break;
case CELL_PAD_CTRL_CIRCLE:
button_id = g_cfg.sys.enter_button_assignment == enter_button_assign::circle ? pad_button::cross : pad_button::circle;
break;
case CELL_PAD_CTRL_SQUARE:
button_id = pad_button::square;
break;
case CELL_PAD_CTRL_CROSS:
button_id = g_cfg.sys.enter_button_assignment == enter_button_assign::circle ? pad_button::circle : pad_button::cross;
break;
}
}
if (button_id < 255)
{
if (button.m_pressed)
{
if (button_id < 4) // d-pad button
{
if (!button_state[pad_index][button_id] || input_timer.GetMsSince(timestamp[pad_index]) > 400)
{
// d-pad button was not pressed, or was pressed more than 400ms ago
timestamp[pad_index] = std::chrono::steady_clock::now();
on_button_pressed(static_cast<pad_button>(button_id));
}
}
else if (!button_state[pad_index][button_id])
{
// button was not pressed
on_button_pressed(static_cast<pad_button>(button_id));
}
}
button_state[pad_index][button_id] = button.m_pressed;
}
if (button.m_flush)
{
button.m_pressed = false;
button.m_flush = false;
button.m_value = 0;
}
if (exit)
return 0;
}
}
refresh();
}
// Unreachable
return 0;
}
void user_interface::close()
{
// Force unload
@ -24,6 +152,12 @@ namespace rsx
manager->remove(uid);
}
{
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_current_handler();
handler->SetIntercepted(false);
}
if (on_close)
on_close(return_code);
}

View File

@ -80,127 +80,7 @@ namespace rsx
void close();
s32 run_input_loop()
{
std::array<std::chrono::steady_clock::time_point, CELL_PAD_MAX_PORT_NUM> timestamp;
timestamp.fill(std::chrono::steady_clock::now());
std::array<std::array<bool, 8>, CELL_PAD_MAX_PORT_NUM> button_state;
for (auto& state : button_state)
{
state.fill(true);
}
input_timer.Start();
while (!exit)
{
if (Emu.IsStopped())
return selection_code::canceled;
std::this_thread::sleep_for(1ms);
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_current_handler();
const PadInfo& rinfo = handler->GetInfo();
if (Emu.IsPaused() || !rinfo.now_connect)
{
continue;
}
int pad_index = -1;
for (const auto &pad : handler->GetPads())
{
if (++pad_index >= CELL_PAD_MAX_PORT_NUM)
{
LOG_FATAL(RSX, "The native overlay cannot handle more than 7 pads! Current number of pads: %d", pad_index + 1);
continue;
}
for (auto &button : pad->m_buttons)
{
u8 button_id = 255;
if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL1)
{
switch (button.m_outKeyCode)
{
case CELL_PAD_CTRL_LEFT:
button_id = pad_button::dpad_left;
break;
case CELL_PAD_CTRL_RIGHT:
button_id = pad_button::dpad_right;
break;
case CELL_PAD_CTRL_DOWN:
button_id = pad_button::dpad_down;
break;
case CELL_PAD_CTRL_UP:
button_id = pad_button::dpad_up;
break;
}
}
else if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL2)
{
switch (button.m_outKeyCode)
{
case CELL_PAD_CTRL_TRIANGLE:
button_id = pad_button::triangle;
break;
case CELL_PAD_CTRL_CIRCLE:
button_id = g_cfg.sys.enter_button_assignment == enter_button_assign::circle ? pad_button::cross : pad_button::circle;
break;
case CELL_PAD_CTRL_SQUARE:
button_id = pad_button::square;
break;
case CELL_PAD_CTRL_CROSS:
button_id = g_cfg.sys.enter_button_assignment == enter_button_assign::circle ? pad_button::circle : pad_button::cross;
break;
}
}
if (button_id < 255)
{
if (button.m_pressed)
{
if (button_id < 4) // d-pad button
{
if (!button_state[pad_index][button_id] || input_timer.GetMsSince(timestamp[pad_index]) > 400)
{
// d-pad button was not pressed, or was pressed more than 400ms ago
timestamp[pad_index] = std::chrono::steady_clock::now();
on_button_pressed(static_cast<pad_button>(button_id));
}
}
else if (!button_state[pad_index][button_id])
{
// button was not pressed
on_button_pressed(static_cast<pad_button>(button_id));
}
}
button_state[pad_index][button_id] = button.m_pressed;
}
if (button.m_flush)
{
button.m_pressed = false;
button.m_flush = false;
button.m_value = 0;
}
if (exit)
return 0;
}
}
refresh();
}
// Unreachable
return 0;
}
s32 run_input_loop();
};
class display_manager

View File

@ -316,9 +316,11 @@ void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std
switch (status)
{
case JOYERR_UNPLUGGED:
{
return fail_callback(padId);
}
case JOYERR_NOERROR:
{
auto data = GetButtonValues(js_info, js_caps);
// Check for each button in our list if its corresponding (maybe remapped) button or axis was pressed.
@ -421,6 +423,9 @@ void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std
break;
}
default:
break;
}
}
void mm_joystick_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold)

View File

@ -57,8 +57,10 @@ void pad_thread::Init()
}
}
const u32 system_info = m_info.system_info;
std::memset(&m_info, 0, sizeof(m_info));
m_info.now_connect = 0;
m_info.system_info |= system_info;
m_pads.clear();
handlers.clear();
@ -147,6 +149,18 @@ void pad_thread::SetEnabled(bool enabled)
is_enabled = enabled;
}
void pad_thread::SetIntercepted(bool intercepted)
{
if (intercepted)
{
m_info.system_info |= CELL_PAD_INFO_INTERCEPTED;
}
else
{
m_info.system_info &= ~CELL_PAD_INFO_INTERCEPTED;
}
}
void pad_thread::ThreadFunc()
{
active = true;

View File

@ -25,6 +25,7 @@ public:
void Init();
void Reset();
void SetEnabled(bool enabled);
void SetIntercepted(bool intercepted);
protected:
void ThreadFunc();
@ -36,7 +37,7 @@ protected:
void *curthread;
void *curwindow;
PadInfo m_info;
PadInfo m_info{ 0, 0 };
std::vector<std::shared_ptr<Pad>> m_pads;
atomic_t<bool> active{ false };
@ -54,4 +55,11 @@ namespace pad
{
return verify(HERE, g_current.load());
};
static inline void SetIntercepted(bool intercepted)
{
std::lock_guard lock(g_pad_mutex);
const auto handler = get_current_handler();
handler->SetIntercepted(intercepted);
}
}

View File

@ -24,7 +24,7 @@ void msg_dialog_frame::Create(const std::string& msg, const std::string& title)
m_text = new QLabel(qstr(msg));
m_text->setAlignment(Qt::AlignCenter);
//Layout
// Layout
QFormLayout* layout = new QFormLayout(m_dialog);
layout->setFormAlignment(Qt::AlignHCenter);
layout->addRow(m_text);
@ -140,7 +140,7 @@ void msg_dialog_frame::Create(const std::string& msg, const std::string& title)
}
});
//Fix size
// Fix size
m_dialog->layout()->setSizeConstraint(QLayout::SetFixedSize);
m_dialog->show();
@ -164,30 +164,30 @@ void msg_dialog_frame::CreateOsk(const std::string& msg, char16_t* osk_text, u32
m_osk_dialog->setModal(true);
m_osk_text_return = osk_text;
//Title
// Title
m_osk_dialog->setWindowTitle(qstr(msg));
//Text Input
// Text Input
QLineEdit* input = new QLineEdit(m_osk_dialog);
input->setFixedWidth(lineEditWidth());
input->setMaxLength(charlimit);
input->setText(QString::fromStdU16String(std::u16string(m_osk_text_return)));
input->setFocus();
//Text Input Counter
// Text Input Counter
QLabel* inputCount = new QLabel(QString("%1/%2").arg(input->text().length()).arg(charlimit));
//Ok Button
// Ok Button
QPushButton* button_ok = new QPushButton("Ok", m_osk_dialog);
//Button Layout
// Button Layout
QHBoxLayout* buttonsLayout = new QHBoxLayout;
buttonsLayout->setAlignment(Qt::AlignCenter);
buttonsLayout->addStretch();
buttonsLayout->addWidget(button_ok);
buttonsLayout->addStretch();
//Input Layout
// Input Layout
QHBoxLayout* inputLayout = new QHBoxLayout;
inputLayout->setAlignment(Qt::AlignHCenter);
inputLayout->addWidget(input);
@ -199,7 +199,7 @@ void msg_dialog_frame::CreateOsk(const std::string& msg, char16_t* osk_text, u32
layout->addRow(buttonsLayout);
m_osk_dialog->setLayout(layout);
//Events
// Events
connect(input, &QLineEdit::textChanged, [=](const QString& text)
{
inputCount->setText(QString("%1/%2").arg(text.length()).arg(charlimit));
@ -223,7 +223,7 @@ void msg_dialog_frame::CreateOsk(const std::string& msg, char16_t* osk_text, u32
on_close(CELL_MSGDIALOG_BUTTON_OK);
});
//Fix size
// Fix size
m_osk_dialog->layout()->setSizeConstraint(QLayout::SetFixedSize);
m_osk_dialog->show();
}
@ -385,7 +385,7 @@ void msg_dialog_frame::UpdateProgress(int progress, bool disable)
properties.insert(QStringLiteral("progress-visible"), false);
else
properties.insert(QStringLiteral("progress-visible"), true);
//Progress takes a value from 0.0 to 0.1
// Progress takes a value from 0.0 to 0.1
properties.insert(QStringLiteral("progress"), (double)progress/(double)m_gauge_max);
message << QStringLiteral("application://rpcs3.desktop") << properties;
QDBusConnection::sessionBus().send(message);

View File

@ -51,7 +51,7 @@ private:
QProgressBar* m_gauge1 = nullptr;
QProgressBar* m_gauge2 = nullptr;
QWindow* m_taskbarTarget; // Window which will be targeted by custom taskbars.
QWindow* m_taskbarTarget; // Window which will be targeted by custom taskbars.
custom_dialog* m_osk_dialog = nullptr;
char16_t* m_osk_text_return;

View File

@ -6,7 +6,7 @@
s32 save_data_dialog::ShowSaveDataList(std::vector<SaveDataEntry>& save_entries, s32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet)
{
//TODO: Install native shell as an Emu callback
// TODO: Install native shell as an Emu callback
if (auto manager = fxm::get<rsx::overlays::display_manager>())
{
auto result = manager->create<rsx::overlays::save_dialog>()->show(save_entries, op, listSet);
@ -14,10 +14,12 @@ s32 save_data_dialog::ShowSaveDataList(std::vector<SaveDataEntry>& save_entries,
return result;
}
//Fall back to front-end GUI
// Fall back to front-end GUI
atomic_t<bool> dlg_result(false);
atomic_t<s32> selection;
pad::SetIntercepted(true);
Emu.CallAfter([&]()
{
save_data_list_dialog sdid(save_entries, focused, op, listSet);
@ -31,5 +33,7 @@ s32 save_data_dialog::ShowSaveDataList(std::vector<SaveDataEntry>& save_entries,
thread_ctrl::wait_for(1000);
}
pad::SetIntercepted(false);
return selection.load();
}

View File

@ -328,6 +328,7 @@ void xinput_pad_handler::ThreadProc()
switch (result)
{
case ERROR_DEVICE_NOT_CONNECTED:
{
if (last_connection_status[i] == true)
{
LOG_ERROR(HLE, "XInput device %d disconnected", padnum);
@ -337,8 +338,9 @@ void xinput_pad_handler::ThreadProc()
connected--;
}
continue;
}
case ERROR_SUCCESS:
{
if (last_connection_status[i] == false)
{
LOG_SUCCESS(HLE, "XInput device %d reconnected", padnum);
@ -437,7 +439,9 @@ void xinput_pad_handler::ThreadProc()
m_dev->last_vibration = clock();
}
}
break;
}
default:
break;
}
}