From e839de50140f6f102d187db7cc5c106fbef38c9d Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Tue, 13 Apr 2021 00:32:26 +0200 Subject: [PATCH] early-access version 1591 --- README.md | 2 +- dist/qt_themes/default/style.qss | 377 ---- dist/qt_themes/qdarkstyle/style.qss | 399 +--- .../qdarkstyle_midnight_blue/style.qss | 439 +---- dist/yuzu.ico | Bin 25355 -> 23159 bytes dist/yuzu.svg | 2 +- src/common/assert.cpp | 6 +- src/core/CMakeLists.txt | 1 - .../frontend/applets/software_keyboard.cpp | 148 +- src/core/frontend/applets/software_keyboard.h | 114 +- src/core/frontend/input_interpreter.cpp | 15 +- src/core/frontend/input_interpreter.h | 3 - src/core/hle/kernel/hle_ipc.cpp | 8 +- src/core/hle/kernel/hle_ipc.h | 10 - src/core/hle/kernel/k_thread.h | 2 +- src/core/hle/kernel/kernel.cpp | 41 +- src/core/hle/kernel/process.cpp | 22 +- src/core/hle/service/am/am.cpp | 79 +- src/core/hle/service/am/am.h | 1 - src/core/hle/service/am/applets/applets.cpp | 18 +- src/core/hle/service/am/applets/applets.h | 10 +- .../hle/service/am/applets/controller.cpp | 5 +- src/core/hle/service/am/applets/controller.h | 4 +- src/core/hle/service/am/applets/error.cpp | 5 +- src/core/hle/service/am/applets/error.h | 4 +- .../service/am/applets/general_backend.cpp | 14 +- .../hle/service/am/applets/general_backend.h | 11 +- .../hle/service/am/applets/profile_select.cpp | 4 +- .../hle/service/am/applets/profile_select.h | 3 +- .../service/am/applets/software_keyboard.cpp | 1167 ++--------- .../service/am/applets/software_keyboard.h | 187 +- .../hle/service/am/applets/web_browser.cpp | 5 +- src/core/hle/service/am/applets/web_browser.h | 4 +- .../service/nvdrv/devices/nvhost_nvdec.cpp | 1 - .../nvdrv/devices/nvhost_nvdec_common.cpp | 8 +- .../nvdrv/devices/nvhost_nvdec_common.h | 1 - .../hle/service/nvdrv/devices/nvhost_vic.cpp | 5 +- src/input_common/sdl/sdl_impl.cpp | 26 +- src/input_common/sdl/sdl_impl.h | 4 - src/video_core/engines/shader_bytecode.h | 4 - src/video_core/memory_manager.cpp | 19 - src/video_core/memory_manager.h | 8 - src/video_core/rasterizer_interface.h | 6 - .../renderer_opengl/gl_arb_decompiler.cpp | 82 +- .../renderer_opengl/gl_rasterizer.cpp | 20 - .../renderer_opengl/gl_rasterizer.h | 2 - .../renderer_opengl/gl_shader_decompiler.cpp | 146 +- .../renderer_vulkan/vk_rasterizer.cpp | 20 - .../renderer_vulkan/vk_rasterizer.h | 2 - .../renderer_vulkan/vk_shader_decompiler.cpp | 115 +- src/video_core/shader/control_flow.cpp | 159 +- src/video_core/shader/control_flow.h | 13 +- src/video_core/shader/decode.cpp | 225 +-- src/video_core/shader/decode/other.cpp | 11 - src/video_core/shader/decode/texture.cpp | 4 +- src/video_core/shader/node.h | 15 +- src/video_core/shader/node_helper.cpp | 5 - src/video_core/shader/node_helper.h | 3 - src/video_core/shader/shader_ir.h | 95 +- src/yuzu/CMakeLists.txt | 4 - src/yuzu/applets/error.cpp | 22 +- src/yuzu/applets/error.h | 2 +- src/yuzu/applets/software_keyboard.cpp | 1714 ++--------------- src/yuzu/applets/software_keyboard.h | 285 +-- src/yuzu/discord_impl.cpp | 2 +- src/yuzu/main.cpp | 187 +- src/yuzu/main.h | 35 +- 67 files changed, 777 insertions(+), 5583 deletions(-) diff --git a/README.md b/README.md index 8f4e6d47e..96e64acfb 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 1588. +This is the source code for early-access 1591. ## Legal Notice diff --git a/dist/qt_themes/default/style.qss b/dist/qt_themes/default/style.qss index 3bc92b69d..836dd25ca 100755 --- a/dist/qt_themes/default/style.qss +++ b/dist/qt_themes/default/style.qss @@ -281,380 +281,3 @@ QWidget#controllerPlayer7, QWidget#controllerPlayer8 { background: transparent; } - -QDialog#QtSoftwareKeyboardDialog, -QStackedWidget#topOSK { - background: rgba(51, 51, 51, .9); -} - - -QDialog#OverlayDialog, -QStackedWidget#stackedDialog { - background: rgba(51, 51, 51, .7); -} - -QWidget#boxOSK, -QWidget#lineOSK, -QWidget#richDialog, -QWidget#lineDialog { - background: transparent; -} - -QStackedWidget#bottomOSK, -QWidget#contentDialog, -QWidget#contentRichDialog { - background: rgba(240, 240, 240, 1); -} - -QWidget#contentDialog, -QWidget#contentRichDialog { - margin: 5px; - border-radius: 6px; -} - -QWidget#buttonsDialog, -QWidget#buttonsRichDialog { - margin: 5px; - border-top: 2px solid rgba(44, 44, 44, 1); -} - -QWidget#legendOSKnum { - border-top: 1px solid rgba(44, 44, 44, 1); -} - -QStackedWidget#stackedDialog QTextBrowser QScrollBar::vertical { - background: #cdcdcd; - width: 15px; - margin: 15px 3px 15px 3px; - border: 1px transparent; - border-radius: 4px; -} - -QStackedWidget#stackedDialog QTextBrowser QScrollBar::horizoncal { - background: #cdcdcd; - height: 15px; - margin: 3px 15px 3px 15px; - border: 1px transparent; - border-radius: 4px; -} - -QStackedWidget#stackedDialog QTextBrowser QScrollBar::handle { - background: #fff; - border-radius: 4px; - min-height: 5px; - min-width: 5px; -} - -QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-line, -QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-line, -QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-page, -QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-page { - background: none; -} - -QWidget#inputOSK { - border-bottom: 3px solid rgba(255, 255, 255, .9); -} - -QWidget#inputOSK QLineEdit { - background: transparent; - border: none; - color: #ccc; -} - -QWidget#inputBoxOSK { - border: 2px solid rgba(255, 255, 255, .9); -} - -QWidget#inputBoxOSK QTextEdit { - background: transparent; - border: none; - color: #ccc; -} - -QWidget#richDialog QTextBrowser { - background: transparent; - border: none; - padding: 35px 65px; -} - - -QWidget#lineOSK QLabel#label_header { - color: #f0f0f0; -} - -QWidget#lineOSK QLabel#label_sub, -QWidget#lineOSK QLabel#label_characters, -QWidget#boxOSK QLabel#label_characters_box { - color: #ccc; -} - -QWidget#contentDialog QLabel#label_title, -QWidget#contentRichDialog QLabel#label_title_rich { - color: #888; -} - -QWidget#contentDialog QLabel#label_dialog { - padding: 20px 65px; -} - -QWidget#contentDialog QLabel#label_title, -QWidget#contentRichDialog QLabel#label_title_rich { - padding: 0px 65px; -} - -QDialog#OverlayDialog QPushButton { - color: rgba(49, 79, 239, 1); - background: transparent; - border: none; - padding: 0px; - min-width: 0px; -} - -QDialog#OverlayDialog QPushButton:focus, -QDialog#OverlayDialog QPushButton:hover { - color: rgba(49, 79, 239, 1); - background: rgba(255, 255, 255, 1); - border: 5px solid rgba(148, 250, 202, 1); - border-radius: 6px; - outline: none; -} - -QDialog#OverlayDialog QPushButton:pressed { - color: rgba(240, 240, 240, 1); - background: rgba(150, 150, 150, 1); - border: 5px solid rgba(148, 250, 202, 1); - border-radius: 6px; - outline: none; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton { - background: rgba(232, 232, 232, 1); - border: 2px solid rgba(240, 240, 240, 1); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift { - background: rgba(218, 218, 218, 1); - border: 2px solid rgba(240, 240, 240, 1); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num { - color: rgba(240, 240, 240, 1); - background: rgba(44, 44, 44, 1); - border: 2px solid rgba(240, 240, 240, 1); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num { - color: rgba(240, 240, 240, 1); - background: rgba(49, 79, 239, 1); - border: 2px solid rgba(240, 240, 240, 1); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:focus, - -QDialog#QtSoftwareKeyboardDialog QPushButton:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:hover { - color: rgba(0, 0, 0, 1); - background: rgba(255, 255, 255, 1); - border: 5px solid rgba(148, 250, 202, 1); - border-radius: 6px; - outline: none; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:pressed { - color: rgba(240, 240, 240, 1); - background: rgba(150, 150, 150, 1); - border: 5px solid rgba(148, 250, 202, 1); - border-radius: 6px; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num { - background-position: right top; - background-repeat: no-repeat; - background-origin: content; - background-image: url(:/overlay/osk_button_B.png); - qproperty-icon: url(:/overlay/osk_button_backspace.png); - qproperty-iconSize: 36px; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift { - background-position: right top; - background-repeat: no-repeat; - background-origin: content; - background-image: url(:/overlay/osk_button_Y.png); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num { - background-position: right top; - background-repeat: no-repeat; - background-origin: content; - background-image: url(:/overlay/osk_button_plus.png); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift { - background-position: left top; - background-repeat: no-repeat; - background-origin: content; - background-image: url(:/overlay/osk_button_shift_lock_off.png); - qproperty-icon: url(:/overlay/osk_button_shift.png); - qproperty-iconSize: 36px; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift { - background-position: left top; - background-repeat: no-repeat; - background-origin: content; - background-image: url(:/overlay/osk_button_shift_lock_off.png); - qproperty-icon: url(:/overlay/osk_button_shift_on.png); - qproperty-iconSize: 36px; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_bracket, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_bracket, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_parenthesis, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_parenthesis { - padding-bottom: 7px; -} - -QDialog#QtSoftwareKeyboardDialog QWidget#titleOSK QLabel { - background: transparent; - color: #ccc; -} - -QDialog#QtSoftwareKeyboardDialog QWidget#button_L, -QDialog#QtSoftwareKeyboardDialog QWidget#button_L_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#button_L_num { - image: url(:/overlay/button_L.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left, -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_num { - image: url(:/overlay/arrow_left.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#button_R, -QDialog#QtSoftwareKeyboardDialog QWidget#button_R_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#button_R_num { - image: url(:/overlay/button_R.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right, -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_num { - image: url(:/overlay/arrow_right.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick, -QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick_shift { - image: url(:/overlay/button_press_stick.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#button_X, -QDialog#QtSoftwareKeyboardDialog QWidget#button_X_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#button_X_num { - image: url(:/overlay/button_X.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#button_A, -QDialog#QtSoftwareKeyboardDialog QWidget#button_A_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#button_A_num { - image: url(:/overlay/button_A.png); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled { - color: rgba(164, 164, 164, 1); - background-color: rgba(218, 218, 218, 1); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_at:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_slash:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_percent:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_1:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_2:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_3:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_4:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_5:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_6:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_7:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_8:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_9:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_0:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled { - color: rgba(164, 164, 164, 1); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled { - background-image: url(:/overlay/osk_button_plus_disabled.png); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled { - background-image: url(:/overlay/osk_button_B_disabled.png); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled { - background-image: url(:/overlay/osk_button_Y_disabled.png); -} diff --git a/dist/qt_themes/qdarkstyle/style.qss b/dist/qt_themes/qdarkstyle/style.qss index 8ce6d75f7..2a1e8ddeb 100755 --- a/dist/qt_themes/qdarkstyle/style.qss +++ b/dist/qt_themes/qdarkstyle/style.qss @@ -1560,400 +1560,7 @@ QWidget#controllerPlayer8 { background: transparent; } -QDialog#QtSoftwareKeyboardDialog, -QStackedWidget#topOSK { - background: rgba(41, 41, 41, .9); -} - - -QDialog#OverlayDialog, -QStackedWidget#stackedDialog { - background: rgba(41, 41, 41, .7); -} - -QWidget#boxOSK, -QWidget#lineOSK, -QWidget#richDialog, -QWidget#lineDialog { - background: transparent; -} - -QStackedWidget#bottomOSK, -QWidget#contentDialog, -QWidget#contentRichDialog { - background: rgba(71, 69, 71, 1); -} - -QWidget#contentDialog, -QWidget#contentRichDialog { - margin: 5px; - border-radius: 6px; -} - -QWidget#buttonsDialog, -QWidget#buttonsRichDialog { - margin: 5px; - border-top: 2px solid rgba(255, 255, 255, .9); -} - -QWidget#legendOSKnum { - border-top: 1px solid rgba(255, 255, 255, 1); -} - -QStackedWidget#stackedDialog QTextBrowser QWidget { - background: transparent; -} - -QStackedWidget#stackedDialog QTextBrowser QScrollBar { - background: #2a2929; -} - -QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-line, -QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-line { - border-image: none; -} - -QWidget#inputOSK { - border-bottom: 3px solid rgba(255, 255, 255, .9); -} - -QWidget#inputOSK QLineEdit { - background: transparent; - border: none; - color: #ccc; - padding: 0px; -} - -QWidget#inputBoxOSK { - border: 2px solid rgba(255, 255, 255, .9); -} - -QWidget#inputBoxOSK QTextEdit { - background: transparent; - border: none; - color: #ccc; -} - -QWidget#richDialog QTextBrowser { - background: transparent; - border: none; - color: #fff; - padding: 35px 65px; -} - -QWidget#lineOSK QLabel#label_header { - color: #f0f0f0; -} - -QWidget#lineOSK QLabel#label_sub, -QWidget#lineOSK QLabel#label_characters, -QWidget#contentDialog QLabel#label_title, -QWidget#contentRichDialog QLabel#label_title_rich, -QWidget#boxOSK QLabel#label_characters_box { - color: #ccc; -} - -QWidget#buttonsDialog, -QWidget#buttonsRichDialog, -QWidget#mainOSK, -QWidget#headerOSK, -QWidget#normalOSK, -QWidget#shiftOSK, -QWidget#numOSK, -QWidget#subOSK, -QWidget#inputOSK, -QWidget#inputBoxOSK, -QWidget#charactersOSK, -QWidget#charactersBoxOSK, -QWidget#legendOSK, -QWidget#legendOSK QWidget, -QWidget#legendOSKshift, -QWidget#legendOSKshift QWidget, -QWidget#legendOSKnum, -QWidget#legendOSKnum QWidget { - background: transparent; -} - -QWidget#contentDialog QLabel, -QWidget#legendOSK QLabel, -QWidget#legendOSKshift QLabel, -QWidget#legendOSKnum QLabel { - color: rgba(255, 255, 255, 1); -} - -QWidget#contentDialog QLabel#label_dialog { - padding: 20px 65px; -} - -QWidget#contentDialog QLabel#label_title, -QWidget#contentRichDialog QLabel#label_title_rich { - padding: 0px 65px; -} - -QDialog#OverlayDialog QPushButton { - color: rgba(1, 253, 201, 1); - background: transparent; - border: none; - padding: 0px; - min-width: 0px; -} - -QDialog#OverlayDialog QPushButton:focus, -QDialog#OverlayDialog QPushButton:hover { - color: rgba(1, 253, 201, 1); - background: rgba(58, 61, 66, 1); - border: 5px solid rgba(56, 189, 225, 1); - border-radius: 6px; - outline: none; -} - -QDialog#OverlayDialog QPushButton:pressed { - color: rgba(240, 240, 240, 1); - background: rgba(150, 150, 150, 1); - border: 5px solid rgba(56, 189, 225, 1); - border-radius: 6px; - outline: none; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton { - color: rgba(255, 255, 255, 1); - background: rgba(80, 79, 80, 1); - border: 2px solid rgba(71, 69, 71, 1); - padding: 0px; - min-width: 0px; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift { - background: rgba(95, 94, 95, 1); - border: 2px solid rgba(71, 69, 71, 1); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num { - color: rgba(240, 240, 240, 1); - background: rgba(255, 255, 255, 1); - border: 2px solid rgba(71, 69, 71, 1); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num { - color: rgba(0, 0, 0, 1); - background: rgba(1, 253, 201, 1); - border: 2px solid rgba(71, 69, 71, 1); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:focus, - -QDialog#QtSoftwareKeyboardDialog QPushButton:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:hover { - color: rgba(255, 255, 255, 1); - background: rgba(58, 61, 66, 1); - border: 5px solid rgba(56, 189, 225, 1); - border-radius: 6px; - outline: none; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:pressed { - color: rgba(240, 240, 240, 1); - background: rgba(150, 150, 150, 1); - border: 5px solid rgba(56, 189, 225, 1); - border-radius: 6px; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num { - background-position: right top; - background-repeat: no-repeat; - background-origin: content; - background-image: url(:/overlay/osk_button_B_dark.png); - qproperty-icon: url(:/overlay/osk_button_backspace_dark.png); - qproperty-iconSize: 36px; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift { - background-position: right top; - background-repeat: no-repeat; - background-origin: content; - background-image: url(:/overlay/osk_button_Y_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num { - color: rgba(44, 44, 44, 1); - background-position: right top; - background-repeat: no-repeat; - background-origin: content; - background-image: url(:/overlay/osk_button_plus_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift { - background-position: left top; - background-repeat: no-repeat; - background-origin: content; - background-image: url(:/overlay/osk_button_shift_lock_off.png); - qproperty-icon: url(:/overlay/osk_button_shift_dark.png); - qproperty-iconSize: 36px; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift { - background-position: left top; - background-repeat: no-repeat; - background-origin: content; - background-image: url(:/overlay/osk_button_shift_lock_off.png); - qproperty-icon: url(:/overlay/osk_button_shift_on_dark.png); - qproperty-iconSize: 36px; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_bracket, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_bracket, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_parenthesis, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_parenthesis { - padding-bottom: 7px; -} - -QDialog#QtSoftwareKeyboardDialog QWidget#titleOSK QLabel { - background: transparent; - color: #ccc; -} - -QDialog#QtSoftwareKeyboardDialog QWidget#button_L, -QDialog#QtSoftwareKeyboardDialog QWidget#button_L_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#button_L_num { - image: url(:/overlay/button_L_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left, -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_num { - image: url(:/overlay/arrow_left_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#button_R, -QDialog#QtSoftwareKeyboardDialog QWidget#button_R_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#button_R_num { - image: url(:/overlay/button_R_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right, -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_num { - image: url(:/overlay/arrow_right_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick, -QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick_shift { - image: url(:/overlay/button_press_stick_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#button_X, -QDialog#QtSoftwareKeyboardDialog QWidget#button_X_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#button_X_num { - image: url(:/overlay/button_X_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#button_A, -QDialog#QtSoftwareKeyboardDialog QWidget#button_A_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#button_A_num { - image: url(:/overlay/button_A_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled { - color: rgba(144, 144, 144, 1); - background-color: rgba(95, 94, 95, 1); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_at:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_slash:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_percent:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_1:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_2:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_3:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_4:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_5:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_6:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_7:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_8:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_9:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_0:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled { - color: rgba(144, 144, 144, 1); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled { - background-image: url(:/overlay/osk_button_plus_dark_disabled.png); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled { - background-image: url(:/overlay/osk_button_B_dark_disabled.png); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled { - background-image: url(:/overlay/osk_button_Y_dark_disabled.png); -} - -QDialog#QtSoftwareKeyboardDialog QFrame, -QDialog#QtSoftwareKeyboardDialog QFrame[frameShape="0"], -QDialog#OverlayDialog QFrame, -QDialog#OverlayDialog QFrame[frameShape="0"] { - border-radius: 0px; - border: none; +/* touchscreen mapping widget */ +TouchScreenPreview { + qproperty-dotHighlightColor: #3daee9; } diff --git a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss index 64e1ecbcc..a64037455 100755 --- a/dist/qt_themes/qdarkstyle_midnight_blue/style.qss +++ b/dist/qt_themes/qdarkstyle_midnight_blue/style.qss @@ -1,10 +1,10 @@ /* --------------------------------------------------------------------------- - Created by the qtsass compiler v0.1.1 + Created by the qtsass compiler v0.1.1 - The definitions are in the "qdarkstyle.qss._styles.scss" module + The definitions are in the "qdarkstyle.qss._styles.scss" module - WARNING! All changes made in this file will be lost! + WARNING! All changes made in this file will be lost! --------------------------------------------------------------------------- */ /* QDarkStyleSheet ----------------------------------------------------------- @@ -15,34 +15,34 @@ It is based on three selecting colors, three greyish (background) colors plus three whitish (foreground) colors. Each set of widgets of the same type have a header like this: - ------------------ - GroupName -------- - ------------------ + ------------------ + GroupName -------- + ------------------ And each widget is separated with a header like this: - QWidgetName ------ + QWidgetName ------ This makes more easy to find and change some css field. The basic configuration is described bellow. - BACKGROUND ----------- + BACKGROUND ----------- - Light (unpressed) - Normal (border, disabled, pressed, checked, toolbars, menus) - Dark (background) + Light (unpressed) + Normal (border, disabled, pressed, checked, toolbars, menus) + Dark (background) - FOREGROUND ----------- + FOREGROUND ----------- - Light (texts/labels) - Normal (not used yet) - Dark (disabled texts) + Light (texts/labels) + Normal (not used yet) + Dark (disabled texts) - SELECTION ------------ + SELECTION ------------ - Light (selection/hover/active) - Normal (selected) - Dark (selected disabled) + Light (selection/hover/active) + Normal (selected) + Dark (selected disabled) If a stranger configuration is required because of a bugfix or anything else, keep the comment on the line above so nobody changes it, including the @@ -2483,404 +2483,3 @@ QWidget#controllerPlayer7, QWidget#controllerPlayer8 { background: transparent; } - -QDialog#QtSoftwareKeyboardDialog, -QStackedWidget#topOSK { - background: rgba(15, 25, 34, .9); -} - -QDialog#OverlayDialog, -QStackedWidget#stackedDialog { - background: rgba(15, 25, 34, .7); -} - -QWidget#boxOSK, -QWidget#lineOSK, -QWidget#richDialog, -QWidget#lineDialog { - background: transparent; -} - -QStackedWidget#bottomOSK, -QWidget#contentDialog, -QWidget#contentRichDialog { - background: rgba(31, 41, 51, 1); -} - -QWidget#contentDialog, -QWidget#contentRichDialog { - margin: 5px; - border-radius: 6px; -} - -QWidget#buttonsDialog, -QWidget#buttonsRichDialog { - margin: 5px; - border-top: 2px solid rgba(255, 255, 255, .9); -} - -QWidget#legendOSKnum { - border-top: 1px solid rgba(255, 255, 255, 1); -} - -QStackedWidget#stackedDialog QTextBrowser QWidget { - background: transparent; -} - -QStackedWidget#stackedDialog QTextBrowser QScrollBar { - background: #19232d; - border: none; -} - -QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-line, -QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-line { - border-image: none; -} - -QWidget#mainOSK QStackedWidget, -QDialog#OverlayDialog QStackedWidget { - border: none; - padding: 0px; -} - -QWidget#inputOSK { - border-bottom: 3px solid rgba(255, 255, 255, .9); -} - -QWidget#inputOSK QLineEdit { - background: transparent; - border: none; - color: #ccc; - padding: 0px; -} - -QWidget#inputBoxOSK { - border: 2px solid rgba(255, 255, 255, .9); -} - -QWidget#inputBoxOSK QTextEdit { - background: transparent; - border: none; - color: #ccc; -} - -QWidget#richDialog QTextBrowser { - background: transparent; - border: none; - color: #fff; - padding: 35px 65px; -} - -QWidget#lineOSK QLabel#label_header { - color: #f0f0f0; -} - -QWidget#lineOSK QLabel#label_sub, -QWidget#lineOSK QLabel#label_characters, -QWidget#contentDialog QLabel#label_title, -QWidget#contentRichDialog QLabel#label_title_rich, -QWidget#boxOSK QLabel#label_characters_box { - color: #ccc; -} - -QWidget#buttonsDialog, -QWidget#buttonsRichDialog, -QWidget#mainOSK, -QWidget#headerOSK, -QWidget#normalOSK, -QWidget#shiftOSK, -QWidget#numOSK, -QWidget#subOSK, -QWidget#inputOSK, -QWidget#inputBoxOSK, -QWidget#charactersOSK, -QWidget#charactersBoxOSK, -QWidget#legendOSK, -QWidget#legendOSK QWidget, -QWidget#legendOSKshift, -QWidget#legendOSKshift QWidget, -QWidget#legendOSKnum, -QWidget#legendOSKnum QWidget { - background: transparent; -} - -QWidget#contentDialog QLabel, -QWidget#legendOSK QLabel, -QWidget#legendOSKshift QLabel, -QWidget#legendOSKnum QLabel { - color: rgba(255, 255, 255, 1); -} - -QWidget#contentDialog QLabel#label_dialog { - padding: 20px 65px; -} - -QWidget#contentDialog QLabel#label_title, -QWidget#contentRichDialog QLabel#label_title_rich { - padding: 0px 65px; -} - -QDialog#OverlayDialog QPushButton { - color: rgba(1, 253, 201, 1); - background: transparent; - border: none; - padding: 0px; - min-width: 0px; -} - -QDialog#OverlayDialog QPushButton:focus, -QDialog#OverlayDialog QPushButton:hover { - color: rgba(1, 253, 201, 1); - background: rgba(18, 33, 46, 1); - border: 5px solid rgba(56, 189, 225, 1); - border-radius: 6px; - outline: none; -} - -QDialog#OverlayDialog QPushButton:pressed { - color: rgba(240, 240, 240, 1); - background: rgba(110, 122, 130, 1); - border: 5px solid rgba(56, 189, 225, 1); - border-radius: 6px; - outline: none; -} - -QDialog#QtSoftwareKeyboardDialog QLabel { - padding: 0px; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton { - color: rgba(255, 255, 255, 1); - background: rgba(40, 51, 60, 1); - border: 2px solid rgba(31, 41, 51, 1); - border-radius: 0px; - padding: 0px; - min-width: 0px; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift { - background: rgba(55, 66, 75, 1); - border: 2px solid rgba(31, 41, 51, 1); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num { - color: rgba(240, 240, 240, 1); - background: rgba(255, 255, 255, 1); - border: 2px solid rgba(31, 41, 51, 1); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num { - color: rgba(0, 0, 0, 1); - background: rgba(1, 253, 201, 1); - border: 2px solid rgba(31, 41, 51, 1); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:focus, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:focus, - -QDialog#QtSoftwareKeyboardDialog QPushButton:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:hover, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:hover { - color: rgba(255, 255, 255, 1); - background: rgba(18, 33, 46, 1); - border: 5px solid rgba(56, 189, 225, 1); - border-radius: 6px; - outline: none; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:pressed, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:pressed { - color: rgba(240, 240, 240, 1); - background: rgba(110, 122, 130, 1); - border: 5px solid rgba(56, 189, 225, 1); - border-radius: 6px; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num { - background-position: right top; - background-repeat: no-repeat; - background-origin: content; - background-image: url(:/overlay/osk_button_B_dark.png); - qproperty-icon: url(:/overlay/osk_button_backspace_dark.png); - qproperty-iconSize: 36px; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift { - background-position: right top; - background-repeat: no-repeat; - background-origin: content; - background-image: url(:/overlay/osk_button_Y_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num { - color: rgba(44, 44, 44, 1); - background-position: right top; - background-repeat: no-repeat; - background-origin: content; - background-image: url(:/overlay/osk_button_plus_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift { - background-position: left top; - background-repeat: no-repeat; - background-origin: content; - background-image: url(:/overlay/osk_button_shift_lock_off.png); - qproperty-icon: url(:/overlay/osk_button_shift_dark.png); - qproperty-iconSize: 36px; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift { - background-position: left top; - background-repeat: no-repeat; - background-origin: content; - background-image: url(:/overlay/osk_button_shift_lock_off.png); - qproperty-icon: url(:/overlay/osk_button_shift_on_dark.png); - qproperty-iconSize: 36px; -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_bracket, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_bracket, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_parenthesis, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_parenthesis { - padding-bottom: 7px; -} - -QDialog#QtSoftwareKeyboardDialog QWidget#titleOSK QLabel { - background: transparent; - color: #ccc; -} - -QDialog#QtSoftwareKeyboardDialog QWidget#button_L, -QDialog#QtSoftwareKeyboardDialog QWidget#button_L_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#button_L_num { - image: url(:/overlay/button_L_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left, -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_num { - image: url(:/overlay/arrow_left_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#button_R, -QDialog#QtSoftwareKeyboardDialog QWidget#button_R_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#button_R_num { - image: url(:/overlay/button_R_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right, -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_num { - image: url(:/overlay/arrow_right_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick, -QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick_shift { - image: url(:/overlay/button_press_stick_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#button_X, -QDialog#QtSoftwareKeyboardDialog QWidget#button_X_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#button_X_num { - image: url(:/overlay/button_X_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QWidget#button_A, -QDialog#QtSoftwareKeyboardDialog QWidget#button_A_shift, -QDialog#QtSoftwareKeyboardDialog QWidget#button_A_num { - image: url(:/overlay/button_A_dark.png); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled { - color: rgba(144, 144, 144, 1); - background-color: rgba(55, 66, 75, 1); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_at:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_slash:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_percent:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_1:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_2:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_3:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_4:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_5:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_6:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_7:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_8:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_9:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_0:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled { - color: rgba(144, 144, 144, 1); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled { - background-image: url(:/overlay/osk_button_plus_dark_disabled.png); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled { - background-image: url(:/overlay/osk_button_B_dark_disabled.png); -} - -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled, -QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled { - background-image: url(:/overlay/osk_button_Y_dark_disabled.png); -} diff --git a/dist/yuzu.ico b/dist/yuzu.ico index 7c998a5c53a3b079b67c526586c269f2efd25447..df3be8464fcb3c0fb10308472ed527dbcdc10d61 100755 GIT binary patch literal 23159 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 literal 25355 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 s8oRK@Tvf05pF diff --git a/dist/yuzu.svg b/dist/yuzu.svg index 98ded2d8f..93171d1bf 100755 --- a/dist/yuzu.svg +++ b/dist/yuzu.svg @@ -1 +1 @@ -newAsset 7 \ No newline at end of file +Artboard 1 \ No newline at end of file diff --git a/src/common/assert.cpp b/src/common/assert.cpp index c3b70797d..d7d91b96b 100755 --- a/src/common/assert.cpp +++ b/src/common/assert.cpp @@ -4,4 +4,8 @@ #include "common/assert.h" -void assert_handle_failure() {} +#include "common/common_funcs.h" + +void assert_handle_failure() { + Crash(); +} diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 7d9eba928..167ee13f3 100755 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -273,7 +273,6 @@ add_library(core STATIC hle/service/am/applets/profile_select.h hle/service/am/applets/software_keyboard.cpp hle/service/am/applets/software_keyboard.h - hle/service/am/applets/software_keyboard_types.h hle/service/am/applets/web_browser.cpp hle/service/am/applets/web_browser.h hle/service/am/applets/web_types.h diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp index 12c76c9ee..856ed33da 100755 --- a/src/core/frontend/applets/software_keyboard.cpp +++ b/src/core/frontend/applets/software_keyboard.cpp @@ -1,149 +1,29 @@ -// Copyright 2021 yuzu Emulator Project +// Copyright 2018 yuzu emulator team // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include - -#include "common/logging/log.h" +#include "common/logging/backend.h" #include "common/string_util.h" #include "core/frontend/applets/software_keyboard.h" namespace Core::Frontend { - SoftwareKeyboardApplet::~SoftwareKeyboardApplet() = default; -DefaultSoftwareKeyboardApplet::~DefaultSoftwareKeyboardApplet() = default; +void DefaultSoftwareKeyboardApplet::RequestText( + std::function)> out, + SoftwareKeyboardParameters parameters) const { + if (parameters.initial_text.empty()) + out(u"yuzu"); -void DefaultSoftwareKeyboardApplet::InitializeKeyboard( - bool is_inline, KeyboardInitializeParameters initialize_parameters, - std::function submit_normal_callback_, - std::function - submit_inline_callback_) { - if (is_inline) { - LOG_WARNING( - Service_AM, - "(STUBBED) called, backend requested to initialize the inline software keyboard."); - - submit_inline_callback = std::move(submit_inline_callback_); - } else { - LOG_WARNING( - Service_AM, - "(STUBBED) called, backend requested to initialize the normal software keyboard."); - - submit_normal_callback = std::move(submit_normal_callback_); - } - - parameters = std::move(initialize_parameters); - - LOG_INFO(Service_AM, - "\nKeyboardInitializeParameters:" - "\nok_text={}" - "\nheader_text={}" - "\nsub_text={}" - "\nguide_text={}" - "\ninitial_text={}" - "\nmax_text_length={}" - "\nmin_text_length={}" - "\ninitial_cursor_position={}" - "\ntype={}" - "\npassword_mode={}" - "\ntext_draw_type={}" - "\nkey_disable_flags={}" - "\nuse_blur_background={}" - "\nenable_backspace_button={}" - "\nenable_return_button={}" - "\ndisable_cancel_button={}", - Common::UTF16ToUTF8(parameters.ok_text), Common::UTF16ToUTF8(parameters.header_text), - Common::UTF16ToUTF8(parameters.sub_text), Common::UTF16ToUTF8(parameters.guide_text), - Common::UTF16ToUTF8(parameters.initial_text), parameters.max_text_length, - parameters.min_text_length, parameters.initial_cursor_position, parameters.type, - parameters.password_mode, parameters.text_draw_type, parameters.key_disable_flags.raw, - parameters.use_blur_background, parameters.enable_backspace_button, - parameters.enable_return_button, parameters.disable_cancel_button); + out(parameters.initial_text); } -void DefaultSoftwareKeyboardApplet::ShowNormalKeyboard() const { +void DefaultSoftwareKeyboardApplet::SendTextCheckDialog( + std::u16string error_message, std::function finished_check) const { LOG_WARNING(Service_AM, - "(STUBBED) called, backend requested to show the normal software keyboard."); - - SubmitNormalText(u"yuzu"); + "(STUBBED) called - Default fallback software keyboard does not support text " + "check! (error_message={})", + Common::UTF16ToUTF8(error_message)); + finished_check(); } - -void DefaultSoftwareKeyboardApplet::ShowTextCheckDialog( - Service::AM::Applets::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message) const { - LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to show the text check dialog."); -} - -void DefaultSoftwareKeyboardApplet::ShowInlineKeyboard( - InlineAppearParameters appear_parameters) const { - LOG_WARNING(Service_AM, - "(STUBBED) called, backend requested to show the inline software keyboard."); - - LOG_INFO(Service_AM, - "\nInlineAppearParameters:" - "\nmax_text_length={}" - "\nmin_text_length={}" - "\nkey_top_scale_x={}" - "\nkey_top_scale_y={}" - "\nkey_top_translate_x={}" - "\nkey_top_translate_y={}" - "\ntype={}" - "\nkey_disable_flags={}" - "\nkey_top_as_floating={}" - "\nenable_backspace_button={}" - "\nenable_return_button={}" - "\ndisable_cancel_button={}", - appear_parameters.max_text_length, appear_parameters.min_text_length, - appear_parameters.key_top_scale_x, appear_parameters.key_top_scale_y, - appear_parameters.key_top_translate_x, appear_parameters.key_top_translate_y, - appear_parameters.type, appear_parameters.key_disable_flags.raw, - appear_parameters.key_top_as_floating, appear_parameters.enable_backspace_button, - appear_parameters.enable_return_button, appear_parameters.disable_cancel_button); - - std::thread([this] { SubmitInlineText(u"yuzu"); }).detach(); -} - -void DefaultSoftwareKeyboardApplet::HideInlineKeyboard() const { - LOG_WARNING(Service_AM, - "(STUBBED) called, backend requested to hide the inline software keyboard."); -} - -void DefaultSoftwareKeyboardApplet::InlineTextChanged(InlineTextParameters text_parameters) const { - LOG_WARNING(Service_AM, - "(STUBBED) called, backend requested to change the inline keyboard text."); - - LOG_INFO(Service_AM, - "\nInlineTextParameters:" - "\ninput_text={}" - "\ncursor_position={}", - Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position); - - submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString, - text_parameters.input_text, text_parameters.cursor_position); -} - -void DefaultSoftwareKeyboardApplet::ExitKeyboard() const { - LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to exit the software keyboard."); -} - -void DefaultSoftwareKeyboardApplet::SubmitNormalText(std::u16string text) const { - submit_normal_callback(Service::AM::Applets::SwkbdResult::Ok, text); -} - -void DefaultSoftwareKeyboardApplet::SubmitInlineText(std::u16string_view text) const { - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - - for (std::size_t index = 0; index < text.size(); ++index) { - submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString, - std::u16string(text.data(), text.data() + index + 1), - static_cast(index) + 1); - - std::this_thread::sleep_for(std::chrono::milliseconds(250)); - } - - submit_inline_callback(Service::AM::Applets::SwkbdReplyType::DecidedEnter, std::u16string(text), - static_cast(text.size())); -} - } // namespace Core::Frontend diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h index 506eb35bb..f9b202664 100755 --- a/src/core/frontend/applets/software_keyboard.h +++ b/src/core/frontend/applets/software_keyboard.h @@ -1,116 +1,54 @@ -// Copyright 2021 yuzu Emulator Project +// Copyright 2018 yuzu emulator team // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #pragma once #include -#include - +#include +#include +#include "common/bit_field.h" #include "common/common_types.h" -#include "core/hle/service/am/applets/software_keyboard_types.h" - namespace Core::Frontend { - -struct KeyboardInitializeParameters { - std::u16string ok_text; +struct SoftwareKeyboardParameters { + std::u16string submit_text; std::u16string header_text; std::u16string sub_text; std::u16string guide_text; std::u16string initial_text; - u32 max_text_length; - u32 min_text_length; - s32 initial_cursor_position; - Service::AM::Applets::SwkbdType type; - Service::AM::Applets::SwkbdPasswordMode password_mode; - Service::AM::Applets::SwkbdTextDrawType text_draw_type; - Service::AM::Applets::SwkbdKeyDisableFlags key_disable_flags; - bool use_blur_background; - bool enable_backspace_button; - bool enable_return_button; - bool disable_cancel_button; -}; + std::size_t max_length; + bool password; + bool cursor_at_beginning; -struct InlineAppearParameters { - u32 max_text_length; - u32 min_text_length; - f32 key_top_scale_x; - f32 key_top_scale_y; - f32 key_top_translate_x; - f32 key_top_translate_y; - Service::AM::Applets::SwkbdType type; - Service::AM::Applets::SwkbdKeyDisableFlags key_disable_flags; - bool key_top_as_floating; - bool enable_backspace_button; - bool enable_return_button; - bool disable_cancel_button; -}; + union { + u8 value; -struct InlineTextParameters { - std::u16string input_text; - s32 cursor_position; + BitField<1, 1, u8> disable_space; + BitField<2, 1, u8> disable_address; + BitField<3, 1, u8> disable_percent; + BitField<4, 1, u8> disable_slash; + BitField<6, 1, u8> disable_number; + BitField<7, 1, u8> disable_download_code; + }; }; class SoftwareKeyboardApplet { public: virtual ~SoftwareKeyboardApplet(); - virtual void InitializeKeyboard( - bool is_inline, KeyboardInitializeParameters initialize_parameters, - std::function - submit_normal_callback_, - std::function - submit_inline_callback_) = 0; - - virtual void ShowNormalKeyboard() const = 0; - - virtual void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message) const = 0; - - virtual void ShowInlineKeyboard(InlineAppearParameters appear_parameters) const = 0; - - virtual void HideInlineKeyboard() const = 0; - - virtual void InlineTextChanged(InlineTextParameters text_parameters) const = 0; - - virtual void ExitKeyboard() const = 0; + virtual void RequestText(std::function)> out, + SoftwareKeyboardParameters parameters) const = 0; + virtual void SendTextCheckDialog(std::u16string error_message, + std::function finished_check) const = 0; }; class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet { public: - ~DefaultSoftwareKeyboardApplet() override; - - void InitializeKeyboard( - bool is_inline, KeyboardInitializeParameters initialize_parameters, - std::function - submit_normal_callback_, - std::function - submit_inline_callback_) override; - - void ShowNormalKeyboard() const override; - - void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message) const override; - - void ShowInlineKeyboard(InlineAppearParameters appear_parameters) const override; - - void HideInlineKeyboard() const override; - - void InlineTextChanged(InlineTextParameters text_parameters) const override; - - void ExitKeyboard() const override; - -private: - void SubmitNormalText(std::u16string text) const; - void SubmitInlineText(std::u16string_view text) const; - - KeyboardInitializeParameters parameters; - - mutable std::function - submit_normal_callback; - mutable std::function - submit_inline_callback; + void RequestText(std::function)> out, + SoftwareKeyboardParameters parameters) const override; + void SendTextCheckDialog(std::u16string error_message, + std::function finished_check) const override; }; } // namespace Core::Frontend diff --git a/src/core/frontend/input_interpreter.cpp b/src/core/frontend/input_interpreter.cpp index 9f6a90e8f..ec5fe660e 100755 --- a/src/core/frontend/input_interpreter.cpp +++ b/src/core/frontend/input_interpreter.cpp @@ -12,9 +12,7 @@ InputInterpreter::InputInterpreter(Core::System& system) : npad{system.ServiceManager() .GetService("hid") ->GetAppletResource() - ->GetController(Service::HID::HidController::NPad)} { - ResetButtonStates(); -} + ->GetController(Service::HID::HidController::NPad)} {} InputInterpreter::~InputInterpreter() = default; @@ -27,17 +25,6 @@ void InputInterpreter::PollInput() { button_states[current_index] = button_state; } -void InputInterpreter::ResetButtonStates() { - previous_index = 0; - current_index = 0; - - button_states[0] = 0xFFFFFFFF; - - for (std::size_t i = 1; i < button_states.size(); ++i) { - button_states[i] = 0; - } -} - bool InputInterpreter::IsButtonPressed(HIDButton button) const { return (button_states[current_index] & (1U << static_cast(button))) != 0; } diff --git a/src/core/frontend/input_interpreter.h b/src/core/frontend/input_interpreter.h index 9495e3daf..73fc47ffb 100755 --- a/src/core/frontend/input_interpreter.h +++ b/src/core/frontend/input_interpreter.h @@ -66,9 +66,6 @@ public: /// Gets a button state from HID and inserts it into the array of button states. void PollInput(); - /// Resets all the button states to their defaults. - void ResetButtonStates(); - /** * Checks whether the button is pressed. * diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 2b363b1d9..161d9f782 100755 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -75,14 +75,10 @@ void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_ if (incoming) { // Populate the object lists with the data in the IPC request. for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) { - const u32 copy_handle{rp.Pop()}; - copy_handles.push_back(copy_handle); - copy_objects.push_back(handle_table.GetGeneric(copy_handle)); + copy_objects.push_back(handle_table.GetGeneric(rp.Pop())); } for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) { - const u32 move_handle{rp.Pop()}; - move_handles.push_back(move_handle); - move_objects.push_back(handle_table.GetGeneric(move_handle)); + move_objects.push_back(handle_table.GetGeneric(rp.Pop())); } } else { // For responses we just ignore the handles, they're empty and will be populated when diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 6fba42615..9a769781b 100755 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -210,14 +210,6 @@ public: /// Helper function to test whether the output buffer at buffer_index can be written bool CanWriteBuffer(std::size_t buffer_index = 0) const; - Handle GetCopyHandle(std::size_t index) const { - return copy_handles.at(index); - } - - Handle GetMoveHandle(std::size_t index) const { - return move_handles.at(index); - } - template std::shared_ptr GetCopyObject(std::size_t index) { return DynamicObjectCast(copy_objects.at(index)); @@ -293,8 +285,6 @@ private: std::shared_ptr server_session; std::shared_ptr thread; // TODO(yuriks): Check common usage of this and optimize size accordingly - boost::container::small_vector move_handles; - boost::container::small_vector copy_handles; boost::container::small_vector, 8> move_objects; boost::container::small_vector, 8> copy_objects; boost::container::small_vector, 8> domain_objects; diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 1c86fdd20..b442dfe57 100755 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -402,7 +402,7 @@ public: return wait_cancelled; } - [[nodiscard]] void ClearWaitCancelled() { + void ClearWaitCancelled() { wait_cancelled = false; } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index f7d3f218a..8fd990577 100755 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -67,13 +67,8 @@ struct KernelCore::Impl { is_phantom_mode_for_singlecore = false; InitializePhysicalCores(); - - // Derive the initial memory layout from the emulated board - KMemoryLayout memory_layout; - DeriveInitialMemoryLayout(memory_layout); - InitializeMemoryLayout(memory_layout); - InitializeSystemResourceLimit(kernel, system, memory_layout); - InitializeSlabHeaps(); + InitializeSystemResourceLimit(kernel, system); + InitializeMemoryLayout(); InitializeSchedulers(); InitializeSuspendThreads(); InitializePreemption(kernel); @@ -142,32 +137,27 @@ struct KernelCore::Impl { } // Creates the default system resource limit - void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system, - const KMemoryLayout& memory_layout) { + void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system) { system_resource_limit = std::make_shared(kernel, system); - const auto [total_size, kernel_size] = memory_layout.GetTotalAndKernelMemorySizes(); // If setting the default system values fails, then something seriously wrong has occurred. - ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, total_size) + ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, 0x100000000) .IsSuccess()); ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess()); ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200) .IsSuccess()); ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess()); - system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size); + // Derived from recent software updates. The kernel reserves 27MB + constexpr u64 kernel_size{0x1b00000}; + if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size)) { + UNREACHABLE(); + } // Reserve secure applet memory, introduced in firmware 5.0.0 - constexpr u64 secure_applet_memory_size{Common::Size_4_MB}; + constexpr u64 secure_applet_memory_size{0x400000}; ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory, secure_applet_memory_size)); - - // This memory seems to be reserved on hardware, but is not reserved/used by yuzu. - // Likely Horizon OS reserved memory - // TODO(ameerj): Derive the memory rather than hardcode it. - constexpr u64 unknown_reserved_memory{0x2f896000}; - ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory, - unknown_reserved_memory)); } void InitializePreemption(KernelCore& kernel) { @@ -541,7 +531,11 @@ struct KernelCore::Impl { linear_region_start); } - void InitializeMemoryLayout(const KMemoryLayout& memory_layout) { + void InitializeMemoryLayout() { + // Derive the initial memory layout from the emulated board + KMemoryLayout memory_layout; + DeriveInitialMemoryLayout(memory_layout); + const auto system_pool = memory_layout.GetKernelSystemPoolRegionPhysicalExtents(); const auto applet_pool = memory_layout.GetKernelAppletPoolRegionPhysicalExtents(); const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents(); @@ -584,14 +578,11 @@ struct KernelCore::Impl { system.Kernel(), system.DeviceMemory(), nullptr, {time_phys_addr, time_size / PageSize}, KMemoryPermission::None, KMemoryPermission::Read, time_phys_addr, time_size, "Time:SharedMemory"); - } - void InitializeSlabHeaps() { // Allocate slab heaps user_slab_heap_pages = std::make_unique>(); - // TODO(ameerj): This should be derived, not hardcoded within the kernel - constexpr u64 user_slab_heap_size{0x3de000}; + constexpr u64 user_slab_heap_size{0x1ef000}; // Reserve slab heaps ASSERT( system_resource_limit->Reserve(LimitableResource::PhysicalMemory, user_slab_heap_size)); diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 51a9c393b..9d5956ead 100755 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -120,7 +120,9 @@ std::shared_ptr Process::Create(Core::System& system, std::string name, std::shared_ptr process = std::make_shared(system); process->name = std::move(name); - process->resource_limit = kernel.GetSystemResourceLimit(); + // TODO: This is inaccurate + // The process should hold a reference to the kernel-wide resource limit. + process->resource_limit = std::make_shared(kernel, system); process->status = ProcessStatus::Created; process->program_id = 0; process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() @@ -158,6 +160,9 @@ void Process::DecrementThreadCount() { } u64 Process::GetTotalPhysicalMemoryAvailable() const { + // TODO: This is expected to always return the application memory pool size after accurately + // reserving kernel resources. The current workaround uses a process-local resource limit of + // application memory pool size, which is inaccurate. const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + main_thread_stack_size}; @@ -165,6 +170,7 @@ u64 Process::GetTotalPhysicalMemoryAvailable() const { if (capacity < memory_usage_capacity) { return capacity; } + return memory_usage_capacity; } @@ -266,6 +272,10 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, system_resource_size = metadata.GetSystemResourceSize(); image_size = code_size; + // Set initial resource limits + resource_limit->SetLimitValue( + LimitableResource::PhysicalMemory, + kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application)); KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, code_size + system_resource_size); if (!memory_reservation.Succeeded()) { @@ -314,6 +324,16 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, UNREACHABLE(); } + // Set initial resource limits + resource_limit->SetLimitValue( + LimitableResource::PhysicalMemory, + kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application)); + + resource_limit->SetLimitValue(LimitableResource::Threads, 608); + resource_limit->SetLimitValue(LimitableResource::Events, 700); + resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128); + resource_limit->SetLimitValue(LimitableResource::Sessions, 894); + // Create TLS region tls_region_address = CreateTLSRegion(); memory_reservation.Commit(); diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index b5cef7f9f..4374487a3 100755 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -971,7 +971,7 @@ private: auto storage = applet->GetBroker().PopNormalDataToGame(); if (storage == nullptr) { - LOG_DEBUG(Service_AM, + LOG_ERROR(Service_AM, "storage is a nullptr. There is no data in the current normal channel"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ERR_NO_DATA_IN_CHANNEL); @@ -1002,7 +1002,7 @@ private: auto storage = applet->GetBroker().PopInteractiveDataToGame(); if (storage == nullptr) { - LOG_DEBUG(Service_AM, + LOG_ERROR(Service_AM, "storage is a nullptr. There is no data in the current interactive channel"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ERR_NO_DATA_IN_CHANNEL); @@ -1125,7 +1125,7 @@ ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_) {2, nullptr, "AreAnyLibraryAppletsLeft"}, {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"}, {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"}, - {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"}, + {12, nullptr, "CreateHandleStorage"}, }; RegisterHandlers(functions); } @@ -1134,15 +1134,14 @@ ILibraryAppletCreator::~ILibraryAppletCreator() = default; void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto applet_id = rp.PopRaw(); - const auto applet_mode = rp.PopRaw(); + const auto applet_mode = rp.PopRaw(); LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id, applet_mode); const auto& applet_manager{system.GetAppletManager()}; - const auto applet = applet_manager.GetApplet(applet_id, applet_mode); + const auto applet = applet_manager.GetApplet(applet_id); if (applet == nullptr) { LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); @@ -1160,18 +1159,9 @@ void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - - const s64 size{rp.Pop()}; - + const u64 size{rp.Pop()}; LOG_DEBUG(Service_AM, "called, size={}", size); - if (size <= 0) { - LOG_ERROR(Service_AM, "size is less than or equal to 0"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_UNKNOWN); - return; - } - std::vector buffer(size); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -1180,65 +1170,18 @@ void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) { } void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called"); + IPC::RequestParser rp{ctx}; - struct Parameters { - u8 permissions; - s64 size; - }; - - const auto parameters{rp.PopRaw()}; - const auto handle{ctx.GetCopyHandle(0)}; - - LOG_DEBUG(Service_AM, "called, permissions={}, size={}, handle={:08X}", parameters.permissions, - parameters.size, handle); - - if (parameters.size <= 0) { - LOG_ERROR(Service_AM, "size is less than or equal to 0"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_UNKNOWN); - return; - } + rp.SetCurrentOffset(3); + const auto handle{rp.Pop()}; auto transfer_mem = system.CurrentProcess()->GetHandleTable().Get(handle); if (transfer_mem == nullptr) { - LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_UNKNOWN); - return; - } - - const u8* const mem_begin = transfer_mem->GetPointer(); - const u8* const mem_end = mem_begin + transfer_mem->GetSize(); - std::vector memory{mem_begin, mem_end}; - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface(system, std::move(memory)); -} - -void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - const s64 size{rp.Pop()}; - const auto handle{ctx.GetCopyHandle(0)}; - - LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle); - - if (size <= 0) { - LOG_ERROR(Service_AM, "size is less than or equal to 0"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_UNKNOWN); - return; - } - - auto transfer_mem = - system.CurrentProcess()->GetHandleTable().Get(handle); - - if (transfer_mem == nullptr) { - LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); + LOG_ERROR(Service_AM, "shared_mem is a nullpr for handle={:08X}", handle); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_UNKNOWN); return; diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index aefbdf0d5..f6a453ab7 100755 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -254,7 +254,6 @@ private: void CreateLibraryApplet(Kernel::HLERequestContext& ctx); void CreateStorage(Kernel::HLERequestContext& ctx); void CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx); - void CreateHandleStorage(Kernel::HLERequestContext& ctx); }; class IApplicationFunctions final : public ServiceFramework { diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index 5ddad851a..e2f3b7563 100755 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp @@ -241,31 +241,31 @@ void AppletManager::ClearAll() { frontend = {}; } -std::shared_ptr AppletManager::GetApplet(AppletId id, LibraryAppletMode mode) const { +std::shared_ptr AppletManager::GetApplet(AppletId id) const { switch (id) { case AppletId::Auth: - return std::make_shared(system, mode, *frontend.parental_controls); + return std::make_shared(system, *frontend.parental_controls); case AppletId::Controller: - return std::make_shared(system, mode, *frontend.controller); + return std::make_shared(system, *frontend.controller); case AppletId::Error: - return std::make_shared(system, mode, *frontend.error); + return std::make_shared(system, *frontend.error); case AppletId::ProfileSelect: - return std::make_shared(system, mode, *frontend.profile_select); + return std::make_shared(system, *frontend.profile_select); case AppletId::SoftwareKeyboard: - return std::make_shared(system, mode, *frontend.software_keyboard); + return std::make_shared(system, *frontend.software_keyboard); case AppletId::Web: case AppletId::Shop: case AppletId::OfflineWeb: case AppletId::LoginShare: case AppletId::WebAuth: - return std::make_shared(system, mode, *frontend.web_browser); + return std::make_shared(system, *frontend.web_browser); case AppletId::PhotoViewer: - return std::make_shared(system, mode, *frontend.photo_viewer); + return std::make_shared(system, *frontend.photo_viewer); default: UNIMPLEMENTED_MSG( "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.", static_cast(id)); - return std::make_shared(system, id, mode); + return std::make_shared(system, id); } } diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index 26b482015..b9a006317 100755 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h @@ -62,14 +62,6 @@ enum class AppletId : u32 { MyPage = 0x1A, }; -enum class LibraryAppletMode : u32 { - AllForeground = 0, - Background = 1, - NoUI = 2, - BackgroundIndirectDisplay = 3, - AllForegroundInitiallyHidden = 4, -}; - class AppletDataBroker final { public: explicit AppletDataBroker(Kernel::KernelCore& kernel_); @@ -208,7 +200,7 @@ public: void SetDefaultAppletsIfMissing(); void ClearAll(); - std::shared_ptr GetApplet(AppletId id, LibraryAppletMode mode) const; + std::shared_ptr GetApplet(AppletId id) const; private: AppletFrontendSet frontend; diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp index a33f05f97..c2bfe698f 100755 --- a/src/core/hle/service/am/applets/controller.cpp +++ b/src/core/hle/service/am/applets/controller.cpp @@ -45,9 +45,8 @@ static Core::Frontend::ControllerParameters ConvertToFrontendParameters( }; } -Controller::Controller(Core::System& system_, LibraryAppletMode applet_mode_, - const Core::Frontend::ControllerApplet& frontend_) - : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {} +Controller::Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_) + : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} Controller::~Controller() = default; diff --git a/src/core/hle/service/am/applets/controller.h b/src/core/hle/service/am/applets/controller.h index 07cb92bf9..d4c9da7b1 100755 --- a/src/core/hle/service/am/applets/controller.h +++ b/src/core/hle/service/am/applets/controller.h @@ -106,8 +106,7 @@ static_assert(sizeof(ControllerSupportResultInfo) == 0xC, class Controller final : public Applet { public: - explicit Controller(Core::System& system_, LibraryAppletMode applet_mode_, - const Core::Frontend::ControllerApplet& frontend_); + explicit Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_); ~Controller() override; void Initialize() override; @@ -120,7 +119,6 @@ public: void ConfigurationComplete(); private: - LibraryAppletMode applet_mode; const Core::Frontend::ControllerApplet& frontend; Core::System& system; diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp index a9f0a9c95..0c8b632e8 100755 --- a/src/core/hle/service/am/applets/error.cpp +++ b/src/core/hle/service/am/applets/error.cpp @@ -86,9 +86,8 @@ ResultCode Decode64BitError(u64 error) { } // Anonymous namespace -Error::Error(Core::System& system_, LibraryAppletMode applet_mode_, - const Core::Frontend::ErrorApplet& frontend_) - : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {} +Error::Error(Core::System& system_, const Core::Frontend::ErrorApplet& frontend_) + : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} Error::~Error() = default; diff --git a/src/core/hle/service/am/applets/error.h b/src/core/hle/service/am/applets/error.h index a3e520cd4..a105cdb0c 100755 --- a/src/core/hle/service/am/applets/error.h +++ b/src/core/hle/service/am/applets/error.h @@ -25,8 +25,7 @@ enum class ErrorAppletMode : u8 { class Error final : public Applet { public: - explicit Error(Core::System& system_, LibraryAppletMode applet_mode_, - const Core::Frontend::ErrorApplet& frontend_); + explicit Error(Core::System& system_, const Core::Frontend::ErrorApplet& frontend_); ~Error() override; void Initialize() override; @@ -41,7 +40,6 @@ public: private: union ErrorArguments; - LibraryAppletMode applet_mode; const Core::Frontend::ErrorApplet& frontend; ResultCode error_code = RESULT_SUCCESS; ErrorAppletMode mode = ErrorAppletMode::ShowError; diff --git a/src/core/hle/service/am/applets/general_backend.cpp b/src/core/hle/service/am/applets/general_backend.cpp index 71016cce7..4d1df5cbe 100755 --- a/src/core/hle/service/am/applets/general_backend.cpp +++ b/src/core/hle/service/am/applets/general_backend.cpp @@ -37,9 +37,8 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) } } -Auth::Auth(Core::System& system_, LibraryAppletMode applet_mode_, - Core::Frontend::ParentalControlsApplet& frontend_) - : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {} +Auth::Auth(Core::System& system_, Core::Frontend::ParentalControlsApplet& frontend_) + : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} Auth::~Auth() = default; @@ -153,9 +152,8 @@ void Auth::AuthFinished(bool is_successful) { broker.SignalStateChanged(); } -PhotoViewer::PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_, - const Core::Frontend::PhotoViewerApplet& frontend_) - : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {} +PhotoViewer::PhotoViewer(Core::System& system_, const Core::Frontend::PhotoViewerApplet& frontend_) + : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} PhotoViewer::~PhotoViewer() = default; @@ -204,8 +202,8 @@ void PhotoViewer::ViewFinished() { broker.SignalStateChanged(); } -StubApplet::StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_) - : Applet{system_.Kernel()}, id{id_}, applet_mode{applet_mode_}, system{system_} {} +StubApplet::StubApplet(Core::System& system_, AppletId id_) + : Applet{system_.Kernel()}, id{id_}, system{system_} {} StubApplet::~StubApplet() = default; diff --git a/src/core/hle/service/am/applets/general_backend.h b/src/core/hle/service/am/applets/general_backend.h index d9e6d4384..ba76ae3d3 100755 --- a/src/core/hle/service/am/applets/general_backend.h +++ b/src/core/hle/service/am/applets/general_backend.h @@ -20,8 +20,7 @@ enum class AuthAppletType : u32 { class Auth final : public Applet { public: - explicit Auth(Core::System& system_, LibraryAppletMode applet_mode_, - Core::Frontend::ParentalControlsApplet& frontend_); + explicit Auth(Core::System& system_, Core::Frontend::ParentalControlsApplet& frontend_); ~Auth() override; void Initialize() override; @@ -33,7 +32,6 @@ public: void AuthFinished(bool is_successful = true); private: - LibraryAppletMode applet_mode; Core::Frontend::ParentalControlsApplet& frontend; Core::System& system; bool complete = false; @@ -52,8 +50,7 @@ enum class PhotoViewerAppletMode : u8 { class PhotoViewer final : public Applet { public: - explicit PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_, - const Core::Frontend::PhotoViewerApplet& frontend_); + explicit PhotoViewer(Core::System& system_, const Core::Frontend::PhotoViewerApplet& frontend_); ~PhotoViewer() override; void Initialize() override; @@ -65,7 +62,6 @@ public: void ViewFinished(); private: - LibraryAppletMode applet_mode; const Core::Frontend::PhotoViewerApplet& frontend; bool complete = false; PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp; @@ -74,7 +70,7 @@ private: class StubApplet final : public Applet { public: - explicit StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_); + explicit StubApplet(Core::System& system_, AppletId id_); ~StubApplet() override; void Initialize() override; @@ -86,7 +82,6 @@ public: private: AppletId id; - LibraryAppletMode applet_mode; Core::System& system; }; diff --git a/src/core/hle/service/am/applets/profile_select.cpp b/src/core/hle/service/am/applets/profile_select.cpp index ab8b6fcc5..77fba16c7 100755 --- a/src/core/hle/service/am/applets/profile_select.cpp +++ b/src/core/hle/service/am/applets/profile_select.cpp @@ -15,9 +15,9 @@ namespace Service::AM::Applets { constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1}; -ProfileSelect::ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_, +ProfileSelect::ProfileSelect(Core::System& system_, const Core::Frontend::ProfileSelectApplet& frontend_) - : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {} + : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} ProfileSelect::~ProfileSelect() = default; diff --git a/src/core/hle/service/am/applets/profile_select.h b/src/core/hle/service/am/applets/profile_select.h index 90f054030..648d33a24 100755 --- a/src/core/hle/service/am/applets/profile_select.h +++ b/src/core/hle/service/am/applets/profile_select.h @@ -33,7 +33,7 @@ static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has inco class ProfileSelect final : public Applet { public: - explicit ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_, + explicit ProfileSelect(Core::System& system_, const Core::Frontend::ProfileSelectApplet& frontend_); ~ProfileSelect() override; @@ -47,7 +47,6 @@ public: void SelectionComplete(std::optional uuid); private: - LibraryAppletMode applet_mode; const Core::Frontend::ProfileSelectApplet& frontend; UserSelectionConfig config; diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index c3a05de9c..79b209c6b 100755 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp @@ -1,80 +1,93 @@ -// Copyright 2021 yuzu Emulator Project +// Copyright 2018 yuzu emulator team // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include +#include "common/assert.h" #include "common/string_util.h" #include "core/core.h" #include "core/frontend/applets/software_keyboard.h" +#include "core/hle/result.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/software_keyboard.h" namespace Service::AM::Applets { namespace { - -// The maximum number of UTF-16 characters that can be input into the swkbd text field. -constexpr u32 DEFAULT_MAX_TEXT_LENGTH = 500; - -constexpr std::size_t REPLY_BASE_SIZE = sizeof(SwkbdState) + sizeof(SwkbdReplyType); -constexpr std::size_t REPLY_UTF8_SIZE = 0x7D4; -constexpr std::size_t REPLY_UTF16_SIZE = 0x3EC; - -constexpr const char* GetTextCheckResultName(SwkbdTextCheckResult text_check_result) { - switch (text_check_result) { - case SwkbdTextCheckResult::Success: - return "Success"; - case SwkbdTextCheckResult::Failure: - return "Failure"; - case SwkbdTextCheckResult::Confirm: - return "Confirm"; - case SwkbdTextCheckResult::Silent: - return "Silent"; - default: - UNIMPLEMENTED_MSG("Unknown TextCheckResult={}", text_check_result); - return "Unknown"; - } -} - -void SetReplyBase(std::vector& reply, SwkbdState state, SwkbdReplyType reply_type) { - std::memcpy(reply.data(), &state, sizeof(SwkbdState)); - std::memcpy(reply.data() + sizeof(SwkbdState), &reply_type, sizeof(SwkbdReplyType)); -} - +enum class Request : u32 { + Finalize = 0x4, + SetUserWordInfo = 0x6, + SetCustomizeDic = 0x7, + Calc = 0xa, + SetCustomizedDictionaries = 0xb, + UnsetCustomizedDictionaries = 0xc, + UnknownD = 0xd, + UnknownE = 0xe, +}; +constexpr std::size_t SWKBD_INLINE_INIT_SIZE = 0x8; +constexpr std::size_t SWKBD_OUTPUT_BUFFER_SIZE = 0x7D8; +constexpr std::size_t SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE = 0x7D4; +constexpr std::size_t DEFAULT_MAX_LENGTH = 500; +constexpr bool INTERACTIVE_STATUS_OK = false; } // Anonymous namespace +static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters( + KeyboardConfig config, std::u16string initial_text) { + Core::Frontend::SoftwareKeyboardParameters params{}; -SoftwareKeyboard::SoftwareKeyboard(Core::System& system_, LibraryAppletMode applet_mode_, - Core::Frontend::SoftwareKeyboardApplet& frontend_) - : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend{frontend_}, system{system_} {} + params.submit_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( + config.submit_text.data(), config.submit_text.size()); + params.header_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( + config.header_text.data(), config.header_text.size()); + params.sub_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(config.sub_text.data(), + config.sub_text.size()); + params.guide_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(config.guide_text.data(), + config.guide_text.size()); + params.initial_text = std::move(initial_text); + params.max_length = config.length_limit == 0 ? DEFAULT_MAX_LENGTH : config.length_limit; + params.password = static_cast(config.is_password); + params.cursor_at_beginning = static_cast(config.initial_cursor_position); + params.value = static_cast(config.keyset_disable_bitmask); + + return params; +} + +SoftwareKeyboard::SoftwareKeyboard(Core::System& system_, + const Core::Frontend::SoftwareKeyboardApplet& frontend_) + : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} SoftwareKeyboard::~SoftwareKeyboard() = default; void SoftwareKeyboard::Initialize() { + complete = false; + is_inline = false; + initial_text.clear(); + final_data.clear(); + Applet::Initialize(); - LOG_INFO(Service_AM, "Initializing Software Keyboard Applet with LibraryAppletMode={}", - applet_mode); + const auto keyboard_config_storage = broker.PopNormalDataToApplet(); + ASSERT(keyboard_config_storage != nullptr); + const auto& keyboard_config = keyboard_config_storage->GetData(); - LOG_DEBUG(Service_AM, - "Initializing Applet with common_args: arg_version={}, lib_version={}, " - "play_startup_sound={}, size={}, system_tick={}, theme_color={}", - common_args.arguments_version, common_args.library_version, - common_args.play_startup_sound, common_args.size, common_args.system_tick, - common_args.theme_color); - - swkbd_applet_version = SwkbdAppletVersion{common_args.library_version}; - - switch (applet_mode) { - case LibraryAppletMode::AllForeground: - InitializeForeground(); - break; - case LibraryAppletMode::Background: - case LibraryAppletMode::BackgroundIndirectDisplay: - InitializeBackground(applet_mode); - break; - default: - UNREACHABLE_MSG("Invalid LibraryAppletMode={}", applet_mode); - break; + if (keyboard_config.size() == SWKBD_INLINE_INIT_SIZE) { + is_inline = true; + return; } + + ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig)); + std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig)); + + const auto work_buffer_storage = broker.PopNormalDataToApplet(); + ASSERT_OR_EXECUTE(work_buffer_storage != nullptr, { return; }); + const auto& work_buffer = work_buffer_storage->GetData(); + + if (config.initial_string_size == 0) + return; + + std::vector string(config.initial_string_size); + std::memcpy(string.data(), work_buffer.data() + config.initial_string_offset, + string.size() * 2); + initial_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()); } bool SoftwareKeyboard::TransactionComplete() const { @@ -82,996 +95,106 @@ bool SoftwareKeyboard::TransactionComplete() const { } ResultCode SoftwareKeyboard::GetStatus() const { - return status; + return RESULT_SUCCESS; } void SoftwareKeyboard::ExecuteInteractive() { - if (complete) { + if (complete) return; - } - if (is_background) { - ProcessInlineKeyboardRequest(); + const auto storage = broker.PopInteractiveDataToApplet(); + ASSERT(storage != nullptr); + const auto data = storage->GetData(); + if (!is_inline) { + const auto status = static_cast(data[0]); + if (status == INTERACTIVE_STATUS_OK) { + complete = true; + } else { + std::array string; + std::memcpy(string.data(), data.data() + 4, string.size() * 2); + frontend.SendTextCheckDialog( + Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()), + [this] { broker.SignalStateChanged(); }); + } } else { - ProcessTextCheck(); + Request request{}; + std::memcpy(&request, data.data(), sizeof(Request)); + + switch (request) { + case Request::Finalize: + complete = true; + broker.SignalStateChanged(); + break; + case Request::Calc: { + broker.PushNormalDataFromApplet(std::make_shared(system, std::vector{1})); + broker.SignalStateChanged(); + break; + } + default: + UNIMPLEMENTED_MSG("Request {:X} is not implemented", request); + break; + } } } void SoftwareKeyboard::Execute() { if (complete) { + broker.PushNormalDataFromApplet(std::make_shared(system, std::move(final_data))); + broker.SignalStateChanged(); return; } - if (is_background) { - return; - } - - ShowNormalKeyboard(); -} - -void SoftwareKeyboard::SubmitTextNormal(SwkbdResult result, std::u16string submitted_text) { - if (complete) { - return; - } - - if (swkbd_config_common.use_text_check && result == SwkbdResult::Ok) { - SubmitForTextCheck(submitted_text); - } else { - SubmitNormalOutputAndExit(result, submitted_text); + const auto parameters = ConvertToFrontendParameters(config, initial_text); + if (!is_inline) { + frontend.RequestText( + [this](std::optional text) { WriteText(std::move(text)); }, parameters); } } -void SoftwareKeyboard::SubmitTextInline(SwkbdReplyType reply_type, std::u16string submitted_text, - s32 cursor_position) { - if (complete) { - return; - } +void SoftwareKeyboard::WriteText(std::optional text) { + std::vector output_main(SWKBD_OUTPUT_BUFFER_SIZE); - current_text = std::move(submitted_text); - current_cursor_position = cursor_position; + if (text.has_value()) { + std::vector output_sub(SWKBD_OUTPUT_BUFFER_SIZE); - if (inline_use_utf8) { - switch (reply_type) { - case SwkbdReplyType::ChangedString: - reply_type = SwkbdReplyType::ChangedStringUtf8; - break; - case SwkbdReplyType::MovedCursor: - reply_type = SwkbdReplyType::MovedCursorUtf8; - break; - case SwkbdReplyType::DecidedEnter: - reply_type = SwkbdReplyType::DecidedEnterUtf8; - break; - default: - break; + if (config.utf_8) { + const u64 size = text->size() + sizeof(u64); + const auto new_text = Common::UTF16ToUTF8(*text); + + std::memcpy(output_sub.data(), &size, sizeof(u64)); + std::memcpy(output_sub.data() + 8, new_text.data(), + std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 8)); + + output_main[0] = INTERACTIVE_STATUS_OK; + std::memcpy(output_main.data() + 4, new_text.data(), + std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 4)); + } else { + const u64 size = text->size() * 2 + sizeof(u64); + std::memcpy(output_sub.data(), &size, sizeof(u64)); + std::memcpy(output_sub.data() + 8, text->data(), + std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 8)); + + output_main[0] = INTERACTIVE_STATUS_OK; + std::memcpy(output_main.data() + 4, text->data(), + std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4)); } - } - if (use_changed_string_v2) { - switch (reply_type) { - case SwkbdReplyType::ChangedString: - reply_type = SwkbdReplyType::ChangedStringV2; - break; - case SwkbdReplyType::ChangedStringUtf8: - reply_type = SwkbdReplyType::ChangedStringUtf8V2; - break; - default: - break; + complete = !config.text_check; + final_data = output_main; + + if (complete) { + broker.PushNormalDataFromApplet( + std::make_shared(system, std::move(output_main))); + broker.SignalStateChanged(); + } else { + broker.PushInteractiveDataFromApplet( + std::make_shared(system, std::move(output_sub))); } - } - - if (use_moved_cursor_v2) { - switch (reply_type) { - case SwkbdReplyType::MovedCursor: - reply_type = SwkbdReplyType::MovedCursorV2; - break; - case SwkbdReplyType::MovedCursorUtf8: - reply_type = SwkbdReplyType::MovedCursorUtf8V2; - break; - default: - break; - } - } - - SendReply(reply_type); -} - -void SoftwareKeyboard::InitializeForeground() { - LOG_INFO(Service_AM, "Initializing Normal Software Keyboard Applet."); - - is_background = false; - - const auto swkbd_config_storage = broker.PopNormalDataToApplet(); - ASSERT(swkbd_config_storage != nullptr); - - const auto& swkbd_config_data = swkbd_config_storage->GetData(); - ASSERT(swkbd_config_data.size() >= sizeof(SwkbdConfigCommon)); - - std::memcpy(&swkbd_config_common, swkbd_config_data.data(), sizeof(SwkbdConfigCommon)); - - switch (swkbd_applet_version) { - case SwkbdAppletVersion::Version5: - case SwkbdAppletVersion::Version65542: - ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigOld)); - std::memcpy(&swkbd_config_old, swkbd_config_data.data() + sizeof(SwkbdConfigCommon), - sizeof(SwkbdConfigOld)); - break; - case SwkbdAppletVersion::Version196615: - case SwkbdAppletVersion::Version262152: - case SwkbdAppletVersion::Version327689: - ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigOld2)); - std::memcpy(&swkbd_config_old2, swkbd_config_data.data() + sizeof(SwkbdConfigCommon), - sizeof(SwkbdConfigOld2)); - break; - case SwkbdAppletVersion::Version393227: - case SwkbdAppletVersion::Version524301: - ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigNew)); - std::memcpy(&swkbd_config_new, swkbd_config_data.data() + sizeof(SwkbdConfigCommon), - sizeof(SwkbdConfigNew)); - break; - default: - UNIMPLEMENTED_MSG("Unknown SwkbdConfig revision={} with size={}", swkbd_applet_version, - swkbd_config_data.size()); - ASSERT(swkbd_config_data.size() >= sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigNew)); - std::memcpy(&swkbd_config_new, swkbd_config_data.data() + sizeof(SwkbdConfigCommon), - sizeof(SwkbdConfigNew)); - break; - } - - const auto work_buffer_storage = broker.PopNormalDataToApplet(); - ASSERT(work_buffer_storage != nullptr); - - if (swkbd_config_common.initial_string_length == 0) { - InitializeFrontendKeyboard(); - return; - } - - const auto& work_buffer = work_buffer_storage->GetData(); - - std::vector initial_string(swkbd_config_common.initial_string_length); - - std::memcpy(initial_string.data(), - work_buffer.data() + swkbd_config_common.initial_string_offset, - swkbd_config_common.initial_string_length * sizeof(char16_t)); - - initial_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(initial_string.data(), - initial_string.size()); - - LOG_DEBUG(Service_AM, "\nInitial Text: {}", Common::UTF16ToUTF8(initial_text)); - - InitializeFrontendKeyboard(); -} - -void SoftwareKeyboard::InitializeBackground(LibraryAppletMode applet_mode) { - LOG_INFO(Service_AM, "Initializing Inline Software Keyboard Applet."); - - is_background = true; - - const auto swkbd_inline_initialize_arg_storage = broker.PopNormalDataToApplet(); - ASSERT(swkbd_inline_initialize_arg_storage != nullptr); - - const auto& swkbd_inline_initialize_arg = swkbd_inline_initialize_arg_storage->GetData(); - ASSERT(swkbd_inline_initialize_arg.size() == sizeof(SwkbdInitializeArg)); - - std::memcpy(&swkbd_initialize_arg, swkbd_inline_initialize_arg.data(), - swkbd_inline_initialize_arg.size()); - - if (swkbd_initialize_arg.library_applet_mode_flag) { - ASSERT(applet_mode == LibraryAppletMode::Background); } else { - ASSERT(applet_mode == LibraryAppletMode::BackgroundIndirectDisplay); + output_main[0] = 1; + complete = true; + broker.PushNormalDataFromApplet(std::make_shared(system, std::move(output_main))); + broker.SignalStateChanged(); } } - -void SoftwareKeyboard::ProcessTextCheck() { - const auto text_check_storage = broker.PopInteractiveDataToApplet(); - ASSERT(text_check_storage != nullptr); - - const auto& text_check_data = text_check_storage->GetData(); - ASSERT(text_check_data.size() == sizeof(SwkbdTextCheck)); - - SwkbdTextCheck swkbd_text_check; - - std::memcpy(&swkbd_text_check, text_check_data.data(), sizeof(SwkbdTextCheck)); - - std::u16string text_check_message = Common::UTF16StringFromFixedZeroTerminatedBuffer( - swkbd_text_check.text_check_message.data(), swkbd_text_check.text_check_message.size()); - - LOG_INFO(Service_AM, "\nTextCheckResult: {}\nTextCheckMessage: {}", - GetTextCheckResultName(swkbd_text_check.text_check_result), - Common::UTF16ToUTF8(text_check_message)); - - switch (swkbd_text_check.text_check_result) { - case SwkbdTextCheckResult::Success: - SubmitNormalOutputAndExit(SwkbdResult::Ok, current_text); - break; - case SwkbdTextCheckResult::Failure: - ShowTextCheckDialog(SwkbdTextCheckResult::Failure, text_check_message); - break; - case SwkbdTextCheckResult::Confirm: - ShowTextCheckDialog(SwkbdTextCheckResult::Confirm, text_check_message); - break; - case SwkbdTextCheckResult::Silent: - default: - break; - } -} - -void SoftwareKeyboard::ProcessInlineKeyboardRequest() { - const auto request_data_storage = broker.PopInteractiveDataToApplet(); - ASSERT(request_data_storage != nullptr); - - const auto& request_data = request_data_storage->GetData(); - ASSERT(request_data.size() >= sizeof(SwkbdRequestCommand)); - - SwkbdRequestCommand request_command; - - std::memcpy(&request_command, request_data.data(), sizeof(SwkbdRequestCommand)); - - switch (request_command) { - case SwkbdRequestCommand::Finalize: - RequestFinalize(request_data); - break; - case SwkbdRequestCommand::SetUserWordInfo: - RequestSetUserWordInfo(request_data); - break; - case SwkbdRequestCommand::SetCustomizeDic: - RequestSetCustomizeDic(request_data); - break; - case SwkbdRequestCommand::Calc: - RequestCalc(request_data); - break; - case SwkbdRequestCommand::SetCustomizedDictionaries: - RequestSetCustomizedDictionaries(request_data); - break; - case SwkbdRequestCommand::UnsetCustomizedDictionaries: - RequestUnsetCustomizedDictionaries(request_data); - break; - case SwkbdRequestCommand::SetChangedStringV2Flag: - RequestSetChangedStringV2Flag(request_data); - break; - case SwkbdRequestCommand::SetMovedCursorV2Flag: - RequestSetMovedCursorV2Flag(request_data); - break; - default: - UNIMPLEMENTED_MSG("Unknown SwkbdRequestCommand={}", request_command); - break; - } -} - -void SoftwareKeyboard::SubmitNormalOutputAndExit(SwkbdResult result, - std::u16string submitted_text) { - std::vector out_data(sizeof(SwkbdResult) + STRING_BUFFER_SIZE); - - if (swkbd_config_common.use_utf8) { - std::string utf8_submitted_text = Common::UTF16ToUTF8(submitted_text); - - LOG_DEBUG(Service_AM, "\nSwkbdResult: {}\nUTF-8 Submitted Text: {}", result, - utf8_submitted_text); - - std::memcpy(out_data.data(), &result, sizeof(SwkbdResult)); - std::memcpy(out_data.data() + sizeof(SwkbdResult), utf8_submitted_text.data(), - utf8_submitted_text.size()); - } else { - LOG_DEBUG(Service_AM, "\nSwkbdResult: {}\nUTF-16 Submitted Text: {}", result, - Common::UTF16ToUTF8(submitted_text)); - - std::memcpy(out_data.data(), &result, sizeof(SwkbdResult)); - std::memcpy(out_data.data() + sizeof(SwkbdResult), submitted_text.data(), - submitted_text.size() * sizeof(char16_t)); - } - - broker.PushNormalDataFromApplet(std::make_shared(system, std::move(out_data))); - - ExitKeyboard(); -} - -void SoftwareKeyboard::SubmitForTextCheck(std::u16string submitted_text) { - current_text = std::move(submitted_text); - - std::vector out_data(sizeof(u64) + STRING_BUFFER_SIZE); - - if (swkbd_config_common.use_utf8) { - std::string utf8_submitted_text = Common::UTF16ToUTF8(current_text); - const u64 buffer_size = sizeof(u64) + utf8_submitted_text.size(); - - LOG_DEBUG(Service_AM, "\nBuffer Size: {}\nUTF-8 Submitted Text: {}", buffer_size, - utf8_submitted_text); - - std::memcpy(out_data.data(), &buffer_size, sizeof(u64)); - std::memcpy(out_data.data() + sizeof(u64), utf8_submitted_text.data(), - utf8_submitted_text.size()); - } else { - const u64 buffer_size = sizeof(u64) + current_text.size() * sizeof(char16_t); - - LOG_DEBUG(Service_AM, "\nBuffer Size: {}\nUTF-16 Submitted Text: {}", buffer_size, - Common::UTF16ToUTF8(current_text)); - - std::memcpy(out_data.data(), &buffer_size, sizeof(u64)); - std::memcpy(out_data.data() + sizeof(u64), current_text.data(), - current_text.size() * sizeof(char16_t)); - } - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(out_data))); -} - -void SoftwareKeyboard::SendReply(SwkbdReplyType reply_type) { - switch (reply_type) { - case SwkbdReplyType::FinishedInitialize: - ReplyFinishedInitialize(); - break; - case SwkbdReplyType::Default: - ReplyDefault(); - break; - case SwkbdReplyType::ChangedString: - ReplyChangedString(); - break; - case SwkbdReplyType::MovedCursor: - ReplyMovedCursor(); - break; - case SwkbdReplyType::MovedTab: - ReplyMovedTab(); - break; - case SwkbdReplyType::DecidedEnter: - ReplyDecidedEnter(); - break; - case SwkbdReplyType::DecidedCancel: - ReplyDecidedCancel(); - break; - case SwkbdReplyType::ChangedStringUtf8: - ReplyChangedStringUtf8(); - break; - case SwkbdReplyType::MovedCursorUtf8: - ReplyMovedCursorUtf8(); - break; - case SwkbdReplyType::DecidedEnterUtf8: - ReplyDecidedEnterUtf8(); - break; - case SwkbdReplyType::UnsetCustomizeDic: - ReplyUnsetCustomizeDic(); - break; - case SwkbdReplyType::ReleasedUserWordInfo: - ReplyReleasedUserWordInfo(); - break; - case SwkbdReplyType::UnsetCustomizedDictionaries: - ReplyUnsetCustomizedDictionaries(); - break; - case SwkbdReplyType::ChangedStringV2: - ReplyChangedStringV2(); - break; - case SwkbdReplyType::MovedCursorV2: - ReplyMovedCursorV2(); - break; - case SwkbdReplyType::ChangedStringUtf8V2: - ReplyChangedStringUtf8V2(); - break; - case SwkbdReplyType::MovedCursorUtf8V2: - ReplyMovedCursorUtf8V2(); - break; - default: - UNIMPLEMENTED_MSG("Unknown SwkbdReplyType={}", reply_type); - ReplyDefault(); - break; - } -} - -void SoftwareKeyboard::ChangeState(SwkbdState state) { - swkbd_state = state; - - ReplyDefault(); -} - -void SoftwareKeyboard::InitializeFrontendKeyboard() { - if (is_background) { - const auto& appear_arg = swkbd_calc_arg.appear_arg; - - std::u16string ok_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( - appear_arg.ok_text.data(), appear_arg.ok_text.size()); - - const u32 max_text_length = - appear_arg.max_text_length > 0 && appear_arg.max_text_length <= DEFAULT_MAX_TEXT_LENGTH - ? appear_arg.max_text_length - : DEFAULT_MAX_TEXT_LENGTH; - - const u32 min_text_length = - appear_arg.min_text_length <= max_text_length ? appear_arg.min_text_length : 0; - - const s32 initial_cursor_position = - current_cursor_position > 0 ? current_cursor_position : 0; - - const auto text_draw_type = - max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box; - - Core::Frontend::KeyboardInitializeParameters initialize_parameters{ - .ok_text{ok_text}, - .header_text{}, - .sub_text{}, - .guide_text{}, - .initial_text{current_text}, - .max_text_length{max_text_length}, - .min_text_length{min_text_length}, - .initial_cursor_position{initial_cursor_position}, - .type{appear_arg.type}, - .password_mode{SwkbdPasswordMode::Disabled}, - .text_draw_type{text_draw_type}, - .key_disable_flags{appear_arg.key_disable_flags}, - .use_blur_background{false}, - .enable_backspace_button{swkbd_calc_arg.enable_backspace_button}, - .enable_return_button{appear_arg.enable_return_button}, - .disable_cancel_button{appear_arg.disable_cancel_button}, - }; - - frontend.InitializeKeyboard( - true, std::move(initialize_parameters), {}, - [this](SwkbdReplyType reply_type, std::u16string submitted_text, s32 cursor_position) { - SubmitTextInline(reply_type, submitted_text, cursor_position); - }); - } else { - std::u16string ok_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( - swkbd_config_common.ok_text.data(), swkbd_config_common.ok_text.size()); - - std::u16string header_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( - swkbd_config_common.header_text.data(), swkbd_config_common.header_text.size()); - - std::u16string sub_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( - swkbd_config_common.sub_text.data(), swkbd_config_common.sub_text.size()); - - std::u16string guide_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( - swkbd_config_common.guide_text.data(), swkbd_config_common.guide_text.size()); - - const u32 max_text_length = - swkbd_config_common.max_text_length > 0 && - swkbd_config_common.max_text_length <= DEFAULT_MAX_TEXT_LENGTH - ? swkbd_config_common.max_text_length - : DEFAULT_MAX_TEXT_LENGTH; - - const u32 min_text_length = swkbd_config_common.min_text_length <= max_text_length - ? swkbd_config_common.min_text_length - : 0; - - const s32 initial_cursor_position = [this] { - switch (swkbd_config_common.initial_cursor_position) { - case SwkbdInitialCursorPosition::Start: - default: - return 0; - case SwkbdInitialCursorPosition::End: - return static_cast(initial_text.size()); - } - }(); - - const auto text_draw_type = [this, max_text_length] { - switch (swkbd_config_common.text_draw_type) { - case SwkbdTextDrawType::Line: - default: - return max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box; - case SwkbdTextDrawType::Box: - case SwkbdTextDrawType::DownloadCode: - return swkbd_config_common.text_draw_type; - } - }(); - - const auto enable_return_button = text_draw_type == SwkbdTextDrawType::Box - ? swkbd_config_common.enable_return_button - : false; - - const auto disable_cancel_button = swkbd_applet_version >= SwkbdAppletVersion::Version393227 - ? swkbd_config_new.disable_cancel_button - : false; - - Core::Frontend::KeyboardInitializeParameters initialize_parameters{ - .ok_text{ok_text}, - .header_text{header_text}, - .sub_text{sub_text}, - .guide_text{guide_text}, - .initial_text{initial_text}, - .max_text_length{max_text_length}, - .min_text_length{min_text_length}, - .initial_cursor_position{initial_cursor_position}, - .type{swkbd_config_common.type}, - .password_mode{swkbd_config_common.password_mode}, - .text_draw_type{text_draw_type}, - .key_disable_flags{swkbd_config_common.key_disable_flags}, - .use_blur_background{swkbd_config_common.use_blur_background}, - .enable_backspace_button{true}, - .enable_return_button{enable_return_button}, - .disable_cancel_button{disable_cancel_button}, - }; - - frontend.InitializeKeyboard(false, std::move(initialize_parameters), - [this](SwkbdResult result, std::u16string submitted_text) { - SubmitTextNormal(result, submitted_text); - }, - {}); - } -} - -void SoftwareKeyboard::ShowNormalKeyboard() { - frontend.ShowNormalKeyboard(); -} - -void SoftwareKeyboard::ShowTextCheckDialog(SwkbdTextCheckResult text_check_result, - std::u16string text_check_message) { - frontend.ShowTextCheckDialog(text_check_result, text_check_message); -} - -void SoftwareKeyboard::ShowInlineKeyboard() { - if (swkbd_state != SwkbdState::InitializedIsHidden) { - return; - } - - ChangeState(SwkbdState::InitializedIsAppearing); - - const auto& appear_arg = swkbd_calc_arg.appear_arg; - - const u32 max_text_length = - appear_arg.max_text_length > 0 && appear_arg.max_text_length <= DEFAULT_MAX_TEXT_LENGTH - ? appear_arg.max_text_length - : DEFAULT_MAX_TEXT_LENGTH; - - const u32 min_text_length = - appear_arg.min_text_length <= max_text_length ? appear_arg.min_text_length : 0; - - Core::Frontend::InlineAppearParameters appear_parameters{ - .max_text_length{max_text_length}, - .min_text_length{min_text_length}, - .key_top_scale_x{swkbd_calc_arg.key_top_scale_x}, - .key_top_scale_y{swkbd_calc_arg.key_top_scale_y}, - .key_top_translate_x{swkbd_calc_arg.key_top_translate_x}, - .key_top_translate_y{swkbd_calc_arg.key_top_translate_y}, - .type{appear_arg.type}, - .key_disable_flags{appear_arg.key_disable_flags}, - .key_top_as_floating{swkbd_calc_arg.key_top_as_floating}, - .enable_backspace_button{swkbd_calc_arg.enable_backspace_button}, - .enable_return_button{appear_arg.enable_return_button}, - .disable_cancel_button{appear_arg.disable_cancel_button}, - }; - - frontend.ShowInlineKeyboard(std::move(appear_parameters)); - - ChangeState(SwkbdState::InitializedIsShown); -} - -void SoftwareKeyboard::HideInlineKeyboard() { - if (swkbd_state != SwkbdState::InitializedIsShown) { - return; - } - - ChangeState(SwkbdState::InitializedIsDisappearing); - - frontend.HideInlineKeyboard(); - - ChangeState(SwkbdState::InitializedIsHidden); -} - -void SoftwareKeyboard::InlineTextChanged() { - Core::Frontend::InlineTextParameters text_parameters{ - .input_text{current_text}, - .cursor_position{current_cursor_position}, - }; - - frontend.InlineTextChanged(std::move(text_parameters)); -} - -void SoftwareKeyboard::ExitKeyboard() { - complete = true; - status = RESULT_SUCCESS; - - frontend.ExitKeyboard(); - - broker.SignalStateChanged(); -} - -// Inline Software Keyboard Requests - -void SoftwareKeyboard::RequestFinalize(const std::vector& request_data) { - LOG_DEBUG(Service_AM, "Processing Request: Finalize"); - - ChangeState(SwkbdState::NotInitialized); - - ExitKeyboard(); -} - -void SoftwareKeyboard::RequestSetUserWordInfo(const std::vector& request_data) { - LOG_WARNING(Service_AM, "SetUserWordInfo is not implemented."); -} - -void SoftwareKeyboard::RequestSetCustomizeDic(const std::vector& request_data) { - LOG_WARNING(Service_AM, "SetCustomizeDic is not implemented."); -} - -void SoftwareKeyboard::RequestCalc(const std::vector& request_data) { - LOG_DEBUG(Service_AM, "Processing Request: Calc"); - - ASSERT(request_data.size() == sizeof(SwkbdRequestCommand) + sizeof(SwkbdCalcArg)); - - std::memcpy(&swkbd_calc_arg, request_data.data() + sizeof(SwkbdRequestCommand), - sizeof(SwkbdCalcArg)); - - if (swkbd_calc_arg.flags.set_input_text) { - current_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( - swkbd_calc_arg.input_text.data(), swkbd_calc_arg.input_text.size()); - } - - if (swkbd_calc_arg.flags.set_cursor_position) { - current_cursor_position = swkbd_calc_arg.cursor_position; - } - - if (swkbd_calc_arg.flags.set_utf8_mode) { - inline_use_utf8 = swkbd_calc_arg.utf8_mode; - } - - if (swkbd_state <= SwkbdState::InitializedIsHidden && - swkbd_calc_arg.flags.unset_customize_dic) { - ReplyUnsetCustomizeDic(); - } - - if (swkbd_state <= SwkbdState::InitializedIsHidden && - swkbd_calc_arg.flags.unset_user_word_info) { - ReplyReleasedUserWordInfo(); - } - - if (swkbd_state == SwkbdState::NotInitialized && swkbd_calc_arg.flags.set_initialize_arg) { - InitializeFrontendKeyboard(); - - ChangeState(SwkbdState::InitializedIsHidden); - - ReplyFinishedInitialize(); - } - - if (!swkbd_calc_arg.flags.set_initialize_arg && - (swkbd_calc_arg.flags.set_input_text || swkbd_calc_arg.flags.set_cursor_position)) { - InlineTextChanged(); - } - - if (swkbd_state == SwkbdState::InitializedIsHidden && swkbd_calc_arg.flags.appear) { - ShowInlineKeyboard(); - return; - } - - if (swkbd_state == SwkbdState::InitializedIsShown && swkbd_calc_arg.flags.disappear) { - HideInlineKeyboard(); - return; - } -} - -void SoftwareKeyboard::RequestSetCustomizedDictionaries(const std::vector& request_data) { - LOG_WARNING(Service_AM, "SetCustomizedDictionaries is not implemented."); -} - -void SoftwareKeyboard::RequestUnsetCustomizedDictionaries(const std::vector& request_data) { - LOG_WARNING(Service_AM, "(STUBBED) Processing Request: UnsetCustomizedDictionaries"); - - ReplyUnsetCustomizedDictionaries(); -} - -void SoftwareKeyboard::RequestSetChangedStringV2Flag(const std::vector& request_data) { - LOG_DEBUG(Service_AM, "Processing Request: SetChangedStringV2Flag"); - - ASSERT(request_data.size() == sizeof(SwkbdRequestCommand) + 1); - - std::memcpy(&use_changed_string_v2, request_data.data() + sizeof(SwkbdRequestCommand), 1); -} - -void SoftwareKeyboard::RequestSetMovedCursorV2Flag(const std::vector& request_data) { - LOG_DEBUG(Service_AM, "Processing Request: SetMovedCursorV2Flag"); - - ASSERT(request_data.size() == sizeof(SwkbdRequestCommand) + 1); - - std::memcpy(&use_moved_cursor_v2, request_data.data() + sizeof(SwkbdRequestCommand), 1); -} - -// Inline Software Keyboard Replies - -void SoftwareKeyboard::ReplyFinishedInitialize() { - LOG_DEBUG(Service_AM, "Sending Reply: FinishedInitialize"); - - std::vector reply(REPLY_BASE_SIZE + 1); - - SetReplyBase(reply, swkbd_state, SwkbdReplyType::FinishedInitialize); - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(reply))); -} - -void SoftwareKeyboard::ReplyDefault() { - LOG_DEBUG(Service_AM, "Sending Reply: Default"); - - std::vector reply(REPLY_BASE_SIZE); - - SetReplyBase(reply, swkbd_state, SwkbdReplyType::Default); - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(reply))); -} - -void SoftwareKeyboard::ReplyChangedString() { - LOG_DEBUG(Service_AM, "Sending Reply: ChangedString"); - - std::vector reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg)); - - SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedString); - - const SwkbdChangedStringArg changed_string_arg{ - .text_length{static_cast(current_text.size())}, - .dictionary_start_cursor_position{-1}, - .dictionary_end_cursor_position{-1}, - .cursor_position{current_cursor_position}, - }; - - std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(), - current_text.size() * sizeof(char16_t)); - std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &changed_string_arg, - sizeof(SwkbdChangedStringArg)); - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(reply))); -} - -void SoftwareKeyboard::ReplyMovedCursor() { - LOG_DEBUG(Service_AM, "Sending Reply: MovedCursor"); - - std::vector reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg)); - - SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursor); - - const SwkbdMovedCursorArg moved_cursor_arg{ - .text_length{static_cast(current_text.size())}, - .cursor_position{current_cursor_position}, - }; - - std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(), - current_text.size() * sizeof(char16_t)); - std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_cursor_arg, - sizeof(SwkbdMovedCursorArg)); - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(reply))); -} - -void SoftwareKeyboard::ReplyMovedTab() { - LOG_DEBUG(Service_AM, "Sending Reply: MovedTab"); - - std::vector reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedTabArg)); - - SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedTab); - - const SwkbdMovedTabArg moved_tab_arg{ - .text_length{static_cast(current_text.size())}, - .cursor_position{current_cursor_position}, - }; - - std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(), - current_text.size() * sizeof(char16_t)); - std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_tab_arg, - sizeof(SwkbdMovedTabArg)); - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(reply))); -} - -void SoftwareKeyboard::ReplyDecidedEnter() { - LOG_DEBUG(Service_AM, "Sending Reply: DecidedEnter"); - - std::vector reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdDecidedEnterArg)); - - SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedEnter); - - const SwkbdDecidedEnterArg decided_enter_arg{ - .text_length{static_cast(current_text.size())}, - }; - - std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(), - current_text.size() * sizeof(char16_t)); - std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &decided_enter_arg, - sizeof(SwkbdDecidedEnterArg)); - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(reply))); - - HideInlineKeyboard(); -} - -void SoftwareKeyboard::ReplyDecidedCancel() { - LOG_DEBUG(Service_AM, "Sending Reply: DecidedCancel"); - - std::vector reply(REPLY_BASE_SIZE); - - SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedCancel); - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(reply))); - - HideInlineKeyboard(); -} - -void SoftwareKeyboard::ReplyChangedStringUtf8() { - LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringUtf8"); - - std::vector reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg)); - - SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedStringUtf8); - - std::string utf8_current_text = Common::UTF16ToUTF8(current_text); - - const SwkbdChangedStringArg changed_string_arg{ - .text_length{static_cast(current_text.size())}, - .dictionary_start_cursor_position{-1}, - .dictionary_end_cursor_position{-1}, - .cursor_position{current_cursor_position}, - }; - - std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size()); - std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &changed_string_arg, - sizeof(SwkbdChangedStringArg)); - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(reply))); -} - -void SoftwareKeyboard::ReplyMovedCursorUtf8() { - LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorUtf8"); - - std::vector reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg)); - - SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursorUtf8); - - std::string utf8_current_text = Common::UTF16ToUTF8(current_text); - - const SwkbdMovedCursorArg moved_cursor_arg{ - .text_length{static_cast(current_text.size())}, - .cursor_position{current_cursor_position}, - }; - - std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size()); - std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &moved_cursor_arg, - sizeof(SwkbdMovedCursorArg)); - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(reply))); -} - -void SoftwareKeyboard::ReplyDecidedEnterUtf8() { - LOG_DEBUG(Service_AM, "Sending Reply: DecidedEnterUtf8"); - - std::vector reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdDecidedEnterArg)); - - SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedEnterUtf8); - - std::string utf8_current_text = Common::UTF16ToUTF8(current_text); - - const SwkbdDecidedEnterArg decided_enter_arg{ - .text_length{static_cast(current_text.size())}, - }; - - std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size()); - std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &decided_enter_arg, - sizeof(SwkbdDecidedEnterArg)); - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(reply))); - - HideInlineKeyboard(); -} - -void SoftwareKeyboard::ReplyUnsetCustomizeDic() { - LOG_DEBUG(Service_AM, "Sending Reply: UnsetCustomizeDic"); - - std::vector reply(REPLY_BASE_SIZE); - - SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizeDic); - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(reply))); -} - -void SoftwareKeyboard::ReplyReleasedUserWordInfo() { - LOG_DEBUG(Service_AM, "Sending Reply: ReleasedUserWordInfo"); - - std::vector reply(REPLY_BASE_SIZE); - - SetReplyBase(reply, swkbd_state, SwkbdReplyType::ReleasedUserWordInfo); - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(reply))); -} - -void SoftwareKeyboard::ReplyUnsetCustomizedDictionaries() { - LOG_DEBUG(Service_AM, "Sending Reply: UnsetCustomizedDictionaries"); - - std::vector reply(REPLY_BASE_SIZE); - - SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizedDictionaries); - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(reply))); -} - -void SoftwareKeyboard::ReplyChangedStringV2() { - LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringV2"); - - std::vector reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg) + 1); - - SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedStringV2); - - const SwkbdChangedStringArg changed_string_arg{ - .text_length{static_cast(current_text.size())}, - .dictionary_start_cursor_position{-1}, - .dictionary_end_cursor_position{-1}, - .cursor_position{current_cursor_position}, - }; - - constexpr u8 flag = 0; - - std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(), - current_text.size() * sizeof(char16_t)); - std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &changed_string_arg, - sizeof(SwkbdChangedStringArg)); - std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg), - &flag, 1); - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(reply))); -} - -void SoftwareKeyboard::ReplyMovedCursorV2() { - LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorV2"); - - std::vector reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg) + 1); - - SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursorV2); - - const SwkbdMovedCursorArg moved_cursor_arg{ - .text_length{static_cast(current_text.size())}, - .cursor_position{current_cursor_position}, - }; - - constexpr u8 flag = 0; - - std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(), - current_text.size() * sizeof(char16_t)); - std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_cursor_arg, - sizeof(SwkbdMovedCursorArg)); - std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg), - &flag, 1); - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(reply))); -} - -void SoftwareKeyboard::ReplyChangedStringUtf8V2() { - LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringUtf8V2"); - - std::vector reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg) + 1); - - SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedStringUtf8V2); - - std::string utf8_current_text = Common::UTF16ToUTF8(current_text); - - const SwkbdChangedStringArg changed_string_arg{ - .text_length{static_cast(current_text.size())}, - .dictionary_start_cursor_position{-1}, - .dictionary_end_cursor_position{-1}, - .cursor_position{current_cursor_position}, - }; - - constexpr u8 flag = 0; - - std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size()); - std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &changed_string_arg, - sizeof(SwkbdChangedStringArg)); - std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg), - &flag, 1); - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(reply))); -} - -void SoftwareKeyboard::ReplyMovedCursorUtf8V2() { - LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorUtf8V2"); - - std::vector reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg) + 1); - - SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursorUtf8V2); - - std::string utf8_current_text = Common::UTF16ToUTF8(current_text); - - const SwkbdMovedCursorArg moved_cursor_arg{ - .text_length{static_cast(current_text.size())}, - .cursor_position{current_cursor_position}, - }; - - constexpr u8 flag = 0; - - std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size()); - std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &moved_cursor_arg, - sizeof(SwkbdMovedCursorArg)); - std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg), - &flag, 1); - - broker.PushInteractiveDataFromApplet(std::make_shared(system, std::move(reply))); -} - } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h index 85aeb4eb1..1d260fef8 100755 --- a/src/core/hle/service/am/applets/software_keyboard.h +++ b/src/core/hle/service/am/applets/software_keyboard.h @@ -1,14 +1,20 @@ -// Copyright 2021 yuzu Emulator Project +// Copyright 2018 yuzu emulator team // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #pragma once +#include +#include +#include + #include "common/common_funcs.h" #include "common/common_types.h" -#include "core/hle/result.h" +#include "common/swap.h" +#include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/applets.h" -#include "core/hle/service/am/applets/software_keyboard_types.h" + +union ResultCode; namespace Core { class System; @@ -16,10 +22,45 @@ class System; namespace Service::AM::Applets { +enum class KeysetDisable : u32 { + Space = 0x02, + Address = 0x04, + Percent = 0x08, + Slashes = 0x10, + Numbers = 0x40, + DownloadCode = 0x80, +}; + +struct KeyboardConfig { + INSERT_PADDING_BYTES(4); + std::array submit_text; + u16_le left_symbol_key; + u16_le right_symbol_key; + INSERT_PADDING_BYTES(1); + KeysetDisable keyset_disable_bitmask; + u32_le initial_cursor_position; + std::array header_text; + std::array sub_text; + std::array guide_text; + u32_le length_limit; + INSERT_PADDING_BYTES(4); + u32_le is_password; + INSERT_PADDING_BYTES(5); + bool utf_8; + bool draw_background; + u32_le initial_string_offset; + u32_le initial_string_size; + u32_le user_dictionary_offset; + u32_le user_dictionary_size; + bool text_check; + u64_le text_check_callback; +}; +static_assert(sizeof(KeyboardConfig) == 0x3E0, "KeyboardConfig has incorrect size."); + class SoftwareKeyboard final : public Applet { public: - explicit SoftwareKeyboard(Core::System& system_, LibraryAppletMode applet_mode_, - Core::Frontend::SoftwareKeyboardApplet& frontend_); + explicit SoftwareKeyboard(Core::System& system_, + const Core::Frontend::SoftwareKeyboardApplet& frontend_); ~SoftwareKeyboard() override; void Initialize() override; @@ -29,139 +70,17 @@ public: void ExecuteInteractive() override; void Execute() override; - /** - * Submits the input text to the application. - * If text checking is enabled, the application will verify the input text. - * If use_utf8 is enabled, the input text will be converted to UTF-8 prior to being submitted. - * This should only be used by the normal software keyboard. - * - * @param result SwkbdResult enum - * @param submitted_text UTF-16 encoded string - */ - void SubmitTextNormal(SwkbdResult result, std::u16string submitted_text); - - /** - * Submits the input text to the application. - * If utf8_mode is enabled, the input text will be converted to UTF-8 prior to being submitted. - * This should only be used by the inline software keyboard. - * - * @param reply_type SwkbdReplyType enum - * @param submitted_text UTF-16 encoded string - * @param cursor_position The current position of the text cursor - */ - void SubmitTextInline(SwkbdReplyType reply_type, std::u16string submitted_text, - s32 cursor_position); + void WriteText(std::optional text); private: - /// Initializes the normal software keyboard. - void InitializeForeground(); + const Core::Frontend::SoftwareKeyboardApplet& frontend; - /// Initializes the inline software keyboard. - void InitializeBackground(LibraryAppletMode applet_mode); - - /// Processes the text check sent by the application. - void ProcessTextCheck(); - - /// Processes the inline software keyboard request command sent by the application. - void ProcessInlineKeyboardRequest(); - - /// Submits the input text and exits the applet. - void SubmitNormalOutputAndExit(SwkbdResult result, std::u16string submitted_text); - - /// Submits the input text for text checking. - void SubmitForTextCheck(std::u16string submitted_text); - - /// Sends a reply to the application after processing a request command. - void SendReply(SwkbdReplyType reply_type); - - /// Changes the inline keyboard state. - void ChangeState(SwkbdState state); - - /** - * Signals the frontend to initialize the software keyboard with common parameters. - * This initializes either the normal software keyboard or the inline software keyboard - * depending on the state of is_background. - * Note that this does not cause the keyboard to appear. - * Use the respective Show*Keyboard() functions to cause the respective keyboards to appear. - */ - void InitializeFrontendKeyboard(); - - /// Signals the frontend to show the normal software keyboard. - void ShowNormalKeyboard(); - - /// Signals the frontend to show the text check dialog. - void ShowTextCheckDialog(SwkbdTextCheckResult text_check_result, - std::u16string text_check_message); - - /// Signals the frontend to show the inline software keyboard. - void ShowInlineKeyboard(); - - /// Signals the frontend to hide the inline software keyboard. - void HideInlineKeyboard(); - - /// Signals the frontend that the current inline keyboard text has changed. - void InlineTextChanged(); - - /// Signals both the frontend and application that the software keyboard is exiting. - void ExitKeyboard(); - - // Inline Software Keyboard Requests - - void RequestFinalize(const std::vector& request_data); - void RequestSetUserWordInfo(const std::vector& request_data); - void RequestSetCustomizeDic(const std::vector& request_data); - void RequestCalc(const std::vector& request_data); - void RequestSetCustomizedDictionaries(const std::vector& request_data); - void RequestUnsetCustomizedDictionaries(const std::vector& request_data); - void RequestSetChangedStringV2Flag(const std::vector& request_data); - void RequestSetMovedCursorV2Flag(const std::vector& request_data); - - // Inline Software Keyboard Replies - - void ReplyFinishedInitialize(); - void ReplyDefault(); - void ReplyChangedString(); - void ReplyMovedCursor(); - void ReplyMovedTab(); - void ReplyDecidedEnter(); - void ReplyDecidedCancel(); - void ReplyChangedStringUtf8(); - void ReplyMovedCursorUtf8(); - void ReplyDecidedEnterUtf8(); - void ReplyUnsetCustomizeDic(); - void ReplyReleasedUserWordInfo(); - void ReplyUnsetCustomizedDictionaries(); - void ReplyChangedStringV2(); - void ReplyMovedCursorV2(); - void ReplyChangedStringUtf8V2(); - void ReplyMovedCursorUtf8V2(); - - LibraryAppletMode applet_mode; - Core::Frontend::SoftwareKeyboardApplet& frontend; - Core::System& system; - - SwkbdAppletVersion swkbd_applet_version; - - SwkbdConfigCommon swkbd_config_common; - SwkbdConfigOld swkbd_config_old; - SwkbdConfigOld2 swkbd_config_old2; - SwkbdConfigNew swkbd_config_new; + KeyboardConfig config; std::u16string initial_text; - - SwkbdState swkbd_state{SwkbdState::NotInitialized}; - SwkbdInitializeArg swkbd_initialize_arg; - SwkbdCalcArg swkbd_calc_arg; - bool use_changed_string_v2{false}; - bool use_moved_cursor_v2{false}; - bool inline_use_utf8{false}; - s32 current_cursor_position{}; - - std::u16string current_text; - - bool is_background{false}; - - bool complete{false}; - ResultCode status{RESULT_SUCCESS}; + bool complete = false; + bool is_inline = false; + std::vector final_data; + Core::System& system; }; } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp index b28b849bc..2ab420789 100755 --- a/src/core/hle/service/am/applets/web_browser.cpp +++ b/src/core/hle/service/am/applets/web_browser.cpp @@ -208,9 +208,8 @@ void ExtractSharedFonts(Core::System& system) { } // namespace -WebBrowser::WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_, - const Core::Frontend::WebBrowserApplet& frontend_) - : Applet{system_.Kernel()}, applet_mode{applet_mode_}, frontend(frontend_), system{system_} {} +WebBrowser::WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_) + : Applet{system_.Kernel()}, frontend(frontend_), system{system_} {} WebBrowser::~WebBrowser() = default; diff --git a/src/core/hle/service/am/applets/web_browser.h b/src/core/hle/service/am/applets/web_browser.h index 5eafbae7b..04c274754 100755 --- a/src/core/hle/service/am/applets/web_browser.h +++ b/src/core/hle/service/am/applets/web_browser.h @@ -25,8 +25,7 @@ namespace Service::AM::Applets { class WebBrowser final : public Applet { public: - WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_, - const Core::Frontend::WebBrowserApplet& frontend_); + WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_); ~WebBrowser() override; @@ -64,7 +63,6 @@ private: void ExecuteWifi(); void ExecuteLobby(); - LibraryAppletMode applet_mode; const Core::Frontend::WebBrowserApplet& frontend; bool complete{false}; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index b9d30927a..c8031970b 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp @@ -36,7 +36,6 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); Tegra::ChCommandHeaderList cmdlist{{0xDEADB33F}}; system.GPU().PushCommandBuffer(cmdlist); - system.GPU().MemoryManager().InvalidateQueuedCaches(); } return UnmapBuffer(input, output); } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index 6654aa66d..c2f152190 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp @@ -198,13 +198,7 @@ NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector& input, std::vec return NvResult::InvalidState; } if (const auto size{RemoveBufferMap(object->dma_map_addr)}; size) { - if (vic_device) { - // UnmapVicFrame defers texture_cache invalidation of the frame address until - // the stream is over - gpu.MemoryManager().UnmapVicFrame(object->dma_map_addr, *size); - } else { - gpu.MemoryManager().Unmap(object->dma_map_addr, *size); - } + gpu.MemoryManager().Unmap(object->dma_map_addr, *size); } else { // This occurs quite frequently, however does not seem to impact functionality LOG_DEBUG(Service_NVDRV, "invalid offset=0x{:X} dma=0x{:X}", object->addr, diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h index 2e0aece2f..4c9d4ba41 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h @@ -160,7 +160,6 @@ protected: s32_le nvmap_fd{}; u32_le submit_timeout{}; - bool vic_device{}; std::shared_ptr nvmap_dev; SyncpointManager& syncpoint_manager; std::array device_syncpoints{}; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index 6c2f95fc0..0421fb956 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp @@ -12,9 +12,8 @@ namespace Service::Nvidia::Devices { nvhost_vic::nvhost_vic(Core::System& system, std::shared_ptr nvmap_dev, SyncpointManager& syncpoint_manager) - : nvhost_nvdec_common(system, std::move(nvmap_dev), syncpoint_manager) { - vic_device = true; -} + : nvhost_nvdec_common(system, std::move(nvmap_dev), syncpoint_manager) {} + nvhost_vic::~nvhost_vic() = default; NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector& input, diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index 51c26c6c3..f67de37e3 100755 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp @@ -761,7 +761,7 @@ std::vector SDLState::GetInputDevices() { for (const auto& joystick : value) { if (auto* const controller = joystick->GetSDLGameController()) { std::string name = - fmt::format("{} {}", GetControllerName(controller), joystick->GetPort()); + fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort()); devices.emplace_back(Common::ParamPackage{ {"class", "sdl"}, {"display", std::move(name)}, @@ -782,17 +782,6 @@ std::vector SDLState::GetInputDevices() { return devices; } -std::string SDLState::GetControllerName(SDL_GameController* controller) const { - switch (SDL_GameControllerGetType(controller)) { - case SDL_CONTROLLER_TYPE_XBOX360: - return "XBox 360 Controller"; - case SDL_CONTROLLER_TYPE_XBOXONE: - return "XBox One Controller"; - default: - return SDL_GameControllerName(controller); - } -} - namespace { Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis, float value = 0.1f) { @@ -941,19 +930,16 @@ ButtonMapping SDLState::GetButtonMappingForDevice(const Common::ParamPackage& pa return {}; } - const bool invert = - SDL_GameControllerGetType(controller) != SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO; - // This list is missing ZL/ZR since those are not considered buttons in SDL GameController. // We will add those afterwards // This list also excludes Screenshot since theres not really a mapping for that using ButtonBindings = std::array, 17>; - const ButtonBindings switch_to_sdl_button{{ - {Settings::NativeButton::A, invert ? SDL_CONTROLLER_BUTTON_B : SDL_CONTROLLER_BUTTON_A}, - {Settings::NativeButton::B, invert ? SDL_CONTROLLER_BUTTON_A : SDL_CONTROLLER_BUTTON_B}, - {Settings::NativeButton::X, invert ? SDL_CONTROLLER_BUTTON_Y : SDL_CONTROLLER_BUTTON_X}, - {Settings::NativeButton::Y, invert ? SDL_CONTROLLER_BUTTON_X : SDL_CONTROLLER_BUTTON_Y}, + static constexpr ButtonBindings switch_to_sdl_button{{ + {Settings::NativeButton::A, SDL_CONTROLLER_BUTTON_B}, + {Settings::NativeButton::B, SDL_CONTROLLER_BUTTON_A}, + {Settings::NativeButton::X, SDL_CONTROLLER_BUTTON_Y}, + {Settings::NativeButton::Y, SDL_CONTROLLER_BUTTON_X}, {Settings::NativeButton::LStick, SDL_CONTROLLER_BUTTON_LEFTSTICK}, {Settings::NativeButton::RStick, SDL_CONTROLLER_BUTTON_RIGHTSTICK}, {Settings::NativeButton::L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h index 8b7363f56..08044b00d 100755 --- a/src/input_common/sdl/sdl_impl.h +++ b/src/input_common/sdl/sdl_impl.h @@ -14,7 +14,6 @@ #include "input_common/sdl/sdl.h" union SDL_Event; -using SDL_GameController = struct _SDL_GameController; using SDL_Joystick = struct _SDL_Joystick; using SDL_JoystickID = s32; @@ -65,9 +64,6 @@ private: /// Needs to be called before SDL_QuitSubSystem. void CloseJoysticks(); - /// Returns a custom name for specific controllers because the default name is not correct - std::string GetControllerName(SDL_GameController* controller) const; - // Set to true if SDL supports game controller subsystem bool has_gamecontroller = false; diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 5d659dcaf..8b45f1b62 100755 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -1785,8 +1785,6 @@ public: SSY, SYNC, BRK, - CAL, - RET, DEPBAR, VOTE, VOTE_VTG, @@ -2110,8 +2108,6 @@ private: INST("1111000011111---", Id::SYNC, Type::Flow, "SYNC"), INST("111000110100----", Id::BRK, Type::Flow, "BRK"), INST("111000110000----", Id::EXIT, Type::Flow, "EXIT"), - INST("111000100110----", Id::CAL, Type::Flow, "CAL"), - INST("111000110010----", Id::RET, Type::Flow, "RET"), INST("1111000011110---", Id::DEPBAR, Type::Synch, "DEPBAR"), INST("0101000011011---", Id::VOTE, Type::Warp, "VOTE"), INST("0101000011100---", Id::VOTE_VTG, Type::Warp, "VOTE_VTG"), diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index 9529a1256..4eb71efbd 100755 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp @@ -114,25 +114,6 @@ void MemoryManager::TryUnlockPage(PageEntry page_entry, std::size_t size) { .IsSuccess()); } -void MemoryManager::UnmapVicFrame(GPUVAddr gpu_addr, std::size_t size) { - if (!size) { - return; - } - - const std::optional cpu_addr = GpuToCpuAddress(gpu_addr); - ASSERT(cpu_addr); - rasterizer->InvalidateExceptTextureCache(*cpu_addr, size); - cache_invalidate_queue.push_back({*cpu_addr, size}); - - UpdateRange(gpu_addr, PageEntry::State::Unmapped, size); -} - -void MemoryManager::InvalidateQueuedCaches() { - for (const auto& entry : cache_invalidate_queue) { - rasterizer->InvalidateTextureCache(entry.first, entry.second); - } - cache_invalidate_queue.clear(); -} PageEntry MemoryManager::GetPageEntry(GPUVAddr gpu_addr) const { return page_table[PageEntryIndex(gpu_addr)]; } diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index 5d6c196fa..b3538d503 100755 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h @@ -123,14 +123,6 @@ public: [[nodiscard]] GPUVAddr Allocate(std::size_t size, std::size_t align); void Unmap(GPUVAddr gpu_addr, std::size_t size); - /** - * Some Decoded NVDEC frames require that texture cache does not get invalidated. - * UnmapVicFrame defers the texture cache invalidation until the stream ends - * by invoking InvalidateQueuedCaches to invalidate all frame texture caches. - */ - void UnmapVicFrame(GPUVAddr gpu_addr, std::size_t size); - void InvalidateQueuedCaches(); - private: [[nodiscard]] PageEntry GetPageEntry(GPUVAddr gpu_addr) const; void SetPageEntry(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size = page_size); diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index afc7ff4ae..50491b758 100755 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h @@ -69,12 +69,6 @@ public: /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory virtual void FlushRegion(VAddr addr, u64 size) = 0; - /// Notify rasterizer to flush the texture cache to Switch memory - virtual void InvalidateExceptTextureCache(VAddr addr, u64 size) = 0; - - /// Notify rasterizer to invalidate the texture cache - virtual void InvalidateTextureCache(VAddr addr, u64 size) = 0; - /// Check if the the specified memory area requires flushing to CPU Memory. virtual bool MustFlushRegion(VAddr addr, u64 size) = 0; diff --git a/src/video_core/renderer_opengl/gl_arb_decompiler.cpp b/src/video_core/renderer_opengl/gl_arb_decompiler.cpp index e98647478..3e4d88c30 100755 --- a/src/video_core/renderer_opengl/gl_arb_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_arb_decompiler.cpp @@ -491,9 +491,6 @@ private: const Registry& registry; const ShaderType stage; - std::shared_ptr context_func; - u32 ast_var_base{}; - std::size_t num_temporaries = 0; std::size_t max_temporaries = 0; @@ -810,33 +807,13 @@ ARBDecompiler::ARBDecompiler(const Device& device_, const ShaderIR& ir_, const R : device{device_}, ir{ir_}, registry{registry_}, stage{stage_} { DefineGlobalMemory(); - context_func = ir.GetMainFunction(); - ast_var_base = 0; - AddLine("TEMP RC;"); AddLine("TEMP FSWZA[4];"); AddLine("TEMP FSWZB[4];"); - InitializeVariables(); - AddLine("main:"); - if (context_func->IsDecompiled()) { + if (ir.IsDecompiled()) { DecompileAST(); } else { DecompileBranchMode(); - AddLine("RET;"); - } - - const auto& subfunctions = ir.GetSubFunctions(); - auto it = subfunctions.begin(); - while (it != subfunctions.end()) { - context_func = *it; - AddLine("func_{}:", context_func->GetId()); - if (context_func->IsDecompiled()) { - DecompileAST(); - } else { - DecompileBranchMode(); - AddLine("RET;"); - } - it++; } AddLine("END"); @@ -1083,38 +1060,41 @@ void ARBDecompiler::InitializeVariables() { } void ARBDecompiler::DecompileAST() { - const u32 num_flow_variables = context_func->GetASTNumVariables(); + const u32 num_flow_variables = ir.GetASTNumVariables(); for (u32 i = 0; i < num_flow_variables; ++i) { - AddLine("TEMP F{};", i + ast_var_base); + AddLine("TEMP F{};", i); } for (u32 i = 0; i < num_flow_variables; ++i) { - AddLine("MOV.U F{}, {{0, 0, 0, 0}};", i + ast_var_base); + AddLine("MOV.U F{}, {{0, 0, 0, 0}};", i); } - VisitAST(context_func->GetASTProgram()); - ast_var_base += num_flow_variables; + InitializeVariables(); + + VisitAST(ir.GetASTProgram()); } void ARBDecompiler::DecompileBranchMode() { static constexpr u32 FLOW_STACK_SIZE = 20; - if (!context_func->IsFlowStackDisabled()) { + if (!ir.IsFlowStackDisabled()) { AddLine("TEMP SSY[{}];", FLOW_STACK_SIZE); AddLine("TEMP PBK[{}];", FLOW_STACK_SIZE); AddLine("TEMP SSY_TOP;"); AddLine("TEMP PBK_TOP;"); } - AddLine("TEMP PC{};", context_func->GetId()); + AddLine("TEMP PC;"); - if (!context_func->IsFlowStackDisabled()) { + if (!ir.IsFlowStackDisabled()) { AddLine("MOV.U SSY_TOP.x, 0;"); AddLine("MOV.U PBK_TOP.x, 0;"); } - const auto basic_block_end = context_func->GetBasicBlocks().end(); - auto basic_block_it = context_func->GetBasicBlocks().begin(); + InitializeVariables(); + + const auto basic_block_end = ir.GetBasicBlocks().end(); + auto basic_block_it = ir.GetBasicBlocks().begin(); const u32 first_address = basic_block_it->first; - AddLine("MOV.U PC{}.x, {};", context_func->GetId(), first_address); + AddLine("MOV.U PC.x, {};", first_address); AddLine("REP;"); @@ -1123,7 +1103,7 @@ void ARBDecompiler::DecompileBranchMode() { const auto& [address, bb] = *basic_block_it; ++num_blocks; - AddLine("SEQ.S.CC RC.x, PC{}.x, {};", context_func->GetId(), address); + AddLine("SEQ.S.CC RC.x, PC.x, {};", address); AddLine("IF NE.x;"); VisitBlock(bb); @@ -1134,7 +1114,7 @@ void ARBDecompiler::DecompileBranchMode() { const auto op = std::get_if(&*bb[bb.size() - 1]); if (!op || op->GetCode() != OperationCode::Branch) { const u32 next_address = basic_block_it->first; - AddLine("MOV.U PC{}.x, {};", context_func->GetId(), next_address); + AddLine("MOV.U PC.x, {};", next_address); AddLine("CONT;"); } } @@ -1172,8 +1152,7 @@ void ARBDecompiler::VisitAST(const ASTNode& node) { } else if (const auto decoded = std::get_if(&*node->GetInnerData())) { VisitBlock(decoded->nodes); } else if (const auto var_set = std::get_if(&*node->GetInnerData())) { - AddLine("MOV.U F{}, {};", var_set->index + ast_var_base, - VisitExpression(var_set->condition)); + AddLine("MOV.U F{}, {};", var_set->index, VisitExpression(var_set->condition)); ResetTemporaries(); } else if (const auto do_while = std::get_if(&*node->GetInnerData())) { const std::string condition = VisitExpression(do_while->condition); @@ -1193,11 +1172,7 @@ void ARBDecompiler::VisitAST(const ASTNode& node) { ResetTemporaries(); } if (ast_return->kills) { - if (stage == ShaderType::Fragment) { - AddLine("KIL TR;"); - } else { - AddLine("RET;"); - } + AddLine("KIL TR;"); } else { Exit(); } @@ -1244,7 +1219,7 @@ std::string ARBDecompiler::VisitExpression(const Expr& node) { return Visit(ir.GetConditionCode(expr->cc)); } if (const auto expr = std::get_if(&*node)) { - return fmt::format("F{}.x", expr->var_index + ast_var_base); + return fmt::format("F{}.x", expr->var_index); } if (const auto expr = std::get_if(&*node)) { return expr->value ? "0xffffffff" : "0"; @@ -1431,11 +1406,6 @@ std::string ARBDecompiler::Visit(const Node& node) { return {}; } - if (const auto func_call = std::get_if(&*node)) { - AddLine("CAL func_{};", func_call->GetFuncId()); - return {}; - } - if ([[maybe_unused]] const auto cmt = std::get_if(&*node)) { // Uncommenting this will generate invalid code. GLASM lacks comments. // AddLine("// {}", cmt->GetText()); @@ -1509,7 +1479,7 @@ std::string ARBDecompiler::GlobalMemoryPointer(const GmemNode& gmem) { } void ARBDecompiler::Exit() { - if (!context_func->IsMain() || stage != ShaderType::Fragment) { + if (stage != ShaderType::Fragment) { AddLine("RET;"); return; } @@ -2051,13 +2021,13 @@ std::string ARBDecompiler::ImageStore(Operation operation) { std::string ARBDecompiler::Branch(Operation operation) { const auto target = std::get(*operation[0]); - AddLine("MOV.U PC{}.x, {};", context_func->GetId(), target.GetValue()); + AddLine("MOV.U PC.x, {};", target.GetValue()); AddLine("CONT;"); return {}; } std::string ARBDecompiler::BranchIndirect(Operation operation) { - AddLine("MOV.U PC{}.x, {};", context_func->GetId(), Visit(operation[0])); + AddLine("MOV.U PC.x, {};", Visit(operation[0])); AddLine("CONT;"); return {}; } @@ -2075,7 +2045,7 @@ std::string ARBDecompiler::PopFlowStack(Operation operation) { const auto stack = std::get(operation.GetMeta()); const std::string_view stack_name = StackName(stack); AddLine("SUB.S {}_TOP.x, {}_TOP.x, 1;", stack_name, stack_name); - AddLine("MOV.U PC{}.x, {}[{}_TOP.x].x;", context_func->GetId(), stack_name, stack_name); + AddLine("MOV.U PC.x, {}[{}_TOP.x].x;", stack_name, stack_name); AddLine("CONT;"); return {}; } @@ -2086,10 +2056,6 @@ std::string ARBDecompiler::Exit(Operation) { } std::string ARBDecompiler::Discard(Operation) { - if (stage != ShaderType::Fragment) { - AddLine("RET;"); - return {}; - } AddLine("KIL TR;"); return {}; } diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index a7f7733eb..4610fd160 100755 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -544,26 +544,6 @@ void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) { query_cache.FlushRegion(addr, size); } -void RasterizerOpenGL::InvalidateExceptTextureCache(VAddr addr, u64 size) { - if (addr == 0 || size == 0) { - return; - } - shader_cache.InvalidateRegion(addr, size); - { - std::scoped_lock lock{buffer_cache.mutex}; - buffer_cache.WriteMemory(addr, size); - } - query_cache.InvalidateRegion(addr, size); -} - -void RasterizerOpenGL::InvalidateTextureCache(VAddr addr, u64 size) { - if (addr == 0 || size == 0) { - return; - } - std::scoped_lock lock{texture_cache.mutex}; - texture_cache.UnmapMemory(addr, size); -} - bool RasterizerOpenGL::MustFlushRegion(VAddr addr, u64 size) { std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; if (!Settings::IsGPULevelHigh()) { diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 9730544d9..3745cf637 100755 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -74,8 +74,6 @@ public: void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override; void FlushAll() override; void FlushRegion(VAddr addr, u64 size) override; - void InvalidateExceptTextureCache(VAddr addr, u64 size) override; - void InvalidateTextureCache(VAddr addr, u64 size) override; bool MustFlushRegion(VAddr addr, u64 size) override; void InvalidateRegion(VAddr addr, u64 size) override; void OnCPUWrite(VAddr addr, u64 size) override; diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index fd49014b9..ac78d344c 100755 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -79,11 +79,6 @@ const float fswzadd_modifiers_a[] = float[4](-1.0f, 1.0f, -1.0f, 0.0f ); const float fswzadd_modifiers_b[] = float[4](-1.0f, -1.0f, 1.0f, -1.0f ); )"; -enum class HelperFunction { - SignedAtomic = 0, - Total, -}; - class ShaderWriter final { public: void AddExpression(std::string_view text) { @@ -439,28 +434,6 @@ public: DeclareInternalFlags(); DeclareCustomVariables(); DeclarePhysicalAttributeReader(); - DeclareHelpersForward(); - - const auto& subfunctions = ir.GetSubFunctions(); - auto it = subfunctions.rbegin(); - while (it != subfunctions.rend()) { - context_func = *it; - code.AddLine("void func_{}() {{", context_func->GetId()); - ++code.scope; - - if (context_func->IsDecompiled()) { - DecompileAST(); - } else { - DecompileBranchMode(); - } - - --code.scope; - code.AddLine("}}"); - - it++; - } - - context_func = ir.GetMainFunction(); code.AddLine("void main() {{"); ++code.scope; @@ -469,7 +442,7 @@ public: code.AddLine("gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);"); } - if (context_func->IsDecompiled()) { + if (ir.IsDecompiled()) { DecompileAST(); } else { DecompileBranchMode(); @@ -477,9 +450,6 @@ public: --code.scope; code.AddLine("}}"); - - code.AddNewLine(); - DeclareHelpers(); } std::string GetResult() { @@ -492,13 +462,13 @@ private: void DecompileBranchMode() { // VM's program counter - const auto first_address = context_func->GetBasicBlocks().begin()->first; + const auto first_address = ir.GetBasicBlocks().begin()->first; code.AddLine("uint jmp_to = {}U;", first_address); // TODO(Subv): Figure out the actual depth of the flow stack, for now it seems // unlikely that shaders will use 20 nested SSYs and PBKs. constexpr u32 FLOW_STACK_SIZE = 20; - if (!context_func->IsFlowStackDisabled()) { + if (!ir.IsFlowStackDisabled()) { for (const auto stack : std::array{MetaStackClass::Ssy, MetaStackClass::Pbk}) { code.AddLine("uint {}[{}];", FlowStackName(stack), FLOW_STACK_SIZE); code.AddLine("uint {} = 0U;", FlowStackTopName(stack)); @@ -510,7 +480,7 @@ private: code.AddLine("switch (jmp_to) {{"); - for (const auto& pair : context_func->GetBasicBlocks()) { + for (const auto& pair : ir.GetBasicBlocks()) { const auto& [address, bb] = pair; code.AddLine("case 0x{:X}U: {{", address); ++code.scope; @@ -629,7 +599,7 @@ private: size = limit; } - code.AddLine("shared uint {}[{}];", GetSharedMemory(), size / 4); + code.AddLine("shared uint smem[{}];", size / 4); code.AddNewLine(); } code.AddLine("layout (local_size_x = {}, local_size_y = {}, local_size_z = {}) in;", @@ -1013,27 +983,6 @@ private: } } - void DeclareHelpersForward() { - code.AddLine("int Helpers_AtomicShared(uint offset, int value, bool is_min);"); - code.AddNewLine(); - } - - void DeclareHelpers() { - if (IsHelperEnabled(HelperFunction::SignedAtomic)) { - code.AddLine( - R"(int Helpers_AtomicShared(uint offset, int value, bool is_min) {{ - uint oldValue, newValue; - do {{ - oldValue = {}[offset]; - newValue = is_min ? uint(min(int(oldValue), value)) : uint(max(int(oldValue), value)); - }} while (atomicCompSwap({}[offset], newValue, oldValue) != oldValue); - return int(oldValue); -}})", - GetSharedMemory(), GetSharedMemory()); - code.AddNewLine(); - } - } - void VisitBlock(const NodeBlock& bb) { for (const auto& node : bb) { Visit(node).CheckVoid(); @@ -1160,9 +1109,7 @@ private: } if (const auto smem = std::get_if(&*node)) { - return { - fmt::format("{}[{} >> 2]", GetSharedMemory(), Visit(smem->GetAddress()).AsUint()), - Type::Uint}; + return {fmt::format("smem[{} >> 2]", Visit(smem->GetAddress()).AsUint()), Type::Uint}; } if (const auto internal_flag = std::get_if(&*node)) { @@ -1184,11 +1131,6 @@ private: return {}; } - if (const auto func_call = std::get_if(&*node)) { - code.AddLine("func_{}();", func_call->GetFuncId()); - return {}; - } - if (const auto comment = std::get_if(&*node)) { code.AddLine("// " + comment->GetText()); return {}; @@ -1656,9 +1598,7 @@ private: Type::Uint}; } else if (const auto smem = std::get_if(&*dest)) { ASSERT(stage == ShaderType::Compute); - target = { - fmt::format("{}[{} >> 2]", GetSharedMemory(), Visit(smem->GetAddress()).AsUint()), - Type::Uint}; + target = {fmt::format("smem[{} >> 2]", Visit(smem->GetAddress()).AsUint()), Type::Uint}; } else if (const auto gmem = std::get_if(&*dest)) { const std::string real = Visit(gmem->GetRealAddress()).AsUint(); const std::string base = Visit(gmem->GetBaseAddress()).AsUint(); @@ -2175,14 +2115,7 @@ private: UNIMPLEMENTED_IF(meta->sampler.is_array); const std::size_t count = operation.GetOperandsCount(); - std::string expr = "texelFetch"; - - if (!meta->aoffi.empty()) { - expr += "Offset"; - } - - expr += '('; - + std::string expr = "texelFetch("; expr += GetSampler(meta->sampler); expr += ", "; @@ -2204,20 +2137,6 @@ private: expr += ", "; expr += Visit(meta->lod).AsInt(); } - - if (!meta->aoffi.empty()) { - expr += ", "; - expr += constructors.at(meta->aoffi.size() - 1); - expr += '('; - for (size_t i = 0; i < meta->aoffi.size(); ++i) { - if (i > 0) { - expr += ", "; - } - expr += Visit(meta->aoffi[i]).AsInt(); - } - expr += ')'; - } - expr += ')'; expr += GetSwizzle(meta->element); @@ -2264,11 +2183,8 @@ private: template Expression Atomic(Operation operation) { if ((opname == Func::Min || opname == Func::Max) && type == Type::Int) { - // Use a helper as a workaround due to memory being uint - SetHelperEnabled(HelperFunction::SignedAtomic, true); - return {fmt::format("Helpers_AtomicShared({}, {}, {})", Visit(operation[0]).AsInt(), - Visit(operation[1]).AsInt(), opname == Func::Min), - Type::Int}; + UNIMPLEMENTED_MSG("Unimplemented Min & Max for atomic operations"); + return {}; } return {fmt::format("atomic{}({}, {})", opname, Visit(operation[0]).GetCode(), Visit(operation[1]).AsUint()), @@ -2351,9 +2267,7 @@ private: } Expression Exit(Operation operation) { - if (context_func->IsMain()) { - PreExit(); - } + PreExit(); code.AddLine("return;"); return {}; } @@ -2363,11 +2277,7 @@ private: // about unexecuted instructions that may follow this. code.AddLine("if (true) {{"); ++code.scope; - if (stage != ShaderType::Fragment) { - code.AddLine("return;"); - } else { - code.AddLine("discard;"); - } + code.AddLine("discard;"); --code.scope; code.AddLine("}}"); return {}; @@ -2478,7 +2388,7 @@ private: } Expression Barrier(Operation) { - if (!context_func->IsDecompiled()) { + if (!ir.IsDecompiled()) { LOG_ERROR(Render_OpenGL, "barrier() used but shader is not decompiled"); return {}; } @@ -2795,10 +2705,6 @@ private: } } - constexpr std::string_view GetSharedMemory() const { - return "shared_mem"; - } - std::string GetInternalFlag(InternalFlag flag) const { constexpr std::array InternalFlagNames = {"zero_flag", "sign_flag", "carry_flag", "overflow_flag"}; @@ -2840,14 +2746,6 @@ private: return std::min(device.GetMaxVaryings(), Maxwell::NumVaryings); } - void SetHelperEnabled(HelperFunction hf, bool enabled) { - helper_functions_enabled[static_cast(hf)] = enabled; - } - - bool IsHelperEnabled(HelperFunction hf) const { - return helper_functions_enabled[static_cast(hf)]; - } - const Device& device; const ShaderIR& ir; const Registry& registry; @@ -2857,13 +2755,9 @@ private: const Header header; std::unordered_map transform_feedback; - std::shared_ptr context_func; - ShaderWriter code; std::optional max_input_vertices; - - std::array(HelperFunction::Total)> helper_functions_enabled{}; }; std::string GetFlowVariable(u32 index) { @@ -3008,15 +2902,9 @@ public: decomp.code.scope++; } if (ast.kills) { - if (decomp.stage != ShaderType::Fragment) { - decomp.code.AddLine("return;"); - } else { - decomp.code.AddLine("discard;"); - } + decomp.code.AddLine("discard;"); } else { - if (decomp.context_func->IsMain()) { - decomp.PreExit(); - } + decomp.PreExit(); decomp.code.AddLine("return;"); } if (!is_true) { @@ -3049,13 +2937,13 @@ private: }; void GLSLDecompiler::DecompileAST() { - const u32 num_flow_variables = context_func->GetASTNumVariables(); + const u32 num_flow_variables = ir.GetASTNumVariables(); for (u32 i = 0; i < num_flow_variables; i++) { code.AddLine("bool {} = false;", GetFlowVariable(i)); } ASTDecompiler decompiler{*this}; - decompiler.Visit(context_func->GetASTProgram()); + decompiler.Visit(ir.GetASTProgram()); } } // Anonymous namespace diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 69a0faca3..df5b7b172 100755 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -493,26 +493,6 @@ void RasterizerVulkan::FlushRegion(VAddr addr, u64 size) { query_cache.FlushRegion(addr, size); } -void Vulkan::RasterizerVulkan::InvalidateExceptTextureCache(VAddr addr, u64 size) { - if (addr == 0 || size == 0) { - return; - } - pipeline_cache.InvalidateRegion(addr, size); - { - std::scoped_lock lock{buffer_cache.mutex}; - buffer_cache.WriteMemory(addr, size); - } - query_cache.InvalidateRegion(addr, size); -} - -void Vulkan::RasterizerVulkan::InvalidateTextureCache(VAddr addr, u64 size) { - if (addr == 0 || size == 0) { - return; - } - std::scoped_lock lock{texture_cache.mutex}; - texture_cache.UnmapMemory(addr, size); -} - bool RasterizerVulkan::MustFlushRegion(VAddr addr, u64 size) { std::scoped_lock lock{texture_cache.mutex, buffer_cache.mutex}; if (!Settings::IsGPULevelHigh()) { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index d8b5bf0fc..235afc6f3 100755 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -66,8 +66,6 @@ public: void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override; void FlushAll() override; void FlushRegion(VAddr addr, u64 size) override; - void InvalidateExceptTextureCache(VAddr addr, u64 size) override; - void InvalidateTextureCache(VAddr addr, u64 size) override; bool MustFlushRegion(VAddr addr, u64 size) override; void InvalidateRegion(VAddr addr, u64 size) override; void OnCPUWrite(VAddr addr, u64 size) override; diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 258e2f5df..c6846d886 100755 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp @@ -406,38 +406,10 @@ private: binding = DeclareStorageTexels(binding); binding = DeclareImages(binding); - const auto& subfunctions = ir.GetSubFunctions(); - - labels.resize(subfunctions.size() + 1); - other_functions.resize(subfunctions.size()); - - auto it = subfunctions.rbegin(); - while (it != subfunctions.rend()) { - context_func = *it; - other_functions[context_func->GetId() - 1] = - OpFunction(t_void, {}, TypeFunction(t_void)); - AddLabel(); - - if (context_func->IsDecompiled()) { - DeclareFlowVariables(); - DecompileAST(); - } else { - AllocateLabels(); - DecompileBranchMode(); - } - - OpReturn(); - OpFunctionEnd(); - - it++; - } - - context_func = ir.GetMainFunction(); - const Id main = OpFunction(t_void, {}, TypeFunction(t_void)); AddLabel(); - if (context_func->IsDecompiled()) { + if (ir.IsDecompiled()) { DeclareFlowVariables(); DecompileAST(); } else { @@ -469,18 +441,16 @@ private: void DecompileAST(); void DecompileBranchMode() { - const u32 first_address = context_func->GetBasicBlocks().begin()->first; - const u32 func_id = context_func->GetId(); - const std::string func_id_msg = std::to_string(func_id); - const Id loop_label = OpLabel("loop_" + func_id_msg); - const Id merge_label = OpLabel("merge_" + func_id_msg); + const u32 first_address = ir.GetBasicBlocks().begin()->first; + const Id loop_label = OpLabel("loop"); + const Id merge_label = OpLabel("merge"); const Id dummy_label = OpLabel(); const Id jump_label = OpLabel(); - continue_label = OpLabel("continue_" + func_id_msg); + continue_label = OpLabel("continue"); std::vector literals; std::vector branch_labels; - for (const auto& [literal, label] : labels[func_id]) { + for (const auto& [literal, label] : labels) { literals.push_back(literal); branch_labels.push_back(label); } @@ -492,11 +462,11 @@ private: std::tie(ssy_flow_stack, ssy_flow_stack_top) = CreateFlowStack(); std::tie(pbk_flow_stack, pbk_flow_stack_top) = CreateFlowStack(); - Name(jmp_to, "jmp_to_" + func_id_msg); - Name(ssy_flow_stack, "ssy_flow_stack_" + func_id_msg); - Name(ssy_flow_stack_top, "ssy_flow_stack_top_" + func_id_msg); - Name(pbk_flow_stack, "pbk_flow_stack_" + func_id_msg); - Name(pbk_flow_stack_top, "pbk_flow_stack_top_" + func_id_msg); + Name(jmp_to, "jmp_to"); + Name(ssy_flow_stack, "ssy_flow_stack"); + Name(ssy_flow_stack_top, "ssy_flow_stack_top"); + Name(pbk_flow_stack, "pbk_flow_stack"); + Name(pbk_flow_stack_top, "pbk_flow_stack_top"); DefinePrologue(); @@ -514,14 +484,13 @@ private: AddLabel(default_branch); OpReturn(); - for (const auto& [address, bb] : context_func->GetBasicBlocks()) { - AddLabel(labels[func_id].at(address)); + for (const auto& [address, bb] : ir.GetBasicBlocks()) { + AddLabel(labels.at(address)); VisitBasicBlock(bb); - const auto next_it = labels[func_id].lower_bound(address + 1); - const Id next_label = - next_it != labels[func_id].end() ? next_it->second : default_branch; + const auto next_it = labels.lower_bound(address + 1); + const Id next_label = next_it != labels.end() ? next_it->second : default_branch; OpBranch(next_label); } @@ -539,10 +508,9 @@ private: static constexpr auto INTERNAL_FLAGS_COUNT = static_cast(InternalFlag::Amount); void AllocateLabels() { - const u32 func_id = context_func->GetId(); - for (const auto& pair : context_func->GetBasicBlocks()) { + for (const auto& pair : ir.GetBasicBlocks()) { const u32 address = pair.first; - labels[func_id].emplace(address, OpLabel(fmt::format("label_0x{:x}", address))); + labels.emplace(address, OpLabel(fmt::format("label_0x{:x}", address))); } } @@ -621,14 +589,6 @@ private: DeclareOutputVertex(); } - void SafeKill() { - if (stage != ShaderType::Fragment) { - OpReturn(); - return; - } - OpKill(); - } - void DeclareFragment() { if (stage != ShaderType::Fragment) { return; @@ -696,7 +656,7 @@ private: } void DeclareFlowVariables() { - for (u32 i = 0; i < context_func->GetASTNumVariables(); i++) { + for (u32 i = 0; i < ir.GetASTNumVariables(); i++) { const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private, v_false); Name(id, fmt::format("flow_var_{}", static_cast(i))); flow_variables.emplace(i, AddGlobalVariable(id)); @@ -1373,12 +1333,6 @@ private: return {}; } - if (const auto func_call = std::get_if(&*node)) { - const u32 func_id = func_call->GetFuncId(); - OpFunctionCall(t_void, other_functions[func_id - 1]); - return {}; - } - if (const auto comment = std::get_if(&*node)) { if (device.HasDebuggingToolAttached()) { // We should insert comments with OpString instead of using named variables @@ -2170,7 +2124,7 @@ private: OpBranchConditional(condition, true_label, discard_label); AddLabel(discard_label); - SafeKill(); + OpKill(); AddLabel(true_label); } @@ -2221,9 +2175,7 @@ private: } Expression Exit(Operation operation) { - if (context_func->IsMain()) { - PreExit(); - } + PreExit(); inside_branch = true; if (conditional_branch_set) { OpReturn(); @@ -2240,12 +2192,12 @@ private: Expression Discard(Operation operation) { inside_branch = true; if (conditional_branch_set) { - SafeKill(); + OpKill(); } else { const Id dummy = OpLabel(); OpBranch(dummy); AddLabel(dummy); - SafeKill(); + OpKill(); AddLabel(); } return {}; @@ -2324,7 +2276,7 @@ private: } Expression Barrier(Operation) { - if (!context_func->IsDecompiled()) { + if (!ir.IsDecompiled()) { LOG_ERROR(Render_Vulkan, "OpBarrier used by shader is not decompiled"); return {}; } @@ -2818,8 +2770,6 @@ private: const Specialization& specialization; std::unordered_map transform_feedback; - std::shared_ptr context_func; - const Id t_void = Name(TypeVoid(), "void"); const Id t_bool = Name(TypeBool(), "bool"); @@ -2946,8 +2896,7 @@ private: Id ssy_flow_stack{}; Id pbk_flow_stack{}; Id continue_label{}; - std::vector> labels; - std::vector other_functions; + std::map labels; bool conditional_branch_set{}; bool inside_branch{}; @@ -3098,11 +3047,9 @@ public: decomp.OpBranchConditional(condition, then_label, endif_label); decomp.AddLabel(then_label); if (ast.kills) { - decomp.SafeKill(); + decomp.OpKill(); } else { - if (decomp.context_func->IsMain()) { - decomp.PreExit(); - } + decomp.PreExit(); decomp.OpReturn(); } decomp.AddLabel(endif_label); @@ -3111,11 +3058,9 @@ public: decomp.OpBranch(next_block); decomp.AddLabel(next_block); if (ast.kills) { - decomp.SafeKill(); + decomp.OpKill(); } else { - if (decomp.context_func->IsMain()) { - decomp.PreExit(); - } + decomp.PreExit(); decomp.OpReturn(); } decomp.AddLabel(decomp.OpLabel()); @@ -3152,7 +3097,7 @@ private: }; void SPIRVDecompiler::DecompileAST() { - const u32 num_flow_variables = context_func->GetASTNumVariables(); + const u32 num_flow_variables = ir.GetASTNumVariables(); for (u32 i = 0; i < num_flow_variables; i++) { const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private, v_false); Name(id, fmt::format("flow_var_{}", i)); @@ -3161,7 +3106,7 @@ void SPIRVDecompiler::DecompileAST() { DefinePrologue(); - const ASTNode program = context_func->GetASTProgram(); + const ASTNode program = ir.GetASTProgram(); ASTDecompiler decompiler{*this}; decompiler.Visit(program); diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp index 7c8bd7e2f..43d965f2f 100755 --- a/src/video_core/shader/control_flow.cpp +++ b/src/video_core/shader/control_flow.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include "common/assert.h" @@ -27,29 +26,17 @@ using Tegra::Shader::OpCode; constexpr s32 unassigned_branch = -2; -enum class JumpLabel : u32 { - SSYClass = 0, - PBKClass = 1, -}; - -struct JumpItem { - JumpLabel type; - u32 address; - - bool operator==(const JumpItem& other) const { - return std::tie(type, address) == std::tie(other.type, other.address); - } -}; - struct Query { u32 address{}; - std::stack stack{}; + std::stack ssy_stack{}; + std::stack pbk_stack{}; }; struct BlockStack { BlockStack() = default; - explicit BlockStack(const Query& q) : stack{q.stack} {} - std::stack stack{}; + explicit BlockStack(const Query& q) : ssy_stack{q.ssy_stack}, pbk_stack{q.pbk_stack} {} + std::stack ssy_stack{}; + std::stack pbk_stack{}; }; template @@ -78,36 +65,20 @@ struct BlockInfo { } }; -struct ProgramControl { - std::unordered_set found_functions{}; - std::list pending_functions{}; - - void RegisterFunction(u32 address) { - if (found_functions.count(address) != 0) { - return; - } - found_functions.insert(address); - pending_functions.emplace_back(address); - } -}; - struct CFGRebuildState { - explicit CFGRebuildState(ProgramControl& control_, const ProgramCode& program_code_, u32 start_, - u32 base_start_, Registry& registry_) - : control{control_}, program_code{program_code_}, registry{registry_}, start{start_}, - base_start{base_start_} {} + explicit CFGRebuildState(const ProgramCode& program_code_, u32 start_, Registry& registry_) + : program_code{program_code_}, registry{registry_}, start{start_} {} - ProgramControl& control; const ProgramCode& program_code; Registry& registry; u32 start{}; - u32 base_start{}; std::vector block_info; std::list inspect_queries; std::list queries; std::unordered_map registered; std::set labels; - std::map jump_labels; + std::map ssy_labels; + std::map pbk_labels; std::unordered_map stacks; ASTManager* manager{}; }; @@ -182,7 +153,7 @@ template std::optional TrackInstruction(const CFGRebuildState& state, u32& pos, TestCallable test, PackCallable pack) { for (; pos >= state.start; --pos) { - if (IsSchedInstruction(pos, state.base_start)) { + if (IsSchedInstruction(pos, state.start)) { continue; } const Instruction instr = state.program_code[pos]; @@ -291,7 +262,7 @@ std::pair ParseCode(CFGRebuildState& state, u32 address) single_branch.ignore = true; break; } - if (IsSchedInstruction(offset, state.base_start)) { + if (IsSchedInstruction(offset, state.start)) { offset++; continue; } @@ -303,7 +274,6 @@ std::pair ParseCode(CFGRebuildState& state, u32 address) } switch (opcode->get().GetId()) { - case OpCode::Id::RET: case OpCode::Id::EXIT: { const auto pred_index = static_cast(instr.pred.pred_index); single_branch.condition.predicate = GetPredicate(pred_index, instr.negate_pred != 0); @@ -441,20 +411,13 @@ std::pair ParseCode(CFGRebuildState& state, u32 address) case OpCode::Id::SSY: { const u32 target = offset + instr.bra.GetBranchTarget(); insert_label(state, target); - JumpItem it = {JumpLabel::SSYClass, target}; - state.jump_labels.emplace(offset, it); + state.ssy_labels.emplace(offset, target); break; } case OpCode::Id::PBK: { const u32 target = offset + instr.bra.GetBranchTarget(); insert_label(state, target); - JumpItem it = {JumpLabel::PBKClass, target}; - state.jump_labels.emplace(offset, it); - break; - } - case OpCode::Id::CAL: { - const u32 target = offset + instr.bra.GetBranchTarget(); - state.control.RegisterFunction(target); + state.pbk_labels.emplace(offset, target); break; } case OpCode::Id::BRX: { @@ -550,7 +513,7 @@ bool TryInspectAddress(CFGRebuildState& state) { } bool TryQuery(CFGRebuildState& state) { - const auto gather_labels = [](std::stack& cc, std::map& labels, + const auto gather_labels = [](std::stack& cc, std::map& labels, BlockInfo& block) { auto gather_start = labels.lower_bound(block.start); const auto gather_end = labels.upper_bound(block.end); @@ -559,19 +522,6 @@ bool TryQuery(CFGRebuildState& state) { ++gather_start; } }; - const auto pop_labels = [](JumpLabel type, SingleBranch* branch, Query& query) -> bool { - while (!query.stack.empty() && query.stack.top().type != type) { - query.stack.pop(); - } - if (query.stack.empty()) { - return false; - } - if (branch->address == unassigned_branch) { - branch->address = query.stack.top().address; - } - query.stack.pop(); - return true; - }; if (state.queries.empty()) { return false; } @@ -584,7 +534,8 @@ bool TryQuery(CFGRebuildState& state) { // consumes a label. Schedule new queries accordingly if (block.visited) { BlockStack& stack = state.stacks[q.address]; - const bool all_okay = (stack.stack.empty() || q.stack == stack.stack); + const bool all_okay = (stack.ssy_stack.empty() || q.ssy_stack == stack.ssy_stack) && + (stack.pbk_stack.empty() || q.pbk_stack == stack.pbk_stack); state.queries.pop_front(); return all_okay; } @@ -593,7 +544,8 @@ bool TryQuery(CFGRebuildState& state) { Query q2(q); state.queries.pop_front(); - gather_labels(q2.stack, state.jump_labels, block); + gather_labels(q2.ssy_stack, state.ssy_labels, block); + gather_labels(q2.pbk_stack, state.pbk_labels, block); if (std::holds_alternative(*block.branch)) { auto* branch = std::get_if(block.branch.get()); if (!branch->condition.IsUnconditional()) { @@ -603,10 +555,16 @@ bool TryQuery(CFGRebuildState& state) { auto& conditional_query = state.queries.emplace_back(q2); if (branch->is_sync) { - pop_labels(JumpLabel::SSYClass, branch, conditional_query); + if (branch->address == unassigned_branch) { + branch->address = conditional_query.ssy_stack.top(); + } + conditional_query.ssy_stack.pop(); } if (branch->is_brk) { - pop_labels(JumpLabel::PBKClass, branch, conditional_query); + if (branch->address == unassigned_branch) { + branch->address = conditional_query.pbk_stack.top(); + } + conditional_query.pbk_stack.pop(); } conditional_query.address = branch->address; return true; @@ -688,23 +646,25 @@ void DecompileShader(CFGRebuildState& state) { state.manager->Decompile(); } -ShaderFunction ScanFunction(ProgramControl& control, const ProgramCode& program_code, - u32 start_address, u32 base_start, const CompilerSettings& settings, - Registry& registry) { - ShaderFunction result_out{}; +} // Anonymous namespace + +std::unique_ptr ScanFlow(const ProgramCode& program_code, u32 start_address, + const CompilerSettings& settings, + Registry& registry) { + auto result_out = std::make_unique(); if (settings.depth == CompileDepth::BruteForce) { - result_out.settings.depth = CompileDepth::BruteForce; + result_out->settings.depth = CompileDepth::BruteForce; return result_out; } - CFGRebuildState state{control, program_code, start_address, base_start, registry}; + CFGRebuildState state{program_code, start_address, registry}; // Inspect Code and generate blocks state.labels.clear(); state.labels.emplace(start_address); state.inspect_queries.push_back(state.start); while (!state.inspect_queries.empty()) { if (!TryInspectAddress(state)) { - result_out.settings.depth = CompileDepth::BruteForce; + result_out->settings.depth = CompileDepth::BruteForce; return result_out; } } @@ -715,7 +675,7 @@ ShaderFunction ScanFunction(ProgramControl& control, const ProgramCode& program_ if (settings.depth != CompileDepth::FlowStack) { // Decompile Stacks - state.queries.push_back(Query{state.start, {}}); + state.queries.push_back(Query{state.start, {}, {}}); decompiled = true; while (!state.queries.empty()) { if (!TryQuery(state)) { @@ -745,18 +705,19 @@ ShaderFunction ScanFunction(ProgramControl& control, const ProgramCode& program_ state.manager->ShowCurrentState("Of Shader"); state.manager->Clear(); } else { - result_out.start = start_address; - result_out.settings.depth = settings.depth; - result_out.manager = std::move(manager); - result_out.end = state.block_info.back().end + 1; - return result_out; + auto characteristics = std::make_unique(); + characteristics->start = start_address; + characteristics->settings.depth = settings.depth; + characteristics->manager = std::move(manager); + characteristics->end = state.block_info.back().end + 1; + return characteristics; } } - result_out.start = start_address; - result_out.settings.depth = + result_out->start = start_address; + result_out->settings.depth = use_flow_stack ? CompileDepth::FlowStack : CompileDepth::NoFlowStack; - result_out.blocks.clear(); + result_out->blocks.clear(); for (auto& block : state.block_info) { ShaderBlock new_block{}; new_block.start = block.start; @@ -765,20 +726,20 @@ ShaderFunction ScanFunction(ProgramControl& control, const ProgramCode& program_ if (!new_block.ignore_branch) { new_block.branch = block.branch; } - result_out.end = std::max(result_out.end, block.end); - result_out.blocks.push_back(new_block); + result_out->end = std::max(result_out->end, block.end); + result_out->blocks.push_back(new_block); } if (!use_flow_stack) { - result_out.labels = std::move(state.labels); + result_out->labels = std::move(state.labels); return result_out; } - auto back = result_out.blocks.begin(); + auto back = result_out->blocks.begin(); auto next = std::next(back); - while (next != result_out.blocks.end()) { + while (next != result_out->blocks.end()) { if (!state.labels.contains(next->start) && next->start == back->end + 1) { back->end = next->end; - next = result_out.blocks.erase(next); + next = result_out->blocks.erase(next); continue; } back = next; @@ -787,22 +748,4 @@ ShaderFunction ScanFunction(ProgramControl& control, const ProgramCode& program_ return result_out; } - -} // Anonymous namespace - -std::unique_ptr ScanFlow(const ProgramCode& program_code, u32 start_address, - const CompilerSettings& settings, Registry& registry) { - ProgramControl control{}; - auto result_out = std::make_unique(); - result_out->main = - ScanFunction(control, program_code, start_address, start_address, settings, registry); - while (!control.pending_functions.empty()) { - u32 address = control.pending_functions.front(); - auto fun = ScanFunction(control, program_code, address, start_address, settings, registry); - result_out->subfunctions.emplace(address, std::move(fun)); - control.pending_functions.pop_front(); - } - return result_out; -} - } // namespace VideoCommon::Shader diff --git a/src/video_core/shader/control_flow.h b/src/video_core/shader/control_flow.h index 5ef2251b9..37bf96492 100755 --- a/src/video_core/shader/control_flow.h +++ b/src/video_core/shader/control_flow.h @@ -5,7 +5,6 @@ #pragma once #include -#include #include #include #include @@ -102,7 +101,7 @@ struct ShaderBlock { } }; -struct ShaderFunction { +struct ShaderCharacteristics { std::list blocks{}; std::set labels{}; u32 start{}; @@ -111,12 +110,8 @@ struct ShaderFunction { CompilerSettings settings{}; }; -struct ShaderProgram { - ShaderFunction main; - std::map subfunctions; -}; - -std::unique_ptr ScanFlow(const ProgramCode& program_code, u32 start_address, - const CompilerSettings& settings, Registry& registry); +std::unique_ptr ScanFlow(const ProgramCode& program_code, u32 start_address, + const CompilerSettings& settings, + Registry& registry); } // namespace VideoCommon::Shader diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp index 355c724a3..6576d1208 100755 --- a/src/video_core/shader/decode.cpp +++ b/src/video_core/shader/decode.cpp @@ -64,52 +64,9 @@ std::optional TryDeduceSamplerSize(const SamplerEntry& sampler_to_deduce, } // Anonymous namespace -class ExprDecoder { -public: - explicit ExprDecoder(ShaderIR& ir_) : ir(ir_) {} - - void operator()(const ExprAnd& expr) { - Visit(expr.operand1); - Visit(expr.operand2); - } - - void operator()(const ExprOr& expr) { - Visit(expr.operand1); - Visit(expr.operand2); - } - - void operator()(const ExprNot& expr) { - Visit(expr.operand1); - } - - void operator()(const ExprPredicate& expr) { - const auto pred = static_cast(expr.predicate); - if (pred != Pred::UnusedIndex && pred != Pred::NeverExecute) { - ir.used_predicates.insert(pred); - } - } - - void operator()(const ExprCondCode& expr) {} - - void operator()(const ExprVar& expr) {} - - void operator()(const ExprBoolean& expr) {} - - void operator()(const ExprGprEqual& expr) { - ir.used_registers.insert(expr.gpr); - } - - void Visit(const Expr& node) { - return std::visit(*this, *node); - } - -private: - ShaderIR& ir; -}; - class ASTDecoder { public: - explicit ASTDecoder(ShaderIR& ir_) : ir(ir_), decoder(ir_) {} + explicit ASTDecoder(ShaderIR& ir_) : ir(ir_) {} void operator()(ASTProgram& ast) { ASTNode current = ast.nodes.GetFirst(); @@ -120,7 +77,6 @@ public: } void operator()(ASTIfThen& ast) { - decoder.Visit(ast.condition); ASTNode current = ast.nodes.GetFirst(); while (current) { Visit(current); @@ -140,18 +96,13 @@ public: void operator()(ASTBlockDecoded& ast) {} - void operator()(ASTVarSet& ast) { - decoder.Visit(ast.condition); - } + void operator()(ASTVarSet& ast) {} void operator()(ASTLabel& ast) {} - void operator()(ASTGoto& ast) { - decoder.Visit(ast.condition); - } + void operator()(ASTGoto& ast) {} void operator()(ASTDoWhile& ast) { - decoder.Visit(ast.condition); ASTNode current = ast.nodes.GetFirst(); while (current) { Visit(current); @@ -159,13 +110,9 @@ public: } } - void operator()(ASTReturn& ast) { - decoder.Visit(ast.condition); - } + void operator()(ASTReturn& ast) {} - void operator()(ASTBreak& ast) { - decoder.Visit(ast.condition); - } + void operator()(ASTBreak& ast) {} void Visit(ASTNode& node) { std::visit(*this, *node->GetInnerData()); @@ -178,113 +125,77 @@ public: private: ShaderIR& ir; - ExprDecoder decoder; }; void ShaderIR::Decode() { - const auto decode_function = ([this](ShaderFunction& shader_info) { - coverage_end = std::max(0, shader_info.end); - switch (shader_info.settings.depth) { - case CompileDepth::FlowStack: { - for (const auto& block : shader_info.blocks) { - basic_blocks.insert({block.start, DecodeRange(block.start, block.end + 1)}); - } - break; - } - case CompileDepth::NoFlowStack: { - disable_flow_stack = true; - const auto insert_block = [this](NodeBlock& nodes, u32 label) { - if (label == static_cast(exit_branch)) { - return; - } - basic_blocks.insert({label, nodes}); - }; - const auto& blocks = shader_info.blocks; - NodeBlock current_block; - u32 current_label = static_cast(exit_branch); - for (const auto& block : blocks) { - if (shader_info.labels.contains(block.start)) { - insert_block(current_block, current_label); - current_block.clear(); - current_label = block.start; - } - if (!block.ignore_branch) { - DecodeRangeInner(current_block, block.start, block.end); - InsertControlFlow(current_block, block); - } else { - DecodeRangeInner(current_block, block.start, block.end + 1); - } - } - insert_block(current_block, current_label); - break; - } - case CompileDepth::DecompileBackwards: - case CompileDepth::FullDecompile: { - program_manager = std::move(shader_info.manager); - disable_flow_stack = true; - decompiled = true; - ASTDecoder decoder{*this}; - ASTNode program = program_manager.GetProgram(); - decoder.Visit(program); - break; - } - default: - LOG_CRITICAL(HW_GPU, "Unknown decompilation mode!"); - [[fallthrough]]; - case CompileDepth::BruteForce: { - const auto shader_end = static_cast(program_code.size()); - coverage_begin = main_offset; - coverage_end = shader_end; - for (u32 label = main_offset; label < shader_end; ++label) { - basic_blocks.insert({label, DecodeRange(label, label + 1)}); - } - break; - } - } - if (settings.depth != shader_info.settings.depth) { - LOG_WARNING( - HW_GPU, - "Decompiling to this setting \"{}\" failed, downgrading to this setting \"{}\"", - CompileDepthAsString(settings.depth), - CompileDepthAsString(shader_info.settings.depth)); - } - }); - const auto gen_function = - ([this](ShaderFunction& shader_info, u32 id) -> std::shared_ptr { - std::shared_ptr result; - if (decompiled) { - result = std::make_shared(std::move(program_manager), id, - shader_info.start, shader_info.end); - } else { - result = - std::make_shared(std::move(basic_blocks), disable_flow_stack, - id, shader_info.start, shader_info.end); - } - decompiled = false; - disable_flow_stack = false; - basic_blocks.clear(); - program_manager.Clear(); - return result; - }); std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header)); decompiled = false; auto info = ScanFlow(program_code, main_offset, settings, registry); - u32 id_start = 1; - for (auto& pair : info->subfunctions) { - func_map.emplace(pair.first, id_start); - id_start++; + auto& shader_info = *info; + coverage_begin = shader_info.start; + coverage_end = shader_info.end; + switch (shader_info.settings.depth) { + case CompileDepth::FlowStack: { + for (const auto& block : shader_info.blocks) { + basic_blocks.insert({block.start, DecodeRange(block.start, block.end + 1)}); + } + break; } - coverage_begin = info->main.start; - coverage_end = 0; - decode_function(info->main); - main_function = gen_function(info->main, 0); - subfunctions.resize(info->subfunctions.size()); - for (auto& pair : info->subfunctions) { - auto& func_info = pair.second; - decode_function(func_info); - u32 id = func_map[pair.first]; - subfunctions[id - 1] = gen_function(func_info, id); + case CompileDepth::NoFlowStack: { + disable_flow_stack = true; + const auto insert_block = [this](NodeBlock& nodes, u32 label) { + if (label == static_cast(exit_branch)) { + return; + } + basic_blocks.insert({label, nodes}); + }; + const auto& blocks = shader_info.blocks; + NodeBlock current_block; + u32 current_label = static_cast(exit_branch); + for (const auto& block : blocks) { + if (shader_info.labels.contains(block.start)) { + insert_block(current_block, current_label); + current_block.clear(); + current_label = block.start; + } + if (!block.ignore_branch) { + DecodeRangeInner(current_block, block.start, block.end); + InsertControlFlow(current_block, block); + } else { + DecodeRangeInner(current_block, block.start, block.end + 1); + } + } + insert_block(current_block, current_label); + break; + } + case CompileDepth::DecompileBackwards: + case CompileDepth::FullDecompile: { + program_manager = std::move(shader_info.manager); + disable_flow_stack = true; + decompiled = true; + ASTDecoder decoder{*this}; + ASTNode program = GetASTProgram(); + decoder.Visit(program); + break; + } + default: + LOG_CRITICAL(HW_GPU, "Unknown decompilation mode!"); + [[fallthrough]]; + case CompileDepth::BruteForce: { + const auto shader_end = static_cast(program_code.size()); + coverage_begin = main_offset; + coverage_end = shader_end; + for (u32 label = main_offset; label < shader_end; ++label) { + basic_blocks.insert({label, DecodeRange(label, label + 1)}); + } + break; + } + } + if (settings.depth != shader_info.settings.depth) { + LOG_WARNING( + HW_GPU, "Decompiling to this setting \"{}\" failed, downgrading to this setting \"{}\"", + CompileDepthAsString(settings.depth), CompileDepthAsString(shader_info.settings.depth)); } } diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp index 2bc596512..5f88537bc 100755 --- a/src/video_core/shader/decode/other.cpp +++ b/src/video_core/shader/decode/other.cpp @@ -33,7 +33,6 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { // With the previous preconditions, this instruction is a no-operation. break; } - case OpCode::Id::RET: case OpCode::Id::EXIT: { const ConditionCode cc = instr.flow_condition_code; UNIMPLEMENTED_IF_MSG(cc != ConditionCode::T, "EXIT condition code used: {}", cc); @@ -313,16 +312,6 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { LOG_DEBUG(HW_GPU, "DEPBAR instruction is stubbed"); break; } - case OpCode::Id::CAL: { - const u32 target = pc + instr.bra.GetBranchTarget(); - const auto it = func_map.find(target); - if (it == func_map.end()) { - UNREACHABLE(); - break; - } - bb.push_back(FunctionCall(it->second)); - break; - } default: UNIMPLEMENTED_MSG("Unhandled instruction: {}", opcode->get().GetName()); } diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index 43a166b6f..c69681e8d 100755 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp @@ -339,6 +339,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { const TextureType texture_type{instr.tlds.GetTextureType()}; const bool is_array{instr.tlds.IsArrayTexture()}; + UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::AOFFI), + "AOFFI is not implemented"); UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::MZ), "MZ is not implemented"); const Node4 components = GetTldsCode(instr, texture_type, is_array); @@ -820,7 +822,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is for (std::size_t i = 0; i < type_coord_count; ++i) { const bool last = (i == (type_coord_count - 1)) && (type_coord_count > 1); coords.push_back( - GetRegister(last && !aoffi_enabled ? last_coord_register : (coord_register + i))); + GetRegister(last && !aoffi_enabled ? last_coord_register : coord_register + i)); } const Node array = is_array ? GetRegister(array_register) : nullptr; diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index a58e7c65e..b54d33763 100755 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h @@ -267,11 +267,10 @@ class PatchNode; class SmemNode; class GmemNode; class CommentNode; -class FunctionCallNode; using NodeData = std::variant; + LmemNode, SmemNode, GmemNode, CommentNode>; using Node = std::shared_ptr; using Node4 = std::array; using NodeBlock = std::vector; @@ -495,18 +494,6 @@ private: std::vector code; ///< Code to execute }; -class FunctionCallNode final : public AmendNode { -public: - explicit FunctionCallNode(u32 func_id_) : func_id{func_id_} {} - - [[nodiscard]] u32 GetFuncId() const { - return func_id; - } - -private: - u32 func_id; ///< Id of the function to call -}; - /// A general purpose register class GprNode final { public: diff --git a/src/video_core/shader/node_helper.cpp b/src/video_core/shader/node_helper.cpp index cef9c26bc..6a5b6940d 100755 --- a/src/video_core/shader/node_helper.cpp +++ b/src/video_core/shader/node_helper.cpp @@ -19,11 +19,6 @@ Node Comment(std::string text) { return MakeNode(std::move(text)); } -/// Creates a function call -Node FunctionCall(u32 func_id) { - return MakeNode(func_id); -} - Node Immediate(u32 value) { return MakeNode(value); } diff --git a/src/video_core/shader/node_helper.h b/src/video_core/shader/node_helper.h index 3f882cd25..1e0886185 100755 --- a/src/video_core/shader/node_helper.h +++ b/src/video_core/shader/node_helper.h @@ -27,9 +27,6 @@ Node Conditional(Node condition, std::vector code); /// Creates a commentary node Node Comment(std::string text); -/// Creates a function call -Node FunctionCall(u32 func_id); - /// Creates an u32 immediate Node Immediate(u32 value); diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 94715b069..1cd7c14d7 100755 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -26,7 +26,7 @@ namespace VideoCommon::Shader { struct ShaderBlock; -constexpr u32 MAX_PROGRAM_LENGTH = 0x2000; +constexpr u32 MAX_PROGRAM_LENGTH = 0x1000; struct ConstBuffer { constexpr explicit ConstBuffer(u32 max_offset_, bool is_indirect_) @@ -64,68 +64,16 @@ struct GlobalMemoryUsage { bool is_written{}; }; -class ShaderFunctionIR final { -public: - explicit ShaderFunctionIR(std::map&& basic_blocks_, bool disable_flow_stack_, - u32 id_, u32 coverage_begin_, u32 coverage_end_) - : basic_blocks{std::move(basic_blocks_)}, decompiled{false}, - disable_flow_stack{disable_flow_stack_}, id{id_}, coverage_begin{coverage_begin_}, - coverage_end{coverage_end_} {} - explicit ShaderFunctionIR(ASTManager&& program_manager_, u32 id_, u32 coverage_begin_, - u32 coverage_end_) - : program_manager{std::move(program_manager_)}, decompiled{true}, disable_flow_stack{true}, - id{id_}, coverage_begin{coverage_begin_}, coverage_end{coverage_end_} {} - - const std::map& GetBasicBlocks() const { - return basic_blocks; - } - - [[nodiscard]] bool IsFlowStackDisabled() const { - return disable_flow_stack; - } - - [[nodiscard]] bool IsDecompiled() const { - return decompiled; - } - - const ASTManager& GetASTManager() const { - return program_manager; - } - - [[nodiscard]] ASTNode GetASTProgram() const { - return program_manager.GetProgram(); - } - - [[nodiscard]] u32 GetASTNumVariables() const { - return program_manager.GetVariables(); - } - - [[nodiscard]] bool IsMain() const { - return id == 0; - } - - [[nodiscard]] u32 GetId() const { - return id; - } - -private: - std::map basic_blocks; - ASTManager program_manager{true, true}; - - bool decompiled{}; - bool disable_flow_stack{}; - u32 id{}; - - u32 coverage_begin{}; - u32 coverage_end{}; -}; - class ShaderIR final { public: explicit ShaderIR(const ProgramCode& program_code_, u32 main_offset_, CompilerSettings settings_, Registry& registry_); ~ShaderIR(); + const std::map& GetBasicBlocks() const { + return basic_blocks; + } + const std::set& GetRegisters() const { return used_registers; } @@ -207,6 +155,26 @@ public: return header; } + bool IsFlowStackDisabled() const { + return disable_flow_stack; + } + + bool IsDecompiled() const { + return decompiled; + } + + const ASTManager& GetASTManager() const { + return program_manager; + } + + ASTNode GetASTProgram() const { + return program_manager.GetProgram(); + } + + u32 GetASTNumVariables() const { + return program_manager.GetVariables(); + } + u32 ConvertAddressToNvidiaSpace(u32 address) const { return (address - main_offset) * static_cast(sizeof(Tegra::Shader::Instruction)); } @@ -222,16 +190,7 @@ public: return num_custom_variables; } - std::shared_ptr GetMainFunction() const { - return main_function; - } - - const std::vector>& GetSubFunctions() const { - return subfunctions; - } - private: - friend class ExprDecoder; friend class ASTDecoder; struct SamplerInfo { @@ -494,10 +453,6 @@ private: std::vector amend_code; u32 num_custom_variables{}; - std::shared_ptr main_function; - std::vector> subfunctions; - std::unordered_map func_map; - std::set used_registers; std::set used_predicates; std::set used_input_attributes; diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index cc0790e07..b025ced1c 100755 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -18,7 +18,6 @@ add_executable(yuzu applets/profile_select.h applets/software_keyboard.cpp applets/software_keyboard.h - applets/software_keyboard.ui applets/web_browser.cpp applets/web_browser.h bootmanager.cpp @@ -144,9 +143,6 @@ add_executable(yuzu uisettings.h util/limitable_input_dialog.cpp util/limitable_input_dialog.h - util/overlay_dialog.cpp - util/overlay_dialog.h - util/overlay_dialog.ui util/sequence_dialog/sequence_dialog.cpp util/sequence_dialog/sequence_dialog.h util/url_request_interceptor.cpp diff --git a/src/yuzu/applets/error.cpp b/src/yuzu/applets/error.cpp index 085688cd4..8ee03ddb3 100755 --- a/src/yuzu/applets/error.cpp +++ b/src/yuzu/applets/error.cpp @@ -19,11 +19,11 @@ QtErrorDisplay::~QtErrorDisplay() = default; void QtErrorDisplay::ShowError(ResultCode error, std::function finished) const { callback = std::move(finished); emit MainWindowDisplayError( - tr("Error Code: %1-%2 (0x%3)") + tr("An error has occurred.\nPlease try again or contact the developer of the " + "software.\n\nError Code: %1-%2 (0x%3)") .arg(static_cast(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) .arg(error.description, 4, 10, QChar::fromLatin1('0')) - .arg(error.raw, 8, 16, QChar::fromLatin1('0')), - tr("An error has occurred.\nPlease try again or contact the developer of the software.")); + .arg(error.raw, 8, 16, QChar::fromLatin1('0'))); } void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time, @@ -32,14 +32,13 @@ void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::secon const QDateTime date_time = QDateTime::fromSecsSinceEpoch(time.count()); emit MainWindowDisplayError( - tr("Error Code: %1-%2 (0x%3)") + tr("An error occurred on %1 at %2.\nPlease try again or contact the " + "developer of the software.\n\nError Code: %3-%4 (0x%5)") + .arg(date_time.toString(QStringLiteral("dddd, MMMM d, yyyy"))) + .arg(date_time.toString(QStringLiteral("h:mm:ss A"))) .arg(static_cast(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) .arg(error.description, 4, 10, QChar::fromLatin1('0')) - .arg(error.raw, 8, 16, QChar::fromLatin1('0')), - tr("An error occurred on %1 at %2.\nPlease try again or contact the developer of the " - "software.") - .arg(date_time.toString(QStringLiteral("dddd, MMMM d, yyyy"))) - .arg(date_time.toString(QStringLiteral("h:mm:ss A")))); + .arg(error.raw, 8, 16, QChar::fromLatin1('0'))); } void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_text, @@ -47,11 +46,10 @@ void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_te std::function finished) const { callback = std::move(finished); emit MainWindowDisplayError( - tr("Error Code: %1-%2 (0x%3)") + tr("An error has occurred.\nError Code: %1-%2 (0x%3)\n\n%4\n\n%5") .arg(static_cast(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) .arg(error.description, 4, 10, QChar::fromLatin1('0')) - .arg(error.raw, 8, 16, QChar::fromLatin1('0')), - tr("An error has occurred.\n\n%1\n\n%2") + .arg(error.raw, 8, 16, QChar::fromLatin1('0')) .arg(QString::fromStdString(dialog_text)) .arg(QString::fromStdString(fullscreen_text))); } diff --git a/src/yuzu/applets/error.h b/src/yuzu/applets/error.h index 8bd895a32..b0932d895 100755 --- a/src/yuzu/applets/error.h +++ b/src/yuzu/applets/error.h @@ -24,7 +24,7 @@ public: std::function finished) const override; signals: - void MainWindowDisplayError(QString error_code, QString error_text) const; + void MainWindowDisplayError(QString error) const; private: void MainWindowFinishedError(); diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index 06bab08d4..ab8cfd8ee 100755 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp @@ -1,1641 +1,153 @@ -// Copyright 2021 yuzu Emulator Project +// Copyright 2018 yuzu Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include -#include -#include - -#include "common/logging/log.h" -#include "common/string_util.h" -#include "core/core.h" -#include "core/frontend/input_interpreter.h" -#include "core/settings.h" -#include "ui_software_keyboard.h" +#include +#include +#include +#include +#include +#include +#include +#include "core/hle/lock.h" #include "yuzu/applets/software_keyboard.h" #include "yuzu/main.h" -#include "yuzu/util/overlay_dialog.h" -namespace { +QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator( + Core::Frontend::SoftwareKeyboardParameters parameters) + : parameters(std::move(parameters)) {} -using namespace Service::AM::Applets; +QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int& pos) const { + if (input.size() > static_cast(parameters.max_length)) { + return Invalid; + } + if (parameters.disable_space && input.contains(QLatin1Char{' '})) { + return Invalid; + } + if (parameters.disable_address && input.contains(QLatin1Char{'@'})) { + return Invalid; + } + if (parameters.disable_percent && input.contains(QLatin1Char{'%'})) { + return Invalid; + } + if (parameters.disable_slash && + (input.contains(QLatin1Char{'/'}) || input.contains(QLatin1Char{'\\'}))) { + return Invalid; + } + if (parameters.disable_number && + std::any_of(input.begin(), input.end(), [](QChar c) { return c.isDigit(); })) { + return Invalid; + } -constexpr float BASE_HEADER_FONT_SIZE = 23.0f; -constexpr float BASE_SUB_FONT_SIZE = 17.0f; -constexpr float BASE_EDITOR_FONT_SIZE = 26.0f; -constexpr float BASE_CHAR_BUTTON_FONT_SIZE = 28.0f; -constexpr float BASE_LABEL_BUTTON_FONT_SIZE = 18.0f; -constexpr float BASE_ICON_BUTTON_SIZE = 36.0f; -[[maybe_unused]] constexpr float BASE_WIDTH = 1280.0f; -constexpr float BASE_HEIGHT = 720.0f; + if (parameters.disable_download_code && std::any_of(input.begin(), input.end(), [](QChar c) { + return c == QLatin1Char{'O'} || c == QLatin1Char{'I'}; + })) { + return Invalid; + } -} // Anonymous namespace + return Acceptable; +} QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( - QWidget* parent, Core::System& system_, bool is_inline_, - Core::Frontend::KeyboardInitializeParameters initialize_parameters_) - : QDialog(parent), ui{std::make_unique()}, system{system_}, - is_inline{is_inline_}, initialize_parameters{std::move(initialize_parameters_)} { - ui->setupUi(this); + QWidget* parent, Core::Frontend::SoftwareKeyboardParameters parameters_) + : QDialog(parent), parameters(std::move(parameters_)) { + layout = new QVBoxLayout; - setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowTitleHint | - Qt::WindowSystemMenuHint | Qt::CustomizeWindowHint); - setWindowModality(Qt::WindowModal); - setAttribute(Qt::WA_DeleteOnClose); - setAttribute(Qt::WA_TranslucentBackground); + header_label = new QLabel(QString::fromStdU16String(parameters.header_text)); + header_label->setFont({header_label->font().family(), 11, QFont::Bold}); + if (header_label->text().isEmpty()) + header_label->setText(tr("Enter text:")); - keyboard_buttons = {{ - {{ - { - ui->button_1, - ui->button_2, - ui->button_3, - ui->button_4, - ui->button_5, - ui->button_6, - ui->button_7, - ui->button_8, - ui->button_9, - ui->button_0, - ui->button_minus, - ui->button_backspace, - }, - { - ui->button_q, - ui->button_w, - ui->button_e, - ui->button_r, - ui->button_t, - ui->button_y, - ui->button_u, - ui->button_i, - ui->button_o, - ui->button_p, - ui->button_slash, - ui->button_return, - }, - { - ui->button_a, - ui->button_s, - ui->button_d, - ui->button_f, - ui->button_g, - ui->button_h, - ui->button_j, - ui->button_k, - ui->button_l, - ui->button_colon, - ui->button_apostrophe, - ui->button_return, - }, - { - ui->button_z, - ui->button_x, - ui->button_c, - ui->button_v, - ui->button_b, - ui->button_n, - ui->button_m, - ui->button_comma, - ui->button_dot, - ui->button_question, - ui->button_exclamation, - ui->button_ok, - }, - { - ui->button_shift, - ui->button_shift, - ui->button_space, - ui->button_space, - ui->button_space, - ui->button_space, - ui->button_space, - ui->button_space, - ui->button_space, - ui->button_space, - ui->button_space, - ui->button_ok, - }, - }}, - {{ - { - ui->button_hash, - ui->button_left_bracket, - ui->button_right_bracket, - ui->button_dollar, - ui->button_percent, - ui->button_circumflex, - ui->button_ampersand, - ui->button_asterisk, - ui->button_left_parenthesis, - ui->button_right_parenthesis, - ui->button_underscore, - ui->button_backspace_shift, - }, - { - ui->button_q_shift, - ui->button_w_shift, - ui->button_e_shift, - ui->button_r_shift, - ui->button_t_shift, - ui->button_y_shift, - ui->button_u_shift, - ui->button_i_shift, - ui->button_o_shift, - ui->button_p_shift, - ui->button_at, - ui->button_return_shift, - }, - { - ui->button_a_shift, - ui->button_s_shift, - ui->button_d_shift, - ui->button_f_shift, - ui->button_g_shift, - ui->button_h_shift, - ui->button_j_shift, - ui->button_k_shift, - ui->button_l_shift, - ui->button_semicolon, - ui->button_quotation, - ui->button_return_shift, - }, - { - ui->button_z_shift, - ui->button_x_shift, - ui->button_c_shift, - ui->button_v_shift, - ui->button_b_shift, - ui->button_n_shift, - ui->button_m_shift, - ui->button_less_than, - ui->button_greater_than, - ui->button_plus, - ui->button_equal, - ui->button_ok_shift, - }, - { - ui->button_shift_shift, - ui->button_shift_shift, - ui->button_space_shift, - ui->button_space_shift, - ui->button_space_shift, - ui->button_space_shift, - ui->button_space_shift, - ui->button_space_shift, - ui->button_space_shift, - ui->button_space_shift, - ui->button_space_shift, - ui->button_ok_shift, - }, - }}, - }}; + sub_label = new QLabel(QString::fromStdU16String(parameters.sub_text)); + sub_label->setFont({sub_label->font().family(), sub_label->font().pointSize(), + sub_label->font().weight(), true}); + sub_label->setHidden(parameters.sub_text.empty()); - numberpad_buttons = {{ - { - ui->button_1_num, - ui->button_2_num, - ui->button_3_num, - ui->button_backspace_num, - }, - { - ui->button_4_num, - ui->button_5_num, - ui->button_6_num, - ui->button_ok_num, - }, - { - ui->button_7_num, - ui->button_8_num, - ui->button_9_num, - ui->button_ok_num, - }, - { - nullptr, - ui->button_0_num, - nullptr, - ui->button_ok_num, - }, - }}; + guide_label = new QLabel(QString::fromStdU16String(parameters.guide_text)); + guide_label->setHidden(parameters.guide_text.empty()); - all_buttons = { - ui->button_1, - ui->button_2, - ui->button_3, - ui->button_4, - ui->button_5, - ui->button_6, - ui->button_7, - ui->button_8, - ui->button_9, - ui->button_0, - ui->button_minus, - ui->button_backspace, - ui->button_q, - ui->button_w, - ui->button_e, - ui->button_r, - ui->button_t, - ui->button_y, - ui->button_u, - ui->button_i, - ui->button_o, - ui->button_p, - ui->button_slash, - ui->button_return, - ui->button_a, - ui->button_s, - ui->button_d, - ui->button_f, - ui->button_g, - ui->button_h, - ui->button_j, - ui->button_k, - ui->button_l, - ui->button_colon, - ui->button_apostrophe, - ui->button_z, - ui->button_x, - ui->button_c, - ui->button_v, - ui->button_b, - ui->button_n, - ui->button_m, - ui->button_comma, - ui->button_dot, - ui->button_question, - ui->button_exclamation, - ui->button_ok, - ui->button_shift, - ui->button_space, - ui->button_hash, - ui->button_left_bracket, - ui->button_right_bracket, - ui->button_dollar, - ui->button_percent, - ui->button_circumflex, - ui->button_ampersand, - ui->button_asterisk, - ui->button_left_parenthesis, - ui->button_right_parenthesis, - ui->button_underscore, - ui->button_backspace_shift, - ui->button_q_shift, - ui->button_w_shift, - ui->button_e_shift, - ui->button_r_shift, - ui->button_t_shift, - ui->button_y_shift, - ui->button_u_shift, - ui->button_i_shift, - ui->button_o_shift, - ui->button_p_shift, - ui->button_at, - ui->button_return_shift, - ui->button_a_shift, - ui->button_s_shift, - ui->button_d_shift, - ui->button_f_shift, - ui->button_g_shift, - ui->button_h_shift, - ui->button_j_shift, - ui->button_k_shift, - ui->button_l_shift, - ui->button_semicolon, - ui->button_quotation, - ui->button_z_shift, - ui->button_x_shift, - ui->button_c_shift, - ui->button_v_shift, - ui->button_b_shift, - ui->button_n_shift, - ui->button_m_shift, - ui->button_less_than, - ui->button_greater_than, - ui->button_plus, - ui->button_equal, - ui->button_ok_shift, - ui->button_shift_shift, - ui->button_space_shift, - ui->button_1_num, - ui->button_2_num, - ui->button_3_num, - ui->button_backspace_num, - ui->button_4_num, - ui->button_5_num, - ui->button_6_num, - ui->button_ok_num, - ui->button_7_num, - ui->button_8_num, - ui->button_9_num, - ui->button_0_num, - }; + length_label = new QLabel(QStringLiteral("0/%1").arg(parameters.max_length)); + length_label->setAlignment(Qt::AlignRight); + length_label->setFont({length_label->font().family(), 8}); - SetupMouseHover(); + line_edit = new QLineEdit; + line_edit->setValidator(new QtSoftwareKeyboardValidator(parameters)); + line_edit->setMaxLength(static_cast(parameters.max_length)); + line_edit->setText(QString::fromStdU16String(parameters.initial_text)); + line_edit->setCursorPosition( + parameters.cursor_at_beginning ? 0 : static_cast(parameters.initial_text.size())); + line_edit->setEchoMode(parameters.password ? QLineEdit::Password : QLineEdit::Normal); - if (!initialize_parameters.ok_text.empty()) { - ui->button_ok->setText(QString::fromStdU16String(initialize_parameters.ok_text)); - } - - ui->label_header->setText(QString::fromStdU16String(initialize_parameters.header_text)); - ui->label_sub->setText(QString::fromStdU16String(initialize_parameters.sub_text)); - - current_text = initialize_parameters.initial_text; - cursor_position = initialize_parameters.initial_cursor_position; - - SetTextDrawType(); - - for (auto* button : all_buttons) { - connect(button, &QPushButton::clicked, this, [this, button](bool) { - if (is_inline) { - InlineKeyboardButtonClicked(button); - } else { - NormalKeyboardButtonClicked(button); - } - }); - } - - // TODO (Morph): Remove this when InputInterpreter no longer relies on the HID backend - if (system.IsPoweredOn()) { - input_interpreter = std::make_unique(system); + connect(line_edit, &QLineEdit::textChanged, this, [this](const QString& text) { + length_label->setText(QStringLiteral("%1/%2").arg(text.size()).arg(parameters.max_length)); + }); + + buttons = new QDialogButtonBox(QDialogButtonBox::Cancel); + if (parameters.submit_text.empty()) { + buttons->addButton(QDialogButtonBox::Ok); + } else { + buttons->addButton(QString::fromStdU16String(parameters.submit_text), + QDialogButtonBox::AcceptRole); } + connect(buttons, &QDialogButtonBox::accepted, this, &QtSoftwareKeyboardDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, &QtSoftwareKeyboardDialog::reject); + layout->addWidget(header_label); + layout->addWidget(sub_label); + layout->addWidget(guide_label); + layout->addWidget(length_label); + layout->addWidget(line_edit); + layout->addWidget(buttons); + setLayout(layout); + setWindowTitle(tr("Software Keyboard")); } -QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() { - StopInputThread(); -} +QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() = default; -void QtSoftwareKeyboardDialog::ShowNormalKeyboard(QPoint pos, QSize size) { - if (isVisible()) { - return; - } - - MoveAndResizeWindow(pos, size); - - SetKeyboardType(); - SetPasswordMode(); - SetControllerImage(); - DisableKeyboardButtons(); - SetBackspaceOkEnabled(); - - open(); -} - -void QtSoftwareKeyboardDialog::ShowTextCheckDialog( - Service::AM::Applets::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message) { - switch (text_check_result) { - case SwkbdTextCheckResult::Success: - case SwkbdTextCheckResult::Silent: - default: - break; - case SwkbdTextCheckResult::Failure: { - StopInputThread(); - - OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message), - QString{}, tr("OK"), Qt::AlignCenter); - dialog.exec(); - - StartInputThread(); - break; - } - case SwkbdTextCheckResult::Confirm: { - StopInputThread(); - - OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message), - tr("Cancel"), tr("OK"), Qt::AlignCenter); - if (dialog.exec() == QDialog::Accepted) { - emit SubmitNormalText(SwkbdResult::Ok, current_text); - break; - } - - StartInputThread(); - break; - } - } -} - -void QtSoftwareKeyboardDialog::ShowInlineKeyboard( - Core::Frontend::InlineAppearParameters appear_parameters, QPoint pos, QSize size) { - MoveAndResizeWindow(pos, size); - - ui->topOSK->setStyleSheet(QStringLiteral("background: rgba(0, 0, 0, 0);")); - - ui->headerOSK->hide(); - ui->subOSK->hide(); - ui->inputOSK->hide(); - ui->charactersOSK->hide(); - ui->inputBoxOSK->hide(); - ui->charactersBoxOSK->hide(); - - initialize_parameters.max_text_length = appear_parameters.max_text_length; - initialize_parameters.min_text_length = appear_parameters.min_text_length; - initialize_parameters.type = appear_parameters.type; - initialize_parameters.key_disable_flags = appear_parameters.key_disable_flags; - initialize_parameters.enable_backspace_button = appear_parameters.enable_backspace_button; - initialize_parameters.enable_return_button = appear_parameters.enable_return_button; - initialize_parameters.disable_cancel_button = initialize_parameters.disable_cancel_button; - - SetKeyboardType(); - SetControllerImage(); - DisableKeyboardButtons(); - SetBackspaceOkEnabled(); - - open(); -} - -void QtSoftwareKeyboardDialog::HideInlineKeyboard() { - StopInputThread(); - QDialog::hide(); -} - -void QtSoftwareKeyboardDialog::InlineTextChanged( - Core::Frontend::InlineTextParameters text_parameters) { - current_text = text_parameters.input_text; - cursor_position = text_parameters.cursor_position; - - SetBackspaceOkEnabled(); -} - -void QtSoftwareKeyboardDialog::ExitKeyboard() { - StopInputThread(); - QDialog::done(QDialog::Accepted); -} - -void QtSoftwareKeyboardDialog::open() { - QDialog::open(); - - row = 0; - column = 0; - - const auto* const curr_button = - keyboard_buttons[static_cast(bottom_osk_index)][row][column]; - - // This is a workaround for setFocus() randomly not showing focus in the UI - QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center())); - - StartInputThread(); +void QtSoftwareKeyboardDialog::accept() { + text = line_edit->text().toStdU16String(); + QDialog::accept(); } void QtSoftwareKeyboardDialog::reject() { - // Pressing the ESC key in a dialog calls QDialog::reject(). - // We will override this behavior to the "Cancel" action on the software keyboard. - if (is_inline) { - emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position); - } else { - emit SubmitNormalText(SwkbdResult::Cancel, current_text); - } + text.clear(); + QDialog::reject(); } -void QtSoftwareKeyboardDialog::keyPressEvent(QKeyEvent* event) { - if (!is_inline) { - QDialog::keyPressEvent(event); - return; - } - - const auto entered_key = event->key(); - - switch (entered_key) { - case Qt::Key_Escape: - QDialog::keyPressEvent(event); - return; - case Qt::Key_Backspace: - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - ui->button_backspace->click(); - break; - case BottomOSKIndex::UpperCase: - ui->button_backspace_shift->click(); - break; - case BottomOSKIndex::NumberPad: - ui->button_backspace_num->click(); - break; - default: - break; - } - return; - case Qt::Key_Return: - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - ui->button_ok->click(); - break; - case BottomOSKIndex::UpperCase: - ui->button_ok_shift->click(); - break; - case BottomOSKIndex::NumberPad: - ui->button_ok_num->click(); - break; - default: - break; - } - return; - case Qt::Key_Left: - MoveTextCursorDirection(Direction::Left); - return; - case Qt::Key_Right: - MoveTextCursorDirection(Direction::Right); - return; - default: - break; - } - - const auto entered_text = event->text(); - - if (entered_text.isEmpty()) { - return; - } - - InlineTextInsertString(entered_text.toStdU16String()); -} - -void QtSoftwareKeyboardDialog::MoveAndResizeWindow(QPoint pos, QSize size) { - QDialog::move(pos); - QDialog::resize(size); - - // High DPI - const float dpi_scale = qApp->screenAt(pos)->logicalDotsPerInch() / 96.0f; - - RescaleKeyboardElements(size.width(), size.height(), dpi_scale); -} - -void QtSoftwareKeyboardDialog::RescaleKeyboardElements(float width, float height, float dpi_scale) { - const auto header_font_size = BASE_HEADER_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; - const auto sub_font_size = BASE_SUB_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; - const auto editor_font_size = BASE_EDITOR_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; - const auto char_button_font_size = - BASE_CHAR_BUTTON_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; - const auto label_button_font_size = - BASE_LABEL_BUTTON_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; - - QFont header_font(QStringLiteral("MS Shell Dlg 2"), header_font_size, QFont::Normal); - QFont sub_font(QStringLiteral("MS Shell Dlg 2"), sub_font_size, QFont::Normal); - QFont editor_font(QStringLiteral("MS Shell Dlg 2"), editor_font_size, QFont::Normal); - QFont char_button_font(QStringLiteral("MS Shell Dlg 2"), char_button_font_size, QFont::Normal); - QFont label_button_font(QStringLiteral("MS Shell Dlg 2"), label_button_font_size, - QFont::Normal); - - ui->label_header->setFont(header_font); - ui->label_sub->setFont(sub_font); - ui->line_edit_osk->setFont(editor_font); - ui->text_edit_osk->setFont(editor_font); - ui->label_characters->setFont(sub_font); - ui->label_characters_box->setFont(sub_font); - - ui->label_shift->setFont(label_button_font); - ui->label_shift_shift->setFont(label_button_font); - ui->label_cancel->setFont(label_button_font); - ui->label_cancel_shift->setFont(label_button_font); - ui->label_cancel_num->setFont(label_button_font); - ui->label_enter->setFont(label_button_font); - ui->label_enter_shift->setFont(label_button_font); - ui->label_enter_num->setFont(label_button_font); - - for (auto* button : all_buttons) { - if (button == ui->button_return || button == ui->button_return_shift) { - button->setFont(label_button_font); - continue; - } - - if (button == ui->button_space || button == ui->button_space_shift) { - button->setFont(label_button_font); - continue; - } - - if (button == ui->button_shift || button == ui->button_shift_shift) { - button->setFont(label_button_font); - button->setIconSize(QSize(BASE_ICON_BUTTON_SIZE, BASE_ICON_BUTTON_SIZE) * - (height / BASE_HEIGHT)); - continue; - } - - if (button == ui->button_backspace || button == ui->button_backspace_shift || - button == ui->button_backspace_num) { - button->setFont(label_button_font); - button->setIconSize(QSize(BASE_ICON_BUTTON_SIZE, BASE_ICON_BUTTON_SIZE) * - (height / BASE_HEIGHT)); - continue; - } - - if (button == ui->button_ok || button == ui->button_ok_shift || - button == ui->button_ok_num) { - button->setFont(label_button_font); - continue; - } - - button->setFont(char_button_font); - } -} - -void QtSoftwareKeyboardDialog::SetKeyboardType() { - switch (initialize_parameters.type) { - case SwkbdType::Normal: - case SwkbdType::Qwerty: - case SwkbdType::Unknown3: - case SwkbdType::Latin: - case SwkbdType::SimplifiedChinese: - case SwkbdType::TraditionalChinese: - case SwkbdType::Korean: - default: { - bottom_osk_index = BottomOSKIndex::LowerCase; - ui->bottomOSK->setCurrentIndex(static_cast(bottom_osk_index)); - - ui->verticalLayout_2->setStretch(0, 320); - ui->verticalLayout_2->setStretch(1, 400); - - ui->gridLineOSK->setRowStretch(5, 94); - ui->gridBoxOSK->setRowStretch(2, 81); - break; - } - case SwkbdType::NumberPad: { - bottom_osk_index = BottomOSKIndex::NumberPad; - ui->bottomOSK->setCurrentIndex(static_cast(bottom_osk_index)); - - ui->verticalLayout_2->setStretch(0, 370); - ui->verticalLayout_2->setStretch(1, 350); - - ui->gridLineOSK->setRowStretch(5, 144); - ui->gridBoxOSK->setRowStretch(2, 131); - break; - } - } -} - -void QtSoftwareKeyboardDialog::SetPasswordMode() { - switch (initialize_parameters.password_mode) { - case SwkbdPasswordMode::Disabled: - default: - ui->line_edit_osk->setEchoMode(QLineEdit::Normal); - break; - case SwkbdPasswordMode::Enabled: - ui->line_edit_osk->setEchoMode(QLineEdit::Password); - break; - } -} - -void QtSoftwareKeyboardDialog::SetTextDrawType() { - switch (initialize_parameters.text_draw_type) { - case SwkbdTextDrawType::Line: - case SwkbdTextDrawType::DownloadCode: { - ui->topOSK->setCurrentIndex(0); - - if (initialize_parameters.max_text_length <= 10) { - ui->gridLineOSK->setColumnStretch(0, 390); - ui->gridLineOSK->setColumnStretch(1, 500); - ui->gridLineOSK->setColumnStretch(2, 390); - } else { - ui->gridLineOSK->setColumnStretch(0, 130); - ui->gridLineOSK->setColumnStretch(1, 1020); - ui->gridLineOSK->setColumnStretch(2, 130); - } - - if (is_inline) { - return; - } - - connect(ui->line_edit_osk, &QLineEdit::textChanged, [this](const QString& changed_string) { - const auto is_valid = ValidateInputText(changed_string); - - const auto text_length = static_cast(changed_string.length()); - - ui->label_characters->setText(QStringLiteral("%1/%2") - .arg(text_length) - .arg(initialize_parameters.max_text_length)); - - ui->button_ok->setEnabled(is_valid); - ui->button_ok_shift->setEnabled(is_valid); - ui->button_ok_num->setEnabled(is_valid); - - ui->line_edit_osk->setFocus(); - }); - - connect(ui->line_edit_osk, &QLineEdit::cursorPositionChanged, - [this](int old_cursor_position, int new_cursor_position) { - ui->button_backspace->setEnabled( - initialize_parameters.enable_backspace_button && new_cursor_position > 0); - ui->button_backspace_shift->setEnabled( - initialize_parameters.enable_backspace_button && new_cursor_position > 0); - ui->button_backspace_num->setEnabled( - initialize_parameters.enable_backspace_button && new_cursor_position > 0); - - ui->line_edit_osk->setFocus(); - }); - - connect(ui->line_edit_osk, &QLineEdit::returnPressed, [this] { - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - ui->button_ok->click(); - break; - case BottomOSKIndex::UpperCase: - ui->button_ok_shift->click(); - break; - case BottomOSKIndex::NumberPad: - ui->button_ok_num->click(); - break; - default: - break; - } - }); - - ui->line_edit_osk->setPlaceholderText( - QString::fromStdU16String(initialize_parameters.guide_text)); - ui->line_edit_osk->setText(QString::fromStdU16String(initialize_parameters.initial_text)); - ui->line_edit_osk->setMaxLength(initialize_parameters.max_text_length); - ui->line_edit_osk->setCursorPosition(initialize_parameters.initial_cursor_position); - - ui->label_characters->setText(QStringLiteral("%1/%2") - .arg(initialize_parameters.initial_text.size()) - .arg(initialize_parameters.max_text_length)); - break; - } - case SwkbdTextDrawType::Box: - default: { - ui->topOSK->setCurrentIndex(1); - - if (is_inline) { - return; - } - - connect(ui->text_edit_osk, &QTextEdit::textChanged, [this] { - if (static_cast(ui->text_edit_osk->toPlainText().length()) > - initialize_parameters.max_text_length) { - auto text_cursor = ui->text_edit_osk->textCursor(); - ui->text_edit_osk->setTextCursor(text_cursor); - text_cursor.deletePreviousChar(); - } - - const auto is_valid = ValidateInputText(ui->text_edit_osk->toPlainText()); - - const auto text_length = static_cast(ui->text_edit_osk->toPlainText().length()); - - ui->label_characters_box->setText(QStringLiteral("%1/%2") - .arg(text_length) - .arg(initialize_parameters.max_text_length)); - - ui->button_ok->setEnabled(is_valid); - ui->button_ok_shift->setEnabled(is_valid); - ui->button_ok_num->setEnabled(is_valid); - - ui->text_edit_osk->setFocus(); - }); - - connect(ui->text_edit_osk, &QTextEdit::cursorPositionChanged, [this] { - const auto new_cursor_position = ui->text_edit_osk->textCursor().position(); - - ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button && - new_cursor_position > 0); - ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button && - new_cursor_position > 0); - ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button && - new_cursor_position > 0); - - ui->text_edit_osk->setFocus(); - }); - - ui->text_edit_osk->setPlaceholderText( - QString::fromStdU16String(initialize_parameters.guide_text)); - ui->text_edit_osk->setText(QString::fromStdU16String(initialize_parameters.initial_text)); - ui->text_edit_osk->moveCursor(initialize_parameters.initial_cursor_position == 0 - ? QTextCursor::Start - : QTextCursor::End); - - ui->label_characters_box->setText(QStringLiteral("%1/%2") - .arg(initialize_parameters.initial_text.size()) - .arg(initialize_parameters.max_text_length)); - break; - } - } -} - -void QtSoftwareKeyboardDialog::SetControllerImage() { - const auto controller_type = Settings::values.players.GetValue()[8].connected - ? Settings::values.players.GetValue()[8].controller_type - : Settings::values.players.GetValue()[0].controller_type; - - const QString theme = [] { - if (QIcon::themeName().contains(QStringLiteral("dark")) || - QIcon::themeName().contains(QStringLiteral("midnight"))) { - return QStringLiteral("_dark"); - } else { - return QString{}; - } - }(); - - switch (controller_type) { - case Settings::ControllerType::ProController: - case Settings::ControllerType::GameCube: - ui->icon_controller->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); - ui->icon_controller_shift->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); - ui->icon_controller_num->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); - break; - case Settings::ControllerType::DualJoyconDetached: - ui->icon_controller->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme)); - ui->icon_controller_shift->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme)); - ui->icon_controller_num->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme)); - break; - case Settings::ControllerType::LeftJoycon: - ui->icon_controller->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);") - .arg(theme)); - ui->icon_controller_shift->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);") - .arg(theme)); - ui->icon_controller_num->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);") - .arg(theme)); - break; - case Settings::ControllerType::RightJoycon: - ui->icon_controller->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);") - .arg(theme)); - ui->icon_controller_shift->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);") - .arg(theme)); - ui->icon_controller_num->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);") - .arg(theme)); - break; - case Settings::ControllerType::Handheld: - ui->icon_controller->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme)); - ui->icon_controller_shift->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme)); - ui->icon_controller_num->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme)); - break; - default: - break; - } -} - -void QtSoftwareKeyboardDialog::DisableKeyboardButtons() { - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - case BottomOSKIndex::UpperCase: - default: { - for (const auto& keys : keyboard_buttons) { - for (const auto& rows : keys) { - for (auto* button : rows) { - if (!button) { - continue; - } - - button->setEnabled(true); - } - } - } - - const auto& key_disable_flags = initialize_parameters.key_disable_flags; - - ui->button_space->setDisabled(key_disable_flags.space); - ui->button_space_shift->setDisabled(key_disable_flags.space); - - ui->button_at->setDisabled(key_disable_flags.at || key_disable_flags.username); - - ui->button_percent->setDisabled(key_disable_flags.percent || key_disable_flags.username); - - ui->button_slash->setDisabled(key_disable_flags.slash); - - ui->button_1->setDisabled(key_disable_flags.numbers); - ui->button_2->setDisabled(key_disable_flags.numbers); - ui->button_3->setDisabled(key_disable_flags.numbers); - ui->button_4->setDisabled(key_disable_flags.numbers); - ui->button_5->setDisabled(key_disable_flags.numbers); - ui->button_6->setDisabled(key_disable_flags.numbers); - ui->button_7->setDisabled(key_disable_flags.numbers); - ui->button_8->setDisabled(key_disable_flags.numbers); - ui->button_9->setDisabled(key_disable_flags.numbers); - ui->button_0->setDisabled(key_disable_flags.numbers); - - ui->button_return->setEnabled(initialize_parameters.enable_return_button); - ui->button_return_shift->setEnabled(initialize_parameters.enable_return_button); - break; - } - case BottomOSKIndex::NumberPad: { - for (const auto& rows : numberpad_buttons) { - for (auto* button : rows) { - if (!button) { - continue; - } - - button->setEnabled(true); - } - } - break; - } - } -} - -void QtSoftwareKeyboardDialog::SetBackspaceOkEnabled() { - if (is_inline) { - ui->button_ok->setEnabled(current_text.size() >= initialize_parameters.min_text_length); - ui->button_ok_shift->setEnabled(current_text.size() >= - initialize_parameters.min_text_length); - ui->button_ok_num->setEnabled(current_text.size() >= initialize_parameters.min_text_length); - - ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button && - cursor_position > 0); - ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button && - cursor_position > 0); - ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button && - cursor_position > 0); - } else { - const auto text_length = [this] { - if (ui->topOSK->currentIndex() == 1) { - return static_cast(ui->text_edit_osk->toPlainText().length()); - } else { - return static_cast(ui->line_edit_osk->text().length()); - } - }(); - - const auto normal_cursor_position = [this] { - if (ui->topOSK->currentIndex() == 1) { - return ui->text_edit_osk->textCursor().position(); - } else { - return ui->line_edit_osk->cursorPosition(); - } - }(); - - ui->button_ok->setEnabled(text_length >= initialize_parameters.min_text_length); - ui->button_ok_shift->setEnabled(text_length >= initialize_parameters.min_text_length); - ui->button_ok_num->setEnabled(text_length >= initialize_parameters.min_text_length); - - ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button && - normal_cursor_position > 0); - ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button && - normal_cursor_position > 0); - ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button && - normal_cursor_position > 0); - } -} - -bool QtSoftwareKeyboardDialog::ValidateInputText(const QString& input_text) { - const auto& key_disable_flags = initialize_parameters.key_disable_flags; - - const auto input_text_length = static_cast(input_text.length()); - - if (input_text_length < initialize_parameters.min_text_length || - input_text_length > initialize_parameters.max_text_length) { - return false; - } - - if (key_disable_flags.space && input_text.contains(QLatin1Char{' '})) { - return false; - } - - if ((key_disable_flags.at || key_disable_flags.username) && - input_text.contains(QLatin1Char{'@'})) { - return false; - } - - if ((key_disable_flags.percent || key_disable_flags.username) && - input_text.contains(QLatin1Char{'%'})) { - return false; - } - - if (key_disable_flags.slash && input_text.contains(QLatin1Char{'/'})) { - return false; - } - - if ((key_disable_flags.backslash || key_disable_flags.username) && - input_text.contains(QLatin1Char('\\'))) { - return false; - } - - if (key_disable_flags.numbers && - std::any_of(input_text.begin(), input_text.end(), [](QChar c) { return c.isDigit(); })) { - return false; - } - - if (bottom_osk_index == BottomOSKIndex::NumberPad && - std::any_of(input_text.begin(), input_text.end(), [](QChar c) { return !c.isDigit(); })) { - return false; - } - - return true; -} - -void QtSoftwareKeyboardDialog::ChangeBottomOSKIndex() { - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - bottom_osk_index = BottomOSKIndex::UpperCase; - ui->bottomOSK->setCurrentIndex(static_cast(bottom_osk_index)); - - ui->button_shift_shift->setStyleSheet( - QStringLiteral("background-image: url(:/overlay/osk_button_shift_lock_off.png);" - "\nbackground-position: left top;" - "\nbackground-repeat: no-repeat;" - "\nbackground-origin: content;")); - - ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); - ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); - break; - case BottomOSKIndex::UpperCase: - if (caps_lock_enabled) { - caps_lock_enabled = false; - - ui->button_shift_shift->setStyleSheet( - QStringLiteral("background-image: url(:/overlay/osk_button_shift_lock_off.png);" - "\nbackground-position: left top;" - "\nbackground-repeat: no-repeat;" - "\nbackground-origin: content;")); - - ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); - ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); - - ui->label_shift_shift->setText(QStringLiteral("Caps Lock")); - - bottom_osk_index = BottomOSKIndex::LowerCase; - ui->bottomOSK->setCurrentIndex(static_cast(bottom_osk_index)); - } else { - caps_lock_enabled = true; - - ui->button_shift_shift->setStyleSheet( - QStringLiteral("background-image: url(:/overlay/osk_button_shift_lock_on.png);" - "\nbackground-position: left top;" - "\nbackground-repeat: no-repeat;" - "\nbackground-origin: content;")); - - ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); - ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); - - ui->label_shift_shift->setText(QStringLiteral("Caps Lock Off")); - } - break; - case BottomOSKIndex::NumberPad: - default: - break; - } -} - -void QtSoftwareKeyboardDialog::NormalKeyboardButtonClicked(QPushButton* button) { - if (button == ui->button_ampersand) { - if (ui->topOSK->currentIndex() == 1) { - ui->text_edit_osk->insertPlainText(QStringLiteral("&")); - } else { - ui->line_edit_osk->insert(QStringLiteral("&")); - } - return; - } - - if (button == ui->button_return || button == ui->button_return_shift) { - if (ui->topOSK->currentIndex() == 1) { - ui->text_edit_osk->insertPlainText(QStringLiteral("\n")); - } else { - ui->line_edit_osk->insert(QStringLiteral("\n")); - } - return; - } - - if (button == ui->button_space || button == ui->button_space_shift) { - if (ui->topOSK->currentIndex() == 1) { - ui->text_edit_osk->insertPlainText(QStringLiteral(" ")); - } else { - ui->line_edit_osk->insert(QStringLiteral(" ")); - } - return; - } - - if (button == ui->button_shift || button == ui->button_shift_shift) { - ChangeBottomOSKIndex(); - return; - } - - if (button == ui->button_backspace || button == ui->button_backspace_shift || - button == ui->button_backspace_num) { - if (ui->topOSK->currentIndex() == 1) { - auto text_cursor = ui->text_edit_osk->textCursor(); - ui->text_edit_osk->setTextCursor(text_cursor); - text_cursor.deletePreviousChar(); - } else { - ui->line_edit_osk->backspace(); - } - return; - } - - if (button == ui->button_ok || button == ui->button_ok_shift || button == ui->button_ok_num) { - if (ui->topOSK->currentIndex() == 1) { - emit SubmitNormalText(SwkbdResult::Ok, - ui->text_edit_osk->toPlainText().toStdU16String()); - } else { - emit SubmitNormalText(SwkbdResult::Ok, ui->line_edit_osk->text().toStdU16String()); - } - return; - } - - if (ui->topOSK->currentIndex() == 1) { - ui->text_edit_osk->insertPlainText(button->text()); - } else { - ui->line_edit_osk->insert(button->text()); - } - - // Revert the keyboard to lowercase if the shift key is active. - if (bottom_osk_index == BottomOSKIndex::UpperCase && !caps_lock_enabled) { - // This is set to true since ChangeBottomOSKIndex will change bottom_osk_index to LowerCase - // if bottom_osk_index is UpperCase and caps_lock_enabled is true. - caps_lock_enabled = true; - ChangeBottomOSKIndex(); - } -} - -void QtSoftwareKeyboardDialog::InlineKeyboardButtonClicked(QPushButton* button) { - if (!button->isEnabled()) { - return; - } - - if (button == ui->button_ampersand) { - InlineTextInsertString(u"&"); - return; - } - - if (button == ui->button_return || button == ui->button_return_shift) { - InlineTextInsertString(u"\n"); - return; - } - - if (button == ui->button_space || button == ui->button_space_shift) { - InlineTextInsertString(u" "); - return; - } - - if (button == ui->button_shift || button == ui->button_shift_shift) { - ChangeBottomOSKIndex(); - return; - } - - if (button == ui->button_backspace || button == ui->button_backspace_shift || - button == ui->button_backspace_num) { - if (cursor_position <= 0 || current_text.empty()) { - cursor_position = 0; - return; - } - - --cursor_position; - - current_text.erase(cursor_position, 1); - - SetBackspaceOkEnabled(); - - emit SubmitInlineText(SwkbdReplyType::ChangedString, current_text, cursor_position); - return; - } - - if (button == ui->button_ok || button == ui->button_ok_shift || button == ui->button_ok_num) { - emit SubmitInlineText(SwkbdReplyType::DecidedEnter, current_text, cursor_position); - return; - } - - InlineTextInsertString(button->text().toStdU16String()); - - // Revert the keyboard to lowercase if the shift key is active. - if (bottom_osk_index == BottomOSKIndex::UpperCase && !caps_lock_enabled) { - // This is set to true since ChangeBottomOSKIndex will change bottom_osk_index to LowerCase - // if bottom_osk_index is UpperCase and caps_lock_enabled is true. - caps_lock_enabled = true; - ChangeBottomOSKIndex(); - } -} - -void QtSoftwareKeyboardDialog::InlineTextInsertString(std::u16string_view string) { - if ((current_text.size() + string.size()) > initialize_parameters.max_text_length) { - return; - } - - current_text.insert(cursor_position, string); - - cursor_position += static_cast(string.size()); - - SetBackspaceOkEnabled(); - - emit SubmitInlineText(SwkbdReplyType::ChangedString, current_text, cursor_position); -} - -void QtSoftwareKeyboardDialog::SetupMouseHover() { - // setFocus() has a bug where continuously changing focus will cause the focus UI to - // mysteriously disappear. A workaround we have found is using the mouse to hover over - // the buttons to act in place of the button focus. As a result, we will have to set - // a blank cursor when hovering over all the buttons and set a no focus policy so the - // buttons do not stay in focus in addition to the mouse hover. - for (auto* button : all_buttons) { - button->setCursor(QCursor(Qt::BlankCursor)); - button->setFocusPolicy(Qt::NoFocus); - } -} - -template -void QtSoftwareKeyboardDialog::HandleButtonPressedOnce() { - const auto f = [this](HIDButton button) { - if (input_interpreter->IsButtonPressedOnce(button)) { - TranslateButtonPress(button); - } - }; - - (f(T), ...); -} - -template -void QtSoftwareKeyboardDialog::HandleButtonHold() { - const auto f = [this](HIDButton button) { - if (input_interpreter->IsButtonHeld(button)) { - TranslateButtonPress(button); - } - }; - - (f(T), ...); -} - -void QtSoftwareKeyboardDialog::TranslateButtonPress(HIDButton button) { - switch (button) { - case HIDButton::A: - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - case BottomOSKIndex::UpperCase: - keyboard_buttons[static_cast(bottom_osk_index)][row][column]->click(); - break; - case BottomOSKIndex::NumberPad: - numberpad_buttons[row][column]->click(); - break; - default: - break; - } - break; - case HIDButton::B: - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - ui->button_backspace->click(); - break; - case BottomOSKIndex::UpperCase: - ui->button_backspace_shift->click(); - break; - case BottomOSKIndex::NumberPad: - ui->button_backspace_num->click(); - break; - default: - break; - } - break; - case HIDButton::X: - if (is_inline) { - emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position); - } else { - if (ui->topOSK->currentIndex() == 1) { - emit SubmitNormalText(SwkbdResult::Cancel, - ui->text_edit_osk->toPlainText().toStdU16String()); - } else { - emit SubmitNormalText(SwkbdResult::Cancel, - ui->line_edit_osk->text().toStdU16String()); - } - } - break; - case HIDButton::Y: - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - ui->button_space->click(); - break; - case BottomOSKIndex::UpperCase: - ui->button_space_shift->click(); - break; - case BottomOSKIndex::NumberPad: - default: - break; - } - break; - case HIDButton::LStick: - case HIDButton::RStick: - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - ui->button_shift->click(); - break; - case BottomOSKIndex::UpperCase: - ui->button_shift_shift->click(); - break; - case BottomOSKIndex::NumberPad: - default: - break; - } - break; - case HIDButton::L: - MoveTextCursorDirection(Direction::Left); - break; - case HIDButton::R: - MoveTextCursorDirection(Direction::Right); - break; - case HIDButton::Plus: - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - ui->button_ok->click(); - break; - case BottomOSKIndex::UpperCase: - ui->button_ok_shift->click(); - break; - case BottomOSKIndex::NumberPad: - ui->button_ok_num->click(); - break; - default: - break; - } - break; - case HIDButton::DLeft: - case HIDButton::LStickLeft: - case HIDButton::RStickLeft: - MoveButtonDirection(Direction::Left); - break; - case HIDButton::DUp: - case HIDButton::LStickUp: - case HIDButton::RStickUp: - MoveButtonDirection(Direction::Up); - break; - case HIDButton::DRight: - case HIDButton::LStickRight: - case HIDButton::RStickRight: - MoveButtonDirection(Direction::Right); - break; - case HIDButton::DDown: - case HIDButton::LStickDown: - case HIDButton::RStickDown: - MoveButtonDirection(Direction::Down); - break; - default: - break; - } -} - -void QtSoftwareKeyboardDialog::MoveButtonDirection(Direction direction) { - // Changes the row or column index depending on the direction. - auto move_direction = [this, direction](std::size_t max_rows, std::size_t max_columns) { - switch (direction) { - case Direction::Left: - column = (column + max_columns - 1) % max_columns; - break; - case Direction::Up: - row = (row + max_rows - 1) % max_rows; - break; - case Direction::Right: - column = (column + 1) % max_columns; - break; - case Direction::Down: - row = (row + 1) % max_rows; - break; - default: - break; - } - }; - - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - case BottomOSKIndex::UpperCase: { - const auto index = static_cast(bottom_osk_index); - - const auto* const prev_button = keyboard_buttons[index][row][column]; - move_direction(NUM_ROWS_NORMAL, NUM_COLUMNS_NORMAL); - auto* curr_button = keyboard_buttons[index][row][column]; - - while (!curr_button || !curr_button->isEnabled() || curr_button == prev_button) { - move_direction(NUM_ROWS_NORMAL, NUM_COLUMNS_NORMAL); - curr_button = keyboard_buttons[index][row][column]; - } - - // This is a workaround for setFocus() randomly not showing focus in the UI - QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center())); - break; - } - case BottomOSKIndex::NumberPad: { - const auto* const prev_button = numberpad_buttons[row][column]; - move_direction(NUM_ROWS_NUMPAD, NUM_COLUMNS_NUMPAD); - auto* curr_button = numberpad_buttons[row][column]; - - while (!curr_button || !curr_button->isEnabled() || curr_button == prev_button) { - move_direction(NUM_ROWS_NUMPAD, NUM_COLUMNS_NUMPAD); - curr_button = numberpad_buttons[row][column]; - } - - // This is a workaround for setFocus() randomly not showing focus in the UI - QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center())); - break; - } - default: - break; - } -} - -void QtSoftwareKeyboardDialog::MoveTextCursorDirection(Direction direction) { - switch (direction) { - case Direction::Left: - if (is_inline) { - if (cursor_position <= 0) { - cursor_position = 0; - } else { - --cursor_position; - emit SubmitInlineText(SwkbdReplyType::MovedCursor, current_text, cursor_position); - } - } else { - if (ui->topOSK->currentIndex() == 1) { - ui->text_edit_osk->moveCursor(QTextCursor::Left); - } else { - ui->line_edit_osk->setCursorPosition(ui->line_edit_osk->cursorPosition() - 1); - } - } - break; - case Direction::Right: - if (is_inline) { - if (cursor_position >= static_cast(current_text.size())) { - cursor_position = static_cast(current_text.size()); - } else { - ++cursor_position; - emit SubmitInlineText(SwkbdReplyType::MovedCursor, current_text, cursor_position); - } - } else { - if (ui->topOSK->currentIndex() == 1) { - ui->text_edit_osk->moveCursor(QTextCursor::Right); - } else { - ui->line_edit_osk->setCursorPosition(ui->line_edit_osk->cursorPosition() + 1); - } - } - break; - default: - break; - } -} - -void QtSoftwareKeyboardDialog::StartInputThread() { - if (input_thread_running) { - return; - } - - input_thread_running = true; - - input_thread = std::thread(&QtSoftwareKeyboardDialog::InputThread, this); -} - -void QtSoftwareKeyboardDialog::StopInputThread() { - input_thread_running = false; - - if (input_thread.joinable()) { - input_thread.join(); - } - - if (input_interpreter) { - input_interpreter->ResetButtonStates(); - } -} - -void QtSoftwareKeyboardDialog::InputThread() { - while (input_thread_running) { - input_interpreter->PollInput(); - - HandleButtonPressedOnce(); - - HandleButtonHold(); - - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - } +std::u16string QtSoftwareKeyboardDialog::GetText() const { + return text; } QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& main_window) { - connect(this, &QtSoftwareKeyboard::MainWindowInitializeKeyboard, &main_window, - &GMainWindow::SoftwareKeyboardInitialize, Qt::QueuedConnection); - connect(this, &QtSoftwareKeyboard::MainWindowShowNormalKeyboard, &main_window, - &GMainWindow::SoftwareKeyboardShowNormal, Qt::QueuedConnection); - connect(this, &QtSoftwareKeyboard::MainWindowShowTextCheckDialog, &main_window, - &GMainWindow::SoftwareKeyboardShowTextCheck, Qt::QueuedConnection); - connect(this, &QtSoftwareKeyboard::MainWindowShowInlineKeyboard, &main_window, - &GMainWindow::SoftwareKeyboardShowInline, Qt::QueuedConnection); - connect(this, &QtSoftwareKeyboard::MainWindowHideInlineKeyboard, &main_window, - &GMainWindow::SoftwareKeyboardHideInline, Qt::QueuedConnection); - connect(this, &QtSoftwareKeyboard::MainWindowInlineTextChanged, &main_window, - &GMainWindow::SoftwareKeyboardInlineTextChanged, Qt::QueuedConnection); - connect(this, &QtSoftwareKeyboard::MainWindowExitKeyboard, &main_window, - &GMainWindow::SoftwareKeyboardExit, Qt::QueuedConnection); - connect(&main_window, &GMainWindow::SoftwareKeyboardSubmitNormalText, this, - &QtSoftwareKeyboard::SubmitNormalText, Qt::QueuedConnection); - connect(&main_window, &GMainWindow::SoftwareKeyboardSubmitInlineText, this, - &QtSoftwareKeyboard::SubmitInlineText, Qt::QueuedConnection); + connect(this, &QtSoftwareKeyboard::MainWindowGetText, &main_window, + &GMainWindow::SoftwareKeyboardGetText, Qt::QueuedConnection); + connect(this, &QtSoftwareKeyboard::MainWindowTextCheckDialog, &main_window, + &GMainWindow::SoftwareKeyboardInvokeCheckDialog, Qt::BlockingQueuedConnection); + connect(&main_window, &GMainWindow::SoftwareKeyboardFinishedText, this, + &QtSoftwareKeyboard::MainWindowFinishedText, Qt::QueuedConnection); } QtSoftwareKeyboard::~QtSoftwareKeyboard() = default; -void QtSoftwareKeyboard::InitializeKeyboard( - bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters, - std::function submit_normal_callback_, - std::function - submit_inline_callback_) { - if (is_inline) { - submit_inline_callback = std::move(submit_inline_callback_); - } else { - submit_normal_callback = std::move(submit_normal_callback_); - } - - LOG_INFO(Service_AM, - "\nKeyboardInitializeParameters:" - "\nok_text={}" - "\nheader_text={}" - "\nsub_text={}" - "\nguide_text={}" - "\ninitial_text={}" - "\nmax_text_length={}" - "\nmin_text_length={}" - "\ninitial_cursor_position={}" - "\ntype={}" - "\npassword_mode={}" - "\ntext_draw_type={}" - "\nkey_disable_flags={}" - "\nuse_blur_background={}" - "\nenable_backspace_button={}" - "\nenable_return_button={}" - "\ndisable_cancel_button={}", - Common::UTF16ToUTF8(initialize_parameters.ok_text), - Common::UTF16ToUTF8(initialize_parameters.header_text), - Common::UTF16ToUTF8(initialize_parameters.sub_text), - Common::UTF16ToUTF8(initialize_parameters.guide_text), - Common::UTF16ToUTF8(initialize_parameters.initial_text), - initialize_parameters.max_text_length, initialize_parameters.min_text_length, - initialize_parameters.initial_cursor_position, initialize_parameters.type, - initialize_parameters.password_mode, initialize_parameters.text_draw_type, - initialize_parameters.key_disable_flags.raw, initialize_parameters.use_blur_background, - initialize_parameters.enable_backspace_button, - initialize_parameters.enable_return_button, - initialize_parameters.disable_cancel_button); - - emit MainWindowInitializeKeyboard(is_inline, std::move(initialize_parameters)); +void QtSoftwareKeyboard::RequestText(std::function)> out, + Core::Frontend::SoftwareKeyboardParameters parameters) const { + text_output = std::move(out); + emit MainWindowGetText(parameters); } -void QtSoftwareKeyboard::ShowNormalKeyboard() const { - emit MainWindowShowNormalKeyboard(); +void QtSoftwareKeyboard::SendTextCheckDialog(std::u16string error_message, + std::function finished_check_) const { + finished_check = std::move(finished_check_); + emit MainWindowTextCheckDialog(error_message); } -void QtSoftwareKeyboard::ShowTextCheckDialog( - Service::AM::Applets::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message) const { - emit MainWindowShowTextCheckDialog(text_check_result, text_check_message); +void QtSoftwareKeyboard::MainWindowFinishedText(std::optional text) { + // Acquire the HLE mutex + std::lock_guard lock{HLE::g_hle_lock}; + text_output(std::move(text)); } -void QtSoftwareKeyboard::ShowInlineKeyboard( - Core::Frontend::InlineAppearParameters appear_parameters) const { - LOG_INFO(Service_AM, - "\nInlineAppearParameters:" - "\nmax_text_length={}" - "\nmin_text_length={}" - "\nkey_top_scale_x={}" - "\nkey_top_scale_y={}" - "\nkey_top_translate_x={}" - "\nkey_top_translate_y={}" - "\ntype={}" - "\nkey_disable_flags={}" - "\nkey_top_as_floating={}" - "\nenable_backspace_button={}" - "\nenable_return_button={}" - "\ndisable_cancel_button={}", - appear_parameters.max_text_length, appear_parameters.min_text_length, - appear_parameters.key_top_scale_x, appear_parameters.key_top_scale_y, - appear_parameters.key_top_translate_x, appear_parameters.key_top_translate_y, - appear_parameters.type, appear_parameters.key_disable_flags.raw, - appear_parameters.key_top_as_floating, appear_parameters.enable_backspace_button, - appear_parameters.enable_return_button, appear_parameters.disable_cancel_button); - - emit MainWindowShowInlineKeyboard(std::move(appear_parameters)); -} - -void QtSoftwareKeyboard::HideInlineKeyboard() const { - emit MainWindowHideInlineKeyboard(); -} - -void QtSoftwareKeyboard::InlineTextChanged( - Core::Frontend::InlineTextParameters text_parameters) const { - LOG_INFO(Service_AM, - "\nInlineTextParameters:" - "\ninput_text={}" - "\ncursor_position={}", - Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position); - - emit MainWindowInlineTextChanged(std::move(text_parameters)); -} - -void QtSoftwareKeyboard::ExitKeyboard() const { - emit MainWindowExitKeyboard(); -} - -void QtSoftwareKeyboard::SubmitNormalText(Service::AM::Applets::SwkbdResult result, - std::u16string submitted_text) const { - submit_normal_callback(result, submitted_text); -} - -void QtSoftwareKeyboard::SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, - std::u16string submitted_text, - s32 cursor_position) const { - submit_inline_callback(reply_type, submitted_text, cursor_position); +void QtSoftwareKeyboard::MainWindowFinishedCheckDialog() { + // Acquire the HLE mutex + std::lock_guard lock{HLE::g_hle_lock}; + finished_check(); } diff --git a/src/yuzu/applets/software_keyboard.h b/src/yuzu/applets/software_keyboard.h index 1a03c098c..9e1094cce 100755 --- a/src/yuzu/applets/software_keyboard.h +++ b/src/yuzu/applets/software_keyboard.h @@ -1,228 +1,54 @@ -// Copyright 2021 yuzu Emulator Project +// Copyright 2018 yuzu Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #pragma once -#include -#include -#include -#include - #include #include - #include "core/frontend/applets/software_keyboard.h" -enum class HIDButton : u8; - -class InputInterpreter; - -namespace Core { -class System; -} - -namespace Ui { -class QtSoftwareKeyboardDialog; -} - class GMainWindow; +class QDialogButtonBox; +class QLabel; +class QLineEdit; +class QVBoxLayout; +class QtSoftwareKeyboard; + +class QtSoftwareKeyboardValidator final : public QValidator { +public: + explicit QtSoftwareKeyboardValidator(Core::Frontend::SoftwareKeyboardParameters parameters); + State validate(QString& input, int& pos) const override; + +private: + Core::Frontend::SoftwareKeyboardParameters parameters; +}; class QtSoftwareKeyboardDialog final : public QDialog { Q_OBJECT public: - QtSoftwareKeyboardDialog(QWidget* parent, Core::System& system_, bool is_inline_, - Core::Frontend::KeyboardInitializeParameters initialize_parameters_); + QtSoftwareKeyboardDialog(QWidget* parent, + Core::Frontend::SoftwareKeyboardParameters parameters); ~QtSoftwareKeyboardDialog() override; - void ShowNormalKeyboard(QPoint pos, QSize size); - - void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message); - - void ShowInlineKeyboard(Core::Frontend::InlineAppearParameters appear_parameters, QPoint pos, - QSize size); - - void HideInlineKeyboard(); - - void InlineTextChanged(Core::Frontend::InlineTextParameters text_parameters); - - void ExitKeyboard(); - -signals: - void SubmitNormalText(Service::AM::Applets::SwkbdResult result, - std::u16string submitted_text) const; - - void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, - std::u16string submitted_text, s32 cursor_position) const; - -public slots: - void open() override; + void accept() override; void reject() override; -protected: - /// We override the keyPressEvent for inputting text into the inline software keyboard. - void keyPressEvent(QKeyEvent* event) override; + std::u16string GetText() const; private: - enum class Direction { - Left, - Up, - Right, - Down, - }; + std::u16string text; - enum class BottomOSKIndex { - LowerCase, - UpperCase, - NumberPad, - }; + QDialogButtonBox* buttons; + QLabel* header_label; + QLabel* sub_label; + QLabel* guide_label; + QLabel* length_label; + QLineEdit* line_edit; + QVBoxLayout* layout; - /** - * Moves and resizes the window to a specified position and size. - * - * @param pos Top-left window position - * @param size Window size - */ - void MoveAndResizeWindow(QPoint pos, QSize size); - - /** - * Rescales all keyboard elements to account for High DPI displays. - * - * @param width Window width - * @param height Window height - * @param dpi_scale Display scaling factor - */ - void RescaleKeyboardElements(float width, float height, float dpi_scale); - - /// Sets the keyboard type based on initialize_parameters. - void SetKeyboardType(); - - /// Sets the password mode based on initialize_parameters. - void SetPasswordMode(); - - /// Sets the text draw type based on initialize_parameters. - void SetTextDrawType(); - - /// Sets the controller image at the bottom left of the software keyboard. - void SetControllerImage(); - - /// Disables buttons based on initialize_parameters. - void DisableKeyboardButtons(); - - /// Changes whether the backspace or/and ok buttons should be enabled or disabled. - void SetBackspaceOkEnabled(); - - /** - * Validates the input text sent in based on the parameters in initialize_parameters. - * - * @param input_text Input text - * - * @returns True if the input text is valid, false otherwise. - */ - bool ValidateInputText(const QString& input_text); - - /// Switches between LowerCase and UpperCase (Shift and Caps Lock) - void ChangeBottomOSKIndex(); - - /// Processes a keyboard button click from the UI as normal keyboard input. - void NormalKeyboardButtonClicked(QPushButton* button); - - /// Processes a keyboard button click from the UI as inline keyboard input. - void InlineKeyboardButtonClicked(QPushButton* button); - - /** - * Inserts a string of arbitrary length into the current_text at the current cursor position. - * This is only used for the inline software keyboard. - */ - void InlineTextInsertString(std::u16string_view string); - - /// Setup the mouse hover workaround for "focusing" buttons. This should only be called once. - void SetupMouseHover(); - - /** - * Handles button presses and converts them into keyboard input. - * - * @tparam HIDButton The list of buttons that can be converted into keyboard input. - */ - template - void HandleButtonPressedOnce(); - - /** - * Handles button holds and converts them into keyboard input. - * - * @tparam HIDButton The list of buttons that can be converted into keyboard input. - */ - template - void HandleButtonHold(); - - /** - * Translates a button press to focus or click a keyboard button. - * - * @param button The button press to process. - */ - void TranslateButtonPress(HIDButton button); - - /** - * Moves the focus of a button in a certain direction. - * - * @param direction The direction to move. - */ - void MoveButtonDirection(Direction direction); - - /** - * Moves the text cursor in a certain direction. - * - * @param direction The direction to move. - */ - void MoveTextCursorDirection(Direction direction); - - void StartInputThread(); - void StopInputThread(); - - /// The thread where input is being polled and processed. - void InputThread(); - - std::unique_ptr ui; - - Core::System& system; - - // True if it is the inline software keyboard. - bool is_inline; - - // Common software keyboard initialize parameters. - Core::Frontend::KeyboardInitializeParameters initialize_parameters; - - // Used only by the inline software keyboard since the QLineEdit or QTextEdit is hidden. - std::u16string current_text; - s32 cursor_position{0}; - - static constexpr std::size_t NUM_ROWS_NORMAL = 5; - static constexpr std::size_t NUM_COLUMNS_NORMAL = 12; - static constexpr std::size_t NUM_ROWS_NUMPAD = 4; - static constexpr std::size_t NUM_COLUMNS_NUMPAD = 4; - - // Stores the normal keyboard layout. - std::array, NUM_ROWS_NORMAL>, 2> - keyboard_buttons; - // Stores the numberpad keyboard layout. - std::array, NUM_ROWS_NUMPAD> numberpad_buttons; - - // Contains a set of all buttons used in keyboard_buttons and numberpad_buttons. - std::array all_buttons; - - std::size_t row{0}; - std::size_t column{0}; - - BottomOSKIndex bottom_osk_index{BottomOSKIndex::LowerCase}; - std::atomic caps_lock_enabled{false}; - - std::unique_ptr input_interpreter; - - std::thread input_thread; - - std::atomic input_thread_running{}; + Core::Frontend::SoftwareKeyboardParameters parameters; }; class QtSoftwareKeyboard final : public QObject, public Core::Frontend::SoftwareKeyboardApplet { @@ -232,54 +58,19 @@ public: explicit QtSoftwareKeyboard(GMainWindow& parent); ~QtSoftwareKeyboard() override; - void InitializeKeyboard( - bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters, - std::function - submit_normal_callback_, - std::function - submit_inline_callback_) override; - - void ShowNormalKeyboard() const override; - - void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message) const override; - - void ShowInlineKeyboard( - Core::Frontend::InlineAppearParameters appear_parameters) const override; - - void HideInlineKeyboard() const override; - - void InlineTextChanged(Core::Frontend::InlineTextParameters text_parameters) const override; - - void ExitKeyboard() const override; + void RequestText(std::function)> out, + Core::Frontend::SoftwareKeyboardParameters parameters) const override; + void SendTextCheckDialog(std::u16string error_message, + std::function finished_check_) const override; signals: - void MainWindowInitializeKeyboard( - bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters) const; - - void MainWindowShowNormalKeyboard() const; - - void MainWindowShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message) const; - - void MainWindowShowInlineKeyboard( - Core::Frontend::InlineAppearParameters appear_parameters) const; - - void MainWindowHideInlineKeyboard() const; - - void MainWindowInlineTextChanged(Core::Frontend::InlineTextParameters text_parameters) const; - - void MainWindowExitKeyboard() const; + void MainWindowGetText(Core::Frontend::SoftwareKeyboardParameters parameters) const; + void MainWindowTextCheckDialog(std::u16string error_message) const; private: - void SubmitNormalText(Service::AM::Applets::SwkbdResult result, - std::u16string submitted_text) const; + void MainWindowFinishedText(std::optional text); + void MainWindowFinishedCheckDialog(); - void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, - std::u16string submitted_text, s32 cursor_position) const; - - mutable std::function - submit_normal_callback; - mutable std::function - submit_inline_callback; + mutable std::function)> text_output; + mutable std::function finished_check; }; diff --git a/src/yuzu/discord_impl.cpp b/src/yuzu/discord_impl.cpp index aad06ac2a..a93733b26 100755 --- a/src/yuzu/discord_impl.cpp +++ b/src/yuzu/discord_impl.cpp @@ -38,7 +38,7 @@ void DiscordImpl::Update() { if (Core::System::GetInstance().IsPoweredOn()) Core::System::GetInstance().GetAppLoader().ReadTitle(title); DiscordRichPresence presence{}; - presence.largeImageKey = "yuzu_logo_ea"; + presence.largeImageKey = "yuzu_logo"; presence.largeImageText = "yuzu is an emulator for the Nintendo Switch"; if (Core::System::GetInstance().IsPoweredOn()) { presence.state = title.c_str(); diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f66b6c476..23ea4983d 100755 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -101,7 +101,6 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include "core/settings.h" #include "core/telemetry_session.h" #include "input_common/main.h" -#include "util/overlay_dialog.h" #include "video_core/gpu.h" #include "video_core/shader_notify.h" #include "yuzu/about_dialog.h" @@ -226,8 +225,6 @@ GMainWindow::GMainWindow() SetDiscordEnabled(UISettings::values.enable_discord_presence); discord_rpc->Update(); - RegisterMetaTypes(); - InitializeWidgets(); InitializeDebugWidgets(); InitializeRecentFileMenuActions(); @@ -376,55 +373,6 @@ GMainWindow::~GMainWindow() { delete render_window; } -void GMainWindow::RegisterMetaTypes() { - // Register integral and floating point types - qRegisterMetaType("u8"); - qRegisterMetaType("u16"); - qRegisterMetaType("u32"); - qRegisterMetaType("u64"); - qRegisterMetaType("u128"); - qRegisterMetaType("s8"); - qRegisterMetaType("s16"); - qRegisterMetaType("s32"); - qRegisterMetaType("s64"); - qRegisterMetaType("f32"); - qRegisterMetaType("f64"); - - // Register string types - qRegisterMetaType("std::string"); - qRegisterMetaType("std::wstring"); - qRegisterMetaType("std::u8string"); - qRegisterMetaType("std::u16string"); - qRegisterMetaType("std::u32string"); - qRegisterMetaType("std::string_view"); - qRegisterMetaType("std::wstring_view"); - qRegisterMetaType("std::u8string_view"); - qRegisterMetaType("std::u16string_view"); - qRegisterMetaType("std::u32string_view"); - - // Register applet types - - // Controller Applet - qRegisterMetaType("Core::Frontend::ControllerParameters"); - - // Software Keyboard Applet - qRegisterMetaType( - "Core::Frontend::KeyboardInitializeParameters"); - qRegisterMetaType( - "Core::Frontend::InlineAppearParameters"); - qRegisterMetaType("Core::Frontend::InlineTextParameters"); - qRegisterMetaType("Service::AM::Applets::SwkbdResult"); - qRegisterMetaType( - "Service::AM::Applets::SwkbdTextCheckResult"); - qRegisterMetaType("Service::AM::Applets::SwkbdReplyType"); - - // Web Browser Applet - qRegisterMetaType("Service::AM::Applets::WebExitReason"); - - // Register loader types - qRegisterMetaType("Core::System::ResultStatus"); -} - void GMainWindow::ControllerSelectorReconfigureControllers( const Core::Frontend::ControllerParameters& parameters) { QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get()); @@ -464,112 +412,25 @@ void GMainWindow::ProfileSelectorSelectProfile() { emit ProfileSelectorFinishedSelection(uuid); } -void GMainWindow::SoftwareKeyboardInitialize( - bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters) { - if (software_keyboard) { - LOG_ERROR(Frontend, "The software keyboard is already initialized!"); +void GMainWindow::SoftwareKeyboardGetText( + const Core::Frontend::SoftwareKeyboardParameters& parameters) { + QtSoftwareKeyboardDialog dialog(this, parameters); + dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | + Qt::WindowTitleHint | Qt::WindowSystemMenuHint | + Qt::WindowCloseButtonHint); + dialog.setWindowModality(Qt::WindowModal); + + if (dialog.exec() == QDialog::Rejected) { + emit SoftwareKeyboardFinishedText(std::nullopt); return; } - software_keyboard = new QtSoftwareKeyboardDialog(render_window, Core::System::GetInstance(), - is_inline, std::move(initialize_parameters)); - - if (is_inline) { - connect( - software_keyboard, &QtSoftwareKeyboardDialog::SubmitInlineText, this, - [this](Service::AM::Applets::SwkbdReplyType reply_type, std::u16string submitted_text, - s32 cursor_position) { - emit SoftwareKeyboardSubmitInlineText(reply_type, submitted_text, cursor_position); - }, - Qt::QueuedConnection); - } else { - connect( - software_keyboard, &QtSoftwareKeyboardDialog::SubmitNormalText, this, - [this](Service::AM::Applets::SwkbdResult result, std::u16string submitted_text) { - emit SoftwareKeyboardSubmitNormalText(result, submitted_text); - }, - Qt::QueuedConnection); - } + emit SoftwareKeyboardFinishedText(dialog.GetText()); } -void GMainWindow::SoftwareKeyboardShowNormal() { - if (!software_keyboard) { - LOG_ERROR(Frontend, "The software keyboard is not initialized!"); - return; - } - - const auto& layout = render_window->GetFramebufferLayout(); - - const auto x = layout.screen.left; - const auto y = layout.screen.top; - const auto w = layout.screen.GetWidth(); - const auto h = layout.screen.GetHeight(); - - software_keyboard->ShowNormalKeyboard(render_window->mapToGlobal(QPoint(x, y)), QSize(w, h)); -} - -void GMainWindow::SoftwareKeyboardShowTextCheck( - Service::AM::Applets::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message) { - if (!software_keyboard) { - LOG_ERROR(Frontend, "The software keyboard is not initialized!"); - return; - } - - software_keyboard->ShowTextCheckDialog(text_check_result, text_check_message); -} - -void GMainWindow::SoftwareKeyboardShowInline( - Core::Frontend::InlineAppearParameters appear_parameters) { - if (!software_keyboard) { - LOG_ERROR(Frontend, "The software keyboard is not initialized!"); - return; - } - - const auto& layout = render_window->GetFramebufferLayout(); - - const auto x = - static_cast(layout.screen.left + (0.5f * layout.screen.GetWidth() * - ((2.0f * appear_parameters.key_top_translate_x) + - (1.0f - appear_parameters.key_top_scale_x)))); - const auto y = - static_cast(layout.screen.top + (layout.screen.GetHeight() * - ((2.0f * appear_parameters.key_top_translate_y) + - (1.0f - appear_parameters.key_top_scale_y)))); - const auto w = static_cast(layout.screen.GetWidth() * appear_parameters.key_top_scale_x); - const auto h = static_cast(layout.screen.GetHeight() * appear_parameters.key_top_scale_y); - - software_keyboard->ShowInlineKeyboard(std::move(appear_parameters), - render_window->mapToGlobal(QPoint(x, y)), QSize(w, h)); -} - -void GMainWindow::SoftwareKeyboardHideInline() { - if (!software_keyboard) { - LOG_ERROR(Frontend, "The software keyboard is not initialized!"); - return; - } - - software_keyboard->HideInlineKeyboard(); -} - -void GMainWindow::SoftwareKeyboardInlineTextChanged( - Core::Frontend::InlineTextParameters text_parameters) { - if (!software_keyboard) { - LOG_ERROR(Frontend, "The software keyboard is not initialized!"); - return; - } - - software_keyboard->InlineTextChanged(std::move(text_parameters)); -} - -void GMainWindow::SoftwareKeyboardExit() { - if (!software_keyboard) { - return; - } - - software_keyboard->ExitKeyboard(); - - software_keyboard = nullptr; +void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message) { + QMessageBox::warning(this, tr("Text Check Failed"), QString::fromStdU16String(error_message)); + emit SoftwareKeyboardFinishedCheckDialog(); } void GMainWindow::WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args, @@ -1115,10 +976,6 @@ void GMainWindow::ConnectWidgetEvents() { connect(this, &GMainWindow::EmulationStopping, render_window, &GRenderWindow::OnEmulationStopping); - // Software Keyboard Applet - connect(this, &GMainWindow::EmulationStarting, this, &GMainWindow::SoftwareKeyboardExit); - connect(this, &GMainWindow::EmulationStopping, this, &GMainWindow::SoftwareKeyboardExit); - connect(&status_bar_update_timer, &QTimer::timeout, this, &GMainWindow::UpdateStatusBar); } @@ -2328,6 +2185,15 @@ void GMainWindow::OnStartGame() { emu_thread->SetRunning(true); + qRegisterMetaType("Core::Frontend::ControllerParameters"); + qRegisterMetaType( + "Core::Frontend::SoftwareKeyboardParameters"); + qRegisterMetaType("Core::System::ResultStatus"); + qRegisterMetaType("std::string"); + qRegisterMetaType>("std::optional"); + qRegisterMetaType("std::string_view"); + qRegisterMetaType("Service::AM::Applets::WebExitReason"); + connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError); ui.action_Start->setEnabled(false); @@ -2376,11 +2242,8 @@ void GMainWindow::OnExecuteProgram(std::size_t program_index) { BootGame(last_filename_booted, program_index); } -void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) { - OverlayDialog dialog(render_window, Core::System::GetInstance(), error_code, error_text, - QString{}, tr("OK"), Qt::AlignLeft | Qt::AlignVCenter); - dialog.exec(); - +void GMainWindow::ErrorDisplayDisplayError(QString body) { + QMessageBox::critical(this, tr("Error Display"), body); emit ErrorDisplayFinished(); } diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 7f1e50a5b..04d37d4ae 100755 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -37,13 +37,9 @@ enum class GameListRemoveTarget; enum class InstalledEntryType; class GameListPlaceholder; -class QtSoftwareKeyboardDialog; - namespace Core::Frontend { struct ControllerParameters; -struct InlineAppearParameters; -struct InlineTextParameters; -struct KeyboardInitializeParameters; +struct SoftwareKeyboardParameters; } // namespace Core::Frontend namespace DiscordRPC { @@ -61,11 +57,8 @@ class InputSubsystem; } namespace Service::AM::Applets { -enum class SwkbdResult : u32; -enum class SwkbdTextCheckResult : u32; -enum class SwkbdReplyType : u32; enum class WebExitReason : u32; -} // namespace Service::AM::Applets +} enum class EmulatedDirectoryTarget { NAND, @@ -135,10 +128,8 @@ signals: void ProfileSelectorFinishedSelection(std::optional uuid); - void SoftwareKeyboardSubmitNormalText(Service::AM::Applets::SwkbdResult result, - std::u16string submitted_text); - void SoftwareKeyboardSubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, - std::u16string submitted_text, s32 cursor_position); + void SoftwareKeyboardFinishedText(std::optional text); + void SoftwareKeyboardFinishedCheckDialog(); void WebBrowserExtractOfflineRomFS(); void WebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, std::string last_url); @@ -148,24 +139,15 @@ public slots: void OnExecuteProgram(std::size_t program_index); void ControllerSelectorReconfigureControllers( const Core::Frontend::ControllerParameters& parameters); - void SoftwareKeyboardInitialize( - bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters); - void SoftwareKeyboardShowNormal(); - void SoftwareKeyboardShowTextCheck(Service::AM::Applets::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message); - void SoftwareKeyboardShowInline(Core::Frontend::InlineAppearParameters appear_parameters); - void SoftwareKeyboardHideInline(); - void SoftwareKeyboardInlineTextChanged(Core::Frontend::InlineTextParameters text_parameters); - void SoftwareKeyboardExit(); - void ErrorDisplayDisplayError(QString error_code, QString error_text); + void ErrorDisplayDisplayError(QString body); void ProfileSelectorSelectProfile(); + void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters); + void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message); void WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args, bool is_local); void OnAppFocusStateChanged(Qt::ApplicationState state); private: - void RegisterMetaTypes(); - void InitializeWidgets(); void InitializeDebugWidgets(); void InitializeRecentFileMenuActions(); @@ -352,9 +334,6 @@ private: // Disables the web applet for the rest of the emulated session bool disable_web_applet{}; - // Applets - QtSoftwareKeyboardDialog* software_keyboard = nullptr; - protected: void dropEvent(QDropEvent* event) override; void dragEnterEvent(QDragEnterEvent* event) override;