1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +01:00

OSK: handle keyboard input

This commit is contained in:
Megamouse 2022-04-04 22:49:59 +02:00
parent abf80cc112
commit ffd36ea662
5 changed files with 173 additions and 16 deletions

View File

@ -56,3 +56,5 @@ struct CellKbConfig
be_t<u32> read_mode;
be_t<u32> code_type;
};
u16 cellKbCnvRawCode(u32 arrange, u32 mkey, u32 led, u16 rawcode);

View File

@ -3,6 +3,7 @@
#include "Emu/RSX/RSXThread.h"
#include "Emu/Cell/Modules/cellSysutil.h"
#include "Emu/Cell/Modules/cellMsgDialog.h"
#include "Emu/Cell/Modules/cellKb.h"
LOG_CHANNEL(osk, "OSK");
@ -12,11 +13,13 @@ namespace rsx
{
osk_dialog::osk_dialog()
{
auto_repeat_buttons.insert(pad_button::L1);
auto_repeat_buttons.insert(pad_button::R1);
auto_repeat_buttons.insert(pad_button::cross);
auto_repeat_buttons.insert(pad_button::triangle);
auto_repeat_buttons.insert(pad_button::square);
m_auto_repeat_buttons.insert(pad_button::L1);
m_auto_repeat_buttons.insert(pad_button::R1);
m_auto_repeat_buttons.insert(pad_button::cross);
m_auto_repeat_buttons.insert(pad_button::triangle);
m_auto_repeat_buttons.insert(pad_button::square);
m_keyboard_input_enabled = true;
}
void osk_dialog::Close(s32 status)
@ -583,6 +586,112 @@ namespace rsx
}
}
void osk_dialog::on_key_pressed(u32 led, u32 mkey, u32 key_code, u32 out_key_code, bool pressed)
{
if (!pressed)
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);
// Get keyboard layout
u32 kb_mapping = CELL_KB_MAPPING_101;
u32 osk_panel_mode = CELL_OSKDIALOG_PANELMODE_DEFAULT;
for (usz i = 0; i < m_panels.size(); ++i)
{
if (m_panel_index == i)
{
osk_panel_mode = m_panels[i].osk_panel_mode;
break;
}
}
switch (osk_panel_mode)
{
case CELL_OSKDIALOG_PANELMODE_DEFAULT : kb_mapping = CELL_KB_MAPPING_101; break;
case CELL_OSKDIALOG_PANELMODE_GERMAN : kb_mapping = CELL_KB_MAPPING_GERMAN_GERMANY; break;
case CELL_OSKDIALOG_PANELMODE_ENGLISH : kb_mapping = CELL_KB_MAPPING_ENGLISH_UK; break;
case CELL_OSKDIALOG_PANELMODE_SPANISH : kb_mapping = CELL_KB_MAPPING_SPANISH_SPAIN; break;
case CELL_OSKDIALOG_PANELMODE_FRENCH : kb_mapping = CELL_KB_MAPPING_FRENCH_FRANCE; break;
case CELL_OSKDIALOG_PANELMODE_ITALIAN : kb_mapping = CELL_KB_MAPPING_ITALIAN_ITALY; break;
case CELL_OSKDIALOG_PANELMODE_DUTCH : kb_mapping = CELL_KB_MAPPING_DUTCH_NETHERLANDS; break;
case CELL_OSKDIALOG_PANELMODE_PORTUGUESE : kb_mapping = CELL_KB_MAPPING_PORTUGUESE_PORTUGAL; break;
case CELL_OSKDIALOG_PANELMODE_RUSSIAN : kb_mapping = CELL_KB_MAPPING_RUSSIAN_RUSSIA; break;
case CELL_OSKDIALOG_PANELMODE_JAPANESE : kb_mapping = CELL_KB_MAPPING_106; break;
case CELL_OSKDIALOG_PANELMODE_DEFAULT_NO_JAPANESE: kb_mapping = CELL_KB_MAPPING_106; break;
case CELL_OSKDIALOG_PANELMODE_POLISH : kb_mapping = CELL_KB_MAPPING_POLISH_POLAND; break;
case CELL_OSKDIALOG_PANELMODE_KOREAN : kb_mapping = CELL_KB_MAPPING_KOREAN_KOREA; break;
case CELL_OSKDIALOG_PANELMODE_TURKEY : kb_mapping = CELL_KB_MAPPING_TURKISH_TURKEY; break;
case CELL_OSKDIALOG_PANELMODE_TRADITIONAL_CHINESE: kb_mapping = CELL_KB_MAPPING_CHINESE_TRADITIONAL; break;
case CELL_OSKDIALOG_PANELMODE_SIMPLIFIED_CHINESE : kb_mapping = CELL_KB_MAPPING_CHINESE_SIMPLIFIED; break;
case CELL_OSKDIALOG_PANELMODE_PORTUGUESE_BRAZIL : kb_mapping = CELL_KB_MAPPING_PORTUGUESE_BRAZIL; break;
case CELL_OSKDIALOG_PANELMODE_DANISH : kb_mapping = CELL_KB_MAPPING_DANISH_DENMARK; break;
case CELL_OSKDIALOG_PANELMODE_SWEDISH : kb_mapping = CELL_KB_MAPPING_SWEDISH_SWEDEN; break;
case CELL_OSKDIALOG_PANELMODE_NORWEGIAN : kb_mapping = CELL_KB_MAPPING_NORWEGIAN_NORWAY; break;
case CELL_OSKDIALOG_PANELMODE_FINNISH : kb_mapping = CELL_KB_MAPPING_FINNISH_FINLAND; break;
case CELL_OSKDIALOG_PANELMODE_JAPANESE_HIRAGANA : kb_mapping = CELL_KB_MAPPING_106; break;
case CELL_OSKDIALOG_PANELMODE_JAPANESE_KATAKANA : kb_mapping = CELL_KB_MAPPING_106_KANA; break;
case CELL_OSKDIALOG_PANELMODE_ALPHABET_FULL_WIDTH: kb_mapping = CELL_KB_MAPPING_106; break;
case CELL_OSKDIALOG_PANELMODE_ALPHABET : kb_mapping = CELL_KB_MAPPING_101; break;
case CELL_OSKDIALOG_PANELMODE_LATIN : kb_mapping = CELL_KB_MAPPING_101; break;
case CELL_OSKDIALOG_PANELMODE_NUMERAL_FULL_WIDTH : kb_mapping = CELL_KB_MAPPING_101; break;
case CELL_OSKDIALOG_PANELMODE_NUMERAL : kb_mapping = CELL_KB_MAPPING_101; break;
case CELL_OSKDIALOG_PANELMODE_URL : kb_mapping = CELL_KB_MAPPING_101; break;
case CELL_OSKDIALOG_PANELMODE_PASSWORD : kb_mapping = CELL_KB_MAPPING_101; break;
default : kb_mapping = CELL_KB_MAPPING_101; break;
}
// Convert key to its u32string presentation
const u16 converted_out_key = cellKbCnvRawCode(kb_mapping, mkey, led, out_key_code);
std::u16string utf16_string;
utf16_string.push_back(converted_out_key);
const std::u32string u32_string = utf16_to_u32string(utf16_string);
const std::string out_key_string = utf16_to_ascii8(utf16_string);
// Find matching key in the OSK
for (const cell& current_cell : m_grid)
{
// TODO: maybe just ignore the current charset and check all outputs
if (m_selected_charset < current_cell.outputs.size())
{
for (const auto& str : current_cell.outputs[m_selected_charset])
{
if (str == u32_string)
{
// Apply key press
if (current_cell.callback)
{
current_cell.callback(str);
}
else
{
on_default_callback(str);
}
return;
}
}
}
}
// Handle special input
if (!out_key_string.empty())
{
switch (out_key_string[0])
{
case ' ':
on_space(u32_string);
return;
case '\b':
on_backspace(u32_string);
return;
case '\n':
on_enter(u32_string);
return;
default:
break;
}
}
}
void osk_dialog::on_text_changed()
{
const auto ws = u32string_to_utf16(m_preview.value);

View File

@ -96,6 +96,7 @@ namespace rsx
void update_selection_by_index(u32 index);
void on_button_pressed(pad_button button_press) override;
void on_key_pressed(u32 led, u32 mkey, u32 key_code, u32 out_key_code, bool pressed) override;
void on_text_changed();
void on_default_callback(const std::u32string& str);

View File

@ -3,6 +3,7 @@
#include "overlay_message_dialog.h"
#include "Input/pad_thread.h"
#include "Emu/Io/interception.h"
#include "Emu/Io/KeyboardHandler.h"
#include "Emu/RSX/RSXThread.h"
#include "Emu/RSX/Common/time.hpp"
@ -64,7 +65,7 @@ namespace rsx
state.fill(true);
}
input_timer.Start();
m_input_timer.Start();
input::SetIntercepted(true);
@ -77,7 +78,7 @@ namespace rsx
if (pressed)
{
const bool is_auto_repeat_button = auto_repeat_buttons.contains(button_id);
const bool is_auto_repeat_button = m_auto_repeat_buttons.contains(button_id);
if (!last_button_state[pad_index][button_id])
{
@ -90,8 +91,8 @@ namespace rsx
else if (is_auto_repeat_button)
{
if (last_auto_repeat_button[pad_index] == button_id
&& input_timer.GetMsSince(initial_timestamp[pad_index]) > ms_threshold
&& input_timer.GetMsSince(timestamp[pad_index]) > ms_interval)
&& m_input_timer.GetMsSince(initial_timestamp[pad_index]) > ms_threshold
&& m_input_timer.GetMsSince(timestamp[pad_index]) > ms_interval)
{
// The auto-repeat button was pressed for at least the given threshold in ms and will trigger at an interval.
timestamp[pad_index] = steady_clock::now();
@ -115,18 +116,60 @@ namespace rsx
while (!exit)
{
std::this_thread::sleep_for(1ms);
if (Emu.IsStopped())
return selection_code::canceled;
std::this_thread::sleep_for(1ms);
if (Emu.IsPaused())
continue;
// Get keyboard input
if (m_keyboard_input_enabled)
{
auto& handler = g_fxo->get<KeyboardHandlerBase>();
std::lock_guard<std::mutex> lock(handler.m_mutex);
const KbInfo& current_info = handler.GetInfo();
if (!handler.GetKeyboards().empty() && current_info.status[0] == CELL_KB_STATUS_CONNECTED)
{
KbData& current_data = handler.GetData(0);
if (current_data.len > 0)
{
for (s32 i = 0; i < current_data.len; i++)
{
const KbButton& key = current_data.buttons[i];
on_key_pressed(current_data.led, current_data.mkey, key.m_keyCode, key.m_outKeyCode, key.m_pressed);
}
// TODO: is the following step necessary in the overlays?
KbConfig& current_config = handler.GetConfig(0);
// For single character mode to work properly we need to "flush" the buffer after reading or else we'll constantly get the same key presses with each call.
// Actual key repeats are handled by adding a new key code to the buffer periodically. Key releases are handled in a similar fashion.
// Warning: Don't do this in packet mode, which is basically the mouse and keyboard gaming mode. Otherwise games like Unreal Tournament will be unplayable.
if (current_config.read_mode == CELL_KB_RMODE_INPUTCHAR)
{
current_data.len = 0;
}
}
}
else
{
// TODO: Init handler only if the game requests keyboard input.
// This probably needs to happen completely seperate from cellKb.
handler.Init(1);
}
}
// Get gamepad input
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)
if (!rinfo.now_connect)
{
continue;
}

View File

@ -81,8 +81,8 @@ namespace rsx
};
protected:
Timer input_timer;
std::set<u8> auto_repeat_buttons = {
Timer m_input_timer;
std::set<u8> m_auto_repeat_buttons = {
pad_button::dpad_up,
pad_button::dpad_down,
pad_button::dpad_left,
@ -96,12 +96,13 @@ namespace rsx
atomic_t<bool> m_interactive = false;
atomic_t<bool> m_stop_pad_interception = false;
atomic_t<u64> thread_bits = 0;
bool m_keyboard_input_enabled = false;
static thread_local u64 g_thread_bit;
u64 alloc_thread_bit();
std::function<void(s32 status)> on_close;
std::function<void(s32 status)> on_close = nullptr;
public:
s32 return_code = 0; // CELL_OK
@ -111,6 +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 close(bool use_callback, bool stop_pad_interception);