mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
OSK: handle keyboard input
This commit is contained in:
parent
abf80cc112
commit
ffd36ea662
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user