2020-12-05 13:08:24 +01:00
# include "stdafx.h"
2017-05-15 13:58:32 +02:00
# include "Emu/System.h"
2020-03-14 22:03:56 +01:00
# include "Emu/system_config.h"
2018-12-30 02:34:15 +01:00
# include "Emu/Cell/PPUModule.h"
2020-10-04 22:46:28 +02:00
# include "Emu/Io/interception.h"
2022-04-19 23:36:18 +02:00
# include "Emu/Io/Keyboard.h"
2020-02-24 20:09:46 +01:00
# include "Emu/RSX/Overlays/overlay_osk.h"
2020-11-06 18:45:06 +01:00
# include "Emu/IdManager.h"
2017-05-15 13:58:32 +02:00
2017-01-18 23:01:25 +01:00
# include "cellSysutil.h"
# include "cellOskDialog.h"
2017-01-23 18:14:12 +01:00
# include "cellMsgDialog.h"
2015-07-30 03:43:03 +02:00
2019-09-26 20:35:27 +02:00
# include "util/init_mutex.hpp"
2020-11-06 18:45:06 +01:00
# include <thread>
2018-08-25 14:39:00 +02:00
LOG_CHANNEL ( cellOskDialog ) ;
2015-07-30 03:43:03 +02:00
2019-01-04 14:45:32 +01:00
template < >
void fmt_class_string < CellOskDialogError > : : format ( std : : string & out , u64 arg )
{
format_enum ( out , arg , [ ] ( auto error )
{
switch ( error )
{
STR_CASE ( CELL_OSKDIALOG_ERROR_IME_ALREADY_IN_USE ) ;
STR_CASE ( CELL_OSKDIALOG_ERROR_GET_SIZE_ERROR ) ;
STR_CASE ( CELL_OSKDIALOG_ERROR_UNKNOWN ) ;
STR_CASE ( CELL_OSKDIALOG_ERROR_PARAM ) ;
}
return unknown ;
} ) ;
}
2021-09-21 00:59:11 +02:00
template < >
void fmt_class_string < CellOskDialogContinuousMode > : : format ( std : : string & out , u64 arg )
{
format_enum ( out , arg , [ ] ( auto mode )
{
switch ( mode )
{
STR_CASE ( CELL_OSKDIALOG_CONTINUOUS_MODE_NONE ) ;
STR_CASE ( CELL_OSKDIALOG_CONTINUOUS_MODE_REMAIN_OPEN ) ;
STR_CASE ( CELL_OSKDIALOG_CONTINUOUS_MODE_HIDE ) ;
STR_CASE ( CELL_OSKDIALOG_CONTINUOUS_MODE_SHOW ) ;
}
return unknown ;
} ) ;
}
2019-01-04 22:28:52 +01:00
OskDialogBase : : ~ OskDialogBase ( )
{
}
2017-01-23 18:14:12 +01:00
2019-09-26 20:35:27 +02:00
struct osk_info
2019-01-29 17:29:55 +01:00
{
2019-09-26 20:35:27 +02:00
std : : shared_ptr < OskDialogBase > dlg ;
2021-09-20 21:19:34 +02:00
std : : array < char16_t , CELL_OSKDIALOG_STRING_SIZE > valid_text { } ;
shared_mutex text_mtx ;
2019-09-26 20:35:27 +02:00
atomic_t < bool > use_separate_windows = false ;
2021-09-19 21:21:56 +02:00
atomic_t < bool > lock_ext_input = false ;
atomic_t < u32 > device_mask = 0 ; // 0 means all devices can influence the OSK
atomic_t < u32 > key_layout = CELL_OSKDIALOG_10KEY_PANEL ;
atomic_t < CellOskDialogInitialKeyLayout > initial_key_layout = CELL_OSKDIALOG_INITIAL_PANEL_LAYOUT_SYSTEM ;
atomic_t < CellOskDialogInputDevice > initial_input_device = CELL_OSKDIALOG_INPUT_DEVICE_PAD ;
atomic_t < bool > clipboard_enabled = false ; // For copy and paste
atomic_t < bool > half_byte_kana_enabled = false ;
atomic_t < u32 > supported_languages = 0 ; // Used to enable non-default languages in the OSK
atomic_t < bool > dimmer_enabled = true ;
2022-04-20 18:16:27 +02:00
atomic_t < OskDialogBase : : color > base_color = OskDialogBase : : color { 0.2f , 0.2f , 0.2f , 1.0f } ;
2021-09-19 21:21:56 +02:00
atomic_t < bool > pointer_enabled = false ;
CellOskDialogPoint pointer_pos { 0.0f , 0.0f } ;
atomic_t < f32 > initial_scale = 1.0f ;
atomic_t < u32 > layout_mode = CELL_OSKDIALOG_LAYOUTMODE_X_ALIGN_LEFT | CELL_OSKDIALOG_LAYOUTMODE_Y_ALIGN_TOP ;
2019-09-26 20:35:27 +02:00
atomic_t < CellOskDialogContinuousMode > osk_continuous_mode = CELL_OSKDIALOG_CONTINUOUS_MODE_NONE ;
2021-09-20 21:19:34 +02:00
atomic_t < u32 > last_dialog_state = CELL_SYSUTIL_OSKDIALOG_UNLOADED ; // Used for continuous seperate window dialog
2019-09-26 20:35:27 +02:00
atomic_t < vm : : ptr < cellOskDialogConfirmWordFilterCallback > > osk_confirm_callback { } ;
2022-04-19 19:15:12 +02:00
atomic_t < vm : : ptr < cellOskDialogForceFinishCallback > > osk_force_finish_callback { } ;
atomic_t < vm : : ptr < cellOskDialogHardwareKeyboardEventHookCallback > > osk_hardware_keyboard_event_hook_callback { } ;
2022-04-19 23:36:18 +02:00
atomic_t < u16 > hook_event_mode { 0 } ;
2019-09-26 20:35:27 +02:00
stx : : init_mutex init ;
2021-09-19 21:51:45 +02:00
void reset ( )
{
2021-09-20 21:19:34 +02:00
std : : lock_guard lock ( text_mtx ) ;
2021-09-19 21:51:45 +02:00
dlg . reset ( ) ;
2021-09-20 21:19:34 +02:00
valid_text = { } ;
2021-09-19 21:51:45 +02:00
use_separate_windows = false ;
lock_ext_input = false ;
device_mask = 0 ;
key_layout = CELL_OSKDIALOG_10KEY_PANEL ;
initial_key_layout = CELL_OSKDIALOG_INITIAL_PANEL_LAYOUT_SYSTEM ;
initial_input_device = CELL_OSKDIALOG_INPUT_DEVICE_PAD ;
clipboard_enabled = false ;
half_byte_kana_enabled = false ;
supported_languages = 0 ;
dimmer_enabled = true ;
2022-04-20 18:16:27 +02:00
base_color = OskDialogBase : : color { 0.2f , 0.2f , 0.2f , 1.0f } ;
2021-09-19 21:51:45 +02:00
pointer_enabled = false ;
pointer_pos = { 0.0f , 0.0f } ;
initial_scale = 1.0f ;
layout_mode = CELL_OSKDIALOG_LAYOUTMODE_X_ALIGN_LEFT | CELL_OSKDIALOG_LAYOUTMODE_Y_ALIGN_TOP ;
osk_continuous_mode = CELL_OSKDIALOG_CONTINUOUS_MODE_NONE ;
2021-09-20 21:19:34 +02:00
last_dialog_state = CELL_SYSUTIL_OSKDIALOG_UNLOADED ;
2021-09-19 21:51:45 +02:00
osk_confirm_callback . store ( { } ) ;
2022-04-19 19:15:12 +02:00
osk_force_finish_callback . store ( { } ) ;
osk_hardware_keyboard_event_hook_callback . store ( { } ) ;
2022-04-19 23:36:18 +02:00
hook_event_mode . store ( 0 ) ;
2021-09-19 21:51:45 +02:00
}
2019-09-26 20:35:27 +02:00
} ;
// TODO: don't use this function
2022-04-19 19:15:12 +02:00
std : : shared_ptr < OskDialogBase > _get_osk_dialog ( bool create )
2019-09-26 20:35:27 +02:00
{
2021-03-02 12:59:19 +01:00
auto & osk = g_fxo - > get < osk_info > ( ) ;
2019-09-26 20:35:27 +02:00
if ( create )
2019-01-29 17:29:55 +01:00
{
2021-03-02 12:59:19 +01:00
const auto init = osk . init . init ( ) ;
2019-09-26 20:35:27 +02:00
if ( ! init )
2019-01-29 17:29:55 +01:00
{
2019-09-26 20:35:27 +02:00
return nullptr ;
}
2021-02-03 19:14:31 +01:00
if ( auto manager = g_fxo - > try_get < rsx : : overlays : : display_manager > ( ) )
2019-09-26 20:35:27 +02:00
{
2020-03-14 22:03:56 +01:00
std : : shared_ptr < rsx : : overlays : : osk_dialog > dlg = std : : make_shared < rsx : : overlays : : osk_dialog > ( ) ;
2021-03-02 12:59:19 +01:00
osk . dlg = manager - > add ( dlg ) ;
2019-09-26 20:35:27 +02:00
}
else
{
2021-03-02 12:59:19 +01:00
osk . dlg = Emu . GetCallbacks ( ) . get_osk_dialog ( ) ;
2019-01-29 17:29:55 +01:00
}
2021-03-02 12:59:19 +01:00
return osk . dlg ;
2019-01-29 17:29:55 +01:00
}
2019-09-26 20:35:27 +02:00
2021-09-20 20:39:37 +02:00
const auto init = osk . init . access ( ) ;
2019-01-29 17:29:55 +01:00
2021-09-20 20:39:37 +02:00
if ( ! init )
{
return nullptr ;
2019-01-29 17:29:55 +01:00
}
2021-09-20 20:39:37 +02:00
return osk . dlg ;
2019-01-29 17:29:55 +01:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogLoadAsync ( u32 container , vm : : ptr < CellOskDialogParam > dialogParam , vm : : ptr < CellOskDialogInputFieldInfo > inputFieldInfo )
2015-07-30 03:43:03 +02:00
{
2017-01-18 23:01:25 +01:00
cellOskDialog . warning ( " cellOskDialogLoadAsync(container=0x%x, dialogParam=*0x%x, inputFieldInfo=*0x%x) " , container , dialogParam , inputFieldInfo ) ;
2017-01-23 18:14:12 +01:00
2019-01-05 18:11:43 +01:00
if ( ! dialogParam | | ! inputFieldInfo | | ! inputFieldInfo - > message | | ! inputFieldInfo - > init_text | | inputFieldInfo - > limit_length > CELL_OSKDIALOG_STRING_SIZE )
2018-12-30 22:27:37 +01:00
{
return CELL_OSKDIALOG_ERROR_PARAM ;
}
2019-01-29 17:29:55 +01:00
auto osk = _get_osk_dialog ( true ) ;
2018-12-30 22:27:37 +01:00
2019-01-04 02:02:26 +01:00
// Can't open another dialog if this one is already open.
2021-09-21 00:59:11 +02:00
if ( ! osk | | osk - > state . load ( ) ! = OskDialogState : : Unloaded )
2018-12-30 22:27:37 +01:00
{
return CELL_SYSUTIL_ERROR_BUSY ;
}
2019-01-05 18:11:43 +01:00
// Get the OSK options
2022-04-19 20:27:32 +02:00
auto & info = g_fxo - > get < osk_info > ( ) ;
2019-12-02 22:31:34 +01:00
u32 maxLength = ( inputFieldInfo - > limit_length > = CELL_OSKDIALOG_STRING_SIZE ) ? 511 : u32 { inputFieldInfo - > limit_length } ;
2020-03-14 22:03:56 +01:00
const u32 prohibitFlgs = dialogParam - > prohibitFlgs ;
const u32 allowOskPanelFlg = dialogParam - > allowOskPanelFlg ;
const u32 firstViewPanel = dialogParam - > firstViewPanel ;
2017-08-21 01:10:28 +02:00
2019-01-04 14:05:37 +01:00
// Get init text and prepare return value
2019-01-04 22:28:52 +01:00
osk - > osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_OK ;
std : : memset ( osk - > osk_text , 0 , sizeof ( osk - > osk_text ) ) ;
2021-09-20 21:19:34 +02:00
// Also clear the info text just to be sure (it should be zeroed at this point anyway)
{
std : : lock_guard lock ( info . text_mtx ) ;
info . valid_text = { } ;
}
2017-01-23 18:14:12 +01:00
2019-12-20 04:51:16 +01:00
if ( inputFieldInfo - > init_text )
2018-12-30 20:58:56 +01:00
{
2017-08-21 01:10:28 +02:00
for ( u32 i = 0 ; ( i < maxLength ) & & ( inputFieldInfo - > init_text [ i ] ! = 0 ) ; i + + )
2018-12-30 20:58:56 +01:00
{
2019-01-04 22:28:52 +01:00
osk - > osk_text [ i ] = inputFieldInfo - > init_text [ i ] ;
2018-12-30 20:58:56 +01:00
}
}
2017-08-21 01:10:28 +02:00
2019-01-04 14:05:37 +01:00
// Get message to display above the input field
// Guarantees 0 terminated (+1). In praxis only 128 but for now lets display all of it
2019-12-20 04:51:16 +01:00
char16_t message [ CELL_OSKDIALOG_STRING_SIZE + 1 ] { } ;
2019-01-04 14:05:37 +01:00
2019-12-20 04:51:16 +01:00
if ( inputFieldInfo - > message )
2019-01-04 14:05:37 +01:00
{
for ( u32 i = 0 ; ( i < CELL_OSKDIALOG_STRING_SIZE ) & & ( inputFieldInfo - > message [ i ] ! = 0 ) ; i + + )
{
message [ i ] = inputFieldInfo - > message [ i ] ;
}
}
2021-02-13 17:05:31 +01:00
atomic_t < bool > result = false ;
2017-01-23 18:14:12 +01:00
2021-04-09 21:12:47 +02:00
osk - > on_osk_close = [ wptr = std : : weak_ptr < OskDialogBase > ( osk ) ] ( s32 status )
2017-01-23 18:14:12 +01:00
{
2022-04-09 23:41:33 +02:00
cellOskDialog . notice ( " on_osk_close(status=%d) " , status ) ;
2019-01-12 11:30:33 +01:00
2021-09-21 00:59:11 +02:00
const auto osk = wptr . lock ( ) ;
osk - > state = OskDialogState : : Closed ;
2019-01-12 11:30:33 +01:00
2021-09-20 21:19:34 +02:00
auto & info = g_fxo - > get < osk_info > ( ) ;
const bool keep_seperate_window_open = info . use_separate_windows . load ( ) & & ( info . osk_continuous_mode . load ( ) ! = CELL_OSKDIALOG_CONTINUOUS_MODE_NONE ) ;
2019-01-04 04:33:05 +01:00
2021-09-19 21:12:42 +02:00
switch ( status )
{
case CELL_OSKDIALOG_CLOSE_CONFIRM :
2019-01-04 04:33:05 +01:00
{
2021-09-20 21:19:34 +02:00
if ( auto ccb = info . osk_confirm_callback . exchange ( { } ) )
2019-01-05 01:32:45 +01:00
{
2021-09-21 10:29:32 +02:00
std : : vector < u16 > string_to_send ( CELL_OSKDIALOG_STRING_SIZE ) ;
2019-01-05 01:32:45 +01:00
atomic_t < bool > done = false ;
2019-06-07 06:27:49 +02:00
u32 i ;
2019-01-05 01:32:45 +01:00
2019-06-07 06:27:49 +02:00
for ( i = 0 ; i < CELL_OSKDIALOG_STRING_SIZE - 1 ; i + + )
2019-01-05 01:32:45 +01:00
{
string_to_send [ i ] = osk - > osk_text [ i ] ;
if ( osk - > osk_text [ i ] = = 0 ) break ;
}
2021-09-21 10:29:32 +02:00
sysutil_register_cb ( [ & , length = i , string_to_send = std : : move ( string_to_send ) ] ( ppu_thread & cb_ppu ) - > s32
2019-01-05 01:32:45 +01:00
{
2021-09-21 10:29:32 +02:00
vm : : var < u16 [ ] , vm : : page_allocator < > > string_var ( CELL_OSKDIALOG_STRING_SIZE , string_to_send . data ( ) ) ;
const u32 return_value = ccb ( cb_ppu , string_var . begin ( ) , static_cast < s32 > ( length ) ) ;
2019-01-05 01:32:45 +01:00
cellOskDialog . warning ( " osk_confirm_callback return_value=%d " , return_value ) ;
for ( u32 i = 0 ; i < CELL_OSKDIALOG_STRING_SIZE - 1 ; i + + )
{
2021-09-21 10:29:32 +02:00
osk - > osk_text [ i ] = string_var . begin ( ) [ i ] ;
2019-01-05 01:32:45 +01:00
}
done = true ;
return 0 ;
} ) ;
2019-01-05 18:11:43 +01:00
// wait for check callback
2021-02-13 17:05:31 +01:00
while ( ! done & & ! Emu . IsStopped ( ) )
2019-01-05 01:32:45 +01:00
{
2019-01-05 18:11:43 +01:00
std : : this_thread : : yield ( ) ;
2019-01-05 01:32:45 +01:00
}
}
2019-01-05 18:11:43 +01:00
2021-09-20 21:19:34 +02:00
if ( info . use_separate_windows . load ( ) & & osk - > osk_text [ 0 ] = = 0 )
2019-01-05 18:11:43 +01:00
{
2019-01-06 13:40:03 +01:00
cellOskDialog . warning ( " cellOskDialogLoadAsync: input result is CELL_OSKDIALOG_INPUT_FIELD_RESULT_NO_INPUT_TEXT " ) ;
osk - > osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_NO_INPUT_TEXT ;
2019-01-05 18:11:43 +01:00
}
else
{
osk - > osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_OK ;
}
2021-09-19 21:12:42 +02:00
break ;
2019-01-05 18:11:43 +01:00
}
2021-09-19 21:12:42 +02:00
case CELL_OSKDIALOG_CLOSE_CANCEL :
2019-01-05 18:11:43 +01:00
{
osk - > osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_CANCELED ;
2021-09-19 21:12:42 +02:00
break ;
}
2021-09-21 00:59:11 +02:00
case FAKE_CELL_OSKDIALOG_CLOSE_ABORT :
2021-09-19 21:12:42 +02:00
{
osk - > osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_ABORT ;
break ;
}
2021-09-21 00:59:11 +02:00
default :
{
cellOskDialog . fatal ( " on_osk_close: Unknown status (%d) " , status ) ;
break ;
}
2019-01-04 04:33:05 +01:00
}
2019-01-05 18:11:43 +01:00
// Send OSK status
2021-09-20 21:19:34 +02:00
if ( keep_seperate_window_open )
2019-01-05 18:11:43 +01:00
{
2021-09-19 21:12:42 +02:00
switch ( status )
{
case CELL_OSKDIALOG_CLOSE_CONFIRM :
2019-01-05 18:11:43 +01:00
{
2021-09-20 21:19:34 +02:00
info . last_dialog_state = CELL_SYSUTIL_OSKDIALOG_INPUT_ENTERED ;
2019-01-06 13:40:03 +01:00
sysutil_send_system_cmd ( CELL_SYSUTIL_OSKDIALOG_INPUT_ENTERED , 0 ) ;
2021-09-19 21:12:42 +02:00
break ;
2019-01-05 18:11:43 +01:00
}
2021-09-19 21:12:42 +02:00
case CELL_OSKDIALOG_CLOSE_CANCEL :
2019-01-05 18:11:43 +01:00
{
2021-09-20 21:19:34 +02:00
info . last_dialog_state = CELL_SYSUTIL_OSKDIALOG_INPUT_CANCELED ;
2019-01-05 18:11:43 +01:00
sysutil_send_system_cmd ( CELL_SYSUTIL_OSKDIALOG_INPUT_CANCELED , 0 ) ;
2021-09-19 21:12:42 +02:00
break ;
}
2021-09-21 00:59:11 +02:00
case FAKE_CELL_OSKDIALOG_CLOSE_ABORT :
{
// Handled in cellOskDialogAbort
break ;
}
2021-09-19 21:12:42 +02:00
default :
{
2021-09-21 00:59:11 +02:00
cellOskDialog . fatal ( " on_osk_close: Unknown status (%d) " , status ) ;
2021-09-19 21:12:42 +02:00
break ;
}
2019-01-05 18:11:43 +01:00
}
2021-09-21 00:59:11 +02:00
if ( info . osk_continuous_mode . load ( ) = = CELL_OSKDIALOG_CONTINUOUS_MODE_HIDE )
{
sysutil_send_system_cmd ( CELL_SYSUTIL_OSKDIALOG_DISPLAY_CHANGED , CELL_OSKDIALOG_DISPLAY_STATUS_HIDE ) ;
}
2019-01-05 18:11:43 +01:00
}
2021-09-21 00:59:11 +02:00
else if ( status ! = FAKE_CELL_OSKDIALOG_CLOSE_ABORT ) // Handled in cellOskDialogAbort
2019-01-05 18:11:43 +01:00
{
2021-09-20 21:19:34 +02:00
info . last_dialog_state = CELL_SYSUTIL_OSKDIALOG_FINISHED ;
2019-01-05 18:11:43 +01:00
sysutil_send_system_cmd ( CELL_SYSUTIL_OSKDIALOG_FINISHED , 0 ) ;
}
2018-12-30 02:34:15 +01:00
2020-10-04 22:46:28 +02:00
input : : SetIntercepted ( false ) ;
2017-01-23 18:14:12 +01:00
} ;
2022-04-19 23:36:18 +02:00
// Set key callback
osk - > on_osk_key_input_entered = [ wptr = std : : weak_ptr < OskDialogBase > ( osk ) ] ( CellOskDialogKeyMessage key_message )
2021-09-21 00:59:11 +02:00
{
2022-04-19 23:36:18 +02:00
const auto osk = wptr . lock ( ) ;
auto & info = g_fxo - > get < osk_info > ( ) ;
2022-04-20 22:44:57 +02:00
std : : lock_guard lock ( info . text_mtx ) ;
auto event_hook_callback = info . osk_hardware_keyboard_event_hook_callback . load ( ) ;
cellOskDialog . notice ( " on_osk_key_input_entered: led=%d, mkey=%d, keycode=%d, hook_event_mode=%d, event_hook_callback=*0x%x " , key_message . led , key_message . mkey , key_message . keycode , info . hook_event_mode . load ( ) , event_hook_callback ) ;
if ( ! event_hook_callback )
{
// Nothing to do here
return ;
}
2022-04-19 23:36:18 +02:00
bool is_kook_key = false ;
switch ( key_message . keycode )
{
case CELL_KEYC_NO_EVENT :
{
// Any shift/alt/ctrl key
is_kook_key = key_message . mkey > 0 & & ( info . hook_event_mode & CELL_OSKDIALOG_EVENT_HOOK_TYPE_ONLY_MODIFIER ) ;
break ;
}
case CELL_KEYC_E_ROLLOVER :
case CELL_KEYC_E_POSTFAIL :
case CELL_KEYC_E_UNDEF :
case CELL_KEYC_ESCAPE :
case CELL_KEYC_106_KANJI :
case CELL_KEYC_CAPS_LOCK :
case CELL_KEYC_F1 :
case CELL_KEYC_F2 :
case CELL_KEYC_F3 :
case CELL_KEYC_F4 :
case CELL_KEYC_F5 :
case CELL_KEYC_F6 :
case CELL_KEYC_F7 :
case CELL_KEYC_F8 :
case CELL_KEYC_F9 :
case CELL_KEYC_F10 :
case CELL_KEYC_F11 :
case CELL_KEYC_F12 :
case CELL_KEYC_PRINTSCREEN :
case CELL_KEYC_SCROLL_LOCK :
case CELL_KEYC_PAUSE :
case CELL_KEYC_INSERT :
case CELL_KEYC_HOME :
case CELL_KEYC_PAGE_UP :
case CELL_KEYC_DELETE :
case CELL_KEYC_END :
case CELL_KEYC_PAGE_DOWN :
case CELL_KEYC_RIGHT_ARROW :
case CELL_KEYC_LEFT_ARROW :
case CELL_KEYC_DOWN_ARROW :
case CELL_KEYC_UP_ARROW :
case CELL_KEYC_NUM_LOCK :
case CELL_KEYC_APPLICATION :
case CELL_KEYC_KANA :
case CELL_KEYC_HENKAN :
case CELL_KEYC_MUHENKAN :
{
// Any function key or other special key like Delete
is_kook_key = ( info . hook_event_mode & CELL_OSKDIALOG_EVENT_HOOK_TYPE_FUNCTION_KEY ) ;
break ;
}
default :
{
// Any regular ascii key
is_kook_key = ( info . hook_event_mode & CELL_OSKDIALOG_EVENT_HOOK_TYPE_ASCII_KEY ) ;
break ;
}
}
if ( ! is_kook_key )
2022-04-20 22:44:57 +02:00
{
cellOskDialog . notice ( " on_osk_key_input_entered: not a hook key: led=%d, mkey=%d, keycode=%d, hook_event_mode=%d " , key_message . led , key_message . mkey , key_message . keycode , info . hook_event_mode . load ( ) ) ;
2022-04-19 23:36:18 +02:00
return ;
2022-04-20 22:44:57 +02:00
}
constexpr u32 max_size = 101 ;
std : : vector < u16 > string_to_send ( max_size , 0 ) ;
atomic_t < bool > done = false ;
2022-04-19 23:36:18 +02:00
2022-04-20 22:44:57 +02:00
for ( u32 i = 0 ; i < max_size - 1 ; i + + )
2022-04-19 23:36:18 +02:00
{
2022-04-20 22:44:57 +02:00
string_to_send [ i ] = osk - > osk_text [ i ] ;
if ( osk - > osk_text [ i ] = = 0 ) break ;
}
2022-04-19 23:36:18 +02:00
2022-04-20 22:44:57 +02:00
sysutil_register_cb ( [ & ] ( ppu_thread & cb_ppu ) - > s32
{
vm : : var < CellOskDialogKeyMessage > keyMessage ( key_message ) ;
vm : : var < u32 > action ( CELL_OSKDIALOG_CHANGE_NO_EVENT ) ;
vm : : var < u16 [ ] , vm : : page_allocator < > > pActionInfo ( max_size , string_to_send . data ( ) ) ;
std : : u16string utf16_string ;
utf16_string . insert ( 0 , reinterpret_cast < char16_t * > ( string_to_send . data ( ) ) , string_to_send . size ( ) ) ;
std : : string action_info = utf16_to_ascii8 ( utf16_string ) ;
2022-04-19 23:36:18 +02:00
2022-04-20 22:44:57 +02:00
cellOskDialog . notice ( " osk_hardware_keyboard_event_hook_callback(led=%d, mkey=%d, keycode=%d, action=%d, pActionInfo='%s') " , keyMessage - > led , keyMessage - > mkey , keyMessage - > keycode , * action , action_info ) ;
const bool return_value = event_hook_callback ( cb_ppu , keyMessage , action , pActionInfo . begin ( ) ) ;
ensure ( action ) ;
ensure ( pActionInfo ) ;
utf16_string . clear ( ) ;
for ( u32 i = 0 ; i < max_size ; i + + )
2022-04-19 23:36:18 +02:00
{
2022-04-20 22:44:57 +02:00
const u16 code = pActionInfo [ i ] ;
if ( ! code ) break ;
utf16_string . push_back ( code ) ;
}
action_info = utf16_to_ascii8 ( utf16_string ) ;
2022-04-19 23:36:18 +02:00
2022-04-20 22:44:57 +02:00
cellOskDialog . notice ( " osk_hardware_keyboard_event_hook_callback: return_value=%d, action=%d, pActionInfo='%s' " , return_value , * action , action_info ) ;
2022-04-19 23:36:18 +02:00
2022-04-20 22:44:57 +02:00
if ( return_value )
{
switch ( * action )
2022-04-19 23:36:18 +02:00
{
2022-04-20 22:44:57 +02:00
case CELL_OSKDIALOG_CHANGE_NO_EVENT :
case CELL_OSKDIALOG_CHANGE_EVENT_CANCEL :
{
// Do nothing
break ;
}
case CELL_OSKDIALOG_CHANGE_WORDS_INPUT :
{
// Set unconfirmed string and reset unconfirmed string
for ( u32 i = 0 ; i < max_size ; i + + )
2022-04-19 23:36:18 +02:00
{
2022-04-20 22:44:57 +02:00
osk - > osk_text [ i ] = pActionInfo . begin ( ) [ i ] ;
2022-04-19 23:36:18 +02:00
}
2022-04-20 22:44:57 +02:00
break ;
}
case CELL_OSKDIALOG_CHANGE_WORDS_INSERT :
{
// Set confirmed string and reset unconfirmed string
for ( u32 i = 0 ; i < max_size ; i + + )
2022-04-19 23:36:18 +02:00
{
2022-04-20 22:44:57 +02:00
info . valid_text [ i ] = pActionInfo . begin ( ) [ i ] ;
osk - > osk_text [ i ] = 0 ;
2022-04-19 23:36:18 +02:00
}
2022-04-20 22:44:57 +02:00
break ;
}
case CELL_OSKDIALOG_CHANGE_WORDS_REPLACE_ALL :
{
// Set confirmed string and reset all strings
for ( u32 i = 0 ; i < max_size ; i + + )
2022-04-19 23:36:18 +02:00
{
2022-04-20 22:44:57 +02:00
info . valid_text [ i ] = pActionInfo . begin ( ) [ i ] ;
osk - > osk_text [ i ] = 0 ;
2022-04-19 23:36:18 +02:00
}
2022-04-20 22:44:57 +02:00
break ;
}
default :
{
cellOskDialog . error ( " osk_hardware_keyboard_event_hook_callback returned invalid action (%d) " , * action ) ;
break ;
2022-04-19 23:36:18 +02:00
}
2022-04-20 22:44:57 +02:00
}
}
2022-04-19 23:36:18 +02:00
2022-04-20 22:44:57 +02:00
done = true ;
return 0 ;
} ) ;
2022-04-19 23:36:18 +02:00
2022-04-20 22:44:57 +02:00
// wait for callback
while ( ! done & & ! Emu . IsStopped ( ) )
{
std : : this_thread : : yield ( ) ;
2022-04-19 23:36:18 +02:00
}
} ;
2021-09-21 00:59:11 +02:00
2022-04-19 20:27:32 +02:00
// 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 ) ;
2018-12-30 02:34:15 +01:00
2022-04-19 23:36:18 +02:00
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 ;
}
2022-04-20 18:16:27 +02:00
Emu . CallFromMainThread ( [ = , & result , & info ] ( )
2017-01-23 18:14:12 +01:00
{
2022-04-26 00:20:07 +02:00
osk - > Create ( get_localized_string ( localized_string_id : : CELL_OSK_DIALOG_TITLE ) , message , osk - > osk_text , maxLength , prohibitFlgs , allowOskPanelFlg , firstViewPanel , info . base_color . load ( ) , info . dimmer_enabled . load ( ) , false ) ;
2018-12-30 02:34:15 +01:00
result = true ;
2021-02-13 17:05:31 +01:00
result . notify_one ( ) ;
2021-09-21 00:59:11 +02:00
if ( g_fxo - > get < osk_info > ( ) . osk_continuous_mode . load ( ) = = CELL_OSKDIALOG_CONTINUOUS_MODE_HIDE )
{
sysutil_send_system_cmd ( CELL_SYSUTIL_OSKDIALOG_DISPLAY_CHANGED , CELL_OSKDIALOG_DISPLAY_STATUS_SHOW ) ;
}
2017-01-23 18:14:12 +01:00
} ) ;
2021-09-21 00:59:11 +02:00
g_fxo - > get < osk_info > ( ) . last_dialog_state = CELL_SYSUTIL_OSKDIALOG_LOADED ;
2017-03-16 10:34:47 +01:00
sysutil_send_system_cmd ( CELL_SYSUTIL_OSKDIALOG_LOADED , 0 ) ;
2021-02-13 17:05:31 +01:00
while ( ! result & & ! Emu . IsStopped ( ) )
2017-01-23 18:14:12 +01:00
{
2021-02-13 17:05:31 +01:00
thread_ctrl : : wait_on ( result , false ) ;
2017-01-23 18:14:12 +01:00
}
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-04-05 20:14:01 +02:00
error_code cellOskDialogLoadAsyncExt ( )
{
2021-09-20 20:39:37 +02:00
cellOskDialog . todo ( " cellOskDialogLoadAsyncExt() " ) ;
2019-04-05 20:14:01 +02:00
return CELL_OK ;
}
2019-01-04 14:45:32 +01:00
error_code getText ( vm : : ptr < CellOskDialogCallbackReturnParam > OutputInfo , bool is_unload )
2015-07-30 03:43:03 +02:00
{
2018-12-30 20:58:56 +01:00
if ( ! OutputInfo | | OutputInfo - > numCharsResultString < 0 )
{
return CELL_OSKDIALOG_ERROR_PARAM ;
}
2022-04-19 19:15:12 +02:00
const auto osk = _get_osk_dialog ( false ) ;
2019-01-04 22:28:52 +01:00
if ( ! osk )
{
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED ;
}
2021-09-20 21:19:34 +02:00
auto & info = g_fxo - > get < osk_info > ( ) ;
const bool keep_seperate_window_open = info . use_separate_windows . load ( ) & & ( info . osk_continuous_mode . load ( ) ! = CELL_OSKDIALOG_CONTINUOUS_MODE_NONE ) ;
info . text_mtx . lock ( ) ;
// Update text buffer if called from cellOskDialogUnloadAsync or if the user accepted the dialog during continuous seperate window mode.
if ( is_unload | | ( keep_seperate_window_open & & info . last_dialog_state = = CELL_SYSUTIL_OSKDIALOG_INPUT_ENTERED ) )
{
for ( s32 i = 0 ; i < CELL_OSKDIALOG_STRING_SIZE - 1 ; i + + )
{
info . valid_text [ i ] = osk - > osk_text [ i ] ;
}
}
2018-12-30 20:58:56 +01:00
if ( is_unload )
{
2019-01-06 13:40:03 +01:00
OutputInfo - > result = osk - > osk_input_result . load ( ) ;
2018-12-30 20:58:56 +01:00
}
else
{
2021-09-20 21:19:34 +02:00
if ( info . valid_text [ 0 ] = = 0 )
2018-12-30 20:58:56 +01:00
{
OutputInfo - > result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_NO_INPUT_TEXT ;
}
else
{
OutputInfo - > result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_OK ;
}
}
2017-01-18 23:01:25 +01:00
2021-09-20 21:19:34 +02:00
const bool do_copy = OutputInfo - > pResultString & & ( OutputInfo - > result = = CELL_OSKDIALOG_INPUT_FIELD_RESULT_OK | | ( is_unload & & OutputInfo - > result = = CELL_OSKDIALOG_INPUT_FIELD_RESULT_NO_INPUT_TEXT ) ) ;
2019-01-04 02:02:26 +01:00
2021-09-20 21:19:34 +02:00
for ( s32 i = 0 ; do_copy & & i < CELL_OSKDIALOG_STRING_SIZE - 1 ; i + + )
2017-05-15 13:58:32 +02:00
{
2021-09-20 21:19:34 +02:00
if ( i < OutputInfo - > numCharsResultString )
2018-12-30 20:58:56 +01:00
{
2021-09-20 21:19:34 +02:00
OutputInfo - > pResultString [ i ] = info . valid_text [ i ] ;
if ( info . valid_text [ i ] = = 0 )
2019-01-12 12:00:50 +01:00
{
2021-09-20 21:19:34 +02:00
break ;
2019-01-12 09:23:43 +01:00
}
2018-12-30 20:58:56 +01:00
}
2021-09-20 21:19:34 +02:00
else
{
OutputInfo - > pResultString [ i ] = 0 ;
break ;
}
2017-01-23 18:14:12 +01:00
}
2017-01-18 23:01:25 +01:00
2021-09-20 21:19:34 +02:00
info . text_mtx . unlock ( ) ;
2019-01-04 22:28:52 +01:00
if ( is_unload )
{
// Unload should be called last, so remove the dialog here
2021-09-20 21:19:34 +02:00
if ( const auto reset_lock = info . init . reset ( ) )
2019-09-26 20:35:27 +02:00
{
2021-09-20 21:19:34 +02:00
info . reset ( ) ;
2019-09-26 20:35:27 +02:00
}
2021-09-21 00:59:11 +02:00
osk - > state = OskDialogState : : Unloaded ;
2019-01-04 22:28:52 +01:00
sysutil_send_system_cmd ( CELL_SYSUTIL_OSKDIALOG_UNLOADED , 0 ) ;
}
2021-09-20 21:19:34 +02:00
else if ( keep_seperate_window_open )
{
// Clear text buffer unless the dialog is still open during continuous seperate window mode.
switch ( info . last_dialog_state )
{
case CELL_SYSUTIL_OSKDIALOG_FINISHED :
case CELL_SYSUTIL_OSKDIALOG_UNLOADED :
case CELL_SYSUTIL_OSKDIALOG_INPUT_CANCELED :
case CELL_SYSUTIL_OSKDIALOG_INPUT_ENTERED :
info . valid_text = { } ;
break ;
default :
break ;
}
}
2017-03-16 10:34:47 +01:00
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogUnloadAsync ( vm : : ptr < CellOskDialogCallbackReturnParam > OutputInfo )
2018-12-30 20:58:56 +01:00
{
cellOskDialog . warning ( " cellOskDialogUnloadAsync(OutputInfo=*0x%x) " , OutputInfo ) ;
return getText ( OutputInfo , true ) ;
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogGetSize ( vm : : ptr < u16 > width , vm : : ptr < u16 > height , u32 /*CellOskDialogType*/ dialogType )
2015-07-30 03:43:03 +02:00
{
2019-01-04 22:28:52 +01:00
cellOskDialog . warning ( " cellOskDialogGetSize(width=*0x%x, height=*0x%x, dialogType=%d) " , width , height , dialogType ) ;
2018-12-30 22:27:37 +01:00
if ( ! width | | ! height )
{
return CELL_OSKDIALOG_ERROR_PARAM ;
}
if ( dialogType > = CELL_OSKDIALOG_TYPE_SEPARATE_SINGLELINE_TEXT_WINDOW )
{
* width = 0 ;
}
else
{
* width = 1 ;
}
2017-01-18 23:01:25 +01:00
* height = 1 ;
2018-12-30 22:27:37 +01:00
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogAbort ( )
2015-07-30 03:43:03 +02:00
{
2017-01-23 18:14:12 +01:00
cellOskDialog . warning ( " cellOskDialogAbort() " ) ;
2018-12-30 02:34:15 +01:00
2022-04-19 19:15:12 +02:00
const auto osk = _get_osk_dialog ( false ) ;
2018-12-30 02:34:15 +01:00
2019-01-12 12:53:18 +01:00
if ( ! osk )
2018-12-30 02:34:15 +01:00
{
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED ;
}
2022-04-09 23:41:33 +02:00
const error_code result = osk - > state . atomic_op ( [ ] ( OskDialogState & state ) - > error_code
2018-12-30 02:34:15 +01:00
{
2021-09-21 00:59:11 +02:00
// Check for open dialog. In this case the dialog is "Open" if it was not unloaded before.
if ( state = = OskDialogState : : Unloaded )
2019-01-12 12:53:18 +01:00
{
2022-04-09 23:41:33 +02:00
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED ;
2019-01-12 12:53:18 +01:00
}
state = OskDialogState : : Abort ;
2022-04-09 23:41:33 +02:00
return CELL_OK ;
2019-01-12 12:53:18 +01:00
} ) ;
2022-04-09 23:44:13 +02:00
if ( result = = CELL_OK )
2019-01-12 12:53:18 +01:00
{
2022-04-09 23:44:13 +02:00
osk - > osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_ABORT ;
osk - > Close ( FAKE_CELL_OSKDIALOG_CLOSE_ABORT ) ;
2018-12-30 02:34:15 +01:00
}
2021-09-21 00:59:11 +02:00
g_fxo - > get < osk_info > ( ) . last_dialog_state = CELL_SYSUTIL_OSKDIALOG_FINISHED ;
sysutil_send_system_cmd ( CELL_SYSUTIL_OSKDIALOG_FINISHED , 0 ) ;
2019-01-05 18:11:43 +01:00
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogSetDeviceMask ( u32 deviceMask )
2015-07-30 03:43:03 +02:00
{
2022-04-20 18:42:32 +02:00
cellOskDialog . warning ( " cellOskDialogSetDeviceMask(deviceMask=0x%x) " , deviceMask ) ;
2021-09-19 21:21:56 +02:00
2022-04-19 19:15:12 +02:00
// TODO: It might also return an error if use_separate_windows is not enabled
if ( deviceMask > CELL_OSKDIALOG_DEVICE_MASK_PAD )
{
return CELL_OSKDIALOG_ERROR_PARAM ;
}
2021-09-19 21:21:56 +02:00
2022-04-19 20:27:32 +02:00
auto & info = g_fxo - > get < osk_info > ( ) ;
info . device_mask = deviceMask ;
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 ) ;
2021-09-19 21:21:56 +02:00
2022-04-19 20:27:32 +02:00
input : : SetIntercepted ( osk - > pad_input_enabled , osk - > keyboard_input_enabled , osk - > mouse_input_enabled ) ;
}
}
2021-09-19 21:21:56 +02:00
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogSetSeparateWindowOption ( vm : : ptr < CellOskDialogSeparateWindowOption > windowOption )
2015-07-30 03:43:03 +02:00
{
2017-01-18 23:01:25 +01:00
cellOskDialog . todo ( " cellOskDialogSetSeparateWindowOption(windowOption=*0x%x) " , windowOption ) ;
2019-01-04 04:33:05 +01:00
2019-01-06 13:40:03 +01:00
if ( ! windowOption )
{
return CELL_OSKDIALOG_ERROR_PARAM ;
}
2021-09-19 21:21:56 +02:00
auto & osk = g_fxo - > get < osk_info > ( ) ;
osk . use_separate_windows = true ;
osk . osk_continuous_mode = static_cast < CellOskDialogContinuousMode > ( + windowOption - > continuousMode ) ;
2022-04-19 20:27:32 +02:00
osk . device_mask = windowOption - > deviceMask ;
2021-09-21 00:59:11 +02:00
// TODO: handle rest of windowOption
2022-04-19 20:27:32 +02:00
// inputFieldWindowWidth;
// inputFieldBackgroundTrans;
// inputFieldLayoutInfo;
// inputPanelLayoutInfo;
2021-09-21 00:59:11 +02:00
2022-04-26 00:15:27 +02:00
cellOskDialog . warning ( " cellOskDialogSetSeparateWindowOption: use_separate_windows=true, continuous_mode=%s, device_mask=0x%x) " , osk . osk_continuous_mode . load ( ) , osk . device_mask . load ( ) ) ;
2019-01-04 04:33:05 +01:00
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2021-09-19 21:21:56 +02:00
error_code cellOskDialogSetInitialInputDevice ( u32 inputDevice )
2015-07-30 03:43:03 +02:00
{
2021-09-19 21:21:56 +02:00
cellOskDialog . todo ( " cellOskDialogSetInitialInputDevice(inputDevice=%d) " , inputDevice ) ;
2022-04-19 19:15:12 +02:00
if ( inputDevice > CELL_OSKDIALOG_INPUT_DEVICE_KEYBOARD )
{
return CELL_OSKDIALOG_ERROR_PARAM ;
}
2021-09-19 21:21:56 +02:00
g_fxo - > get < osk_info > ( ) . initial_input_device = static_cast < CellOskDialogInputDevice > ( inputDevice ) ;
// TODO: use value
2022-04-19 22:30:20 +02:00
// TODO: Signal CELL_SYSUTIL_OSKDIALOG_INPUT_DEVICE_CHANGED if the input device changed (probably only when the dialog is already open)
2021-09-19 21:21:56 +02:00
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2021-09-19 21:21:56 +02:00
error_code cellOskDialogSetInitialKeyLayout ( u32 initialKeyLayout )
2015-07-30 03:43:03 +02:00
{
2021-09-19 21:21:56 +02:00
cellOskDialog . todo ( " cellOskDialogSetInitialKeyLayout(initialKeyLayout=%d) " , initialKeyLayout ) ;
2022-04-19 19:15:12 +02:00
if ( initialKeyLayout > ( CELL_OSKDIALOG_INITIAL_PANEL_LAYOUT_10KEY | CELL_OSKDIALOG_INITIAL_PANEL_LAYOUT_FULLKEY ) )
{
return CELL_OSKDIALOG_ERROR_PARAM ;
}
2021-09-19 21:21:56 +02:00
g_fxo - > get < osk_info > ( ) . initial_key_layout = static_cast < CellOskDialogInitialKeyLayout > ( initialKeyLayout ) ;
// TODO: use value
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogDisableDimmer ( )
2015-07-30 03:43:03 +02:00
{
2022-04-20 18:42:32 +02:00
cellOskDialog . warning ( " cellOskDialogDisableDimmer() " ) ;
2021-09-19 21:21:56 +02:00
g_fxo - > get < osk_info > ( ) . dimmer_enabled = false ;
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogSetKeyLayoutOption ( u32 option )
2015-07-30 03:43:03 +02:00
{
2017-01-18 23:01:25 +01:00
cellOskDialog . todo ( " cellOskDialogSetKeyLayoutOption(option=0x%x) " , option ) ;
2019-10-06 11:32:54 +02:00
if ( option = = 0 | | option > 3 ) // CELL_OSKDIALOG_10KEY_PANEL OR CELL_OSKDIALOG_FULLKEY_PANEL
{
return CELL_OSKDIALOG_ERROR_PARAM ;
}
2021-09-19 21:21:56 +02:00
g_fxo - > get < osk_info > ( ) . key_layout = option ;
// TODO: use value
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogAddSupportLanguage ( u32 supportLanguage )
2015-07-30 03:43:03 +02:00
{
2017-01-18 23:01:25 +01:00
cellOskDialog . todo ( " cellOskDialogAddSupportLanguage(supportLanguage=0x%x) " , supportLanguage ) ;
2021-09-19 21:21:56 +02:00
// TODO: error checks
g_fxo - > get < osk_info > ( ) . supported_languages = supportLanguage ;
// TODO: disable extra languages unless they were enabled here
// Extra languages are:
// CELL_OSKDIALOG_PANELMODE_POLISH
// CELL_OSKDIALOG_PANELMODE_KOREAN
// CELL_OSKDIALOG_PANELMODE_TURKEY
// CELL_OSKDIALOG_PANELMODE_TRADITIONAL_CHINESE
// CELL_OSKDIALOG_PANELMODE_SIMPLIFIED_CHINESE
// CELL_OSKDIALOG_PANELMODE_PORTUGUESE_BRAZIL
// CELL_OSKDIALOG_PANELMODE_DANISH
// CELL_OSKDIALOG_PANELMODE_SWEDISH
// CELL_OSKDIALOG_PANELMODE_NORWEGIAN
// CELL_OSKDIALOG_PANELMODE_FINNISH
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogSetLayoutMode ( s32 layoutMode )
2015-07-30 03:43:03 +02:00
{
2017-01-18 23:01:25 +01:00
cellOskDialog . todo ( " cellOskDialogSetLayoutMode(layoutMode=%d) " , layoutMode ) ;
2021-09-19 21:21:56 +02:00
// TODO: error checks
g_fxo - > get < osk_info > ( ) . layout_mode = layoutMode ;
// TODO: use layout mode
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogGetInputText ( vm : : ptr < CellOskDialogCallbackReturnParam > OutputInfo )
2015-07-30 03:43:03 +02:00
{
2017-01-18 23:01:25 +01:00
cellOskDialog . warning ( " cellOskDialogGetInputText(OutputInfo=*0x%x) " , OutputInfo ) ;
2018-12-30 20:58:56 +01:00
return getText ( OutputInfo , false ) ;
2015-07-30 03:43:03 +02:00
}
2019-10-06 11:32:54 +02:00
error_code register_keyboard_event_hook_callback ( u16 hookEventMode , vm : : ptr < cellOskDialogHardwareKeyboardEventHookCallback > pCallback )
{
2022-04-20 18:42:32 +02:00
cellOskDialog . warning ( " register_keyboard_event_hook_callback(hookEventMode=%u, pCallback=*0x%x) " , hookEventMode , pCallback ) ;
2019-10-06 11:32:54 +02:00
if ( ! pCallback )
{
return CELL_OSKDIALOG_ERROR_PARAM ;
}
2022-04-19 19:15:12 +02:00
g_fxo - > get < osk_info > ( ) . osk_hardware_keyboard_event_hook_callback = pCallback ;
2022-04-19 23:36:18 +02:00
g_fxo - > get < osk_info > ( ) . hook_event_mode = hookEventMode ;
2021-09-19 21:21:56 +02:00
2019-10-06 11:32:54 +02:00
return CELL_OK ;
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogExtRegisterKeyboardEventHookCallback ( u16 hookEventMode , vm : : ptr < cellOskDialogHardwareKeyboardEventHookCallback > pCallback )
2015-07-30 03:43:03 +02:00
{
2022-04-20 18:42:32 +02:00
cellOskDialog . warning ( " cellOskDialogExtRegisterKeyboardEventHookCallback(hookEventMode=%u, pCallback=*0x%x) " , hookEventMode , pCallback ) ;
2019-10-06 11:32:54 +02:00
2022-04-19 19:15:12 +02:00
if ( hookEventMode = = 0 | | hookEventMode > ( CELL_OSKDIALOG_EVENT_HOOK_TYPE_FUNCTION_KEY | CELL_OSKDIALOG_EVENT_HOOK_TYPE_ASCII_KEY ) )
2019-10-06 11:32:54 +02:00
{
return CELL_OSKDIALOG_ERROR_PARAM ;
}
return register_keyboard_event_hook_callback ( hookEventMode , pCallback ) ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogExtRegisterKeyboardEventHookCallbackEx ( u16 hookEventMode , vm : : ptr < cellOskDialogHardwareKeyboardEventHookCallback > pCallback )
2017-07-21 17:41:11 +02:00
{
2022-04-20 18:42:32 +02:00
cellOskDialog . warning ( " cellOskDialogExtRegisterKeyboardEventHookCallbackEx(hookEventMode=%u, pCallback=*0x%x) " , hookEventMode , pCallback ) ;
2019-10-06 11:32:54 +02:00
2022-04-19 19:15:12 +02:00
if ( hookEventMode = = 0 | | hookEventMode > ( CELL_OSKDIALOG_EVENT_HOOK_TYPE_FUNCTION_KEY | CELL_OSKDIALOG_EVENT_HOOK_TYPE_ASCII_KEY | CELL_OSKDIALOG_EVENT_HOOK_TYPE_ONLY_MODIFIER ) )
2019-10-06 11:32:54 +02:00
{
return CELL_OSKDIALOG_ERROR_PARAM ;
}
return register_keyboard_event_hook_callback ( hookEventMode , pCallback ) ;
2017-07-21 17:41:11 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogExtAddJapaneseOptionDictionary ( vm : : cpptr < char > filePath )
2015-07-30 03:43:03 +02:00
{
2017-01-26 15:53:07 +01:00
cellOskDialog . todo ( " cellOskDialogExtAddJapaneseOptionDictionary(filePath=**0x%0x) " , filePath ) ;
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogExtEnableClipboard ( )
2015-07-30 03:43:03 +02:00
{
2017-01-18 23:01:25 +01:00
cellOskDialog . todo ( " cellOskDialogExtEnableClipboard() " ) ;
2021-09-19 21:21:56 +02:00
// TODO: error checks
g_fxo - > get < osk_info > ( ) . clipboard_enabled = true ;
// TODO: implement copy paste
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-05 18:11:43 +01:00
error_code cellOskDialogExtSendFinishMessage ( u32 /*CellOskDialogFinishReason*/ finishReason )
2015-07-30 03:43:03 +02:00
{
2019-01-05 18:11:43 +01:00
cellOskDialog . warning ( " cellOskDialogExtSendFinishMessage(finishReason=%d) " , finishReason ) ;
2022-04-19 19:15:12 +02:00
const auto osk = _get_osk_dialog ( false ) ;
2019-01-05 18:11:43 +01:00
2021-09-21 00:59:11 +02:00
// Check for "Open" dialog.
if ( ! osk | | osk - > state . load ( ) = = OskDialogState : : Unloaded )
2019-01-05 18:11:43 +01:00
{
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED ;
}
2021-09-19 21:12:42 +02:00
osk - > Close ( finishReason ) ;
2019-01-05 18:11:43 +01:00
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogExtAddOptionDictionary ( vm : : cptr < CellOskDialogImeDictionaryInfo > dictionaryInfo )
2015-07-30 03:43:03 +02:00
{
2017-01-18 23:01:25 +01:00
cellOskDialog . todo ( " cellOskDialogExtAddOptionDictionary(dictionaryInfo=*0x%x) " , dictionaryInfo ) ;
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogExtSetInitialScale ( f32 initialScale )
2015-07-30 03:43:03 +02:00
{
2017-01-26 15:53:07 +01:00
cellOskDialog . todo ( " cellOskDialogExtSetInitialScale(initialScale=%f) " , initialScale ) ;
2021-09-19 21:21:56 +02:00
2022-04-19 19:15:12 +02:00
if ( initialScale < CELL_OSKDIALOG_SCALE_MIN | | initialScale > CELL_OSKDIALOG_SCALE_MAX )
{
return CELL_OSKDIALOG_ERROR_PARAM ;
}
2021-09-19 21:21:56 +02:00
g_fxo - > get < osk_info > ( ) . initial_scale = initialScale ;
// TODO: implement overlay scaling
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogExtInputDeviceLock ( )
2015-07-30 03:43:03 +02:00
{
2022-04-20 18:42:32 +02:00
cellOskDialog . warning ( " cellOskDialogExtInputDeviceLock() " ) ;
2021-09-19 21:21:56 +02:00
// TODO: error checks
g_fxo - > get < osk_info > ( ) . lock_ext_input = true ;
2022-04-19 20:27:32 +02:00
if ( const auto osk = _get_osk_dialog ( false ) )
{
osk - > ignore_input_events = true ;
}
2021-09-19 21:21:56 +02:00
return CELL_OK ;
}
error_code cellOskDialogExtInputDeviceUnlock ( )
{
2022-04-20 18:42:32 +02:00
cellOskDialog . warning ( " cellOskDialogExtInputDeviceUnlock() " ) ;
2021-09-19 21:21:56 +02:00
// TODO: error checks
g_fxo - > get < osk_info > ( ) . lock_ext_input = false ;
2022-04-19 20:27:32 +02:00
if ( const auto osk = _get_osk_dialog ( false ) )
{
osk - > ignore_input_events = false ;
}
2021-09-19 21:21:56 +02:00
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2022-04-19 19:15:12 +02:00
error_code cellOskDialogExtSetBaseColor ( f32 red , f32 green , f32 blue , f32 alpha )
2015-07-30 03:43:03 +02:00
{
2022-04-20 18:42:32 +02:00
cellOskDialog . warning ( " cellOskDialogExtSetBaseColor(red=%f, blue=%f, green=%f, alpha=%f) " , red , blue , green , alpha ) ;
2021-09-19 21:21:56 +02:00
2022-04-19 19:15:12 +02:00
if ( red < 0.0f | | red > 1.0f | | green < 0.0f | | green > 1.0f | | blue < 0.0f | | blue > 1.0f | | alpha < 0.0f | | alpha > 1.0f )
{
return CELL_OSKDIALOG_ERROR_PARAM ;
}
2021-09-19 21:21:56 +02:00
auto & osk = g_fxo - > get < osk_info > ( ) ;
2022-04-20 18:16:27 +02:00
osk . base_color = OskDialogBase : : color { red , green , blue , alpha } ;
2021-09-19 21:21:56 +02:00
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogExtRegisterConfirmWordFilterCallback ( vm : : ptr < cellOskDialogConfirmWordFilterCallback > pCallback )
2015-07-30 03:43:03 +02:00
{
2019-01-04 22:28:52 +01:00
cellOskDialog . warning ( " cellOskDialogExtRegisterConfirmWordFilterCallback(pCallback=*0x%x) " , pCallback ) ;
2019-01-05 01:32:45 +01:00
2019-01-12 09:23:43 +01:00
if ( ! pCallback )
{
return CELL_OSKDIALOG_ERROR_PARAM ;
}
2021-09-19 21:21:56 +02:00
g_fxo - > get < osk_info > ( ) . osk_confirm_callback = pCallback ;
2019-01-05 01:32:45 +01:00
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogExtUpdateInputText ( )
2015-07-30 03:43:03 +02:00
{
2017-01-26 15:53:07 +01:00
cellOskDialog . todo ( " cellOskDialogExtUpdateInputText() " ) ;
2021-09-20 21:19:34 +02:00
// Usually, user input is only available when the dialog was accepted.
// This function seems to be called in order to copy the current text to an internal buffer.
// Afterwards, cellOskDialogGetInputText can be called to fetch the current text regardless of
// user confirmation, even if the dialog is still in use.
// TODO: error checks
2022-04-19 19:15:12 +02:00
const auto osk = _get_osk_dialog ( false ) ;
2021-09-20 21:19:34 +02:00
if ( osk )
{
auto & info = g_fxo - > get < osk_info > ( ) ;
std : : lock_guard lock ( info . text_mtx ) ;
for ( s32 i = 0 ; i < CELL_OSKDIALOG_STRING_SIZE - 1 ; i + + )
{
info . valid_text [ i ] = osk - > osk_text [ i ] ;
}
}
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogExtSetPointerEnable ( b8 enable )
2015-07-30 03:43:03 +02:00
{
2017-01-18 23:01:25 +01:00
cellOskDialog . todo ( " cellOskDialogExtSetPointerEnable(enable=%d) " , enable ) ;
2021-09-19 21:21:56 +02:00
// TODO: error checks
g_fxo - > get < osk_info > ( ) . pointer_enabled = enable ;
2022-04-19 20:27:32 +02:00
// TODO: Show/hide pointer at the specified position in the OSK overlay.
2021-09-19 21:21:56 +02:00
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2021-09-19 21:21:56 +02:00
error_code cellOskDialogExtUpdatePointerDisplayPos ( vm : : cptr < CellOskDialogPoint > pos )
2015-07-30 03:43:03 +02:00
{
2021-09-19 21:21:56 +02:00
cellOskDialog . todo ( " cellOskDialogExtUpdatePointerDisplayPos(pos=0x%x, posX=%f, posY=%f) " , pos - > x , pos - > y ) ;
// TODO: error checks
if ( pos )
{
g_fxo - > get < osk_info > ( ) . pointer_pos = * pos ;
}
2022-04-19 20:27:32 +02:00
// TODO: Update pointer position in the OSK overlay.
2021-09-19 21:21:56 +02:00
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogExtEnableHalfByteKana ( )
2015-07-30 03:43:03 +02:00
{
2017-01-18 23:01:25 +01:00
cellOskDialog . todo ( " cellOskDialogExtEnableHalfByteKana() " ) ;
2021-09-19 21:21:56 +02:00
// TODO: error checks
g_fxo - > get < osk_info > ( ) . half_byte_kana_enabled = true ;
// TODO: use new value in osk
return CELL_OK ;
}
error_code cellOskDialogExtDisableHalfByteKana ( )
{
cellOskDialog . todo ( " cellOskDialogExtDisableHalfByteKana() " ) ;
// TODO: error checks
g_fxo - > get < osk_info > ( ) . half_byte_kana_enabled = false ;
// TODO: use new value in osk
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellOskDialogExtRegisterForceFinishCallback ( vm : : ptr < cellOskDialogForceFinishCallback > pCallback )
2015-07-30 03:43:03 +02:00
{
2017-01-26 15:53:07 +01:00
cellOskDialog . todo ( " cellOskDialogExtRegisterForceFinishCallback(pCallback=*0x%x) " , pCallback ) ;
2019-10-06 11:32:54 +02:00
if ( ! pCallback )
{
return CELL_OSKDIALOG_ERROR_PARAM ;
}
2022-04-19 19:15:12 +02:00
g_fxo - > get < osk_info > ( ) . osk_force_finish_callback = pCallback ;
// TODO: use force finish callback when the PS-Button is pressed and a System dialog shall be spawned while the OSK is loaded
// 1. Check if current mode is CELL_OSKDIALOG_CONTINUOUS_MODE_HIDE or (CELL_OSKDIALOG_CONTINUOUS_MODE_SHOW && hidden)
// 2. If one of the above is true, call osk_force_finish_callback
// 3. Check the return value of osk_force_finish_callback. If false, ignore the PS-Button press, else go to the next step
// 4. Close dialog etc., send CELL_SYSUTIL_OSKDIALOG_FINISHED
// 5. After we return from the System dialog, send CELL_SYSUTIL_SYSTEM_MENU_CLOSE to notify the game that it can load the OSK and resume.
2021-09-19 21:21:56 +02:00
2017-05-15 13:58:32 +02:00
return CELL_OK ;
2015-07-30 03:43:03 +02:00
}
void cellSysutil_OskDialog_init ( )
{
REG_FUNC ( cellSysutil , cellOskDialogLoadAsync ) ;
2019-04-05 20:14:01 +02:00
REG_FUNC ( cellSysutil , cellOskDialogLoadAsyncExt ) ;
2015-07-30 03:43:03 +02:00
REG_FUNC ( cellSysutil , cellOskDialogUnloadAsync ) ;
REG_FUNC ( cellSysutil , cellOskDialogGetSize ) ;
REG_FUNC ( cellSysutil , cellOskDialogAbort ) ;
REG_FUNC ( cellSysutil , cellOskDialogSetDeviceMask ) ;
REG_FUNC ( cellSysutil , cellOskDialogSetSeparateWindowOption ) ;
REG_FUNC ( cellSysutil , cellOskDialogSetInitialInputDevice ) ;
REG_FUNC ( cellSysutil , cellOskDialogSetInitialKeyLayout ) ;
REG_FUNC ( cellSysutil , cellOskDialogDisableDimmer ) ;
REG_FUNC ( cellSysutil , cellOskDialogSetKeyLayoutOption ) ;
REG_FUNC ( cellSysutil , cellOskDialogAddSupportLanguage ) ;
REG_FUNC ( cellSysutil , cellOskDialogSetLayoutMode ) ;
REG_FUNC ( cellSysutil , cellOskDialogGetInputText ) ;
}
2016-03-21 20:43:03 +01:00
DECLARE ( ppu_module_manager : : cellOskDialog ) ( " cellOskExtUtility " , [ ] ( )
{
REG_FUNC ( cellOskExtUtility , cellOskDialogExtInputDeviceUnlock ) ;
REG_FUNC ( cellOskExtUtility , cellOskDialogExtRegisterKeyboardEventHookCallback ) ;
2017-07-21 17:41:11 +02:00
REG_FUNC ( cellOskExtUtility , cellOskDialogExtRegisterKeyboardEventHookCallbackEx ) ;
2016-03-21 20:43:03 +01:00
REG_FUNC ( cellOskExtUtility , cellOskDialogExtAddJapaneseOptionDictionary ) ;
REG_FUNC ( cellOskExtUtility , cellOskDialogExtEnableClipboard ) ;
REG_FUNC ( cellOskExtUtility , cellOskDialogExtSendFinishMessage ) ;
REG_FUNC ( cellOskExtUtility , cellOskDialogExtAddOptionDictionary ) ;
REG_FUNC ( cellOskExtUtility , cellOskDialogExtSetInitialScale ) ;
REG_FUNC ( cellOskExtUtility , cellOskDialogExtInputDeviceLock ) ;
REG_FUNC ( cellOskExtUtility , cellOskDialogExtSetBaseColor ) ;
REG_FUNC ( cellOskExtUtility , cellOskDialogExtRegisterConfirmWordFilterCallback ) ;
REG_FUNC ( cellOskExtUtility , cellOskDialogExtUpdateInputText ) ;
REG_FUNC ( cellOskExtUtility , cellOskDialogExtDisableHalfByteKana ) ;
REG_FUNC ( cellOskExtUtility , cellOskDialogExtSetPointerEnable ) ;
REG_FUNC ( cellOskExtUtility , cellOskDialogExtUpdatePointerDisplayPos ) ;
REG_FUNC ( cellOskExtUtility , cellOskDialogExtEnableHalfByteKana ) ;
REG_FUNC ( cellOskExtUtility , cellOskDialogExtRegisterForceFinishCallback ) ;
2015-07-30 03:43:03 +02:00
} ) ;