diff --git a/rpcs3/Emu/Cell/Modules/cellMsgDialog.h b/rpcs3/Emu/Cell/Modules/cellMsgDialog.h index cba0035725..077c07cb1d 100644 --- a/rpcs3/Emu/Cell/Modules/cellMsgDialog.h +++ b/rpcs3/Emu/Cell/Modules/cellMsgDialog.h @@ -96,11 +96,9 @@ public: MsgDialogType type{}; std::function on_close; - std::function on_osk_input_entered; virtual ~MsgDialogBase(); virtual void Create(const std::string& msg, const std::string& title = "") = 0; - virtual void CreateOsk(const std::string& title, const std::u16string& message, char16_t* osk_text, u32 charlimit) = 0; virtual void SetMsg(const std::string& msg) = 0; virtual void ProgressBarSetMsg(u32 progressBarIndex, const std::string& msg) = 0; virtual void ProgressBarReset(u32 progressBarIndex) = 0; diff --git a/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp b/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp index 19701aecc6..c770c0ef13 100644 --- a/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp +++ b/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp @@ -27,9 +27,9 @@ void fmt_class_string::format(std::string& out, u64 arg) }); } -static CellOskDialogInputFieldResult s_osk_input_result; -static char16_t s_osk_text[CELL_OSKDIALOG_STRING_SIZE]; -static char16_t s_osk_text_old[CELL_OSKDIALOG_STRING_SIZE]; +OskDialogBase::~OskDialogBase() +{ +} error_code cellOskDialogLoadAsync(u32 container, vm::ptr dialogParam, vm::ptr inputFieldInfo) { @@ -40,10 +40,10 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia return CELL_OSKDIALOG_ERROR_PARAM; } - const auto osk = fxm::import(Emu.GetCallbacks().get_msg_dialog); + const auto osk = fxm::import(Emu.GetCallbacks().get_osk_dialog); // Can't open another dialog if this one is already open. - if (!osk || osk->state.load() == MsgDialogState::Open) + if (!osk || osk->state.load() == OskDialogState::Open) { return CELL_SYSUTIL_ERROR_BUSY; } @@ -52,16 +52,16 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia u32 maxLength = (inputFieldInfo->limit_length >= CELL_OSKDIALOG_STRING_SIZE) ? 511 : (u32)inputFieldInfo->limit_length; // Get init text and prepare return value - s_osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_OK; - std::memset(s_osk_text, 0, sizeof(s_osk_text)); - std::memset(s_osk_text_old, 0, sizeof(s_osk_text_old)); + osk->osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_OK; + std::memset(osk->osk_text, 0, sizeof(osk->osk_text)); + std::memset(osk->osk_text_old, 0, sizeof(osk->osk_text_old)); if (inputFieldInfo->init_text.addr() != 0) { for (u32 i = 0; (i < maxLength) && (inputFieldInfo->init_text[i] != 0); i++) { - s_osk_text[i] = inputFieldInfo->init_text[i]; - s_osk_text_old[i] = inputFieldInfo->init_text[i]; + osk->osk_text[i] = inputFieldInfo->init_text[i]; + osk->osk_text_old[i] = inputFieldInfo->init_text[i]; } } @@ -80,18 +80,14 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia bool result = false; - osk->on_close = [wptr = std::weak_ptr(osk)](s32 status) + osk->on_close = [wptr = std::weak_ptr(osk)](s32 status) { const auto osk = wptr.lock(); - - if (osk && osk->state.compare_and_swap_test(MsgDialogState::Open, MsgDialogState::Close)) - { - fxm::remove(); - } + osk->state = OskDialogState::Close; if (status != CELL_MSGDIALOG_BUTTON_OK) { - s_osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_CANCELED; + osk->osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_CANCELED; if (false/* TODO: check for seperate window */) { @@ -100,10 +96,10 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia } else { - if (s_osk_text[0] == 0 && false/* TODO: check for seperate window */) + if (osk->osk_text[0] == 0 && false/* TODO: check for seperate window */) { cellOskDialog.warning("cellOskDialogLoadAsync: input result is CELL_OSKDIALOG_INPUT_FIELD_RESULT_NO_INPUT_TEXT"); - s_osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_NO_INPUT_TEXT; + osk->osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_NO_INPUT_TEXT; } } @@ -124,7 +120,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia Emu.CallAfter([&]() { - osk->CreateOsk("On Screen Keyboard", message, s_osk_text, maxLength); + osk->Create("On Screen Keyboard", message, osk->osk_text, maxLength); result = true; }); @@ -145,13 +141,20 @@ error_code getText(vm::ptr OutputInfo, bool is return CELL_OSKDIALOG_ERROR_PARAM; } + const auto osk = fxm::get(); + + if (!osk) + { + return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED; + } + if (is_unload) { - OutputInfo->result = s_osk_input_result; + OutputInfo->result = osk->osk_input_result; } else { - if (memcmp(s_osk_text_old, s_osk_text, sizeof(s_osk_text)) == 0) + if (memcmp(osk->osk_text_old, osk->osk_text, sizeof(osk->osk_text)) == 0) { OutputInfo->result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_NO_INPUT_TEXT; } @@ -163,17 +166,22 @@ error_code getText(vm::ptr OutputInfo, bool is const bool is_valid = OutputInfo->pResultString && (OutputInfo->result == CELL_OSKDIALOG_INPUT_FIELD_RESULT_OK || (is_unload && OutputInfo->result == CELL_OSKDIALOG_INPUT_FIELD_RESULT_NO_INPUT_TEXT)); - for (s32 i = 0; i < sizeof(s_osk_text); i++) + for (u32 i = 0; i < CELL_OSKDIALOG_STRING_SIZE - 1; i++) { - s_osk_text_old[i] = s_osk_text[i]; + osk->osk_text_old[i] = osk->osk_text[i]; if (is_valid && i < OutputInfo->numCharsResultString) { - OutputInfo->pResultString[i] = s_osk_text[i]; + OutputInfo->pResultString[i] = osk->osk_text[i]; } } - sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_UNLOADED, 0); + if (is_unload) + { + // Unload should be called last, so remove the dialog here + fxm::remove(); + sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_UNLOADED, 0); + } return CELL_OK; } @@ -186,7 +194,7 @@ error_code cellOskDialogUnloadAsync(vm::ptr Ou error_code cellOskDialogGetSize(vm::ptr width, vm::ptr height, u32 /*CellOskDialogType*/ dialogType) { - cellOskDialog.warning("cellOskDialogGetSize(width=*0x%x, height=*0x%x, dialogType=*0x%x)", width, height, dialogType); + cellOskDialog.warning("cellOskDialogGetSize(width=*0x%x, height=*0x%x, dialogType=%d)", width, height, dialogType); if (!width || !height) { @@ -211,24 +219,21 @@ error_code cellOskDialogAbort() { cellOskDialog.warning("cellOskDialogAbort()"); - const auto dlg = fxm::get(); + const auto osk = fxm::get(); // Check for open dialog. In this case the dialog is only "Open" if it was not aborted before. - if (!dlg || dlg->state.load() == MsgDialogState::Abort) + if (!osk || osk->state.load() == OskDialogState::Abort) { return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED; } // If the dialog has the Open state then it is in use. Only dialogs with the Close state can be aborted. - if (!dlg->state.compare_and_swap_test(MsgDialogState::Open, MsgDialogState::Abort)) + if (!osk->state.compare_and_swap_test(OskDialogState::Open, OskDialogState::Abort)) { return CELL_SYSUTIL_ERROR_BUSY; } - s_osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_ABORT; - - verify(HERE), fxm::remove(); - + osk->osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_ABORT; sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0); return CELL_OK; } @@ -346,13 +351,13 @@ error_code cellOskDialogExtInputDeviceLock() error_code cellOskDialogExtSetBaseColor(f32 red, f32 blue, f32 green, f32 alpha) { - cellOskDialog.warning("cellOskDialogExtSetBaseColor(red=%f, blue=%f, green=%f, alpha=%f)", red, blue, green, alpha); + cellOskDialog.todo("cellOskDialogExtSetBaseColor(red=%f, blue=%f, green=%f, alpha=%f)", red, blue, green, alpha); return CELL_OK; } error_code cellOskDialogExtRegisterConfirmWordFilterCallback(vm::ptr pCallback) { - cellOskDialog.todo("cellOskDialogExtRegisterConfirmWordFilterCallback(pCallback=*0x%x)", pCallback); + cellOskDialog.warning("cellOskDialogExtRegisterConfirmWordFilterCallback(pCallback=*0x%x)", pCallback); return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/cellOskDialog.h b/rpcs3/Emu/Cell/Modules/cellOskDialog.h index 3e017c2374..6a6ed55e2a 100644 --- a/rpcs3/Emu/Cell/Modules/cellOskDialog.h +++ b/rpcs3/Emu/Cell/Modules/cellOskDialog.h @@ -232,3 +232,26 @@ struct CellOskDialogImeDictionaryInfo using cellOskDialogConfirmWordFilterCallback = int(vm::ptr pConfirmString, s32 wordLength); using cellOskDialogHardwareKeyboardEventHookCallback = class b8(vm::ptr keyMessage, vm::ptr action, vm::ptr pActionInfo); using cellOskDialogForceFinishCallback = class b8(); + +enum class OskDialogState +{ + Open, + Abort, + Close, +}; + +class OskDialogBase +{ +public: + virtual void Create(const std::string& title, const std::u16string& message, char16_t* init_text, u32 charlimit) = 0; + virtual ~OskDialogBase(); + + std::function on_close; + std::function on_osk_input_entered; + + atomic_t state{ OskDialogState::Close }; + + CellOskDialogInputFieldResult osk_input_result; + char16_t osk_text[CELL_OSKDIALOG_STRING_SIZE]; + char16_t osk_text_old[CELL_OSKDIALOG_STRING_SIZE]; +}; diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 793f237b8f..c285ded8e4 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -198,6 +198,7 @@ struct EmuCallbacks std::function()> get_gs_render; std::function()> get_audio; std::function()> get_msg_dialog; + std::function()> get_osk_dialog; std::function()> get_save_dialog; std::function()> get_trophy_notification_dialog; }; diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 4be148aeab..2a6675dcc8 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -371,6 +371,11 @@ true true + + true + true + true + true true @@ -441,6 +446,11 @@ true true + + true + true + true + true true @@ -541,6 +551,11 @@ true true + + true + true + true + true true @@ -611,6 +626,11 @@ true true + + true + true + true + true true @@ -731,6 +751,11 @@ true true + + true + true + true + true true @@ -801,6 +826,11 @@ true true + + true + true + true + true true @@ -901,6 +931,11 @@ true true + + true + true + true + true true @@ -971,6 +1006,11 @@ true true + + true + true + true + true true @@ -1044,8 +1084,10 @@ + + @@ -1468,6 +1510,24 @@ .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DLLVM_AVAILABLE -D_SCL_SECURE_NO_WARNINGS -D_UNICODE "-I$(VULKAN_SDK)\Include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DBRANCH= -DLLVM_AVAILABLE -DPUGIXML_HEADER_ONLY -D_ENABLE_EXTENDED_ALIGNED_STORAGE -D_UNICODE "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -D_SCL_SECURE_NO_WARNINGS -DPUGIXML_HEADER_ONLY -D_ENABLE_EXTENDED_ALIGNED_STORAGE -D_UNICODE "-I$(VULKAN_SDK)\Include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DPUGIXML_HEADER_ONLY -D_ENABLE_EXTENDED_ALIGNED_STORAGE -D_UNICODE "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DLLVM_AVAILABLE -D_SCL_SECURE_NO_WARNINGS -DPUGIXML_HEADER_ONLY -D_ENABLE_EXTENDED_ALIGNED_STORAGE -D_UNICODE "-I$(VULKAN_SDK)\Include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" + $(QTDIR)\bin\moc.exe;%(FullPath) @@ -1505,6 +1565,24 @@ .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DLLVM_AVAILABLE -D_SCL_SECURE_NO_WARNINGS -DPUGIXML_HEADER_ONLY -D_ENABLE_EXTENDED_ALIGNED_STORAGE -D_UNICODE "-I$(VULKAN_SDK)\Include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DBRANCH= -DLLVM_AVAILABLE -DPUGIXML_HEADER_ONLY -D_ENABLE_EXTENDED_ALIGNED_STORAGE -D_UNICODE "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -D_SCL_SECURE_NO_WARNINGS -DPUGIXML_HEADER_ONLY -D_ENABLE_EXTENDED_ALIGNED_STORAGE -D_UNICODE "-I$(VULKAN_SDK)\Include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DPUGIXML_HEADER_ONLY -D_ENABLE_EXTENDED_ALIGNED_STORAGE -D_UNICODE "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DLLVM_AVAILABLE -D_SCL_SECURE_NO_WARNINGS -DPUGIXML_HEADER_ONLY -D_ENABLE_EXTENDED_ALIGNED_STORAGE -D_UNICODE "-I$(VULKAN_SDK)\Include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 5d45bf67f2..212b19fbb8 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -689,6 +689,36 @@ Generated Files\Debug - LLVM + + Gui\message dialog + + + Generated Files\Release - LLVM + + + Generated Files\Debug + + + Generated Files\Release + + + Generated Files\Debug - LLVM + + + Gui\message dialog + + + Generated Files\Release - LLVM + + + Generated Files\Debug + + + Generated Files\Release + + + Generated Files\Debug - LLVM + @@ -912,6 +942,12 @@ Gui\misc dialogs + + Gui\message dialog + + + Gui\message dialog + diff --git a/rpcs3/rpcs3_app.cpp b/rpcs3/rpcs3_app.cpp index af333b181b..3e425e8554 100644 --- a/rpcs3/rpcs3_app.cpp +++ b/rpcs3/rpcs3_app.cpp @@ -279,6 +279,11 @@ void rpcs3_app::InitializeCallbacks() return std::make_shared(RPCS3MainWin->windowHandle()); }; + callbacks.get_osk_dialog = [=]() -> std::shared_ptr + { + return std::make_shared(); + }; + callbacks.get_save_dialog = [=]() -> std::unique_ptr { return std::make_unique(); diff --git a/rpcs3/rpcs3_app.h b/rpcs3/rpcs3_app.h index cfc3906020..70d4e17f79 100644 --- a/rpcs3/rpcs3_app.h +++ b/rpcs3/rpcs3_app.h @@ -15,6 +15,7 @@ #include "Emu/Audio/AudioThread.h" #include "rpcs3qt/msg_dialog_frame.h" +#include "rpcs3qt/osk_dialog_frame.h" #include "rpcs3qt/main_window.h" #include "rpcs3qt/gui_settings.h" #include "rpcs3qt/emu_settings.h" diff --git a/rpcs3/rpcs3qt/custom_dialog.cpp b/rpcs3/rpcs3qt/custom_dialog.cpp new file mode 100644 index 0000000000..beed9f8d11 --- /dev/null +++ b/rpcs3/rpcs3qt/custom_dialog.cpp @@ -0,0 +1,36 @@ +#include "custom_dialog.h" + +custom_dialog::custom_dialog(bool disableCancel, QWidget* parent) + : QDialog(parent), m_disable_cancel(disableCancel) +{ + if (m_disable_cancel) + { + setWindowFlags(windowFlags() & ~Qt::WindowCloseButtonHint); + } +} + +void custom_dialog::keyPressEvent(QKeyEvent* event) +{ + // this won't work with Alt+F4, the window still closes + if (m_disable_cancel && event->key() == Qt::Key_Escape) + { + event->ignore(); + } + else + { + QDialog::keyPressEvent(event); + } +} + +void custom_dialog::closeEvent(QCloseEvent* event) +{ + // spontaneous: don't close on external system level events like Alt+F4 + if (m_disable_cancel && event->spontaneous()) + { + event->ignore(); + } + else + { + QDialog::closeEvent(event); + } +} diff --git a/rpcs3/rpcs3qt/custom_dialog.h b/rpcs3/rpcs3qt/custom_dialog.h new file mode 100644 index 0000000000..737fb2d63e --- /dev/null +++ b/rpcs3/rpcs3qt/custom_dialog.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +class custom_dialog : public QDialog +{ + Q_OBJECT + +public: + explicit custom_dialog(bool disableCancel, QWidget* parent = nullptr); + bool m_disable_cancel; + +private: + void keyPressEvent(QKeyEvent* event) override; + void closeEvent(QCloseEvent* event) override; +}; diff --git a/rpcs3/rpcs3qt/msg_dialog_frame.cpp b/rpcs3/rpcs3qt/msg_dialog_frame.cpp index eec606a058..1a0ba5aa88 100644 --- a/rpcs3/rpcs3qt/msg_dialog_frame.cpp +++ b/rpcs3/rpcs3qt/msg_dialog_frame.cpp @@ -77,8 +77,8 @@ void msg_dialog_frame::Create(const std::string& msg, const std::string& title) { m_dialog->setModal(true); - m_button_yes = new QPushButton("&Yes", m_dialog); - m_button_no = new QPushButton("&No", m_dialog); + QPushButton* m_button_yes = new QPushButton("&Yes", m_dialog); + QPushButton* m_button_no = new QPushButton("&No", m_dialog); QHBoxLayout* hBoxButtons = new QHBoxLayout; hBoxButtons->setAlignment(Qt::AlignCenter); @@ -112,7 +112,7 @@ void msg_dialog_frame::Create(const std::string& msg, const std::string& title) { m_dialog->setModal(true); - m_button_ok = new QPushButton("&OK", m_dialog); + QPushButton* m_button_ok = new QPushButton("&OK", m_dialog); m_button_ok->setFixedWidth(50); QHBoxLayout* hBoxButtons = new QHBoxLayout; @@ -152,90 +152,6 @@ void msg_dialog_frame::Create(const std::string& msg, const std::string& title) #endif } -void msg_dialog_frame::CreateOsk(const std::string& title, const std::u16string& message, char16_t* osk_text, u32 charlimit) -{ - state = MsgDialogState::Open; - - static const auto& lineEditWidth = []() {return QLabel("This is the very length of the lineedit due to hidpi reasons.").sizeHint().width(); }; - - if (m_osk_dialog) - { - m_osk_dialog->close(); - delete m_osk_dialog; - } - - m_osk_dialog = new custom_dialog(type.disable_cancel); - m_osk_dialog->setModal(true); - m_osk_text_return = osk_text; - - // Title - m_osk_dialog->setWindowTitle(qstr(title)); - - // Message - QLabel* message_label = new QLabel(QString::fromStdU16String(message)); - - // Text Input - QLineEdit* input = new QLineEdit(m_osk_dialog); - input->setFixedWidth(lineEditWidth()); - input->setMaxLength(charlimit); - input->setText(QString::fromStdU16String(std::u16string(m_osk_text_return))); - input->setFocus(); - - // Text Input Counter - QLabel* inputCount = new QLabel(QString("%1/%2").arg(input->text().length()).arg(charlimit)); - - // Ok Button - QPushButton* button_ok = new QPushButton("Ok", m_osk_dialog); - - // Button Layout - QHBoxLayout* buttonsLayout = new QHBoxLayout; - buttonsLayout->setAlignment(Qt::AlignCenter); - buttonsLayout->addStretch(); - buttonsLayout->addWidget(button_ok); - buttonsLayout->addStretch(); - - // Input Layout - QHBoxLayout* inputLayout = new QHBoxLayout; - inputLayout->setAlignment(Qt::AlignHCenter); - inputLayout->addWidget(input); - inputLayout->addWidget(inputCount); - - QFormLayout* layout = new QFormLayout(m_osk_dialog); - layout->setFormAlignment(Qt::AlignHCenter); - layout->addRow(message_label); - layout->addRow(inputLayout); - layout->addRow(buttonsLayout); - m_osk_dialog->setLayout(layout); - - // Events - connect(input, &QLineEdit::textChanged, [=](const QString& text) - { - inputCount->setText(QString("%1/%2").arg(text.length()).arg(charlimit)); - on_osk_input_entered(); - }); - - connect(input, &QLineEdit::returnPressed, m_osk_dialog, &QDialog::accept); - connect(button_ok, &QAbstractButton::clicked, m_osk_dialog, &QDialog::accept); - - connect(m_osk_dialog, &QDialog::rejected, [=] - { - if (!type.disable_cancel) - { - on_close(CELL_MSGDIALOG_BUTTON_ESCAPE); - } - }); - - connect(m_osk_dialog, &QDialog::accepted, [=] - { - std::memcpy(m_osk_text_return, reinterpret_cast(input->text().constData()), ((input->text()).size() + 1) * sizeof(char16_t)); - on_close(CELL_MSGDIALOG_BUTTON_OK); - }); - - // Fix size - m_osk_dialog->layout()->setSizeConstraint(QLayout::SetFixedSize); - m_osk_dialog->show(); -} - msg_dialog_frame::msg_dialog_frame(QWindow* taskbarTarget) : m_taskbarTarget(taskbarTarget) {} msg_dialog_frame::~msg_dialog_frame() @@ -257,10 +173,6 @@ msg_dialog_frame::~msg_dialog_frame() { m_dialog->deleteLater(); } - if (m_osk_dialog) - { - m_osk_dialog->deleteLater(); - } } void msg_dialog_frame::SetMsg(const std::string& msg) diff --git a/rpcs3/rpcs3qt/msg_dialog_frame.h b/rpcs3/rpcs3qt/msg_dialog_frame.h index 27fe3b4aa8..e607273814 100644 --- a/rpcs3/rpcs3qt/msg_dialog_frame.h +++ b/rpcs3/rpcs3qt/msg_dialog_frame.h @@ -4,18 +4,17 @@ #include "Emu/Memory/vm.h" #include "Emu/Cell/Modules/cellMsgDialog.h" #include "Emu/System.h" -#include "Emu/Memory/vm.h" #include "Emu/Cell/lv2/sys_time.h" +#include "custom_dialog.h" + #include #include -#include #include #include #include #include #include -#include #include #ifdef _WIN32 @@ -28,8 +27,6 @@ #include #endif -class custom_dialog; - class msg_dialog_frame : public QObject, public MsgDialogBase { Q_OBJECT @@ -45,24 +42,17 @@ private: QLabel* m_text = nullptr; QLabel* m_text1 = nullptr; QLabel* m_text2 = nullptr; - QPushButton* m_button_ok = nullptr; - QPushButton* m_button_yes = nullptr; - QPushButton* m_button_no = nullptr; QProgressBar* m_gauge1 = nullptr; QProgressBar* m_gauge2 = nullptr; QWindow* m_taskbarTarget; // Window which will be targeted by custom taskbars. - custom_dialog* m_osk_dialog = nullptr; - char16_t* m_osk_text_return; - int m_gauge_max = 0; public: msg_dialog_frame(QWindow* taskbarTarget); ~msg_dialog_frame(); virtual void Create(const std::string& msg, const std::string& title = "") override; - virtual void CreateOsk(const std::string& title, const std::u16string& message, char16_t* osk_text, u32 charlimit) override; virtual void SetMsg(const std::string& msg) override; virtual void ProgressBarSetMsg(u32 progressBarIndex, const std::string& msg) override; virtual void ProgressBarReset(u32 progressBarIndex) override; @@ -73,44 +63,3 @@ private: void UpdateProgress(int progress, bool disable = false); #endif }; - -class custom_dialog : public QDialog -{ - Q_OBJECT - - bool m_disable_cancel; -public: - explicit custom_dialog(bool disableCancel, QWidget* parent = 0) - : QDialog(parent), m_disable_cancel(disableCancel) - { - if (m_disable_cancel) - { - setWindowFlags(windowFlags() & ~Qt::WindowCloseButtonHint); - } - } -private: - void keyPressEvent(QKeyEvent* event) override - { - // this won't work with Alt+F4, the window still closes - if (m_disable_cancel && event->key() == Qt::Key_Escape) - { - event->ignore(); - } - else - { - QDialog::keyPressEvent(event); - } - } - void closeEvent(QCloseEvent* event) override - { - // spontaneous: don't close on external system level events like Alt+F4 - if (m_disable_cancel && event->spontaneous()) - { - event->ignore(); - } - else - { - QDialog::closeEvent(event); - } - } -}; diff --git a/rpcs3/rpcs3qt/osk_dialog_frame.cpp b/rpcs3/rpcs3qt/osk_dialog_frame.cpp new file mode 100644 index 0000000000..b093931958 --- /dev/null +++ b/rpcs3/rpcs3qt/osk_dialog_frame.cpp @@ -0,0 +1,103 @@ + +#include "osk_dialog_frame.h" +#include "Emu/Cell/Modules/cellMsgDialog.h" + +#include +#include +#include +#include +#include + +constexpr auto qstr = QString::fromStdString; + +osk_dialog_frame::osk_dialog_frame() +{ +} + +osk_dialog_frame::~osk_dialog_frame() +{ + if (m_dialog) + { + m_dialog->deleteLater(); + } +} + +void osk_dialog_frame::Create(const std::string& title, const std::u16string& message, char16_t* init_text, u32 charlimit) +{ + state = OskDialogState::Open; + + static const auto& lineEditWidth = []() {return QLabel("This is the very length of the lineedit due to hidpi reasons.").sizeHint().width(); }; + + if (m_dialog) + { + m_dialog->close(); + delete m_dialog; + } + + m_dialog = new custom_dialog(false); + m_dialog->setModal(true); + + // Title + m_dialog->setWindowTitle(qstr(title)); + + // Message + QLabel* message_label = new QLabel(QString::fromStdU16String(message)); + + // Text Input + QLineEdit* input = new QLineEdit(m_dialog); + input->setFixedWidth(lineEditWidth()); + input->setMaxLength(charlimit); + input->setText(QString::fromStdU16String(std::u16string(init_text))); + input->setFocus(); + + // Text Input Counter + QLabel* inputCount = new QLabel(QString("%1/%2").arg(input->text().length()).arg(charlimit)); + + // Ok Button + QPushButton* button_ok = new QPushButton("Ok", m_dialog); + + // Button Layout + QHBoxLayout* buttonsLayout = new QHBoxLayout; + buttonsLayout->setAlignment(Qt::AlignCenter); + buttonsLayout->addStretch(); + buttonsLayout->addWidget(button_ok); + buttonsLayout->addStretch(); + + // Input Layout + QHBoxLayout* inputLayout = new QHBoxLayout; + inputLayout->setAlignment(Qt::AlignHCenter); + inputLayout->addWidget(input); + inputLayout->addWidget(inputCount); + + QFormLayout* layout = new QFormLayout(m_dialog); + layout->setFormAlignment(Qt::AlignHCenter); + layout->addRow(message_label); + layout->addRow(inputLayout); + layout->addRow(buttonsLayout); + m_dialog->setLayout(layout); + + // Events + connect(input, &QLineEdit::textChanged, [=](const QString& text) + { + inputCount->setText(QString("%1/%2").arg(text.length()).arg(charlimit)); + on_osk_input_entered(); + }); + + connect(input, &QLineEdit::returnPressed, m_dialog, &QDialog::accept); + connect(button_ok, &QAbstractButton::clicked, m_dialog, &QDialog::accept); + + connect(m_dialog, &QDialog::accepted, [=] + { + std::memcpy(osk_text, reinterpret_cast(input->text().constData()), ((input->text()).size() + 1) * sizeof(char16_t)); + on_close(CELL_MSGDIALOG_BUTTON_OK); + }); + + connect(m_dialog, &QDialog::rejected, [=] + { + on_close(CELL_MSGDIALOG_BUTTON_ESCAPE); + }); + + // Fix size + m_dialog->layout()->setSizeConstraint(QLayout::SetFixedSize); + m_dialog->show(); +} diff --git a/rpcs3/rpcs3qt/osk_dialog_frame.h b/rpcs3/rpcs3qt/osk_dialog_frame.h new file mode 100644 index 0000000000..a6e0ba1b1a --- /dev/null +++ b/rpcs3/rpcs3qt/osk_dialog_frame.h @@ -0,0 +1,22 @@ +#pragma once + +#include "stdafx.h" +#include "Emu/Memory/vm.h" +#include "Emu/Cell/Modules/cellOskDialog.h" +#include "Emu/System.h" +#include "Emu/Cell/lv2/sys_time.h" + +#include "custom_dialog.h" + +class osk_dialog_frame : public QObject, public OskDialogBase +{ + Q_OBJECT + +public: + osk_dialog_frame(); + ~osk_dialog_frame(); + virtual void Create(const std::string& title, const std::u16string& message, char16_t* init_text, u32 charlimit) override; + +private: + custom_dialog* m_dialog = nullptr; +};