cellOskDialog: implement device mask and lock

This commit is contained in:
Megamouse 2022-04-19 20:27:32 +02:00
parent 43e7776f4d
commit 9adab801ac
8 changed files with 72 additions and 23 deletions

View File

@ -181,6 +181,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dia
} }
// Get the OSK options // Get the OSK options
auto& info = g_fxo->get<osk_info>();
u32 maxLength = (inputFieldInfo->limit_length >= CELL_OSKDIALOG_STRING_SIZE) ? 511 : u32{inputFieldInfo->limit_length}; u32 maxLength = (inputFieldInfo->limit_length >= CELL_OSKDIALOG_STRING_SIZE) ? 511 : u32{inputFieldInfo->limit_length};
const u32 prohibitFlgs = dialogParam->prohibitFlgs; const u32 prohibitFlgs = dialogParam->prohibitFlgs;
const u32 allowOskPanelFlg = dialogParam->allowOskPanelFlg; const u32 allowOskPanelFlg = dialogParam->allowOskPanelFlg;
@ -192,7 +193,6 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dia
// Also clear the info text just to be sure (it should be zeroed at this point anyway) // Also clear the info text just to be sure (it should be zeroed at this point anyway)
{ {
auto& info = g_fxo->get<osk_info>();
std::lock_guard lock(info.text_mtx); std::lock_guard lock(info.text_mtx);
info.valid_text = {}; info.valid_text = {};
} }
@ -340,14 +340,23 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dia
input::SetIntercepted(false); input::SetIntercepted(false);
}; };
if (auto& info = g_fxo->get<osk_info>(); info.osk_continuous_mode == CELL_OSKDIALOG_CONTINUOUS_MODE_HIDE) if (info.osk_continuous_mode == CELL_OSKDIALOG_CONTINUOUS_MODE_HIDE)
{ {
info.last_dialog_state = CELL_SYSUTIL_OSKDIALOG_LOADED; info.last_dialog_state = CELL_SYSUTIL_OSKDIALOG_LOADED;
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_LOADED, 0); sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_LOADED, 0);
return CELL_OK; return CELL_OK;
} }
input::SetIntercepted(true); // Set device mask and event lock
osk->ignore_input_events = info.lock_ext_input.load();
if (info.use_separate_windows)
{
osk->pad_input_enabled = (info.device_mask != CELL_OSKDIALOG_DEVICE_MASK_PAD);
osk->mouse_input_enabled = (info.device_mask != CELL_OSKDIALOG_DEVICE_MASK_PAD);
}
input::SetIntercepted(osk->pad_input_enabled, osk->keyboard_input_enabled, osk->mouse_input_enabled);
Emu.CallFromMainThread([=, &result]() Emu.CallFromMainThread([=, &result]()
{ {
@ -550,9 +559,19 @@ error_code cellOskDialogSetDeviceMask(u32 deviceMask)
return CELL_OSKDIALOG_ERROR_PARAM; return CELL_OSKDIALOG_ERROR_PARAM;
} }
g_fxo->get<osk_info>().device_mask = deviceMask; auto& info = g_fxo->get<osk_info>();
info.device_mask = deviceMask;
// TODO: change osk device input if (info.use_separate_windows)
{
if (const auto osk = _get_osk_dialog(false))
{
osk->pad_input_enabled = (deviceMask != CELL_OSKDIALOG_DEVICE_MASK_PAD);
osk->mouse_input_enabled = (deviceMask != CELL_OSKDIALOG_DEVICE_MASK_PAD);
input::SetIntercepted(osk->pad_input_enabled, osk->keyboard_input_enabled, osk->mouse_input_enabled);
}
}
return CELL_OK; return CELL_OK;
} }
@ -569,7 +588,12 @@ error_code cellOskDialogSetSeparateWindowOption(vm::ptr<CellOskDialogSeparateWin
auto& osk = g_fxo->get<osk_info>(); auto& osk = g_fxo->get<osk_info>();
osk.use_separate_windows = true; osk.use_separate_windows = true;
osk.osk_continuous_mode = static_cast<CellOskDialogContinuousMode>(+windowOption->continuousMode); osk.osk_continuous_mode = static_cast<CellOskDialogContinuousMode>(+windowOption->continuousMode);
osk.device_mask = windowOption->deviceMask;
// TODO: handle rest of windowOption // TODO: handle rest of windowOption
// inputFieldWindowWidth;
// inputFieldBackgroundTrans;
// inputFieldLayoutInfo;
// inputPanelLayoutInfo;
cellOskDialog.warning("cellOskDialogSetSeparateWindowOption: continuousMode=%s)", osk.osk_continuous_mode.load()); cellOskDialog.warning("cellOskDialogSetSeparateWindowOption: continuousMode=%s)", osk.osk_continuous_mode.load());
@ -801,7 +825,10 @@ error_code cellOskDialogExtInputDeviceLock()
g_fxo->get<osk_info>().lock_ext_input = true; g_fxo->get<osk_info>().lock_ext_input = true;
// TODO: change osk device input if (const auto osk = _get_osk_dialog(false))
{
osk->ignore_input_events = true;
}
return CELL_OK; return CELL_OK;
} }
@ -814,7 +841,10 @@ error_code cellOskDialogExtInputDeviceUnlock()
g_fxo->get<osk_info>().lock_ext_input = false; g_fxo->get<osk_info>().lock_ext_input = false;
// TODO: change osk device input if (const auto osk = _get_osk_dialog(false))
{
osk->ignore_input_events = false;
}
return CELL_OK; return CELL_OK;
} }
@ -888,7 +918,7 @@ error_code cellOskDialogExtSetPointerEnable(b8 enable)
g_fxo->get<osk_info>().pointer_enabled = enable; g_fxo->get<osk_info>().pointer_enabled = enable;
// TODO: use new value in osk // TODO: Show/hide pointer at the specified position in the OSK overlay.
return CELL_OK; return CELL_OK;
} }
@ -904,7 +934,7 @@ error_code cellOskDialogExtUpdatePointerDisplayPos(vm::cptr<CellOskDialogPoint>
g_fxo->get<osk_info>().pointer_pos = *pos; g_fxo->get<osk_info>().pointer_pos = *pos;
} }
// TODO: use new value in osk // TODO: Update pointer position in the OSK overlay.
return CELL_OK; return CELL_OK;
} }

View File

@ -265,6 +265,10 @@ public:
std::function<void()> on_osk_input_entered; std::function<void()> on_osk_input_entered;
atomic_t<OskDialogState> state{ OskDialogState::Unloaded }; atomic_t<OskDialogState> state{ OskDialogState::Unloaded };
atomic_t<bool> pad_input_enabled{ true }; // Determines if the OSK consumes the device's events.
atomic_t<bool> mouse_input_enabled{ true }; // Determines if the OSK consumes the device's events.
atomic_t<bool> keyboard_input_enabled{ true }; // Determines if the OSK consumes the device's events.
atomic_t<bool> ignore_input_events{ false }; // Determines if the OSK ignores all consumed events.
atomic_t<CellOskDialogInputFieldResult> osk_input_result{ CellOskDialogInputFieldResult::CELL_OSKDIALOG_INPUT_FIELD_RESULT_OK }; atomic_t<CellOskDialogInputFieldResult> osk_input_result{ CellOskDialogInputFieldResult::CELL_OSKDIALOG_INPUT_FIELD_RESULT_OK };
char16_t osk_text[CELL_OSKDIALOG_STRING_SIZE]{}; char16_t osk_text[CELL_OSKDIALOG_STRING_SIZE]{};

View File

@ -7,22 +7,31 @@
namespace input namespace input
{ {
atomic_t<bool> g_intercepted{false}; atomic_t<bool> g_pads_intercepted{false};
atomic_t<bool> g_keyboards_intercepted{false};
atomic_t<bool> g_mice_intercepted{false};
void SetIntercepted(bool intercepted) void SetIntercepted(bool pads_intercepted, bool keyboards_intercepted, bool mice_intercepted)
{ {
g_intercepted = intercepted; g_pads_intercepted = pads_intercepted;
g_keyboards_intercepted = keyboards_intercepted;
g_mice_intercepted = mice_intercepted;
pad::SetIntercepted(intercepted); pad::SetIntercepted(pads_intercepted);
if (const auto handler = g_fxo->try_get<KeyboardHandlerBase>()) if (const auto handler = g_fxo->try_get<KeyboardHandlerBase>())
{ {
handler->SetIntercepted(intercepted); handler->SetIntercepted(keyboards_intercepted);
} }
if (const auto handler = g_fxo->try_get<MouseHandlerBase>()) if (const auto handler = g_fxo->try_get<MouseHandlerBase>())
{ {
handler->SetIntercepted(intercepted); handler->SetIntercepted(mice_intercepted);
} }
} }
void SetIntercepted(bool all_intercepted)
{
SetIntercepted(all_intercepted, all_intercepted, all_intercepted);
}
} }

View File

@ -4,7 +4,10 @@
namespace input namespace input
{ {
extern atomic_t<bool> g_intercepted; extern atomic_t<bool> g_pads_intercepted;
extern atomic_t<bool> g_keyboards_intercepted;
extern atomic_t<bool> g_mice_intercepted;
void SetIntercepted(bool intercepted); void SetIntercepted(bool pads_intercepted, bool keyboards_intercepted, bool mice_intercepted);
void SetIntercepted(bool all_intercepted);
} }

View File

@ -393,6 +393,9 @@ namespace rsx
void osk_dialog::on_button_pressed(pad_button button_press) void osk_dialog::on_button_pressed(pad_button button_press)
{ {
if (!pad_input_enabled || ignore_input_events)
return;
const auto index_limit = (num_columns * num_rows) - 1; const auto index_limit = (num_columns * num_rows) - 1;
const auto on_accept = [this]() const auto on_accept = [this]()
@ -588,7 +591,7 @@ namespace rsx
void osk_dialog::on_key_pressed(u32 led, u32 mkey, u32 key_code, u32 out_key_code, bool pressed) void osk_dialog::on_key_pressed(u32 led, u32 mkey, u32 key_code, u32 out_key_code, bool pressed)
{ {
if (!pressed) if (!pressed || !keyboard_input_enabled || ignore_input_events)
return; return;
osk.notice("osk_dialog::on_key_pressed(led=%d, mkey=%d, key_code=%d, out_key_code=%d, pressed=%d)", led, mkey, key_code, out_key_code, pressed); osk.notice("osk_dialog::on_key_pressed(led=%d, mkey=%d, key_code=%d, out_key_code=%d, pressed=%d)", led, mkey, key_code, out_key_code, pressed);

View File

@ -112,7 +112,7 @@ namespace rsx
compiled_resource get_compiled() override = 0; compiled_resource get_compiled() override = 0;
virtual void on_button_pressed(pad_button /*button_press*/) {} virtual void on_button_pressed(pad_button /*button_press*/) {}
virtual void on_key_pressed(u32 led, u32 mkey, u32 key_code, u32 out_key_code, bool pressed) {} virtual void on_key_pressed(u32 /*led*/, u32 /*mkey*/, u32 /*key_code*/, u32 /*out_key_code*/, bool /*pressed*/) {}
virtual void close(bool use_callback, bool stop_pad_interception); virtual void close(bool use_callback, bool stop_pad_interception);

View File

@ -26,7 +26,7 @@ void basic_keyboard_handler::Init(const u32 max_connect)
memset(&m_info, 0, sizeof(KbInfo)); memset(&m_info, 0, sizeof(KbInfo));
m_info.max_connect = max_connect; m_info.max_connect = max_connect;
m_info.now_connect = std::min(::size32(m_keyboards), max_connect); m_info.now_connect = std::min(::size32(m_keyboards), max_connect);
m_info.info = input::g_intercepted ? CELL_KB_INFO_INTERCEPTED : 0; // Ownership of keyboard data: 0=Application, 1=System m_info.info = input::g_keyboards_intercepted ? CELL_KB_INFO_INTERCEPTED : 0; // Ownership of keyboard data: 0=Application, 1=System
m_info.status[0] = CELL_KB_STATUS_CONNECTED; // (TODO: Support for more keyboards) m_info.status[0] = CELL_KB_STATUS_CONNECTED; // (TODO: Support for more keyboards)
} }
@ -53,7 +53,7 @@ void basic_keyboard_handler::SetTargetWindow(QWindow* target)
bool basic_keyboard_handler::eventFilter(QObject* watched, QEvent* event) bool basic_keyboard_handler::eventFilter(QObject* watched, QEvent* event)
{ {
if (!event || input::g_intercepted) if (!event || input::g_keyboards_intercepted)
{ {
return false; return false;
} }

View File

@ -16,7 +16,7 @@ void basic_mouse_handler::Init(const u32 max_connect)
memset(&m_info, 0, sizeof(MouseInfo)); memset(&m_info, 0, sizeof(MouseInfo));
m_info.max_connect = max_connect; m_info.max_connect = max_connect;
m_info.now_connect = std::min(::size32(m_mice), max_connect); m_info.now_connect = std::min(::size32(m_mice), max_connect);
m_info.info = input::g_intercepted ? CELL_MOUSE_INFO_INTERCEPTED : 0; // Ownership of mouse data: 0=Application, 1=System m_info.info = input::g_mice_intercepted ? CELL_MOUSE_INFO_INTERCEPTED : 0; // Ownership of mouse data: 0=Application, 1=System
for (u32 i = 1; i < max_connect; i++) for (u32 i = 1; i < max_connect; i++)
{ {
m_info.status[i] = CELL_MOUSE_STATUS_DISCONNECTED; m_info.status[i] = CELL_MOUSE_STATUS_DISCONNECTED;
@ -50,7 +50,7 @@ void basic_mouse_handler::SetTargetWindow(QWindow* target)
bool basic_mouse_handler::eventFilter(QObject* target, QEvent* ev) bool basic_mouse_handler::eventFilter(QObject* target, QEvent* ev)
{ {
if (!ev || input::g_intercepted) if (!ev || input::g_mice_intercepted)
{ {
return false; return false;
} }