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
auto& info = g_fxo->get<osk_info>();
u32 maxLength = (inputFieldInfo->limit_length >= CELL_OSKDIALOG_STRING_SIZE) ? 511 : u32{inputFieldInfo->limit_length};
const u32 prohibitFlgs = dialogParam->prohibitFlgs;
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)
{
auto& info = g_fxo->get<osk_info>();
std::lock_guard lock(info.text_mtx);
info.valid_text = {};
}
@ -340,14 +340,23 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dia
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;
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_LOADED, 0);
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]()
{
@ -550,9 +559,19 @@ error_code cellOskDialogSetDeviceMask(u32 deviceMask)
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;
}
@ -569,7 +588,12 @@ error_code cellOskDialogSetSeparateWindowOption(vm::ptr<CellOskDialogSeparateWin
auto& osk = g_fxo->get<osk_info>();
osk.use_separate_windows = true;
osk.osk_continuous_mode = static_cast<CellOskDialogContinuousMode>(+windowOption->continuousMode);
osk.device_mask = windowOption->deviceMask;
// TODO: handle rest of windowOption
// inputFieldWindowWidth;
// inputFieldBackgroundTrans;
// inputFieldLayoutInfo;
// inputPanelLayoutInfo;
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;
// TODO: change osk device input
if (const auto osk = _get_osk_dialog(false))
{
osk->ignore_input_events = true;
}
return CELL_OK;
}
@ -814,7 +841,10 @@ error_code cellOskDialogExtInputDeviceUnlock()
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;
}
@ -888,7 +918,7 @@ error_code cellOskDialogExtSetPointerEnable(b8 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;
}
@ -904,7 +934,7 @@ error_code cellOskDialogExtUpdatePointerDisplayPos(vm::cptr<CellOskDialogPoint>
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;
}

View File

@ -265,6 +265,10 @@ public:
std::function<void()> on_osk_input_entered;
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 };
char16_t osk_text[CELL_OSKDIALOG_STRING_SIZE]{};

View File

@ -7,22 +7,31 @@
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>())
{
handler->SetIntercepted(intercepted);
handler->SetIntercepted(keyboards_intercepted);
}
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
{
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)
{
if (!pad_input_enabled || ignore_input_events)
return;
const auto index_limit = (num_columns * num_rows) - 1;
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)
{
if (!pressed)
if (!pressed || !keyboard_input_enabled || ignore_input_events)
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);

View File

@ -112,7 +112,7 @@ namespace rsx
compiled_resource get_compiled() override = 0;
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);

View File

@ -26,7 +26,7 @@ void basic_keyboard_handler::Init(const u32 max_connect)
memset(&m_info, 0, sizeof(KbInfo));
m_info.max_connect = 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)
}
@ -53,7 +53,7 @@ void basic_keyboard_handler::SetTargetWindow(QWindow* target)
bool basic_keyboard_handler::eventFilter(QObject* watched, QEvent* event)
{
if (!event || input::g_intercepted)
if (!event || input::g_keyboards_intercepted)
{
return false;
}

View File

@ -16,7 +16,7 @@ void basic_mouse_handler::Init(const u32 max_connect)
memset(&m_info, 0, sizeof(MouseInfo));
m_info.max_connect = 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++)
{
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)
{
if (!ev || input::g_intercepted)
if (!ev || input::g_mice_intercepted)
{
return false;
}